four-flap-meme-sdk 1.5.61 → 1.5.63
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 +90 -28
- package/dist/xlayer/types.d.ts +4 -0
- package/package.json +1 -1
package/dist/xlayer/bundle.js
CHANGED
|
@@ -131,7 +131,7 @@ export class BundleExecutor {
|
|
|
131
131
|
/**
|
|
132
132
|
* 执行 handleOps 并解析结果
|
|
133
133
|
*/
|
|
134
|
-
async runHandleOps(label, ops, bundlerSigner, beneficiary) {
|
|
134
|
+
async runHandleOps(label, ops, bundlerSigner, beneficiary, overrides) {
|
|
135
135
|
if (ops.length === 0) {
|
|
136
136
|
console.log(`\n[${label}] 没有 ops,跳过`);
|
|
137
137
|
return null;
|
|
@@ -142,7 +142,16 @@ export class BundleExecutor {
|
|
|
142
142
|
console.log(`\n[${label}] 发送 handleOps,ops=${ops.length} ...`);
|
|
143
143
|
// 使用 bundlerSigner 创建新的合约实例以调用 handleOps
|
|
144
144
|
const entryPointWithSigner = new Contract(entryPointAddress, ENTRYPOINT_ABI, bundlerSigner);
|
|
145
|
-
|
|
145
|
+
// 优先使用手动指定的 gas 配置,其次使用实例全局配置中的配置,最后使用网络获取的值或默认值
|
|
146
|
+
const gasPrice = overrides?.gasPrice ??
|
|
147
|
+
(this.config.minGasPriceGwei ? ethers.parseUnits(this.config.minGasPriceGwei.toString(), 'gwei') : undefined) ??
|
|
148
|
+
feeData.gasPrice ??
|
|
149
|
+
100000000n;
|
|
150
|
+
const gasLimit = overrides?.gasLimit ?? this.config.gasLimit;
|
|
151
|
+
const tx = await entryPointWithSigner.handleOps(ops, beneficiary, {
|
|
152
|
+
gasPrice,
|
|
153
|
+
...(gasLimit ? { gasLimit } : {})
|
|
154
|
+
});
|
|
146
155
|
console.log(`[${label}] txHash:`, tx.hash);
|
|
147
156
|
const receipt = await tx.wait();
|
|
148
157
|
console.log(`[${label}] mined block=${receipt.blockNumber} status=${receipt.status}`);
|
|
@@ -189,9 +198,12 @@ export class BundleExecutor {
|
|
|
189
198
|
const epIface = new Interface(ENTRYPOINT_ABI);
|
|
190
199
|
const data = epIface.encodeFunctionData('handleOps', [params.ops, params.beneficiary]);
|
|
191
200
|
const feeData = await provider.getFeeData();
|
|
192
|
-
const gasPrice = params.gasPrice ??
|
|
201
|
+
const gasPrice = params.gasPrice ??
|
|
202
|
+
(this.config.minGasPriceGwei ? ethers.parseUnits(this.config.minGasPriceGwei.toString(), 'gwei') : undefined) ??
|
|
203
|
+
feeData.gasPrice ??
|
|
204
|
+
100000000n;
|
|
193
205
|
const nonce = params.nonce ?? await provider.getTransactionCount(params.payerWallet.address, 'pending');
|
|
194
|
-
let gasLimit = params.gasLimit;
|
|
206
|
+
let gasLimit = params.gasLimit ?? this.config.gasLimit;
|
|
195
207
|
if (!gasLimit) {
|
|
196
208
|
try {
|
|
197
209
|
const est = await provider.estimateGas({
|
|
@@ -675,14 +687,24 @@ export class BundleExecutor {
|
|
|
675
687
|
}
|
|
676
688
|
});
|
|
677
689
|
const initCodes = accountInfos.map((ai, i) => ai.deployed ? '0x' : this.aaManager.generateInitCode(wallets[i].address));
|
|
678
|
-
|
|
679
|
-
|
|
690
|
+
// ✅ 使用固定 Gas 构建买入 UserOps(避免 Bundler 估算对未部署账户不准确)
|
|
691
|
+
const buyNonces = accountInfos.map((ai) => nonceMap.next(ai.sender));
|
|
692
|
+
const buyUserOpsBuilt = await mapWithConcurrency(accountInfos, 6, async (ai, i) => {
|
|
693
|
+
return this.aaManager.buildUserOpWithFixedGas({
|
|
694
|
+
ownerWallet: wallets[i],
|
|
680
695
|
sender: ai.sender,
|
|
681
|
-
nonce: nonceMap.next(ai.sender),
|
|
682
696
|
callData: buyCallDatas[i],
|
|
697
|
+
nonce: buyNonces[i],
|
|
683
698
|
initCode: initCodes[i],
|
|
684
|
-
|
|
699
|
+
deployed: ai.deployed,
|
|
700
|
+
fixedGas: {
|
|
701
|
+
...(effConfig.fixedGas ?? {}),
|
|
702
|
+
callGasLimit: effConfig.fixedGas?.callGasLimit ?? DEFAULT_CALL_GAS_LIMIT_BUY,
|
|
703
|
+
},
|
|
704
|
+
});
|
|
685
705
|
});
|
|
706
|
+
const buyUserOps = buyUserOpsBuilt.map((r) => r.userOp);
|
|
707
|
+
const prefundWeis = buyUserOpsBuilt.map((r) => r.prefundWei);
|
|
686
708
|
// 补足 prefund + 买入金额(使用扣除利润后的金额)
|
|
687
709
|
await mapWithConcurrency(accountInfos, 6, async (ai, i) => {
|
|
688
710
|
if (useNativeToken) {
|
|
@@ -726,7 +748,10 @@ export class BundleExecutor {
|
|
|
726
748
|
}
|
|
727
749
|
// 2. 执行买入 + 利润转账(同一笔 handleOps)
|
|
728
750
|
const allBuyOps = [...buyOps, ...profitOps];
|
|
729
|
-
const buyResult = await this.runHandleOps('buyBundle', allBuyOps, bundlerSigner, beneficiary
|
|
751
|
+
const buyResult = await this.runHandleOps('buyBundle', allBuyOps, bundlerSigner, beneficiary, {
|
|
752
|
+
gasLimit: effConfig.gasLimit,
|
|
753
|
+
gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
|
|
754
|
+
});
|
|
730
755
|
if (!buyResult) {
|
|
731
756
|
throw new Error('买入交易失败');
|
|
732
757
|
}
|
|
@@ -825,7 +850,11 @@ export class BundleExecutor {
|
|
|
825
850
|
});
|
|
826
851
|
sellOps.push(...signedSells);
|
|
827
852
|
}
|
|
828
|
-
const
|
|
853
|
+
const effConfig = { ...(this.config ?? {}), ...(config ?? {}) };
|
|
854
|
+
const sellResult = await this.runHandleOps('sellBundle', sellOps, bundlerSigner, beneficiary, {
|
|
855
|
+
gasLimit: effConfig.gasLimit,
|
|
856
|
+
gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
|
|
857
|
+
});
|
|
829
858
|
if (!sellResult) {
|
|
830
859
|
throw new Error('卖出交易失败');
|
|
831
860
|
}
|
|
@@ -874,7 +903,10 @@ export class BundleExecutor {
|
|
|
874
903
|
withdrawOps.push(op);
|
|
875
904
|
}
|
|
876
905
|
if (withdrawOps.length > 0) {
|
|
877
|
-
withdrawResult = await this.runHandleOps('withdrawBundle', withdrawOps, bundlerSigner, beneficiary
|
|
906
|
+
withdrawResult = await this.runHandleOps('withdrawBundle', withdrawOps, bundlerSigner, beneficiary, {
|
|
907
|
+
gasLimit: effConfig.gasLimit,
|
|
908
|
+
gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
|
|
909
|
+
}) ?? undefined;
|
|
878
910
|
}
|
|
879
911
|
}
|
|
880
912
|
return {
|
|
@@ -915,8 +947,8 @@ export class BundleExecutor {
|
|
|
915
947
|
const nonceMap = new AANonceMap();
|
|
916
948
|
for (const ai of accountInfos)
|
|
917
949
|
nonceMap.init(ai.sender, ai.nonce);
|
|
918
|
-
const
|
|
919
|
-
const profitSettingsBuySell = resolveProfitSettings(
|
|
950
|
+
const effConfig = { ...(this.config ?? {}), ...(config ?? {}) };
|
|
951
|
+
const profitSettingsBuySell = resolveProfitSettings(effConfig);
|
|
920
952
|
// ✅ 确定 inputToken:如果传入了 quoteToken 且非零地址,则使用它;否则使用零地址(原生代币)
|
|
921
953
|
const inputToken = quoteToken && quoteToken !== ZERO_ADDRESS ? quoteToken : ZERO_ADDRESS;
|
|
922
954
|
const useNativeToken = inputToken === ZERO_ADDRESS;
|
|
@@ -947,7 +979,7 @@ export class BundleExecutor {
|
|
|
947
979
|
// ✅ ERC20 购买:获取代币利润等值的原生代币(OKB)报价
|
|
948
980
|
let nativeBuyProfitAmount = totalBuyProfitWei; // 原生代币购买时直接使用
|
|
949
981
|
if (!useNativeToken && profitSettingsBuySell.extractProfit && totalBuyProfitWei > 0n) {
|
|
950
|
-
const dexQuery = new DexQuery(
|
|
982
|
+
const dexQuery = new DexQuery(effConfig);
|
|
951
983
|
try {
|
|
952
984
|
nativeBuyProfitAmount = await dexQuery.quoteTokenToOkb(totalBuyProfitWei, inputToken);
|
|
953
985
|
}
|
|
@@ -1012,14 +1044,24 @@ export class BundleExecutor {
|
|
|
1012
1044
|
}
|
|
1013
1045
|
});
|
|
1014
1046
|
const initCodes = accountInfos.map((ai, i) => (ai.deployed ? '0x' : this.aaManager.generateInitCode(wallets[i].address)));
|
|
1015
|
-
|
|
1016
|
-
|
|
1047
|
+
// ✅ 使用固定 Gas 构建买入 UserOps(避免 Bundler 估算对未部署账户不准确)
|
|
1048
|
+
const buyNonces = accountInfos.map((ai) => nonceMap.next(ai.sender));
|
|
1049
|
+
const buyUserOpsBuilt = await mapWithConcurrency(accountInfos, 6, async (ai, i) => {
|
|
1050
|
+
return this.aaManager.buildUserOpWithFixedGas({
|
|
1051
|
+
ownerWallet: wallets[i],
|
|
1017
1052
|
sender: ai.sender,
|
|
1018
|
-
nonce: nonceMap.next(ai.sender),
|
|
1019
1053
|
callData: buyCallDatas[i],
|
|
1054
|
+
nonce: buyNonces[i],
|
|
1020
1055
|
initCode: initCodes[i],
|
|
1021
|
-
|
|
1056
|
+
deployed: ai.deployed,
|
|
1057
|
+
fixedGas: {
|
|
1058
|
+
...(effConfig.fixedGas ?? {}),
|
|
1059
|
+
callGasLimit: effConfig.fixedGas?.callGasLimit ?? DEFAULT_CALL_GAS_LIMIT_BUY,
|
|
1060
|
+
},
|
|
1061
|
+
});
|
|
1022
1062
|
});
|
|
1063
|
+
const buyUserOps = buyUserOpsBuilt.map((r) => r.userOp);
|
|
1064
|
+
const prefundWeis = buyUserOpsBuilt.map((r) => r.prefundWei);
|
|
1023
1065
|
await mapWithConcurrency(accountInfos, 6, async (ai, i) => {
|
|
1024
1066
|
const buyWei = buyWeis[i] ?? 0n;
|
|
1025
1067
|
if (useNativeToken) {
|
|
@@ -1050,8 +1092,8 @@ export class BundleExecutor {
|
|
|
1050
1092
|
callData: profitCallData,
|
|
1051
1093
|
deployed: accountInfos[maxProfitIndex].deployed,
|
|
1052
1094
|
fixedGas: {
|
|
1053
|
-
...(
|
|
1054
|
-
callGasLimit:
|
|
1095
|
+
...(effConfig.fixedGas ?? {}),
|
|
1096
|
+
callGasLimit: effConfig.fixedGas?.callGasLimit ?? DEFAULT_CALL_GAS_LIMIT_WITHDRAW,
|
|
1055
1097
|
},
|
|
1056
1098
|
});
|
|
1057
1099
|
await this.aaManager.ensureSenderBalance(profitOwner, profitSender, nativeBuyProfitAmount + profitPrefund + parseOkb('0.0001'), `profit-transfer-fund`);
|
|
@@ -1059,7 +1101,10 @@ export class BundleExecutor {
|
|
|
1059
1101
|
profitOps.push(signedProfit.userOp);
|
|
1060
1102
|
}
|
|
1061
1103
|
const allBuyOps = [...buyOps, ...profitOps];
|
|
1062
|
-
const buyResult = await this.runHandleOps('buyBundle', allBuyOps, bundlerSigner, beneficiary
|
|
1104
|
+
const buyResult = await this.runHandleOps('buyBundle', allBuyOps, bundlerSigner, beneficiary, {
|
|
1105
|
+
gasLimit: effConfig.gasLimit,
|
|
1106
|
+
gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
|
|
1107
|
+
});
|
|
1063
1108
|
if (!buyResult) {
|
|
1064
1109
|
throw new Error('买入交易失败');
|
|
1065
1110
|
}
|
|
@@ -1087,7 +1132,10 @@ export class BundleExecutor {
|
|
|
1087
1132
|
});
|
|
1088
1133
|
for (const ops of sellPerWallet)
|
|
1089
1134
|
sellOps.push(...ops);
|
|
1090
|
-
const sellResult = await this.runHandleOps('sellBundle', sellOps, bundlerSigner, beneficiary
|
|
1135
|
+
const sellResult = await this.runHandleOps('sellBundle', sellOps, bundlerSigner, beneficiary, {
|
|
1136
|
+
gasLimit: effConfig.gasLimit,
|
|
1137
|
+
gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
|
|
1138
|
+
});
|
|
1091
1139
|
if (!sellResult) {
|
|
1092
1140
|
throw new Error('卖出交易失败');
|
|
1093
1141
|
}
|
|
@@ -1132,7 +1180,10 @@ export class BundleExecutor {
|
|
|
1132
1180
|
withdrawOps.push(op);
|
|
1133
1181
|
}
|
|
1134
1182
|
if (withdrawOps.length > 0) {
|
|
1135
|
-
withdrawResult = await this.runHandleOps('withdrawBundle', withdrawOps, bundlerSigner, beneficiary
|
|
1183
|
+
withdrawResult = await this.runHandleOps('withdrawBundle', withdrawOps, bundlerSigner, beneficiary, {
|
|
1184
|
+
gasLimit: effConfig.gasLimit,
|
|
1185
|
+
gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
|
|
1186
|
+
}) ?? undefined;
|
|
1136
1187
|
if (profitSettingsBuySell.extractProfit) {
|
|
1137
1188
|
const totalProfitForTail = nativeBuyProfitAmount + totalSellWithdrawProfitWei;
|
|
1138
1189
|
if (totalProfitForTail > 0n) {
|
|
@@ -1356,7 +1407,9 @@ export class BundleExecutor {
|
|
|
1356
1407
|
ops,
|
|
1357
1408
|
payerWallet: payer,
|
|
1358
1409
|
beneficiary: useBeneficiary,
|
|
1359
|
-
nonce: startNonce
|
|
1410
|
+
nonce: startNonce,
|
|
1411
|
+
gasLimit: effConfig.gasLimit,
|
|
1412
|
+
gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
|
|
1360
1413
|
});
|
|
1361
1414
|
signedTransactions.push(signedMainTx);
|
|
1362
1415
|
// === 2. 利润提取交易(独立的 EOA 转账)===
|
|
@@ -1415,7 +1468,8 @@ export class BundleExecutor {
|
|
|
1415
1468
|
const payerAccount = await aaManager.getAccountInfo(payerWallet.address);
|
|
1416
1469
|
const nonceMap = new AANonceMap();
|
|
1417
1470
|
nonceMap.init(payerAccount.sender, payerAccount.nonce);
|
|
1418
|
-
const
|
|
1471
|
+
const effConfig = { ...(this.config ?? {}), ...(config ?? {}) };
|
|
1472
|
+
const profitSettings = resolveProfitSettings(effConfig);
|
|
1419
1473
|
const signedTransactions = [];
|
|
1420
1474
|
let totalCurveBuyWei = 0n;
|
|
1421
1475
|
let totalDexBuyWei = 0n;
|
|
@@ -1490,7 +1544,9 @@ export class BundleExecutor {
|
|
|
1490
1544
|
ops: ops1,
|
|
1491
1545
|
payerWallet: payerWallet,
|
|
1492
1546
|
beneficiary: params.beneficiary ?? payerWallet.address,
|
|
1493
|
-
nonce: startNonce
|
|
1547
|
+
nonce: startNonce,
|
|
1548
|
+
gasLimit: effConfig.gasLimit,
|
|
1549
|
+
gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
|
|
1494
1550
|
});
|
|
1495
1551
|
signedTransactions.push(signedMainTx);
|
|
1496
1552
|
// --- 4. 构建外盘买入 handleOps (如果启用) ---
|
|
@@ -1533,7 +1589,9 @@ export class BundleExecutor {
|
|
|
1533
1589
|
ops: ops2,
|
|
1534
1590
|
payerWallet: payerWallet,
|
|
1535
1591
|
beneficiary: params.beneficiary ?? payerWallet.address,
|
|
1536
|
-
nonce: startNonce + 1
|
|
1592
|
+
nonce: startNonce + 1,
|
|
1593
|
+
gasLimit: effConfig.gasLimit,
|
|
1594
|
+
gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
|
|
1537
1595
|
});
|
|
1538
1596
|
signedTransactions.push(signedDexTx);
|
|
1539
1597
|
}
|
|
@@ -1712,7 +1770,11 @@ export class BundleExecutor {
|
|
|
1712
1770
|
};
|
|
1713
1771
|
}
|
|
1714
1772
|
// ============ 非 signOnly 模式:执行 handleOps ============
|
|
1715
|
-
const
|
|
1773
|
+
const effConfig = { ...(this.config ?? {}), ...(config ?? {}) };
|
|
1774
|
+
const approveResult = await this.runHandleOps('preApproveBundle', approveOps, bundlerSigner, beneficiary, {
|
|
1775
|
+
gasLimit: effConfig.gasLimit,
|
|
1776
|
+
gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
|
|
1777
|
+
});
|
|
1716
1778
|
if (!approveResult) {
|
|
1717
1779
|
throw new Error('预授权交易失败');
|
|
1718
1780
|
}
|
package/dist/xlayer/types.d.ts
CHANGED
|
@@ -76,6 +76,10 @@ export interface XLayerConfig {
|
|
|
76
76
|
timeoutMs?: number;
|
|
77
77
|
/** Gas 估算安全余量倍数 */
|
|
78
78
|
gasLimitMultiplier?: number;
|
|
79
|
+
/** Payer handleOps 交易的 gasLimit(手动覆盖) */
|
|
80
|
+
gasLimit?: bigint;
|
|
81
|
+
/** Payer handleOps 交易的最小 gasPrice (Gwei) */
|
|
82
|
+
minGasPriceGwei?: number;
|
|
79
83
|
/** 利润尾笔原生转账 gasLimit(默认 21000n) */
|
|
80
84
|
profitTailGasLimit?: bigint;
|
|
81
85
|
/**
|