@exagent/sdk 0.1.3 → 0.1.4

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.mjs CHANGED
@@ -1,10 +1,3 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
1
  // src/client.ts
9
2
  import {
10
3
  createPublicClient,
@@ -24,7 +17,10 @@ var EXAGENT_REGISTRY_ABI = [
24
17
  name: "registerAgent",
25
18
  inputs: [
26
19
  { name: "name", type: "string" },
27
- { name: "metadataURI", type: "string" }
20
+ { name: "metadataURI", type: "string" },
21
+ { name: "riskUniverse", type: "uint8" },
22
+ { name: "maxPositionSizeBps", type: "uint256" },
23
+ { name: "maxDailyLossBps", type: "uint256" }
28
24
  ],
29
25
  outputs: [{ name: "agentId", type: "uint256" }],
30
26
  stateMutability: "nonpayable"
@@ -254,6 +250,62 @@ var EXAGENT_REGISTRY_ABI = [
254
250
  outputs: [{ name: "", type: "bytes32" }],
255
251
  stateMutability: "view"
256
252
  },
253
+ // Mainnet: Agent retirement
254
+ {
255
+ type: "function",
256
+ name: "retireAgent",
257
+ inputs: [{ name: "agentId", type: "uint256" }],
258
+ outputs: [],
259
+ stateMutability: "nonpayable"
260
+ },
261
+ {
262
+ type: "function",
263
+ name: "retired",
264
+ inputs: [{ name: "agentId", type: "uint256" }],
265
+ outputs: [{ type: "bool" }],
266
+ stateMutability: "view"
267
+ },
268
+ {
269
+ type: "function",
270
+ name: "isRetired",
271
+ inputs: [{ name: "agentId", type: "uint256" }],
272
+ outputs: [{ type: "bool" }],
273
+ stateMutability: "view"
274
+ },
275
+ // Mainnet: Risk universe token whitelists
276
+ {
277
+ type: "function",
278
+ name: "isTradeAllowed",
279
+ inputs: [
280
+ { name: "agentId", type: "uint256" },
281
+ { name: "token", type: "address" },
282
+ { name: "aggregator", type: "address" }
283
+ ],
284
+ outputs: [{ type: "bool" }],
285
+ stateMutability: "view"
286
+ },
287
+ {
288
+ type: "function",
289
+ name: "getRiskUniverse",
290
+ inputs: [{ name: "agentId", type: "uint256" }],
291
+ outputs: [{ type: "uint8" }],
292
+ stateMutability: "view"
293
+ },
294
+ {
295
+ type: "function",
296
+ name: "tradeCount",
297
+ inputs: [{ name: "agentId", type: "uint256" }],
298
+ outputs: [{ type: "uint256" }],
299
+ stateMutability: "view"
300
+ },
301
+ // Events
302
+ {
303
+ type: "event",
304
+ name: "AgentRetired",
305
+ inputs: [
306
+ { name: "agentId", type: "uint256", indexed: true }
307
+ ]
308
+ },
257
309
  {
258
310
  type: "event",
259
311
  name: "ConfigUpdated",
@@ -264,7 +316,16 @@ var EXAGENT_REGISTRY_ABI = [
264
316
  { name: "epochId", type: "uint256", indexed: false },
265
317
  { name: "blockNumber", type: "uint256", indexed: false }
266
318
  ]
267
- }
319
+ },
320
+ // Custom errors
321
+ { type: "error", name: "OwnerAlreadyHasAgent", inputs: [{ name: "existingAgentId", type: "uint256" }] },
322
+ { type: "error", name: "InvalidMetadataURI", inputs: [] },
323
+ { type: "error", name: "InvalidName", inputs: [] },
324
+ { type: "error", name: "InvalidRiskUniverse", inputs: [] },
325
+ { type: "error", name: "InvalidTradingConfig", inputs: [] },
326
+ { type: "error", name: "NameAlreadyTaken", inputs: [] },
327
+ { type: "error", name: "AgentNotOwner", inputs: [] },
328
+ { type: "error", name: "AgentIsRetired", inputs: [] }
268
329
  ];
269
330
  var ExagentRegistry = class {
270
331
  address;
@@ -285,9 +346,12 @@ var ExagentRegistry = class {
285
346
  * Register a new agent
286
347
  * @param name Unique agent name (3-32 chars, alphanumeric + spaces/hyphens/underscores)
287
348
  * @param metadataURI IPFS URI for agent metadata
349
+ * @param riskUniverse Risk tier: 0=Core, 1=Established, 2=Derivatives, 3=Emerging, 4=Frontier
350
+ * @param maxPositionSizeBps Maximum position size in basis points (1-10000)
351
+ * @param maxDailyLossBps Maximum daily loss in basis points (1-10000)
288
352
  * @returns Transaction hash
289
353
  */
290
- async register(name, metadataURI) {
354
+ async register(name, metadataURI, riskUniverse = 1, maxPositionSizeBps = 1000n, maxDailyLossBps = 500n) {
291
355
  if (!this.walletClient || !this.account) throw new Error("Wallet client and account required for write operations");
292
356
  const hash = await this.walletClient.writeContract({
293
357
  account: this.account,
@@ -295,7 +359,7 @@ var ExagentRegistry = class {
295
359
  address: this.address,
296
360
  abi: EXAGENT_REGISTRY_ABI,
297
361
  functionName: "registerAgent",
298
- args: [name, metadataURI]
362
+ args: [name, metadataURI, riskUniverse, maxPositionSizeBps, maxDailyLossBps]
299
363
  });
300
364
  return hash;
301
365
  }
@@ -630,8 +694,84 @@ var ExagentRegistry = class {
630
694
  * @returns keccak256 hash of the config
631
695
  */
632
696
  static calculateConfigHash(provider, model) {
633
- const { keccak256: keccak2562, encodePacked: encodePacked2 } = __require("viem");
634
- return keccak2562(encodePacked2(["string", "string"], [provider, model]));
697
+ return keccak256(encodePacked(["string", "string"], [provider, model]));
698
+ }
699
+ // ============ Agent Retirement ============
700
+ /**
701
+ * Retire an agent — marks it as retired, unlinks all wallets, allows new agent registration
702
+ * @param agentId The agent's ID
703
+ * @returns Transaction hash
704
+ */
705
+ async retireAgent(agentId) {
706
+ if (!this.walletClient || !this.account) throw new Error("Wallet client and account required for write operations");
707
+ const hash = await this.walletClient.writeContract({
708
+ account: this.account,
709
+ chain: this.chain,
710
+ address: this.address,
711
+ abi: EXAGENT_REGISTRY_ABI,
712
+ functionName: "retireAgent",
713
+ args: [agentId]
714
+ });
715
+ return hash;
716
+ }
717
+ /**
718
+ * Check if an agent is retired
719
+ * @param agentId The agent's ID
720
+ * @returns True if agent is retired
721
+ */
722
+ async isRetired(agentId) {
723
+ const result = await this.publicClient.readContract({
724
+ address: this.address,
725
+ abi: EXAGENT_REGISTRY_ABI,
726
+ functionName: "isRetired",
727
+ args: [agentId]
728
+ });
729
+ return result;
730
+ }
731
+ // ============ Risk Universe Token Eligibility ============
732
+ /**
733
+ * Check if a token trade is allowed for an agent's risk universe
734
+ * @param agentId The agent's ID
735
+ * @param token The token address to check
736
+ * @param aggregator The aggregator being used (for trusted aggregator bypass)
737
+ * @returns True if the trade is allowed
738
+ */
739
+ async isTradeAllowed(agentId, token, aggregator) {
740
+ const result = await this.publicClient.readContract({
741
+ address: this.address,
742
+ abi: EXAGENT_REGISTRY_ABI,
743
+ functionName: "isTradeAllowed",
744
+ args: [agentId, token, aggregator]
745
+ });
746
+ return result;
747
+ }
748
+ /**
749
+ * Get the risk universe for an agent
750
+ * @param agentId The agent's ID
751
+ * @returns Risk universe (0=Core, 1=Established, 2=Derivatives, 3=Emerging, 4=Frontier)
752
+ */
753
+ async getRiskUniverse(agentId) {
754
+ const result = await this.publicClient.readContract({
755
+ address: this.address,
756
+ abi: EXAGENT_REGISTRY_ABI,
757
+ functionName: "getRiskUniverse",
758
+ args: [agentId]
759
+ });
760
+ return Number(result);
761
+ }
762
+ /**
763
+ * Get trade count for an agent
764
+ * @param agentId The agent's ID
765
+ * @returns Number of recorded trades
766
+ */
767
+ async getTradeCount(agentId) {
768
+ const result = await this.publicClient.readContract({
769
+ address: this.address,
770
+ abi: EXAGENT_REGISTRY_ABI,
771
+ functionName: "tradeCount",
772
+ args: [agentId]
773
+ });
774
+ return result;
635
775
  }
636
776
  };
637
777
 
@@ -722,6 +862,9 @@ var ExagentVault = class {
722
862
  this.address = vaultAddress;
723
863
  this.publicClient = publicClient;
724
864
  this.walletClient = walletClient;
865
+ if (!chain) {
866
+ throw new Error("Chain parameter is required");
867
+ }
725
868
  this.chain = chain;
726
869
  this.account = account;
727
870
  }
@@ -1068,17 +1211,34 @@ var ExagentVault = class {
1068
1211
  var EXAGENT_STAKING_ABI = [
1069
1212
  // ============ State Variables ============
1070
1213
  { type: "function", name: "exaToken", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
1071
- { type: "function", name: "totalStaked", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1214
+ { type: "function", name: "totalDeposited", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1215
+ { type: "function", name: "totalLocked", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1072
1216
  { type: "function", name: "totalVeEXA", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1073
- { type: "function", name: "registry", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
1217
+ { type: "function", name: "totalEffectiveVeEXA", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1074
1218
  // ============ Constants ============
1075
1219
  { type: "function", name: "MIN_LOCK_DURATION", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1076
1220
  { type: "function", name: "MAX_LOCK_DURATION", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1221
+ { type: "function", name: "VAULT_ACCESS_THRESHOLD", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1077
1222
  { type: "function", name: "PRECISION", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1078
- // ============ Staking Functions ============
1223
+ // ============ Phase 1: Deposit / Withdraw ============
1224
+ {
1225
+ type: "function",
1226
+ name: "deposit",
1227
+ inputs: [{ name: "amount", type: "uint256" }],
1228
+ outputs: [],
1229
+ stateMutability: "nonpayable"
1230
+ },
1231
+ {
1232
+ type: "function",
1233
+ name: "withdraw",
1234
+ inputs: [{ name: "amount", type: "uint256" }],
1235
+ outputs: [],
1236
+ stateMutability: "nonpayable"
1237
+ },
1238
+ // ============ Phase 2: Lock / Unlock ============
1079
1239
  {
1080
1240
  type: "function",
1081
- name: "stake",
1241
+ name: "lock",
1082
1242
  inputs: [
1083
1243
  { name: "amount", type: "uint256" },
1084
1244
  { name: "lockDuration", type: "uint256" }
@@ -1086,7 +1246,6 @@ var EXAGENT_STAKING_ABI = [
1086
1246
  outputs: [],
1087
1247
  stateMutability: "nonpayable"
1088
1248
  },
1089
- { type: "function", name: "unstake", inputs: [], outputs: [], stateMutability: "nonpayable" },
1090
1249
  {
1091
1250
  type: "function",
1092
1251
  name: "extendLock",
@@ -1094,6 +1253,8 @@ var EXAGENT_STAKING_ABI = [
1094
1253
  outputs: [],
1095
1254
  stateMutability: "nonpayable"
1096
1255
  },
1256
+ { type: "function", name: "unlock", inputs: [], outputs: [], stateMutability: "nonpayable" },
1257
+ { type: "function", name: "emergencyWithdraw", inputs: [], outputs: [], stateMutability: "nonpayable" },
1097
1258
  // ============ Reward Functions ============
1098
1259
  { type: "function", name: "claimRewards", inputs: [], outputs: [], stateMutability: "nonpayable" },
1099
1260
  { type: "function", name: "claimRewardsMulti", inputs: [], outputs: [], stateMutability: "nonpayable" },
@@ -1104,26 +1265,17 @@ var EXAGENT_STAKING_ABI = [
1104
1265
  outputs: [],
1105
1266
  stateMutability: "nonpayable"
1106
1267
  },
1107
- // ============ Delegation Functions ============
1108
- {
1109
- type: "function",
1110
- name: "delegate",
1111
- inputs: [{ name: "agentId", type: "uint256" }],
1112
- outputs: [],
1113
- stateMutability: "nonpayable"
1114
- },
1115
- { type: "function", name: "undelegate", inputs: [], outputs: [], stateMutability: "nonpayable" },
1268
+ // ============ View Functions ============
1116
1269
  {
1117
1270
  type: "function",
1118
- name: "redelegate",
1119
- inputs: [{ name: "newAgentId", type: "uint256" }],
1120
- outputs: [],
1121
- stateMutability: "nonpayable"
1271
+ name: "depositedAmount",
1272
+ inputs: [{ name: "user", type: "address" }],
1273
+ outputs: [{ type: "uint256" }],
1274
+ stateMutability: "view"
1122
1275
  },
1123
- // ============ View Functions ============
1124
1276
  {
1125
1277
  type: "function",
1126
- name: "stakes",
1278
+ name: "locks",
1127
1279
  inputs: [{ name: "user", type: "address" }],
1128
1280
  outputs: [
1129
1281
  { name: "amount", type: "uint256" },
@@ -1140,6 +1292,13 @@ var EXAGENT_STAKING_ABI = [
1140
1292
  outputs: [{ type: "uint256" }],
1141
1293
  stateMutability: "view"
1142
1294
  },
1295
+ {
1296
+ type: "function",
1297
+ name: "getEffectiveVeEXA",
1298
+ inputs: [{ name: "user", type: "address" }],
1299
+ outputs: [{ type: "uint256" }],
1300
+ stateMutability: "view"
1301
+ },
1143
1302
  {
1144
1303
  type: "function",
1145
1304
  name: "calculateVeEXA",
@@ -1169,61 +1328,40 @@ var EXAGENT_STAKING_ABI = [
1169
1328
  },
1170
1329
  {
1171
1330
  type: "function",
1172
- name: "getDelegatedAgent",
1331
+ name: "getEarningsTier",
1173
1332
  inputs: [{ name: "user", type: "address" }],
1174
- outputs: [{ type: "uint256" }],
1175
- stateMutability: "view"
1176
- },
1177
- {
1178
- type: "function",
1179
- name: "getAgentDelegation",
1180
- inputs: [{ name: "agentId", type: "uint256" }],
1181
1333
  outputs: [
1182
- { name: "vexa", type: "uint256" },
1183
- { name: "count", type: "uint256" }
1334
+ { name: "multiplierBps", type: "uint256" },
1335
+ { name: "tierName", type: "string" }
1184
1336
  ],
1185
1337
  stateMutability: "view"
1186
1338
  },
1187
1339
  {
1188
1340
  type: "function",
1189
- name: "getDiscountTier",
1341
+ name: "getEmergencyWithdrawPenalty",
1190
1342
  inputs: [{ name: "user", type: "address" }],
1191
- outputs: [{ name: "discountBps", type: "uint256" }],
1343
+ outputs: [{ name: "penaltyBps", type: "uint256" }],
1192
1344
  stateMutability: "view"
1193
1345
  },
1194
1346
  {
1195
1347
  type: "function",
1196
- name: "getRewardTokens",
1197
- inputs: [],
1198
- outputs: [{ type: "address[]" }],
1199
- stateMutability: "view"
1200
- },
1201
- {
1202
- type: "function",
1203
- name: "delegatedTo",
1348
+ name: "hasVaultAccess",
1204
1349
  inputs: [{ name: "user", type: "address" }],
1205
- outputs: [{ type: "uint256" }],
1350
+ outputs: [{ type: "bool" }],
1206
1351
  stateMutability: "view"
1207
1352
  },
1208
1353
  {
1209
1354
  type: "function",
1210
- name: "userDelegatedVeEXA",
1355
+ name: "getUnlockedBalance",
1211
1356
  inputs: [{ name: "user", type: "address" }],
1212
1357
  outputs: [{ type: "uint256" }],
1213
1358
  stateMutability: "view"
1214
1359
  },
1215
1360
  {
1216
1361
  type: "function",
1217
- name: "agentDelegatedVeEXA",
1218
- inputs: [{ name: "agentId", type: "uint256" }],
1219
- outputs: [{ type: "uint256" }],
1220
- stateMutability: "view"
1221
- },
1222
- {
1223
- type: "function",
1224
- name: "agentDelegatorCount",
1225
- inputs: [{ name: "agentId", type: "uint256" }],
1226
- outputs: [{ type: "uint256" }],
1362
+ name: "getRewardTokens",
1363
+ inputs: [],
1364
+ outputs: [{ type: "address[]" }],
1227
1365
  stateMutability: "view"
1228
1366
  },
1229
1367
  {
@@ -1236,35 +1374,36 @@ var EXAGENT_STAKING_ABI = [
1236
1374
  // ============ Events ============
1237
1375
  {
1238
1376
  type: "event",
1239
- name: "Staked",
1377
+ name: "Deposited",
1240
1378
  inputs: [
1241
1379
  { name: "user", type: "address", indexed: true },
1242
1380
  { name: "amount", type: "uint256", indexed: false },
1243
- { name: "lockDuration", type: "uint256", indexed: false },
1244
- { name: "unlockTime", type: "uint256", indexed: false },
1245
- { name: "vEXABalance", type: "uint256", indexed: false }
1381
+ { name: "totalDeposited", type: "uint256", indexed: false }
1246
1382
  ]
1247
1383
  },
1248
1384
  {
1249
1385
  type: "event",
1250
- name: "Unstaked",
1386
+ name: "Withdrawn",
1251
1387
  inputs: [
1252
1388
  { name: "user", type: "address", indexed: true },
1253
- { name: "amount", type: "uint256", indexed: false }
1389
+ { name: "amount", type: "uint256", indexed: false },
1390
+ { name: "totalDeposited", type: "uint256", indexed: false }
1254
1391
  ]
1255
1392
  },
1256
1393
  {
1257
1394
  type: "event",
1258
- name: "LockExtended",
1395
+ name: "Locked",
1259
1396
  inputs: [
1260
1397
  { name: "user", type: "address", indexed: true },
1261
- { name: "newUnlockTime", type: "uint256", indexed: false },
1262
- { name: "newVeEXABalance", type: "uint256", indexed: false }
1398
+ { name: "amount", type: "uint256", indexed: false },
1399
+ { name: "lockDuration", type: "uint256", indexed: false },
1400
+ { name: "unlockTime", type: "uint256", indexed: false },
1401
+ { name: "vEXABalance", type: "uint256", indexed: false }
1263
1402
  ]
1264
1403
  },
1265
1404
  {
1266
1405
  type: "event",
1267
- name: "RewardsClaimed",
1406
+ name: "Unlocked",
1268
1407
  inputs: [
1269
1408
  { name: "user", type: "address", indexed: true },
1270
1409
  { name: "amount", type: "uint256", indexed: false }
@@ -1272,20 +1411,29 @@ var EXAGENT_STAKING_ABI = [
1272
1411
  },
1273
1412
  {
1274
1413
  type: "event",
1275
- name: "Delegated",
1414
+ name: "EmergencyWithdrawal",
1276
1415
  inputs: [
1277
- { name: "delegator", type: "address", indexed: true },
1278
- { name: "agentId", type: "uint256", indexed: true },
1279
- { name: "veEXAAmount", type: "uint256", indexed: false }
1416
+ { name: "user", type: "address", indexed: true },
1417
+ { name: "returned", type: "uint256", indexed: false },
1418
+ { name: "penalty", type: "uint256", indexed: false },
1419
+ { name: "penaltyBps", type: "uint256", indexed: false }
1280
1420
  ]
1281
1421
  },
1282
1422
  {
1283
1423
  type: "event",
1284
- name: "Undelegated",
1424
+ name: "LockExtended",
1285
1425
  inputs: [
1286
- { name: "delegator", type: "address", indexed: true },
1287
- { name: "agentId", type: "uint256", indexed: true },
1288
- { name: "veEXAAmount", type: "uint256", indexed: false }
1426
+ { name: "user", type: "address", indexed: true },
1427
+ { name: "newUnlockTime", type: "uint256", indexed: false },
1428
+ { name: "newVeEXABalance", type: "uint256", indexed: false }
1429
+ ]
1430
+ },
1431
+ {
1432
+ type: "event",
1433
+ name: "RewardsClaimed",
1434
+ inputs: [
1435
+ { name: "user", type: "address", indexed: true },
1436
+ { name: "amount", type: "uint256", indexed: false }
1289
1437
  ]
1290
1438
  },
1291
1439
  {
@@ -1310,15 +1458,6 @@ var ERC20_APPROVE_ABI2 = [
1310
1458
  stateMutability: "nonpayable"
1311
1459
  }
1312
1460
  ];
1313
- var DISCOUNT_TIERS = {
1314
- none: 0,
1315
- bronze: 1e3,
1316
- // 10% discount at 10,000 vEXA
1317
- silver: 2500,
1318
- // 25% discount at 50,000 vEXA
1319
- gold: 5e3
1320
- // 50% discount at 100,000 vEXA
1321
- };
1322
1461
  var ExagentStaking = class {
1323
1462
  address;
1324
1463
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -1331,108 +1470,119 @@ var ExagentStaking = class {
1331
1470
  this.address = stakingAddress;
1332
1471
  this.publicClient = publicClient;
1333
1472
  this.walletClient = walletClient;
1473
+ if (!chain) {
1474
+ throw new Error("Chain parameter is required");
1475
+ }
1334
1476
  this.chain = chain;
1335
1477
  this.account = account;
1336
1478
  }
1337
- // ============ Staking Write Functions ============
1479
+ // ============ Phase 1: Deposit / Withdraw ============
1338
1480
  /**
1339
- * Stake EXA tokens to receive vEXA voting power
1340
- * @param amount Amount of EXA to stake (in wei)
1341
- * @param lockDuration Lock duration in seconds (30 days to 2 years)
1481
+ * Deposit EXA tokens for vault access (no lock required)
1482
+ * @param amount Amount of EXA to deposit (in wei)
1342
1483
  * @returns Transaction hash
1343
1484
  *
1344
1485
  * @example
1345
1486
  * ```typescript
1346
- * // Stake 1000 EXA for 6 months
1347
- * const tx = await staking.stake(
1348
- * parseEther('1000'),
1349
- * BigInt(180 * 24 * 60 * 60) // 180 days in seconds
1350
- * );
1487
+ * // Deposit 1000 EXA to unlock vault access
1488
+ * const tx = await staking.deposit(parseEther('1000'));
1351
1489
  * ```
1352
1490
  */
1353
- async stake(amount, lockDuration) {
1491
+ async deposit(amount) {
1354
1492
  if (!this.walletClient || !this.account) {
1355
1493
  throw new Error("Wallet client required for write operations");
1356
1494
  }
1357
1495
  const hash = await this.walletClient.writeContract({
1358
1496
  address: this.address,
1359
1497
  abi: EXAGENT_STAKING_ABI,
1360
- functionName: "stake",
1361
- args: [amount, lockDuration],
1498
+ functionName: "deposit",
1499
+ args: [amount],
1362
1500
  account: this.account,
1363
1501
  chain: this.chain
1364
1502
  });
1365
1503
  return hash;
1366
1504
  }
1367
1505
  /**
1368
- * Unstake EXA tokens after lock expires
1506
+ * Withdraw unlocked EXA tokens (instant, no penalty)
1507
+ * @param amount Amount of EXA to withdraw (in wei)
1369
1508
  * @returns Transaction hash
1370
- * @throws Error if lock has not expired
1371
1509
  */
1372
- async unstake() {
1510
+ async withdraw(amount) {
1373
1511
  if (!this.walletClient || !this.account) {
1374
1512
  throw new Error("Wallet client required for write operations");
1375
1513
  }
1376
1514
  const hash = await this.walletClient.writeContract({
1377
1515
  address: this.address,
1378
1516
  abi: EXAGENT_STAKING_ABI,
1379
- functionName: "unstake",
1380
- args: [],
1517
+ functionName: "withdraw",
1518
+ args: [amount],
1381
1519
  account: this.account,
1382
1520
  chain: this.chain
1383
1521
  });
1384
1522
  return hash;
1385
1523
  }
1524
+ // ============ Phase 2: Lock / Unlock ============
1386
1525
  /**
1387
- * Extend lock duration for additional voting power
1388
- * @param newLockDuration New lock duration in seconds (must be longer than remaining)
1526
+ * Lock deposited EXA to receive vEXA voting power and earn rewards
1527
+ * @param amount Amount of deposited EXA to lock (in wei)
1528
+ * @param lockDuration Lock duration in seconds (30 days to 2 years)
1389
1529
  * @returns Transaction hash
1530
+ *
1531
+ * @example
1532
+ * ```typescript
1533
+ * // Lock 1000 EXA for 6 months
1534
+ * const tx = await staking.lock(
1535
+ * parseEther('1000'),
1536
+ * ExagentStaking.LOCK_6_MONTHS
1537
+ * );
1538
+ * ```
1390
1539
  */
1391
- async extendLock(newLockDuration) {
1540
+ async lock(amount, lockDuration) {
1392
1541
  if (!this.walletClient || !this.account) {
1393
1542
  throw new Error("Wallet client required for write operations");
1394
1543
  }
1395
1544
  const hash = await this.walletClient.writeContract({
1396
1545
  address: this.address,
1397
1546
  abi: EXAGENT_STAKING_ABI,
1398
- functionName: "extendLock",
1399
- args: [newLockDuration],
1547
+ functionName: "lock",
1548
+ args: [amount, lockDuration],
1400
1549
  account: this.account,
1401
1550
  chain: this.chain
1402
1551
  });
1403
1552
  return hash;
1404
1553
  }
1405
- // ============ Reward Write Functions ============
1406
1554
  /**
1407
- * Claim accumulated EXA rewards
1555
+ * Extend lock duration for additional voting power
1556
+ * @param newLockDuration New lock duration in seconds (must be longer than remaining)
1408
1557
  * @returns Transaction hash
1409
1558
  */
1410
- async claimRewards() {
1559
+ async extendLock(newLockDuration) {
1411
1560
  if (!this.walletClient || !this.account) {
1412
1561
  throw new Error("Wallet client required for write operations");
1413
1562
  }
1414
1563
  const hash = await this.walletClient.writeContract({
1415
1564
  address: this.address,
1416
1565
  abi: EXAGENT_STAKING_ABI,
1417
- functionName: "claimRewards",
1418
- args: [],
1566
+ functionName: "extendLock",
1567
+ args: [newLockDuration],
1419
1568
  account: this.account,
1420
1569
  chain: this.chain
1421
1570
  });
1422
1571
  return hash;
1423
1572
  }
1424
1573
  /**
1425
- * Claim all pending multi-token rewards (ETH, USDC, etc.)
1574
+ * Unlock EXA after lock expires (normal path — no penalty)
1575
+ * Returns locked amount to unlocked deposited balance.
1426
1576
  * @returns Transaction hash
1427
1577
  */
1428
- async claimRewardsMulti() {
1578
+ async unlock() {
1429
1579
  if (!this.walletClient || !this.account) {
1430
1580
  throw new Error("Wallet client required for write operations");
1431
1581
  }
1432
1582
  const hash = await this.walletClient.writeContract({
1433
1583
  address: this.address,
1434
1584
  abi: EXAGENT_STAKING_ABI,
1435
- functionName: "claimRewardsMulti",
1585
+ functionName: "unlock",
1436
1586
  args: [],
1437
1587
  account: this.account,
1438
1588
  chain: this.chain
@@ -1440,56 +1590,56 @@ var ExagentStaking = class {
1440
1590
  return hash;
1441
1591
  }
1442
1592
  /**
1443
- * Claim pending rewards for a specific token
1444
- * @param token The reward token address to claim
1593
+ * Emergency withdrawal instant exit from lock with graduated penalty
1594
+ * Two-phase penalty: 50%→20% over the first quarter of the lock, then flat 20% until expiry.
1595
+ * Penalty goes to treasury. Remaining returns to unlocked deposit balance.
1445
1596
  * @returns Transaction hash
1446
1597
  */
1447
- async claimRewardsToken(token) {
1598
+ async emergencyWithdraw() {
1448
1599
  if (!this.walletClient || !this.account) {
1449
1600
  throw new Error("Wallet client required for write operations");
1450
1601
  }
1451
1602
  const hash = await this.walletClient.writeContract({
1452
1603
  address: this.address,
1453
1604
  abi: EXAGENT_STAKING_ABI,
1454
- functionName: "claimRewardsToken",
1455
- args: [token],
1605
+ functionName: "emergencyWithdraw",
1606
+ args: [],
1456
1607
  account: this.account,
1457
1608
  chain: this.chain
1458
1609
  });
1459
1610
  return hash;
1460
1611
  }
1461
- // ============ Delegation Write Functions ============
1612
+ // ============ Reward Functions ============
1462
1613
  /**
1463
- * Delegate vEXA voting power to an agent ("Agent Wars")
1464
- * @param agentId The agent ID to delegate to
1614
+ * Claim accumulated EXA rewards
1465
1615
  * @returns Transaction hash
1466
1616
  */
1467
- async delegate(agentId) {
1617
+ async claimRewards() {
1468
1618
  if (!this.walletClient || !this.account) {
1469
1619
  throw new Error("Wallet client required for write operations");
1470
1620
  }
1471
1621
  const hash = await this.walletClient.writeContract({
1472
1622
  address: this.address,
1473
1623
  abi: EXAGENT_STAKING_ABI,
1474
- functionName: "delegate",
1475
- args: [agentId],
1624
+ functionName: "claimRewards",
1625
+ args: [],
1476
1626
  account: this.account,
1477
1627
  chain: this.chain
1478
1628
  });
1479
1629
  return hash;
1480
1630
  }
1481
1631
  /**
1482
- * Remove delegation from current agent
1632
+ * Claim all pending multi-token rewards (ETH, USDC, etc.)
1483
1633
  * @returns Transaction hash
1484
1634
  */
1485
- async undelegate() {
1635
+ async claimRewardsMulti() {
1486
1636
  if (!this.walletClient || !this.account) {
1487
1637
  throw new Error("Wallet client required for write operations");
1488
1638
  }
1489
1639
  const hash = await this.walletClient.writeContract({
1490
1640
  address: this.address,
1491
1641
  abi: EXAGENT_STAKING_ABI,
1492
- functionName: "undelegate",
1642
+ functionName: "claimRewardsMulti",
1493
1643
  args: [],
1494
1644
  account: this.account,
1495
1645
  chain: this.chain
@@ -1497,19 +1647,19 @@ var ExagentStaking = class {
1497
1647
  return hash;
1498
1648
  }
1499
1649
  /**
1500
- * Re-delegate to a different agent (undelegate + delegate in one tx)
1501
- * @param newAgentId The new agent ID to delegate to
1650
+ * Claim pending rewards for a specific token
1651
+ * @param token The reward token address to claim
1502
1652
  * @returns Transaction hash
1503
1653
  */
1504
- async redelegate(newAgentId) {
1654
+ async claimRewardsToken(token) {
1505
1655
  if (!this.walletClient || !this.account) {
1506
1656
  throw new Error("Wallet client required for write operations");
1507
1657
  }
1508
1658
  const hash = await this.walletClient.writeContract({
1509
1659
  address: this.address,
1510
1660
  abi: EXAGENT_STAKING_ABI,
1511
- functionName: "redelegate",
1512
- args: [newAgentId],
1661
+ functionName: "claimRewardsToken",
1662
+ args: [token],
1513
1663
  account: this.account,
1514
1664
  chain: this.chain
1515
1665
  });
@@ -1517,20 +1667,26 @@ var ExagentStaking = class {
1517
1667
  }
1518
1668
  // ============ Read Functions ============
1519
1669
  /**
1520
- * Get comprehensive staking info for a user
1670
+ * Get comprehensive staking info for a user (deposit + lock)
1521
1671
  * @param userAddress Address to check (defaults to connected wallet)
1522
- * @returns Staking info with amount, unlock time, and vEXA balance
1672
+ * @returns Combined staking info
1523
1673
  */
1524
- async getStakeInfo(userAddress) {
1674
+ async getStakingInfo(userAddress) {
1525
1675
  const user = userAddress ?? this.account?.address;
1526
1676
  if (!user) {
1527
1677
  throw new Error("User address required");
1528
1678
  }
1529
- const [stakeResult, currentVeEXA] = await Promise.all([
1679
+ const [deposited, lockResult, currentVeEXA, vaultAccess, unlockedBalance] = await Promise.all([
1530
1680
  this.publicClient.readContract({
1531
1681
  address: this.address,
1532
1682
  abi: EXAGENT_STAKING_ABI,
1533
- functionName: "stakes",
1683
+ functionName: "depositedAmount",
1684
+ args: [user]
1685
+ }),
1686
+ this.publicClient.readContract({
1687
+ address: this.address,
1688
+ abi: EXAGENT_STAKING_ABI,
1689
+ functionName: "locks",
1534
1690
  args: [user]
1535
1691
  }),
1536
1692
  this.publicClient.readContract({
@@ -1538,20 +1694,88 @@ var ExagentStaking = class {
1538
1694
  abi: EXAGENT_STAKING_ABI,
1539
1695
  functionName: "getVeEXABalance",
1540
1696
  args: [user]
1697
+ }),
1698
+ this.publicClient.readContract({
1699
+ address: this.address,
1700
+ abi: EXAGENT_STAKING_ABI,
1701
+ functionName: "hasVaultAccess",
1702
+ args: [user]
1703
+ }),
1704
+ this.publicClient.readContract({
1705
+ address: this.address,
1706
+ abi: EXAGENT_STAKING_ABI,
1707
+ functionName: "getUnlockedBalance",
1708
+ args: [user]
1541
1709
  })
1542
1710
  ]);
1543
- const stake = stakeResult;
1711
+ const lockData = lockResult;
1712
+ const depositedBigint = deposited;
1713
+ const lockedAmount = lockData[0];
1544
1714
  const now = BigInt(Math.floor(Date.now() / 1e3));
1545
- const isUnlocked = stake[1] <= now;
1546
- const remainingLockTime = isUnlocked ? 0n : stake[1] - now;
1715
+ const depositInfo = {
1716
+ deposited: depositedBigint,
1717
+ locked: lockedAmount,
1718
+ unlocked: unlockedBalance,
1719
+ hasVaultAccess: vaultAccess
1720
+ };
1721
+ let lockInfo = null;
1722
+ if (lockedAmount > 0n) {
1723
+ const isUnlocked = lockData[1] <= now;
1724
+ const remainingLockTime = isUnlocked ? 0n : lockData[1] - now;
1725
+ lockInfo = {
1726
+ amount: lockData[0],
1727
+ unlockTime: lockData[1],
1728
+ lockDuration: lockData[2],
1729
+ vEXABalance: lockData[3],
1730
+ currentVeEXA,
1731
+ isUnlocked,
1732
+ remainingLockTime
1733
+ };
1734
+ }
1735
+ return { deposit: depositInfo, lock: lockInfo };
1736
+ }
1737
+ /**
1738
+ * Get deposit info for a user
1739
+ * @param userAddress Address to check (defaults to connected wallet)
1740
+ * @returns Deposit info
1741
+ */
1742
+ async getDepositInfo(userAddress) {
1743
+ const user = userAddress ?? this.account?.address;
1744
+ if (!user) {
1745
+ throw new Error("User address required");
1746
+ }
1747
+ const [deposited, lockResult, vaultAccess, unlockedBalance] = await Promise.all([
1748
+ this.publicClient.readContract({
1749
+ address: this.address,
1750
+ abi: EXAGENT_STAKING_ABI,
1751
+ functionName: "depositedAmount",
1752
+ args: [user]
1753
+ }),
1754
+ this.publicClient.readContract({
1755
+ address: this.address,
1756
+ abi: EXAGENT_STAKING_ABI,
1757
+ functionName: "locks",
1758
+ args: [user]
1759
+ }),
1760
+ this.publicClient.readContract({
1761
+ address: this.address,
1762
+ abi: EXAGENT_STAKING_ABI,
1763
+ functionName: "hasVaultAccess",
1764
+ args: [user]
1765
+ }),
1766
+ this.publicClient.readContract({
1767
+ address: this.address,
1768
+ abi: EXAGENT_STAKING_ABI,
1769
+ functionName: "getUnlockedBalance",
1770
+ args: [user]
1771
+ })
1772
+ ]);
1773
+ const lockData = lockResult;
1547
1774
  return {
1548
- amount: stake[0],
1549
- unlockTime: stake[1],
1550
- lockDuration: stake[2],
1551
- vEXABalance: stake[3],
1552
- currentVeEXA,
1553
- isUnlocked,
1554
- remainingLockTime
1775
+ deposited,
1776
+ locked: lockData[0],
1777
+ unlocked: unlockedBalance,
1778
+ hasVaultAccess: vaultAccess
1555
1779
  };
1556
1780
  }
1557
1781
  /**
@@ -1572,11 +1796,28 @@ var ExagentStaking = class {
1572
1796
  });
1573
1797
  }
1574
1798
  /**
1575
- * Get the agent ID a user is delegating to
1799
+ * Get effective vEXA (with tier multiplier applied)
1800
+ * @param userAddress Address to check (defaults to connected wallet)
1801
+ * @returns Effective vEXA balance
1802
+ */
1803
+ async getEffectiveVeEXA(userAddress) {
1804
+ const user = userAddress ?? this.account?.address;
1805
+ if (!user) {
1806
+ throw new Error("User address required");
1807
+ }
1808
+ return this.publicClient.readContract({
1809
+ address: this.address,
1810
+ abi: EXAGENT_STAKING_ABI,
1811
+ functionName: "getEffectiveVeEXA",
1812
+ args: [user]
1813
+ });
1814
+ }
1815
+ /**
1816
+ * Check if user has vault access (meets deposit threshold)
1576
1817
  * @param userAddress Address to check (defaults to connected wallet)
1577
- * @returns Agent ID (0 if not delegating)
1818
+ * @returns True if user can access vaults
1578
1819
  */
1579
- async getDelegatedAgent(userAddress) {
1820
+ async hasVaultAccess(userAddress) {
1580
1821
  const user = userAddress ?? this.account?.address;
1581
1822
  if (!user) {
1582
1823
  throw new Error("User address required");
@@ -1584,52 +1825,47 @@ var ExagentStaking = class {
1584
1825
  return this.publicClient.readContract({
1585
1826
  address: this.address,
1586
1827
  abi: EXAGENT_STAKING_ABI,
1587
- functionName: "getDelegatedAgent",
1828
+ functionName: "hasVaultAccess",
1588
1829
  args: [user]
1589
1830
  });
1590
1831
  }
1591
1832
  /**
1592
- * Get delegation stats for an agent
1593
- * @param agentId The agent ID to check
1594
- * @returns Delegation info with total vEXA and delegator count
1833
+ * Get earnings tier for a user (Bronze/Silver/Gold/Platinum/Diamond)
1834
+ * @param userAddress Address to check (defaults to connected wallet)
1835
+ * @returns Tier info with multiplier and name
1595
1836
  */
1596
- async getAgentDelegation(agentId) {
1837
+ async getEarningsTier(userAddress) {
1838
+ const user = userAddress ?? this.account?.address;
1839
+ if (!user) {
1840
+ throw new Error("User address required");
1841
+ }
1597
1842
  const result = await this.publicClient.readContract({
1598
1843
  address: this.address,
1599
1844
  abi: EXAGENT_STAKING_ABI,
1600
- functionName: "getAgentDelegation",
1601
- args: [agentId]
1845
+ functionName: "getEarningsTier",
1846
+ args: [user]
1602
1847
  });
1603
1848
  return {
1604
- totalVeEXA: result[0],
1605
- delegatorCount: result[1]
1849
+ multiplierBps: result[0],
1850
+ tierName: result[1]
1606
1851
  };
1607
1852
  }
1608
1853
  /**
1609
- * Get trading fee discount tier for a user
1854
+ * Get current emergency withdrawal penalty for a user
1610
1855
  * @param userAddress Address to check (defaults to connected wallet)
1611
- * @returns Discount tier name and basis points
1856
+ * @returns Penalty in basis points (5000 = 50% at lock start, ramps to 2000 over first 25% of lock, then flat 2000)
1612
1857
  */
1613
- async getDiscountTier(userAddress) {
1858
+ async getEmergencyWithdrawPenalty(userAddress) {
1614
1859
  const user = userAddress ?? this.account?.address;
1615
1860
  if (!user) {
1616
1861
  throw new Error("User address required");
1617
1862
  }
1618
- const discountBps = await this.publicClient.readContract({
1863
+ return this.publicClient.readContract({
1619
1864
  address: this.address,
1620
1865
  abi: EXAGENT_STAKING_ABI,
1621
- functionName: "getDiscountTier",
1866
+ functionName: "getEmergencyWithdrawPenalty",
1622
1867
  args: [user]
1623
1868
  });
1624
- let tier = "none";
1625
- if (discountBps >= 5000n) {
1626
- tier = "gold";
1627
- } else if (discountBps >= 2500n) {
1628
- tier = "silver";
1629
- } else if (discountBps >= 1000n) {
1630
- tier = "bronze";
1631
- }
1632
- return { tier, discountBps };
1633
1869
  }
1634
1870
  /**
1635
1871
  * Get pending EXA rewards for a user
@@ -1691,14 +1927,25 @@ var ExagentStaking = class {
1691
1927
  });
1692
1928
  }
1693
1929
  /**
1694
- * Get total staked EXA across all users
1695
- * @returns Total staked amount in wei
1930
+ * Get total EXA deposited across all users
1931
+ * @returns Total deposited amount in wei
1696
1932
  */
1697
- async getTotalStaked() {
1933
+ async getTotalDeposited() {
1698
1934
  return this.publicClient.readContract({
1699
1935
  address: this.address,
1700
1936
  abi: EXAGENT_STAKING_ABI,
1701
- functionName: "totalStaked"
1937
+ functionName: "totalDeposited"
1938
+ });
1939
+ }
1940
+ /**
1941
+ * Get total EXA locked across all users
1942
+ * @returns Total locked amount in wei
1943
+ */
1944
+ async getTotalLocked() {
1945
+ return this.publicClient.readContract({
1946
+ address: this.address,
1947
+ abi: EXAGENT_STAKING_ABI,
1948
+ functionName: "totalLocked"
1702
1949
  });
1703
1950
  }
1704
1951
  /**
@@ -1713,8 +1960,8 @@ var ExagentStaking = class {
1713
1960
  });
1714
1961
  }
1715
1962
  /**
1716
- * Calculate vEXA balance for a given stake (preview)
1717
- * @param amount Amount of EXA to stake
1963
+ * Calculate vEXA balance for a given lock (preview)
1964
+ * @param amount Amount of EXA to lock
1718
1965
  * @param lockDuration Lock duration in seconds
1719
1966
  * @returns Expected vEXA balance
1720
1967
  */
@@ -1739,7 +1986,7 @@ var ExagentStaking = class {
1739
1986
  }
1740
1987
  // ============ Helper Functions ============
1741
1988
  /**
1742
- * Approve EXA token spending for staking
1989
+ * Approve EXA token spending for deposits
1743
1990
  * @param amount Amount to approve
1744
1991
  * @returns Transaction hash
1745
1992
  */
@@ -1777,25 +2024,28 @@ var ExagentStaking = class {
1777
2024
 
1778
2025
  // src/constants.ts
1779
2026
  import { base, baseSepolia } from "viem/chains";
2027
+ var SDK_VERSION = "0.1.4";
1780
2028
  var CHAIN_CONFIG = {
1781
2029
  mainnet: base,
1782
2030
  testnet: baseSepolia
1783
2031
  };
1784
2032
  var CONTRACT_ADDRESSES = {
1785
2033
  mainnet: {
1786
- agentRegistry: "0x0000000000000000000000000000000000000000",
1787
- // To be deployed
1788
- exaToken: "0x0000000000000000000000000000000000000000",
1789
- staking: "0x0000000000000000000000000000000000000000",
1790
- router: "0x0000000000000000000000000000000000000000",
2034
+ agentRegistry: "0x2261706C751F8ac5cdDb481B7b56EA2137d4A723",
2035
+ exaToken: "0x13403Fb738C97cF7564F279288468c140AaEd05c",
2036
+ staking: "0xAF1729D1519A72f7d9b87aa23a305b775e2849DA",
2037
+ router: "0x11daD5366D903a3eF5d8f07EFF87ce6b173859a9",
1791
2038
  vaultFactory: "0x0000000000000000000000000000000000000000",
1792
- feeCollector: "0x0000000000000000000000000000000000000000",
2039
+ // Phase 2 — pending deploy
2040
+ feeCollector: "0xe66328a964AF93bEF2eDB226D039C35aE6e66De1",
1793
2041
  buyback: "0x0000000000000000000000000000000000000000",
2042
+ // Phase 2 — pending deploy
1794
2043
  serviceEscrow: "0x0000000000000000000000000000000000000000"
2044
+ // Phase 2 — pending deploy
1795
2045
  },
1796
2046
  testnet: {
1797
2047
  agentRegistry: "0xCF48C341e3FebeCA5ECB7eb2535f61A2Ba855d9C",
1798
- // V4 UUPS proxy, one-agent-per-wallet
2048
+ // one-agent-per-wallet
1799
2049
  exaToken: "0x66c39b0ad96B3f5eE198Fef913c6636353a48A87",
1800
2050
  staking: "0x439441468e1b1b616E9D36b80969C241F261A011",
1801
2051
  // V2 with delegation
@@ -1825,21 +2075,47 @@ var ZERO_X_CONFIG = {
1825
2075
  // Base
1826
2076
  };
1827
2077
  var EXAGENT_API_CONFIG = {
1828
- mainnet: "https://api.exagent.io",
1829
- testnet: "https://api.testnet.exagent.io"
2078
+ mainnet: "https://exagent-api.onrender.com",
2079
+ testnet: "https://exagent-api.onrender.com"
1830
2080
  };
1831
2081
  var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
2082
+ var PHASE_1_CONTRACTS = /* @__PURE__ */ new Set([
2083
+ "agentRegistry",
2084
+ "exaToken",
2085
+ "staking",
2086
+ "router",
2087
+ "feeCollector"
2088
+ ]);
1832
2089
  function validateContractAddresses(network) {
1833
2090
  const addresses = CONTRACT_ADDRESSES[network];
1834
- const zeroEntries = Object.entries(addresses).filter(([, addr]) => addr === ZERO_ADDRESS);
1835
- if (network === "mainnet" && zeroEntries.length > 0) {
1836
- const missing = zeroEntries.map(([name]) => name).join(", ");
1837
- throw new Error(
1838
- `Mainnet contracts not yet deployed. Missing addresses: ${missing}. Deploy contracts before using the SDK on mainnet.`
1839
- );
2091
+ if (network === "mainnet") {
2092
+ const missingPhase1 = Object.entries(addresses).filter(([name, addr]) => PHASE_1_CONTRACTS.has(name) && addr === ZERO_ADDRESS).map(([name]) => name);
2093
+ if (missingPhase1.length > 0) {
2094
+ throw new Error(
2095
+ `Mainnet Phase 1 contracts not deployed. Missing: ${missingPhase1.join(", ")}. Update @exagent/sdk to the latest version.`
2096
+ );
2097
+ }
1840
2098
  }
1841
2099
  }
1842
2100
 
2101
+ // src/types.ts
2102
+ function buildGlobalAgentId(chainId, registryAddress, agentId) {
2103
+ return `eip155:${chainId}:${registryAddress}:${Number(agentId)}`;
2104
+ }
2105
+ function parseGlobalAgentId(globalId) {
2106
+ const parts = globalId.split(":");
2107
+ if (parts.length !== 4 || parts[0] !== "eip155") {
2108
+ throw new Error(`Invalid ERC-8004 global agent ID: ${globalId}`);
2109
+ }
2110
+ const chainId = parseInt(parts[1], 10);
2111
+ const registryAddress = parts[2];
2112
+ const agentId = parseInt(parts[3], 10);
2113
+ if (isNaN(chainId) || isNaN(agentId)) {
2114
+ throw new Error(`Invalid ERC-8004 global agent ID: ${globalId}`);
2115
+ }
2116
+ return { chainId, registryAddress, agentId };
2117
+ }
2118
+
1843
2119
  // src/client.ts
1844
2120
  var ExagentClient = class {
1845
2121
  publicClient;
@@ -1890,6 +2166,14 @@ var ExagentClient = class {
1890
2166
  this.account
1891
2167
  );
1892
2168
  }
2169
+ /** Standard headers for all API requests (includes SDK version for gating) */
2170
+ apiHeaders(contentType) {
2171
+ return {
2172
+ ...contentType && { "Content-Type": contentType },
2173
+ "X-Exagent-SDK-Version": SDK_VERSION,
2174
+ ...this.apiKey && { "X-API-Key": this.apiKey }
2175
+ };
2176
+ }
1893
2177
  // ============ Agent Registration ============
1894
2178
  /**
1895
2179
  * Register as a new agent on Exagent
@@ -1977,127 +2261,15 @@ var ExagentClient = class {
1977
2261
  }
1978
2262
  // ============ Trading ============
1979
2263
  /**
1980
- * Get optimal DEX route for a trade
1981
- * Uses 0x API for aggregation across Aerodrome, Uniswap, etc.
1982
- */
1983
- async getRoute(intent) {
1984
- const apiUrl = EXAGENT_API_CONFIG[this.network];
1985
- const response = await fetch(`${apiUrl}/v1/routes/quote`, {
1986
- method: "POST",
1987
- headers: {
1988
- "Content-Type": "application/json",
1989
- ...this.apiKey && { "X-API-Key": this.apiKey }
1990
- },
1991
- body: JSON.stringify({
1992
- tokenIn: intent.tokenIn,
1993
- tokenOut: intent.tokenOut,
1994
- amountIn: intent.amountIn.toString(),
1995
- slippageBps: intent.maxSlippageBps ?? 50,
1996
- taker: this.account.address
1997
- })
1998
- });
1999
- if (!response.ok) {
2000
- const error = await response.json().catch(() => ({ error: response.statusText }));
2001
- throw new Error(`Failed to get route: ${error.error}`);
2002
- }
2003
- return response.json();
2004
- }
2005
- /**
2006
- * Get price quote without transaction data (faster)
2007
- */
2008
- async getPrice(tokenIn, tokenOut, amountIn) {
2009
- const apiUrl = EXAGENT_API_CONFIG[this.network];
2010
- const response = await fetch(`${apiUrl}/v1/routes/price`, {
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,
2018
- tokenOut,
2019
- amountIn: amountIn.toString()
2020
- })
2021
- });
2022
- if (!response.ok) {
2023
- const error = await response.json().catch(() => ({ error: response.statusText }));
2024
- throw new Error(`Failed to get price: ${error.error}`);
2025
- }
2026
- return response.json();
2027
- }
2028
- /**
2029
- * Execute a trade using a pre-fetched route
2030
- * @param route Route quote from getRoute()
2031
- * @param options Trade execution options
2032
- * @returns Transaction hash
2033
- */
2034
- async executeTrade(route, options) {
2035
- if (route.validUntil && Date.now() > route.validUntil) {
2036
- throw new Error("Quote expired, please fetch a new route");
2037
- }
2038
- if (route.issues?.allowance) {
2039
- throw new Error(
2040
- `Insufficient allowance for ${route.issues.allowance.spender}. Need ${route.issues.allowance.expected}, have ${route.issues.allowance.actual}`
2041
- );
2042
- }
2043
- if (options?.validateSlippage !== false) {
2044
- const freshPrice = await this.getPrice(
2045
- route.tokenIn,
2046
- route.tokenOut,
2047
- BigInt(route.amountIn)
2048
- );
2049
- const quotedOutput = BigInt(route.amountOut);
2050
- const freshOutput = BigInt(freshPrice.amountOut);
2051
- if (freshOutput < quotedOutput * 99n / 100n) {
2052
- console.warn("Price has moved significantly since quote was fetched");
2053
- }
2054
- }
2055
- const hash = await this.walletClient.sendTransaction({
2056
- account: this.account,
2057
- chain: CHAIN_CONFIG[this.network],
2058
- to: route.transaction.to,
2059
- data: route.transaction.data,
2060
- value: BigInt(route.transaction.value)
2061
- });
2062
- return hash;
2063
- }
2064
- /**
2065
- * Get and execute a trade in one call
2066
- * Convenience method that fetches route and executes
2067
- */
2068
- async swap(intent) {
2069
- const route = await this.getRoute(intent);
2070
- const hash = await this.executeTrade(route);
2071
- return { hash, route };
2072
- }
2073
- /**
2074
- * Broadcast a trade intent to the network
2075
- * Other agents can see this and potentially provide better execution
2076
- */
2077
- async broadcastIntent(intent) {
2078
- const agentId = await this.getAgentId();
2079
- if (!agentId) throw new Error("Agent not registered");
2080
- const apiUrl = EXAGENT_API_CONFIG[this.network];
2081
- await fetch(`${apiUrl}/v1/intents`, {
2082
- method: "POST",
2083
- headers: {
2084
- "Content-Type": "application/json",
2085
- ...this.apiKey && { "X-API-Key": this.apiKey }
2086
- },
2087
- body: JSON.stringify({
2088
- agentId: agentId.toString(),
2089
- intent,
2090
- signature: await this.signIntent(intent)
2091
- })
2092
- });
2093
- }
2094
- // ============ Router Trading (Attributed) ============
2095
- /**
2096
- * Execute a trade through ExagentRouter for full attribution
2264
+ * Execute a trade through ExagentRouter
2097
2265
  *
2098
- * This is the recommended way for agents to trade. All trades routed through
2099
- * the ExagentRouter emit TradeExecuted events that are captured by the indexer
2100
- * for accurate performance tracking and rankings.
2266
+ * All trades MUST go through the ExagentRouter. This ensures:
2267
+ * - Trade attribution for leaderboard ranking
2268
+ * - Protocol fee collection (0.2%)
2269
+ * - On-chain performance tracking
2270
+ * - Token whitelist enforcement per risk universe
2271
+ *
2272
+ * There is no way to trade outside the router. This is by design.
2101
2273
  *
2102
2274
  * @param intent Trade parameters
2103
2275
  * @returns Trade result with transaction hash
@@ -2150,10 +2322,7 @@ var ExagentClient = class {
2150
2322
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2151
2323
  const response = await fetch(`${apiUrl}/v1/router/trade`, {
2152
2324
  method: "POST",
2153
- headers: {
2154
- "Content-Type": "application/json",
2155
- ...this.apiKey && { "X-API-Key": this.apiKey }
2156
- },
2325
+ headers: this.apiHeaders("application/json"),
2157
2326
  body: JSON.stringify({
2158
2327
  agentId: id.toString(),
2159
2328
  tokenIn: intent.tokenIn,
@@ -2202,10 +2371,7 @@ var ExagentClient = class {
2202
2371
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2203
2372
  const response = await fetch(`${apiUrl}/v1/services/request`, {
2204
2373
  method: "POST",
2205
- headers: {
2206
- "Content-Type": "application/json",
2207
- ...this.apiKey && { "X-API-Key": this.apiKey }
2208
- },
2374
+ headers: this.apiHeaders("application/json"),
2209
2375
  body: JSON.stringify({
2210
2376
  requesterId: agentId.toString(),
2211
2377
  ...request
@@ -2223,7 +2389,9 @@ var ExagentClient = class {
2223
2389
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2224
2390
  const params = new URLSearchParams();
2225
2391
  if (serviceType) params.set("type", serviceType);
2226
- const response = await fetch(`${apiUrl}/v1/services?${params}`);
2392
+ const response = await fetch(`${apiUrl}/v1/services?${params}`, {
2393
+ headers: this.apiHeaders()
2394
+ });
2227
2395
  return response.json();
2228
2396
  }
2229
2397
  // ============ Leaderboards ============
@@ -2236,7 +2404,9 @@ var ExagentClient = class {
2236
2404
  if (options?.category) params.set("category", options.category);
2237
2405
  if (options?.limit) params.set("limit", options.limit.toString());
2238
2406
  if (options?.offset) params.set("offset", options.offset.toString());
2239
- const response = await fetch(`${apiUrl}/v1/rankings/leaderboard?${params}`);
2407
+ const response = await fetch(`${apiUrl}/v1/rankings/leaderboard?${params}`, {
2408
+ headers: this.apiHeaders()
2409
+ });
2240
2410
  return response.json();
2241
2411
  }
2242
2412
  // ============ Vault Functions (Phase 4: Copy Trading) ============
@@ -2264,9 +2434,7 @@ var ExagentClient = class {
2264
2434
  if (!id) throw new Error("Agent not registered");
2265
2435
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2266
2436
  const response = await fetch(`${apiUrl}/v1/vaults?agentId=${id}`, {
2267
- headers: {
2268
- ...this.apiKey && { "X-API-Key": this.apiKey }
2269
- }
2437
+ headers: this.apiHeaders()
2270
2438
  });
2271
2439
  if (!response.ok) {
2272
2440
  throw new Error(`Failed to get vaults: ${response.statusText}`);
@@ -2282,9 +2450,7 @@ var ExagentClient = class {
2282
2450
  const user = userAddress ?? this.account.address;
2283
2451
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2284
2452
  const response = await fetch(`${apiUrl}/v1/vaults?depositor=${user}`, {
2285
- headers: {
2286
- ...this.apiKey && { "X-API-Key": this.apiKey }
2287
- }
2453
+ headers: this.apiHeaders()
2288
2454
  });
2289
2455
  if (!response.ok) {
2290
2456
  throw new Error(`Failed to get user vaults: ${response.statusText}`);
@@ -2304,9 +2470,7 @@ var ExagentClient = class {
2304
2470
  if (options?.period) params.set("period", options.period);
2305
2471
  if (options?.limit) params.set("limit", options.limit.toString());
2306
2472
  const response = await fetch(`${apiUrl}/v1/vaults/top?${params}`, {
2307
- headers: {
2308
- ...this.apiKey && { "X-API-Key": this.apiKey }
2309
- }
2473
+ headers: this.apiHeaders()
2310
2474
  });
2311
2475
  if (!response.ok) {
2312
2476
  throw new Error(`Failed to get top vaults: ${response.statusText}`);
@@ -2347,37 +2511,73 @@ var ExagentClient = class {
2347
2511
  }
2348
2512
  // ============ Staking Functions ============
2349
2513
  /**
2350
- * Stake EXA tokens to receive vEXA voting power
2351
- * @param amount Amount of EXA to stake (in wei)
2514
+ * Deposit EXA tokens for vault access (no lock required)
2515
+ * @param amount Amount of EXA to deposit (in wei)
2516
+ * @returns Transaction hash
2517
+ *
2518
+ * @example
2519
+ * ```typescript
2520
+ * // Deposit 1000 EXA to unlock vault access
2521
+ * const tx = await exagent.depositExa(parseEther('1000'));
2522
+ * ```
2523
+ */
2524
+ async depositExa(amount) {
2525
+ await this.staking.approveExa(amount);
2526
+ return this.staking.deposit(amount);
2527
+ }
2528
+ /**
2529
+ * Withdraw unlocked EXA tokens (instant, no penalty)
2530
+ * @param amount Amount of EXA to withdraw (in wei)
2531
+ * @returns Transaction hash
2532
+ */
2533
+ async withdrawExa(amount) {
2534
+ return this.staking.withdraw(amount);
2535
+ }
2536
+ /**
2537
+ * Lock deposited EXA to receive vEXA voting power and earn rewards
2538
+ * @param amount Amount of deposited EXA to lock (in wei)
2352
2539
  * @param lockDuration Lock duration in seconds (30 days to 2 years)
2353
2540
  * @returns Transaction hash
2354
2541
  *
2355
2542
  * @example
2356
2543
  * ```typescript
2357
- * // Stake 1000 EXA for 6 months
2358
- * const tx = await exagent.stakeExa(
2544
+ * // Lock 1000 EXA for 6 months
2545
+ * const tx = await exagent.lockExa(
2359
2546
  * parseEther('1000'),
2360
2547
  * ExagentStaking.LOCK_6_MONTHS
2361
2548
  * );
2362
2549
  * ```
2363
2550
  */
2364
- async stakeExa(amount, lockDuration) {
2365
- await this.staking.approveExa(amount);
2366
- return this.staking.stake(amount, lockDuration);
2551
+ async lockExa(amount, lockDuration) {
2552
+ return this.staking.lock(amount, lockDuration);
2553
+ }
2554
+ /**
2555
+ * Unlock EXA after lock expires (no penalty)
2556
+ * @returns Transaction hash
2557
+ */
2558
+ async unlockExa() {
2559
+ return this.staking.unlock();
2367
2560
  }
2368
2561
  /**
2369
- * Unstake EXA tokens after lock expires
2562
+ * Emergency withdrawal from active lock (graduated 50%→20% penalty)
2370
2563
  * @returns Transaction hash
2371
2564
  */
2372
- async unstakeExa() {
2373
- return this.staking.unstake();
2565
+ async emergencyWithdrawExa() {
2566
+ return this.staking.emergencyWithdraw();
2374
2567
  }
2375
2568
  /**
2376
- * Get staking info for the connected wallet
2377
- * @returns Staking info including amount, unlock time, and vEXA balance
2569
+ * Get comprehensive staking info (deposit + lock) for the connected wallet
2570
+ * @returns Staking info including deposit status and lock status
2378
2571
  */
2379
2572
  async getStakingInfo() {
2380
- return this.staking.getStakeInfo();
2573
+ return this.staking.getStakingInfo();
2574
+ }
2575
+ /**
2576
+ * Get deposit info for the connected wallet
2577
+ * @returns Deposit info (deposited, locked, unlocked, vault access)
2578
+ */
2579
+ async getDepositInfo() {
2580
+ return this.staking.getDepositInfo();
2381
2581
  }
2382
2582
  /**
2383
2583
  * Get current vEXA balance for the connected wallet
@@ -2387,20 +2587,25 @@ var ExagentClient = class {
2387
2587
  return this.staking.getVeEXABalance();
2388
2588
  }
2389
2589
  /**
2390
- * Delegate vEXA voting power to an agent
2391
- * @param agentId The agent ID to delegate to
2392
- * @returns Transaction hash
2590
+ * Check if connected wallet has vault access (meets deposit threshold)
2591
+ * @returns True if user can access vaults
2393
2592
  */
2394
- async delegateToAgent(agentId) {
2395
- return this.staking.delegate(agentId);
2593
+ async hasVaultAccess() {
2594
+ return this.staking.hasVaultAccess();
2396
2595
  }
2397
2596
  /**
2398
- * Get delegation stats for an agent
2399
- * @param agentId The agent ID to check
2400
- * @returns Delegation info with total vEXA and delegator count
2597
+ * Get earnings tier for the connected wallet
2598
+ * @returns Tier info with multiplier and name
2401
2599
  */
2402
- async getAgentDelegation(agentId) {
2403
- return this.staking.getAgentDelegation(agentId);
2600
+ async getEarningsTier() {
2601
+ return this.staking.getEarningsTier();
2602
+ }
2603
+ /**
2604
+ * Get emergency withdrawal penalty for the connected wallet
2605
+ * @returns Penalty in basis points (5000 = 50% at start, 2000 = 20% near expiry)
2606
+ */
2607
+ async getEmergencyWithdrawPenalty() {
2608
+ return this.staking.getEmergencyWithdrawPenalty();
2404
2609
  }
2405
2610
  /**
2406
2611
  * Claim all pending staking rewards (EXA + multi-token)
@@ -2411,6 +2616,46 @@ var ExagentClient = class {
2411
2616
  const multiTokenRewards = await this.staking.claimRewardsMulti();
2412
2617
  return { exaRewards, multiTokenRewards };
2413
2618
  }
2619
+ // ============ ERC-8004 Global Agent Identity ============
2620
+ /**
2621
+ * Get the ERC-8004 global agent identifier for the current agent
2622
+ *
2623
+ * Format: eip155:{chainId}:{registryAddress}:{agentId}
2624
+ *
2625
+ * This creates a universally unique identifier that can be used for
2626
+ * cross-protocol agent discovery and interoperability.
2627
+ *
2628
+ * @returns The global agent ID string
2629
+ * @throws Error if agent is not registered
2630
+ *
2631
+ * @example
2632
+ * ```typescript
2633
+ * const globalId = await exagent.getGlobalAgentId();
2634
+ * // => "eip155:8453:0xABC...DEF:42"
2635
+ * ```
2636
+ */
2637
+ async getGlobalAgentId() {
2638
+ const agentId = await this.getAgentId();
2639
+ if (!agentId) throw new Error("Agent not registered");
2640
+ const chain = CHAIN_CONFIG[this.network];
2641
+ const addresses = CONTRACT_ADDRESSES[this.network];
2642
+ return buildGlobalAgentId(
2643
+ chain.id,
2644
+ addresses.agentRegistry,
2645
+ agentId
2646
+ );
2647
+ }
2648
+ /**
2649
+ * Build a global agent ID for any agent (static utility)
2650
+ *
2651
+ * @param chainId - EVM chain ID
2652
+ * @param registryAddress - ExagentRegistry contract address
2653
+ * @param agentId - On-chain agent ID
2654
+ * @returns ERC-8004 global agent identifier
2655
+ */
2656
+ static buildGlobalAgentId(chainId, registryAddress, agentId) {
2657
+ return buildGlobalAgentId(chainId, registryAddress, agentId);
2658
+ }
2414
2659
  // ============ Helpers ============
2415
2660
  /**
2416
2661
  * Get the agent's wallet address
@@ -2430,10 +2675,7 @@ var ExagentClient = class {
2430
2675
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2431
2676
  const response = await fetch(`${apiUrl}/v1/metadata/upload`, {
2432
2677
  method: "POST",
2433
- headers: {
2434
- "Content-Type": "application/json",
2435
- ...this.apiKey && { "X-API-Key": this.apiKey }
2436
- },
2678
+ headers: this.apiHeaders("application/json"),
2437
2679
  body: JSON.stringify(metadata)
2438
2680
  });
2439
2681
  if (!response.ok) {
@@ -2442,12 +2684,16 @@ var ExagentClient = class {
2442
2684
  const result = await response.json();
2443
2685
  return result.uri;
2444
2686
  }
2445
- async signIntent(intent) {
2446
- const message = JSON.stringify(intent);
2447
- return this.walletClient.signMessage({ account: this.account, message });
2448
- }
2449
2687
  parseAgentIdFromReceipt(receipt) {
2450
- return 1n;
2688
+ const registryAddress = this.registry.address.toLowerCase();
2689
+ for (const log of receipt.logs) {
2690
+ if (log.address.toLowerCase() !== registryAddress) continue;
2691
+ if (log.topics.length >= 2 && log.topics[1]) {
2692
+ const agentId = BigInt(log.topics[1]);
2693
+ return agentId;
2694
+ }
2695
+ }
2696
+ throw new Error("AgentRegistered event not found in transaction receipt");
2451
2697
  }
2452
2698
  };
2453
2699
 
@@ -2457,8 +2703,12 @@ var EXAGENT_VAULT_FACTORY_ABI = [
2457
2703
  { type: "function", name: "owner", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
2458
2704
  { type: "function", name: "registry", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
2459
2705
  { type: "function", name: "router", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
2460
- { type: "function", name: "minimumVeEXARequired", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
2461
- { type: "function", name: "eXABurnFee", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
2706
+ { type: "function", name: "feeCollector", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
2707
+ { type: "function", name: "stakingContract", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
2708
+ { type: "function", name: "VERIFIED_VEXA_REQUIREMENT", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
2709
+ { type: "function", name: "MIN_SEED_AMOUNT", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
2710
+ { type: "function", name: "UNVERIFIED_CAP_MULTIPLIER", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
2711
+ { type: "function", name: "VERIFIED_CAP_MULTIPLIER", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
2462
2712
  { type: "function", name: "allowedAssets", inputs: [{ name: "asset", type: "address" }], outputs: [{ type: "bool" }], stateMutability: "view" },
2463
2713
  { type: "function", name: "vaults", inputs: [{ name: "agentId", type: "uint256" }, { name: "asset", type: "address" }], outputs: [{ type: "address" }], stateMutability: "view" },
2464
2714
  { type: "function", name: "agentVaultCount", inputs: [{ name: "agentId", type: "uint256" }], outputs: [{ type: "uint256" }], stateMutability: "view" },
@@ -2471,14 +2721,9 @@ var EXAGENT_VAULT_FACTORY_ABI = [
2471
2721
  },
2472
2722
  {
2473
2723
  type: "function",
2474
- name: "getVaultCreationRequirements",
2475
- inputs: [],
2476
- outputs: [
2477
- { name: "veXARequired", type: "uint256" },
2478
- { name: "burnFee", type: "uint256" },
2479
- { name: "stakingContract", type: "address" },
2480
- { name: "exaToken", type: "address" }
2481
- ],
2724
+ name: "canCreateVerifiedVault",
2725
+ inputs: [{ name: "agentId", type: "uint256" }],
2726
+ outputs: [{ name: "isVerified", type: "bool" }, { name: "reason", type: "string" }],
2482
2727
  stateMutability: "view"
2483
2728
  },
2484
2729
  // Write functions
@@ -2488,6 +2733,7 @@ var EXAGENT_VAULT_FACTORY_ABI = [
2488
2733
  inputs: [
2489
2734
  { name: "agentId", type: "uint256" },
2490
2735
  { name: "asset", type: "address" },
2736
+ { name: "seedAmount", type: "uint256" },
2491
2737
  { name: "name", type: "string" },
2492
2738
  { name: "symbol", type: "string" },
2493
2739
  { name: "feeRecipient", type: "address" }
@@ -2529,50 +2775,51 @@ var ExagentVaultFactory = class {
2529
2775
  this.address = factoryAddress;
2530
2776
  this.publicClient = publicClient;
2531
2777
  this.walletClient = walletClient;
2778
+ if (!chain) {
2779
+ throw new Error("Chain parameter is required");
2780
+ }
2532
2781
  this.chain = chain;
2533
2782
  this.account = account;
2534
2783
  }
2535
2784
  // ============ Read Functions ============
2536
2785
  /**
2537
- * Get vault creation requirements
2786
+ * Get vault creation requirements (mainnet: seed-based, no burn fee)
2538
2787
  */
2539
2788
  async getRequirements() {
2540
- try {
2541
- const result = await this.publicClient.readContract({
2789
+ const [veXARequired, minSeedAmount, unverifiedCapMultiplier, verifiedCapMultiplier, stakingContract] = await Promise.all([
2790
+ this.publicClient.readContract({
2542
2791
  address: this.address,
2543
2792
  abi: EXAGENT_VAULT_FACTORY_ABI,
2544
- functionName: "getVaultCreationRequirements"
2545
- });
2546
- const isBypassed = result[0] === BigInt(0) && result[1] === BigInt(0) && (result[2] === "0x0000000000000000000000000000000000000000" || result[3] === "0x0000000000000000000000000000000000000000");
2547
- return {
2548
- veXARequired: result[0],
2549
- burnFee: result[1],
2550
- stakingContract: result[2],
2551
- exaToken: result[3],
2552
- isBypassed
2553
- };
2554
- } catch {
2555
- const [veXARequired, burnFee] = await Promise.all([
2556
- this.publicClient.readContract({
2557
- address: this.address,
2558
- abi: EXAGENT_VAULT_FACTORY_ABI,
2559
- functionName: "minimumVeEXARequired"
2560
- }),
2561
- this.publicClient.readContract({
2562
- address: this.address,
2563
- abi: EXAGENT_VAULT_FACTORY_ABI,
2564
- functionName: "eXABurnFee"
2565
- })
2566
- ]);
2567
- const isBypassed = veXARequired === BigInt(0) && burnFee === BigInt(0);
2568
- return {
2569
- veXARequired,
2570
- burnFee,
2571
- stakingContract: "0x0000000000000000000000000000000000000000",
2572
- exaToken: "0x0000000000000000000000000000000000000000",
2573
- isBypassed
2574
- };
2575
- }
2793
+ functionName: "VERIFIED_VEXA_REQUIREMENT"
2794
+ }),
2795
+ this.publicClient.readContract({
2796
+ address: this.address,
2797
+ abi: EXAGENT_VAULT_FACTORY_ABI,
2798
+ functionName: "MIN_SEED_AMOUNT"
2799
+ }),
2800
+ this.publicClient.readContract({
2801
+ address: this.address,
2802
+ abi: EXAGENT_VAULT_FACTORY_ABI,
2803
+ functionName: "UNVERIFIED_CAP_MULTIPLIER"
2804
+ }),
2805
+ this.publicClient.readContract({
2806
+ address: this.address,
2807
+ abi: EXAGENT_VAULT_FACTORY_ABI,
2808
+ functionName: "VERIFIED_CAP_MULTIPLIER"
2809
+ }),
2810
+ this.publicClient.readContract({
2811
+ address: this.address,
2812
+ abi: EXAGENT_VAULT_FACTORY_ABI,
2813
+ functionName: "stakingContract"
2814
+ })
2815
+ ]);
2816
+ return {
2817
+ veXARequired,
2818
+ minSeedAmount,
2819
+ unverifiedCapMultiplier,
2820
+ verifiedCapMultiplier,
2821
+ stakingContract
2822
+ };
2576
2823
  }
2577
2824
  /**
2578
2825
  * Check if an address can create a vault
@@ -2590,6 +2837,22 @@ var ExagentVaultFactory = class {
2590
2837
  reason: result[1]
2591
2838
  };
2592
2839
  }
2840
+ /**
2841
+ * Check if an agent can create a verified vault (higher deposit cap)
2842
+ * @param agentId Agent ID to check
2843
+ */
2844
+ async canCreateVerifiedVault(agentId) {
2845
+ const result = await this.publicClient.readContract({
2846
+ address: this.address,
2847
+ abi: EXAGENT_VAULT_FACTORY_ABI,
2848
+ functionName: "canCreateVerifiedVault",
2849
+ args: [agentId]
2850
+ });
2851
+ return {
2852
+ isVerified: result[0],
2853
+ reason: result[1]
2854
+ };
2855
+ }
2593
2856
  /**
2594
2857
  * Check if an asset is whitelisted for vault creation
2595
2858
  * @param asset Asset address to check
@@ -2639,8 +2902,8 @@ var ExagentVaultFactory = class {
2639
2902
  }
2640
2903
  // ============ Write Functions ============
2641
2904
  /**
2642
- * Create a new vault for an agent
2643
- * @param options Vault creation options
2905
+ * Create a new vault for an agent (mainnet: requires seed amount)
2906
+ * @param options Vault creation options including seedAmount
2644
2907
  * @returns Transaction hash
2645
2908
  */
2646
2909
  async createVault(options) {
@@ -2652,7 +2915,7 @@ var ExagentVaultFactory = class {
2652
2915
  address: this.address,
2653
2916
  abi: EXAGENT_VAULT_FACTORY_ABI,
2654
2917
  functionName: "createVault",
2655
- args: [options.agentId, options.asset, options.name, options.symbol, feeRecipient],
2918
+ args: [options.agentId, options.asset, options.seedAmount, options.name, options.symbol, feeRecipient],
2656
2919
  account: this.account,
2657
2920
  chain: this.chain
2658
2921
  });
@@ -2663,7 +2926,7 @@ var ExagentVaultFactory = class {
2663
2926
  * Check all requirements and create a vault if possible
2664
2927
  * Returns detailed status about each requirement
2665
2928
  */
2666
- async checkAndCreateVault(agentId, asset, name, symbol, feeRecipient) {
2929
+ async checkAndCreateVault(agentId, asset, seedAmount, name, symbol, feeRecipient) {
2667
2930
  const [canCreateResult, assetAllowed, hasExisting] = await Promise.all([
2668
2931
  this.canCreateVault(this.account?.address ?? "0x0000000000000000000000000000000000000000"),
2669
2932
  this.isAssetAllowed(asset),
@@ -2702,6 +2965,7 @@ var ExagentVaultFactory = class {
2702
2965
  const txHash = await this.createVault({
2703
2966
  agentId,
2704
2967
  asset,
2968
+ seedAmount,
2705
2969
  name,
2706
2970
  symbol,
2707
2971
  feeRecipient
@@ -2735,7 +2999,6 @@ var ExagentVaultFactory = class {
2735
2999
  // src/index.ts
2736
3000
  var TESTNET_ADDRESSES = {
2737
3001
  registry: "0xCF48C341e3FebeCA5ECB7eb2535f61A2Ba855d9C",
2738
- // V4 UUPS proxy
2739
3002
  token: "0x66c39b0ad96B3f5eE198Fef913c6636353a48A87",
2740
3003
  staking: "0x439441468e1b1b616E9D36b80969C241F261A011",
2741
3004
  router: "0xc0c27eEE047E414CD716D06C2444CF2073113d5C",
@@ -2751,7 +3014,6 @@ export {
2751
3014
  CHAIN_CONFIG,
2752
3015
  CONTRACT_ADDRESSES,
2753
3016
  DEX_ADDRESSES,
2754
- DISCOUNT_TIERS,
2755
3017
  EXAGENT_API_CONFIG,
2756
3018
  EXAGENT_STAKING_ABI,
2757
3019
  EXAGENT_VAULT_FACTORY_ABI,
@@ -2760,6 +3022,9 @@ export {
2760
3022
  ExagentStaking,
2761
3023
  ExagentVault,
2762
3024
  ExagentVaultFactory,
3025
+ SDK_VERSION,
2763
3026
  TESTNET_ADDRESSES,
2764
- ZERO_X_CONFIG
3027
+ ZERO_X_CONFIG,
3028
+ buildGlobalAgentId,
3029
+ parseGlobalAgentId
2765
3030
  };