four-flap-meme-sdk 1.5.21 → 1.5.23

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.
@@ -6,7 +6,7 @@ export * from './config.js';
6
6
  export * from './types.js';
7
7
  export { createTokenWithBundleBuyMerkle, batchBuyWithBundleMerkle, batchSellWithBundleMerkle } from './core.js';
8
8
  export { fourPrivateBuyMerkle, fourPrivateSellMerkle, fourBatchPrivateBuyMerkle, fourBatchPrivateSellMerkle } from './private.js';
9
- export { disperseWithBundleMerkle, sweepWithBundleMerkle } from './utils.js';
9
+ export { disperseWithBundleMerkle, sweepWithBundleMerkle, pairwiseTransferWithBundleMerkle } from './utils.js';
10
10
  export { fourPancakeProxyBatchBuyMerkle, fourPancakeProxyBatchSellMerkle, approveFourPancakeProxy, approveFourPancakeProxyBatch } from './pancake-proxy.js';
11
11
  export { approveFourTokenManagerBatch, type ApproveFourTokenManagerBatchParams, type ApproveFourTokenManagerBatchResult } from './approve-tokenmanager.js';
12
12
  export { submitBundleToMerkle, submitMultipleBundles, submitMultipleBundlesParallel, type MerkleSubmitConfig, type SubmitBundleResult, submitBundleToBlockRazor, submitMultipleBundlesToBlockRazor, submitMultipleBundlesToBlockRazorParallel, type BlockRazorSubmitConfig, type BlockRazorSubmitResult, submitDirectToRpc, submitDirectToRpcSequential, // ✅ 新增:顺序广播并等待确认(用于多跳)
@@ -10,7 +10,7 @@ export { createTokenWithBundleBuyMerkle, batchBuyWithBundleMerkle, batchSellWith
10
10
  // 私有交易方法
11
11
  export { fourPrivateBuyMerkle, fourPrivateSellMerkle, fourBatchPrivateBuyMerkle, fourBatchPrivateSellMerkle } from './private.js';
12
12
  // 工具方法
13
- export { disperseWithBundleMerkle, sweepWithBundleMerkle } from './utils.js';
13
+ export { disperseWithBundleMerkle, sweepWithBundleMerkle, pairwiseTransferWithBundleMerkle } from './utils.js';
14
14
  // PancakeSwapProxy 代理交易方法
15
15
  export { fourPancakeProxyBatchBuyMerkle, fourPancakeProxyBatchSellMerkle, approveFourPancakeProxy, approveFourPancakeProxyBatch } from './pancake-proxy.js';
16
16
  // TokenManager 授权方法
@@ -337,6 +337,30 @@ export type SweepSignParams = {
337
337
  * 包含 hopWallets 用于返回生成的多跳钱包私钥
338
338
  */
339
339
  export type SweepMerkleResult = MerkleSignedResult;
340
+ /**
341
+ * 多对多(地址一一对应)转账参数(仅签名版本)
342
+ * - senderPrivateKeys / receiverAddresses 必须等长
343
+ * - amount / amounts 二选一(amounts 优先)
344
+ * - 支持多跳:hopCount 可为 number 或逐对数组
345
+ * - 支持利润刮取:利润由第一个 sender 支付(作为额外费用,不扣减每对转账金额)
346
+ */
347
+ export type PairwiseTransferSignParams = {
348
+ senderPrivateKeys: string[];
349
+ receiverAddresses: string[];
350
+ amount?: AmountLike;
351
+ amounts?: AmountLike[];
352
+ tokenAddress?: string;
353
+ tokenDecimals?: number;
354
+ hopCount?: number | number[];
355
+ hopPrivateKeys?: string[][];
356
+ config: FourSignConfig;
357
+ /** ✅ 起始 nonce(仅对第一个 sender 生效,用于并行调用避免 nonce 冲突) */
358
+ startNonce?: number;
359
+ tokenPoolType?: TokenPoolType;
360
+ quoteToken?: QuoteTokenType;
361
+ userType?: UserType;
362
+ };
363
+ export type PairwiseTransferMerkleResult = MerkleSignedResult;
340
364
  /** ✅ PancakeProxy 批量购买参数(Merkle 版本 - 完整) */
341
365
  export type FourPancakeProxyBatchBuyParams = {
342
366
  privateKeys: string[];
@@ -1,4 +1,4 @@
1
- import { DisperseSignParams, DisperseMerkleResult, SweepSignParams, SweepMerkleResult } from './types.js';
1
+ import { DisperseSignParams, DisperseMerkleResult, SweepSignParams, SweepMerkleResult, PairwiseTransferSignParams, PairwiseTransferMerkleResult } from './types.js';
2
2
  /**
3
3
  * 分发(仅签名版本 - 不依赖 Merkle)
4
4
  * ✅ 精简版:只负责签名交易,不提交到 Merkle
@@ -11,3 +11,10 @@ export declare function disperseWithBundleMerkle(params: DisperseSignParams): Pr
11
11
  * ✅ 优化版:支持 startNonce 参数避免并行调用时的 nonce 冲突
12
12
  */
13
13
  export declare function sweepWithBundleMerkle(params: SweepSignParams): Promise<SweepMerkleResult>;
14
+ /**
15
+ * 多对多(地址一一对应)转账(仅签名版本 - 不依赖 Merkle)
16
+ * - 支持原生币 / ERC20
17
+ * - 支持多跳(逐对)
18
+ * - 支持利润刮取:利润由第一个 sender 支付(作为额外费用,不扣减每对转账金额)
19
+ */
20
+ export declare function pairwiseTransferWithBundleMerkle(params: PairwiseTransferSignParams): Promise<PairwiseTransferMerkleResult>;
@@ -1389,3 +1389,290 @@ export async function sweepWithBundleMerkle(params) {
1389
1389
  } : undefined
1390
1390
  };
1391
1391
  }
1392
+ /**
1393
+ * 多对多(地址一一对应)转账(仅签名版本 - 不依赖 Merkle)
1394
+ * - 支持原生币 / ERC20
1395
+ * - 支持多跳(逐对)
1396
+ * - 支持利润刮取:利润由第一个 sender 支付(作为额外费用,不扣减每对转账金额)
1397
+ */
1398
+ export async function pairwiseTransferWithBundleMerkle(params) {
1399
+ const { senderPrivateKeys, receiverAddresses, amount, amounts, tokenAddress, tokenDecimals, hopCount = 0, hopPrivateKeys, config, startNonce, tokenPoolType = 'v2', quoteToken = 'native', userType = 'v0', } = params;
1400
+ if (!senderPrivateKeys || senderPrivateKeys.length === 0) {
1401
+ return { signedTransactions: [], hopWallets: undefined };
1402
+ }
1403
+ if (!receiverAddresses || receiverAddresses.length === 0) {
1404
+ return { signedTransactions: [], hopWallets: undefined };
1405
+ }
1406
+ if (senderPrivateKeys.length !== receiverAddresses.length) {
1407
+ throw new Error(`senderPrivateKeys length (${senderPrivateKeys.length}) must match receiverAddresses length (${receiverAddresses.length})`);
1408
+ }
1409
+ const pairCount = senderPrivateKeys.length;
1410
+ const normalizedAmounts = (() => {
1411
+ if (amounts && amounts.length > 0) {
1412
+ if (amounts.length !== pairCount) {
1413
+ throw new Error(`amounts length (${amounts.length}) must match pair count (${pairCount})`);
1414
+ }
1415
+ return amounts.map(a => (typeof a === 'bigint' ? a.toString() : String(a)));
1416
+ }
1417
+ if (amount !== undefined && String(amount).trim().length > 0) {
1418
+ const v = typeof amount === 'bigint' ? amount.toString() : String(amount);
1419
+ return new Array(pairCount).fill(v);
1420
+ }
1421
+ throw new Error('Either amount or amounts must be provided');
1422
+ })();
1423
+ const chainIdNum = config.chainId ?? 56;
1424
+ const chainName = chainIdNum === 143 ? 'Monad' : chainIdNum === 56 ? 'BSC' : `Chain-${chainIdNum}`;
1425
+ const provider = new ethers.JsonRpcProvider(config.rpcUrl, { chainId: chainIdNum, name: chainName });
1426
+ const txType = getTxType(config);
1427
+ const isNative = _isNativeTokenAddress(tokenAddress);
1428
+ const nonceManager = new NonceManager(provider);
1429
+ // hop 私钥链优先使用传入
1430
+ const providedHops = (() => {
1431
+ if (hopPrivateKeys && hopPrivateKeys.length > 0) {
1432
+ if (hopPrivateKeys.length !== pairCount) {
1433
+ throw new Error(`hopPrivateKeys length (${hopPrivateKeys.length}) must match pair count (${pairCount})`);
1434
+ }
1435
+ return hopPrivateKeys.every(h => h.length === 0) ? null : hopPrivateKeys;
1436
+ }
1437
+ return null;
1438
+ })();
1439
+ const preparedHops = providedHops ?? _generateHopWallets(pairCount, hopCount);
1440
+ const hasHops = preparedHops !== null;
1441
+ const maxHopCount = hasHops ? Math.max(...preparedHops.map(h => h.length)) : 0;
1442
+ const finalGasLimit = _calculateGasLimit(config, isNative, hasHops, maxHopCount);
1443
+ const nativeGasLimit = (config.prefer21000ForNative ?? false) ? 21000n : finalGasLimit;
1444
+ // 与 disperse 保持一致:多跳场景固定 gas limit
1445
+ const nativeTransferGasLimit = 21000n;
1446
+ const erc20TransferGasLimit = 65000n;
1447
+ const [gasPrice, decimals] = await Promise.all([
1448
+ getOptimizedGasPrice(provider, getGasPriceConfig(config)),
1449
+ isNative ? Promise.resolve(18) : Promise.resolve(tokenDecimals ?? await _getErc20DecimalsMerkle(provider, tokenAddress, chainIdNum))
1450
+ ]);
1451
+ const iface = isNative ? null : new ethers.Interface(['function transfer(address,uint256) returns (bool)']);
1452
+ // 利润:按每对金额计算,但由第一个 sender 支付(额外费用)
1453
+ const extractProfit = shouldExtractProfit(config);
1454
+ let totalAmountBeforeProfit = 0n;
1455
+ let totalTokenProfit = 0n;
1456
+ let totalProfitNative = 0n;
1457
+ const parsedAmountsWei = normalizedAmounts.map(v => {
1458
+ const amt = isNative ? ethers.parseEther(v) : ethers.parseUnits(v, decimals);
1459
+ totalAmountBeforeProfit += amt;
1460
+ if (extractProfit && amt > 0n) {
1461
+ const { profit } = calculateProfit(amt, userType);
1462
+ if (isNative)
1463
+ totalProfitNative += profit;
1464
+ else
1465
+ totalTokenProfit += profit;
1466
+ }
1467
+ return amt;
1468
+ });
1469
+ if (!isNative && extractProfit && totalTokenProfit > 0n) {
1470
+ totalProfitNative = await getTokenToNativeQuote(provider, tokenAddress, totalTokenProfit, chainIdNum, tokenPoolType, quoteToken, config.rpcUrl);
1471
+ }
1472
+ // 计算每个 sender 需要的 nonce 数量(聚合到地址)
1473
+ const senderWallets = senderPrivateKeys.map(pk => new Wallet(pk, provider));
1474
+ const senderAddrLowerList = senderWallets.map(w => w.address.toLowerCase());
1475
+ const firstSenderAddrLower = senderAddrLowerList[0];
1476
+ const nonceNeedBySender = new Map();
1477
+ for (let i = 0; i < pairCount; i++) {
1478
+ const addrLower = senderAddrLowerList[i];
1479
+ const hopLen = preparedHops ? preparedHops[i].length : 0;
1480
+ const perPairTxCount = (() => {
1481
+ if (isNative)
1482
+ return 1;
1483
+ return hopLen > 0 ? 2 : 1;
1484
+ })();
1485
+ const cur = nonceNeedBySender.get(addrLower);
1486
+ if (cur)
1487
+ cur.count += perPairTxCount;
1488
+ else
1489
+ nonceNeedBySender.set(addrLower, { wallet: senderWallets[i], count: perPairTxCount });
1490
+ }
1491
+ if (extractProfit && totalProfitNative > 0n) {
1492
+ const cur = nonceNeedBySender.get(firstSenderAddrLower);
1493
+ if (cur)
1494
+ cur.count += 1;
1495
+ }
1496
+ const nonceQueueBySender = new Map();
1497
+ for (const [addrLower, entry] of nonceNeedBySender.entries()) {
1498
+ const count = entry.count;
1499
+ const nonces = (addrLower === firstSenderAddrLower && startNonce !== undefined)
1500
+ ? Array.from({ length: count }, (_, i) => startNonce + i)
1501
+ : await nonceManager.getNextNonceBatch(entry.wallet, count);
1502
+ nonceQueueBySender.set(addrLower, nonces);
1503
+ }
1504
+ const popNonce = (addrLower) => {
1505
+ const q = nonceQueueBySender.get(addrLower);
1506
+ if (!q || q.length === 0)
1507
+ throw new Error(`nonce queue empty for sender ${addrLower}`);
1508
+ return q.shift();
1509
+ };
1510
+ const txsToSign = [];
1511
+ const nativeHopGasFee = nativeTransferGasLimit * gasPrice;
1512
+ const erc20HopGasFee = erc20TransferGasLimit * gasPrice;
1513
+ const nativeHopGasFeeForErc20 = nativeTransferGasLimit * gasPrice;
1514
+ for (let i = 0; i < pairCount; i++) {
1515
+ const senderWallet = senderWallets[i];
1516
+ const senderLower = senderAddrLowerList[i];
1517
+ const to = receiverAddresses[i];
1518
+ const amtWei = parsedAmountsWei[i];
1519
+ const hopChain = preparedHops ? preparedHops[i] : [];
1520
+ if (!hopChain || hopChain.length === 0) {
1521
+ const nonce = popNonce(senderLower);
1522
+ if (isNative) {
1523
+ txsToSign.push({
1524
+ wallet: senderWallet,
1525
+ tx: { to, value: amtWei, nonce, gasPrice, gasLimit: nativeGasLimit, chainId: chainIdNum, type: txType }
1526
+ });
1527
+ }
1528
+ else {
1529
+ const data = iface.encodeFunctionData('transfer', [to, amtWei]);
1530
+ txsToSign.push({
1531
+ wallet: senderWallet,
1532
+ tx: { to: tokenAddress, data, value: 0n, nonce, gasPrice, gasLimit: finalGasLimit, chainId: chainIdNum, type: txType }
1533
+ });
1534
+ }
1535
+ continue;
1536
+ }
1537
+ const fullChain = [senderWallet, ...hopChain.map(w => new Wallet(typeof w === 'string' ? w : w.privateKey, provider))];
1538
+ const addresses = [...fullChain.map(w => w.address), to];
1539
+ if (isNative) {
1540
+ for (let j = 0; j < addresses.length - 1; j++) {
1541
+ const fromWallet = fullChain[j];
1542
+ const toAddress = addresses[j + 1];
1543
+ const nonce = j === 0 ? popNonce(senderLower) : 0;
1544
+ const remainingHops = addresses.length - 2 - j;
1545
+ const additionalGas = nativeHopGasFee * BigInt(remainingHops);
1546
+ const transferValue = amtWei + additionalGas;
1547
+ txsToSign.push({
1548
+ wallet: fromWallet,
1549
+ tx: { to: toAddress, value: transferValue, nonce, gasPrice, gasLimit: nativeTransferGasLimit, chainId: chainIdNum, type: txType }
1550
+ });
1551
+ }
1552
+ }
1553
+ else {
1554
+ // ERC20 多跳:gas + ERC20 逐层传递(与 disperse 一致)
1555
+ const hopGasNeeds = [];
1556
+ for (let j = hopChain.length - 1; j >= 0; j--) {
1557
+ if (j === hopChain.length - 1)
1558
+ hopGasNeeds.unshift(erc20HopGasFee);
1559
+ else {
1560
+ const nextHopGas = hopGasNeeds[0];
1561
+ hopGasNeeds.unshift(nativeHopGasFeeForErc20 + erc20HopGasFee + nextHopGas);
1562
+ }
1563
+ }
1564
+ // sender -> firstHop:转 gas
1565
+ txsToSign.push({
1566
+ wallet: senderWallet,
1567
+ tx: {
1568
+ to: fullChain[1].address,
1569
+ value: hopGasNeeds[0],
1570
+ nonce: popNonce(senderLower),
1571
+ gasPrice,
1572
+ gasLimit: nativeTransferGasLimit,
1573
+ chainId: chainIdNum,
1574
+ type: txType
1575
+ }
1576
+ });
1577
+ // sender -> firstHop:转 ERC20
1578
+ const mainToFirstHopData = iface.encodeFunctionData('transfer', [fullChain[1].address, amtWei]);
1579
+ txsToSign.push({
1580
+ wallet: senderWallet,
1581
+ tx: {
1582
+ to: tokenAddress,
1583
+ data: mainToFirstHopData,
1584
+ value: 0n,
1585
+ nonce: popNonce(senderLower),
1586
+ gasPrice,
1587
+ gasLimit: erc20TransferGasLimit,
1588
+ chainId: chainIdNum,
1589
+ type: txType
1590
+ }
1591
+ });
1592
+ // hop wallets:逐层传递
1593
+ for (let j = 1; j < fullChain.length; j++) {
1594
+ const fromWallet = fullChain[j];
1595
+ const toAddress = addresses[j + 1];
1596
+ const isLastHop = j === fullChain.length - 1;
1597
+ if (!isLastHop) {
1598
+ const gasToTransfer = hopGasNeeds[j];
1599
+ txsToSign.push({
1600
+ wallet: fromWallet,
1601
+ tx: {
1602
+ to: toAddress,
1603
+ value: gasToTransfer,
1604
+ nonce: 0,
1605
+ gasPrice,
1606
+ gasLimit: nativeTransferGasLimit,
1607
+ chainId: chainIdNum,
1608
+ type: txType
1609
+ }
1610
+ });
1611
+ const erc20Data = iface.encodeFunctionData('transfer', [toAddress, amtWei]);
1612
+ txsToSign.push({
1613
+ wallet: fromWallet,
1614
+ tx: {
1615
+ to: tokenAddress,
1616
+ data: erc20Data,
1617
+ value: 0n,
1618
+ nonce: 1,
1619
+ gasPrice,
1620
+ gasLimit: erc20TransferGasLimit,
1621
+ chainId: chainIdNum,
1622
+ type: txType
1623
+ }
1624
+ });
1625
+ }
1626
+ else {
1627
+ const erc20Data = iface.encodeFunctionData('transfer', [toAddress, amtWei]);
1628
+ txsToSign.push({
1629
+ wallet: fromWallet,
1630
+ tx: {
1631
+ to: tokenAddress,
1632
+ data: erc20Data,
1633
+ value: 0n,
1634
+ nonce: 0,
1635
+ gasPrice,
1636
+ gasLimit: erc20TransferGasLimit,
1637
+ chainId: chainIdNum,
1638
+ type: txType
1639
+ }
1640
+ });
1641
+ }
1642
+ }
1643
+ }
1644
+ }
1645
+ const signedTxs = await Promise.all(txsToSign.map(({ wallet, tx }) => wallet.signTransaction(tx)));
1646
+ // 利润多跳(固定 2 hop)
1647
+ let profitHopWallets;
1648
+ if (extractProfit && totalProfitNative > 0n) {
1649
+ const firstSenderWallet = senderWallets[0];
1650
+ const profitNonce = popNonce(firstSenderAddrLower);
1651
+ const profitHopResult = await buildProfitHopTransactions({
1652
+ provider,
1653
+ payerWallet: firstSenderWallet,
1654
+ profitAmount: totalProfitNative,
1655
+ profitRecipient: getProfitRecipient(),
1656
+ hopCount: PROFIT_HOP_COUNT,
1657
+ gasPrice,
1658
+ chainId: chainIdNum,
1659
+ txType,
1660
+ startNonce: profitNonce
1661
+ });
1662
+ signedTxs.push(...profitHopResult.signedTransactions);
1663
+ profitHopWallets = profitHopResult.hopWallets;
1664
+ }
1665
+ return {
1666
+ signedTransactions: signedTxs,
1667
+ hopWallets: preparedHops || undefined,
1668
+ profitHopWallets,
1669
+ metadata: extractProfit ? {
1670
+ pairCount,
1671
+ isNative,
1672
+ tokenAddress: isNative ? undefined : tokenAddress,
1673
+ totalAmount: isNative ? ethers.formatEther(totalAmountBeforeProfit) : ethers.formatUnits(totalAmountBeforeProfit, decimals),
1674
+ profitAmount: ethers.formatEther(totalProfitNative),
1675
+ profitRecipient: getProfitRecipient(),
1676
+ } : undefined
1677
+ };
1678
+ }
package/dist/index.d.ts CHANGED
@@ -28,7 +28,7 @@ export { createTokenWithBundleBuy as flapCreateTokenWithBundleBuy, batchBuyWithB
28
28
  export { fourPrivateBuy, fourPrivateSell, fourBatchPrivateBuy, fourBatchPrivateSell, type FourPrivateBuyParams, type FourPrivateSellParams, type FourBatchPrivateBuyParams, type FourBatchPrivateSellParams } from './contracts/tm-bundle.js';
29
29
  export { flapPrivateBuy, flapPrivateSell, flapBatchPrivateBuy, flapBatchPrivateSell, type FlapPrivateBuyParams, type FlapPrivateSellParams, type FlapBatchPrivateBuyParams, type FlapBatchPrivateSellParams, type FlapBatchPrivateSellResult } from './flap/portal-bundle.js';
30
30
  export { createTokenWithBundleBuyMerkle as flapCreateTokenWithBundleBuyMerkle, batchBuyWithBundleMerkle as flapBatchBuyWithBundleMerkle, batchSellWithBundleMerkle as flapBatchSellWithBundleMerkle, flapPrivateBuyMerkle, flapPrivateSellMerkle, flapBatchPrivateBuyMerkle, flapBatchPrivateSellMerkle, pancakeProxyBatchBuyMerkle, pancakeProxyBatchSellMerkle, approvePancakeProxy, approvePancakeProxyBatch, flapDisperseWithBundleMerkle, flapSweepWithBundleMerkle, type FlapBundleMerkleConfig, type FlapSignConfig, type FlapChainForMerkleBundle, type FlapCreateWithBundleBuySignParams, type FlapCreateWithBundleBuyMerkleParams, type FlapCreateWithBundleBuyMerkleResult, type FlapBatchBuySignParams, type FlapBatchBuyMerkleParams, type FlapBatchBuyMerkleResult, type FlapBatchSellSignParams, type FlapBatchSellMerkleParams, type FlapBatchSellMerkleResult, type MerkleTransactionStatus, type MerkleBundleStatus, type FlapPrivateBuyMerkleParams, type FlapPrivateSellMerkleParams, type FlapBatchPrivateBuyMerkleParams, type FlapBatchPrivateSellMerkleParams, type FlapBatchPrivateMerkleResult, type FlapPrivateTransactionResult, type PancakeProxyBatchBuyParams, type PancakeProxyBatchBuyResult, type PancakeProxyBatchSellParams, type PancakeProxyBatchSellResult, type PancakeProxyApprovalParams, type PancakeProxyApprovalBatchParams, type PancakeProxyApprovalBatchResult, type FlapDisperseSignParams, type FlapDisperseMerkleResult, type FlapSweepSignParams, type FlapSweepMerkleResult } from './flap/portal-bundle-merkle/index.js';
31
- export { createTokenWithBundleBuyMerkle as fourCreateTokenWithBundleBuyMerkle, batchBuyWithBundleMerkle as fourBatchBuyWithBundleMerkle, batchSellWithBundleMerkle as fourBatchSellWithBundleMerkle, fourPrivateBuyMerkle, fourPrivateSellMerkle, fourBatchPrivateBuyMerkle, fourBatchPrivateSellMerkle, disperseWithBundleMerkle, sweepWithBundleMerkle, fourPancakeProxyBatchBuyMerkle, fourPancakeProxyBatchSellMerkle, approveFourPancakeProxy, approveFourPancakeProxyBatch, approveFourTokenManagerBatch, submitBundleToMerkle, submitMultipleBundles, submitMultipleBundlesParallel, submitBundleToBlockRazor, submitMultipleBundlesToBlockRazor, submitMultipleBundlesToBlockRazorParallel, type MerkleSubmitConfig, type SubmitBundleResult, type BlockRazorSubmitConfig, type BlockRazorSubmitResult, type FourBundleMerkleConfig, type FourSignConfig, type FourCreateWithBundleBuySignParams, type FourBatchBuySignParams, type FourBatchSellSignParams, type FourPrivateBuySignParams, type FourPrivateSellSignParams, type FourBatchPrivateBuySignParams, type FourBatchPrivateSellSignParams, type FourPancakeProxyBatchBuySignParams, type FourPancakeProxyBatchSellSignParams, type DisperseSignParams as FourDisperseSignParams, type SweepSignParams as FourSweepSignParams, type FourCreateWithBundleBuyMerkleParams, type FourCreateWithBundleBuyMerkleResult, type FourBatchBuyMerkleParams, type FourBatchBuyMerkleResult, type FourBatchSellMerkleParams, type FourBatchSellMerkleResult, type FourPrivateBuyMerkleParams, type FourPrivateSellMerkleParams, type FourBatchPrivateBuyMerkleParams, type FourBatchPrivateSellMerkleParams, type FourBatchPrivateMerkleResult, type FourPrivateTransactionResult, type DisperseMerkleParams, type DisperseMerkleResult, type SweepMerkleParams, type SweepMerkleResult, type FourPancakeProxyBatchBuyParams, type FourPancakeProxyBatchBuyResult, type FourPancakeProxyBatchSellParams, type FourPancakeProxyBatchSellResult, type FourPancakeProxyApprovalParams, type FourPancakeProxyApprovalBatchParams, type FourPancakeProxyApprovalBatchResult, type ApproveFourTokenManagerBatchParams, type ApproveFourTokenManagerBatchResult } from './contracts/tm-bundle-merkle/index.js';
31
+ export { createTokenWithBundleBuyMerkle as fourCreateTokenWithBundleBuyMerkle, batchBuyWithBundleMerkle as fourBatchBuyWithBundleMerkle, batchSellWithBundleMerkle as fourBatchSellWithBundleMerkle, fourPrivateBuyMerkle, fourPrivateSellMerkle, fourBatchPrivateBuyMerkle, fourBatchPrivateSellMerkle, disperseWithBundleMerkle, sweepWithBundleMerkle, pairwiseTransferWithBundleMerkle, fourPancakeProxyBatchBuyMerkle, fourPancakeProxyBatchSellMerkle, approveFourPancakeProxy, approveFourPancakeProxyBatch, approveFourTokenManagerBatch, submitBundleToMerkle, submitMultipleBundles, submitMultipleBundlesParallel, submitBundleToBlockRazor, submitMultipleBundlesToBlockRazor, submitMultipleBundlesToBlockRazorParallel, type MerkleSubmitConfig, type SubmitBundleResult, type BlockRazorSubmitConfig, type BlockRazorSubmitResult, type FourBundleMerkleConfig, type FourSignConfig, type FourCreateWithBundleBuySignParams, type FourBatchBuySignParams, type FourBatchSellSignParams, type FourPrivateBuySignParams, type FourPrivateSellSignParams, type FourBatchPrivateBuySignParams, type FourBatchPrivateSellSignParams, type FourPancakeProxyBatchBuySignParams, type FourPancakeProxyBatchSellSignParams, type DisperseSignParams as FourDisperseSignParams, type SweepSignParams as FourSweepSignParams, type FourCreateWithBundleBuyMerkleParams, type FourCreateWithBundleBuyMerkleResult, type FourBatchBuyMerkleParams, type FourBatchBuyMerkleResult, type FourBatchSellMerkleParams, type FourBatchSellMerkleResult, type FourPrivateBuyMerkleParams, type FourPrivateSellMerkleParams, type FourBatchPrivateBuyMerkleParams, type FourBatchPrivateSellMerkleParams, type FourBatchPrivateMerkleResult, type FourPrivateTransactionResult, type DisperseMerkleParams, type DisperseMerkleResult, type SweepMerkleParams, type SweepMerkleResult, type FourPancakeProxyBatchBuyParams, type FourPancakeProxyBatchBuyResult, type FourPancakeProxyBatchSellParams, type FourPancakeProxyBatchSellResult, type FourPancakeProxyApprovalParams, type FourPancakeProxyApprovalBatchParams, type FourPancakeProxyApprovalBatchResult, type ApproveFourTokenManagerBatchParams, type ApproveFourTokenManagerBatchResult } from './contracts/tm-bundle-merkle/index.js';
32
32
  export { PinataClient, type PinataConfig } from './flap/pinata.js';
33
33
  export { pinFileToIPFSWithJWT, pinImageByPath, pinFileToIPFSWithJWTWeb, pinDataURLWithJWTWeb, dataURLToBlob, type PinataPinResp } from './flap/pinata.js';
34
34
  export { generateWallets, type GeneratedWallet } from './utils/wallet.js';
package/dist/index.js CHANGED
@@ -47,7 +47,7 @@ export { createTokenWithBundleBuy as flapCreateTokenWithBundleBuy, batchBuyWithB
47
47
  export { fourPrivateBuy, fourPrivateSell, fourBatchPrivateBuy, fourBatchPrivateSell } from './contracts/tm-bundle.js';
48
48
  export { flapPrivateBuy, flapPrivateSell, flapBatchPrivateBuy, flapBatchPrivateSell } from './flap/portal-bundle.js';
49
49
  export { createTokenWithBundleBuyMerkle as flapCreateTokenWithBundleBuyMerkle, batchBuyWithBundleMerkle as flapBatchBuyWithBundleMerkle, batchSellWithBundleMerkle as flapBatchSellWithBundleMerkle, flapPrivateBuyMerkle, flapPrivateSellMerkle, flapBatchPrivateBuyMerkle, flapBatchPrivateSellMerkle, pancakeProxyBatchBuyMerkle, pancakeProxyBatchSellMerkle, approvePancakeProxy, approvePancakeProxyBatch, flapDisperseWithBundleMerkle, flapSweepWithBundleMerkle } from './flap/portal-bundle-merkle/index.js';
50
- export { createTokenWithBundleBuyMerkle as fourCreateTokenWithBundleBuyMerkle, batchBuyWithBundleMerkle as fourBatchBuyWithBundleMerkle, batchSellWithBundleMerkle as fourBatchSellWithBundleMerkle, fourPrivateBuyMerkle, fourPrivateSellMerkle, fourBatchPrivateBuyMerkle, fourBatchPrivateSellMerkle, disperseWithBundleMerkle, sweepWithBundleMerkle, fourPancakeProxyBatchBuyMerkle, fourPancakeProxyBatchSellMerkle, approveFourPancakeProxy, approveFourPancakeProxyBatch, approveFourTokenManagerBatch, submitBundleToMerkle, submitMultipleBundles, submitMultipleBundlesParallel, submitBundleToBlockRazor, submitMultipleBundlesToBlockRazor, submitMultipleBundlesToBlockRazorParallel } from './contracts/tm-bundle-merkle/index.js';
50
+ export { createTokenWithBundleBuyMerkle as fourCreateTokenWithBundleBuyMerkle, batchBuyWithBundleMerkle as fourBatchBuyWithBundleMerkle, batchSellWithBundleMerkle as fourBatchSellWithBundleMerkle, fourPrivateBuyMerkle, fourPrivateSellMerkle, fourBatchPrivateBuyMerkle, fourBatchPrivateSellMerkle, disperseWithBundleMerkle, sweepWithBundleMerkle, pairwiseTransferWithBundleMerkle, fourPancakeProxyBatchBuyMerkle, fourPancakeProxyBatchSellMerkle, approveFourPancakeProxy, approveFourPancakeProxyBatch, approveFourTokenManagerBatch, submitBundleToMerkle, submitMultipleBundles, submitMultipleBundlesParallel, submitBundleToBlockRazor, submitMultipleBundlesToBlockRazor, submitMultipleBundlesToBlockRazorParallel } from './contracts/tm-bundle-merkle/index.js';
51
51
  export { PinataClient } from './flap/pinata.js';
52
52
  export { pinFileToIPFSWithJWT, pinImageByPath, pinFileToIPFSWithJWTWeb, pinDataURLWithJWTWeb, dataURLToBlob } from './flap/pinata.js';
53
53
  export { generateWallets } from './utils/wallet.js';
@@ -8,7 +8,7 @@
8
8
  * - initCode 生成
9
9
  */
10
10
  import { ethers, JsonRpcProvider, Wallet, Contract } from 'ethers';
11
- import type { UserOperation, SignedUserOp, AAAccount, XLayerConfig } from './types.js';
11
+ import type { UserOperation, SignedUserOp, AAAccount, XLayerConfig, GasPolicy, FixedGasConfig } from './types.js';
12
12
  import { BundlerClient } from './bundler.js';
13
13
  /**
14
14
  * AA 账户管理器
@@ -33,6 +33,11 @@ export declare class AAAccountManager {
33
33
  private paymasterData?;
34
34
  private gasLimitMultiplier;
35
35
  private senderCache;
36
+ private deployedSenderSet;
37
+ private feeDataCache?;
38
+ private readonly feeDataCacheTtlMs;
39
+ private defaultGasPolicy?;
40
+ private defaultFixedGas?;
36
41
  constructor(config?: XLayerConfig);
37
42
  /**
38
43
  * 获取 Provider
@@ -127,6 +132,23 @@ export declare class AAAccountManager {
127
132
  userOp: UserOperation;
128
133
  prefundWei: bigint;
129
134
  }>;
135
+ /**
136
+ * 构建未签名的 UserOperation(固定 Gas,不做任何 estimate)
137
+ *
138
+ * 适用于大规模(1000 地址)场景:尽量减少 RPC 调用量。
139
+ */
140
+ buildUserOpWithFixedGas(params: {
141
+ ownerWallet: Wallet;
142
+ sender: string;
143
+ callData: string;
144
+ nonce: bigint;
145
+ initCode?: string;
146
+ deployed?: boolean;
147
+ fixedGas?: FixedGasConfig;
148
+ }): Promise<{
149
+ userOp: UserOperation;
150
+ prefundWei: bigint;
151
+ }>;
130
152
  /**
131
153
  * 签名 UserOperation
132
154
  */
@@ -138,6 +160,8 @@ export declare class AAAccountManager {
138
160
  ownerWallet: Wallet;
139
161
  callData: string;
140
162
  value?: bigint;
163
+ gasPolicy?: GasPolicy;
164
+ fixedGas?: FixedGasConfig;
141
165
  useBundlerEstimate?: boolean;
142
166
  callGasLimit?: bigint;
143
167
  }): Promise<SignedUserOp>;
@@ -159,6 +183,13 @@ export declare class AAAccountManager {
159
183
  */
160
184
  getMultipleAccountInfo(ownerAddresses: string[]): Promise<AAAccount[]>;
161
185
  }
186
+ /**
187
+ * ERC-4337 v0.6 userOpHash 本地计算
188
+ *
189
+ * pack 规则(v0.6):对 (sender,nonce,keccak(initCode),keccak(callData),callGasLimit,verificationGasLimit,preVerificationGas,maxFeePerGas,maxPriorityFeePerGas,keccak(paymasterAndData))
190
+ * 做 abi.encode 后 keccak 得到 packHash;再 abi.encode(packHash, entryPoint, chainId) 后 keccak 得到 userOpHash。
191
+ */
192
+ export declare function computeUserOpHashV06(userOp: UserOperation, entryPoint: string, chainId: number | bigint): string;
162
193
  /**
163
194
  * 编码 SimpleAccount.execute 调用
164
195
  */