four-flap-meme-sdk 1.2.95 → 1.2.97
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.
|
@@ -124,9 +124,9 @@ export async function createTokenWithBundleBuyMerkle(params) {
|
|
|
124
124
|
* ✅ 支持 quoteToken:传入 USDC 等地址时使用该代币购买,否则使用原生代币
|
|
125
125
|
*/
|
|
126
126
|
export async function batchBuyWithBundleMerkle(params) {
|
|
127
|
-
const { chain, privateKeys, buyAmounts, tokenAddress, quoteToken, config } = params;
|
|
127
|
+
const { chain, privateKeys, buyAmounts, tokenAddress, quoteToken, quoteTokenDecimals, config } = params;
|
|
128
128
|
console.log('🔍 SDK batchBuyWithBundleMerkle - quoteToken:', quoteToken);
|
|
129
|
-
console.log('🔍 SDK batchBuyWithBundleMerkle -
|
|
129
|
+
console.log('🔍 SDK batchBuyWithBundleMerkle - quoteTokenDecimals:', quoteTokenDecimals);
|
|
130
130
|
if (privateKeys.length === 0 || buyAmounts.length !== privateKeys.length) {
|
|
131
131
|
throw new Error(getErrorMessage('KEY_AMOUNT_MISMATCH'));
|
|
132
132
|
}
|
|
@@ -142,12 +142,25 @@ export async function batchBuyWithBundleMerkle(params) {
|
|
|
142
142
|
const inputToken = quoteToken && quoteToken !== ZERO_ADDRESS ? quoteToken : ZERO_ADDRESS;
|
|
143
143
|
// ✅ 如果使用非原生代币,则 value 应为 0(不发送原生代币)
|
|
144
144
|
const useNativeToken = inputToken === ZERO_ADDRESS;
|
|
145
|
+
// ✅ 如果使用非原生代币(如 USDC),需要根据精度转换金额
|
|
146
|
+
// buyAmounts 是按 18 位精度传入的,需要转换为目标代币精度
|
|
147
|
+
let adjustedFundsList = fundsList;
|
|
148
|
+
if (!useNativeToken && quoteTokenDecimals !== undefined && quoteTokenDecimals !== 18) {
|
|
149
|
+
// 从 18 位精度转换为目标精度
|
|
150
|
+
// 例如:0.1 ETH (18位) = 100000000000000000 wei
|
|
151
|
+
// 转为 USDC (6位) = 100000 (0.1 USDC)
|
|
152
|
+
const decimalsDiff = 18 - quoteTokenDecimals;
|
|
153
|
+
const divisor = BigInt(10 ** decimalsDiff);
|
|
154
|
+
adjustedFundsList = fundsList.map(amount => amount / divisor);
|
|
155
|
+
console.log('🔍 SDK 精度转换: 18 -> ', quoteTokenDecimals, ', 原始:', fundsList, ', 转换后:', adjustedFundsList);
|
|
156
|
+
}
|
|
145
157
|
console.log('🔍 SDK inputToken 计算结果:', inputToken);
|
|
146
158
|
console.log('🔍 SDK useNativeToken:', useNativeToken);
|
|
159
|
+
console.log('🔍 SDK adjustedFundsList:', adjustedFundsList);
|
|
147
160
|
// ✅ 优化:并行执行 gasPrice 和 populateBuyTransactions(最耗时的两个操作)
|
|
148
161
|
const [gasPrice, unsignedBuys] = await Promise.all([
|
|
149
162
|
resolveGasPrice(provider, config),
|
|
150
|
-
populateBuyTransactionsWithQuote(buyers, FLAP_PORTAL_ADDRESSES[chain], tokenAddress,
|
|
163
|
+
populateBuyTransactionsWithQuote(buyers, FLAP_PORTAL_ADDRESSES[chain], tokenAddress, adjustedFundsList, inputToken, useNativeToken)
|
|
151
164
|
]);
|
|
152
165
|
const buyerNonces = await allocateBuyerNonces(buyers, extractProfit, maxFundsIndex, totalProfit, nonceManager);
|
|
153
166
|
const signedBuys = await signBuyTransactions({
|
|
@@ -121,6 +121,8 @@ export type FlapBatchBuySignParams = {
|
|
|
121
121
|
tokenAddress: string;
|
|
122
122
|
/** 报价代币地址(如 USDC),零地址或不传表示使用原生代币(MON/BNB) */
|
|
123
123
|
quoteToken?: string;
|
|
124
|
+
/** ✅ 报价代币精度(如 USDC 为 6),不传默认 18 */
|
|
125
|
+
quoteTokenDecimals?: number;
|
|
124
126
|
minOutputAmounts?: (string | bigint)[];
|
|
125
127
|
config: FlapSignConfig;
|
|
126
128
|
};
|
package/dist/utils/lp-inspect.js
CHANGED
|
@@ -37,9 +37,27 @@ const I_UNIV3_FACTORY_ABI = ['function getPool(address,address,uint24) view retu
|
|
|
37
37
|
const I_ROUTER_WITH_FACTORY_ABI = ['function factory() view returns (address)'];
|
|
38
38
|
// 数字转字符串(避免 BigInt JSON 兼容问题)
|
|
39
39
|
function toStr(v) { return typeof v === 'bigint' ? v.toString() : String(v); }
|
|
40
|
-
// 格式化余额:将 Wei
|
|
41
|
-
function formatBalance(balance, format) {
|
|
42
|
-
return format ? formatUnits(balance,
|
|
40
|
+
// 格式化余额:将 Wei 转换为指定精度的单位
|
|
41
|
+
function formatBalance(balance, format, decimals = 18) {
|
|
42
|
+
return format ? formatUnits(balance, decimals) : balance.toString();
|
|
43
|
+
}
|
|
44
|
+
// ✅ 动态查询代币精度(带缓存)
|
|
45
|
+
const decimalsCache = new Map();
|
|
46
|
+
async function getTokenDecimals(tokenAddress, provider) {
|
|
47
|
+
const key = tokenAddress.toLowerCase();
|
|
48
|
+
if (decimalsCache.has(key)) {
|
|
49
|
+
return decimalsCache.get(key);
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const contract = new Contract(tokenAddress, I_ERC20_ABI, provider);
|
|
53
|
+
const decimals = await contract.decimals();
|
|
54
|
+
const result = Number(decimals);
|
|
55
|
+
decimalsCache.set(key, result);
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return 18; // 默认 18 位精度
|
|
60
|
+
}
|
|
43
61
|
}
|
|
44
62
|
export async function inspectTokenLP(token, opts) {
|
|
45
63
|
const provider = new JsonRpcProvider(opts.rpcUrl);
|
|
@@ -189,7 +207,9 @@ export async function inspectTokenLP(token, opts) {
|
|
|
189
207
|
const [r0, r1] = await pair.getReserves();
|
|
190
208
|
const reserveToken = t0.toLowerCase() === token.toLowerCase() ? r0 : r1;
|
|
191
209
|
const reserveWBNB = t0.toLowerCase() === chainTokens.wrappedNative.toLowerCase() ? r0 : r1;
|
|
192
|
-
|
|
210
|
+
// ✅ 动态查询 WBNB/WMON 精度
|
|
211
|
+
const wbnbDecimals = await getTokenDecimals(chainTokens.wrappedNative, provider);
|
|
212
|
+
v2.wbnbPair = { address: v2PairWbnb, reserveToken: formatBalance(reserveToken, shouldFormat, tokenDecimals ?? 18), reserveWBNB: formatBalance(reserveWBNB, shouldFormat, wbnbDecimals) };
|
|
193
213
|
}
|
|
194
214
|
catch {
|
|
195
215
|
v2.wbnbPair = { address: v2PairWbnb, reserveToken: '0', reserveWBNB: '0' };
|
|
@@ -207,7 +227,9 @@ export async function inspectTokenLP(token, opts) {
|
|
|
207
227
|
const [r0, r1] = await pair.getReserves();
|
|
208
228
|
const reserveToken = t0.toLowerCase() === token.toLowerCase() ? r0 : r1;
|
|
209
229
|
const reserveUSDT = t0.toLowerCase() === chainTokens.stableCoin.toLowerCase() ? r0 : r1;
|
|
210
|
-
|
|
230
|
+
// ✅ 动态查询稳定币精度
|
|
231
|
+
const stableDecimals = await getTokenDecimals(chainTokens.stableCoin, provider);
|
|
232
|
+
v2.usdtPair = { address: v2PairUsdt, reserveToken: formatBalance(reserveToken, shouldFormat, tokenDecimals ?? 18), reserveUSDT: formatBalance(reserveUSDT, shouldFormat, stableDecimals) };
|
|
211
233
|
}
|
|
212
234
|
catch {
|
|
213
235
|
v2.usdtPair = { address: v2PairUsdt, reserveToken: '0', reserveUSDT: '0' };
|
|
@@ -328,7 +350,9 @@ export async function inspectTokenLP(token, opts) {
|
|
|
328
350
|
console.log(`[V3 Debug] ${p.base} fee=${p.fee}: base balance decode error`, err);
|
|
329
351
|
}
|
|
330
352
|
idx++;
|
|
331
|
-
|
|
353
|
+
// ✅ 动态查询基础代币精度
|
|
354
|
+
const baseDecimals = await getTokenDecimals(p.baseAddress, provider);
|
|
355
|
+
v3Results.push({ base: p.base, fee: p.fee, pool: p.pool, tokenBalance: formatBalance(tb, shouldFormat, tokenDecimals ?? 18), baseBalance: formatBalance(bb, shouldFormat, baseDecimals) });
|
|
332
356
|
}
|
|
333
357
|
if (v3Results.length > 0)
|
|
334
358
|
out.v3 = v3Results;
|
|
@@ -370,7 +394,9 @@ export async function inspectTokenLP(token, opts) {
|
|
|
370
394
|
bb = await baseContract.balanceOf(pool);
|
|
371
395
|
}
|
|
372
396
|
catch { }
|
|
373
|
-
|
|
397
|
+
// ✅ 动态查询基础代币精度
|
|
398
|
+
const baseDecimals = await getTokenDecimals(baseAddr, provider);
|
|
399
|
+
v3Results.push({ base: basePair.symbol, fee, pool, tokenBalance: formatBalance(tb, shouldFormat, tokenDecimals ?? 18), baseBalance: formatBalance(bb, shouldFormat, baseDecimals) });
|
|
374
400
|
}
|
|
375
401
|
}
|
|
376
402
|
}
|