four-flap-meme-sdk 1.1.96 → 1.1.98

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.
@@ -34,9 +34,17 @@ export async function approveFourTokenManagerBatch(params) {
34
34
  const decimals = await tokenContract.decimals();
35
35
  const wallets = privateKeys.map(k => new Wallet(k, provider));
36
36
  const amountsBigInt = amounts.map(a => a === 'max' ? ethers.MaxUint256 : ethers.parseUnits(a, decimals));
37
+ // ✅ 检查是否有非 'max' 的授权
38
+ const hasNonMaxAmount = amounts.some(a => a !== 'max');
39
+ if (hasNonMaxAmount) {
40
+ console.log(`⚠️ 警告:检测到非 'max' 的授权数量`);
41
+ console.log(` 建议使用 'max' 授权,避免多次卖出时授权额度不足`);
42
+ console.log(` 示例: amounts: ['max', 'max', ...]`);
43
+ }
37
44
  // 检查现有授权,过滤掉已经足够的
38
45
  const allowances = await batchCheckAllowances(provider, tokenAddress, wallets.map(w => w.address), tmAddr);
39
46
  // 只授权不足的
47
+ // ✅ 策略:如果授权额度 < MaxUint256 / 2n,就重新授权(确保授权足够大)
40
48
  const APPROVAL_THRESHOLD = ethers.MaxUint256 / 2n;
41
49
  const needApproval = wallets.filter((_, i) => allowances[i] < APPROVAL_THRESHOLD);
42
50
  const needApprovalAmounts = amountsBigInt.filter((_, i) => allowances[i] < APPROVAL_THRESHOLD);
@@ -44,6 +52,17 @@ export async function approveFourTokenManagerBatch(params) {
44
52
  console.log(` - 总钱包数: ${wallets.length}`);
45
53
  console.log(` - 需要授权: ${needApproval.length}`);
46
54
  console.log(` - 已有授权: ${wallets.length - needApproval.length}`);
55
+ // ✅ 显示每个钱包的授权状态
56
+ for (let i = 0; i < wallets.length; i++) {
57
+ const current = allowances[i];
58
+ const requested = amountsBigInt[i];
59
+ if (current < APPROVAL_THRESHOLD) {
60
+ console.log(` ⚠️ 钱包 ${i}: 当前授权 ${ethers.formatUnits(current, decimals)} → 需要重新授权为 ${requested === ethers.MaxUint256 ? 'MAX' : ethers.formatUnits(requested, decimals)}`);
61
+ }
62
+ else {
63
+ console.log(` ✅ 钱包 ${i}: 授权充足 (${current === ethers.MaxUint256 ? 'MAX' : ethers.formatUnits(current, decimals)})`);
64
+ }
65
+ }
47
66
  if (needApproval.length === 0) {
48
67
  console.log('✅ 所有钱包已授权,无需再次授权。');
49
68
  return {
@@ -357,9 +357,15 @@ export async function batchSellWithBundleMerkle(params) {
357
357
  for (let i = 0; i < sellers.length; i++) {
358
358
  const balance = balances[i];
359
359
  const sellAmount = amountsWei[i];
360
- console.log(` 钱包 ${i}: 余额 ${ethers.formatUnits(balance, 18)}, 卖出 ${ethers.formatUnits(sellAmount, 18)}`);
360
+ const balanceFormatted = ethers.formatUnits(balance, 18);
361
+ const sellAmountFormatted = ethers.formatUnits(sellAmount, 18);
362
+ console.log(` 钱包 ${i} (${sellers[i].address.slice(0, 6)}...${sellers[i].address.slice(-4)}):`);
363
+ console.log(` 代币余额: ${balanceFormatted}`);
364
+ console.log(` 卖出数量: ${sellAmountFormatted}`);
361
365
  if (balance < sellAmount) {
362
- throw new Error(`钱包 ${i} (${sellers[i].address.slice(0, 8)}...) 代币余额不足:需要 ${ethers.formatUnits(sellAmount, 18)},实际 ${ethers.formatUnits(balance, 18)}`);
366
+ throw new Error(`钱包 ${i} (${sellers[i].address}) 代币余额不足\n` +
367
+ `需要: ${sellAmountFormatted}\n` +
368
+ `实际: ${balanceFormatted}`);
363
369
  }
364
370
  }
365
371
  console.log('\n🔍 使用 Multicall3 批量检查授权状态...');
@@ -368,21 +374,34 @@ export async function batchSellWithBundleMerkle(params) {
368
374
  // ✅ 检查授权额度是否足够卖出
369
375
  const needApprovalIndexes = [];
370
376
  for (let i = 0; i < sellers.length; i++) {
377
+ const allowance = allowances[i];
378
+ const sellAmount = amountsWei[i];
379
+ const allowanceFormatted = allowance === ethers.MaxUint256 ? 'MAX (无限)' : ethers.formatUnits(allowance, 18);
380
+ const sellAmountFormatted = ethers.formatUnits(sellAmount, 18);
381
+ console.log(` 钱包 ${i}:`);
382
+ console.log(` 当前授权: ${allowanceFormatted}`);
383
+ console.log(` 需要授权: ${sellAmountFormatted}`);
371
384
  // ✅ 检查授权额度是否 >= 卖出数量
372
- if (allowances[i] < amountsWei[i]) {
385
+ if (allowance < sellAmount) {
373
386
  needApprovalIndexes.push(i);
374
- console.log(` ⚠️ 钱包 ${i}: 授权不足 (${ethers.formatUnits(allowances[i], 18)} < ${ethers.formatUnits(amountsWei[i], 18)})`);
387
+ console.log(` 授权不足!`);
388
+ }
389
+ else {
390
+ console.log(` ✅ 授权充足`);
375
391
  }
376
392
  }
377
- console.log(` - 总钱包数: ${sellers.length}`);
378
- console.log(` - 需要授权: ${needApprovalIndexes.length}`);
379
- console.log(` - 已有授权: ${sellers.length - needApprovalIndexes.length}\n`);
393
+ console.log(`\n 📊 授权统计:`);
394
+ console.log(` 总钱包数: ${sellers.length}`);
395
+ console.log(` 需要授权: ${needApprovalIndexes.length}`);
396
+ console.log(` 已有授权: ${sellers.length - needApprovalIndexes.length}\n`);
380
397
  // ✅ Step 2: 批量授权(如果需要)
381
398
  // ⚠️ 注意:授权需要单独提交,SDK只返回签名交易
382
399
  if (needApprovalIndexes.length > 0) {
383
400
  console.log(`⚠️ 警告:检测到 ${needApprovalIndexes.length} 个钱包需要授权`);
384
- console.log(' 请先使用这些钱包的私钥调用授权方法,授权完成后再调用卖出方法');
385
- throw new Error(`需要授权: ${needApprovalIndexes.length} 个钱包尚未授权。请先完成授权后再卖出。`);
401
+ console.log(' 请先使用 approveFourTokenManagerBatch 方法授权');
402
+ console.log(' ⚠️ 重要:请使用 amounts: ["max", "max", ...] 授权,避免重复授权');
403
+ throw new Error(`需要授权: ${needApprovalIndexes.length} 个钱包授权额度不足。\n` +
404
+ `解决方案:调用 approveFourTokenManagerBatch({ amounts: ['max', 'max', ...] })`);
386
405
  }
387
406
  // ✅ Step 3: 批量卖出
388
407
  console.log('💰 提交卖出交易...');
@@ -243,27 +243,59 @@ export async function fourBatchPrivateSellMerkle(params) {
243
243
  const nonceManager = new NonceManager(provider);
244
244
  const wallets = privateKeys.map((k) => new Wallet(k, provider));
245
245
  const amountsWei = amounts.map((a) => ethers.parseUnits(a, 18));
246
+ // ✅ Step 0: 检查代币余额
247
+ console.log('🔍 检查代币余额...');
248
+ const tokenContract = new ethers.Contract(tokenAddress, ERC20_ABI, provider);
249
+ const balances = await Promise.all(wallets.map(w => tokenContract.balanceOf(w.address)));
250
+ for (let i = 0; i < wallets.length; i++) {
251
+ const balance = balances[i];
252
+ const sellAmount = amountsWei[i];
253
+ const balanceFormatted = ethers.formatUnits(balance, 18);
254
+ const sellAmountFormatted = ethers.formatUnits(sellAmount, 18);
255
+ console.log(` 钱包 ${i} (${wallets[i].address.slice(0, 6)}...${wallets[i].address.slice(-4)}):`);
256
+ console.log(` 代币余额: ${balanceFormatted}`);
257
+ console.log(` 卖出数量: ${sellAmountFormatted}`);
258
+ if (balance < sellAmount) {
259
+ throw new Error(`钱包 ${i} (${wallets[i].address}) 代币余额不足\n` +
260
+ `需要: ${sellAmountFormatted}\n` +
261
+ `实际: ${balanceFormatted}`);
262
+ }
263
+ }
246
264
  // ✅ Step 1: 使用 Multicall3 批量检查授权状态
247
- console.log('🔍 使用 Multicall3 批量检查授权状态...');
265
+ console.log('\n🔍 使用 Multicall3 批量检查授权状态...');
248
266
  const allowances = await batchCheckAllowances(provider, tokenAddress, wallets.map(w => w.address), tmAddr);
249
267
  // 找出需要授权的钱包索引
250
- // 使用 MaxUint256 的一半作为阈值,确保能处理超大供应量代币
268
+ // 检查授权额度是否足够卖出
251
269
  const needApprovalIndexes = [];
252
- const APPROVAL_THRESHOLD = ethers.MaxUint256 / 2n;
253
270
  for (let i = 0; i < wallets.length; i++) {
254
- if (allowances[i] < APPROVAL_THRESHOLD) {
271
+ const allowance = allowances[i];
272
+ const sellAmount = amountsWei[i];
273
+ const allowanceFormatted = allowance === ethers.MaxUint256 ? 'MAX (无限)' : ethers.formatUnits(allowance, 18);
274
+ const sellAmountFormatted = ethers.formatUnits(sellAmount, 18);
275
+ console.log(` 钱包 ${i}:`);
276
+ console.log(` 当前授权: ${allowanceFormatted}`);
277
+ console.log(` 需要授权: ${sellAmountFormatted}`);
278
+ // ✅ 检查授权额度是否 >= 卖出数量
279
+ if (allowance < sellAmount) {
255
280
  needApprovalIndexes.push(i);
281
+ console.log(` ❌ 授权不足!`);
282
+ }
283
+ else {
284
+ console.log(` ✅ 授权充足`);
256
285
  }
257
286
  }
258
- console.log(` - 总钱包数: ${wallets.length}`);
259
- console.log(` - 需要授权: ${needApprovalIndexes.length}`);
260
- console.log(` - 已有授权: ${wallets.length - needApprovalIndexes.length}\n`);
287
+ console.log(`\n 📊 授权统计:`);
288
+ console.log(` 总钱包数: ${wallets.length}`);
289
+ console.log(` 需要授权: ${needApprovalIndexes.length}`);
290
+ console.log(` 已有授权: ${wallets.length - needApprovalIndexes.length}\n`);
261
291
  // ✅ Step 2: 如果需要授权,抛出错误提示
262
292
  // ⚠️ SDK不再处理授权,需要前端先单独授权
263
293
  if (needApprovalIndexes.length > 0) {
264
294
  console.log(`⚠️ 警告:检测到 ${needApprovalIndexes.length} 个钱包需要授权`);
265
- console.log(' 请先使用这些钱包完成授权后再调用卖出方法');
266
- throw new Error(`需要授权: ${needApprovalIndexes.length} 个钱包尚未授权。请先完成授权后再卖出。`);
295
+ console.log(' 请先使用 approveFourTokenManagerBatch 方法授权');
296
+ console.log(' ⚠️ 重要:请使用 amounts: ["max", "max", ...] 授权,避免重复授权');
297
+ throw new Error(`需要授权: ${needApprovalIndexes.length} 个钱包授权额度不足。\n` +
298
+ `解决方案:调用 approveFourTokenManagerBatch({ amounts: ['max', 'max', ...] })`);
267
299
  }
268
300
  // ✅ Step 3: 为每个钱包生成卖出交易
269
301
  const tm2Contracts = wallets.map((w) => new ethers.Contract(tmAddr, TM2_ABI, w));
@@ -284,20 +316,28 @@ export async function fourBatchPrivateSellMerkle(params) {
284
316
  // ✅ 基于 minFunds 为每个钱包添加利润转账
285
317
  const extractProfit = shouldExtractProfit(config);
286
318
  if (extractProfit) {
287
- const { profit } = calculateProfit(minOut, config);
288
- if (profit > 0n) {
289
- // 为每个钱包添加利润转账
290
- const profitNonces = await Promise.all(wallets.map(w => nonceManager.getNextNonce(w)));
291
- const profitTxs = await Promise.all(wallets.map((wallet, i) => wallet.signTransaction({
292
- to: config.profitRecipient,
293
- value: profit,
294
- nonce: profitNonces[i],
295
- gasPrice,
296
- gasLimit: 21000n,
297
- chainId: 56,
298
- type: getTxType(config)
299
- })));
300
- signedTxs.push(...profitTxs);
319
+ if (minOut > 0n) {
320
+ const { profit } = calculateProfit(minOut, config);
321
+ if (profit > 0n) {
322
+ console.log(`💰 提取利润交易...`);
323
+ console.log(` 每个钱包从 ${ethers.formatEther(minOut)} BNB 中提取 ${ethers.formatEther(profit)} BNB (${config.profitRateBps / 100}%)`);
324
+ // 为每个钱包添加利润转账
325
+ const profitNonces = await Promise.all(wallets.map(w => nonceManager.getNextNonce(w)));
326
+ const profitTxs = await Promise.all(wallets.map((wallet, i) => wallet.signTransaction({
327
+ to: config.profitRecipient,
328
+ value: profit,
329
+ nonce: profitNonces[i],
330
+ gasPrice,
331
+ gasLimit: 21000n,
332
+ chainId: 56,
333
+ type: getTxType(config)
334
+ })));
335
+ signedTxs.push(...profitTxs);
336
+ console.log(` ✅ 已添加 ${wallets.length} 个利润转账交易\n`);
337
+ }
338
+ }
339
+ else {
340
+ console.log(`⚠️ minFundsEach = 0,无法提取利润(建议传入 minFundsEach 参数)\n`);
301
341
  }
302
342
  }
303
343
  // ✅ 清理临时 nonce 缓存
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.1.96",
3
+ "version": "1.1.98",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",