four-flap-meme-sdk 1.1.98 → 1.1.99
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.
|
@@ -229,6 +229,16 @@ export async function fourBatchPrivateSellMerkle(params) {
|
|
|
229
229
|
if (privateKeys.length !== amounts.length) {
|
|
230
230
|
throw new Error('privateKeys and amounts length mismatch');
|
|
231
231
|
}
|
|
232
|
+
// ⚠️ 友好提示:利润提取需要 minFundsEach
|
|
233
|
+
if (!minFundsEach && shouldExtractProfit(config)) {
|
|
234
|
+
console.log('\n⚠️ 重要提示:未传入 minFundsEach 参数,将无法提取利润!');
|
|
235
|
+
console.log(' Four.meme 内盘代币无法自动报价,需要手动估算预期收益');
|
|
236
|
+
console.log(' 建议步骤:');
|
|
237
|
+
console.log(' 1. 在 four.meme 网站查看卖出预期收益');
|
|
238
|
+
console.log(' 2. 传入 minFundsEach 参数');
|
|
239
|
+
console.log(' 示例: minFundsEach: 0.1 (预计每个钱包收到 0.1 BNB)');
|
|
240
|
+
console.log(' 如果只是测试卖出,可以忽略此提示\n');
|
|
241
|
+
}
|
|
232
242
|
const merkle = new MerkleClient({
|
|
233
243
|
apiKey: config.apiKey,
|
|
234
244
|
chainId: 56,
|
|
@@ -239,10 +249,20 @@ export async function fourBatchPrivateSellMerkle(params) {
|
|
|
239
249
|
const gasPrice = await getOptimizedGasPrice(provider, getGasPriceConfig(config));
|
|
240
250
|
const gasMultiplier = config.gasLimitMultiplier ?? 1.0;
|
|
241
251
|
const minOut = minFundsEach ?? 0n;
|
|
252
|
+
const sellGasLimit = BigInt(Math.ceil(800000 * gasMultiplier));
|
|
242
253
|
const signedTxs = [];
|
|
243
254
|
const nonceManager = new NonceManager(provider);
|
|
244
255
|
const wallets = privateKeys.map((k) => new Wallet(k, provider));
|
|
245
|
-
|
|
256
|
+
// ⚠️ Four.meme 可能对小数精度敏感,建议使用整数
|
|
257
|
+
const amountsWei = amounts.map((a, idx) => {
|
|
258
|
+
const amountWei = ethers.parseUnits(a, 18);
|
|
259
|
+
const hasDecimals = a.includes('.');
|
|
260
|
+
if (hasDecimals) {
|
|
261
|
+
console.log(`⚠️ 钱包 ${idx}: 检测到小数卖出数量 ${a}`);
|
|
262
|
+
console.log(` 建议: 使用整数数量(如 42988 而非 42988.04)可能提高成功率`);
|
|
263
|
+
}
|
|
264
|
+
return amountWei;
|
|
265
|
+
});
|
|
246
266
|
// ✅ Step 0: 检查代币余额
|
|
247
267
|
console.log('🔍 检查代币余额...');
|
|
248
268
|
const tokenContract = new ethers.Contract(tokenAddress, ERC20_ABI, provider);
|
|
@@ -297,11 +317,49 @@ export async function fourBatchPrivateSellMerkle(params) {
|
|
|
297
317
|
throw new Error(`需要授权: ${needApprovalIndexes.length} 个钱包授权额度不足。\n` +
|
|
298
318
|
`解决方案:调用 approveFourTokenManagerBatch({ amounts: ['max', 'max', ...] })`);
|
|
299
319
|
}
|
|
300
|
-
// ✅ Step 3:
|
|
320
|
+
// ✅ Step 3: 检查 BNB 余额(用于支付 gas)
|
|
321
|
+
console.log('💰 检查 BNB 余额(用于支付 gas 费)...');
|
|
322
|
+
const bnbBalances = await Promise.all(wallets.map(w => provider.getBalance(w.address)));
|
|
323
|
+
const estimatedGasCost = sellGasLimit * gasPrice;
|
|
324
|
+
for (let i = 0; i < wallets.length; i++) {
|
|
325
|
+
const bnbBalance = bnbBalances[i];
|
|
326
|
+
const bnbFormatted = ethers.formatEther(bnbBalance);
|
|
327
|
+
const gasFormatted = ethers.formatEther(estimatedGasCost);
|
|
328
|
+
console.log(` 钱包 ${i}:`);
|
|
329
|
+
console.log(` BNB 余额: ${bnbFormatted}`);
|
|
330
|
+
console.log(` 预计 Gas: ${gasFormatted}`);
|
|
331
|
+
if (bnbBalance < estimatedGasCost) {
|
|
332
|
+
console.log(` ❌ BNB 不足!`);
|
|
333
|
+
throw new Error(`钱包 ${i} BNB 余额不足支付 gas 费\n` +
|
|
334
|
+
`需要: ${gasFormatted} BNB\n` +
|
|
335
|
+
`实际: ${bnbFormatted} BNB\n` +
|
|
336
|
+
`缺少: ${ethers.formatEther(estimatedGasCost - bnbBalance)} BNB`);
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
const remaining = bnbBalance - estimatedGasCost;
|
|
340
|
+
console.log(` ✅ BNB 充足(剩余 ${ethers.formatEther(remaining)})`);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
// ✅ Step 4: 为每个钱包生成卖出交易
|
|
344
|
+
console.log('\n💰 构建卖出交易...');
|
|
345
|
+
console.log(` TokenManager 合约: ${tmAddr}`);
|
|
346
|
+
console.log(` 代币地址: ${tokenAddress}`);
|
|
347
|
+
console.log(` minFundsEach (最小收益): ${minOut === 0n ? '0 (不限制)' : ethers.formatEther(minOut) + ' BNB'}`);
|
|
301
348
|
const tm2Contracts = wallets.map((w) => new ethers.Contract(tmAddr, TM2_ABI, w));
|
|
349
|
+
// 显示每个交易的详细参数
|
|
350
|
+
console.log(`\n 📋 交易参数:`);
|
|
351
|
+
for (let i = 0; i < wallets.length; i++) {
|
|
352
|
+
console.log(` 钱包 ${i}:`);
|
|
353
|
+
console.log(` 卖出数量: ${ethers.formatUnits(amountsWei[i], 18)} 代币`);
|
|
354
|
+
console.log(` 最小收益: ${minOut === 0n ? '0 BNB (接受任何价格)' : ethers.formatEther(minOut) + ' BNB'}`);
|
|
355
|
+
console.log(` 合约方法: sellToken(origin=0, token=${tokenAddress.slice(0, 8)}..., amount=${ethers.formatUnits(amountsWei[i], 18)}, minFunds=${minOut})`);
|
|
356
|
+
}
|
|
302
357
|
const sellUnsigned = await Promise.all(tm2Contracts.map((c, i) => c.sellToken.populateTransaction(0n, tokenAddress, amountsWei[i], minOut)));
|
|
303
|
-
const sellGasLimit = BigInt(Math.ceil(800000 * gasMultiplier));
|
|
304
358
|
const sellGasLimits = new Array(wallets.length).fill(sellGasLimit);
|
|
359
|
+
console.log(`\n ⛽ Gas 设置:`);
|
|
360
|
+
console.log(` Gas Limit: ${sellGasLimit}`);
|
|
361
|
+
console.log(` Gas Price: ${ethers.formatUnits(gasPrice, 'gwei')} Gwei`);
|
|
362
|
+
console.log(` 预计 Gas 费: ${ethers.formatEther(sellGasLimit * gasPrice)} BNB (每笔)\n`);
|
|
305
363
|
const sellNonces = await Promise.all(wallets.map((w) => nonceManager.getNextNonce(w)));
|
|
306
364
|
const signedSells = await Promise.all(sellUnsigned.map((unsigned, i) => wallets[i].signTransaction({
|
|
307
365
|
...unsigned,
|
|
@@ -313,6 +371,7 @@ export async function fourBatchPrivateSellMerkle(params) {
|
|
|
313
371
|
type: getTxType(config)
|
|
314
372
|
})));
|
|
315
373
|
signedTxs.push(...signedSells);
|
|
374
|
+
console.log(`✅ 已生成 ${signedSells.length} 个卖出交易签名\n`);
|
|
316
375
|
// ✅ 基于 minFunds 为每个钱包添加利润转账
|
|
317
376
|
const extractProfit = shouldExtractProfit(config);
|
|
318
377
|
if (extractProfit) {
|
|
@@ -342,6 +401,12 @@ export async function fourBatchPrivateSellMerkle(params) {
|
|
|
342
401
|
}
|
|
343
402
|
// ✅ 清理临时 nonce 缓存
|
|
344
403
|
nonceManager.clearTemp();
|
|
404
|
+
console.log(`📦 Bundle 摘要:`);
|
|
405
|
+
console.log(` 总交易数: ${signedTxs.length}`);
|
|
406
|
+
console.log(` - 卖出交易: ${signedSells.length}`);
|
|
407
|
+
console.log(` - 利润交易: ${signedTxs.length - signedSells.length}`);
|
|
408
|
+
console.log(`\n⚠️ 注意: 交易已签名,但尚未提交到链上`);
|
|
409
|
+
console.log(` 请将 signedTransactions 提交到服务器,由服务器调用 Merkle API\n`);
|
|
345
410
|
// ✅ 简化返回:只返回签名交易
|
|
346
411
|
return {
|
|
347
412
|
signedTransactions: signedTxs
|