@exagent/sdk 0.1.15 → 0.1.17

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
@@ -3,7 +3,8 @@ import {
3
3
  createPublicClient,
4
4
  createWalletClient,
5
5
  http,
6
- decodeErrorResult
6
+ decodeErrorResult,
7
+ maxUint256
7
8
  } from "viem";
8
9
  import { privateKeyToAccount } from "viem/accounts";
9
10
 
@@ -1163,821 +1164,6 @@ var ExagentVault = class {
1163
1164
  }
1164
1165
  };
1165
1166
 
1166
- // src/contracts/staking.ts
1167
- var EXAGENT_STAKING_ABI = [
1168
- // ============ State Variables ============
1169
- { type: "function", name: "exaToken", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
1170
- { type: "function", name: "totalDeposited", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1171
- { type: "function", name: "totalLocked", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1172
- { type: "function", name: "totalVeEXA", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1173
- { type: "function", name: "totalEffectiveVeEXA", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1174
- // ============ Constants ============
1175
- { type: "function", name: "MIN_LOCK_DURATION", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1176
- { type: "function", name: "MAX_LOCK_DURATION", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1177
- { type: "function", name: "VAULT_ACCESS_THRESHOLD", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1178
- { type: "function", name: "PRECISION", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
1179
- // ============ Phase 1: Deposit / Withdraw ============
1180
- {
1181
- type: "function",
1182
- name: "deposit",
1183
- inputs: [{ name: "amount", type: "uint256" }],
1184
- outputs: [],
1185
- stateMutability: "nonpayable"
1186
- },
1187
- {
1188
- type: "function",
1189
- name: "withdraw",
1190
- inputs: [{ name: "amount", type: "uint256" }],
1191
- outputs: [],
1192
- stateMutability: "nonpayable"
1193
- },
1194
- // ============ Phase 2: Lock / Unlock ============
1195
- {
1196
- type: "function",
1197
- name: "lock",
1198
- inputs: [
1199
- { name: "amount", type: "uint256" },
1200
- { name: "lockDuration", type: "uint256" }
1201
- ],
1202
- outputs: [],
1203
- stateMutability: "nonpayable"
1204
- },
1205
- {
1206
- type: "function",
1207
- name: "extendLock",
1208
- inputs: [{ name: "newLockDuration", type: "uint256" }],
1209
- outputs: [],
1210
- stateMutability: "nonpayable"
1211
- },
1212
- { type: "function", name: "unlock", inputs: [], outputs: [], stateMutability: "nonpayable" },
1213
- { type: "function", name: "emergencyWithdraw", inputs: [], outputs: [], stateMutability: "nonpayable" },
1214
- // ============ Reward Functions ============
1215
- { type: "function", name: "claimRewards", inputs: [], outputs: [], stateMutability: "nonpayable" },
1216
- { type: "function", name: "claimRewardsMulti", inputs: [], outputs: [], stateMutability: "nonpayable" },
1217
- {
1218
- type: "function",
1219
- name: "claimRewardsToken",
1220
- inputs: [{ name: "token", type: "address" }],
1221
- outputs: [],
1222
- stateMutability: "nonpayable"
1223
- },
1224
- // ============ View Functions ============
1225
- {
1226
- type: "function",
1227
- name: "depositedAmount",
1228
- inputs: [{ name: "user", type: "address" }],
1229
- outputs: [{ type: "uint256" }],
1230
- stateMutability: "view"
1231
- },
1232
- {
1233
- type: "function",
1234
- name: "locks",
1235
- inputs: [{ name: "user", type: "address" }],
1236
- outputs: [
1237
- { name: "amount", type: "uint256" },
1238
- { name: "unlockTime", type: "uint256" },
1239
- { name: "lockDuration", type: "uint256" },
1240
- { name: "vEXABalance", type: "uint256" }
1241
- ],
1242
- stateMutability: "view"
1243
- },
1244
- {
1245
- type: "function",
1246
- name: "getVeEXABalance",
1247
- inputs: [{ name: "user", type: "address" }],
1248
- outputs: [{ type: "uint256" }],
1249
- stateMutability: "view"
1250
- },
1251
- {
1252
- type: "function",
1253
- name: "getEffectiveVeEXA",
1254
- inputs: [{ name: "user", type: "address" }],
1255
- outputs: [{ type: "uint256" }],
1256
- stateMutability: "view"
1257
- },
1258
- {
1259
- type: "function",
1260
- name: "calculateVeEXA",
1261
- inputs: [
1262
- { name: "amount", type: "uint256" },
1263
- { name: "lockDuration", type: "uint256" }
1264
- ],
1265
- outputs: [{ type: "uint256" }],
1266
- stateMutability: "pure"
1267
- },
1268
- {
1269
- type: "function",
1270
- name: "pendingRewards",
1271
- inputs: [{ name: "user", type: "address" }],
1272
- outputs: [{ type: "uint256" }],
1273
- stateMutability: "view"
1274
- },
1275
- {
1276
- type: "function",
1277
- name: "pendingRewardsForToken",
1278
- inputs: [
1279
- { name: "user", type: "address" },
1280
- { name: "token", type: "address" }
1281
- ],
1282
- outputs: [{ type: "uint256" }],
1283
- stateMutability: "view"
1284
- },
1285
- {
1286
- type: "function",
1287
- name: "getEarningsTier",
1288
- inputs: [{ name: "user", type: "address" }],
1289
- outputs: [
1290
- { name: "multiplierBps", type: "uint256" },
1291
- { name: "tierName", type: "string" }
1292
- ],
1293
- stateMutability: "view"
1294
- },
1295
- {
1296
- type: "function",
1297
- name: "getEmergencyWithdrawPenalty",
1298
- inputs: [{ name: "user", type: "address" }],
1299
- outputs: [{ name: "penaltyBps", type: "uint256" }],
1300
- stateMutability: "view"
1301
- },
1302
- {
1303
- type: "function",
1304
- name: "hasVaultAccess",
1305
- inputs: [{ name: "user", type: "address" }],
1306
- outputs: [{ type: "bool" }],
1307
- stateMutability: "view"
1308
- },
1309
- {
1310
- type: "function",
1311
- name: "getUnlockedBalance",
1312
- inputs: [{ name: "user", type: "address" }],
1313
- outputs: [{ type: "uint256" }],
1314
- stateMutability: "view"
1315
- },
1316
- {
1317
- type: "function",
1318
- name: "getRewardTokens",
1319
- inputs: [],
1320
- outputs: [{ type: "address[]" }],
1321
- stateMutability: "view"
1322
- },
1323
- {
1324
- type: "function",
1325
- name: "isRewardToken",
1326
- inputs: [{ name: "token", type: "address" }],
1327
- outputs: [{ type: "bool" }],
1328
- stateMutability: "view"
1329
- },
1330
- // ============ Events ============
1331
- {
1332
- type: "event",
1333
- name: "Deposited",
1334
- inputs: [
1335
- { name: "user", type: "address", indexed: true },
1336
- { name: "amount", type: "uint256", indexed: false },
1337
- { name: "totalDeposited", type: "uint256", indexed: false }
1338
- ]
1339
- },
1340
- {
1341
- type: "event",
1342
- name: "Withdrawn",
1343
- inputs: [
1344
- { name: "user", type: "address", indexed: true },
1345
- { name: "amount", type: "uint256", indexed: false },
1346
- { name: "totalDeposited", type: "uint256", indexed: false }
1347
- ]
1348
- },
1349
- {
1350
- type: "event",
1351
- name: "Locked",
1352
- inputs: [
1353
- { name: "user", type: "address", indexed: true },
1354
- { name: "amount", type: "uint256", indexed: false },
1355
- { name: "lockDuration", type: "uint256", indexed: false },
1356
- { name: "unlockTime", type: "uint256", indexed: false },
1357
- { name: "vEXABalance", type: "uint256", indexed: false }
1358
- ]
1359
- },
1360
- {
1361
- type: "event",
1362
- name: "Unlocked",
1363
- inputs: [
1364
- { name: "user", type: "address", indexed: true },
1365
- { name: "amount", type: "uint256", indexed: false }
1366
- ]
1367
- },
1368
- {
1369
- type: "event",
1370
- name: "EmergencyWithdrawal",
1371
- inputs: [
1372
- { name: "user", type: "address", indexed: true },
1373
- { name: "returned", type: "uint256", indexed: false },
1374
- { name: "penalty", type: "uint256", indexed: false },
1375
- { name: "penaltyBps", type: "uint256", indexed: false }
1376
- ]
1377
- },
1378
- {
1379
- type: "event",
1380
- name: "LockExtended",
1381
- inputs: [
1382
- { name: "user", type: "address", indexed: true },
1383
- { name: "newUnlockTime", type: "uint256", indexed: false },
1384
- { name: "newVeEXABalance", type: "uint256", indexed: false }
1385
- ]
1386
- },
1387
- {
1388
- type: "event",
1389
- name: "RewardsClaimed",
1390
- inputs: [
1391
- { name: "user", type: "address", indexed: true },
1392
- { name: "amount", type: "uint256", indexed: false }
1393
- ]
1394
- },
1395
- {
1396
- type: "event",
1397
- name: "MultiTokenRewardsClaimed",
1398
- inputs: [
1399
- { name: "user", type: "address", indexed: true },
1400
- { name: "token", type: "address", indexed: true },
1401
- { name: "amount", type: "uint256", indexed: false }
1402
- ]
1403
- }
1404
- ];
1405
- var ERC20_APPROVE_ABI2 = [
1406
- {
1407
- type: "function",
1408
- name: "approve",
1409
- inputs: [
1410
- { name: "spender", type: "address" },
1411
- { name: "amount", type: "uint256" }
1412
- ],
1413
- outputs: [{ type: "bool" }],
1414
- stateMutability: "nonpayable"
1415
- }
1416
- ];
1417
- var ExagentStaking = class {
1418
- address;
1419
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1420
- publicClient;
1421
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1422
- walletClient;
1423
- chain;
1424
- account;
1425
- constructor(stakingAddress, publicClient, walletClient, chain, account) {
1426
- this.address = stakingAddress;
1427
- this.publicClient = publicClient;
1428
- this.walletClient = walletClient;
1429
- if (!chain) {
1430
- throw new Error("Chain parameter is required");
1431
- }
1432
- this.chain = chain;
1433
- this.account = account;
1434
- }
1435
- // ============ Phase 1: Deposit / Withdraw ============
1436
- /**
1437
- * Deposit EXA tokens for vault access (no lock required)
1438
- * @param amount Amount of EXA to deposit (in wei)
1439
- * @returns Transaction hash
1440
- *
1441
- * @example
1442
- * ```typescript
1443
- * // Deposit 1000 EXA to unlock vault access
1444
- * const tx = await staking.deposit(parseEther('1000'));
1445
- * ```
1446
- */
1447
- async deposit(amount) {
1448
- if (!this.walletClient || !this.account) {
1449
- throw new Error("Wallet client required for write operations");
1450
- }
1451
- const hash = await this.walletClient.writeContract({
1452
- address: this.address,
1453
- abi: EXAGENT_STAKING_ABI,
1454
- functionName: "deposit",
1455
- args: [amount],
1456
- account: this.account,
1457
- chain: this.chain
1458
- });
1459
- return hash;
1460
- }
1461
- /**
1462
- * Withdraw unlocked EXA tokens (instant, no penalty)
1463
- * @param amount Amount of EXA to withdraw (in wei)
1464
- * @returns Transaction hash
1465
- */
1466
- async withdraw(amount) {
1467
- if (!this.walletClient || !this.account) {
1468
- throw new Error("Wallet client required for write operations");
1469
- }
1470
- const hash = await this.walletClient.writeContract({
1471
- address: this.address,
1472
- abi: EXAGENT_STAKING_ABI,
1473
- functionName: "withdraw",
1474
- args: [amount],
1475
- account: this.account,
1476
- chain: this.chain
1477
- });
1478
- return hash;
1479
- }
1480
- // ============ Phase 2: Lock / Unlock ============
1481
- /**
1482
- * Lock deposited EXA to receive vEXA voting power and earn rewards
1483
- * @param amount Amount of deposited EXA to lock (in wei)
1484
- * @param lockDuration Lock duration in seconds (30 days to 2 years)
1485
- * @returns Transaction hash
1486
- *
1487
- * @example
1488
- * ```typescript
1489
- * // Lock 1000 EXA for 6 months
1490
- * const tx = await staking.lock(
1491
- * parseEther('1000'),
1492
- * ExagentStaking.LOCK_6_MONTHS
1493
- * );
1494
- * ```
1495
- */
1496
- async lock(amount, lockDuration) {
1497
- if (!this.walletClient || !this.account) {
1498
- throw new Error("Wallet client required for write operations");
1499
- }
1500
- const hash = await this.walletClient.writeContract({
1501
- address: this.address,
1502
- abi: EXAGENT_STAKING_ABI,
1503
- functionName: "lock",
1504
- args: [amount, lockDuration],
1505
- account: this.account,
1506
- chain: this.chain
1507
- });
1508
- return hash;
1509
- }
1510
- /**
1511
- * Extend lock duration for additional voting power
1512
- * @param newLockDuration New lock duration in seconds (must be longer than remaining)
1513
- * @returns Transaction hash
1514
- */
1515
- async extendLock(newLockDuration) {
1516
- if (!this.walletClient || !this.account) {
1517
- throw new Error("Wallet client required for write operations");
1518
- }
1519
- const hash = await this.walletClient.writeContract({
1520
- address: this.address,
1521
- abi: EXAGENT_STAKING_ABI,
1522
- functionName: "extendLock",
1523
- args: [newLockDuration],
1524
- account: this.account,
1525
- chain: this.chain
1526
- });
1527
- return hash;
1528
- }
1529
- /**
1530
- * Unlock EXA after lock expires (normal path — no penalty)
1531
- * Returns locked amount to unlocked deposited balance.
1532
- * @returns Transaction hash
1533
- */
1534
- async unlock() {
1535
- if (!this.walletClient || !this.account) {
1536
- throw new Error("Wallet client required for write operations");
1537
- }
1538
- const hash = await this.walletClient.writeContract({
1539
- address: this.address,
1540
- abi: EXAGENT_STAKING_ABI,
1541
- functionName: "unlock",
1542
- args: [],
1543
- account: this.account,
1544
- chain: this.chain
1545
- });
1546
- return hash;
1547
- }
1548
- /**
1549
- * Emergency withdrawal — instant exit from lock with graduated penalty
1550
- * Two-phase penalty: 50%→20% over the first quarter of the lock, then flat 20% until expiry.
1551
- * Penalty goes to treasury. Remaining returns to unlocked deposit balance.
1552
- * @returns Transaction hash
1553
- */
1554
- async emergencyWithdraw() {
1555
- if (!this.walletClient || !this.account) {
1556
- throw new Error("Wallet client required for write operations");
1557
- }
1558
- const hash = await this.walletClient.writeContract({
1559
- address: this.address,
1560
- abi: EXAGENT_STAKING_ABI,
1561
- functionName: "emergencyWithdraw",
1562
- args: [],
1563
- account: this.account,
1564
- chain: this.chain
1565
- });
1566
- return hash;
1567
- }
1568
- // ============ Reward Functions ============
1569
- /**
1570
- * Claim accumulated EXA rewards
1571
- * @returns Transaction hash
1572
- */
1573
- async claimRewards() {
1574
- if (!this.walletClient || !this.account) {
1575
- throw new Error("Wallet client required for write operations");
1576
- }
1577
- const hash = await this.walletClient.writeContract({
1578
- address: this.address,
1579
- abi: EXAGENT_STAKING_ABI,
1580
- functionName: "claimRewards",
1581
- args: [],
1582
- account: this.account,
1583
- chain: this.chain
1584
- });
1585
- return hash;
1586
- }
1587
- /**
1588
- * Claim all pending multi-token rewards (ETH, USDC, etc.)
1589
- * @returns Transaction hash
1590
- */
1591
- async claimRewardsMulti() {
1592
- if (!this.walletClient || !this.account) {
1593
- throw new Error("Wallet client required for write operations");
1594
- }
1595
- const hash = await this.walletClient.writeContract({
1596
- address: this.address,
1597
- abi: EXAGENT_STAKING_ABI,
1598
- functionName: "claimRewardsMulti",
1599
- args: [],
1600
- account: this.account,
1601
- chain: this.chain
1602
- });
1603
- return hash;
1604
- }
1605
- /**
1606
- * Claim pending rewards for a specific token
1607
- * @param token The reward token address to claim
1608
- * @returns Transaction hash
1609
- */
1610
- async claimRewardsToken(token) {
1611
- if (!this.walletClient || !this.account) {
1612
- throw new Error("Wallet client required for write operations");
1613
- }
1614
- const hash = await this.walletClient.writeContract({
1615
- address: this.address,
1616
- abi: EXAGENT_STAKING_ABI,
1617
- functionName: "claimRewardsToken",
1618
- args: [token],
1619
- account: this.account,
1620
- chain: this.chain
1621
- });
1622
- return hash;
1623
- }
1624
- // ============ Read Functions ============
1625
- /**
1626
- * Get comprehensive staking info for a user (deposit + lock)
1627
- * @param userAddress Address to check (defaults to connected wallet)
1628
- * @returns Combined staking info
1629
- */
1630
- async getStakingInfo(userAddress) {
1631
- const user = userAddress ?? this.account?.address;
1632
- if (!user) {
1633
- throw new Error("User address required");
1634
- }
1635
- const [deposited, lockResult, currentVeEXA, vaultAccess, unlockedBalance] = await Promise.all([
1636
- this.publicClient.readContract({
1637
- address: this.address,
1638
- abi: EXAGENT_STAKING_ABI,
1639
- functionName: "depositedAmount",
1640
- args: [user]
1641
- }),
1642
- this.publicClient.readContract({
1643
- address: this.address,
1644
- abi: EXAGENT_STAKING_ABI,
1645
- functionName: "locks",
1646
- args: [user]
1647
- }),
1648
- this.publicClient.readContract({
1649
- address: this.address,
1650
- abi: EXAGENT_STAKING_ABI,
1651
- functionName: "getVeEXABalance",
1652
- args: [user]
1653
- }),
1654
- this.publicClient.readContract({
1655
- address: this.address,
1656
- abi: EXAGENT_STAKING_ABI,
1657
- functionName: "hasVaultAccess",
1658
- args: [user]
1659
- }),
1660
- this.publicClient.readContract({
1661
- address: this.address,
1662
- abi: EXAGENT_STAKING_ABI,
1663
- functionName: "getUnlockedBalance",
1664
- args: [user]
1665
- })
1666
- ]);
1667
- const lockData = lockResult;
1668
- const depositedBigint = deposited;
1669
- const lockedAmount = lockData[0];
1670
- const now = BigInt(Math.floor(Date.now() / 1e3));
1671
- const depositInfo = {
1672
- deposited: depositedBigint,
1673
- locked: lockedAmount,
1674
- unlocked: unlockedBalance,
1675
- hasVaultAccess: vaultAccess
1676
- };
1677
- let lockInfo = null;
1678
- if (lockedAmount > 0n) {
1679
- const isUnlocked = lockData[1] <= now;
1680
- const remainingLockTime = isUnlocked ? 0n : lockData[1] - now;
1681
- lockInfo = {
1682
- amount: lockData[0],
1683
- unlockTime: lockData[1],
1684
- lockDuration: lockData[2],
1685
- vEXABalance: lockData[3],
1686
- currentVeEXA,
1687
- isUnlocked,
1688
- remainingLockTime
1689
- };
1690
- }
1691
- return { deposit: depositInfo, lock: lockInfo };
1692
- }
1693
- /**
1694
- * Get deposit info for a user
1695
- * @param userAddress Address to check (defaults to connected wallet)
1696
- * @returns Deposit info
1697
- */
1698
- async getDepositInfo(userAddress) {
1699
- const user = userAddress ?? this.account?.address;
1700
- if (!user) {
1701
- throw new Error("User address required");
1702
- }
1703
- const [deposited, lockResult, vaultAccess, unlockedBalance] = await Promise.all([
1704
- this.publicClient.readContract({
1705
- address: this.address,
1706
- abi: EXAGENT_STAKING_ABI,
1707
- functionName: "depositedAmount",
1708
- args: [user]
1709
- }),
1710
- this.publicClient.readContract({
1711
- address: this.address,
1712
- abi: EXAGENT_STAKING_ABI,
1713
- functionName: "locks",
1714
- args: [user]
1715
- }),
1716
- this.publicClient.readContract({
1717
- address: this.address,
1718
- abi: EXAGENT_STAKING_ABI,
1719
- functionName: "hasVaultAccess",
1720
- args: [user]
1721
- }),
1722
- this.publicClient.readContract({
1723
- address: this.address,
1724
- abi: EXAGENT_STAKING_ABI,
1725
- functionName: "getUnlockedBalance",
1726
- args: [user]
1727
- })
1728
- ]);
1729
- const lockData = lockResult;
1730
- return {
1731
- deposited,
1732
- locked: lockData[0],
1733
- unlocked: unlockedBalance,
1734
- hasVaultAccess: vaultAccess
1735
- };
1736
- }
1737
- /**
1738
- * Get current vEXA balance (with time decay applied)
1739
- * @param userAddress Address to check (defaults to connected wallet)
1740
- * @returns Current vEXA balance
1741
- */
1742
- async getVeEXABalance(userAddress) {
1743
- const user = userAddress ?? this.account?.address;
1744
- if (!user) {
1745
- throw new Error("User address required");
1746
- }
1747
- return this.publicClient.readContract({
1748
- address: this.address,
1749
- abi: EXAGENT_STAKING_ABI,
1750
- functionName: "getVeEXABalance",
1751
- args: [user]
1752
- });
1753
- }
1754
- /**
1755
- * Get effective vEXA (with tier multiplier applied)
1756
- * @param userAddress Address to check (defaults to connected wallet)
1757
- * @returns Effective vEXA balance
1758
- */
1759
- async getEffectiveVeEXA(userAddress) {
1760
- const user = userAddress ?? this.account?.address;
1761
- if (!user) {
1762
- throw new Error("User address required");
1763
- }
1764
- return this.publicClient.readContract({
1765
- address: this.address,
1766
- abi: EXAGENT_STAKING_ABI,
1767
- functionName: "getEffectiveVeEXA",
1768
- args: [user]
1769
- });
1770
- }
1771
- /**
1772
- * Check if user has vault access (meets deposit threshold)
1773
- * @param userAddress Address to check (defaults to connected wallet)
1774
- * @returns True if user can access vaults
1775
- */
1776
- async hasVaultAccess(userAddress) {
1777
- const user = userAddress ?? this.account?.address;
1778
- if (!user) {
1779
- throw new Error("User address required");
1780
- }
1781
- return this.publicClient.readContract({
1782
- address: this.address,
1783
- abi: EXAGENT_STAKING_ABI,
1784
- functionName: "hasVaultAccess",
1785
- args: [user]
1786
- });
1787
- }
1788
- /**
1789
- * Get earnings tier for a user (Bronze/Silver/Gold/Platinum/Diamond)
1790
- * @param userAddress Address to check (defaults to connected wallet)
1791
- * @returns Tier info with multiplier and name
1792
- */
1793
- async getEarningsTier(userAddress) {
1794
- const user = userAddress ?? this.account?.address;
1795
- if (!user) {
1796
- throw new Error("User address required");
1797
- }
1798
- const result = await this.publicClient.readContract({
1799
- address: this.address,
1800
- abi: EXAGENT_STAKING_ABI,
1801
- functionName: "getEarningsTier",
1802
- args: [user]
1803
- });
1804
- return {
1805
- multiplierBps: result[0],
1806
- tierName: result[1]
1807
- };
1808
- }
1809
- /**
1810
- * Get current emergency withdrawal penalty for a user
1811
- * @param userAddress Address to check (defaults to connected wallet)
1812
- * @returns Penalty in basis points (5000 = 50% at lock start, ramps to 2000 over first 25% of lock, then flat 2000)
1813
- */
1814
- async getEmergencyWithdrawPenalty(userAddress) {
1815
- const user = userAddress ?? this.account?.address;
1816
- if (!user) {
1817
- throw new Error("User address required");
1818
- }
1819
- return this.publicClient.readContract({
1820
- address: this.address,
1821
- abi: EXAGENT_STAKING_ABI,
1822
- functionName: "getEmergencyWithdrawPenalty",
1823
- args: [user]
1824
- });
1825
- }
1826
- /**
1827
- * Get pending EXA rewards for a user
1828
- * @param userAddress Address to check (defaults to connected wallet)
1829
- * @returns Pending reward amount in wei
1830
- */
1831
- async pendingRewards(userAddress) {
1832
- const user = userAddress ?? this.account?.address;
1833
- if (!user) {
1834
- throw new Error("User address required");
1835
- }
1836
- return this.publicClient.readContract({
1837
- address: this.address,
1838
- abi: EXAGENT_STAKING_ABI,
1839
- functionName: "pendingRewards",
1840
- args: [user]
1841
- });
1842
- }
1843
- /**
1844
- * Get pending rewards for a specific token
1845
- * @param token The reward token address
1846
- * @param userAddress Address to check (defaults to connected wallet)
1847
- * @returns Pending reward amount in wei
1848
- */
1849
- async pendingRewardsMulti(token, userAddress) {
1850
- const user = userAddress ?? this.account?.address;
1851
- if (!user) {
1852
- throw new Error("User address required");
1853
- }
1854
- return this.publicClient.readContract({
1855
- address: this.address,
1856
- abi: EXAGENT_STAKING_ABI,
1857
- functionName: "pendingRewardsForToken",
1858
- args: [user, token]
1859
- });
1860
- }
1861
- /**
1862
- * Get list of whitelisted reward tokens
1863
- * @returns Array of reward token addresses
1864
- */
1865
- async getRewardTokens() {
1866
- return this.publicClient.readContract({
1867
- address: this.address,
1868
- abi: EXAGENT_STAKING_ABI,
1869
- functionName: "getRewardTokens"
1870
- });
1871
- }
1872
- /**
1873
- * Check if a token is whitelisted for rewards
1874
- * @param token The token address to check
1875
- * @returns True if token is whitelisted
1876
- */
1877
- async isRewardToken(token) {
1878
- return this.publicClient.readContract({
1879
- address: this.address,
1880
- abi: EXAGENT_STAKING_ABI,
1881
- functionName: "isRewardToken",
1882
- args: [token]
1883
- });
1884
- }
1885
- /**
1886
- * Get total EXA deposited across all users
1887
- * @returns Total deposited amount in wei
1888
- */
1889
- async getTotalDeposited() {
1890
- return this.publicClient.readContract({
1891
- address: this.address,
1892
- abi: EXAGENT_STAKING_ABI,
1893
- functionName: "totalDeposited"
1894
- });
1895
- }
1896
- /**
1897
- * Get total EXA locked across all users
1898
- * @returns Total locked amount in wei
1899
- */
1900
- async getTotalLocked() {
1901
- return this.publicClient.readContract({
1902
- address: this.address,
1903
- abi: EXAGENT_STAKING_ABI,
1904
- functionName: "totalLocked"
1905
- });
1906
- }
1907
- /**
1908
- * Get total vEXA supply across all users
1909
- * @returns Total vEXA supply
1910
- */
1911
- async getTotalVeEXA() {
1912
- return this.publicClient.readContract({
1913
- address: this.address,
1914
- abi: EXAGENT_STAKING_ABI,
1915
- functionName: "totalVeEXA"
1916
- });
1917
- }
1918
- /**
1919
- * Calculate vEXA balance for a given lock (preview)
1920
- * @param amount Amount of EXA to lock
1921
- * @param lockDuration Lock duration in seconds
1922
- * @returns Expected vEXA balance
1923
- */
1924
- async calculateVeEXA(amount, lockDuration) {
1925
- return this.publicClient.readContract({
1926
- address: this.address,
1927
- abi: EXAGENT_STAKING_ABI,
1928
- functionName: "calculateVeEXA",
1929
- args: [amount, lockDuration]
1930
- });
1931
- }
1932
- /**
1933
- * Get the EXA token address
1934
- * @returns EXA token contract address
1935
- */
1936
- async getExaTokenAddress() {
1937
- return this.publicClient.readContract({
1938
- address: this.address,
1939
- abi: EXAGENT_STAKING_ABI,
1940
- functionName: "exaToken"
1941
- });
1942
- }
1943
- // ============ Helper Functions ============
1944
- /**
1945
- * Approve EXA token spending for deposits
1946
- * @param amount Amount to approve
1947
- * @returns Transaction hash
1948
- */
1949
- async approveExa(amount) {
1950
- if (!this.walletClient || !this.account) {
1951
- throw new Error("Wallet client required for write operations");
1952
- }
1953
- const exaToken = await this.getExaTokenAddress();
1954
- const hash = await this.walletClient.writeContract({
1955
- address: exaToken,
1956
- abi: ERC20_APPROVE_ABI2,
1957
- functionName: "approve",
1958
- args: [this.address, amount],
1959
- account: this.account,
1960
- chain: this.chain
1961
- });
1962
- return hash;
1963
- }
1964
- // ============ Lock Duration Constants ============
1965
- /** Minimum lock duration: 30 days in seconds */
1966
- static MIN_LOCK_DURATION = 30n * 24n * 60n * 60n;
1967
- /** Maximum lock duration: 2 years in seconds */
1968
- static MAX_LOCK_DURATION = 730n * 24n * 60n * 60n;
1969
- /** 1 month lock duration in seconds */
1970
- static LOCK_1_MONTH = 30n * 24n * 60n * 60n;
1971
- /** 3 months lock duration in seconds */
1972
- static LOCK_3_MONTHS = 90n * 24n * 60n * 60n;
1973
- /** 6 months lock duration in seconds */
1974
- static LOCK_6_MONTHS = 180n * 24n * 60n * 60n;
1975
- /** 1 year lock duration in seconds */
1976
- static LOCK_1_YEAR = 365n * 24n * 60n * 60n;
1977
- /** 2 years lock duration in seconds */
1978
- static LOCK_2_YEARS = 730n * 24n * 60n * 60n;
1979
- };
1980
-
1981
1167
  // src/constants.ts
1982
1168
  import { base } from "viem/chains";
1983
1169
  var SDK_VERSION = "0.1.14";
@@ -1994,12 +1180,9 @@ var CHAIN_CONFIG = {
1994
1180
  var CONTRACT_ADDRESSES = {
1995
1181
  mainnet: {
1996
1182
  agentRegistry: "0x2261706C751F8ac5cdDb481B7b56EA2137d4A723",
1997
- exaToken: "0x13403Fb738C97cF7564F279288468c140AaEd05c",
1998
- staking: "0xe925727B21f1B86008f291E8f3102345A57B6c17",
1999
1183
  router: "0x1BCFa13f677fDCf697D8b7d5120f544817F1de1A",
2000
- vaultFactory: "0x5b90C7F9F02F9130a92481360E9aa5Be4fcc9500",
2001
- feeCollector: "0xe66328a964AF93bEF2eDB226D039C35aE6e66De1",
2002
- buyback: "0x39967532b640B2f735548c7a5b46d8D890A0B2f2",
1184
+ vaultFactory: "0x1E0e4E445A9fda2e7aBBfFEcA80392ABb0921554",
1185
+ feeCollector: "0x00Ab9847049b5496619dFDd1A7bd36FA49eB7195",
2003
1186
  serviceEscrow: "0x63A4d1dA774422EFC2cc57d71F948231BD812516"
2004
1187
  }
2005
1188
  };
@@ -2023,19 +1206,12 @@ var EXAGENT_API_CONFIG = {
2023
1206
  mainnet: "https://exagent-api.onrender.com"
2024
1207
  };
2025
1208
  var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
2026
- var PHASE_1_CONTRACTS = /* @__PURE__ */ new Set([
2027
- "agentRegistry",
2028
- "exaToken",
2029
- "staking",
2030
- "router",
2031
- "feeCollector"
2032
- ]);
2033
1209
  function validateContractAddresses(network) {
2034
1210
  const addresses = CONTRACT_ADDRESSES[network];
2035
- const missingPhase1 = Object.entries(addresses).filter(([name, addr]) => PHASE_1_CONTRACTS.has(name) && addr === ZERO_ADDRESS).map(([name]) => name);
2036
- if (missingPhase1.length > 0) {
1211
+ const missing = Object.entries(addresses).filter(([, addr]) => addr === ZERO_ADDRESS).map(([name]) => name);
1212
+ if (missing.length > 0) {
2037
1213
  throw new Error(
2038
- `Mainnet Phase 1 contracts not deployed. Missing: ${missingPhase1.join(", ")}. Update @exagent/sdk to the latest version.`
1214
+ `Contract addresses not deployed on ${network}. Missing: ${missing.join(", ")}. Update @exagent/sdk to the latest version.`
2039
1215
  );
2040
1216
  }
2041
1217
  }
@@ -2067,7 +1243,6 @@ var ExagentClient = class {
2067
1243
  apiKey;
2068
1244
  // Contract interfaces
2069
1245
  registry;
2070
- staking;
2071
1246
  // Cached agent ID
2072
1247
  _agentId;
2073
1248
  constructor(config) {
@@ -2102,13 +1277,6 @@ var ExagentClient = class {
2102
1277
  chain,
2103
1278
  this.account
2104
1279
  );
2105
- this.staking = new ExagentStaking(
2106
- addresses.staking,
2107
- this.publicClient,
2108
- this.walletClient,
2109
- chain,
2110
- this.account
2111
- );
2112
1280
  }
2113
1281
  /** Standard headers for all API requests (includes SDK version for gating) */
2114
1282
  apiHeaders(contentType) {
@@ -2257,7 +1425,7 @@ var ExagentClient = class {
2257
1425
  await this.approveToken(
2258
1426
  approval.token,
2259
1427
  approval.spender,
2260
- amount
1428
+ maxUint256
2261
1429
  );
2262
1430
  }
2263
1431
  const txParams = {
@@ -2278,6 +1446,7 @@ var ExagentClient = class {
2278
1446
  } catch (err) {
2279
1447
  const errorData = err?.data;
2280
1448
  if (errorData && errorData.length > 2) {
1449
+ console.error(`Gas estimation revert data: ${errorData}`);
2281
1450
  try {
2282
1451
  const decoded = decodeErrorResult({
2283
1452
  abi: [...EXAGENT_ROUTER_ABI, ...EXAGENT_REGISTRY_ABI],
@@ -2286,6 +1455,7 @@ var ExagentClient = class {
2286
1455
  throw new Error(`Trade will revert: ${decoded.errorName}${decoded.args ? ` (${decoded.args.join(", ")})` : ""}`);
2287
1456
  } catch (decodeErr) {
2288
1457
  if (decodeErr instanceof Error && decodeErr.message.startsWith("Trade will revert:")) throw decodeErr;
1458
+ throw new Error(`Trade will revert: unknown error selector ${errorData.slice(0, 10)} (raw: ${errorData.slice(0, 66)})`);
2289
1459
  }
2290
1460
  }
2291
1461
  throw new Error(`Trade will revert: gas estimation failed. ${err?.message || "Unknown reason"}`);
@@ -2350,7 +1520,9 @@ var ExagentClient = class {
2350
1520
  }
2351
1521
  }
2352
1522
  /**
2353
- * Approve token spending for router
1523
+ * Approve token spending for router.
1524
+ * Verifies the approval receipt succeeded — previous version silently continued
1525
+ * on reverted approvals, causing downstream "transfer amount exceeds allowance" errors.
2354
1526
  */
2355
1527
  async approveToken(token, spender, amount) {
2356
1528
  const approveData = this.encodeApprove(spender, amount);
@@ -2360,7 +1532,12 @@ var ExagentClient = class {
2360
1532
  to: token,
2361
1533
  data: approveData
2362
1534
  });
2363
- await this.publicClient.waitForTransactionReceipt({ hash });
1535
+ const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
1536
+ if (receipt.status === "reverted") {
1537
+ throw new Error(
1538
+ `Token approval reverted: approve(${spender}, ${amount}) on ${token}. The token may have non-standard approval behavior.`
1539
+ );
1540
+ }
2364
1541
  return hash;
2365
1542
  }
2366
1543
  /**
@@ -2521,113 +1698,6 @@ var ExagentClient = class {
2521
1698
  const vault = this.getVault(vaultAddress);
2522
1699
  return vault.redeem(shares);
2523
1700
  }
2524
- // ============ Staking Functions ============
2525
- /**
2526
- * Deposit EXA tokens for vault access (no lock required)
2527
- * @param amount Amount of EXA to deposit (in wei)
2528
- * @returns Transaction hash
2529
- *
2530
- * @example
2531
- * ```typescript
2532
- * // Deposit 1000 EXA to unlock vault access
2533
- * const tx = await exagent.depositExa(parseEther('1000'));
2534
- * ```
2535
- */
2536
- async depositExa(amount) {
2537
- await this.staking.approveExa(amount);
2538
- return this.staking.deposit(amount);
2539
- }
2540
- /**
2541
- * Withdraw unlocked EXA tokens (instant, no penalty)
2542
- * @param amount Amount of EXA to withdraw (in wei)
2543
- * @returns Transaction hash
2544
- */
2545
- async withdrawExa(amount) {
2546
- return this.staking.withdraw(amount);
2547
- }
2548
- /**
2549
- * Lock deposited EXA to receive vEXA voting power and earn rewards
2550
- * @param amount Amount of deposited EXA to lock (in wei)
2551
- * @param lockDuration Lock duration in seconds (30 days to 2 years)
2552
- * @returns Transaction hash
2553
- *
2554
- * @example
2555
- * ```typescript
2556
- * // Lock 1000 EXA for 6 months
2557
- * const tx = await exagent.lockExa(
2558
- * parseEther('1000'),
2559
- * ExagentStaking.LOCK_6_MONTHS
2560
- * );
2561
- * ```
2562
- */
2563
- async lockExa(amount, lockDuration) {
2564
- return this.staking.lock(amount, lockDuration);
2565
- }
2566
- /**
2567
- * Unlock EXA after lock expires (no penalty)
2568
- * @returns Transaction hash
2569
- */
2570
- async unlockExa() {
2571
- return this.staking.unlock();
2572
- }
2573
- /**
2574
- * Emergency withdrawal from active lock (graduated 50%→20% penalty)
2575
- * @returns Transaction hash
2576
- */
2577
- async emergencyWithdrawExa() {
2578
- return this.staking.emergencyWithdraw();
2579
- }
2580
- /**
2581
- * Get comprehensive staking info (deposit + lock) for the connected wallet
2582
- * @returns Staking info including deposit status and lock status
2583
- */
2584
- async getStakingInfo() {
2585
- return this.staking.getStakingInfo();
2586
- }
2587
- /**
2588
- * Get deposit info for the connected wallet
2589
- * @returns Deposit info (deposited, locked, unlocked, vault access)
2590
- */
2591
- async getDepositInfo() {
2592
- return this.staking.getDepositInfo();
2593
- }
2594
- /**
2595
- * Get current vEXA balance for the connected wallet
2596
- * @returns Current vEXA balance (with time decay applied)
2597
- */
2598
- async getVeEXABalance() {
2599
- return this.staking.getVeEXABalance();
2600
- }
2601
- /**
2602
- * Check if connected wallet has vault access (meets deposit threshold)
2603
- * @returns True if user can access vaults
2604
- */
2605
- async hasVaultAccess() {
2606
- return this.staking.hasVaultAccess();
2607
- }
2608
- /**
2609
- * Get earnings tier for the connected wallet
2610
- * @returns Tier info with multiplier and name
2611
- */
2612
- async getEarningsTier() {
2613
- return this.staking.getEarningsTier();
2614
- }
2615
- /**
2616
- * Get emergency withdrawal penalty for the connected wallet
2617
- * @returns Penalty in basis points (5000 = 50% at start, 2000 = 20% near expiry)
2618
- */
2619
- async getEmergencyWithdrawPenalty() {
2620
- return this.staking.getEmergencyWithdrawPenalty();
2621
- }
2622
- /**
2623
- * Claim all pending staking rewards (EXA + multi-token)
2624
- * @returns Transaction hashes for EXA and multi-token claims
2625
- */
2626
- async claimAllRewards() {
2627
- const exaRewards = await this.staking.claimRewards();
2628
- const multiTokenRewards = await this.staking.claimRewardsMulti();
2629
- return { exaRewards, multiTokenRewards };
2630
- }
2631
1701
  // ============ ERC-8004 Global Agent Identity ============
2632
1702
  /**
2633
1703
  * Get the ERC-8004 global agent identifier for the current agent
@@ -2724,20 +1794,9 @@ var EXAGENT_VAULT_FACTORY_ABI = [
2724
1794
  { type: "function", name: "allowedAssets", inputs: [{ name: "asset", type: "address" }], outputs: [{ type: "bool" }], stateMutability: "view" },
2725
1795
  { type: "function", name: "vaults", inputs: [{ name: "agentId", type: "uint256" }, { name: "asset", type: "address" }], outputs: [{ type: "address" }], stateMutability: "view" },
2726
1796
  { type: "function", name: "agentVaultCount", inputs: [{ name: "agentId", type: "uint256" }], outputs: [{ type: "uint256" }], stateMutability: "view" },
2727
- {
2728
- type: "function",
2729
- name: "canCreateVault",
2730
- inputs: [{ name: "creator", type: "address" }],
2731
- outputs: [{ name: "canCreate", type: "bool" }, { name: "reason", type: "string" }],
2732
- stateMutability: "view"
2733
- },
2734
- {
2735
- type: "function",
2736
- name: "canCreateVerifiedVault",
2737
- inputs: [{ name: "agentId", type: "uint256" }],
2738
- outputs: [{ name: "isVerified", type: "bool" }, { name: "reason", type: "string" }],
2739
- stateMutability: "view"
2740
- },
1797
+ // NOTE: canCreateVault() and canCreateVerifiedVault() do not exist on the
1798
+ // deployed ExagentVaultFactoryV2 contract. SDK methods that called these
1799
+ // now use inline validation (allowedAssets, vaults, MIN_SEED_AMOUNT) instead.
2741
1800
  // Write functions
2742
1801
  {
2743
1802
  type: "function",
@@ -2798,12 +1857,7 @@ var ExagentVaultFactory = class {
2798
1857
  * Get vault creation requirements (mainnet: seed-based, no burn fee)
2799
1858
  */
2800
1859
  async getRequirements() {
2801
- const [veXARequired, minSeedAmount, unverifiedCapMultiplier, verifiedCapMultiplier, stakingContract] = await Promise.all([
2802
- this.publicClient.readContract({
2803
- address: this.address,
2804
- abi: EXAGENT_VAULT_FACTORY_ABI,
2805
- functionName: "VERIFIED_VEXA_REQUIREMENT"
2806
- }),
1860
+ const [minSeedAmount, unverifiedCapMultiplier, verifiedCapMultiplier] = await Promise.all([
2807
1861
  this.publicClient.readContract({
2808
1862
  address: this.address,
2809
1863
  abi: EXAGENT_VAULT_FACTORY_ABI,
@@ -2818,52 +1872,29 @@ var ExagentVaultFactory = class {
2818
1872
  address: this.address,
2819
1873
  abi: EXAGENT_VAULT_FACTORY_ABI,
2820
1874
  functionName: "VERIFIED_CAP_MULTIPLIER"
2821
- }),
2822
- this.publicClient.readContract({
2823
- address: this.address,
2824
- abi: EXAGENT_VAULT_FACTORY_ABI,
2825
- functionName: "stakingContract"
2826
1875
  })
2827
1876
  ]);
2828
1877
  return {
2829
- veXARequired,
2830
1878
  minSeedAmount,
2831
1879
  unverifiedCapMultiplier,
2832
- verifiedCapMultiplier,
2833
- stakingContract
1880
+ verifiedCapMultiplier
2834
1881
  };
2835
1882
  }
2836
1883
  /**
2837
- * Check if an address can create a vault
1884
+ * Check if an address can create a vault.
1885
+ * Performs inline validation since the on-chain contract does not expose
1886
+ * a canCreateVault() view function.
2838
1887
  * @param creator Address to check
2839
1888
  */
2840
1889
  async canCreateVault(creator) {
2841
- const result = await this.publicClient.readContract({
2842
- address: this.address,
2843
- abi: EXAGENT_VAULT_FACTORY_ABI,
2844
- functionName: "canCreateVault",
2845
- args: [creator]
2846
- });
2847
- return {
2848
- canCreate: result[0],
2849
- reason: result[1]
2850
- };
2851
- }
2852
- /**
2853
- * Check if an agent can create a verified vault (higher deposit cap)
2854
- * @param agentId Agent ID to check
2855
- */
2856
- async canCreateVerifiedVault(agentId) {
2857
- const result = await this.publicClient.readContract({
2858
- address: this.address,
2859
- abi: EXAGENT_VAULT_FACTORY_ABI,
2860
- functionName: "canCreateVerifiedVault",
2861
- args: [agentId]
2862
- });
2863
- return {
2864
- isVerified: result[0],
2865
- reason: result[1]
2866
- };
1890
+ try {
1891
+ const isUsdcAllowed = await this.isAssetAllowed("0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913");
1892
+ if (!isUsdcAllowed) {
1893
+ return { canCreate: false, reason: "USDC is not an allowed asset" };
1894
+ }
1895
+ } catch {
1896
+ }
1897
+ return { canCreate: true, reason: "" };
2867
1898
  }
2868
1899
  /**
2869
1900
  * Check if an asset is whitelisted for vault creation
@@ -3015,11 +2046,9 @@ export {
3015
2046
  EXAGENT_API_CONFIG,
3016
2047
  EXAGENT_REGISTRY_ABI,
3017
2048
  EXAGENT_ROUTER_ABI,
3018
- EXAGENT_STAKING_ABI,
3019
2049
  EXAGENT_VAULT_FACTORY_ABI,
3020
2050
  ExagentClient,
3021
2051
  ExagentRegistry,
3022
- ExagentStaking,
3023
2052
  ExagentVault,
3024
2053
  ExagentVaultFactory,
3025
2054
  SDK_VERSION,