four-flap-meme-sdk 2.0.0 → 2.2.0
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/__tests__/subpath-exports.test.js +64 -0
- package/dist/chains/bsc/iro.d.ts +5 -0
- package/dist/chains/bsc/iro.js +4 -0
- package/dist/chains/eni/flat-aliases.d.ts +10 -0
- package/dist/chains/eni/flat-aliases.js +8 -0
- package/dist/chains/eni/index.d.ts +1 -0
- package/dist/chains/eni/index.js +1 -0
- package/dist/chains/index.d.ts +13 -0
- package/dist/chains/index.js +13 -0
- package/dist/chains/xlayer/eip7702/flat-aliases.d.ts +13 -0
- package/dist/chains/xlayer/eip7702/flat-aliases.js +10 -0
- package/dist/chains/xlayer/eip7702/index.d.ts +1 -0
- package/dist/chains/xlayer/eip7702/index.js +1 -0
- package/dist/chains/xlayer/index.d.ts +3 -2
- package/dist/chains/xlayer/index.js +4 -7
- package/dist/flap/index.d.ts +10 -0
- package/dist/flap/index.js +8 -0
- package/dist/merkle/index.d.ts +12 -0
- package/dist/merkle/index.js +11 -0
- package/dist/shared/constants/index.d.ts +2 -0
- package/dist/shared/index.d.ts +2 -0
- package/dist/vanity/index.d.ts +5 -0
- package/dist/vanity/index.js +5 -0
- package/package.json +93 -2
- package/dist/chains/bsc/four/disperse.d.ts +0 -12
- package/dist/chains/bsc/four/disperse.js +0 -470
- package/dist/chains/bsc/four/pairwise.d.ts +0 -7
- package/dist/chains/bsc/four/pairwise.js +0 -308
- package/dist/chains/bsc/four/submit/blockrazor.d.ts +0 -18
- package/dist/chains/bsc/four/submit/blockrazor.js +0 -86
- package/dist/chains/bsc/four/submit/direct.d.ts +0 -66
- package/dist/chains/bsc/four/submit/direct.js +0 -452
- package/dist/chains/bsc/four/submit/helpers.d.ts +0 -18
- package/dist/chains/bsc/four/submit/helpers.js +0 -57
- package/dist/chains/bsc/four/submit/index.d.ts +0 -12
- package/dist/chains/bsc/four/submit/index.js +0 -11
- package/dist/chains/bsc/four/submit/merkle.d.ts +0 -18
- package/dist/chains/bsc/four/submit/merkle.js +0 -74
- package/dist/chains/bsc/four/submit/types.d.ts +0 -143
- package/dist/chains/bsc/four/swap/index.d.ts +0 -32
- package/dist/chains/bsc/four/swap/index.js +0 -829
- package/dist/chains/bsc/four/swap/types.d.ts +0 -70
- package/dist/chains/bsc/four/swap/types.js +0 -1
- package/dist/chains/bsc/four/sweep.d.ts +0 -13
- package/dist/chains/bsc/four/sweep.js +0 -788
- package/dist/chains/bsc/four/utils/index.d.ts +0 -20
- package/dist/chains/bsc/four/utils/index.js +0 -1558
- package/dist/chains/bsc/four/utils/types.d.ts +0 -1
- package/dist/chains/bsc/four/utils/types.js +0 -1
- package/dist/chains/bsc/pancake/bundle-buy-first/index.d.ts +0 -8
- package/dist/chains/bsc/pancake/bundle-buy-first/index.js +0 -907
- package/dist/chains/bsc/pancake/bundle-buy-first/types.d.ts +0 -73
- package/dist/chains/bsc/pancake/bundle-buy-first/types.js +0 -1
- package/dist/chains/bsc/pancake/bundle-swap/helpers.d.ts +0 -102
- package/dist/chains/bsc/pancake/bundle-swap/helpers.js +0 -572
- package/dist/chains/bsc/pancake/bundle-swap/index.d.ts +0 -50
- package/dist/chains/bsc/pancake/bundle-swap/index.js +0 -1066
- package/dist/chains/bsc/pancake/bundle-swap/types.d.ts +0 -202
- package/dist/chains/bsc/pancake/bundle-swap/types.js +0 -3
- package/dist/chains/xlayer/eip7702/bundle-swap/index.d.ts +0 -72
- package/dist/chains/xlayer/eip7702/bundle-swap/index.js +0 -921
- package/dist/chains/xlayer/eip7702/bundle-swap/types.d.ts +0 -65
- package/dist/chains/xlayer/eip7702/bundle-swap/types.js +0 -1
- package/dist/chains/xlayer/eip7702/multi-hop-transfer/index.d.ts +0 -128
- package/dist/chains/xlayer/eip7702/multi-hop-transfer/index.js +0 -857
- package/dist/chains/xlayer/eip7702/multi-hop-transfer/types.d.ts +0 -85
- package/dist/chains/xlayer/eip7702/multi-hop-transfer/types.js +0 -1
- package/dist/chains/xlayer/eip7702/volume/index.d.ts +0 -96
- package/dist/chains/xlayer/eip7702/volume/index.js +0 -793
- package/dist/chains/xlayer/eip7702/volume/types.d.ts +0 -124
- package/dist/chains/xlayer/eip7702/volume/types.js +0 -1
- package/dist/chains/xlayer/eoa/types-core.d.ts +0 -363
- package/dist/chains/xlayer/eoa/types-core.js +0 -53
- package/dist/chains/xlayer/eoa/types-create.d.ts +0 -413
- package/dist/chains/xlayer/eoa/types-create.js +0 -9
- package/dist/chains/xlayer/eoa/types-volume.d.ts +0 -209
- package/dist/chains/xlayer/eoa/types-volume.js +0 -13
- package/dist/dex/direct-router/index.d.ts +0 -70
- package/dist/dex/direct-router/index.js +0 -1410
- package/dist/dex/direct-router/types.d.ts +0 -81
- package/dist/dex/direct-router/types.js +0 -1
- package/dist/shared/abis/TaxToken.json +0 -969
- package/dist/shared/abis/TokenManager.json +0 -836
- package/dist/shared/abis/TokenManager2.json +0 -136
- package/dist/shared/abis/TokenManagerHelper3.json +0 -993
- package/dist/shared/abis 2/TaxToken.json +0 -105
- package/dist/shared/abis 2/TokenManager.json +0 -836
- package/dist/shared/abis 2/TokenManager2.json +0 -60
- package/dist/shared/abis 2/TokenManagerHelper3.json +0 -993
- package/dist/shared/abis 2/common.d.ts +0 -85
- package/dist/shared/abis 2/common.js +0 -254
- package/dist/shared/abis 2/index.d.ts +0 -8
- package/dist/shared/abis 2/index.js +0 -8
- package/dist/shared/clients 2/blockrazor.d.ts +0 -314
- package/dist/shared/clients 2/blockrazor.js +0 -596
- package/dist/shared/clients 2/club48.d.ts +0 -154
- package/dist/shared/clients 2/club48.js +0 -331
- package/dist/shared/clients 2/emitservice.d.ts +0 -47
- package/dist/shared/clients 2/emitservice.js +0 -44
- package/dist/shared/clients 2/four.d.ts +0 -132
- package/dist/shared/clients 2/four.js +0 -281
- package/dist/shared/clients 2/merkle.d.ts +0 -210
- package/dist/shared/clients 2/merkle.js +0 -400
- package/dist/shared/flap/__tests__/curve.test.d.ts +0 -1
- package/dist/shared/flap/__tests__/curve.test.js +0 -85
- package/dist/shared/flap/portal/index.d.ts +0 -12
- package/dist/shared/flap/portal/index.js +0 -11
- package/dist/shared/flap/portal/portal.d.ts +0 -47
- package/dist/shared/flap/portal/portal.js +0 -218
- package/dist/shared/flap/portal/types.d.ts +0 -227
- package/dist/shared/flap/portal/types.js +0 -80
- package/dist/shared/flap/portal/writer.d.ts +0 -121
- package/dist/shared/flap/portal/writer.js +0 -265
- package/dist/shared/flap/portal-bundle-merkle/core/index.d.ts +0 -18
- package/dist/shared/flap/portal-bundle-merkle/core/index.js +0 -938
- package/dist/shared/flap/portal-bundle-merkle/core/types.d.ts +0 -1
- package/dist/shared/flap/portal-bundle-merkle/core/types.js +0 -1
- package/dist/shared/flap/portal-bundle-merkle/swap/index.d.ts +0 -42
- package/dist/shared/flap/portal-bundle-merkle/swap/index.js +0 -1448
- package/dist/shared/flap/portal-bundle-merkle/swap/types.d.ts +0 -84
- package/dist/shared/flap/portal-bundle-merkle/swap/types.js +0 -1
- package/dist/shared/flap/portal-bundle-merkle/utils/index.d.ts +0 -17
- package/dist/shared/flap/portal-bundle-merkle/utils/index.js +0 -1024
- package/dist/shared/flap/portal-bundle-merkle/utils/types.d.ts +0 -16
- package/dist/shared/flap/portal-bundle-merkle/utils/types.js +0 -1
- package/dist/shared/flap/portal-bundle-merkle/utils-helpers.d.ts +0 -100
- package/dist/shared/flap/portal-bundle-merkle/utils-helpers.js +0 -133
- package/dist/shared/flap 2/__tests__/curve.test.d.ts +0 -1
- package/dist/shared/flap 2/__tests__/curve.test.js +0 -85
- package/dist/shared/flap 2/abi.d.ts +0 -4
- package/dist/shared/flap 2/abi.js +0 -4
- package/dist/shared/flap 2/constants.d.ts +0 -128
- package/dist/shared/flap 2/constants.js +0 -143
- package/dist/shared/flap 2/curve.d.ts +0 -33
- package/dist/shared/flap 2/curve.js +0 -84
- package/dist/shared/flap 2/errors.d.ts +0 -37
- package/dist/shared/flap 2/errors.js +0 -114
- package/dist/shared/flap 2/index.d.ts +0 -22
- package/dist/shared/flap 2/index.js +0 -33
- package/dist/shared/flap 2/ipfs.d.ts +0 -21
- package/dist/shared/flap 2/ipfs.js +0 -38
- package/dist/shared/flap 2/meta.d.ts +0 -30
- package/dist/shared/flap 2/meta.js +0 -195
- package/dist/shared/flap 2/permit.d.ts +0 -16
- package/dist/shared/flap 2/permit.js +0 -67
- package/dist/shared/flap 2/pinata.d.ts +0 -40
- package/dist/shared/flap 2/pinata.js +0 -106
- package/dist/shared/flap 2/portal-bundle-merkle/config.d.ts +0 -79
- package/dist/shared/flap 2/portal-bundle-merkle/config.js +0 -133
- package/dist/shared/flap 2/portal-bundle-merkle/core.d.ts +0 -18
- package/dist/shared/flap 2/portal-bundle-merkle/core.js +0 -938
- package/dist/shared/flap 2/portal-bundle-merkle/create-to-dex.d.ts +0 -125
- package/dist/shared/flap 2/portal-bundle-merkle/create-to-dex.js +0 -665
- package/dist/shared/flap 2/portal-bundle-merkle/curve-to-dex.d.ts +0 -88
- package/dist/shared/flap 2/portal-bundle-merkle/curve-to-dex.js +0 -446
- package/dist/shared/flap 2/portal-bundle-merkle/index.d.ts +0 -14
- package/dist/shared/flap 2/portal-bundle-merkle/index.js +0 -26
- package/dist/shared/flap 2/portal-bundle-merkle/pancake-proxy.d.ts +0 -28
- package/dist/shared/flap 2/portal-bundle-merkle/pancake-proxy.js +0 -701
- package/dist/shared/flap 2/portal-bundle-merkle/private.d.ts +0 -17
- package/dist/shared/flap 2/portal-bundle-merkle/private.js +0 -549
- package/dist/shared/flap 2/portal-bundle-merkle/swap-buy-first.d.ts +0 -65
- package/dist/shared/flap 2/portal-bundle-merkle/swap-buy-first.js +0 -831
- package/dist/shared/flap 2/portal-bundle-merkle/swap.d.ts +0 -201
- package/dist/shared/flap 2/portal-bundle-merkle/swap.js +0 -1359
- package/dist/shared/flap 2/portal-bundle-merkle/types.d.ts +0 -358
- package/dist/shared/flap 2/portal-bundle-merkle/types.js +0 -1
- package/dist/shared/flap 2/portal-bundle-merkle/utils.d.ts +0 -89
- package/dist/shared/flap 2/portal-bundle-merkle/utils.js +0 -963
- package/dist/shared/flap 2/portal-bundle.d.ts +0 -119
- package/dist/shared/flap 2/portal-bundle.js +0 -584
- package/dist/shared/flap 2/portal.d.ts +0 -392
- package/dist/shared/flap 2/portal.js +0 -559
- package/dist/shared/flap 2/vanity.d.ts +0 -48
- package/dist/shared/flap 2/vanity.js +0 -110
- package/dist/shared/flap 2/vault.d.ts +0 -240
- package/dist/shared/flap 2/vault.js +0 -366
- package/dist/shared/four 2/index.d.ts +0 -7
- package/dist/shared/four 2/index.js +0 -22
- package/dist/shared/four 2/tax-token.d.ts +0 -176
- package/dist/shared/four 2/tax-token.js +0 -302
- package/dist/shared/index 2.js +0 -10
- package/dist/shared/index.d 2.ts +0 -10
- package/dist/types/distribute.d.ts +0 -72
- package/dist/types/distribute.js +0 -1
- package/dist/types 2/errors.d.ts +0 -27
- package/dist/types 2/errors.js +0 -34
- package/dist/utils/__tests__/errors.test.d.ts +0 -1
- package/dist/utils/__tests__/errors.test.js +0 -76
- package/dist/utils/airdrop-sweep-types.d.ts +0 -1
- package/dist/utils/airdrop-sweep-types.js +0 -1
- package/dist/utils/erc20/index.d.ts +0 -242
- package/dist/utils/erc20/index.js +0 -645
- package/dist/utils/erc20/types.d.ts +0 -77
- package/dist/utils/erc20/types.js +0 -1
- package/dist/utils/erc20-types.d.ts +0 -1
- package/dist/utils/erc20-types.js +0 -1
- package/dist/utils/holders-maker/helpers.d.ts +0 -43
- package/dist/utils/holders-maker/helpers.js +0 -371
- package/dist/utils/holders-maker/index.d.ts +0 -26
- package/dist/utils/holders-maker/index.js +0 -218
- package/dist/utils/holders-maker/types.d.ts +0 -72
- package/dist/utils/holders-maker/types.js +0 -4
- package/dist/utils/holders-maker-types.d.ts +0 -1
- package/dist/utils/holders-maker-types.js +0 -1
- package/dist/utils/lp-inspect/index.d.ts +0 -44
- package/dist/utils/lp-inspect/index.js +0 -937
- package/dist/utils/lp-inspect/types.d.ts +0 -100
- package/dist/utils/lp-inspect/types.js +0 -1
- package/dist/utils/lp-inspect-types.d.ts +0 -1
- package/dist/utils/lp-inspect-types.js +0 -1
- package/dist/utils/private-sale-types.d.ts +0 -1
- package/dist/utils/private-sale-types.js +0 -1
- package/dist/utils/quote-helpers/index.d.ts +0 -107
- package/dist/utils/quote-helpers/index.js +0 -346
- package/dist/utils/quote-helpers/types.d.ts +0 -16
- package/dist/utils/quote-helpers/types.js +0 -1
- package/dist/utils/quote-helpers-types.d.ts +0 -1
- package/dist/utils/quote-helpers-types.js +0 -1
- /package/dist/{chains/bsc/four/submit/types.js → __tests__/subpath-exports.test.d.ts} +0 -0
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { FlapPrivateBuyMerkleParams, FlapPrivateSellMerkleParams, FlapPrivateTransactionResult, FlapBatchPrivateBuyMerkleParams, FlapBatchPrivateSellMerkleParams, FlapBatchPrivateMerkleResult } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* 私有购买(单笔)(Merkle 版本)
|
|
4
|
-
*/
|
|
5
|
-
export declare function flapPrivateBuyMerkle(params: FlapPrivateBuyMerkleParams): Promise<FlapPrivateTransactionResult>;
|
|
6
|
-
/**
|
|
7
|
-
* 私有卖出(单笔)(Merkle 版本)
|
|
8
|
-
*/
|
|
9
|
-
export declare function flapPrivateSellMerkle(params: FlapPrivateSellMerkleParams): Promise<FlapPrivateTransactionResult>;
|
|
10
|
-
/**
|
|
11
|
-
* 批量私有购买(Merkle 版本)
|
|
12
|
-
*/
|
|
13
|
-
export declare function flapBatchPrivateBuyMerkle(params: FlapBatchPrivateBuyMerkleParams): Promise<FlapBatchPrivateMerkleResult>;
|
|
14
|
-
/**
|
|
15
|
-
* 批量私有卖出(Merkle 版本)
|
|
16
|
-
*/
|
|
17
|
-
export declare function flapBatchPrivateSellMerkle(params: FlapBatchPrivateSellMerkleParams): Promise<FlapBatchPrivateMerkleResult>;
|
|
@@ -1,549 +0,0 @@
|
|
|
1
|
-
import { ethers, Wallet } from 'ethers';
|
|
2
|
-
import { MerkleClient } from '../../clients/merkle.js';
|
|
3
|
-
import { getOptimizedGasPrice, buildProfitHopTransactions, PROFIT_HOP_COUNT } from '../../../utils/bundle-helpers.js';
|
|
4
|
-
import { FLAP_PORTAL_ADDRESSES } from '../constants.js';
|
|
5
|
-
import { ZERO_ADDRESS } from '../../../utils/constants.js';
|
|
6
|
-
import { GAS_LIMITS, CHAINS } from '../../constants/index.js';
|
|
7
|
-
import { CHAIN_ID_MAP, PORTAL_ABI, getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, calculateBatchProfit, getProfitRecipient, getBribeAmount, BLOCKRAZOR_BUILDER_EOA } from './config.js';
|
|
8
|
-
const DEFAULT_GAS_LIMIT = 800000;
|
|
9
|
-
/**
|
|
10
|
-
* 私有购买(单笔)(Merkle 版本)
|
|
11
|
-
*/
|
|
12
|
-
export async function flapPrivateBuyMerkle(params) {
|
|
13
|
-
const { chain, privateKey, tokenAddress, amountIn, minOutputAmount, config } = params;
|
|
14
|
-
const { chainId, provider } = createMerkleContext(chain, config);
|
|
15
|
-
const wallet = new Wallet(privateKey, provider);
|
|
16
|
-
const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
|
|
17
|
-
const originalAmountWei = ethers.parseEther(amountIn);
|
|
18
|
-
// ✅ 利润提取配置
|
|
19
|
-
const extractProfit = shouldExtractProfit(config);
|
|
20
|
-
const { actualAmountWei, profitWei } = splitBuyAmount(originalAmountWei, extractProfit, config);
|
|
21
|
-
const minAmountOut = parseMinOutput(minOutputAmount);
|
|
22
|
-
const portal = new ethers.Contract(portalAddr, PORTAL_ABI, wallet);
|
|
23
|
-
// ✅ 并行获取 gasPrice、nonce 和构建未签名交易
|
|
24
|
-
const [gasPrice, currentNonce, unsigned] = await Promise.all([
|
|
25
|
-
getOptimizedGasPrice(provider, getGasPriceConfig(config)),
|
|
26
|
-
// ✅ 使用 pending nonce,避免 xLayer 等链上“已有 pending 交易”导致 nonce too low
|
|
27
|
-
provider.getTransactionCount(wallet.address, 'pending'),
|
|
28
|
-
portal.swapExactInput.populateTransaction({
|
|
29
|
-
inputToken: ZERO_ADDRESS,
|
|
30
|
-
outputToken: tokenAddress,
|
|
31
|
-
inputAmount: actualAmountWei,
|
|
32
|
-
minOutputAmount: minAmountOut,
|
|
33
|
-
permitData: '0x',
|
|
34
|
-
}, { value: actualAmountWei })
|
|
35
|
-
]);
|
|
36
|
-
const gasLimit = resolveGasLimit(config.gasLimitMultiplier);
|
|
37
|
-
// ✅ 获取贿赂金额
|
|
38
|
-
const bribeAmount = getBribeAmount(config);
|
|
39
|
-
const needBribeTx = bribeAmount > 0n;
|
|
40
|
-
const needProfitTx = extractProfit && profitWei > 0n;
|
|
41
|
-
// ✅ 分配 nonces:贿赂 → 买入 → 利润
|
|
42
|
-
let nonceIdx = 0;
|
|
43
|
-
const bribeNonce = needBribeTx ? currentNonce + nonceIdx++ : undefined;
|
|
44
|
-
const buyNonce = currentNonce + nonceIdx++;
|
|
45
|
-
const profitNonce = needProfitTx ? currentNonce + nonceIdx : undefined;
|
|
46
|
-
// ✅ 并行签名所有交易(贿赂、买入、利润)
|
|
47
|
-
const signPromises = [];
|
|
48
|
-
const txType = getTxType(config);
|
|
49
|
-
// 贿赂交易
|
|
50
|
-
if (needBribeTx && bribeNonce !== undefined) {
|
|
51
|
-
signPromises.push(wallet.signTransaction({
|
|
52
|
-
to: BLOCKRAZOR_BUILDER_EOA,
|
|
53
|
-
value: bribeAmount,
|
|
54
|
-
nonce: bribeNonce,
|
|
55
|
-
gasPrice,
|
|
56
|
-
gasLimit: GAS_LIMITS.BRIBE,
|
|
57
|
-
chainId,
|
|
58
|
-
type: txType
|
|
59
|
-
}));
|
|
60
|
-
}
|
|
61
|
-
// 买入交易
|
|
62
|
-
signPromises.push(wallet.signTransaction({
|
|
63
|
-
...unsigned,
|
|
64
|
-
from: wallet.address,
|
|
65
|
-
nonce: buyNonce,
|
|
66
|
-
gasLimit,
|
|
67
|
-
gasPrice,
|
|
68
|
-
chainId,
|
|
69
|
-
type: txType,
|
|
70
|
-
value: actualAmountWei
|
|
71
|
-
}));
|
|
72
|
-
// ✅ 并行签名完成后按顺序返回
|
|
73
|
-
const signedTxs = await Promise.all(signPromises);
|
|
74
|
-
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
75
|
-
let profitHopWallets;
|
|
76
|
-
if (needProfitTx && profitNonce !== undefined) {
|
|
77
|
-
const profitHopResult = await buildProfitHopTransactions({
|
|
78
|
-
provider,
|
|
79
|
-
payerWallet: wallet,
|
|
80
|
-
profitAmount: profitWei,
|
|
81
|
-
profitRecipient: getProfitRecipient(),
|
|
82
|
-
hopCount: PROFIT_HOP_COUNT,
|
|
83
|
-
gasPrice,
|
|
84
|
-
chainId,
|
|
85
|
-
txType,
|
|
86
|
-
startNonce: profitNonce
|
|
87
|
-
});
|
|
88
|
-
signedTxs.push(...profitHopResult.signedTransactions);
|
|
89
|
-
profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
|
|
90
|
-
}
|
|
91
|
-
return { signedTransactions: signedTxs, profitHopWallets }; // ✅ 返回利润多跳钱包
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* 私有卖出(单笔)(Merkle 版本)
|
|
95
|
-
*/
|
|
96
|
-
export async function flapPrivateSellMerkle(params) {
|
|
97
|
-
const { chain, privateKey, tokenAddress, amount, minOutputAmount, config } = params;
|
|
98
|
-
const { chainId, provider } = createMerkleContext(chain, config);
|
|
99
|
-
const wallet = new Wallet(privateKey, provider);
|
|
100
|
-
const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
|
|
101
|
-
const amountWei = ethers.parseUnits(amount, 18);
|
|
102
|
-
const portal = new ethers.Contract(portalAddr, PORTAL_ABI, wallet);
|
|
103
|
-
// ✅ 并行获取 gasPrice、nonce、报价和构建未签名交易
|
|
104
|
-
const [gasPrice, currentNonce, { quotedOutput }, unsigned] = await Promise.all([
|
|
105
|
-
getOptimizedGasPrice(provider, getGasPriceConfig(config)),
|
|
106
|
-
// ✅ 使用 pending nonce,避免 xLayer 等链上“已有 pending 交易”导致 nonce too low
|
|
107
|
-
provider.getTransactionCount(wallet.address, 'pending'),
|
|
108
|
-
resolveSingleSellOutputs(portal, tokenAddress, amountWei, minOutputAmount),
|
|
109
|
-
portal.swapExactInput.populateTransaction({
|
|
110
|
-
inputToken: tokenAddress,
|
|
111
|
-
outputToken: ZERO_ADDRESS,
|
|
112
|
-
inputAmount: amountWei,
|
|
113
|
-
minOutputAmount: 0n, // ✅ 已移除滑点保护
|
|
114
|
-
permitData: '0x',
|
|
115
|
-
})
|
|
116
|
-
]);
|
|
117
|
-
const gasLimit = resolveGasLimit(config.gasLimitMultiplier);
|
|
118
|
-
const txType = getTxType(config);
|
|
119
|
-
// ✅ 获取贿赂金额
|
|
120
|
-
const bribeAmount = getBribeAmount(config);
|
|
121
|
-
const needBribeTx = bribeAmount > 0n;
|
|
122
|
-
// ✅ 利润计算
|
|
123
|
-
const extractProfit = shouldExtractProfit(config);
|
|
124
|
-
const { profit: profitWei } = extractProfit && quotedOutput > 0n
|
|
125
|
-
? calculateProfit(quotedOutput, config)
|
|
126
|
-
: { profit: 0n };
|
|
127
|
-
const needProfitTx = extractProfit && profitWei > 0n;
|
|
128
|
-
// ✅ 分配 nonces:贿赂 → 卖出 → 利润
|
|
129
|
-
let nonceIdx = 0;
|
|
130
|
-
const bribeNonce = needBribeTx ? currentNonce + nonceIdx++ : undefined;
|
|
131
|
-
const sellNonce = currentNonce + nonceIdx++;
|
|
132
|
-
const profitNonce = needProfitTx ? currentNonce + nonceIdx : undefined;
|
|
133
|
-
// ✅ 并行签名所有交易(贿赂、卖出、利润)
|
|
134
|
-
const signPromises = [];
|
|
135
|
-
// 贿赂交易
|
|
136
|
-
if (needBribeTx && bribeNonce !== undefined) {
|
|
137
|
-
signPromises.push(wallet.signTransaction({
|
|
138
|
-
to: BLOCKRAZOR_BUILDER_EOA,
|
|
139
|
-
value: bribeAmount,
|
|
140
|
-
nonce: bribeNonce,
|
|
141
|
-
gasPrice,
|
|
142
|
-
gasLimit: GAS_LIMITS.BRIBE,
|
|
143
|
-
chainId,
|
|
144
|
-
type: txType
|
|
145
|
-
}));
|
|
146
|
-
}
|
|
147
|
-
// 卖出交易
|
|
148
|
-
signPromises.push(wallet.signTransaction({
|
|
149
|
-
...unsigned,
|
|
150
|
-
from: wallet.address,
|
|
151
|
-
nonce: sellNonce,
|
|
152
|
-
gasLimit,
|
|
153
|
-
gasPrice,
|
|
154
|
-
chainId,
|
|
155
|
-
type: txType
|
|
156
|
-
}));
|
|
157
|
-
// ✅ 并行签名完成后按顺序返回
|
|
158
|
-
const signedTxs = await Promise.all(signPromises);
|
|
159
|
-
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
160
|
-
let profitHopWallets;
|
|
161
|
-
if (needProfitTx && profitNonce !== undefined) {
|
|
162
|
-
const profitHopResult = await buildProfitHopTransactions({
|
|
163
|
-
provider,
|
|
164
|
-
payerWallet: wallet,
|
|
165
|
-
profitAmount: profitWei,
|
|
166
|
-
profitRecipient: getProfitRecipient(),
|
|
167
|
-
hopCount: PROFIT_HOP_COUNT,
|
|
168
|
-
gasPrice,
|
|
169
|
-
chainId,
|
|
170
|
-
txType,
|
|
171
|
-
startNonce: profitNonce
|
|
172
|
-
});
|
|
173
|
-
signedTxs.push(...profitHopResult.signedTransactions);
|
|
174
|
-
profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
|
|
175
|
-
}
|
|
176
|
-
return { signedTransactions: signedTxs, profitHopWallets }; // ✅ 返回利润多跳钱包
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* 批量私有购买(Merkle 版本)
|
|
180
|
-
*/
|
|
181
|
-
export async function flapBatchPrivateBuyMerkle(params) {
|
|
182
|
-
const { chain, privateKeys, amountsIn, tokenAddress, minOutputAmounts, config } = params;
|
|
183
|
-
if (privateKeys.length !== amountsIn.length) {
|
|
184
|
-
throw new Error('privateKeys and amountsIn length mismatch');
|
|
185
|
-
}
|
|
186
|
-
const { chainId, provider } = createMerkleContext(chain, config);
|
|
187
|
-
const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
|
|
188
|
-
const wallets = privateKeys.map(k => new Wallet(k, provider));
|
|
189
|
-
const originalAmountsWei = amountsIn.map(a => ethers.parseEther(a));
|
|
190
|
-
// ✅ 利润提取配置
|
|
191
|
-
const extractProfit = shouldExtractProfit(config);
|
|
192
|
-
const { totalProfit, remainingAmounts } = calculateBatchProfit(originalAmountsWei, config);
|
|
193
|
-
const actualAmountsWei = remainingAmounts;
|
|
194
|
-
const maxFundsIndex = findMaxIndex(originalAmountsWei);
|
|
195
|
-
const minOuts = resolveBatchMinOutputs(minOutputAmounts, wallets.length);
|
|
196
|
-
const portals = wallets.map(w => new ethers.Contract(portalAddr, PORTAL_ABI, w));
|
|
197
|
-
// ✅ 获取贿赂金额
|
|
198
|
-
const bribeAmount = getBribeAmount(config);
|
|
199
|
-
const needBribeTx = bribeAmount > 0n;
|
|
200
|
-
const needProfitTx = extractProfit && totalProfit > 0n;
|
|
201
|
-
// ✅ 并行获取 gasPrice、所有 nonces 和构建未签名交易
|
|
202
|
-
const [gasPrice, initialNonces, unsignedList] = await Promise.all([
|
|
203
|
-
getOptimizedGasPrice(provider, getGasPriceConfig(config)),
|
|
204
|
-
// ✅ 使用 pending nonce,避免 xLayer 等链上“已有 pending 交易”导致 nonce too low
|
|
205
|
-
Promise.all(wallets.map(w => provider.getTransactionCount(w.address, 'pending'))),
|
|
206
|
-
Promise.all(portals.map((portal, i) => portal.swapExactInput.populateTransaction({
|
|
207
|
-
inputToken: ZERO_ADDRESS,
|
|
208
|
-
outputToken: tokenAddress,
|
|
209
|
-
inputAmount: actualAmountsWei[i],
|
|
210
|
-
minOutputAmount: minOuts[i],
|
|
211
|
-
permitData: '0x',
|
|
212
|
-
}, { value: actualAmountsWei[i] })))
|
|
213
|
-
]);
|
|
214
|
-
// ✅ 分配 nonces:贿赂(可选) → 买入 → 利润(可选)
|
|
215
|
-
let payerNonceOffset = 0;
|
|
216
|
-
let bribeNonce;
|
|
217
|
-
if (needBribeTx && maxFundsIndex >= 0) {
|
|
218
|
-
bribeNonce = initialNonces[maxFundsIndex];
|
|
219
|
-
payerNonceOffset++;
|
|
220
|
-
}
|
|
221
|
-
const nonces = initialNonces.map((n, i) => {
|
|
222
|
-
if (i === maxFundsIndex) {
|
|
223
|
-
return n + payerNonceOffset; // payer 的买入 nonce 需要偏移
|
|
224
|
-
}
|
|
225
|
-
return n;
|
|
226
|
-
});
|
|
227
|
-
const profitNonce = needProfitTx && maxFundsIndex >= 0
|
|
228
|
-
? initialNonces[maxFundsIndex] + payerNonceOffset + 1
|
|
229
|
-
: undefined;
|
|
230
|
-
const gasLimit = resolveGasLimit(config.gasLimitMultiplier);
|
|
231
|
-
const gasLimits = new Array(wallets.length).fill(gasLimit);
|
|
232
|
-
const signedTxs = [];
|
|
233
|
-
// ✅ 贿赂交易放在首位
|
|
234
|
-
if (needBribeTx && bribeNonce !== undefined && maxFundsIndex >= 0) {
|
|
235
|
-
const bribeTx = await wallets[maxFundsIndex].signTransaction({
|
|
236
|
-
to: BLOCKRAZOR_BUILDER_EOA,
|
|
237
|
-
value: bribeAmount,
|
|
238
|
-
nonce: bribeNonce,
|
|
239
|
-
gasPrice,
|
|
240
|
-
gasLimit: GAS_LIMITS.BRIBE,
|
|
241
|
-
chainId,
|
|
242
|
-
type: getTxType(config)
|
|
243
|
-
});
|
|
244
|
-
signedTxs.push(bribeTx);
|
|
245
|
-
}
|
|
246
|
-
// ✅ 并行签名所有买入交易
|
|
247
|
-
const signedList = await signBatchTransactions({
|
|
248
|
-
unsignedList,
|
|
249
|
-
wallets,
|
|
250
|
-
nonces,
|
|
251
|
-
gasLimits,
|
|
252
|
-
gasPrice,
|
|
253
|
-
chainId,
|
|
254
|
-
config,
|
|
255
|
-
values: actualAmountsWei
|
|
256
|
-
});
|
|
257
|
-
signedTxs.push(...signedList);
|
|
258
|
-
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
259
|
-
let profitHopWallets;
|
|
260
|
-
if (needProfitTx && profitNonce !== undefined && maxFundsIndex >= 0) {
|
|
261
|
-
const profitHopResult = await buildProfitHopTransactions({
|
|
262
|
-
provider,
|
|
263
|
-
payerWallet: wallets[maxFundsIndex],
|
|
264
|
-
profitAmount: totalProfit,
|
|
265
|
-
profitRecipient: getProfitRecipient(),
|
|
266
|
-
hopCount: PROFIT_HOP_COUNT,
|
|
267
|
-
gasPrice,
|
|
268
|
-
chainId,
|
|
269
|
-
txType: getTxType(config),
|
|
270
|
-
startNonce: profitNonce
|
|
271
|
-
});
|
|
272
|
-
signedTxs.push(...profitHopResult.signedTransactions);
|
|
273
|
-
profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
|
|
274
|
-
}
|
|
275
|
-
return { signedTransactions: signedTxs, profitHopWallets }; // ✅ 返回利润多跳钱包
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* 批量私有卖出(Merkle 版本)
|
|
279
|
-
*/
|
|
280
|
-
export async function flapBatchPrivateSellMerkle(params) {
|
|
281
|
-
const { chain, privateKeys, amounts, tokenAddress, minOutputAmounts, config } = params;
|
|
282
|
-
if (privateKeys.length !== amounts.length) {
|
|
283
|
-
throw new Error('privateKeys and amounts length mismatch');
|
|
284
|
-
}
|
|
285
|
-
const { chainId, provider } = createMerkleContext(chain, config);
|
|
286
|
-
const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
|
|
287
|
-
const wallets = privateKeys.map(k => new Wallet(k, provider));
|
|
288
|
-
const amountsWei = amounts.map(a => ethers.parseUnits(a, 18));
|
|
289
|
-
const portal = new ethers.Contract(portalAddr, PORTAL_ABI, provider);
|
|
290
|
-
const portals = wallets.map(w => new ethers.Contract(portalAddr, PORTAL_ABI, w));
|
|
291
|
-
// ✅ 并行获取 gasPrice、所有 nonces、所有报价和构建未签名交易
|
|
292
|
-
const [gasPrice, initialNonces, quotedOutputs, unsignedList] = await Promise.all([
|
|
293
|
-
getOptimizedGasPrice(provider, getGasPriceConfig(config)),
|
|
294
|
-
// ✅ 使用 pending nonce,避免 xLayer 等链上“已有 pending 交易”导致 nonce too low
|
|
295
|
-
Promise.all(wallets.map(w => provider.getTransactionCount(w.address, 'pending'))),
|
|
296
|
-
Promise.all(amountsWei.map(amount => portal.quoteExactInput.staticCall({
|
|
297
|
-
inputToken: tokenAddress,
|
|
298
|
-
outputToken: ZERO_ADDRESS,
|
|
299
|
-
inputAmount: amount
|
|
300
|
-
}).catch(() => 0n))),
|
|
301
|
-
// ✅ 并行构建未签名交易(已移除滑点保护:minOuts 固定为 0)
|
|
302
|
-
Promise.all(portals.map((p, i) => p.swapExactInput.populateTransaction({
|
|
303
|
-
inputToken: tokenAddress,
|
|
304
|
-
outputToken: ZERO_ADDRESS,
|
|
305
|
-
inputAmount: amountsWei[i],
|
|
306
|
-
minOutputAmount: 0n,
|
|
307
|
-
permitData: '0x'
|
|
308
|
-
})))
|
|
309
|
-
]);
|
|
310
|
-
const extractProfit = shouldExtractProfit(config);
|
|
311
|
-
const { totalProfit, maxRevenueIndex } = summarizeSellProfits(quotedOutputs, extractProfit, config);
|
|
312
|
-
// ✅ 获取贿赂金额
|
|
313
|
-
const bribeAmount = getBribeAmount(config);
|
|
314
|
-
const needBribeTx = bribeAmount > 0n;
|
|
315
|
-
const needProfitTx = extractProfit && totalProfit > 0n;
|
|
316
|
-
// ✅ 分配 nonces:贿赂(可选) → 卖出 → 利润(可选)
|
|
317
|
-
let payerNonceOffset = 0;
|
|
318
|
-
let bribeNonce;
|
|
319
|
-
if (needBribeTx && maxRevenueIndex >= 0) {
|
|
320
|
-
bribeNonce = initialNonces[maxRevenueIndex];
|
|
321
|
-
payerNonceOffset++;
|
|
322
|
-
}
|
|
323
|
-
const nonces = initialNonces.map((n, i) => {
|
|
324
|
-
if (i === maxRevenueIndex) {
|
|
325
|
-
return n + payerNonceOffset; // payer 的卖出 nonce 需要偏移
|
|
326
|
-
}
|
|
327
|
-
return n;
|
|
328
|
-
});
|
|
329
|
-
const profitNonce = needProfitTx && maxRevenueIndex >= 0
|
|
330
|
-
? initialNonces[maxRevenueIndex] + payerNonceOffset + 1
|
|
331
|
-
: undefined;
|
|
332
|
-
const gasLimit = resolveGasLimit(config.gasLimitMultiplier);
|
|
333
|
-
const gasLimits = new Array(wallets.length).fill(gasLimit);
|
|
334
|
-
const signedTxs = [];
|
|
335
|
-
// ✅ 贿赂交易放在首位
|
|
336
|
-
if (needBribeTx && bribeNonce !== undefined && maxRevenueIndex >= 0) {
|
|
337
|
-
const bribeTx = await wallets[maxRevenueIndex].signTransaction({
|
|
338
|
-
to: BLOCKRAZOR_BUILDER_EOA,
|
|
339
|
-
value: bribeAmount,
|
|
340
|
-
nonce: bribeNonce,
|
|
341
|
-
gasPrice,
|
|
342
|
-
gasLimit: GAS_LIMITS.BRIBE,
|
|
343
|
-
chainId,
|
|
344
|
-
type: getTxType(config)
|
|
345
|
-
});
|
|
346
|
-
signedTxs.push(bribeTx);
|
|
347
|
-
}
|
|
348
|
-
// ✅ 并行签名所有卖出交易
|
|
349
|
-
const signedList = await signBatchTransactions({
|
|
350
|
-
unsignedList,
|
|
351
|
-
wallets,
|
|
352
|
-
nonces,
|
|
353
|
-
gasLimits,
|
|
354
|
-
gasPrice,
|
|
355
|
-
chainId,
|
|
356
|
-
config
|
|
357
|
-
});
|
|
358
|
-
signedTxs.push(...signedList);
|
|
359
|
-
// ✅ 利润多跳转账(强制 2 跳中转)
|
|
360
|
-
let profitHopWallets;
|
|
361
|
-
if (needProfitTx && profitNonce !== undefined && maxRevenueIndex >= 0) {
|
|
362
|
-
const profitHopResult = await buildProfitHopTransactions({
|
|
363
|
-
provider,
|
|
364
|
-
payerWallet: wallets[maxRevenueIndex],
|
|
365
|
-
profitAmount: totalProfit,
|
|
366
|
-
profitRecipient: getProfitRecipient(),
|
|
367
|
-
hopCount: PROFIT_HOP_COUNT,
|
|
368
|
-
gasPrice,
|
|
369
|
-
chainId,
|
|
370
|
-
txType: getTxType(config),
|
|
371
|
-
startNonce: profitNonce
|
|
372
|
-
});
|
|
373
|
-
signedTxs.push(...profitHopResult.signedTransactions);
|
|
374
|
-
profitHopWallets = profitHopResult.hopWallets; // ✅ 收集利润多跳钱包
|
|
375
|
-
}
|
|
376
|
-
return { signedTransactions: signedTxs, profitHopWallets }; // ✅ 返回利润多跳钱包
|
|
377
|
-
}
|
|
378
|
-
// ==================== 内部工具函数 ====================
|
|
379
|
-
function createMerkleContext(chain, config) {
|
|
380
|
-
const chainId = CHAIN_ID_MAP[chain];
|
|
381
|
-
// ✅ 检查是否为 Merkle 支持的链(BSC, ETH)
|
|
382
|
-
// Monad 不支持 Merkle 捆绑服务,使用普通 RPC
|
|
383
|
-
if (chainId !== CHAINS.BSC.chainId && chainId !== CHAINS.ETHEREUM.chainId) {
|
|
384
|
-
// 对于不支持 Merkle 的链(如 Monad),必须提供自定义 RPC
|
|
385
|
-
if (!config.customRpcUrl) {
|
|
386
|
-
throw new Error(`Chain ${chain} (chainId: ${chainId}) does not support Merkle bundle service. Please provide customRpcUrl.`);
|
|
387
|
-
}
|
|
388
|
-
const { JsonRpcProvider } = require('ethers');
|
|
389
|
-
// ✅ 禁用 ENS: 避免 "network does not support ENS" 错误
|
|
390
|
-
return {
|
|
391
|
-
chainId,
|
|
392
|
-
provider: new JsonRpcProvider(config.customRpcUrl, { chainId, name: chain.toLowerCase(), ensAddress: undefined })
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
const merkle = new MerkleClient({
|
|
396
|
-
apiKey: config.apiKey,
|
|
397
|
-
chainId: chainId, // 类型断言为 Merkle 支持的 chainId
|
|
398
|
-
customRpcUrl: config.customRpcUrl
|
|
399
|
-
});
|
|
400
|
-
return {
|
|
401
|
-
chainId,
|
|
402
|
-
provider: merkle.getProvider()
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
|
-
function splitBuyAmount(amount, extractProfit, config) {
|
|
406
|
-
if (!extractProfit) {
|
|
407
|
-
return { actualAmountWei: amount, profitWei: 0n };
|
|
408
|
-
}
|
|
409
|
-
const { remaining, profit } = calculateProfit(amount, config);
|
|
410
|
-
return { actualAmountWei: remaining, profitWei: profit };
|
|
411
|
-
}
|
|
412
|
-
function parseMinOutput(value) {
|
|
413
|
-
if (value === undefined) {
|
|
414
|
-
return 0n;
|
|
415
|
-
}
|
|
416
|
-
return typeof value === 'string' ? ethers.parseUnits(value, 18) : value;
|
|
417
|
-
}
|
|
418
|
-
function resolveGasLimit(multiplier, defaultGas = DEFAULT_GAS_LIMIT) {
|
|
419
|
-
const factor = multiplier ?? 1.0;
|
|
420
|
-
return BigInt(Math.ceil(defaultGas * factor));
|
|
421
|
-
}
|
|
422
|
-
/**
|
|
423
|
-
* 追加利润多跳转账交易(强制 2 跳中转)
|
|
424
|
-
*/
|
|
425
|
-
async function appendSingleProfitTransfer({ extractProfit, profitWei, wallet, baseNonce, provider, gasPrice, chainId, config, signedTxs }) {
|
|
426
|
-
if (!extractProfit || profitWei === 0n) {
|
|
427
|
-
return undefined;
|
|
428
|
-
}
|
|
429
|
-
const profitHopResult = await buildProfitHopTransactions({
|
|
430
|
-
provider,
|
|
431
|
-
payerWallet: wallet,
|
|
432
|
-
profitAmount: profitWei,
|
|
433
|
-
profitRecipient: getProfitRecipient(),
|
|
434
|
-
hopCount: PROFIT_HOP_COUNT,
|
|
435
|
-
gasPrice,
|
|
436
|
-
chainId,
|
|
437
|
-
txType: getTxType(config),
|
|
438
|
-
startNonce: baseNonce + 1
|
|
439
|
-
});
|
|
440
|
-
signedTxs.push(...profitHopResult.signedTransactions);
|
|
441
|
-
return profitHopResult.hopWallets; // ✅ 返回利润多跳钱包
|
|
442
|
-
}
|
|
443
|
-
async function resolveSingleSellOutputs(portal, tokenAddress, amountWei, minOutputAmount) {
|
|
444
|
-
if (minOutputAmount !== undefined) {
|
|
445
|
-
const minOut = typeof minOutputAmount === 'string'
|
|
446
|
-
? ethers.parseEther(minOutputAmount)
|
|
447
|
-
: minOutputAmount;
|
|
448
|
-
return {
|
|
449
|
-
quotedOutput: minOut,
|
|
450
|
-
minOut
|
|
451
|
-
};
|
|
452
|
-
}
|
|
453
|
-
try {
|
|
454
|
-
const quotedOutput = await portal.quoteExactInput.staticCall({
|
|
455
|
-
inputToken: tokenAddress,
|
|
456
|
-
outputToken: ZERO_ADDRESS,
|
|
457
|
-
inputAmount: amountWei
|
|
458
|
-
});
|
|
459
|
-
return {
|
|
460
|
-
quotedOutput,
|
|
461
|
-
minOut: 0n // ✅ 已移除滑点保护:minOut 固定为 0
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
catch {
|
|
465
|
-
return {
|
|
466
|
-
quotedOutput: 0n,
|
|
467
|
-
minOut: 0n
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
/**
|
|
472
|
-
* 追加卖出利润多跳转账交易(强制 2 跳中转)
|
|
473
|
-
*/
|
|
474
|
-
async function appendSingleSellProfitTransfer({ extractProfit, quotedOutput, wallet, baseNonce, provider, gasPrice, chainId, config, signedTxs }) {
|
|
475
|
-
if (!extractProfit || quotedOutput <= 0n) {
|
|
476
|
-
return undefined;
|
|
477
|
-
}
|
|
478
|
-
const { profit } = calculateProfit(quotedOutput, config);
|
|
479
|
-
if (profit === 0n) {
|
|
480
|
-
return undefined;
|
|
481
|
-
}
|
|
482
|
-
const profitHopResult = await buildProfitHopTransactions({
|
|
483
|
-
provider,
|
|
484
|
-
payerWallet: wallet,
|
|
485
|
-
profitAmount: profit,
|
|
486
|
-
profitRecipient: getProfitRecipient(),
|
|
487
|
-
hopCount: PROFIT_HOP_COUNT,
|
|
488
|
-
gasPrice,
|
|
489
|
-
chainId,
|
|
490
|
-
txType: getTxType(config),
|
|
491
|
-
startNonce: baseNonce + 1
|
|
492
|
-
});
|
|
493
|
-
signedTxs.push(...profitHopResult.signedTransactions);
|
|
494
|
-
return profitHopResult.hopWallets; // ✅ 返回利润多跳钱包
|
|
495
|
-
}
|
|
496
|
-
function resolveBatchMinOutputs(minOutputAmounts, walletCount) {
|
|
497
|
-
if (minOutputAmounts && minOutputAmounts.length === walletCount) {
|
|
498
|
-
return minOutputAmounts.map(m => typeof m === 'string' ? ethers.parseUnits(m, 18) : m);
|
|
499
|
-
}
|
|
500
|
-
return new Array(walletCount).fill(0n);
|
|
501
|
-
}
|
|
502
|
-
function findMaxIndex(values) {
|
|
503
|
-
if (values.length === 0) {
|
|
504
|
-
return -1;
|
|
505
|
-
}
|
|
506
|
-
let maxIndex = 0;
|
|
507
|
-
let maxValue = values[0];
|
|
508
|
-
for (let i = 1; i < values.length; i++) {
|
|
509
|
-
if (values[i] > maxValue) {
|
|
510
|
-
maxValue = values[i];
|
|
511
|
-
maxIndex = i;
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
return maxIndex;
|
|
515
|
-
}
|
|
516
|
-
async function signBatchTransactions({ unsignedList, wallets, nonces, gasLimits, gasPrice, chainId, config, values }) {
|
|
517
|
-
return await Promise.all(unsignedList.map((unsigned, i) => {
|
|
518
|
-
const value = values ? values[i] : unsigned.value;
|
|
519
|
-
return wallets[i].signTransaction({
|
|
520
|
-
...unsigned,
|
|
521
|
-
from: wallets[i].address,
|
|
522
|
-
nonce: nonces[i],
|
|
523
|
-
gasLimit: gasLimits[i],
|
|
524
|
-
gasPrice,
|
|
525
|
-
chainId,
|
|
526
|
-
type: getTxType(config),
|
|
527
|
-
value
|
|
528
|
-
});
|
|
529
|
-
}));
|
|
530
|
-
}
|
|
531
|
-
function summarizeSellProfits(quotedOutputs, extractProfit, config) {
|
|
532
|
-
let totalProfit = 0n;
|
|
533
|
-
let maxRevenueIndex = -1;
|
|
534
|
-
let maxRevenue = 0n;
|
|
535
|
-
if (extractProfit) {
|
|
536
|
-
for (let i = 0; i < quotedOutputs.length; i++) {
|
|
537
|
-
const quoted = quotedOutputs[i];
|
|
538
|
-
if (quoted > 0n) {
|
|
539
|
-
const { profit } = calculateProfit(quoted, config);
|
|
540
|
-
totalProfit += profit;
|
|
541
|
-
if (quoted > maxRevenue) {
|
|
542
|
-
maxRevenue = quoted;
|
|
543
|
-
maxRevenueIndex = i;
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
return { totalProfit, maxRevenueIndex: maxRevenueIndex < 0 ? 0 : maxRevenueIndex };
|
|
549
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Flap Protocol 内盘捆绑换手(Merkle Bundle)- 先买后卖
|
|
3
|
-
*
|
|
4
|
-
* 功能:钱包B先买入代币 → 钱包A卖出相同数量 → 原子执行
|
|
5
|
-
*/
|
|
6
|
-
import { CommonBundleConfig } from '../../../utils/bundle-helpers.js';
|
|
7
|
-
import { FlapSignConfig } from './config.js';
|
|
8
|
-
import type { GeneratedWallet } from '../../../utils/wallet.js';
|
|
9
|
-
export type FlapChain = 'bsc' | 'xlayer' | 'base';
|
|
10
|
-
export type UserType = 'v0' | 'v1';
|
|
11
|
-
export interface FlapBuyFirstSignConfig extends FlapSignConfig {
|
|
12
|
-
reserveGasETH?: number;
|
|
13
|
-
skipQuoteOnError?: boolean;
|
|
14
|
-
userType?: UserType;
|
|
15
|
-
}
|
|
16
|
-
export interface FlapBuyFirstConfig extends CommonBundleConfig {
|
|
17
|
-
apiKey: string;
|
|
18
|
-
customRpcUrl?: string;
|
|
19
|
-
bundleBlockOffset?: number;
|
|
20
|
-
reserveGasETH?: number;
|
|
21
|
-
skipQuoteOnError?: boolean;
|
|
22
|
-
waitForConfirmation?: boolean;
|
|
23
|
-
waitTimeoutMs?: number;
|
|
24
|
-
}
|
|
25
|
-
export interface FlapBundleBuyFirstSignParams {
|
|
26
|
-
chain: FlapChain;
|
|
27
|
-
buyerPrivateKey?: string;
|
|
28
|
-
buyerPrivateKeys?: string[];
|
|
29
|
-
sellerPrivateKey?: string;
|
|
30
|
-
sellerPrivateKeys?: string[];
|
|
31
|
-
tokenAddress: string;
|
|
32
|
-
buyerFunds?: string;
|
|
33
|
-
buyerFundsPercentage?: number;
|
|
34
|
-
config: FlapBuyFirstSignConfig;
|
|
35
|
-
quoteToken?: string;
|
|
36
|
-
quoteTokenDecimals?: number;
|
|
37
|
-
buyCount?: number;
|
|
38
|
-
sellCount?: number;
|
|
39
|
-
}
|
|
40
|
-
export interface FlapBundleBuyFirstParams {
|
|
41
|
-
chain: FlapChain;
|
|
42
|
-
buyerPrivateKey: string;
|
|
43
|
-
sellerPrivateKey: string;
|
|
44
|
-
tokenAddress: string;
|
|
45
|
-
buyerFunds?: string;
|
|
46
|
-
buyerFundsPercentage?: number;
|
|
47
|
-
config: FlapBuyFirstConfig;
|
|
48
|
-
}
|
|
49
|
-
/** ✅ Flap BuyFirst 结果(简化版) */
|
|
50
|
-
export type FlapBuyFirstResult = {
|
|
51
|
-
signedTransactions: string[];
|
|
52
|
-
profitHopWallets?: GeneratedWallet[];
|
|
53
|
-
metadata?: {
|
|
54
|
-
buyerAddress: string;
|
|
55
|
-
sellerAddress: string;
|
|
56
|
-
buyAmount: string;
|
|
57
|
-
sellAmount: string;
|
|
58
|
-
profitAmount?: string;
|
|
59
|
-
buyCount?: number;
|
|
60
|
-
sellCount?: number;
|
|
61
|
-
buyAmounts?: string[];
|
|
62
|
-
sellAmounts?: string[];
|
|
63
|
-
};
|
|
64
|
-
};
|
|
65
|
-
export declare function flapBundleBuyFirstMerkle(params: FlapBundleBuyFirstSignParams): Promise<FlapBuyFirstResult>;
|