four-flap-meme-sdk 1.5.75 → 1.5.77

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.
@@ -1536,16 +1536,19 @@ export class BundleExecutor {
1536
1536
  * 自动计算剩余毕业容量,将钱包分为内盘和外盘组,生成签名的交易列表
1537
1537
  */
1538
1538
  async bundleGraduateBuy(params) {
1539
- const { tokenAddress, privateKeys, payerPrivateKey, amountMode, totalBuyAmount, minAmount, maxAmount, walletAmounts, enableDexBuy = false, config = {} } = params;
1539
+ const { tokenAddress, privateKeys, payerPrivateKey, amountMode, totalBuyAmount, minAmount, maxAmount, walletAmounts, enableDexBuy = false,
1540
+ // ✅ 新增:前端传递的分组信息
1541
+ curveAddresses, dexAddresses, graduationAmount, config = {} } = params;
1540
1542
  const aaManager = this.getAAManager();
1541
1543
  const provider = aaManager.getProvider();
1542
1544
  // 1. 获取代币状态,计算剩余毕业容量
1543
1545
  const tokenState = await this.portalQuery.getTokenV5(tokenAddress);
1544
1546
  const poolReserveOkb = ethers.formatEther(tokenState.reserve);
1545
- const graduateCapacity = 73.38; // 毕业阈值
1547
+ // 优先使用前端传递的动态毕业阈值
1548
+ const graduateCapacity = graduationAmount ?? 73.38;
1546
1549
  const remainingToGraduate = Math.max(0, graduateCapacity - parseFloat(poolReserveOkb));
1547
1550
  const remainingToGraduateWei = ethers.parseEther(remainingToGraduate.toFixed(18));
1548
- console.log(`[GraduateBuy] Pool Reserve: ${poolReserveOkb} OKB, Remaining: ${remainingToGraduate} OKB`);
1551
+ console.log(`[GraduateBuy] Pool Reserve: ${poolReserveOkb} OKB, GraduateCapacity: ${graduateCapacity} OKB, Remaining: ${remainingToGraduate} OKB`);
1549
1552
  // 2. 准备钱包
1550
1553
  const sharedProvider = this.aaManager.getProvider();
1551
1554
  const wallets = privateKeys.map(pk => new Wallet(pk, sharedProvider));
@@ -1573,27 +1576,53 @@ export class BundleExecutor {
1573
1576
  // 4. 钱包分组
1574
1577
  const curveBuyers = [];
1575
1578
  const dexBuyers = [];
1576
- let currentCurveTotal = 0n;
1577
- for (let i = 0; i < wallets.length; i++) {
1578
- const wallet = wallets[i];
1579
- const amountWei = ethers.parseEther(finalAmounts[i].toFixed(18));
1580
- if (currentCurveTotal < remainingToGraduateWei) {
1581
- const needed = remainingToGraduateWei - currentCurveTotal;
1582
- if (amountWei <= needed) {
1579
+ // 优先使用前端传递的分组信息
1580
+ const hasFrontendGrouping = curveAddresses && curveAddresses.length > 0;
1581
+ if (hasFrontendGrouping) {
1582
+ // 使用前端计算好的分组,不再重新计算
1583
+ const curveSet = new Set(curveAddresses.map(a => a.toLowerCase()));
1584
+ const dexSet = dexAddresses ? new Set(dexAddresses.map(a => a.toLowerCase())) : new Set();
1585
+ console.log(`[GraduateBuy] Using frontend grouping: ${curveAddresses.length} curve, ${dexAddresses?.length || 0} dex`);
1586
+ for (let i = 0; i < wallets.length; i++) {
1587
+ const wallet = wallets[i];
1588
+ const addr = wallet.address.toLowerCase();
1589
+ const amountWei = ethers.parseEther(finalAmounts[i].toFixed(18));
1590
+ if (curveSet.has(addr)) {
1583
1591
  curveBuyers.push({ wallet, amount: amountWei });
1584
- currentCurveTotal += amountWei;
1585
1592
  }
1586
- else {
1587
- // 当前钱包金额超过了剩余容量,将其限制为 needed
1588
- curveBuyers.push({ wallet, amount: needed });
1589
- currentCurveTotal = remainingToGraduateWei;
1590
- // 超出部分暂不处理(遵循单钱包单属性逻辑)
1593
+ else if (dexSet.has(addr) && enableDexBuy) {
1594
+ dexBuyers.push({ wallet, amount: amountWei });
1591
1595
  }
1596
+ // 如果钱包既不在 curveSet 也不在 dexSet,则跳过
1592
1597
  }
1593
- else if (enableDexBuy) {
1594
- dexBuyers.push({ wallet, amount: amountWei });
1598
+ }
1599
+ else {
1600
+ // ✅ 原逻辑:SDK 自动分组(可能与前端不一致)
1601
+ console.log(`[GraduateBuy] No frontend grouping, using auto-split by remainingToGraduate=${remainingToGraduate} OKB`);
1602
+ let currentCurveTotal = 0n;
1603
+ for (let i = 0; i < wallets.length; i++) {
1604
+ const wallet = wallets[i];
1605
+ const amountWei = ethers.parseEther(finalAmounts[i].toFixed(18));
1606
+ if (currentCurveTotal < remainingToGraduateWei) {
1607
+ const needed = remainingToGraduateWei - currentCurveTotal;
1608
+ if (amountWei <= needed) {
1609
+ curveBuyers.push({ wallet, amount: amountWei });
1610
+ currentCurveTotal += amountWei;
1611
+ }
1612
+ else {
1613
+ // 当前钱包金额超过了剩余容量,将其限制为 needed
1614
+ curveBuyers.push({ wallet, amount: needed });
1615
+ currentCurveTotal = remainingToGraduateWei;
1616
+ // 超出部分暂不处理(遵循单钱包单属性逻辑)
1617
+ }
1618
+ }
1619
+ else if (enableDexBuy) {
1620
+ dexBuyers.push({ wallet, amount: amountWei });
1621
+ }
1595
1622
  }
1596
1623
  }
1624
+ // ✅ 统一计算内盘买入总金额(无论使用哪种分组方式)
1625
+ const curveTotalWei = curveBuyers.reduce((sum, b) => sum + b.amount, 0n);
1597
1626
  // 5. 构建 UserOps
1598
1627
  const effConfig = { ...(this.config ?? {}), ...(config ?? {}) };
1599
1628
  const signedTransactions = [];
@@ -1612,7 +1641,7 @@ export class BundleExecutor {
1612
1641
  // ✅ 判断是否是最后一笔内盘买入(触发毕业的那笔)
1613
1642
  const isGraduationTrigger = (i === curveBuyers.length - 1);
1614
1643
  const callGasLimit = isGraduationTrigger
1615
- ? 7000000n // 毕业触发交易需要更高 gas
1644
+ ? 8000000n // 毕业触发交易需要更高 gas
1616
1645
  : (effConfig.fixedGas?.callGasLimit ?? 800000n); // 其他买入使用前端配置或默认值
1617
1646
  const buyOpRes = await aaManager.buildUserOpWithFixedGas({
1618
1647
  ownerWallet: wallet,
@@ -1652,7 +1681,7 @@ export class BundleExecutor {
1652
1681
  nonce: nonceMap.next(info.sender),
1653
1682
  initCode: info.deployed ? '0x' : (await aaManager.generateInitCode(wallet.address)),
1654
1683
  deployed: info.deployed,
1655
- fixedGas: { callGasLimit: effConfig.fixedGas?.callGasLimit ?? 800000n } // ✅ 提高到 800K
1684
+ fixedGas: { callGasLimit: effConfig.fixedGas?.callGasLimit ?? 600000n } // ✅ 提高到 800K
1656
1685
  });
1657
1686
  const signedDexBuyOp = await aaManager.signUserOp(dexBuyOpRes.userOp, wallet);
1658
1687
  return signedDexBuyOp.userOp;
@@ -1671,7 +1700,7 @@ export class BundleExecutor {
1671
1700
  });
1672
1701
  signedTransactions.push(signedMainTx);
1673
1702
  // 7. 计算并签利润提取交易 (EOA 转账,千分之 4)
1674
- const totalBuyWei = currentCurveTotal + totalDexBuyWei;
1703
+ const totalBuyWei = curveTotalWei + totalDexBuyWei;
1675
1704
  const profitWei = (totalBuyWei * 4n) / 1000n; // 0.4%
1676
1705
  if (profitWei > 0n) {
1677
1706
  const profitRecipient = effConfig.profitRecipient || PROFIT_CONFIG.RECIPIENT;
@@ -1693,7 +1722,7 @@ export class BundleExecutor {
1693
1722
  metadata: {
1694
1723
  curveCount: curveBuyers.length,
1695
1724
  dexCount: dexBuyers.length,
1696
- curveTotalAmount: ethers.formatEther(currentCurveTotal),
1725
+ curveTotalAmount: ethers.formatEther(curveTotalWei),
1697
1726
  dexTotalAmount: ethers.formatEther(totalDexBuyWei),
1698
1727
  tokenAddress
1699
1728
  }
@@ -856,6 +856,12 @@ export interface BundleGraduateBuyParams {
856
856
  walletAmounts?: Record<string, number>;
857
857
  /** 是否启用外盘买入(默认 false) */
858
858
  enableDexBuy?: boolean;
859
+ /** 内盘钱包地址列表(可选,传入则使用前端分组,不传则 SDK 自动分组) */
860
+ curveAddresses?: string[];
861
+ /** 外盘钱包地址列表(可选) */
862
+ dexAddresses?: string[];
863
+ /** 动态毕业阈值(可选,不传则使用默认 73.38 OKB) */
864
+ graduationAmount?: number;
859
865
  /** 配置覆盖 */
860
866
  config?: Partial<XLayerConfig>;
861
867
  /** Payer 起始 nonce */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.5.75",
3
+ "version": "1.5.77",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",