@exagent/sdk 0.1.14 → 0.1.16

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) {
@@ -2244,6 +1412,10 @@ var ExagentClient = class {
2244
1412
  const key = `${approval.token.toLowerCase()}:${approval.spender.toLowerCase()}`;
2245
1413
  if (seen.has(key)) continue;
2246
1414
  seen.add(key);
1415
+ if (!approval.amount) {
1416
+ console.warn(`Skipping approval with missing amount for token ${approval.token} \u2014 0x did not return expected allowance`);
1417
+ continue;
1418
+ }
2247
1419
  const amount = BigInt(approval.amount);
2248
1420
  const existing = await this.getAllowance(
2249
1421
  approval.token,
@@ -2253,7 +1425,7 @@ var ExagentClient = class {
2253
1425
  await this.approveToken(
2254
1426
  approval.token,
2255
1427
  approval.spender,
2256
- amount
1428
+ maxUint256
2257
1429
  );
2258
1430
  }
2259
1431
  const txParams = {
@@ -2346,7 +1518,9 @@ var ExagentClient = class {
2346
1518
  }
2347
1519
  }
2348
1520
  /**
2349
- * Approve token spending for router
1521
+ * Approve token spending for router.
1522
+ * Verifies the approval receipt succeeded — previous version silently continued
1523
+ * on reverted approvals, causing downstream "transfer amount exceeds allowance" errors.
2350
1524
  */
2351
1525
  async approveToken(token, spender, amount) {
2352
1526
  const approveData = this.encodeApprove(spender, amount);
@@ -2356,7 +1530,12 @@ var ExagentClient = class {
2356
1530
  to: token,
2357
1531
  data: approveData
2358
1532
  });
2359
- await this.publicClient.waitForTransactionReceipt({ hash });
1533
+ const receipt = await this.publicClient.waitForTransactionReceipt({ hash });
1534
+ if (receipt.status === "reverted") {
1535
+ throw new Error(
1536
+ `Token approval reverted: approve(${spender}, ${amount}) on ${token}. The token may have non-standard approval behavior.`
1537
+ );
1538
+ }
2360
1539
  return hash;
2361
1540
  }
2362
1541
  /**
@@ -2517,113 +1696,6 @@ var ExagentClient = class {
2517
1696
  const vault = this.getVault(vaultAddress);
2518
1697
  return vault.redeem(shares);
2519
1698
  }
2520
- // ============ Staking Functions ============
2521
- /**
2522
- * Deposit EXA tokens for vault access (no lock required)
2523
- * @param amount Amount of EXA to deposit (in wei)
2524
- * @returns Transaction hash
2525
- *
2526
- * @example
2527
- * ```typescript
2528
- * // Deposit 1000 EXA to unlock vault access
2529
- * const tx = await exagent.depositExa(parseEther('1000'));
2530
- * ```
2531
- */
2532
- async depositExa(amount) {
2533
- await this.staking.approveExa(amount);
2534
- return this.staking.deposit(amount);
2535
- }
2536
- /**
2537
- * Withdraw unlocked EXA tokens (instant, no penalty)
2538
- * @param amount Amount of EXA to withdraw (in wei)
2539
- * @returns Transaction hash
2540
- */
2541
- async withdrawExa(amount) {
2542
- return this.staking.withdraw(amount);
2543
- }
2544
- /**
2545
- * Lock deposited EXA to receive vEXA voting power and earn rewards
2546
- * @param amount Amount of deposited EXA to lock (in wei)
2547
- * @param lockDuration Lock duration in seconds (30 days to 2 years)
2548
- * @returns Transaction hash
2549
- *
2550
- * @example
2551
- * ```typescript
2552
- * // Lock 1000 EXA for 6 months
2553
- * const tx = await exagent.lockExa(
2554
- * parseEther('1000'),
2555
- * ExagentStaking.LOCK_6_MONTHS
2556
- * );
2557
- * ```
2558
- */
2559
- async lockExa(amount, lockDuration) {
2560
- return this.staking.lock(amount, lockDuration);
2561
- }
2562
- /**
2563
- * Unlock EXA after lock expires (no penalty)
2564
- * @returns Transaction hash
2565
- */
2566
- async unlockExa() {
2567
- return this.staking.unlock();
2568
- }
2569
- /**
2570
- * Emergency withdrawal from active lock (graduated 50%→20% penalty)
2571
- * @returns Transaction hash
2572
- */
2573
- async emergencyWithdrawExa() {
2574
- return this.staking.emergencyWithdraw();
2575
- }
2576
- /**
2577
- * Get comprehensive staking info (deposit + lock) for the connected wallet
2578
- * @returns Staking info including deposit status and lock status
2579
- */
2580
- async getStakingInfo() {
2581
- return this.staking.getStakingInfo();
2582
- }
2583
- /**
2584
- * Get deposit info for the connected wallet
2585
- * @returns Deposit info (deposited, locked, unlocked, vault access)
2586
- */
2587
- async getDepositInfo() {
2588
- return this.staking.getDepositInfo();
2589
- }
2590
- /**
2591
- * Get current vEXA balance for the connected wallet
2592
- * @returns Current vEXA balance (with time decay applied)
2593
- */
2594
- async getVeEXABalance() {
2595
- return this.staking.getVeEXABalance();
2596
- }
2597
- /**
2598
- * Check if connected wallet has vault access (meets deposit threshold)
2599
- * @returns True if user can access vaults
2600
- */
2601
- async hasVaultAccess() {
2602
- return this.staking.hasVaultAccess();
2603
- }
2604
- /**
2605
- * Get earnings tier for the connected wallet
2606
- * @returns Tier info with multiplier and name
2607
- */
2608
- async getEarningsTier() {
2609
- return this.staking.getEarningsTier();
2610
- }
2611
- /**
2612
- * Get emergency withdrawal penalty for the connected wallet
2613
- * @returns Penalty in basis points (5000 = 50% at start, 2000 = 20% near expiry)
2614
- */
2615
- async getEmergencyWithdrawPenalty() {
2616
- return this.staking.getEmergencyWithdrawPenalty();
2617
- }
2618
- /**
2619
- * Claim all pending staking rewards (EXA + multi-token)
2620
- * @returns Transaction hashes for EXA and multi-token claims
2621
- */
2622
- async claimAllRewards() {
2623
- const exaRewards = await this.staking.claimRewards();
2624
- const multiTokenRewards = await this.staking.claimRewardsMulti();
2625
- return { exaRewards, multiTokenRewards };
2626
- }
2627
1699
  // ============ ERC-8004 Global Agent Identity ============
2628
1700
  /**
2629
1701
  * Get the ERC-8004 global agent identifier for the current agent
@@ -2794,12 +1866,7 @@ var ExagentVaultFactory = class {
2794
1866
  * Get vault creation requirements (mainnet: seed-based, no burn fee)
2795
1867
  */
2796
1868
  async getRequirements() {
2797
- const [veXARequired, minSeedAmount, unverifiedCapMultiplier, verifiedCapMultiplier, stakingContract] = await Promise.all([
2798
- this.publicClient.readContract({
2799
- address: this.address,
2800
- abi: EXAGENT_VAULT_FACTORY_ABI,
2801
- functionName: "VERIFIED_VEXA_REQUIREMENT"
2802
- }),
1869
+ const [minSeedAmount, unverifiedCapMultiplier, verifiedCapMultiplier] = await Promise.all([
2803
1870
  this.publicClient.readContract({
2804
1871
  address: this.address,
2805
1872
  abi: EXAGENT_VAULT_FACTORY_ABI,
@@ -2814,19 +1881,12 @@ var ExagentVaultFactory = class {
2814
1881
  address: this.address,
2815
1882
  abi: EXAGENT_VAULT_FACTORY_ABI,
2816
1883
  functionName: "VERIFIED_CAP_MULTIPLIER"
2817
- }),
2818
- this.publicClient.readContract({
2819
- address: this.address,
2820
- abi: EXAGENT_VAULT_FACTORY_ABI,
2821
- functionName: "stakingContract"
2822
1884
  })
2823
1885
  ]);
2824
1886
  return {
2825
- veXARequired,
2826
1887
  minSeedAmount,
2827
1888
  unverifiedCapMultiplier,
2828
- verifiedCapMultiplier,
2829
- stakingContract
1889
+ verifiedCapMultiplier
2830
1890
  };
2831
1891
  }
2832
1892
  /**
@@ -3011,11 +2071,9 @@ export {
3011
2071
  EXAGENT_API_CONFIG,
3012
2072
  EXAGENT_REGISTRY_ABI,
3013
2073
  EXAGENT_ROUTER_ABI,
3014
- EXAGENT_STAKING_ABI,
3015
2074
  EXAGENT_VAULT_FACTORY_ABI,
3016
2075
  ExagentClient,
3017
2076
  ExagentRegistry,
3018
- ExagentStaking,
3019
2077
  ExagentVault,
3020
2078
  ExagentVaultFactory,
3021
2079
  SDK_VERSION,