four-flap-meme-sdk 1.7.7 → 1.7.9

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.
@@ -1,12 +1,20 @@
1
1
  /**
2
2
  * X-Layer Bundle 批量授权
3
3
  *
4
- * 使用 Bundle 实现多钱包批量授权
4
+ * 完整授权支持:
5
+ * - 代币授权给内盘 Flap Portal
6
+ * - 代币授权给外盘 V2/V3 Router
7
+ * - WOKB 授权给路由(用于卖出/交换)
8
+ * - 稳定币授权(USDT、USDC、USDT0)
5
9
  *
6
10
  * 优化:第一个钱包作为 Sponsor,支付 gas
7
11
  * 其他钱包不需要 gas
8
12
  */
9
13
  import type { BatchOperationResult } from './types.js';
14
+ /** 授权目标类型 */
15
+ export type ApprovalTarget = 'all' | 'flap' | 'v2' | 'v3' | 'v3-02';
16
+ /** 授权模式 */
17
+ export type ApprovalMode = 'token' | 'base' | 'full';
10
18
  /**
11
19
  * 批量授权参数
12
20
  *
@@ -16,7 +24,7 @@ import type { BatchOperationResult } from './types.js';
16
24
  export interface BatchApproveParams {
17
25
  /** RPC URL */
18
26
  rpcUrl: string;
19
- /** 代币地址 */
27
+ /** 代币地址(要授权的代币) */
20
28
  tokenAddress: string;
21
29
  /** 要授权的钱包列表(第一个钱包作为 Sponsor,支付 gas) */
22
30
  wallets: Array<{
@@ -24,6 +32,31 @@ export interface BatchApproveParams {
24
32
  }>;
25
33
  /** Gas Price (可选) */
26
34
  gasPrice?: bigint;
35
+ /** 授权目标(默认 'all':授权给所有路由) */
36
+ target?: ApprovalTarget;
37
+ /** 授权模式(默认 'token':只授权代币) */
38
+ mode?: ApprovalMode;
39
+ /** 是否包含 WOKB 授权(默认 false) */
40
+ includeWokb?: boolean;
41
+ /** 是否包含稳定币授权(默认 false) */
42
+ includeStablecoins?: boolean;
43
+ }
44
+ /**
45
+ * 完整授权参数(代币 + WOKB + 稳定币)
46
+ */
47
+ export interface FullApproveParams {
48
+ /** RPC URL */
49
+ rpcUrl: string;
50
+ /** 代币地址(要授权的代币) */
51
+ tokenAddress: string;
52
+ /** 要授权的钱包列表(第一个钱包作为 Sponsor,支付 gas) */
53
+ wallets: Array<{
54
+ privateKey: string;
55
+ }>;
56
+ /** Gas Price (可选) */
57
+ gasPrice?: bigint;
58
+ /** 授权目标(默认 'all':授权给所有路由) */
59
+ target?: ApprovalTarget;
27
60
  }
28
61
  /**
29
62
  * 单个钱包授权参数
@@ -39,14 +72,54 @@ export interface SingleApproveParams {
39
72
  walletPrivateKey: string;
40
73
  /** Gas Price (可选) */
41
74
  gasPrice?: bigint;
75
+ /** 授权目标(默认 'all') */
76
+ target?: ApprovalTarget;
77
+ /** 授权模式(默认 'token') */
78
+ mode?: ApprovalMode;
79
+ /** 是否包含 WOKB 授权 */
80
+ includeWokb?: boolean;
81
+ /** 是否包含稳定币授权 */
82
+ includeStablecoins?: boolean;
42
83
  }
43
84
  /**
44
85
  * Bundle 批量授权
45
86
  *
46
87
  * 将多个钱包对所有 Spender 的授权打包成一笔交易
47
88
  * 第一个钱包作为 Sponsor,支付 gas
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * // 只授权代币给所有路由
93
+ * await bundleBatchApprove({
94
+ * rpcUrl,
95
+ * tokenAddress,
96
+ * wallets: [{ privateKey: pk1 }, { privateKey: pk2 }],
97
+ * });
98
+ *
99
+ * // 授权代币 + WOKB
100
+ * await bundleBatchApprove({
101
+ * rpcUrl,
102
+ * tokenAddress,
103
+ * wallets: [{ privateKey: pk1 }],
104
+ * includeWokb: true,
105
+ * });
106
+ *
107
+ * // 完整授权(代币 + WOKB + 稳定币)
108
+ * await bundleBatchApprove({
109
+ * rpcUrl,
110
+ * tokenAddress,
111
+ * wallets: [{ privateKey: pk1 }],
112
+ * mode: 'full',
113
+ * });
114
+ * ```
48
115
  */
49
116
  export declare function bundleBatchApprove(params: BatchApproveParams): Promise<BatchOperationResult>;
117
+ /**
118
+ * Bundle 完整授权(代币 + WOKB + 稳定币)
119
+ *
120
+ * 一次性完成所有授权,跟 BSC 链一样
121
+ */
122
+ export declare function bundleFullApprove(params: FullApproveParams): Promise<BatchOperationResult>;
50
123
  /**
51
124
  * Bundle 单钱包授权
52
125
  *
@@ -57,4 +130,12 @@ export declare function bundleSingleApprove(params: SingleApproveParams): Promis
57
130
  /**
58
131
  * 获取需要授权的 Spender 列表
59
132
  */
60
- export declare function getSpendersToApprove(): readonly string[];
133
+ export declare function getSpendersToApprove(target?: ApprovalTarget): readonly string[];
134
+ /**
135
+ * 获取基础代币列表(WOKB + 稳定币)
136
+ */
137
+ export declare function getBaseTokensToApprove(): readonly string[];
138
+ /**
139
+ * 获取稳定币列表
140
+ */
141
+ export declare function getStablecoins(): readonly string[];
@@ -1,33 +1,114 @@
1
1
  /**
2
2
  * X-Layer Bundle 批量授权
3
3
  *
4
- * 使用 Bundle 实现多钱包批量授权
4
+ * 完整授权支持:
5
+ * - 代币授权给内盘 Flap Portal
6
+ * - 代币授权给外盘 V2/V3 Router
7
+ * - WOKB 授权给路由(用于卖出/交换)
8
+ * - 稳定币授权(USDT、USDC、USDT0)
5
9
  *
6
10
  * 优化:第一个钱包作为 Sponsor,支付 gas
7
11
  * 其他钱包不需要 gas
8
12
  */
9
- import { SPENDERS_TO_APPROVE, MAX_UINT256 } from './constants.js';
13
+ import { SPENDERS_TO_APPROVE, BASE_TOKENS_TO_APPROVE, MAX_UINT256, WOKB, USDT, USDC, USDT0, FLAP_PORTAL, POTATOSWAP_V2_ROUTER, POTATOSWAP_V3_ROUTER, POTATOSWAP_SWAP_ROUTER02, } from './constants.js';
10
14
  import { XLayerBundle } from './bundle.js';
11
15
  import { buildApprove } from './builders.js';
16
+ // ==================== 辅助函数 ====================
17
+ /**
18
+ * 获取目标 Spender 列表
19
+ */
20
+ function getSpenders(target = 'all') {
21
+ switch (target) {
22
+ case 'flap':
23
+ return [FLAP_PORTAL];
24
+ case 'v2':
25
+ return [POTATOSWAP_V2_ROUTER];
26
+ case 'v3':
27
+ return [POTATOSWAP_V3_ROUTER];
28
+ case 'v3-02':
29
+ return [POTATOSWAP_SWAP_ROUTER02];
30
+ case 'all':
31
+ default:
32
+ return SPENDERS_TO_APPROVE;
33
+ }
34
+ }
35
+ /**
36
+ * 构建授权 calls
37
+ */
38
+ function buildApproveCalls(tokenAddress, target = 'all', mode = 'token', includeWokb = false, includeStablecoins = false) {
39
+ const spenders = getSpenders(target);
40
+ const calls = [];
41
+ // 1. 代币授权给路由
42
+ if (mode === 'token' || mode === 'full') {
43
+ for (const spender of spenders) {
44
+ calls.push(buildApprove(tokenAddress, spender, MAX_UINT256));
45
+ }
46
+ }
47
+ // 2. WOKB 授权给路由(用于 V3 卖出等)
48
+ if (includeWokb || mode === 'base' || mode === 'full') {
49
+ for (const spender of spenders) {
50
+ calls.push(buildApprove(WOKB, spender, MAX_UINT256));
51
+ }
52
+ }
53
+ // 3. 稳定币授权给路由
54
+ if (includeStablecoins || mode === 'full') {
55
+ const stablecoins = [USDT, USDC, USDT0];
56
+ for (const stablecoin of stablecoins) {
57
+ for (const spender of spenders) {
58
+ calls.push(buildApprove(stablecoin, spender, MAX_UINT256));
59
+ }
60
+ }
61
+ }
62
+ return calls;
63
+ }
12
64
  // ==================== 批量授权 ====================
13
65
  /**
14
66
  * Bundle 批量授权
15
67
  *
16
68
  * 将多个钱包对所有 Spender 的授权打包成一笔交易
17
69
  * 第一个钱包作为 Sponsor,支付 gas
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * // 只授权代币给所有路由
74
+ * await bundleBatchApprove({
75
+ * rpcUrl,
76
+ * tokenAddress,
77
+ * wallets: [{ privateKey: pk1 }, { privateKey: pk2 }],
78
+ * });
79
+ *
80
+ * // 授权代币 + WOKB
81
+ * await bundleBatchApprove({
82
+ * rpcUrl,
83
+ * tokenAddress,
84
+ * wallets: [{ privateKey: pk1 }],
85
+ * includeWokb: true,
86
+ * });
87
+ *
88
+ * // 完整授权(代币 + WOKB + 稳定币)
89
+ * await bundleBatchApprove({
90
+ * rpcUrl,
91
+ * tokenAddress,
92
+ * wallets: [{ privateKey: pk1 }],
93
+ * mode: 'full',
94
+ * });
95
+ * ```
18
96
  */
19
97
  export async function bundleBatchApprove(params) {
20
- const { rpcUrl, tokenAddress, wallets, gasPrice } = params;
98
+ const { rpcUrl, tokenAddress, wallets, gasPrice, target = 'all', mode = 'token', includeWokb = false, includeStablecoins = false, } = params;
21
99
  if (wallets.length === 0) {
22
100
  return { success: false, successCount: 0, totalCount: 0, error: '没有钱包' };
23
101
  }
24
102
  const bundle = new XLayerBundle({ rpcUrl, gasPrice });
25
- // 构建参与者:每个钱包授权给所有 Spender
103
+ const calls = buildApproveCalls(tokenAddress, target, mode, includeWokb, includeStablecoins);
104
+ // 构建参与者:每个钱包执行相同的授权 calls
26
105
  const participants = wallets.map(w => ({
27
106
  wallet: w.privateKey,
28
- calls: SPENDERS_TO_APPROVE.map(spender => buildApprove(tokenAddress, spender, MAX_UINT256)),
107
+ calls,
29
108
  }));
30
- console.log(`[Bundle授权] 执行批量授权: ${wallets.length} 个钱包, ${SPENDERS_TO_APPROVE.length} 个 Spender`);
109
+ const spenders = getSpenders(target);
110
+ console.log(`[Bundle授权] 执行批量授权: ${wallets.length} 个钱包, ${spenders.length} 个 Spender, ${calls.length / wallets.length} 个授权/钱包`);
111
+ console.log(`[Bundle授权] 模式: ${mode}, 目标: ${target}, WOKB: ${includeWokb}, 稳定币: ${includeStablecoins}`);
31
112
  console.log(`[Bundle授权] 第一个钱包作为 Sponsor,支付 gas`);
32
113
  const result = await bundle.execute(participants);
33
114
  return {
@@ -36,6 +117,19 @@ export async function bundleBatchApprove(params) {
36
117
  totalCount: wallets.length,
37
118
  };
38
119
  }
120
+ /**
121
+ * Bundle 完整授权(代币 + WOKB + 稳定币)
122
+ *
123
+ * 一次性完成所有授权,跟 BSC 链一样
124
+ */
125
+ export async function bundleFullApprove(params) {
126
+ return bundleBatchApprove({
127
+ ...params,
128
+ mode: 'full',
129
+ includeWokb: true,
130
+ includeStablecoins: true,
131
+ });
132
+ }
39
133
  /**
40
134
  * Bundle 单钱包授权
41
135
  *
@@ -48,11 +142,27 @@ export async function bundleSingleApprove(params) {
48
142
  tokenAddress: params.tokenAddress,
49
143
  wallets: [{ privateKey: params.walletPrivateKey }],
50
144
  gasPrice: params.gasPrice,
145
+ target: params.target,
146
+ mode: params.mode,
147
+ includeWokb: params.includeWokb,
148
+ includeStablecoins: params.includeStablecoins,
51
149
  });
52
150
  }
53
151
  /**
54
152
  * 获取需要授权的 Spender 列表
55
153
  */
56
- export function getSpendersToApprove() {
57
- return SPENDERS_TO_APPROVE;
154
+ export function getSpendersToApprove(target = 'all') {
155
+ return getSpenders(target);
156
+ }
157
+ /**
158
+ * 获取基础代币列表(WOKB + 稳定币)
159
+ */
160
+ export function getBaseTokensToApprove() {
161
+ return BASE_TOKENS_TO_APPROVE;
162
+ }
163
+ /**
164
+ * 获取稳定币列表
165
+ */
166
+ export function getStablecoins() {
167
+ return [USDT, USDC, USDT0];
58
168
  }
@@ -8,13 +8,24 @@
8
8
  */
9
9
  import { ethers, Wallet, JsonRpcProvider, Interface } from 'ethers';
10
10
  import { XLAYER_CHAIN_ID, EXECUTOR_ADDRESS, EXECUTOR_ABI, DEFAULT_GAS_PRICE, GAS_LIMIT_MULTIPLIER, } from './constants.js';
11
+ // ==================== RLP 编码工具 ====================
12
+ /**
13
+ * 将整数转换为符合 RLP 规范的十六进制字符串
14
+ * 零值必须编码为空字符串 "0x",而不是 "0x00"
15
+ */
16
+ function toRlpHex(value) {
17
+ if (value === 0 || value === 0n) {
18
+ return '0x';
19
+ }
20
+ return ethers.toBeHex(value);
21
+ }
11
22
  // ==================== 工具函数 ====================
12
23
  /** 计算授权消息哈希 */
13
24
  function hashAuthorization(chainId, executorAddress, nonce) {
14
25
  const encoded = ethers.encodeRlp([
15
- ethers.toBeHex(chainId),
26
+ toRlpHex(chainId),
16
27
  executorAddress,
17
- ethers.toBeHex(nonce),
28
+ toRlpHex(nonce),
18
29
  ]);
19
30
  const prefixed = ethers.concat([new Uint8Array([0x05]), encoded]);
20
31
  return ethers.keccak256(prefixed);
@@ -171,21 +182,21 @@ export class XLayerBundle {
171
182
  // EIP-7702 RLP 字段顺序:
172
183
  // [chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data, accessList, authorizationList]
173
184
  const fields = [
174
- ethers.toBeHex(tx.chainId),
175
- ethers.toBeHex(tx.nonce),
176
- ethers.toBeHex(tx.maxPriorityFeePerGas),
177
- ethers.toBeHex(tx.maxFeePerGas),
178
- ethers.toBeHex(tx.gasLimit),
185
+ toRlpHex(tx.chainId),
186
+ toRlpHex(tx.nonce),
187
+ toRlpHex(tx.maxPriorityFeePerGas),
188
+ toRlpHex(tx.maxFeePerGas),
189
+ toRlpHex(tx.gasLimit),
179
190
  tx.to,
180
- ethers.toBeHex(tx.value),
191
+ toRlpHex(tx.value),
181
192
  tx.data,
182
193
  (tx.accessList || []).map((item) => [item.address, item.storageKeys]), // accessList
183
194
  // Authorization list
184
195
  tx.authorizationList.map((auth) => [
185
- ethers.toBeHex(auth.chainId),
196
+ toRlpHex(auth.chainId),
186
197
  auth.address,
187
- ethers.toBeHex(auth.nonce),
188
- ethers.toBeHex(auth.v),
198
+ toRlpHex(auth.nonce),
199
+ toRlpHex(auth.v),
189
200
  auth.r,
190
201
  auth.s,
191
202
  ]),
@@ -199,14 +210,14 @@ export class XLayerBundle {
199
210
  // 添加签名
200
211
  const signedFields = [
201
212
  ...fields,
202
- ethers.toBeHex(signature.v),
213
+ toRlpHex(signature.v),
203
214
  signature.r,
204
215
  signature.s,
205
216
  ];
206
- return ethers.concat([
217
+ return ethers.hexlify(ethers.concat([
207
218
  new Uint8Array([0x04]),
208
219
  ethers.encodeRlp(signedFields),
209
- ]);
220
+ ]));
210
221
  }
211
222
  }
212
223
  // ==================== 便捷函数 ====================
@@ -1,26 +1,86 @@
1
1
  /**
2
2
  * X-Layer Bundle 授权检查
3
3
  *
4
- * 检查钱包是否已授权所有 Spender
4
+ * 完整功能:
5
+ * - 批量检查授权状态(使用 Multicall3 优化)
6
+ * - 检查所有路由(Flap + V2 + V3)
7
+ * - 检查基础代币(WOKB + 稳定币)
8
+ * - 返回详细授权信息
5
9
  */
10
+ /** 授权目标类型 */
11
+ export type ApprovalTarget = 'all' | 'flap' | 'v2' | 'v3' | 'v3-02';
12
+ /** 授权状态详情 */
13
+ export interface ApprovalStatusDetail {
14
+ /** 钱包地址 */
15
+ walletAddress: string;
16
+ /** 是否所有 Spender 都已授权 */
17
+ isFullyApproved: boolean;
18
+ /** 每个 Spender 的授权详情 */
19
+ spenderDetails: Array<{
20
+ spender: string;
21
+ spenderName: string;
22
+ isApproved: boolean;
23
+ currentAllowance: bigint;
24
+ }>;
25
+ }
26
+ /** 批量授权检查结果 */
27
+ export interface BatchApprovalCheckResult {
28
+ /** 代币地址 */
29
+ tokenAddress: string;
30
+ /** 钱包总数 */
31
+ totalWallets: number;
32
+ /** 已完全授权的钱包数 */
33
+ fullyApprovedCount: number;
34
+ /** 需要授权的钱包数 */
35
+ needApprovalCount: number;
36
+ /** 详细信息 */
37
+ details: ApprovalStatusDetail[];
38
+ }
39
+ /** 完整授权检查结果(包含基础代币) */
40
+ export interface FullApprovalCheckResult {
41
+ /** 代币授权状态 */
42
+ token: BatchApprovalCheckResult;
43
+ /** WOKB 授权状态 */
44
+ wokb: BatchApprovalCheckResult;
45
+ /** 稳定币授权状态 */
46
+ stablecoins: {
47
+ usdt: BatchApprovalCheckResult;
48
+ usdc: BatchApprovalCheckResult;
49
+ usdt0: BatchApprovalCheckResult;
50
+ };
51
+ }
6
52
  /**
7
53
  * 检查钱包是否已授权(检查所有 Spender)
8
54
  *
9
55
  * @param rpcUrl RPC URL
10
56
  * @param tokenAddress 代币地址
11
57
  * @param walletAddress 钱包地址
58
+ * @param target 授权目标(默认 'all')
12
59
  * @returns 是否所有 Spender 都已授权
13
60
  */
14
- export declare function checkApprovalStatus(rpcUrl: string, tokenAddress: string, walletAddress: string): Promise<boolean>;
61
+ export declare function checkApprovalStatus(rpcUrl: string, tokenAddress: string, walletAddress: string, target?: ApprovalTarget): Promise<boolean>;
15
62
  /**
16
- * 批量检查授权状态
63
+ * 批量检查授权状态(使用 Multicall3 优化)
64
+ *
65
+ * ✅ 跟 BSC 链一样,返回详细的授权信息
66
+ *
67
+ * @param rpcUrl RPC URL
68
+ * @param tokenAddress 代币地址
69
+ * @param walletAddresses 钱包地址列表
70
+ * @param target 授权目标(默认 'all')
71
+ * @returns 批量授权检查结果
72
+ */
73
+ export declare function checkApprovalStatusBatch(rpcUrl: string, tokenAddress: string, walletAddresses: string[], target?: ApprovalTarget): Promise<BatchApprovalCheckResult>;
74
+ /**
75
+ * 批量检查授权状态(简化版,返回 Map)
17
76
  *
18
77
  * @param rpcUrl RPC URL
19
78
  * @param tokenAddress 代币地址
20
79
  * @param walletAddresses 钱包地址列表
80
+ * @param target 授权目标
21
81
  * @returns 钱包地址 -> 是否已授权
22
82
  */
23
- export declare function checkApprovalStatusBatch(rpcUrl: string, tokenAddress: string, walletAddresses: string[]): Promise<Map<string, boolean>>;
83
+ export declare function checkApprovalStatusBatchSimple(rpcUrl: string, tokenAddress: string, walletAddresses: string[], target?: ApprovalTarget): Promise<Map<string, boolean>>;
24
84
  /**
25
85
  * 检查单个 Spender 的授权状态
26
86
  *
@@ -37,15 +97,54 @@ export declare function checkSingleApprovalStatus(rpcUrl: string, tokenAddress:
37
97
  * @param rpcUrl RPC URL
38
98
  * @param tokenAddress 代币地址
39
99
  * @param walletAddress 钱包地址
100
+ * @param target 授权目标
40
101
  * @returns Spender 地址 -> 授权额度
41
102
  */
42
- export declare function getApprovalDetails(rpcUrl: string, tokenAddress: string, walletAddress: string): Promise<Map<string, bigint>>;
103
+ export declare function getApprovalDetails(rpcUrl: string, tokenAddress: string, walletAddress: string, target?: ApprovalTarget): Promise<Map<string, bigint>>;
43
104
  /**
44
105
  * 获取需要授权的 Spender 列表(未授权的)
45
106
  *
46
107
  * @param rpcUrl RPC URL
47
108
  * @param tokenAddress 代币地址
48
109
  * @param walletAddress 钱包地址
110
+ * @param target 授权目标
49
111
  * @returns 未授权的 Spender 地址列表
50
112
  */
51
- export declare function getUnapprovedSpenders(rpcUrl: string, tokenAddress: string, walletAddress: string): Promise<string[]>;
113
+ export declare function getUnapprovedSpenders(rpcUrl: string, tokenAddress: string, walletAddress: string, target?: ApprovalTarget): Promise<string[]>;
114
+ /**
115
+ * 获取需要授权的钱包列表
116
+ *
117
+ * @param rpcUrl RPC URL
118
+ * @param tokenAddress 代币地址
119
+ * @param walletAddresses 钱包地址列表
120
+ * @param target 授权目标
121
+ * @returns 需要授权的钱包地址列表
122
+ */
123
+ export declare function getWalletsNeedApproval(rpcUrl: string, tokenAddress: string, walletAddresses: string[], target?: ApprovalTarget): Promise<string[]>;
124
+ /**
125
+ * 完整授权检查(代币 + WOKB + 稳定币)
126
+ *
127
+ * ✅ 跟 BSC 链一样,一次性检查所有授权状态
128
+ *
129
+ * @param rpcUrl RPC URL
130
+ * @param tokenAddress 代币地址
131
+ * @param walletAddresses 钱包地址列表
132
+ * @param target 授权目标
133
+ * @returns 完整授权检查结果
134
+ */
135
+ export declare function checkFullApprovalStatus(rpcUrl: string, tokenAddress: string, walletAddresses: string[], target?: ApprovalTarget): Promise<FullApprovalCheckResult>;
136
+ /**
137
+ * 获取授权汇总信息
138
+ *
139
+ * @param rpcUrl RPC URL
140
+ * @param tokenAddress 代币地址
141
+ * @param walletAddresses 钱包地址列表
142
+ * @returns 授权汇总
143
+ */
144
+ export declare function getApprovalSummary(rpcUrl: string, tokenAddress: string, walletAddresses: string[]): Promise<{
145
+ totalWallets: number;
146
+ tokenApproved: number;
147
+ wokbApproved: number;
148
+ allApproved: number;
149
+ needApproval: number;
150
+ }>;