four-flap-meme-sdk 1.4.11 → 1.4.13
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.
- package/dist/dex/direct-router.js +3 -307
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/pancake/bundle-swap.d.ts +8 -4
- package/dist/pancake/bundle-swap.js +305 -357
- package/dist/utils/quote-helpers.d.ts +111 -0
- package/dist/utils/quote-helpers.js +358 -0
- package/package.json +1 -1
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { ethers, Wallet, JsonRpcProvider, Contract } from 'ethers';
|
|
11
11
|
import { NonceManager, getOptimizedGasPrice } from '../utils/bundle-helpers.js';
|
|
12
12
|
import { PROFIT_CONFIG } from '../utils/constants.js';
|
|
13
|
+
import { getTokenToNativeQuote } from '../utils/quote-helpers.js';
|
|
13
14
|
// ============================================================================
|
|
14
15
|
// 常量配置
|
|
15
16
|
// ============================================================================
|
|
@@ -44,56 +45,7 @@ const DEFAULT_GAS_LIMIT = 300000;
|
|
|
44
45
|
const DEADLINE_MINUTES = 20;
|
|
45
46
|
// ✅ BlockRazor Builder EOA 地址(用于贿赂,仅 BSC 链)
|
|
46
47
|
const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
|
|
47
|
-
// ✅ V2
|
|
48
|
-
const QUOTE_ROUTER_ABI = [
|
|
49
|
-
'function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts)'
|
|
50
|
-
];
|
|
51
|
-
// ✅ V3 QuoterV2 ABI(用于 V3 报价)
|
|
52
|
-
// PancakeSwap V3 使用结构体参数版本
|
|
53
|
-
const V3_QUOTER_ABI = [
|
|
54
|
-
{
|
|
55
|
-
"inputs": [{
|
|
56
|
-
"components": [
|
|
57
|
-
{ "name": "tokenIn", "type": "address" },
|
|
58
|
-
{ "name": "tokenOut", "type": "address" },
|
|
59
|
-
{ "name": "amountIn", "type": "uint256" },
|
|
60
|
-
{ "name": "fee", "type": "uint24" },
|
|
61
|
-
{ "name": "sqrtPriceLimitX96", "type": "uint160" }
|
|
62
|
-
],
|
|
63
|
-
"name": "params",
|
|
64
|
-
"type": "tuple"
|
|
65
|
-
}],
|
|
66
|
-
"name": "quoteExactInputSingle",
|
|
67
|
-
"outputs": [
|
|
68
|
-
{ "name": "amountOut", "type": "uint256" },
|
|
69
|
-
{ "name": "sqrtPriceX96After", "type": "uint160" },
|
|
70
|
-
{ "name": "initializedTicksCrossed", "type": "uint32" },
|
|
71
|
-
{ "name": "gasEstimate", "type": "uint256" }
|
|
72
|
-
],
|
|
73
|
-
"stateMutability": "nonpayable",
|
|
74
|
-
"type": "function"
|
|
75
|
-
}
|
|
76
|
-
];
|
|
77
|
-
// ✅ 各链的报价配置(V2 Router + V3 Quoter)
|
|
78
|
-
const QUOTE_CONFIG = {
|
|
79
|
-
BSC: {
|
|
80
|
-
router: '0x10ED43C718714eb63d5aA57B78B54704E256024E', // PancakeSwap V2 Router
|
|
81
|
-
quoter: '0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997', // PancakeSwap V3 Quoter
|
|
82
|
-
wrappedNative: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c', // WBNB
|
|
83
|
-
},
|
|
84
|
-
MONAD: {
|
|
85
|
-
router: '0xb1bc24c34e88f7d43d5923034e3a14b24daacff9', // PancakeSwap V2
|
|
86
|
-
quoter: '', // TODO: 添加 Monad V3 Quoter
|
|
87
|
-
wrappedNative: '0x3bd359c1119da7da1d913d1c4d2b7c461115433a', // WMON
|
|
88
|
-
},
|
|
89
|
-
XLAYER: {
|
|
90
|
-
router: '0x881fb2f98c13d521009464e7d1cbf16e1b394e8e', // PotatoSwap V2
|
|
91
|
-
quoter: '', // TODO: 添加 XLayer V3 Quoter
|
|
92
|
-
wrappedNative: '0xe538905cf8410324e03a5a23c1c177a474d59b2b', // WOKB
|
|
93
|
-
},
|
|
94
|
-
};
|
|
95
|
-
// ✅ V3 常用费率档位(用于报价尝试)
|
|
96
|
-
const V3_FEE_TIERS = [100, 500, 2500, 10000]; // 0.01%, 0.05%, 0.25%, 1%
|
|
48
|
+
// ✅ V2/V3 报价相关常量和函数已移至 ../utils/quote-helpers.ts
|
|
97
49
|
/**
|
|
98
50
|
* 截断小数位数,避免超过代币精度导致 parseUnits 报错
|
|
99
51
|
* 例如:truncateDecimals("21906.025000000000000000", 1) => "21906.0"
|
|
@@ -255,92 +207,6 @@ const DYORSWAP_SELECTORS = {
|
|
|
255
207
|
*/
|
|
256
208
|
function encodeDYORSwapExactTokensForTokens(amountIn, amountOutMin, path, pools, to, // 可以是地址 (string) 或 address(2) 这样的特殊值 (bigint)
|
|
257
209
|
flag, factory) {
|
|
258
|
-
const abiCoder = ethers.AbiCoder.defaultAbiCoder();
|
|
259
|
-
// 固定参数: amountIn, amountOutMin, offset_path, offset_pools, to, flag, factory
|
|
260
|
-
// 共 7 个 slot = 7 * 32 = 224 bytes
|
|
261
|
-
//
|
|
262
|
-
// offset 是从参数区域开始计算的,不是从固定参数后面
|
|
263
|
-
// path offset = 5 * 32 = 160 (跳过 amountIn, amountOutMin, offset_path, offset_pools, to)
|
|
264
|
-
// 不对,成功交易显示 offset = 160 = 0xa0,而固定参数有 7 个
|
|
265
|
-
//
|
|
266
|
-
// 重新分析:offset 可能是从某个特定位置开始
|
|
267
|
-
// 成功交易: path offset = 160, pools offset = 224
|
|
268
|
-
// 差值 = 64 = 2 * 32 (path 有 2 个元素)
|
|
269
|
-
//
|
|
270
|
-
// 所以 offset 是从 (amountIn, amountOutMin, offset_path, offset_pools, to) 之后开始
|
|
271
|
-
// 即 5 * 32 = 160 是 path 数据的开始位置
|
|
272
|
-
// 计算 path 和 pools 数据
|
|
273
|
-
const pathDataRaw = abiCoder.encode(['address[]'], [path]).slice(2);
|
|
274
|
-
const poolsDataRaw = abiCoder.encode(['address[]'], [pools]).slice(2);
|
|
275
|
-
// offset 从第 5 个参数后开始 (跳过 amountIn, amountOutMin, offset_path, offset_pools, to)
|
|
276
|
-
// 但实际上,ABI 编码中 offset 是从整个编码数据的开始计算的
|
|
277
|
-
// 7 个固定参数 * 32 = 224 bytes
|
|
278
|
-
// 但成功交易显示 path offset = 160,这意味着它是从某个不同的基准点计算的
|
|
279
|
-
// 让我们直接使用成功交易的模式:
|
|
280
|
-
// path offset = 5 * 32 = 160 (第 5 个 slot 后开始,即 to 之后)
|
|
281
|
-
// 但 to 在 slot 4,flag 在 slot 5,factory 在 slot 6
|
|
282
|
-
// 所以 path 数据在 slot 7 开始
|
|
283
|
-
//
|
|
284
|
-
// 等等,offset 160 = 5 * 32,但 slot 5 是 flag
|
|
285
|
-
// 这说明 offset 是相对于整个参数数据的开始(不包括 selector)
|
|
286
|
-
//
|
|
287
|
-
// 重新计算:
|
|
288
|
-
// slot 0: amountIn
|
|
289
|
-
// slot 1: amountOutMin
|
|
290
|
-
// slot 2: path offset
|
|
291
|
-
// slot 3: pools offset
|
|
292
|
-
// slot 4: to
|
|
293
|
-
// slot 5: flag
|
|
294
|
-
// slot 6: factory
|
|
295
|
-
// slot 7: path.length (offset 160 指向这里? 不对,160/32 = 5)
|
|
296
|
-
//
|
|
297
|
-
// 160 / 32 = 5,所以 offset 160 指向 slot 5
|
|
298
|
-
// 但 slot 5 是 flag,不是 path.length
|
|
299
|
-
//
|
|
300
|
-
// 我觉得这个 ABI 可能有特殊的编码方式,让我直接复制成功交易的结构
|
|
301
|
-
// 根据成功交易,参数顺序和 offset 计算方式:
|
|
302
|
-
// [0] amountIn
|
|
303
|
-
// [1] amountOutMin
|
|
304
|
-
// [2] path offset = 0xa0 = 160
|
|
305
|
-
// [3] pools offset = 0xe0 = 224
|
|
306
|
-
// [4] to
|
|
307
|
-
// [5] flag
|
|
308
|
-
// [6] factory
|
|
309
|
-
// [7] path.length = 2
|
|
310
|
-
// [8] path[0]
|
|
311
|
-
// [9] path[1]
|
|
312
|
-
// [10] pools.length = 1
|
|
313
|
-
// [11] pools[0]
|
|
314
|
-
// 160 / 32 = 5,指向 slot 5,但 slot 5 是 flag
|
|
315
|
-
// 这说明 offset 可能不是标准的 ABI 编码
|
|
316
|
-
//
|
|
317
|
-
// 让我尝试另一种理解:offset 是从 (to, flag, factory) 之后开始
|
|
318
|
-
// 即 offset 0 = slot 7 的位置
|
|
319
|
-
// 那么 path offset = 160 - 7*32 = 160 - 224 = -64? 不对
|
|
320
|
-
//
|
|
321
|
-
// 让我直接硬编码 offset 值:
|
|
322
|
-
// path offset = 0xa0 = 160
|
|
323
|
-
// pools offset = path offset + (1 + path.length) * 32
|
|
324
|
-
// = 160 + (1 + 2) * 32 = 160 + 96 = 256? 但成功交易是 224
|
|
325
|
-
//
|
|
326
|
-
// 成功交易: pools offset = 224 = 0xe0
|
|
327
|
-
// 224 - 160 = 64 = 2 * 32
|
|
328
|
-
// 所以 pools offset = path offset + path.length * 32 (不包括 length slot?)
|
|
329
|
-
//
|
|
330
|
-
// 让我直接按成功交易的模式来:
|
|
331
|
-
// path offset = 5 * 32 = 160 (固定)
|
|
332
|
-
// pools offset = path offset + 32 + path.length * 32
|
|
333
|
-
// = 160 + 32 + 2 * 32 = 160 + 96 = 256? 还是不对
|
|
334
|
-
//
|
|
335
|
-
// 实际 pools offset = 224 = 160 + 64 = 160 + 2 * 32
|
|
336
|
-
// 所以 pools offset = path offset + path.length * 32 (不算 length slot)
|
|
337
|
-
//
|
|
338
|
-
// 但这不符合标准 ABI 编码...让我直接试试
|
|
339
|
-
// 成功交易分析:
|
|
340
|
-
// pathOffset = 160 (0xa0) = 5 * 32
|
|
341
|
-
// poolsOffset = 224 (0xe0) = 7 * 32
|
|
342
|
-
// 但实际上没有单独的 pools 数据!
|
|
343
|
-
// poolsOffset 指向的是 path 数据结束后的位置(空)
|
|
344
210
|
const pathOffset = 5n * 32n; // 160
|
|
345
211
|
// poolsOffset = pathOffset + (1 + path.length) * 32 = 160 + 96 = 256?
|
|
346
212
|
// 不对,成功交易是 224 = 160 + 64 = pathOffset + path.length * 32
|
|
@@ -582,177 +448,7 @@ async function getGasPrice(provider, config) {
|
|
|
582
448
|
function isNativeToken(quoteToken) {
|
|
583
449
|
return !quoteToken || quoteToken === ZERO_ADDRESS;
|
|
584
450
|
}
|
|
585
|
-
// ✅
|
|
586
|
-
const STABLE_COINS = {
|
|
587
|
-
BSC: [
|
|
588
|
-
'0x55d398326f99059fF775485246999027B3197955', // USDT
|
|
589
|
-
'0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d', // USDC
|
|
590
|
-
'0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56', // BUSD
|
|
591
|
-
],
|
|
592
|
-
MONAD: [],
|
|
593
|
-
XLAYER: [
|
|
594
|
-
'0x1E4a5963aBFD975d8c9021ce480b42188849D41d', // USDT
|
|
595
|
-
],
|
|
596
|
-
};
|
|
597
|
-
/**
|
|
598
|
-
* ✅ 获取 ERC20 代币 → 原生代币的报价
|
|
599
|
-
* 用于将 ERC20 利润转换为原生代币(和 core.ts 逻辑一致)
|
|
600
|
-
*
|
|
601
|
-
* @param provider - Provider 实例
|
|
602
|
-
* @param tokenAddress - ERC20 代币地址
|
|
603
|
-
* @param tokenAmount - 代币数量(wei)
|
|
604
|
-
* @param chain - 链名称
|
|
605
|
-
* @param version - 'v2' | 'v3',指定使用哪个版本的报价
|
|
606
|
-
* @param fee - V3 费率档位(仅 V3 时使用)
|
|
607
|
-
* @returns 等值的原生代币数量(wei),失败返回 0n
|
|
608
|
-
*/
|
|
609
|
-
async function getTokenToNativeQuote(provider, tokenAddress, tokenAmount, chain, version = 'v2', fee) {
|
|
610
|
-
if (tokenAmount <= 0n)
|
|
611
|
-
return 0n;
|
|
612
|
-
const chainUpper = chain.toUpperCase();
|
|
613
|
-
const config = QUOTE_CONFIG[chainUpper];
|
|
614
|
-
if (!config) {
|
|
615
|
-
console.warn(`[getTokenToNativeQuote] 不支持的链: ${chain}`);
|
|
616
|
-
return 0n;
|
|
617
|
-
}
|
|
618
|
-
const tokenLower = tokenAddress.toLowerCase();
|
|
619
|
-
const wrappedNativeLower = config.wrappedNative.toLowerCase();
|
|
620
|
-
const stableCoins = STABLE_COINS[chainUpper] || [];
|
|
621
|
-
// 如果代币本身就是包装原生代币,直接返回
|
|
622
|
-
if (tokenLower === wrappedNativeLower) {
|
|
623
|
-
return tokenAmount;
|
|
624
|
-
}
|
|
625
|
-
// ==================== V2 报价 ====================
|
|
626
|
-
if (version === 'v2') {
|
|
627
|
-
const router = new Contract(config.router, QUOTE_ROUTER_ABI, provider);
|
|
628
|
-
// V2 策略 1:直接路径 代币 → WBNB
|
|
629
|
-
try {
|
|
630
|
-
const amounts = await router.getAmountsOut(tokenAmount, [tokenAddress, config.wrappedNative]);
|
|
631
|
-
const nativeAmount = amounts[1];
|
|
632
|
-
if (nativeAmount > 0n) {
|
|
633
|
-
console.log(`[getTokenToNativeQuote] V2 直接路径成功: ${ethers.formatEther(nativeAmount)} BNB`);
|
|
634
|
-
return nativeAmount;
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
catch {
|
|
638
|
-
// V2 直接路径失败,尝试多跳
|
|
639
|
-
}
|
|
640
|
-
// V2 策略 2:多跳路径 代币 → 稳定币 → WBNB
|
|
641
|
-
for (const stableCoin of stableCoins) {
|
|
642
|
-
// 跳过:代币本身就是稳定币
|
|
643
|
-
if (tokenLower === stableCoin.toLowerCase()) {
|
|
644
|
-
try {
|
|
645
|
-
const amounts = await router.getAmountsOut(tokenAmount, [stableCoin, config.wrappedNative]);
|
|
646
|
-
const nativeAmount = amounts[1];
|
|
647
|
-
if (nativeAmount > 0n) {
|
|
648
|
-
console.log(`[getTokenToNativeQuote] V2 稳定币直接路径成功: ${ethers.formatEther(nativeAmount)} BNB`);
|
|
649
|
-
return nativeAmount;
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
catch {
|
|
653
|
-
continue;
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
// 多跳:代币 → 稳定币 → WBNB
|
|
657
|
-
try {
|
|
658
|
-
const amounts = await router.getAmountsOut(tokenAmount, [tokenAddress, stableCoin, config.wrappedNative]);
|
|
659
|
-
const nativeAmount = amounts[2];
|
|
660
|
-
if (nativeAmount > 0n) {
|
|
661
|
-
console.log(`[getTokenToNativeQuote] V2 多跳路径成功 (via ${stableCoin.slice(0, 10)}...): ${ethers.formatEther(nativeAmount)} BNB`);
|
|
662
|
-
return nativeAmount;
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
catch {
|
|
666
|
-
continue;
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
console.warn(`[getTokenToNativeQuote] V2 所有报价路径均失败,跳过利润提取`);
|
|
670
|
-
return 0n;
|
|
671
|
-
}
|
|
672
|
-
// ==================== V3 报价 ====================
|
|
673
|
-
if (version === 'v3') {
|
|
674
|
-
if (!config.quoter) {
|
|
675
|
-
console.warn(`[getTokenToNativeQuote] 该链不支持 V3 Quoter: ${chain}`);
|
|
676
|
-
return 0n;
|
|
677
|
-
}
|
|
678
|
-
const quoter = new Contract(config.quoter, V3_QUOTER_ABI, provider);
|
|
679
|
-
// V3 策略 1:直接路径 代币 → WBNB
|
|
680
|
-
// 如果指定了 fee,只用指定的 fee;否则尝试所有费率
|
|
681
|
-
const feesToTry = fee ? [fee] : V3_FEE_TIERS;
|
|
682
|
-
console.log(`[getTokenToNativeQuote] 开始 V3 报价: token=${tokenAddress.slice(0, 10)}..., amount=${tokenAmount}, feesToTry=${feesToTry}`);
|
|
683
|
-
for (const tryFee of feesToTry) {
|
|
684
|
-
try {
|
|
685
|
-
// ✅ 使用结构体参数调用 QuoterV2
|
|
686
|
-
const result = await quoter.quoteExactInputSingle.staticCall({
|
|
687
|
-
tokenIn: tokenAddress,
|
|
688
|
-
tokenOut: config.wrappedNative,
|
|
689
|
-
amountIn: tokenAmount,
|
|
690
|
-
fee: tryFee,
|
|
691
|
-
sqrtPriceLimitX96: 0n
|
|
692
|
-
});
|
|
693
|
-
// QuoterV2 返回多个值,第一个是 amountOut
|
|
694
|
-
const amountOut = result[0];
|
|
695
|
-
if (amountOut > 0n) {
|
|
696
|
-
console.log(`[getTokenToNativeQuote] V3 直接路径成功 (fee=${tryFee}): ${ethers.formatEther(amountOut)} BNB`);
|
|
697
|
-
return amountOut;
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
catch (err) {
|
|
701
|
-
console.log(`[getTokenToNativeQuote] V3 直接路径失败 (fee=${tryFee}): ${String(err).slice(0, 100)}`);
|
|
702
|
-
continue;
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
// V3 策略 2:多跳路径 代币 → USDT → WBNB
|
|
706
|
-
for (const stableCoin of stableCoins) {
|
|
707
|
-
if (tokenLower === stableCoin.toLowerCase())
|
|
708
|
-
continue;
|
|
709
|
-
for (const fee1 of feesToTry) {
|
|
710
|
-
try {
|
|
711
|
-
// 第一跳:代币 → 稳定币(使用结构体参数)
|
|
712
|
-
const midResult = await quoter.quoteExactInputSingle.staticCall({
|
|
713
|
-
tokenIn: tokenAddress,
|
|
714
|
-
tokenOut: stableCoin,
|
|
715
|
-
amountIn: tokenAmount,
|
|
716
|
-
fee: fee1,
|
|
717
|
-
sqrtPriceLimitX96: 0n
|
|
718
|
-
});
|
|
719
|
-
const midAmount = midResult[0];
|
|
720
|
-
if (midAmount <= 0n)
|
|
721
|
-
continue;
|
|
722
|
-
console.log(`[getTokenToNativeQuote] V3 第一跳成功: 代币 → ${stableCoin.slice(0, 10)}... = ${midAmount}`);
|
|
723
|
-
// 第二跳:稳定币 → WBNB(尝试多个费率)
|
|
724
|
-
const stableFees = [100, 500, 2500]; // 0.01%, 0.05%, 0.25%
|
|
725
|
-
for (const fee2 of stableFees) {
|
|
726
|
-
try {
|
|
727
|
-
const finalResult = await quoter.quoteExactInputSingle.staticCall({
|
|
728
|
-
tokenIn: stableCoin,
|
|
729
|
-
tokenOut: config.wrappedNative,
|
|
730
|
-
amountIn: midAmount,
|
|
731
|
-
fee: fee2,
|
|
732
|
-
sqrtPriceLimitX96: 0n
|
|
733
|
-
});
|
|
734
|
-
const amountOut = finalResult[0];
|
|
735
|
-
if (amountOut > 0n) {
|
|
736
|
-
console.log(`[getTokenToNativeQuote] V3 多跳路径成功 (${fee1}→${fee2}): ${ethers.formatEther(amountOut)} BNB`);
|
|
737
|
-
return amountOut;
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
catch {
|
|
741
|
-
continue;
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
catch (err) {
|
|
746
|
-
console.log(`[getTokenToNativeQuote] V3 第一跳失败 (fee=${fee1}): ${err}`);
|
|
747
|
-
continue;
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
console.warn(`[getTokenToNativeQuote] V3 所有报价路径均失败,跳过利润提取`);
|
|
752
|
-
return 0n;
|
|
753
|
-
}
|
|
754
|
-
return 0n;
|
|
755
|
-
}
|
|
451
|
+
// ✅ getTokenToNativeQuote 函数已移至 ../utils/quote-helpers.ts
|
|
756
452
|
/**
|
|
757
453
|
* ✅ 找到金额最大的钱包索引(和 core.ts 逻辑一致)
|
|
758
454
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -43,6 +43,7 @@ export { fourBundleBuyFirstMerkle, type FourBuyFirstConfig, type FourBundleBuyFi
|
|
|
43
43
|
export { flapBundleBuyFirstMerkle, type FlapBuyFirstSignConfig, type FlapBuyFirstConfig, type FlapBundleBuyFirstSignParams, type FlapBundleBuyFirstParams, type FlapBuyFirstResult } from './flap/portal-bundle-merkle/swap-buy-first.js';
|
|
44
44
|
export { pancakeBundleBuyFirstMerkle, type PancakeBuyFirstSignConfig, type PancakeBuyFirstConfig, type PancakeBundleBuyFirstSignParams, type PancakeBundleBuyFirstParams, type PancakeBuyFirstResult } from './pancake/bundle-buy-first.js';
|
|
45
45
|
export { PROFIT_CONFIG } from './utils/constants.js';
|
|
46
|
+
export { quoteV2, quoteV3, quote, getTokenToNativeQuote, getNativeToTokenQuote, getWrappedNativeAddress, getStableCoins, V3_FEE_TIERS, QUOTE_CONFIG, type QuoteParams, type QuoteResult, type SupportedChain, } from './utils/quote-helpers.js';
|
|
46
47
|
export { submitDirectToRpc, submitDirectToRpcSequential, // ✅ 新增:顺序广播并等待确认(用于多跳)
|
|
47
48
|
submitDirectToRpcParallel, type DirectSubmitConfig, type DirectSubmitResult, type DirectTxResult } from './contracts/tm-bundle-merkle/submit.js';
|
|
48
49
|
export { directV2BatchBuy, directV2BatchSell, directV3BatchBuy, directV3BatchSell, getRouterAddress, DIRECT_ROUTERS, type DirectV2BuyParams, type DirectV2SellParams, type DirectV3BuyParams, type DirectV3SellParams, type DirectRouterResult, type DirectRouterSignConfig, type DexKey, type RouterVersion, } from './dex/index.js';
|
package/dist/index.js
CHANGED
|
@@ -63,6 +63,8 @@ export { flapBundleBuyFirstMerkle } from './flap/portal-bundle-merkle/swap-buy-f
|
|
|
63
63
|
export { pancakeBundleBuyFirstMerkle } from './pancake/bundle-buy-first.js';
|
|
64
64
|
// ✅ 硬编码利润配置(统一管理)
|
|
65
65
|
export { PROFIT_CONFIG } from './utils/constants.js';
|
|
66
|
+
// ✅ V2/V3 报价工具(统一管理)
|
|
67
|
+
export { quoteV2, quoteV3, quote, getTokenToNativeQuote, getNativeToTokenQuote, getWrappedNativeAddress, getStableCoins, V3_FEE_TIERS, QUOTE_CONFIG, } from './utils/quote-helpers.js';
|
|
66
68
|
// ✅ Monad 等不支持 Bundle 的链:逐笔 RPC 广播方法(服务器端使用)
|
|
67
69
|
export { submitDirectToRpc, submitDirectToRpcSequential, // ✅ 新增:顺序广播并等待确认(用于多跳)
|
|
68
70
|
submitDirectToRpcParallel } from './contracts/tm-bundle-merkle/submit.js';
|
|
@@ -129,6 +129,8 @@ export interface PancakeQuickBatchSwapParams {
|
|
|
129
129
|
tokenAddress: string;
|
|
130
130
|
routeParams: RouteParams;
|
|
131
131
|
config: PancakeSwapSignConfig;
|
|
132
|
+
quoteToken?: string;
|
|
133
|
+
quoteTokenDecimals?: number;
|
|
132
134
|
}
|
|
133
135
|
/**
|
|
134
136
|
* 快捷批量换手结果
|
|
@@ -139,21 +141,23 @@ export interface PancakeQuickBatchSwapResult {
|
|
|
139
141
|
sellerAddress: string;
|
|
140
142
|
buyerAddresses: string[];
|
|
141
143
|
sellAmount: string;
|
|
142
|
-
|
|
144
|
+
estimatedOutput: string;
|
|
143
145
|
transferAmounts: string[];
|
|
144
146
|
profitAmount?: string;
|
|
147
|
+
useNativeToken: boolean;
|
|
145
148
|
};
|
|
146
149
|
}
|
|
147
150
|
/**
|
|
148
151
|
* PancakeSwap 快捷批量换手(资金自动流转)
|
|
149
152
|
*
|
|
150
|
-
* 流程:[贿赂] → [卖出] → [
|
|
153
|
+
* 流程:[贿赂] → [卖出] → [转账1, 转账2, ...] → [买入1, 买入2, ...] → [利润]
|
|
151
154
|
*
|
|
152
155
|
* 特点:
|
|
153
|
-
* -
|
|
156
|
+
* - 子钱包不需要预先有余额
|
|
154
157
|
* - 资金来自主钱包卖出代币所得
|
|
155
158
|
* - 提升资金利用率
|
|
159
|
+
* - 支持 BNB 和 ERC20(如 USDT)两种模式
|
|
156
160
|
*
|
|
157
|
-
* 限制:最多
|
|
161
|
+
* 限制:最多 23 个买方(转账 + 买入 = 46 笔,加上贿赂/卖出/利润 = 50 笔限制)
|
|
158
162
|
*/
|
|
159
163
|
export declare function pancakeQuickBatchSwapMerkle(params: PancakeQuickBatchSwapParams): Promise<PancakeQuickBatchSwapResult>;
|