four-flap-meme-sdk 1.3.81 → 1.3.82
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.js +224 -113
- package/dist/flap/portal-bundle-merkle/private.js +87 -107
- package/dist/utils/airdrop-sweep.js +86 -76
- package/dist/utils/erc20.d.ts +1 -0
- package/dist/utils/erc20.js +22 -20
- package/dist/utils/lp-inspect.js +77 -65
- package/dist/utils/stealth-transfer.js +34 -37
- package/dist/utils/swap-helpers.js +8 -4
- package/package.json +1 -1
|
@@ -231,43 +231,54 @@ export async function createTokenWithBundleBuy(params) {
|
|
|
231
231
|
// 4.2 购买交易
|
|
232
232
|
const buyTxs = [];
|
|
233
233
|
const profitTxs = [];
|
|
234
|
-
const buyAmountsWei =
|
|
234
|
+
const buyAmountsWei = buyAmounts.map(a => ethers.parseEther(a));
|
|
235
235
|
// 🔍 找出买入金额最多的买家(由他支付所有利润)
|
|
236
236
|
let maxBuyerIndex = 0;
|
|
237
|
-
let maxAmount =
|
|
238
|
-
for (let i = 1; i <
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
maxAmount = amount;
|
|
237
|
+
let maxAmount = buyAmountsWei[0];
|
|
238
|
+
for (let i = 1; i < buyAmountsWei.length; i++) {
|
|
239
|
+
if (buyAmountsWei[i] > maxAmount) {
|
|
240
|
+
maxAmount = buyAmountsWei[i];
|
|
242
241
|
maxBuyerIndex = i;
|
|
243
242
|
}
|
|
244
243
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
244
|
+
// ✅ 并行构建所有购买交易
|
|
245
|
+
const buyerWallets = privateKeys.slice(1).map(pk => new Wallet(pk, provider));
|
|
246
|
+
// 并行获取所有买家的 nonce
|
|
247
|
+
const buyerNonces = await Promise.all(buyerWallets.map(w => getNextNonce(w)));
|
|
248
|
+
// 并行构建未签名交易和估算 gas
|
|
249
|
+
const buyTxDataList = await Promise.all(buyAmountsWei.map(async (fundsWei, i) => {
|
|
250
|
+
const buyerWallet = buyerWallets[i];
|
|
250
251
|
const buyTm2 = new ethers.Contract(tmAddr, TM2Abi, buyerWallet);
|
|
251
|
-
const buyTxUnsigned = await buyTm2.buyTokenAMAP.populateTransaction(0n, tokenAddress, buyerWallet.address, fundsWei,
|
|
252
|
+
const buyTxUnsigned = await buyTm2.buyTokenAMAP.populateTransaction(0n, tokenAddress, buyerWallet.address, fundsWei, 0n, { value: fundsWei });
|
|
252
253
|
// 估算 gas 并添加 20% 安全余量
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
254
|
+
let buyGasLimit;
|
|
255
|
+
try {
|
|
256
|
+
const estimatedBuyGas = await provider.estimateGas({
|
|
257
|
+
...buyTxUnsigned,
|
|
258
|
+
from: buyerWallet.address,
|
|
259
|
+
value: fundsWei
|
|
260
|
+
});
|
|
261
|
+
buyGasLimit = (estimatedBuyGas * 120n) / 100n;
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
buyGasLimit = 600000n; // 兜底值
|
|
265
|
+
}
|
|
266
|
+
return { buyTxUnsigned, buyGasLimit, buyerWallet, fundsWei };
|
|
267
|
+
}));
|
|
268
|
+
// 并行签名所有购买交易
|
|
269
|
+
const signedBuyTxList = await Promise.all(buyTxDataList.map(async (data, i) => {
|
|
259
270
|
const buyTxRequest = {
|
|
260
|
-
...buyTxUnsigned,
|
|
261
|
-
from: buyerWallet.address,
|
|
262
|
-
nonce:
|
|
263
|
-
gasLimit: buyGasLimit,
|
|
271
|
+
...data.buyTxUnsigned,
|
|
272
|
+
from: data.buyerWallet.address,
|
|
273
|
+
nonce: buyerNonces[i],
|
|
274
|
+
gasLimit: data.buyGasLimit,
|
|
264
275
|
gasPrice: gasPrice,
|
|
265
276
|
chainId: 56
|
|
266
277
|
};
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
278
|
+
return data.buyerWallet.signTransaction(buyTxRequest);
|
|
279
|
+
}));
|
|
280
|
+
signedTxs.push(...signedBuyTxList);
|
|
281
|
+
buyTxs.push(...signedBuyTxList);
|
|
271
282
|
// ✅ 聚合利润:由买入最多的人支付总利润
|
|
272
283
|
const totalBuyAmount = buyAmountsWei.reduce((sum, amount) => sum + amount, 0n);
|
|
273
284
|
const totalProfitAmount = (totalBuyAmount * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
|
|
@@ -404,13 +415,36 @@ export async function batchBuyWithBundle(params) {
|
|
|
404
415
|
nextNonceMap.set(key, onchain + 1);
|
|
405
416
|
return onchain;
|
|
406
417
|
};
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
418
|
+
// ✅ 并行处理所有买家
|
|
419
|
+
const wallets = privateKeys.map(pk => new Wallet(pk, provider));
|
|
420
|
+
const fundsWeiList = buyAmounts.map(a => ethers.parseEther(a));
|
|
421
|
+
// 找出买入最多的买家(由他支付所有利润)
|
|
422
|
+
let maxBuyerIndex = 0;
|
|
423
|
+
let maxFunds = fundsWeiList[0];
|
|
424
|
+
for (let i = 1; i < fundsWeiList.length; i++) {
|
|
425
|
+
if (fundsWeiList[i] > maxFunds) {
|
|
426
|
+
maxFunds = fundsWeiList[i];
|
|
427
|
+
maxBuyerIndex = i;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
// 并行获取所有钱包的初始 nonce
|
|
431
|
+
const initialNonces = await Promise.all(wallets.map(w => w.getNonce()));
|
|
432
|
+
// 为每个钱包分配 nonce(普通钱包1个,利润支付者2个)
|
|
433
|
+
const nonceMap = new Map();
|
|
434
|
+
wallets.forEach((w, i) => {
|
|
435
|
+
nonceMap.set(w.address.toLowerCase(), initialNonces[i]);
|
|
436
|
+
});
|
|
437
|
+
const getNextNonceLocal = (w) => {
|
|
438
|
+
const key = w.address.toLowerCase();
|
|
439
|
+
const n = nonceMap.get(key);
|
|
440
|
+
nonceMap.set(key, n + 1);
|
|
441
|
+
return n;
|
|
442
|
+
};
|
|
443
|
+
// 并行构建未签名交易和估算 gas
|
|
444
|
+
const txDataList = await Promise.all(wallets.map(async (buyerWallet, i) => {
|
|
445
|
+
const fundsWei = fundsWeiList[i];
|
|
411
446
|
const tm2 = new ethers.Contract(tmAddr, TM2Abi, buyerWallet);
|
|
412
|
-
const buyTxUnsigned = await tm2.buyTokenAMAP.populateTransaction(0n, tokenAddress, buyerWallet.address, fundsWei,
|
|
413
|
-
// 估算 gas 并添加 20% 安全余量;若预估回滚,使用保守兜底值
|
|
447
|
+
const buyTxUnsigned = await tm2.buyTokenAMAP.populateTransaction(0n, tokenAddress, buyerWallet.address, fundsWei, 0n, { value: fundsWei });
|
|
414
448
|
let gasLimit;
|
|
415
449
|
try {
|
|
416
450
|
const estimatedGas = await provider.estimateGas({
|
|
@@ -421,33 +455,38 @@ export async function batchBuyWithBundle(params) {
|
|
|
421
455
|
gasLimit = (estimatedGas * 120n) / 100n;
|
|
422
456
|
}
|
|
423
457
|
catch {
|
|
424
|
-
// 与 Flap 一致的保守兜底:在 BSC 上对 buyTokenAMAP 采用 600000
|
|
425
458
|
gasLimit = 600000n;
|
|
426
459
|
}
|
|
460
|
+
return { buyTxUnsigned, gasLimit, buyerWallet, fundsWei };
|
|
461
|
+
}));
|
|
462
|
+
// 并行签名所有买入交易
|
|
463
|
+
const signedBuyTxList = await Promise.all(txDataList.map(async (data, i) => {
|
|
427
464
|
const buyTxRequest = {
|
|
428
|
-
...buyTxUnsigned,
|
|
429
|
-
from: buyerWallet.address,
|
|
430
|
-
nonce:
|
|
431
|
-
gasLimit: gasLimit,
|
|
465
|
+
...data.buyTxUnsigned,
|
|
466
|
+
from: data.buyerWallet.address,
|
|
467
|
+
nonce: getNextNonceLocal(data.buyerWallet),
|
|
468
|
+
gasLimit: data.gasLimit,
|
|
432
469
|
gasPrice: gasPrice,
|
|
433
470
|
chainId: 56
|
|
434
471
|
};
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
472
|
+
return data.buyerWallet.signTransaction(buyTxRequest);
|
|
473
|
+
}));
|
|
474
|
+
signedTxs.push(...signedBuyTxList);
|
|
475
|
+
// ✅ 聚合利润:由买入最多的人支付总利润
|
|
476
|
+
const totalFunds = fundsWeiList.reduce((sum, f) => sum + f, 0n);
|
|
477
|
+
const totalProfit = (totalFunds * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
|
|
478
|
+
if (totalProfit > 0n) {
|
|
479
|
+
const payerWallet = wallets[maxBuyerIndex];
|
|
480
|
+
const profitTx = await payerWallet.signTransaction({
|
|
481
|
+
to: PROFIT_CONFIG.RECIPIENT,
|
|
482
|
+
value: totalProfit,
|
|
483
|
+
nonce: getNextNonceLocal(payerWallet),
|
|
484
|
+
gasPrice,
|
|
485
|
+
gasLimit: 21000n,
|
|
486
|
+
chainId: 56,
|
|
487
|
+
type: 0
|
|
488
|
+
});
|
|
489
|
+
signedTxs.push(profitTx);
|
|
451
490
|
}
|
|
452
491
|
// 可选 tipTx(置前)
|
|
453
492
|
if (config.tipAmountWei && config.tipAmountWei > 0n) {
|
|
@@ -505,54 +544,86 @@ export async function batchSellWithBundle(params) {
|
|
|
505
544
|
nextNonceMap.set(key, onchain + 1);
|
|
506
545
|
return onchain;
|
|
507
546
|
};
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
547
|
+
// ✅ 并行处理所有卖家
|
|
548
|
+
const wallets = privateKeys.map(pk => new Wallet(pk, provider));
|
|
549
|
+
const amountsWei = sellAmounts.map(a => ethers.parseUnits(a, 18));
|
|
550
|
+
// 并行预估所有卖出能获得的 BNB
|
|
551
|
+
const estimatedBnbOuts = await Promise.all(amountsWei.map(async (amountWei) => {
|
|
513
552
|
try {
|
|
514
|
-
const
|
|
515
|
-
|
|
553
|
+
const result = await trySell('BSC', config.rpcUrl, tokenAddress, amountWei);
|
|
554
|
+
return result.funds;
|
|
516
555
|
}
|
|
517
556
|
catch {
|
|
518
|
-
|
|
519
|
-
|
|
557
|
+
return 0n;
|
|
558
|
+
}
|
|
559
|
+
}));
|
|
560
|
+
// 找出收益最高的卖家(由他支付所有利润)
|
|
561
|
+
let maxSellerIndex = 0;
|
|
562
|
+
let maxBnbOut = estimatedBnbOuts[0];
|
|
563
|
+
for (let i = 1; i < estimatedBnbOuts.length; i++) {
|
|
564
|
+
if (estimatedBnbOuts[i] > maxBnbOut) {
|
|
565
|
+
maxBnbOut = estimatedBnbOuts[i];
|
|
566
|
+
maxSellerIndex = i;
|
|
520
567
|
}
|
|
521
|
-
|
|
568
|
+
}
|
|
569
|
+
// 并行获取所有钱包的初始 nonce
|
|
570
|
+
const initialNonces = await Promise.all(wallets.map(w => w.getNonce()));
|
|
571
|
+
const nonceMap = new Map();
|
|
572
|
+
wallets.forEach((w, i) => {
|
|
573
|
+
nonceMap.set(w.address.toLowerCase(), initialNonces[i]);
|
|
574
|
+
});
|
|
575
|
+
const getNextNonceLocal = (w) => {
|
|
576
|
+
const key = w.address.toLowerCase();
|
|
577
|
+
const n = nonceMap.get(key);
|
|
578
|
+
nonceMap.set(key, n + 1);
|
|
579
|
+
return n;
|
|
580
|
+
};
|
|
581
|
+
// 并行构建未签名交易和估算 gas
|
|
582
|
+
const txDataList = await Promise.all(wallets.map(async (sellerWallet, i) => {
|
|
583
|
+
const amountWei = amountsWei[i];
|
|
522
584
|
const tm2 = new ethers.Contract(tmAddr, TM2Abi, sellerWallet);
|
|
523
|
-
const sellTxUnsigned = await tm2.sellToken.populateTransaction(0n, tokenAddress, amountWei,
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
585
|
+
const sellTxUnsigned = await tm2.sellToken.populateTransaction(0n, tokenAddress, amountWei, 0n);
|
|
586
|
+
let gasLimit;
|
|
587
|
+
try {
|
|
588
|
+
const estimatedGas = await provider.estimateGas({
|
|
589
|
+
...sellTxUnsigned,
|
|
590
|
+
from: sellerWallet.address
|
|
591
|
+
});
|
|
592
|
+
gasLimit = (estimatedGas * 120n) / 100n;
|
|
593
|
+
}
|
|
594
|
+
catch {
|
|
595
|
+
gasLimit = 600000n;
|
|
596
|
+
}
|
|
597
|
+
return { sellTxUnsigned, gasLimit, sellerWallet };
|
|
598
|
+
}));
|
|
599
|
+
// 并行签名所有卖出交易
|
|
600
|
+
const signedSellTxList = await Promise.all(txDataList.map(async (data, i) => {
|
|
530
601
|
const sellTxRequest = {
|
|
531
|
-
...sellTxUnsigned,
|
|
532
|
-
from: sellerWallet.address,
|
|
533
|
-
nonce:
|
|
534
|
-
gasLimit: gasLimit,
|
|
602
|
+
...data.sellTxUnsigned,
|
|
603
|
+
from: data.sellerWallet.address,
|
|
604
|
+
nonce: getNextNonceLocal(data.sellerWallet),
|
|
605
|
+
gasLimit: data.gasLimit,
|
|
535
606
|
gasPrice: gasPrice,
|
|
536
607
|
chainId: 56
|
|
537
608
|
};
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
609
|
+
return data.sellerWallet.signTransaction(sellTxRequest);
|
|
610
|
+
}));
|
|
611
|
+
signedTxs.push(...signedSellTxList);
|
|
612
|
+
// ✅ 聚合利润:由收益最高的人支付总利润
|
|
613
|
+
const totalBnbOut = estimatedBnbOuts.reduce((sum, b) => sum + b, 0n);
|
|
614
|
+
const totalProfit = (totalBnbOut * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
|
|
615
|
+
if (totalProfit > 0n) {
|
|
616
|
+
const payerWallet = wallets[maxSellerIndex];
|
|
617
|
+
const profitTx = await payerWallet.signTransaction({
|
|
618
|
+
to: PROFIT_CONFIG.RECIPIENT,
|
|
619
|
+
value: totalProfit,
|
|
620
|
+
nonce: getNextNonceLocal(payerWallet),
|
|
621
|
+
gasPrice,
|
|
622
|
+
gasLimit: 21000n,
|
|
623
|
+
chainId: 56,
|
|
624
|
+
type: 0
|
|
625
|
+
});
|
|
626
|
+
signedTxs.push(profitTx);
|
|
556
627
|
}
|
|
557
628
|
// 可选 tipTx(置前)
|
|
558
629
|
if (config.tipAmountWei && config.tipAmountWei > 0n) {
|
|
@@ -627,25 +698,42 @@ export async function fourBatchPrivateBuy(params) {
|
|
|
627
698
|
const provider = new JsonRpcProvider(rpcUrl);
|
|
628
699
|
const club48 = new Club48Client({ endpoint: club48Endpoint, explorerEndpoint: club48ExplorerEndpoint });
|
|
629
700
|
const tmAddr = ADDRESSES.BSC.TokenManagerV2Proxy;
|
|
630
|
-
|
|
631
|
-
const
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
701
|
+
// ✅ 并行处理
|
|
702
|
+
const wallets = privateKeys.map(pk => new Wallet(pk, provider));
|
|
703
|
+
const fundsWeiList = fundsList.map(f => ethers.parseEther(f));
|
|
704
|
+
// 并行获取 gasPrice 和所有 nonce
|
|
705
|
+
const [gasPrice, nonces] = await Promise.all([
|
|
706
|
+
club48.getMinGasPrice(),
|
|
707
|
+
Promise.all(wallets.map(w => w.getNonce()))
|
|
708
|
+
]);
|
|
709
|
+
// 并行构建未签名交易和估算 gas
|
|
710
|
+
const txDataList = await Promise.all(wallets.map(async (w, i) => {
|
|
711
|
+
const fundsWei = fundsWeiList[i];
|
|
635
712
|
const tm2 = new ethers.Contract(tmAddr, TM2Abi, w);
|
|
636
713
|
const unsigned = await tm2.buyTokenAMAP.populateTransaction(0n, tokenAddress, w.address, fundsWei, 0n, { value: fundsWei });
|
|
637
|
-
// 估算 gas 并添加 20% 安全余量;预估失败则使用保守兜底
|
|
638
714
|
let gasLimit;
|
|
639
715
|
try {
|
|
640
716
|
const estimatedGas = await provider.estimateGas({ ...unsigned, from: w.address, value: fundsWei });
|
|
641
717
|
gasLimit = (estimatedGas * 120n) / 100n;
|
|
642
718
|
}
|
|
643
719
|
catch {
|
|
644
|
-
gasLimit = 600000n;
|
|
720
|
+
gasLimit = 600000n;
|
|
645
721
|
}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
722
|
+
return { unsigned, gasLimit, wallet: w, fundsWei };
|
|
723
|
+
}));
|
|
724
|
+
// 并行签名所有交易
|
|
725
|
+
const signedTxs = await Promise.all(txDataList.map(async (data, i) => {
|
|
726
|
+
const req = {
|
|
727
|
+
...data.unsigned,
|
|
728
|
+
from: data.wallet.address,
|
|
729
|
+
nonce: nonces[i],
|
|
730
|
+
gasLimit: data.gasLimit,
|
|
731
|
+
gasPrice,
|
|
732
|
+
chainId: 56,
|
|
733
|
+
type: 0
|
|
734
|
+
};
|
|
735
|
+
return data.wallet.signTransaction(req);
|
|
736
|
+
}));
|
|
649
737
|
if (spPrivateKey) {
|
|
650
738
|
return await sendBatchPrivateTransactions(signedTxs, spPrivateKey, club48Endpoint || 'https://puissant-bsc.48.club');
|
|
651
739
|
}
|
|
@@ -660,19 +748,42 @@ export async function fourBatchPrivateSell(params) {
|
|
|
660
748
|
const provider = new JsonRpcProvider(rpcUrl);
|
|
661
749
|
const club48 = new Club48Client({ endpoint: club48Endpoint, explorerEndpoint: club48ExplorerEndpoint });
|
|
662
750
|
const tmAddr = ADDRESSES.BSC.TokenManagerV2Proxy;
|
|
663
|
-
const gasPrice = await club48.getMinGasPrice();
|
|
664
751
|
const minOut = minFundsEach ?? 0n;
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
752
|
+
// ✅ 并行处理
|
|
753
|
+
const wallets = privateKeys.map(pk => new Wallet(pk, provider));
|
|
754
|
+
const amountsWei = amounts.map(a => ethers.parseUnits(a, 18));
|
|
755
|
+
// 并行获取 gasPrice 和所有 nonce
|
|
756
|
+
const [gasPrice, nonces] = await Promise.all([
|
|
757
|
+
club48.getMinGasPrice(),
|
|
758
|
+
Promise.all(wallets.map(w => w.getNonce()))
|
|
759
|
+
]);
|
|
760
|
+
// 并行构建未签名交易和估算 gas
|
|
761
|
+
const txDataList = await Promise.all(wallets.map(async (w, i) => {
|
|
762
|
+
const amountWei = amountsWei[i];
|
|
669
763
|
const tm2 = new ethers.Contract(tmAddr, TM2Abi, w);
|
|
670
764
|
const unsigned = await tm2.sellToken.populateTransaction(0n, tokenAddress, amountWei, minOut);
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
765
|
+
let gasLimit;
|
|
766
|
+
try {
|
|
767
|
+
const estimatedGas = await provider.estimateGas({ ...unsigned, from: w.address });
|
|
768
|
+
gasLimit = (estimatedGas * 120n) / 100n;
|
|
769
|
+
}
|
|
770
|
+
catch {
|
|
771
|
+
gasLimit = 600000n;
|
|
772
|
+
}
|
|
773
|
+
return { unsigned, gasLimit, wallet: w };
|
|
774
|
+
}));
|
|
775
|
+
// 并行签名所有交易
|
|
776
|
+
const signedTxs = await Promise.all(txDataList.map(async (data, i) => {
|
|
777
|
+
const req = {
|
|
778
|
+
...data.unsigned,
|
|
779
|
+
from: data.wallet.address,
|
|
780
|
+
nonce: nonces[i],
|
|
781
|
+
gasLimit: data.gasLimit,
|
|
782
|
+
gasPrice,
|
|
783
|
+
chainId: 56,
|
|
784
|
+
type: 0
|
|
785
|
+
};
|
|
786
|
+
return data.wallet.signTransaction(req);
|
|
787
|
+
}));
|
|
677
788
|
return await sendBatchPrivateTransactions(signedTxs, spPrivateKey, club48Endpoint || 'https://puissant-bsc.48.club');
|
|
678
789
|
}
|