four-flap-meme-sdk 1.3.99 → 1.4.2
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/contracts/tm-bundle-merkle/core.js +4 -23
- package/dist/contracts/tm-bundle-merkle/pancake-proxy.js +50 -60
- package/dist/contracts/tm-bundle-merkle/private.js +151 -96
- package/dist/dex/direct-router.d.ts +4 -0
- package/dist/dex/direct-router.js +23 -19
- package/dist/flap/portal-bundle-merkle/pancake-proxy.js +58 -71
- package/dist/flap/portal-bundle-merkle/private.js +185 -72
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import { ethers, Wallet } from 'ethers';
|
|
|
2
2
|
import { MerkleClient } from '../../clients/merkle.js';
|
|
3
3
|
import { getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
|
|
4
4
|
import { FLAP_PORTAL_ADDRESSES } from '../constants.js';
|
|
5
|
-
import { CHAIN_ID_MAP, PORTAL_ABI, getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, calculateBatchProfit, getProfitRecipient } from './config.js';
|
|
5
|
+
import { CHAIN_ID_MAP, PORTAL_ABI, getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, calculateBatchProfit, getProfitRecipient, getBribeAmount, BLOCKRAZOR_BUILDER_EOA } from './config.js';
|
|
6
6
|
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
7
7
|
const DEFAULT_GAS_LIMIT = 800000;
|
|
8
8
|
/**
|
|
@@ -32,27 +32,55 @@ export async function flapPrivateBuyMerkle(params) {
|
|
|
32
32
|
}, { value: actualAmountWei })
|
|
33
33
|
]);
|
|
34
34
|
const gasLimit = resolveGasLimit(config.gasLimitMultiplier);
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
// ✅ 获取贿赂金额
|
|
36
|
+
const bribeAmount = getBribeAmount(config);
|
|
37
|
+
const needBribeTx = bribeAmount > 0n;
|
|
38
|
+
const needProfitTx = extractProfit && profitWei > 0n;
|
|
39
|
+
// ✅ 分配 nonces:贿赂 → 买入 → 利润
|
|
40
|
+
let nonceIdx = 0;
|
|
41
|
+
const bribeNonce = needBribeTx ? currentNonce + nonceIdx++ : undefined;
|
|
42
|
+
const buyNonce = currentNonce + nonceIdx++;
|
|
43
|
+
const profitNonce = needProfitTx ? currentNonce + nonceIdx : undefined;
|
|
44
|
+
// ✅ 并行签名所有交易(贿赂、买入、利润)
|
|
45
|
+
const signPromises = [];
|
|
46
|
+
const txType = getTxType(config);
|
|
47
|
+
// 贿赂交易
|
|
48
|
+
if (needBribeTx && bribeNonce !== undefined) {
|
|
49
|
+
signPromises.push(wallet.signTransaction({
|
|
50
|
+
to: BLOCKRAZOR_BUILDER_EOA,
|
|
51
|
+
value: bribeAmount,
|
|
52
|
+
nonce: bribeNonce,
|
|
53
|
+
gasPrice,
|
|
54
|
+
gasLimit: 21000n,
|
|
55
|
+
chainId,
|
|
56
|
+
type: txType
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
// 买入交易
|
|
60
|
+
signPromises.push(wallet.signTransaction({
|
|
37
61
|
...unsigned,
|
|
38
62
|
from: wallet.address,
|
|
39
|
-
nonce:
|
|
63
|
+
nonce: buyNonce,
|
|
40
64
|
gasLimit,
|
|
41
65
|
gasPrice,
|
|
42
66
|
chainId,
|
|
43
|
-
type:
|
|
67
|
+
type: txType,
|
|
44
68
|
value: actualAmountWei
|
|
45
69
|
}));
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
70
|
+
// 利润交易
|
|
71
|
+
if (needProfitTx && profitNonce !== undefined) {
|
|
72
|
+
signPromises.push(wallet.signTransaction({
|
|
73
|
+
to: getProfitRecipient(),
|
|
74
|
+
value: profitWei,
|
|
75
|
+
nonce: profitNonce,
|
|
76
|
+
gasPrice,
|
|
77
|
+
gasLimit: 21000n,
|
|
78
|
+
chainId,
|
|
79
|
+
type: txType
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
// ✅ 并行签名完成后按顺序返回
|
|
83
|
+
const signedTxs = await Promise.all(signPromises);
|
|
56
84
|
return { signedTransactions: signedTxs };
|
|
57
85
|
}
|
|
58
86
|
/**
|
|
@@ -65,41 +93,73 @@ export async function flapPrivateSellMerkle(params) {
|
|
|
65
93
|
const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
|
|
66
94
|
const amountWei = ethers.parseUnits(amount, 18);
|
|
67
95
|
const portal = new ethers.Contract(portalAddr, PORTAL_ABI, wallet);
|
|
68
|
-
// ✅ 并行获取 gasPrice、nonce
|
|
69
|
-
const [gasPrice, currentNonce, { quotedOutput,
|
|
96
|
+
// ✅ 并行获取 gasPrice、nonce、报价和构建未签名交易
|
|
97
|
+
const [gasPrice, currentNonce, { quotedOutput }, unsigned] = await Promise.all([
|
|
70
98
|
getOptimizedGasPrice(provider, getGasPriceConfig(config)),
|
|
71
99
|
wallet.getNonce(),
|
|
72
|
-
resolveSingleSellOutputs(portal, tokenAddress, amountWei, minOutputAmount)
|
|
100
|
+
resolveSingleSellOutputs(portal, tokenAddress, amountWei, minOutputAmount),
|
|
101
|
+
portal.swapExactInput.populateTransaction({
|
|
102
|
+
inputToken: tokenAddress,
|
|
103
|
+
outputToken: ZERO_ADDRESS,
|
|
104
|
+
inputAmount: amountWei,
|
|
105
|
+
minOutputAmount: 0n, // ✅ 已移除滑点保护
|
|
106
|
+
permitData: '0x',
|
|
107
|
+
})
|
|
73
108
|
]);
|
|
74
|
-
// 构建未签名交易
|
|
75
|
-
const unsigned = await portal.swapExactInput.populateTransaction({
|
|
76
|
-
inputToken: tokenAddress,
|
|
77
|
-
outputToken: ZERO_ADDRESS,
|
|
78
|
-
inputAmount: amountWei,
|
|
79
|
-
minOutputAmount: minOut,
|
|
80
|
-
permitData: '0x',
|
|
81
|
-
});
|
|
82
109
|
const gasLimit = resolveGasLimit(config.gasLimitMultiplier);
|
|
83
|
-
const
|
|
84
|
-
|
|
110
|
+
const txType = getTxType(config);
|
|
111
|
+
// ✅ 获取贿赂金额
|
|
112
|
+
const bribeAmount = getBribeAmount(config);
|
|
113
|
+
const needBribeTx = bribeAmount > 0n;
|
|
114
|
+
// ✅ 利润计算
|
|
115
|
+
const extractProfit = shouldExtractProfit(config);
|
|
116
|
+
const { profit: profitWei } = extractProfit && quotedOutput > 0n
|
|
117
|
+
? calculateProfit(quotedOutput, config)
|
|
118
|
+
: { profit: 0n };
|
|
119
|
+
const needProfitTx = extractProfit && profitWei > 0n;
|
|
120
|
+
// ✅ 分配 nonces:贿赂 → 卖出 → 利润
|
|
121
|
+
let nonceIdx = 0;
|
|
122
|
+
const bribeNonce = needBribeTx ? currentNonce + nonceIdx++ : undefined;
|
|
123
|
+
const sellNonce = currentNonce + nonceIdx++;
|
|
124
|
+
const profitNonce = needProfitTx ? currentNonce + nonceIdx : undefined;
|
|
125
|
+
// ✅ 并行签名所有交易(贿赂、卖出、利润)
|
|
126
|
+
const signPromises = [];
|
|
127
|
+
// 贿赂交易
|
|
128
|
+
if (needBribeTx && bribeNonce !== undefined) {
|
|
129
|
+
signPromises.push(wallet.signTransaction({
|
|
130
|
+
to: BLOCKRAZOR_BUILDER_EOA,
|
|
131
|
+
value: bribeAmount,
|
|
132
|
+
nonce: bribeNonce,
|
|
133
|
+
gasPrice,
|
|
134
|
+
gasLimit: 21000n,
|
|
135
|
+
chainId,
|
|
136
|
+
type: txType
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
// 卖出交易
|
|
140
|
+
signPromises.push(wallet.signTransaction({
|
|
85
141
|
...unsigned,
|
|
86
142
|
from: wallet.address,
|
|
87
|
-
nonce:
|
|
143
|
+
nonce: sellNonce,
|
|
88
144
|
gasLimit,
|
|
89
145
|
gasPrice,
|
|
90
146
|
chainId,
|
|
91
|
-
type:
|
|
147
|
+
type: txType
|
|
92
148
|
}));
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
149
|
+
// 利润交易
|
|
150
|
+
if (needProfitTx && profitNonce !== undefined) {
|
|
151
|
+
signPromises.push(wallet.signTransaction({
|
|
152
|
+
to: getProfitRecipient(),
|
|
153
|
+
value: profitWei,
|
|
154
|
+
nonce: profitNonce,
|
|
155
|
+
gasPrice,
|
|
156
|
+
gasLimit: 21000n,
|
|
157
|
+
chainId,
|
|
158
|
+
type: txType
|
|
159
|
+
}));
|
|
160
|
+
}
|
|
161
|
+
// ✅ 并行签名完成后按顺序返回
|
|
162
|
+
const signedTxs = await Promise.all(signPromises);
|
|
103
163
|
return { signedTransactions: signedTxs };
|
|
104
164
|
}
|
|
105
165
|
/**
|
|
@@ -121,6 +181,10 @@ export async function flapBatchPrivateBuyMerkle(params) {
|
|
|
121
181
|
const maxFundsIndex = findMaxIndex(originalAmountsWei);
|
|
122
182
|
const minOuts = resolveBatchMinOutputs(minOutputAmounts, wallets.length);
|
|
123
183
|
const portals = wallets.map(w => new ethers.Contract(portalAddr, PORTAL_ABI, w));
|
|
184
|
+
// ✅ 获取贿赂金额
|
|
185
|
+
const bribeAmount = getBribeAmount(config);
|
|
186
|
+
const needBribeTx = bribeAmount > 0n;
|
|
187
|
+
const needProfitTx = extractProfit && totalProfit > 0n;
|
|
124
188
|
// ✅ 并行获取 gasPrice、所有 nonces 和构建未签名交易
|
|
125
189
|
const [gasPrice, initialNonces, unsignedList] = await Promise.all([
|
|
126
190
|
getOptimizedGasPrice(provider, getGasPriceConfig(config)),
|
|
@@ -133,14 +197,39 @@ export async function flapBatchPrivateBuyMerkle(params) {
|
|
|
133
197
|
permitData: '0x',
|
|
134
198
|
}, { value: actualAmountsWei[i] })))
|
|
135
199
|
]);
|
|
136
|
-
// ✅
|
|
200
|
+
// ✅ 分配 nonces:贿赂(可选) → 买入 → 利润(可选)
|
|
201
|
+
let payerNonceOffset = 0;
|
|
202
|
+
let bribeNonce;
|
|
203
|
+
if (needBribeTx && maxFundsIndex >= 0) {
|
|
204
|
+
bribeNonce = initialNonces[maxFundsIndex];
|
|
205
|
+
payerNonceOffset++;
|
|
206
|
+
}
|
|
137
207
|
const nonces = initialNonces.map((n, i) => {
|
|
138
|
-
|
|
208
|
+
if (i === maxFundsIndex) {
|
|
209
|
+
return n + payerNonceOffset; // payer 的买入 nonce 需要偏移
|
|
210
|
+
}
|
|
139
211
|
return n;
|
|
140
212
|
});
|
|
213
|
+
const profitNonce = needProfitTx && maxFundsIndex >= 0
|
|
214
|
+
? initialNonces[maxFundsIndex] + payerNonceOffset + 1
|
|
215
|
+
: undefined;
|
|
141
216
|
const gasLimit = resolveGasLimit(config.gasLimitMultiplier);
|
|
142
217
|
const gasLimits = new Array(wallets.length).fill(gasLimit);
|
|
143
|
-
|
|
218
|
+
const signedTxs = [];
|
|
219
|
+
// ✅ 贿赂交易放在首位
|
|
220
|
+
if (needBribeTx && bribeNonce !== undefined && maxFundsIndex >= 0) {
|
|
221
|
+
const bribeTx = await wallets[maxFundsIndex].signTransaction({
|
|
222
|
+
to: BLOCKRAZOR_BUILDER_EOA,
|
|
223
|
+
value: bribeAmount,
|
|
224
|
+
nonce: bribeNonce,
|
|
225
|
+
gasPrice,
|
|
226
|
+
gasLimit: 21000n,
|
|
227
|
+
chainId,
|
|
228
|
+
type: getTxType(config)
|
|
229
|
+
});
|
|
230
|
+
signedTxs.push(bribeTx);
|
|
231
|
+
}
|
|
232
|
+
// ✅ 并行签名所有买入交易
|
|
144
233
|
const signedList = await signBatchTransactions({
|
|
145
234
|
unsignedList,
|
|
146
235
|
wallets,
|
|
@@ -151,10 +240,9 @@ export async function flapBatchPrivateBuyMerkle(params) {
|
|
|
151
240
|
config,
|
|
152
241
|
values: actualAmountsWei
|
|
153
242
|
});
|
|
154
|
-
|
|
155
|
-
//
|
|
156
|
-
if (
|
|
157
|
-
const profitNonce = initialNonces[maxFundsIndex] + 1;
|
|
243
|
+
signedTxs.push(...signedList);
|
|
244
|
+
// ✅ 利润交易放在末尾
|
|
245
|
+
if (needProfitTx && profitNonce !== undefined && maxFundsIndex >= 0) {
|
|
158
246
|
const profitTx = await wallets[maxFundsIndex].signTransaction({
|
|
159
247
|
to: getProfitRecipient(),
|
|
160
248
|
value: totalProfit,
|
|
@@ -182,50 +270,75 @@ export async function flapBatchPrivateSellMerkle(params) {
|
|
|
182
270
|
const amountsWei = amounts.map(a => ethers.parseUnits(a, 18));
|
|
183
271
|
const portal = new ethers.Contract(portalAddr, PORTAL_ABI, provider);
|
|
184
272
|
const portals = wallets.map(w => new ethers.Contract(portalAddr, PORTAL_ABI, w));
|
|
185
|
-
// ✅ 并行获取 gasPrice、所有 nonces
|
|
186
|
-
const [gasPrice, initialNonces, quotedOutputs] = await Promise.all([
|
|
273
|
+
// ✅ 并行获取 gasPrice、所有 nonces、所有报价和构建未签名交易
|
|
274
|
+
const [gasPrice, initialNonces, quotedOutputs, unsignedList] = await Promise.all([
|
|
187
275
|
getOptimizedGasPrice(provider, getGasPriceConfig(config)),
|
|
188
276
|
Promise.all(wallets.map(w => w.getNonce())),
|
|
189
277
|
Promise.all(amountsWei.map(amount => portal.quoteExactInput.staticCall({
|
|
190
278
|
inputToken: tokenAddress,
|
|
191
279
|
outputToken: ZERO_ADDRESS,
|
|
192
280
|
inputAmount: amount
|
|
193
|
-
}).catch(() => 0n)))
|
|
281
|
+
}).catch(() => 0n))),
|
|
282
|
+
// ✅ 并行构建未签名交易(已移除滑点保护:minOuts 固定为 0)
|
|
283
|
+
Promise.all(portals.map((p, i) => p.swapExactInput.populateTransaction({
|
|
284
|
+
inputToken: tokenAddress,
|
|
285
|
+
outputToken: ZERO_ADDRESS,
|
|
286
|
+
inputAmount: amountsWei[i],
|
|
287
|
+
minOutputAmount: 0n,
|
|
288
|
+
permitData: '0x'
|
|
289
|
+
})))
|
|
194
290
|
]);
|
|
195
|
-
// 计算 minOuts
|
|
196
|
-
let minOuts;
|
|
197
|
-
if (minOutputAmounts && minOutputAmounts.length === wallets.length) {
|
|
198
|
-
minOuts = minOutputAmounts.map(m => typeof m === 'string' ? ethers.parseEther(m) : m);
|
|
199
|
-
}
|
|
200
|
-
else {
|
|
201
|
-
minOuts = quotedOutputs.map(quoted => quoted * 95n / 100n);
|
|
202
|
-
}
|
|
203
|
-
// ✅ 并行构建未签名交易
|
|
204
|
-
const unsignedList = await Promise.all(portals.map((p, i) => p.swapExactInput.populateTransaction({
|
|
205
|
-
inputToken: tokenAddress,
|
|
206
|
-
outputToken: ZERO_ADDRESS,
|
|
207
|
-
inputAmount: amountsWei[i],
|
|
208
|
-
minOutputAmount: minOuts[i],
|
|
209
|
-
permitData: '0x'
|
|
210
|
-
})));
|
|
211
291
|
const extractProfit = shouldExtractProfit(config);
|
|
212
292
|
const { totalProfit, maxRevenueIndex } = summarizeSellProfits(quotedOutputs, extractProfit, config);
|
|
293
|
+
// ✅ 获取贿赂金额
|
|
294
|
+
const bribeAmount = getBribeAmount(config);
|
|
295
|
+
const needBribeTx = bribeAmount > 0n;
|
|
296
|
+
const needProfitTx = extractProfit && totalProfit > 0n;
|
|
297
|
+
// ✅ 分配 nonces:贿赂(可选) → 卖出 → 利润(可选)
|
|
298
|
+
let payerNonceOffset = 0;
|
|
299
|
+
let bribeNonce;
|
|
300
|
+
if (needBribeTx && maxRevenueIndex >= 0) {
|
|
301
|
+
bribeNonce = initialNonces[maxRevenueIndex];
|
|
302
|
+
payerNonceOffset++;
|
|
303
|
+
}
|
|
304
|
+
const nonces = initialNonces.map((n, i) => {
|
|
305
|
+
if (i === maxRevenueIndex) {
|
|
306
|
+
return n + payerNonceOffset; // payer 的卖出 nonce 需要偏移
|
|
307
|
+
}
|
|
308
|
+
return n;
|
|
309
|
+
});
|
|
310
|
+
const profitNonce = needProfitTx && maxRevenueIndex >= 0
|
|
311
|
+
? initialNonces[maxRevenueIndex] + payerNonceOffset + 1
|
|
312
|
+
: undefined;
|
|
213
313
|
const gasLimit = resolveGasLimit(config.gasLimitMultiplier);
|
|
214
314
|
const gasLimits = new Array(wallets.length).fill(gasLimit);
|
|
315
|
+
const signedTxs = [];
|
|
316
|
+
// ✅ 贿赂交易放在首位
|
|
317
|
+
if (needBribeTx && bribeNonce !== undefined && maxRevenueIndex >= 0) {
|
|
318
|
+
const bribeTx = await wallets[maxRevenueIndex].signTransaction({
|
|
319
|
+
to: BLOCKRAZOR_BUILDER_EOA,
|
|
320
|
+
value: bribeAmount,
|
|
321
|
+
nonce: bribeNonce,
|
|
322
|
+
gasPrice,
|
|
323
|
+
gasLimit: 21000n,
|
|
324
|
+
chainId,
|
|
325
|
+
type: getTxType(config)
|
|
326
|
+
});
|
|
327
|
+
signedTxs.push(bribeTx);
|
|
328
|
+
}
|
|
215
329
|
// ✅ 并行签名所有卖出交易
|
|
216
330
|
const signedList = await signBatchTransactions({
|
|
217
331
|
unsignedList,
|
|
218
332
|
wallets,
|
|
219
|
-
nonces
|
|
333
|
+
nonces,
|
|
220
334
|
gasLimits,
|
|
221
335
|
gasPrice,
|
|
222
336
|
chainId,
|
|
223
337
|
config
|
|
224
338
|
});
|
|
225
|
-
|
|
226
|
-
//
|
|
227
|
-
if (
|
|
228
|
-
const profitNonce = initialNonces[maxRevenueIndex] + 1;
|
|
339
|
+
signedTxs.push(...signedList);
|
|
340
|
+
// ✅ 利润交易放在末尾
|
|
341
|
+
if (needProfitTx && profitNonce !== undefined && maxRevenueIndex >= 0) {
|
|
229
342
|
const profitTx = await wallets[maxRevenueIndex].signTransaction({
|
|
230
343
|
to: getProfitRecipient(),
|
|
231
344
|
value: totalProfit,
|
|
@@ -315,7 +428,7 @@ async function resolveSingleSellOutputs(portal, tokenAddress, amountWei, minOutp
|
|
|
315
428
|
});
|
|
316
429
|
return {
|
|
317
430
|
quotedOutput,
|
|
318
|
-
minOut:
|
|
431
|
+
minOut: 0n // ✅ 已移除滑点保护:minOut 固定为 0
|
|
319
432
|
};
|
|
320
433
|
}
|
|
321
434
|
catch {
|