four-flap-meme-sdk 1.6.84 → 1.6.85

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.
@@ -331,47 +331,101 @@ export async function buildWashOps(params) {
331
331
  // 批量预测买入后获得的代币数量(用于卖出,避免 maxUint256 问题)
332
332
  let expectedTokenAmounts = [];
333
333
  if (poolType === 'flap') {
334
+ // ✅ Flap 报价:使用【总金额报价 + 按比例分配】(和 BSC 一样)
334
335
  const portalQuery = new PortalQuery({ rpcUrl: config.rpcUrl, chainId: config.chainId });
335
- expectedTokenAmounts = await mapWithConcurrency(buyWeiList, 4, async (buyWei) => {
336
- if (buyWei <= 0n)
337
- return 0n;
336
+ const totalBuyWei = buyWeiList.reduce((a, b) => a + b, 0n);
337
+ console.log(`[buildWashOps] Flap 总金额报价: ${buyWeiList.length} 个钱包, 总金额=${totalBuyWei}`);
338
+ // 1. 用总金额获取总代币数量
339
+ let totalTokenAmount = 0n;
340
+ try {
341
+ totalTokenAmount = await portalQuery.previewBuy(params.tokenAddress, totalBuyWei);
342
+ }
343
+ catch {
338
344
  try {
339
- return await portalQuery.previewBuy(params.tokenAddress, buyWei);
345
+ totalTokenAmount = await portalQuery.quoteExactInput('0x0000000000000000000000000000000000000000', params.tokenAddress, totalBuyWei);
340
346
  }
341
347
  catch {
342
- try {
343
- return await portalQuery.quoteExactInput('0x0000000000000000000000000000000000000000', params.tokenAddress, buyWei);
344
- }
345
- catch {
346
- return 0n;
347
- }
348
+ totalTokenAmount = 0n;
348
349
  }
349
- });
350
+ }
351
+ // 2. 按每个钱包的买入金额比例分配代币数量
352
+ if (totalBuyWei > 0n && totalTokenAmount > 0n) {
353
+ let allocated = 0n;
354
+ expectedTokenAmounts = buyWeiList.map((buyWei, i) => {
355
+ if (i === buyWeiList.length - 1) {
356
+ return totalTokenAmount - allocated;
357
+ }
358
+ const share = (totalTokenAmount * buyWei) / totalBuyWei;
359
+ allocated += share;
360
+ return share;
361
+ });
362
+ }
363
+ else {
364
+ expectedTokenAmounts = buyWeiList.map(() => 0n);
365
+ }
366
+ console.log(`[buildWashOps] Flap 总代币=${totalTokenAmount}, 分配:`, expectedTokenAmounts.map(a => a.toString()));
350
367
  }
351
368
  else if (poolType === 'v2') {
369
+ // ✅ V2 报价:使用【总金额报价 + 按比例分配】(和 BSC 一样)
352
370
  const dexQuery = new DexQuery({ rpcUrl: config.rpcUrl, routerAddress, wokbAddress: wokb });
353
- expectedTokenAmounts = await mapWithConcurrency(buyWeiList, 4, async (buyWei) => {
354
- if (buyWei <= 0n)
355
- return 0n;
356
- try {
357
- return await dexQuery.quoteOkbToToken(buyWei, params.tokenAddress);
358
- }
359
- catch {
360
- return 0n;
361
- }
362
- });
371
+ const totalBuyWei = buyWeiList.reduce((a, b) => a + b, 0n);
372
+ console.log(`[buildWashOps] V2 总金额报价: ${buyWeiList.length} 个钱包, 总金额=${totalBuyWei}`);
373
+ // 1. 用总金额获取总代币数量
374
+ let totalTokenAmount = 0n;
375
+ try {
376
+ totalTokenAmount = await dexQuery.quoteOkbToToken(totalBuyWei, params.tokenAddress);
377
+ }
378
+ catch {
379
+ totalTokenAmount = 0n;
380
+ }
381
+ // 2. 按每个钱包的买入金额比例分配代币数量
382
+ if (totalBuyWei > 0n && totalTokenAmount > 0n) {
383
+ let allocated = 0n;
384
+ expectedTokenAmounts = buyWeiList.map((buyWei, i) => {
385
+ if (i === buyWeiList.length - 1) {
386
+ return totalTokenAmount - allocated;
387
+ }
388
+ const share = (totalTokenAmount * buyWei) / totalBuyWei;
389
+ allocated += share;
390
+ return share;
391
+ });
392
+ }
393
+ else {
394
+ expectedTokenAmounts = buyWeiList.map(() => 0n);
395
+ }
396
+ console.log(`[buildWashOps] V2 总代币=${totalTokenAmount}, 分配:`, expectedTokenAmounts.map(a => a.toString()));
363
397
  }
364
398
  else if (poolType === 'v3') {
365
- // ✅ V3 报价:使用 Multicall3 批量查询(单次 RPC 请求获取所有钱包的报价)
366
- // PotatoSwap V3 QuoterV2: 0x5A6f3723346aF54a4D0693bfC1718D64d4915C3e
367
- console.log(`[buildWashOps] V3 批量报价: ${buyWeiList.length} 个钱包, fee=${v3Fee}`);
368
- expectedTokenAmounts = await batchQuoteV3WithMulticall({
399
+ // ✅ V3 报价:使用【总金额报价 + 按比例分配】(和 BSC 一样)
400
+ // 这样可以正确考虑多钱包累积价格影响,确保卖干净
401
+ const totalBuyWei = buyWeiList.reduce((a, b) => a + b, 0n);
402
+ console.log(`[buildWashOps] V3 总金额报价: ${buyWeiList.length} 个钱包, 总金额=${totalBuyWei}, fee=${v3Fee}`);
403
+ // 1. 用总金额获取总代币数量
404
+ const totalQuoteResult = await batchQuoteV3WithMulticall({
369
405
  rpcUrl: config.rpcUrl,
370
406
  tokenIn: wokb,
371
407
  tokenOut: params.tokenAddress,
372
- amountsIn: buyWeiList,
408
+ amountsIn: [totalBuyWei],
373
409
  fee: v3Fee,
374
410
  });
411
+ const totalTokenAmount = totalQuoteResult[0] || 0n;
412
+ // 2. 按每个钱包的买入金额比例分配代币数量
413
+ if (totalBuyWei > 0n && totalTokenAmount > 0n) {
414
+ let allocated = 0n;
415
+ expectedTokenAmounts = buyWeiList.map((buyWei, i) => {
416
+ if (i === buyWeiList.length - 1) {
417
+ // 最后一个钱包分配剩余的全部(避免精度损失)
418
+ return totalTokenAmount - allocated;
419
+ }
420
+ const share = (totalTokenAmount * buyWei) / totalBuyWei;
421
+ allocated += share;
422
+ return share;
423
+ });
424
+ }
425
+ else {
426
+ expectedTokenAmounts = buyWeiList.map(() => 0n);
427
+ }
428
+ console.log(`[buildWashOps] V3 总代币=${totalTokenAmount}, 分配:`, expectedTokenAmounts.map(a => a.toString()));
375
429
  }
376
430
  console.log(`[buildWashOps] 预测买入代币数量 (${poolType}):`, expectedTokenAmounts.map(a => a.toString()));
377
431
  // 构建所有 UserOps 的骨架
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.6.84",
3
+ "version": "1.6.85",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",