@exagent/sdk 0.1.3 → 0.1.5

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.js CHANGED
@@ -23,7 +23,6 @@ __export(index_exports, {
23
23
  CHAIN_CONFIG: () => CHAIN_CONFIG,
24
24
  CONTRACT_ADDRESSES: () => CONTRACT_ADDRESSES,
25
25
  DEX_ADDRESSES: () => DEX_ADDRESSES,
26
- DISCOUNT_TIERS: () => DISCOUNT_TIERS,
27
26
  EXAGENT_API_CONFIG: () => EXAGENT_API_CONFIG,
28
27
  EXAGENT_STAKING_ABI: () => EXAGENT_STAKING_ABI,
29
28
  EXAGENT_VAULT_FACTORY_ABI: () => EXAGENT_VAULT_FACTORY_ABI,
@@ -32,8 +31,10 @@ __export(index_exports, {
32
31
  ExagentStaking: () => ExagentStaking,
33
32
  ExagentVault: () => ExagentVault,
34
33
  ExagentVaultFactory: () => ExagentVaultFactory,
35
- TESTNET_ADDRESSES: () => TESTNET_ADDRESSES,
36
- ZERO_X_CONFIG: () => ZERO_X_CONFIG
34
+ SDK_VERSION: () => SDK_VERSION,
35
+ ZERO_X_CONFIG: () => ZERO_X_CONFIG,
36
+ buildGlobalAgentId: () => buildGlobalAgentId,
37
+ parseGlobalAgentId: () => parseGlobalAgentId
37
38
  });
38
39
  module.exports = __toCommonJS(index_exports);
39
40
 
@@ -49,7 +50,10 @@ var EXAGENT_REGISTRY_ABI = [
49
50
  name: "registerAgent",
50
51
  inputs: [
51
52
  { name: "name", type: "string" },
52
- { name: "metadataURI", type: "string" }
53
+ { name: "metadataURI", type: "string" },
54
+ { name: "riskUniverse", type: "uint8" },
55
+ { name: "maxPositionSizeBps", type: "uint256" },
56
+ { name: "maxDailyLossBps", type: "uint256" }
53
57
  ],
54
58
  outputs: [{ name: "agentId", type: "uint256" }],
55
59
  stateMutability: "nonpayable"
@@ -279,6 +283,62 @@ var EXAGENT_REGISTRY_ABI = [
279
283
  outputs: [{ name: "", type: "bytes32" }],
280
284
  stateMutability: "view"
281
285
  },
286
+ // Mainnet: Agent retirement
287
+ {
288
+ type: "function",
289
+ name: "retireAgent",
290
+ inputs: [{ name: "agentId", type: "uint256" }],
291
+ outputs: [],
292
+ stateMutability: "nonpayable"
293
+ },
294
+ {
295
+ type: "function",
296
+ name: "retired",
297
+ inputs: [{ name: "agentId", type: "uint256" }],
298
+ outputs: [{ type: "bool" }],
299
+ stateMutability: "view"
300
+ },
301
+ {
302
+ type: "function",
303
+ name: "isRetired",
304
+ inputs: [{ name: "agentId", type: "uint256" }],
305
+ outputs: [{ type: "bool" }],
306
+ stateMutability: "view"
307
+ },
308
+ // Mainnet: Risk universe token whitelists
309
+ {
310
+ type: "function",
311
+ name: "isTradeAllowed",
312
+ inputs: [
313
+ { name: "agentId", type: "uint256" },
314
+ { name: "token", type: "address" },
315
+ { name: "aggregator", type: "address" }
316
+ ],
317
+ outputs: [{ type: "bool" }],
318
+ stateMutability: "view"
319
+ },
320
+ {
321
+ type: "function",
322
+ name: "getRiskUniverse",
323
+ inputs: [{ name: "agentId", type: "uint256" }],
324
+ outputs: [{ type: "uint8" }],
325
+ stateMutability: "view"
326
+ },
327
+ {
328
+ type: "function",
329
+ name: "tradeCount",
330
+ inputs: [{ name: "agentId", type: "uint256" }],
331
+ outputs: [{ type: "uint256" }],
332
+ stateMutability: "view"
333
+ },
334
+ // Events
335
+ {
336
+ type: "event",
337
+ name: "AgentRetired",
338
+ inputs: [
339
+ { name: "agentId", type: "uint256", indexed: true }
340
+ ]
341
+ },
282
342
  {
283
343
  type: "event",
284
344
  name: "ConfigUpdated",
@@ -289,7 +349,16 @@ var EXAGENT_REGISTRY_ABI = [
289
349
  { name: "epochId", type: "uint256", indexed: false },
290
350
  { name: "blockNumber", type: "uint256", indexed: false }
291
351
  ]
292
- }
352
+ },
353
+ // Custom errors
354
+ { type: "error", name: "OwnerAlreadyHasAgent", inputs: [{ name: "existingAgentId", type: "uint256" }] },
355
+ { type: "error", name: "InvalidMetadataURI", inputs: [] },
356
+ { type: "error", name: "InvalidName", inputs: [] },
357
+ { type: "error", name: "InvalidRiskUniverse", inputs: [] },
358
+ { type: "error", name: "InvalidTradingConfig", inputs: [] },
359
+ { type: "error", name: "NameAlreadyTaken", inputs: [] },
360
+ { type: "error", name: "AgentNotOwner", inputs: [] },
361
+ { type: "error", name: "AgentIsRetired", inputs: [] }
293
362
  ];
294
363
  var ExagentRegistry = class {
295
364
  address;
@@ -310,9 +379,12 @@ var ExagentRegistry = class {
310
379
  * Register a new agent
311
380
  * @param name Unique agent name (3-32 chars, alphanumeric + spaces/hyphens/underscores)
312
381
  * @param metadataURI IPFS URI for agent metadata
382
+ * @param riskUniverse Risk tier: 0=Core, 1=Established, 2=Derivatives, 3=Emerging, 4=Frontier
383
+ * @param maxPositionSizeBps Maximum position size in basis points (1-10000)
384
+ * @param maxDailyLossBps Maximum daily loss in basis points (1-10000)
313
385
  * @returns Transaction hash
314
386
  */
315
- async register(name, metadataURI) {
387
+ async register(name, metadataURI, riskUniverse = 1, maxPositionSizeBps = 1000n, maxDailyLossBps = 500n) {
316
388
  if (!this.walletClient || !this.account) throw new Error("Wallet client and account required for write operations");
317
389
  const hash = await this.walletClient.writeContract({
318
390
  account: this.account,
@@ -320,7 +392,7 @@ var ExagentRegistry = class {
320
392
  address: this.address,
321
393
  abi: EXAGENT_REGISTRY_ABI,
322
394
  functionName: "registerAgent",
323
- args: [name, metadataURI]
395
+ args: [name, metadataURI, riskUniverse, maxPositionSizeBps, maxDailyLossBps]
324
396
  });
325
397
  return hash;
326
398
  }
@@ -655,8 +727,84 @@ var ExagentRegistry = class {
655
727
  * @returns keccak256 hash of the config
656
728
  */
657
729
  static calculateConfigHash(provider, model) {
658
- const { keccak256: keccak2562, encodePacked: encodePacked2 } = require("viem");
659
- return keccak2562(encodePacked2(["string", "string"], [provider, model]));
730
+ return (0, import_viem.keccak256)((0, import_viem.encodePacked)(["string", "string"], [provider, model]));
731
+ }
732
+ // ============ Agent Retirement ============
733
+ /**
734
+ * Retire an agent — marks it as retired, unlinks all wallets, allows new agent registration
735
+ * @param agentId The agent's ID
736
+ * @returns Transaction hash
737
+ */
738
+ async retireAgent(agentId) {
739
+ if (!this.walletClient || !this.account) throw new Error("Wallet client and account required for write operations");
740
+ const hash = await this.walletClient.writeContract({
741
+ account: this.account,
742
+ chain: this.chain,
743
+ address: this.address,
744
+ abi: EXAGENT_REGISTRY_ABI,
745
+ functionName: "retireAgent",
746
+ args: [agentId]
747
+ });
748
+ return hash;
749
+ }
750
+ /**
751
+ * Check if an agent is retired
752
+ * @param agentId The agent's ID
753
+ * @returns True if agent is retired
754
+ */
755
+ async isRetired(agentId) {
756
+ const result = await this.publicClient.readContract({
757
+ address: this.address,
758
+ abi: EXAGENT_REGISTRY_ABI,
759
+ functionName: "isRetired",
760
+ args: [agentId]
761
+ });
762
+ return result;
763
+ }
764
+ // ============ Risk Universe Token Eligibility ============
765
+ /**
766
+ * Check if a token trade is allowed for an agent's risk universe
767
+ * @param agentId The agent's ID
768
+ * @param token The token address to check
769
+ * @param aggregator The aggregator being used (for trusted aggregator bypass)
770
+ * @returns True if the trade is allowed
771
+ */
772
+ async isTradeAllowed(agentId, token, aggregator) {
773
+ const result = await this.publicClient.readContract({
774
+ address: this.address,
775
+ abi: EXAGENT_REGISTRY_ABI,
776
+ functionName: "isTradeAllowed",
777
+ args: [agentId, token, aggregator]
778
+ });
779
+ return result;
780
+ }
781
+ /**
782
+ * Get the risk universe for an agent
783
+ * @param agentId The agent's ID
784
+ * @returns Risk universe (0=Core, 1=Established, 2=Derivatives, 3=Emerging, 4=Frontier)
785
+ */
786
+ async getRiskUniverse(agentId) {
787
+ const result = await this.publicClient.readContract({
788
+ address: this.address,
789
+ abi: EXAGENT_REGISTRY_ABI,
790
+ functionName: "getRiskUniverse",
791
+ args: [agentId]
792
+ });
793
+ return Number(result);
794
+ }
795
+ /**
796
+ * Get trade count for an agent
797
+ * @param agentId The agent's ID
798
+ * @returns Number of recorded trades
799
+ */
800
+ async getTradeCount(agentId) {
801
+ const result = await this.publicClient.readContract({
802
+ address: this.address,
803
+ abi: EXAGENT_REGISTRY_ABI,
804
+ functionName: "tradeCount",
805
+ args: [agentId]
806
+ });
807
+ return result;
660
808
  }
661
809
  };
662
810
 
@@ -747,6 +895,9 @@ var ExagentVault = class {
747
895
  this.address = vaultAddress;
748
896
  this.publicClient = publicClient;
749
897
  this.walletClient = walletClient;
898
+ if (!chain) {
899
+ throw new Error("Chain parameter is required");
900
+ }
750
901
  this.chain = chain;
751
902
  this.account = account;
752
903
  }
@@ -1093,17 +1244,34 @@ var ExagentVault = class {
1093
1244
  var EXAGENT_STAKING_ABI = [
1094
1245
  // ============ State Variables ============
1095
1246
  { type: "function", name: "exaToken", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
1096
- { type: "function", name: "totalStaked", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1247
+ { type: "function", name: "totalDeposited", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1248
+ { type: "function", name: "totalLocked", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1097
1249
  { type: "function", name: "totalVeEXA", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1098
- { type: "function", name: "registry", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
1250
+ { type: "function", name: "totalEffectiveVeEXA", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1099
1251
  // ============ Constants ============
1100
1252
  { type: "function", name: "MIN_LOCK_DURATION", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1101
1253
  { type: "function", name: "MAX_LOCK_DURATION", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1254
+ { type: "function", name: "VAULT_ACCESS_THRESHOLD", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1102
1255
  { type: "function", name: "PRECISION", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1103
- // ============ Staking Functions ============
1256
+ // ============ Phase 1: Deposit / Withdraw ============
1257
+ {
1258
+ type: "function",
1259
+ name: "deposit",
1260
+ inputs: [{ name: "amount", type: "uint256" }],
1261
+ outputs: [],
1262
+ stateMutability: "nonpayable"
1263
+ },
1264
+ {
1265
+ type: "function",
1266
+ name: "withdraw",
1267
+ inputs: [{ name: "amount", type: "uint256" }],
1268
+ outputs: [],
1269
+ stateMutability: "nonpayable"
1270
+ },
1271
+ // ============ Phase 2: Lock / Unlock ============
1104
1272
  {
1105
1273
  type: "function",
1106
- name: "stake",
1274
+ name: "lock",
1107
1275
  inputs: [
1108
1276
  { name: "amount", type: "uint256" },
1109
1277
  { name: "lockDuration", type: "uint256" }
@@ -1111,7 +1279,6 @@ var EXAGENT_STAKING_ABI = [
1111
1279
  outputs: [],
1112
1280
  stateMutability: "nonpayable"
1113
1281
  },
1114
- { type: "function", name: "unstake", inputs: [], outputs: [], stateMutability: "nonpayable" },
1115
1282
  {
1116
1283
  type: "function",
1117
1284
  name: "extendLock",
@@ -1119,6 +1286,8 @@ var EXAGENT_STAKING_ABI = [
1119
1286
  outputs: [],
1120
1287
  stateMutability: "nonpayable"
1121
1288
  },
1289
+ { type: "function", name: "unlock", inputs: [], outputs: [], stateMutability: "nonpayable" },
1290
+ { type: "function", name: "emergencyWithdraw", inputs: [], outputs: [], stateMutability: "nonpayable" },
1122
1291
  // ============ Reward Functions ============
1123
1292
  { type: "function", name: "claimRewards", inputs: [], outputs: [], stateMutability: "nonpayable" },
1124
1293
  { type: "function", name: "claimRewardsMulti", inputs: [], outputs: [], stateMutability: "nonpayable" },
@@ -1129,26 +1298,17 @@ var EXAGENT_STAKING_ABI = [
1129
1298
  outputs: [],
1130
1299
  stateMutability: "nonpayable"
1131
1300
  },
1132
- // ============ Delegation Functions ============
1133
- {
1134
- type: "function",
1135
- name: "delegate",
1136
- inputs: [{ name: "agentId", type: "uint256" }],
1137
- outputs: [],
1138
- stateMutability: "nonpayable"
1139
- },
1140
- { type: "function", name: "undelegate", inputs: [], outputs: [], stateMutability: "nonpayable" },
1301
+ // ============ View Functions ============
1141
1302
  {
1142
1303
  type: "function",
1143
- name: "redelegate",
1144
- inputs: [{ name: "newAgentId", type: "uint256" }],
1145
- outputs: [],
1146
- stateMutability: "nonpayable"
1304
+ name: "depositedAmount",
1305
+ inputs: [{ name: "user", type: "address" }],
1306
+ outputs: [{ type: "uint256" }],
1307
+ stateMutability: "view"
1147
1308
  },
1148
- // ============ View Functions ============
1149
1309
  {
1150
1310
  type: "function",
1151
- name: "stakes",
1311
+ name: "locks",
1152
1312
  inputs: [{ name: "user", type: "address" }],
1153
1313
  outputs: [
1154
1314
  { name: "amount", type: "uint256" },
@@ -1165,6 +1325,13 @@ var EXAGENT_STAKING_ABI = [
1165
1325
  outputs: [{ type: "uint256" }],
1166
1326
  stateMutability: "view"
1167
1327
  },
1328
+ {
1329
+ type: "function",
1330
+ name: "getEffectiveVeEXA",
1331
+ inputs: [{ name: "user", type: "address" }],
1332
+ outputs: [{ type: "uint256" }],
1333
+ stateMutability: "view"
1334
+ },
1168
1335
  {
1169
1336
  type: "function",
1170
1337
  name: "calculateVeEXA",
@@ -1194,61 +1361,40 @@ var EXAGENT_STAKING_ABI = [
1194
1361
  },
1195
1362
  {
1196
1363
  type: "function",
1197
- name: "getDelegatedAgent",
1364
+ name: "getEarningsTier",
1198
1365
  inputs: [{ name: "user", type: "address" }],
1199
- outputs: [{ type: "uint256" }],
1200
- stateMutability: "view"
1201
- },
1202
- {
1203
- type: "function",
1204
- name: "getAgentDelegation",
1205
- inputs: [{ name: "agentId", type: "uint256" }],
1206
1366
  outputs: [
1207
- { name: "vexa", type: "uint256" },
1208
- { name: "count", type: "uint256" }
1367
+ { name: "multiplierBps", type: "uint256" },
1368
+ { name: "tierName", type: "string" }
1209
1369
  ],
1210
1370
  stateMutability: "view"
1211
1371
  },
1212
1372
  {
1213
1373
  type: "function",
1214
- name: "getDiscountTier",
1374
+ name: "getEmergencyWithdrawPenalty",
1215
1375
  inputs: [{ name: "user", type: "address" }],
1216
- outputs: [{ name: "discountBps", type: "uint256" }],
1217
- stateMutability: "view"
1218
- },
1219
- {
1220
- type: "function",
1221
- name: "getRewardTokens",
1222
- inputs: [],
1223
- outputs: [{ type: "address[]" }],
1376
+ outputs: [{ name: "penaltyBps", type: "uint256" }],
1224
1377
  stateMutability: "view"
1225
1378
  },
1226
1379
  {
1227
1380
  type: "function",
1228
- name: "delegatedTo",
1381
+ name: "hasVaultAccess",
1229
1382
  inputs: [{ name: "user", type: "address" }],
1230
- outputs: [{ type: "uint256" }],
1383
+ outputs: [{ type: "bool" }],
1231
1384
  stateMutability: "view"
1232
1385
  },
1233
1386
  {
1234
1387
  type: "function",
1235
- name: "userDelegatedVeEXA",
1388
+ name: "getUnlockedBalance",
1236
1389
  inputs: [{ name: "user", type: "address" }],
1237
1390
  outputs: [{ type: "uint256" }],
1238
1391
  stateMutability: "view"
1239
1392
  },
1240
1393
  {
1241
1394
  type: "function",
1242
- name: "agentDelegatedVeEXA",
1243
- inputs: [{ name: "agentId", type: "uint256" }],
1244
- outputs: [{ type: "uint256" }],
1245
- stateMutability: "view"
1246
- },
1247
- {
1248
- type: "function",
1249
- name: "agentDelegatorCount",
1250
- inputs: [{ name: "agentId", type: "uint256" }],
1251
- outputs: [{ type: "uint256" }],
1395
+ name: "getRewardTokens",
1396
+ inputs: [],
1397
+ outputs: [{ type: "address[]" }],
1252
1398
  stateMutability: "view"
1253
1399
  },
1254
1400
  {
@@ -1261,35 +1407,36 @@ var EXAGENT_STAKING_ABI = [
1261
1407
  // ============ Events ============
1262
1408
  {
1263
1409
  type: "event",
1264
- name: "Staked",
1410
+ name: "Deposited",
1265
1411
  inputs: [
1266
1412
  { name: "user", type: "address", indexed: true },
1267
1413
  { name: "amount", type: "uint256", indexed: false },
1268
- { name: "lockDuration", type: "uint256", indexed: false },
1269
- { name: "unlockTime", type: "uint256", indexed: false },
1270
- { name: "vEXABalance", type: "uint256", indexed: false }
1414
+ { name: "totalDeposited", type: "uint256", indexed: false }
1271
1415
  ]
1272
1416
  },
1273
1417
  {
1274
1418
  type: "event",
1275
- name: "Unstaked",
1419
+ name: "Withdrawn",
1276
1420
  inputs: [
1277
1421
  { name: "user", type: "address", indexed: true },
1278
- { name: "amount", type: "uint256", indexed: false }
1422
+ { name: "amount", type: "uint256", indexed: false },
1423
+ { name: "totalDeposited", type: "uint256", indexed: false }
1279
1424
  ]
1280
1425
  },
1281
1426
  {
1282
1427
  type: "event",
1283
- name: "LockExtended",
1428
+ name: "Locked",
1284
1429
  inputs: [
1285
1430
  { name: "user", type: "address", indexed: true },
1286
- { name: "newUnlockTime", type: "uint256", indexed: false },
1287
- { name: "newVeEXABalance", type: "uint256", indexed: false }
1431
+ { name: "amount", type: "uint256", indexed: false },
1432
+ { name: "lockDuration", type: "uint256", indexed: false },
1433
+ { name: "unlockTime", type: "uint256", indexed: false },
1434
+ { name: "vEXABalance", type: "uint256", indexed: false }
1288
1435
  ]
1289
1436
  },
1290
1437
  {
1291
1438
  type: "event",
1292
- name: "RewardsClaimed",
1439
+ name: "Unlocked",
1293
1440
  inputs: [
1294
1441
  { name: "user", type: "address", indexed: true },
1295
1442
  { name: "amount", type: "uint256", indexed: false }
@@ -1297,20 +1444,29 @@ var EXAGENT_STAKING_ABI = [
1297
1444
  },
1298
1445
  {
1299
1446
  type: "event",
1300
- name: "Delegated",
1447
+ name: "EmergencyWithdrawal",
1301
1448
  inputs: [
1302
- { name: "delegator", type: "address", indexed: true },
1303
- { name: "agentId", type: "uint256", indexed: true },
1304
- { name: "veEXAAmount", type: "uint256", indexed: false }
1449
+ { name: "user", type: "address", indexed: true },
1450
+ { name: "returned", type: "uint256", indexed: false },
1451
+ { name: "penalty", type: "uint256", indexed: false },
1452
+ { name: "penaltyBps", type: "uint256", indexed: false }
1305
1453
  ]
1306
1454
  },
1307
1455
  {
1308
1456
  type: "event",
1309
- name: "Undelegated",
1457
+ name: "LockExtended",
1310
1458
  inputs: [
1311
- { name: "delegator", type: "address", indexed: true },
1312
- { name: "agentId", type: "uint256", indexed: true },
1313
- { name: "veEXAAmount", type: "uint256", indexed: false }
1459
+ { name: "user", type: "address", indexed: true },
1460
+ { name: "newUnlockTime", type: "uint256", indexed: false },
1461
+ { name: "newVeEXABalance", type: "uint256", indexed: false }
1462
+ ]
1463
+ },
1464
+ {
1465
+ type: "event",
1466
+ name: "RewardsClaimed",
1467
+ inputs: [
1468
+ { name: "user", type: "address", indexed: true },
1469
+ { name: "amount", type: "uint256", indexed: false }
1314
1470
  ]
1315
1471
  },
1316
1472
  {
@@ -1335,15 +1491,6 @@ var ERC20_APPROVE_ABI2 = [
1335
1491
  stateMutability: "nonpayable"
1336
1492
  }
1337
1493
  ];
1338
- var DISCOUNT_TIERS = {
1339
- none: 0,
1340
- bronze: 1e3,
1341
- // 10% discount at 10,000 vEXA
1342
- silver: 2500,
1343
- // 25% discount at 50,000 vEXA
1344
- gold: 5e3
1345
- // 50% discount at 100,000 vEXA
1346
- };
1347
1494
  var ExagentStaking = class {
1348
1495
  address;
1349
1496
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -1356,108 +1503,119 @@ var ExagentStaking = class {
1356
1503
  this.address = stakingAddress;
1357
1504
  this.publicClient = publicClient;
1358
1505
  this.walletClient = walletClient;
1506
+ if (!chain) {
1507
+ throw new Error("Chain parameter is required");
1508
+ }
1359
1509
  this.chain = chain;
1360
1510
  this.account = account;
1361
1511
  }
1362
- // ============ Staking Write Functions ============
1512
+ // ============ Phase 1: Deposit / Withdraw ============
1363
1513
  /**
1364
- * Stake EXA tokens to receive vEXA voting power
1365
- * @param amount Amount of EXA to stake (in wei)
1366
- * @param lockDuration Lock duration in seconds (30 days to 2 years)
1514
+ * Deposit EXA tokens for vault access (no lock required)
1515
+ * @param amount Amount of EXA to deposit (in wei)
1367
1516
  * @returns Transaction hash
1368
1517
  *
1369
1518
  * @example
1370
1519
  * ```typescript
1371
- * // Stake 1000 EXA for 6 months
1372
- * const tx = await staking.stake(
1373
- * parseEther('1000'),
1374
- * BigInt(180 * 24 * 60 * 60) // 180 days in seconds
1375
- * );
1520
+ * // Deposit 1000 EXA to unlock vault access
1521
+ * const tx = await staking.deposit(parseEther('1000'));
1376
1522
  * ```
1377
1523
  */
1378
- async stake(amount, lockDuration) {
1524
+ async deposit(amount) {
1379
1525
  if (!this.walletClient || !this.account) {
1380
1526
  throw new Error("Wallet client required for write operations");
1381
1527
  }
1382
1528
  const hash = await this.walletClient.writeContract({
1383
1529
  address: this.address,
1384
1530
  abi: EXAGENT_STAKING_ABI,
1385
- functionName: "stake",
1386
- args: [amount, lockDuration],
1531
+ functionName: "deposit",
1532
+ args: [amount],
1387
1533
  account: this.account,
1388
1534
  chain: this.chain
1389
1535
  });
1390
1536
  return hash;
1391
1537
  }
1392
1538
  /**
1393
- * Unstake EXA tokens after lock expires
1539
+ * Withdraw unlocked EXA tokens (instant, no penalty)
1540
+ * @param amount Amount of EXA to withdraw (in wei)
1394
1541
  * @returns Transaction hash
1395
- * @throws Error if lock has not expired
1396
1542
  */
1397
- async unstake() {
1543
+ async withdraw(amount) {
1398
1544
  if (!this.walletClient || !this.account) {
1399
1545
  throw new Error("Wallet client required for write operations");
1400
1546
  }
1401
1547
  const hash = await this.walletClient.writeContract({
1402
1548
  address: this.address,
1403
1549
  abi: EXAGENT_STAKING_ABI,
1404
- functionName: "unstake",
1405
- args: [],
1550
+ functionName: "withdraw",
1551
+ args: [amount],
1406
1552
  account: this.account,
1407
1553
  chain: this.chain
1408
1554
  });
1409
1555
  return hash;
1410
1556
  }
1557
+ // ============ Phase 2: Lock / Unlock ============
1411
1558
  /**
1412
- * Extend lock duration for additional voting power
1413
- * @param newLockDuration New lock duration in seconds (must be longer than remaining)
1559
+ * Lock deposited EXA to receive vEXA voting power and earn rewards
1560
+ * @param amount Amount of deposited EXA to lock (in wei)
1561
+ * @param lockDuration Lock duration in seconds (30 days to 2 years)
1414
1562
  * @returns Transaction hash
1563
+ *
1564
+ * @example
1565
+ * ```typescript
1566
+ * // Lock 1000 EXA for 6 months
1567
+ * const tx = await staking.lock(
1568
+ * parseEther('1000'),
1569
+ * ExagentStaking.LOCK_6_MONTHS
1570
+ * );
1571
+ * ```
1415
1572
  */
1416
- async extendLock(newLockDuration) {
1573
+ async lock(amount, lockDuration) {
1417
1574
  if (!this.walletClient || !this.account) {
1418
1575
  throw new Error("Wallet client required for write operations");
1419
1576
  }
1420
1577
  const hash = await this.walletClient.writeContract({
1421
1578
  address: this.address,
1422
1579
  abi: EXAGENT_STAKING_ABI,
1423
- functionName: "extendLock",
1424
- args: [newLockDuration],
1580
+ functionName: "lock",
1581
+ args: [amount, lockDuration],
1425
1582
  account: this.account,
1426
1583
  chain: this.chain
1427
1584
  });
1428
1585
  return hash;
1429
1586
  }
1430
- // ============ Reward Write Functions ============
1431
1587
  /**
1432
- * Claim accumulated EXA rewards
1588
+ * Extend lock duration for additional voting power
1589
+ * @param newLockDuration New lock duration in seconds (must be longer than remaining)
1433
1590
  * @returns Transaction hash
1434
1591
  */
1435
- async claimRewards() {
1592
+ async extendLock(newLockDuration) {
1436
1593
  if (!this.walletClient || !this.account) {
1437
1594
  throw new Error("Wallet client required for write operations");
1438
1595
  }
1439
1596
  const hash = await this.walletClient.writeContract({
1440
1597
  address: this.address,
1441
1598
  abi: EXAGENT_STAKING_ABI,
1442
- functionName: "claimRewards",
1443
- args: [],
1599
+ functionName: "extendLock",
1600
+ args: [newLockDuration],
1444
1601
  account: this.account,
1445
1602
  chain: this.chain
1446
1603
  });
1447
1604
  return hash;
1448
1605
  }
1449
1606
  /**
1450
- * Claim all pending multi-token rewards (ETH, USDC, etc.)
1607
+ * Unlock EXA after lock expires (normal path — no penalty)
1608
+ * Returns locked amount to unlocked deposited balance.
1451
1609
  * @returns Transaction hash
1452
1610
  */
1453
- async claimRewardsMulti() {
1611
+ async unlock() {
1454
1612
  if (!this.walletClient || !this.account) {
1455
1613
  throw new Error("Wallet client required for write operations");
1456
1614
  }
1457
1615
  const hash = await this.walletClient.writeContract({
1458
1616
  address: this.address,
1459
1617
  abi: EXAGENT_STAKING_ABI,
1460
- functionName: "claimRewardsMulti",
1618
+ functionName: "unlock",
1461
1619
  args: [],
1462
1620
  account: this.account,
1463
1621
  chain: this.chain
@@ -1465,56 +1623,56 @@ var ExagentStaking = class {
1465
1623
  return hash;
1466
1624
  }
1467
1625
  /**
1468
- * Claim pending rewards for a specific token
1469
- * @param token The reward token address to claim
1626
+ * Emergency withdrawal instant exit from lock with graduated penalty
1627
+ * Two-phase penalty: 50%→20% over the first quarter of the lock, then flat 20% until expiry.
1628
+ * Penalty goes to treasury. Remaining returns to unlocked deposit balance.
1470
1629
  * @returns Transaction hash
1471
1630
  */
1472
- async claimRewardsToken(token) {
1631
+ async emergencyWithdraw() {
1473
1632
  if (!this.walletClient || !this.account) {
1474
1633
  throw new Error("Wallet client required for write operations");
1475
1634
  }
1476
1635
  const hash = await this.walletClient.writeContract({
1477
1636
  address: this.address,
1478
1637
  abi: EXAGENT_STAKING_ABI,
1479
- functionName: "claimRewardsToken",
1480
- args: [token],
1638
+ functionName: "emergencyWithdraw",
1639
+ args: [],
1481
1640
  account: this.account,
1482
1641
  chain: this.chain
1483
1642
  });
1484
1643
  return hash;
1485
1644
  }
1486
- // ============ Delegation Write Functions ============
1645
+ // ============ Reward Functions ============
1487
1646
  /**
1488
- * Delegate vEXA voting power to an agent ("Agent Wars")
1489
- * @param agentId The agent ID to delegate to
1647
+ * Claim accumulated EXA rewards
1490
1648
  * @returns Transaction hash
1491
1649
  */
1492
- async delegate(agentId) {
1650
+ async claimRewards() {
1493
1651
  if (!this.walletClient || !this.account) {
1494
1652
  throw new Error("Wallet client required for write operations");
1495
1653
  }
1496
1654
  const hash = await this.walletClient.writeContract({
1497
1655
  address: this.address,
1498
1656
  abi: EXAGENT_STAKING_ABI,
1499
- functionName: "delegate",
1500
- args: [agentId],
1657
+ functionName: "claimRewards",
1658
+ args: [],
1501
1659
  account: this.account,
1502
1660
  chain: this.chain
1503
1661
  });
1504
1662
  return hash;
1505
1663
  }
1506
1664
  /**
1507
- * Remove delegation from current agent
1665
+ * Claim all pending multi-token rewards (ETH, USDC, etc.)
1508
1666
  * @returns Transaction hash
1509
1667
  */
1510
- async undelegate() {
1668
+ async claimRewardsMulti() {
1511
1669
  if (!this.walletClient || !this.account) {
1512
1670
  throw new Error("Wallet client required for write operations");
1513
1671
  }
1514
1672
  const hash = await this.walletClient.writeContract({
1515
1673
  address: this.address,
1516
1674
  abi: EXAGENT_STAKING_ABI,
1517
- functionName: "undelegate",
1675
+ functionName: "claimRewardsMulti",
1518
1676
  args: [],
1519
1677
  account: this.account,
1520
1678
  chain: this.chain
@@ -1522,19 +1680,19 @@ var ExagentStaking = class {
1522
1680
  return hash;
1523
1681
  }
1524
1682
  /**
1525
- * Re-delegate to a different agent (undelegate + delegate in one tx)
1526
- * @param newAgentId The new agent ID to delegate to
1683
+ * Claim pending rewards for a specific token
1684
+ * @param token The reward token address to claim
1527
1685
  * @returns Transaction hash
1528
1686
  */
1529
- async redelegate(newAgentId) {
1687
+ async claimRewardsToken(token) {
1530
1688
  if (!this.walletClient || !this.account) {
1531
1689
  throw new Error("Wallet client required for write operations");
1532
1690
  }
1533
1691
  const hash = await this.walletClient.writeContract({
1534
1692
  address: this.address,
1535
1693
  abi: EXAGENT_STAKING_ABI,
1536
- functionName: "redelegate",
1537
- args: [newAgentId],
1694
+ functionName: "claimRewardsToken",
1695
+ args: [token],
1538
1696
  account: this.account,
1539
1697
  chain: this.chain
1540
1698
  });
@@ -1542,20 +1700,26 @@ var ExagentStaking = class {
1542
1700
  }
1543
1701
  // ============ Read Functions ============
1544
1702
  /**
1545
- * Get comprehensive staking info for a user
1703
+ * Get comprehensive staking info for a user (deposit + lock)
1546
1704
  * @param userAddress Address to check (defaults to connected wallet)
1547
- * @returns Staking info with amount, unlock time, and vEXA balance
1705
+ * @returns Combined staking info
1548
1706
  */
1549
- async getStakeInfo(userAddress) {
1707
+ async getStakingInfo(userAddress) {
1550
1708
  const user = userAddress ?? this.account?.address;
1551
1709
  if (!user) {
1552
1710
  throw new Error("User address required");
1553
1711
  }
1554
- const [stakeResult, currentVeEXA] = await Promise.all([
1712
+ const [deposited, lockResult, currentVeEXA, vaultAccess, unlockedBalance] = await Promise.all([
1713
+ this.publicClient.readContract({
1714
+ address: this.address,
1715
+ abi: EXAGENT_STAKING_ABI,
1716
+ functionName: "depositedAmount",
1717
+ args: [user]
1718
+ }),
1555
1719
  this.publicClient.readContract({
1556
1720
  address: this.address,
1557
1721
  abi: EXAGENT_STAKING_ABI,
1558
- functionName: "stakes",
1722
+ functionName: "locks",
1559
1723
  args: [user]
1560
1724
  }),
1561
1725
  this.publicClient.readContract({
@@ -1563,20 +1727,88 @@ var ExagentStaking = class {
1563
1727
  abi: EXAGENT_STAKING_ABI,
1564
1728
  functionName: "getVeEXABalance",
1565
1729
  args: [user]
1730
+ }),
1731
+ this.publicClient.readContract({
1732
+ address: this.address,
1733
+ abi: EXAGENT_STAKING_ABI,
1734
+ functionName: "hasVaultAccess",
1735
+ args: [user]
1736
+ }),
1737
+ this.publicClient.readContract({
1738
+ address: this.address,
1739
+ abi: EXAGENT_STAKING_ABI,
1740
+ functionName: "getUnlockedBalance",
1741
+ args: [user]
1566
1742
  })
1567
1743
  ]);
1568
- const stake = stakeResult;
1744
+ const lockData = lockResult;
1745
+ const depositedBigint = deposited;
1746
+ const lockedAmount = lockData[0];
1569
1747
  const now = BigInt(Math.floor(Date.now() / 1e3));
1570
- const isUnlocked = stake[1] <= now;
1571
- const remainingLockTime = isUnlocked ? 0n : stake[1] - now;
1748
+ const depositInfo = {
1749
+ deposited: depositedBigint,
1750
+ locked: lockedAmount,
1751
+ unlocked: unlockedBalance,
1752
+ hasVaultAccess: vaultAccess
1753
+ };
1754
+ let lockInfo = null;
1755
+ if (lockedAmount > 0n) {
1756
+ const isUnlocked = lockData[1] <= now;
1757
+ const remainingLockTime = isUnlocked ? 0n : lockData[1] - now;
1758
+ lockInfo = {
1759
+ amount: lockData[0],
1760
+ unlockTime: lockData[1],
1761
+ lockDuration: lockData[2],
1762
+ vEXABalance: lockData[3],
1763
+ currentVeEXA,
1764
+ isUnlocked,
1765
+ remainingLockTime
1766
+ };
1767
+ }
1768
+ return { deposit: depositInfo, lock: lockInfo };
1769
+ }
1770
+ /**
1771
+ * Get deposit info for a user
1772
+ * @param userAddress Address to check (defaults to connected wallet)
1773
+ * @returns Deposit info
1774
+ */
1775
+ async getDepositInfo(userAddress) {
1776
+ const user = userAddress ?? this.account?.address;
1777
+ if (!user) {
1778
+ throw new Error("User address required");
1779
+ }
1780
+ const [deposited, lockResult, vaultAccess, unlockedBalance] = await Promise.all([
1781
+ this.publicClient.readContract({
1782
+ address: this.address,
1783
+ abi: EXAGENT_STAKING_ABI,
1784
+ functionName: "depositedAmount",
1785
+ args: [user]
1786
+ }),
1787
+ this.publicClient.readContract({
1788
+ address: this.address,
1789
+ abi: EXAGENT_STAKING_ABI,
1790
+ functionName: "locks",
1791
+ args: [user]
1792
+ }),
1793
+ this.publicClient.readContract({
1794
+ address: this.address,
1795
+ abi: EXAGENT_STAKING_ABI,
1796
+ functionName: "hasVaultAccess",
1797
+ args: [user]
1798
+ }),
1799
+ this.publicClient.readContract({
1800
+ address: this.address,
1801
+ abi: EXAGENT_STAKING_ABI,
1802
+ functionName: "getUnlockedBalance",
1803
+ args: [user]
1804
+ })
1805
+ ]);
1806
+ const lockData = lockResult;
1572
1807
  return {
1573
- amount: stake[0],
1574
- unlockTime: stake[1],
1575
- lockDuration: stake[2],
1576
- vEXABalance: stake[3],
1577
- currentVeEXA,
1578
- isUnlocked,
1579
- remainingLockTime
1808
+ deposited,
1809
+ locked: lockData[0],
1810
+ unlocked: unlockedBalance,
1811
+ hasVaultAccess: vaultAccess
1580
1812
  };
1581
1813
  }
1582
1814
  /**
@@ -1597,11 +1829,28 @@ var ExagentStaking = class {
1597
1829
  });
1598
1830
  }
1599
1831
  /**
1600
- * Get the agent ID a user is delegating to
1832
+ * Get effective vEXA (with tier multiplier applied)
1833
+ * @param userAddress Address to check (defaults to connected wallet)
1834
+ * @returns Effective vEXA balance
1835
+ */
1836
+ async getEffectiveVeEXA(userAddress) {
1837
+ const user = userAddress ?? this.account?.address;
1838
+ if (!user) {
1839
+ throw new Error("User address required");
1840
+ }
1841
+ return this.publicClient.readContract({
1842
+ address: this.address,
1843
+ abi: EXAGENT_STAKING_ABI,
1844
+ functionName: "getEffectiveVeEXA",
1845
+ args: [user]
1846
+ });
1847
+ }
1848
+ /**
1849
+ * Check if user has vault access (meets deposit threshold)
1601
1850
  * @param userAddress Address to check (defaults to connected wallet)
1602
- * @returns Agent ID (0 if not delegating)
1851
+ * @returns True if user can access vaults
1603
1852
  */
1604
- async getDelegatedAgent(userAddress) {
1853
+ async hasVaultAccess(userAddress) {
1605
1854
  const user = userAddress ?? this.account?.address;
1606
1855
  if (!user) {
1607
1856
  throw new Error("User address required");
@@ -1609,52 +1858,47 @@ var ExagentStaking = class {
1609
1858
  return this.publicClient.readContract({
1610
1859
  address: this.address,
1611
1860
  abi: EXAGENT_STAKING_ABI,
1612
- functionName: "getDelegatedAgent",
1861
+ functionName: "hasVaultAccess",
1613
1862
  args: [user]
1614
1863
  });
1615
1864
  }
1616
1865
  /**
1617
- * Get delegation stats for an agent
1618
- * @param agentId The agent ID to check
1619
- * @returns Delegation info with total vEXA and delegator count
1866
+ * Get earnings tier for a user (Bronze/Silver/Gold/Platinum/Diamond)
1867
+ * @param userAddress Address to check (defaults to connected wallet)
1868
+ * @returns Tier info with multiplier and name
1620
1869
  */
1621
- async getAgentDelegation(agentId) {
1870
+ async getEarningsTier(userAddress) {
1871
+ const user = userAddress ?? this.account?.address;
1872
+ if (!user) {
1873
+ throw new Error("User address required");
1874
+ }
1622
1875
  const result = await this.publicClient.readContract({
1623
1876
  address: this.address,
1624
1877
  abi: EXAGENT_STAKING_ABI,
1625
- functionName: "getAgentDelegation",
1626
- args: [agentId]
1878
+ functionName: "getEarningsTier",
1879
+ args: [user]
1627
1880
  });
1628
1881
  return {
1629
- totalVeEXA: result[0],
1630
- delegatorCount: result[1]
1882
+ multiplierBps: result[0],
1883
+ tierName: result[1]
1631
1884
  };
1632
1885
  }
1633
1886
  /**
1634
- * Get trading fee discount tier for a user
1887
+ * Get current emergency withdrawal penalty for a user
1635
1888
  * @param userAddress Address to check (defaults to connected wallet)
1636
- * @returns Discount tier name and basis points
1889
+ * @returns Penalty in basis points (5000 = 50% at lock start, ramps to 2000 over first 25% of lock, then flat 2000)
1637
1890
  */
1638
- async getDiscountTier(userAddress) {
1891
+ async getEmergencyWithdrawPenalty(userAddress) {
1639
1892
  const user = userAddress ?? this.account?.address;
1640
1893
  if (!user) {
1641
1894
  throw new Error("User address required");
1642
1895
  }
1643
- const discountBps = await this.publicClient.readContract({
1896
+ return this.publicClient.readContract({
1644
1897
  address: this.address,
1645
1898
  abi: EXAGENT_STAKING_ABI,
1646
- functionName: "getDiscountTier",
1899
+ functionName: "getEmergencyWithdrawPenalty",
1647
1900
  args: [user]
1648
1901
  });
1649
- let tier = "none";
1650
- if (discountBps >= 5000n) {
1651
- tier = "gold";
1652
- } else if (discountBps >= 2500n) {
1653
- tier = "silver";
1654
- } else if (discountBps >= 1000n) {
1655
- tier = "bronze";
1656
- }
1657
- return { tier, discountBps };
1658
1902
  }
1659
1903
  /**
1660
1904
  * Get pending EXA rewards for a user
@@ -1716,14 +1960,25 @@ var ExagentStaking = class {
1716
1960
  });
1717
1961
  }
1718
1962
  /**
1719
- * Get total staked EXA across all users
1720
- * @returns Total staked amount in wei
1963
+ * Get total EXA deposited across all users
1964
+ * @returns Total deposited amount in wei
1721
1965
  */
1722
- async getTotalStaked() {
1966
+ async getTotalDeposited() {
1723
1967
  return this.publicClient.readContract({
1724
1968
  address: this.address,
1725
1969
  abi: EXAGENT_STAKING_ABI,
1726
- functionName: "totalStaked"
1970
+ functionName: "totalDeposited"
1971
+ });
1972
+ }
1973
+ /**
1974
+ * Get total EXA locked across all users
1975
+ * @returns Total locked amount in wei
1976
+ */
1977
+ async getTotalLocked() {
1978
+ return this.publicClient.readContract({
1979
+ address: this.address,
1980
+ abi: EXAGENT_STAKING_ABI,
1981
+ functionName: "totalLocked"
1727
1982
  });
1728
1983
  }
1729
1984
  /**
@@ -1738,8 +1993,8 @@ var ExagentStaking = class {
1738
1993
  });
1739
1994
  }
1740
1995
  /**
1741
- * Calculate vEXA balance for a given stake (preview)
1742
- * @param amount Amount of EXA to stake
1996
+ * Calculate vEXA balance for a given lock (preview)
1997
+ * @param amount Amount of EXA to lock
1743
1998
  * @param lockDuration Lock duration in seconds
1744
1999
  * @returns Expected vEXA balance
1745
2000
  */
@@ -1764,7 +2019,7 @@ var ExagentStaking = class {
1764
2019
  }
1765
2020
  // ============ Helper Functions ============
1766
2021
  /**
1767
- * Approve EXA token spending for staking
2022
+ * Approve EXA token spending for deposits
1768
2023
  * @param amount Amount to approve
1769
2024
  * @returns Transaction hash
1770
2025
  */
@@ -1802,35 +2057,23 @@ var ExagentStaking = class {
1802
2057
 
1803
2058
  // src/constants.ts
1804
2059
  var import_chains = require("viem/chains");
2060
+ var SDK_VERSION = "0.1.4";
1805
2061
  var CHAIN_CONFIG = {
1806
- mainnet: import_chains.base,
1807
- testnet: import_chains.baseSepolia
2062
+ mainnet: import_chains.base
1808
2063
  };
1809
2064
  var CONTRACT_ADDRESSES = {
1810
2065
  mainnet: {
1811
- agentRegistry: "0x0000000000000000000000000000000000000000",
1812
- // To be deployed
1813
- exaToken: "0x0000000000000000000000000000000000000000",
1814
- staking: "0x0000000000000000000000000000000000000000",
1815
- router: "0x0000000000000000000000000000000000000000",
2066
+ agentRegistry: "0x2261706C751F8ac5cdDb481B7b56EA2137d4A723",
2067
+ exaToken: "0x13403Fb738C97cF7564F279288468c140AaEd05c",
2068
+ staking: "0xAF1729D1519A72f7d9b87aa23a305b775e2849DA",
2069
+ router: "0x11daD5366D903a3eF5d8f07EFF87ce6b173859a9",
1816
2070
  vaultFactory: "0x0000000000000000000000000000000000000000",
1817
- feeCollector: "0x0000000000000000000000000000000000000000",
2071
+ // Phase 2 — pending deploy
2072
+ feeCollector: "0xe66328a964AF93bEF2eDB226D039C35aE6e66De1",
1818
2073
  buyback: "0x0000000000000000000000000000000000000000",
2074
+ // Phase 2 — pending deploy
1819
2075
  serviceEscrow: "0x0000000000000000000000000000000000000000"
1820
- },
1821
- testnet: {
1822
- agentRegistry: "0xCF48C341e3FebeCA5ECB7eb2535f61A2Ba855d9C",
1823
- // V4 UUPS proxy, one-agent-per-wallet
1824
- exaToken: "0x66c39b0ad96B3f5eE198Fef913c6636353a48A87",
1825
- staking: "0x439441468e1b1b616E9D36b80969C241F261A011",
1826
- // V2 with delegation
1827
- router: "0xc0c27eEE047E414CD716D06C2444CF2073113d5C",
1828
- // V3 with config epochs
1829
- vaultFactory: "0x5c099daaE33801a907Bb57011c6749655b55dc75",
1830
- // V2 with requirements
1831
- feeCollector: "0xcB57b03a50df054b9C738Df1324C17A4fDe4fe46",
1832
- buyback: "0x35cdEa810A130A846265682e5c71A68A507aB895",
1833
- serviceEscrow: "0x74a3496b148DEE735ac388299aF9Ac2F7C4EdCBf"
2076
+ // Phase 2 — pending deploy
1834
2077
  }
1835
2078
  };
1836
2079
  var DEX_ADDRESSES = {
@@ -1850,21 +2093,44 @@ var ZERO_X_CONFIG = {
1850
2093
  // Base
1851
2094
  };
1852
2095
  var EXAGENT_API_CONFIG = {
1853
- mainnet: "https://api.exagent.io",
1854
- testnet: "https://api.testnet.exagent.io"
2096
+ mainnet: "https://exagent-api.onrender.com"
1855
2097
  };
1856
2098
  var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
2099
+ var PHASE_1_CONTRACTS = /* @__PURE__ */ new Set([
2100
+ "agentRegistry",
2101
+ "exaToken",
2102
+ "staking",
2103
+ "router",
2104
+ "feeCollector"
2105
+ ]);
1857
2106
  function validateContractAddresses(network) {
1858
2107
  const addresses = CONTRACT_ADDRESSES[network];
1859
- const zeroEntries = Object.entries(addresses).filter(([, addr]) => addr === ZERO_ADDRESS);
1860
- if (network === "mainnet" && zeroEntries.length > 0) {
1861
- const missing = zeroEntries.map(([name]) => name).join(", ");
2108
+ const missingPhase1 = Object.entries(addresses).filter(([name, addr]) => PHASE_1_CONTRACTS.has(name) && addr === ZERO_ADDRESS).map(([name]) => name);
2109
+ if (missingPhase1.length > 0) {
1862
2110
  throw new Error(
1863
- `Mainnet contracts not yet deployed. Missing addresses: ${missing}. Deploy contracts before using the SDK on mainnet.`
2111
+ `Mainnet Phase 1 contracts not deployed. Missing: ${missingPhase1.join(", ")}. Update @exagent/sdk to the latest version.`
1864
2112
  );
1865
2113
  }
1866
2114
  }
1867
2115
 
2116
+ // src/types.ts
2117
+ function buildGlobalAgentId(chainId, registryAddress, agentId) {
2118
+ return `eip155:${chainId}:${registryAddress}:${Number(agentId)}`;
2119
+ }
2120
+ function parseGlobalAgentId(globalId) {
2121
+ const parts = globalId.split(":");
2122
+ if (parts.length !== 4 || parts[0] !== "eip155") {
2123
+ throw new Error(`Invalid ERC-8004 global agent ID: ${globalId}`);
2124
+ }
2125
+ const chainId = parseInt(parts[1], 10);
2126
+ const registryAddress = parts[2];
2127
+ const agentId = parseInt(parts[3], 10);
2128
+ if (isNaN(chainId) || isNaN(agentId)) {
2129
+ throw new Error(`Invalid ERC-8004 global agent ID: ${globalId}`);
2130
+ }
2131
+ return { chainId, registryAddress, agentId };
2132
+ }
2133
+
1868
2134
  // src/client.ts
1869
2135
  var ExagentClient = class {
1870
2136
  publicClient;
@@ -1878,7 +2144,7 @@ var ExagentClient = class {
1878
2144
  // Cached agent ID
1879
2145
  _agentId;
1880
2146
  constructor(config) {
1881
- this.network = config.network ?? "testnet";
2147
+ this.network = config.network ?? "mainnet";
1882
2148
  this.apiKey = config.apiKey;
1883
2149
  validateContractAddresses(this.network);
1884
2150
  const chain = CHAIN_CONFIG[this.network];
@@ -1915,6 +2181,14 @@ var ExagentClient = class {
1915
2181
  this.account
1916
2182
  );
1917
2183
  }
2184
+ /** Standard headers for all API requests (includes SDK version for gating) */
2185
+ apiHeaders(contentType) {
2186
+ return {
2187
+ ...contentType && { "Content-Type": contentType },
2188
+ "X-Exagent-SDK-Version": SDK_VERSION,
2189
+ ...this.apiKey && { "X-API-Key": this.apiKey }
2190
+ };
2191
+ }
1918
2192
  // ============ Agent Registration ============
1919
2193
  /**
1920
2194
  * Register as a new agent on Exagent
@@ -2002,127 +2276,15 @@ var ExagentClient = class {
2002
2276
  }
2003
2277
  // ============ Trading ============
2004
2278
  /**
2005
- * Get optimal DEX route for a trade
2006
- * Uses 0x API for aggregation across Aerodrome, Uniswap, etc.
2007
- */
2008
- async getRoute(intent) {
2009
- const apiUrl = EXAGENT_API_CONFIG[this.network];
2010
- const response = await fetch(`${apiUrl}/v1/routes/quote`, {
2011
- method: "POST",
2012
- headers: {
2013
- "Content-Type": "application/json",
2014
- ...this.apiKey && { "X-API-Key": this.apiKey }
2015
- },
2016
- body: JSON.stringify({
2017
- tokenIn: intent.tokenIn,
2018
- tokenOut: intent.tokenOut,
2019
- amountIn: intent.amountIn.toString(),
2020
- slippageBps: intent.maxSlippageBps ?? 50,
2021
- taker: this.account.address
2022
- })
2023
- });
2024
- if (!response.ok) {
2025
- const error = await response.json().catch(() => ({ error: response.statusText }));
2026
- throw new Error(`Failed to get route: ${error.error}`);
2027
- }
2028
- return response.json();
2029
- }
2030
- /**
2031
- * Get price quote without transaction data (faster)
2032
- */
2033
- async getPrice(tokenIn, tokenOut, amountIn) {
2034
- const apiUrl = EXAGENT_API_CONFIG[this.network];
2035
- const response = await fetch(`${apiUrl}/v1/routes/price`, {
2036
- method: "POST",
2037
- headers: {
2038
- "Content-Type": "application/json",
2039
- ...this.apiKey && { "X-API-Key": this.apiKey }
2040
- },
2041
- body: JSON.stringify({
2042
- tokenIn,
2043
- tokenOut,
2044
- amountIn: amountIn.toString()
2045
- })
2046
- });
2047
- if (!response.ok) {
2048
- const error = await response.json().catch(() => ({ error: response.statusText }));
2049
- throw new Error(`Failed to get price: ${error.error}`);
2050
- }
2051
- return response.json();
2052
- }
2053
- /**
2054
- * Execute a trade using a pre-fetched route
2055
- * @param route Route quote from getRoute()
2056
- * @param options Trade execution options
2057
- * @returns Transaction hash
2058
- */
2059
- async executeTrade(route, options) {
2060
- if (route.validUntil && Date.now() > route.validUntil) {
2061
- throw new Error("Quote expired, please fetch a new route");
2062
- }
2063
- if (route.issues?.allowance) {
2064
- throw new Error(
2065
- `Insufficient allowance for ${route.issues.allowance.spender}. Need ${route.issues.allowance.expected}, have ${route.issues.allowance.actual}`
2066
- );
2067
- }
2068
- if (options?.validateSlippage !== false) {
2069
- const freshPrice = await this.getPrice(
2070
- route.tokenIn,
2071
- route.tokenOut,
2072
- BigInt(route.amountIn)
2073
- );
2074
- const quotedOutput = BigInt(route.amountOut);
2075
- const freshOutput = BigInt(freshPrice.amountOut);
2076
- if (freshOutput < quotedOutput * 99n / 100n) {
2077
- console.warn("Price has moved significantly since quote was fetched");
2078
- }
2079
- }
2080
- const hash = await this.walletClient.sendTransaction({
2081
- account: this.account,
2082
- chain: CHAIN_CONFIG[this.network],
2083
- to: route.transaction.to,
2084
- data: route.transaction.data,
2085
- value: BigInt(route.transaction.value)
2086
- });
2087
- return hash;
2088
- }
2089
- /**
2090
- * Get and execute a trade in one call
2091
- * Convenience method that fetches route and executes
2092
- */
2093
- async swap(intent) {
2094
- const route = await this.getRoute(intent);
2095
- const hash = await this.executeTrade(route);
2096
- return { hash, route };
2097
- }
2098
- /**
2099
- * Broadcast a trade intent to the network
2100
- * Other agents can see this and potentially provide better execution
2101
- */
2102
- async broadcastIntent(intent) {
2103
- const agentId = await this.getAgentId();
2104
- if (!agentId) throw new Error("Agent not registered");
2105
- const apiUrl = EXAGENT_API_CONFIG[this.network];
2106
- await fetch(`${apiUrl}/v1/intents`, {
2107
- method: "POST",
2108
- headers: {
2109
- "Content-Type": "application/json",
2110
- ...this.apiKey && { "X-API-Key": this.apiKey }
2111
- },
2112
- body: JSON.stringify({
2113
- agentId: agentId.toString(),
2114
- intent,
2115
- signature: await this.signIntent(intent)
2116
- })
2117
- });
2118
- }
2119
- // ============ Router Trading (Attributed) ============
2120
- /**
2121
- * Execute a trade through ExagentRouter for full attribution
2279
+ * Execute a trade through ExagentRouter
2280
+ *
2281
+ * All trades MUST go through the ExagentRouter. This ensures:
2282
+ * - Trade attribution for leaderboard ranking
2283
+ * - Protocol fee collection (0.2%)
2284
+ * - On-chain performance tracking
2285
+ * - Token whitelist enforcement per risk universe
2122
2286
  *
2123
- * This is the recommended way for agents to trade. All trades routed through
2124
- * the ExagentRouter emit TradeExecuted events that are captured by the indexer
2125
- * for accurate performance tracking and rankings.
2287
+ * There is no way to trade outside the router. This is by design.
2126
2288
  *
2127
2289
  * @param intent Trade parameters
2128
2290
  * @returns Trade result with transaction hash
@@ -2175,10 +2337,7 @@ var ExagentClient = class {
2175
2337
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2176
2338
  const response = await fetch(`${apiUrl}/v1/router/trade`, {
2177
2339
  method: "POST",
2178
- headers: {
2179
- "Content-Type": "application/json",
2180
- ...this.apiKey && { "X-API-Key": this.apiKey }
2181
- },
2340
+ headers: this.apiHeaders("application/json"),
2182
2341
  body: JSON.stringify({
2183
2342
  agentId: id.toString(),
2184
2343
  tokenIn: intent.tokenIn,
@@ -2227,10 +2386,7 @@ var ExagentClient = class {
2227
2386
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2228
2387
  const response = await fetch(`${apiUrl}/v1/services/request`, {
2229
2388
  method: "POST",
2230
- headers: {
2231
- "Content-Type": "application/json",
2232
- ...this.apiKey && { "X-API-Key": this.apiKey }
2233
- },
2389
+ headers: this.apiHeaders("application/json"),
2234
2390
  body: JSON.stringify({
2235
2391
  requesterId: agentId.toString(),
2236
2392
  ...request
@@ -2248,7 +2404,9 @@ var ExagentClient = class {
2248
2404
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2249
2405
  const params = new URLSearchParams();
2250
2406
  if (serviceType) params.set("type", serviceType);
2251
- const response = await fetch(`${apiUrl}/v1/services?${params}`);
2407
+ const response = await fetch(`${apiUrl}/v1/services?${params}`, {
2408
+ headers: this.apiHeaders()
2409
+ });
2252
2410
  return response.json();
2253
2411
  }
2254
2412
  // ============ Leaderboards ============
@@ -2261,7 +2419,9 @@ var ExagentClient = class {
2261
2419
  if (options?.category) params.set("category", options.category);
2262
2420
  if (options?.limit) params.set("limit", options.limit.toString());
2263
2421
  if (options?.offset) params.set("offset", options.offset.toString());
2264
- const response = await fetch(`${apiUrl}/v1/rankings/leaderboard?${params}`);
2422
+ const response = await fetch(`${apiUrl}/v1/rankings/leaderboard?${params}`, {
2423
+ headers: this.apiHeaders()
2424
+ });
2265
2425
  return response.json();
2266
2426
  }
2267
2427
  // ============ Vault Functions (Phase 4: Copy Trading) ============
@@ -2289,9 +2449,7 @@ var ExagentClient = class {
2289
2449
  if (!id) throw new Error("Agent not registered");
2290
2450
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2291
2451
  const response = await fetch(`${apiUrl}/v1/vaults?agentId=${id}`, {
2292
- headers: {
2293
- ...this.apiKey && { "X-API-Key": this.apiKey }
2294
- }
2452
+ headers: this.apiHeaders()
2295
2453
  });
2296
2454
  if (!response.ok) {
2297
2455
  throw new Error(`Failed to get vaults: ${response.statusText}`);
@@ -2307,9 +2465,7 @@ var ExagentClient = class {
2307
2465
  const user = userAddress ?? this.account.address;
2308
2466
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2309
2467
  const response = await fetch(`${apiUrl}/v1/vaults?depositor=${user}`, {
2310
- headers: {
2311
- ...this.apiKey && { "X-API-Key": this.apiKey }
2312
- }
2468
+ headers: this.apiHeaders()
2313
2469
  });
2314
2470
  if (!response.ok) {
2315
2471
  throw new Error(`Failed to get user vaults: ${response.statusText}`);
@@ -2329,9 +2485,7 @@ var ExagentClient = class {
2329
2485
  if (options?.period) params.set("period", options.period);
2330
2486
  if (options?.limit) params.set("limit", options.limit.toString());
2331
2487
  const response = await fetch(`${apiUrl}/v1/vaults/top?${params}`, {
2332
- headers: {
2333
- ...this.apiKey && { "X-API-Key": this.apiKey }
2334
- }
2488
+ headers: this.apiHeaders()
2335
2489
  });
2336
2490
  if (!response.ok) {
2337
2491
  throw new Error(`Failed to get top vaults: ${response.statusText}`);
@@ -2372,37 +2526,73 @@ var ExagentClient = class {
2372
2526
  }
2373
2527
  // ============ Staking Functions ============
2374
2528
  /**
2375
- * Stake EXA tokens to receive vEXA voting power
2376
- * @param amount Amount of EXA to stake (in wei)
2529
+ * Deposit EXA tokens for vault access (no lock required)
2530
+ * @param amount Amount of EXA to deposit (in wei)
2531
+ * @returns Transaction hash
2532
+ *
2533
+ * @example
2534
+ * ```typescript
2535
+ * // Deposit 1000 EXA to unlock vault access
2536
+ * const tx = await exagent.depositExa(parseEther('1000'));
2537
+ * ```
2538
+ */
2539
+ async depositExa(amount) {
2540
+ await this.staking.approveExa(amount);
2541
+ return this.staking.deposit(amount);
2542
+ }
2543
+ /**
2544
+ * Withdraw unlocked EXA tokens (instant, no penalty)
2545
+ * @param amount Amount of EXA to withdraw (in wei)
2546
+ * @returns Transaction hash
2547
+ */
2548
+ async withdrawExa(amount) {
2549
+ return this.staking.withdraw(amount);
2550
+ }
2551
+ /**
2552
+ * Lock deposited EXA to receive vEXA voting power and earn rewards
2553
+ * @param amount Amount of deposited EXA to lock (in wei)
2377
2554
  * @param lockDuration Lock duration in seconds (30 days to 2 years)
2378
2555
  * @returns Transaction hash
2379
2556
  *
2380
2557
  * @example
2381
2558
  * ```typescript
2382
- * // Stake 1000 EXA for 6 months
2383
- * const tx = await exagent.stakeExa(
2559
+ * // Lock 1000 EXA for 6 months
2560
+ * const tx = await exagent.lockExa(
2384
2561
  * parseEther('1000'),
2385
2562
  * ExagentStaking.LOCK_6_MONTHS
2386
2563
  * );
2387
2564
  * ```
2388
2565
  */
2389
- async stakeExa(amount, lockDuration) {
2390
- await this.staking.approveExa(amount);
2391
- return this.staking.stake(amount, lockDuration);
2566
+ async lockExa(amount, lockDuration) {
2567
+ return this.staking.lock(amount, lockDuration);
2392
2568
  }
2393
2569
  /**
2394
- * Unstake EXA tokens after lock expires
2570
+ * Unlock EXA after lock expires (no penalty)
2395
2571
  * @returns Transaction hash
2396
2572
  */
2397
- async unstakeExa() {
2398
- return this.staking.unstake();
2573
+ async unlockExa() {
2574
+ return this.staking.unlock();
2399
2575
  }
2400
2576
  /**
2401
- * Get staking info for the connected wallet
2402
- * @returns Staking info including amount, unlock time, and vEXA balance
2577
+ * Emergency withdrawal from active lock (graduated 50%→20% penalty)
2578
+ * @returns Transaction hash
2579
+ */
2580
+ async emergencyWithdrawExa() {
2581
+ return this.staking.emergencyWithdraw();
2582
+ }
2583
+ /**
2584
+ * Get comprehensive staking info (deposit + lock) for the connected wallet
2585
+ * @returns Staking info including deposit status and lock status
2403
2586
  */
2404
2587
  async getStakingInfo() {
2405
- return this.staking.getStakeInfo();
2588
+ return this.staking.getStakingInfo();
2589
+ }
2590
+ /**
2591
+ * Get deposit info for the connected wallet
2592
+ * @returns Deposit info (deposited, locked, unlocked, vault access)
2593
+ */
2594
+ async getDepositInfo() {
2595
+ return this.staking.getDepositInfo();
2406
2596
  }
2407
2597
  /**
2408
2598
  * Get current vEXA balance for the connected wallet
@@ -2412,20 +2602,25 @@ var ExagentClient = class {
2412
2602
  return this.staking.getVeEXABalance();
2413
2603
  }
2414
2604
  /**
2415
- * Delegate vEXA voting power to an agent
2416
- * @param agentId The agent ID to delegate to
2417
- * @returns Transaction hash
2605
+ * Check if connected wallet has vault access (meets deposit threshold)
2606
+ * @returns True if user can access vaults
2607
+ */
2608
+ async hasVaultAccess() {
2609
+ return this.staking.hasVaultAccess();
2610
+ }
2611
+ /**
2612
+ * Get earnings tier for the connected wallet
2613
+ * @returns Tier info with multiplier and name
2418
2614
  */
2419
- async delegateToAgent(agentId) {
2420
- return this.staking.delegate(agentId);
2615
+ async getEarningsTier() {
2616
+ return this.staking.getEarningsTier();
2421
2617
  }
2422
2618
  /**
2423
- * Get delegation stats for an agent
2424
- * @param agentId The agent ID to check
2425
- * @returns Delegation info with total vEXA and delegator count
2619
+ * Get emergency withdrawal penalty for the connected wallet
2620
+ * @returns Penalty in basis points (5000 = 50% at start, 2000 = 20% near expiry)
2426
2621
  */
2427
- async getAgentDelegation(agentId) {
2428
- return this.staking.getAgentDelegation(agentId);
2622
+ async getEmergencyWithdrawPenalty() {
2623
+ return this.staking.getEmergencyWithdrawPenalty();
2429
2624
  }
2430
2625
  /**
2431
2626
  * Claim all pending staking rewards (EXA + multi-token)
@@ -2436,6 +2631,46 @@ var ExagentClient = class {
2436
2631
  const multiTokenRewards = await this.staking.claimRewardsMulti();
2437
2632
  return { exaRewards, multiTokenRewards };
2438
2633
  }
2634
+ // ============ ERC-8004 Global Agent Identity ============
2635
+ /**
2636
+ * Get the ERC-8004 global agent identifier for the current agent
2637
+ *
2638
+ * Format: eip155:{chainId}:{registryAddress}:{agentId}
2639
+ *
2640
+ * This creates a universally unique identifier that can be used for
2641
+ * cross-protocol agent discovery and interoperability.
2642
+ *
2643
+ * @returns The global agent ID string
2644
+ * @throws Error if agent is not registered
2645
+ *
2646
+ * @example
2647
+ * ```typescript
2648
+ * const globalId = await exagent.getGlobalAgentId();
2649
+ * // => "eip155:8453:0xABC...DEF:42"
2650
+ * ```
2651
+ */
2652
+ async getGlobalAgentId() {
2653
+ const agentId = await this.getAgentId();
2654
+ if (!agentId) throw new Error("Agent not registered");
2655
+ const chain = CHAIN_CONFIG[this.network];
2656
+ const addresses = CONTRACT_ADDRESSES[this.network];
2657
+ return buildGlobalAgentId(
2658
+ chain.id,
2659
+ addresses.agentRegistry,
2660
+ agentId
2661
+ );
2662
+ }
2663
+ /**
2664
+ * Build a global agent ID for any agent (static utility)
2665
+ *
2666
+ * @param chainId - EVM chain ID
2667
+ * @param registryAddress - ExagentRegistry contract address
2668
+ * @param agentId - On-chain agent ID
2669
+ * @returns ERC-8004 global agent identifier
2670
+ */
2671
+ static buildGlobalAgentId(chainId, registryAddress, agentId) {
2672
+ return buildGlobalAgentId(chainId, registryAddress, agentId);
2673
+ }
2439
2674
  // ============ Helpers ============
2440
2675
  /**
2441
2676
  * Get the agent's wallet address
@@ -2455,10 +2690,7 @@ var ExagentClient = class {
2455
2690
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2456
2691
  const response = await fetch(`${apiUrl}/v1/metadata/upload`, {
2457
2692
  method: "POST",
2458
- headers: {
2459
- "Content-Type": "application/json",
2460
- ...this.apiKey && { "X-API-Key": this.apiKey }
2461
- },
2693
+ headers: this.apiHeaders("application/json"),
2462
2694
  body: JSON.stringify(metadata)
2463
2695
  });
2464
2696
  if (!response.ok) {
@@ -2467,12 +2699,16 @@ var ExagentClient = class {
2467
2699
  const result = await response.json();
2468
2700
  return result.uri;
2469
2701
  }
2470
- async signIntent(intent) {
2471
- const message = JSON.stringify(intent);
2472
- return this.walletClient.signMessage({ account: this.account, message });
2473
- }
2474
2702
  parseAgentIdFromReceipt(receipt) {
2475
- return 1n;
2703
+ const registryAddress = this.registry.address.toLowerCase();
2704
+ for (const log of receipt.logs) {
2705
+ if (log.address.toLowerCase() !== registryAddress) continue;
2706
+ if (log.topics.length >= 2 && log.topics[1]) {
2707
+ const agentId = BigInt(log.topics[1]);
2708
+ return agentId;
2709
+ }
2710
+ }
2711
+ throw new Error("AgentRegistered event not found in transaction receipt");
2476
2712
  }
2477
2713
  };
2478
2714
 
@@ -2482,8 +2718,12 @@ var EXAGENT_VAULT_FACTORY_ABI = [
2482
2718
  { type: "function", name: "owner", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
2483
2719
  { type: "function", name: "registry", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
2484
2720
  { type: "function", name: "router", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
2485
- { type: "function", name: "minimumVeEXARequired", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
2486
- { type: "function", name: "eXABurnFee", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
2721
+ { type: "function", name: "feeCollector", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
2722
+ { type: "function", name: "stakingContract", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
2723
+ { type: "function", name: "VERIFIED_VEXA_REQUIREMENT", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
2724
+ { type: "function", name: "MIN_SEED_AMOUNT", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
2725
+ { type: "function", name: "UNVERIFIED_CAP_MULTIPLIER", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
2726
+ { type: "function", name: "VERIFIED_CAP_MULTIPLIER", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
2487
2727
  { type: "function", name: "allowedAssets", inputs: [{ name: "asset", type: "address" }], outputs: [{ type: "bool" }], stateMutability: "view" },
2488
2728
  { type: "function", name: "vaults", inputs: [{ name: "agentId", type: "uint256" }, { name: "asset", type: "address" }], outputs: [{ type: "address" }], stateMutability: "view" },
2489
2729
  { type: "function", name: "agentVaultCount", inputs: [{ name: "agentId", type: "uint256" }], outputs: [{ type: "uint256" }], stateMutability: "view" },
@@ -2496,14 +2736,9 @@ var EXAGENT_VAULT_FACTORY_ABI = [
2496
2736
  },
2497
2737
  {
2498
2738
  type: "function",
2499
- name: "getVaultCreationRequirements",
2500
- inputs: [],
2501
- outputs: [
2502
- { name: "veXARequired", type: "uint256" },
2503
- { name: "burnFee", type: "uint256" },
2504
- { name: "stakingContract", type: "address" },
2505
- { name: "exaToken", type: "address" }
2506
- ],
2739
+ name: "canCreateVerifiedVault",
2740
+ inputs: [{ name: "agentId", type: "uint256" }],
2741
+ outputs: [{ name: "isVerified", type: "bool" }, { name: "reason", type: "string" }],
2507
2742
  stateMutability: "view"
2508
2743
  },
2509
2744
  // Write functions
@@ -2513,6 +2748,7 @@ var EXAGENT_VAULT_FACTORY_ABI = [
2513
2748
  inputs: [
2514
2749
  { name: "agentId", type: "uint256" },
2515
2750
  { name: "asset", type: "address" },
2751
+ { name: "seedAmount", type: "uint256" },
2516
2752
  { name: "name", type: "string" },
2517
2753
  { name: "symbol", type: "string" },
2518
2754
  { name: "feeRecipient", type: "address" }
@@ -2554,50 +2790,51 @@ var ExagentVaultFactory = class {
2554
2790
  this.address = factoryAddress;
2555
2791
  this.publicClient = publicClient;
2556
2792
  this.walletClient = walletClient;
2793
+ if (!chain) {
2794
+ throw new Error("Chain parameter is required");
2795
+ }
2557
2796
  this.chain = chain;
2558
2797
  this.account = account;
2559
2798
  }
2560
2799
  // ============ Read Functions ============
2561
2800
  /**
2562
- * Get vault creation requirements
2801
+ * Get vault creation requirements (mainnet: seed-based, no burn fee)
2563
2802
  */
2564
2803
  async getRequirements() {
2565
- try {
2566
- const result = await this.publicClient.readContract({
2804
+ const [veXARequired, minSeedAmount, unverifiedCapMultiplier, verifiedCapMultiplier, stakingContract] = await Promise.all([
2805
+ this.publicClient.readContract({
2567
2806
  address: this.address,
2568
2807
  abi: EXAGENT_VAULT_FACTORY_ABI,
2569
- functionName: "getVaultCreationRequirements"
2570
- });
2571
- const isBypassed = result[0] === BigInt(0) && result[1] === BigInt(0) && (result[2] === "0x0000000000000000000000000000000000000000" || result[3] === "0x0000000000000000000000000000000000000000");
2572
- return {
2573
- veXARequired: result[0],
2574
- burnFee: result[1],
2575
- stakingContract: result[2],
2576
- exaToken: result[3],
2577
- isBypassed
2578
- };
2579
- } catch {
2580
- const [veXARequired, burnFee] = await Promise.all([
2581
- this.publicClient.readContract({
2582
- address: this.address,
2583
- abi: EXAGENT_VAULT_FACTORY_ABI,
2584
- functionName: "minimumVeEXARequired"
2585
- }),
2586
- this.publicClient.readContract({
2587
- address: this.address,
2588
- abi: EXAGENT_VAULT_FACTORY_ABI,
2589
- functionName: "eXABurnFee"
2590
- })
2591
- ]);
2592
- const isBypassed = veXARequired === BigInt(0) && burnFee === BigInt(0);
2593
- return {
2594
- veXARequired,
2595
- burnFee,
2596
- stakingContract: "0x0000000000000000000000000000000000000000",
2597
- exaToken: "0x0000000000000000000000000000000000000000",
2598
- isBypassed
2599
- };
2600
- }
2808
+ functionName: "VERIFIED_VEXA_REQUIREMENT"
2809
+ }),
2810
+ this.publicClient.readContract({
2811
+ address: this.address,
2812
+ abi: EXAGENT_VAULT_FACTORY_ABI,
2813
+ functionName: "MIN_SEED_AMOUNT"
2814
+ }),
2815
+ this.publicClient.readContract({
2816
+ address: this.address,
2817
+ abi: EXAGENT_VAULT_FACTORY_ABI,
2818
+ functionName: "UNVERIFIED_CAP_MULTIPLIER"
2819
+ }),
2820
+ this.publicClient.readContract({
2821
+ address: this.address,
2822
+ abi: EXAGENT_VAULT_FACTORY_ABI,
2823
+ functionName: "VERIFIED_CAP_MULTIPLIER"
2824
+ }),
2825
+ this.publicClient.readContract({
2826
+ address: this.address,
2827
+ abi: EXAGENT_VAULT_FACTORY_ABI,
2828
+ functionName: "stakingContract"
2829
+ })
2830
+ ]);
2831
+ return {
2832
+ veXARequired,
2833
+ minSeedAmount,
2834
+ unverifiedCapMultiplier,
2835
+ verifiedCapMultiplier,
2836
+ stakingContract
2837
+ };
2601
2838
  }
2602
2839
  /**
2603
2840
  * Check if an address can create a vault
@@ -2615,6 +2852,22 @@ var ExagentVaultFactory = class {
2615
2852
  reason: result[1]
2616
2853
  };
2617
2854
  }
2855
+ /**
2856
+ * Check if an agent can create a verified vault (higher deposit cap)
2857
+ * @param agentId Agent ID to check
2858
+ */
2859
+ async canCreateVerifiedVault(agentId) {
2860
+ const result = await this.publicClient.readContract({
2861
+ address: this.address,
2862
+ abi: EXAGENT_VAULT_FACTORY_ABI,
2863
+ functionName: "canCreateVerifiedVault",
2864
+ args: [agentId]
2865
+ });
2866
+ return {
2867
+ isVerified: result[0],
2868
+ reason: result[1]
2869
+ };
2870
+ }
2618
2871
  /**
2619
2872
  * Check if an asset is whitelisted for vault creation
2620
2873
  * @param asset Asset address to check
@@ -2664,8 +2917,8 @@ var ExagentVaultFactory = class {
2664
2917
  }
2665
2918
  // ============ Write Functions ============
2666
2919
  /**
2667
- * Create a new vault for an agent
2668
- * @param options Vault creation options
2920
+ * Create a new vault for an agent (mainnet: requires seed amount)
2921
+ * @param options Vault creation options including seedAmount
2669
2922
  * @returns Transaction hash
2670
2923
  */
2671
2924
  async createVault(options) {
@@ -2677,7 +2930,7 @@ var ExagentVaultFactory = class {
2677
2930
  address: this.address,
2678
2931
  abi: EXAGENT_VAULT_FACTORY_ABI,
2679
2932
  functionName: "createVault",
2680
- args: [options.agentId, options.asset, options.name, options.symbol, feeRecipient],
2933
+ args: [options.agentId, options.asset, options.seedAmount, options.name, options.symbol, feeRecipient],
2681
2934
  account: this.account,
2682
2935
  chain: this.chain
2683
2936
  });
@@ -2688,7 +2941,7 @@ var ExagentVaultFactory = class {
2688
2941
  * Check all requirements and create a vault if possible
2689
2942
  * Returns detailed status about each requirement
2690
2943
  */
2691
- async checkAndCreateVault(agentId, asset, name, symbol, feeRecipient) {
2944
+ async checkAndCreateVault(agentId, asset, seedAmount, name, symbol, feeRecipient) {
2692
2945
  const [canCreateResult, assetAllowed, hasExisting] = await Promise.all([
2693
2946
  this.canCreateVault(this.account?.address ?? "0x0000000000000000000000000000000000000000"),
2694
2947
  this.isAssetAllowed(asset),
@@ -2727,6 +2980,7 @@ var ExagentVaultFactory = class {
2727
2980
  const txHash = await this.createVault({
2728
2981
  agentId,
2729
2982
  asset,
2983
+ seedAmount,
2730
2984
  name,
2731
2985
  symbol,
2732
2986
  feeRecipient
@@ -2756,28 +3010,11 @@ var ExagentVaultFactory = class {
2756
3010
  }
2757
3011
  }
2758
3012
  };
2759
-
2760
- // src/index.ts
2761
- var TESTNET_ADDRESSES = {
2762
- registry: "0xCF48C341e3FebeCA5ECB7eb2535f61A2Ba855d9C",
2763
- // V4 UUPS proxy
2764
- token: "0x66c39b0ad96B3f5eE198Fef913c6636353a48A87",
2765
- staking: "0x439441468e1b1b616E9D36b80969C241F261A011",
2766
- router: "0xc0c27eEE047E414CD716D06C2444CF2073113d5C",
2767
- // V3 with config epochs
2768
- vaultFactory: "0x5c099daaE33801a907Bb57011c6749655b55dc75",
2769
- feeCollector: "0xcB57b03a50df054b9C738Df1324C17A4fDe4fe46",
2770
- buyback: "0x35cdEa810A130A846265682e5c71A68A507aB895",
2771
- serviceEscrow: "0x74a3496b148DEE735ac388299aF9Ac2F7C4EdCBf",
2772
- usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
2773
- // Circle's Base Sepolia USDC (only vault asset)
2774
- };
2775
3013
  // Annotate the CommonJS export names for ESM import in node:
2776
3014
  0 && (module.exports = {
2777
3015
  CHAIN_CONFIG,
2778
3016
  CONTRACT_ADDRESSES,
2779
3017
  DEX_ADDRESSES,
2780
- DISCOUNT_TIERS,
2781
3018
  EXAGENT_API_CONFIG,
2782
3019
  EXAGENT_STAKING_ABI,
2783
3020
  EXAGENT_VAULT_FACTORY_ABI,
@@ -2786,6 +3023,8 @@ var TESTNET_ADDRESSES = {
2786
3023
  ExagentStaking,
2787
3024
  ExagentVault,
2788
3025
  ExagentVaultFactory,
2789
- TESTNET_ADDRESSES,
2790
- ZERO_X_CONFIG
3026
+ SDK_VERSION,
3027
+ ZERO_X_CONFIG,
3028
+ buildGlobalAgentId,
3029
+ parseGlobalAgentId
2791
3030
  });