@exagent/agent 0.1.11 → 0.1.13

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-7GQXIIL2.mjs";
9
+ } from "./chunk-BSNYL2DK.mjs";
10
10
 
11
11
  // src/cli.ts
12
12
  import { Command } from "commander";
@@ -184,7 +184,7 @@ async function checkFirstRunSetup(configPath) {
184
184
  EXAGENT_PRIVATE_KEY=${privateKey}
185
185
 
186
186
  # Network
187
- EXAGENT_NETWORK=${config.network || "testnet"}
187
+ EXAGENT_NETWORK=${config.network || "mainnet"}
188
188
 
189
189
  # LLM (${llmProvider})
190
190
  ${llmEnvVar}EXAGENT_LLM_MODEL=${config.llm?.model || ""}
@@ -235,7 +235,7 @@ ${llmEnvVar}EXAGENT_LLM_MODEL=${config.llm?.model || ""}
235
235
  console.log("");
236
236
  if (walletSetup === "generate") {
237
237
  console.log(" NEXT: Fund your wallet before starting to trade.");
238
- console.log(` Send testnet ETH to: ${walletAddress}`);
238
+ console.log(` Send ETH to: ${walletAddress}`);
239
239
  }
240
240
  console.log("");
241
241
  console.log(" The agent will now start...");
package/dist/index.d.mts CHANGED
@@ -35,36 +35,42 @@ declare const TradingConfigSchema: z.ZodObject<{
35
35
  maxDailyLossBps: z.ZodDefault<z.ZodNumber>;
36
36
  maxConcurrentPositions: z.ZodDefault<z.ZodNumber>;
37
37
  tradingIntervalMs: z.ZodDefault<z.ZodNumber>;
38
+ maxSlippageBps: z.ZodDefault<z.ZodNumber>;
39
+ minTradeValueUSD: z.ZodDefault<z.ZodNumber>;
38
40
  }, "strip", z.ZodTypeAny, {
39
41
  timeHorizon: "intraday" | "swing" | "position";
40
42
  maxPositionSizeBps: number;
41
43
  maxDailyLossBps: number;
42
44
  maxConcurrentPositions: number;
43
45
  tradingIntervalMs: number;
46
+ maxSlippageBps: number;
47
+ minTradeValueUSD: number;
44
48
  }, {
45
49
  timeHorizon?: "intraday" | "swing" | "position" | undefined;
46
50
  maxPositionSizeBps?: number | undefined;
47
51
  maxDailyLossBps?: number | undefined;
48
52
  maxConcurrentPositions?: number | undefined;
49
53
  tradingIntervalMs?: number | undefined;
54
+ maxSlippageBps?: number | undefined;
55
+ minTradeValueUSD?: number | undefined;
50
56
  }>;
51
57
  type TradingConfig = z.infer<typeof TradingConfigSchema>;
52
- declare const VaultPolicySchema: z.ZodEnum<["disabled", "manual", "auto_when_qualified"]>;
58
+ declare const VaultPolicySchema: z.ZodEnum<["disabled", "manual"]>;
53
59
  type VaultPolicy = z.infer<typeof VaultPolicySchema>;
54
60
  declare const VaultConfigSchema: z.ZodObject<{
55
- policy: z.ZodDefault<z.ZodEnum<["disabled", "manual", "auto_when_qualified"]>>;
61
+ policy: z.ZodDefault<z.ZodEnum<["disabled", "manual"]>>;
56
62
  defaultName: z.ZodOptional<z.ZodString>;
57
63
  defaultSymbol: z.ZodOptional<z.ZodString>;
58
64
  feeRecipient: z.ZodOptional<z.ZodString>;
59
65
  preferVaultTrading: z.ZodDefault<z.ZodBoolean>;
60
66
  }, "strip", z.ZodTypeAny, {
61
- policy: "disabled" | "manual" | "auto_when_qualified";
67
+ policy: "disabled" | "manual";
62
68
  preferVaultTrading: boolean;
63
69
  defaultName?: string | undefined;
64
70
  defaultSymbol?: string | undefined;
65
71
  feeRecipient?: string | undefined;
66
72
  }, {
67
- policy?: "disabled" | "manual" | "auto_when_qualified" | undefined;
73
+ policy?: "disabled" | "manual" | undefined;
68
74
  defaultName?: string | undefined;
69
75
  defaultSymbol?: string | undefined;
70
76
  feeRecipient?: string | undefined;
@@ -88,7 +94,7 @@ type RelayConfig$1 = z.infer<typeof RelayConfigSchema>;
88
94
  declare const AgentConfigSchema: z.ZodObject<{
89
95
  agentId: z.ZodUnion<[z.ZodNumber, z.ZodString]>;
90
96
  name: z.ZodString;
91
- network: z.ZodDefault<z.ZodEnum<["mainnet", "testnet"]>>;
97
+ network: z.ZodDefault<z.ZodLiteral<"mainnet">>;
92
98
  wallet: z.ZodOptional<z.ZodObject<{
93
99
  setup: z.ZodDefault<z.ZodEnum<["generate", "provide"]>>;
94
100
  }, "strip", z.ZodTypeAny, {
@@ -125,33 +131,39 @@ declare const AgentConfigSchema: z.ZodObject<{
125
131
  maxDailyLossBps: z.ZodDefault<z.ZodNumber>;
126
132
  maxConcurrentPositions: z.ZodDefault<z.ZodNumber>;
127
133
  tradingIntervalMs: z.ZodDefault<z.ZodNumber>;
134
+ maxSlippageBps: z.ZodDefault<z.ZodNumber>;
135
+ minTradeValueUSD: z.ZodDefault<z.ZodNumber>;
128
136
  }, "strip", z.ZodTypeAny, {
129
137
  timeHorizon: "intraday" | "swing" | "position";
130
138
  maxPositionSizeBps: number;
131
139
  maxDailyLossBps: number;
132
140
  maxConcurrentPositions: number;
133
141
  tradingIntervalMs: number;
142
+ maxSlippageBps: number;
143
+ minTradeValueUSD: number;
134
144
  }, {
135
145
  timeHorizon?: "intraday" | "swing" | "position" | undefined;
136
146
  maxPositionSizeBps?: number | undefined;
137
147
  maxDailyLossBps?: number | undefined;
138
148
  maxConcurrentPositions?: number | undefined;
139
149
  tradingIntervalMs?: number | undefined;
150
+ maxSlippageBps?: number | undefined;
151
+ minTradeValueUSD?: number | undefined;
140
152
  }>>;
141
153
  vault: z.ZodDefault<z.ZodObject<{
142
- policy: z.ZodDefault<z.ZodEnum<["disabled", "manual", "auto_when_qualified"]>>;
154
+ policy: z.ZodDefault<z.ZodEnum<["disabled", "manual"]>>;
143
155
  defaultName: z.ZodOptional<z.ZodString>;
144
156
  defaultSymbol: z.ZodOptional<z.ZodString>;
145
157
  feeRecipient: z.ZodOptional<z.ZodString>;
146
158
  preferVaultTrading: z.ZodDefault<z.ZodBoolean>;
147
159
  }, "strip", z.ZodTypeAny, {
148
- policy: "disabled" | "manual" | "auto_when_qualified";
160
+ policy: "disabled" | "manual";
149
161
  preferVaultTrading: boolean;
150
162
  defaultName?: string | undefined;
151
163
  defaultSymbol?: string | undefined;
152
164
  feeRecipient?: string | undefined;
153
165
  }, {
154
- policy?: "disabled" | "manual" | "auto_when_qualified" | undefined;
166
+ policy?: "disabled" | "manual" | undefined;
155
167
  defaultName?: string | undefined;
156
168
  defaultSymbol?: string | undefined;
157
169
  feeRecipient?: string | undefined;
@@ -174,7 +186,7 @@ declare const AgentConfigSchema: z.ZodObject<{
174
186
  }, "strip", z.ZodTypeAny, {
175
187
  agentId: string | number;
176
188
  name: string;
177
- network: "mainnet" | "testnet";
189
+ network: "mainnet";
178
190
  llm: {
179
191
  provider: "custom" | "openai" | "anthropic" | "google" | "deepseek" | "mistral" | "groq" | "together" | "ollama";
180
192
  temperature: number;
@@ -190,9 +202,11 @@ declare const AgentConfigSchema: z.ZodObject<{
190
202
  maxDailyLossBps: number;
191
203
  maxConcurrentPositions: number;
192
204
  tradingIntervalMs: number;
205
+ maxSlippageBps: number;
206
+ minTradeValueUSD: number;
193
207
  };
194
208
  vault: {
195
- policy: "disabled" | "manual" | "auto_when_qualified";
209
+ policy: "disabled" | "manual";
196
210
  preferVaultTrading: boolean;
197
211
  defaultName?: string | undefined;
198
212
  defaultSymbol?: string | undefined;
@@ -218,7 +232,7 @@ declare const AgentConfigSchema: z.ZodObject<{
218
232
  temperature?: number | undefined;
219
233
  maxTokens?: number | undefined;
220
234
  };
221
- network?: "mainnet" | "testnet" | undefined;
235
+ network?: "mainnet" | undefined;
222
236
  wallet?: {
223
237
  setup?: "generate" | "provide" | undefined;
224
238
  } | undefined;
@@ -229,9 +243,11 @@ declare const AgentConfigSchema: z.ZodObject<{
229
243
  maxDailyLossBps?: number | undefined;
230
244
  maxConcurrentPositions?: number | undefined;
231
245
  tradingIntervalMs?: number | undefined;
246
+ maxSlippageBps?: number | undefined;
247
+ minTradeValueUSD?: number | undefined;
232
248
  } | undefined;
233
249
  vault?: {
234
- policy?: "disabled" | "manual" | "auto_when_qualified" | undefined;
250
+ policy?: "disabled" | "manual" | undefined;
235
251
  defaultName?: string | undefined;
236
252
  defaultSymbol?: string | undefined;
237
253
  feeRecipient?: string | undefined;
@@ -253,6 +269,17 @@ interface MarketData {
253
269
  prices: Record<string, number>;
254
270
  balances: Record<string, bigint>;
255
271
  portfolioValue: number;
272
+ /** 24h trading volume in USD per token */
273
+ volume24h?: Record<string, number>;
274
+ /** 24h price change percentage per token */
275
+ priceChange24h?: Record<string, number>;
276
+ /** Current Base gas price in wei */
277
+ gasPrice?: bigint;
278
+ /** Network context */
279
+ network?: {
280
+ chainId: number;
281
+ blockNumber?: number;
282
+ };
256
283
  }
257
284
  interface TradeSignal {
258
285
  action: 'buy' | 'sell' | 'hold';
@@ -289,7 +316,7 @@ interface LLMMetadata {
289
316
  * Vault Manager for Trading Agents
290
317
  *
291
318
  * Handles vault creation, qualification checking, and vault-aware trading.
292
- * Respects the agent's vault policy (disabled, manual, auto_when_qualified).
319
+ * Respects the agent's vault policy (disabled, manual).
293
320
  */
294
321
 
295
322
  interface VaultStatus {
@@ -301,14 +328,13 @@ interface VaultStatus {
301
328
  requirementsMet: boolean;
302
329
  requirements: {
303
330
  veXARequired: bigint;
304
- burnFee: bigint;
305
331
  isBypassed: boolean;
306
332
  };
307
333
  }
308
334
  interface VaultManagerConfig {
309
335
  agentId: bigint;
310
336
  agentName: string;
311
- network: 'mainnet' | 'testnet';
337
+ network: 'mainnet';
312
338
  walletKey: `0x${string}`;
313
339
  vaultConfig: VaultConfig;
314
340
  }
@@ -325,6 +351,7 @@ declare class VaultManager {
325
351
  private cachedVaultAddress;
326
352
  private lastVaultCheck;
327
353
  private readonly VAULT_CACHE_TTL;
354
+ private enabled;
328
355
  constructor(config: VaultManagerConfig);
329
356
  /**
330
357
  * Get the agent's vault policy
@@ -340,28 +367,22 @@ declare class VaultManager {
340
367
  getVaultStatus(): Promise<VaultStatus>;
341
368
  /**
342
369
  * Get vault creation requirements
370
+ * Note: No burnFee on mainnet — vault creation requires USDC seed instead
343
371
  */
344
372
  getRequirements(): Promise<{
345
373
  veXARequired: bigint;
346
- burnFee: bigint;
347
374
  isBypassed: boolean;
348
375
  }>;
349
376
  /**
350
377
  * Get the agent's vault address (cached)
351
378
  */
352
379
  getVaultAddress(): Promise<Address | null>;
353
- /**
354
- * Check if the agent should create a vault based on policy and qualification
355
- */
356
- shouldCreateVault(): Promise<{
357
- should: boolean;
358
- reason: string;
359
- }>;
360
380
  /**
361
381
  * Create a vault for the agent
382
+ * @param seedAmount - USDC seed amount in raw units (default: 100e6 = 100 USDC)
362
383
  * @returns Vault address if successful
363
384
  */
364
- createVault(): Promise<{
385
+ createVault(seedAmount?: bigint): Promise<{
365
386
  success: boolean;
366
387
  vaultAddress?: Address;
367
388
  txHash?: Hash;
@@ -384,15 +405,6 @@ declare class VaultManager {
384
405
  txHash?: Hash;
385
406
  error?: string;
386
407
  } | null>;
387
- /**
388
- * Run the auto-creation check (call this periodically in the agent loop)
389
- * Only creates vault if policy is 'auto_when_qualified'
390
- */
391
- checkAndAutoCreateVault(): Promise<{
392
- action: 'created' | 'skipped' | 'already_exists' | 'not_qualified';
393
- vaultAddress?: Address;
394
- reason: string;
395
- }>;
396
408
  }
397
409
 
398
410
  /**
@@ -464,13 +476,13 @@ declare class AgentRuntime {
464
476
  private isRunning;
465
477
  private mode;
466
478
  private configHash;
467
- private lastVaultCheck;
468
479
  private cycleCount;
469
480
  private lastCycleAt;
470
481
  private lastPortfolioValue;
471
482
  private lastEthBalance;
472
483
  private processAlive;
473
- private readonly VAULT_CHECK_INTERVAL;
484
+ private riskUniverse;
485
+ private allowedTokens;
474
486
  constructor(config: RuntimeConfig);
475
487
  /**
476
488
  * Initialize the agent runtime
@@ -490,6 +502,11 @@ declare class AgentRuntime {
490
502
  * that waits for the owner to link it from the website.
491
503
  */
492
504
  private ensureWalletLinked;
505
+ /**
506
+ * Load risk universe and allowed tokens from on-chain registry.
507
+ * This prevents the agent from wasting gas on trades that will revert.
508
+ */
509
+ private loadTradingRestrictions;
493
510
  /**
494
511
  * Sync the LLM config hash to chain for epoch tracking.
495
512
  * If the wallet has insufficient gas, enters a recovery loop
@@ -521,13 +538,10 @@ declare class AgentRuntime {
521
538
  */
522
539
  private runCycle;
523
540
  /**
524
- * Check if ETH balance is below threshold and notify
541
+ * Check if ETH balance is below threshold and notify.
542
+ * Returns true if trading should continue, false if ETH is critically low.
525
543
  */
526
544
  private checkFundsLow;
527
- /**
528
- * Check for vault auto-creation based on policy
529
- */
530
- private checkVaultAutoCreation;
531
545
  /**
532
546
  * Stop the agent process completely
533
547
  */
@@ -537,7 +551,9 @@ declare class AgentRuntime {
537
551
  */
538
552
  private getRpcUrl;
539
553
  /**
540
- * Default tokens to track
554
+ * Default tokens to track.
555
+ * These are validated against the on-chain registry's isTradeAllowed() during init —
556
+ * agents in restricted risk universes will have ineligible tokens filtered out.
541
557
  */
542
558
  private getDefaultTokens;
543
559
  private sleep;
@@ -745,11 +761,14 @@ declare function getAllStrategyTemplates(): StrategyTemplate[];
745
761
 
746
762
  /**
747
763
  * Trade Executor
748
- * Handles execution of trade signals through the ExagentRouter
764
+ * Handles execution of trade signals through the ExagentRouter.
765
+ * All trades go through the router — there is no direct DEX bypass.
766
+ * Pre-checks token eligibility to avoid wasting gas on reverts.
749
767
  */
750
768
  declare class TradeExecutor {
751
769
  private client;
752
770
  private config;
771
+ private allowedTokens;
753
772
  constructor(client: ExagentClient, config: RuntimeConfig);
754
773
  /**
755
774
  * Execute a single trade signal
@@ -770,7 +789,7 @@ declare class TradeExecutor {
770
789
  error?: string;
771
790
  }>>;
772
791
  /**
773
- * Validate a signal against config limits
792
+ * Validate a signal against config limits and token restrictions
774
793
  */
775
794
  private validateSignal;
776
795
  private delay;
@@ -783,7 +802,10 @@ declare class TradeExecutor {
783
802
  declare class RiskManager {
784
803
  private config;
785
804
  private dailyPnL;
805
+ private dailyFees;
786
806
  private lastResetDate;
807
+ /** Minimum trade value in USD — trades below this are rejected as dust */
808
+ private minTradeValueUSD;
787
809
  constructor(config: TradingConfig);
788
810
  /**
789
811
  * Filter signals through risk checks
@@ -794,6 +816,10 @@ declare class RiskManager {
794
816
  * Validate individual signal against risk limits
795
817
  */
796
818
  private validateSignal;
819
+ /**
820
+ * Count non-zero token positions (excluding native ETH and stablecoins used as base currency)
821
+ */
822
+ private countActivePositions;
797
823
  /**
798
824
  * Check if daily loss limit has been hit
799
825
  */
@@ -803,14 +829,23 @@ declare class RiskManager {
803
829
  */
804
830
  private estimateSignalValue;
805
831
  /**
806
- * Update daily PnL after a trade
832
+ * Update daily PnL after a trade (market gains/losses only)
807
833
  */
808
834
  updatePnL(pnl: number): void;
835
+ /**
836
+ * Update daily fees (trading fees, gas costs, etc.)
837
+ * Fees are tracked separately and do NOT count toward the daily loss limit.
838
+ * This prevents protocol fees from triggering circuit breakers.
839
+ */
840
+ updateFees(fees: number): void;
809
841
  /**
810
842
  * Get current risk status
843
+ * @param portfolioValue - Current portfolio value in USD (needed for accurate loss limit)
811
844
  */
812
- getStatus(): {
845
+ getStatus(portfolioValue?: number): {
813
846
  dailyPnL: number;
847
+ dailyFees: number;
848
+ dailyNetPnL: number;
814
849
  dailyLossLimit: number;
815
850
  isLimitHit: boolean;
816
851
  };
@@ -818,22 +853,39 @@ declare class RiskManager {
818
853
 
819
854
  /**
820
855
  * Market Data Service
821
- * Fetches prices and portfolio data for strategy analysis.
856
+ * Fetches real prices from CoinGecko and on-chain balances for strategy analysis.
822
857
  *
823
858
  * Queries real on-chain balances for:
824
859
  * - Native ETH (via eth_getBalance)
825
860
  * - ERC-20 tokens (via balanceOf)
861
+ *
862
+ * Fetches real prices from CoinGecko free API.
863
+ * Refuses to return data if prices are stale (>60s old) to prevent
864
+ * agents from making decisions with outdated price information.
826
865
  */
827
866
  declare class MarketDataService {
828
867
  private rpcUrl;
829
868
  private client;
869
+ /** Cached prices from last fetch */
870
+ private cachedPrices;
871
+ /** Timestamp of last successful price fetch */
872
+ private lastPriceFetchAt;
830
873
  constructor(rpcUrl: string);
874
+ /** Cached volume data */
875
+ private cachedVolume24h;
876
+ /** Cached price change data */
877
+ private cachedPriceChange24h;
831
878
  /**
832
879
  * Fetch current market data for the agent
833
880
  */
834
881
  fetchMarketData(walletAddress: string, tokenAddresses: string[]): Promise<MarketData>;
835
882
  /**
836
- * Fetch token prices from price oracle
883
+ * Check if cached prices are still fresh
884
+ */
885
+ get pricesAreFresh(): boolean;
886
+ /**
887
+ * Fetch token prices from CoinGecko free API
888
+ * Returns cached prices if still fresh (<60s old)
837
889
  */
838
890
  private fetchPrices;
839
891
  /**