mantle-agent-kit-sdk 1.0.3 → 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/README.md +192 -87
- package/dist/index.cjs +978 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1051 -261
- package/dist/index.d.ts +1051 -261
- package/dist/index.js +970 -5
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseUnits, parseEther, encodeFunctionData, createWalletClient, http, publicActions, erc20Abi as erc20Abi$1 } from 'viem';
|
|
1
|
+
import { parseUnits, parseEther, encodeFunctionData, getAddress, parseAbiItem, createWalletClient, http, publicActions, erc20Abi as erc20Abi$1 } from 'viem';
|
|
2
2
|
import { privateKeyToAccount } from 'viem/accounts';
|
|
3
3
|
import { mantle, mantleSepoliaTestnet } from 'viem/chains';
|
|
4
4
|
import { getTransactionReceipt } from 'viem/actions';
|
|
@@ -465,8 +465,8 @@ async function approveToken2(agent, tokenAddress, spenderAddress, amount) {
|
|
|
465
465
|
return { approved: true, txHash: null };
|
|
466
466
|
}
|
|
467
467
|
console.log("Insufficient allowance, approving tokens...");
|
|
468
|
-
const { encodeFunctionData:
|
|
469
|
-
const approveData =
|
|
468
|
+
const { encodeFunctionData: encodeFunctionData11 } = await import('viem');
|
|
469
|
+
const approveData = encodeFunctionData11({
|
|
470
470
|
abi: erc20Abi$1,
|
|
471
471
|
functionName: "approve",
|
|
472
472
|
args: [spenderAddress, BigInt(amount)]
|
|
@@ -495,6 +495,9 @@ async function swapOnOpenOcean(agent, fromToken, toToken, amount, slippage = "1"
|
|
|
495
495
|
if (agent.demo) {
|
|
496
496
|
return createMockOpenOceanSwapResponse(amount);
|
|
497
497
|
}
|
|
498
|
+
if (!agent.demo && agent.chain != "mainnet") {
|
|
499
|
+
throw new Error("Openocean swaps happen only on mainnet");
|
|
500
|
+
}
|
|
498
501
|
const walletAddress = agent.account.address;
|
|
499
502
|
if (fromToken.toLowerCase() !== NATIVE_TOKEN_ADDRESS.toLowerCase()) {
|
|
500
503
|
await approveToken2(agent, fromToken, OPENOCEAN_EXCHANGE_PROXY, amount);
|
|
@@ -944,8 +947,10 @@ __export(lendle_exports, {
|
|
|
944
947
|
LENDING_POOL: () => LENDING_POOL,
|
|
945
948
|
LENDING_POOL_ABI: () => LENDING_POOL_ABI,
|
|
946
949
|
LENDING_POOL_ADDRESSES_PROVIDER: () => LENDING_POOL_ADDRESSES_PROVIDER,
|
|
950
|
+
LENDLE_SUPPORTED_ASSETS: () => LENDLE_SUPPORTED_ASSETS,
|
|
947
951
|
ORACLE: () => ORACLE,
|
|
948
952
|
PROTOCOL_DATA_PROVIDER: () => PROTOCOL_DATA_PROVIDER,
|
|
953
|
+
PROTOCOL_DATA_PROVIDER_ABI: () => PROTOCOL_DATA_PROVIDER_ABI,
|
|
949
954
|
WMNT_ADDRESS: () => WMNT_ADDRESS2
|
|
950
955
|
});
|
|
951
956
|
var LENDING_POOL = {
|
|
@@ -1060,6 +1065,65 @@ var LENDING_POOL_ABI = [
|
|
|
1060
1065
|
type: "function"
|
|
1061
1066
|
}
|
|
1062
1067
|
];
|
|
1068
|
+
var PROTOCOL_DATA_PROVIDER_ABI = [
|
|
1069
|
+
{
|
|
1070
|
+
inputs: [],
|
|
1071
|
+
name: "getAllReservesTokens",
|
|
1072
|
+
outputs: [
|
|
1073
|
+
{
|
|
1074
|
+
components: [
|
|
1075
|
+
{ name: "symbol", type: "string" },
|
|
1076
|
+
{ name: "tokenAddress", type: "address" }
|
|
1077
|
+
],
|
|
1078
|
+
name: "",
|
|
1079
|
+
type: "tuple[]"
|
|
1080
|
+
}
|
|
1081
|
+
],
|
|
1082
|
+
stateMutability: "view",
|
|
1083
|
+
type: "function"
|
|
1084
|
+
},
|
|
1085
|
+
{
|
|
1086
|
+
inputs: [
|
|
1087
|
+
{ name: "asset", type: "address" },
|
|
1088
|
+
{ name: "user", type: "address" }
|
|
1089
|
+
],
|
|
1090
|
+
name: "getUserReserveData",
|
|
1091
|
+
outputs: [
|
|
1092
|
+
{ name: "currentATokenBalance", type: "uint256" },
|
|
1093
|
+
{ name: "currentStableDebt", type: "uint256" },
|
|
1094
|
+
{ name: "currentVariableDebt", type: "uint256" },
|
|
1095
|
+
{ name: "principalStableDebt", type: "uint256" },
|
|
1096
|
+
{ name: "scaledVariableDebt", type: "uint256" },
|
|
1097
|
+
{ name: "stableBorrowRate", type: "uint256" },
|
|
1098
|
+
{ name: "liquidityRate", type: "uint256" },
|
|
1099
|
+
{ name: "stableRateLastUpdated", type: "uint40" },
|
|
1100
|
+
{ name: "usageAsCollateralEnabled", type: "bool" }
|
|
1101
|
+
],
|
|
1102
|
+
stateMutability: "view",
|
|
1103
|
+
type: "function"
|
|
1104
|
+
},
|
|
1105
|
+
{
|
|
1106
|
+
inputs: [{ name: "asset", type: "address" }],
|
|
1107
|
+
name: "getReserveTokensAddresses",
|
|
1108
|
+
outputs: [
|
|
1109
|
+
{ name: "aTokenAddress", type: "address" },
|
|
1110
|
+
{ name: "stableDebtTokenAddress", type: "address" },
|
|
1111
|
+
{ name: "variableDebtTokenAddress", type: "address" }
|
|
1112
|
+
],
|
|
1113
|
+
stateMutability: "view",
|
|
1114
|
+
type: "function"
|
|
1115
|
+
}
|
|
1116
|
+
];
|
|
1117
|
+
var LENDLE_SUPPORTED_ASSETS = {
|
|
1118
|
+
mainnet: [
|
|
1119
|
+
{ symbol: "WMNT", address: "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8" },
|
|
1120
|
+
{ symbol: "WETH", address: "0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111" },
|
|
1121
|
+
{ symbol: "USDC", address: "0x09Bc4E0D10C81b3a3766c49F0f98a8aaa7adA8D2" },
|
|
1122
|
+
{ symbol: "USDT", address: "0x201EBa5CC46D216Ce6DC03F6a759e8E766e956aE" },
|
|
1123
|
+
{ symbol: "mETH", address: "0xcDA86A272531e8640cD7F1a92c01839911B90bb0" }
|
|
1124
|
+
],
|
|
1125
|
+
testnet: []
|
|
1126
|
+
};
|
|
1063
1127
|
|
|
1064
1128
|
// src/tools/lendle/supply.ts
|
|
1065
1129
|
async function lendleSupply(agent, tokenAddress, amount) {
|
|
@@ -1165,6 +1229,67 @@ async function lendleRepay(agent, tokenAddress, amount, rateMode = INTEREST_RATE
|
|
|
1165
1229
|
await agent.client.waitForTransactionReceipt({ hash });
|
|
1166
1230
|
return hash;
|
|
1167
1231
|
}
|
|
1232
|
+
async function lendleGetPositions(agent, userAddress) {
|
|
1233
|
+
const dataProviderAddress = PROTOCOL_DATA_PROVIDER[agent.chain];
|
|
1234
|
+
const address = userAddress || agent.account.address;
|
|
1235
|
+
if (dataProviderAddress === "0x0000000000000000000000000000000000000000") {
|
|
1236
|
+
throw new Error(
|
|
1237
|
+
`Lendle ProtocolDataProvider not configured for ${agent.chain}. Only available on mainnet.`
|
|
1238
|
+
);
|
|
1239
|
+
}
|
|
1240
|
+
const supportedAssets = LENDLE_SUPPORTED_ASSETS[agent.chain];
|
|
1241
|
+
if (!supportedAssets || supportedAssets.length === 0) {
|
|
1242
|
+
throw new Error(`No supported assets configured for ${agent.chain}`);
|
|
1243
|
+
}
|
|
1244
|
+
const positions = [];
|
|
1245
|
+
let totalSupplied = 0n;
|
|
1246
|
+
let totalDebt = 0n;
|
|
1247
|
+
for (const asset of supportedAssets) {
|
|
1248
|
+
try {
|
|
1249
|
+
const assetAddress = getAddress(asset.address);
|
|
1250
|
+
const result = await agent.client.readContract({
|
|
1251
|
+
address: dataProviderAddress,
|
|
1252
|
+
abi: PROTOCOL_DATA_PROVIDER_ABI,
|
|
1253
|
+
functionName: "getUserReserveData",
|
|
1254
|
+
args: [assetAddress, address]
|
|
1255
|
+
});
|
|
1256
|
+
const [
|
|
1257
|
+
currentATokenBalance,
|
|
1258
|
+
currentStableDebt,
|
|
1259
|
+
currentVariableDebt,
|
|
1260
|
+
_principalStableDebt,
|
|
1261
|
+
_scaledVariableDebt,
|
|
1262
|
+
stableBorrowRate,
|
|
1263
|
+
liquidityRate,
|
|
1264
|
+
_stableRateLastUpdated,
|
|
1265
|
+
usageAsCollateralEnabled
|
|
1266
|
+
] = result;
|
|
1267
|
+
if (currentATokenBalance > 0n || currentStableDebt > 0n || currentVariableDebt > 0n) {
|
|
1268
|
+
const assetTotalDebt = currentStableDebt + currentVariableDebt;
|
|
1269
|
+
positions.push({
|
|
1270
|
+
asset: assetAddress,
|
|
1271
|
+
symbol: asset.symbol,
|
|
1272
|
+
supplied: currentATokenBalance,
|
|
1273
|
+
stableDebt: currentStableDebt,
|
|
1274
|
+
variableDebt: currentVariableDebt,
|
|
1275
|
+
totalDebt: assetTotalDebt,
|
|
1276
|
+
liquidityRate,
|
|
1277
|
+
stableBorrowRate,
|
|
1278
|
+
usageAsCollateralEnabled
|
|
1279
|
+
});
|
|
1280
|
+
totalSupplied += currentATokenBalance;
|
|
1281
|
+
totalDebt += assetTotalDebt;
|
|
1282
|
+
}
|
|
1283
|
+
} catch (error) {
|
|
1284
|
+
console.warn(`Failed to get position for ${asset.symbol}:`, error);
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
return {
|
|
1288
|
+
positions,
|
|
1289
|
+
totalSupplied,
|
|
1290
|
+
totalDebt
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1168
1293
|
|
|
1169
1294
|
// src/constants/agni/index.ts
|
|
1170
1295
|
var agni_exports = {};
|
|
@@ -1327,12 +1452,736 @@ async function merchantMoeSwap(agent, tokenIn, tokenOut, amountIn, slippagePerce
|
|
|
1327
1452
|
// src/constants/meth/index.ts
|
|
1328
1453
|
var meth_exports = {};
|
|
1329
1454
|
__export(meth_exports, {
|
|
1330
|
-
|
|
1455
|
+
METH_ABI: () => METH_ABI,
|
|
1456
|
+
METH_TOKEN: () => METH_TOKEN,
|
|
1457
|
+
NATIVE_MNT_ADDRESS: () => NATIVE_MNT_ADDRESS,
|
|
1458
|
+
WETH_TOKEN: () => WETH_TOKEN,
|
|
1459
|
+
WMNT_TOKEN: () => WMNT_TOKEN
|
|
1331
1460
|
});
|
|
1332
1461
|
var METH_TOKEN = {
|
|
1333
1462
|
mainnet: "0xcDA86A272531e8640cD7F1a92c01839911B90bb0",
|
|
1334
1463
|
testnet: "0x0000000000000000000000000000000000000000"
|
|
1335
1464
|
};
|
|
1465
|
+
var WETH_TOKEN = {
|
|
1466
|
+
mainnet: "0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111",
|
|
1467
|
+
testnet: "0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111"
|
|
1468
|
+
};
|
|
1469
|
+
var WMNT_TOKEN = {
|
|
1470
|
+
mainnet: "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8",
|
|
1471
|
+
testnet: "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8"
|
|
1472
|
+
};
|
|
1473
|
+
var NATIVE_MNT_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
|
1474
|
+
var METH_ABI = [
|
|
1475
|
+
{
|
|
1476
|
+
inputs: [{ name: "account", type: "address" }],
|
|
1477
|
+
name: "balanceOf",
|
|
1478
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
1479
|
+
stateMutability: "view",
|
|
1480
|
+
type: "function"
|
|
1481
|
+
},
|
|
1482
|
+
{
|
|
1483
|
+
inputs: [],
|
|
1484
|
+
name: "totalSupply",
|
|
1485
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
1486
|
+
stateMutability: "view",
|
|
1487
|
+
type: "function"
|
|
1488
|
+
},
|
|
1489
|
+
{
|
|
1490
|
+
inputs: [],
|
|
1491
|
+
name: "decimals",
|
|
1492
|
+
outputs: [{ name: "", type: "uint8" }],
|
|
1493
|
+
stateMutability: "view",
|
|
1494
|
+
type: "function"
|
|
1495
|
+
},
|
|
1496
|
+
{
|
|
1497
|
+
inputs: [],
|
|
1498
|
+
name: "symbol",
|
|
1499
|
+
outputs: [{ name: "", type: "string" }],
|
|
1500
|
+
stateMutability: "view",
|
|
1501
|
+
type: "function"
|
|
1502
|
+
},
|
|
1503
|
+
{
|
|
1504
|
+
inputs: [
|
|
1505
|
+
{ name: "spender", type: "address" },
|
|
1506
|
+
{ name: "amount", type: "uint256" }
|
|
1507
|
+
],
|
|
1508
|
+
name: "approve",
|
|
1509
|
+
outputs: [{ name: "", type: "bool" }],
|
|
1510
|
+
stateMutability: "nonpayable",
|
|
1511
|
+
type: "function"
|
|
1512
|
+
},
|
|
1513
|
+
{
|
|
1514
|
+
inputs: [
|
|
1515
|
+
{ name: "owner", type: "address" },
|
|
1516
|
+
{ name: "spender", type: "address" }
|
|
1517
|
+
],
|
|
1518
|
+
name: "allowance",
|
|
1519
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
1520
|
+
stateMutability: "view",
|
|
1521
|
+
type: "function"
|
|
1522
|
+
}
|
|
1523
|
+
];
|
|
1524
|
+
async function methGetPosition(agent, userAddress) {
|
|
1525
|
+
const methTokenAddress = METH_TOKEN[agent.chain];
|
|
1526
|
+
const wethTokenAddress = WETH_TOKEN[agent.chain];
|
|
1527
|
+
const wmntTokenAddress = WMNT_TOKEN[agent.chain];
|
|
1528
|
+
const address = userAddress || agent.account.address;
|
|
1529
|
+
if (methTokenAddress === "0x0000000000000000000000000000000000000000") {
|
|
1530
|
+
throw new Error(
|
|
1531
|
+
`mETH not available on ${agent.chain}. Only available on mainnet.`
|
|
1532
|
+
);
|
|
1533
|
+
}
|
|
1534
|
+
const methBalance = await agent.client.readContract({
|
|
1535
|
+
address: methTokenAddress,
|
|
1536
|
+
abi: METH_ABI,
|
|
1537
|
+
functionName: "balanceOf",
|
|
1538
|
+
args: [address]
|
|
1539
|
+
});
|
|
1540
|
+
let wethBalance = 0n;
|
|
1541
|
+
try {
|
|
1542
|
+
wethBalance = await agent.client.readContract({
|
|
1543
|
+
address: wethTokenAddress,
|
|
1544
|
+
abi: METH_ABI,
|
|
1545
|
+
// Same ERC20 ABI works for WETH
|
|
1546
|
+
functionName: "balanceOf",
|
|
1547
|
+
args: [address]
|
|
1548
|
+
});
|
|
1549
|
+
} catch {
|
|
1550
|
+
}
|
|
1551
|
+
let wmntBalance = 0n;
|
|
1552
|
+
try {
|
|
1553
|
+
wmntBalance = await agent.client.readContract({
|
|
1554
|
+
address: wmntTokenAddress,
|
|
1555
|
+
abi: METH_ABI,
|
|
1556
|
+
// Same ERC20 ABI works for WMNT
|
|
1557
|
+
functionName: "balanceOf",
|
|
1558
|
+
args: [address]
|
|
1559
|
+
});
|
|
1560
|
+
} catch {
|
|
1561
|
+
}
|
|
1562
|
+
return {
|
|
1563
|
+
methBalance,
|
|
1564
|
+
wethBalance,
|
|
1565
|
+
wmntBalance,
|
|
1566
|
+
methTokenAddress,
|
|
1567
|
+
wethTokenAddress,
|
|
1568
|
+
wmntTokenAddress
|
|
1569
|
+
};
|
|
1570
|
+
}
|
|
1571
|
+
async function swapToMeth(agent, amount, slippage = 0.5) {
|
|
1572
|
+
const methTokenAddress = METH_TOKEN[agent.chain];
|
|
1573
|
+
const wethTokenAddress = WETH_TOKEN[agent.chain];
|
|
1574
|
+
if (methTokenAddress === "0x0000000000000000000000000000000000000000") {
|
|
1575
|
+
throw new Error(
|
|
1576
|
+
`mETH not available on ${agent.chain}. Only available on mainnet.`
|
|
1577
|
+
);
|
|
1578
|
+
}
|
|
1579
|
+
const result = await swapOnOpenOcean(
|
|
1580
|
+
agent,
|
|
1581
|
+
wethTokenAddress,
|
|
1582
|
+
methTokenAddress,
|
|
1583
|
+
amount,
|
|
1584
|
+
slippage.toString()
|
|
1585
|
+
);
|
|
1586
|
+
return result.txHash;
|
|
1587
|
+
}
|
|
1588
|
+
async function swapFromMeth(agent, amount, slippage = 0.5) {
|
|
1589
|
+
const methTokenAddress = METH_TOKEN[agent.chain];
|
|
1590
|
+
const wethTokenAddress = WETH_TOKEN[agent.chain];
|
|
1591
|
+
if (methTokenAddress === "0x0000000000000000000000000000000000000000") {
|
|
1592
|
+
throw new Error(
|
|
1593
|
+
`mETH not available on ${agent.chain}. Only available on mainnet.`
|
|
1594
|
+
);
|
|
1595
|
+
}
|
|
1596
|
+
const result = await swapOnOpenOcean(
|
|
1597
|
+
agent,
|
|
1598
|
+
methTokenAddress,
|
|
1599
|
+
wethTokenAddress,
|
|
1600
|
+
amount,
|
|
1601
|
+
slippage.toString()
|
|
1602
|
+
);
|
|
1603
|
+
return result.txHash;
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
// src/constants/pikeperps/index.ts
|
|
1607
|
+
var pikeperps_exports = {};
|
|
1608
|
+
__export(pikeperps_exports, {
|
|
1609
|
+
BONDING_CURVE_MARKET: () => BONDING_CURVE_MARKET,
|
|
1610
|
+
BONDING_CURVE_MARKET_ABI: () => BONDING_CURVE_MARKET_ABI,
|
|
1611
|
+
PERPETUAL_TRADING: () => PERPETUAL_TRADING,
|
|
1612
|
+
PERPETUAL_TRADING_ABI: () => PERPETUAL_TRADING_ABI,
|
|
1613
|
+
PIKE_PERPS_CONFIG: () => PIKE_PERPS_CONFIG
|
|
1614
|
+
});
|
|
1615
|
+
var PERPETUAL_TRADING = {
|
|
1616
|
+
mainnet: "0x0000000000000000000000000000000000000000",
|
|
1617
|
+
// Not deployed yet
|
|
1618
|
+
testnet: "0x8081b646f349c049f2d5e8a400057d411dd657bd"
|
|
1619
|
+
};
|
|
1620
|
+
var BONDING_CURVE_MARKET = {
|
|
1621
|
+
mainnet: "0x0000000000000000000000000000000000000000",
|
|
1622
|
+
testnet: "0x93b268325A9862645c82b32229f3B52264750Ca2"
|
|
1623
|
+
};
|
|
1624
|
+
var PIKE_PERPS_CONFIG = {
|
|
1625
|
+
MAX_LEVERAGE: 100,
|
|
1626
|
+
DEFAULT_LEVERAGE: 10,
|
|
1627
|
+
MIN_LEVERAGE: 1,
|
|
1628
|
+
TRADING_FEE_BPS: 5,
|
|
1629
|
+
// 0.05%
|
|
1630
|
+
LIQUIDATION_REWARD_BPS: 500,
|
|
1631
|
+
// 5%
|
|
1632
|
+
PRICE_DECIMALS: 8
|
|
1633
|
+
// Prices are scaled by 1e8
|
|
1634
|
+
};
|
|
1635
|
+
var PERPETUAL_TRADING_ABI = [
|
|
1636
|
+
{
|
|
1637
|
+
inputs: [
|
|
1638
|
+
{ internalType: "address", name: "_pyth", type: "address" }
|
|
1639
|
+
],
|
|
1640
|
+
stateMutability: "nonpayable",
|
|
1641
|
+
type: "constructor"
|
|
1642
|
+
},
|
|
1643
|
+
{
|
|
1644
|
+
anonymous: false,
|
|
1645
|
+
inputs: [
|
|
1646
|
+
{ indexed: true, internalType: "uint256", name: "positionId", type: "uint256" },
|
|
1647
|
+
{ indexed: true, internalType: "address", name: "user", type: "address" },
|
|
1648
|
+
{ indexed: false, internalType: "uint256", name: "pnl", type: "uint256" },
|
|
1649
|
+
{ indexed: false, internalType: "uint256", name: "exitPrice", type: "uint256" }
|
|
1650
|
+
],
|
|
1651
|
+
name: "PositionClosed",
|
|
1652
|
+
type: "event"
|
|
1653
|
+
},
|
|
1654
|
+
{
|
|
1655
|
+
anonymous: false,
|
|
1656
|
+
inputs: [
|
|
1657
|
+
{ indexed: true, internalType: "uint256", name: "positionId", type: "uint256" },
|
|
1658
|
+
{ indexed: true, internalType: "address", name: "user", type: "address" },
|
|
1659
|
+
{ indexed: false, internalType: "uint256", name: "liquidationPrice", type: "uint256" }
|
|
1660
|
+
],
|
|
1661
|
+
name: "PositionLiquidated",
|
|
1662
|
+
type: "event"
|
|
1663
|
+
},
|
|
1664
|
+
{
|
|
1665
|
+
anonymous: false,
|
|
1666
|
+
inputs: [
|
|
1667
|
+
{ indexed: true, internalType: "uint256", name: "positionId", type: "uint256" },
|
|
1668
|
+
{ indexed: true, internalType: "address", name: "user", type: "address" },
|
|
1669
|
+
{ indexed: true, internalType: "address", name: "token", type: "address" },
|
|
1670
|
+
{ indexed: false, internalType: "bool", name: "isLong", type: "bool" },
|
|
1671
|
+
{ indexed: false, internalType: "uint256", name: "size", type: "uint256" },
|
|
1672
|
+
{ indexed: false, internalType: "uint256", name: "margin", type: "uint256" },
|
|
1673
|
+
{ indexed: false, internalType: "uint256", name: "leverage", type: "uint256" },
|
|
1674
|
+
{ indexed: false, internalType: "uint256", name: "entryPrice", type: "uint256" }
|
|
1675
|
+
],
|
|
1676
|
+
name: "PositionOpened",
|
|
1677
|
+
type: "event"
|
|
1678
|
+
},
|
|
1679
|
+
{
|
|
1680
|
+
inputs: [{ internalType: "uint256", name: "_positionId", type: "uint256" }],
|
|
1681
|
+
name: "closePosition",
|
|
1682
|
+
outputs: [],
|
|
1683
|
+
stateMutability: "nonpayable",
|
|
1684
|
+
type: "function"
|
|
1685
|
+
},
|
|
1686
|
+
{
|
|
1687
|
+
inputs: [{ internalType: "address", name: "_token", type: "address" }],
|
|
1688
|
+
name: "getCurrentPrice",
|
|
1689
|
+
outputs: [
|
|
1690
|
+
{ internalType: "uint256", name: "currentPrice", type: "uint256" },
|
|
1691
|
+
{ internalType: "bool", name: "hasPrice", type: "bool" }
|
|
1692
|
+
],
|
|
1693
|
+
stateMutability: "view",
|
|
1694
|
+
type: "function"
|
|
1695
|
+
},
|
|
1696
|
+
{
|
|
1697
|
+
inputs: [{ internalType: "uint256", name: "_positionId", type: "uint256" }],
|
|
1698
|
+
name: "getLiquidationPrice",
|
|
1699
|
+
outputs: [{ internalType: "uint256", name: "liquidationPrice", type: "uint256" }],
|
|
1700
|
+
stateMutability: "view",
|
|
1701
|
+
type: "function"
|
|
1702
|
+
},
|
|
1703
|
+
{
|
|
1704
|
+
inputs: [{ internalType: "uint256", name: "_positionId", type: "uint256" }],
|
|
1705
|
+
name: "getPosition",
|
|
1706
|
+
outputs: [
|
|
1707
|
+
{
|
|
1708
|
+
components: [
|
|
1709
|
+
{ internalType: "address", name: "user", type: "address" },
|
|
1710
|
+
{ internalType: "address", name: "token", type: "address" },
|
|
1711
|
+
{ internalType: "bool", name: "isLong", type: "bool" },
|
|
1712
|
+
{ internalType: "uint256", name: "size", type: "uint256" },
|
|
1713
|
+
{ internalType: "uint256", name: "margin", type: "uint256" },
|
|
1714
|
+
{ internalType: "uint256", name: "leverage", type: "uint256" },
|
|
1715
|
+
{ internalType: "uint256", name: "entryPrice", type: "uint256" },
|
|
1716
|
+
{ internalType: "uint256", name: "entryTime", type: "uint256" },
|
|
1717
|
+
{ internalType: "uint256", name: "lastFundingTime", type: "uint256" },
|
|
1718
|
+
{ internalType: "bool", name: "isOpen", type: "bool" }
|
|
1719
|
+
],
|
|
1720
|
+
internalType: "struct PerpetualTrading.Position",
|
|
1721
|
+
name: "",
|
|
1722
|
+
type: "tuple"
|
|
1723
|
+
}
|
|
1724
|
+
],
|
|
1725
|
+
stateMutability: "view",
|
|
1726
|
+
type: "function"
|
|
1727
|
+
},
|
|
1728
|
+
{
|
|
1729
|
+
inputs: [{ internalType: "uint256", name: "_positionId", type: "uint256" }],
|
|
1730
|
+
name: "getPositionPnL",
|
|
1731
|
+
outputs: [
|
|
1732
|
+
{ internalType: "uint256", name: "pnl", type: "uint256" },
|
|
1733
|
+
{ internalType: "bool", name: "isProfit", type: "bool" }
|
|
1734
|
+
],
|
|
1735
|
+
stateMutability: "view",
|
|
1736
|
+
type: "function"
|
|
1737
|
+
},
|
|
1738
|
+
{
|
|
1739
|
+
inputs: [{ internalType: "address", name: "_user", type: "address" }],
|
|
1740
|
+
name: "getUserPositions",
|
|
1741
|
+
outputs: [{ internalType: "uint256[]", name: "", type: "uint256[]" }],
|
|
1742
|
+
stateMutability: "view",
|
|
1743
|
+
type: "function"
|
|
1744
|
+
},
|
|
1745
|
+
{
|
|
1746
|
+
inputs: [{ internalType: "uint256", name: "_positionId", type: "uint256" }],
|
|
1747
|
+
name: "liquidatePosition",
|
|
1748
|
+
outputs: [],
|
|
1749
|
+
stateMutability: "nonpayable",
|
|
1750
|
+
type: "function"
|
|
1751
|
+
},
|
|
1752
|
+
{
|
|
1753
|
+
inputs: [],
|
|
1754
|
+
name: "maxLeverage",
|
|
1755
|
+
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
1756
|
+
stateMutability: "view",
|
|
1757
|
+
type: "function"
|
|
1758
|
+
},
|
|
1759
|
+
{
|
|
1760
|
+
inputs: [],
|
|
1761
|
+
name: "minMarginBps",
|
|
1762
|
+
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
1763
|
+
stateMutability: "view",
|
|
1764
|
+
type: "function"
|
|
1765
|
+
},
|
|
1766
|
+
{
|
|
1767
|
+
inputs: [],
|
|
1768
|
+
name: "nextPositionId",
|
|
1769
|
+
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
1770
|
+
stateMutability: "view",
|
|
1771
|
+
type: "function"
|
|
1772
|
+
},
|
|
1773
|
+
{
|
|
1774
|
+
inputs: [
|
|
1775
|
+
{ internalType: "address", name: "_token", type: "address" },
|
|
1776
|
+
{ internalType: "bool", name: "_isLong", type: "bool" },
|
|
1777
|
+
{ internalType: "uint256", name: "_margin", type: "uint256" },
|
|
1778
|
+
{ internalType: "uint256", name: "_leverage", type: "uint256" }
|
|
1779
|
+
],
|
|
1780
|
+
name: "openPosition",
|
|
1781
|
+
outputs: [{ internalType: "uint256", name: "positionId", type: "uint256" }],
|
|
1782
|
+
stateMutability: "payable",
|
|
1783
|
+
type: "function"
|
|
1784
|
+
},
|
|
1785
|
+
{
|
|
1786
|
+
inputs: [{ internalType: "uint256", name: "_positionId", type: "uint256" }],
|
|
1787
|
+
name: "shouldLiquidate",
|
|
1788
|
+
outputs: [{ internalType: "bool", name: "", type: "bool" }],
|
|
1789
|
+
stateMutability: "view",
|
|
1790
|
+
type: "function"
|
|
1791
|
+
},
|
|
1792
|
+
{
|
|
1793
|
+
inputs: [],
|
|
1794
|
+
name: "tradingFeeBps",
|
|
1795
|
+
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
1796
|
+
stateMutability: "view",
|
|
1797
|
+
type: "function"
|
|
1798
|
+
}
|
|
1799
|
+
];
|
|
1800
|
+
var BONDING_CURVE_MARKET_ABI = [
|
|
1801
|
+
{
|
|
1802
|
+
inputs: [{ internalType: "address", name: "_token", type: "address" }],
|
|
1803
|
+
name: "getCurrentPrice",
|
|
1804
|
+
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
1805
|
+
stateMutability: "view",
|
|
1806
|
+
type: "function"
|
|
1807
|
+
},
|
|
1808
|
+
{
|
|
1809
|
+
inputs: [{ internalType: "address", name: "_token", type: "address" }],
|
|
1810
|
+
name: "isListed",
|
|
1811
|
+
outputs: [{ internalType: "bool", name: "", type: "bool" }],
|
|
1812
|
+
stateMutability: "view",
|
|
1813
|
+
type: "function"
|
|
1814
|
+
},
|
|
1815
|
+
{
|
|
1816
|
+
inputs: [{ internalType: "address", name: "_token", type: "address" }],
|
|
1817
|
+
name: "getCurveProgress",
|
|
1818
|
+
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
|
1819
|
+
stateMutability: "view",
|
|
1820
|
+
type: "function"
|
|
1821
|
+
}
|
|
1822
|
+
];
|
|
1823
|
+
|
|
1824
|
+
// src/tools/pikeperps/openLong.ts
|
|
1825
|
+
async function pikeperpsOpenLong(agent, tokenAddress, margin, leverage = PIKE_PERPS_CONFIG.DEFAULT_LEVERAGE) {
|
|
1826
|
+
const perpetualTradingAddress = PERPETUAL_TRADING[agent.chain];
|
|
1827
|
+
if (perpetualTradingAddress === "0x0000000000000000000000000000000000000000") {
|
|
1828
|
+
throw new Error(
|
|
1829
|
+
`PikePerps not available on ${agent.chain}. Only available on testnet.`
|
|
1830
|
+
);
|
|
1831
|
+
}
|
|
1832
|
+
if (leverage < PIKE_PERPS_CONFIG.MIN_LEVERAGE || leverage > PIKE_PERPS_CONFIG.MAX_LEVERAGE) {
|
|
1833
|
+
throw new Error(
|
|
1834
|
+
`Leverage must be between ${PIKE_PERPS_CONFIG.MIN_LEVERAGE} and ${PIKE_PERPS_CONFIG.MAX_LEVERAGE}`
|
|
1835
|
+
);
|
|
1836
|
+
}
|
|
1837
|
+
if (agent.demo) {
|
|
1838
|
+
return {
|
|
1839
|
+
positionId: BigInt(Math.floor(Math.random() * 1e3)),
|
|
1840
|
+
txHash: "0xdemo_open_long_tx_hash"
|
|
1841
|
+
};
|
|
1842
|
+
}
|
|
1843
|
+
const marginBigInt = BigInt(margin);
|
|
1844
|
+
const data = encodeFunctionData({
|
|
1845
|
+
abi: PERPETUAL_TRADING_ABI,
|
|
1846
|
+
functionName: "openPosition",
|
|
1847
|
+
args: [tokenAddress, true, marginBigInt, BigInt(leverage)]
|
|
1848
|
+
});
|
|
1849
|
+
const txHash = await agent.client.sendTransaction({
|
|
1850
|
+
to: perpetualTradingAddress,
|
|
1851
|
+
data,
|
|
1852
|
+
value: marginBigInt
|
|
1853
|
+
});
|
|
1854
|
+
const receipt = await agent.client.waitForTransactionReceipt({ hash: txHash });
|
|
1855
|
+
let positionId = 0n;
|
|
1856
|
+
for (const log of receipt.logs) {
|
|
1857
|
+
try {
|
|
1858
|
+
if (log.topics[0] === "0x2e5b0e8c5f5d55d89e89f5b5d5e5f5d55d89e89f5b5d5e5f5d55d89e89f5b5d5") {
|
|
1859
|
+
positionId = BigInt(log.topics[1] || "0");
|
|
1860
|
+
break;
|
|
1861
|
+
}
|
|
1862
|
+
} catch {
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
if (positionId === 0n) {
|
|
1866
|
+
try {
|
|
1867
|
+
const nextId = await agent.client.readContract({
|
|
1868
|
+
address: perpetualTradingAddress,
|
|
1869
|
+
abi: PERPETUAL_TRADING_ABI,
|
|
1870
|
+
functionName: "nextPositionId"
|
|
1871
|
+
});
|
|
1872
|
+
positionId = nextId - 1n;
|
|
1873
|
+
} catch {
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
return {
|
|
1877
|
+
positionId,
|
|
1878
|
+
txHash
|
|
1879
|
+
};
|
|
1880
|
+
}
|
|
1881
|
+
async function pikeperpsOpenShort(agent, tokenAddress, margin, leverage = PIKE_PERPS_CONFIG.DEFAULT_LEVERAGE) {
|
|
1882
|
+
const perpetualTradingAddress = PERPETUAL_TRADING[agent.chain];
|
|
1883
|
+
if (perpetualTradingAddress === "0x0000000000000000000000000000000000000000") {
|
|
1884
|
+
throw new Error(
|
|
1885
|
+
`PikePerps not available on ${agent.chain}. Only available on testnet.`
|
|
1886
|
+
);
|
|
1887
|
+
}
|
|
1888
|
+
if (leverage < PIKE_PERPS_CONFIG.MIN_LEVERAGE || leverage > PIKE_PERPS_CONFIG.MAX_LEVERAGE) {
|
|
1889
|
+
throw new Error(
|
|
1890
|
+
`Leverage must be between ${PIKE_PERPS_CONFIG.MIN_LEVERAGE} and ${PIKE_PERPS_CONFIG.MAX_LEVERAGE}`
|
|
1891
|
+
);
|
|
1892
|
+
}
|
|
1893
|
+
if (agent.demo) {
|
|
1894
|
+
return {
|
|
1895
|
+
positionId: BigInt(Math.floor(Math.random() * 1e3)),
|
|
1896
|
+
txHash: "0xdemo_open_short_tx_hash"
|
|
1897
|
+
};
|
|
1898
|
+
}
|
|
1899
|
+
const marginBigInt = BigInt(margin);
|
|
1900
|
+
const data = encodeFunctionData({
|
|
1901
|
+
abi: PERPETUAL_TRADING_ABI,
|
|
1902
|
+
functionName: "openPosition",
|
|
1903
|
+
args: [tokenAddress, false, marginBigInt, BigInt(leverage)]
|
|
1904
|
+
});
|
|
1905
|
+
const txHash = await agent.client.sendTransaction({
|
|
1906
|
+
to: perpetualTradingAddress,
|
|
1907
|
+
data,
|
|
1908
|
+
value: marginBigInt
|
|
1909
|
+
});
|
|
1910
|
+
const receipt = await agent.client.waitForTransactionReceipt({ hash: txHash });
|
|
1911
|
+
let positionId = 0n;
|
|
1912
|
+
for (const log of receipt.logs) {
|
|
1913
|
+
try {
|
|
1914
|
+
if (log.topics[0] === "0x2e5b0e8c5f5d55d89e89f5b5d5e5f5d55d89e89f5b5d5e5f5d55d89e89f5b5d5") {
|
|
1915
|
+
positionId = BigInt(log.topics[1] || "0");
|
|
1916
|
+
break;
|
|
1917
|
+
}
|
|
1918
|
+
} catch {
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
if (positionId === 0n) {
|
|
1922
|
+
try {
|
|
1923
|
+
const nextId = await agent.client.readContract({
|
|
1924
|
+
address: perpetualTradingAddress,
|
|
1925
|
+
abi: PERPETUAL_TRADING_ABI,
|
|
1926
|
+
functionName: "nextPositionId"
|
|
1927
|
+
});
|
|
1928
|
+
positionId = nextId - 1n;
|
|
1929
|
+
} catch {
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
return {
|
|
1933
|
+
positionId,
|
|
1934
|
+
txHash
|
|
1935
|
+
};
|
|
1936
|
+
}
|
|
1937
|
+
async function pikeperpsClosePosition(agent, positionId) {
|
|
1938
|
+
const perpetualTradingAddress = PERPETUAL_TRADING[agent.chain];
|
|
1939
|
+
if (perpetualTradingAddress === "0x0000000000000000000000000000000000000000") {
|
|
1940
|
+
throw new Error(
|
|
1941
|
+
`PikePerps not available on ${agent.chain}. Only available on testnet.`
|
|
1942
|
+
);
|
|
1943
|
+
}
|
|
1944
|
+
if (agent.demo) {
|
|
1945
|
+
return "0xdemo_close_position_tx_hash";
|
|
1946
|
+
}
|
|
1947
|
+
const data = encodeFunctionData({
|
|
1948
|
+
abi: PERPETUAL_TRADING_ABI,
|
|
1949
|
+
functionName: "closePosition",
|
|
1950
|
+
args: [positionId]
|
|
1951
|
+
});
|
|
1952
|
+
const txHash = await agent.client.sendTransaction({
|
|
1953
|
+
to: perpetualTradingAddress,
|
|
1954
|
+
data
|
|
1955
|
+
});
|
|
1956
|
+
await agent.client.waitForTransactionReceipt({ hash: txHash });
|
|
1957
|
+
return txHash;
|
|
1958
|
+
}
|
|
1959
|
+
async function pikeperpsGetPositions(agent, userAddress) {
|
|
1960
|
+
const perpetualTradingAddress = PERPETUAL_TRADING[agent.chain];
|
|
1961
|
+
const address = userAddress || agent.account.address;
|
|
1962
|
+
if (perpetualTradingAddress === "0x0000000000000000000000000000000000000000") {
|
|
1963
|
+
throw new Error(
|
|
1964
|
+
`PikePerps not available on ${agent.chain}. Only available on testnet.`
|
|
1965
|
+
);
|
|
1966
|
+
}
|
|
1967
|
+
if (agent.demo) {
|
|
1968
|
+
return [
|
|
1969
|
+
{
|
|
1970
|
+
positionId: 1n,
|
|
1971
|
+
token: "0x0000000000000000000000000000000000000001",
|
|
1972
|
+
isLong: true,
|
|
1973
|
+
size: BigInt("1000000000000000000"),
|
|
1974
|
+
// 1 ETH equivalent
|
|
1975
|
+
margin: BigInt("100000000000000000"),
|
|
1976
|
+
// 0.1 ETH
|
|
1977
|
+
leverage: 10,
|
|
1978
|
+
entryPrice: BigInt("100000000"),
|
|
1979
|
+
// $1.00 scaled by 1e8
|
|
1980
|
+
entryTime: BigInt(Math.floor(Date.now() / 1e3) - 3600),
|
|
1981
|
+
currentPrice: BigInt("110000000"),
|
|
1982
|
+
// $1.10
|
|
1983
|
+
pnl: BigInt("10000000000000000"),
|
|
1984
|
+
// 0.01 ETH profit
|
|
1985
|
+
isProfit: true,
|
|
1986
|
+
liquidationPrice: BigInt("90000000"),
|
|
1987
|
+
// $0.90
|
|
1988
|
+
isOpen: true
|
|
1989
|
+
}
|
|
1990
|
+
];
|
|
1991
|
+
}
|
|
1992
|
+
const positionIds = await agent.client.readContract({
|
|
1993
|
+
address: perpetualTradingAddress,
|
|
1994
|
+
abi: PERPETUAL_TRADING_ABI,
|
|
1995
|
+
functionName: "getUserPositions",
|
|
1996
|
+
args: [address]
|
|
1997
|
+
});
|
|
1998
|
+
if (positionIds.length === 0) {
|
|
1999
|
+
return [];
|
|
2000
|
+
}
|
|
2001
|
+
const positions = [];
|
|
2002
|
+
for (const positionId of positionIds) {
|
|
2003
|
+
try {
|
|
2004
|
+
const rawPosition = await agent.client.readContract({
|
|
2005
|
+
address: perpetualTradingAddress,
|
|
2006
|
+
abi: PERPETUAL_TRADING_ABI,
|
|
2007
|
+
functionName: "getPosition",
|
|
2008
|
+
args: [positionId]
|
|
2009
|
+
});
|
|
2010
|
+
if (!rawPosition.isOpen) {
|
|
2011
|
+
continue;
|
|
2012
|
+
}
|
|
2013
|
+
const [pnl, isProfit] = await agent.client.readContract({
|
|
2014
|
+
address: perpetualTradingAddress,
|
|
2015
|
+
abi: PERPETUAL_TRADING_ABI,
|
|
2016
|
+
functionName: "getPositionPnL",
|
|
2017
|
+
args: [positionId]
|
|
2018
|
+
});
|
|
2019
|
+
const liquidationPrice = await agent.client.readContract({
|
|
2020
|
+
address: perpetualTradingAddress,
|
|
2021
|
+
abi: PERPETUAL_TRADING_ABI,
|
|
2022
|
+
functionName: "getLiquidationPrice",
|
|
2023
|
+
args: [positionId]
|
|
2024
|
+
});
|
|
2025
|
+
let currentPrice = 0n;
|
|
2026
|
+
try {
|
|
2027
|
+
const [price, hasPrice] = await agent.client.readContract({
|
|
2028
|
+
address: perpetualTradingAddress,
|
|
2029
|
+
abi: PERPETUAL_TRADING_ABI,
|
|
2030
|
+
functionName: "getCurrentPrice",
|
|
2031
|
+
args: [rawPosition.token]
|
|
2032
|
+
});
|
|
2033
|
+
if (hasPrice) {
|
|
2034
|
+
currentPrice = price;
|
|
2035
|
+
}
|
|
2036
|
+
} catch {
|
|
2037
|
+
currentPrice = rawPosition.entryPrice;
|
|
2038
|
+
}
|
|
2039
|
+
positions.push({
|
|
2040
|
+
positionId,
|
|
2041
|
+
token: rawPosition.token,
|
|
2042
|
+
isLong: rawPosition.isLong,
|
|
2043
|
+
size: rawPosition.size,
|
|
2044
|
+
margin: rawPosition.margin,
|
|
2045
|
+
leverage: Number(rawPosition.leverage),
|
|
2046
|
+
entryPrice: rawPosition.entryPrice,
|
|
2047
|
+
entryTime: rawPosition.entryTime,
|
|
2048
|
+
currentPrice,
|
|
2049
|
+
pnl,
|
|
2050
|
+
isProfit,
|
|
2051
|
+
liquidationPrice,
|
|
2052
|
+
isOpen: rawPosition.isOpen
|
|
2053
|
+
});
|
|
2054
|
+
} catch (error) {
|
|
2055
|
+
console.warn(`Failed to fetch position ${positionId}:`, error);
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
return positions;
|
|
2059
|
+
}
|
|
2060
|
+
async function pikeperpsGetMarketData(agent, tokenAddress, limit = 20) {
|
|
2061
|
+
const perpetualTradingAddress = PERPETUAL_TRADING[agent.chain];
|
|
2062
|
+
const bondingCurveAddress = BONDING_CURVE_MARKET[agent.chain];
|
|
2063
|
+
if (perpetualTradingAddress === "0x0000000000000000000000000000000000000000") {
|
|
2064
|
+
throw new Error(
|
|
2065
|
+
`PikePerps not available on ${agent.chain}. Only available on testnet.`
|
|
2066
|
+
);
|
|
2067
|
+
}
|
|
2068
|
+
if (agent.demo) {
|
|
2069
|
+
return {
|
|
2070
|
+
token: tokenAddress,
|
|
2071
|
+
currentPrice: BigInt("100000000"),
|
|
2072
|
+
// $1.00 scaled by 1e8
|
|
2073
|
+
hasPrice: true,
|
|
2074
|
+
isListed: true,
|
|
2075
|
+
curveProgress: BigInt("5000"),
|
|
2076
|
+
// 50%
|
|
2077
|
+
recentTrades: [
|
|
2078
|
+
{
|
|
2079
|
+
positionId: 1n,
|
|
2080
|
+
trader: "0x0000000000000000000000000000000000000001",
|
|
2081
|
+
token: tokenAddress,
|
|
2082
|
+
isLong: true,
|
|
2083
|
+
size: BigInt("1000000000000000000"),
|
|
2084
|
+
margin: BigInt("100000000000000000"),
|
|
2085
|
+
leverage: 10n,
|
|
2086
|
+
entryPrice: BigInt("100000000"),
|
|
2087
|
+
timestamp: Math.floor(Date.now() / 1e3) - 300,
|
|
2088
|
+
txHash: "0xdemo_trade_hash",
|
|
2089
|
+
blockNumber: 1000n
|
|
2090
|
+
}
|
|
2091
|
+
]
|
|
2092
|
+
};
|
|
2093
|
+
}
|
|
2094
|
+
let currentPrice = 0n;
|
|
2095
|
+
let hasPrice = false;
|
|
2096
|
+
try {
|
|
2097
|
+
const [price, hasPriceResult] = await agent.client.readContract({
|
|
2098
|
+
address: perpetualTradingAddress,
|
|
2099
|
+
abi: PERPETUAL_TRADING_ABI,
|
|
2100
|
+
functionName: "getCurrentPrice",
|
|
2101
|
+
args: [tokenAddress]
|
|
2102
|
+
});
|
|
2103
|
+
currentPrice = price;
|
|
2104
|
+
hasPrice = hasPriceResult;
|
|
2105
|
+
} catch {
|
|
2106
|
+
}
|
|
2107
|
+
let isListed = false;
|
|
2108
|
+
let curveProgress = 0n;
|
|
2109
|
+
if (bondingCurveAddress !== "0x0000000000000000000000000000000000000000") {
|
|
2110
|
+
try {
|
|
2111
|
+
isListed = await agent.client.readContract({
|
|
2112
|
+
address: bondingCurveAddress,
|
|
2113
|
+
abi: BONDING_CURVE_MARKET_ABI,
|
|
2114
|
+
functionName: "isListed",
|
|
2115
|
+
args: [tokenAddress]
|
|
2116
|
+
});
|
|
2117
|
+
if (isListed) {
|
|
2118
|
+
curveProgress = await agent.client.readContract({
|
|
2119
|
+
address: bondingCurveAddress,
|
|
2120
|
+
abi: BONDING_CURVE_MARKET_ABI,
|
|
2121
|
+
functionName: "getCurveProgress",
|
|
2122
|
+
args: [tokenAddress]
|
|
2123
|
+
});
|
|
2124
|
+
}
|
|
2125
|
+
} catch {
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
const recentTrades = [];
|
|
2129
|
+
try {
|
|
2130
|
+
const currentBlock = await agent.client.getBlockNumber();
|
|
2131
|
+
const fromBlock = currentBlock > 1000n ? currentBlock - 1000n : 0n;
|
|
2132
|
+
const logs = await agent.client.getLogs({
|
|
2133
|
+
address: perpetualTradingAddress,
|
|
2134
|
+
event: parseAbiItem(
|
|
2135
|
+
"event PositionOpened(uint256 indexed positionId, address indexed user, address indexed token, bool isLong, uint256 size, uint256 margin, uint256 leverage, uint256 entryPrice)"
|
|
2136
|
+
),
|
|
2137
|
+
args: {
|
|
2138
|
+
token: tokenAddress
|
|
2139
|
+
},
|
|
2140
|
+
fromBlock,
|
|
2141
|
+
toBlock: currentBlock
|
|
2142
|
+
});
|
|
2143
|
+
const blockCache = /* @__PURE__ */ new Map();
|
|
2144
|
+
for (const log of logs.slice(-limit)) {
|
|
2145
|
+
let timestamp = 0;
|
|
2146
|
+
if (!blockCache.has(log.blockNumber)) {
|
|
2147
|
+
try {
|
|
2148
|
+
const block = await agent.client.getBlock({
|
|
2149
|
+
blockNumber: log.blockNumber
|
|
2150
|
+
});
|
|
2151
|
+
timestamp = Number(block.timestamp);
|
|
2152
|
+
blockCache.set(log.blockNumber, timestamp);
|
|
2153
|
+
} catch {
|
|
2154
|
+
timestamp = Math.floor(Date.now() / 1e3);
|
|
2155
|
+
}
|
|
2156
|
+
} else {
|
|
2157
|
+
timestamp = blockCache.get(log.blockNumber) || 0;
|
|
2158
|
+
}
|
|
2159
|
+
recentTrades.push({
|
|
2160
|
+
positionId: BigInt(log.topics[1] || "0"),
|
|
2161
|
+
trader: log.topics[2],
|
|
2162
|
+
token: tokenAddress,
|
|
2163
|
+
isLong: log.args.isLong || false,
|
|
2164
|
+
size: log.args.size || 0n,
|
|
2165
|
+
margin: log.args.margin || 0n,
|
|
2166
|
+
leverage: log.args.leverage || 0n,
|
|
2167
|
+
entryPrice: log.args.entryPrice || 0n,
|
|
2168
|
+
timestamp,
|
|
2169
|
+
txHash: log.transactionHash,
|
|
2170
|
+
blockNumber: log.blockNumber
|
|
2171
|
+
});
|
|
2172
|
+
}
|
|
2173
|
+
} catch (error) {
|
|
2174
|
+
console.warn("Failed to fetch recent trades:", error);
|
|
2175
|
+
}
|
|
2176
|
+
return {
|
|
2177
|
+
token: tokenAddress,
|
|
2178
|
+
currentPrice,
|
|
2179
|
+
hasPrice,
|
|
2180
|
+
isListed,
|
|
2181
|
+
curveProgress,
|
|
2182
|
+
recentTrades
|
|
2183
|
+
};
|
|
2184
|
+
}
|
|
1336
2185
|
|
|
1337
2186
|
// src/tools/okx/getSwapQuote.ts
|
|
1338
2187
|
var getSwapQuote = async (agent, from, to, amount, slippagePercentage) => {
|
|
@@ -1425,6 +2274,29 @@ function getProjectConfig() {
|
|
|
1425
2274
|
}
|
|
1426
2275
|
return cachedConfig;
|
|
1427
2276
|
}
|
|
2277
|
+
async function getUserAccountData(agent, userAddress) {
|
|
2278
|
+
const lendingPoolAddress = LENDING_POOL[agent.chain];
|
|
2279
|
+
const address = userAddress || agent.account.address;
|
|
2280
|
+
if (lendingPoolAddress === "0x0000000000000000000000000000000000000000") {
|
|
2281
|
+
throw new Error(
|
|
2282
|
+
`Lendle LendingPool not configured for ${agent.chain}. Only available on mainnet.`
|
|
2283
|
+
);
|
|
2284
|
+
}
|
|
2285
|
+
const result = await agent.client.readContract({
|
|
2286
|
+
address: lendingPoolAddress,
|
|
2287
|
+
abi: LENDING_POOL_ABI,
|
|
2288
|
+
functionName: "getUserAccountData",
|
|
2289
|
+
args: [address]
|
|
2290
|
+
});
|
|
2291
|
+
return {
|
|
2292
|
+
totalCollateralETH: result[0],
|
|
2293
|
+
totalDebtETH: result[1],
|
|
2294
|
+
availableBorrowsETH: result[2],
|
|
2295
|
+
currentLiquidationThreshold: result[3],
|
|
2296
|
+
ltv: result[4],
|
|
2297
|
+
healthFactor: result[5]
|
|
2298
|
+
};
|
|
2299
|
+
}
|
|
1428
2300
|
var MNTAgentKit = class {
|
|
1429
2301
|
account;
|
|
1430
2302
|
client;
|
|
@@ -1540,6 +2412,24 @@ var MNTAgentKit = class {
|
|
|
1540
2412
|
async lendleRepay(tokenAddress, amount, rateMode = 2, onBehalfOf) {
|
|
1541
2413
|
return await lendleRepay(this, tokenAddress, amount, rateMode, onBehalfOf);
|
|
1542
2414
|
}
|
|
2415
|
+
/**
|
|
2416
|
+
* Get user account data from Lendle LendingPool
|
|
2417
|
+
* Returns overall position including total collateral, debt, and health factor
|
|
2418
|
+
* @param userAddress - User wallet address (optional, defaults to agent account)
|
|
2419
|
+
* @returns User account data with collateral, debt, available borrows, and health factor
|
|
2420
|
+
*/
|
|
2421
|
+
async lendleGetUserAccountData(userAddress) {
|
|
2422
|
+
return await getUserAccountData(this, userAddress);
|
|
2423
|
+
}
|
|
2424
|
+
/**
|
|
2425
|
+
* Get all Lendle positions for a user (per-token breakdown)
|
|
2426
|
+
* Returns detailed supply and borrow amounts for each asset
|
|
2427
|
+
* @param userAddress - User wallet address (optional, defaults to agent account)
|
|
2428
|
+
* @returns Array of positions with supply/borrow amounts per asset
|
|
2429
|
+
*/
|
|
2430
|
+
async lendleGetPositions(userAddress) {
|
|
2431
|
+
return await lendleGetPositions(this, userAddress);
|
|
2432
|
+
}
|
|
1543
2433
|
// Agni Finance DEX (#1 on Mantle)
|
|
1544
2434
|
async agniSwap(tokenIn, tokenOut, amountIn, slippagePercent = 0.5, feeTier) {
|
|
1545
2435
|
return await agniSwap(
|
|
@@ -1568,6 +2458,33 @@ var MNTAgentKit = class {
|
|
|
1568
2458
|
}
|
|
1569
2459
|
return METH_TOKEN[this.chain];
|
|
1570
2460
|
}
|
|
2461
|
+
/**
|
|
2462
|
+
* Get mETH staking position for a user
|
|
2463
|
+
* Returns mETH balance and WETH balance for comparison
|
|
2464
|
+
* @param userAddress - User wallet address (optional, defaults to agent account)
|
|
2465
|
+
* @returns mETH position with balances
|
|
2466
|
+
*/
|
|
2467
|
+
async methGetPosition(userAddress) {
|
|
2468
|
+
return await methGetPosition(this, userAddress);
|
|
2469
|
+
}
|
|
2470
|
+
/**
|
|
2471
|
+
* Swap WETH to mETH using DEX aggregator
|
|
2472
|
+
* @param amount - Amount of WETH to swap (in wei as string)
|
|
2473
|
+
* @param slippage - Slippage tolerance percentage (default 0.5%)
|
|
2474
|
+
* @returns Transaction hash
|
|
2475
|
+
*/
|
|
2476
|
+
async swapToMeth(amount, slippage = 0.5) {
|
|
2477
|
+
return await swapToMeth(this, amount, slippage);
|
|
2478
|
+
}
|
|
2479
|
+
/**
|
|
2480
|
+
* Swap mETH to WETH using DEX aggregator
|
|
2481
|
+
* @param amount - Amount of mETH to swap (in wei as string)
|
|
2482
|
+
* @param slippage - Slippage tolerance percentage (default 0.5%)
|
|
2483
|
+
* @returns Transaction hash
|
|
2484
|
+
*/
|
|
2485
|
+
async swapFromMeth(amount, slippage = 0.5) {
|
|
2486
|
+
return await swapFromMeth(this, amount, slippage);
|
|
2487
|
+
}
|
|
1571
2488
|
// Squid Router Cross-chain
|
|
1572
2489
|
async getSquidRoute(fromToken, toToken, fromChain, toChain, amount, slippage = 1) {
|
|
1573
2490
|
return await getSquidRoute(
|
|
@@ -1591,8 +2508,56 @@ var MNTAgentKit = class {
|
|
|
1591
2508
|
slippage
|
|
1592
2509
|
);
|
|
1593
2510
|
}
|
|
2511
|
+
// PikePerps - Perpetual Trading
|
|
2512
|
+
/**
|
|
2513
|
+
* Open a long position on PikePerps
|
|
2514
|
+
* @param tokenAddress - Token to trade (meme token address)
|
|
2515
|
+
* @param margin - Margin amount in wei (as string)
|
|
2516
|
+
* @param leverage - Leverage multiplier (1-100, default 10)
|
|
2517
|
+
* @returns Position ID and transaction hash
|
|
2518
|
+
*/
|
|
2519
|
+
async pikeperpsOpenLong(tokenAddress, margin, leverage = 10) {
|
|
2520
|
+
return await pikeperpsOpenLong(this, tokenAddress, margin, leverage);
|
|
2521
|
+
}
|
|
2522
|
+
/**
|
|
2523
|
+
* Open a short position on PikePerps
|
|
2524
|
+
* @param tokenAddress - Token to trade (meme token address)
|
|
2525
|
+
* @param margin - Margin amount in wei (as string)
|
|
2526
|
+
* @param leverage - Leverage multiplier (1-100, default 10)
|
|
2527
|
+
* @returns Position ID and transaction hash
|
|
2528
|
+
*/
|
|
2529
|
+
async pikeperpsOpenShort(tokenAddress, margin, leverage = 10) {
|
|
2530
|
+
return await pikeperpsOpenShort(this, tokenAddress, margin, leverage);
|
|
2531
|
+
}
|
|
2532
|
+
/**
|
|
2533
|
+
* Close an existing position on PikePerps
|
|
2534
|
+
* @param positionId - Position ID to close
|
|
2535
|
+
* @returns Transaction hash
|
|
2536
|
+
*/
|
|
2537
|
+
async pikeperpsClosePosition(positionId) {
|
|
2538
|
+
return await pikeperpsClosePosition(this, positionId);
|
|
2539
|
+
}
|
|
2540
|
+
/**
|
|
2541
|
+
* Get all positions for a user on PikePerps
|
|
2542
|
+
* Returns detailed position data including PnL and liquidation prices
|
|
2543
|
+
* @param userAddress - User wallet address (optional, defaults to agent account)
|
|
2544
|
+
* @returns Array of positions with PnL and liquidation data
|
|
2545
|
+
*/
|
|
2546
|
+
async pikeperpsGetPositions(userAddress) {
|
|
2547
|
+
return await pikeperpsGetPositions(this, userAddress);
|
|
2548
|
+
}
|
|
2549
|
+
/**
|
|
2550
|
+
* Get market data for a token on PikePerps
|
|
2551
|
+
* Returns current price and recent trades
|
|
2552
|
+
* @param tokenAddress - Token address to get market data for
|
|
2553
|
+
* @param limit - Maximum number of recent trades to return (default 20)
|
|
2554
|
+
* @returns Market data with price and recent trades
|
|
2555
|
+
*/
|
|
2556
|
+
async pikeperpsGetMarketData(tokenAddress, limit = 20) {
|
|
2557
|
+
return await pikeperpsGetMarketData(this, tokenAddress, limit);
|
|
2558
|
+
}
|
|
1594
2559
|
};
|
|
1595
2560
|
|
|
1596
|
-
export { agni_exports as AgniConstants, lendle_exports as LendleConstants, METH_TOKEN, MNTAgentKit, merchantmoe_exports as MerchantMoeConstants, meth_exports as MethConstants, okx_exports as OKXConstants, oneinch_exports as OneInchConstants, openocean_exports as OpenOceanConstants, squid_exports as SquidConstants, uniswap_exports as UniswapConstants, agniSwap, approveToken, crossChainSwapViaSquid, executeSwap, get1inchQuote, getOpenOceanQuote, getProjectConfig, getSquidRoute, getUniswapQuote, initializePlatform, lendleBorrow, lendleRepay, lendleSupply, lendleWithdraw, merchantMoeSwap, sendTransaction, swapOn1inch, swapOnOpenOcean, swapOnUniswap };
|
|
2561
|
+
export { agni_exports as AgniConstants, lendle_exports as LendleConstants, METH_TOKEN, MNTAgentKit, merchantmoe_exports as MerchantMoeConstants, meth_exports as MethConstants, okx_exports as OKXConstants, oneinch_exports as OneInchConstants, openocean_exports as OpenOceanConstants, pikeperps_exports as PikePerpsConstants, squid_exports as SquidConstants, uniswap_exports as UniswapConstants, agniSwap, approveToken, crossChainSwapViaSquid, executeSwap, get1inchQuote, getOpenOceanQuote, getProjectConfig, getSquidRoute, getUniswapQuote, initializePlatform, lendleBorrow, lendleGetPositions, lendleRepay, lendleSupply, lendleWithdraw, merchantMoeSwap, methGetPosition, pikeperpsClosePosition, pikeperpsGetMarketData, pikeperpsGetPositions, pikeperpsOpenLong, pikeperpsOpenShort, sendTransaction, swapFromMeth, swapOn1inch, swapOnOpenOcean, swapOnUniswap, swapToMeth };
|
|
1597
2562
|
//# sourceMappingURL=index.js.map
|
|
1598
2563
|
//# sourceMappingURL=index.js.map
|