@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.mjs
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
-
}) : x)(function(x) {
|
|
4
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
1
|
// src/client.ts
|
|
9
2
|
import {
|
|
10
3
|
createPublicClient,
|
|
@@ -15,7 +8,8 @@ import { privateKeyToAccount } from "viem/accounts";
|
|
|
15
8
|
|
|
16
9
|
// src/contracts/registry.ts
|
|
17
10
|
import {
|
|
18
|
-
encodePacked
|
|
11
|
+
encodePacked,
|
|
12
|
+
keccak256
|
|
19
13
|
} from "viem";
|
|
20
14
|
var EXAGENT_REGISTRY_ABI = [
|
|
21
15
|
{
|
|
@@ -23,7 +17,10 @@ var EXAGENT_REGISTRY_ABI = [
|
|
|
23
17
|
name: "registerAgent",
|
|
24
18
|
inputs: [
|
|
25
19
|
{ name: "name", type: "string" },
|
|
26
|
-
{ name: "metadataURI", type: "string" }
|
|
20
|
+
{ name: "metadataURI", type: "string" },
|
|
21
|
+
{ name: "riskUniverse", type: "uint8" },
|
|
22
|
+
{ name: "maxPositionSizeBps", type: "uint256" },
|
|
23
|
+
{ name: "maxDailyLossBps", type: "uint256" }
|
|
27
24
|
],
|
|
28
25
|
outputs: [{ name: "agentId", type: "uint256" }],
|
|
29
26
|
stateMutability: "nonpayable"
|
|
@@ -253,6 +250,62 @@ var EXAGENT_REGISTRY_ABI = [
|
|
|
253
250
|
outputs: [{ name: "", type: "bytes32" }],
|
|
254
251
|
stateMutability: "view"
|
|
255
252
|
},
|
|
253
|
+
// Mainnet: Agent retirement
|
|
254
|
+
{
|
|
255
|
+
type: "function",
|
|
256
|
+
name: "retireAgent",
|
|
257
|
+
inputs: [{ name: "agentId", type: "uint256" }],
|
|
258
|
+
outputs: [],
|
|
259
|
+
stateMutability: "nonpayable"
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
type: "function",
|
|
263
|
+
name: "retired",
|
|
264
|
+
inputs: [{ name: "agentId", type: "uint256" }],
|
|
265
|
+
outputs: [{ type: "bool" }],
|
|
266
|
+
stateMutability: "view"
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
type: "function",
|
|
270
|
+
name: "isRetired",
|
|
271
|
+
inputs: [{ name: "agentId", type: "uint256" }],
|
|
272
|
+
outputs: [{ type: "bool" }],
|
|
273
|
+
stateMutability: "view"
|
|
274
|
+
},
|
|
275
|
+
// Mainnet: Risk universe token whitelists
|
|
276
|
+
{
|
|
277
|
+
type: "function",
|
|
278
|
+
name: "isTradeAllowed",
|
|
279
|
+
inputs: [
|
|
280
|
+
{ name: "agentId", type: "uint256" },
|
|
281
|
+
{ name: "token", type: "address" },
|
|
282
|
+
{ name: "aggregator", type: "address" }
|
|
283
|
+
],
|
|
284
|
+
outputs: [{ type: "bool" }],
|
|
285
|
+
stateMutability: "view"
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
type: "function",
|
|
289
|
+
name: "getRiskUniverse",
|
|
290
|
+
inputs: [{ name: "agentId", type: "uint256" }],
|
|
291
|
+
outputs: [{ type: "uint8" }],
|
|
292
|
+
stateMutability: "view"
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
type: "function",
|
|
296
|
+
name: "tradeCount",
|
|
297
|
+
inputs: [{ name: "agentId", type: "uint256" }],
|
|
298
|
+
outputs: [{ type: "uint256" }],
|
|
299
|
+
stateMutability: "view"
|
|
300
|
+
},
|
|
301
|
+
// Events
|
|
302
|
+
{
|
|
303
|
+
type: "event",
|
|
304
|
+
name: "AgentRetired",
|
|
305
|
+
inputs: [
|
|
306
|
+
{ name: "agentId", type: "uint256", indexed: true }
|
|
307
|
+
]
|
|
308
|
+
},
|
|
256
309
|
{
|
|
257
310
|
type: "event",
|
|
258
311
|
name: "ConfigUpdated",
|
|
@@ -263,7 +316,16 @@ var EXAGENT_REGISTRY_ABI = [
|
|
|
263
316
|
{ name: "epochId", type: "uint256", indexed: false },
|
|
264
317
|
{ name: "blockNumber", type: "uint256", indexed: false }
|
|
265
318
|
]
|
|
266
|
-
}
|
|
319
|
+
},
|
|
320
|
+
// Custom errors
|
|
321
|
+
{ type: "error", name: "OwnerAlreadyHasAgent", inputs: [{ name: "existingAgentId", type: "uint256" }] },
|
|
322
|
+
{ type: "error", name: "InvalidMetadataURI", inputs: [] },
|
|
323
|
+
{ type: "error", name: "InvalidName", inputs: [] },
|
|
324
|
+
{ type: "error", name: "InvalidRiskUniverse", inputs: [] },
|
|
325
|
+
{ type: "error", name: "InvalidTradingConfig", inputs: [] },
|
|
326
|
+
{ type: "error", name: "NameAlreadyTaken", inputs: [] },
|
|
327
|
+
{ type: "error", name: "AgentNotOwner", inputs: [] },
|
|
328
|
+
{ type: "error", name: "AgentIsRetired", inputs: [] }
|
|
267
329
|
];
|
|
268
330
|
var ExagentRegistry = class {
|
|
269
331
|
address;
|
|
@@ -284,9 +346,12 @@ var ExagentRegistry = class {
|
|
|
284
346
|
* Register a new agent
|
|
285
347
|
* @param name Unique agent name (3-32 chars, alphanumeric + spaces/hyphens/underscores)
|
|
286
348
|
* @param metadataURI IPFS URI for agent metadata
|
|
349
|
+
* @param riskUniverse Risk tier: 0=Core, 1=Established, 2=Derivatives, 3=Emerging, 4=Frontier
|
|
350
|
+
* @param maxPositionSizeBps Maximum position size in basis points (1-10000)
|
|
351
|
+
* @param maxDailyLossBps Maximum daily loss in basis points (1-10000)
|
|
287
352
|
* @returns Transaction hash
|
|
288
353
|
*/
|
|
289
|
-
async register(name, metadataURI) {
|
|
354
|
+
async register(name, metadataURI, riskUniverse = 1, maxPositionSizeBps = 1000n, maxDailyLossBps = 500n) {
|
|
290
355
|
if (!this.walletClient || !this.account) throw new Error("Wallet client and account required for write operations");
|
|
291
356
|
const hash = await this.walletClient.writeContract({
|
|
292
357
|
account: this.account,
|
|
@@ -294,7 +359,7 @@ var ExagentRegistry = class {
|
|
|
294
359
|
address: this.address,
|
|
295
360
|
abi: EXAGENT_REGISTRY_ABI,
|
|
296
361
|
functionName: "registerAgent",
|
|
297
|
-
args: [name, metadataURI]
|
|
362
|
+
args: [name, metadataURI, riskUniverse, maxPositionSizeBps, maxDailyLossBps]
|
|
298
363
|
});
|
|
299
364
|
return hash;
|
|
300
365
|
}
|
|
@@ -485,19 +550,19 @@ var ExagentRegistry = class {
|
|
|
485
550
|
return nextId;
|
|
486
551
|
}
|
|
487
552
|
/**
|
|
488
|
-
* Generate the
|
|
489
|
-
*
|
|
490
|
-
*
|
|
553
|
+
* Generate the message hash for wallet linking.
|
|
554
|
+
* Matches the contract's keccak256(abi.encodePacked(...)) exactly.
|
|
555
|
+
* Sign the returned hash with signMessage({ raw: hash }) to produce a valid signature.
|
|
491
556
|
* @param wallet The wallet to link
|
|
492
557
|
* @param agentId The agent ID to link to
|
|
493
558
|
* @param nonce The current nonce for the wallet
|
|
494
|
-
* @returns
|
|
559
|
+
* @returns keccak256 hash of the packed message (32 bytes)
|
|
495
560
|
*/
|
|
496
561
|
static generateLinkMessage(wallet, agentId, nonce) {
|
|
497
|
-
return encodePacked(
|
|
562
|
+
return keccak256(encodePacked(
|
|
498
563
|
["string", "address", "string", "uint256", "string", "uint256"],
|
|
499
564
|
["Link wallet ", wallet, " to Exagent ", agentId, " nonce ", nonce]
|
|
500
|
-
);
|
|
565
|
+
));
|
|
501
566
|
}
|
|
502
567
|
// ============ V4: One Agent Per Wallet ============
|
|
503
568
|
/**
|
|
@@ -629,8 +694,84 @@ var ExagentRegistry = class {
|
|
|
629
694
|
* @returns keccak256 hash of the config
|
|
630
695
|
*/
|
|
631
696
|
static calculateConfigHash(provider, model) {
|
|
632
|
-
|
|
633
|
-
|
|
697
|
+
return keccak256(encodePacked(["string", "string"], [provider, model]));
|
|
698
|
+
}
|
|
699
|
+
// ============ Agent Retirement ============
|
|
700
|
+
/**
|
|
701
|
+
* Retire an agent — marks it as retired, unlinks all wallets, allows new agent registration
|
|
702
|
+
* @param agentId The agent's ID
|
|
703
|
+
* @returns Transaction hash
|
|
704
|
+
*/
|
|
705
|
+
async retireAgent(agentId) {
|
|
706
|
+
if (!this.walletClient || !this.account) throw new Error("Wallet client and account required for write operations");
|
|
707
|
+
const hash = await this.walletClient.writeContract({
|
|
708
|
+
account: this.account,
|
|
709
|
+
chain: this.chain,
|
|
710
|
+
address: this.address,
|
|
711
|
+
abi: EXAGENT_REGISTRY_ABI,
|
|
712
|
+
functionName: "retireAgent",
|
|
713
|
+
args: [agentId]
|
|
714
|
+
});
|
|
715
|
+
return hash;
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Check if an agent is retired
|
|
719
|
+
* @param agentId The agent's ID
|
|
720
|
+
* @returns True if agent is retired
|
|
721
|
+
*/
|
|
722
|
+
async isRetired(agentId) {
|
|
723
|
+
const result = await this.publicClient.readContract({
|
|
724
|
+
address: this.address,
|
|
725
|
+
abi: EXAGENT_REGISTRY_ABI,
|
|
726
|
+
functionName: "isRetired",
|
|
727
|
+
args: [agentId]
|
|
728
|
+
});
|
|
729
|
+
return result;
|
|
730
|
+
}
|
|
731
|
+
// ============ Risk Universe Token Eligibility ============
|
|
732
|
+
/**
|
|
733
|
+
* Check if a token trade is allowed for an agent's risk universe
|
|
734
|
+
* @param agentId The agent's ID
|
|
735
|
+
* @param token The token address to check
|
|
736
|
+
* @param aggregator The aggregator being used (for trusted aggregator bypass)
|
|
737
|
+
* @returns True if the trade is allowed
|
|
738
|
+
*/
|
|
739
|
+
async isTradeAllowed(agentId, token, aggregator) {
|
|
740
|
+
const result = await this.publicClient.readContract({
|
|
741
|
+
address: this.address,
|
|
742
|
+
abi: EXAGENT_REGISTRY_ABI,
|
|
743
|
+
functionName: "isTradeAllowed",
|
|
744
|
+
args: [agentId, token, aggregator]
|
|
745
|
+
});
|
|
746
|
+
return result;
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* Get the risk universe for an agent
|
|
750
|
+
* @param agentId The agent's ID
|
|
751
|
+
* @returns Risk universe (0=Core, 1=Established, 2=Derivatives, 3=Emerging, 4=Frontier)
|
|
752
|
+
*/
|
|
753
|
+
async getRiskUniverse(agentId) {
|
|
754
|
+
const result = await this.publicClient.readContract({
|
|
755
|
+
address: this.address,
|
|
756
|
+
abi: EXAGENT_REGISTRY_ABI,
|
|
757
|
+
functionName: "getRiskUniverse",
|
|
758
|
+
args: [agentId]
|
|
759
|
+
});
|
|
760
|
+
return Number(result);
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Get trade count for an agent
|
|
764
|
+
* @param agentId The agent's ID
|
|
765
|
+
* @returns Number of recorded trades
|
|
766
|
+
*/
|
|
767
|
+
async getTradeCount(agentId) {
|
|
768
|
+
const result = await this.publicClient.readContract({
|
|
769
|
+
address: this.address,
|
|
770
|
+
abi: EXAGENT_REGISTRY_ABI,
|
|
771
|
+
functionName: "tradeCount",
|
|
772
|
+
args: [agentId]
|
|
773
|
+
});
|
|
774
|
+
return result;
|
|
634
775
|
}
|
|
635
776
|
};
|
|
636
777
|
|
|
@@ -721,6 +862,9 @@ var ExagentVault = class {
|
|
|
721
862
|
this.address = vaultAddress;
|
|
722
863
|
this.publicClient = publicClient;
|
|
723
864
|
this.walletClient = walletClient;
|
|
865
|
+
if (!chain) {
|
|
866
|
+
throw new Error("Chain parameter is required");
|
|
867
|
+
}
|
|
724
868
|
this.chain = chain;
|
|
725
869
|
this.account = account;
|
|
726
870
|
}
|
|
@@ -1067,17 +1211,34 @@ var ExagentVault = class {
|
|
|
1067
1211
|
var EXAGENT_STAKING_ABI = [
|
|
1068
1212
|
// ============ State Variables ============
|
|
1069
1213
|
{ type: "function", name: "exaToken", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
|
|
1070
|
-
{ type: "function", name: "
|
|
1214
|
+
{ type: "function", name: "totalDeposited", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
1215
|
+
{ type: "function", name: "totalLocked", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
1071
1216
|
{ type: "function", name: "totalVeEXA", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
1072
|
-
{ type: "function", name: "
|
|
1217
|
+
{ type: "function", name: "totalEffectiveVeEXA", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
1073
1218
|
// ============ Constants ============
|
|
1074
1219
|
{ type: "function", name: "MIN_LOCK_DURATION", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
1075
1220
|
{ type: "function", name: "MAX_LOCK_DURATION", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
1221
|
+
{ type: "function", name: "VAULT_ACCESS_THRESHOLD", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
1076
1222
|
{ type: "function", name: "PRECISION", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
1077
|
-
// ============
|
|
1223
|
+
// ============ Phase 1: Deposit / Withdraw ============
|
|
1224
|
+
{
|
|
1225
|
+
type: "function",
|
|
1226
|
+
name: "deposit",
|
|
1227
|
+
inputs: [{ name: "amount", type: "uint256" }],
|
|
1228
|
+
outputs: [],
|
|
1229
|
+
stateMutability: "nonpayable"
|
|
1230
|
+
},
|
|
1078
1231
|
{
|
|
1079
1232
|
type: "function",
|
|
1080
|
-
name: "
|
|
1233
|
+
name: "withdraw",
|
|
1234
|
+
inputs: [{ name: "amount", type: "uint256" }],
|
|
1235
|
+
outputs: [],
|
|
1236
|
+
stateMutability: "nonpayable"
|
|
1237
|
+
},
|
|
1238
|
+
// ============ Phase 2: Lock / Unlock ============
|
|
1239
|
+
{
|
|
1240
|
+
type: "function",
|
|
1241
|
+
name: "lock",
|
|
1081
1242
|
inputs: [
|
|
1082
1243
|
{ name: "amount", type: "uint256" },
|
|
1083
1244
|
{ name: "lockDuration", type: "uint256" }
|
|
@@ -1085,7 +1246,6 @@ var EXAGENT_STAKING_ABI = [
|
|
|
1085
1246
|
outputs: [],
|
|
1086
1247
|
stateMutability: "nonpayable"
|
|
1087
1248
|
},
|
|
1088
|
-
{ type: "function", name: "unstake", inputs: [], outputs: [], stateMutability: "nonpayable" },
|
|
1089
1249
|
{
|
|
1090
1250
|
type: "function",
|
|
1091
1251
|
name: "extendLock",
|
|
@@ -1093,6 +1253,8 @@ var EXAGENT_STAKING_ABI = [
|
|
|
1093
1253
|
outputs: [],
|
|
1094
1254
|
stateMutability: "nonpayable"
|
|
1095
1255
|
},
|
|
1256
|
+
{ type: "function", name: "unlock", inputs: [], outputs: [], stateMutability: "nonpayable" },
|
|
1257
|
+
{ type: "function", name: "emergencyWithdraw", inputs: [], outputs: [], stateMutability: "nonpayable" },
|
|
1096
1258
|
// ============ Reward Functions ============
|
|
1097
1259
|
{ type: "function", name: "claimRewards", inputs: [], outputs: [], stateMutability: "nonpayable" },
|
|
1098
1260
|
{ type: "function", name: "claimRewardsMulti", inputs: [], outputs: [], stateMutability: "nonpayable" },
|
|
@@ -1103,26 +1265,17 @@ var EXAGENT_STAKING_ABI = [
|
|
|
1103
1265
|
outputs: [],
|
|
1104
1266
|
stateMutability: "nonpayable"
|
|
1105
1267
|
},
|
|
1106
|
-
// ============
|
|
1107
|
-
{
|
|
1108
|
-
type: "function",
|
|
1109
|
-
name: "delegate",
|
|
1110
|
-
inputs: [{ name: "agentId", type: "uint256" }],
|
|
1111
|
-
outputs: [],
|
|
1112
|
-
stateMutability: "nonpayable"
|
|
1113
|
-
},
|
|
1114
|
-
{ type: "function", name: "undelegate", inputs: [], outputs: [], stateMutability: "nonpayable" },
|
|
1268
|
+
// ============ View Functions ============
|
|
1115
1269
|
{
|
|
1116
1270
|
type: "function",
|
|
1117
|
-
name: "
|
|
1118
|
-
inputs: [{ name: "
|
|
1119
|
-
outputs: [],
|
|
1120
|
-
stateMutability: "
|
|
1271
|
+
name: "depositedAmount",
|
|
1272
|
+
inputs: [{ name: "user", type: "address" }],
|
|
1273
|
+
outputs: [{ type: "uint256" }],
|
|
1274
|
+
stateMutability: "view"
|
|
1121
1275
|
},
|
|
1122
|
-
// ============ View Functions ============
|
|
1123
1276
|
{
|
|
1124
1277
|
type: "function",
|
|
1125
|
-
name: "
|
|
1278
|
+
name: "locks",
|
|
1126
1279
|
inputs: [{ name: "user", type: "address" }],
|
|
1127
1280
|
outputs: [
|
|
1128
1281
|
{ name: "amount", type: "uint256" },
|
|
@@ -1139,6 +1292,13 @@ var EXAGENT_STAKING_ABI = [
|
|
|
1139
1292
|
outputs: [{ type: "uint256" }],
|
|
1140
1293
|
stateMutability: "view"
|
|
1141
1294
|
},
|
|
1295
|
+
{
|
|
1296
|
+
type: "function",
|
|
1297
|
+
name: "getEffectiveVeEXA",
|
|
1298
|
+
inputs: [{ name: "user", type: "address" }],
|
|
1299
|
+
outputs: [{ type: "uint256" }],
|
|
1300
|
+
stateMutability: "view"
|
|
1301
|
+
},
|
|
1142
1302
|
{
|
|
1143
1303
|
type: "function",
|
|
1144
1304
|
name: "calculateVeEXA",
|
|
@@ -1168,61 +1328,40 @@ var EXAGENT_STAKING_ABI = [
|
|
|
1168
1328
|
},
|
|
1169
1329
|
{
|
|
1170
1330
|
type: "function",
|
|
1171
|
-
name: "
|
|
1331
|
+
name: "getEarningsTier",
|
|
1172
1332
|
inputs: [{ name: "user", type: "address" }],
|
|
1173
|
-
outputs: [{ type: "uint256" }],
|
|
1174
|
-
stateMutability: "view"
|
|
1175
|
-
},
|
|
1176
|
-
{
|
|
1177
|
-
type: "function",
|
|
1178
|
-
name: "getAgentDelegation",
|
|
1179
|
-
inputs: [{ name: "agentId", type: "uint256" }],
|
|
1180
1333
|
outputs: [
|
|
1181
|
-
{ name: "
|
|
1182
|
-
{ name: "
|
|
1334
|
+
{ name: "multiplierBps", type: "uint256" },
|
|
1335
|
+
{ name: "tierName", type: "string" }
|
|
1183
1336
|
],
|
|
1184
1337
|
stateMutability: "view"
|
|
1185
1338
|
},
|
|
1186
1339
|
{
|
|
1187
1340
|
type: "function",
|
|
1188
|
-
name: "
|
|
1341
|
+
name: "getEmergencyWithdrawPenalty",
|
|
1189
1342
|
inputs: [{ name: "user", type: "address" }],
|
|
1190
|
-
outputs: [{ name: "
|
|
1343
|
+
outputs: [{ name: "penaltyBps", type: "uint256" }],
|
|
1191
1344
|
stateMutability: "view"
|
|
1192
1345
|
},
|
|
1193
1346
|
{
|
|
1194
1347
|
type: "function",
|
|
1195
|
-
name: "
|
|
1196
|
-
inputs: [],
|
|
1197
|
-
outputs: [{ type: "address[]" }],
|
|
1198
|
-
stateMutability: "view"
|
|
1199
|
-
},
|
|
1200
|
-
{
|
|
1201
|
-
type: "function",
|
|
1202
|
-
name: "delegatedTo",
|
|
1348
|
+
name: "hasVaultAccess",
|
|
1203
1349
|
inputs: [{ name: "user", type: "address" }],
|
|
1204
|
-
outputs: [{ type: "
|
|
1350
|
+
outputs: [{ type: "bool" }],
|
|
1205
1351
|
stateMutability: "view"
|
|
1206
1352
|
},
|
|
1207
1353
|
{
|
|
1208
1354
|
type: "function",
|
|
1209
|
-
name: "
|
|
1355
|
+
name: "getUnlockedBalance",
|
|
1210
1356
|
inputs: [{ name: "user", type: "address" }],
|
|
1211
1357
|
outputs: [{ type: "uint256" }],
|
|
1212
1358
|
stateMutability: "view"
|
|
1213
1359
|
},
|
|
1214
1360
|
{
|
|
1215
1361
|
type: "function",
|
|
1216
|
-
name: "
|
|
1217
|
-
inputs: [
|
|
1218
|
-
outputs: [{ type: "
|
|
1219
|
-
stateMutability: "view"
|
|
1220
|
-
},
|
|
1221
|
-
{
|
|
1222
|
-
type: "function",
|
|
1223
|
-
name: "agentDelegatorCount",
|
|
1224
|
-
inputs: [{ name: "agentId", type: "uint256" }],
|
|
1225
|
-
outputs: [{ type: "uint256" }],
|
|
1362
|
+
name: "getRewardTokens",
|
|
1363
|
+
inputs: [],
|
|
1364
|
+
outputs: [{ type: "address[]" }],
|
|
1226
1365
|
stateMutability: "view"
|
|
1227
1366
|
},
|
|
1228
1367
|
{
|
|
@@ -1235,35 +1374,36 @@ var EXAGENT_STAKING_ABI = [
|
|
|
1235
1374
|
// ============ Events ============
|
|
1236
1375
|
{
|
|
1237
1376
|
type: "event",
|
|
1238
|
-
name: "
|
|
1377
|
+
name: "Deposited",
|
|
1239
1378
|
inputs: [
|
|
1240
1379
|
{ name: "user", type: "address", indexed: true },
|
|
1241
1380
|
{ name: "amount", type: "uint256", indexed: false },
|
|
1242
|
-
{ name: "
|
|
1243
|
-
{ name: "unlockTime", type: "uint256", indexed: false },
|
|
1244
|
-
{ name: "vEXABalance", type: "uint256", indexed: false }
|
|
1381
|
+
{ name: "totalDeposited", type: "uint256", indexed: false }
|
|
1245
1382
|
]
|
|
1246
1383
|
},
|
|
1247
1384
|
{
|
|
1248
1385
|
type: "event",
|
|
1249
|
-
name: "
|
|
1386
|
+
name: "Withdrawn",
|
|
1250
1387
|
inputs: [
|
|
1251
1388
|
{ name: "user", type: "address", indexed: true },
|
|
1252
|
-
{ name: "amount", type: "uint256", indexed: false }
|
|
1389
|
+
{ name: "amount", type: "uint256", indexed: false },
|
|
1390
|
+
{ name: "totalDeposited", type: "uint256", indexed: false }
|
|
1253
1391
|
]
|
|
1254
1392
|
},
|
|
1255
1393
|
{
|
|
1256
1394
|
type: "event",
|
|
1257
|
-
name: "
|
|
1395
|
+
name: "Locked",
|
|
1258
1396
|
inputs: [
|
|
1259
1397
|
{ name: "user", type: "address", indexed: true },
|
|
1260
|
-
{ name: "
|
|
1261
|
-
{ name: "
|
|
1398
|
+
{ name: "amount", type: "uint256", indexed: false },
|
|
1399
|
+
{ name: "lockDuration", type: "uint256", indexed: false },
|
|
1400
|
+
{ name: "unlockTime", type: "uint256", indexed: false },
|
|
1401
|
+
{ name: "vEXABalance", type: "uint256", indexed: false }
|
|
1262
1402
|
]
|
|
1263
1403
|
},
|
|
1264
1404
|
{
|
|
1265
1405
|
type: "event",
|
|
1266
|
-
name: "
|
|
1406
|
+
name: "Unlocked",
|
|
1267
1407
|
inputs: [
|
|
1268
1408
|
{ name: "user", type: "address", indexed: true },
|
|
1269
1409
|
{ name: "amount", type: "uint256", indexed: false }
|
|
@@ -1271,20 +1411,29 @@ var EXAGENT_STAKING_ABI = [
|
|
|
1271
1411
|
},
|
|
1272
1412
|
{
|
|
1273
1413
|
type: "event",
|
|
1274
|
-
name: "
|
|
1414
|
+
name: "EmergencyWithdrawal",
|
|
1275
1415
|
inputs: [
|
|
1276
|
-
{ name: "
|
|
1277
|
-
{ name: "
|
|
1278
|
-
{ name: "
|
|
1416
|
+
{ name: "user", type: "address", indexed: true },
|
|
1417
|
+
{ name: "returned", type: "uint256", indexed: false },
|
|
1418
|
+
{ name: "penalty", type: "uint256", indexed: false },
|
|
1419
|
+
{ name: "penaltyBps", type: "uint256", indexed: false }
|
|
1279
1420
|
]
|
|
1280
1421
|
},
|
|
1281
1422
|
{
|
|
1282
1423
|
type: "event",
|
|
1283
|
-
name: "
|
|
1424
|
+
name: "LockExtended",
|
|
1284
1425
|
inputs: [
|
|
1285
|
-
{ name: "
|
|
1286
|
-
{ name: "
|
|
1287
|
-
{ name: "
|
|
1426
|
+
{ name: "user", type: "address", indexed: true },
|
|
1427
|
+
{ name: "newUnlockTime", type: "uint256", indexed: false },
|
|
1428
|
+
{ name: "newVeEXABalance", type: "uint256", indexed: false }
|
|
1429
|
+
]
|
|
1430
|
+
},
|
|
1431
|
+
{
|
|
1432
|
+
type: "event",
|
|
1433
|
+
name: "RewardsClaimed",
|
|
1434
|
+
inputs: [
|
|
1435
|
+
{ name: "user", type: "address", indexed: true },
|
|
1436
|
+
{ name: "amount", type: "uint256", indexed: false }
|
|
1288
1437
|
]
|
|
1289
1438
|
},
|
|
1290
1439
|
{
|
|
@@ -1309,15 +1458,6 @@ var ERC20_APPROVE_ABI2 = [
|
|
|
1309
1458
|
stateMutability: "nonpayable"
|
|
1310
1459
|
}
|
|
1311
1460
|
];
|
|
1312
|
-
var DISCOUNT_TIERS = {
|
|
1313
|
-
none: 0,
|
|
1314
|
-
bronze: 1e3,
|
|
1315
|
-
// 10% discount at 10,000 vEXA
|
|
1316
|
-
silver: 2500,
|
|
1317
|
-
// 25% discount at 50,000 vEXA
|
|
1318
|
-
gold: 5e3
|
|
1319
|
-
// 50% discount at 100,000 vEXA
|
|
1320
|
-
};
|
|
1321
1461
|
var ExagentStaking = class {
|
|
1322
1462
|
address;
|
|
1323
1463
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -1330,108 +1470,119 @@ var ExagentStaking = class {
|
|
|
1330
1470
|
this.address = stakingAddress;
|
|
1331
1471
|
this.publicClient = publicClient;
|
|
1332
1472
|
this.walletClient = walletClient;
|
|
1473
|
+
if (!chain) {
|
|
1474
|
+
throw new Error("Chain parameter is required");
|
|
1475
|
+
}
|
|
1333
1476
|
this.chain = chain;
|
|
1334
1477
|
this.account = account;
|
|
1335
1478
|
}
|
|
1336
|
-
// ============
|
|
1479
|
+
// ============ Phase 1: Deposit / Withdraw ============
|
|
1337
1480
|
/**
|
|
1338
|
-
*
|
|
1339
|
-
* @param amount Amount of EXA to
|
|
1340
|
-
* @param lockDuration Lock duration in seconds (30 days to 2 years)
|
|
1481
|
+
* Deposit EXA tokens for vault access (no lock required)
|
|
1482
|
+
* @param amount Amount of EXA to deposit (in wei)
|
|
1341
1483
|
* @returns Transaction hash
|
|
1342
1484
|
*
|
|
1343
1485
|
* @example
|
|
1344
1486
|
* ```typescript
|
|
1345
|
-
* //
|
|
1346
|
-
* const tx = await staking.
|
|
1347
|
-
* parseEther('1000'),
|
|
1348
|
-
* BigInt(180 * 24 * 60 * 60) // 180 days in seconds
|
|
1349
|
-
* );
|
|
1487
|
+
* // Deposit 1000 EXA to unlock vault access
|
|
1488
|
+
* const tx = await staking.deposit(parseEther('1000'));
|
|
1350
1489
|
* ```
|
|
1351
1490
|
*/
|
|
1352
|
-
async
|
|
1491
|
+
async deposit(amount) {
|
|
1353
1492
|
if (!this.walletClient || !this.account) {
|
|
1354
1493
|
throw new Error("Wallet client required for write operations");
|
|
1355
1494
|
}
|
|
1356
1495
|
const hash = await this.walletClient.writeContract({
|
|
1357
1496
|
address: this.address,
|
|
1358
1497
|
abi: EXAGENT_STAKING_ABI,
|
|
1359
|
-
functionName: "
|
|
1360
|
-
args: [amount
|
|
1498
|
+
functionName: "deposit",
|
|
1499
|
+
args: [amount],
|
|
1361
1500
|
account: this.account,
|
|
1362
1501
|
chain: this.chain
|
|
1363
1502
|
});
|
|
1364
1503
|
return hash;
|
|
1365
1504
|
}
|
|
1366
1505
|
/**
|
|
1367
|
-
*
|
|
1506
|
+
* Withdraw unlocked EXA tokens (instant, no penalty)
|
|
1507
|
+
* @param amount Amount of EXA to withdraw (in wei)
|
|
1368
1508
|
* @returns Transaction hash
|
|
1369
|
-
* @throws Error if lock has not expired
|
|
1370
1509
|
*/
|
|
1371
|
-
async
|
|
1510
|
+
async withdraw(amount) {
|
|
1372
1511
|
if (!this.walletClient || !this.account) {
|
|
1373
1512
|
throw new Error("Wallet client required for write operations");
|
|
1374
1513
|
}
|
|
1375
1514
|
const hash = await this.walletClient.writeContract({
|
|
1376
1515
|
address: this.address,
|
|
1377
1516
|
abi: EXAGENT_STAKING_ABI,
|
|
1378
|
-
functionName: "
|
|
1379
|
-
args: [],
|
|
1517
|
+
functionName: "withdraw",
|
|
1518
|
+
args: [amount],
|
|
1380
1519
|
account: this.account,
|
|
1381
1520
|
chain: this.chain
|
|
1382
1521
|
});
|
|
1383
1522
|
return hash;
|
|
1384
1523
|
}
|
|
1524
|
+
// ============ Phase 2: Lock / Unlock ============
|
|
1385
1525
|
/**
|
|
1386
|
-
*
|
|
1387
|
-
* @param
|
|
1526
|
+
* Lock deposited EXA to receive vEXA voting power and earn rewards
|
|
1527
|
+
* @param amount Amount of deposited EXA to lock (in wei)
|
|
1528
|
+
* @param lockDuration Lock duration in seconds (30 days to 2 years)
|
|
1388
1529
|
* @returns Transaction hash
|
|
1530
|
+
*
|
|
1531
|
+
* @example
|
|
1532
|
+
* ```typescript
|
|
1533
|
+
* // Lock 1000 EXA for 6 months
|
|
1534
|
+
* const tx = await staking.lock(
|
|
1535
|
+
* parseEther('1000'),
|
|
1536
|
+
* ExagentStaking.LOCK_6_MONTHS
|
|
1537
|
+
* );
|
|
1538
|
+
* ```
|
|
1389
1539
|
*/
|
|
1390
|
-
async
|
|
1540
|
+
async lock(amount, lockDuration) {
|
|
1391
1541
|
if (!this.walletClient || !this.account) {
|
|
1392
1542
|
throw new Error("Wallet client required for write operations");
|
|
1393
1543
|
}
|
|
1394
1544
|
const hash = await this.walletClient.writeContract({
|
|
1395
1545
|
address: this.address,
|
|
1396
1546
|
abi: EXAGENT_STAKING_ABI,
|
|
1397
|
-
functionName: "
|
|
1398
|
-
args: [
|
|
1547
|
+
functionName: "lock",
|
|
1548
|
+
args: [amount, lockDuration],
|
|
1399
1549
|
account: this.account,
|
|
1400
1550
|
chain: this.chain
|
|
1401
1551
|
});
|
|
1402
1552
|
return hash;
|
|
1403
1553
|
}
|
|
1404
|
-
// ============ Reward Write Functions ============
|
|
1405
1554
|
/**
|
|
1406
|
-
*
|
|
1555
|
+
* Extend lock duration for additional voting power
|
|
1556
|
+
* @param newLockDuration New lock duration in seconds (must be longer than remaining)
|
|
1407
1557
|
* @returns Transaction hash
|
|
1408
1558
|
*/
|
|
1409
|
-
async
|
|
1559
|
+
async extendLock(newLockDuration) {
|
|
1410
1560
|
if (!this.walletClient || !this.account) {
|
|
1411
1561
|
throw new Error("Wallet client required for write operations");
|
|
1412
1562
|
}
|
|
1413
1563
|
const hash = await this.walletClient.writeContract({
|
|
1414
1564
|
address: this.address,
|
|
1415
1565
|
abi: EXAGENT_STAKING_ABI,
|
|
1416
|
-
functionName: "
|
|
1417
|
-
args: [],
|
|
1566
|
+
functionName: "extendLock",
|
|
1567
|
+
args: [newLockDuration],
|
|
1418
1568
|
account: this.account,
|
|
1419
1569
|
chain: this.chain
|
|
1420
1570
|
});
|
|
1421
1571
|
return hash;
|
|
1422
1572
|
}
|
|
1423
1573
|
/**
|
|
1424
|
-
*
|
|
1574
|
+
* Unlock EXA after lock expires (normal path — no penalty)
|
|
1575
|
+
* Returns locked amount to unlocked deposited balance.
|
|
1425
1576
|
* @returns Transaction hash
|
|
1426
1577
|
*/
|
|
1427
|
-
async
|
|
1578
|
+
async unlock() {
|
|
1428
1579
|
if (!this.walletClient || !this.account) {
|
|
1429
1580
|
throw new Error("Wallet client required for write operations");
|
|
1430
1581
|
}
|
|
1431
1582
|
const hash = await this.walletClient.writeContract({
|
|
1432
1583
|
address: this.address,
|
|
1433
1584
|
abi: EXAGENT_STAKING_ABI,
|
|
1434
|
-
functionName: "
|
|
1585
|
+
functionName: "unlock",
|
|
1435
1586
|
args: [],
|
|
1436
1587
|
account: this.account,
|
|
1437
1588
|
chain: this.chain
|
|
@@ -1439,56 +1590,56 @@ var ExagentStaking = class {
|
|
|
1439
1590
|
return hash;
|
|
1440
1591
|
}
|
|
1441
1592
|
/**
|
|
1442
|
-
*
|
|
1443
|
-
*
|
|
1593
|
+
* Emergency withdrawal — instant exit from lock with graduated penalty
|
|
1594
|
+
* Two-phase penalty: 50%→20% over the first quarter of the lock, then flat 20% until expiry.
|
|
1595
|
+
* Penalty goes to treasury. Remaining returns to unlocked deposit balance.
|
|
1444
1596
|
* @returns Transaction hash
|
|
1445
1597
|
*/
|
|
1446
|
-
async
|
|
1598
|
+
async emergencyWithdraw() {
|
|
1447
1599
|
if (!this.walletClient || !this.account) {
|
|
1448
1600
|
throw new Error("Wallet client required for write operations");
|
|
1449
1601
|
}
|
|
1450
1602
|
const hash = await this.walletClient.writeContract({
|
|
1451
1603
|
address: this.address,
|
|
1452
1604
|
abi: EXAGENT_STAKING_ABI,
|
|
1453
|
-
functionName: "
|
|
1454
|
-
args: [
|
|
1605
|
+
functionName: "emergencyWithdraw",
|
|
1606
|
+
args: [],
|
|
1455
1607
|
account: this.account,
|
|
1456
1608
|
chain: this.chain
|
|
1457
1609
|
});
|
|
1458
1610
|
return hash;
|
|
1459
1611
|
}
|
|
1460
|
-
// ============
|
|
1612
|
+
// ============ Reward Functions ============
|
|
1461
1613
|
/**
|
|
1462
|
-
*
|
|
1463
|
-
* @param agentId The agent ID to delegate to
|
|
1614
|
+
* Claim accumulated EXA rewards
|
|
1464
1615
|
* @returns Transaction hash
|
|
1465
1616
|
*/
|
|
1466
|
-
async
|
|
1617
|
+
async claimRewards() {
|
|
1467
1618
|
if (!this.walletClient || !this.account) {
|
|
1468
1619
|
throw new Error("Wallet client required for write operations");
|
|
1469
1620
|
}
|
|
1470
1621
|
const hash = await this.walletClient.writeContract({
|
|
1471
1622
|
address: this.address,
|
|
1472
1623
|
abi: EXAGENT_STAKING_ABI,
|
|
1473
|
-
functionName: "
|
|
1474
|
-
args: [
|
|
1624
|
+
functionName: "claimRewards",
|
|
1625
|
+
args: [],
|
|
1475
1626
|
account: this.account,
|
|
1476
1627
|
chain: this.chain
|
|
1477
1628
|
});
|
|
1478
1629
|
return hash;
|
|
1479
1630
|
}
|
|
1480
1631
|
/**
|
|
1481
|
-
*
|
|
1632
|
+
* Claim all pending multi-token rewards (ETH, USDC, etc.)
|
|
1482
1633
|
* @returns Transaction hash
|
|
1483
1634
|
*/
|
|
1484
|
-
async
|
|
1635
|
+
async claimRewardsMulti() {
|
|
1485
1636
|
if (!this.walletClient || !this.account) {
|
|
1486
1637
|
throw new Error("Wallet client required for write operations");
|
|
1487
1638
|
}
|
|
1488
1639
|
const hash = await this.walletClient.writeContract({
|
|
1489
1640
|
address: this.address,
|
|
1490
1641
|
abi: EXAGENT_STAKING_ABI,
|
|
1491
|
-
functionName: "
|
|
1642
|
+
functionName: "claimRewardsMulti",
|
|
1492
1643
|
args: [],
|
|
1493
1644
|
account: this.account,
|
|
1494
1645
|
chain: this.chain
|
|
@@ -1496,19 +1647,19 @@ var ExagentStaking = class {
|
|
|
1496
1647
|
return hash;
|
|
1497
1648
|
}
|
|
1498
1649
|
/**
|
|
1499
|
-
*
|
|
1500
|
-
* @param
|
|
1650
|
+
* Claim pending rewards for a specific token
|
|
1651
|
+
* @param token The reward token address to claim
|
|
1501
1652
|
* @returns Transaction hash
|
|
1502
1653
|
*/
|
|
1503
|
-
async
|
|
1654
|
+
async claimRewardsToken(token) {
|
|
1504
1655
|
if (!this.walletClient || !this.account) {
|
|
1505
1656
|
throw new Error("Wallet client required for write operations");
|
|
1506
1657
|
}
|
|
1507
1658
|
const hash = await this.walletClient.writeContract({
|
|
1508
1659
|
address: this.address,
|
|
1509
1660
|
abi: EXAGENT_STAKING_ABI,
|
|
1510
|
-
functionName: "
|
|
1511
|
-
args: [
|
|
1661
|
+
functionName: "claimRewardsToken",
|
|
1662
|
+
args: [token],
|
|
1512
1663
|
account: this.account,
|
|
1513
1664
|
chain: this.chain
|
|
1514
1665
|
});
|
|
@@ -1516,20 +1667,26 @@ var ExagentStaking = class {
|
|
|
1516
1667
|
}
|
|
1517
1668
|
// ============ Read Functions ============
|
|
1518
1669
|
/**
|
|
1519
|
-
* Get comprehensive staking info for a user
|
|
1670
|
+
* Get comprehensive staking info for a user (deposit + lock)
|
|
1520
1671
|
* @param userAddress Address to check (defaults to connected wallet)
|
|
1521
|
-
* @returns
|
|
1672
|
+
* @returns Combined staking info
|
|
1522
1673
|
*/
|
|
1523
|
-
async
|
|
1674
|
+
async getStakingInfo(userAddress) {
|
|
1524
1675
|
const user = userAddress ?? this.account?.address;
|
|
1525
1676
|
if (!user) {
|
|
1526
1677
|
throw new Error("User address required");
|
|
1527
1678
|
}
|
|
1528
|
-
const [
|
|
1679
|
+
const [deposited, lockResult, currentVeEXA, vaultAccess, unlockedBalance] = await Promise.all([
|
|
1680
|
+
this.publicClient.readContract({
|
|
1681
|
+
address: this.address,
|
|
1682
|
+
abi: EXAGENT_STAKING_ABI,
|
|
1683
|
+
functionName: "depositedAmount",
|
|
1684
|
+
args: [user]
|
|
1685
|
+
}),
|
|
1529
1686
|
this.publicClient.readContract({
|
|
1530
1687
|
address: this.address,
|
|
1531
1688
|
abi: EXAGENT_STAKING_ABI,
|
|
1532
|
-
functionName: "
|
|
1689
|
+
functionName: "locks",
|
|
1533
1690
|
args: [user]
|
|
1534
1691
|
}),
|
|
1535
1692
|
this.publicClient.readContract({
|
|
@@ -1537,20 +1694,88 @@ var ExagentStaking = class {
|
|
|
1537
1694
|
abi: EXAGENT_STAKING_ABI,
|
|
1538
1695
|
functionName: "getVeEXABalance",
|
|
1539
1696
|
args: [user]
|
|
1697
|
+
}),
|
|
1698
|
+
this.publicClient.readContract({
|
|
1699
|
+
address: this.address,
|
|
1700
|
+
abi: EXAGENT_STAKING_ABI,
|
|
1701
|
+
functionName: "hasVaultAccess",
|
|
1702
|
+
args: [user]
|
|
1703
|
+
}),
|
|
1704
|
+
this.publicClient.readContract({
|
|
1705
|
+
address: this.address,
|
|
1706
|
+
abi: EXAGENT_STAKING_ABI,
|
|
1707
|
+
functionName: "getUnlockedBalance",
|
|
1708
|
+
args: [user]
|
|
1540
1709
|
})
|
|
1541
1710
|
]);
|
|
1542
|
-
const
|
|
1711
|
+
const lockData = lockResult;
|
|
1712
|
+
const depositedBigint = deposited;
|
|
1713
|
+
const lockedAmount = lockData[0];
|
|
1543
1714
|
const now = BigInt(Math.floor(Date.now() / 1e3));
|
|
1544
|
-
const
|
|
1545
|
-
|
|
1715
|
+
const depositInfo = {
|
|
1716
|
+
deposited: depositedBigint,
|
|
1717
|
+
locked: lockedAmount,
|
|
1718
|
+
unlocked: unlockedBalance,
|
|
1719
|
+
hasVaultAccess: vaultAccess
|
|
1720
|
+
};
|
|
1721
|
+
let lockInfo = null;
|
|
1722
|
+
if (lockedAmount > 0n) {
|
|
1723
|
+
const isUnlocked = lockData[1] <= now;
|
|
1724
|
+
const remainingLockTime = isUnlocked ? 0n : lockData[1] - now;
|
|
1725
|
+
lockInfo = {
|
|
1726
|
+
amount: lockData[0],
|
|
1727
|
+
unlockTime: lockData[1],
|
|
1728
|
+
lockDuration: lockData[2],
|
|
1729
|
+
vEXABalance: lockData[3],
|
|
1730
|
+
currentVeEXA,
|
|
1731
|
+
isUnlocked,
|
|
1732
|
+
remainingLockTime
|
|
1733
|
+
};
|
|
1734
|
+
}
|
|
1735
|
+
return { deposit: depositInfo, lock: lockInfo };
|
|
1736
|
+
}
|
|
1737
|
+
/**
|
|
1738
|
+
* Get deposit info for a user
|
|
1739
|
+
* @param userAddress Address to check (defaults to connected wallet)
|
|
1740
|
+
* @returns Deposit info
|
|
1741
|
+
*/
|
|
1742
|
+
async getDepositInfo(userAddress) {
|
|
1743
|
+
const user = userAddress ?? this.account?.address;
|
|
1744
|
+
if (!user) {
|
|
1745
|
+
throw new Error("User address required");
|
|
1746
|
+
}
|
|
1747
|
+
const [deposited, lockResult, vaultAccess, unlockedBalance] = await Promise.all([
|
|
1748
|
+
this.publicClient.readContract({
|
|
1749
|
+
address: this.address,
|
|
1750
|
+
abi: EXAGENT_STAKING_ABI,
|
|
1751
|
+
functionName: "depositedAmount",
|
|
1752
|
+
args: [user]
|
|
1753
|
+
}),
|
|
1754
|
+
this.publicClient.readContract({
|
|
1755
|
+
address: this.address,
|
|
1756
|
+
abi: EXAGENT_STAKING_ABI,
|
|
1757
|
+
functionName: "locks",
|
|
1758
|
+
args: [user]
|
|
1759
|
+
}),
|
|
1760
|
+
this.publicClient.readContract({
|
|
1761
|
+
address: this.address,
|
|
1762
|
+
abi: EXAGENT_STAKING_ABI,
|
|
1763
|
+
functionName: "hasVaultAccess",
|
|
1764
|
+
args: [user]
|
|
1765
|
+
}),
|
|
1766
|
+
this.publicClient.readContract({
|
|
1767
|
+
address: this.address,
|
|
1768
|
+
abi: EXAGENT_STAKING_ABI,
|
|
1769
|
+
functionName: "getUnlockedBalance",
|
|
1770
|
+
args: [user]
|
|
1771
|
+
})
|
|
1772
|
+
]);
|
|
1773
|
+
const lockData = lockResult;
|
|
1546
1774
|
return {
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
currentVeEXA,
|
|
1552
|
-
isUnlocked,
|
|
1553
|
-
remainingLockTime
|
|
1775
|
+
deposited,
|
|
1776
|
+
locked: lockData[0],
|
|
1777
|
+
unlocked: unlockedBalance,
|
|
1778
|
+
hasVaultAccess: vaultAccess
|
|
1554
1779
|
};
|
|
1555
1780
|
}
|
|
1556
1781
|
/**
|
|
@@ -1571,11 +1796,11 @@ var ExagentStaking = class {
|
|
|
1571
1796
|
});
|
|
1572
1797
|
}
|
|
1573
1798
|
/**
|
|
1574
|
-
* Get
|
|
1799
|
+
* Get effective vEXA (with tier multiplier applied)
|
|
1575
1800
|
* @param userAddress Address to check (defaults to connected wallet)
|
|
1576
|
-
* @returns
|
|
1801
|
+
* @returns Effective vEXA balance
|
|
1577
1802
|
*/
|
|
1578
|
-
async
|
|
1803
|
+
async getEffectiveVeEXA(userAddress) {
|
|
1579
1804
|
const user = userAddress ?? this.account?.address;
|
|
1580
1805
|
if (!user) {
|
|
1581
1806
|
throw new Error("User address required");
|
|
@@ -1583,52 +1808,64 @@ var ExagentStaking = class {
|
|
|
1583
1808
|
return this.publicClient.readContract({
|
|
1584
1809
|
address: this.address,
|
|
1585
1810
|
abi: EXAGENT_STAKING_ABI,
|
|
1586
|
-
functionName: "
|
|
1811
|
+
functionName: "getEffectiveVeEXA",
|
|
1587
1812
|
args: [user]
|
|
1588
1813
|
});
|
|
1589
1814
|
}
|
|
1590
1815
|
/**
|
|
1591
|
-
*
|
|
1592
|
-
* @param
|
|
1593
|
-
* @returns
|
|
1816
|
+
* Check if user has vault access (meets deposit threshold)
|
|
1817
|
+
* @param userAddress Address to check (defaults to connected wallet)
|
|
1818
|
+
* @returns True if user can access vaults
|
|
1594
1819
|
*/
|
|
1595
|
-
async
|
|
1820
|
+
async hasVaultAccess(userAddress) {
|
|
1821
|
+
const user = userAddress ?? this.account?.address;
|
|
1822
|
+
if (!user) {
|
|
1823
|
+
throw new Error("User address required");
|
|
1824
|
+
}
|
|
1825
|
+
return this.publicClient.readContract({
|
|
1826
|
+
address: this.address,
|
|
1827
|
+
abi: EXAGENT_STAKING_ABI,
|
|
1828
|
+
functionName: "hasVaultAccess",
|
|
1829
|
+
args: [user]
|
|
1830
|
+
});
|
|
1831
|
+
}
|
|
1832
|
+
/**
|
|
1833
|
+
* Get earnings tier for a user (Bronze/Silver/Gold/Platinum/Diamond)
|
|
1834
|
+
* @param userAddress Address to check (defaults to connected wallet)
|
|
1835
|
+
* @returns Tier info with multiplier and name
|
|
1836
|
+
*/
|
|
1837
|
+
async getEarningsTier(userAddress) {
|
|
1838
|
+
const user = userAddress ?? this.account?.address;
|
|
1839
|
+
if (!user) {
|
|
1840
|
+
throw new Error("User address required");
|
|
1841
|
+
}
|
|
1596
1842
|
const result = await this.publicClient.readContract({
|
|
1597
1843
|
address: this.address,
|
|
1598
1844
|
abi: EXAGENT_STAKING_ABI,
|
|
1599
|
-
functionName: "
|
|
1600
|
-
args: [
|
|
1845
|
+
functionName: "getEarningsTier",
|
|
1846
|
+
args: [user]
|
|
1601
1847
|
});
|
|
1602
1848
|
return {
|
|
1603
|
-
|
|
1604
|
-
|
|
1849
|
+
multiplierBps: result[0],
|
|
1850
|
+
tierName: result[1]
|
|
1605
1851
|
};
|
|
1606
1852
|
}
|
|
1607
1853
|
/**
|
|
1608
|
-
* Get
|
|
1854
|
+
* Get current emergency withdrawal penalty for a user
|
|
1609
1855
|
* @param userAddress Address to check (defaults to connected wallet)
|
|
1610
|
-
* @returns
|
|
1856
|
+
* @returns Penalty in basis points (5000 = 50% at lock start, ramps to 2000 over first 25% of lock, then flat 2000)
|
|
1611
1857
|
*/
|
|
1612
|
-
async
|
|
1858
|
+
async getEmergencyWithdrawPenalty(userAddress) {
|
|
1613
1859
|
const user = userAddress ?? this.account?.address;
|
|
1614
1860
|
if (!user) {
|
|
1615
1861
|
throw new Error("User address required");
|
|
1616
1862
|
}
|
|
1617
|
-
|
|
1863
|
+
return this.publicClient.readContract({
|
|
1618
1864
|
address: this.address,
|
|
1619
1865
|
abi: EXAGENT_STAKING_ABI,
|
|
1620
|
-
functionName: "
|
|
1866
|
+
functionName: "getEmergencyWithdrawPenalty",
|
|
1621
1867
|
args: [user]
|
|
1622
1868
|
});
|
|
1623
|
-
let tier = "none";
|
|
1624
|
-
if (discountBps >= 5000n) {
|
|
1625
|
-
tier = "gold";
|
|
1626
|
-
} else if (discountBps >= 2500n) {
|
|
1627
|
-
tier = "silver";
|
|
1628
|
-
} else if (discountBps >= 1000n) {
|
|
1629
|
-
tier = "bronze";
|
|
1630
|
-
}
|
|
1631
|
-
return { tier, discountBps };
|
|
1632
1869
|
}
|
|
1633
1870
|
/**
|
|
1634
1871
|
* Get pending EXA rewards for a user
|
|
@@ -1690,14 +1927,25 @@ var ExagentStaking = class {
|
|
|
1690
1927
|
});
|
|
1691
1928
|
}
|
|
1692
1929
|
/**
|
|
1693
|
-
* Get total
|
|
1694
|
-
* @returns Total
|
|
1930
|
+
* Get total EXA deposited across all users
|
|
1931
|
+
* @returns Total deposited amount in wei
|
|
1695
1932
|
*/
|
|
1696
|
-
async
|
|
1933
|
+
async getTotalDeposited() {
|
|
1697
1934
|
return this.publicClient.readContract({
|
|
1698
1935
|
address: this.address,
|
|
1699
1936
|
abi: EXAGENT_STAKING_ABI,
|
|
1700
|
-
functionName: "
|
|
1937
|
+
functionName: "totalDeposited"
|
|
1938
|
+
});
|
|
1939
|
+
}
|
|
1940
|
+
/**
|
|
1941
|
+
* Get total EXA locked across all users
|
|
1942
|
+
* @returns Total locked amount in wei
|
|
1943
|
+
*/
|
|
1944
|
+
async getTotalLocked() {
|
|
1945
|
+
return this.publicClient.readContract({
|
|
1946
|
+
address: this.address,
|
|
1947
|
+
abi: EXAGENT_STAKING_ABI,
|
|
1948
|
+
functionName: "totalLocked"
|
|
1701
1949
|
});
|
|
1702
1950
|
}
|
|
1703
1951
|
/**
|
|
@@ -1712,8 +1960,8 @@ var ExagentStaking = class {
|
|
|
1712
1960
|
});
|
|
1713
1961
|
}
|
|
1714
1962
|
/**
|
|
1715
|
-
* Calculate vEXA balance for a given
|
|
1716
|
-
* @param amount Amount of EXA to
|
|
1963
|
+
* Calculate vEXA balance for a given lock (preview)
|
|
1964
|
+
* @param amount Amount of EXA to lock
|
|
1717
1965
|
* @param lockDuration Lock duration in seconds
|
|
1718
1966
|
* @returns Expected vEXA balance
|
|
1719
1967
|
*/
|
|
@@ -1738,7 +1986,7 @@ var ExagentStaking = class {
|
|
|
1738
1986
|
}
|
|
1739
1987
|
// ============ Helper Functions ============
|
|
1740
1988
|
/**
|
|
1741
|
-
* Approve EXA token spending for
|
|
1989
|
+
* Approve EXA token spending for deposits
|
|
1742
1990
|
* @param amount Amount to approve
|
|
1743
1991
|
* @returns Transaction hash
|
|
1744
1992
|
*/
|
|
@@ -1776,25 +2024,28 @@ var ExagentStaking = class {
|
|
|
1776
2024
|
|
|
1777
2025
|
// src/constants.ts
|
|
1778
2026
|
import { base, baseSepolia } from "viem/chains";
|
|
2027
|
+
var SDK_VERSION = "0.1.4";
|
|
1779
2028
|
var CHAIN_CONFIG = {
|
|
1780
2029
|
mainnet: base,
|
|
1781
2030
|
testnet: baseSepolia
|
|
1782
2031
|
};
|
|
1783
2032
|
var CONTRACT_ADDRESSES = {
|
|
1784
2033
|
mainnet: {
|
|
1785
|
-
agentRegistry: "
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
router: "0x0000000000000000000000000000000000000000",
|
|
2034
|
+
agentRegistry: "0x2261706C751F8ac5cdDb481B7b56EA2137d4A723",
|
|
2035
|
+
exaToken: "0x13403Fb738C97cF7564F279288468c140AaEd05c",
|
|
2036
|
+
staking: "0xAF1729D1519A72f7d9b87aa23a305b775e2849DA",
|
|
2037
|
+
router: "0x11daD5366D903a3eF5d8f07EFF87ce6b173859a9",
|
|
1790
2038
|
vaultFactory: "0x0000000000000000000000000000000000000000",
|
|
1791
|
-
|
|
2039
|
+
// Phase 2 — pending deploy
|
|
2040
|
+
feeCollector: "0xe66328a964AF93bEF2eDB226D039C35aE6e66De1",
|
|
1792
2041
|
buyback: "0x0000000000000000000000000000000000000000",
|
|
2042
|
+
// Phase 2 — pending deploy
|
|
1793
2043
|
serviceEscrow: "0x0000000000000000000000000000000000000000"
|
|
2044
|
+
// Phase 2 — pending deploy
|
|
1794
2045
|
},
|
|
1795
2046
|
testnet: {
|
|
1796
2047
|
agentRegistry: "0xCF48C341e3FebeCA5ECB7eb2535f61A2Ba855d9C",
|
|
1797
|
-
//
|
|
2048
|
+
// one-agent-per-wallet
|
|
1798
2049
|
exaToken: "0x66c39b0ad96B3f5eE198Fef913c6636353a48A87",
|
|
1799
2050
|
staking: "0x439441468e1b1b616E9D36b80969C241F261A011",
|
|
1800
2051
|
// V2 with delegation
|
|
@@ -1824,21 +2075,47 @@ var ZERO_X_CONFIG = {
|
|
|
1824
2075
|
// Base
|
|
1825
2076
|
};
|
|
1826
2077
|
var EXAGENT_API_CONFIG = {
|
|
1827
|
-
mainnet: "https://api.
|
|
1828
|
-
testnet: "https://api.
|
|
2078
|
+
mainnet: "https://exagent-api.onrender.com",
|
|
2079
|
+
testnet: "https://exagent-api.onrender.com"
|
|
1829
2080
|
};
|
|
1830
2081
|
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
2082
|
+
var PHASE_1_CONTRACTS = /* @__PURE__ */ new Set([
|
|
2083
|
+
"agentRegistry",
|
|
2084
|
+
"exaToken",
|
|
2085
|
+
"staking",
|
|
2086
|
+
"router",
|
|
2087
|
+
"feeCollector"
|
|
2088
|
+
]);
|
|
1831
2089
|
function validateContractAddresses(network) {
|
|
1832
2090
|
const addresses = CONTRACT_ADDRESSES[network];
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
2091
|
+
if (network === "mainnet") {
|
|
2092
|
+
const missingPhase1 = Object.entries(addresses).filter(([name, addr]) => PHASE_1_CONTRACTS.has(name) && addr === ZERO_ADDRESS).map(([name]) => name);
|
|
2093
|
+
if (missingPhase1.length > 0) {
|
|
2094
|
+
throw new Error(
|
|
2095
|
+
`Mainnet Phase 1 contracts not deployed. Missing: ${missingPhase1.join(", ")}. Update @exagent/sdk to the latest version.`
|
|
2096
|
+
);
|
|
2097
|
+
}
|
|
1839
2098
|
}
|
|
1840
2099
|
}
|
|
1841
2100
|
|
|
2101
|
+
// src/types.ts
|
|
2102
|
+
function buildGlobalAgentId(chainId, registryAddress, agentId) {
|
|
2103
|
+
return `eip155:${chainId}:${registryAddress}:${Number(agentId)}`;
|
|
2104
|
+
}
|
|
2105
|
+
function parseGlobalAgentId(globalId) {
|
|
2106
|
+
const parts = globalId.split(":");
|
|
2107
|
+
if (parts.length !== 4 || parts[0] !== "eip155") {
|
|
2108
|
+
throw new Error(`Invalid ERC-8004 global agent ID: ${globalId}`);
|
|
2109
|
+
}
|
|
2110
|
+
const chainId = parseInt(parts[1], 10);
|
|
2111
|
+
const registryAddress = parts[2];
|
|
2112
|
+
const agentId = parseInt(parts[3], 10);
|
|
2113
|
+
if (isNaN(chainId) || isNaN(agentId)) {
|
|
2114
|
+
throw new Error(`Invalid ERC-8004 global agent ID: ${globalId}`);
|
|
2115
|
+
}
|
|
2116
|
+
return { chainId, registryAddress, agentId };
|
|
2117
|
+
}
|
|
2118
|
+
|
|
1842
2119
|
// src/client.ts
|
|
1843
2120
|
var ExagentClient = class {
|
|
1844
2121
|
publicClient;
|
|
@@ -1889,6 +2166,14 @@ var ExagentClient = class {
|
|
|
1889
2166
|
this.account
|
|
1890
2167
|
);
|
|
1891
2168
|
}
|
|
2169
|
+
/** Standard headers for all API requests (includes SDK version for gating) */
|
|
2170
|
+
apiHeaders(contentType) {
|
|
2171
|
+
return {
|
|
2172
|
+
...contentType && { "Content-Type": contentType },
|
|
2173
|
+
"X-Exagent-SDK-Version": SDK_VERSION,
|
|
2174
|
+
...this.apiKey && { "X-API-Key": this.apiKey }
|
|
2175
|
+
};
|
|
2176
|
+
}
|
|
1892
2177
|
// ============ Agent Registration ============
|
|
1893
2178
|
/**
|
|
1894
2179
|
* Register as a new agent on Exagent
|
|
@@ -1956,14 +2241,14 @@ var ExagentClient = class {
|
|
|
1956
2241
|
/**
|
|
1957
2242
|
* Link an additional wallet to this agent
|
|
1958
2243
|
* @param wallet Wallet address to link
|
|
1959
|
-
* @param signMessage Function to sign
|
|
2244
|
+
* @param signMessage Function to sign the message hash with the wallet (use signMessage({ raw: hash }))
|
|
1960
2245
|
*/
|
|
1961
2246
|
async linkWallet(wallet, signMessage) {
|
|
1962
2247
|
const agentId = await this.getAgentId();
|
|
1963
2248
|
if (!agentId) throw new Error("Agent not registered");
|
|
1964
2249
|
const nonce = await this.registry.getNonce(wallet);
|
|
1965
|
-
const
|
|
1966
|
-
const signature = await signMessage(
|
|
2250
|
+
const messageHash = ExagentRegistry.generateLinkMessage(wallet, agentId, nonce);
|
|
2251
|
+
const signature = await signMessage({ raw: messageHash });
|
|
1967
2252
|
return this.registry.linkWallet(agentId, wallet, signature);
|
|
1968
2253
|
}
|
|
1969
2254
|
/**
|
|
@@ -1976,127 +2261,15 @@ var ExagentClient = class {
|
|
|
1976
2261
|
}
|
|
1977
2262
|
// ============ Trading ============
|
|
1978
2263
|
/**
|
|
1979
|
-
*
|
|
1980
|
-
* Uses 0x API for aggregation across Aerodrome, Uniswap, etc.
|
|
1981
|
-
*/
|
|
1982
|
-
async getRoute(intent) {
|
|
1983
|
-
const apiUrl = EXAGENT_API_CONFIG[this.network];
|
|
1984
|
-
const response = await fetch(`${apiUrl}/v1/routes/quote`, {
|
|
1985
|
-
method: "POST",
|
|
1986
|
-
headers: {
|
|
1987
|
-
"Content-Type": "application/json",
|
|
1988
|
-
...this.apiKey && { "X-API-Key": this.apiKey }
|
|
1989
|
-
},
|
|
1990
|
-
body: JSON.stringify({
|
|
1991
|
-
tokenIn: intent.tokenIn,
|
|
1992
|
-
tokenOut: intent.tokenOut,
|
|
1993
|
-
amountIn: intent.amountIn.toString(),
|
|
1994
|
-
slippageBps: intent.maxSlippageBps ?? 50,
|
|
1995
|
-
taker: this.account.address
|
|
1996
|
-
})
|
|
1997
|
-
});
|
|
1998
|
-
if (!response.ok) {
|
|
1999
|
-
const error = await response.json().catch(() => ({ error: response.statusText }));
|
|
2000
|
-
throw new Error(`Failed to get route: ${error.error}`);
|
|
2001
|
-
}
|
|
2002
|
-
return response.json();
|
|
2003
|
-
}
|
|
2004
|
-
/**
|
|
2005
|
-
* Get price quote without transaction data (faster)
|
|
2006
|
-
*/
|
|
2007
|
-
async getPrice(tokenIn, tokenOut, amountIn) {
|
|
2008
|
-
const apiUrl = EXAGENT_API_CONFIG[this.network];
|
|
2009
|
-
const response = await fetch(`${apiUrl}/v1/routes/price`, {
|
|
2010
|
-
method: "POST",
|
|
2011
|
-
headers: {
|
|
2012
|
-
"Content-Type": "application/json",
|
|
2013
|
-
...this.apiKey && { "X-API-Key": this.apiKey }
|
|
2014
|
-
},
|
|
2015
|
-
body: JSON.stringify({
|
|
2016
|
-
tokenIn,
|
|
2017
|
-
tokenOut,
|
|
2018
|
-
amountIn: amountIn.toString()
|
|
2019
|
-
})
|
|
2020
|
-
});
|
|
2021
|
-
if (!response.ok) {
|
|
2022
|
-
const error = await response.json().catch(() => ({ error: response.statusText }));
|
|
2023
|
-
throw new Error(`Failed to get price: ${error.error}`);
|
|
2024
|
-
}
|
|
2025
|
-
return response.json();
|
|
2026
|
-
}
|
|
2027
|
-
/**
|
|
2028
|
-
* Execute a trade using a pre-fetched route
|
|
2029
|
-
* @param route Route quote from getRoute()
|
|
2030
|
-
* @param options Trade execution options
|
|
2031
|
-
* @returns Transaction hash
|
|
2032
|
-
*/
|
|
2033
|
-
async executeTrade(route, options) {
|
|
2034
|
-
if (route.validUntil && Date.now() > route.validUntil) {
|
|
2035
|
-
throw new Error("Quote expired, please fetch a new route");
|
|
2036
|
-
}
|
|
2037
|
-
if (route.issues?.allowance) {
|
|
2038
|
-
throw new Error(
|
|
2039
|
-
`Insufficient allowance for ${route.issues.allowance.spender}. Need ${route.issues.allowance.expected}, have ${route.issues.allowance.actual}`
|
|
2040
|
-
);
|
|
2041
|
-
}
|
|
2042
|
-
if (options?.validateSlippage !== false) {
|
|
2043
|
-
const freshPrice = await this.getPrice(
|
|
2044
|
-
route.tokenIn,
|
|
2045
|
-
route.tokenOut,
|
|
2046
|
-
BigInt(route.amountIn)
|
|
2047
|
-
);
|
|
2048
|
-
const quotedOutput = BigInt(route.amountOut);
|
|
2049
|
-
const freshOutput = BigInt(freshPrice.amountOut);
|
|
2050
|
-
if (freshOutput < quotedOutput * 99n / 100n) {
|
|
2051
|
-
console.warn("Price has moved significantly since quote was fetched");
|
|
2052
|
-
}
|
|
2053
|
-
}
|
|
2054
|
-
const hash = await this.walletClient.sendTransaction({
|
|
2055
|
-
account: this.account,
|
|
2056
|
-
chain: CHAIN_CONFIG[this.network],
|
|
2057
|
-
to: route.transaction.to,
|
|
2058
|
-
data: route.transaction.data,
|
|
2059
|
-
value: BigInt(route.transaction.value)
|
|
2060
|
-
});
|
|
2061
|
-
return hash;
|
|
2062
|
-
}
|
|
2063
|
-
/**
|
|
2064
|
-
* Get and execute a trade in one call
|
|
2065
|
-
* Convenience method that fetches route and executes
|
|
2066
|
-
*/
|
|
2067
|
-
async swap(intent) {
|
|
2068
|
-
const route = await this.getRoute(intent);
|
|
2069
|
-
const hash = await this.executeTrade(route);
|
|
2070
|
-
return { hash, route };
|
|
2071
|
-
}
|
|
2072
|
-
/**
|
|
2073
|
-
* Broadcast a trade intent to the network
|
|
2074
|
-
* Other agents can see this and potentially provide better execution
|
|
2075
|
-
*/
|
|
2076
|
-
async broadcastIntent(intent) {
|
|
2077
|
-
const agentId = await this.getAgentId();
|
|
2078
|
-
if (!agentId) throw new Error("Agent not registered");
|
|
2079
|
-
const apiUrl = EXAGENT_API_CONFIG[this.network];
|
|
2080
|
-
await fetch(`${apiUrl}/v1/intents`, {
|
|
2081
|
-
method: "POST",
|
|
2082
|
-
headers: {
|
|
2083
|
-
"Content-Type": "application/json",
|
|
2084
|
-
...this.apiKey && { "X-API-Key": this.apiKey }
|
|
2085
|
-
},
|
|
2086
|
-
body: JSON.stringify({
|
|
2087
|
-
agentId: agentId.toString(),
|
|
2088
|
-
intent,
|
|
2089
|
-
signature: await this.signIntent(intent)
|
|
2090
|
-
})
|
|
2091
|
-
});
|
|
2092
|
-
}
|
|
2093
|
-
// ============ Router Trading (Attributed) ============
|
|
2094
|
-
/**
|
|
2095
|
-
* Execute a trade through ExagentRouter for full attribution
|
|
2264
|
+
* Execute a trade through ExagentRouter
|
|
2096
2265
|
*
|
|
2097
|
-
*
|
|
2098
|
-
*
|
|
2099
|
-
*
|
|
2266
|
+
* All trades MUST go through the ExagentRouter. This ensures:
|
|
2267
|
+
* - Trade attribution for leaderboard ranking
|
|
2268
|
+
* - Protocol fee collection (0.2%)
|
|
2269
|
+
* - On-chain performance tracking
|
|
2270
|
+
* - Token whitelist enforcement per risk universe
|
|
2271
|
+
*
|
|
2272
|
+
* There is no way to trade outside the router. This is by design.
|
|
2100
2273
|
*
|
|
2101
2274
|
* @param intent Trade parameters
|
|
2102
2275
|
* @returns Trade result with transaction hash
|
|
@@ -2149,10 +2322,7 @@ var ExagentClient = class {
|
|
|
2149
2322
|
const apiUrl = EXAGENT_API_CONFIG[this.network];
|
|
2150
2323
|
const response = await fetch(`${apiUrl}/v1/router/trade`, {
|
|
2151
2324
|
method: "POST",
|
|
2152
|
-
headers:
|
|
2153
|
-
"Content-Type": "application/json",
|
|
2154
|
-
...this.apiKey && { "X-API-Key": this.apiKey }
|
|
2155
|
-
},
|
|
2325
|
+
headers: this.apiHeaders("application/json"),
|
|
2156
2326
|
body: JSON.stringify({
|
|
2157
2327
|
agentId: id.toString(),
|
|
2158
2328
|
tokenIn: intent.tokenIn,
|
|
@@ -2201,10 +2371,7 @@ var ExagentClient = class {
|
|
|
2201
2371
|
const apiUrl = EXAGENT_API_CONFIG[this.network];
|
|
2202
2372
|
const response = await fetch(`${apiUrl}/v1/services/request`, {
|
|
2203
2373
|
method: "POST",
|
|
2204
|
-
headers:
|
|
2205
|
-
"Content-Type": "application/json",
|
|
2206
|
-
...this.apiKey && { "X-API-Key": this.apiKey }
|
|
2207
|
-
},
|
|
2374
|
+
headers: this.apiHeaders("application/json"),
|
|
2208
2375
|
body: JSON.stringify({
|
|
2209
2376
|
requesterId: agentId.toString(),
|
|
2210
2377
|
...request
|
|
@@ -2222,7 +2389,9 @@ var ExagentClient = class {
|
|
|
2222
2389
|
const apiUrl = EXAGENT_API_CONFIG[this.network];
|
|
2223
2390
|
const params = new URLSearchParams();
|
|
2224
2391
|
if (serviceType) params.set("type", serviceType);
|
|
2225
|
-
const response = await fetch(`${apiUrl}/v1/services?${params}
|
|
2392
|
+
const response = await fetch(`${apiUrl}/v1/services?${params}`, {
|
|
2393
|
+
headers: this.apiHeaders()
|
|
2394
|
+
});
|
|
2226
2395
|
return response.json();
|
|
2227
2396
|
}
|
|
2228
2397
|
// ============ Leaderboards ============
|
|
@@ -2235,7 +2404,9 @@ var ExagentClient = class {
|
|
|
2235
2404
|
if (options?.category) params.set("category", options.category);
|
|
2236
2405
|
if (options?.limit) params.set("limit", options.limit.toString());
|
|
2237
2406
|
if (options?.offset) params.set("offset", options.offset.toString());
|
|
2238
|
-
const response = await fetch(`${apiUrl}/v1/rankings/leaderboard?${params}
|
|
2407
|
+
const response = await fetch(`${apiUrl}/v1/rankings/leaderboard?${params}`, {
|
|
2408
|
+
headers: this.apiHeaders()
|
|
2409
|
+
});
|
|
2239
2410
|
return response.json();
|
|
2240
2411
|
}
|
|
2241
2412
|
// ============ Vault Functions (Phase 4: Copy Trading) ============
|
|
@@ -2263,9 +2434,7 @@ var ExagentClient = class {
|
|
|
2263
2434
|
if (!id) throw new Error("Agent not registered");
|
|
2264
2435
|
const apiUrl = EXAGENT_API_CONFIG[this.network];
|
|
2265
2436
|
const response = await fetch(`${apiUrl}/v1/vaults?agentId=${id}`, {
|
|
2266
|
-
headers:
|
|
2267
|
-
...this.apiKey && { "X-API-Key": this.apiKey }
|
|
2268
|
-
}
|
|
2437
|
+
headers: this.apiHeaders()
|
|
2269
2438
|
});
|
|
2270
2439
|
if (!response.ok) {
|
|
2271
2440
|
throw new Error(`Failed to get vaults: ${response.statusText}`);
|
|
@@ -2281,9 +2450,7 @@ var ExagentClient = class {
|
|
|
2281
2450
|
const user = userAddress ?? this.account.address;
|
|
2282
2451
|
const apiUrl = EXAGENT_API_CONFIG[this.network];
|
|
2283
2452
|
const response = await fetch(`${apiUrl}/v1/vaults?depositor=${user}`, {
|
|
2284
|
-
headers:
|
|
2285
|
-
...this.apiKey && { "X-API-Key": this.apiKey }
|
|
2286
|
-
}
|
|
2453
|
+
headers: this.apiHeaders()
|
|
2287
2454
|
});
|
|
2288
2455
|
if (!response.ok) {
|
|
2289
2456
|
throw new Error(`Failed to get user vaults: ${response.statusText}`);
|
|
@@ -2303,9 +2470,7 @@ var ExagentClient = class {
|
|
|
2303
2470
|
if (options?.period) params.set("period", options.period);
|
|
2304
2471
|
if (options?.limit) params.set("limit", options.limit.toString());
|
|
2305
2472
|
const response = await fetch(`${apiUrl}/v1/vaults/top?${params}`, {
|
|
2306
|
-
headers:
|
|
2307
|
-
...this.apiKey && { "X-API-Key": this.apiKey }
|
|
2308
|
-
}
|
|
2473
|
+
headers: this.apiHeaders()
|
|
2309
2474
|
});
|
|
2310
2475
|
if (!response.ok) {
|
|
2311
2476
|
throw new Error(`Failed to get top vaults: ${response.statusText}`);
|
|
@@ -2346,37 +2511,73 @@ var ExagentClient = class {
|
|
|
2346
2511
|
}
|
|
2347
2512
|
// ============ Staking Functions ============
|
|
2348
2513
|
/**
|
|
2349
|
-
*
|
|
2350
|
-
* @param amount Amount of EXA to
|
|
2514
|
+
* Deposit EXA tokens for vault access (no lock required)
|
|
2515
|
+
* @param amount Amount of EXA to deposit (in wei)
|
|
2516
|
+
* @returns Transaction hash
|
|
2517
|
+
*
|
|
2518
|
+
* @example
|
|
2519
|
+
* ```typescript
|
|
2520
|
+
* // Deposit 1000 EXA to unlock vault access
|
|
2521
|
+
* const tx = await exagent.depositExa(parseEther('1000'));
|
|
2522
|
+
* ```
|
|
2523
|
+
*/
|
|
2524
|
+
async depositExa(amount) {
|
|
2525
|
+
await this.staking.approveExa(amount);
|
|
2526
|
+
return this.staking.deposit(amount);
|
|
2527
|
+
}
|
|
2528
|
+
/**
|
|
2529
|
+
* Withdraw unlocked EXA tokens (instant, no penalty)
|
|
2530
|
+
* @param amount Amount of EXA to withdraw (in wei)
|
|
2531
|
+
* @returns Transaction hash
|
|
2532
|
+
*/
|
|
2533
|
+
async withdrawExa(amount) {
|
|
2534
|
+
return this.staking.withdraw(amount);
|
|
2535
|
+
}
|
|
2536
|
+
/**
|
|
2537
|
+
* Lock deposited EXA to receive vEXA voting power and earn rewards
|
|
2538
|
+
* @param amount Amount of deposited EXA to lock (in wei)
|
|
2351
2539
|
* @param lockDuration Lock duration in seconds (30 days to 2 years)
|
|
2352
2540
|
* @returns Transaction hash
|
|
2353
2541
|
*
|
|
2354
2542
|
* @example
|
|
2355
2543
|
* ```typescript
|
|
2356
|
-
* //
|
|
2357
|
-
* const tx = await exagent.
|
|
2544
|
+
* // Lock 1000 EXA for 6 months
|
|
2545
|
+
* const tx = await exagent.lockExa(
|
|
2358
2546
|
* parseEther('1000'),
|
|
2359
2547
|
* ExagentStaking.LOCK_6_MONTHS
|
|
2360
2548
|
* );
|
|
2361
2549
|
* ```
|
|
2362
2550
|
*/
|
|
2363
|
-
async
|
|
2364
|
-
|
|
2365
|
-
|
|
2551
|
+
async lockExa(amount, lockDuration) {
|
|
2552
|
+
return this.staking.lock(amount, lockDuration);
|
|
2553
|
+
}
|
|
2554
|
+
/**
|
|
2555
|
+
* Unlock EXA after lock expires (no penalty)
|
|
2556
|
+
* @returns Transaction hash
|
|
2557
|
+
*/
|
|
2558
|
+
async unlockExa() {
|
|
2559
|
+
return this.staking.unlock();
|
|
2366
2560
|
}
|
|
2367
2561
|
/**
|
|
2368
|
-
*
|
|
2562
|
+
* Emergency withdrawal from active lock (graduated 50%→20% penalty)
|
|
2369
2563
|
* @returns Transaction hash
|
|
2370
2564
|
*/
|
|
2371
|
-
async
|
|
2372
|
-
return this.staking.
|
|
2565
|
+
async emergencyWithdrawExa() {
|
|
2566
|
+
return this.staking.emergencyWithdraw();
|
|
2373
2567
|
}
|
|
2374
2568
|
/**
|
|
2375
|
-
* Get staking info for the connected wallet
|
|
2376
|
-
* @returns Staking info including
|
|
2569
|
+
* Get comprehensive staking info (deposit + lock) for the connected wallet
|
|
2570
|
+
* @returns Staking info including deposit status and lock status
|
|
2377
2571
|
*/
|
|
2378
2572
|
async getStakingInfo() {
|
|
2379
|
-
return this.staking.
|
|
2573
|
+
return this.staking.getStakingInfo();
|
|
2574
|
+
}
|
|
2575
|
+
/**
|
|
2576
|
+
* Get deposit info for the connected wallet
|
|
2577
|
+
* @returns Deposit info (deposited, locked, unlocked, vault access)
|
|
2578
|
+
*/
|
|
2579
|
+
async getDepositInfo() {
|
|
2580
|
+
return this.staking.getDepositInfo();
|
|
2380
2581
|
}
|
|
2381
2582
|
/**
|
|
2382
2583
|
* Get current vEXA balance for the connected wallet
|
|
@@ -2386,20 +2587,25 @@ var ExagentClient = class {
|
|
|
2386
2587
|
return this.staking.getVeEXABalance();
|
|
2387
2588
|
}
|
|
2388
2589
|
/**
|
|
2389
|
-
*
|
|
2390
|
-
* @
|
|
2391
|
-
* @returns Transaction hash
|
|
2590
|
+
* Check if connected wallet has vault access (meets deposit threshold)
|
|
2591
|
+
* @returns True if user can access vaults
|
|
2392
2592
|
*/
|
|
2393
|
-
async
|
|
2394
|
-
return this.staking.
|
|
2593
|
+
async hasVaultAccess() {
|
|
2594
|
+
return this.staking.hasVaultAccess();
|
|
2395
2595
|
}
|
|
2396
2596
|
/**
|
|
2397
|
-
* Get
|
|
2398
|
-
* @
|
|
2399
|
-
* @returns Delegation info with total vEXA and delegator count
|
|
2597
|
+
* Get earnings tier for the connected wallet
|
|
2598
|
+
* @returns Tier info with multiplier and name
|
|
2400
2599
|
*/
|
|
2401
|
-
async
|
|
2402
|
-
return this.staking.
|
|
2600
|
+
async getEarningsTier() {
|
|
2601
|
+
return this.staking.getEarningsTier();
|
|
2602
|
+
}
|
|
2603
|
+
/**
|
|
2604
|
+
* Get emergency withdrawal penalty for the connected wallet
|
|
2605
|
+
* @returns Penalty in basis points (5000 = 50% at start, 2000 = 20% near expiry)
|
|
2606
|
+
*/
|
|
2607
|
+
async getEmergencyWithdrawPenalty() {
|
|
2608
|
+
return this.staking.getEmergencyWithdrawPenalty();
|
|
2403
2609
|
}
|
|
2404
2610
|
/**
|
|
2405
2611
|
* Claim all pending staking rewards (EXA + multi-token)
|
|
@@ -2410,6 +2616,46 @@ var ExagentClient = class {
|
|
|
2410
2616
|
const multiTokenRewards = await this.staking.claimRewardsMulti();
|
|
2411
2617
|
return { exaRewards, multiTokenRewards };
|
|
2412
2618
|
}
|
|
2619
|
+
// ============ ERC-8004 Global Agent Identity ============
|
|
2620
|
+
/**
|
|
2621
|
+
* Get the ERC-8004 global agent identifier for the current agent
|
|
2622
|
+
*
|
|
2623
|
+
* Format: eip155:{chainId}:{registryAddress}:{agentId}
|
|
2624
|
+
*
|
|
2625
|
+
* This creates a universally unique identifier that can be used for
|
|
2626
|
+
* cross-protocol agent discovery and interoperability.
|
|
2627
|
+
*
|
|
2628
|
+
* @returns The global agent ID string
|
|
2629
|
+
* @throws Error if agent is not registered
|
|
2630
|
+
*
|
|
2631
|
+
* @example
|
|
2632
|
+
* ```typescript
|
|
2633
|
+
* const globalId = await exagent.getGlobalAgentId();
|
|
2634
|
+
* // => "eip155:8453:0xABC...DEF:42"
|
|
2635
|
+
* ```
|
|
2636
|
+
*/
|
|
2637
|
+
async getGlobalAgentId() {
|
|
2638
|
+
const agentId = await this.getAgentId();
|
|
2639
|
+
if (!agentId) throw new Error("Agent not registered");
|
|
2640
|
+
const chain = CHAIN_CONFIG[this.network];
|
|
2641
|
+
const addresses = CONTRACT_ADDRESSES[this.network];
|
|
2642
|
+
return buildGlobalAgentId(
|
|
2643
|
+
chain.id,
|
|
2644
|
+
addresses.agentRegistry,
|
|
2645
|
+
agentId
|
|
2646
|
+
);
|
|
2647
|
+
}
|
|
2648
|
+
/**
|
|
2649
|
+
* Build a global agent ID for any agent (static utility)
|
|
2650
|
+
*
|
|
2651
|
+
* @param chainId - EVM chain ID
|
|
2652
|
+
* @param registryAddress - ExagentRegistry contract address
|
|
2653
|
+
* @param agentId - On-chain agent ID
|
|
2654
|
+
* @returns ERC-8004 global agent identifier
|
|
2655
|
+
*/
|
|
2656
|
+
static buildGlobalAgentId(chainId, registryAddress, agentId) {
|
|
2657
|
+
return buildGlobalAgentId(chainId, registryAddress, agentId);
|
|
2658
|
+
}
|
|
2413
2659
|
// ============ Helpers ============
|
|
2414
2660
|
/**
|
|
2415
2661
|
* Get the agent's wallet address
|
|
@@ -2429,10 +2675,7 @@ var ExagentClient = class {
|
|
|
2429
2675
|
const apiUrl = EXAGENT_API_CONFIG[this.network];
|
|
2430
2676
|
const response = await fetch(`${apiUrl}/v1/metadata/upload`, {
|
|
2431
2677
|
method: "POST",
|
|
2432
|
-
headers:
|
|
2433
|
-
"Content-Type": "application/json",
|
|
2434
|
-
...this.apiKey && { "X-API-Key": this.apiKey }
|
|
2435
|
-
},
|
|
2678
|
+
headers: this.apiHeaders("application/json"),
|
|
2436
2679
|
body: JSON.stringify(metadata)
|
|
2437
2680
|
});
|
|
2438
2681
|
if (!response.ok) {
|
|
@@ -2441,12 +2684,16 @@ var ExagentClient = class {
|
|
|
2441
2684
|
const result = await response.json();
|
|
2442
2685
|
return result.uri;
|
|
2443
2686
|
}
|
|
2444
|
-
async signIntent(intent) {
|
|
2445
|
-
const message = JSON.stringify(intent);
|
|
2446
|
-
return this.walletClient.signMessage({ account: this.account, message });
|
|
2447
|
-
}
|
|
2448
2687
|
parseAgentIdFromReceipt(receipt) {
|
|
2449
|
-
|
|
2688
|
+
const registryAddress = this.registry.address.toLowerCase();
|
|
2689
|
+
for (const log of receipt.logs) {
|
|
2690
|
+
if (log.address.toLowerCase() !== registryAddress) continue;
|
|
2691
|
+
if (log.topics.length >= 2 && log.topics[1]) {
|
|
2692
|
+
const agentId = BigInt(log.topics[1]);
|
|
2693
|
+
return agentId;
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
throw new Error("AgentRegistered event not found in transaction receipt");
|
|
2450
2697
|
}
|
|
2451
2698
|
};
|
|
2452
2699
|
|
|
@@ -2456,8 +2703,12 @@ var EXAGENT_VAULT_FACTORY_ABI = [
|
|
|
2456
2703
|
{ type: "function", name: "owner", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
|
|
2457
2704
|
{ type: "function", name: "registry", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
|
|
2458
2705
|
{ type: "function", name: "router", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
|
|
2459
|
-
{ type: "function", name: "
|
|
2460
|
-
{ type: "function", name: "
|
|
2706
|
+
{ type: "function", name: "feeCollector", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
|
|
2707
|
+
{ type: "function", name: "stakingContract", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
|
|
2708
|
+
{ type: "function", name: "VERIFIED_VEXA_REQUIREMENT", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
2709
|
+
{ type: "function", name: "MIN_SEED_AMOUNT", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
2710
|
+
{ type: "function", name: "UNVERIFIED_CAP_MULTIPLIER", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
2711
|
+
{ type: "function", name: "VERIFIED_CAP_MULTIPLIER", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
2461
2712
|
{ type: "function", name: "allowedAssets", inputs: [{ name: "asset", type: "address" }], outputs: [{ type: "bool" }], stateMutability: "view" },
|
|
2462
2713
|
{ type: "function", name: "vaults", inputs: [{ name: "agentId", type: "uint256" }, { name: "asset", type: "address" }], outputs: [{ type: "address" }], stateMutability: "view" },
|
|
2463
2714
|
{ type: "function", name: "agentVaultCount", inputs: [{ name: "agentId", type: "uint256" }], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
@@ -2470,14 +2721,9 @@ var EXAGENT_VAULT_FACTORY_ABI = [
|
|
|
2470
2721
|
},
|
|
2471
2722
|
{
|
|
2472
2723
|
type: "function",
|
|
2473
|
-
name: "
|
|
2474
|
-
inputs: [],
|
|
2475
|
-
outputs: [
|
|
2476
|
-
{ name: "veXARequired", type: "uint256" },
|
|
2477
|
-
{ name: "burnFee", type: "uint256" },
|
|
2478
|
-
{ name: "stakingContract", type: "address" },
|
|
2479
|
-
{ name: "exaToken", type: "address" }
|
|
2480
|
-
],
|
|
2724
|
+
name: "canCreateVerifiedVault",
|
|
2725
|
+
inputs: [{ name: "agentId", type: "uint256" }],
|
|
2726
|
+
outputs: [{ name: "isVerified", type: "bool" }, { name: "reason", type: "string" }],
|
|
2481
2727
|
stateMutability: "view"
|
|
2482
2728
|
},
|
|
2483
2729
|
// Write functions
|
|
@@ -2487,6 +2733,7 @@ var EXAGENT_VAULT_FACTORY_ABI = [
|
|
|
2487
2733
|
inputs: [
|
|
2488
2734
|
{ name: "agentId", type: "uint256" },
|
|
2489
2735
|
{ name: "asset", type: "address" },
|
|
2736
|
+
{ name: "seedAmount", type: "uint256" },
|
|
2490
2737
|
{ name: "name", type: "string" },
|
|
2491
2738
|
{ name: "symbol", type: "string" },
|
|
2492
2739
|
{ name: "feeRecipient", type: "address" }
|
|
@@ -2528,50 +2775,51 @@ var ExagentVaultFactory = class {
|
|
|
2528
2775
|
this.address = factoryAddress;
|
|
2529
2776
|
this.publicClient = publicClient;
|
|
2530
2777
|
this.walletClient = walletClient;
|
|
2778
|
+
if (!chain) {
|
|
2779
|
+
throw new Error("Chain parameter is required");
|
|
2780
|
+
}
|
|
2531
2781
|
this.chain = chain;
|
|
2532
2782
|
this.account = account;
|
|
2533
2783
|
}
|
|
2534
2784
|
// ============ Read Functions ============
|
|
2535
2785
|
/**
|
|
2536
|
-
* Get vault creation requirements
|
|
2786
|
+
* Get vault creation requirements (mainnet: seed-based, no burn fee)
|
|
2537
2787
|
*/
|
|
2538
2788
|
async getRequirements() {
|
|
2539
|
-
|
|
2540
|
-
|
|
2789
|
+
const [veXARequired, minSeedAmount, unverifiedCapMultiplier, verifiedCapMultiplier, stakingContract] = await Promise.all([
|
|
2790
|
+
this.publicClient.readContract({
|
|
2541
2791
|
address: this.address,
|
|
2542
2792
|
abi: EXAGENT_VAULT_FACTORY_ABI,
|
|
2543
|
-
functionName: "
|
|
2544
|
-
})
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
};
|
|
2574
|
-
}
|
|
2793
|
+
functionName: "VERIFIED_VEXA_REQUIREMENT"
|
|
2794
|
+
}),
|
|
2795
|
+
this.publicClient.readContract({
|
|
2796
|
+
address: this.address,
|
|
2797
|
+
abi: EXAGENT_VAULT_FACTORY_ABI,
|
|
2798
|
+
functionName: "MIN_SEED_AMOUNT"
|
|
2799
|
+
}),
|
|
2800
|
+
this.publicClient.readContract({
|
|
2801
|
+
address: this.address,
|
|
2802
|
+
abi: EXAGENT_VAULT_FACTORY_ABI,
|
|
2803
|
+
functionName: "UNVERIFIED_CAP_MULTIPLIER"
|
|
2804
|
+
}),
|
|
2805
|
+
this.publicClient.readContract({
|
|
2806
|
+
address: this.address,
|
|
2807
|
+
abi: EXAGENT_VAULT_FACTORY_ABI,
|
|
2808
|
+
functionName: "VERIFIED_CAP_MULTIPLIER"
|
|
2809
|
+
}),
|
|
2810
|
+
this.publicClient.readContract({
|
|
2811
|
+
address: this.address,
|
|
2812
|
+
abi: EXAGENT_VAULT_FACTORY_ABI,
|
|
2813
|
+
functionName: "stakingContract"
|
|
2814
|
+
})
|
|
2815
|
+
]);
|
|
2816
|
+
return {
|
|
2817
|
+
veXARequired,
|
|
2818
|
+
minSeedAmount,
|
|
2819
|
+
unverifiedCapMultiplier,
|
|
2820
|
+
verifiedCapMultiplier,
|
|
2821
|
+
stakingContract
|
|
2822
|
+
};
|
|
2575
2823
|
}
|
|
2576
2824
|
/**
|
|
2577
2825
|
* Check if an address can create a vault
|
|
@@ -2589,6 +2837,22 @@ var ExagentVaultFactory = class {
|
|
|
2589
2837
|
reason: result[1]
|
|
2590
2838
|
};
|
|
2591
2839
|
}
|
|
2840
|
+
/**
|
|
2841
|
+
* Check if an agent can create a verified vault (higher deposit cap)
|
|
2842
|
+
* @param agentId Agent ID to check
|
|
2843
|
+
*/
|
|
2844
|
+
async canCreateVerifiedVault(agentId) {
|
|
2845
|
+
const result = await this.publicClient.readContract({
|
|
2846
|
+
address: this.address,
|
|
2847
|
+
abi: EXAGENT_VAULT_FACTORY_ABI,
|
|
2848
|
+
functionName: "canCreateVerifiedVault",
|
|
2849
|
+
args: [agentId]
|
|
2850
|
+
});
|
|
2851
|
+
return {
|
|
2852
|
+
isVerified: result[0],
|
|
2853
|
+
reason: result[1]
|
|
2854
|
+
};
|
|
2855
|
+
}
|
|
2592
2856
|
/**
|
|
2593
2857
|
* Check if an asset is whitelisted for vault creation
|
|
2594
2858
|
* @param asset Asset address to check
|
|
@@ -2638,8 +2902,8 @@ var ExagentVaultFactory = class {
|
|
|
2638
2902
|
}
|
|
2639
2903
|
// ============ Write Functions ============
|
|
2640
2904
|
/**
|
|
2641
|
-
* Create a new vault for an agent
|
|
2642
|
-
* @param options Vault creation options
|
|
2905
|
+
* Create a new vault for an agent (mainnet: requires seed amount)
|
|
2906
|
+
* @param options Vault creation options including seedAmount
|
|
2643
2907
|
* @returns Transaction hash
|
|
2644
2908
|
*/
|
|
2645
2909
|
async createVault(options) {
|
|
@@ -2651,7 +2915,7 @@ var ExagentVaultFactory = class {
|
|
|
2651
2915
|
address: this.address,
|
|
2652
2916
|
abi: EXAGENT_VAULT_FACTORY_ABI,
|
|
2653
2917
|
functionName: "createVault",
|
|
2654
|
-
args: [options.agentId, options.asset, options.name, options.symbol, feeRecipient],
|
|
2918
|
+
args: [options.agentId, options.asset, options.seedAmount, options.name, options.symbol, feeRecipient],
|
|
2655
2919
|
account: this.account,
|
|
2656
2920
|
chain: this.chain
|
|
2657
2921
|
});
|
|
@@ -2662,7 +2926,7 @@ var ExagentVaultFactory = class {
|
|
|
2662
2926
|
* Check all requirements and create a vault if possible
|
|
2663
2927
|
* Returns detailed status about each requirement
|
|
2664
2928
|
*/
|
|
2665
|
-
async checkAndCreateVault(agentId, asset, name, symbol, feeRecipient) {
|
|
2929
|
+
async checkAndCreateVault(agentId, asset, seedAmount, name, symbol, feeRecipient) {
|
|
2666
2930
|
const [canCreateResult, assetAllowed, hasExisting] = await Promise.all([
|
|
2667
2931
|
this.canCreateVault(this.account?.address ?? "0x0000000000000000000000000000000000000000"),
|
|
2668
2932
|
this.isAssetAllowed(asset),
|
|
@@ -2701,6 +2965,7 @@ var ExagentVaultFactory = class {
|
|
|
2701
2965
|
const txHash = await this.createVault({
|
|
2702
2966
|
agentId,
|
|
2703
2967
|
asset,
|
|
2968
|
+
seedAmount,
|
|
2704
2969
|
name,
|
|
2705
2970
|
symbol,
|
|
2706
2971
|
feeRecipient
|
|
@@ -2734,7 +2999,6 @@ var ExagentVaultFactory = class {
|
|
|
2734
2999
|
// src/index.ts
|
|
2735
3000
|
var TESTNET_ADDRESSES = {
|
|
2736
3001
|
registry: "0xCF48C341e3FebeCA5ECB7eb2535f61A2Ba855d9C",
|
|
2737
|
-
// V4 UUPS proxy
|
|
2738
3002
|
token: "0x66c39b0ad96B3f5eE198Fef913c6636353a48A87",
|
|
2739
3003
|
staking: "0x439441468e1b1b616E9D36b80969C241F261A011",
|
|
2740
3004
|
router: "0xc0c27eEE047E414CD716D06C2444CF2073113d5C",
|
|
@@ -2750,7 +3014,6 @@ export {
|
|
|
2750
3014
|
CHAIN_CONFIG,
|
|
2751
3015
|
CONTRACT_ADDRESSES,
|
|
2752
3016
|
DEX_ADDRESSES,
|
|
2753
|
-
DISCOUNT_TIERS,
|
|
2754
3017
|
EXAGENT_API_CONFIG,
|
|
2755
3018
|
EXAGENT_STAKING_ABI,
|
|
2756
3019
|
EXAGENT_VAULT_FACTORY_ABI,
|
|
@@ -2759,6 +3022,9 @@ export {
|
|
|
2759
3022
|
ExagentStaking,
|
|
2760
3023
|
ExagentVault,
|
|
2761
3024
|
ExagentVaultFactory,
|
|
3025
|
+
SDK_VERSION,
|
|
2762
3026
|
TESTNET_ADDRESSES,
|
|
2763
|
-
ZERO_X_CONFIG
|
|
3027
|
+
ZERO_X_CONFIG,
|
|
3028
|
+
buildGlobalAgentId,
|
|
3029
|
+
parseGlobalAgentId
|
|
2764
3030
|
};
|