@exagent/agent 0.1.32 → 0.1.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { Address, Hash, WalletClient } from 'viem';
2
+ import { Address, Hash, PublicClient, WalletClient } from 'viem';
3
3
  import { ExagentClient } from '@exagent/sdk';
4
4
 
5
5
  /** Risk state persisted across restarts */
@@ -339,9 +339,9 @@ declare const AgentConfigSchema: z.ZodObject<{
339
339
  }>>;
340
340
  allowedTokens: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
341
341
  }, "strip", z.ZodTypeAny, {
342
+ agentId: string | number;
342
343
  name: string;
343
344
  network: "mainnet";
344
- agentId: string | number;
345
345
  llm: {
346
346
  provider: "custom" | "openai" | "anthropic" | "google" | "deepseek" | "mistral" | "groq" | "together" | "ollama";
347
347
  temperature: number;
@@ -388,8 +388,8 @@ declare const AgentConfigSchema: z.ZodObject<{
388
388
  } | undefined;
389
389
  allowedTokens?: string[] | undefined;
390
390
  }, {
391
- name: string;
392
391
  agentId: string | number;
392
+ name: string;
393
393
  llm: {
394
394
  provider: "custom" | "openai" | "anthropic" | "google" | "deepseek" | "mistral" | "groq" | "together" | "ollama";
395
395
  model?: string | undefined;
@@ -1426,30 +1426,101 @@ declare class RiskManager {
1426
1426
  private calculateLiquidationProximity;
1427
1427
  }
1428
1428
 
1429
+ /**
1430
+ * TokenResolver — bulletproof token metadata resolution with 3-tier fallback.
1431
+ *
1432
+ * Resolution chain:
1433
+ * 1. Hardcoded map (39 whitelisted tokens — instant)
1434
+ * 2. Multicall3 batch on-chain (decimals + symbol in 1 RPC call)
1435
+ * 3. Blockscout API (free, near-universal coverage for Base tokens)
1436
+ *
1437
+ * If ALL tiers fail, the token is marked "unresolvable" and skipped from
1438
+ * portfolio calculations. This is better than silently defaulting to 18
1439
+ * decimals, which causes 10^9–10^12 errors for tokens with 6/8/9 decimals.
1440
+ *
1441
+ * Resolved metadata is persisted to FileStore and never re-fetched (ERC-20
1442
+ * decimals are immutable by convention).
1443
+ */
1444
+ declare class TokenResolver {
1445
+ private client;
1446
+ private store;
1447
+ private cache;
1448
+ private unresolvable;
1449
+ constructor(client: PublicClient, store?: StrategyStore);
1450
+ /**
1451
+ * Get decimals for a token (synchronous).
1452
+ * Returns undefined if the token has never been resolved and is not hardcoded.
1453
+ * Call resolve() first for unknown tokens.
1454
+ */
1455
+ getDecimals(address: string): number | undefined;
1456
+ /**
1457
+ * Get symbol for a token (synchronous).
1458
+ */
1459
+ getSymbol(address: string): string | undefined;
1460
+ /**
1461
+ * Set symbol for a token (used when DexScreener returns symbol data).
1462
+ */
1463
+ setSymbol(address: string, symbol: string): void;
1464
+ /**
1465
+ * Check if a token has been marked as unresolvable by all tiers.
1466
+ */
1467
+ isUnresolvable(address: string): boolean;
1468
+ /**
1469
+ * Batch-resolve metadata for a list of token addresses.
1470
+ *
1471
+ * Skips already-resolved tokens. For unknown tokens:
1472
+ * 1. Multicall3 on-chain batch (decimals + symbol)
1473
+ * 2. Blockscout API for any multicall failures
1474
+ * 3. Mark remaining as unresolvable
1475
+ */
1476
+ resolve(addresses: string[]): Promise<void>;
1477
+ /**
1478
+ * Tier 2: Batch-fetch decimals + symbol via Multicall3.
1479
+ * Returns addresses that failed (for next tier).
1480
+ */
1481
+ private resolveViaMulticall;
1482
+ /**
1483
+ * Tier 3: Fetch token metadata from Blockscout (Base's block explorer API).
1484
+ * Free, no API key, near-universal coverage for any token indexed by the explorer.
1485
+ * Returns addresses that failed (truly unresolvable).
1486
+ */
1487
+ private resolveViaBlockscout;
1488
+ /**
1489
+ * Persist resolved metadata to FileStore.
1490
+ */
1491
+ private persist;
1492
+ /**
1493
+ * Persist unresolvable token list to FileStore.
1494
+ */
1495
+ private persistUnresolvable;
1496
+ }
1497
+
1429
1498
  /**
1430
1499
  * Market Data Service
1431
1500
  * Fetches real prices from CoinGecko and on-chain balances for strategy analysis.
1432
1501
  *
1433
- * Queries real on-chain balances for:
1434
- * - Native ETH (via eth_getBalance)
1435
- * - ERC-20 tokens (via balanceOf)
1502
+ * Uses TokenResolver for bulletproof token metadata resolution:
1503
+ * 1. Hardcoded map (39 whitelisted tokens)
1504
+ * 2. Multicall3 batch on-chain (1 RPC call for N tokens)
1505
+ * 3. Blockscout API (free, near-universal coverage)
1436
1506
  *
1437
- * Fetches real prices from CoinGecko free API.
1438
- * Refuses to return data if prices are stale (>60s old) to prevent
1439
- * agents from making decisions with outdated price information.
1507
+ * Uses Multicall3 for batched balance fetching (1 RPC call for N balanceOf).
1440
1508
  */
1441
1509
  declare class MarketDataService {
1442
1510
  private rpcUrl;
1443
1511
  private client;
1512
+ private resolver;
1444
1513
  /** Cached prices from last fetch */
1445
1514
  private cachedPrices;
1446
1515
  /** Timestamp of last successful price fetch */
1447
1516
  private lastPriceFetchAt;
1448
- constructor(rpcUrl: string);
1449
1517
  /** Cached volume data */
1450
1518
  private cachedVolume24h;
1451
1519
  /** Cached price change data */
1452
1520
  private cachedPriceChange24h;
1521
+ constructor(rpcUrl: string, store?: StrategyStore);
1522
+ /** Get the underlying TokenResolver for direct access */
1523
+ getResolver(): TokenResolver;
1453
1524
  /**
1454
1525
  * Fetch current market data for the agent
1455
1526
  */
@@ -1464,11 +1535,17 @@ declare class MarketDataService {
1464
1535
  */
1465
1536
  private fetchPrices;
1466
1537
  /**
1467
- * Fetch real on-chain balances: native ETH + ERC-20 tokens
1538
+ * Fetch real on-chain balances: native ETH + ERC-20 tokens.
1539
+ * Uses Multicall3 to batch all balanceOf calls into a single RPC request.
1468
1540
  */
1469
1541
  private fetchBalances;
1470
1542
  /**
1471
- * Calculate total portfolio value in USD
1543
+ * Fallback: fetch ERC-20 balances individually (if multicall fails).
1544
+ */
1545
+ private fetchBalancesIndividual;
1546
+ /**
1547
+ * Calculate total portfolio value in USD.
1548
+ * Skips tokens with unresolvable decimals to avoid corrupted calculations.
1472
1549
  */
1473
1550
  private calculatePortfolioValue;
1474
1551
  }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { Address, Hash, WalletClient } from 'viem';
2
+ import { Address, Hash, PublicClient, WalletClient } from 'viem';
3
3
  import { ExagentClient } from '@exagent/sdk';
4
4
 
5
5
  /** Risk state persisted across restarts */
@@ -339,9 +339,9 @@ declare const AgentConfigSchema: z.ZodObject<{
339
339
  }>>;
340
340
  allowedTokens: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
341
341
  }, "strip", z.ZodTypeAny, {
342
+ agentId: string | number;
342
343
  name: string;
343
344
  network: "mainnet";
344
- agentId: string | number;
345
345
  llm: {
346
346
  provider: "custom" | "openai" | "anthropic" | "google" | "deepseek" | "mistral" | "groq" | "together" | "ollama";
347
347
  temperature: number;
@@ -388,8 +388,8 @@ declare const AgentConfigSchema: z.ZodObject<{
388
388
  } | undefined;
389
389
  allowedTokens?: string[] | undefined;
390
390
  }, {
391
- name: string;
392
391
  agentId: string | number;
392
+ name: string;
393
393
  llm: {
394
394
  provider: "custom" | "openai" | "anthropic" | "google" | "deepseek" | "mistral" | "groq" | "together" | "ollama";
395
395
  model?: string | undefined;
@@ -1426,30 +1426,101 @@ declare class RiskManager {
1426
1426
  private calculateLiquidationProximity;
1427
1427
  }
1428
1428
 
1429
+ /**
1430
+ * TokenResolver — bulletproof token metadata resolution with 3-tier fallback.
1431
+ *
1432
+ * Resolution chain:
1433
+ * 1. Hardcoded map (39 whitelisted tokens — instant)
1434
+ * 2. Multicall3 batch on-chain (decimals + symbol in 1 RPC call)
1435
+ * 3. Blockscout API (free, near-universal coverage for Base tokens)
1436
+ *
1437
+ * If ALL tiers fail, the token is marked "unresolvable" and skipped from
1438
+ * portfolio calculations. This is better than silently defaulting to 18
1439
+ * decimals, which causes 10^9–10^12 errors for tokens with 6/8/9 decimals.
1440
+ *
1441
+ * Resolved metadata is persisted to FileStore and never re-fetched (ERC-20
1442
+ * decimals are immutable by convention).
1443
+ */
1444
+ declare class TokenResolver {
1445
+ private client;
1446
+ private store;
1447
+ private cache;
1448
+ private unresolvable;
1449
+ constructor(client: PublicClient, store?: StrategyStore);
1450
+ /**
1451
+ * Get decimals for a token (synchronous).
1452
+ * Returns undefined if the token has never been resolved and is not hardcoded.
1453
+ * Call resolve() first for unknown tokens.
1454
+ */
1455
+ getDecimals(address: string): number | undefined;
1456
+ /**
1457
+ * Get symbol for a token (synchronous).
1458
+ */
1459
+ getSymbol(address: string): string | undefined;
1460
+ /**
1461
+ * Set symbol for a token (used when DexScreener returns symbol data).
1462
+ */
1463
+ setSymbol(address: string, symbol: string): void;
1464
+ /**
1465
+ * Check if a token has been marked as unresolvable by all tiers.
1466
+ */
1467
+ isUnresolvable(address: string): boolean;
1468
+ /**
1469
+ * Batch-resolve metadata for a list of token addresses.
1470
+ *
1471
+ * Skips already-resolved tokens. For unknown tokens:
1472
+ * 1. Multicall3 on-chain batch (decimals + symbol)
1473
+ * 2. Blockscout API for any multicall failures
1474
+ * 3. Mark remaining as unresolvable
1475
+ */
1476
+ resolve(addresses: string[]): Promise<void>;
1477
+ /**
1478
+ * Tier 2: Batch-fetch decimals + symbol via Multicall3.
1479
+ * Returns addresses that failed (for next tier).
1480
+ */
1481
+ private resolveViaMulticall;
1482
+ /**
1483
+ * Tier 3: Fetch token metadata from Blockscout (Base's block explorer API).
1484
+ * Free, no API key, near-universal coverage for any token indexed by the explorer.
1485
+ * Returns addresses that failed (truly unresolvable).
1486
+ */
1487
+ private resolveViaBlockscout;
1488
+ /**
1489
+ * Persist resolved metadata to FileStore.
1490
+ */
1491
+ private persist;
1492
+ /**
1493
+ * Persist unresolvable token list to FileStore.
1494
+ */
1495
+ private persistUnresolvable;
1496
+ }
1497
+
1429
1498
  /**
1430
1499
  * Market Data Service
1431
1500
  * Fetches real prices from CoinGecko and on-chain balances for strategy analysis.
1432
1501
  *
1433
- * Queries real on-chain balances for:
1434
- * - Native ETH (via eth_getBalance)
1435
- * - ERC-20 tokens (via balanceOf)
1502
+ * Uses TokenResolver for bulletproof token metadata resolution:
1503
+ * 1. Hardcoded map (39 whitelisted tokens)
1504
+ * 2. Multicall3 batch on-chain (1 RPC call for N tokens)
1505
+ * 3. Blockscout API (free, near-universal coverage)
1436
1506
  *
1437
- * Fetches real prices from CoinGecko free API.
1438
- * Refuses to return data if prices are stale (>60s old) to prevent
1439
- * agents from making decisions with outdated price information.
1507
+ * Uses Multicall3 for batched balance fetching (1 RPC call for N balanceOf).
1440
1508
  */
1441
1509
  declare class MarketDataService {
1442
1510
  private rpcUrl;
1443
1511
  private client;
1512
+ private resolver;
1444
1513
  /** Cached prices from last fetch */
1445
1514
  private cachedPrices;
1446
1515
  /** Timestamp of last successful price fetch */
1447
1516
  private lastPriceFetchAt;
1448
- constructor(rpcUrl: string);
1449
1517
  /** Cached volume data */
1450
1518
  private cachedVolume24h;
1451
1519
  /** Cached price change data */
1452
1520
  private cachedPriceChange24h;
1521
+ constructor(rpcUrl: string, store?: StrategyStore);
1522
+ /** Get the underlying TokenResolver for direct access */
1523
+ getResolver(): TokenResolver;
1453
1524
  /**
1454
1525
  * Fetch current market data for the agent
1455
1526
  */
@@ -1464,11 +1535,17 @@ declare class MarketDataService {
1464
1535
  */
1465
1536
  private fetchPrices;
1466
1537
  /**
1467
- * Fetch real on-chain balances: native ETH + ERC-20 tokens
1538
+ * Fetch real on-chain balances: native ETH + ERC-20 tokens.
1539
+ * Uses Multicall3 to batch all balanceOf calls into a single RPC request.
1468
1540
  */
1469
1541
  private fetchBalances;
1470
1542
  /**
1471
- * Calculate total portfolio value in USD
1543
+ * Fallback: fetch ERC-20 balances individually (if multicall fails).
1544
+ */
1545
+ private fetchBalancesIndividual;
1546
+ /**
1547
+ * Calculate total portfolio value in USD.
1548
+ * Skips tokens with unresolvable decimals to avoid corrupted calculations.
1472
1549
  */
1473
1550
  private calculatePortfolioValue;
1474
1551
  }