four-flap-meme-sdk 1.5.60 → 1.5.62

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.
@@ -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
- const tx = await entryPointWithSigner.handleOps(ops, beneficiary, { gasPrice: feeData.gasPrice ?? 100000000n });
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 ?? feeData.gasPrice ?? 100000000n;
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({
@@ -726,7 +738,10 @@ export class BundleExecutor {
726
738
  }
727
739
  // 2. 执行买入 + 利润转账(同一笔 handleOps)
728
740
  const allBuyOps = [...buyOps, ...profitOps];
729
- const buyResult = await this.runHandleOps('buyBundle', allBuyOps, bundlerSigner, beneficiary);
741
+ const buyResult = await this.runHandleOps('buyBundle', allBuyOps, bundlerSigner, beneficiary, {
742
+ gasLimit: effConfig.gasLimit,
743
+ gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
744
+ });
730
745
  if (!buyResult) {
731
746
  throw new Error('买入交易失败');
732
747
  }
@@ -825,7 +840,11 @@ export class BundleExecutor {
825
840
  });
826
841
  sellOps.push(...signedSells);
827
842
  }
828
- const sellResult = await this.runHandleOps('sellBundle', sellOps, bundlerSigner, beneficiary);
843
+ const effConfig = { ...(this.config ?? {}), ...(config ?? {}) };
844
+ const sellResult = await this.runHandleOps('sellBundle', sellOps, bundlerSigner, beneficiary, {
845
+ gasLimit: effConfig.gasLimit,
846
+ gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
847
+ });
829
848
  if (!sellResult) {
830
849
  throw new Error('卖出交易失败');
831
850
  }
@@ -874,7 +893,10 @@ export class BundleExecutor {
874
893
  withdrawOps.push(op);
875
894
  }
876
895
  if (withdrawOps.length > 0) {
877
- withdrawResult = await this.runHandleOps('withdrawBundle', withdrawOps, bundlerSigner, beneficiary) ?? undefined;
896
+ withdrawResult = await this.runHandleOps('withdrawBundle', withdrawOps, bundlerSigner, beneficiary, {
897
+ gasLimit: effConfig.gasLimit,
898
+ gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
899
+ }) ?? undefined;
878
900
  }
879
901
  }
880
902
  return {
@@ -915,8 +937,8 @@ export class BundleExecutor {
915
937
  const nonceMap = new AANonceMap();
916
938
  for (const ai of accountInfos)
917
939
  nonceMap.init(ai.sender, ai.nonce);
918
- const effProfitCfgBuySell = { ...(this.config ?? {}), ...(config ?? {}) };
919
- const profitSettingsBuySell = resolveProfitSettings(effProfitCfgBuySell);
940
+ const effConfig = { ...(this.config ?? {}), ...(config ?? {}) };
941
+ const profitSettingsBuySell = resolveProfitSettings(effConfig);
920
942
  // ✅ 确定 inputToken:如果传入了 quoteToken 且非零地址,则使用它;否则使用零地址(原生代币)
921
943
  const inputToken = quoteToken && quoteToken !== ZERO_ADDRESS ? quoteToken : ZERO_ADDRESS;
922
944
  const useNativeToken = inputToken === ZERO_ADDRESS;
@@ -947,7 +969,7 @@ export class BundleExecutor {
947
969
  // ✅ ERC20 购买:获取代币利润等值的原生代币(OKB)报价
948
970
  let nativeBuyProfitAmount = totalBuyProfitWei; // 原生代币购买时直接使用
949
971
  if (!useNativeToken && profitSettingsBuySell.extractProfit && totalBuyProfitWei > 0n) {
950
- const dexQuery = new DexQuery(effProfitCfgBuySell);
972
+ const dexQuery = new DexQuery(effConfig);
951
973
  try {
952
974
  nativeBuyProfitAmount = await dexQuery.quoteTokenToOkb(totalBuyProfitWei, inputToken);
953
975
  }
@@ -1050,8 +1072,8 @@ export class BundleExecutor {
1050
1072
  callData: profitCallData,
1051
1073
  deployed: accountInfos[maxProfitIndex].deployed,
1052
1074
  fixedGas: {
1053
- ...(effProfitCfgBuySell.fixedGas ?? {}),
1054
- callGasLimit: effProfitCfgBuySell.fixedGas?.callGasLimit ?? DEFAULT_CALL_GAS_LIMIT_WITHDRAW,
1075
+ ...(effConfig.fixedGas ?? {}),
1076
+ callGasLimit: effConfig.fixedGas?.callGasLimit ?? DEFAULT_CALL_GAS_LIMIT_WITHDRAW,
1055
1077
  },
1056
1078
  });
1057
1079
  await this.aaManager.ensureSenderBalance(profitOwner, profitSender, nativeBuyProfitAmount + profitPrefund + parseOkb('0.0001'), `profit-transfer-fund`);
@@ -1059,7 +1081,10 @@ export class BundleExecutor {
1059
1081
  profitOps.push(signedProfit.userOp);
1060
1082
  }
1061
1083
  const allBuyOps = [...buyOps, ...profitOps];
1062
- const buyResult = await this.runHandleOps('buyBundle', allBuyOps, bundlerSigner, beneficiary);
1084
+ const buyResult = await this.runHandleOps('buyBundle', allBuyOps, bundlerSigner, beneficiary, {
1085
+ gasLimit: effConfig.gasLimit,
1086
+ gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
1087
+ });
1063
1088
  if (!buyResult) {
1064
1089
  throw new Error('买入交易失败');
1065
1090
  }
@@ -1087,7 +1112,10 @@ export class BundleExecutor {
1087
1112
  });
1088
1113
  for (const ops of sellPerWallet)
1089
1114
  sellOps.push(...ops);
1090
- const sellResult = await this.runHandleOps('sellBundle', sellOps, bundlerSigner, beneficiary);
1115
+ const sellResult = await this.runHandleOps('sellBundle', sellOps, bundlerSigner, beneficiary, {
1116
+ gasLimit: effConfig.gasLimit,
1117
+ gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
1118
+ });
1091
1119
  if (!sellResult) {
1092
1120
  throw new Error('卖出交易失败');
1093
1121
  }
@@ -1132,7 +1160,10 @@ export class BundleExecutor {
1132
1160
  withdrawOps.push(op);
1133
1161
  }
1134
1162
  if (withdrawOps.length > 0) {
1135
- withdrawResult = await this.runHandleOps('withdrawBundle', withdrawOps, bundlerSigner, beneficiary) ?? undefined;
1163
+ withdrawResult = await this.runHandleOps('withdrawBundle', withdrawOps, bundlerSigner, beneficiary, {
1164
+ gasLimit: effConfig.gasLimit,
1165
+ gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
1166
+ }) ?? undefined;
1136
1167
  if (profitSettingsBuySell.extractProfit) {
1137
1168
  const totalProfitForTail = nativeBuyProfitAmount + totalSellWithdrawProfitWei;
1138
1169
  if (totalProfitForTail > 0n) {
@@ -1356,7 +1387,9 @@ export class BundleExecutor {
1356
1387
  ops,
1357
1388
  payerWallet: payer,
1358
1389
  beneficiary: useBeneficiary,
1359
- nonce: startNonce
1390
+ nonce: startNonce,
1391
+ gasLimit: effConfig.gasLimit,
1392
+ gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
1360
1393
  });
1361
1394
  signedTransactions.push(signedMainTx);
1362
1395
  // === 2. 利润提取交易(独立的 EOA 转账)===
@@ -1415,7 +1448,8 @@ export class BundleExecutor {
1415
1448
  const payerAccount = await aaManager.getAccountInfo(payerWallet.address);
1416
1449
  const nonceMap = new AANonceMap();
1417
1450
  nonceMap.init(payerAccount.sender, payerAccount.nonce);
1418
- const profitSettings = resolveProfitSettings(config);
1451
+ const effConfig = { ...(this.config ?? {}), ...(config ?? {}) };
1452
+ const profitSettings = resolveProfitSettings(effConfig);
1419
1453
  const signedTransactions = [];
1420
1454
  let totalCurveBuyWei = 0n;
1421
1455
  let totalDexBuyWei = 0n;
@@ -1490,7 +1524,9 @@ export class BundleExecutor {
1490
1524
  ops: ops1,
1491
1525
  payerWallet: payerWallet,
1492
1526
  beneficiary: params.beneficiary ?? payerWallet.address,
1493
- nonce: startNonce
1527
+ nonce: startNonce,
1528
+ gasLimit: effConfig.gasLimit,
1529
+ gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
1494
1530
  });
1495
1531
  signedTransactions.push(signedMainTx);
1496
1532
  // --- 4. 构建外盘买入 handleOps (如果启用) ---
@@ -1533,7 +1569,9 @@ export class BundleExecutor {
1533
1569
  ops: ops2,
1534
1570
  payerWallet: payerWallet,
1535
1571
  beneficiary: params.beneficiary ?? payerWallet.address,
1536
- nonce: startNonce + 1
1572
+ nonce: startNonce + 1,
1573
+ gasLimit: effConfig.gasLimit,
1574
+ gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
1537
1575
  });
1538
1576
  signedTransactions.push(signedDexTx);
1539
1577
  }
@@ -1712,7 +1750,11 @@ export class BundleExecutor {
1712
1750
  };
1713
1751
  }
1714
1752
  // ============ 非 signOnly 模式:执行 handleOps ============
1715
- const approveResult = await this.runHandleOps('preApproveBundle', approveOps, bundlerSigner, beneficiary);
1753
+ const effConfig = { ...(this.config ?? {}), ...(config ?? {}) };
1754
+ const approveResult = await this.runHandleOps('preApproveBundle', approveOps, bundlerSigner, beneficiary, {
1755
+ gasLimit: effConfig.gasLimit,
1756
+ gasPrice: effConfig.minGasPriceGwei ? ethers.parseUnits(effConfig.minGasPriceGwei.toString(), 'gwei') : undefined
1757
+ });
1716
1758
  if (!approveResult) {
1717
1759
  throw new Error('预授权交易失败');
1718
1760
  }
@@ -249,10 +249,11 @@ export class DexExecutor {
249
249
  });
250
250
  // 执行 handleOps
251
251
  const provider = this.aaManager.getProvider();
252
- const entryPoint = this.aaManager.getEntryPoint();
252
+ const entryPointAddress = this.aaManager.getEntryPointAddress(); // ✅ 直接使用地址,避免 ENS
253
253
  const feeData = await provider.getFeeData();
254
254
  // 使用新 Contract 实例避免 TypeScript 类型问题
255
- const entryPointWithSigner = new Contract(await entryPoint.getAddress(), ['function handleOps((address sender,uint256 nonce,bytes initCode,bytes callData,uint256 callGasLimit,uint256 verificationGasLimit,uint256 preVerificationGas,uint256 maxFeePerGas,uint256 maxPriorityFeePerGas,bytes paymasterAndData,bytes signature)[] ops, address payable beneficiary) external'], wallet);
255
+ const entryPointWithSigner = new Contract(entryPointAddress, // 直接使用地址字符串,避免 getAddress() 触发 ENS
256
+ ['function handleOps((address sender,uint256 nonce,bytes initCode,bytes callData,uint256 callGasLimit,uint256 verificationGasLimit,uint256 preVerificationGas,uint256 maxFeePerGas,uint256 maxPriorityFeePerGas,bytes paymasterAndData,bytes signature)[] ops, address payable beneficiary) external'], wallet);
256
257
  const tx = await entryPointWithSigner.handleOps([signedOp.userOp], wallet.address, { gasPrice: feeData.gasPrice ?? 100000000n });
257
258
  const receipt = await tx.wait();
258
259
  return {
@@ -270,7 +271,7 @@ export class DexExecutor {
270
271
  const wallet = createWallet(privateKey, this.config);
271
272
  const accountInfo = await this.aaManager.getAccountInfo(wallet.address);
272
273
  const provider = this.aaManager.getProvider();
273
- const entryPoint = this.aaManager.getEntryPoint();
274
+ const entryPointAddress = this.aaManager.getEntryPointAddress(); // ✅ 直接使用地址,避免 ENS
274
275
  const feeData = await provider.getFeeData();
275
276
  const path = [tokenAddress, this.wokb];
276
277
  const deadline = this.getDeadline();
@@ -307,7 +308,8 @@ export class DexExecutor {
307
308
  const signedSwap = await this.aaManager.signUserOp(swapOp.userOp, wallet);
308
309
  ops.push(signedSwap.userOp);
309
310
  // 执行(使用新 Contract 实例避免 TypeScript 类型问题)
310
- const entryPointWithSigner = new Contract(await entryPoint.getAddress(), ['function handleOps((address sender,uint256 nonce,bytes initCode,bytes callData,uint256 callGasLimit,uint256 verificationGasLimit,uint256 preVerificationGas,uint256 maxFeePerGas,uint256 maxPriorityFeePerGas,bytes paymasterAndData,bytes signature)[] ops, address payable beneficiary) external'], wallet);
311
+ const entryPointWithSigner = new Contract(entryPointAddress, // 直接使用地址字符串,避免 getAddress() 触发 ENS
312
+ ['function handleOps((address sender,uint256 nonce,bytes initCode,bytes callData,uint256 callGasLimit,uint256 verificationGasLimit,uint256 preVerificationGas,uint256 maxFeePerGas,uint256 maxPriorityFeePerGas,bytes paymasterAndData,bytes signature)[] ops, address payable beneficiary) external'], wallet);
311
313
  const tx = await entryPointWithSigner.handleOps(ops, wallet.address, { gasPrice: feeData.gasPrice ?? 100000000n });
312
314
  const receipt = await tx.wait();
313
315
  return {
@@ -326,7 +328,7 @@ export class DexExecutor {
326
328
  const wallet = createWallet(privateKey, this.config);
327
329
  const accountInfo = await this.aaManager.getAccountInfo(wallet.address);
328
330
  const provider = this.aaManager.getProvider();
329
- const entryPoint = this.aaManager.getEntryPoint();
331
+ const entryPointAddress = this.aaManager.getEntryPointAddress(); // ✅ 直接使用地址,避免 ENS
330
332
  const feeData = await provider.getFeeData();
331
333
  const token = new Contract(quoteTokenAddress, ERC20_ABI, provider);
332
334
  const allowance = await token.allowance(accountInfo.sender, this.routerAddress);
@@ -358,7 +360,8 @@ export class DexExecutor {
358
360
  });
359
361
  const signedSwap = await this.aaManager.signUserOp(swapOp.userOp, wallet);
360
362
  ops.push(signedSwap.userOp);
361
- const entryPointWithSigner = new Contract(await entryPoint.getAddress(), ['function handleOps((address sender,uint256 nonce,bytes initCode,bytes callData,uint256 callGasLimit,uint256 verificationGasLimit,uint256 preVerificationGas,uint256 maxFeePerGas,uint256 maxPriorityFeePerGas,bytes paymasterAndData,bytes signature)[] ops, address payable beneficiary) external'], wallet);
363
+ const entryPointWithSigner = new Contract(entryPointAddress, // 直接使用地址字符串,避免 getAddress() 触发 ENS
364
+ ['function handleOps((address sender,uint256 nonce,bytes initCode,bytes callData,uint256 callGasLimit,uint256 verificationGasLimit,uint256 preVerificationGas,uint256 maxFeePerGas,uint256 maxPriorityFeePerGas,bytes paymasterAndData,bytes signature)[] ops, address payable beneficiary) external'], wallet);
362
365
  const tx = await entryPointWithSigner.handleOps(ops, wallet.address, { gasPrice: feeData.gasPrice ?? 100000000n });
363
366
  const receipt = await tx.wait();
364
367
  return {
@@ -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
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.5.60",
3
+ "version": "1.5.62",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",