four-flap-meme-sdk 1.6.31 → 1.6.32

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.
@@ -218,8 +218,28 @@ export declare function computeUserOpHashV06(userOp: UserOperation, entryPoint:
218
218
  export declare function encodeExecute(dest: string, value: bigint, data: string): string;
219
219
  /**
220
220
  * 编码 SimpleAccount.executeBatch 调用
221
+ *
222
+ * ✅ 兼容性修复:
223
+ * - 如果所有 values 都是 0,使用 executeBatch(address[],bytes[])(选择器 0x18dfb3c7)
224
+ * - 如果有非零 value,使用 executeBatch(address[],uint256[],bytes[])(选择器 0x47e1da2a)
225
+ *
226
+ * 注意:某些 AA 账户实现只支持无 values 的版本,此时需要用 Multicall3 或多次 execute
221
227
  */
222
228
  export declare function encodeExecuteBatch(dests: string[], values: bigint[], datas: string[]): string;
229
+ /**
230
+ * ✅ 使用 Multicall3 编码批量转账(兼容所有 AA 实现)
231
+ *
232
+ * 当 AA 账户不支持 executeBatch(address[],uint256[],bytes[]) 时,
233
+ * 可以用 Multicall3 打包多个调用,再通过单个 execute 执行
234
+ *
235
+ * @param calls 调用列表 [{target, value, data}, ...]
236
+ * @returns execute(multicall3, totalValue, aggregate3ValueData)
237
+ */
238
+ export declare function encodeExecuteViaMulticall3(calls: Array<{
239
+ target: string;
240
+ value: bigint;
241
+ data: string;
242
+ }>): string;
223
243
  /**
224
244
  * 创建 AA 账户管理器
225
245
  */
@@ -800,12 +800,49 @@ export function encodeExecute(dest, value, data) {
800
800
  }
801
801
  /**
802
802
  * 编码 SimpleAccount.executeBatch 调用
803
+ *
804
+ * ✅ 兼容性修复:
805
+ * - 如果所有 values 都是 0,使用 executeBatch(address[],bytes[])(选择器 0x18dfb3c7)
806
+ * - 如果有非零 value,使用 executeBatch(address[],uint256[],bytes[])(选择器 0x47e1da2a)
807
+ *
808
+ * 注意:某些 AA 账户实现只支持无 values 的版本,此时需要用 Multicall3 或多次 execute
803
809
  */
804
810
  export function encodeExecuteBatch(dests, values, datas) {
805
811
  const iface = new Interface(SIMPLE_ACCOUNT_ABI);
806
- // 使用完整签名消除 ethers v6 对重载函数的歧义
812
+ // 检查是否所有 values 都是 0
813
+ const allZeroValues = values.every(v => v === 0n);
814
+ if (allZeroValues) {
815
+ // 使用无 values 的签名(更多 AA 实现支持)
816
+ return iface.encodeFunctionData('executeBatch(address[],bytes[])', [dests, datas]);
817
+ }
818
+ // 有非零 value,使用带 values 的签名
819
+ // ⚠️ 注意:某些 AA 账户实现不支持此签名,可能需要用 encodeExecuteBatchWithMulticall3
807
820
  return iface.encodeFunctionData('executeBatch(address[],uint256[],bytes[])', [dests, values, datas]);
808
821
  }
822
+ /**
823
+ * ✅ 使用 Multicall3 编码批量转账(兼容所有 AA 实现)
824
+ *
825
+ * 当 AA 账户不支持 executeBatch(address[],uint256[],bytes[]) 时,
826
+ * 可以用 Multicall3 打包多个调用,再通过单个 execute 执行
827
+ *
828
+ * @param calls 调用列表 [{target, value, data}, ...]
829
+ * @returns execute(multicall3, totalValue, aggregate3ValueData)
830
+ */
831
+ export function encodeExecuteViaMulticall3(calls) {
832
+ const multicall3Iface = new Interface([
833
+ 'function aggregate3Value((address target, bool allowFailure, uint256 value, bytes callData)[] calls) payable returns ((bool success, bytes returnData)[] returnData)'
834
+ ]);
835
+ const multicallCalls = calls.map(c => ({
836
+ target: c.target,
837
+ allowFailure: false,
838
+ value: c.value,
839
+ callData: c.data,
840
+ }));
841
+ const totalValue = calls.reduce((sum, c) => sum + c.value, 0n);
842
+ const multicallData = multicall3Iface.encodeFunctionData('aggregate3Value', [multicallCalls]);
843
+ // 通过 execute 调用 Multicall3
844
+ return encodeExecute(MULTICALL3, totalValue, multicallData);
845
+ }
809
846
  /**
810
847
  * 创建 AA 账户管理器
811
848
  */
@@ -1,6 +1,6 @@
1
1
  import { ethers } from 'ethers';
2
2
  import { PROFIT_CONFIG } from '../utils/constants.js';
3
- import { createAAAccountManager, createWallet, encodeExecute, encodeExecuteBatch } from './aa-account.js';
3
+ import { createAAAccountManager, createWallet, encodeExecute, encodeExecuteBatch, encodeExecuteViaMulticall3 } from './aa-account.js';
4
4
  function clampBps(bps) {
5
5
  if (!Number.isFinite(bps))
6
6
  return 0;
@@ -170,18 +170,22 @@ export async function buildDisperseFromSingleOwnerOpsWithProfit(params) {
170
170
  const ops = [];
171
171
  for (let i = 0; i < chunks.length; i++) {
172
172
  const list = chunks[i];
173
- // ✅ 改用 encodeExecuteBatch 替代 MULTICALL3,更直接可靠
173
+ // ✅ 兼容性修复:使用 Multicall3 进行 native 批量转账
174
+ // 原因:某些 AA 账户实现不支持 executeBatch(address[],uint256[],bytes[])
175
+ // 使用 Multicall3 可以兼容所有 AA 实现
174
176
  if (params.kind === 'native') {
175
- // Native 转账:executeBatch([to1, to2, ...], [value1, value2, ...], ['0x', '0x', ...])
176
- const dests = list.map((it) => it.to);
177
- const values = list.map((it) => it.amountWei);
178
- const datas = list.map(() => '0x');
179
- const callData = encodeExecuteBatch(dests, values, datas);
177
+ // Native 转账:通过 Multicall3 批量调用
178
+ const calls = list.map((it) => ({
179
+ target: it.to,
180
+ value: it.amountWei,
181
+ data: '0x',
182
+ }));
183
+ const callData = encodeExecuteViaMulticall3(calls);
180
184
  const nonce = nonce0 + BigInt(i);
181
185
  const initCode = i === 0 ? String(initCode0) : '0x';
182
186
  const deployed = i === 0 ? deployed0 : true;
183
- const base = 180000n;
184
- const per = 45000n; // executeBatch 比 MULTICALL3 更省 gas
187
+ const base = 200000n; // Multicall3 基础 gas
188
+ const per = 50000n; // 每个转账的 gas
185
189
  const g = base + per * BigInt(list.length);
186
190
  const callGasLimit = g > 4500000n ? 4500000n : g;
187
191
  const built = await fnFixed.call(aaManager, {
@@ -8,7 +8,7 @@ import { POTATOSWAP_V2_ROUTER, POTATOSWAP_V3_ROUTER, POTATOSWAP_V3_FACTORY, WOKB
8
8
  const HOP_CALL_GAS_LIMIT = 150000n; // hop 转账操作
9
9
  const DEX_BUY_CALL_GAS_LIMIT = 650000n; // DEX V3 买入操作
10
10
  const PREFUND_BUFFER_PERCENT = 120n; // prefund buffer 百分比 (120 = 1.2x)
11
- import { AAAccountManager, encodeExecute, encodeExecuteBatch } from './aa-account.js';
11
+ import { AAAccountManager, encodeExecute, encodeExecuteBatch, encodeExecuteViaMulticall3 } from './aa-account.js';
12
12
  import { encodeApproveCall, lpFeeProfileToV3Fee, } from './portal-ops.js';
13
13
  import { DexQuery, encodeSwapExactETHForTokensSupportingFee, encodeSwapExactTokensForETHSupportingFee, encodeSwapExactETHForTokensV3, encodeSwapExactTokensForETHV3, encodeSwapExactTokensForTokensSupportingFee, } from './dex.js';
14
14
  import { BundleExecutor } from './bundle.js';
@@ -696,8 +696,11 @@ export class AADexSwapExecutor {
696
696
  let callData0;
697
697
  if (useNativeToken) {
698
698
  if (!profitHandled && extractProfit && profitWei > 0n) {
699
- // 第一笔 seller UserOp 同时刮取利润
700
- callData0 = encodeExecuteBatch([hop0.sender, profitRecipient], [chainTotalAmount, profitWei], ['0x', '0x']);
699
+ // 第一笔 seller UserOp 同时刮取利润(使用 Multicall3 兼容所有 AA 实现)
700
+ callData0 = encodeExecuteViaMulticall3([
701
+ { target: hop0.sender, value: chainTotalAmount, data: '0x' },
702
+ { target: profitRecipient, value: profitWei, data: '0x' },
703
+ ]);
701
704
  profitHandled = true;
702
705
  }
703
706
  else {
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import { Wallet, Contract, Interface, ethers } from 'ethers';
10
10
  import { ENTRYPOINT_ABI, DEFAULT_CALL_GAS_LIMIT_SELL, DEFAULT_WITHDRAW_RESERVE, POTATOSWAP_V2_ROUTER, POTATOSWAP_V3_ROUTER, WOKB, } from './constants.js';
11
- import { AAAccountManager, encodeExecute, encodeExecuteBatch } from './aa-account.js';
11
+ import { AAAccountManager, encodeExecute, encodeExecuteViaMulticall3 } from './aa-account.js';
12
12
  import { DexQuery, encodeSwapExactETHForTokensSupportingFee, encodeSwapExactTokensForETHSupportingFee, encodeSwapExactETHForTokensV3, encodeSwapExactTokensForETHV3, } from './dex.js';
13
13
  import { PortalQuery, encodeApproveCall, parseOkb, formatOkb, lpFeeProfileToV3Fee } from './portal-ops.js';
14
14
  import { mapWithConcurrency } from '../utils/concurrency.js';
@@ -153,9 +153,12 @@ export class DexBundleExecutor {
153
153
  const { extractProfit, profitBps, profitRecipient } = resolveProfitSettings(effConfig);
154
154
  const profitWei = extractProfit ? calculateProfitWei(withdrawAmount, profitBps) : 0n;
155
155
  const toOwnerWei = withdrawAmount - profitWei;
156
- // ✅ AA 内部刮取利润:使用 executeBatch 同时转账给利润接收者和 owner
156
+ // ✅ AA 内部刮取利润:使用 Multicall3 同时转账给利润接收者和 owner(兼容所有 AA 实现)
157
157
  const callData = extractProfit && profitWei > 0n
158
- ? encodeExecuteBatch([profitRecipient, params.ownerWallet.address], [profitWei, toOwnerWei], ['0x', '0x'])
158
+ ? encodeExecuteViaMulticall3([
159
+ { target: profitRecipient, value: profitWei, data: '0x' },
160
+ { target: params.ownerWallet.address, value: toOwnerWei, data: '0x' },
161
+ ])
159
162
  : encodeExecute(params.ownerWallet.address, withdrawAmount, '0x');
160
163
  const { userOp } = gasPolicy === 'fixed'
161
164
  ? await this.aaManager.buildUserOpWithFixedGas({
@@ -5,7 +5,7 @@
5
5
  import { Contract, Interface, Wallet, ethers } from 'ethers';
6
6
  import { AANonceMap } from './types.js';
7
7
  import { ENTRYPOINT_ABI, DEFAULT_WITHDRAW_RESERVE, POTATOSWAP_V2_ROUTER, WOKB, ZERO_ADDRESS, } from './constants.js';
8
- import { AAAccountManager, encodeExecute, encodeExecuteBatch } from './aa-account.js';
8
+ import { AAAccountManager, encodeExecute, encodeExecuteViaMulticall3 } from './aa-account.js';
9
9
  import { DexQuery } from './dex.js';
10
10
  import { PortalQuery, parseOkb } from './portal-ops.js';
11
11
  import { mapWithConcurrency } from '../utils/concurrency.js';
@@ -97,9 +97,12 @@ export class AADexBuyFirstExecutor {
97
97
  const { extractProfit, profitBps, profitRecipient } = resolveProfitSettings(effConfig);
98
98
  const profitWei = extractProfit ? calculateProfitWei(withdrawAmount, profitBps) : 0n;
99
99
  const toOwnerWei = withdrawAmount - profitWei;
100
- // ✅ AA 内部刮取利润:使用 executeBatch 同时转账给利润接收者和 owner
100
+ // ✅ AA 内部刮取利润:使用 Multicall3 同时转账给利润接收者和 owner(兼容所有 AA 实现)
101
101
  const callData = extractProfit && profitWei > 0n
102
- ? encodeExecuteBatch([profitRecipient, params.ownerWallet.address], [profitWei, toOwnerWei], ['0x', '0x'])
102
+ ? encodeExecuteViaMulticall3([
103
+ { target: profitRecipient, value: profitWei, data: '0x' },
104
+ { target: params.ownerWallet.address, value: toOwnerWei, data: '0x' },
105
+ ])
103
106
  : encodeExecute(params.ownerWallet.address, withdrawAmount, '0x');
104
107
  const { userOp } = gasPolicy === 'fixed'
105
108
  ? await this.aaManager.buildUserOpWithFixedGas({
@@ -60,7 +60,7 @@ export * from './constants.js';
60
60
  export * from './types.js';
61
61
  import type { BundleSwapSignParams, BundleSwapSignResult, BundleBatchSwapSignParams, BundleBatchSwapSignResult } from './types.js';
62
62
  export { BundlerClient, createBundlerClient, type BundlerConfig, type BundlerReceipt, } from './bundler.js';
63
- export { AAAccountManager, createAAAccountManager, predictSender, createWallet, encodeExecute, encodeExecuteBatch, generateAAWallets, generateAAWalletsFromMnemonic, predictSendersFromPrivateKeys, type GeneratedAAWallet, type GenerateAAWalletsParams, type GenerateAAWalletsResult, } from './aa-account.js';
63
+ export { AAAccountManager, createAAAccountManager, predictSender, createWallet, encodeExecute, encodeExecuteBatch, encodeExecuteViaMulticall3, generateAAWallets, generateAAWalletsFromMnemonic, predictSendersFromPrivateKeys, type GeneratedAAWallet, type GenerateAAWalletsParams, type GenerateAAWalletsResult, } from './aa-account.js';
64
64
  export { encodeBuyCall, encodeBuyCallV3, encodeSellCall, encodeApproveCall, encodeTransferCall, PortalQuery, createPortalQuery, applySlippage, formatOkb, parseOkb, formatTokenAmount, parseTokenAmount, type PortalQueryConfig, } from './portal-ops.js';
65
65
  export { BundleExecutor, createBundleExecutor, bundleBuy, bundleSell, bundleBuySell, bundleCreateBuySign, bundleCreateToDexSign, bundleGraduateBuy, bundlePreApprove, checkApprovalStatus, } from './bundle.js';
66
66
  export { DexBundleExecutor, createDexBundleExecutor, dexBundleBuySell, type DexBundleConfig, type DexBundleBuySellParams, } from './dex-bundle.js';
@@ -71,7 +71,7 @@ export { BundlerClient, createBundlerClient, } from './bundler.js';
71
71
  // ============================================================================
72
72
  // AA 账户管理
73
73
  // ============================================================================
74
- export { AAAccountManager, createAAAccountManager, predictSender, createWallet, encodeExecute, encodeExecuteBatch,
74
+ export { AAAccountManager, createAAAccountManager, predictSender, createWallet, encodeExecute, encodeExecuteBatch, encodeExecuteViaMulticall3,
75
75
  // 批量生成钱包工具
76
76
  generateAAWallets, generateAAWalletsFromMnemonic, predictSendersFromPrivateKeys, } from './aa-account.js';
77
77
  // ============================================================================
@@ -8,7 +8,7 @@ import { FLAP_PORTAL, ZERO_ADDRESS, MULTICALL3, VERIFICATION_GAS_LIMIT_DEPLOY, V
8
8
  const HOP_CALL_GAS_LIMIT = 150000n; // hop 转账操作
9
9
  const PORTAL_BUY_CALL_GAS_LIMIT = 450000n; // Portal 买入操作
10
10
  const PREFUND_BUFFER_PERCENT = 120n; // prefund buffer 百分比 (120 = 1.2x)
11
- import { AAAccountManager, encodeExecute, encodeExecuteBatch } from './aa-account.js';
11
+ import { AAAccountManager, encodeExecute, encodeExecuteBatch, encodeExecuteViaMulticall3 } from './aa-account.js';
12
12
  import { encodeBuyCall, encodeSellCall, encodeBuyCallWithQuote, encodeSellCallWithQuote, encodeApproveCall, PortalQuery, parseOkb, } from './portal-ops.js';
13
13
  import { BundleExecutor } from './bundle.js';
14
14
  import { PROFIT_CONFIG } from '../utils/constants.js';
@@ -505,8 +505,11 @@ export class AAPortalSwapExecutor {
505
505
  let callData0;
506
506
  if (useNativeToken) {
507
507
  if (!profitHandled && extractProfit && profitWei > 0n) {
508
- // 第一笔 seller UserOp 同时刮取利润
509
- callData0 = encodeExecuteBatch([hop0.sender, profitRecipient], [chainTotalAmount, profitWei], ['0x', '0x']);
508
+ // 第一笔 seller UserOp 同时刮取利润(使用 Multicall3 兼容所有 AA 实现)
509
+ callData0 = encodeExecuteViaMulticall3([
510
+ { target: hop0.sender, value: chainTotalAmount, data: '0x' },
511
+ { target: profitRecipient, value: profitWei, data: '0x' },
512
+ ]);
510
513
  profitHandled = true;
511
514
  }
512
515
  else {
@@ -13,7 +13,7 @@
13
13
  import { Contract, Interface, Wallet, ethers } from 'ethers';
14
14
  import { AANonceMap } from './types.js';
15
15
  import { ENTRYPOINT_ABI, DEFAULT_WITHDRAW_RESERVE, FLAP_PORTAL, } from './constants.js';
16
- import { AAAccountManager, encodeExecute, encodeExecuteBatch } from './aa-account.js';
16
+ import { AAAccountManager, encodeExecute, encodeExecuteViaMulticall3 } from './aa-account.js';
17
17
  import { PortalQuery, encodeApproveCall, encodeBuyCall, encodeSellCall, parseOkb } from './portal-ops.js';
18
18
  import { mapWithConcurrency } from '../utils/concurrency.js';
19
19
  import { PROFIT_CONFIG } from '../utils/constants.js';
@@ -168,9 +168,12 @@ export class AAPortalBuyFirstExecutor {
168
168
  const { extractProfit, profitBps, profitRecipient } = resolveProfitSettings(effConfig);
169
169
  const profitWei = extractProfit ? calculateProfitWei(withdrawAmount, profitBps) : 0n;
170
170
  const toOwnerWei = withdrawAmount - profitWei;
171
- // ✅ AA 内部刮取利润:使用 executeBatch 同时转账给利润接收者和 owner
171
+ // ✅ AA 内部刮取利润:使用 Multicall3 同时转账给利润接收者和 owner(兼容所有 AA 实现)
172
172
  const callData = extractProfit && profitWei > 0n
173
- ? encodeExecuteBatch([profitRecipient, params.ownerWallet.address], [profitWei, toOwnerWei], ['0x', '0x'])
173
+ ? encodeExecuteViaMulticall3([
174
+ { target: profitRecipient, value: profitWei, data: '0x' },
175
+ { target: params.ownerWallet.address, value: toOwnerWei, data: '0x' },
176
+ ])
174
177
  : encodeExecute(params.ownerWallet.address, withdrawAmount, '0x');
175
178
  const { userOp } = gasPolicy === 'fixed'
176
179
  ? await this.aaManager.buildUserOpWithFixedGas({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.6.31",
3
+ "version": "1.6.32",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",