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