four-flap-meme-sdk 1.7.2 → 1.7.4

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.
@@ -0,0 +1,60 @@
1
+ /**
2
+ * X-Layer Bundle 批量授权
3
+ *
4
+ * 使用 Bundle 实现多钱包批量授权
5
+ *
6
+ * 优化:第一个钱包作为 Sponsor,支付 gas
7
+ * 其他钱包不需要 gas
8
+ */
9
+ import type { BatchOperationResult } from './types.js';
10
+ /**
11
+ * 批量授权参数
12
+ *
13
+ * 不需要单独的 Sponsor 私钥
14
+ * 第一个钱包自动作为 Sponsor,支付 gas
15
+ */
16
+ export interface BatchApproveParams {
17
+ /** RPC URL */
18
+ rpcUrl: string;
19
+ /** 代币地址 */
20
+ tokenAddress: string;
21
+ /** 要授权的钱包列表(第一个钱包作为 Sponsor,支付 gas) */
22
+ wallets: Array<{
23
+ privateKey: string;
24
+ }>;
25
+ /** Gas Price (可选) */
26
+ gasPrice?: bigint;
27
+ }
28
+ /**
29
+ * 单个钱包授权参数
30
+ *
31
+ * 该钱包自己支付 gas
32
+ */
33
+ export interface SingleApproveParams {
34
+ /** RPC URL */
35
+ rpcUrl: string;
36
+ /** 代币地址 */
37
+ tokenAddress: string;
38
+ /** 钱包私钥(该钱包自己支付 gas) */
39
+ walletPrivateKey: string;
40
+ /** Gas Price (可选) */
41
+ gasPrice?: bigint;
42
+ }
43
+ /**
44
+ * Bundle 批量授权
45
+ *
46
+ * 将多个钱包对所有 Spender 的授权打包成一笔交易
47
+ * 第一个钱包作为 Sponsor,支付 gas
48
+ */
49
+ export declare function bundleBatchApprove(params: BatchApproveParams): Promise<BatchOperationResult>;
50
+ /**
51
+ * Bundle 单钱包授权
52
+ *
53
+ * 对单个钱包授权所有 Spender
54
+ * 该钱包自己支付 gas
55
+ */
56
+ export declare function bundleSingleApprove(params: SingleApproveParams): Promise<BatchOperationResult>;
57
+ /**
58
+ * 获取需要授权的 Spender 列表
59
+ */
60
+ export declare function getSpendersToApprove(): readonly string[];
@@ -0,0 +1,58 @@
1
+ /**
2
+ * X-Layer Bundle 批量授权
3
+ *
4
+ * 使用 Bundle 实现多钱包批量授权
5
+ *
6
+ * 优化:第一个钱包作为 Sponsor,支付 gas
7
+ * 其他钱包不需要 gas
8
+ */
9
+ import { SPENDERS_TO_APPROVE, MAX_UINT256 } from './constants.js';
10
+ import { XLayerBundle } from './bundle.js';
11
+ import { buildApprove } from './builders.js';
12
+ // ==================== 批量授权 ====================
13
+ /**
14
+ * Bundle 批量授权
15
+ *
16
+ * 将多个钱包对所有 Spender 的授权打包成一笔交易
17
+ * 第一个钱包作为 Sponsor,支付 gas
18
+ */
19
+ export async function bundleBatchApprove(params) {
20
+ const { rpcUrl, tokenAddress, wallets, gasPrice } = params;
21
+ if (wallets.length === 0) {
22
+ return { success: false, successCount: 0, totalCount: 0, error: '没有钱包' };
23
+ }
24
+ const bundle = new XLayerBundle({ rpcUrl, gasPrice });
25
+ // 构建参与者:每个钱包授权给所有 Spender
26
+ const participants = wallets.map(w => ({
27
+ wallet: w.privateKey,
28
+ calls: SPENDERS_TO_APPROVE.map(spender => buildApprove(tokenAddress, spender, MAX_UINT256)),
29
+ }));
30
+ console.log(`[Bundle授权] 执行批量授权: ${wallets.length} 个钱包, ${SPENDERS_TO_APPROVE.length} 个 Spender`);
31
+ console.log(`[Bundle授权] 第一个钱包作为 Sponsor,支付 gas`);
32
+ const result = await bundle.execute(participants);
33
+ return {
34
+ ...result,
35
+ successCount: result.success ? wallets.length : 0,
36
+ totalCount: wallets.length,
37
+ };
38
+ }
39
+ /**
40
+ * Bundle 单钱包授权
41
+ *
42
+ * 对单个钱包授权所有 Spender
43
+ * 该钱包自己支付 gas
44
+ */
45
+ export async function bundleSingleApprove(params) {
46
+ return bundleBatchApprove({
47
+ rpcUrl: params.rpcUrl,
48
+ tokenAddress: params.tokenAddress,
49
+ wallets: [{ privateKey: params.walletPrivateKey }],
50
+ gasPrice: params.gasPrice,
51
+ });
52
+ }
53
+ /**
54
+ * 获取需要授权的 Spender 列表
55
+ */
56
+ export function getSpendersToApprove() {
57
+ return SPENDERS_TO_APPROVE;
58
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * X-Layer Bundle 广播模块
3
+ *
4
+ * 后端使用:接收前端已签名的交易数据,广播到链上
5
+ * 后端不需要任何私钥,只负责广播和记录
6
+ */
7
+ import type { BundleResult } from './types.js';
8
+ import type { SignedTransaction } from './sign.js';
9
+ /** 广播配置(后端不需要私钥) */
10
+ export interface BroadcastConfig {
11
+ /** RPC URL */
12
+ rpcUrl: string;
13
+ }
14
+ /** 广播结果 */
15
+ export interface BroadcastResult extends BundleResult {
16
+ /** 参与者数量 */
17
+ participantCount: number;
18
+ /** 调用数量 */
19
+ callCount: number;
20
+ }
21
+ /**
22
+ * 广播已签名的交易
23
+ *
24
+ * 后端调用,接收前端签名的数据并广播
25
+ * 后端不需要任何私钥
26
+ *
27
+ * @param config 广播配置(只需要 RPC URL)
28
+ * @param signedData 前端签名的交易数据
29
+ */
30
+ export declare function broadcastSignedBundle(config: BroadcastConfig, signedData: SignedTransaction): Promise<BroadcastResult>;
31
+ /**
32
+ * 批量广播多个已签名的交易
33
+ *
34
+ * @param config 广播配置
35
+ * @param signedDataList 签名数据列表
36
+ */
37
+ export declare function broadcastSignedBundleBatch(config: BroadcastConfig, signedDataList: SignedTransaction[]): Promise<BroadcastResult[]>;
38
+ /**
39
+ * 并行广播多个已签名的交易
40
+ *
41
+ * @param config 广播配置
42
+ * @param signedDataList 签名数据列表
43
+ */
44
+ export declare function broadcastSignedBundleParallel(config: BroadcastConfig, signedDataList: SignedTransaction[]): Promise<BroadcastResult[]>;
45
+ /**
46
+ * 直接广播原始交易(兼容 submitBundleToBlockRazor 风格)
47
+ *
48
+ * 接收签名后的原始交易字符串数组,逐个广播
49
+ *
50
+ * @param signatures 签名后的原始交易数组(hex string)
51
+ * @param config 广播配置
52
+ */
53
+ export declare function submitBundleToXLayer(signatures: string[], config: BroadcastConfig): Promise<{
54
+ code: boolean;
55
+ txHashes: string[];
56
+ successCount: number;
57
+ failCount: number;
58
+ results: Array<{
59
+ success: boolean;
60
+ txHash?: string;
61
+ error?: string;
62
+ }>;
63
+ }>;
@@ -0,0 +1,112 @@
1
+ /**
2
+ * X-Layer Bundle 广播模块
3
+ *
4
+ * 后端使用:接收前端已签名的交易数据,广播到链上
5
+ * 后端不需要任何私钥,只负责广播和记录
6
+ */
7
+ import { JsonRpcProvider } from 'ethers';
8
+ // ==================== 广播函数 ====================
9
+ /**
10
+ * 广播已签名的交易
11
+ *
12
+ * 后端调用,接收前端签名的数据并广播
13
+ * 后端不需要任何私钥
14
+ *
15
+ * @param config 广播配置(只需要 RPC URL)
16
+ * @param signedData 前端签名的交易数据
17
+ */
18
+ export async function broadcastSignedBundle(config, signedData) {
19
+ try {
20
+ const provider = new JsonRpcProvider(config.rpcUrl);
21
+ console.log(`[Bundle广播] 广播交易: ${signedData.txHash}`);
22
+ console.log(`[Bundle广播] 参与者: ${signedData.participantCount}, 调用: ${signedData.callCount}`);
23
+ // 直接广播已签名的原始交易
24
+ const txResponse = await provider.broadcastTransaction(signedData.signedTx);
25
+ const receipt = await txResponse.wait();
26
+ console.log(`[Bundle广播] 成功: ${txResponse.hash}, 区块: ${receipt?.blockNumber}`);
27
+ return {
28
+ success: receipt?.status === 1,
29
+ txHash: txResponse.hash,
30
+ blockNumber: receipt?.blockNumber,
31
+ gasUsed: receipt?.gasUsed,
32
+ participantCount: signedData.participantCount,
33
+ callCount: signedData.callCount,
34
+ };
35
+ }
36
+ catch (error) {
37
+ console.error('[Bundle广播] 失败:', error);
38
+ return {
39
+ success: false,
40
+ error: error instanceof Error ? error.message : String(error),
41
+ participantCount: signedData.participantCount,
42
+ callCount: signedData.callCount,
43
+ };
44
+ }
45
+ }
46
+ /**
47
+ * 批量广播多个已签名的交易
48
+ *
49
+ * @param config 广播配置
50
+ * @param signedDataList 签名数据列表
51
+ */
52
+ export async function broadcastSignedBundleBatch(config, signedDataList) {
53
+ const results = [];
54
+ for (const signedData of signedDataList) {
55
+ const result = await broadcastSignedBundle(config, signedData);
56
+ results.push(result);
57
+ }
58
+ return results;
59
+ }
60
+ /**
61
+ * 并行广播多个已签名的交易
62
+ *
63
+ * @param config 广播配置
64
+ * @param signedDataList 签名数据列表
65
+ */
66
+ export async function broadcastSignedBundleParallel(config, signedDataList) {
67
+ return Promise.all(signedDataList.map(signedData => broadcastSignedBundle(config, signedData)));
68
+ }
69
+ /**
70
+ * 直接广播原始交易(兼容 submitBundleToBlockRazor 风格)
71
+ *
72
+ * 接收签名后的原始交易字符串数组,逐个广播
73
+ *
74
+ * @param signatures 签名后的原始交易数组(hex string)
75
+ * @param config 广播配置
76
+ */
77
+ export async function submitBundleToXLayer(signatures, config) {
78
+ const provider = new JsonRpcProvider(config.rpcUrl);
79
+ const results = [];
80
+ const txHashes = [];
81
+ let successCount = 0;
82
+ let failCount = 0;
83
+ for (const signedTx of signatures) {
84
+ try {
85
+ const txResponse = await provider.broadcastTransaction(signedTx);
86
+ const receipt = await txResponse.wait();
87
+ if (receipt?.status === 1) {
88
+ successCount++;
89
+ txHashes.push(txResponse.hash);
90
+ results.push({ success: true, txHash: txResponse.hash });
91
+ }
92
+ else {
93
+ failCount++;
94
+ results.push({ success: false, txHash: txResponse.hash, error: 'Transaction reverted' });
95
+ }
96
+ }
97
+ catch (error) {
98
+ failCount++;
99
+ results.push({
100
+ success: false,
101
+ error: error instanceof Error ? error.message : String(error),
102
+ });
103
+ }
104
+ }
105
+ return {
106
+ code: successCount > 0,
107
+ txHashes,
108
+ successCount,
109
+ failCount,
110
+ results,
111
+ };
112
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * X-Layer Bundle 调用构建器
3
+ *
4
+ * 提供构建各种调用的便捷方法
5
+ */
6
+ import type { Call } from './types.js';
7
+ /**
8
+ * 构建 ERC20 approve 调用
9
+ */
10
+ export declare function buildApprove(token: string, spender: string, amount: bigint): Call;
11
+ /**
12
+ * 构建 ERC20 transfer 调用
13
+ */
14
+ export declare function buildTransfer(token: string, to: string, amount: bigint): Call;
15
+ /**
16
+ * 构建原生代币转账调用
17
+ */
18
+ export declare function buildNativeTransfer(to: string, amount: bigint): Call;
19
+ /**
20
+ * 构建 V2 Swap 买入调用 (OKB -> Token)
21
+ */
22
+ export declare function buildV2SwapBuy(tokenAddress: string, amountInOkb: bigint, amountOutMin: bigint | undefined, to: string, deadline?: number): Call;
23
+ /**
24
+ * 构建 V2 Swap 卖出调用 (Token -> OKB)
25
+ */
26
+ export declare function buildV2SwapSell(tokenAddress: string, amountIn: bigint, amountOutMin: bigint | undefined, to: string, deadline?: number): Call;
27
+ /**
28
+ * 构建 Flap Portal 买入调用 (内盘买入)
29
+ */
30
+ export declare function buildPortalBuy(tokenAddress: string, amountInOkb: bigint, amountOutMin: bigint | undefined, to: string, deadline?: number): Call;
31
+ /**
32
+ * 构建 Flap Portal 卖出调用 (内盘卖出)
33
+ */
34
+ export declare function buildPortalSell(tokenAddress: string, amountIn: bigint, amountOutMin: bigint | undefined, to: string, deadline?: number): Call;
@@ -0,0 +1,100 @@
1
+ /**
2
+ * X-Layer Bundle 调用构建器
3
+ *
4
+ * 提供构建各种调用的便捷方法
5
+ */
6
+ import { Interface } from 'ethers';
7
+ import { WOKB, POTATOSWAP_V2_ROUTER, FLAP_PORTAL } from './constants.js';
8
+ // ==================== ERC20 相关 ====================
9
+ /**
10
+ * 构建 ERC20 approve 调用
11
+ */
12
+ export function buildApprove(token, spender, amount) {
13
+ const iface = new Interface(['function approve(address,uint256) returns (bool)']);
14
+ return {
15
+ target: token,
16
+ value: 0n,
17
+ data: iface.encodeFunctionData('approve', [spender, amount]),
18
+ };
19
+ }
20
+ /**
21
+ * 构建 ERC20 transfer 调用
22
+ */
23
+ export function buildTransfer(token, to, amount) {
24
+ const iface = new Interface(['function transfer(address,uint256) returns (bool)']);
25
+ return {
26
+ target: token,
27
+ value: 0n,
28
+ data: iface.encodeFunctionData('transfer', [to, amount]),
29
+ };
30
+ }
31
+ /**
32
+ * 构建原生代币转账调用
33
+ */
34
+ export function buildNativeTransfer(to, amount) {
35
+ return {
36
+ target: to,
37
+ value: amount,
38
+ data: '0x',
39
+ };
40
+ }
41
+ // ==================== V2 Swap 相关 ====================
42
+ /**
43
+ * 构建 V2 Swap 买入调用 (OKB -> Token)
44
+ */
45
+ export function buildV2SwapBuy(tokenAddress, amountInOkb, amountOutMin = 0n, to, deadline) {
46
+ const iface = new Interface([
47
+ 'function swapExactETHForTokens(uint256 amountOutMin, address[] path, address to, uint256 deadline) payable returns (uint256[] amounts)',
48
+ ]);
49
+ const path = [WOKB, tokenAddress];
50
+ const dl = deadline || Math.floor(Date.now() / 1000) + 1200; // 20 分钟
51
+ return {
52
+ target: POTATOSWAP_V2_ROUTER,
53
+ value: amountInOkb,
54
+ data: iface.encodeFunctionData('swapExactETHForTokens', [amountOutMin, path, to, dl]),
55
+ };
56
+ }
57
+ /**
58
+ * 构建 V2 Swap 卖出调用 (Token -> OKB)
59
+ */
60
+ export function buildV2SwapSell(tokenAddress, amountIn, amountOutMin = 0n, to, deadline) {
61
+ const iface = new Interface([
62
+ 'function swapExactTokensForETH(uint256 amountIn, uint256 amountOutMin, address[] path, address to, uint256 deadline) returns (uint256[] amounts)',
63
+ ]);
64
+ const path = [tokenAddress, WOKB];
65
+ const dl = deadline || Math.floor(Date.now() / 1000) + 1200;
66
+ return {
67
+ target: POTATOSWAP_V2_ROUTER,
68
+ value: 0n,
69
+ data: iface.encodeFunctionData('swapExactTokensForETH', [amountIn, amountOutMin, path, to, dl]),
70
+ };
71
+ }
72
+ // ==================== Flap Portal 相关 ====================
73
+ /**
74
+ * 构建 Flap Portal 买入调用 (内盘买入)
75
+ */
76
+ export function buildPortalBuy(tokenAddress, amountInOkb, amountOutMin = 0n, to, deadline) {
77
+ const iface = new Interface([
78
+ 'function buy(address token, uint256 amountOutMin, address to, uint256 deadline) payable returns (uint256 amountOut)',
79
+ ]);
80
+ const dl = deadline || Math.floor(Date.now() / 1000) + 1200;
81
+ return {
82
+ target: FLAP_PORTAL,
83
+ value: amountInOkb,
84
+ data: iface.encodeFunctionData('buy', [tokenAddress, amountOutMin, to, dl]),
85
+ };
86
+ }
87
+ /**
88
+ * 构建 Flap Portal 卖出调用 (内盘卖出)
89
+ */
90
+ export function buildPortalSell(tokenAddress, amountIn, amountOutMin = 0n, to, deadline) {
91
+ const iface = new Interface([
92
+ 'function sell(address token, uint256 amountIn, uint256 amountOutMin, address to, uint256 deadline) returns (uint256 amountOut)',
93
+ ]);
94
+ const dl = deadline || Math.floor(Date.now() / 1000) + 1200;
95
+ return {
96
+ target: FLAP_PORTAL,
97
+ value: 0n,
98
+ data: iface.encodeFunctionData('sell', [tokenAddress, amountIn, amountOutMin, to, dl]),
99
+ };
100
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * X-Layer Bundle 执行器
3
+ *
4
+ * 核心的捆绑交易执行类
5
+ *
6
+ * 优化:第一个参与钱包作为 Sponsor,支付 gas
7
+ * 其他参与钱包不需要 gas
8
+ */
9
+ import { Wallet, JsonRpcProvider } from 'ethers';
10
+ import type { Call, BundleConfig, BundleResult } from './types.js';
11
+ /** Bundle 参与者 */
12
+ export interface BundleParticipant {
13
+ /** 钱包(或私钥字符串) */
14
+ wallet: Wallet | string;
15
+ /** 该钱包要执行的调用列表 */
16
+ calls: Call[];
17
+ }
18
+ /**
19
+ * X-Layer Bundle 执行器
20
+ *
21
+ * 使用 Type 4 交易实现多地址原子化捆绑
22
+ *
23
+ * 第一个参与钱包作为 Sponsor,支付 gas
24
+ * 其他参与钱包不需要 gas
25
+ */
26
+ export declare class XLayerBundle {
27
+ private provider;
28
+ private gasPrice;
29
+ private executorInterface;
30
+ constructor(config: BundleConfig);
31
+ /**
32
+ * 获取 Provider
33
+ */
34
+ getProvider(): JsonRpcProvider;
35
+ /**
36
+ * 执行 Bundle 交易
37
+ *
38
+ * 第一个参与者作为 Sponsor,支付 gas
39
+ * 其他参与者不需要 gas
40
+ *
41
+ * @param participants 参与者列表(第一个作为 Sponsor)
42
+ * @returns 执行结果
43
+ */
44
+ execute(participants: BundleParticipant[]): Promise<BundleResult>;
45
+ /**
46
+ * 简化的单钱包批量执行
47
+ */
48
+ executeBatch(wallet: Wallet | string, calls: Call[]): Promise<BundleResult>;
49
+ /**
50
+ * 获取 Sponsor 地址(第一个参与者)
51
+ *
52
+ * 注意:必须在 execute 时传入参与者才能确定 Sponsor
53
+ */
54
+ getSponsorAddress(participants: BundleParticipant[]): string;
55
+ /**
56
+ * 获取授权 nonce
57
+ */
58
+ private getAuthorizationNonce;
59
+ /**
60
+ * 签名 Type 4 交易
61
+ */
62
+ private signType4Transaction;
63
+ }
64
+ /**
65
+ * 创建 Bundle 执行器
66
+ *
67
+ * 不需要单独的 Sponsor 私钥
68
+ * 第一个参与钱包自动作为 Sponsor
69
+ */
70
+ export declare function createBundle(rpcUrl: string, gasPrice?: bigint): XLayerBundle;