four-flap-meme-sdk 1.3.91 → 1.3.93
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/clients/blockrazor.js +0 -1
- package/dist/contracts/tm-bundle-merkle/config.d.ts +5 -0
- package/dist/contracts/tm-bundle-merkle/config.js +10 -0
- package/dist/contracts/tm-bundle-merkle/core.js +92 -24
- package/dist/contracts/tm-bundle-merkle/pancake-proxy.js +103 -54
- package/dist/contracts/tm-bundle-merkle/swap-buy-first.d.ts +0 -1
- package/dist/contracts/tm-bundle-merkle/swap-buy-first.js +36 -6
- package/dist/contracts/tm-bundle-merkle/swap.d.ts +0 -3
- package/dist/contracts/tm-bundle-merkle/swap.js +59 -6
- package/dist/flap/portal-bundle-merkle/config.d.ts +8 -0
- package/dist/flap/portal-bundle-merkle/config.js +17 -0
- package/dist/flap/portal-bundle-merkle/core.js +120 -68
- package/dist/flap/portal-bundle-merkle/encryption.d.ts +16 -0
- package/dist/flap/portal-bundle-merkle/encryption.js +146 -0
- package/dist/flap/portal-bundle-merkle/pancake-proxy.js +136 -78
- package/dist/flap/portal-bundle-merkle/swap-buy-first.d.ts +0 -2
- package/dist/flap/portal-bundle-merkle/swap-buy-first.js +49 -30
- package/dist/flap/portal-bundle-merkle/swap.d.ts +0 -2
- package/dist/flap/portal-bundle-merkle/swap.js +75 -47
- package/dist/flap/portal-bundle-merkle/types.d.ts +1 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.js +0 -1
- package/dist/pancake/bundle-buy-first.d.ts +1 -1
- package/dist/pancake/bundle-buy-first.js +49 -17
- package/dist/pancake/bundle-swap.d.ts +1 -4
- package/dist/pancake/bundle-swap.js +98 -33
- package/dist/utils/erc20.d.ts +108 -2
- package/dist/utils/erc20.js +65 -17
- package/package.json +4 -39
- package/dist/sol/constants.d.ts +0 -126
- package/dist/sol/constants.js +0 -145
- package/dist/sol/dex/index.d.ts +0 -8
- package/dist/sol/dex/index.js +0 -12
- package/dist/sol/dex/meteora/client.d.ts +0 -76
- package/dist/sol/dex/meteora/client.js +0 -219
- package/dist/sol/dex/meteora/damm-v1-bundle.d.ts +0 -61
- package/dist/sol/dex/meteora/damm-v1-bundle.js +0 -112
- package/dist/sol/dex/meteora/damm-v1.d.ts +0 -118
- package/dist/sol/dex/meteora/damm-v1.js +0 -315
- package/dist/sol/dex/meteora/damm-v2-bundle.d.ts +0 -82
- package/dist/sol/dex/meteora/damm-v2-bundle.js +0 -242
- package/dist/sol/dex/meteora/damm-v2.d.ts +0 -172
- package/dist/sol/dex/meteora/damm-v2.js +0 -632
- package/dist/sol/dex/meteora/dbc-bundle.d.ts +0 -123
- package/dist/sol/dex/meteora/dbc-bundle.js +0 -304
- package/dist/sol/dex/meteora/dbc.d.ts +0 -192
- package/dist/sol/dex/meteora/dbc.js +0 -619
- package/dist/sol/dex/meteora/dlmm-bundle.d.ts +0 -39
- package/dist/sol/dex/meteora/dlmm-bundle.js +0 -189
- package/dist/sol/dex/meteora/dlmm.d.ts +0 -146
- package/dist/sol/dex/meteora/dlmm.js +0 -593
- package/dist/sol/dex/meteora/index.d.ts +0 -25
- package/dist/sol/dex/meteora/index.js +0 -65
- package/dist/sol/dex/meteora/types.d.ts +0 -787
- package/dist/sol/dex/meteora/types.js +0 -110
- package/dist/sol/dex/orca/index.d.ts +0 -10
- package/dist/sol/dex/orca/index.js +0 -16
- package/dist/sol/dex/orca/orca-bundle.d.ts +0 -41
- package/dist/sol/dex/orca/orca-bundle.js +0 -173
- package/dist/sol/dex/orca/orca.d.ts +0 -65
- package/dist/sol/dex/orca/orca.js +0 -474
- package/dist/sol/dex/orca/types.d.ts +0 -263
- package/dist/sol/dex/orca/types.js +0 -38
- package/dist/sol/dex/orca/wavebreak-bundle.d.ts +0 -34
- package/dist/sol/dex/orca/wavebreak-bundle.js +0 -198
- package/dist/sol/dex/orca/wavebreak-types.d.ts +0 -227
- package/dist/sol/dex/orca/wavebreak-types.js +0 -23
- package/dist/sol/dex/orca/wavebreak.d.ts +0 -78
- package/dist/sol/dex/orca/wavebreak.js +0 -497
- package/dist/sol/dex/pump/index.d.ts +0 -9
- package/dist/sol/dex/pump/index.js +0 -14
- package/dist/sol/dex/pump/pump-bundle.d.ts +0 -92
- package/dist/sol/dex/pump/pump-bundle.js +0 -383
- package/dist/sol/dex/pump/pump-swap-bundle.d.ts +0 -103
- package/dist/sol/dex/pump/pump-swap-bundle.js +0 -380
- package/dist/sol/dex/pump/pump-swap.d.ts +0 -46
- package/dist/sol/dex/pump/pump-swap.js +0 -199
- package/dist/sol/dex/pump/pump.d.ts +0 -35
- package/dist/sol/dex/pump/pump.js +0 -352
- package/dist/sol/dex/pump/types.d.ts +0 -215
- package/dist/sol/dex/pump/types.js +0 -5
- package/dist/sol/dex/raydium/index.d.ts +0 -8
- package/dist/sol/dex/raydium/index.js +0 -12
- package/dist/sol/dex/raydium/launchlab.d.ts +0 -68
- package/dist/sol/dex/raydium/launchlab.js +0 -210
- package/dist/sol/dex/raydium/raydium-bundle.d.ts +0 -64
- package/dist/sol/dex/raydium/raydium-bundle.js +0 -324
- package/dist/sol/dex/raydium/raydium.d.ts +0 -40
- package/dist/sol/dex/raydium/raydium.js +0 -366
- package/dist/sol/dex/raydium/types.d.ts +0 -240
- package/dist/sol/dex/raydium/types.js +0 -5
- package/dist/sol/index.d.ts +0 -10
- package/dist/sol/index.js +0 -16
- package/dist/sol/jito/bundle.d.ts +0 -90
- package/dist/sol/jito/bundle.js +0 -263
- package/dist/sol/jito/index.d.ts +0 -7
- package/dist/sol/jito/index.js +0 -7
- package/dist/sol/jito/tip.d.ts +0 -51
- package/dist/sol/jito/tip.js +0 -83
- package/dist/sol/jito/types.d.ts +0 -100
- package/dist/sol/jito/types.js +0 -5
- package/dist/sol/token/create-complete.d.ts +0 -115
- package/dist/sol/token/create-complete.js +0 -235
- package/dist/sol/token/create-token.d.ts +0 -57
- package/dist/sol/token/create-token.js +0 -230
- package/dist/sol/token/index.d.ts +0 -9
- package/dist/sol/token/index.js +0 -14
- package/dist/sol/token/metadata-upload.d.ts +0 -86
- package/dist/sol/token/metadata-upload.js +0 -173
- package/dist/sol/token/metadata.d.ts +0 -92
- package/dist/sol/token/metadata.js +0 -274
- package/dist/sol/token/types.d.ts +0 -153
- package/dist/sol/token/types.js +0 -5
- package/dist/sol/types.d.ts +0 -176
- package/dist/sol/types.js +0 -7
- package/dist/sol/utils/balance.d.ts +0 -160
- package/dist/sol/utils/balance.js +0 -638
- package/dist/sol/utils/connection.d.ts +0 -78
- package/dist/sol/utils/connection.js +0 -168
- package/dist/sol/utils/index.d.ts +0 -9
- package/dist/sol/utils/index.js +0 -9
- package/dist/sol/utils/lp-inspect.d.ts +0 -129
- package/dist/sol/utils/lp-inspect.js +0 -529
- package/dist/sol/utils/transfer.d.ts +0 -125
- package/dist/sol/utils/transfer.js +0 -220
- package/dist/sol/utils/wallet.d.ts +0 -107
- package/dist/sol/utils/wallet.js +0 -210
|
@@ -151,7 +151,6 @@ export class BlockRazorClient {
|
|
|
151
151
|
const gasPrice = tx.gasPrice || 0n;
|
|
152
152
|
const minGasPrice = ethers.parseUnits(String(MIN_GAS_PRICE_GWEI), 'gwei');
|
|
153
153
|
if (gasPrice < minGasPrice) {
|
|
154
|
-
console.warn(`⚠️ 交易 Gas Price (${ethers.formatUnits(gasPrice, 'gwei')} Gwei) 低于最低要求 (${MIN_GAS_PRICE_GWEI} Gwei)`);
|
|
155
154
|
}
|
|
156
155
|
}
|
|
157
156
|
catch {
|
|
@@ -64,3 +64,8 @@ export declare function calculateBatchProfit(amounts: bigint[], config?: FourAny
|
|
|
64
64
|
totalProfit: bigint;
|
|
65
65
|
remainingAmounts: bigint[];
|
|
66
66
|
};
|
|
67
|
+
/**
|
|
68
|
+
* 获取贿赂金额(Wei)
|
|
69
|
+
* ✅ 从配置中读取贿赂金额,转换为 Wei
|
|
70
|
+
*/
|
|
71
|
+
export declare function getBribeAmount(config?: FourAnyConfig): bigint;
|
|
@@ -103,3 +103,13 @@ export function calculateBatchProfit(amounts, config) {
|
|
|
103
103
|
}
|
|
104
104
|
return { totalProfit, remainingAmounts };
|
|
105
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* 获取贿赂金额(Wei)
|
|
108
|
+
* ✅ 从配置中读取贿赂金额,转换为 Wei
|
|
109
|
+
*/
|
|
110
|
+
export function getBribeAmount(config) {
|
|
111
|
+
if (!config || !config.bribeAmount || config.bribeAmount <= 0) {
|
|
112
|
+
return 0n;
|
|
113
|
+
}
|
|
114
|
+
return ethers.parseEther(String(config.bribeAmount));
|
|
115
|
+
}
|
|
@@ -2,7 +2,9 @@ import { ethers, Wallet, Contract, Interface } from 'ethers';
|
|
|
2
2
|
import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
|
|
3
3
|
import { ADDRESSES } from '../../utils/constants.js';
|
|
4
4
|
import { FourClient, buildLoginMessage } from '../../clients/four.js';
|
|
5
|
-
import { getErrorMessage, getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, getProfitRecipient } from './config.js';
|
|
5
|
+
import { getErrorMessage, getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, getProfitRecipient, getBribeAmount } from './config.js';
|
|
6
|
+
// ✅ BlockRazor Builder EOA 地址(用于贿赂)
|
|
7
|
+
const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
|
|
6
8
|
import { batchCheckAllowances } from '../../utils/erc20.js';
|
|
7
9
|
import { trySell } from '../tm.js';
|
|
8
10
|
import Helper3Abi from '../../abis/TokenManagerHelper3.json' with { type: 'json' };
|
|
@@ -87,7 +89,6 @@ export async function createTokenWithBundleBuyMerkle(params) {
|
|
|
87
89
|
const txType = getTxType(config);
|
|
88
90
|
const signedTxs = [];
|
|
89
91
|
const tmCreateAddr = ADDRESSES.BSC.TokenManagerOriginal;
|
|
90
|
-
const tmBuyAddr = ADDRESSES.BSC.TokenManagerOriginal;
|
|
91
92
|
// ✅ 单笔交易: 和 Four.meme 官网一样
|
|
92
93
|
// 计算利润
|
|
93
94
|
const extractProfit = shouldExtractProfit(config);
|
|
@@ -103,6 +104,9 @@ export async function createTokenWithBundleBuyMerkle(params) {
|
|
|
103
104
|
actualBuyFunds = originalBuyAmount;
|
|
104
105
|
profitAmount = 0n;
|
|
105
106
|
}
|
|
107
|
+
// ✅ 获取贿赂金额
|
|
108
|
+
const bribeAmount = getBribeAmount(config);
|
|
109
|
+
const needBribeTx = bribeAmount > 0n;
|
|
106
110
|
const b0AmountWei = ethers.parseEther(params.b0Amount ?? '0');
|
|
107
111
|
const preSaleWei = tokenInfo.preSale ? ethers.parseEther(tokenInfo.preSale) : 0n;
|
|
108
112
|
// ✅ 关键: value = 创建费用 + b0Amount + preSale + 买入金额
|
|
@@ -111,6 +115,21 @@ export async function createTokenWithBundleBuyMerkle(params) {
|
|
|
111
115
|
const tmCreate = new ethers.Contract(tmCreateAddr, TM2_ABI, devWallet);
|
|
112
116
|
const createTxUnsigned = await tmCreate.createToken.populateTransaction(createResp.createArg, createResp.signature, { value: valueWei } // ✅ 包含买入金额
|
|
113
117
|
);
|
|
118
|
+
// ✅ 贿赂交易放在首位(由 devWallet 发送)
|
|
119
|
+
let bribeNonce;
|
|
120
|
+
if (needBribeTx) {
|
|
121
|
+
bribeNonce = await nonceManager.getNextNonce(devWallet);
|
|
122
|
+
const bribeTx = await devWallet.signTransaction({
|
|
123
|
+
to: BLOCKRAZOR_BUILDER_EOA,
|
|
124
|
+
value: bribeAmount,
|
|
125
|
+
nonce: bribeNonce,
|
|
126
|
+
gasPrice,
|
|
127
|
+
gasLimit: 21000n,
|
|
128
|
+
chainId,
|
|
129
|
+
type: txType
|
|
130
|
+
});
|
|
131
|
+
signedTxs.push(bribeTx);
|
|
132
|
+
}
|
|
114
133
|
const createTxRequest = {
|
|
115
134
|
...createTxUnsigned,
|
|
116
135
|
from: devWallet.address,
|
|
@@ -122,7 +141,7 @@ export async function createTokenWithBundleBuyMerkle(params) {
|
|
|
122
141
|
value: valueWei
|
|
123
142
|
};
|
|
124
143
|
signedTxs.push(await devWallet.signTransaction(createTxRequest));
|
|
125
|
-
// ✅
|
|
144
|
+
// ✅ 添加利润转账交易(放在末尾)
|
|
126
145
|
if (extractProfit && profitAmount > 0n) {
|
|
127
146
|
const profitNonce = await nonceManager.getNextNonce(devWallet);
|
|
128
147
|
const profitTx = await devWallet.signTransaction({
|
|
@@ -257,6 +276,27 @@ async function executeBuyFlow(options) {
|
|
|
257
276
|
const extractProfit = shouldExtractProfit(config);
|
|
258
277
|
const analysis = analyzeBuyFunds(buyAmounts, config, extractProfit);
|
|
259
278
|
const finalGasLimit = getGasLimit(config);
|
|
279
|
+
// ✅ 获取贿赂金额
|
|
280
|
+
const bribeAmount = getBribeAmount(config);
|
|
281
|
+
const needBribeTx = bribeAmount > 0n;
|
|
282
|
+
const payer = profitMode.type === 'aggregated' ? (profitMode.payer ?? wallets[0]) : wallets[0];
|
|
283
|
+
// ✅ 贿赂交易放在首位
|
|
284
|
+
const signedTxs = [];
|
|
285
|
+
let bribeNonceOffset = 0;
|
|
286
|
+
if (needBribeTx) {
|
|
287
|
+
const bribeNonce = await nonceManager.getNextNonce(payer);
|
|
288
|
+
const bribeTx = await payer.signTransaction({
|
|
289
|
+
to: BLOCKRAZOR_BUILDER_EOA,
|
|
290
|
+
value: bribeAmount,
|
|
291
|
+
nonce: bribeNonce,
|
|
292
|
+
gasPrice,
|
|
293
|
+
gasLimit: 21000n,
|
|
294
|
+
chainId,
|
|
295
|
+
type: txType
|
|
296
|
+
});
|
|
297
|
+
signedTxs.push(bribeTx);
|
|
298
|
+
bribeNonceOffset = 1; // payer 的买入交易 nonce 需要偏移
|
|
299
|
+
}
|
|
260
300
|
// ✅ 优化:并行执行 populateBuyTransactions 和批量获取 nonces(JSON-RPC 批量请求)
|
|
261
301
|
const [unsignedBuys, nonces] = await Promise.all([
|
|
262
302
|
populateBuyTransactions({
|
|
@@ -267,27 +307,24 @@ async function executeBuyFlow(options) {
|
|
|
267
307
|
}),
|
|
268
308
|
nonceManager.getNextNoncesForWallets(wallets) // ✅ 批量获取 nonce
|
|
269
309
|
]);
|
|
270
|
-
// ✅
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const payer = profitMode.payer ?? wallets[0];
|
|
274
|
-
profitNonce = await nonceManager.getNextNonce(payer);
|
|
275
|
-
}
|
|
310
|
+
// ✅ 调整 payer 的 nonce(如果有贿赂交易,需要偏移)
|
|
311
|
+
const payerIndex = wallets.findIndex(w => w.address.toLowerCase() === payer.address.toLowerCase());
|
|
312
|
+
const adjustedNonces = nonces.map((n, i) => i === payerIndex ? n + bribeNonceOffset : n);
|
|
276
313
|
// ✅ 并行签名所有买入交易
|
|
277
314
|
const signedBuys = await Promise.all(unsignedBuys.map((unsigned, index) => wallets[index].signTransaction({
|
|
278
315
|
...unsigned,
|
|
279
316
|
from: wallets[index].address,
|
|
280
|
-
nonce:
|
|
317
|
+
nonce: adjustedNonces[index],
|
|
281
318
|
gasLimit: finalGasLimit,
|
|
282
319
|
gasPrice,
|
|
283
320
|
chainId,
|
|
284
321
|
type: txType,
|
|
285
322
|
value: analysis.fundsList[index]
|
|
286
323
|
})));
|
|
287
|
-
|
|
288
|
-
// ✅
|
|
289
|
-
if (extractProfit &&
|
|
290
|
-
const
|
|
324
|
+
signedTxs.push(...signedBuys);
|
|
325
|
+
// ✅ 添加利润转账交易(放在末尾,由 payer 发送)
|
|
326
|
+
if (extractProfit && analysis.totalProfit > 0n && profitMode.type === 'aggregated') {
|
|
327
|
+
const profitNonce = await nonceManager.getNextNonce(payer);
|
|
291
328
|
const profitTx = await payer.signTransaction({
|
|
292
329
|
to: getProfitRecipient(),
|
|
293
330
|
value: analysis.totalProfit,
|
|
@@ -307,6 +344,9 @@ async function executeSellFlow(options) {
|
|
|
307
344
|
const amountsWei = sellAmounts.map((amount) => ethers.parseUnits(amount, 18));
|
|
308
345
|
const finalGasLimit = getGasLimit(config);
|
|
309
346
|
const extractProfit = shouldExtractProfit(config);
|
|
347
|
+
// ✅ 获取贿赂金额
|
|
348
|
+
const bribeAmount = getBribeAmount(config);
|
|
349
|
+
const needBribeTx = bribeAmount > 0n;
|
|
310
350
|
// ✅ 优化:并行执行 resolveSellOutputs、ensureSellerBalances、ensureSellAllowances 和批量获取 nonces
|
|
311
351
|
const [sellOutputs, , , nonces] = await Promise.all([
|
|
312
352
|
resolveSellOutputs({
|
|
@@ -326,6 +366,29 @@ async function executeSellFlow(options) {
|
|
|
326
366
|
}),
|
|
327
367
|
nonceManager.getNextNoncesForWallets(wallets) // ✅ 批量获取 nonce(JSON-RPC 批量请求)
|
|
328
368
|
]);
|
|
369
|
+
// ✅ 找出收益最多的钱包作为 payer(贿赂和利润都由它发送)
|
|
370
|
+
const { totalProfit, payer } = summarizeSellProfits(sellOutputs.quotedOutputs, wallets, config);
|
|
371
|
+
const payerWallet = payer ?? wallets[0];
|
|
372
|
+
const payerIndex = wallets.findIndex(w => w.address.toLowerCase() === payerWallet.address.toLowerCase());
|
|
373
|
+
// ✅ 贿赂交易放在首位
|
|
374
|
+
const signedTxs = [];
|
|
375
|
+
let bribeNonceOffset = 0;
|
|
376
|
+
if (needBribeTx) {
|
|
377
|
+
const bribeNonce = nonces[payerIndex];
|
|
378
|
+
const bribeTx = await payerWallet.signTransaction({
|
|
379
|
+
to: BLOCKRAZOR_BUILDER_EOA,
|
|
380
|
+
value: bribeAmount,
|
|
381
|
+
nonce: bribeNonce,
|
|
382
|
+
gasPrice,
|
|
383
|
+
gasLimit: 21000n,
|
|
384
|
+
chainId,
|
|
385
|
+
type: txType
|
|
386
|
+
});
|
|
387
|
+
signedTxs.push(bribeTx);
|
|
388
|
+
bribeNonceOffset = 1;
|
|
389
|
+
}
|
|
390
|
+
// ✅ 调整 payer 的 nonce(如果有贿赂交易,需要偏移)
|
|
391
|
+
const adjustedNonces = nonces.map((n, i) => i === payerIndex ? n + bribeNonceOffset : n);
|
|
329
392
|
// ✅ 构建未签名交易
|
|
330
393
|
const unsignedSells = await populateSellTransactions({
|
|
331
394
|
sellers: wallets,
|
|
@@ -338,23 +401,24 @@ async function executeSellFlow(options) {
|
|
|
338
401
|
const signedSells = await Promise.all(unsignedSells.map((unsigned, index) => wallets[index].signTransaction({
|
|
339
402
|
...unsigned,
|
|
340
403
|
from: wallets[index].address,
|
|
341
|
-
nonce:
|
|
404
|
+
nonce: adjustedNonces[index],
|
|
342
405
|
gasLimit: finalGasLimit,
|
|
343
406
|
gasPrice,
|
|
344
407
|
chainId,
|
|
345
408
|
type: txType
|
|
346
409
|
})));
|
|
347
|
-
|
|
348
|
-
|
|
410
|
+
signedTxs.push(...signedSells);
|
|
411
|
+
// ✅ 利润交易放在末尾
|
|
349
412
|
await appendAggregatedProfitTransfer({
|
|
350
413
|
extractProfit,
|
|
351
414
|
totalProfit,
|
|
352
|
-
payer,
|
|
415
|
+
payer: payerWallet,
|
|
353
416
|
nonceManager,
|
|
354
417
|
gasPrice,
|
|
355
418
|
chainId,
|
|
356
419
|
txType,
|
|
357
|
-
signedTxs
|
|
420
|
+
signedTxs,
|
|
421
|
+
baseNonce: adjustedNonces[payerIndex] + 1 // ✅ 传入基础 nonce
|
|
358
422
|
});
|
|
359
423
|
return { signedTxs };
|
|
360
424
|
}
|
|
@@ -412,7 +476,8 @@ async function resolveSellOutputs(params) {
|
|
|
412
476
|
try {
|
|
413
477
|
const result = await trySell('BSC', rpcUrl, tokenAddress, amountsWei[0]);
|
|
414
478
|
const quotedOutputs = [result.funds];
|
|
415
|
-
|
|
479
|
+
// ✅ 已移除滑点保护:minOuts 固定为 0
|
|
480
|
+
const minOuts = [0n];
|
|
416
481
|
return { minOuts, quotedOutputs };
|
|
417
482
|
}
|
|
418
483
|
catch {
|
|
@@ -445,7 +510,8 @@ async function resolveSellOutputs(params) {
|
|
|
445
510
|
}
|
|
446
511
|
return 0n;
|
|
447
512
|
});
|
|
448
|
-
|
|
513
|
+
// ✅ 已移除滑点保护:minOuts 固定为 0
|
|
514
|
+
const minOuts = quotedOutputs.map(() => 0n);
|
|
449
515
|
return { minOuts, quotedOutputs };
|
|
450
516
|
}
|
|
451
517
|
catch {
|
|
@@ -459,7 +525,8 @@ async function resolveSellOutputs(params) {
|
|
|
459
525
|
return 0n;
|
|
460
526
|
}
|
|
461
527
|
}));
|
|
462
|
-
|
|
528
|
+
// ✅ 已移除滑点保护:minOuts 固定为 0
|
|
529
|
+
const minOuts = quotedOutputs.map(() => 0n);
|
|
463
530
|
return { minOuts, quotedOutputs };
|
|
464
531
|
}
|
|
465
532
|
}
|
|
@@ -509,11 +576,12 @@ function summarizeSellProfits(quotedOutputs, sellers, config) {
|
|
|
509
576
|
return { totalProfit, payer };
|
|
510
577
|
}
|
|
511
578
|
async function appendAggregatedProfitTransfer(params) {
|
|
512
|
-
const { extractProfit, totalProfit, payer, nonceManager, gasPrice, chainId, txType, signedTxs } = params;
|
|
579
|
+
const { extractProfit, totalProfit, payer, nonceManager, gasPrice, chainId, txType, signedTxs, baseNonce } = params;
|
|
513
580
|
if (!extractProfit || totalProfit <= 0n || !payer) {
|
|
514
581
|
return;
|
|
515
582
|
}
|
|
516
|
-
|
|
583
|
+
// ✅ 如果提供了 baseNonce,直接使用;否则从 nonceManager 获取
|
|
584
|
+
const profitNonce = baseNonce ?? await nonceManager.getNextNonce(payer);
|
|
517
585
|
const profitTx = await payer.signTransaction({
|
|
518
586
|
to: getProfitRecipient(),
|
|
519
587
|
value: totalProfit,
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { ethers, Wallet, JsonRpcProvider, Contract, Interface } from 'ethers';
|
|
2
2
|
import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
|
|
3
3
|
import { ADDRESSES } from '../../utils/constants.js';
|
|
4
|
-
import { getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, calculateBatchProfit, getProfitRecipient } from './config.js';
|
|
4
|
+
import { getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, calculateBatchProfit, getProfitRecipient, getBribeAmount } from './config.js';
|
|
5
5
|
import { batchCheckAllowances } from '../../utils/erc20.js';
|
|
6
|
+
// ✅ BlockRazor Builder EOA 地址(用于贿赂)
|
|
7
|
+
const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
|
|
6
8
|
const MULTICALL3_ADDRESS = '0xcA11bde05977b3631167028862bE2a173976CA11';
|
|
7
9
|
const MULTICALL3_ABI = [
|
|
8
10
|
'function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) external payable returns (tuple(bool success, bytes returnData)[])'
|
|
@@ -303,15 +305,22 @@ export async function fourPancakeProxyBatchBuyMerkle(params) {
|
|
|
303
305
|
const actualAmountsWei = remainingAmounts; // 扣除利润后用于购买的金额
|
|
304
306
|
const finalGasLimit = getGasLimit(config);
|
|
305
307
|
const nonceManager = new NonceManager(provider);
|
|
308
|
+
// ✅ 获取贿赂金额
|
|
309
|
+
const bribeAmount = getBribeAmount(config);
|
|
310
|
+
const needBribeTx = bribeAmount > 0n;
|
|
306
311
|
// ✅ 优化:并行获取 gasPrice 和 tokenDecimals
|
|
307
312
|
const [gasPrice, tokenDecimals] = await Promise.all([
|
|
308
313
|
getOptimizedGasPrice(provider, getGasPriceConfig(config)),
|
|
309
314
|
getTokenDecimals(tokenAddress, provider)
|
|
310
315
|
]);
|
|
311
316
|
// ✅ 修复:先计算需要的 nonce 数量,再统一获取
|
|
312
|
-
// buyers[0] 可能需要
|
|
317
|
+
// buyers[0] 可能需要 3 个 nonce(贿赂 + 买入 + 利润转账)
|
|
313
318
|
const needProfitTx = extractProfit && totalProfit > 0n;
|
|
314
|
-
|
|
319
|
+
let buyer0NeedCount = 1; // 买入交易
|
|
320
|
+
if (needBribeTx)
|
|
321
|
+
buyer0NeedCount++; // 贿赂交易
|
|
322
|
+
if (needProfitTx)
|
|
323
|
+
buyer0NeedCount++; // 利润交易
|
|
315
324
|
// 获取 buyers[0] 的连续 nonces
|
|
316
325
|
const buyer0Nonces = await nonceManager.getNextNonceBatch(buyers[0], buyer0NeedCount);
|
|
317
326
|
// 获取其他 buyers 的 nonces(如果有)
|
|
@@ -319,9 +328,13 @@ export async function fourPancakeProxyBatchBuyMerkle(params) {
|
|
|
319
328
|
if (buyers.length > 1) {
|
|
320
329
|
otherNonces = await nonceManager.getNextNoncesForWallets(buyers.slice(1));
|
|
321
330
|
}
|
|
331
|
+
// 分配 nonces
|
|
332
|
+
let buyer0NonceIdx = 0;
|
|
333
|
+
const bribeNonce = needBribeTx ? buyer0Nonces[buyer0NonceIdx++] : undefined;
|
|
334
|
+
const buyer0BuyNonce = buyer0Nonces[buyer0NonceIdx++];
|
|
335
|
+
const profitNonce = needProfitTx ? buyer0Nonces[buyer0NonceIdx] : undefined;
|
|
322
336
|
// 组装最终的 nonces 数组
|
|
323
|
-
const nonces = [
|
|
324
|
-
const profitNonce = needProfitTx ? buyer0Nonces[1] : undefined;
|
|
337
|
+
const nonces = [buyer0BuyNonce, ...otherNonces];
|
|
325
338
|
// 计算 minOutputAmounts
|
|
326
339
|
let minOuts;
|
|
327
340
|
if (params.minOutputAmounts && params.minOutputAmounts.length === buyers.length) {
|
|
@@ -356,8 +369,22 @@ export async function fourPancakeProxyBatchBuyMerkle(params) {
|
|
|
356
369
|
else {
|
|
357
370
|
throw new Error(`Unsupported routeType: ${routeType}`);
|
|
358
371
|
}
|
|
372
|
+
// ✅ 贿赂交易放在首位
|
|
373
|
+
const signedTxs = [];
|
|
374
|
+
if (needBribeTx && bribeNonce !== undefined) {
|
|
375
|
+
const bribeTx = await buyers[0].signTransaction({
|
|
376
|
+
to: BLOCKRAZOR_BUILDER_EOA,
|
|
377
|
+
value: bribeAmount,
|
|
378
|
+
nonce: bribeNonce,
|
|
379
|
+
gasPrice,
|
|
380
|
+
gasLimit: 21000n,
|
|
381
|
+
chainId: 56,
|
|
382
|
+
type: txType
|
|
383
|
+
});
|
|
384
|
+
signedTxs.push(bribeTx);
|
|
385
|
+
}
|
|
359
386
|
// ✅ 并行签名所有买入交易
|
|
360
|
-
const
|
|
387
|
+
const signedBuys = await Promise.all(unsignedBuys.map((unsigned, i) => buyers[i].signTransaction({
|
|
361
388
|
...unsigned,
|
|
362
389
|
from: buyers[i].address,
|
|
363
390
|
nonce: nonces[i],
|
|
@@ -367,7 +394,8 @@ export async function fourPancakeProxyBatchBuyMerkle(params) {
|
|
|
367
394
|
type: txType,
|
|
368
395
|
value: unsigned.value // ✅ 显式保留 value(BNB 金额 + 手续费)
|
|
369
396
|
})));
|
|
370
|
-
|
|
397
|
+
signedTxs.push(...signedBuys);
|
|
398
|
+
// ✅ 添加利润转账(放在末尾,使用预先获取的 nonce)
|
|
371
399
|
if (extractProfit && totalProfit > 0n && profitNonce !== undefined) {
|
|
372
400
|
const profitTx = await buyers[0].signTransaction({
|
|
373
401
|
to: getProfitRecipient(),
|
|
@@ -409,6 +437,9 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
|
|
|
409
437
|
const finalGasLimit = getGasLimit(config);
|
|
410
438
|
const nonceManager = new NonceManager(provider);
|
|
411
439
|
const extractProfit = shouldExtractProfit(config);
|
|
440
|
+
// ✅ 获取贿赂金额
|
|
441
|
+
const bribeAmount = getBribeAmount(config);
|
|
442
|
+
const needBribeTx = bribeAmount > 0n;
|
|
412
443
|
// ✅ 优化:并行获取 gasPrice、tokenDecimals 和 allowances
|
|
413
444
|
const [gasPrice, tokenDecimals, allowances] = await Promise.all([
|
|
414
445
|
getOptimizedGasPrice(provider, getGasPriceConfig(config)),
|
|
@@ -429,48 +460,40 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
|
|
|
429
460
|
if (needApprovalIndexes.length > 0) {
|
|
430
461
|
throw new Error(`需要授权: ${needApprovalIndexes.length} 个钱包尚未授权。请先完成授权后再卖出。`);
|
|
431
462
|
}
|
|
432
|
-
// ✅
|
|
433
|
-
let minOuts;
|
|
463
|
+
// ✅ 获取报价(用于计算利润),已移除滑点保护
|
|
434
464
|
let quotedOutputs;
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
465
|
+
// ✅ 使用 Multicall3 批量获取报价(仅 V2 路由支持)
|
|
466
|
+
if (routeType === 'v2' && params.v2Path && params.v2Path.length >= 2) {
|
|
467
|
+
quotedOutputs = await batchGetV2Quotes(provider, amountsWei, params.v2Path);
|
|
468
|
+
}
|
|
469
|
+
else if (routeType === 'v3-single') {
|
|
470
|
+
// V3 单跳:并行调用(V3 Quoter 是 non-view 函数,不支持 Multicall3)
|
|
471
|
+
quotedOutputs = await Promise.all(amountsWei.map(async (amount) => {
|
|
472
|
+
try {
|
|
473
|
+
const quoter = new Contract(PANCAKE_V3_QUOTER_ADDRESS, PANCAKE_V3_QUOTER_ABI, provider);
|
|
474
|
+
const result = await quoter.quoteExactInputSingle.staticCall({
|
|
475
|
+
tokenIn: tokenAddress,
|
|
476
|
+
tokenOut: params.v3TokenOut,
|
|
477
|
+
amountIn: amount,
|
|
478
|
+
fee: params.v3Fee,
|
|
479
|
+
sqrtPriceLimitX96: 0
|
|
480
|
+
});
|
|
481
|
+
return result[0];
|
|
482
|
+
}
|
|
483
|
+
catch {
|
|
484
|
+
return 0n;
|
|
485
|
+
}
|
|
486
|
+
}));
|
|
487
|
+
}
|
|
488
|
+
else if (routeType === 'v3-multi' && params.v2Path && params.v2Path.length >= 2) {
|
|
489
|
+
// V3 多跳:使用 V2 备选路由
|
|
490
|
+
quotedOutputs = await batchGetV2Quotes(provider, amountsWei, params.v2Path);
|
|
439
491
|
}
|
|
440
492
|
else {
|
|
441
|
-
|
|
442
|
-
if (routeType === 'v2' && params.v2Path && params.v2Path.length >= 2) {
|
|
443
|
-
quotedOutputs = await batchGetV2Quotes(provider, amountsWei, params.v2Path);
|
|
444
|
-
}
|
|
445
|
-
else if (routeType === 'v3-single') {
|
|
446
|
-
// V3 单跳:并行调用(V3 Quoter 是 non-view 函数,不支持 Multicall3)
|
|
447
|
-
quotedOutputs = await Promise.all(amountsWei.map(async (amount) => {
|
|
448
|
-
try {
|
|
449
|
-
const quoter = new Contract(PANCAKE_V3_QUOTER_ADDRESS, PANCAKE_V3_QUOTER_ABI, provider);
|
|
450
|
-
const result = await quoter.quoteExactInputSingle.staticCall({
|
|
451
|
-
tokenIn: tokenAddress,
|
|
452
|
-
tokenOut: params.v3TokenOut,
|
|
453
|
-
amountIn: amount,
|
|
454
|
-
fee: params.v3Fee,
|
|
455
|
-
sqrtPriceLimitX96: 0
|
|
456
|
-
});
|
|
457
|
-
return result[0];
|
|
458
|
-
}
|
|
459
|
-
catch {
|
|
460
|
-
return 0n;
|
|
461
|
-
}
|
|
462
|
-
}));
|
|
463
|
-
}
|
|
464
|
-
else if (routeType === 'v3-multi' && params.v2Path && params.v2Path.length >= 2) {
|
|
465
|
-
// V3 多跳:使用 V2 备选路由
|
|
466
|
-
quotedOutputs = await batchGetV2Quotes(provider, amountsWei, params.v2Path);
|
|
467
|
-
}
|
|
468
|
-
else {
|
|
469
|
-
quotedOutputs = new Array(amountsWei.length).fill(0n);
|
|
470
|
-
}
|
|
471
|
-
// ✅ minOuts = 0,不设置滑点限制(大额交易更稳定)
|
|
472
|
-
minOuts = quotedOutputs.map(() => 0n);
|
|
493
|
+
quotedOutputs = new Array(amountsWei.length).fill(0n);
|
|
473
494
|
}
|
|
495
|
+
// ✅ 已移除滑点保护:minOuts 固定为 0
|
|
496
|
+
const minOuts = new Array(sellers.length).fill(0n);
|
|
474
497
|
// ✅ 计算利润并找出收益最多的钱包
|
|
475
498
|
let totalProfit = 0n;
|
|
476
499
|
let maxRevenueIndex = 0;
|
|
@@ -489,32 +512,43 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
|
|
|
489
512
|
}
|
|
490
513
|
// ✅ 修复:先计算需要的 nonce 数量,再统一获取
|
|
491
514
|
const needProfitTx = extractProfit && totalProfit > 0n && maxRevenue > 0n;
|
|
492
|
-
// 分配 nonces:收益最多的钱包可能需要
|
|
515
|
+
// 分配 nonces:收益最多的钱包可能需要 3 个 nonce(贿赂 + 卖出 + 利润转账)
|
|
493
516
|
let nonces;
|
|
517
|
+
let bribeNonce;
|
|
494
518
|
let profitNonce;
|
|
495
|
-
if (needProfitTx) {
|
|
496
|
-
//
|
|
497
|
-
|
|
519
|
+
if (needBribeTx || needProfitTx) {
|
|
520
|
+
// 计算收益最多的钱包需要的 nonce 数量
|
|
521
|
+
let maxRevenueNonceCount = 1; // 卖出交易
|
|
522
|
+
if (needBribeTx)
|
|
523
|
+
maxRevenueNonceCount++; // 贿赂交易
|
|
524
|
+
if (needProfitTx)
|
|
525
|
+
maxRevenueNonceCount++; // 利润交易
|
|
526
|
+
// 收益最多的钱包需要连续 nonce
|
|
527
|
+
const maxRevenueNonces = await nonceManager.getNextNonceBatch(sellers[maxRevenueIndex], maxRevenueNonceCount);
|
|
498
528
|
// 其他钱包各需要 1 个 nonce
|
|
499
529
|
const otherSellers = sellers.filter((_, i) => i !== maxRevenueIndex);
|
|
500
530
|
const otherNonces = otherSellers.length > 0
|
|
501
531
|
? await nonceManager.getNextNoncesForWallets(otherSellers)
|
|
502
532
|
: [];
|
|
533
|
+
// 分配收益最多钱包的 nonces
|
|
534
|
+
let maxRevenueNonceIdx = 0;
|
|
535
|
+
bribeNonce = needBribeTx ? maxRevenueNonces[maxRevenueNonceIdx++] : undefined;
|
|
536
|
+
const maxRevenueSellNonce = maxRevenueNonces[maxRevenueNonceIdx++];
|
|
537
|
+
profitNonce = needProfitTx ? maxRevenueNonces[maxRevenueNonceIdx] : undefined;
|
|
503
538
|
// 组装最终的 nonces 数组(保持原顺序)
|
|
504
539
|
nonces = [];
|
|
505
540
|
let otherIdx = 0;
|
|
506
541
|
for (let i = 0; i < sellers.length; i++) {
|
|
507
542
|
if (i === maxRevenueIndex) {
|
|
508
|
-
nonces.push(
|
|
543
|
+
nonces.push(maxRevenueSellNonce); // 卖出交易 nonce
|
|
509
544
|
}
|
|
510
545
|
else {
|
|
511
546
|
nonces.push(otherNonces[otherIdx++]);
|
|
512
547
|
}
|
|
513
548
|
}
|
|
514
|
-
profitNonce = maxRevenueNonces[1]; // 利润交易用第二个 nonce
|
|
515
549
|
}
|
|
516
550
|
else {
|
|
517
|
-
//
|
|
551
|
+
// 不需要贿赂和利润交易,所有钱包各 1 个 nonce
|
|
518
552
|
nonces = await nonceManager.getNextNoncesForWallets(sellers);
|
|
519
553
|
}
|
|
520
554
|
// 卖出不需要发送 BNB,只需要 flatFee
|
|
@@ -543,8 +577,22 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
|
|
|
543
577
|
else {
|
|
544
578
|
throw new Error(`Unsupported routeType: ${routeType}`);
|
|
545
579
|
}
|
|
580
|
+
// ✅ 贿赂交易放在首位
|
|
581
|
+
const signedTxs = [];
|
|
582
|
+
if (needBribeTx && bribeNonce !== undefined) {
|
|
583
|
+
const bribeTx = await sellers[maxRevenueIndex].signTransaction({
|
|
584
|
+
to: BLOCKRAZOR_BUILDER_EOA,
|
|
585
|
+
value: bribeAmount,
|
|
586
|
+
nonce: bribeNonce,
|
|
587
|
+
gasPrice,
|
|
588
|
+
gasLimit: 21000n,
|
|
589
|
+
chainId: 56,
|
|
590
|
+
type: txType
|
|
591
|
+
});
|
|
592
|
+
signedTxs.push(bribeTx);
|
|
593
|
+
}
|
|
546
594
|
// ✅ 并行签名所有卖出交易
|
|
547
|
-
const
|
|
595
|
+
const signedSells = await Promise.all(unsignedSells.map((unsigned, i) => sellers[i].signTransaction({
|
|
548
596
|
...unsigned,
|
|
549
597
|
from: sellers[i].address,
|
|
550
598
|
nonce: nonces[i],
|
|
@@ -554,7 +602,8 @@ export async function fourPancakeProxyBatchSellMerkle(params) {
|
|
|
554
602
|
type: txType,
|
|
555
603
|
value: unsigned.value // ✅ 显式保留 value(手续费)
|
|
556
604
|
})));
|
|
557
|
-
|
|
605
|
+
signedTxs.push(...signedSells);
|
|
606
|
+
// ✅ 添加利润转账(放在末尾,使用预先获取的 nonce)
|
|
558
607
|
if (extractProfit && totalProfit > 0n && profitNonce !== undefined) {
|
|
559
608
|
const profitTx = await sellers[maxRevenueIndex].signTransaction({
|
|
560
609
|
to: getProfitRecipient(),
|
|
@@ -7,7 +7,6 @@ import { CommonBundleConfig } from '../../utils/bundle-helpers.js';
|
|
|
7
7
|
import { FourSignConfig } from './types.js';
|
|
8
8
|
export interface FourBuyFirstSignConfig extends FourSignConfig {
|
|
9
9
|
reserveGasBNB?: number;
|
|
10
|
-
slippageBps?: number;
|
|
11
10
|
}
|
|
12
11
|
export interface FourBuyFirstConfig extends CommonBundleConfig {
|
|
13
12
|
apiKey: string;
|
|
@@ -7,8 +7,10 @@ import { ethers, Contract, Wallet } from 'ethers';
|
|
|
7
7
|
import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
|
|
8
8
|
import { ADDRESSES } from '../../utils/constants.js';
|
|
9
9
|
import { TM_ABI, HELPER3_ABI, TM_ADDRESS } from './swap-internal.js';
|
|
10
|
-
import { getTxType, getGasPriceConfig, getProfitRecipient, getProfitRateBps } from './config.js';
|
|
10
|
+
import { getTxType, getGasPriceConfig, getProfitRecipient, getProfitRateBps, getBribeAmount } from './config.js';
|
|
11
11
|
import { trySell } from '../tm.js';
|
|
12
|
+
// ✅ BlockRazor Builder EOA 地址(用于贿赂)
|
|
13
|
+
const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
|
|
12
14
|
/**
|
|
13
15
|
* 获取 Gas Limit(支持 FourAnyConfig)
|
|
14
16
|
*/
|
|
@@ -82,14 +84,19 @@ export async function fourBundleBuyFirstMerkle(params) {
|
|
|
82
84
|
// ✅ 优化:第三批并行 - trySell、构建交易、获取 nonces
|
|
83
85
|
const tmBuyer = new Contract(TM_ADDRESS, TM_ABI, buyer);
|
|
84
86
|
const tmSeller = new Contract(TM_ADDRESS, TM_ABI, seller);
|
|
85
|
-
|
|
86
|
-
const minBuyAmount =
|
|
87
|
+
// ✅ 已移除滑点保护:minBuyAmount 固定为 0
|
|
88
|
+
const minBuyAmount = 0n;
|
|
87
89
|
// 预先规划 nonces
|
|
88
90
|
const extractProfit = true;
|
|
89
91
|
const profitRateBps = getProfitRateBps();
|
|
92
|
+
// ✅ 获取贿赂金额
|
|
93
|
+
const bribeAmount = getBribeAmount(config);
|
|
94
|
+
const needBribeTx = bribeAmount > 0n;
|
|
90
95
|
// 计算需要的 nonce 数量
|
|
91
96
|
let buyerNonceCount = 1; // 买入交易
|
|
92
97
|
let sellerNonceCount = 1; // 卖出交易
|
|
98
|
+
if (needBribeTx)
|
|
99
|
+
sellerNonceCount++; // 贿赂交易(由卖方发送)
|
|
93
100
|
if (needApproval)
|
|
94
101
|
sellerNonceCount++; // 授权交易
|
|
95
102
|
if (extractProfit)
|
|
@@ -121,7 +128,8 @@ export async function fourBundleBuyFirstMerkle(params) {
|
|
|
121
128
|
]);
|
|
122
129
|
const { buyerNonces, sellerNonces } = noncesResult;
|
|
123
130
|
const estimatedSellFunds = sellResult.funds;
|
|
124
|
-
|
|
131
|
+
// ✅ 已移除滑点保护:minSellFunds 固定为 0
|
|
132
|
+
const minSellFunds = 0n;
|
|
125
133
|
const profitAmount = extractProfit ? (estimatedSellFunds * BigInt(profitRateBps)) / 10000n : 0n;
|
|
126
134
|
// 更新卖出交易的 minSellFunds
|
|
127
135
|
sellUnsigned.data = tmSeller.interface.encodeFunctionData('sellToken', [
|
|
@@ -130,10 +138,13 @@ export async function fourBundleBuyFirstMerkle(params) {
|
|
|
130
138
|
// 分配 nonces
|
|
131
139
|
let buyerNonce;
|
|
132
140
|
let sellerNonce;
|
|
141
|
+
let bribeNonce;
|
|
133
142
|
let approvalNonce;
|
|
134
143
|
let profitNonce;
|
|
135
144
|
if (sameAddress) {
|
|
136
145
|
let idx = 0;
|
|
146
|
+
if (needBribeTx)
|
|
147
|
+
bribeNonce = sellerNonces[idx++];
|
|
137
148
|
if (needApproval)
|
|
138
149
|
approvalNonce = sellerNonces[idx++];
|
|
139
150
|
buyerNonce = sellerNonces[idx++];
|
|
@@ -144,6 +155,8 @@ export async function fourBundleBuyFirstMerkle(params) {
|
|
|
144
155
|
else {
|
|
145
156
|
buyerNonce = buyerNonces[0];
|
|
146
157
|
let idx = 0;
|
|
158
|
+
if (needBribeTx)
|
|
159
|
+
bribeNonce = sellerNonces[idx++];
|
|
147
160
|
if (needApproval)
|
|
148
161
|
approvalNonce = sellerNonces[idx++];
|
|
149
162
|
sellerNonce = sellerNonces[idx++];
|
|
@@ -152,6 +165,19 @@ export async function fourBundleBuyFirstMerkle(params) {
|
|
|
152
165
|
}
|
|
153
166
|
// ✅ 并行签名所有交易
|
|
154
167
|
const signPromises = [];
|
|
168
|
+
// ✅ 贿赂交易放在首位
|
|
169
|
+
let bribeTx = null;
|
|
170
|
+
if (needBribeTx && bribeNonce !== undefined) {
|
|
171
|
+
signPromises.push(seller.signTransaction({
|
|
172
|
+
to: BLOCKRAZOR_BUILDER_EOA,
|
|
173
|
+
value: bribeAmount,
|
|
174
|
+
nonce: bribeNonce,
|
|
175
|
+
gasPrice,
|
|
176
|
+
gasLimit: 21000n,
|
|
177
|
+
chainId: chainIdNum,
|
|
178
|
+
type: txType
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
155
181
|
// 授权交易
|
|
156
182
|
let approvalTx = null;
|
|
157
183
|
if (needApproval && approvalNonce !== undefined) {
|
|
@@ -190,7 +216,7 @@ export async function fourBundleBuyFirstMerkle(params) {
|
|
|
190
216
|
type: txType,
|
|
191
217
|
value: 0n // ✅ 卖出交易不发送原生代币
|
|
192
218
|
}));
|
|
193
|
-
//
|
|
219
|
+
// ✅ 利润交易放在末尾
|
|
194
220
|
let profitTx = null;
|
|
195
221
|
if (extractProfit && profitAmount > 0n && profitNonce !== undefined) {
|
|
196
222
|
signPromises.push(seller.signTransaction({
|
|
@@ -206,6 +232,8 @@ export async function fourBundleBuyFirstMerkle(params) {
|
|
|
206
232
|
const signedTxs = await Promise.all(signPromises);
|
|
207
233
|
// 解析签名结果
|
|
208
234
|
let idx = 0;
|
|
235
|
+
if (needBribeTx)
|
|
236
|
+
bribeTx = signedTxs[idx++];
|
|
209
237
|
if (needApproval)
|
|
210
238
|
approvalTx = signedTxs[idx++];
|
|
211
239
|
const signedBuy = signedTxs[idx++];
|
|
@@ -213,8 +241,10 @@ export async function fourBundleBuyFirstMerkle(params) {
|
|
|
213
241
|
if (extractProfit && profitAmount > 0n)
|
|
214
242
|
profitTx = signedTxs[idx];
|
|
215
243
|
nonceManager.clearTemp();
|
|
216
|
-
//
|
|
244
|
+
// ✅ 组装交易列表:贿赂 → 授权 → 买入 → 卖出 → 利润
|
|
217
245
|
const allTransactions = [];
|
|
246
|
+
if (bribeTx)
|
|
247
|
+
allTransactions.push(bribeTx);
|
|
218
248
|
if (approvalTx)
|
|
219
249
|
allTransactions.push(approvalTx);
|
|
220
250
|
allTransactions.push(signedBuy, signedSell);
|