@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.d.mts +489 -279
- package/dist/index.d.ts +489 -279
- package/dist/index.js +705 -431
- package/dist/index.mjs +703 -437
- package/package.json +1 -1
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
|
|
515
|
-
*
|
|
516
|
-
*
|
|
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
|
|
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
|
-
|
|
659
|
-
|
|
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: "
|
|
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: "
|
|
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
|
-
// ============
|
|
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: "
|
|
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
|
-
// ============
|
|
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: "
|
|
1144
|
-
inputs: [{ name: "
|
|
1145
|
-
outputs: [],
|
|
1146
|
-
stateMutability: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
1208
|
-
{ name: "
|
|
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: "
|
|
1375
|
+
name: "getEmergencyWithdrawPenalty",
|
|
1215
1376
|
inputs: [{ name: "user", type: "address" }],
|
|
1216
|
-
outputs: [{ name: "
|
|
1377
|
+
outputs: [{ name: "penaltyBps", type: "uint256" }],
|
|
1217
1378
|
stateMutability: "view"
|
|
1218
1379
|
},
|
|
1219
1380
|
{
|
|
1220
1381
|
type: "function",
|
|
1221
|
-
name: "
|
|
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: "
|
|
1384
|
+
outputs: [{ type: "bool" }],
|
|
1231
1385
|
stateMutability: "view"
|
|
1232
1386
|
},
|
|
1233
1387
|
{
|
|
1234
1388
|
type: "function",
|
|
1235
|
-
name: "
|
|
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: "
|
|
1243
|
-
inputs: [
|
|
1244
|
-
outputs: [{ type: "
|
|
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: "
|
|
1411
|
+
name: "Deposited",
|
|
1265
1412
|
inputs: [
|
|
1266
1413
|
{ name: "user", type: "address", indexed: true },
|
|
1267
1414
|
{ name: "amount", type: "uint256", indexed: false },
|
|
1268
|
-
{ name: "
|
|
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: "
|
|
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: "
|
|
1429
|
+
name: "Locked",
|
|
1284
1430
|
inputs: [
|
|
1285
1431
|
{ name: "user", type: "address", indexed: true },
|
|
1286
|
-
{ name: "
|
|
1287
|
-
{ name: "
|
|
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: "
|
|
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: "
|
|
1448
|
+
name: "EmergencyWithdrawal",
|
|
1301
1449
|
inputs: [
|
|
1302
|
-
{ name: "
|
|
1303
|
-
{ name: "
|
|
1304
|
-
{ name: "
|
|
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: "
|
|
1458
|
+
name: "LockExtended",
|
|
1310
1459
|
inputs: [
|
|
1311
|
-
{ name: "
|
|
1312
|
-
{ name: "
|
|
1313
|
-
{ name: "
|
|
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
|
-
// ============
|
|
1513
|
+
// ============ Phase 1: Deposit / Withdraw ============
|
|
1363
1514
|
/**
|
|
1364
|
-
*
|
|
1365
|
-
* @param amount Amount of EXA to
|
|
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
|
-
* //
|
|
1372
|
-
* const tx = await staking.
|
|
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
|
|
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: "
|
|
1386
|
-
args: [amount
|
|
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
|
-
*
|
|
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
|
|
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: "
|
|
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
|
-
*
|
|
1413
|
-
* @param
|
|
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
|
|
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: "
|
|
1424
|
-
args: [
|
|
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
|
-
*
|
|
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
|
|
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: "
|
|
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
|
-
*
|
|
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
|
|
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: "
|
|
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
|
-
*
|
|
1469
|
-
*
|
|
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
|
|
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: "
|
|
1480
|
-
args: [
|
|
1639
|
+
functionName: "emergencyWithdraw",
|
|
1640
|
+
args: [],
|
|
1481
1641
|
account: this.account,
|
|
1482
1642
|
chain: this.chain
|
|
1483
1643
|
});
|
|
1484
1644
|
return hash;
|
|
1485
1645
|
}
|
|
1486
|
-
// ============
|
|
1646
|
+
// ============ Reward Functions ============
|
|
1487
1647
|
/**
|
|
1488
|
-
*
|
|
1489
|
-
* @param agentId The agent ID to delegate to
|
|
1648
|
+
* Claim accumulated EXA rewards
|
|
1490
1649
|
* @returns Transaction hash
|
|
1491
1650
|
*/
|
|
1492
|
-
async
|
|
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: "
|
|
1500
|
-
args: [
|
|
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
|
-
*
|
|
1666
|
+
* Claim all pending multi-token rewards (ETH, USDC, etc.)
|
|
1508
1667
|
* @returns Transaction hash
|
|
1509
1668
|
*/
|
|
1510
|
-
async
|
|
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: "
|
|
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
|
-
*
|
|
1526
|
-
* @param
|
|
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
|
|
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: "
|
|
1537
|
-
args: [
|
|
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
|
|
1706
|
+
* @returns Combined staking info
|
|
1548
1707
|
*/
|
|
1549
|
-
async
|
|
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 [
|
|
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: "
|
|
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
|
|
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
|
|
1571
|
-
|
|
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
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
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
|
|
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
|
|
1852
|
+
* @returns True if user can access vaults
|
|
1603
1853
|
*/
|
|
1604
|
-
async
|
|
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: "
|
|
1862
|
+
functionName: "hasVaultAccess",
|
|
1613
1863
|
args: [user]
|
|
1614
1864
|
});
|
|
1615
1865
|
}
|
|
1616
1866
|
/**
|
|
1617
|
-
* Get
|
|
1618
|
-
* @param
|
|
1619
|
-
* @returns
|
|
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
|
|
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: "
|
|
1626
|
-
args: [
|
|
1879
|
+
functionName: "getEarningsTier",
|
|
1880
|
+
args: [user]
|
|
1627
1881
|
});
|
|
1628
1882
|
return {
|
|
1629
|
-
|
|
1630
|
-
|
|
1883
|
+
multiplierBps: result[0],
|
|
1884
|
+
tierName: result[1]
|
|
1631
1885
|
};
|
|
1632
1886
|
}
|
|
1633
1887
|
/**
|
|
1634
|
-
* Get
|
|
1888
|
+
* Get current emergency withdrawal penalty for a user
|
|
1635
1889
|
* @param userAddress Address to check (defaults to connected wallet)
|
|
1636
|
-
* @returns
|
|
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
|
|
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
|
-
|
|
1897
|
+
return this.publicClient.readContract({
|
|
1644
1898
|
address: this.address,
|
|
1645
1899
|
abi: EXAGENT_STAKING_ABI,
|
|
1646
|
-
functionName: "
|
|
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
|
|
1720
|
-
* @returns Total
|
|
1964
|
+
* Get total EXA deposited across all users
|
|
1965
|
+
* @returns Total deposited amount in wei
|
|
1721
1966
|
*/
|
|
1722
|
-
async
|
|
1967
|
+
async getTotalDeposited() {
|
|
1723
1968
|
return this.publicClient.readContract({
|
|
1724
1969
|
address: this.address,
|
|
1725
1970
|
abi: EXAGENT_STAKING_ABI,
|
|
1726
|
-
functionName: "
|
|
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
|
|
1742
|
-
* @param amount Amount of EXA to
|
|
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
|
|
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: "
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
router: "0x0000000000000000000000000000000000000000",
|
|
2068
|
+
agentRegistry: "0x2261706C751F8ac5cdDb481B7b56EA2137d4A723",
|
|
2069
|
+
exaToken: "0x13403Fb738C97cF7564F279288468c140AaEd05c",
|
|
2070
|
+
staking: "0xAF1729D1519A72f7d9b87aa23a305b775e2849DA",
|
|
2071
|
+
router: "0x11daD5366D903a3eF5d8f07EFF87ce6b173859a9",
|
|
1816
2072
|
vaultFactory: "0x0000000000000000000000000000000000000000",
|
|
1817
|
-
|
|
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
|
-
//
|
|
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.
|
|
1854
|
-
testnet: "https://api.
|
|
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
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
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
|
|
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
|
|
1992
|
-
const signature = await signMessage(
|
|
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
|
-
*
|
|
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
|
-
*
|
|
2124
|
-
*
|
|
2125
|
-
*
|
|
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
|
-
*
|
|
2376
|
-
* @param amount Amount of EXA to
|
|
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
|
-
* //
|
|
2383
|
-
* const tx = await exagent.
|
|
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
|
|
2390
|
-
|
|
2391
|
-
|
|
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
|
-
*
|
|
2596
|
+
* Emergency withdrawal from active lock (graduated 50%→20% penalty)
|
|
2395
2597
|
* @returns Transaction hash
|
|
2396
2598
|
*/
|
|
2397
|
-
async
|
|
2398
|
-
return this.staking.
|
|
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
|
|
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.
|
|
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
|
-
*
|
|
2416
|
-
* @
|
|
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
|
|
2420
|
-
return this.staking.
|
|
2627
|
+
async hasVaultAccess() {
|
|
2628
|
+
return this.staking.hasVaultAccess();
|
|
2421
2629
|
}
|
|
2422
2630
|
/**
|
|
2423
|
-
* Get
|
|
2424
|
-
* @
|
|
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
|
|
2428
|
-
return this.staking.
|
|
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
|
-
|
|
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: "
|
|
2486
|
-
{ type: "function", name: "
|
|
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: "
|
|
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
|
-
|
|
2566
|
-
|
|
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: "
|
|
2570
|
-
})
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
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
|
});
|