Skip to content

feat(provider): add optional GoldRush multi-chain token balance enrichment#26

Open
dinxsh wants to merge 1 commit intoelizaos-plugins:1.xfrom
dinxsh:feat/goldrush-multichain-balances
Open

feat(provider): add optional GoldRush multi-chain token balance enrichment#26
dinxsh wants to merge 1 commit intoelizaos-plugins:1.xfrom
dinxsh:feat/goldrush-multichain-balances

Conversation

@dinxsh
Copy link
Copy Markdown

@dinxsh dinxsh commented Mar 15, 2026

Fixes #15

Summary

  • Extends WalletProvider in src/providers/wallet.ts to optionally fetch full token balances across all configured chains via GoldRush API when GOLDRUSH_API_KEY is set
  • Falls back to existing viem balance fetching when key is absent — zero breaking changes
  • All chains are fetched in parallel via Promise.allSettled; per-chain errors are isolated and never block others

Why GoldRush

  • Single API covers 100+ EVM chains
  • Returns USD values, spam filtering (noSpam: true), and decoded token metadata
  • Parallel fetching across chains in a single provider call

Configuration

GOLDRUSH_API_KEY=your_key_here  # optional — get yours at https://goldrush.dev

Without key: existing behavior unchanged
With key: agent context includes full multi-chain token portfolio appended to the existing wallet output:

Token Holdings (via GoldRush):
ETH (eth-mainnet): 1.5 ETH — $3,840
USDC (base-mainnet): 2,400 USDC — $2,400
ARB (arbitrum-mainnet): 500 ARB — $320
Total Portfolio Value: $6,560

Powered by GoldRush (goldrush.dev) — 100+ chains

Changes

  • src/providers/wallet.ts — added CHAIN_MAP, getMultiChainBalances, buildGoldRushText helpers; enrichment hook in evmWalletProvider.get
  • package.json — added @covalenthq/client-sdk to dependencies
  • README.md — documented GOLDRUSH_API_KEY env var

Test plan

  • Without GOLDRUSH_API_KEY: provider output is identical to pre-PR behavior
  • With GOLDRUSH_API_KEY: token holdings section appended for each configured chain
  • One chain returning a GoldRush error does not block others
  • Chains not in CHAIN_MAP are silently skipped

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added multi-chain token balance enrichment powered by GoldRush, displaying token holdings and USD totals across supported blockchains.
  • Documentation

    • Updated README to document the optional GOLDRUSH_API_KEY environment variable for enabling enhanced wallet balance enrichment.

Greptile Summary

This PR adds optional multi-chain token balance enrichment to the evmWalletProvider via the GoldRush (Covalent) API. When GOLDRUSH_API_KEY is set, the provider appends detailed token holdings (with USD values and spam filtering) across all configured EVM chains to the agent context. The integration is purely additive — when the key is absent, existing behavior is unchanged.

  • Adds CHAIN_MAP, getMultiChainBalances, and buildGoldRushText helpers to src/providers/wallet.ts for GoldRush API integration
  • Uses Promise.allSettled for parallel per-chain fetching with isolated error handling
  • Refactors evmWalletProvider.get to accumulate a result variable before optionally enriching it with GoldRush data
  • GoldRush API errors (invalid key, rate limiting) are silently swallowed — recommend checking resp.error and logging warnings
  • A single malformed token in the API response can cause the entire GoldRush output to be discarded due to a broad try/catch — recommend per-item error handling
  • GoldRushClient is re-instantiated on every provider call — consider caching the client instance for better performance

Confidence Score: 3/5

  • This PR is likely safe to merge as the GoldRush integration is optional and fallback behavior is preserved, but error handling gaps should be addressed to avoid silent failures in production.
  • Score of 3 reflects that the core design is sound (optional enrichment, parallel fetching, graceful fallback) but there are two logic-level concerns: GoldRush API errors are silently swallowed (making misconfiguration hard to diagnose), and a single malformed token in the API response can discard all token data due to broad error handling.
  • src/providers/wallet.ts — the GoldRush integration helpers (getMultiChainBalances and buildGoldRushText) need improved error handling

Important Files Changed

Filename Overview
src/providers/wallet.ts Adds GoldRush multi-chain token balance enrichment. Core logic is sound with good use of Promise.allSettled for isolation, but API errors are silently swallowed and a single malformed token can wipe all output. GoldRushClient is also re-instantiated on every call.
package.json Adds @covalenthq/client-sdk ^3.0.5 dependency. Appropriate version pinning.
README.md Documents the optional GOLDRUSH_API_KEY env variable. Clear and concise.
bun.lock Lock file updated for the new @covalenthq/client-sdk dependency and its transitive dependencies.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[evmWalletProvider.get] --> B{EVM Service available?}
    B -- No --> C[directFetchWalletData]
    B -- Yes --> D{Cached wallet data?}
    D -- No --> C
    D -- Yes --> E[Build result from cached data]
    C --> F{GOLDRUSH_API_KEY set?}
    E --> F
    F -- No --> G[Return result as-is]
    F -- Yes --> H[genChainsFromRuntime]
    H --> I[buildGoldRushText]
    I --> J[getMultiChainBalances]
    J --> K[Map chains via CHAIN_MAP]
    K --> L[Promise.allSettled: GoldRush API calls]
    L --> M[Format token holdings text]
    M --> N[Append GoldRush text to result]
    N --> G
Loading

Last reviewed commit: 4f7dacf

Greptile also left 3 inline comments on this PR.

(2/5) Greptile learns from your feedback when you react with thumbs up/down!

…hment

Fixes elizaos-plugins#15

Extends WalletProvider to optionally fetch full token balances across
all configured chains via GoldRush API when GOLDRUSH_API_KEY is set.

Falls back to existing behavior if key is not present — zero breaking changes.

Why GoldRush:
- Single API covers 100+ EVM chains
- Returns USD values, spam filtering, and decoded token metadata
- Parallel fetching across chains in one provider call

Configuration:
  GOLDRUSH_API_KEY=your_key_here  # optional

Without key: existing behavior unchanged
With key: agent context includes full multi-chain token portfolio

Tested on: eth-mainnet, base-mainnet, arbitrum-mainnet, matic-mainnet

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 15, 2026

Walkthrough

This PR adds GoldRush integration to the EVM wallet provider for multi-chain token balance enrichment. A new dependency (@covalenthq/client-sdk) is added, environment configuration is documented, and the wallet provider is enhanced to optionally fetch and aggregate multi-chain token balances when an API key is available.

Changes

Cohort / File(s) Summary
Documentation & Dependencies
README.md, package.json
Added GOLDRUSH_API_KEY environment variable documentation and introduced @covalenthq/client-sdk v3.0.5 dependency.
Wallet Provider Enhancement
src/providers/wallet.ts
Integrated GoldRush multi-chain balance enrichment: added CHAIN_MAP for chain name translation, getMultiChainBalances() for fetching per-chain token balances, buildGoldRushText() for rendering multi-chain holdings reports, and modified evmWalletProvider to optionally append GoldRush data when API key and address are available.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Wallet Provider Client
    participant Provider as EVM Wallet Provider
    participant EVMService as EVM Service
    participant GoldRush as GoldRush API
    
    Client->>Provider: get(address)
    Provider->>EVMService: fetch cached data
    alt EVMService returns data
        EVMService-->>Provider: wallet data + text
    else EVMService unavailable or no cache
        Provider->>EVMService: direct fetch attempt
        EVMService-->>Provider: data or fallback
    end
    
    alt GOLDRUSH_API_KEY & address available
        Provider->>GoldRush: getMultiChainBalances(address)
        GoldRush-->>Provider: per-chain token balances
        Provider->>Provider: buildGoldRushText(data)
        Provider->>Provider: append GoldRush text to result
    end
    
    Provider-->>Client: enriched wallet result (text + data + values)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Hops with glee through blockchains wide,
GoldRush tokens by our side,
Multi-chain balances now in sight,
Wallets enriched, the data's bright!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR adds infrastructure to display token holdings across chains but does not directly address the core issue that the agent is 'not aware' of or cannot access the EVM plugin. The PR should clarify how GoldRush enrichment makes the agent aware of plugin-evm, or additional changes may be needed to ensure the EVM plugin is properly integrated and discoverable.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately describes the main change: adding optional GoldRush multi-chain token balance enrichment to the provider.
Out of Scope Changes check ✅ Passed All changes (CHAIN_MAP, getMultiChainBalances, buildGoldRushText, enrichment hook, dependency addition, and README documentation) are directly scoped to implementing optional GoldRush multi-chain balance enrichment.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment on lines +71 to +84
const resp = await client.BalanceService.getTokenBalancesForWalletAddress(
goldrushChain,
address,
{ quoteCurrency: 'USD', noSpam: true }
);

return {
chain: goldrushChain,
items: resp.data?.items ?? [],
totalUSD: (resp.data?.items ?? []).reduce(
(sum: number, item: any) => sum + (item.quote ?? 0),
0
),
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GoldRush API errors silently swallowed

The GoldRush SDK returns a standardized response of {data, error, error_message, error_code}. When the API returns an error (invalid API key, rate limiting, invalid chain name), resp.error will be true and resp.data may be null. The current code only uses resp.data?.items ?? [], which silently treats API errors as "no tokens found."

This means if the API key is invalid or expired, or the account hits rate limits, the agent will silently receive no token data with no indication of failure — making it very difficult to diagnose configuration issues.

Suggested change
const resp = await client.BalanceService.getTokenBalancesForWalletAddress(
goldrushChain,
address,
{ quoteCurrency: 'USD', noSpam: true }
);
return {
chain: goldrushChain,
items: resp.data?.items ?? [],
totalUSD: (resp.data?.items ?? []).reduce(
(sum: number, item: any) => sum + (item.quote ?? 0),
0
),
};
const resp = await client.BalanceService.getTokenBalancesForWalletAddress(
goldrushChain,
address,
{ quoteCurrency: 'USD', noSpam: true }
);
if (resp.error) {
elizaLogger.warn(`GoldRush API error for ${goldrushChain}: ${resp.error_message}`);
return null;
}
return {
chain: goldrushChain,
items: resp.data?.items ?? [],
totalUSD: (resp.data?.items ?? []).reduce(
(sum: number, item: any) => sum + (item.quote ?? 0),
0
),
};

Comment on lines +106 to +120
for (const result of chainResults) {
for (const item of result.items) {
if (!item.balance || item.balance === '0') continue;
const symbol = item.contract_ticker_symbol ?? '???';
const decimals = item.contract_decimals ?? 18;
const balance = formatUnits(BigInt(item.balance), decimals);
const formattedBalance = Number(balance).toLocaleString('en-US', {
maximumFractionDigits: 4,
});
const usdValue = item.quote ?? 0;
const formattedUSD = `$${usdValue.toLocaleString('en-US', { maximumFractionDigits: 0 })}`;
lines.push(`${symbol} (${result.chain}): ${formattedBalance} ${symbol} — ${formattedUSD}`);
totalPortfolioUSD += usdValue;
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One malformed token breaks all output

The outer try/catch in buildGoldRushText wraps the entire token iteration. If any single token item from the API has an unexpected balance value (e.g., a non-numeric string or a type that BigInt() can't parse), the error will bubble up to the catch block and the function returns '' — discarding data for all tokens across all chains.

Consider wrapping the per-item processing in its own try/catch so that one bad token doesn't wipe out the entire portfolio output:

Suggested change
for (const result of chainResults) {
for (const item of result.items) {
if (!item.balance || item.balance === '0') continue;
const symbol = item.contract_ticker_symbol ?? '???';
const decimals = item.contract_decimals ?? 18;
const balance = formatUnits(BigInt(item.balance), decimals);
const formattedBalance = Number(balance).toLocaleString('en-US', {
maximumFractionDigits: 4,
});
const usdValue = item.quote ?? 0;
const formattedUSD = `$${usdValue.toLocaleString('en-US', { maximumFractionDigits: 0 })}`;
lines.push(`${symbol} (${result.chain}): ${formattedBalance} ${symbol}${formattedUSD}`);
totalPortfolioUSD += usdValue;
}
}
for (const result of chainResults) {
for (const item of result.items) {
try {
if (!item.balance || item.balance === '0') continue;
const symbol = item.contract_ticker_symbol ?? '???';
const decimals = item.contract_decimals ?? 18;
const balance = formatUnits(BigInt(item.balance), decimals);
const formattedBalance = Number(balance).toLocaleString('en-US', {
maximumFractionDigits: 4,
});
const usdValue = item.quote ?? 0;
const formattedUSD = `$${usdValue.toLocaleString('en-US', { maximumFractionDigits: 0 })}`;
lines.push(`${symbol} (${result.chain}): ${formattedBalance} ${symbol}${formattedUSD}`);
totalPortfolioUSD += usdValue;
} catch (itemError) {
elizaLogger.warn(`Skipping malformed token on ${result.chain}: ${itemError}`);
}
}
}

Comment on lines +63 to +64
const getMultiChainBalances = async (address: string, chains: string[], apiKey: string) => {
const client = new GoldRushClient(apiKey);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New GoldRushClient created on every provider call

evmWalletProvider.get is called on every agent message cycle. Each call creates a brand new GoldRushClient instance inside getMultiChainBalances. The GoldRush SDK client manages internal state for thread pooling, retry logic, and rate limiting — recreating it on every call loses those benefits and adds unnecessary overhead.

Consider instantiating the client once (e.g., at module level or cached by API key) and reusing it across calls.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
src/providers/wallet.ts (1)

111-116: Avoid Number() when formatting token balances.

formatUnits() returns decimal strings that can exceed JavaScript's safe numeric range. Coercing them through Number() causes precision loss for large token holdings—for example, a balance like 123456789012345678901234567890.1234 becomes 123,456,789,012,345,680,000,000,000,000 after rounding.

String-safe formatting
-        const formattedBalance = Number(balance).toLocaleString('en-US', {
-          maximumFractionDigits: 4,
-        });
+        const [whole, fraction = ''] = balance.split('.');
+        const formattedBalance = `${BigInt(whole).toLocaleString('en-US')}${
+          fraction ? `.${fraction.slice(0, 4)}` : ''
+        }`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/providers/wallet.ts` around lines 111 - 116, The code coerces the token
balance string returned by formatUnits into a Number (in formattedBalance),
which loses precision for very large balances; change formattedBalance to use a
string-safe formatter instead of Number(): preserve the balance string returned
by formatUnits(item.balance, decimals) and format it without numeric coercion
(e.g., implement or call a utility like formatTokenBalance(balanceString, {
maximumFractionDigits: 4 }) that splits integer/fraction parts and inserts
thousands separators, or use a decimal library such as Big/decimal.js to format
safely). Update the usage around formatUnits, formattedBalance, and
item.balance/decimals to avoid Number() conversions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@package.json`:
- Line 25: The plugin manifest (package.json) is missing the new
GOLDRUSH_API_KEY declaration referenced by src/providers/wallet.ts; update the
manifest's agentConfig.pluginParameters to include a GOLDRUSH_API_KEY parameter
(name "GOLDRUSH_API_KEY", type string, add a short description and mark
required/optional per the provider's expectations) so schema-driven UIs and
README-consumers can discover and validate the setting; ensure the parameter key
matches exactly "GOLDRUSH_API_KEY" and appears alongside the other
pluginParameters entries in package.json.

In `@README.md`:
- Around line 38-42: Update the README wording to clarify that GoldRush only
enriches token holdings for chains that are supported by the implementation:
explicitly state that the provider only queries chains listed in CHAIN_MAP (in
src/providers/wallet.ts) and any configured chains not present in CHAIN_MAP are
skipped, and keep the GOLDRUSH_API_KEY note but add this limitation sentence
next to it.

In `@src/providers/wallet.ts`:
- Around line 500-512: The GoldRush enrichment is blocking the provider return;
change the flow so when GOLDRUSH_API_KEY is present you kick off
buildGoldRushText(result.data.address, chainNames, goldRushApiKey)
asynchronously with a bounded timeout (use Promise.race or equivalent) and apply
the returned goldRushText to result.text only if it completes before the
timeout; additionally add a simple cache keyed by address+chainNames+apiKey
(lookup before calling buildGoldRushText and store the rendered text after
success) to prevent repeated fan-out; locate changes around
genChainsFromRuntime, buildGoldRushText and the result merging logic and ensure
the main provider returns immediately if the enrichment does not finish in time.
- Around line 63-91: getMultiChainBalances currently swallows rejected GoldRush
calls and returns only successful balances, causing buildGoldRushText to print a
misleading unconditional total; change getMultiChainBalances to return an object
like { successes: [...], failedChains: [...] } by capturing Promise.allSettled
results (use CHAIN_MAP and GoldRushClient as currently) and populate
failedChains with chain names/ids for any rejected or null entries, and then
update buildGoldRushText to accept that object, surface failedChains to the user
(e.g., list which chains failed) and only compute/print the Total Portfolio
Value when failedChains is empty or otherwise clearly mark the total as partial
when some chains failed.

---

Nitpick comments:
In `@src/providers/wallet.ts`:
- Around line 111-116: The code coerces the token balance string returned by
formatUnits into a Number (in formattedBalance), which loses precision for very
large balances; change formattedBalance to use a string-safe formatter instead
of Number(): preserve the balance string returned by formatUnits(item.balance,
decimals) and format it without numeric coercion (e.g., implement or call a
utility like formatTokenBalance(balanceString, { maximumFractionDigits: 4 })
that splits integer/fraction parts and inserts thousands separators, or use a
decimal library such as Big/decimal.js to format safely). Update the usage
around formatUnits, formattedBalance, and item.balance/decimals to avoid
Number() conversions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f1ed17aa-0ed4-4324-a080-25b3d8250c6e

📥 Commits

Reviewing files that changed from the base of the PR and between a423863 and 4f7dacf.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • README.md
  • package.json
  • src/providers/wallet.ts

"dist"
],
"dependencies": {
"@covalenthq/client-sdk": "^3.0.5",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add GOLDRUSH_API_KEY to agentConfig.pluginParameters.

src/providers/wallet.ts now reads this setting, but the plugin manifest never declares it. That keeps the new feature out of schema-driven config/UIs and makes the README the only place users can discover it.

Suggested manifest addition
       "ETHEREUM_PROVIDER_OPTIMISM": {
         "type": "string",
         "description": "Custom RPC URL for Optimism mainnet. For other chains, set ETHEREUM_PROVIDER_<CHAINNAME> (or EVM_PROVIDER_<CHAINNAME>) in your .env.",
         "required": false,
         "sensitive": false
       },
+      "GOLDRUSH_API_KEY": {
+        "type": "string",
+        "description": "Optional GoldRush API key used to enrich wallet context with multi-chain token balances.",
+        "required": false,
+        "sensitive": true
+      },
       "TEE_MODE": {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` at line 25, The plugin manifest (package.json) is missing the
new GOLDRUSH_API_KEY declaration referenced by src/providers/wallet.ts; update
the manifest's agentConfig.pluginParameters to include a GOLDRUSH_API_KEY
parameter (name "GOLDRUSH_API_KEY", type string, add a short description and
mark required/optional per the provider's expectations) so schema-driven UIs and
README-consumers can discover and validate the setting; ensure the parameter key
matches exactly "GOLDRUSH_API_KEY" and appears alongside the other
pluginParameters entries in package.json.

Comment on lines +38 to +42
# Optional - GoldRush API for multi-chain token balances
# When set, the wallet provider enriches agent context with full token
# holdings across all configured chains (USD values, spam filtering).
# Get your free API key at https://goldrush.dev
GOLDRUSH_API_KEY=your_goldrush_api_key
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Clarify that GoldRush does not cover every configured chain.

The text says this enriches holdings across “all configured chains”, but the implementation only queries chains present in src/providers/wallet.ts’s CHAIN_MAP; unsupported configured chains are skipped. Please make that limitation explicit here.

Suggested wording
-# holdings across all configured chains (USD values, spam filtering).
+# holdings across supported configured chains (USD values, spam filtering).
+# Chains without a GoldRush mapping are skipped.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 38 - 42, Update the README wording to clarify that
GoldRush only enriches token holdings for chains that are supported by the
implementation: explicitly state that the provider only queries chains listed in
CHAIN_MAP (in src/providers/wallet.ts) and any configured chains not present in
CHAIN_MAP are skipped, and keep the GOLDRUSH_API_KEY note but add this
limitation sentence next to it.

Comment on lines +63 to +91
const getMultiChainBalances = async (address: string, chains: string[], apiKey: string) => {
const client = new GoldRushClient(apiKey);

const results = await Promise.allSettled(
chains.map(async (chain) => {
const goldrushChain = CHAIN_MAP[chain];
if (!goldrushChain) return null;

const resp = await client.BalanceService.getTokenBalancesForWalletAddress(
goldrushChain,
address,
{ quoteCurrency: 'USD', noSpam: true }
);

return {
chain: goldrushChain,
items: resp.data?.items ?? [],
totalUSD: (resp.data?.items ?? []).reduce(
(sum: number, item: any) => sum + (item.quote ?? 0),
0
),
};
})
);

return results
.filter((r) => r.status === 'fulfilled' && r.value !== null)
.map((r) => (r as PromiseFulfilledResult<any>).value);
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don’t label a partial portfolio as complete.

Rejected GoldRush calls are filtered out here, so buildGoldRushText() later emits Total Portfolio Value over only the successful subset. That underreports holdings without any warning when one configured chain fails.

Suggested direction
-  return results
-    .filter((r) => r.status === 'fulfilled' && r.value !== null)
-    .map((r) => (r as PromiseFulfilledResult<any>).value);
+  const chainResults = [];
+  const failedChains: string[] = [];
+
+  results.forEach((result, index) => {
+    if (result.status === 'fulfilled' && result.value !== null) {
+      chainResults.push(result.value);
+      return;
+    }
+
+    if (CHAIN_MAP[chains[index]]) {
+      failedChains.push(chains[index]);
+    }
+  });
+
+  return { chainResults, failedChains };

Have buildGoldRushText() surface failedChains and avoid printing an unconditional total when the enrichment is partial.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/providers/wallet.ts` around lines 63 - 91, getMultiChainBalances
currently swallows rejected GoldRush calls and returns only successful balances,
causing buildGoldRushText to print a misleading unconditional total; change
getMultiChainBalances to return an object like { successes: [...], failedChains:
[...] } by capturing Promise.allSettled results (use CHAIN_MAP and
GoldRushClient as currently) and populate failedChains with chain names/ids for
any rejected or null entries, and then update buildGoldRushText to accept that
object, surface failedChains to the user (e.g., list which chains failed) and
only compute/print the Total Portfolio Value when failedChains is empty or
otherwise clearly mark the total as partial when some chains failed.

Comment on lines +500 to +512
// Optionally enrich with GoldRush multi-chain token balances
const goldRushApiKey = runtime.getSetting('GOLDRUSH_API_KEY');
if (goldRushApiKey && result.data?.address) {
const chains = genChainsFromRuntime(runtime);
const chainNames = Object.keys(chains);
const goldRushText = await buildGoldRushText(
result.data.address as string,
chainNames,
goldRushApiKey
);
if (goldRushText) {
result = { ...result, text: result.text + goldRushText };
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Keep GoldRush enrichment off the critical path.

With GOLDRUSH_API_KEY set, every provider call now waits for fresh GoldRush requests across all chains before returning. That makes optional enrichment a latency hit on the hot path even though the base wallet data is already ready.

At minimum, bound the enrichment with a timeout
-        const goldRushText = await buildGoldRushText(
-          result.data.address as string,
-          chainNames,
-          goldRushApiKey
-        );
+        const goldRushText = await Promise.race([
+          buildGoldRushText(result.data.address as string, chainNames, goldRushApiKey),
+          new Promise<string>((resolve) => setTimeout(() => resolve(''), 3_000)),
+        ]);

I’d also cache the rendered GoldRush section separately so repeated prompts don’t fan out to the API every time.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/providers/wallet.ts` around lines 500 - 512, The GoldRush enrichment is
blocking the provider return; change the flow so when GOLDRUSH_API_KEY is
present you kick off buildGoldRushText(result.data.address, chainNames,
goldRushApiKey) asynchronously with a bounded timeout (use Promise.race or
equivalent) and apply the returned goldRushText to result.text only if it
completes before the timeout; additionally add a simple cache keyed by
address+chainNames+apiKey (lookup before calling buildGoldRushText and store the
rendered text after success) to prevent repeated fan-out; locate changes around
genChainsFromRuntime, buildGoldRushText and the result merging logic and ensure
the main provider returns immediately if the enrichment does not finish in time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Eliza agent is not aware by plugin evm

1 participant