four-flap-meme-sdk 1.2.92 → 1.2.95

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.
@@ -18,10 +18,12 @@ export async function disperseWithBundleMerkle(params) {
18
18
  }
19
19
  // 初始化
20
20
  const chainIdNum = config.chainId ?? 56;
21
+ // ✅ 根据 chainId 动态设置链名
22
+ const chainName = chainIdNum === 143 ? 'Monad' : chainIdNum === 56 ? 'BSC' : `Chain-${chainIdNum}`;
21
23
  // ✅ 直接使用传入的 RPC URL 创建 provider(不依赖 Merkle)
22
24
  const provider = new ethers.JsonRpcProvider(config.rpcUrl, {
23
25
  chainId: chainIdNum,
24
- name: 'BSC'
26
+ name: chainName
25
27
  });
26
28
  const [gasPrice, mainWallet] = await Promise.all([
27
29
  getOptimizedGasPrice(provider, getGasPriceConfig(config)),
@@ -325,10 +327,12 @@ export async function sweepWithBundleMerkle(params) {
325
327
  }
326
328
  // 初始化
327
329
  const chainIdNum = config.chainId ?? 56;
330
+ // ✅ 根据 chainId 动态设置链名
331
+ const chainName = chainIdNum === 143 ? 'Monad' : chainIdNum === 56 ? 'BSC' : `Chain-${chainIdNum}`;
328
332
  // ✅ 直接使用传入的 RPC URL 创建 provider(不依赖 Merkle)
329
333
  const provider = new ethers.JsonRpcProvider(config.rpcUrl, {
330
334
  chainId: chainIdNum,
331
- name: 'BSC'
335
+ name: chainName
332
336
  });
333
337
  const gasPrice = await getOptimizedGasPrice(provider, getGasPriceConfig(config));
334
338
  const isNative = _isNativeTokenAddress(tokenAddress);
@@ -7,10 +7,12 @@ export declare function createTokenWithBundleBuyMerkle(params: FlapCreateWithBun
7
7
  /**
8
8
  * Flap Protocol: 批量购买(仅签名版本 - 不依赖 Merkle)
9
9
  * ✅ 精简版:只负责签名交易,不提交到 Merkle
10
+ * ✅ 支持 quoteToken:传入 USDC 等地址时使用该代币购买,否则使用原生代币
10
11
  */
11
12
  export declare function batchBuyWithBundleMerkle(params: FlapBatchBuySignParams): Promise<FlapBatchBuyMerkleResult>;
12
13
  /**
13
14
  * Flap Protocol: 批量卖出(仅签名版本 - 不依赖 Merkle)
14
15
  * ✅ 精简版:只负责签名交易,不提交到 Merkle
16
+ * ✅ 支持 quoteToken:传入 USDC 等地址时卖出为该代币,否则卖出为原生代币
15
17
  */
16
18
  export declare function batchSellWithBundleMerkle(params: FlapBatchSellSignParams): Promise<FlapBatchSellMerkleResult>;
@@ -121,9 +121,12 @@ export async function createTokenWithBundleBuyMerkle(params) {
121
121
  /**
122
122
  * Flap Protocol: 批量购买(仅签名版本 - 不依赖 Merkle)
123
123
  * ✅ 精简版:只负责签名交易,不提交到 Merkle
124
+ * ✅ 支持 quoteToken:传入 USDC 等地址时使用该代币购买,否则使用原生代币
124
125
  */
125
126
  export async function batchBuyWithBundleMerkle(params) {
126
- const { chain, privateKeys, buyAmounts, tokenAddress, config } = params;
127
+ const { chain, privateKeys, buyAmounts, tokenAddress, quoteToken, config } = params;
128
+ console.log('🔍 SDK batchBuyWithBundleMerkle - quoteToken:', quoteToken);
129
+ console.log('🔍 SDK batchBuyWithBundleMerkle - params.quoteToken:', params.quoteToken);
127
130
  if (privateKeys.length === 0 || buyAmounts.length !== privateKeys.length) {
128
131
  throw new Error(getErrorMessage('KEY_AMOUNT_MISMATCH'));
129
132
  }
@@ -135,10 +138,16 @@ export async function batchBuyWithBundleMerkle(params) {
135
138
  const { fundsList, originalAmounts, totalBuyAmount, totalProfit } = analyzeBuyFunds(buyAmounts, config, extractProfit);
136
139
  const maxFundsIndex = findMaxIndex(originalAmounts);
137
140
  const gasLimits = buildGasLimitList(buyers.length, config);
141
+ // ✅ 确定 inputToken:如果传入了 quoteToken 且非零地址,则使用它;否则使用零地址(原生代币)
142
+ const inputToken = quoteToken && quoteToken !== ZERO_ADDRESS ? quoteToken : ZERO_ADDRESS;
143
+ // ✅ 如果使用非原生代币,则 value 应为 0(不发送原生代币)
144
+ const useNativeToken = inputToken === ZERO_ADDRESS;
145
+ console.log('🔍 SDK inputToken 计算结果:', inputToken);
146
+ console.log('🔍 SDK useNativeToken:', useNativeToken);
138
147
  // ✅ 优化:并行执行 gasPrice 和 populateBuyTransactions(最耗时的两个操作)
139
148
  const [gasPrice, unsignedBuys] = await Promise.all([
140
149
  resolveGasPrice(provider, config),
141
- populateBuyTransactions(buyers, FLAP_PORTAL_ADDRESSES[chain], tokenAddress, fundsList)
150
+ populateBuyTransactionsWithQuote(buyers, FLAP_PORTAL_ADDRESSES[chain], tokenAddress, fundsList, inputToken, useNativeToken)
142
151
  ]);
143
152
  const buyerNonces = await allocateBuyerNonces(buyers, extractProfit, maxFundsIndex, totalProfit, nonceManager);
144
153
  const signedBuys = await signBuyTransactions({
@@ -172,9 +181,10 @@ export async function batchBuyWithBundleMerkle(params) {
172
181
  /**
173
182
  * Flap Protocol: 批量卖出(仅签名版本 - 不依赖 Merkle)
174
183
  * ✅ 精简版:只负责签名交易,不提交到 Merkle
184
+ * ✅ 支持 quoteToken:传入 USDC 等地址时卖出为该代币,否则卖出为原生代币
175
185
  */
176
186
  export async function batchSellWithBundleMerkle(params) {
177
- const { chain, privateKeys, sellAmounts, tokenAddress, minOutputAmounts, config } = params;
187
+ const { chain, privateKeys, sellAmounts, tokenAddress, quoteToken, minOutputAmounts, config } = params;
178
188
  if (privateKeys.length === 0 || sellAmounts.length !== privateKeys.length) {
179
189
  throw new Error(getErrorMessage('SELL_KEY_AMOUNT_MISMATCH'));
180
190
  }
@@ -186,16 +196,18 @@ export async function batchSellWithBundleMerkle(params) {
186
196
  const portalAddr = FLAP_PORTAL_ADDRESSES[chain];
187
197
  const readOnlyPortal = new ethers.Contract(portalAddr, PORTAL_ABI, provider);
188
198
  const gasLimits = buildGasLimitList(wallets.length, config);
199
+ // ✅ 确定 outputToken:如果传入了 quoteToken 且非零地址,则使用它;否则使用零地址(原生代币)
200
+ const outputToken = quoteToken && quoteToken !== ZERO_ADDRESS ? quoteToken : ZERO_ADDRESS;
189
201
  // ✅ 优化:并行执行 gasPrice 和 quoteSellOutputs(最耗时的两个操作)
190
202
  const [gasPrice, quotedOutputs] = await Promise.all([
191
203
  resolveGasPrice(provider, config),
192
- quoteSellOutputs(readOnlyPortal, tokenAddress, amountsWei)
204
+ quoteSellOutputsWithQuote(readOnlyPortal, tokenAddress, amountsWei, outputToken)
193
205
  ]);
194
206
  const minOuts = resolveMinOutputs(minOutputAmounts, wallets.length, quotedOutputs);
195
207
  const portals = wallets.map(w => new ethers.Contract(portalAddr, PORTAL_ABI, w));
196
208
  const unsignedList = await Promise.all(portals.map((portal, i) => portal.swapExactInput.populateTransaction({
197
209
  inputToken: tokenAddress,
198
- outputToken: ZERO_ADDRESS,
210
+ outputToken, // ✅ 使用动态 outputToken
199
211
  inputAmount: amountsWei[i],
200
212
  minOutputAmount: minOuts[i],
201
213
  permitData: '0x'
@@ -285,6 +297,22 @@ async function populateBuyTransactions(buyers, portalAddr, tokenAddress, fundsLi
285
297
  permitData: '0x'
286
298
  }, { value: fundsList[i] })));
287
299
  }
300
+ /**
301
+ * ✅ 支持 quoteToken 的买入交易构建
302
+ * 当 inputToken 为非零地址(如 USDC)时,value 为 0
303
+ */
304
+ async function populateBuyTransactionsWithQuote(buyers, portalAddr, tokenAddress, fundsList, inputToken, useNativeToken) {
305
+ const portals = buyers.map(wallet => new ethers.Contract(portalAddr, PORTAL_ABI, wallet));
306
+ return await Promise.all(portals.map((portal, i) => portal.swapExactInput.populateTransaction({
307
+ inputToken,
308
+ outputToken: tokenAddress,
309
+ inputAmount: fundsList[i],
310
+ minOutputAmount: 0n,
311
+ permitData: '0x'
312
+ },
313
+ // ✅ 如果使用原生代币,value 为购买金额;否则为 0
314
+ useNativeToken ? { value: fundsList[i] } : {})));
315
+ }
288
316
  function buildGasLimitList(length, config) {
289
317
  const gasLimit = getGasLimit(config);
290
318
  return new Array(length).fill(gasLimit);
@@ -356,6 +384,23 @@ async function quoteSellOutputs(portal, tokenAddress, amountsWei) {
356
384
  }
357
385
  }));
358
386
  }
387
+ /**
388
+ * ✅ 支持 quoteToken 的卖出报价
389
+ */
390
+ async function quoteSellOutputsWithQuote(portal, tokenAddress, amountsWei, outputToken) {
391
+ return await Promise.all(amountsWei.map(async (amount) => {
392
+ try {
393
+ return await portal.quoteExactInput.staticCall({
394
+ inputToken: tokenAddress,
395
+ outputToken, // ✅ 使用动态 outputToken
396
+ inputAmount: amount
397
+ });
398
+ }
399
+ catch {
400
+ return 0n;
401
+ }
402
+ }));
403
+ }
359
404
  function resolveMinOutputs(provided, walletCount, quotedOutputs) {
360
405
  if (provided && provided.length === walletCount) {
361
406
  return provided.map(m => typeof m === 'string' ? ethers.parseEther(m) : BigInt(m));
@@ -119,6 +119,8 @@ export type FlapBatchBuySignParams = {
119
119
  privateKeys: string[];
120
120
  buyAmounts: string[];
121
121
  tokenAddress: string;
122
+ /** 报价代币地址(如 USDC),零地址或不传表示使用原生代币(MON/BNB) */
123
+ quoteToken?: string;
122
124
  minOutputAmounts?: (string | bigint)[];
123
125
  config: FlapSignConfig;
124
126
  };
@@ -139,6 +141,8 @@ export type FlapBatchSellSignParams = {
139
141
  privateKeys: string[];
140
142
  sellAmounts: string[];
141
143
  tokenAddress: string;
144
+ /** 报价代币地址(如 USDC),零地址或不传表示输出原生代币(MON/BNB) */
145
+ quoteToken?: string;
142
146
  minOutputAmounts?: (string | bigint)[];
143
147
  config: FlapSignConfig;
144
148
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.2.92",
3
+ "version": "1.2.95",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",