@exagent/sdk 0.1.2 → 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,
@@ -15,7 +8,8 @@ import { privateKeyToAccount } from "viem/accounts";
15
8
 
16
9
  // src/contracts/registry.ts
17
10
  import {
18
- encodePacked
11
+ encodePacked,
12
+ keccak256
19
13
  } from "viem";
20
14
  var EXAGENT_REGISTRY_ABI = [
21
15
  {
@@ -23,7 +17,10 @@ var EXAGENT_REGISTRY_ABI = [
23
17
  name: "registerAgent",
24
18
  inputs: [
25
19
  { name: "name", type: "string" },
26
- { name: "metadataURI", type: "string" }
20
+ { name: "metadataURI", type: "string" },
21
+ { name: "riskUniverse", type: "uint8" },
22
+ { name: "maxPositionSizeBps", type: "uint256" },
23
+ { name: "maxDailyLossBps", type: "uint256" }
27
24
  ],
28
25
  outputs: [{ name: "agentId", type: "uint256" }],
29
26
  stateMutability: "nonpayable"
@@ -253,6 +250,62 @@ var EXAGENT_REGISTRY_ABI = [
253
250
  outputs: [{ name: "", type: "bytes32" }],
254
251
  stateMutability: "view"
255
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
+ },
256
309
  {
257
310
  type: "event",
258
311
  name: "ConfigUpdated",
@@ -263,7 +316,16 @@ var EXAGENT_REGISTRY_ABI = [
263
316
  { name: "epochId", type: "uint256", indexed: false },
264
317
  { name: "blockNumber", type: "uint256", indexed: false }
265
318
  ]
266
- }
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: [] }
267
329
  ];
268
330
  var ExagentRegistry = class {
269
331
  address;
@@ -284,9 +346,12 @@ var ExagentRegistry = class {
284
346
  * Register a new agent
285
347
  * @param name Unique agent name (3-32 chars, alphanumeric + spaces/hyphens/underscores)
286
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)
287
352
  * @returns Transaction hash
288
353
  */
289
- async register(name, metadataURI) {
354
+ async register(name, metadataURI, riskUniverse = 1, maxPositionSizeBps = 1000n, maxDailyLossBps = 500n) {
290
355
  if (!this.walletClient || !this.account) throw new Error("Wallet client and account required for write operations");
291
356
  const hash = await this.walletClient.writeContract({
292
357
  account: this.account,
@@ -294,7 +359,7 @@ var ExagentRegistry = class {
294
359
  address: this.address,
295
360
  abi: EXAGENT_REGISTRY_ABI,
296
361
  functionName: "registerAgent",
297
- args: [name, metadataURI]
362
+ args: [name, metadataURI, riskUniverse, maxPositionSizeBps, maxDailyLossBps]
298
363
  });
299
364
  return hash;
300
365
  }
@@ -485,19 +550,19 @@ var ExagentRegistry = class {
485
550
  return nextId;
486
551
  }
487
552
  /**
488
- * Generate the raw packed message bytes for wallet linking.
489
- * Must match the contract's abi.encodePacked format exactly:
490
- * keccak256(abi.encodePacked("Link wallet ", wallet, " to Exagent ", agentId, " nonce ", nonce))
553
+ * Generate the message hash for wallet linking.
554
+ * Matches the contract's keccak256(abi.encodePacked(...)) exactly.
555
+ * Sign the returned hash with signMessage({ raw: hash }) to produce a valid signature.
491
556
  * @param wallet The wallet to link
492
557
  * @param agentId The agent ID to link to
493
558
  * @param nonce The current nonce for the wallet
494
- * @returns Raw packed bytes as hex string
559
+ * @returns keccak256 hash of the packed message (32 bytes)
495
560
  */
496
561
  static generateLinkMessage(wallet, agentId, nonce) {
497
- return encodePacked(
562
+ return keccak256(encodePacked(
498
563
  ["string", "address", "string", "uint256", "string", "uint256"],
499
564
  ["Link wallet ", wallet, " to Exagent ", agentId, " nonce ", nonce]
500
- );
565
+ ));
501
566
  }
502
567
  // ============ V4: One Agent Per Wallet ============
503
568
  /**
@@ -629,8 +694,84 @@ var ExagentRegistry = class {
629
694
  * @returns keccak256 hash of the config
630
695
  */
631
696
  static calculateConfigHash(provider, model) {
632
- const { keccak256, encodePacked: encodePacked2 } = __require("viem");
633
- return keccak256(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;
634
775
  }
635
776
  };
636
777
 
@@ -721,6 +862,9 @@ var ExagentVault = class {
721
862
  this.address = vaultAddress;
722
863
  this.publicClient = publicClient;
723
864
  this.walletClient = walletClient;
865
+ if (!chain) {
866
+ throw new Error("Chain parameter is required");
867
+ }
724
868
  this.chain = chain;
725
869
  this.account = account;
726
870
  }
@@ -1067,17 +1211,34 @@ var ExagentVault = class {
1067
1211
  var EXAGENT_STAKING_ABI = [
1068
1212
  // ============ State Variables ============
1069
1213
  { type: "function", name: "exaToken", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
1070
- { 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" },
1071
1216
  { type: "function", name: "totalVeEXA", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1072
- { type: "function", name: "registry", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
1217
+ { type: "function", name: "totalEffectiveVeEXA", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1073
1218
  // ============ Constants ============
1074
1219
  { type: "function", name: "MIN_LOCK_DURATION", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1075
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" },
1076
1222
  { type: "function", name: "PRECISION", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1077
- // ============ 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
+ },
1078
1231
  {
1079
1232
  type: "function",
1080
- name: "stake",
1233
+ name: "withdraw",
1234
+ inputs: [{ name: "amount", type: "uint256" }],
1235
+ outputs: [],
1236
+ stateMutability: "nonpayable"
1237
+ },
1238
+ // ============ Phase 2: Lock / Unlock ============
1239
+ {
1240
+ type: "function",
1241
+ name: "lock",
1081
1242
  inputs: [
1082
1243
  { name: "amount", type: "uint256" },
1083
1244
  { name: "lockDuration", type: "uint256" }
@@ -1085,7 +1246,6 @@ var EXAGENT_STAKING_ABI = [
1085
1246
  outputs: [],
1086
1247
  stateMutability: "nonpayable"
1087
1248
  },
1088
- { type: "function", name: "unstake", inputs: [], outputs: [], stateMutability: "nonpayable" },
1089
1249
  {
1090
1250
  type: "function",
1091
1251
  name: "extendLock",
@@ -1093,6 +1253,8 @@ var EXAGENT_STAKING_ABI = [
1093
1253
  outputs: [],
1094
1254
  stateMutability: "nonpayable"
1095
1255
  },
1256
+ { type: "function", name: "unlock", inputs: [], outputs: [], stateMutability: "nonpayable" },
1257
+ { type: "function", name: "emergencyWithdraw", inputs: [], outputs: [], stateMutability: "nonpayable" },
1096
1258
  // ============ Reward Functions ============
1097
1259
  { type: "function", name: "claimRewards", inputs: [], outputs: [], stateMutability: "nonpayable" },
1098
1260
  { type: "function", name: "claimRewardsMulti", inputs: [], outputs: [], stateMutability: "nonpayable" },
@@ -1103,26 +1265,17 @@ var EXAGENT_STAKING_ABI = [
1103
1265
  outputs: [],
1104
1266
  stateMutability: "nonpayable"
1105
1267
  },
1106
- // ============ Delegation Functions ============
1107
- {
1108
- type: "function",
1109
- name: "delegate",
1110
- inputs: [{ name: "agentId", type: "uint256" }],
1111
- outputs: [],
1112
- stateMutability: "nonpayable"
1113
- },
1114
- { type: "function", name: "undelegate", inputs: [], outputs: [], stateMutability: "nonpayable" },
1268
+ // ============ View Functions ============
1115
1269
  {
1116
1270
  type: "function",
1117
- name: "redelegate",
1118
- inputs: [{ name: "newAgentId", type: "uint256" }],
1119
- outputs: [],
1120
- stateMutability: "nonpayable"
1271
+ name: "depositedAmount",
1272
+ inputs: [{ name: "user", type: "address" }],
1273
+ outputs: [{ type: "uint256" }],
1274
+ stateMutability: "view"
1121
1275
  },
1122
- // ============ View Functions ============
1123
1276
  {
1124
1277
  type: "function",
1125
- name: "stakes",
1278
+ name: "locks",
1126
1279
  inputs: [{ name: "user", type: "address" }],
1127
1280
  outputs: [
1128
1281
  { name: "amount", type: "uint256" },
@@ -1139,6 +1292,13 @@ var EXAGENT_STAKING_ABI = [
1139
1292
  outputs: [{ type: "uint256" }],
1140
1293
  stateMutability: "view"
1141
1294
  },
1295
+ {
1296
+ type: "function",
1297
+ name: "getEffectiveVeEXA",
1298
+ inputs: [{ name: "user", type: "address" }],
1299
+ outputs: [{ type: "uint256" }],
1300
+ stateMutability: "view"
1301
+ },
1142
1302
  {
1143
1303
  type: "function",
1144
1304
  name: "calculateVeEXA",
@@ -1168,61 +1328,40 @@ var EXAGENT_STAKING_ABI = [
1168
1328
  },
1169
1329
  {
1170
1330
  type: "function",
1171
- name: "getDelegatedAgent",
1331
+ name: "getEarningsTier",
1172
1332
  inputs: [{ name: "user", type: "address" }],
1173
- outputs: [{ type: "uint256" }],
1174
- stateMutability: "view"
1175
- },
1176
- {
1177
- type: "function",
1178
- name: "getAgentDelegation",
1179
- inputs: [{ name: "agentId", type: "uint256" }],
1180
1333
  outputs: [
1181
- { name: "vexa", type: "uint256" },
1182
- { name: "count", type: "uint256" }
1334
+ { name: "multiplierBps", type: "uint256" },
1335
+ { name: "tierName", type: "string" }
1183
1336
  ],
1184
1337
  stateMutability: "view"
1185
1338
  },
1186
1339
  {
1187
1340
  type: "function",
1188
- name: "getDiscountTier",
1341
+ name: "getEmergencyWithdrawPenalty",
1189
1342
  inputs: [{ name: "user", type: "address" }],
1190
- outputs: [{ name: "discountBps", type: "uint256" }],
1343
+ outputs: [{ name: "penaltyBps", type: "uint256" }],
1191
1344
  stateMutability: "view"
1192
1345
  },
1193
1346
  {
1194
1347
  type: "function",
1195
- name: "getRewardTokens",
1196
- inputs: [],
1197
- outputs: [{ type: "address[]" }],
1198
- stateMutability: "view"
1199
- },
1200
- {
1201
- type: "function",
1202
- name: "delegatedTo",
1348
+ name: "hasVaultAccess",
1203
1349
  inputs: [{ name: "user", type: "address" }],
1204
- outputs: [{ type: "uint256" }],
1350
+ outputs: [{ type: "bool" }],
1205
1351
  stateMutability: "view"
1206
1352
  },
1207
1353
  {
1208
1354
  type: "function",
1209
- name: "userDelegatedVeEXA",
1355
+ name: "getUnlockedBalance",
1210
1356
  inputs: [{ name: "user", type: "address" }],
1211
1357
  outputs: [{ type: "uint256" }],
1212
1358
  stateMutability: "view"
1213
1359
  },
1214
1360
  {
1215
1361
  type: "function",
1216
- name: "agentDelegatedVeEXA",
1217
- inputs: [{ name: "agentId", type: "uint256" }],
1218
- outputs: [{ type: "uint256" }],
1219
- stateMutability: "view"
1220
- },
1221
- {
1222
- type: "function",
1223
- name: "agentDelegatorCount",
1224
- inputs: [{ name: "agentId", type: "uint256" }],
1225
- outputs: [{ type: "uint256" }],
1362
+ name: "getRewardTokens",
1363
+ inputs: [],
1364
+ outputs: [{ type: "address[]" }],
1226
1365
  stateMutability: "view"
1227
1366
  },
1228
1367
  {
@@ -1235,35 +1374,36 @@ var EXAGENT_STAKING_ABI = [
1235
1374
  // ============ Events ============
1236
1375
  {
1237
1376
  type: "event",
1238
- name: "Staked",
1377
+ name: "Deposited",
1239
1378
  inputs: [
1240
1379
  { name: "user", type: "address", indexed: true },
1241
1380
  { name: "amount", type: "uint256", indexed: false },
1242
- { name: "lockDuration", type: "uint256", indexed: false },
1243
- { name: "unlockTime", type: "uint256", indexed: false },
1244
- { name: "vEXABalance", type: "uint256", indexed: false }
1381
+ { name: "totalDeposited", type: "uint256", indexed: false }
1245
1382
  ]
1246
1383
  },
1247
1384
  {
1248
1385
  type: "event",
1249
- name: "Unstaked",
1386
+ name: "Withdrawn",
1250
1387
  inputs: [
1251
1388
  { name: "user", type: "address", indexed: true },
1252
- { name: "amount", type: "uint256", indexed: false }
1389
+ { name: "amount", type: "uint256", indexed: false },
1390
+ { name: "totalDeposited", type: "uint256", indexed: false }
1253
1391
  ]
1254
1392
  },
1255
1393
  {
1256
1394
  type: "event",
1257
- name: "LockExtended",
1395
+ name: "Locked",
1258
1396
  inputs: [
1259
1397
  { name: "user", type: "address", indexed: true },
1260
- { name: "newUnlockTime", type: "uint256", indexed: false },
1261
- { 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 }
1262
1402
  ]
1263
1403
  },
1264
1404
  {
1265
1405
  type: "event",
1266
- name: "RewardsClaimed",
1406
+ name: "Unlocked",
1267
1407
  inputs: [
1268
1408
  { name: "user", type: "address", indexed: true },
1269
1409
  { name: "amount", type: "uint256", indexed: false }
@@ -1271,20 +1411,29 @@ var EXAGENT_STAKING_ABI = [
1271
1411
  },
1272
1412
  {
1273
1413
  type: "event",
1274
- name: "Delegated",
1414
+ name: "EmergencyWithdrawal",
1275
1415
  inputs: [
1276
- { name: "delegator", type: "address", indexed: true },
1277
- { name: "agentId", type: "uint256", indexed: true },
1278
- { 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 }
1279
1420
  ]
1280
1421
  },
1281
1422
  {
1282
1423
  type: "event",
1283
- name: "Undelegated",
1424
+ name: "LockExtended",
1284
1425
  inputs: [
1285
- { name: "delegator", type: "address", indexed: true },
1286
- { name: "agentId", type: "uint256", indexed: true },
1287
- { 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 }
1288
1437
  ]
1289
1438
  },
1290
1439
  {
@@ -1309,15 +1458,6 @@ var ERC20_APPROVE_ABI2 = [
1309
1458
  stateMutability: "nonpayable"
1310
1459
  }
1311
1460
  ];
1312
- var DISCOUNT_TIERS = {
1313
- none: 0,
1314
- bronze: 1e3,
1315
- // 10% discount at 10,000 vEXA
1316
- silver: 2500,
1317
- // 25% discount at 50,000 vEXA
1318
- gold: 5e3
1319
- // 50% discount at 100,000 vEXA
1320
- };
1321
1461
  var ExagentStaking = class {
1322
1462
  address;
1323
1463
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -1330,108 +1470,119 @@ var ExagentStaking = class {
1330
1470
  this.address = stakingAddress;
1331
1471
  this.publicClient = publicClient;
1332
1472
  this.walletClient = walletClient;
1473
+ if (!chain) {
1474
+ throw new Error("Chain parameter is required");
1475
+ }
1333
1476
  this.chain = chain;
1334
1477
  this.account = account;
1335
1478
  }
1336
- // ============ Staking Write Functions ============
1479
+ // ============ Phase 1: Deposit / Withdraw ============
1337
1480
  /**
1338
- * Stake EXA tokens to receive vEXA voting power
1339
- * @param amount Amount of EXA to stake (in wei)
1340
- * @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)
1341
1483
  * @returns Transaction hash
1342
1484
  *
1343
1485
  * @example
1344
1486
  * ```typescript
1345
- * // Stake 1000 EXA for 6 months
1346
- * const tx = await staking.stake(
1347
- * parseEther('1000'),
1348
- * BigInt(180 * 24 * 60 * 60) // 180 days in seconds
1349
- * );
1487
+ * // Deposit 1000 EXA to unlock vault access
1488
+ * const tx = await staking.deposit(parseEther('1000'));
1350
1489
  * ```
1351
1490
  */
1352
- async stake(amount, lockDuration) {
1491
+ async deposit(amount) {
1353
1492
  if (!this.walletClient || !this.account) {
1354
1493
  throw new Error("Wallet client required for write operations");
1355
1494
  }
1356
1495
  const hash = await this.walletClient.writeContract({
1357
1496
  address: this.address,
1358
1497
  abi: EXAGENT_STAKING_ABI,
1359
- functionName: "stake",
1360
- args: [amount, lockDuration],
1498
+ functionName: "deposit",
1499
+ args: [amount],
1361
1500
  account: this.account,
1362
1501
  chain: this.chain
1363
1502
  });
1364
1503
  return hash;
1365
1504
  }
1366
1505
  /**
1367
- * Unstake EXA tokens after lock expires
1506
+ * Withdraw unlocked EXA tokens (instant, no penalty)
1507
+ * @param amount Amount of EXA to withdraw (in wei)
1368
1508
  * @returns Transaction hash
1369
- * @throws Error if lock has not expired
1370
1509
  */
1371
- async unstake() {
1510
+ async withdraw(amount) {
1372
1511
  if (!this.walletClient || !this.account) {
1373
1512
  throw new Error("Wallet client required for write operations");
1374
1513
  }
1375
1514
  const hash = await this.walletClient.writeContract({
1376
1515
  address: this.address,
1377
1516
  abi: EXAGENT_STAKING_ABI,
1378
- functionName: "unstake",
1379
- args: [],
1517
+ functionName: "withdraw",
1518
+ args: [amount],
1380
1519
  account: this.account,
1381
1520
  chain: this.chain
1382
1521
  });
1383
1522
  return hash;
1384
1523
  }
1524
+ // ============ Phase 2: Lock / Unlock ============
1385
1525
  /**
1386
- * Extend lock duration for additional voting power
1387
- * @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)
1388
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
+ * ```
1389
1539
  */
1390
- async extendLock(newLockDuration) {
1540
+ async lock(amount, lockDuration) {
1391
1541
  if (!this.walletClient || !this.account) {
1392
1542
  throw new Error("Wallet client required for write operations");
1393
1543
  }
1394
1544
  const hash = await this.walletClient.writeContract({
1395
1545
  address: this.address,
1396
1546
  abi: EXAGENT_STAKING_ABI,
1397
- functionName: "extendLock",
1398
- args: [newLockDuration],
1547
+ functionName: "lock",
1548
+ args: [amount, lockDuration],
1399
1549
  account: this.account,
1400
1550
  chain: this.chain
1401
1551
  });
1402
1552
  return hash;
1403
1553
  }
1404
- // ============ Reward Write Functions ============
1405
1554
  /**
1406
- * 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)
1407
1557
  * @returns Transaction hash
1408
1558
  */
1409
- async claimRewards() {
1559
+ async extendLock(newLockDuration) {
1410
1560
  if (!this.walletClient || !this.account) {
1411
1561
  throw new Error("Wallet client required for write operations");
1412
1562
  }
1413
1563
  const hash = await this.walletClient.writeContract({
1414
1564
  address: this.address,
1415
1565
  abi: EXAGENT_STAKING_ABI,
1416
- functionName: "claimRewards",
1417
- args: [],
1566
+ functionName: "extendLock",
1567
+ args: [newLockDuration],
1418
1568
  account: this.account,
1419
1569
  chain: this.chain
1420
1570
  });
1421
1571
  return hash;
1422
1572
  }
1423
1573
  /**
1424
- * 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.
1425
1576
  * @returns Transaction hash
1426
1577
  */
1427
- async claimRewardsMulti() {
1578
+ async unlock() {
1428
1579
  if (!this.walletClient || !this.account) {
1429
1580
  throw new Error("Wallet client required for write operations");
1430
1581
  }
1431
1582
  const hash = await this.walletClient.writeContract({
1432
1583
  address: this.address,
1433
1584
  abi: EXAGENT_STAKING_ABI,
1434
- functionName: "claimRewardsMulti",
1585
+ functionName: "unlock",
1435
1586
  args: [],
1436
1587
  account: this.account,
1437
1588
  chain: this.chain
@@ -1439,56 +1590,56 @@ var ExagentStaking = class {
1439
1590
  return hash;
1440
1591
  }
1441
1592
  /**
1442
- * Claim pending rewards for a specific token
1443
- * @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.
1444
1596
  * @returns Transaction hash
1445
1597
  */
1446
- async claimRewardsToken(token) {
1598
+ async emergencyWithdraw() {
1447
1599
  if (!this.walletClient || !this.account) {
1448
1600
  throw new Error("Wallet client required for write operations");
1449
1601
  }
1450
1602
  const hash = await this.walletClient.writeContract({
1451
1603
  address: this.address,
1452
1604
  abi: EXAGENT_STAKING_ABI,
1453
- functionName: "claimRewardsToken",
1454
- args: [token],
1605
+ functionName: "emergencyWithdraw",
1606
+ args: [],
1455
1607
  account: this.account,
1456
1608
  chain: this.chain
1457
1609
  });
1458
1610
  return hash;
1459
1611
  }
1460
- // ============ Delegation Write Functions ============
1612
+ // ============ Reward Functions ============
1461
1613
  /**
1462
- * Delegate vEXA voting power to an agent ("Agent Wars")
1463
- * @param agentId The agent ID to delegate to
1614
+ * Claim accumulated EXA rewards
1464
1615
  * @returns Transaction hash
1465
1616
  */
1466
- async delegate(agentId) {
1617
+ async claimRewards() {
1467
1618
  if (!this.walletClient || !this.account) {
1468
1619
  throw new Error("Wallet client required for write operations");
1469
1620
  }
1470
1621
  const hash = await this.walletClient.writeContract({
1471
1622
  address: this.address,
1472
1623
  abi: EXAGENT_STAKING_ABI,
1473
- functionName: "delegate",
1474
- args: [agentId],
1624
+ functionName: "claimRewards",
1625
+ args: [],
1475
1626
  account: this.account,
1476
1627
  chain: this.chain
1477
1628
  });
1478
1629
  return hash;
1479
1630
  }
1480
1631
  /**
1481
- * Remove delegation from current agent
1632
+ * Claim all pending multi-token rewards (ETH, USDC, etc.)
1482
1633
  * @returns Transaction hash
1483
1634
  */
1484
- async undelegate() {
1635
+ async claimRewardsMulti() {
1485
1636
  if (!this.walletClient || !this.account) {
1486
1637
  throw new Error("Wallet client required for write operations");
1487
1638
  }
1488
1639
  const hash = await this.walletClient.writeContract({
1489
1640
  address: this.address,
1490
1641
  abi: EXAGENT_STAKING_ABI,
1491
- functionName: "undelegate",
1642
+ functionName: "claimRewardsMulti",
1492
1643
  args: [],
1493
1644
  account: this.account,
1494
1645
  chain: this.chain
@@ -1496,19 +1647,19 @@ var ExagentStaking = class {
1496
1647
  return hash;
1497
1648
  }
1498
1649
  /**
1499
- * Re-delegate to a different agent (undelegate + delegate in one tx)
1500
- * @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
1501
1652
  * @returns Transaction hash
1502
1653
  */
1503
- async redelegate(newAgentId) {
1654
+ async claimRewardsToken(token) {
1504
1655
  if (!this.walletClient || !this.account) {
1505
1656
  throw new Error("Wallet client required for write operations");
1506
1657
  }
1507
1658
  const hash = await this.walletClient.writeContract({
1508
1659
  address: this.address,
1509
1660
  abi: EXAGENT_STAKING_ABI,
1510
- functionName: "redelegate",
1511
- args: [newAgentId],
1661
+ functionName: "claimRewardsToken",
1662
+ args: [token],
1512
1663
  account: this.account,
1513
1664
  chain: this.chain
1514
1665
  });
@@ -1516,20 +1667,26 @@ var ExagentStaking = class {
1516
1667
  }
1517
1668
  // ============ Read Functions ============
1518
1669
  /**
1519
- * Get comprehensive staking info for a user
1670
+ * Get comprehensive staking info for a user (deposit + lock)
1520
1671
  * @param userAddress Address to check (defaults to connected wallet)
1521
- * @returns Staking info with amount, unlock time, and vEXA balance
1672
+ * @returns Combined staking info
1522
1673
  */
1523
- async getStakeInfo(userAddress) {
1674
+ async getStakingInfo(userAddress) {
1524
1675
  const user = userAddress ?? this.account?.address;
1525
1676
  if (!user) {
1526
1677
  throw new Error("User address required");
1527
1678
  }
1528
- const [stakeResult, currentVeEXA] = await Promise.all([
1679
+ const [deposited, lockResult, currentVeEXA, vaultAccess, unlockedBalance] = await Promise.all([
1680
+ this.publicClient.readContract({
1681
+ address: this.address,
1682
+ abi: EXAGENT_STAKING_ABI,
1683
+ functionName: "depositedAmount",
1684
+ args: [user]
1685
+ }),
1529
1686
  this.publicClient.readContract({
1530
1687
  address: this.address,
1531
1688
  abi: EXAGENT_STAKING_ABI,
1532
- functionName: "stakes",
1689
+ functionName: "locks",
1533
1690
  args: [user]
1534
1691
  }),
1535
1692
  this.publicClient.readContract({
@@ -1537,20 +1694,88 @@ var ExagentStaking = class {
1537
1694
  abi: EXAGENT_STAKING_ABI,
1538
1695
  functionName: "getVeEXABalance",
1539
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]
1540
1709
  })
1541
1710
  ]);
1542
- const stake = stakeResult;
1711
+ const lockData = lockResult;
1712
+ const depositedBigint = deposited;
1713
+ const lockedAmount = lockData[0];
1543
1714
  const now = BigInt(Math.floor(Date.now() / 1e3));
1544
- const isUnlocked = stake[1] <= now;
1545
- 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;
1546
1774
  return {
1547
- amount: stake[0],
1548
- unlockTime: stake[1],
1549
- lockDuration: stake[2],
1550
- vEXABalance: stake[3],
1551
- currentVeEXA,
1552
- isUnlocked,
1553
- remainingLockTime
1775
+ deposited,
1776
+ locked: lockData[0],
1777
+ unlocked: unlockedBalance,
1778
+ hasVaultAccess: vaultAccess
1554
1779
  };
1555
1780
  }
1556
1781
  /**
@@ -1571,11 +1796,11 @@ var ExagentStaking = class {
1571
1796
  });
1572
1797
  }
1573
1798
  /**
1574
- * Get the agent ID a user is delegating to
1799
+ * Get effective vEXA (with tier multiplier applied)
1575
1800
  * @param userAddress Address to check (defaults to connected wallet)
1576
- * @returns Agent ID (0 if not delegating)
1801
+ * @returns Effective vEXA balance
1577
1802
  */
1578
- async getDelegatedAgent(userAddress) {
1803
+ async getEffectiveVeEXA(userAddress) {
1579
1804
  const user = userAddress ?? this.account?.address;
1580
1805
  if (!user) {
1581
1806
  throw new Error("User address required");
@@ -1583,52 +1808,64 @@ var ExagentStaking = class {
1583
1808
  return this.publicClient.readContract({
1584
1809
  address: this.address,
1585
1810
  abi: EXAGENT_STAKING_ABI,
1586
- functionName: "getDelegatedAgent",
1811
+ functionName: "getEffectiveVeEXA",
1587
1812
  args: [user]
1588
1813
  });
1589
1814
  }
1590
1815
  /**
1591
- * Get delegation stats for an agent
1592
- * @param agentId The agent ID to check
1593
- * @returns Delegation info with total vEXA and delegator count
1816
+ * Check if user has vault access (meets deposit threshold)
1817
+ * @param userAddress Address to check (defaults to connected wallet)
1818
+ * @returns True if user can access vaults
1594
1819
  */
1595
- async getAgentDelegation(agentId) {
1820
+ async hasVaultAccess(userAddress) {
1821
+ const user = userAddress ?? this.account?.address;
1822
+ if (!user) {
1823
+ throw new Error("User address required");
1824
+ }
1825
+ return this.publicClient.readContract({
1826
+ address: this.address,
1827
+ abi: EXAGENT_STAKING_ABI,
1828
+ functionName: "hasVaultAccess",
1829
+ args: [user]
1830
+ });
1831
+ }
1832
+ /**
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
1836
+ */
1837
+ async getEarningsTier(userAddress) {
1838
+ const user = userAddress ?? this.account?.address;
1839
+ if (!user) {
1840
+ throw new Error("User address required");
1841
+ }
1596
1842
  const result = await this.publicClient.readContract({
1597
1843
  address: this.address,
1598
1844
  abi: EXAGENT_STAKING_ABI,
1599
- functionName: "getAgentDelegation",
1600
- args: [agentId]
1845
+ functionName: "getEarningsTier",
1846
+ args: [user]
1601
1847
  });
1602
1848
  return {
1603
- totalVeEXA: result[0],
1604
- delegatorCount: result[1]
1849
+ multiplierBps: result[0],
1850
+ tierName: result[1]
1605
1851
  };
1606
1852
  }
1607
1853
  /**
1608
- * Get trading fee discount tier for a user
1854
+ * Get current emergency withdrawal penalty for a user
1609
1855
  * @param userAddress Address to check (defaults to connected wallet)
1610
- * @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)
1611
1857
  */
1612
- async getDiscountTier(userAddress) {
1858
+ async getEmergencyWithdrawPenalty(userAddress) {
1613
1859
  const user = userAddress ?? this.account?.address;
1614
1860
  if (!user) {
1615
1861
  throw new Error("User address required");
1616
1862
  }
1617
- const discountBps = await this.publicClient.readContract({
1863
+ return this.publicClient.readContract({
1618
1864
  address: this.address,
1619
1865
  abi: EXAGENT_STAKING_ABI,
1620
- functionName: "getDiscountTier",
1866
+ functionName: "getEmergencyWithdrawPenalty",
1621
1867
  args: [user]
1622
1868
  });
1623
- let tier = "none";
1624
- if (discountBps >= 5000n) {
1625
- tier = "gold";
1626
- } else if (discountBps >= 2500n) {
1627
- tier = "silver";
1628
- } else if (discountBps >= 1000n) {
1629
- tier = "bronze";
1630
- }
1631
- return { tier, discountBps };
1632
1869
  }
1633
1870
  /**
1634
1871
  * Get pending EXA rewards for a user
@@ -1690,14 +1927,25 @@ var ExagentStaking = class {
1690
1927
  });
1691
1928
  }
1692
1929
  /**
1693
- * Get total staked EXA across all users
1694
- * @returns Total staked amount in wei
1930
+ * Get total EXA deposited across all users
1931
+ * @returns Total deposited amount in wei
1695
1932
  */
1696
- async getTotalStaked() {
1933
+ async getTotalDeposited() {
1697
1934
  return this.publicClient.readContract({
1698
1935
  address: this.address,
1699
1936
  abi: EXAGENT_STAKING_ABI,
1700
- 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"
1701
1949
  });
1702
1950
  }
1703
1951
  /**
@@ -1712,8 +1960,8 @@ var ExagentStaking = class {
1712
1960
  });
1713
1961
  }
1714
1962
  /**
1715
- * Calculate vEXA balance for a given stake (preview)
1716
- * @param amount Amount of EXA to stake
1963
+ * Calculate vEXA balance for a given lock (preview)
1964
+ * @param amount Amount of EXA to lock
1717
1965
  * @param lockDuration Lock duration in seconds
1718
1966
  * @returns Expected vEXA balance
1719
1967
  */
@@ -1738,7 +1986,7 @@ var ExagentStaking = class {
1738
1986
  }
1739
1987
  // ============ Helper Functions ============
1740
1988
  /**
1741
- * Approve EXA token spending for staking
1989
+ * Approve EXA token spending for deposits
1742
1990
  * @param amount Amount to approve
1743
1991
  * @returns Transaction hash
1744
1992
  */
@@ -1776,25 +2024,28 @@ var ExagentStaking = class {
1776
2024
 
1777
2025
  // src/constants.ts
1778
2026
  import { base, baseSepolia } from "viem/chains";
2027
+ var SDK_VERSION = "0.1.4";
1779
2028
  var CHAIN_CONFIG = {
1780
2029
  mainnet: base,
1781
2030
  testnet: baseSepolia
1782
2031
  };
1783
2032
  var CONTRACT_ADDRESSES = {
1784
2033
  mainnet: {
1785
- agentRegistry: "0x0000000000000000000000000000000000000000",
1786
- // To be deployed
1787
- exaToken: "0x0000000000000000000000000000000000000000",
1788
- staking: "0x0000000000000000000000000000000000000000",
1789
- router: "0x0000000000000000000000000000000000000000",
2034
+ agentRegistry: "0x2261706C751F8ac5cdDb481B7b56EA2137d4A723",
2035
+ exaToken: "0x13403Fb738C97cF7564F279288468c140AaEd05c",
2036
+ staking: "0xAF1729D1519A72f7d9b87aa23a305b775e2849DA",
2037
+ router: "0x11daD5366D903a3eF5d8f07EFF87ce6b173859a9",
1790
2038
  vaultFactory: "0x0000000000000000000000000000000000000000",
1791
- feeCollector: "0x0000000000000000000000000000000000000000",
2039
+ // Phase 2 — pending deploy
2040
+ feeCollector: "0xe66328a964AF93bEF2eDB226D039C35aE6e66De1",
1792
2041
  buyback: "0x0000000000000000000000000000000000000000",
2042
+ // Phase 2 — pending deploy
1793
2043
  serviceEscrow: "0x0000000000000000000000000000000000000000"
2044
+ // Phase 2 — pending deploy
1794
2045
  },
1795
2046
  testnet: {
1796
2047
  agentRegistry: "0xCF48C341e3FebeCA5ECB7eb2535f61A2Ba855d9C",
1797
- // V4 UUPS proxy, one-agent-per-wallet
2048
+ // one-agent-per-wallet
1798
2049
  exaToken: "0x66c39b0ad96B3f5eE198Fef913c6636353a48A87",
1799
2050
  staking: "0x439441468e1b1b616E9D36b80969C241F261A011",
1800
2051
  // V2 with delegation
@@ -1824,21 +2075,47 @@ var ZERO_X_CONFIG = {
1824
2075
  // Base
1825
2076
  };
1826
2077
  var EXAGENT_API_CONFIG = {
1827
- mainnet: "https://api.exagent.io",
1828
- testnet: "https://api.testnet.exagent.io"
2078
+ mainnet: "https://exagent-api.onrender.com",
2079
+ testnet: "https://exagent-api.onrender.com"
1829
2080
  };
1830
2081
  var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
2082
+ var PHASE_1_CONTRACTS = /* @__PURE__ */ new Set([
2083
+ "agentRegistry",
2084
+ "exaToken",
2085
+ "staking",
2086
+ "router",
2087
+ "feeCollector"
2088
+ ]);
1831
2089
  function validateContractAddresses(network) {
1832
2090
  const addresses = CONTRACT_ADDRESSES[network];
1833
- const zeroEntries = Object.entries(addresses).filter(([, addr]) => addr === ZERO_ADDRESS);
1834
- if (network === "mainnet" && zeroEntries.length > 0) {
1835
- const missing = zeroEntries.map(([name]) => name).join(", ");
1836
- throw new Error(
1837
- `Mainnet contracts not yet deployed. Missing addresses: ${missing}. Deploy contracts before using the SDK on mainnet.`
1838
- );
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
+ }
1839
2098
  }
1840
2099
  }
1841
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
+
1842
2119
  // src/client.ts
1843
2120
  var ExagentClient = class {
1844
2121
  publicClient;
@@ -1889,6 +2166,14 @@ var ExagentClient = class {
1889
2166
  this.account
1890
2167
  );
1891
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
+ }
1892
2177
  // ============ Agent Registration ============
1893
2178
  /**
1894
2179
  * Register as a new agent on Exagent
@@ -1956,14 +2241,14 @@ var ExagentClient = class {
1956
2241
  /**
1957
2242
  * Link an additional wallet to this agent
1958
2243
  * @param wallet Wallet address to link
1959
- * @param signMessage Function to sign a message with the wallet
2244
+ * @param signMessage Function to sign the message hash with the wallet (use signMessage({ raw: hash }))
1960
2245
  */
1961
2246
  async linkWallet(wallet, signMessage) {
1962
2247
  const agentId = await this.getAgentId();
1963
2248
  if (!agentId) throw new Error("Agent not registered");
1964
2249
  const nonce = await this.registry.getNonce(wallet);
1965
- const message = ExagentRegistry.generateLinkMessage(wallet, agentId, nonce);
1966
- const signature = await signMessage(message);
2250
+ const messageHash = ExagentRegistry.generateLinkMessage(wallet, agentId, nonce);
2251
+ const signature = await signMessage({ raw: messageHash });
1967
2252
  return this.registry.linkWallet(agentId, wallet, signature);
1968
2253
  }
1969
2254
  /**
@@ -1976,127 +2261,15 @@ var ExagentClient = class {
1976
2261
  }
1977
2262
  // ============ Trading ============
1978
2263
  /**
1979
- * Get optimal DEX route for a trade
1980
- * Uses 0x API for aggregation across Aerodrome, Uniswap, etc.
1981
- */
1982
- async getRoute(intent) {
1983
- const apiUrl = EXAGENT_API_CONFIG[this.network];
1984
- const response = await fetch(`${apiUrl}/v1/routes/quote`, {
1985
- method: "POST",
1986
- headers: {
1987
- "Content-Type": "application/json",
1988
- ...this.apiKey && { "X-API-Key": this.apiKey }
1989
- },
1990
- body: JSON.stringify({
1991
- tokenIn: intent.tokenIn,
1992
- tokenOut: intent.tokenOut,
1993
- amountIn: intent.amountIn.toString(),
1994
- slippageBps: intent.maxSlippageBps ?? 50,
1995
- taker: this.account.address
1996
- })
1997
- });
1998
- if (!response.ok) {
1999
- const error = await response.json().catch(() => ({ error: response.statusText }));
2000
- throw new Error(`Failed to get route: ${error.error}`);
2001
- }
2002
- return response.json();
2003
- }
2004
- /**
2005
- * Get price quote without transaction data (faster)
2006
- */
2007
- async getPrice(tokenIn, tokenOut, amountIn) {
2008
- const apiUrl = EXAGENT_API_CONFIG[this.network];
2009
- const response = await fetch(`${apiUrl}/v1/routes/price`, {
2010
- method: "POST",
2011
- headers: {
2012
- "Content-Type": "application/json",
2013
- ...this.apiKey && { "X-API-Key": this.apiKey }
2014
- },
2015
- body: JSON.stringify({
2016
- tokenIn,
2017
- tokenOut,
2018
- amountIn: amountIn.toString()
2019
- })
2020
- });
2021
- if (!response.ok) {
2022
- const error = await response.json().catch(() => ({ error: response.statusText }));
2023
- throw new Error(`Failed to get price: ${error.error}`);
2024
- }
2025
- return response.json();
2026
- }
2027
- /**
2028
- * Execute a trade using a pre-fetched route
2029
- * @param route Route quote from getRoute()
2030
- * @param options Trade execution options
2031
- * @returns Transaction hash
2032
- */
2033
- async executeTrade(route, options) {
2034
- if (route.validUntil && Date.now() > route.validUntil) {
2035
- throw new Error("Quote expired, please fetch a new route");
2036
- }
2037
- if (route.issues?.allowance) {
2038
- throw new Error(
2039
- `Insufficient allowance for ${route.issues.allowance.spender}. Need ${route.issues.allowance.expected}, have ${route.issues.allowance.actual}`
2040
- );
2041
- }
2042
- if (options?.validateSlippage !== false) {
2043
- const freshPrice = await this.getPrice(
2044
- route.tokenIn,
2045
- route.tokenOut,
2046
- BigInt(route.amountIn)
2047
- );
2048
- const quotedOutput = BigInt(route.amountOut);
2049
- const freshOutput = BigInt(freshPrice.amountOut);
2050
- if (freshOutput < quotedOutput * 99n / 100n) {
2051
- console.warn("Price has moved significantly since quote was fetched");
2052
- }
2053
- }
2054
- const hash = await this.walletClient.sendTransaction({
2055
- account: this.account,
2056
- chain: CHAIN_CONFIG[this.network],
2057
- to: route.transaction.to,
2058
- data: route.transaction.data,
2059
- value: BigInt(route.transaction.value)
2060
- });
2061
- return hash;
2062
- }
2063
- /**
2064
- * Get and execute a trade in one call
2065
- * Convenience method that fetches route and executes
2066
- */
2067
- async swap(intent) {
2068
- const route = await this.getRoute(intent);
2069
- const hash = await this.executeTrade(route);
2070
- return { hash, route };
2071
- }
2072
- /**
2073
- * Broadcast a trade intent to the network
2074
- * Other agents can see this and potentially provide better execution
2075
- */
2076
- async broadcastIntent(intent) {
2077
- const agentId = await this.getAgentId();
2078
- if (!agentId) throw new Error("Agent not registered");
2079
- const apiUrl = EXAGENT_API_CONFIG[this.network];
2080
- await fetch(`${apiUrl}/v1/intents`, {
2081
- method: "POST",
2082
- headers: {
2083
- "Content-Type": "application/json",
2084
- ...this.apiKey && { "X-API-Key": this.apiKey }
2085
- },
2086
- body: JSON.stringify({
2087
- agentId: agentId.toString(),
2088
- intent,
2089
- signature: await this.signIntent(intent)
2090
- })
2091
- });
2092
- }
2093
- // ============ Router Trading (Attributed) ============
2094
- /**
2095
- * Execute a trade through ExagentRouter for full attribution
2264
+ * Execute a trade through ExagentRouter
2096
2265
  *
2097
- * This is the recommended way for agents to trade. All trades routed through
2098
- * the ExagentRouter emit TradeExecuted events that are captured by the indexer
2099
- * 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.
2100
2273
  *
2101
2274
  * @param intent Trade parameters
2102
2275
  * @returns Trade result with transaction hash
@@ -2149,10 +2322,7 @@ var ExagentClient = class {
2149
2322
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2150
2323
  const response = await fetch(`${apiUrl}/v1/router/trade`, {
2151
2324
  method: "POST",
2152
- headers: {
2153
- "Content-Type": "application/json",
2154
- ...this.apiKey && { "X-API-Key": this.apiKey }
2155
- },
2325
+ headers: this.apiHeaders("application/json"),
2156
2326
  body: JSON.stringify({
2157
2327
  agentId: id.toString(),
2158
2328
  tokenIn: intent.tokenIn,
@@ -2201,10 +2371,7 @@ var ExagentClient = class {
2201
2371
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2202
2372
  const response = await fetch(`${apiUrl}/v1/services/request`, {
2203
2373
  method: "POST",
2204
- headers: {
2205
- "Content-Type": "application/json",
2206
- ...this.apiKey && { "X-API-Key": this.apiKey }
2207
- },
2374
+ headers: this.apiHeaders("application/json"),
2208
2375
  body: JSON.stringify({
2209
2376
  requesterId: agentId.toString(),
2210
2377
  ...request
@@ -2222,7 +2389,9 @@ var ExagentClient = class {
2222
2389
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2223
2390
  const params = new URLSearchParams();
2224
2391
  if (serviceType) params.set("type", serviceType);
2225
- const response = await fetch(`${apiUrl}/v1/services?${params}`);
2392
+ const response = await fetch(`${apiUrl}/v1/services?${params}`, {
2393
+ headers: this.apiHeaders()
2394
+ });
2226
2395
  return response.json();
2227
2396
  }
2228
2397
  // ============ Leaderboards ============
@@ -2235,7 +2404,9 @@ var ExagentClient = class {
2235
2404
  if (options?.category) params.set("category", options.category);
2236
2405
  if (options?.limit) params.set("limit", options.limit.toString());
2237
2406
  if (options?.offset) params.set("offset", options.offset.toString());
2238
- const response = await fetch(`${apiUrl}/v1/rankings/leaderboard?${params}`);
2407
+ const response = await fetch(`${apiUrl}/v1/rankings/leaderboard?${params}`, {
2408
+ headers: this.apiHeaders()
2409
+ });
2239
2410
  return response.json();
2240
2411
  }
2241
2412
  // ============ Vault Functions (Phase 4: Copy Trading) ============
@@ -2263,9 +2434,7 @@ var ExagentClient = class {
2263
2434
  if (!id) throw new Error("Agent not registered");
2264
2435
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2265
2436
  const response = await fetch(`${apiUrl}/v1/vaults?agentId=${id}`, {
2266
- headers: {
2267
- ...this.apiKey && { "X-API-Key": this.apiKey }
2268
- }
2437
+ headers: this.apiHeaders()
2269
2438
  });
2270
2439
  if (!response.ok) {
2271
2440
  throw new Error(`Failed to get vaults: ${response.statusText}`);
@@ -2281,9 +2450,7 @@ var ExagentClient = class {
2281
2450
  const user = userAddress ?? this.account.address;
2282
2451
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2283
2452
  const response = await fetch(`${apiUrl}/v1/vaults?depositor=${user}`, {
2284
- headers: {
2285
- ...this.apiKey && { "X-API-Key": this.apiKey }
2286
- }
2453
+ headers: this.apiHeaders()
2287
2454
  });
2288
2455
  if (!response.ok) {
2289
2456
  throw new Error(`Failed to get user vaults: ${response.statusText}`);
@@ -2303,9 +2470,7 @@ var ExagentClient = class {
2303
2470
  if (options?.period) params.set("period", options.period);
2304
2471
  if (options?.limit) params.set("limit", options.limit.toString());
2305
2472
  const response = await fetch(`${apiUrl}/v1/vaults/top?${params}`, {
2306
- headers: {
2307
- ...this.apiKey && { "X-API-Key": this.apiKey }
2308
- }
2473
+ headers: this.apiHeaders()
2309
2474
  });
2310
2475
  if (!response.ok) {
2311
2476
  throw new Error(`Failed to get top vaults: ${response.statusText}`);
@@ -2346,37 +2511,73 @@ var ExagentClient = class {
2346
2511
  }
2347
2512
  // ============ Staking Functions ============
2348
2513
  /**
2349
- * Stake EXA tokens to receive vEXA voting power
2350
- * @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)
2351
2539
  * @param lockDuration Lock duration in seconds (30 days to 2 years)
2352
2540
  * @returns Transaction hash
2353
2541
  *
2354
2542
  * @example
2355
2543
  * ```typescript
2356
- * // Stake 1000 EXA for 6 months
2357
- * const tx = await exagent.stakeExa(
2544
+ * // Lock 1000 EXA for 6 months
2545
+ * const tx = await exagent.lockExa(
2358
2546
  * parseEther('1000'),
2359
2547
  * ExagentStaking.LOCK_6_MONTHS
2360
2548
  * );
2361
2549
  * ```
2362
2550
  */
2363
- async stakeExa(amount, lockDuration) {
2364
- await this.staking.approveExa(amount);
2365
- 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();
2366
2560
  }
2367
2561
  /**
2368
- * Unstake EXA tokens after lock expires
2562
+ * Emergency withdrawal from active lock (graduated 50%→20% penalty)
2369
2563
  * @returns Transaction hash
2370
2564
  */
2371
- async unstakeExa() {
2372
- return this.staking.unstake();
2565
+ async emergencyWithdrawExa() {
2566
+ return this.staking.emergencyWithdraw();
2373
2567
  }
2374
2568
  /**
2375
- * Get staking info for the connected wallet
2376
- * @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
2377
2571
  */
2378
2572
  async getStakingInfo() {
2379
- 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();
2380
2581
  }
2381
2582
  /**
2382
2583
  * Get current vEXA balance for the connected wallet
@@ -2386,20 +2587,25 @@ var ExagentClient = class {
2386
2587
  return this.staking.getVeEXABalance();
2387
2588
  }
2388
2589
  /**
2389
- * Delegate vEXA voting power to an agent
2390
- * @param agentId The agent ID to delegate to
2391
- * @returns Transaction hash
2590
+ * Check if connected wallet has vault access (meets deposit threshold)
2591
+ * @returns True if user can access vaults
2392
2592
  */
2393
- async delegateToAgent(agentId) {
2394
- return this.staking.delegate(agentId);
2593
+ async hasVaultAccess() {
2594
+ return this.staking.hasVaultAccess();
2395
2595
  }
2396
2596
  /**
2397
- * Get delegation stats for an agent
2398
- * @param agentId The agent ID to check
2399
- * @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
2400
2599
  */
2401
- async getAgentDelegation(agentId) {
2402
- 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();
2403
2609
  }
2404
2610
  /**
2405
2611
  * Claim all pending staking rewards (EXA + multi-token)
@@ -2410,6 +2616,46 @@ var ExagentClient = class {
2410
2616
  const multiTokenRewards = await this.staking.claimRewardsMulti();
2411
2617
  return { exaRewards, multiTokenRewards };
2412
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
+ }
2413
2659
  // ============ Helpers ============
2414
2660
  /**
2415
2661
  * Get the agent's wallet address
@@ -2429,10 +2675,7 @@ var ExagentClient = class {
2429
2675
  const apiUrl = EXAGENT_API_CONFIG[this.network];
2430
2676
  const response = await fetch(`${apiUrl}/v1/metadata/upload`, {
2431
2677
  method: "POST",
2432
- headers: {
2433
- "Content-Type": "application/json",
2434
- ...this.apiKey && { "X-API-Key": this.apiKey }
2435
- },
2678
+ headers: this.apiHeaders("application/json"),
2436
2679
  body: JSON.stringify(metadata)
2437
2680
  });
2438
2681
  if (!response.ok) {
@@ -2441,12 +2684,16 @@ var ExagentClient = class {
2441
2684
  const result = await response.json();
2442
2685
  return result.uri;
2443
2686
  }
2444
- async signIntent(intent) {
2445
- const message = JSON.stringify(intent);
2446
- return this.walletClient.signMessage({ account: this.account, message });
2447
- }
2448
2687
  parseAgentIdFromReceipt(receipt) {
2449
- 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");
2450
2697
  }
2451
2698
  };
2452
2699
 
@@ -2456,8 +2703,12 @@ var EXAGENT_VAULT_FACTORY_ABI = [
2456
2703
  { type: "function", name: "owner", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
2457
2704
  { type: "function", name: "registry", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
2458
2705
  { type: "function", name: "router", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
2459
- { type: "function", name: "minimumVeEXARequired", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
2460
- { 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" },
2461
2712
  { type: "function", name: "allowedAssets", inputs: [{ name: "asset", type: "address" }], outputs: [{ type: "bool" }], stateMutability: "view" },
2462
2713
  { type: "function", name: "vaults", inputs: [{ name: "agentId", type: "uint256" }, { name: "asset", type: "address" }], outputs: [{ type: "address" }], stateMutability: "view" },
2463
2714
  { type: "function", name: "agentVaultCount", inputs: [{ name: "agentId", type: "uint256" }], outputs: [{ type: "uint256" }], stateMutability: "view" },
@@ -2470,14 +2721,9 @@ var EXAGENT_VAULT_FACTORY_ABI = [
2470
2721
  },
2471
2722
  {
2472
2723
  type: "function",
2473
- name: "getVaultCreationRequirements",
2474
- inputs: [],
2475
- outputs: [
2476
- { name: "veXARequired", type: "uint256" },
2477
- { name: "burnFee", type: "uint256" },
2478
- { name: "stakingContract", type: "address" },
2479
- { name: "exaToken", type: "address" }
2480
- ],
2724
+ name: "canCreateVerifiedVault",
2725
+ inputs: [{ name: "agentId", type: "uint256" }],
2726
+ outputs: [{ name: "isVerified", type: "bool" }, { name: "reason", type: "string" }],
2481
2727
  stateMutability: "view"
2482
2728
  },
2483
2729
  // Write functions
@@ -2487,6 +2733,7 @@ var EXAGENT_VAULT_FACTORY_ABI = [
2487
2733
  inputs: [
2488
2734
  { name: "agentId", type: "uint256" },
2489
2735
  { name: "asset", type: "address" },
2736
+ { name: "seedAmount", type: "uint256" },
2490
2737
  { name: "name", type: "string" },
2491
2738
  { name: "symbol", type: "string" },
2492
2739
  { name: "feeRecipient", type: "address" }
@@ -2528,50 +2775,51 @@ var ExagentVaultFactory = class {
2528
2775
  this.address = factoryAddress;
2529
2776
  this.publicClient = publicClient;
2530
2777
  this.walletClient = walletClient;
2778
+ if (!chain) {
2779
+ throw new Error("Chain parameter is required");
2780
+ }
2531
2781
  this.chain = chain;
2532
2782
  this.account = account;
2533
2783
  }
2534
2784
  // ============ Read Functions ============
2535
2785
  /**
2536
- * Get vault creation requirements
2786
+ * Get vault creation requirements (mainnet: seed-based, no burn fee)
2537
2787
  */
2538
2788
  async getRequirements() {
2539
- try {
2540
- const result = await this.publicClient.readContract({
2789
+ const [veXARequired, minSeedAmount, unverifiedCapMultiplier, verifiedCapMultiplier, stakingContract] = await Promise.all([
2790
+ this.publicClient.readContract({
2541
2791
  address: this.address,
2542
2792
  abi: EXAGENT_VAULT_FACTORY_ABI,
2543
- functionName: "getVaultCreationRequirements"
2544
- });
2545
- const isBypassed = result[0] === BigInt(0) && result[1] === BigInt(0) && (result[2] === "0x0000000000000000000000000000000000000000" || result[3] === "0x0000000000000000000000000000000000000000");
2546
- return {
2547
- veXARequired: result[0],
2548
- burnFee: result[1],
2549
- stakingContract: result[2],
2550
- exaToken: result[3],
2551
- isBypassed
2552
- };
2553
- } catch {
2554
- const [veXARequired, burnFee] = await Promise.all([
2555
- this.publicClient.readContract({
2556
- address: this.address,
2557
- abi: EXAGENT_VAULT_FACTORY_ABI,
2558
- functionName: "minimumVeEXARequired"
2559
- }),
2560
- this.publicClient.readContract({
2561
- address: this.address,
2562
- abi: EXAGENT_VAULT_FACTORY_ABI,
2563
- functionName: "eXABurnFee"
2564
- })
2565
- ]);
2566
- const isBypassed = veXARequired === BigInt(0) && burnFee === BigInt(0);
2567
- return {
2568
- veXARequired,
2569
- burnFee,
2570
- stakingContract: "0x0000000000000000000000000000000000000000",
2571
- exaToken: "0x0000000000000000000000000000000000000000",
2572
- isBypassed
2573
- };
2574
- }
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
+ };
2575
2823
  }
2576
2824
  /**
2577
2825
  * Check if an address can create a vault
@@ -2589,6 +2837,22 @@ var ExagentVaultFactory = class {
2589
2837
  reason: result[1]
2590
2838
  };
2591
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
+ }
2592
2856
  /**
2593
2857
  * Check if an asset is whitelisted for vault creation
2594
2858
  * @param asset Asset address to check
@@ -2638,8 +2902,8 @@ var ExagentVaultFactory = class {
2638
2902
  }
2639
2903
  // ============ Write Functions ============
2640
2904
  /**
2641
- * Create a new vault for an agent
2642
- * @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
2643
2907
  * @returns Transaction hash
2644
2908
  */
2645
2909
  async createVault(options) {
@@ -2651,7 +2915,7 @@ var ExagentVaultFactory = class {
2651
2915
  address: this.address,
2652
2916
  abi: EXAGENT_VAULT_FACTORY_ABI,
2653
2917
  functionName: "createVault",
2654
- args: [options.agentId, options.asset, options.name, options.symbol, feeRecipient],
2918
+ args: [options.agentId, options.asset, options.seedAmount, options.name, options.symbol, feeRecipient],
2655
2919
  account: this.account,
2656
2920
  chain: this.chain
2657
2921
  });
@@ -2662,7 +2926,7 @@ var ExagentVaultFactory = class {
2662
2926
  * Check all requirements and create a vault if possible
2663
2927
  * Returns detailed status about each requirement
2664
2928
  */
2665
- async checkAndCreateVault(agentId, asset, name, symbol, feeRecipient) {
2929
+ async checkAndCreateVault(agentId, asset, seedAmount, name, symbol, feeRecipient) {
2666
2930
  const [canCreateResult, assetAllowed, hasExisting] = await Promise.all([
2667
2931
  this.canCreateVault(this.account?.address ?? "0x0000000000000000000000000000000000000000"),
2668
2932
  this.isAssetAllowed(asset),
@@ -2701,6 +2965,7 @@ var ExagentVaultFactory = class {
2701
2965
  const txHash = await this.createVault({
2702
2966
  agentId,
2703
2967
  asset,
2968
+ seedAmount,
2704
2969
  name,
2705
2970
  symbol,
2706
2971
  feeRecipient
@@ -2734,7 +2999,6 @@ var ExagentVaultFactory = class {
2734
2999
  // src/index.ts
2735
3000
  var TESTNET_ADDRESSES = {
2736
3001
  registry: "0xCF48C341e3FebeCA5ECB7eb2535f61A2Ba855d9C",
2737
- // V4 UUPS proxy
2738
3002
  token: "0x66c39b0ad96B3f5eE198Fef913c6636353a48A87",
2739
3003
  staking: "0x439441468e1b1b616E9D36b80969C241F261A011",
2740
3004
  router: "0xc0c27eEE047E414CD716D06C2444CF2073113d5C",
@@ -2750,7 +3014,6 @@ export {
2750
3014
  CHAIN_CONFIG,
2751
3015
  CONTRACT_ADDRESSES,
2752
3016
  DEX_ADDRESSES,
2753
- DISCOUNT_TIERS,
2754
3017
  EXAGENT_API_CONFIG,
2755
3018
  EXAGENT_STAKING_ABI,
2756
3019
  EXAGENT_VAULT_FACTORY_ABI,
@@ -2759,6 +3022,9 @@ export {
2759
3022
  ExagentStaking,
2760
3023
  ExagentVault,
2761
3024
  ExagentVaultFactory,
3025
+ SDK_VERSION,
2762
3026
  TESTNET_ADDRESSES,
2763
- ZERO_X_CONFIG
3027
+ ZERO_X_CONFIG,
3028
+ buildGlobalAgentId,
3029
+ parseGlobalAgentId
2764
3030
  };