four-flap-meme-sdk 1.5.51 → 1.5.52
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/xlayer/bundle.js +87 -59
- package/package.json +1 -1
package/dist/xlayer/bundle.js
CHANGED
|
@@ -648,7 +648,7 @@ export class BundleExecutor {
|
|
|
648
648
|
// TODO: 如果需要,可以在这里检查并转账 ERC20 代币到 sender
|
|
649
649
|
}
|
|
650
650
|
});
|
|
651
|
-
// ✅ 构建买入 callData:如果使用 ERC20
|
|
651
|
+
// ✅ 构建买入 callData:如果使用 ERC20 代币,需要先 approve
|
|
652
652
|
const buyCallDatas = buyWeis.map((buyWei) => {
|
|
653
653
|
// 使用 portal 的 swapExactInput,支持 inputToken 参数
|
|
654
654
|
const portalIface = new Interface([
|
|
@@ -663,8 +663,16 @@ export class BundleExecutor {
|
|
|
663
663
|
permitData: '0x',
|
|
664
664
|
},
|
|
665
665
|
]);
|
|
666
|
-
//
|
|
667
|
-
|
|
666
|
+
// ✅ ERC20 代币需要先 approve,使用 executeBatch 将 approve + swap 合并为一个 UserOp
|
|
667
|
+
if (useNativeToken) {
|
|
668
|
+
// 原生代币:直接 swap
|
|
669
|
+
return encodeExecute(this.portalAddress, buyWei, swapData);
|
|
670
|
+
}
|
|
671
|
+
else {
|
|
672
|
+
// ERC20 代币:approve + swap 批量调用
|
|
673
|
+
const approveData = encodeApproveCall(this.portalAddress, buyWei);
|
|
674
|
+
return encodeExecuteBatch([inputToken, this.portalAddress], [0n, 0n], [approveData, swapData]);
|
|
675
|
+
}
|
|
668
676
|
});
|
|
669
677
|
const initCodes = accountInfos.map((ai, i) => ai.deployed ? '0x' : this.aaManager.generateInitCode(wallets[i].address));
|
|
670
678
|
const { userOps: buyUserOps, prefundWeis } = await this.aaManager.buildUserOpsWithBundlerEstimateBatch({
|
|
@@ -977,7 +985,7 @@ export class BundleExecutor {
|
|
|
977
985
|
// TODO: 如果需要,可以在这里检查并转账 ERC20 代币到 sender
|
|
978
986
|
}
|
|
979
987
|
});
|
|
980
|
-
// ✅ 构建买入 callData:如果使用 ERC20
|
|
988
|
+
// ✅ 构建买入 callData:如果使用 ERC20 代币,需要先 approve
|
|
981
989
|
const buyCallDatas = buyWeis.map((buyWei) => {
|
|
982
990
|
// 使用 portal 的 swapExactInput,支持 inputToken 参数
|
|
983
991
|
const portalIface = new Interface([
|
|
@@ -992,8 +1000,16 @@ export class BundleExecutor {
|
|
|
992
1000
|
permitData: '0x',
|
|
993
1001
|
},
|
|
994
1002
|
]);
|
|
995
|
-
//
|
|
996
|
-
|
|
1003
|
+
// ✅ ERC20 代币需要先 approve,使用 executeBatch 将 approve + swap 合并为一个 UserOp
|
|
1004
|
+
if (useNativeToken) {
|
|
1005
|
+
// 原生代币:直接 swap
|
|
1006
|
+
return encodeExecute(this.portalAddress, buyWei, swapData);
|
|
1007
|
+
}
|
|
1008
|
+
else {
|
|
1009
|
+
// ERC20 代币:approve + swap 批量调用
|
|
1010
|
+
const approveData = encodeApproveCall(this.portalAddress, buyWei);
|
|
1011
|
+
return encodeExecuteBatch([inputToken, this.portalAddress], [0n, 0n], [approveData, swapData]);
|
|
1012
|
+
}
|
|
997
1013
|
});
|
|
998
1014
|
const initCodes = accountInfos.map((ai, i) => (ai.deployed ? '0x' : this.aaManager.generateInitCode(wallets[i].address)));
|
|
999
1015
|
const { userOps: buyUserOps, prefundWeis } = await this.aaManager.buildUserOpsWithBundlerEstimateBatch({
|
|
@@ -1252,12 +1268,15 @@ export class BundleExecutor {
|
|
|
1252
1268
|
const inputToken = params.quoteToken && params.quoteToken !== ZERO_ADDRESS ? params.quoteToken : ZERO_ADDRESS;
|
|
1253
1269
|
const useNativeToken = inputToken === ZERO_ADDRESS;
|
|
1254
1270
|
const quoteDecimals = 18;
|
|
1255
|
-
let totalBuyWei = 0n;
|
|
1256
|
-
let totalBuyProfitWei = 0n;
|
|
1257
|
-
const buyerSenders = [];
|
|
1258
1271
|
const portalIface = new Interface(PORTAL_ABI);
|
|
1259
|
-
|
|
1260
|
-
|
|
1272
|
+
// ✅ 批量获取所有买家的账户信息(并行优化)
|
|
1273
|
+
const buyerAccountInfos = await this.aaManager.getMultipleAccountInfo(buyerWallets.map(w => w.address));
|
|
1274
|
+
const buyerSenders = buyerAccountInfos.map(ai => ai.sender);
|
|
1275
|
+
for (const ai of buyerAccountInfos) {
|
|
1276
|
+
nonceMap.init(ai.sender, ai.nonce);
|
|
1277
|
+
}
|
|
1278
|
+
// ✅ 预计算所有买家的金额和利润
|
|
1279
|
+
const buyerData = buyerWallets.map((buyer, i) => {
|
|
1261
1280
|
const amountStr = buyAmounts[i] || '0';
|
|
1262
1281
|
const originalWei = useNativeToken ? parseOkb(amountStr) : ethers.parseUnits(amountStr, quoteDecimals);
|
|
1263
1282
|
let buyWei = originalWei;
|
|
@@ -1267,11 +1286,13 @@ export class BundleExecutor {
|
|
|
1267
1286
|
buyWei = res.remaining;
|
|
1268
1287
|
profitWei = res.profit;
|
|
1269
1288
|
}
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1289
|
+
return { buyer, buyWei, profitWei, accountInfo: buyerAccountInfos[i] };
|
|
1290
|
+
});
|
|
1291
|
+
const totalBuyWei = buyerData.reduce((sum, d) => sum + d.buyWei, 0n);
|
|
1292
|
+
const totalBuyProfitWei = buyerData.reduce((sum, d) => sum + d.profitWei, 0n);
|
|
1293
|
+
// ✅ 并行构建和签名所有买家的 UserOps
|
|
1294
|
+
const signedBuyOps = await mapWithConcurrency(buyerData, 5, async (data) => {
|
|
1295
|
+
const { buyer, buyWei, accountInfo } = data;
|
|
1275
1296
|
const swapData = portalIface.encodeFunctionData('swapExactInput', [
|
|
1276
1297
|
{
|
|
1277
1298
|
inputToken,
|
|
@@ -1281,17 +1302,28 @@ export class BundleExecutor {
|
|
|
1281
1302
|
permitData: '0x',
|
|
1282
1303
|
},
|
|
1283
1304
|
]);
|
|
1305
|
+
// ✅ ERC20 代币需要先 approve,使用 executeBatch 将 approve + swap 合并为一个 UserOp
|
|
1306
|
+
let buyCallData;
|
|
1307
|
+
if (useNativeToken) {
|
|
1308
|
+
buyCallData = encodeExecute(this.portalAddress, buyWei, swapData);
|
|
1309
|
+
}
|
|
1310
|
+
else {
|
|
1311
|
+
const approveData = encodeApproveCall(this.portalAddress, buyWei);
|
|
1312
|
+
buyCallData = encodeExecuteBatch([inputToken, this.portalAddress], [0n, 0n], [approveData, swapData]);
|
|
1313
|
+
}
|
|
1284
1314
|
const buyOp = await this.aaManager.buildUserOpWithFixedGas({
|
|
1285
1315
|
ownerWallet: buyer,
|
|
1286
|
-
sender:
|
|
1287
|
-
callData:
|
|
1288
|
-
nonce: nonceMap.next(
|
|
1289
|
-
initCode:
|
|
1290
|
-
deployed:
|
|
1316
|
+
sender: accountInfo.sender,
|
|
1317
|
+
callData: buyCallData,
|
|
1318
|
+
nonce: nonceMap.next(accountInfo.sender),
|
|
1319
|
+
initCode: accountInfo.deployed ? '0x' : this.aaManager.generateInitCode(buyer.address),
|
|
1320
|
+
deployed: accountInfo.deployed
|
|
1291
1321
|
});
|
|
1292
1322
|
const signedBuyOp = await this.aaManager.signUserOp(buyOp.userOp, buyer);
|
|
1293
|
-
|
|
1294
|
-
}
|
|
1323
|
+
return signedBuyOp.userOp;
|
|
1324
|
+
});
|
|
1325
|
+
// 将所有签名的买入 UserOps 添加到操作列表
|
|
1326
|
+
ops.push(...signedBuyOps);
|
|
1295
1327
|
// 利润由尾笔交易处理(不再在买入阶段追加利润转账 UserOp)
|
|
1296
1328
|
// === 计算利润金额 ===
|
|
1297
1329
|
let nativeProfitAmount = 0n;
|
|
@@ -1425,17 +1457,20 @@ export class BundleExecutor {
|
|
|
1425
1457
|
});
|
|
1426
1458
|
const signedCreateOp = await aaManager.signUserOp(createOpRes.userOp, payerWallet);
|
|
1427
1459
|
ops1.push(signedCreateOp.userOp);
|
|
1428
|
-
// --- 3. 构建内盘买入 Ops
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
const info = curveBuyerInfos[i];
|
|
1460
|
+
// --- 3. 构建内盘买入 Ops(并行优化)---
|
|
1461
|
+
// ✅ 预计算所有买入金额
|
|
1462
|
+
const curveBuyData = curveBuyerWallets.map((wallet, i) => {
|
|
1432
1463
|
const buyWei = parseOkb(curveBuyAmounts[i]);
|
|
1433
|
-
|
|
1464
|
+
const isLast = i === curveBuyerWallets.length - 1;
|
|
1465
|
+
const gasLimit = isLast ? 8000000n : 800000n; // 最后一笔触发毕业,给大一点
|
|
1466
|
+
return { wallet, info: curveBuyerInfos[i], buyWei, gasLimit };
|
|
1467
|
+
});
|
|
1468
|
+
totalCurveBuyWei = curveBuyData.reduce((sum, d) => sum + d.buyWei, 0n);
|
|
1469
|
+
// ✅ 并行构建和签名所有内盘买入 UserOps
|
|
1470
|
+
const signedCurveBuyOps = await mapWithConcurrency(curveBuyData, 5, async (data) => {
|
|
1471
|
+
const { wallet, info, buyWei, gasLimit } = data;
|
|
1434
1472
|
const buyData = encodeBuyCall(tokenAddress, buyWei, 0n);
|
|
1435
1473
|
const buyCallData = encodeExecute(FLAP_PORTAL, buyWei, buyData);
|
|
1436
|
-
// 最后一笔买入通常触发毕业,GasLimit 给大一点 (8M)
|
|
1437
|
-
const isLast = i === curveBuyerWallets.length - 1;
|
|
1438
|
-
const gasLimit = isLast ? 8000000n : 800000n;
|
|
1439
1474
|
const buyOpRes = await aaManager.buildUserOpWithFixedGas({
|
|
1440
1475
|
ownerWallet: wallet,
|
|
1441
1476
|
sender: info.sender,
|
|
@@ -1446,8 +1481,9 @@ export class BundleExecutor {
|
|
|
1446
1481
|
fixedGas: { callGasLimit: gasLimit }
|
|
1447
1482
|
});
|
|
1448
1483
|
const signedBuyOp = await aaManager.signUserOp(buyOpRes.userOp, wallet);
|
|
1449
|
-
|
|
1450
|
-
}
|
|
1484
|
+
return signedBuyOp.userOp;
|
|
1485
|
+
});
|
|
1486
|
+
ops1.push(...signedCurveBuyOps);
|
|
1451
1487
|
// 签名第一个 handleOps
|
|
1452
1488
|
const startNonce = params.payerStartNonce ?? (await provider.getTransactionCount(payerWallet.address, 'pending'));
|
|
1453
1489
|
const signedMainTx = await this.signHandleOpsTx({
|
|
@@ -1467,40 +1503,32 @@ export class BundleExecutor {
|
|
|
1467
1503
|
});
|
|
1468
1504
|
const ops2 = [];
|
|
1469
1505
|
const deadline = Math.floor(Date.now() / 1000) + 1200; // 20 min
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
const info = dexBuyerInfos[i];
|
|
1506
|
+
// ✅ 预计算所有外盘买入金额
|
|
1507
|
+
const dexBuyData = dexBuyerWallets.map((wallet, i) => {
|
|
1473
1508
|
const buyWei = parseOkb(dexBuyAmounts[i]);
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1509
|
+
return { wallet, info: dexBuyerInfos[i], buyWei };
|
|
1510
|
+
});
|
|
1511
|
+
totalDexBuyWei = dexBuyData.reduce((sum, d) => sum + d.buyWei, 0n);
|
|
1512
|
+
// ✅ 并行构建和签名所有外盘买入 UserOps
|
|
1513
|
+
const signedDexBuyOps = await mapWithConcurrency(dexBuyData, 5, async (data) => {
|
|
1514
|
+
const { wallet, info, buyWei } = data;
|
|
1515
|
+
// AA 模式外盘:使用 executeBatch 将 Approve + Swap 合并为一个 UserOp
|
|
1477
1516
|
const approveData = encodeApproveCall(POTATOSWAP_V2_ROUTER);
|
|
1478
|
-
const approveCallData = encodeExecute(tokenAddress, 0n, approveData);
|
|
1479
|
-
const approveOpRes = await aaManager.buildUserOpWithFixedGas({
|
|
1480
|
-
ownerWallet: wallet,
|
|
1481
|
-
sender: info.sender,
|
|
1482
|
-
callData: approveCallData,
|
|
1483
|
-
nonce: nonceMap.next(info.sender),
|
|
1484
|
-
initCode: '0x', // HandleOps1 已部署
|
|
1485
|
-
deployed: true,
|
|
1486
|
-
fixedGas: { callGasLimit: 100000n }
|
|
1487
|
-
});
|
|
1488
|
-
const signedApprove = await aaManager.signUserOp(approveOpRes.userOp, wallet);
|
|
1489
|
-
ops2.push(signedApprove.userOp);
|
|
1490
|
-
// 2. Swap (PotatoSwap V2)
|
|
1491
1517
|
const swapData = encodeSwapExactETHForTokensSupportingFee(0n, [WOKB, tokenAddress], info.sender, deadline);
|
|
1492
|
-
const
|
|
1493
|
-
const
|
|
1518
|
+
const batchCallData = encodeExecuteBatch([tokenAddress, POTATOSWAP_V2_ROUTER], [0n, buyWei], [approveData, swapData]);
|
|
1519
|
+
const dexBuyOpRes = await aaManager.buildUserOpWithFixedGas({
|
|
1494
1520
|
ownerWallet: wallet,
|
|
1495
1521
|
sender: info.sender,
|
|
1496
|
-
callData:
|
|
1522
|
+
callData: batchCallData,
|
|
1497
1523
|
nonce: nonceMap.next(info.sender),
|
|
1524
|
+
initCode: '0x', // HandleOps1 已部署
|
|
1498
1525
|
deployed: true,
|
|
1499
|
-
fixedGas: { callGasLimit:
|
|
1526
|
+
fixedGas: { callGasLimit: 600000n }
|
|
1500
1527
|
});
|
|
1501
|
-
const
|
|
1502
|
-
|
|
1503
|
-
}
|
|
1528
|
+
const signedDexBuyOp = await aaManager.signUserOp(dexBuyOpRes.userOp, wallet);
|
|
1529
|
+
return signedDexBuyOp.userOp;
|
|
1530
|
+
});
|
|
1531
|
+
ops2.push(...signedDexBuyOps);
|
|
1504
1532
|
const signedDexTx = await this.signHandleOpsTx({
|
|
1505
1533
|
ops: ops2,
|
|
1506
1534
|
payerWallet: payerWallet,
|