mantle-agent-kit-sdk 1.0.2 → 1.0.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.cjs CHANGED
@@ -6,6 +6,7 @@ var chains = require('viem/chains');
6
6
  var actions = require('viem/actions');
7
7
  var axios6 = require('axios');
8
8
  var CryptoJS = require('crypto-js');
9
+ var experimental = require('viem/experimental');
9
10
 
10
11
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
12
 
@@ -17,11 +18,43 @@ var __export = (target, all) => {
17
18
  for (var name in all)
18
19
  __defProp(target, name, { get: all[name], enumerable: true });
19
20
  };
20
- var sendTransaction = async (agent, to, amount) => {
21
- const hash = await agent.client.sendTransaction({
22
- to,
23
- value: viem.parseEther(amount)
24
- });
21
+ var erc20Abi = [
22
+ {
23
+ name: "transfer",
24
+ type: "function",
25
+ inputs: [
26
+ { name: "to", type: "address" },
27
+ { name: "amount", type: "uint256" }
28
+ ],
29
+ outputs: [{ type: "bool" }]
30
+ },
31
+ {
32
+ name: "decimals",
33
+ type: "function",
34
+ inputs: [],
35
+ outputs: [{ type: "uint8" }]
36
+ }
37
+ ];
38
+ var sendTransaction = async (agent, to, amount, tokenAddress) => {
39
+ let hash;
40
+ if (tokenAddress) {
41
+ const decimals = await agent.client.readContract({
42
+ address: tokenAddress,
43
+ abi: erc20Abi,
44
+ functionName: "decimals"
45
+ });
46
+ hash = await agent.client.writeContract({
47
+ address: tokenAddress,
48
+ abi: erc20Abi,
49
+ functionName: "transfer",
50
+ args: [to, viem.parseUnits(amount, decimals)]
51
+ });
52
+ } else {
53
+ hash = await agent.client.sendTransaction({
54
+ to,
55
+ value: viem.parseEther(amount)
56
+ });
57
+ }
25
58
  const receipt = await actions.getTransactionReceipt(agent.client, {
26
59
  hash
27
60
  });
@@ -195,9 +228,85 @@ async function getSwapTransaction(fromTokenAddress, toTokenAddress, amount, user
195
228
  throw error;
196
229
  }
197
230
  }
231
+ var DEMO_TX_HASH = "0xdemo000000000000000000000000000000000000000000000000000000000001";
232
+ function createMockSwapResponse(protocol, inputAmount) {
233
+ return {
234
+ txHash: DEMO_TX_HASH,
235
+ amountOut: inputAmount,
236
+ demo: true,
237
+ message: `[DEMO] ${protocol} swap simulated`
238
+ };
239
+ }
240
+ function createMockQuoteResponse(protocol, inputAmount) {
241
+ return {
242
+ estimatedAmount: inputAmount,
243
+ demo: true,
244
+ message: `[DEMO] ${protocol} quote simulated`
245
+ };
246
+ }
247
+ function createMockLendleResponse(action, amount) {
248
+ return {
249
+ txHash: DEMO_TX_HASH,
250
+ amount,
251
+ demo: true,
252
+ message: `[DEMO] Lendle ${action} simulated`
253
+ };
254
+ }
255
+ function createMockTxHash() {
256
+ return DEMO_TX_HASH;
257
+ }
258
+ function createMock1inchSwapResponse(inputAmount) {
259
+ return {
260
+ txHash: DEMO_TX_HASH,
261
+ dstAmount: inputAmount,
262
+ demo: true,
263
+ message: "[DEMO] 1inch swap simulated"
264
+ };
265
+ }
266
+ function createMockOkxSwapResponse(inputAmount) {
267
+ return {
268
+ data: DEMO_TX_HASH,
269
+ demo: true,
270
+ message: "[DEMO] OKX swap simulated"
271
+ };
272
+ }
273
+ function createMockOpenOceanSwapResponse(inputAmount) {
274
+ return {
275
+ txHash: DEMO_TX_HASH,
276
+ outAmount: inputAmount,
277
+ demo: true,
278
+ message: "[DEMO] OpenOcean swap simulated"
279
+ };
280
+ }
281
+ function createMockUniswapSwapResponse(inputAmount) {
282
+ return {
283
+ txHash: DEMO_TX_HASH,
284
+ amountOut: inputAmount,
285
+ demo: true,
286
+ message: "[DEMO] Uniswap swap simulated"
287
+ };
288
+ }
289
+ function createMockSquidRoute(amount) {
290
+ return {
291
+ route: {
292
+ estimate: { toAmount: amount },
293
+ transactionRequest: {
294
+ targetAddress: "0x0000000000000000000000000000000000000000",
295
+ data: "0x",
296
+ value: "0",
297
+ gasLimit: "0"
298
+ }
299
+ },
300
+ demo: true,
301
+ message: "[DEMO] Squid route simulated"
302
+ };
303
+ }
198
304
 
199
305
  // src/tools/okx/swap.ts
200
306
  async function executeSwap(agent, fromTokenAddress, toTokenAddress, amount, slippagePercent) {
307
+ if (agent.demo) {
308
+ return createMockOkxSwapResponse();
309
+ }
201
310
  const chainIndex = agent.chain === "mainnet" ? "5000" : "5003";
202
311
  const walletAddress = agent.account.address;
203
312
  if (fromTokenAddress !== ETH_ADDRESS) {
@@ -331,6 +440,9 @@ async function getSwapData(fromToken, toToken, amount, userAddress, slippage, ch
331
440
 
332
441
  // src/tools/openocean/getQuote.ts
333
442
  async function getOpenOceanQuote(agent, fromToken, toToken, amount) {
443
+ if (agent.demo) {
444
+ return createMockQuoteResponse("OpenOcean", amount);
445
+ }
334
446
  return await getQuoteData(fromToken, toToken, amount, agent.chain);
335
447
  }
336
448
  async function checkAllowance2(agent, tokenAddress, ownerAddress, spenderAddress) {
@@ -360,8 +472,8 @@ async function approveToken2(agent, tokenAddress, spenderAddress, amount) {
360
472
  return { approved: true, txHash: null };
361
473
  }
362
474
  console.log("Insufficient allowance, approving tokens...");
363
- const { encodeFunctionData: encodeFunctionData8 } = await import('viem');
364
- const approveData = encodeFunctionData8({
475
+ const { encodeFunctionData: encodeFunctionData11 } = await import('viem');
476
+ const approveData = encodeFunctionData11({
365
477
  abi: viem.erc20Abi,
366
478
  functionName: "approve",
367
479
  args: [spenderAddress, BigInt(amount)]
@@ -387,6 +499,12 @@ async function approveToken2(agent, tokenAddress, spenderAddress, amount) {
387
499
 
388
500
  // src/tools/openocean/swap.ts
389
501
  async function swapOnOpenOcean(agent, fromToken, toToken, amount, slippage = "1") {
502
+ if (agent.demo) {
503
+ return createMockOpenOceanSwapResponse(amount);
504
+ }
505
+ if (!agent.demo && agent.chain != "mainnet") {
506
+ throw new Error("Openocean swaps happen only on mainnet");
507
+ }
390
508
  const walletAddress = agent.account.address;
391
509
  if (fromToken.toLowerCase() !== NATIVE_TOKEN_ADDRESS.toLowerCase()) {
392
510
  await approveToken2(agent, fromToken, OPENOCEAN_EXCHANGE_PROXY, amount);
@@ -498,11 +616,17 @@ async function getSwapData2(fromToken, toToken, amount, userAddress, slippage, c
498
616
 
499
617
  // src/tools/oneinch/getQuote.ts
500
618
  async function get1inchQuote(agent, fromToken, toToken, amount) {
619
+ if (agent.demo) {
620
+ return createMockQuoteResponse("1inch", amount);
621
+ }
501
622
  return await getQuoteData2(fromToken, toToken, amount, agent.chain);
502
623
  }
503
624
 
504
625
  // src/tools/oneinch/swap.ts
505
626
  async function swapOn1inch(agent, fromToken, toToken, amount, slippage = "1") {
627
+ if (agent.demo) {
628
+ return createMock1inchSwapResponse(amount);
629
+ }
506
630
  const walletAddress = agent.account.address;
507
631
  if (fromToken.toLowerCase() !== NATIVE_TOKEN_ADDRESS2.toLowerCase()) {
508
632
  await approveToken2(agent, fromToken, ONEINCH_ROUTER_ADDRESS, amount);
@@ -669,11 +793,17 @@ function buildSwapCalldata(params, fee = DEFAULT_POOL_FEE) {
669
793
 
670
794
  // src/tools/uniswap/getQuote.ts
671
795
  async function getUniswapQuote(agent, fromToken, toToken, amount, fee = DEFAULT_POOL_FEE) {
796
+ if (agent.demo) {
797
+ return createMockQuoteResponse("Uniswap", amount);
798
+ }
672
799
  return await getUniswapQuoteData(agent, fromToken, toToken, amount, fee);
673
800
  }
674
801
 
675
802
  // src/tools/uniswap/swap.ts
676
803
  async function swapOnUniswap(agent, fromToken, toToken, amount, slippage = "0.5", fee = DEFAULT_POOL_FEE) {
804
+ if (agent.demo) {
805
+ return createMockUniswapSwapResponse(amount);
806
+ }
677
807
  const walletAddress = agent.account.address;
678
808
  const isNativeIn = fromToken.toLowerCase() === NATIVE_TOKEN_ADDRESS3.toLowerCase();
679
809
  const quote = await getUniswapQuoteData(agent, fromToken, toToken, amount, fee);
@@ -772,6 +902,9 @@ async function getRouteData(fromToken, toToken, fromChain, toChain, amount, from
772
902
 
773
903
  // src/tools/squid/crossChainSwap.ts
774
904
  async function crossChainSwapViaSquid(agent, fromToken, toToken, fromChain, toChain, amount, slippage = 1) {
905
+ if (agent.demo) {
906
+ return createMockTxHash();
907
+ }
775
908
  const routeData = await getRouteData(
776
909
  fromToken,
777
910
  toToken,
@@ -800,6 +933,9 @@ async function crossChainSwapViaSquid(agent, fromToken, toToken, fromChain, toCh
800
933
  return hash;
801
934
  }
802
935
  async function getSquidRoute(agent, fromToken, toToken, fromChain, toChain, amount, slippage = 1) {
936
+ if (agent.demo) {
937
+ return createMockSquidRoute(amount);
938
+ }
803
939
  return await getRouteData(
804
940
  fromToken,
805
941
  toToken,
@@ -818,8 +954,10 @@ __export(lendle_exports, {
818
954
  LENDING_POOL: () => LENDING_POOL,
819
955
  LENDING_POOL_ABI: () => LENDING_POOL_ABI,
820
956
  LENDING_POOL_ADDRESSES_PROVIDER: () => LENDING_POOL_ADDRESSES_PROVIDER,
957
+ LENDLE_SUPPORTED_ASSETS: () => LENDLE_SUPPORTED_ASSETS,
821
958
  ORACLE: () => ORACLE,
822
959
  PROTOCOL_DATA_PROVIDER: () => PROTOCOL_DATA_PROVIDER,
960
+ PROTOCOL_DATA_PROVIDER_ABI: () => PROTOCOL_DATA_PROVIDER_ABI,
823
961
  WMNT_ADDRESS: () => WMNT_ADDRESS2
824
962
  });
825
963
  var LENDING_POOL = {
@@ -934,11 +1072,73 @@ var LENDING_POOL_ABI = [
934
1072
  type: "function"
935
1073
  }
936
1074
  ];
1075
+ var PROTOCOL_DATA_PROVIDER_ABI = [
1076
+ {
1077
+ inputs: [],
1078
+ name: "getAllReservesTokens",
1079
+ outputs: [
1080
+ {
1081
+ components: [
1082
+ { name: "symbol", type: "string" },
1083
+ { name: "tokenAddress", type: "address" }
1084
+ ],
1085
+ name: "",
1086
+ type: "tuple[]"
1087
+ }
1088
+ ],
1089
+ stateMutability: "view",
1090
+ type: "function"
1091
+ },
1092
+ {
1093
+ inputs: [
1094
+ { name: "asset", type: "address" },
1095
+ { name: "user", type: "address" }
1096
+ ],
1097
+ name: "getUserReserveData",
1098
+ outputs: [
1099
+ { name: "currentATokenBalance", type: "uint256" },
1100
+ { name: "currentStableDebt", type: "uint256" },
1101
+ { name: "currentVariableDebt", type: "uint256" },
1102
+ { name: "principalStableDebt", type: "uint256" },
1103
+ { name: "scaledVariableDebt", type: "uint256" },
1104
+ { name: "stableBorrowRate", type: "uint256" },
1105
+ { name: "liquidityRate", type: "uint256" },
1106
+ { name: "stableRateLastUpdated", type: "uint40" },
1107
+ { name: "usageAsCollateralEnabled", type: "bool" }
1108
+ ],
1109
+ stateMutability: "view",
1110
+ type: "function"
1111
+ },
1112
+ {
1113
+ inputs: [{ name: "asset", type: "address" }],
1114
+ name: "getReserveTokensAddresses",
1115
+ outputs: [
1116
+ { name: "aTokenAddress", type: "address" },
1117
+ { name: "stableDebtTokenAddress", type: "address" },
1118
+ { name: "variableDebtTokenAddress", type: "address" }
1119
+ ],
1120
+ stateMutability: "view",
1121
+ type: "function"
1122
+ }
1123
+ ];
1124
+ var LENDLE_SUPPORTED_ASSETS = {
1125
+ mainnet: [
1126
+ { symbol: "WMNT", address: "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8" },
1127
+ { symbol: "WETH", address: "0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111" },
1128
+ { symbol: "USDC", address: "0x09Bc4E0D10C81b3a3766c49F0f98a8aaa7adA8D2" },
1129
+ { symbol: "USDT", address: "0x201EBa5CC46D216Ce6DC03F6a759e8E766e956aE" },
1130
+ { symbol: "mETH", address: "0xcDA86A272531e8640cD7F1a92c01839911B90bb0" }
1131
+ ],
1132
+ testnet: []
1133
+ };
937
1134
 
938
1135
  // src/tools/lendle/supply.ts
939
1136
  async function lendleSupply(agent, tokenAddress, amount) {
940
1137
  const lendingPoolAddress = LENDING_POOL[agent.chain];
941
1138
  if (lendingPoolAddress === "0x0000000000000000000000000000000000000000") {
1139
+ if (agent.demo) {
1140
+ return createMockLendleResponse("supply", amount).txHash;
1141
+ }
942
1142
  throw new Error(
943
1143
  `Lendle LendingPool not configured for ${agent.chain}. Only available on mainnet.`
944
1144
  );
@@ -965,6 +1165,9 @@ async function lendleSupply(agent, tokenAddress, amount) {
965
1165
  async function lendleWithdraw(agent, tokenAddress, amount, to) {
966
1166
  const lendingPoolAddress = LENDING_POOL[agent.chain];
967
1167
  if (lendingPoolAddress === "0x0000000000000000000000000000000000000000") {
1168
+ if (agent.demo) {
1169
+ return createMockLendleResponse("withdraw", amount).txHash;
1170
+ }
968
1171
  throw new Error(
969
1172
  `Lendle LendingPool not configured for ${agent.chain}. Only available on mainnet.`
970
1173
  );
@@ -986,6 +1189,9 @@ async function lendleWithdraw(agent, tokenAddress, amount, to) {
986
1189
  async function lendleBorrow(agent, tokenAddress, amount, interestRateMode = INTEREST_RATE_MODE.VARIABLE, onBehalfOf) {
987
1190
  const lendingPoolAddress = LENDING_POOL[agent.chain];
988
1191
  if (lendingPoolAddress === "0x0000000000000000000000000000000000000000") {
1192
+ if (agent.demo) {
1193
+ return createMockLendleResponse("borrow", amount).txHash;
1194
+ }
989
1195
  throw new Error(
990
1196
  `Lendle LendingPool not configured for ${agent.chain}. Only available on mainnet.`
991
1197
  );
@@ -1008,6 +1214,9 @@ async function lendleBorrow(agent, tokenAddress, amount, interestRateMode = INTE
1008
1214
  async function lendleRepay(agent, tokenAddress, amount, rateMode = INTEREST_RATE_MODE.VARIABLE, onBehalfOf) {
1009
1215
  const lendingPoolAddress = LENDING_POOL[agent.chain];
1010
1216
  if (lendingPoolAddress === "0x0000000000000000000000000000000000000000") {
1217
+ if (agent.demo) {
1218
+ return createMockLendleResponse("repay", amount).txHash;
1219
+ }
1011
1220
  throw new Error(
1012
1221
  `Lendle LendingPool not configured for ${agent.chain}. Only available on mainnet.`
1013
1222
  );
@@ -1027,6 +1236,67 @@ async function lendleRepay(agent, tokenAddress, amount, rateMode = INTEREST_RATE
1027
1236
  await agent.client.waitForTransactionReceipt({ hash });
1028
1237
  return hash;
1029
1238
  }
1239
+ async function lendleGetPositions(agent, userAddress) {
1240
+ const dataProviderAddress = PROTOCOL_DATA_PROVIDER[agent.chain];
1241
+ const address = userAddress || agent.account.address;
1242
+ if (dataProviderAddress === "0x0000000000000000000000000000000000000000") {
1243
+ throw new Error(
1244
+ `Lendle ProtocolDataProvider not configured for ${agent.chain}. Only available on mainnet.`
1245
+ );
1246
+ }
1247
+ const supportedAssets = LENDLE_SUPPORTED_ASSETS[agent.chain];
1248
+ if (!supportedAssets || supportedAssets.length === 0) {
1249
+ throw new Error(`No supported assets configured for ${agent.chain}`);
1250
+ }
1251
+ const positions = [];
1252
+ let totalSupplied = 0n;
1253
+ let totalDebt = 0n;
1254
+ for (const asset of supportedAssets) {
1255
+ try {
1256
+ const assetAddress = viem.getAddress(asset.address);
1257
+ const result = await agent.client.readContract({
1258
+ address: dataProviderAddress,
1259
+ abi: PROTOCOL_DATA_PROVIDER_ABI,
1260
+ functionName: "getUserReserveData",
1261
+ args: [assetAddress, address]
1262
+ });
1263
+ const [
1264
+ currentATokenBalance,
1265
+ currentStableDebt,
1266
+ currentVariableDebt,
1267
+ _principalStableDebt,
1268
+ _scaledVariableDebt,
1269
+ stableBorrowRate,
1270
+ liquidityRate,
1271
+ _stableRateLastUpdated,
1272
+ usageAsCollateralEnabled
1273
+ ] = result;
1274
+ if (currentATokenBalance > 0n || currentStableDebt > 0n || currentVariableDebt > 0n) {
1275
+ const assetTotalDebt = currentStableDebt + currentVariableDebt;
1276
+ positions.push({
1277
+ asset: assetAddress,
1278
+ symbol: asset.symbol,
1279
+ supplied: currentATokenBalance,
1280
+ stableDebt: currentStableDebt,
1281
+ variableDebt: currentVariableDebt,
1282
+ totalDebt: assetTotalDebt,
1283
+ liquidityRate,
1284
+ stableBorrowRate,
1285
+ usageAsCollateralEnabled
1286
+ });
1287
+ totalSupplied += currentATokenBalance;
1288
+ totalDebt += assetTotalDebt;
1289
+ }
1290
+ } catch (error) {
1291
+ console.warn(`Failed to get position for ${asset.symbol}:`, error);
1292
+ }
1293
+ }
1294
+ return {
1295
+ positions,
1296
+ totalSupplied,
1297
+ totalDebt
1298
+ };
1299
+ }
1030
1300
 
1031
1301
  // src/constants/agni/index.ts
1032
1302
  var agni_exports = {};
@@ -1088,6 +1358,9 @@ var FEE_TIERS2 = {
1088
1358
  async function agniSwap(agent, tokenIn, tokenOut, amountIn, slippagePercent = 0.5, feeTier = FEE_TIERS2.MEDIUM) {
1089
1359
  const swapRouterAddress = SWAP_ROUTER[agent.chain];
1090
1360
  if (swapRouterAddress === "0x0000000000000000000000000000000000000000") {
1361
+ if (agent.demo) {
1362
+ return createMockSwapResponse("Agni", amountIn).txHash;
1363
+ }
1091
1364
  throw new Error(`Agni SwapRouter not available on ${agent.chain}`);
1092
1365
  }
1093
1366
  const amountInBigInt = BigInt(amountIn);
@@ -1160,6 +1433,9 @@ var LB_ROUTER_ABI = [
1160
1433
  async function merchantMoeSwap(agent, tokenIn, tokenOut, amountIn, slippagePercent = 0.5) {
1161
1434
  const routerAddress = LB_ROUTER[agent.chain];
1162
1435
  if (routerAddress === "0x0000000000000000000000000000000000000000") {
1436
+ if (agent.demo) {
1437
+ return createMockSwapResponse("MerchantMoe", amountIn).txHash;
1438
+ }
1163
1439
  throw new Error(`Merchant Moe LB Router not available on ${agent.chain}`);
1164
1440
  }
1165
1441
  const amountInBigInt = BigInt(amountIn);
@@ -1183,15 +1459,742 @@ async function merchantMoeSwap(agent, tokenIn, tokenOut, amountIn, slippagePerce
1183
1459
  // src/constants/meth/index.ts
1184
1460
  var meth_exports = {};
1185
1461
  __export(meth_exports, {
1186
- METH_TOKEN: () => METH_TOKEN
1462
+ METH_ABI: () => METH_ABI,
1463
+ METH_TOKEN: () => METH_TOKEN,
1464
+ NATIVE_MNT_ADDRESS: () => NATIVE_MNT_ADDRESS,
1465
+ WETH_TOKEN: () => WETH_TOKEN,
1466
+ WMNT_TOKEN: () => WMNT_TOKEN
1187
1467
  });
1188
1468
  var METH_TOKEN = {
1189
1469
  mainnet: "0xcDA86A272531e8640cD7F1a92c01839911B90bb0",
1190
1470
  testnet: "0x0000000000000000000000000000000000000000"
1191
1471
  };
1472
+ var WETH_TOKEN = {
1473
+ mainnet: "0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111",
1474
+ testnet: "0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111"
1475
+ };
1476
+ var WMNT_TOKEN = {
1477
+ mainnet: "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8",
1478
+ testnet: "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8"
1479
+ };
1480
+ var NATIVE_MNT_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
1481
+ var METH_ABI = [
1482
+ {
1483
+ inputs: [{ name: "account", type: "address" }],
1484
+ name: "balanceOf",
1485
+ outputs: [{ name: "", type: "uint256" }],
1486
+ stateMutability: "view",
1487
+ type: "function"
1488
+ },
1489
+ {
1490
+ inputs: [],
1491
+ name: "totalSupply",
1492
+ outputs: [{ name: "", type: "uint256" }],
1493
+ stateMutability: "view",
1494
+ type: "function"
1495
+ },
1496
+ {
1497
+ inputs: [],
1498
+ name: "decimals",
1499
+ outputs: [{ name: "", type: "uint8" }],
1500
+ stateMutability: "view",
1501
+ type: "function"
1502
+ },
1503
+ {
1504
+ inputs: [],
1505
+ name: "symbol",
1506
+ outputs: [{ name: "", type: "string" }],
1507
+ stateMutability: "view",
1508
+ type: "function"
1509
+ },
1510
+ {
1511
+ inputs: [
1512
+ { name: "spender", type: "address" },
1513
+ { name: "amount", type: "uint256" }
1514
+ ],
1515
+ name: "approve",
1516
+ outputs: [{ name: "", type: "bool" }],
1517
+ stateMutability: "nonpayable",
1518
+ type: "function"
1519
+ },
1520
+ {
1521
+ inputs: [
1522
+ { name: "owner", type: "address" },
1523
+ { name: "spender", type: "address" }
1524
+ ],
1525
+ name: "allowance",
1526
+ outputs: [{ name: "", type: "uint256" }],
1527
+ stateMutability: "view",
1528
+ type: "function"
1529
+ }
1530
+ ];
1531
+ async function methGetPosition(agent, userAddress) {
1532
+ const methTokenAddress = METH_TOKEN[agent.chain];
1533
+ const wethTokenAddress = WETH_TOKEN[agent.chain];
1534
+ const wmntTokenAddress = WMNT_TOKEN[agent.chain];
1535
+ const address = userAddress || agent.account.address;
1536
+ if (methTokenAddress === "0x0000000000000000000000000000000000000000") {
1537
+ throw new Error(
1538
+ `mETH not available on ${agent.chain}. Only available on mainnet.`
1539
+ );
1540
+ }
1541
+ const methBalance = await agent.client.readContract({
1542
+ address: methTokenAddress,
1543
+ abi: METH_ABI,
1544
+ functionName: "balanceOf",
1545
+ args: [address]
1546
+ });
1547
+ let wethBalance = 0n;
1548
+ try {
1549
+ wethBalance = await agent.client.readContract({
1550
+ address: wethTokenAddress,
1551
+ abi: METH_ABI,
1552
+ // Same ERC20 ABI works for WETH
1553
+ functionName: "balanceOf",
1554
+ args: [address]
1555
+ });
1556
+ } catch {
1557
+ }
1558
+ let wmntBalance = 0n;
1559
+ try {
1560
+ wmntBalance = await agent.client.readContract({
1561
+ address: wmntTokenAddress,
1562
+ abi: METH_ABI,
1563
+ // Same ERC20 ABI works for WMNT
1564
+ functionName: "balanceOf",
1565
+ args: [address]
1566
+ });
1567
+ } catch {
1568
+ }
1569
+ return {
1570
+ methBalance,
1571
+ wethBalance,
1572
+ wmntBalance,
1573
+ methTokenAddress,
1574
+ wethTokenAddress,
1575
+ wmntTokenAddress
1576
+ };
1577
+ }
1578
+ async function swapToMeth(agent, amount, slippage = 0.5) {
1579
+ const methTokenAddress = METH_TOKEN[agent.chain];
1580
+ const wethTokenAddress = WETH_TOKEN[agent.chain];
1581
+ if (methTokenAddress === "0x0000000000000000000000000000000000000000") {
1582
+ throw new Error(
1583
+ `mETH not available on ${agent.chain}. Only available on mainnet.`
1584
+ );
1585
+ }
1586
+ const result = await swapOnOpenOcean(
1587
+ agent,
1588
+ wethTokenAddress,
1589
+ methTokenAddress,
1590
+ amount,
1591
+ slippage.toString()
1592
+ );
1593
+ return result.txHash;
1594
+ }
1595
+ async function swapFromMeth(agent, amount, slippage = 0.5) {
1596
+ const methTokenAddress = METH_TOKEN[agent.chain];
1597
+ const wethTokenAddress = WETH_TOKEN[agent.chain];
1598
+ if (methTokenAddress === "0x0000000000000000000000000000000000000000") {
1599
+ throw new Error(
1600
+ `mETH not available on ${agent.chain}. Only available on mainnet.`
1601
+ );
1602
+ }
1603
+ const result = await swapOnOpenOcean(
1604
+ agent,
1605
+ methTokenAddress,
1606
+ wethTokenAddress,
1607
+ amount,
1608
+ slippage.toString()
1609
+ );
1610
+ return result.txHash;
1611
+ }
1612
+
1613
+ // src/constants/pikeperps/index.ts
1614
+ var pikeperps_exports = {};
1615
+ __export(pikeperps_exports, {
1616
+ BONDING_CURVE_MARKET: () => BONDING_CURVE_MARKET,
1617
+ BONDING_CURVE_MARKET_ABI: () => BONDING_CURVE_MARKET_ABI,
1618
+ PERPETUAL_TRADING: () => PERPETUAL_TRADING,
1619
+ PERPETUAL_TRADING_ABI: () => PERPETUAL_TRADING_ABI,
1620
+ PIKE_PERPS_CONFIG: () => PIKE_PERPS_CONFIG
1621
+ });
1622
+ var PERPETUAL_TRADING = {
1623
+ mainnet: "0x0000000000000000000000000000000000000000",
1624
+ // Not deployed yet
1625
+ testnet: "0x8081b646f349c049f2d5e8a400057d411dd657bd"
1626
+ };
1627
+ var BONDING_CURVE_MARKET = {
1628
+ mainnet: "0x0000000000000000000000000000000000000000",
1629
+ testnet: "0x93b268325A9862645c82b32229f3B52264750Ca2"
1630
+ };
1631
+ var PIKE_PERPS_CONFIG = {
1632
+ MAX_LEVERAGE: 100,
1633
+ DEFAULT_LEVERAGE: 10,
1634
+ MIN_LEVERAGE: 1,
1635
+ TRADING_FEE_BPS: 5,
1636
+ // 0.05%
1637
+ LIQUIDATION_REWARD_BPS: 500,
1638
+ // 5%
1639
+ PRICE_DECIMALS: 8
1640
+ // Prices are scaled by 1e8
1641
+ };
1642
+ var PERPETUAL_TRADING_ABI = [
1643
+ {
1644
+ inputs: [
1645
+ { internalType: "address", name: "_pyth", type: "address" }
1646
+ ],
1647
+ stateMutability: "nonpayable",
1648
+ type: "constructor"
1649
+ },
1650
+ {
1651
+ anonymous: false,
1652
+ inputs: [
1653
+ { indexed: true, internalType: "uint256", name: "positionId", type: "uint256" },
1654
+ { indexed: true, internalType: "address", name: "user", type: "address" },
1655
+ { indexed: false, internalType: "uint256", name: "pnl", type: "uint256" },
1656
+ { indexed: false, internalType: "uint256", name: "exitPrice", type: "uint256" }
1657
+ ],
1658
+ name: "PositionClosed",
1659
+ type: "event"
1660
+ },
1661
+ {
1662
+ anonymous: false,
1663
+ inputs: [
1664
+ { indexed: true, internalType: "uint256", name: "positionId", type: "uint256" },
1665
+ { indexed: true, internalType: "address", name: "user", type: "address" },
1666
+ { indexed: false, internalType: "uint256", name: "liquidationPrice", type: "uint256" }
1667
+ ],
1668
+ name: "PositionLiquidated",
1669
+ type: "event"
1670
+ },
1671
+ {
1672
+ anonymous: false,
1673
+ inputs: [
1674
+ { indexed: true, internalType: "uint256", name: "positionId", type: "uint256" },
1675
+ { indexed: true, internalType: "address", name: "user", type: "address" },
1676
+ { indexed: true, internalType: "address", name: "token", type: "address" },
1677
+ { indexed: false, internalType: "bool", name: "isLong", type: "bool" },
1678
+ { indexed: false, internalType: "uint256", name: "size", type: "uint256" },
1679
+ { indexed: false, internalType: "uint256", name: "margin", type: "uint256" },
1680
+ { indexed: false, internalType: "uint256", name: "leverage", type: "uint256" },
1681
+ { indexed: false, internalType: "uint256", name: "entryPrice", type: "uint256" }
1682
+ ],
1683
+ name: "PositionOpened",
1684
+ type: "event"
1685
+ },
1686
+ {
1687
+ inputs: [{ internalType: "uint256", name: "_positionId", type: "uint256" }],
1688
+ name: "closePosition",
1689
+ outputs: [],
1690
+ stateMutability: "nonpayable",
1691
+ type: "function"
1692
+ },
1693
+ {
1694
+ inputs: [{ internalType: "address", name: "_token", type: "address" }],
1695
+ name: "getCurrentPrice",
1696
+ outputs: [
1697
+ { internalType: "uint256", name: "currentPrice", type: "uint256" },
1698
+ { internalType: "bool", name: "hasPrice", type: "bool" }
1699
+ ],
1700
+ stateMutability: "view",
1701
+ type: "function"
1702
+ },
1703
+ {
1704
+ inputs: [{ internalType: "uint256", name: "_positionId", type: "uint256" }],
1705
+ name: "getLiquidationPrice",
1706
+ outputs: [{ internalType: "uint256", name: "liquidationPrice", type: "uint256" }],
1707
+ stateMutability: "view",
1708
+ type: "function"
1709
+ },
1710
+ {
1711
+ inputs: [{ internalType: "uint256", name: "_positionId", type: "uint256" }],
1712
+ name: "getPosition",
1713
+ outputs: [
1714
+ {
1715
+ components: [
1716
+ { internalType: "address", name: "user", type: "address" },
1717
+ { internalType: "address", name: "token", type: "address" },
1718
+ { internalType: "bool", name: "isLong", type: "bool" },
1719
+ { internalType: "uint256", name: "size", type: "uint256" },
1720
+ { internalType: "uint256", name: "margin", type: "uint256" },
1721
+ { internalType: "uint256", name: "leverage", type: "uint256" },
1722
+ { internalType: "uint256", name: "entryPrice", type: "uint256" },
1723
+ { internalType: "uint256", name: "entryTime", type: "uint256" },
1724
+ { internalType: "uint256", name: "lastFundingTime", type: "uint256" },
1725
+ { internalType: "bool", name: "isOpen", type: "bool" }
1726
+ ],
1727
+ internalType: "struct PerpetualTrading.Position",
1728
+ name: "",
1729
+ type: "tuple"
1730
+ }
1731
+ ],
1732
+ stateMutability: "view",
1733
+ type: "function"
1734
+ },
1735
+ {
1736
+ inputs: [{ internalType: "uint256", name: "_positionId", type: "uint256" }],
1737
+ name: "getPositionPnL",
1738
+ outputs: [
1739
+ { internalType: "uint256", name: "pnl", type: "uint256" },
1740
+ { internalType: "bool", name: "isProfit", type: "bool" }
1741
+ ],
1742
+ stateMutability: "view",
1743
+ type: "function"
1744
+ },
1745
+ {
1746
+ inputs: [{ internalType: "address", name: "_user", type: "address" }],
1747
+ name: "getUserPositions",
1748
+ outputs: [{ internalType: "uint256[]", name: "", type: "uint256[]" }],
1749
+ stateMutability: "view",
1750
+ type: "function"
1751
+ },
1752
+ {
1753
+ inputs: [{ internalType: "uint256", name: "_positionId", type: "uint256" }],
1754
+ name: "liquidatePosition",
1755
+ outputs: [],
1756
+ stateMutability: "nonpayable",
1757
+ type: "function"
1758
+ },
1759
+ {
1760
+ inputs: [],
1761
+ name: "maxLeverage",
1762
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
1763
+ stateMutability: "view",
1764
+ type: "function"
1765
+ },
1766
+ {
1767
+ inputs: [],
1768
+ name: "minMarginBps",
1769
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
1770
+ stateMutability: "view",
1771
+ type: "function"
1772
+ },
1773
+ {
1774
+ inputs: [],
1775
+ name: "nextPositionId",
1776
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
1777
+ stateMutability: "view",
1778
+ type: "function"
1779
+ },
1780
+ {
1781
+ inputs: [
1782
+ { internalType: "address", name: "_token", type: "address" },
1783
+ { internalType: "bool", name: "_isLong", type: "bool" },
1784
+ { internalType: "uint256", name: "_margin", type: "uint256" },
1785
+ { internalType: "uint256", name: "_leverage", type: "uint256" }
1786
+ ],
1787
+ name: "openPosition",
1788
+ outputs: [{ internalType: "uint256", name: "positionId", type: "uint256" }],
1789
+ stateMutability: "payable",
1790
+ type: "function"
1791
+ },
1792
+ {
1793
+ inputs: [{ internalType: "uint256", name: "_positionId", type: "uint256" }],
1794
+ name: "shouldLiquidate",
1795
+ outputs: [{ internalType: "bool", name: "", type: "bool" }],
1796
+ stateMutability: "view",
1797
+ type: "function"
1798
+ },
1799
+ {
1800
+ inputs: [],
1801
+ name: "tradingFeeBps",
1802
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
1803
+ stateMutability: "view",
1804
+ type: "function"
1805
+ }
1806
+ ];
1807
+ var BONDING_CURVE_MARKET_ABI = [
1808
+ {
1809
+ inputs: [{ internalType: "address", name: "_token", type: "address" }],
1810
+ name: "getCurrentPrice",
1811
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
1812
+ stateMutability: "view",
1813
+ type: "function"
1814
+ },
1815
+ {
1816
+ inputs: [{ internalType: "address", name: "_token", type: "address" }],
1817
+ name: "isListed",
1818
+ outputs: [{ internalType: "bool", name: "", type: "bool" }],
1819
+ stateMutability: "view",
1820
+ type: "function"
1821
+ },
1822
+ {
1823
+ inputs: [{ internalType: "address", name: "_token", type: "address" }],
1824
+ name: "getCurveProgress",
1825
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
1826
+ stateMutability: "view",
1827
+ type: "function"
1828
+ }
1829
+ ];
1830
+
1831
+ // src/tools/pikeperps/openLong.ts
1832
+ async function pikeperpsOpenLong(agent, tokenAddress, margin, leverage = PIKE_PERPS_CONFIG.DEFAULT_LEVERAGE) {
1833
+ const perpetualTradingAddress = PERPETUAL_TRADING[agent.chain];
1834
+ if (perpetualTradingAddress === "0x0000000000000000000000000000000000000000") {
1835
+ throw new Error(
1836
+ `PikePerps not available on ${agent.chain}. Only available on testnet.`
1837
+ );
1838
+ }
1839
+ if (leverage < PIKE_PERPS_CONFIG.MIN_LEVERAGE || leverage > PIKE_PERPS_CONFIG.MAX_LEVERAGE) {
1840
+ throw new Error(
1841
+ `Leverage must be between ${PIKE_PERPS_CONFIG.MIN_LEVERAGE} and ${PIKE_PERPS_CONFIG.MAX_LEVERAGE}`
1842
+ );
1843
+ }
1844
+ if (agent.demo) {
1845
+ return {
1846
+ positionId: BigInt(Math.floor(Math.random() * 1e3)),
1847
+ txHash: "0xdemo_open_long_tx_hash"
1848
+ };
1849
+ }
1850
+ const marginBigInt = BigInt(margin);
1851
+ const data = viem.encodeFunctionData({
1852
+ abi: PERPETUAL_TRADING_ABI,
1853
+ functionName: "openPosition",
1854
+ args: [tokenAddress, true, marginBigInt, BigInt(leverage)]
1855
+ });
1856
+ const txHash = await agent.client.sendTransaction({
1857
+ to: perpetualTradingAddress,
1858
+ data,
1859
+ value: marginBigInt
1860
+ });
1861
+ const receipt = await agent.client.waitForTransactionReceipt({ hash: txHash });
1862
+ let positionId = 0n;
1863
+ for (const log of receipt.logs) {
1864
+ try {
1865
+ if (log.topics[0] === "0x2e5b0e8c5f5d55d89e89f5b5d5e5f5d55d89e89f5b5d5e5f5d55d89e89f5b5d5") {
1866
+ positionId = BigInt(log.topics[1] || "0");
1867
+ break;
1868
+ }
1869
+ } catch {
1870
+ }
1871
+ }
1872
+ if (positionId === 0n) {
1873
+ try {
1874
+ const nextId = await agent.client.readContract({
1875
+ address: perpetualTradingAddress,
1876
+ abi: PERPETUAL_TRADING_ABI,
1877
+ functionName: "nextPositionId"
1878
+ });
1879
+ positionId = nextId - 1n;
1880
+ } catch {
1881
+ }
1882
+ }
1883
+ return {
1884
+ positionId,
1885
+ txHash
1886
+ };
1887
+ }
1888
+ async function pikeperpsOpenShort(agent, tokenAddress, margin, leverage = PIKE_PERPS_CONFIG.DEFAULT_LEVERAGE) {
1889
+ const perpetualTradingAddress = PERPETUAL_TRADING[agent.chain];
1890
+ if (perpetualTradingAddress === "0x0000000000000000000000000000000000000000") {
1891
+ throw new Error(
1892
+ `PikePerps not available on ${agent.chain}. Only available on testnet.`
1893
+ );
1894
+ }
1895
+ if (leverage < PIKE_PERPS_CONFIG.MIN_LEVERAGE || leverage > PIKE_PERPS_CONFIG.MAX_LEVERAGE) {
1896
+ throw new Error(
1897
+ `Leverage must be between ${PIKE_PERPS_CONFIG.MIN_LEVERAGE} and ${PIKE_PERPS_CONFIG.MAX_LEVERAGE}`
1898
+ );
1899
+ }
1900
+ if (agent.demo) {
1901
+ return {
1902
+ positionId: BigInt(Math.floor(Math.random() * 1e3)),
1903
+ txHash: "0xdemo_open_short_tx_hash"
1904
+ };
1905
+ }
1906
+ const marginBigInt = BigInt(margin);
1907
+ const data = viem.encodeFunctionData({
1908
+ abi: PERPETUAL_TRADING_ABI,
1909
+ functionName: "openPosition",
1910
+ args: [tokenAddress, false, marginBigInt, BigInt(leverage)]
1911
+ });
1912
+ const txHash = await agent.client.sendTransaction({
1913
+ to: perpetualTradingAddress,
1914
+ data,
1915
+ value: marginBigInt
1916
+ });
1917
+ const receipt = await agent.client.waitForTransactionReceipt({ hash: txHash });
1918
+ let positionId = 0n;
1919
+ for (const log of receipt.logs) {
1920
+ try {
1921
+ if (log.topics[0] === "0x2e5b0e8c5f5d55d89e89f5b5d5e5f5d55d89e89f5b5d5e5f5d55d89e89f5b5d5") {
1922
+ positionId = BigInt(log.topics[1] || "0");
1923
+ break;
1924
+ }
1925
+ } catch {
1926
+ }
1927
+ }
1928
+ if (positionId === 0n) {
1929
+ try {
1930
+ const nextId = await agent.client.readContract({
1931
+ address: perpetualTradingAddress,
1932
+ abi: PERPETUAL_TRADING_ABI,
1933
+ functionName: "nextPositionId"
1934
+ });
1935
+ positionId = nextId - 1n;
1936
+ } catch {
1937
+ }
1938
+ }
1939
+ return {
1940
+ positionId,
1941
+ txHash
1942
+ };
1943
+ }
1944
+ async function pikeperpsClosePosition(agent, positionId) {
1945
+ const perpetualTradingAddress = PERPETUAL_TRADING[agent.chain];
1946
+ if (perpetualTradingAddress === "0x0000000000000000000000000000000000000000") {
1947
+ throw new Error(
1948
+ `PikePerps not available on ${agent.chain}. Only available on testnet.`
1949
+ );
1950
+ }
1951
+ if (agent.demo) {
1952
+ return "0xdemo_close_position_tx_hash";
1953
+ }
1954
+ const data = viem.encodeFunctionData({
1955
+ abi: PERPETUAL_TRADING_ABI,
1956
+ functionName: "closePosition",
1957
+ args: [positionId]
1958
+ });
1959
+ const txHash = await agent.client.sendTransaction({
1960
+ to: perpetualTradingAddress,
1961
+ data
1962
+ });
1963
+ await agent.client.waitForTransactionReceipt({ hash: txHash });
1964
+ return txHash;
1965
+ }
1966
+ async function pikeperpsGetPositions(agent, userAddress) {
1967
+ const perpetualTradingAddress = PERPETUAL_TRADING[agent.chain];
1968
+ const address = userAddress || agent.account.address;
1969
+ if (perpetualTradingAddress === "0x0000000000000000000000000000000000000000") {
1970
+ throw new Error(
1971
+ `PikePerps not available on ${agent.chain}. Only available on testnet.`
1972
+ );
1973
+ }
1974
+ if (agent.demo) {
1975
+ return [
1976
+ {
1977
+ positionId: 1n,
1978
+ token: "0x0000000000000000000000000000000000000001",
1979
+ isLong: true,
1980
+ size: BigInt("1000000000000000000"),
1981
+ // 1 ETH equivalent
1982
+ margin: BigInt("100000000000000000"),
1983
+ // 0.1 ETH
1984
+ leverage: 10,
1985
+ entryPrice: BigInt("100000000"),
1986
+ // $1.00 scaled by 1e8
1987
+ entryTime: BigInt(Math.floor(Date.now() / 1e3) - 3600),
1988
+ currentPrice: BigInt("110000000"),
1989
+ // $1.10
1990
+ pnl: BigInt("10000000000000000"),
1991
+ // 0.01 ETH profit
1992
+ isProfit: true,
1993
+ liquidationPrice: BigInt("90000000"),
1994
+ // $0.90
1995
+ isOpen: true
1996
+ }
1997
+ ];
1998
+ }
1999
+ const positionIds = await agent.client.readContract({
2000
+ address: perpetualTradingAddress,
2001
+ abi: PERPETUAL_TRADING_ABI,
2002
+ functionName: "getUserPositions",
2003
+ args: [address]
2004
+ });
2005
+ if (positionIds.length === 0) {
2006
+ return [];
2007
+ }
2008
+ const positions = [];
2009
+ for (const positionId of positionIds) {
2010
+ try {
2011
+ const rawPosition = await agent.client.readContract({
2012
+ address: perpetualTradingAddress,
2013
+ abi: PERPETUAL_TRADING_ABI,
2014
+ functionName: "getPosition",
2015
+ args: [positionId]
2016
+ });
2017
+ if (!rawPosition.isOpen) {
2018
+ continue;
2019
+ }
2020
+ const [pnl, isProfit] = await agent.client.readContract({
2021
+ address: perpetualTradingAddress,
2022
+ abi: PERPETUAL_TRADING_ABI,
2023
+ functionName: "getPositionPnL",
2024
+ args: [positionId]
2025
+ });
2026
+ const liquidationPrice = await agent.client.readContract({
2027
+ address: perpetualTradingAddress,
2028
+ abi: PERPETUAL_TRADING_ABI,
2029
+ functionName: "getLiquidationPrice",
2030
+ args: [positionId]
2031
+ });
2032
+ let currentPrice = 0n;
2033
+ try {
2034
+ const [price, hasPrice] = await agent.client.readContract({
2035
+ address: perpetualTradingAddress,
2036
+ abi: PERPETUAL_TRADING_ABI,
2037
+ functionName: "getCurrentPrice",
2038
+ args: [rawPosition.token]
2039
+ });
2040
+ if (hasPrice) {
2041
+ currentPrice = price;
2042
+ }
2043
+ } catch {
2044
+ currentPrice = rawPosition.entryPrice;
2045
+ }
2046
+ positions.push({
2047
+ positionId,
2048
+ token: rawPosition.token,
2049
+ isLong: rawPosition.isLong,
2050
+ size: rawPosition.size,
2051
+ margin: rawPosition.margin,
2052
+ leverage: Number(rawPosition.leverage),
2053
+ entryPrice: rawPosition.entryPrice,
2054
+ entryTime: rawPosition.entryTime,
2055
+ currentPrice,
2056
+ pnl,
2057
+ isProfit,
2058
+ liquidationPrice,
2059
+ isOpen: rawPosition.isOpen
2060
+ });
2061
+ } catch (error) {
2062
+ console.warn(`Failed to fetch position ${positionId}:`, error);
2063
+ }
2064
+ }
2065
+ return positions;
2066
+ }
2067
+ async function pikeperpsGetMarketData(agent, tokenAddress, limit = 20) {
2068
+ const perpetualTradingAddress = PERPETUAL_TRADING[agent.chain];
2069
+ const bondingCurveAddress = BONDING_CURVE_MARKET[agent.chain];
2070
+ if (perpetualTradingAddress === "0x0000000000000000000000000000000000000000") {
2071
+ throw new Error(
2072
+ `PikePerps not available on ${agent.chain}. Only available on testnet.`
2073
+ );
2074
+ }
2075
+ if (agent.demo) {
2076
+ return {
2077
+ token: tokenAddress,
2078
+ currentPrice: BigInt("100000000"),
2079
+ // $1.00 scaled by 1e8
2080
+ hasPrice: true,
2081
+ isListed: true,
2082
+ curveProgress: BigInt("5000"),
2083
+ // 50%
2084
+ recentTrades: [
2085
+ {
2086
+ positionId: 1n,
2087
+ trader: "0x0000000000000000000000000000000000000001",
2088
+ token: tokenAddress,
2089
+ isLong: true,
2090
+ size: BigInt("1000000000000000000"),
2091
+ margin: BigInt("100000000000000000"),
2092
+ leverage: 10n,
2093
+ entryPrice: BigInt("100000000"),
2094
+ timestamp: Math.floor(Date.now() / 1e3) - 300,
2095
+ txHash: "0xdemo_trade_hash",
2096
+ blockNumber: 1000n
2097
+ }
2098
+ ]
2099
+ };
2100
+ }
2101
+ let currentPrice = 0n;
2102
+ let hasPrice = false;
2103
+ try {
2104
+ const [price, hasPriceResult] = await agent.client.readContract({
2105
+ address: perpetualTradingAddress,
2106
+ abi: PERPETUAL_TRADING_ABI,
2107
+ functionName: "getCurrentPrice",
2108
+ args: [tokenAddress]
2109
+ });
2110
+ currentPrice = price;
2111
+ hasPrice = hasPriceResult;
2112
+ } catch {
2113
+ }
2114
+ let isListed = false;
2115
+ let curveProgress = 0n;
2116
+ if (bondingCurveAddress !== "0x0000000000000000000000000000000000000000") {
2117
+ try {
2118
+ isListed = await agent.client.readContract({
2119
+ address: bondingCurveAddress,
2120
+ abi: BONDING_CURVE_MARKET_ABI,
2121
+ functionName: "isListed",
2122
+ args: [tokenAddress]
2123
+ });
2124
+ if (isListed) {
2125
+ curveProgress = await agent.client.readContract({
2126
+ address: bondingCurveAddress,
2127
+ abi: BONDING_CURVE_MARKET_ABI,
2128
+ functionName: "getCurveProgress",
2129
+ args: [tokenAddress]
2130
+ });
2131
+ }
2132
+ } catch {
2133
+ }
2134
+ }
2135
+ const recentTrades = [];
2136
+ try {
2137
+ const currentBlock = await agent.client.getBlockNumber();
2138
+ const fromBlock = currentBlock > 1000n ? currentBlock - 1000n : 0n;
2139
+ const logs = await agent.client.getLogs({
2140
+ address: perpetualTradingAddress,
2141
+ event: viem.parseAbiItem(
2142
+ "event PositionOpened(uint256 indexed positionId, address indexed user, address indexed token, bool isLong, uint256 size, uint256 margin, uint256 leverage, uint256 entryPrice)"
2143
+ ),
2144
+ args: {
2145
+ token: tokenAddress
2146
+ },
2147
+ fromBlock,
2148
+ toBlock: currentBlock
2149
+ });
2150
+ const blockCache = /* @__PURE__ */ new Map();
2151
+ for (const log of logs.slice(-limit)) {
2152
+ let timestamp = 0;
2153
+ if (!blockCache.has(log.blockNumber)) {
2154
+ try {
2155
+ const block = await agent.client.getBlock({
2156
+ blockNumber: log.blockNumber
2157
+ });
2158
+ timestamp = Number(block.timestamp);
2159
+ blockCache.set(log.blockNumber, timestamp);
2160
+ } catch {
2161
+ timestamp = Math.floor(Date.now() / 1e3);
2162
+ }
2163
+ } else {
2164
+ timestamp = blockCache.get(log.blockNumber) || 0;
2165
+ }
2166
+ recentTrades.push({
2167
+ positionId: BigInt(log.topics[1] || "0"),
2168
+ trader: log.topics[2],
2169
+ token: tokenAddress,
2170
+ isLong: log.args.isLong || false,
2171
+ size: log.args.size || 0n,
2172
+ margin: log.args.margin || 0n,
2173
+ leverage: log.args.leverage || 0n,
2174
+ entryPrice: log.args.entryPrice || 0n,
2175
+ timestamp,
2176
+ txHash: log.transactionHash,
2177
+ blockNumber: log.blockNumber
2178
+ });
2179
+ }
2180
+ } catch (error) {
2181
+ console.warn("Failed to fetch recent trades:", error);
2182
+ }
2183
+ return {
2184
+ token: tokenAddress,
2185
+ currentPrice,
2186
+ hasPrice,
2187
+ isListed,
2188
+ curveProgress,
2189
+ recentTrades
2190
+ };
2191
+ }
1192
2192
 
1193
2193
  // src/tools/okx/getSwapQuote.ts
1194
2194
  var getSwapQuote = async (agent, from, to, amount, slippagePercentage) => {
2195
+ if (agent.demo) {
2196
+ return createMockQuoteResponse("OKX", amount);
2197
+ }
1195
2198
  const chainIndex = agent.chain === "mainnet" ? "5000" : "5003";
1196
2199
  return getSwapTransaction(from, to, amount, chainIndex, slippagePercentage);
1197
2200
  };
@@ -1278,21 +2281,44 @@ function getProjectConfig() {
1278
2281
  }
1279
2282
  return cachedConfig;
1280
2283
  }
1281
-
1282
- // src/agent.ts
2284
+ async function getUserAccountData(agent, userAddress) {
2285
+ const lendingPoolAddress = LENDING_POOL[agent.chain];
2286
+ const address = userAddress || agent.account.address;
2287
+ if (lendingPoolAddress === "0x0000000000000000000000000000000000000000") {
2288
+ throw new Error(
2289
+ `Lendle LendingPool not configured for ${agent.chain}. Only available on mainnet.`
2290
+ );
2291
+ }
2292
+ const result = await agent.client.readContract({
2293
+ address: lendingPoolAddress,
2294
+ abi: LENDING_POOL_ABI,
2295
+ functionName: "getUserAccountData",
2296
+ args: [address]
2297
+ });
2298
+ return {
2299
+ totalCollateralETH: result[0],
2300
+ totalDebtETH: result[1],
2301
+ availableBorrowsETH: result[2],
2302
+ currentLiquidationThreshold: result[3],
2303
+ ltv: result[4],
2304
+ healthFactor: result[5]
2305
+ };
2306
+ }
1283
2307
  var MNTAgentKit = class {
1284
2308
  account;
1285
2309
  client;
1286
2310
  chain;
2311
+ demo;
1287
2312
  projectConfig;
1288
2313
  constructor(privateKey, chain) {
1289
2314
  this.account = accounts.privateKeyToAccount(privateKey);
1290
- this.chain = chain;
2315
+ this.demo = chain === "testnet-demo";
2316
+ this.chain = chain === "testnet-demo" ? "testnet" : chain;
1291
2317
  this.client = viem.createWalletClient({
1292
- chain: chain == "mainnet" ? chains.mantle : chains.mantleSepoliaTestnet,
2318
+ chain: this.chain == "mainnet" ? chains.mantle : chains.mantleSepoliaTestnet,
1293
2319
  transport: viem.http(),
1294
2320
  account: this.account
1295
- }).extend(viem.publicActions);
2321
+ }).extend(viem.publicActions).extend(experimental.erc7811Actions());
1296
2322
  }
1297
2323
  /**
1298
2324
  * Initialize the agent with platform validation
@@ -1327,15 +2353,13 @@ var MNTAgentKit = class {
1327
2353
  );
1328
2354
  }
1329
2355
  async executeSwap(fromTokenAddress, toTokenAddress, amount, slippagePercentage = "0.5") {
1330
- if (this.chain === "mainnet") {
1331
- return await executeSwap(
1332
- this,
1333
- fromTokenAddress,
1334
- toTokenAddress,
1335
- amount,
1336
- slippagePercentage
1337
- );
1338
- }
2356
+ return await executeSwap(
2357
+ this,
2358
+ fromTokenAddress,
2359
+ toTokenAddress,
2360
+ amount,
2361
+ slippagePercentage
2362
+ );
1339
2363
  }
1340
2364
  // OpenOcean DEX Aggregator
1341
2365
  async getOpenOceanQuote(fromToken, toToken, amount) {
@@ -1395,6 +2419,24 @@ var MNTAgentKit = class {
1395
2419
  async lendleRepay(tokenAddress, amount, rateMode = 2, onBehalfOf) {
1396
2420
  return await lendleRepay(this, tokenAddress, amount, rateMode, onBehalfOf);
1397
2421
  }
2422
+ /**
2423
+ * Get user account data from Lendle LendingPool
2424
+ * Returns overall position including total collateral, debt, and health factor
2425
+ * @param userAddress - User wallet address (optional, defaults to agent account)
2426
+ * @returns User account data with collateral, debt, available borrows, and health factor
2427
+ */
2428
+ async lendleGetUserAccountData(userAddress) {
2429
+ return await getUserAccountData(this, userAddress);
2430
+ }
2431
+ /**
2432
+ * Get all Lendle positions for a user (per-token breakdown)
2433
+ * Returns detailed supply and borrow amounts for each asset
2434
+ * @param userAddress - User wallet address (optional, defaults to agent account)
2435
+ * @returns Array of positions with supply/borrow amounts per asset
2436
+ */
2437
+ async lendleGetPositions(userAddress) {
2438
+ return await lendleGetPositions(this, userAddress);
2439
+ }
1398
2440
  // Agni Finance DEX (#1 on Mantle)
1399
2441
  async agniSwap(tokenIn, tokenOut, amountIn, slippagePercent = 0.5, feeTier) {
1400
2442
  return await agniSwap(
@@ -1418,8 +2460,38 @@ var MNTAgentKit = class {
1418
2460
  }
1419
2461
  // mETH Protocol - Liquid Staking Token
1420
2462
  getMethTokenAddress() {
2463
+ if (this.demo) {
2464
+ return METH_TOKEN.mainnet;
2465
+ }
1421
2466
  return METH_TOKEN[this.chain];
1422
2467
  }
2468
+ /**
2469
+ * Get mETH staking position for a user
2470
+ * Returns mETH balance and WETH balance for comparison
2471
+ * @param userAddress - User wallet address (optional, defaults to agent account)
2472
+ * @returns mETH position with balances
2473
+ */
2474
+ async methGetPosition(userAddress) {
2475
+ return await methGetPosition(this, userAddress);
2476
+ }
2477
+ /**
2478
+ * Swap WETH to mETH using DEX aggregator
2479
+ * @param amount - Amount of WETH to swap (in wei as string)
2480
+ * @param slippage - Slippage tolerance percentage (default 0.5%)
2481
+ * @returns Transaction hash
2482
+ */
2483
+ async swapToMeth(amount, slippage = 0.5) {
2484
+ return await swapToMeth(this, amount, slippage);
2485
+ }
2486
+ /**
2487
+ * Swap mETH to WETH using DEX aggregator
2488
+ * @param amount - Amount of mETH to swap (in wei as string)
2489
+ * @param slippage - Slippage tolerance percentage (default 0.5%)
2490
+ * @returns Transaction hash
2491
+ */
2492
+ async swapFromMeth(amount, slippage = 0.5) {
2493
+ return await swapFromMeth(this, amount, slippage);
2494
+ }
1423
2495
  // Squid Router Cross-chain
1424
2496
  async getSquidRoute(fromToken, toToken, fromChain, toChain, amount, slippage = 1) {
1425
2497
  return await getSquidRoute(
@@ -1443,6 +2515,54 @@ var MNTAgentKit = class {
1443
2515
  slippage
1444
2516
  );
1445
2517
  }
2518
+ // PikePerps - Perpetual Trading
2519
+ /**
2520
+ * Open a long position on PikePerps
2521
+ * @param tokenAddress - Token to trade (meme token address)
2522
+ * @param margin - Margin amount in wei (as string)
2523
+ * @param leverage - Leverage multiplier (1-100, default 10)
2524
+ * @returns Position ID and transaction hash
2525
+ */
2526
+ async pikeperpsOpenLong(tokenAddress, margin, leverage = 10) {
2527
+ return await pikeperpsOpenLong(this, tokenAddress, margin, leverage);
2528
+ }
2529
+ /**
2530
+ * Open a short position on PikePerps
2531
+ * @param tokenAddress - Token to trade (meme token address)
2532
+ * @param margin - Margin amount in wei (as string)
2533
+ * @param leverage - Leverage multiplier (1-100, default 10)
2534
+ * @returns Position ID and transaction hash
2535
+ */
2536
+ async pikeperpsOpenShort(tokenAddress, margin, leverage = 10) {
2537
+ return await pikeperpsOpenShort(this, tokenAddress, margin, leverage);
2538
+ }
2539
+ /**
2540
+ * Close an existing position on PikePerps
2541
+ * @param positionId - Position ID to close
2542
+ * @returns Transaction hash
2543
+ */
2544
+ async pikeperpsClosePosition(positionId) {
2545
+ return await pikeperpsClosePosition(this, positionId);
2546
+ }
2547
+ /**
2548
+ * Get all positions for a user on PikePerps
2549
+ * Returns detailed position data including PnL and liquidation prices
2550
+ * @param userAddress - User wallet address (optional, defaults to agent account)
2551
+ * @returns Array of positions with PnL and liquidation data
2552
+ */
2553
+ async pikeperpsGetPositions(userAddress) {
2554
+ return await pikeperpsGetPositions(this, userAddress);
2555
+ }
2556
+ /**
2557
+ * Get market data for a token on PikePerps
2558
+ * Returns current price and recent trades
2559
+ * @param tokenAddress - Token address to get market data for
2560
+ * @param limit - Maximum number of recent trades to return (default 20)
2561
+ * @returns Market data with price and recent trades
2562
+ */
2563
+ async pikeperpsGetMarketData(tokenAddress, limit = 20) {
2564
+ return await pikeperpsGetMarketData(this, tokenAddress, limit);
2565
+ }
1446
2566
  };
1447
2567
 
1448
2568
  exports.AgniConstants = agni_exports;
@@ -1454,6 +2574,7 @@ exports.MethConstants = meth_exports;
1454
2574
  exports.OKXConstants = okx_exports;
1455
2575
  exports.OneInchConstants = oneinch_exports;
1456
2576
  exports.OpenOceanConstants = openocean_exports;
2577
+ exports.PikePerpsConstants = pikeperps_exports;
1457
2578
  exports.SquidConstants = squid_exports;
1458
2579
  exports.UniswapConstants = uniswap_exports;
1459
2580
  exports.agniSwap = agniSwap;
@@ -1467,13 +2588,22 @@ exports.getSquidRoute = getSquidRoute;
1467
2588
  exports.getUniswapQuote = getUniswapQuote;
1468
2589
  exports.initializePlatform = initializePlatform;
1469
2590
  exports.lendleBorrow = lendleBorrow;
2591
+ exports.lendleGetPositions = lendleGetPositions;
1470
2592
  exports.lendleRepay = lendleRepay;
1471
2593
  exports.lendleSupply = lendleSupply;
1472
2594
  exports.lendleWithdraw = lendleWithdraw;
1473
2595
  exports.merchantMoeSwap = merchantMoeSwap;
2596
+ exports.methGetPosition = methGetPosition;
2597
+ exports.pikeperpsClosePosition = pikeperpsClosePosition;
2598
+ exports.pikeperpsGetMarketData = pikeperpsGetMarketData;
2599
+ exports.pikeperpsGetPositions = pikeperpsGetPositions;
2600
+ exports.pikeperpsOpenLong = pikeperpsOpenLong;
2601
+ exports.pikeperpsOpenShort = pikeperpsOpenShort;
1474
2602
  exports.sendTransaction = sendTransaction;
2603
+ exports.swapFromMeth = swapFromMeth;
1475
2604
  exports.swapOn1inch = swapOn1inch;
1476
2605
  exports.swapOnOpenOcean = swapOnOpenOcean;
1477
2606
  exports.swapOnUniswap = swapOnUniswap;
2607
+ exports.swapToMeth = swapToMeth;
1478
2608
  //# sourceMappingURL=index.cjs.map
1479
2609
  //# sourceMappingURL=index.cjs.map