four-flap-meme-sdk 1.4.25 → 1.4.26
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/abis/common.d.ts +85 -0
- package/dist/abis/common.js +242 -0
- package/dist/abis/index.d.ts +1 -0
- package/dist/abis/index.js +2 -0
- package/dist/contracts/tm-bundle-merkle/approve-tokenmanager.js +1 -6
- package/dist/contracts/tm-bundle-merkle/core.js +9 -16
- package/dist/contracts/tm-bundle-merkle/internal.js +6 -8
- package/dist/contracts/tm-bundle-merkle/pancake-proxy.d.ts +12 -6
- package/dist/contracts/tm-bundle-merkle/pancake-proxy.js +224 -166
- package/dist/contracts/tm-bundle-merkle/private.js +6 -19
- package/dist/contracts/tm-bundle-merkle/swap-buy-first.js +2 -7
- package/dist/contracts/tm-bundle-merkle/swap-internal.d.ts +1 -1
- package/dist/contracts/tm-bundle-merkle/swap-internal.js +9 -2
- package/dist/contracts/tm-bundle-merkle/swap.js +1 -3
- package/dist/contracts/tm-bundle-merkle/types.d.ts +20 -0
- package/dist/contracts/tm-bundle-merkle/utils.js +2 -3
- package/dist/dex/direct-router.d.ts +2 -1
- package/dist/dex/direct-router.js +25 -140
- package/dist/flap/constants.d.ts +2 -1
- package/dist/flap/constants.js +2 -1
- package/dist/flap/meta.js +6 -4
- package/dist/flap/portal-bundle-merkle/config.js +6 -12
- package/dist/flap/portal-bundle-merkle/core.js +8 -11
- package/dist/flap/portal-bundle-merkle/pancake-proxy.d.ts +12 -10
- package/dist/flap/portal-bundle-merkle/pancake-proxy.js +307 -370
- package/dist/flap/portal-bundle-merkle/private.js +1 -1
- package/dist/flap/portal-bundle-merkle/swap-buy-first.js +12 -30
- package/dist/flap/portal-bundle-merkle/swap.js +13 -26
- package/dist/flap/portal-bundle-merkle/types.d.ts +22 -2
- package/dist/flap/portal-bundle-merkle/utils.js +11 -16
- package/dist/index.d.ts +3 -2
- package/dist/index.js +9 -2
- package/dist/pancake/bundle-buy-first.js +56 -38
- package/dist/pancake/bundle-swap.js +114 -61
- package/dist/utils/bundle-helpers.d.ts +28 -0
- package/dist/utils/bundle-helpers.js +64 -0
- package/dist/utils/constants.d.ts +23 -1
- package/dist/utils/constants.js +37 -7
- package/dist/utils/erc20.js +17 -25
- package/dist/utils/lp-inspect.js +9 -20
- package/dist/utils/private-sale.js +1 -2
- package/dist/utils/quote-helpers.js +3 -29
- package/dist/utils/swap-helpers.js +1 -6
- package/dist/utils/wallet.d.ts +8 -13
- package/dist/utils/wallet.js +154 -342
- package/package.json +1 -1
|
@@ -1,32 +1,19 @@
|
|
|
1
1
|
import { ethers, Wallet } from 'ethers';
|
|
2
2
|
import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
|
|
3
|
-
import { ADDRESSES } from '../../utils/constants.js';
|
|
4
|
-
import {
|
|
5
|
-
} from './config.js';
|
|
6
|
-
// ✅ BlockRazor Builder EOA 地址(用于贿赂)
|
|
7
|
-
const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
|
|
8
|
-
// ✅ 已移除授权检查(前端负责确保授权)
|
|
3
|
+
import { ADDRESSES, BLOCKRAZOR_BUILDER_EOA } from '../../utils/constants.js';
|
|
4
|
+
import { TM2_ABI } from '../../abis/common.js';
|
|
5
|
+
import { getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, calculateBatchProfit, getProfitRecipient, getBribeAmount } from './config.js';
|
|
9
6
|
import { trySell } from '../tm.js';
|
|
10
7
|
const CHAIN_ID = 56;
|
|
11
8
|
const DEFAULT_GAS_LIMIT = 800000;
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
'function buyTokenAMAP(uint256 origin, address token, address to, uint256 funds, uint256 minAmount) payable',
|
|
15
|
-
'function sellToken(uint256 origin, address token, uint256 amount, uint256 minFunds)'
|
|
16
|
-
];
|
|
17
|
-
// ==================== ERC20 ABI ====================
|
|
18
|
-
const ERC20_ABI = [
|
|
19
|
-
'function approve(address spender, uint256 amount) returns (bool)',
|
|
20
|
-
'function allowance(address owner, address spender) view returns (uint256)',
|
|
21
|
-
'function decimals() view returns (uint8)'
|
|
22
|
-
];
|
|
9
|
+
// ✅ TM2_ABI 从公共模块导入
|
|
10
|
+
// ✅ 本地 getGasLimit(FourAnyConfig 支持 bigint gasLimit)
|
|
23
11
|
function getGasLimit(config, defaultGas = DEFAULT_GAS_LIMIT) {
|
|
24
12
|
if (config.gasLimit !== undefined) {
|
|
25
13
|
return typeof config.gasLimit === 'bigint' ? config.gasLimit : BigInt(config.gasLimit);
|
|
26
14
|
}
|
|
27
15
|
const multiplier = config.gasLimitMultiplier ?? 1.0;
|
|
28
|
-
|
|
29
|
-
return BigInt(calculatedGas);
|
|
16
|
+
return BigInt(Math.ceil(defaultGas * multiplier));
|
|
30
17
|
}
|
|
31
18
|
/**
|
|
32
19
|
* 私有购买(单笔)(仅签名版本 - 不依赖 Merkle)
|
|
@@ -5,16 +5,11 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { ethers, Contract, Wallet } from 'ethers';
|
|
7
7
|
import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
|
|
8
|
-
import { ADDRESSES } from '../../utils/constants.js';
|
|
8
|
+
import { ADDRESSES, PROFIT_CONFIG, BLOCKRAZOR_BUILDER_EOA } from '../../utils/constants.js';
|
|
9
9
|
import { TM_ABI, HELPER3_ABI, TM_ADDRESS } from './swap-internal.js';
|
|
10
10
|
import { getTxType, getGasPriceConfig, getProfitRecipient, getBribeAmount } from './config.js';
|
|
11
|
-
import { PROFIT_CONFIG } from '../../utils/constants.js';
|
|
12
11
|
import { trySell } from '../tm.js';
|
|
13
|
-
// ✅
|
|
14
|
-
const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
|
|
15
|
-
/**
|
|
16
|
-
* 获取 Gas Limit(支持 FourAnyConfig)
|
|
17
|
-
*/
|
|
12
|
+
// ✅ 本地 getGasLimit(FourAnyConfig 支持 bigint gasLimit)
|
|
18
13
|
function getGasLimit(config, defaultGas = 800000) {
|
|
19
14
|
if (config.gasLimit !== undefined) {
|
|
20
15
|
return typeof config.gasLimit === 'bigint' ? config.gasLimit : BigInt(config.gasLimit);
|
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
// 共享的 Swap 内部常量与 ABI
|
|
1
|
+
// 共享的 Swap 内部常量与 ABI
|
|
2
|
+
// ✅ 从公共模块重新导出
|
|
3
|
+
import { TM2_ABI, HELPER3_ABI as _HELPER3_ABI } from '../../abis/common.js';
|
|
4
|
+
import { ADDRESSES } from '../../utils/constants.js';
|
|
5
|
+
// ✅ Four.meme 内盘 ABI(与公共 TM2_ABI 扩展)
|
|
2
6
|
export const TM_ABI = [
|
|
7
|
+
...TM2_ABI,
|
|
3
8
|
'function sellToken(uint256 origin, address token, uint256 amount, uint256 minFunds) returns (uint256)',
|
|
4
9
|
'function buyTokenAMAP(uint256 origin, address token, address to, uint256 funds, uint256 minAmount) payable returns (uint256)'
|
|
5
10
|
];
|
|
11
|
+
// ✅ Helper3 ABI(与公共 HELPER3_ABI 扩展)
|
|
6
12
|
export const HELPER3_ABI = [
|
|
13
|
+
..._HELPER3_ABI,
|
|
7
14
|
'function tryBuy(address token, uint256 amount, uint256 funds) view returns (address tokenManager, address quote, uint256 estimatedAmount, uint256 estimatedCost, uint256 estimatedFee, uint256 amountMsgValue, uint256 amountApproval, uint256 amountFunds)',
|
|
8
15
|
'function trySell(address token, uint256 amount) view returns (address tokenManager, address quote, uint256 funds, uint256 fee)'
|
|
9
16
|
];
|
|
10
|
-
export const TM_ADDRESS =
|
|
17
|
+
export const TM_ADDRESS = ADDRESSES.BSC.TokenManagerV2Proxy;
|
|
@@ -6,11 +6,9 @@
|
|
|
6
6
|
import { ethers, Contract, Wallet } from 'ethers';
|
|
7
7
|
import { calculateSellAmount } from '../../utils/swap-helpers.js';
|
|
8
8
|
import { NonceManager, getOptimizedGasPrice, getGasLimit, getGasPriceConfig, getTxType } from '../../utils/bundle-helpers.js';
|
|
9
|
-
import { ADDRESSES, PROFIT_CONFIG } from '../../utils/constants.js';
|
|
9
|
+
import { ADDRESSES, PROFIT_CONFIG, BLOCKRAZOR_BUILDER_EOA } from '../../utils/constants.js';
|
|
10
10
|
import { TM_ABI, HELPER3_ABI, TM_ADDRESS } from './swap-internal.js';
|
|
11
11
|
import { getBribeAmount } from './config.js';
|
|
12
|
-
// ✅ BlockRazor Builder EOA 地址(用于贿赂)
|
|
13
|
-
const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
|
|
14
12
|
/**
|
|
15
13
|
* Four内盘捆绑换手
|
|
16
14
|
*/
|
|
@@ -334,6 +334,10 @@ export type FourPancakeProxyBatchBuyParams = {
|
|
|
334
334
|
v3Fee?: number;
|
|
335
335
|
v3LpAddresses?: string[];
|
|
336
336
|
v3ExactTokenIn?: string;
|
|
337
|
+
/** V3 多跳:代币路径 [tokenIn, tokenMid1, ..., tokenOut] */
|
|
338
|
+
v3Tokens?: string[];
|
|
339
|
+
/** V3 多跳:费率路径 [fee0, fee1, ...] - 长度 = v3Tokens.length - 1 */
|
|
340
|
+
v3Fees?: number[];
|
|
337
341
|
minOutputAmounts?: (string | bigint)[];
|
|
338
342
|
config: FourBundleMerkleConfig;
|
|
339
343
|
};
|
|
@@ -348,6 +352,10 @@ export type FourPancakeProxyBatchBuySignParams = {
|
|
|
348
352
|
v3Fee?: number;
|
|
349
353
|
v3LpAddresses?: string[];
|
|
350
354
|
v3ExactTokenIn?: string;
|
|
355
|
+
/** V3 多跳:代币路径 [tokenIn, tokenMid1, ..., tokenOut] */
|
|
356
|
+
v3Tokens?: string[];
|
|
357
|
+
/** V3 多跳:费率路径 [fee0, fee1, ...] - 长度 = v3Tokens.length - 1 */
|
|
358
|
+
v3Fees?: number[];
|
|
351
359
|
minOutputAmounts?: (string | bigint)[];
|
|
352
360
|
config: FourSignConfig;
|
|
353
361
|
};
|
|
@@ -364,6 +372,10 @@ export type FourPancakeProxyBatchSellParams = {
|
|
|
364
372
|
v3Fee?: number;
|
|
365
373
|
v3LpAddresses?: string[];
|
|
366
374
|
v3ExactTokenIn?: string;
|
|
375
|
+
/** V3 多跳:代币路径 [tokenIn, tokenMid1, ..., tokenOut] */
|
|
376
|
+
v3Tokens?: string[];
|
|
377
|
+
/** V3 多跳:费率路径 [fee0, fee1, ...] - 长度 = v3Tokens.length - 1 */
|
|
378
|
+
v3Fees?: number[];
|
|
367
379
|
minOutputAmounts?: (string | bigint)[];
|
|
368
380
|
config: FourBundleMerkleConfig;
|
|
369
381
|
};
|
|
@@ -378,6 +390,10 @@ export type FourPancakeProxyBatchSellSignParams = {
|
|
|
378
390
|
v3Fee?: number;
|
|
379
391
|
v3LpAddresses?: string[];
|
|
380
392
|
v3ExactTokenIn?: string;
|
|
393
|
+
/** V3 多跳:代币路径 [tokenIn, tokenMid1, ..., tokenOut] */
|
|
394
|
+
v3Tokens?: string[];
|
|
395
|
+
/** V3 多跳:费率路径 [fee0, fee1, ...] - 长度 = v3Tokens.length - 1 */
|
|
396
|
+
v3Fees?: number[];
|
|
381
397
|
minOutputAmounts?: (string | bigint)[];
|
|
382
398
|
config: FourSignConfig;
|
|
383
399
|
};
|
|
@@ -388,12 +404,16 @@ export type FourPancakeProxyApprovalParams = {
|
|
|
388
404
|
tokenAddress: string;
|
|
389
405
|
amount: string | 'max';
|
|
390
406
|
rpcUrl: string;
|
|
407
|
+
/** 路由类型,用于确定授权目标(V2 或 V3 Router) */
|
|
408
|
+
routeType?: 'v2' | 'v3-single' | 'v3-multi';
|
|
391
409
|
};
|
|
392
410
|
export type FourPancakeProxyApprovalBatchParams = {
|
|
393
411
|
privateKeys: string[];
|
|
394
412
|
tokenAddress: string;
|
|
395
413
|
amounts: (string | 'max')[];
|
|
396
414
|
config: FourSignConfig;
|
|
415
|
+
/** 路由类型,用于确定授权目标(V2 或 V3 Router) */
|
|
416
|
+
routeType?: 'v2' | 'v3-single' | 'v3-multi';
|
|
397
417
|
};
|
|
398
418
|
/** ✅ PancakeProxy 批量授权结果 */
|
|
399
419
|
export type FourPancakeProxyApprovalBatchResult = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ethers, Wallet } from 'ethers';
|
|
2
2
|
import { getOptimizedGasPrice, NonceManager } from '../../utils/bundle-helpers.js';
|
|
3
|
-
import { PROFIT_CONFIG } from '../../utils/constants.js';
|
|
3
|
+
import { PROFIT_CONFIG, ZERO_ADDRESS } from '../../utils/constants.js';
|
|
4
4
|
import { getTxType, getGasPriceConfig, shouldExtractProfit, getProfitRecipient } from './config.js';
|
|
5
5
|
import { getErc20DecimalsMerkle as _getErc20DecimalsMerkle, generateHopWallets as _generateHopWallets, normalizeAmounts as _normalizeAmounts, batchGetBalances as _batchGetBalances, calculateGasLimit as _calculateGasLimit, isNativeTokenAddress as _isNativeTokenAddress } from './internal.js';
|
|
6
6
|
// ==================== 本地利润计算(万分之三)====================
|
|
@@ -56,8 +56,7 @@ async function getFourInnerQuote(rpcUrl, tokenAddress, tokenAmount) {
|
|
|
56
56
|
return 0n;
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
-
|
|
60
|
-
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
59
|
+
// ✅ ZERO_ADDRESS 从公共模块导入
|
|
61
60
|
/**
|
|
62
61
|
* 获取 FLAP 内盘代币 → 原生代币的报价
|
|
63
62
|
* ✅ 与 portal-bundle-merkle/core.ts 使用相同的 quoteExactInput 方法
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* 收费方式:交易末尾附加利润提取交易(和内盘一致)
|
|
9
9
|
*/
|
|
10
|
-
/** Router 地址配置 */
|
|
10
|
+
/** Router 地址配置 - ✅ 使用公共模块中的地址 */
|
|
11
11
|
export declare const DIRECT_ROUTERS: {
|
|
12
12
|
readonly BSC: {
|
|
13
13
|
readonly PANCAKESWAP_V2: "0x10ED43C718714eb63d5aA57B78B54704E256024E";
|
|
@@ -31,6 +31,7 @@ export declare const DIRECT_ROUTERS: {
|
|
|
31
31
|
readonly WOKB: "0xe538905cf8410324e03a5a23c1c177a474d59b2b";
|
|
32
32
|
};
|
|
33
33
|
};
|
|
34
|
+
/** ERC20 ABI - ✅ 从公共模块导入 */
|
|
34
35
|
export interface DirectRouterSignConfig {
|
|
35
36
|
rpcUrl: string;
|
|
36
37
|
chainId?: number;
|
|
@@ -8,14 +8,11 @@
|
|
|
8
8
|
* 收费方式:交易末尾附加利润提取交易(和内盘一致)
|
|
9
9
|
*/
|
|
10
10
|
import { ethers, Wallet, JsonRpcProvider, Contract } from 'ethers';
|
|
11
|
-
import { NonceManager, getOptimizedGasPrice } from '../utils/bundle-helpers.js';
|
|
12
|
-
import { PROFIT_CONFIG } from '../utils/constants.js';
|
|
11
|
+
import { NonceManager, getOptimizedGasPrice, getDeadline as _getDeadline } from '../utils/bundle-helpers.js';
|
|
12
|
+
import { PROFIT_CONFIG, ZERO_ADDRESS, BLOCKRAZOR_BUILDER_EOA, ADDRESSES } from '../utils/constants.js';
|
|
13
|
+
import { V2_ROUTER_ABI as _V2_ROUTER_ABI, V3_ROUTER02_ABI as _V3_ROUTER02_ABI, V3_ROUTER_LEGACY_ABI as _V3_ROUTER_LEGACY_ABI, SWAP_ROUTER02_V2_ABI as _SWAP_ROUTER02_V2_ABI, ERC20_ABI } from '../abis/common.js';
|
|
13
14
|
import { getTokenToNativeQuote } from '../utils/quote-helpers.js';
|
|
14
15
|
// ============================================================================
|
|
15
|
-
// 常量配置
|
|
16
|
-
// ============================================================================
|
|
17
|
-
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
18
|
-
// ============================================================================
|
|
19
16
|
// ✅ 方案 C:Provider 缓存(避免重复创建)
|
|
20
17
|
// ============================================================================
|
|
21
18
|
const providerCache = new Map();
|
|
@@ -43,9 +40,7 @@ function getCachedProvider(rpcUrl, chainId, chainName) {
|
|
|
43
40
|
}
|
|
44
41
|
const DEFAULT_GAS_LIMIT = 300000;
|
|
45
42
|
const DEADLINE_MINUTES = 20;
|
|
46
|
-
// ✅
|
|
47
|
-
const BLOCKRAZOR_BUILDER_EOA = '0x1266C6bE60392A8Ff346E8d5ECCd3E69dD9c5F20';
|
|
48
|
-
// ✅ V2/V3 报价相关常量和函数已移至 ../utils/quote-helpers.ts
|
|
43
|
+
// ✅ BLOCKRAZOR_BUILDER_EOA 从公共模块导入
|
|
49
44
|
/**
|
|
50
45
|
* 截断小数位数,避免超过代币精度导致 parseUnits 报错
|
|
51
46
|
* 例如:truncateDecimals("21906.025000000000000000", 1) => "21906.0"
|
|
@@ -67,36 +62,31 @@ function truncateDecimals(value, decimals) {
|
|
|
67
62
|
return integerPart;
|
|
68
63
|
return `${integerPart}.${truncatedDecimal}`;
|
|
69
64
|
}
|
|
70
|
-
/** Router 地址配置 */
|
|
65
|
+
/** Router 地址配置 - ✅ 使用公共模块中的地址 */
|
|
71
66
|
export const DIRECT_ROUTERS = {
|
|
72
67
|
BSC: {
|
|
73
|
-
PANCAKESWAP_V2:
|
|
74
|
-
PANCAKESWAP_V3:
|
|
75
|
-
WBNB:
|
|
68
|
+
PANCAKESWAP_V2: ADDRESSES.BSC.PancakeV2Router,
|
|
69
|
+
PANCAKESWAP_V3: ADDRESSES.BSC.PancakeV3Router,
|
|
70
|
+
WBNB: ADDRESSES.BSC.WBNB,
|
|
76
71
|
},
|
|
77
72
|
MONAD: {
|
|
78
73
|
// PancakeSwap
|
|
79
74
|
PANCAKESWAP_V2: '0xB1Bc24c34e88f7D43D5923034E3a14B24DaACfF9',
|
|
80
|
-
PANCAKESWAP_V3: '0x1b81D678ffb9C0263b24A97847620C99d213eB14',
|
|
75
|
+
PANCAKESWAP_V3: '0x1b81D678ffb9C0263b24A97847620C99d213eB14',
|
|
81
76
|
// Uniswap
|
|
82
77
|
UNISWAP_V2: '0x4b2ab38dbf28d31d467aa8993f6c2585981d6804',
|
|
83
78
|
UNISWAP_V3: '0xd6145b2d3f379919e8cdeda7b97e37c4b2ca9c40',
|
|
84
79
|
// Wrapped Native
|
|
85
|
-
WMON:
|
|
80
|
+
WMON: ADDRESSES.MONAD.WMON,
|
|
86
81
|
},
|
|
87
|
-
//
|
|
82
|
+
// XLayer (PotatoSwap + DYORSwap)
|
|
88
83
|
XLAYER: {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
// DYORSwap - 使用 Uniswap V3 SwapRouter02 接口(支持 multicall)
|
|
94
|
-
DYORSWAP_ROUTER: '0xfb001fbbace32f09cb6d3c449b935183de53ee96', // ✅ DYORSwap Router
|
|
95
|
-
DYORSWAP_FACTORY: '0x2CcaDb1e437AA9cDc741574bDa154686B1F04C09', // ✅ DYORSwap V2 Factory
|
|
96
|
-
// V3 专用 Router
|
|
84
|
+
POTATOSWAP_V2: '0x881fb2f98c13d521009464e7d1cbf16e1b394e8e',
|
|
85
|
+
POTATOSWAP_V3: '0xB45D0149249488333E3F3f9F359807F4b810C1FC',
|
|
86
|
+
DYORSWAP_ROUTER: '0xfb001fbbace32f09cb6d3c449b935183de53ee96',
|
|
87
|
+
DYORSWAP_FACTORY: '0x2CcaDb1e437AA9cDc741574bDa154686B1F04C09',
|
|
97
88
|
V3_ROUTER: '0xBB069e9465BcabC4F488d21e793BDEf0F2d41D41',
|
|
98
89
|
V3_FACTORY: '0xa1415fAe79c4B196d087F02b8aD5a622B8A827E5',
|
|
99
|
-
// Wrapped Native
|
|
100
90
|
WOKB: '0xe538905cf8410324e03a5a23c1c177a474d59b2b',
|
|
101
91
|
}
|
|
102
92
|
};
|
|
@@ -118,52 +108,12 @@ function getWrappedNative(chain) {
|
|
|
118
108
|
throw new Error(`Unsupported chain: ${chain}`);
|
|
119
109
|
}
|
|
120
110
|
// ============================================================================
|
|
121
|
-
// ABI
|
|
111
|
+
// ABI - ✅ 使用公共模块
|
|
122
112
|
// ============================================================================
|
|
123
113
|
/** V2 Router ABI */
|
|
124
|
-
const V2_ROUTER_ABI =
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
'function swapExactETHForTokensSupportingFeeOnTransferTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable',
|
|
128
|
-
// Token → 原生币
|
|
129
|
-
'function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts)',
|
|
130
|
-
'function swapExactTokensForETHSupportingFeeOnTransferTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external',
|
|
131
|
-
// Token → Token
|
|
132
|
-
'function swapExactTokensForTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts)',
|
|
133
|
-
'function swapExactTokensForTokensSupportingFeeOnTransferTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external',
|
|
134
|
-
// 报价
|
|
135
|
-
'function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts)',
|
|
136
|
-
];
|
|
137
|
-
/**
|
|
138
|
-
* SwapRouter02 的 V2 方法 ABI (PotatoSwap)
|
|
139
|
-
*
|
|
140
|
-
* 重要:根据实际 ABI,SwapRouter02 的 V2 方法只有:
|
|
141
|
-
* - swapExactTokensForTokens(amountIn, amountOutMin, path[], to)
|
|
142
|
-
* - swapTokensForExactTokens(amountOut, amountInMax, path[], to)
|
|
143
|
-
*
|
|
144
|
-
* 没有 swapExactETHForTokens / swapExactTokensForETH!
|
|
145
|
-
* 必须手动处理 ETH/WETH 转换:
|
|
146
|
-
* - 买入(ETH→Token): wrapETH + swapExactTokensForTokens,通过 multicall 组合
|
|
147
|
-
* - 卖出(Token→ETH): swapExactTokensForTokens(to=ADDRESS_THIS) + unwrapWETH9,通过 multicall 组合
|
|
148
|
-
*/
|
|
149
|
-
const SWAP_ROUTER02_V2_ABI = [
|
|
150
|
-
// V2 交换方法(只有 token-to-token)
|
|
151
|
-
'function swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to) external payable returns (uint256 amountOut)',
|
|
152
|
-
'function swapTokensForExactTokens(uint256 amountOut, uint256 amountInMax, address[] calldata path, address to) external payable returns (uint256 amountIn)',
|
|
153
|
-
// Multicall - 多种重载
|
|
154
|
-
'function multicall(uint256 deadline, bytes[] calldata data) external payable returns (bytes[] memory results)',
|
|
155
|
-
'function multicall(bytes32 previousBlockhash, bytes[] calldata data) external payable returns (bytes[] memory results)',
|
|
156
|
-
'function multicall(bytes[] calldata data) external payable returns (bytes[] memory results)',
|
|
157
|
-
// 辅助方法 - ETH/WETH 转换
|
|
158
|
-
'function wrapETH(uint256 value) external payable',
|
|
159
|
-
'function unwrapWETH9(uint256 amountMinimum, address recipient) external payable',
|
|
160
|
-
'function unwrapWETH9(uint256 amountMinimum) external payable',
|
|
161
|
-
'function refundETH() external payable',
|
|
162
|
-
// 代币操作
|
|
163
|
-
'function pull(address token, uint256 value) external payable',
|
|
164
|
-
'function sweepToken(address token, uint256 amountMinimum, address recipient) external payable',
|
|
165
|
-
'function sweepToken(address token, uint256 amountMinimum) external payable',
|
|
166
|
-
];
|
|
114
|
+
const V2_ROUTER_ABI = _V2_ROUTER_ABI;
|
|
115
|
+
/** SwapRouter02 的 V2 方法 ABI - ✅ 从公共模块导入 */
|
|
116
|
+
const SWAP_ROUTER02_V2_ABI = _SWAP_ROUTER02_V2_ABI;
|
|
167
117
|
/**
|
|
168
118
|
* DYORSwap SwapRouter02 的 V2 方法
|
|
169
119
|
*
|
|
@@ -309,69 +259,10 @@ function encodeDYORMulticall(deadline, data) {
|
|
|
309
259
|
const encoded = abiCoder.encode(['uint256', 'bytes[]'], [deadline, formattedData]).slice(2);
|
|
310
260
|
return '0x' + DYORSWAP_SELECTORS.multicall.slice(2) + encoded;
|
|
311
261
|
}
|
|
312
|
-
/**
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
*/
|
|
317
|
-
const V3_ROUTER02_ABI = [
|
|
318
|
-
// SwapRouter02 的 exactInputSingle - 不含 deadline
|
|
319
|
-
{
|
|
320
|
-
"inputs": [{
|
|
321
|
-
"components": [
|
|
322
|
-
{ "name": "tokenIn", "type": "address" },
|
|
323
|
-
{ "name": "tokenOut", "type": "address" },
|
|
324
|
-
{ "name": "fee", "type": "uint24" },
|
|
325
|
-
{ "name": "recipient", "type": "address" },
|
|
326
|
-
{ "name": "amountIn", "type": "uint256" },
|
|
327
|
-
{ "name": "amountOutMinimum", "type": "uint256" },
|
|
328
|
-
{ "name": "sqrtPriceLimitX96", "type": "uint160" }
|
|
329
|
-
],
|
|
330
|
-
"name": "params",
|
|
331
|
-
"type": "tuple"
|
|
332
|
-
}],
|
|
333
|
-
"name": "exactInputSingle",
|
|
334
|
-
"outputs": [{ "name": "amountOut", "type": "uint256" }],
|
|
335
|
-
"stateMutability": "payable",
|
|
336
|
-
"type": "function"
|
|
337
|
-
},
|
|
338
|
-
// Multicall - 带 deadline 版本 (SwapRouter02)
|
|
339
|
-
'function multicall(uint256 deadline, bytes[] calldata data) external payable returns (bytes[] memory results)',
|
|
340
|
-
'function refundETH() external payable',
|
|
341
|
-
'function unwrapWETH9(uint256 amountMinimum, address recipient) external payable',
|
|
342
|
-
];
|
|
343
|
-
/**
|
|
344
|
-
* V3 SwapRouter(旧版)ABI (Monad Uniswap V3)
|
|
345
|
-
* - exactInputSingle: 包含 deadline 在 struct 内部
|
|
346
|
-
* - multicall: 只有 bytes[] 版本,不带 deadline
|
|
347
|
-
*/
|
|
348
|
-
const V3_ROUTER_LEGACY_ABI = [
|
|
349
|
-
// 旧版 SwapRouter 的 exactInputSingle - 包含 deadline
|
|
350
|
-
{
|
|
351
|
-
"inputs": [{
|
|
352
|
-
"components": [
|
|
353
|
-
{ "name": "tokenIn", "type": "address" },
|
|
354
|
-
{ "name": "tokenOut", "type": "address" },
|
|
355
|
-
{ "name": "fee", "type": "uint24" },
|
|
356
|
-
{ "name": "recipient", "type": "address" },
|
|
357
|
-
{ "name": "deadline", "type": "uint256" }, // ✅ 旧版包含 deadline
|
|
358
|
-
{ "name": "amountIn", "type": "uint256" },
|
|
359
|
-
{ "name": "amountOutMinimum", "type": "uint256" },
|
|
360
|
-
{ "name": "sqrtPriceLimitX96", "type": "uint160" }
|
|
361
|
-
],
|
|
362
|
-
"name": "params",
|
|
363
|
-
"type": "tuple"
|
|
364
|
-
}],
|
|
365
|
-
"name": "exactInputSingle",
|
|
366
|
-
"outputs": [{ "name": "amountOut", "type": "uint256" }],
|
|
367
|
-
"stateMutability": "payable",
|
|
368
|
-
"type": "function"
|
|
369
|
-
},
|
|
370
|
-
// 旧版 Multicall - 只有 bytes[] 版本,不带 deadline
|
|
371
|
-
'function multicall(bytes[] calldata data) external payable returns (bytes[] memory results)',
|
|
372
|
-
'function refundETH() external payable',
|
|
373
|
-
'function unwrapWETH9(uint256 amountMinimum, address recipient) external payable',
|
|
374
|
-
];
|
|
262
|
+
/** V3 SwapRouter02 ABI (PancakeSwap V3, 新版 Uniswap) */
|
|
263
|
+
const V3_ROUTER02_ABI = _V3_ROUTER02_ABI;
|
|
264
|
+
/** V3 SwapRouter(旧版)ABI (Monad Uniswap V3) */
|
|
265
|
+
const V3_ROUTER_LEGACY_ABI = _V3_ROUTER_LEGACY_ABI;
|
|
375
266
|
/**
|
|
376
267
|
* 判断是否使用旧版 SwapRouter
|
|
377
268
|
*
|
|
@@ -412,18 +303,12 @@ function isLegacySwapRouter(chain, routerAddress) {
|
|
|
412
303
|
// ✅ BSC PancakeSwap V3 使用新版 SwapRouter02
|
|
413
304
|
return false;
|
|
414
305
|
}
|
|
415
|
-
/** ERC20 ABI */
|
|
416
|
-
const ERC20_ABI = [
|
|
417
|
-
'function approve(address spender, uint256 amount) external returns (bool)',
|
|
418
|
-
'function allowance(address owner, address spender) external view returns (uint256)',
|
|
419
|
-
'function balanceOf(address account) external view returns (uint256)',
|
|
420
|
-
'function decimals() external view returns (uint8)',
|
|
421
|
-
];
|
|
422
306
|
// ============================================================================
|
|
423
307
|
// 工具函数
|
|
424
308
|
// ============================================================================
|
|
309
|
+
// ✅ 使用公共模块的 getDeadline
|
|
425
310
|
function getDeadline(minutes = DEADLINE_MINUTES) {
|
|
426
|
-
return
|
|
311
|
+
return _getDeadline(minutes);
|
|
427
312
|
}
|
|
428
313
|
function getGasLimit(config, defaultGas = DEFAULT_GAS_LIMIT) {
|
|
429
314
|
if (config.gasLimit !== undefined) {
|
package/dist/flap/constants.d.ts
CHANGED
|
@@ -122,5 +122,6 @@ export declare const FLAP_DEX_THRESHOLDS: {
|
|
|
122
122
|
export declare const FLAP_TOTAL_SUPPLY: bigint;
|
|
123
123
|
/**
|
|
124
124
|
* 零地址(用于表示原生代币)
|
|
125
|
+
* ✅ 从公共模块重新导出
|
|
125
126
|
*/
|
|
126
|
-
export
|
|
127
|
+
export { ZERO_ADDRESS } from '../utils/constants.js';
|
package/dist/flap/constants.js
CHANGED
|
@@ -137,5 +137,6 @@ export const FLAP_DEX_THRESHOLDS = {
|
|
|
137
137
|
export const FLAP_TOTAL_SUPPLY = BigInt(1000000000) * BigInt(10 ** 18);
|
|
138
138
|
/**
|
|
139
139
|
* 零地址(用于表示原生代币)
|
|
140
|
+
* ✅ 从公共模块重新导出
|
|
140
141
|
*/
|
|
141
|
-
export
|
|
142
|
+
export { ZERO_ADDRESS } from '../utils/constants.js';
|
package/dist/flap/meta.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { JsonRpcProvider, Contract, Interface } from 'ethers';
|
|
2
|
+
import { ADDRESSES } from '../utils/constants.js';
|
|
2
3
|
const DEFAULT_GATEWAYS = {
|
|
3
4
|
BSC: 'https://ipfs.io/ipfs/',
|
|
4
5
|
BASE: 'https://ipfs.io/ipfs/',
|
|
@@ -87,11 +88,12 @@ export async function getFlapMetasByAddresses(chain, rpcUrl, tokenAddresses, opt
|
|
|
87
88
|
* 使用 Multicall3 批量读取 metaURI()/meta(),metaURI 优先、meta 兜底。
|
|
88
89
|
*/
|
|
89
90
|
export async function getFlapMetaUrisWithMulticall(provider, chain, tokenAddresses, multicall3, ipfsGateway) {
|
|
91
|
+
// ✅ 所有链使用相同的 Multicall3 地址
|
|
90
92
|
const DEFAULT_MULTICALL3 = {
|
|
91
|
-
BSC:
|
|
92
|
-
BASE:
|
|
93
|
-
XLAYER:
|
|
94
|
-
MORPH:
|
|
93
|
+
BSC: ADDRESSES.BSC.Multicall3,
|
|
94
|
+
BASE: ADDRESSES.BSC.Multicall3, // 所有链使用相同地址
|
|
95
|
+
XLAYER: ADDRESSES.BSC.Multicall3,
|
|
96
|
+
MORPH: ADDRESSES.BSC.Multicall3
|
|
95
97
|
};
|
|
96
98
|
const mcAddress = multicall3 || DEFAULT_MULTICALL3[chain];
|
|
97
99
|
const mcAbi = [
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ethers } from 'ethers';
|
|
2
|
-
import { PROFIT_CONFIG } from '../../utils/constants.js';
|
|
3
|
-
|
|
4
|
-
//
|
|
5
|
-
export const BLOCKRAZOR_BUILDER_EOA =
|
|
2
|
+
import { PROFIT_CONFIG, BLOCKRAZOR_BUILDER_EOA as _BLOCKRAZOR_BUILDER_EOA } from '../../utils/constants.js';
|
|
3
|
+
import { FLAP_PORTAL_ABI } from '../../abis/common.js';
|
|
4
|
+
// ✅ 从公共模块重新导出
|
|
5
|
+
export const BLOCKRAZOR_BUILDER_EOA = _BLOCKRAZOR_BUILDER_EOA;
|
|
6
6
|
// ✅ Chain ID 映射
|
|
7
7
|
// 注意:Merkle 捆绑服务目前只支持 BSC (56) 和 ETH (1)
|
|
8
8
|
// 其他链仅用于非捆绑的签名交易
|
|
@@ -13,14 +13,8 @@ export const CHAIN_ID_MAP = {
|
|
|
13
13
|
};
|
|
14
14
|
// Merkle 服务支持的 chainId(用于类型断言)
|
|
15
15
|
export const MERKLE_SUPPORTED_CHAIN_IDS = [56, 1];
|
|
16
|
-
// Portal ABI
|
|
17
|
-
export const PORTAL_ABI =
|
|
18
|
-
'function newToken(string name, string symbol, string meta) external payable returns (address)',
|
|
19
|
-
'function newTokenV2((string name,string symbol,string meta,uint8 dexThresh,bytes32 salt,uint16 taxRate,uint8 migratorType,address quoteToken,uint256 quoteAmt,address beneficiary,bytes permitData)) external payable returns (address)',
|
|
20
|
-
'function newTokenV3((string name,string symbol,string meta,uint8 dexThresh,bytes32 salt,uint16 taxRate,uint8 migratorType,address quoteToken,uint256 quoteAmt,address beneficiary,bytes permitData,bytes32 extensionID,bytes extensionData)) external payable returns (address)',
|
|
21
|
-
'function swapExactInput((address inputToken,address outputToken,uint256 inputAmount,uint256 minOutputAmount,bytes permitData)) external payable returns (uint256)',
|
|
22
|
-
'function quoteExactInput((address inputToken,address outputToken,uint256 inputAmount)) external view returns (uint256)'
|
|
23
|
-
];
|
|
16
|
+
// ✅ Portal ABI 从公共模块导入
|
|
17
|
+
export const PORTAL_ABI = FLAP_PORTAL_ABI;
|
|
24
18
|
// 错误信息国际化
|
|
25
19
|
export const ERRORS = {
|
|
26
20
|
NO_PRIVATE_KEY: {
|
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
import { ethers, Wallet, Contract, Interface } from 'ethers';
|
|
2
2
|
import { NonceManager, getOptimizedGasPrice } from '../../utils/bundle-helpers.js';
|
|
3
|
+
import { ADDRESSES, ZERO_ADDRESS } from '../../utils/constants.js';
|
|
4
|
+
import { MULTICALL3_ABI, V2_ROUTER_QUOTE_ABI } from '../../abis/common.js';
|
|
3
5
|
import { FLAP_PORTAL_ADDRESSES, FLAP_ORIGINAL_PORTAL_ADDRESSES } from '../constants.js';
|
|
4
6
|
import { CHAIN_ID_MAP, PORTAL_ABI, getErrorMessage, getTxType, getGasPriceConfig, shouldExtractProfit, calculateProfit, getProfitRecipient, getBribeAmount, BLOCKRAZOR_BUILDER_EOA } from './config.js';
|
|
5
|
-
|
|
6
|
-
const MULTICALL3_ADDRESS =
|
|
7
|
-
const MULTICALL3_ABI = [
|
|
8
|
-
'function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) external payable returns (tuple(bool success, bytes returnData)[])'
|
|
9
|
-
];
|
|
7
|
+
// ✅ 常量
|
|
8
|
+
const MULTICALL3_ADDRESS = ADDRESSES.BSC.Multicall3;
|
|
10
9
|
// ==================== ERC20 → 原生代币报价 ====================
|
|
11
10
|
// BSC 链常量
|
|
12
|
-
const BSC_PANCAKE_V2_ROUTER =
|
|
13
|
-
const BSC_WBNB =
|
|
11
|
+
const BSC_PANCAKE_V2_ROUTER = ADDRESSES.BSC.PancakeV2Router;
|
|
12
|
+
const BSC_WBNB = ADDRESSES.BSC.WBNB;
|
|
14
13
|
// ✅ Monad 链常量
|
|
15
14
|
const MONAD_PANCAKE_V2_ROUTER = '0xb1bc24c34e88f7d43d5923034e3a14b24daacff9';
|
|
16
|
-
const MONAD_WMON =
|
|
17
|
-
const ROUTER_ABI =
|
|
18
|
-
'function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts)'
|
|
19
|
-
];
|
|
15
|
+
const MONAD_WMON = ADDRESSES.MONAD.WMON;
|
|
16
|
+
const ROUTER_ABI = V2_ROUTER_QUOTE_ABI;
|
|
20
17
|
/**
|
|
21
18
|
* 获取 ERC20 代币 → 原生代币的报价
|
|
22
19
|
* @param provider - Provider 实例
|
|
@@ -1,26 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PancakeSwap 官方 Router 交易模块(Flap 版本,支持多链)
|
|
3
|
+
*
|
|
4
|
+
* ✅ 使用官方 PancakeSwap V2/V3 Router(非代理合约)
|
|
5
|
+
* - V2 Router (BSC): 0x10ED43C718714eb63d5aA57B78B54704E256024E
|
|
6
|
+
* - V3 Router (BSC): 0x13f4EA83D0bd40E75C8222255bc855a974568Dd4
|
|
7
|
+
* - V3 Quoter (BSC): 0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997
|
|
8
|
+
*/
|
|
1
9
|
import { PancakeProxyBatchBuySignParams, PancakeProxyBatchBuyResult, PancakeProxyBatchSellSignParams, PancakeProxyBatchSellResult, PancakeProxyApprovalParams, PancakeProxyApprovalBatchParams, PancakeProxyApprovalBatchResult } from './types.js';
|
|
2
10
|
/**
|
|
3
|
-
* 授权代币给
|
|
11
|
+
* ✅ 授权代币给 PancakeSwap Router
|
|
4
12
|
*/
|
|
5
13
|
export declare function approvePancakeProxy(params: PancakeProxyApprovalParams): Promise<{
|
|
6
14
|
txHash: string;
|
|
7
15
|
approved: boolean;
|
|
8
16
|
}>;
|
|
9
17
|
/**
|
|
10
|
-
* 批量授权代币给
|
|
18
|
+
* ✅ 批量授权代币给 PancakeSwap Router
|
|
11
19
|
*/
|
|
12
20
|
export declare function approvePancakeProxyBatch(params: PancakeProxyApprovalBatchParams): Promise<PancakeProxyApprovalBatchResult>;
|
|
13
21
|
/**
|
|
14
|
-
*
|
|
15
|
-
* ✅ 精简版:只负责签名交易,不提交到 Merkle
|
|
22
|
+
* ✅ 使用 PancakeSwap 官方 Router 批量购买代币
|
|
16
23
|
*/
|
|
17
24
|
export declare function pancakeProxyBatchBuyMerkle(params: PancakeProxyBatchBuySignParams): Promise<PancakeProxyBatchBuyResult>;
|
|
18
25
|
/**
|
|
19
|
-
* 使用
|
|
20
|
-
* ✅ 自动检查授权,智能处理授权+卖出
|
|
21
|
-
*/
|
|
22
|
-
/**
|
|
23
|
-
* PancakeSwapProxy 批量卖出(仅签名版本 - 不依赖 Merkle)
|
|
24
|
-
* ✅ 精简版:只负责签名交易,不提交到 Merkle
|
|
26
|
+
* ✅ 使用 PancakeSwap 官方 Router 批量卖出代币
|
|
25
27
|
*/
|
|
26
28
|
export declare function pancakeProxyBatchSellMerkle(params: PancakeProxyBatchSellSignParams): Promise<PancakeProxyBatchSellResult>;
|