four-flap-meme-sdk 1.4.91 → 1.4.93
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/index.d.ts +2 -0
- package/dist/index.js +24 -0
- package/dist/xlayer/aa-account.d.ts +240 -0
- package/dist/xlayer/aa-account.js +510 -0
- package/dist/xlayer/bundle.d.ts +93 -0
- package/dist/xlayer/bundle.js +472 -0
- package/dist/xlayer/bundler.d.ts +111 -0
- package/dist/xlayer/bundler.js +162 -0
- package/dist/xlayer/constants.d.ts +75 -0
- package/dist/xlayer/constants.js +145 -0
- package/dist/xlayer/dex.d.ts +132 -0
- package/dist/xlayer/dex.js +335 -0
- package/dist/xlayer/examples/bundle-buy-sell.d.ts +11 -0
- package/dist/xlayer/examples/bundle-buy-sell.js +194 -0
- package/dist/xlayer/index.d.ts +75 -0
- package/dist/xlayer/index.js +130 -0
- package/dist/xlayer/portal-ops.d.ts +152 -0
- package/dist/xlayer/portal-ops.js +239 -0
- package/dist/xlayer/types.d.ts +298 -0
- package/dist/xlayer/types.js +6 -0
- package/dist/xlayer/volume.d.ts +65 -0
- package/dist/xlayer/volume.js +235 -0
- package/package.json +1 -1
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XLayer SDK
|
|
3
|
+
*
|
|
4
|
+
* 完整的 XLayer 链 Flap 内盘交易 SDK
|
|
5
|
+
*
|
|
6
|
+
* 功能特性:
|
|
7
|
+
* - 🔗 基于 ERC-4337 AA 账户抽象
|
|
8
|
+
* - 📦 捆绑买入/卖出(多地址同一笔 handleOps)
|
|
9
|
+
* - 🔄 买卖一体化(买入 -> 授权 -> 卖出 -> 归集)
|
|
10
|
+
* - 📊 刷量/做市(多轮买卖循环)
|
|
11
|
+
* - 🌐 外盘交易(PotatoSwap DEX)
|
|
12
|
+
* - 💰 支持 Paymaster(免 Gas)
|
|
13
|
+
*
|
|
14
|
+
* 使用示例:
|
|
15
|
+
*
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import {
|
|
18
|
+
* bundleBuy,
|
|
19
|
+
* bundleSell,
|
|
20
|
+
* bundleBuySell,
|
|
21
|
+
* makeVolume,
|
|
22
|
+
* createBundleExecutor
|
|
23
|
+
* } from './xlayer';
|
|
24
|
+
*
|
|
25
|
+
* // 捆绑买入
|
|
26
|
+
* const buyResult = await bundleBuy({
|
|
27
|
+
* tokenAddress: '0x...',
|
|
28
|
+
* privateKeys: ['0x...', '0x...'],
|
|
29
|
+
* buyAmounts: ['0.01', '0.02'],
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* // 捆绑卖出
|
|
33
|
+
* const sellResult = await bundleSell({
|
|
34
|
+
* tokenAddress: '0x...',
|
|
35
|
+
* privateKeys: ['0x...', '0x...'],
|
|
36
|
+
* sellPercent: 100,
|
|
37
|
+
* withdrawToOwner: true,
|
|
38
|
+
* });
|
|
39
|
+
*
|
|
40
|
+
* // 买卖一体化
|
|
41
|
+
* const buySellResult = await bundleBuySell({
|
|
42
|
+
* tokenAddress: '0x...',
|
|
43
|
+
* privateKeys: ['0x...', '0x...'],
|
|
44
|
+
* buyAmounts: ['0.01', '0.02'],
|
|
45
|
+
* sellPercent: 100,
|
|
46
|
+
* withdrawToOwner: true,
|
|
47
|
+
* });
|
|
48
|
+
*
|
|
49
|
+
* // 刷量
|
|
50
|
+
* const volumeResult = await makeVolume({
|
|
51
|
+
* tokenAddress: '0x...',
|
|
52
|
+
* privateKeys: ['0x...', '0x...'],
|
|
53
|
+
* buyAmountPerRound: '0.01',
|
|
54
|
+
* rounds: 10,
|
|
55
|
+
* intervalMs: 3000,
|
|
56
|
+
* });
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
// ============================================================================
|
|
60
|
+
// 常量
|
|
61
|
+
// ============================================================================
|
|
62
|
+
export * from './constants.js';
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// 类型
|
|
65
|
+
// ============================================================================
|
|
66
|
+
export * from './types.js';
|
|
67
|
+
// ============================================================================
|
|
68
|
+
// Bundler 客户端
|
|
69
|
+
// ============================================================================
|
|
70
|
+
export { BundlerClient, createBundlerClient, } from './bundler.js';
|
|
71
|
+
// ============================================================================
|
|
72
|
+
// AA 账户管理
|
|
73
|
+
// ============================================================================
|
|
74
|
+
export { AAAccountManager, createAAAccountManager, predictSender, createWallet, encodeExecute, encodeExecuteBatch,
|
|
75
|
+
// 批量生成钱包工具
|
|
76
|
+
generateAAWallets, generateAAWalletsFromMnemonic, predictSendersFromPrivateKeys, } from './aa-account.js';
|
|
77
|
+
// ============================================================================
|
|
78
|
+
// Portal 操作
|
|
79
|
+
// ============================================================================
|
|
80
|
+
export { encodeBuyCall, encodeSellCall, encodeApproveCall, encodeTransferCall, PortalQuery, createPortalQuery, applySlippage, formatOkb, parseOkb, formatTokenAmount, parseTokenAmount, } from './portal-ops.js';
|
|
81
|
+
// ============================================================================
|
|
82
|
+
// 捆绑交易
|
|
83
|
+
// ============================================================================
|
|
84
|
+
export { BundleExecutor, createBundleExecutor, bundleBuy, bundleSell, bundleBuySell, } from './bundle.js';
|
|
85
|
+
// ============================================================================
|
|
86
|
+
// 刷量/做市
|
|
87
|
+
// ============================================================================
|
|
88
|
+
export { VolumeExecutor, createVolumeExecutor, makeVolume, singleRoundVolume, } from './volume.js';
|
|
89
|
+
// ============================================================================
|
|
90
|
+
// 外盘交易 (DEX)
|
|
91
|
+
// ============================================================================
|
|
92
|
+
export { DexQuery, DexExecutor, createDexQuery, createDexExecutor, quoteOkbToToken, quoteTokenToOkb,
|
|
93
|
+
// 标准 swap 编码函数
|
|
94
|
+
encodeSwapExactETHForTokens, encodeSwapExactTokensForETH, encodeSwapExactTokensForTokens,
|
|
95
|
+
// SupportingFeeOnTransferTokens 版本(推荐使用)
|
|
96
|
+
encodeSwapExactETHForTokensSupportingFee, encodeSwapExactTokensForETHSupportingFee, encodeSwapExactTokensForTokensSupportingFee, } from './dex.js';
|
|
97
|
+
// ============================================================================
|
|
98
|
+
// 便捷重导出
|
|
99
|
+
// ============================================================================
|
|
100
|
+
// 将最常用的函数放在默认导出对象中
|
|
101
|
+
export const xlayer = {
|
|
102
|
+
// 捆绑交易
|
|
103
|
+
bundleBuy: async (...args) => {
|
|
104
|
+
const { bundleBuy } = await import('./bundle.js');
|
|
105
|
+
return bundleBuy(...args);
|
|
106
|
+
},
|
|
107
|
+
bundleSell: async (...args) => {
|
|
108
|
+
const { bundleSell } = await import('./bundle.js');
|
|
109
|
+
return bundleSell(...args);
|
|
110
|
+
},
|
|
111
|
+
bundleBuySell: async (...args) => {
|
|
112
|
+
const { bundleBuySell } = await import('./bundle.js');
|
|
113
|
+
return bundleBuySell(...args);
|
|
114
|
+
},
|
|
115
|
+
// 刷量
|
|
116
|
+
makeVolume: async (...args) => {
|
|
117
|
+
const { makeVolume } = await import('./volume.js');
|
|
118
|
+
return makeVolume(...args);
|
|
119
|
+
},
|
|
120
|
+
// DEX
|
|
121
|
+
quoteOkbToToken: async (...args) => {
|
|
122
|
+
const { quoteOkbToToken } = await import('./dex.js');
|
|
123
|
+
return quoteOkbToToken(...args);
|
|
124
|
+
},
|
|
125
|
+
quoteTokenToOkb: async (...args) => {
|
|
126
|
+
const { quoteTokenToOkb } = await import('./dex.js');
|
|
127
|
+
return quoteTokenToOkb(...args);
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
export default xlayer;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XLayer Portal 操作核心
|
|
3
|
+
*
|
|
4
|
+
* Flap Portal 内盘交易的核心逻辑:
|
|
5
|
+
* - 买入(swapExactInput: native -> token)
|
|
6
|
+
* - 卖出(swapExactInput: token -> native)
|
|
7
|
+
* - 授权(approve)
|
|
8
|
+
* - 代币转账
|
|
9
|
+
*/
|
|
10
|
+
import { JsonRpcProvider } from 'ethers';
|
|
11
|
+
/**
|
|
12
|
+
* 编码买入调用(swapExactInput: native -> token)
|
|
13
|
+
*
|
|
14
|
+
* @param tokenAddress 目标代币地址
|
|
15
|
+
* @param inputAmount 输入 OKB 数量(wei)
|
|
16
|
+
* @param minOutputAmount 最小输出代币数量(默认 0)
|
|
17
|
+
*/
|
|
18
|
+
export declare function encodeBuyCall(tokenAddress: string, inputAmount: bigint, minOutputAmount?: bigint): string;
|
|
19
|
+
/**
|
|
20
|
+
* 编码卖出调用(swapExactInput: token -> native)
|
|
21
|
+
*
|
|
22
|
+
* @param tokenAddress 目标代币地址
|
|
23
|
+
* @param inputAmount 输入代币数量
|
|
24
|
+
* @param minOutputAmount 最小输出 OKB 数量(默认 0)
|
|
25
|
+
*/
|
|
26
|
+
export declare function encodeSellCall(tokenAddress: string, inputAmount: bigint, minOutputAmount?: bigint): string;
|
|
27
|
+
/**
|
|
28
|
+
* 编码授权调用
|
|
29
|
+
*
|
|
30
|
+
* @param spender 授权对象地址
|
|
31
|
+
* @param amount 授权数量(默认无限)
|
|
32
|
+
*/
|
|
33
|
+
export declare function encodeApproveCall(spender: string, amount?: bigint): string;
|
|
34
|
+
/**
|
|
35
|
+
* 编码代币转账调用
|
|
36
|
+
*
|
|
37
|
+
* @param to 接收地址
|
|
38
|
+
* @param amount 转账数量
|
|
39
|
+
*/
|
|
40
|
+
export declare function encodeTransferCall(to: string, amount: bigint): string;
|
|
41
|
+
export interface PortalQueryConfig {
|
|
42
|
+
rpcUrl?: string;
|
|
43
|
+
chainId?: number;
|
|
44
|
+
portalAddress?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Portal 查询器
|
|
48
|
+
*
|
|
49
|
+
* 提供只读查询方法:
|
|
50
|
+
* - 代币余额
|
|
51
|
+
* - 授权额度
|
|
52
|
+
* - 预览买入/卖出
|
|
53
|
+
* - 代币状态
|
|
54
|
+
*/
|
|
55
|
+
export declare class PortalQuery {
|
|
56
|
+
private provider;
|
|
57
|
+
private portal;
|
|
58
|
+
private portalAddress;
|
|
59
|
+
constructor(config?: PortalQueryConfig);
|
|
60
|
+
/**
|
|
61
|
+
* 获取 Provider
|
|
62
|
+
*/
|
|
63
|
+
getProvider(): JsonRpcProvider;
|
|
64
|
+
/**
|
|
65
|
+
* 获取 Portal 地址
|
|
66
|
+
*/
|
|
67
|
+
getPortalAddress(): string;
|
|
68
|
+
/**
|
|
69
|
+
* 获取代币余额
|
|
70
|
+
*/
|
|
71
|
+
getTokenBalance(tokenAddress: string, account: string): Promise<bigint>;
|
|
72
|
+
/**
|
|
73
|
+
* 获取 OKB 余额
|
|
74
|
+
*/
|
|
75
|
+
getOkbBalance(account: string): Promise<bigint>;
|
|
76
|
+
/**
|
|
77
|
+
* 获取授权额度
|
|
78
|
+
*/
|
|
79
|
+
getAllowance(tokenAddress: string, owner: string, spender?: string): Promise<bigint>;
|
|
80
|
+
/**
|
|
81
|
+
* 检查是否需要授权
|
|
82
|
+
*/
|
|
83
|
+
needsApproval(tokenAddress: string, owner: string, amount: bigint, spender?: string): Promise<boolean>;
|
|
84
|
+
/**
|
|
85
|
+
* 预览买入输出
|
|
86
|
+
*/
|
|
87
|
+
previewBuy(tokenAddress: string, okbAmount: bigint): Promise<bigint>;
|
|
88
|
+
/**
|
|
89
|
+
* 预览卖出输出
|
|
90
|
+
*/
|
|
91
|
+
previewSell(tokenAddress: string, tokenAmount: bigint): Promise<bigint>;
|
|
92
|
+
/**
|
|
93
|
+
* 使用 quoteExactInput 查询报价
|
|
94
|
+
*/
|
|
95
|
+
quoteExactInput(inputToken: string, outputToken: string, inputAmount: bigint): Promise<bigint>;
|
|
96
|
+
/**
|
|
97
|
+
* 获取代币状态 V5
|
|
98
|
+
*/
|
|
99
|
+
getTokenV5(tokenAddress: string): Promise<{
|
|
100
|
+
status: number;
|
|
101
|
+
reserve: bigint;
|
|
102
|
+
circulatingSupply: bigint;
|
|
103
|
+
price: bigint;
|
|
104
|
+
tokenVersion: number;
|
|
105
|
+
r: bigint;
|
|
106
|
+
h: bigint;
|
|
107
|
+
k: bigint;
|
|
108
|
+
dexSupplyThresh: bigint;
|
|
109
|
+
quoteTokenAddress: string;
|
|
110
|
+
nativeToQuoteSwapEnabled: boolean;
|
|
111
|
+
extensionID: string;
|
|
112
|
+
}>;
|
|
113
|
+
/**
|
|
114
|
+
* 批量获取多个账户的代币余额
|
|
115
|
+
*/
|
|
116
|
+
getMultipleTokenBalances(tokenAddress: string, accounts: string[]): Promise<Map<string, bigint>>;
|
|
117
|
+
/**
|
|
118
|
+
* 批量获取多个账户的 OKB 余额
|
|
119
|
+
*/
|
|
120
|
+
getMultipleOkbBalances(accounts: string[]): Promise<Map<string, bigint>>;
|
|
121
|
+
/**
|
|
122
|
+
* 批量获取授权额度
|
|
123
|
+
*/
|
|
124
|
+
getMultipleAllowances(tokenAddress: string, owners: string[], spender?: string): Promise<Map<string, bigint>>;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* 计算带滑点的最小输出
|
|
128
|
+
*
|
|
129
|
+
* @param expectedOutput 预期输出
|
|
130
|
+
* @param slippageBps 滑点基点(如 100 = 1%)
|
|
131
|
+
*/
|
|
132
|
+
export declare function applySlippage(expectedOutput: bigint, slippageBps: number): bigint;
|
|
133
|
+
/**
|
|
134
|
+
* 创建 Portal 查询器
|
|
135
|
+
*/
|
|
136
|
+
export declare function createPortalQuery(config?: PortalQueryConfig): PortalQuery;
|
|
137
|
+
/**
|
|
138
|
+
* 格式化 OKB 金额(wei -> OKB 字符串)
|
|
139
|
+
*/
|
|
140
|
+
export declare function formatOkb(wei: bigint): string;
|
|
141
|
+
/**
|
|
142
|
+
* 解析 OKB 金额(OKB 字符串 -> wei)
|
|
143
|
+
*/
|
|
144
|
+
export declare function parseOkb(okb: string): bigint;
|
|
145
|
+
/**
|
|
146
|
+
* 格式化代币金额(考虑精度)
|
|
147
|
+
*/
|
|
148
|
+
export declare function formatTokenAmount(amount: bigint, decimals?: number): string;
|
|
149
|
+
/**
|
|
150
|
+
* 解析代币金额(考虑精度)
|
|
151
|
+
*/
|
|
152
|
+
export declare function parseTokenAmount(amount: string, decimals?: number): bigint;
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XLayer Portal 操作核心
|
|
3
|
+
*
|
|
4
|
+
* Flap Portal 内盘交易的核心逻辑:
|
|
5
|
+
* - 买入(swapExactInput: native -> token)
|
|
6
|
+
* - 卖出(swapExactInput: token -> native)
|
|
7
|
+
* - 授权(approve)
|
|
8
|
+
* - 代币转账
|
|
9
|
+
*/
|
|
10
|
+
import { ethers, Interface, Contract, JsonRpcProvider } from 'ethers';
|
|
11
|
+
import { FLAP_PORTAL, ZERO_ADDRESS, PORTAL_ABI, ERC20_ABI, DEFAULT_RPC_URL, XLAYER_CHAIN_ID, } from './constants.js';
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Portal 操作编码器
|
|
14
|
+
// ============================================================================
|
|
15
|
+
const portalIface = new Interface(PORTAL_ABI);
|
|
16
|
+
const erc20Iface = new Interface(ERC20_ABI);
|
|
17
|
+
/**
|
|
18
|
+
* 编码买入调用(swapExactInput: native -> token)
|
|
19
|
+
*
|
|
20
|
+
* @param tokenAddress 目标代币地址
|
|
21
|
+
* @param inputAmount 输入 OKB 数量(wei)
|
|
22
|
+
* @param minOutputAmount 最小输出代币数量(默认 0)
|
|
23
|
+
*/
|
|
24
|
+
export function encodeBuyCall(tokenAddress, inputAmount, minOutputAmount = 0n) {
|
|
25
|
+
return portalIface.encodeFunctionData('swapExactInput', [
|
|
26
|
+
{
|
|
27
|
+
inputToken: ZERO_ADDRESS,
|
|
28
|
+
outputToken: tokenAddress,
|
|
29
|
+
inputAmount,
|
|
30
|
+
minOutputAmount,
|
|
31
|
+
permitData: '0x',
|
|
32
|
+
},
|
|
33
|
+
]);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 编码卖出调用(swapExactInput: token -> native)
|
|
37
|
+
*
|
|
38
|
+
* @param tokenAddress 目标代币地址
|
|
39
|
+
* @param inputAmount 输入代币数量
|
|
40
|
+
* @param minOutputAmount 最小输出 OKB 数量(默认 0)
|
|
41
|
+
*/
|
|
42
|
+
export function encodeSellCall(tokenAddress, inputAmount, minOutputAmount = 0n) {
|
|
43
|
+
return portalIface.encodeFunctionData('swapExactInput', [
|
|
44
|
+
{
|
|
45
|
+
inputToken: tokenAddress,
|
|
46
|
+
outputToken: ZERO_ADDRESS,
|
|
47
|
+
inputAmount,
|
|
48
|
+
minOutputAmount,
|
|
49
|
+
permitData: '0x',
|
|
50
|
+
},
|
|
51
|
+
]);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 编码授权调用
|
|
55
|
+
*
|
|
56
|
+
* @param spender 授权对象地址
|
|
57
|
+
* @param amount 授权数量(默认无限)
|
|
58
|
+
*/
|
|
59
|
+
export function encodeApproveCall(spender, amount = ethers.MaxUint256) {
|
|
60
|
+
return erc20Iface.encodeFunctionData('approve', [spender, amount]);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* 编码代币转账调用
|
|
64
|
+
*
|
|
65
|
+
* @param to 接收地址
|
|
66
|
+
* @param amount 转账数量
|
|
67
|
+
*/
|
|
68
|
+
export function encodeTransferCall(to, amount) {
|
|
69
|
+
return erc20Iface.encodeFunctionData('transfer', [to, amount]);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Portal 查询器
|
|
73
|
+
*
|
|
74
|
+
* 提供只读查询方法:
|
|
75
|
+
* - 代币余额
|
|
76
|
+
* - 授权额度
|
|
77
|
+
* - 预览买入/卖出
|
|
78
|
+
* - 代币状态
|
|
79
|
+
*/
|
|
80
|
+
export class PortalQuery {
|
|
81
|
+
constructor(config = {}) {
|
|
82
|
+
const rpcUrl = config.rpcUrl ?? DEFAULT_RPC_URL;
|
|
83
|
+
const chainId = config.chainId ?? XLAYER_CHAIN_ID;
|
|
84
|
+
this.provider = new JsonRpcProvider(rpcUrl, { chainId, name: 'xlayer' });
|
|
85
|
+
this.portalAddress = config.portalAddress ?? FLAP_PORTAL;
|
|
86
|
+
this.portal = new Contract(this.portalAddress, PORTAL_ABI, this.provider);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 获取 Provider
|
|
90
|
+
*/
|
|
91
|
+
getProvider() {
|
|
92
|
+
return this.provider;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 获取 Portal 地址
|
|
96
|
+
*/
|
|
97
|
+
getPortalAddress() {
|
|
98
|
+
return this.portalAddress;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* 获取代币余额
|
|
102
|
+
*/
|
|
103
|
+
async getTokenBalance(tokenAddress, account) {
|
|
104
|
+
const token = new Contract(tokenAddress, ERC20_ABI, this.provider);
|
|
105
|
+
return await token.balanceOf(account);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 获取 OKB 余额
|
|
109
|
+
*/
|
|
110
|
+
async getOkbBalance(account) {
|
|
111
|
+
return await this.provider.getBalance(account);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* 获取授权额度
|
|
115
|
+
*/
|
|
116
|
+
async getAllowance(tokenAddress, owner, spender) {
|
|
117
|
+
const token = new Contract(tokenAddress, ERC20_ABI, this.provider);
|
|
118
|
+
return await token.allowance(owner, spender ?? this.portalAddress);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* 检查是否需要授权
|
|
122
|
+
*/
|
|
123
|
+
async needsApproval(tokenAddress, owner, amount, spender) {
|
|
124
|
+
const allowance = await this.getAllowance(tokenAddress, owner, spender);
|
|
125
|
+
return allowance < amount;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* 预览买入输出
|
|
129
|
+
*/
|
|
130
|
+
async previewBuy(tokenAddress, okbAmount) {
|
|
131
|
+
return await this.portal.previewBuy(tokenAddress, okbAmount);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* 预览卖出输出
|
|
135
|
+
*/
|
|
136
|
+
async previewSell(tokenAddress, tokenAmount) {
|
|
137
|
+
return await this.portal.previewSell(tokenAddress, tokenAmount);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* 使用 quoteExactInput 查询报价
|
|
141
|
+
*/
|
|
142
|
+
async quoteExactInput(inputToken, outputToken, inputAmount) {
|
|
143
|
+
return await this.portal.quoteExactInput.staticCall({
|
|
144
|
+
inputToken,
|
|
145
|
+
outputToken,
|
|
146
|
+
inputAmount,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* 获取代币状态 V5
|
|
151
|
+
*/
|
|
152
|
+
async getTokenV5(tokenAddress) {
|
|
153
|
+
const raw = await this.portal.getTokenV5(tokenAddress);
|
|
154
|
+
return {
|
|
155
|
+
status: raw[0],
|
|
156
|
+
reserve: raw[1],
|
|
157
|
+
circulatingSupply: raw[2],
|
|
158
|
+
price: raw[3],
|
|
159
|
+
tokenVersion: raw[4],
|
|
160
|
+
r: raw[5],
|
|
161
|
+
h: raw[6],
|
|
162
|
+
k: raw[7],
|
|
163
|
+
dexSupplyThresh: raw[8],
|
|
164
|
+
quoteTokenAddress: raw[9],
|
|
165
|
+
nativeToQuoteSwapEnabled: raw[10],
|
|
166
|
+
extensionID: raw[11],
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* 批量获取多个账户的代币余额
|
|
171
|
+
*/
|
|
172
|
+
async getMultipleTokenBalances(tokenAddress, accounts) {
|
|
173
|
+
const balances = new Map();
|
|
174
|
+
const results = await Promise.all(accounts.map((acc) => this.getTokenBalance(tokenAddress, acc)));
|
|
175
|
+
accounts.forEach((acc, i) => balances.set(acc, results[i]));
|
|
176
|
+
return balances;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* 批量获取多个账户的 OKB 余额
|
|
180
|
+
*/
|
|
181
|
+
async getMultipleOkbBalances(accounts) {
|
|
182
|
+
const balances = new Map();
|
|
183
|
+
const results = await Promise.all(accounts.map((acc) => this.getOkbBalance(acc)));
|
|
184
|
+
accounts.forEach((acc, i) => balances.set(acc, results[i]));
|
|
185
|
+
return balances;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* 批量获取授权额度
|
|
189
|
+
*/
|
|
190
|
+
async getMultipleAllowances(tokenAddress, owners, spender) {
|
|
191
|
+
const allowances = new Map();
|
|
192
|
+
const results = await Promise.all(owners.map((owner) => this.getAllowance(tokenAddress, owner, spender)));
|
|
193
|
+
owners.forEach((owner, i) => allowances.set(owner, results[i]));
|
|
194
|
+
return allowances;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// ============================================================================
|
|
198
|
+
// 辅助函数
|
|
199
|
+
// ============================================================================
|
|
200
|
+
/**
|
|
201
|
+
* 计算带滑点的最小输出
|
|
202
|
+
*
|
|
203
|
+
* @param expectedOutput 预期输出
|
|
204
|
+
* @param slippageBps 滑点基点(如 100 = 1%)
|
|
205
|
+
*/
|
|
206
|
+
export function applySlippage(expectedOutput, slippageBps) {
|
|
207
|
+
const keep = BigInt(10000 - Math.max(0, Math.min(5000, slippageBps)));
|
|
208
|
+
return (expectedOutput * keep) / 10000n;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* 创建 Portal 查询器
|
|
212
|
+
*/
|
|
213
|
+
export function createPortalQuery(config) {
|
|
214
|
+
return new PortalQuery(config);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* 格式化 OKB 金额(wei -> OKB 字符串)
|
|
218
|
+
*/
|
|
219
|
+
export function formatOkb(wei) {
|
|
220
|
+
return ethers.formatEther(wei);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* 解析 OKB 金额(OKB 字符串 -> wei)
|
|
224
|
+
*/
|
|
225
|
+
export function parseOkb(okb) {
|
|
226
|
+
return ethers.parseEther(okb);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* 格式化代币金额(考虑精度)
|
|
230
|
+
*/
|
|
231
|
+
export function formatTokenAmount(amount, decimals = 18) {
|
|
232
|
+
return ethers.formatUnits(amount, decimals);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* 解析代币金额(考虑精度)
|
|
236
|
+
*/
|
|
237
|
+
export function parseTokenAmount(amount, decimals = 18) {
|
|
238
|
+
return ethers.parseUnits(amount, decimals);
|
|
239
|
+
}
|