@exagent/agent 0.1.31 → 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/cli.mjs CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  loadConfig,
7
7
  loadSecureEnv,
8
8
  validateConfig
9
- } from "./chunk-4NASRDHJ.mjs";
9
+ } from "./chunk-Q23UPFHO.mjs";
10
10
 
11
11
  // src/cli.ts
12
12
  import { Command } from "commander";
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 */
@@ -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
  }
@@ -2114,6 +2191,6 @@ declare function decryptEnvFile(encPath: string, passphrase: string): Record<str
2114
2191
  declare function loadSecureEnv(basePath: string, passphrase?: string): boolean;
2115
2192
 
2116
2193
  /** @exagent/agent package version — update alongside package.json */
2117
- declare const AGENT_VERSION = "0.1.31";
2194
+ declare const AGENT_VERSION = "0.1.32";
2118
2195
 
2119
2196
  export { AGENT_VERSION, type AccountSummary, type AgentConfig, AgentConfigSchema, type AgentMode, AgentRuntime, type AgentStatusPayload, AnthropicAdapter, BaseLLMAdapter, type CommandType, DeepSeekAdapter, FileStore, type FillCallback, type FundingCallback, type FundingPayment, GoogleAdapter, GroqAdapter, HYPERLIQUID_DOMAIN, HyperliquidClient, HyperliquidSigner, HyperliquidWebSocket, type LLMAdapter, type LLMConfig, LLMConfigSchema, type LLMMessage, type LLMMetadata, type LLMProvider, LLMProviderSchema, type LLMResponse, type LiquidationCallback, type MarketData, MarketDataService, type MessageLevel, type MessageType, MistralAdapter, OllamaAdapter, type OnboardingStatus, OpenAIAdapter, OrderManager, type OrderResult, type PerpAction, type PerpConfig$1 as PerpConfig, PerpConfigSchema, type PerpFill, type PerpMarketData, PerpOnboarding, type PerpPosition, type PerpStrategyFunction, PerpTradeRecorder, type PerpTradeSignal, type PerpConfig as PerpTradingConfig, PositionManager, type PositionSummary, PositionTracker, type RecordPerpTradeParams, RelayClient, type RelayCommand, type RelayConfig$1 as RelayConfig, RelayConfigSchema, RiskManager, type RiskState, type RiskUniverse, RiskUniverseSchema, type RuntimeConfig, STRATEGY_TEMPLATES, type StrategyContext, type StrategyFunction, type StrategyStore, type StrategyTemplate, TogetherAdapter, type TrackedPosition, TradeExecutor, type TradeRecord, type TradeSignal, type TradingConfig, TradingConfigSchema, type VaultConfig, VaultConfigSchema, VaultManager, type VaultManagerConfig, type VaultPolicy, VaultPolicySchema, type VaultStatus, createLLMAdapter, createSampleConfig, decryptEnvFile, encryptEnvFile, fillHashToBytes32, fillOidToBytes32, getAllStrategyTemplates, getNextNonce, getStrategyTemplate, loadConfig, loadSecureEnv, loadStrategy, validateConfig, validateStrategy };
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 */
@@ -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
  }
@@ -2114,6 +2191,6 @@ declare function decryptEnvFile(encPath: string, passphrase: string): Record<str
2114
2191
  declare function loadSecureEnv(basePath: string, passphrase?: string): boolean;
2115
2192
 
2116
2193
  /** @exagent/agent package version — update alongside package.json */
2117
- declare const AGENT_VERSION = "0.1.31";
2194
+ declare const AGENT_VERSION = "0.1.32";
2118
2195
 
2119
2196
  export { AGENT_VERSION, type AccountSummary, type AgentConfig, AgentConfigSchema, type AgentMode, AgentRuntime, type AgentStatusPayload, AnthropicAdapter, BaseLLMAdapter, type CommandType, DeepSeekAdapter, FileStore, type FillCallback, type FundingCallback, type FundingPayment, GoogleAdapter, GroqAdapter, HYPERLIQUID_DOMAIN, HyperliquidClient, HyperliquidSigner, HyperliquidWebSocket, type LLMAdapter, type LLMConfig, LLMConfigSchema, type LLMMessage, type LLMMetadata, type LLMProvider, LLMProviderSchema, type LLMResponse, type LiquidationCallback, type MarketData, MarketDataService, type MessageLevel, type MessageType, MistralAdapter, OllamaAdapter, type OnboardingStatus, OpenAIAdapter, OrderManager, type OrderResult, type PerpAction, type PerpConfig$1 as PerpConfig, PerpConfigSchema, type PerpFill, type PerpMarketData, PerpOnboarding, type PerpPosition, type PerpStrategyFunction, PerpTradeRecorder, type PerpTradeSignal, type PerpConfig as PerpTradingConfig, PositionManager, type PositionSummary, PositionTracker, type RecordPerpTradeParams, RelayClient, type RelayCommand, type RelayConfig$1 as RelayConfig, RelayConfigSchema, RiskManager, type RiskState, type RiskUniverse, RiskUniverseSchema, type RuntimeConfig, STRATEGY_TEMPLATES, type StrategyContext, type StrategyFunction, type StrategyStore, type StrategyTemplate, TogetherAdapter, type TrackedPosition, TradeExecutor, type TradeRecord, type TradeSignal, type TradingConfig, TradingConfigSchema, type VaultConfig, VaultConfigSchema, VaultManager, type VaultManagerConfig, type VaultPolicy, VaultPolicySchema, type VaultStatus, createLLMAdapter, createSampleConfig, decryptEnvFile, encryptEnvFile, fillHashToBytes32, fillOidToBytes32, getAllStrategyTemplates, getNextNonce, getStrategyTemplate, loadConfig, loadSecureEnv, loadStrategy, validateConfig, validateStrategy };