four-flap-meme-sdk 1.7.3 → 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.
- package/dist/eip7702/xlayer/disperse.d.ts +98 -0
- package/dist/eip7702/xlayer/disperse.js +277 -0
- package/dist/eip7702/xlayer/index.d.ts +3 -1
- package/dist/eip7702/xlayer/index.js +5 -1
- package/dist/eip7702/xlayer/sign.d.ts +42 -20
- package/dist/eip7702/xlayer/sign.js +109 -25
- package/dist/eip7702/xlayer/sweep.d.ts +101 -0
- package/dist/eip7702/xlayer/sweep.js +301 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* X-Layer Bundle 代币分发
|
|
3
|
+
*
|
|
4
|
+
* 支持:
|
|
5
|
+
* - 原生代币 (OKB) 分发
|
|
6
|
+
* - ERC20 代币分发
|
|
7
|
+
* - 多跳转账(隐藏资金流向)
|
|
8
|
+
* - 自动利润计算
|
|
9
|
+
*
|
|
10
|
+
* 优化:
|
|
11
|
+
* - Type 4 交易:所有多跳在一个原子交易中完成
|
|
12
|
+
* - 第一个钱包作为 Sponsor,支付 gas + 利润
|
|
13
|
+
*/
|
|
14
|
+
/** 用户类型 */
|
|
15
|
+
export type UserType = 'v0' | 'v1' | 'normal';
|
|
16
|
+
/** 分发配置 */
|
|
17
|
+
export interface DisperseConfig {
|
|
18
|
+
/** RPC URL */
|
|
19
|
+
rpcUrl: string;
|
|
20
|
+
/** Gas Price (可选) */
|
|
21
|
+
gasPrice?: bigint;
|
|
22
|
+
/** 用户类型(影响利润率) */
|
|
23
|
+
userType?: UserType;
|
|
24
|
+
}
|
|
25
|
+
/** 分发接收者 */
|
|
26
|
+
export interface DisperseRecipient {
|
|
27
|
+
/** 接收地址 */
|
|
28
|
+
address: string;
|
|
29
|
+
/** 接收金额 */
|
|
30
|
+
amount: string;
|
|
31
|
+
/** 多跳钱包私钥(可选) */
|
|
32
|
+
hopPrivateKeys?: string[];
|
|
33
|
+
}
|
|
34
|
+
/** 原生代币分发参数 */
|
|
35
|
+
export interface DisperseNativeParams extends DisperseConfig {
|
|
36
|
+
/** 发送者私钥(第一个钱包,支付 gas + 利润) */
|
|
37
|
+
senderPrivateKey: string;
|
|
38
|
+
/** 接收者列表 */
|
|
39
|
+
recipients: DisperseRecipient[];
|
|
40
|
+
}
|
|
41
|
+
/** ERC20 分发参数 */
|
|
42
|
+
export interface DisperseERC20Params extends DisperseConfig {
|
|
43
|
+
/** 发送者私钥 */
|
|
44
|
+
senderPrivateKey: string;
|
|
45
|
+
/** 代币地址 */
|
|
46
|
+
tokenAddress: string;
|
|
47
|
+
/** 代币精度 */
|
|
48
|
+
tokenDecimals?: number;
|
|
49
|
+
/** 接收者列表 */
|
|
50
|
+
recipients: DisperseRecipient[];
|
|
51
|
+
}
|
|
52
|
+
/** 签名结果 */
|
|
53
|
+
export interface DisperseSignedResult {
|
|
54
|
+
/** 签名后的 Type 4 交易 */
|
|
55
|
+
signedTx: string;
|
|
56
|
+
/** 交易哈希 */
|
|
57
|
+
txHash: string;
|
|
58
|
+
/** Sponsor 地址 */
|
|
59
|
+
sponsorAddress: string;
|
|
60
|
+
/** 接收者数量 */
|
|
61
|
+
recipientCount: number;
|
|
62
|
+
/** 总金额 */
|
|
63
|
+
totalAmount: string;
|
|
64
|
+
/** 多跳钱包(如果有) */
|
|
65
|
+
hopWallets?: Array<{
|
|
66
|
+
address: string;
|
|
67
|
+
privateKey: string;
|
|
68
|
+
}>;
|
|
69
|
+
/** 时间戳 */
|
|
70
|
+
timestamp: number;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 原生代币 (OKB) 分发
|
|
74
|
+
*
|
|
75
|
+
* 支持多跳转账,所有操作在一个 Type 4 交易中原子完成
|
|
76
|
+
*
|
|
77
|
+
* 流程(无多跳):sender → [recipient1, recipient2, ...]
|
|
78
|
+
* 流程(有多跳):sender → hop1 → hop2 → ... → recipient
|
|
79
|
+
*/
|
|
80
|
+
export declare function signDisperseNative(params: DisperseNativeParams): Promise<DisperseSignedResult>;
|
|
81
|
+
/**
|
|
82
|
+
* ERC20 代币分发
|
|
83
|
+
*
|
|
84
|
+
* 支持多跳转账,所有操作在一个 Type 4 交易中原子完成
|
|
85
|
+
*/
|
|
86
|
+
export declare function signDisperseERC20(params: DisperseERC20Params): Promise<DisperseSignedResult>;
|
|
87
|
+
/**
|
|
88
|
+
* 快捷分发(自动生成多跳钱包)
|
|
89
|
+
*
|
|
90
|
+
* @param hopCount 多跳数量(0 = 无多跳)
|
|
91
|
+
*/
|
|
92
|
+
export declare function signDisperseNativeWithAutoHop(params: Omit<DisperseNativeParams, 'recipients'> & {
|
|
93
|
+
recipients: Array<{
|
|
94
|
+
address: string;
|
|
95
|
+
amount: string;
|
|
96
|
+
}>;
|
|
97
|
+
hopCount?: number;
|
|
98
|
+
}): Promise<DisperseSignedResult>;
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* X-Layer Bundle 代币分发
|
|
3
|
+
*
|
|
4
|
+
* 支持:
|
|
5
|
+
* - 原生代币 (OKB) 分发
|
|
6
|
+
* - ERC20 代币分发
|
|
7
|
+
* - 多跳转账(隐藏资金流向)
|
|
8
|
+
* - 自动利润计算
|
|
9
|
+
*
|
|
10
|
+
* 优化:
|
|
11
|
+
* - Type 4 交易:所有多跳在一个原子交易中完成
|
|
12
|
+
* - 第一个钱包作为 Sponsor,支付 gas + 利润
|
|
13
|
+
*/
|
|
14
|
+
import { ethers, Wallet, JsonRpcProvider, Interface } from 'ethers';
|
|
15
|
+
import { XLAYER_CHAIN_ID, EXECUTOR_ADDRESS, EXECUTOR_ABI, DEFAULT_GAS_PRICE, GAS_LIMIT_MULTIPLIER, XLAYER_PROFIT_CONFIG, } from './constants.js';
|
|
16
|
+
import { buildNativeTransfer, buildTransfer } from './builders.js';
|
|
17
|
+
// ==================== 利润计算 ====================
|
|
18
|
+
function getProfitRateBps(userType = 'v0') {
|
|
19
|
+
switch (userType) {
|
|
20
|
+
case 'v0':
|
|
21
|
+
return XLAYER_PROFIT_CONFIG.RATE_BPS_V0;
|
|
22
|
+
case 'v1':
|
|
23
|
+
return XLAYER_PROFIT_CONFIG.RATE_BPS_V1;
|
|
24
|
+
default:
|
|
25
|
+
return XLAYER_PROFIT_CONFIG.RATE_BPS;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function calculateProfitWei(amount, userType = 'v0') {
|
|
29
|
+
const bps = getProfitRateBps(userType);
|
|
30
|
+
return (amount * BigInt(bps)) / 10000n;
|
|
31
|
+
}
|
|
32
|
+
// ==================== 授权签名 ====================
|
|
33
|
+
function hashAuthorization(chainId, executorAddress, nonce) {
|
|
34
|
+
const encoded = ethers.encodeRlp([
|
|
35
|
+
ethers.toBeHex(chainId),
|
|
36
|
+
executorAddress,
|
|
37
|
+
ethers.toBeHex(nonce),
|
|
38
|
+
]);
|
|
39
|
+
const prefixed = ethers.concat([new Uint8Array([0x05]), encoded]);
|
|
40
|
+
return ethers.keccak256(prefixed);
|
|
41
|
+
}
|
|
42
|
+
function signAuthorization(wallet, nonce = 0) {
|
|
43
|
+
const messageHash = hashAuthorization(XLAYER_CHAIN_ID, EXECUTOR_ADDRESS, nonce);
|
|
44
|
+
const signature = wallet.signingKey.sign(messageHash);
|
|
45
|
+
return {
|
|
46
|
+
chainId: XLAYER_CHAIN_ID,
|
|
47
|
+
address: EXECUTOR_ADDRESS,
|
|
48
|
+
nonce,
|
|
49
|
+
v: signature.v,
|
|
50
|
+
r: signature.r,
|
|
51
|
+
s: signature.s,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
// ==================== 生成多跳钱包 ====================
|
|
55
|
+
function generateHopWallets(count) {
|
|
56
|
+
const wallets = [];
|
|
57
|
+
for (let i = 0; i < count; i++) {
|
|
58
|
+
const w = Wallet.createRandom();
|
|
59
|
+
wallets.push({
|
|
60
|
+
address: w.address,
|
|
61
|
+
privateKey: w.privateKey,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return wallets;
|
|
65
|
+
}
|
|
66
|
+
// ==================== 核心签名函数 ====================
|
|
67
|
+
async function buildAndSignType4Transaction(config, participants) {
|
|
68
|
+
const { rpcUrl, gasPrice = DEFAULT_GAS_PRICE } = config;
|
|
69
|
+
const provider = new JsonRpcProvider(rpcUrl);
|
|
70
|
+
const executorInterface = new Interface(EXECUTOR_ABI);
|
|
71
|
+
const sponsor = participants[0].wallet;
|
|
72
|
+
// 准备授权
|
|
73
|
+
const authorizations = [];
|
|
74
|
+
const allCalls = [];
|
|
75
|
+
for (const p of participants) {
|
|
76
|
+
const auth = signAuthorization(p.wallet);
|
|
77
|
+
authorizations.push(auth);
|
|
78
|
+
allCalls.push(...p.calls);
|
|
79
|
+
}
|
|
80
|
+
// 构建 execute 调用
|
|
81
|
+
const executeData = executorInterface.encodeFunctionData('execute', [
|
|
82
|
+
allCalls.map(c => ({
|
|
83
|
+
target: c.target,
|
|
84
|
+
value: c.value || 0n,
|
|
85
|
+
data: c.data,
|
|
86
|
+
})),
|
|
87
|
+
]);
|
|
88
|
+
const totalValue = allCalls.reduce((sum, c) => sum + (c.value || 0n), 0n);
|
|
89
|
+
const gasLimit = BigInt(Math.ceil(Number(100000n + BigInt(allCalls.length) * 150000n) * GAS_LIMIT_MULTIPLIER));
|
|
90
|
+
const sponsorNonce = await provider.getTransactionCount(sponsor.address);
|
|
91
|
+
// 构建 Type 4 交易
|
|
92
|
+
const tx = {
|
|
93
|
+
type: 4,
|
|
94
|
+
chainId: XLAYER_CHAIN_ID,
|
|
95
|
+
to: sponsor.address,
|
|
96
|
+
data: executeData,
|
|
97
|
+
value: totalValue,
|
|
98
|
+
authorizationList: authorizations,
|
|
99
|
+
gasLimit,
|
|
100
|
+
gasPrice,
|
|
101
|
+
nonce: sponsorNonce,
|
|
102
|
+
};
|
|
103
|
+
// 签名
|
|
104
|
+
const fields = [
|
|
105
|
+
ethers.toBeHex(tx.chainId),
|
|
106
|
+
ethers.toBeHex(tx.nonce),
|
|
107
|
+
ethers.toBeHex(tx.gasPrice),
|
|
108
|
+
ethers.toBeHex(tx.gasLimit),
|
|
109
|
+
tx.to,
|
|
110
|
+
ethers.toBeHex(tx.value),
|
|
111
|
+
tx.data,
|
|
112
|
+
tx.authorizationList.map((auth) => [
|
|
113
|
+
ethers.toBeHex(auth.chainId),
|
|
114
|
+
auth.address,
|
|
115
|
+
ethers.toBeHex(auth.nonce),
|
|
116
|
+
ethers.toBeHex(auth.v),
|
|
117
|
+
auth.r,
|
|
118
|
+
auth.s,
|
|
119
|
+
]),
|
|
120
|
+
];
|
|
121
|
+
const unsigned = ethers.concat([new Uint8Array([0x04]), ethers.encodeRlp(fields)]);
|
|
122
|
+
const txHashToSign = ethers.keccak256(unsigned);
|
|
123
|
+
const signature = sponsor.signingKey.sign(txHashToSign);
|
|
124
|
+
const signedFields = [...fields, ethers.toBeHex(signature.v), signature.r, signature.s];
|
|
125
|
+
const signedTx = ethers.hexlify(ethers.concat([new Uint8Array([0x04]), ethers.encodeRlp(signedFields)]));
|
|
126
|
+
const txHash = ethers.keccak256(signedTx);
|
|
127
|
+
return { signedTx, txHash, sponsorAddress: sponsor.address };
|
|
128
|
+
}
|
|
129
|
+
// ==================== 分发函数 ====================
|
|
130
|
+
/**
|
|
131
|
+
* 原生代币 (OKB) 分发
|
|
132
|
+
*
|
|
133
|
+
* 支持多跳转账,所有操作在一个 Type 4 交易中原子完成
|
|
134
|
+
*
|
|
135
|
+
* 流程(无多跳):sender → [recipient1, recipient2, ...]
|
|
136
|
+
* 流程(有多跳):sender → hop1 → hop2 → ... → recipient
|
|
137
|
+
*/
|
|
138
|
+
export async function signDisperseNative(params) {
|
|
139
|
+
const { senderPrivateKey, recipients, userType = 'v0', ...config } = params;
|
|
140
|
+
if (recipients.length === 0) {
|
|
141
|
+
throw new Error('至少需要一个接收者');
|
|
142
|
+
}
|
|
143
|
+
const provider = new JsonRpcProvider(config.rpcUrl);
|
|
144
|
+
const sender = new Wallet(senderPrivateKey, provider);
|
|
145
|
+
// 计算总金额
|
|
146
|
+
let totalAmountWei = 0n;
|
|
147
|
+
for (const r of recipients) {
|
|
148
|
+
totalAmountWei += ethers.parseEther(r.amount);
|
|
149
|
+
}
|
|
150
|
+
// 计算利润
|
|
151
|
+
const profitWei = calculateProfitWei(totalAmountWei, userType);
|
|
152
|
+
const profitRecipient = XLAYER_PROFIT_CONFIG.RECIPIENT;
|
|
153
|
+
console.log(`[Bundle分发] OKB分发: ${recipients.length} 个接收者, 总金额=${ethers.formatEther(totalAmountWei)} OKB, 利润=${ethers.formatEther(profitWei)} OKB`);
|
|
154
|
+
// 收集所有多跳钱包
|
|
155
|
+
const allHopWallets = [];
|
|
156
|
+
const participants = [];
|
|
157
|
+
// 发送者的 calls
|
|
158
|
+
const senderCalls = [];
|
|
159
|
+
for (const recipient of recipients) {
|
|
160
|
+
const amountWei = ethers.parseEther(recipient.amount);
|
|
161
|
+
const hopKeys = recipient.hopPrivateKeys || [];
|
|
162
|
+
if (hopKeys.length === 0) {
|
|
163
|
+
// 无多跳:直接转账
|
|
164
|
+
senderCalls.push(buildNativeTransfer(recipient.address, amountWei));
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
// 有多跳:sender → hop1 → hop2 → ... → recipient
|
|
168
|
+
// 构建多跳链
|
|
169
|
+
const hopWallets = hopKeys.map(pk => new Wallet(pk, provider));
|
|
170
|
+
// 记录多跳钱包
|
|
171
|
+
hopWallets.forEach(w => allHopWallets.push({ address: w.address, privateKey: w.privateKey }));
|
|
172
|
+
// sender → hop1
|
|
173
|
+
senderCalls.push(buildNativeTransfer(hopWallets[0].address, amountWei));
|
|
174
|
+
// 添加中间钱包的转账
|
|
175
|
+
for (let i = 0; i < hopWallets.length; i++) {
|
|
176
|
+
const from = hopWallets[i];
|
|
177
|
+
const to = i === hopWallets.length - 1 ? recipient.address : hopWallets[i + 1].address;
|
|
178
|
+
// 添加中间钱包为参与者
|
|
179
|
+
participants.push({
|
|
180
|
+
wallet: from,
|
|
181
|
+
calls: [buildNativeTransfer(to, amountWei)],
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// 添加利润转账(由 sender 支付)
|
|
187
|
+
if (profitWei > 0n) {
|
|
188
|
+
senderCalls.push(buildNativeTransfer(profitRecipient, profitWei));
|
|
189
|
+
}
|
|
190
|
+
// sender 作为第一个参与者
|
|
191
|
+
participants.unshift({ wallet: sender, calls: senderCalls });
|
|
192
|
+
const result = await buildAndSignType4Transaction(config, participants);
|
|
193
|
+
return {
|
|
194
|
+
...result,
|
|
195
|
+
recipientCount: recipients.length,
|
|
196
|
+
totalAmount: totalAmountWei.toString(),
|
|
197
|
+
hopWallets: allHopWallets.length > 0 ? allHopWallets : undefined,
|
|
198
|
+
timestamp: Date.now(),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* ERC20 代币分发
|
|
203
|
+
*
|
|
204
|
+
* 支持多跳转账,所有操作在一个 Type 4 交易中原子完成
|
|
205
|
+
*/
|
|
206
|
+
export async function signDisperseERC20(params) {
|
|
207
|
+
const { senderPrivateKey, tokenAddress, tokenDecimals = 18, recipients, userType = 'v0', ...config } = params;
|
|
208
|
+
if (recipients.length === 0) {
|
|
209
|
+
throw new Error('至少需要一个接收者');
|
|
210
|
+
}
|
|
211
|
+
const provider = new JsonRpcProvider(config.rpcUrl);
|
|
212
|
+
const sender = new Wallet(senderPrivateKey, provider);
|
|
213
|
+
// 计算总金额
|
|
214
|
+
let totalAmountWei = 0n;
|
|
215
|
+
for (const r of recipients) {
|
|
216
|
+
totalAmountWei += ethers.parseUnits(r.amount, tokenDecimals);
|
|
217
|
+
}
|
|
218
|
+
console.log(`[Bundle分发] ERC20分发: ${recipients.length} 个接收者, 代币=${tokenAddress}`);
|
|
219
|
+
const allHopWallets = [];
|
|
220
|
+
const participants = [];
|
|
221
|
+
const senderCalls = [];
|
|
222
|
+
for (const recipient of recipients) {
|
|
223
|
+
const amountWei = ethers.parseUnits(recipient.amount, tokenDecimals);
|
|
224
|
+
const hopKeys = recipient.hopPrivateKeys || [];
|
|
225
|
+
if (hopKeys.length === 0) {
|
|
226
|
+
senderCalls.push(buildTransfer(tokenAddress, recipient.address, amountWei));
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
const hopWallets = hopKeys.map(pk => new Wallet(pk, provider));
|
|
230
|
+
hopWallets.forEach(w => allHopWallets.push({ address: w.address, privateKey: w.privateKey }));
|
|
231
|
+
senderCalls.push(buildTransfer(tokenAddress, hopWallets[0].address, amountWei));
|
|
232
|
+
for (let i = 0; i < hopWallets.length; i++) {
|
|
233
|
+
const from = hopWallets[i];
|
|
234
|
+
const to = i === hopWallets.length - 1 ? recipient.address : hopWallets[i + 1].address;
|
|
235
|
+
participants.push({
|
|
236
|
+
wallet: from,
|
|
237
|
+
calls: [buildTransfer(tokenAddress, to, amountWei)],
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
participants.unshift({ wallet: sender, calls: senderCalls });
|
|
243
|
+
const result = await buildAndSignType4Transaction(config, participants);
|
|
244
|
+
return {
|
|
245
|
+
...result,
|
|
246
|
+
recipientCount: recipients.length,
|
|
247
|
+
totalAmount: totalAmountWei.toString(),
|
|
248
|
+
hopWallets: allHopWallets.length > 0 ? allHopWallets : undefined,
|
|
249
|
+
timestamp: Date.now(),
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* 快捷分发(自动生成多跳钱包)
|
|
254
|
+
*
|
|
255
|
+
* @param hopCount 多跳数量(0 = 无多跳)
|
|
256
|
+
*/
|
|
257
|
+
export async function signDisperseNativeWithAutoHop(params) {
|
|
258
|
+
const { hopCount = 0, recipients, ...rest } = params;
|
|
259
|
+
if (hopCount <= 0) {
|
|
260
|
+
return signDisperseNative({
|
|
261
|
+
...rest,
|
|
262
|
+
recipients: recipients.map(r => ({ ...r, hopPrivateKeys: [] })),
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
// 为每个接收者生成多跳钱包
|
|
266
|
+
const recipientsWithHops = recipients.map(r => {
|
|
267
|
+
const hops = generateHopWallets(hopCount);
|
|
268
|
+
return {
|
|
269
|
+
...r,
|
|
270
|
+
hopPrivateKeys: hops.map(h => h.privateKey),
|
|
271
|
+
};
|
|
272
|
+
});
|
|
273
|
+
return signDisperseNative({
|
|
274
|
+
...rest,
|
|
275
|
+
recipients: recipientsWithHops,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
@@ -56,5 +56,7 @@ export { bundleBatchApprove, bundleSingleApprove, getSpendersToApprove, type Bat
|
|
|
56
56
|
export { bundleBatchBuy, bundleBatchSell, bundleBuySellPair, type BatchBuyParams, type BatchSellParams, type BuySellPairParams, } from './trade.js';
|
|
57
57
|
export { checkApprovalStatus, checkApprovalStatusBatch, checkSingleApprovalStatus, getApprovalDetails, getUnapprovedSpenders, } from './check.js';
|
|
58
58
|
export { collectProfit, collectProfitBatch, collectProfitFromTrade, calculateProfit, getProfitRateBps, getProfitRecipient, type UserType, type ProfitMode, type ProfitParams, type BatchProfitParams, type ProfitResult, } from './profit.js';
|
|
59
|
-
export { signBatchApprove, signBatchBuy, signBatchSell,
|
|
59
|
+
export { signBatchApprove, signBatchBuy, signBatchSell, signBuySellPair, signCustomCalls, type SignConfig, type SignedTransaction, type BatchApproveSignParams, type BatchBuySignParams, type BatchSellSignParams, type BuySellPairSignParams, type UserType as SignUserType, } from './sign.js';
|
|
60
60
|
export { broadcastSignedBundle, broadcastSignedBundleBatch, broadcastSignedBundleParallel, submitBundleToXLayer, type BroadcastConfig, type BroadcastResult, } from './broadcast.js';
|
|
61
|
+
export { signDisperseNative, signDisperseERC20, signDisperseNativeWithAutoHop, type DisperseConfig, type DisperseRecipient, type DisperseNativeParams, type DisperseERC20Params, type DisperseSignedResult, } from './disperse.js';
|
|
62
|
+
export { signSweepNative, signSweepERC20, signSweepNativeWithAutoHop, type SweepConfig, type SweepSource, type SweepNativeParams, type SweepERC20Params, type SweepSignedResult, } from './sweep.js';
|
|
@@ -65,6 +65,10 @@ export { checkApprovalStatus, checkApprovalStatusBatch, checkSingleApprovalStatu
|
|
|
65
65
|
// ==================== 利润刮取 ====================
|
|
66
66
|
export { collectProfit, collectProfitBatch, collectProfitFromTrade, calculateProfit, getProfitRateBps, getProfitRecipient, } from './profit.js';
|
|
67
67
|
// ==================== 前端签名(完整签名,后端只需广播) ====================
|
|
68
|
-
export { signBatchApprove, signBatchBuy, signBatchSell,
|
|
68
|
+
export { signBatchApprove, signBatchBuy, signBatchSell, signBuySellPair, signCustomCalls, } from './sign.js';
|
|
69
69
|
// ==================== 后端广播(不需要私钥) ====================
|
|
70
70
|
export { broadcastSignedBundle, broadcastSignedBundleBatch, broadcastSignedBundleParallel, submitBundleToXLayer, } from './broadcast.js';
|
|
71
|
+
// ==================== 代币分发(支持多跳) ====================
|
|
72
|
+
export { signDisperseNative, signDisperseERC20, signDisperseNativeWithAutoHop, } from './disperse.js';
|
|
73
|
+
// ==================== 代币归集(支持多跳) ====================
|
|
74
|
+
export { signSweepNative, signSweepERC20, signSweepNativeWithAutoHop, } from './sweep.js';
|
|
@@ -4,16 +4,22 @@
|
|
|
4
4
|
* 前端使用:构建并签名完整的 Type 4 交易
|
|
5
5
|
* 返回已签名的原始交易数据,后端只需广播
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* 优化:
|
|
8
|
+
* - 第一个参与钱包作为 Sponsor,支付 gas
|
|
9
|
+
* - 其他参与钱包不需要 gas
|
|
10
|
+
* - 利润自动计算并包含在交易中(不需要前端传递)
|
|
9
11
|
*/
|
|
10
12
|
import type { Call } from './types.js';
|
|
13
|
+
/** 用户类型(影响利润率) */
|
|
14
|
+
export type UserType = 'v0' | 'v1' | 'normal';
|
|
11
15
|
/** 签名配置(简化版:不需要单独的 Sponsor) */
|
|
12
16
|
export interface SignConfig {
|
|
13
17
|
/** RPC URL(用于获取 nonce) */
|
|
14
18
|
rpcUrl: string;
|
|
15
19
|
/** Gas Price (可选) */
|
|
16
20
|
gasPrice?: bigint;
|
|
21
|
+
/** 用户类型(影响利润率,默认 v0) */
|
|
22
|
+
userType?: UserType;
|
|
17
23
|
}
|
|
18
24
|
/** 签名后的交易数据(发送到后端广播) */
|
|
19
25
|
export interface SignedTransaction {
|
|
@@ -43,19 +49,21 @@ export interface BatchApproveSignParams extends SignConfig {
|
|
|
43
49
|
export interface BatchBuySignParams extends SignConfig {
|
|
44
50
|
/** 代币地址 */
|
|
45
51
|
tokenAddress: string;
|
|
46
|
-
/** 买入列表(第一个钱包作为 Sponsor,支付 gas
|
|
52
|
+
/** 买入列表(第一个钱包作为 Sponsor,支付 gas + 利润) */
|
|
47
53
|
wallets: Array<{
|
|
48
54
|
privateKey: string;
|
|
49
55
|
buyAmount: string;
|
|
50
56
|
}>;
|
|
51
57
|
/** 交易类型 */
|
|
52
58
|
tradeType?: 'v2' | 'portal';
|
|
59
|
+
/** 总交易笔数(用于计算利润,默认 = 买入数量) */
|
|
60
|
+
totalTxCount?: number;
|
|
53
61
|
}
|
|
54
62
|
/** 批量卖出签名参数 */
|
|
55
63
|
export interface BatchSellSignParams extends SignConfig {
|
|
56
64
|
/** 代币地址 */
|
|
57
65
|
tokenAddress: string;
|
|
58
|
-
/** 卖出列表(第一个钱包作为 Sponsor,支付 gas
|
|
66
|
+
/** 卖出列表(第一个钱包作为 Sponsor,支付 gas + 利润) */
|
|
59
67
|
wallets: Array<{
|
|
60
68
|
privateKey: string;
|
|
61
69
|
sellAmount: string;
|
|
@@ -63,48 +71,62 @@ export interface BatchSellSignParams extends SignConfig {
|
|
|
63
71
|
}>;
|
|
64
72
|
/** 交易类型 */
|
|
65
73
|
tradeType?: 'v2' | 'portal';
|
|
74
|
+
/** 卖出金额(OKB)用于计算利润 */
|
|
75
|
+
sellValueOkb?: string;
|
|
76
|
+
/** 总交易笔数(用于计算利润,默认 = 卖出数量) */
|
|
77
|
+
totalTxCount?: number;
|
|
66
78
|
}
|
|
67
|
-
/**
|
|
68
|
-
export interface
|
|
69
|
-
/**
|
|
70
|
-
|
|
79
|
+
/** 买卖配对签名参数(刷量用) */
|
|
80
|
+
export interface BuySellPairSignParams extends SignConfig {
|
|
81
|
+
/** 代币地址 */
|
|
82
|
+
tokenAddress: string;
|
|
83
|
+
/** 买入钱包 */
|
|
84
|
+
buyWallet: {
|
|
71
85
|
privateKey: string;
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
|
|
86
|
+
buyAmount: string;
|
|
87
|
+
};
|
|
88
|
+
/** 卖出钱包 */
|
|
89
|
+
sellWallet: {
|
|
90
|
+
privateKey: string;
|
|
91
|
+
sellAmount: string;
|
|
92
|
+
sellDecimals?: number;
|
|
93
|
+
};
|
|
94
|
+
/** 交易类型 */
|
|
95
|
+
tradeType?: 'v2' | 'portal';
|
|
76
96
|
}
|
|
77
97
|
/**
|
|
78
98
|
* 批量授权签名(前端调用)
|
|
79
99
|
*
|
|
80
100
|
* 第一个钱包作为 Sponsor,支付 gas
|
|
81
|
-
*
|
|
101
|
+
* 授权不需要利润
|
|
82
102
|
*/
|
|
83
103
|
export declare function signBatchApprove(params: BatchApproveSignParams): Promise<SignedTransaction>;
|
|
84
104
|
/**
|
|
85
105
|
* 批量买入签名(前端调用)
|
|
86
106
|
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
107
|
+
* ✅ 利润自动计算:根据交易金额和笔数自动计算利润
|
|
108
|
+
* 利润由第一个钱包支付,包含在交易中
|
|
89
109
|
*/
|
|
90
110
|
export declare function signBatchBuy(params: BatchBuySignParams): Promise<SignedTransaction>;
|
|
91
111
|
/**
|
|
92
112
|
* 批量卖出签名(前端调用)
|
|
93
113
|
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
114
|
+
* ✅ 利润自动计算:根据交易金额和笔数自动计算利润
|
|
115
|
+
* 利润由第一个钱包支付,包含在交易中
|
|
96
116
|
*/
|
|
97
117
|
export declare function signBatchSell(params: BatchSellSignParams): Promise<SignedTransaction>;
|
|
98
118
|
/**
|
|
99
|
-
*
|
|
119
|
+
* 买卖配对签名(刷量用)
|
|
100
120
|
*
|
|
101
|
-
*
|
|
121
|
+
* ✅ 利润自动计算:根据买入金额计算利润
|
|
122
|
+
* 买入钱包作为 Sponsor,支付 gas + 利润
|
|
102
123
|
*/
|
|
103
|
-
export declare function
|
|
124
|
+
export declare function signBuySellPair(params: BuySellPairSignParams): Promise<SignedTransaction>;
|
|
104
125
|
/**
|
|
105
126
|
* 通用签名(前端调用)
|
|
106
127
|
*
|
|
107
128
|
* 第一个钱包作为 Sponsor,支付 gas
|
|
129
|
+
* 需要自行添加利润转账 call
|
|
108
130
|
*/
|
|
109
131
|
export declare function signCustomCalls(config: SignConfig, walletsWithCalls: Array<{
|
|
110
132
|
privateKey: string;
|
|
@@ -4,12 +4,46 @@
|
|
|
4
4
|
* 前端使用:构建并签名完整的 Type 4 交易
|
|
5
5
|
* 返回已签名的原始交易数据,后端只需广播
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* 优化:
|
|
8
|
+
* - 第一个参与钱包作为 Sponsor,支付 gas
|
|
9
|
+
* - 其他参与钱包不需要 gas
|
|
10
|
+
* - 利润自动计算并包含在交易中(不需要前端传递)
|
|
9
11
|
*/
|
|
10
12
|
import { ethers, Wallet, JsonRpcProvider, Interface } from 'ethers';
|
|
11
|
-
import { XLAYER_CHAIN_ID, EXECUTOR_ADDRESS, EXECUTOR_ABI, SPENDERS_TO_APPROVE, MAX_UINT256, DEFAULT_GAS_PRICE, GAS_LIMIT_MULTIPLIER, } from './constants.js';
|
|
13
|
+
import { XLAYER_CHAIN_ID, EXECUTOR_ADDRESS, EXECUTOR_ABI, SPENDERS_TO_APPROVE, MAX_UINT256, DEFAULT_GAS_PRICE, GAS_LIMIT_MULTIPLIER, XLAYER_PROFIT_CONFIG, } from './constants.js';
|
|
12
14
|
import { buildApprove, buildV2SwapBuy, buildV2SwapSell, buildPortalBuy, buildPortalSell, buildNativeTransfer } from './builders.js';
|
|
15
|
+
// ==================== 利润计算 ====================
|
|
16
|
+
/**
|
|
17
|
+
* 获取利润比例(基点)
|
|
18
|
+
*
|
|
19
|
+
* 捆绑模式:按交易笔数收费
|
|
20
|
+
* - v0: 4 bps/笔
|
|
21
|
+
* - v1: 5 bps/笔
|
|
22
|
+
* - normal: 6 bps/笔(换手模式)
|
|
23
|
+
*/
|
|
24
|
+
function getProfitRateBps(userType = 'v0') {
|
|
25
|
+
switch (userType) {
|
|
26
|
+
case 'v0':
|
|
27
|
+
return XLAYER_PROFIT_CONFIG.RATE_BPS_V0_DOUBLE; // 4 bps
|
|
28
|
+
case 'v1':
|
|
29
|
+
return XLAYER_PROFIT_CONFIG.RATE_BPS_V1_DOUBLE; // 5 bps
|
|
30
|
+
default:
|
|
31
|
+
return XLAYER_PROFIT_CONFIG.RATE_BPS_SWAP; // 6 bps
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 计算利润金额
|
|
36
|
+
*
|
|
37
|
+
* @param amount 交易金额
|
|
38
|
+
* @param txCount 交易笔数
|
|
39
|
+
* @param userType 用户类型
|
|
40
|
+
* @returns 利润金额
|
|
41
|
+
*/
|
|
42
|
+
function calculateProfitWei(amount, txCount, userType = 'v0') {
|
|
43
|
+
const bpsPerTx = getProfitRateBps(userType);
|
|
44
|
+
const totalBps = bpsPerTx * txCount;
|
|
45
|
+
return (amount * BigInt(totalBps)) / 10000n;
|
|
46
|
+
}
|
|
13
47
|
// ==================== 授权签名工具 ====================
|
|
14
48
|
/** 计算授权消息哈希 */
|
|
15
49
|
function hashAuthorization(chainId, executorAddress, nonce) {
|
|
@@ -138,7 +172,7 @@ async function buildAndSignType4Transaction(config, participants) {
|
|
|
138
172
|
* 批量授权签名(前端调用)
|
|
139
173
|
*
|
|
140
174
|
* 第一个钱包作为 Sponsor,支付 gas
|
|
141
|
-
*
|
|
175
|
+
* 授权不需要利润
|
|
142
176
|
*/
|
|
143
177
|
export async function signBatchApprove(params) {
|
|
144
178
|
const { tokenAddress, privateKeys, ...config } = params;
|
|
@@ -151,60 +185,110 @@ export async function signBatchApprove(params) {
|
|
|
151
185
|
/**
|
|
152
186
|
* 批量买入签名(前端调用)
|
|
153
187
|
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
188
|
+
* ✅ 利润自动计算:根据交易金额和笔数自动计算利润
|
|
189
|
+
* 利润由第一个钱包支付,包含在交易中
|
|
156
190
|
*/
|
|
157
191
|
export async function signBatchBuy(params) {
|
|
158
|
-
const { tokenAddress, wallets, tradeType = 'v2', ...config } = params;
|
|
159
|
-
|
|
192
|
+
const { tokenAddress, wallets, tradeType = 'v2', userType = 'v0', totalTxCount, ...config } = params;
|
|
193
|
+
// 计算总交易金额
|
|
194
|
+
let totalAmountWei = 0n;
|
|
195
|
+
for (const w of wallets) {
|
|
196
|
+
totalAmountWei += ethers.parseEther(w.buyAmount);
|
|
197
|
+
}
|
|
198
|
+
// 计算利润(根据交易笔数)
|
|
199
|
+
const txCount = totalTxCount ?? wallets.length;
|
|
200
|
+
const profitWei = calculateProfitWei(totalAmountWei, txCount, userType);
|
|
201
|
+
const profitRecipient = XLAYER_PROFIT_CONFIG.RECIPIENT;
|
|
202
|
+
console.log(`[Bundle买入] 利润计算: 交易金额=${ethers.formatEther(totalAmountWei)} OKB, 笔数=${txCount}, userType=${userType}, 利润=${ethers.formatEther(profitWei)} OKB`);
|
|
203
|
+
// 构建参与者 calls
|
|
204
|
+
const participants = wallets.map((w, index) => {
|
|
160
205
|
const wallet = new Wallet(w.privateKey);
|
|
161
206
|
const amountWei = ethers.parseEther(w.buyAmount);
|
|
162
207
|
const call = tradeType === 'portal'
|
|
163
208
|
? buildPortalBuy(tokenAddress, amountWei, 0n, wallet.address)
|
|
164
209
|
: buildV2SwapBuy(tokenAddress, amountWei, 0n, wallet.address);
|
|
165
|
-
|
|
210
|
+
const calls = [call];
|
|
211
|
+
// ✅ 第一个钱包添加利润转账
|
|
212
|
+
if (index === 0 && profitWei > 0n) {
|
|
213
|
+
calls.push(buildNativeTransfer(profitRecipient, profitWei));
|
|
214
|
+
}
|
|
215
|
+
return { privateKey: w.privateKey, calls };
|
|
166
216
|
});
|
|
167
217
|
return buildAndSignType4Transaction(config, participants);
|
|
168
218
|
}
|
|
169
219
|
/**
|
|
170
220
|
* 批量卖出签名(前端调用)
|
|
171
221
|
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
222
|
+
* ✅ 利润自动计算:根据交易金额和笔数自动计算利润
|
|
223
|
+
* 利润由第一个钱包支付,包含在交易中
|
|
174
224
|
*/
|
|
175
225
|
export async function signBatchSell(params) {
|
|
176
|
-
const { tokenAddress, wallets, tradeType = 'v2', ...config } = params;
|
|
177
|
-
|
|
226
|
+
const { tokenAddress, wallets, tradeType = 'v2', userType = 'v0', sellValueOkb, totalTxCount, ...config } = params;
|
|
227
|
+
// 计算利润(需要前端提供卖出金额的 OKB 等值)
|
|
228
|
+
// 因为卖出时不知道能得到多少 OKB,需要前端预估
|
|
229
|
+
const txCount = totalTxCount ?? wallets.length;
|
|
230
|
+
let profitWei = 0n;
|
|
231
|
+
const profitRecipient = XLAYER_PROFIT_CONFIG.RECIPIENT;
|
|
232
|
+
if (sellValueOkb) {
|
|
233
|
+
const sellAmountWei = ethers.parseEther(sellValueOkb);
|
|
234
|
+
profitWei = calculateProfitWei(sellAmountWei, txCount, userType);
|
|
235
|
+
console.log(`[Bundle卖出] 利润计算: 预估金额=${sellValueOkb} OKB, 笔数=${txCount}, userType=${userType}, 利润=${ethers.formatEther(profitWei)} OKB`);
|
|
236
|
+
}
|
|
237
|
+
// 构建参与者 calls
|
|
238
|
+
const participants = wallets.map((w, index) => {
|
|
178
239
|
const wallet = new Wallet(w.privateKey);
|
|
179
240
|
const decimals = w.sellDecimals ?? 18;
|
|
180
241
|
const amountWei = ethers.parseUnits(w.sellAmount, decimals);
|
|
181
242
|
const call = tradeType === 'portal'
|
|
182
243
|
? buildPortalSell(tokenAddress, amountWei, 0n, wallet.address)
|
|
183
244
|
: buildV2SwapSell(tokenAddress, amountWei, 0n, wallet.address);
|
|
184
|
-
|
|
245
|
+
const calls = [call];
|
|
246
|
+
// ✅ 第一个钱包添加利润转账
|
|
247
|
+
if (index === 0 && profitWei > 0n) {
|
|
248
|
+
calls.push(buildNativeTransfer(profitRecipient, profitWei));
|
|
249
|
+
}
|
|
250
|
+
return { privateKey: w.privateKey, calls };
|
|
185
251
|
});
|
|
186
252
|
return buildAndSignType4Transaction(config, participants);
|
|
187
253
|
}
|
|
188
254
|
/**
|
|
189
|
-
*
|
|
255
|
+
* 买卖配对签名(刷量用)
|
|
190
256
|
*
|
|
191
|
-
*
|
|
257
|
+
* ✅ 利润自动计算:根据买入金额计算利润
|
|
258
|
+
* 买入钱包作为 Sponsor,支付 gas + 利润
|
|
192
259
|
*/
|
|
193
|
-
export async function
|
|
194
|
-
const {
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
260
|
+
export async function signBuySellPair(params) {
|
|
261
|
+
const { tokenAddress, buyWallet, sellWallet, tradeType = 'v2', userType = 'v0', ...config } = params;
|
|
262
|
+
const buyAmountWei = ethers.parseEther(buyWallet.buyAmount);
|
|
263
|
+
// 刷量模式:2笔交易(买+卖),按 2 笔计费
|
|
264
|
+
const profitWei = calculateProfitWei(buyAmountWei, 2, userType);
|
|
265
|
+
const profitRecipient = XLAYER_PROFIT_CONFIG.RECIPIENT;
|
|
266
|
+
console.log(`[Bundle刷量] 利润计算: 交易金额=${buyWallet.buyAmount} OKB, 笔数=2, userType=${userType}, 利润=${ethers.formatEther(profitWei)} OKB`);
|
|
267
|
+
const buyerWallet = new Wallet(buyWallet.privateKey);
|
|
268
|
+
const buyCall = tradeType === 'portal'
|
|
269
|
+
? buildPortalBuy(tokenAddress, buyAmountWei, 0n, buyerWallet.address)
|
|
270
|
+
: buildV2SwapBuy(tokenAddress, buyAmountWei, 0n, buyerWallet.address);
|
|
271
|
+
const sellerWallet = new Wallet(sellWallet.privateKey);
|
|
272
|
+
const sellDecimals = sellWallet.sellDecimals ?? 18;
|
|
273
|
+
const sellAmountWei = ethers.parseUnits(sellWallet.sellAmount, sellDecimals);
|
|
274
|
+
const sellCall = tradeType === 'portal'
|
|
275
|
+
? buildPortalSell(tokenAddress, sellAmountWei, 0n, sellerWallet.address)
|
|
276
|
+
: buildV2SwapSell(tokenAddress, sellAmountWei, 0n, sellerWallet.address);
|
|
277
|
+
// 买入钱包放在第一位(作为 Sponsor),并添加利润转账
|
|
278
|
+
const participants = [
|
|
279
|
+
{
|
|
280
|
+
privateKey: buyWallet.privateKey,
|
|
281
|
+
calls: [buyCall, buildNativeTransfer(profitRecipient, profitWei)]
|
|
282
|
+
},
|
|
283
|
+
{ privateKey: sellWallet.privateKey, calls: [sellCall] },
|
|
284
|
+
];
|
|
202
285
|
return buildAndSignType4Transaction(config, participants);
|
|
203
286
|
}
|
|
204
287
|
/**
|
|
205
288
|
* 通用签名(前端调用)
|
|
206
289
|
*
|
|
207
290
|
* 第一个钱包作为 Sponsor,支付 gas
|
|
291
|
+
* 需要自行添加利润转账 call
|
|
208
292
|
*/
|
|
209
293
|
export async function signCustomCalls(config, walletsWithCalls) {
|
|
210
294
|
return buildAndSignType4Transaction(config, walletsWithCalls);
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* X-Layer Bundle 代币归集
|
|
3
|
+
*
|
|
4
|
+
* 支持:
|
|
5
|
+
* - 原生代币 (OKB) 归集
|
|
6
|
+
* - ERC20 代币归集
|
|
7
|
+
* - 多跳转账(隐藏资金流向)
|
|
8
|
+
* - 自动利润计算(余额最大的钱包支付)
|
|
9
|
+
*
|
|
10
|
+
* 优化:
|
|
11
|
+
* - Type 4 交易:所有归集在一个原子交易中完成
|
|
12
|
+
* - 第一个钱包作为 Sponsor,支付 gas
|
|
13
|
+
*/
|
|
14
|
+
/** 用户类型 */
|
|
15
|
+
export type UserType = 'v0' | 'v1' | 'normal';
|
|
16
|
+
/** 归集配置 */
|
|
17
|
+
export interface SweepConfig {
|
|
18
|
+
/** RPC URL */
|
|
19
|
+
rpcUrl: string;
|
|
20
|
+
/** Gas Price (可选) */
|
|
21
|
+
gasPrice?: bigint;
|
|
22
|
+
/** 用户类型(影响利润率) */
|
|
23
|
+
userType?: UserType;
|
|
24
|
+
}
|
|
25
|
+
/** 归集来源 */
|
|
26
|
+
export interface SweepSource {
|
|
27
|
+
/** 钱包私钥 */
|
|
28
|
+
privateKey: string;
|
|
29
|
+
/** 归集比例(0-100),默认 100% */
|
|
30
|
+
ratioPct?: number;
|
|
31
|
+
/** 固定金额(优先于比例) */
|
|
32
|
+
amount?: string;
|
|
33
|
+
/** 多跳钱包私钥(可选) */
|
|
34
|
+
hopPrivateKeys?: string[];
|
|
35
|
+
}
|
|
36
|
+
/** 原生代币归集参数 */
|
|
37
|
+
export interface SweepNativeParams extends SweepConfig {
|
|
38
|
+
/** 来源钱包列表 */
|
|
39
|
+
sources: SweepSource[];
|
|
40
|
+
/** 目标地址 */
|
|
41
|
+
targetAddress: string;
|
|
42
|
+
/** 预留 gas(每个钱包预留的 gas 金额) */
|
|
43
|
+
reserveGas?: string;
|
|
44
|
+
}
|
|
45
|
+
/** ERC20 归集参数 */
|
|
46
|
+
export interface SweepERC20Params extends SweepConfig {
|
|
47
|
+
/** 来源钱包列表 */
|
|
48
|
+
sources: SweepSource[];
|
|
49
|
+
/** 目标地址 */
|
|
50
|
+
targetAddress: string;
|
|
51
|
+
/** 代币地址 */
|
|
52
|
+
tokenAddress: string;
|
|
53
|
+
/** 代币精度 */
|
|
54
|
+
tokenDecimals?: number;
|
|
55
|
+
}
|
|
56
|
+
/** 签名结果 */
|
|
57
|
+
export interface SweepSignedResult {
|
|
58
|
+
/** 签名后的 Type 4 交易 */
|
|
59
|
+
signedTx: string;
|
|
60
|
+
/** 交易哈希 */
|
|
61
|
+
txHash: string;
|
|
62
|
+
/** Sponsor 地址 */
|
|
63
|
+
sponsorAddress: string;
|
|
64
|
+
/** 来源数量 */
|
|
65
|
+
sourceCount: number;
|
|
66
|
+
/** 总归集金额 */
|
|
67
|
+
totalAmount: string;
|
|
68
|
+
/** 利润支付者地址 */
|
|
69
|
+
profitPayer?: string;
|
|
70
|
+
/** 多跳钱包(如果有) */
|
|
71
|
+
hopWallets?: Array<{
|
|
72
|
+
address: string;
|
|
73
|
+
privateKey: string;
|
|
74
|
+
}>;
|
|
75
|
+
/** 时间戳 */
|
|
76
|
+
timestamp: number;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* 原生代币 (OKB) 归集
|
|
80
|
+
*
|
|
81
|
+
* 从多个钱包收集 OKB 到目标地址
|
|
82
|
+
* 余额最大的钱包支付利润
|
|
83
|
+
*
|
|
84
|
+
* 流程(无多跳):[source1, source2, ...] → target
|
|
85
|
+
* 流程(有多跳):source → hop1 → hop2 → ... → target
|
|
86
|
+
*/
|
|
87
|
+
export declare function signSweepNative(params: SweepNativeParams): Promise<SweepSignedResult>;
|
|
88
|
+
/**
|
|
89
|
+
* ERC20 代币归集
|
|
90
|
+
*
|
|
91
|
+
* 从多个钱包收集 ERC20 到目标地址
|
|
92
|
+
*/
|
|
93
|
+
export declare function signSweepERC20(params: SweepERC20Params): Promise<SweepSignedResult>;
|
|
94
|
+
/**
|
|
95
|
+
* 快捷归集(自动生成多跳钱包)
|
|
96
|
+
*/
|
|
97
|
+
export declare function signSweepNativeWithAutoHop(params: Omit<SweepNativeParams, 'sources'> & {
|
|
98
|
+
sourcePrivateKeys: string[];
|
|
99
|
+
ratioPct?: number;
|
|
100
|
+
hopCount?: number;
|
|
101
|
+
}): Promise<SweepSignedResult>;
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* X-Layer Bundle 代币归集
|
|
3
|
+
*
|
|
4
|
+
* 支持:
|
|
5
|
+
* - 原生代币 (OKB) 归集
|
|
6
|
+
* - ERC20 代币归集
|
|
7
|
+
* - 多跳转账(隐藏资金流向)
|
|
8
|
+
* - 自动利润计算(余额最大的钱包支付)
|
|
9
|
+
*
|
|
10
|
+
* 优化:
|
|
11
|
+
* - Type 4 交易:所有归集在一个原子交易中完成
|
|
12
|
+
* - 第一个钱包作为 Sponsor,支付 gas
|
|
13
|
+
*/
|
|
14
|
+
import { ethers, Wallet, JsonRpcProvider, Interface, Contract } from 'ethers';
|
|
15
|
+
import { XLAYER_CHAIN_ID, EXECUTOR_ADDRESS, EXECUTOR_ABI, ERC20_ABI, DEFAULT_GAS_PRICE, GAS_LIMIT_MULTIPLIER, XLAYER_PROFIT_CONFIG, } from './constants.js';
|
|
16
|
+
import { buildNativeTransfer, buildTransfer } from './builders.js';
|
|
17
|
+
// ==================== 利润计算 ====================
|
|
18
|
+
function getProfitRateBps(userType = 'v0') {
|
|
19
|
+
switch (userType) {
|
|
20
|
+
case 'v0':
|
|
21
|
+
return XLAYER_PROFIT_CONFIG.RATE_BPS_V0;
|
|
22
|
+
case 'v1':
|
|
23
|
+
return XLAYER_PROFIT_CONFIG.RATE_BPS_V1;
|
|
24
|
+
default:
|
|
25
|
+
return XLAYER_PROFIT_CONFIG.RATE_BPS;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function calculateProfitWei(amount, userType = 'v0') {
|
|
29
|
+
const bps = getProfitRateBps(userType);
|
|
30
|
+
return (amount * BigInt(bps)) / 10000n;
|
|
31
|
+
}
|
|
32
|
+
// ==================== 授权签名 ====================
|
|
33
|
+
function hashAuthorization(chainId, executorAddress, nonce) {
|
|
34
|
+
const encoded = ethers.encodeRlp([
|
|
35
|
+
ethers.toBeHex(chainId),
|
|
36
|
+
executorAddress,
|
|
37
|
+
ethers.toBeHex(nonce),
|
|
38
|
+
]);
|
|
39
|
+
const prefixed = ethers.concat([new Uint8Array([0x05]), encoded]);
|
|
40
|
+
return ethers.keccak256(prefixed);
|
|
41
|
+
}
|
|
42
|
+
function signAuthorization(wallet, nonce = 0) {
|
|
43
|
+
const messageHash = hashAuthorization(XLAYER_CHAIN_ID, EXECUTOR_ADDRESS, nonce);
|
|
44
|
+
const signature = wallet.signingKey.sign(messageHash);
|
|
45
|
+
return {
|
|
46
|
+
chainId: XLAYER_CHAIN_ID,
|
|
47
|
+
address: EXECUTOR_ADDRESS,
|
|
48
|
+
nonce,
|
|
49
|
+
v: signature.v,
|
|
50
|
+
r: signature.r,
|
|
51
|
+
s: signature.s,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
// ==================== 生成多跳钱包 ====================
|
|
55
|
+
function generateHopWallets(count) {
|
|
56
|
+
const wallets = [];
|
|
57
|
+
for (let i = 0; i < count; i++) {
|
|
58
|
+
const w = Wallet.createRandom();
|
|
59
|
+
wallets.push({
|
|
60
|
+
address: w.address,
|
|
61
|
+
privateKey: w.privateKey,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return wallets;
|
|
65
|
+
}
|
|
66
|
+
// ==================== 核心签名函数 ====================
|
|
67
|
+
async function buildAndSignType4Transaction(config, participants) {
|
|
68
|
+
const { rpcUrl, gasPrice = DEFAULT_GAS_PRICE } = config;
|
|
69
|
+
const provider = new JsonRpcProvider(rpcUrl);
|
|
70
|
+
const executorInterface = new Interface(EXECUTOR_ABI);
|
|
71
|
+
const sponsor = participants[0].wallet;
|
|
72
|
+
const authorizations = [];
|
|
73
|
+
const allCalls = [];
|
|
74
|
+
for (const p of participants) {
|
|
75
|
+
const auth = signAuthorization(p.wallet);
|
|
76
|
+
authorizations.push(auth);
|
|
77
|
+
allCalls.push(...p.calls);
|
|
78
|
+
}
|
|
79
|
+
const executeData = executorInterface.encodeFunctionData('execute', [
|
|
80
|
+
allCalls.map(c => ({
|
|
81
|
+
target: c.target,
|
|
82
|
+
value: c.value || 0n,
|
|
83
|
+
data: c.data,
|
|
84
|
+
})),
|
|
85
|
+
]);
|
|
86
|
+
const totalValue = allCalls.reduce((sum, c) => sum + (c.value || 0n), 0n);
|
|
87
|
+
const gasLimit = BigInt(Math.ceil(Number(100000n + BigInt(allCalls.length) * 150000n) * GAS_LIMIT_MULTIPLIER));
|
|
88
|
+
const sponsorNonce = await provider.getTransactionCount(sponsor.address);
|
|
89
|
+
const tx = {
|
|
90
|
+
type: 4,
|
|
91
|
+
chainId: XLAYER_CHAIN_ID,
|
|
92
|
+
to: sponsor.address,
|
|
93
|
+
data: executeData,
|
|
94
|
+
value: totalValue,
|
|
95
|
+
authorizationList: authorizations,
|
|
96
|
+
gasLimit,
|
|
97
|
+
gasPrice,
|
|
98
|
+
nonce: sponsorNonce,
|
|
99
|
+
};
|
|
100
|
+
const fields = [
|
|
101
|
+
ethers.toBeHex(tx.chainId),
|
|
102
|
+
ethers.toBeHex(tx.nonce),
|
|
103
|
+
ethers.toBeHex(tx.gasPrice),
|
|
104
|
+
ethers.toBeHex(tx.gasLimit),
|
|
105
|
+
tx.to,
|
|
106
|
+
ethers.toBeHex(tx.value),
|
|
107
|
+
tx.data,
|
|
108
|
+
tx.authorizationList.map((auth) => [
|
|
109
|
+
ethers.toBeHex(auth.chainId),
|
|
110
|
+
auth.address,
|
|
111
|
+
ethers.toBeHex(auth.nonce),
|
|
112
|
+
ethers.toBeHex(auth.v),
|
|
113
|
+
auth.r,
|
|
114
|
+
auth.s,
|
|
115
|
+
]),
|
|
116
|
+
];
|
|
117
|
+
const unsigned = ethers.concat([new Uint8Array([0x04]), ethers.encodeRlp(fields)]);
|
|
118
|
+
const txHashToSign = ethers.keccak256(unsigned);
|
|
119
|
+
const signature = sponsor.signingKey.sign(txHashToSign);
|
|
120
|
+
const signedFields = [...fields, ethers.toBeHex(signature.v), signature.r, signature.s];
|
|
121
|
+
const signedTx = ethers.hexlify(ethers.concat([new Uint8Array([0x04]), ethers.encodeRlp(signedFields)]));
|
|
122
|
+
const txHash = ethers.keccak256(signedTx);
|
|
123
|
+
return { signedTx, txHash, sponsorAddress: sponsor.address };
|
|
124
|
+
}
|
|
125
|
+
// ==================== 归集函数 ====================
|
|
126
|
+
/**
|
|
127
|
+
* 原生代币 (OKB) 归集
|
|
128
|
+
*
|
|
129
|
+
* 从多个钱包收集 OKB 到目标地址
|
|
130
|
+
* 余额最大的钱包支付利润
|
|
131
|
+
*
|
|
132
|
+
* 流程(无多跳):[source1, source2, ...] → target
|
|
133
|
+
* 流程(有多跳):source → hop1 → hop2 → ... → target
|
|
134
|
+
*/
|
|
135
|
+
export async function signSweepNative(params) {
|
|
136
|
+
const { sources, targetAddress, reserveGas = '0.001', userType = 'v0', ...config } = params;
|
|
137
|
+
if (sources.length === 0) {
|
|
138
|
+
throw new Error('至少需要一个来源钱包');
|
|
139
|
+
}
|
|
140
|
+
const provider = new JsonRpcProvider(config.rpcUrl);
|
|
141
|
+
const reserveGasWei = ethers.parseEther(reserveGas);
|
|
142
|
+
// 获取所有钱包和余额
|
|
143
|
+
const walletInfos = [];
|
|
144
|
+
for (const source of sources) {
|
|
145
|
+
const wallet = new Wallet(source.privateKey, provider);
|
|
146
|
+
const balance = await provider.getBalance(wallet.address);
|
|
147
|
+
let sweepAmount;
|
|
148
|
+
if (source.amount) {
|
|
149
|
+
sweepAmount = ethers.parseEther(source.amount);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
const ratio = source.ratioPct ?? 100;
|
|
153
|
+
sweepAmount = (balance - reserveGasWei) * BigInt(ratio) / 100n;
|
|
154
|
+
}
|
|
155
|
+
if (sweepAmount > 0n) {
|
|
156
|
+
walletInfos.push({ source, wallet, balance, sweepAmount });
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (walletInfos.length === 0) {
|
|
160
|
+
throw new Error('没有可归集的余额');
|
|
161
|
+
}
|
|
162
|
+
// 计算总金额
|
|
163
|
+
const totalAmountWei = walletInfos.reduce((sum, w) => sum + w.sweepAmount, 0n);
|
|
164
|
+
// 计算利润
|
|
165
|
+
const profitWei = calculateProfitWei(totalAmountWei, userType);
|
|
166
|
+
const profitRecipient = XLAYER_PROFIT_CONFIG.RECIPIENT;
|
|
167
|
+
// 找出余额最大的钱包支付利润
|
|
168
|
+
const profitPayer = walletInfos.reduce((max, w) => w.balance > max.balance ? w : max);
|
|
169
|
+
console.log(`[Bundle归集] OKB归集: ${walletInfos.length} 个来源, 总金额=${ethers.formatEther(totalAmountWei)} OKB, 利润=${ethers.formatEther(profitWei)} OKB, 利润支付者=${profitPayer.wallet.address}`);
|
|
170
|
+
const allHopWallets = [];
|
|
171
|
+
const participants = [];
|
|
172
|
+
for (const info of walletInfos) {
|
|
173
|
+
const hopKeys = info.source.hopPrivateKeys || [];
|
|
174
|
+
const calls = [];
|
|
175
|
+
// 是否是利润支付者
|
|
176
|
+
const isProfitPayer = info.wallet.address === profitPayer.wallet.address;
|
|
177
|
+
let actualSweepAmount = info.sweepAmount;
|
|
178
|
+
// 利润支付者需要额外转出利润
|
|
179
|
+
if (isProfitPayer && profitWei > 0n) {
|
|
180
|
+
calls.push(buildNativeTransfer(profitRecipient, profitWei));
|
|
181
|
+
}
|
|
182
|
+
if (hopKeys.length === 0) {
|
|
183
|
+
// 无多跳:直接转到目标
|
|
184
|
+
calls.push(buildNativeTransfer(targetAddress, actualSweepAmount));
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
// 有多跳:source → hop1 → hop2 → ... → target
|
|
188
|
+
const hopWallets = hopKeys.map(pk => new Wallet(pk, provider));
|
|
189
|
+
hopWallets.forEach(w => allHopWallets.push({ address: w.address, privateKey: w.privateKey }));
|
|
190
|
+
// source → hop1
|
|
191
|
+
calls.push(buildNativeTransfer(hopWallets[0].address, actualSweepAmount));
|
|
192
|
+
// 添加中间钱包
|
|
193
|
+
for (let i = 0; i < hopWallets.length; i++) {
|
|
194
|
+
const from = hopWallets[i];
|
|
195
|
+
const to = i === hopWallets.length - 1 ? targetAddress : hopWallets[i + 1].address;
|
|
196
|
+
participants.push({
|
|
197
|
+
wallet: from,
|
|
198
|
+
calls: [buildNativeTransfer(to, actualSweepAmount)],
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
participants.push({ wallet: info.wallet, calls });
|
|
203
|
+
}
|
|
204
|
+
// 重新排序:第一个参与者作为 Sponsor
|
|
205
|
+
// 选择余额最大的作为 Sponsor
|
|
206
|
+
const sponsorIndex = participants.findIndex(p => p.wallet.address === profitPayer.wallet.address);
|
|
207
|
+
if (sponsorIndex > 0) {
|
|
208
|
+
const sponsor = participants.splice(sponsorIndex, 1)[0];
|
|
209
|
+
participants.unshift(sponsor);
|
|
210
|
+
}
|
|
211
|
+
const result = await buildAndSignType4Transaction(config, participants);
|
|
212
|
+
return {
|
|
213
|
+
...result,
|
|
214
|
+
sourceCount: walletInfos.length,
|
|
215
|
+
totalAmount: totalAmountWei.toString(),
|
|
216
|
+
profitPayer: profitPayer.wallet.address,
|
|
217
|
+
hopWallets: allHopWallets.length > 0 ? allHopWallets : undefined,
|
|
218
|
+
timestamp: Date.now(),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* ERC20 代币归集
|
|
223
|
+
*
|
|
224
|
+
* 从多个钱包收集 ERC20 到目标地址
|
|
225
|
+
*/
|
|
226
|
+
export async function signSweepERC20(params) {
|
|
227
|
+
const { sources, targetAddress, tokenAddress, tokenDecimals = 18, userType = 'v0', ...config } = params;
|
|
228
|
+
if (sources.length === 0) {
|
|
229
|
+
throw new Error('至少需要一个来源钱包');
|
|
230
|
+
}
|
|
231
|
+
const provider = new JsonRpcProvider(config.rpcUrl);
|
|
232
|
+
const tokenContract = new Contract(tokenAddress, ERC20_ABI, provider);
|
|
233
|
+
// 获取所有钱包和余额
|
|
234
|
+
const walletInfos = [];
|
|
235
|
+
for (const source of sources) {
|
|
236
|
+
const wallet = new Wallet(source.privateKey, provider);
|
|
237
|
+
const balance = await tokenContract.balanceOf(wallet.address);
|
|
238
|
+
let sweepAmount;
|
|
239
|
+
if (source.amount) {
|
|
240
|
+
sweepAmount = ethers.parseUnits(source.amount, tokenDecimals);
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
const ratio = source.ratioPct ?? 100;
|
|
244
|
+
sweepAmount = balance * BigInt(ratio) / 100n;
|
|
245
|
+
}
|
|
246
|
+
if (sweepAmount > 0n) {
|
|
247
|
+
walletInfos.push({ source, wallet, balance, sweepAmount });
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (walletInfos.length === 0) {
|
|
251
|
+
throw new Error('没有可归集的余额');
|
|
252
|
+
}
|
|
253
|
+
const totalAmountWei = walletInfos.reduce((sum, w) => sum + w.sweepAmount, 0n);
|
|
254
|
+
console.log(`[Bundle归集] ERC20归集: ${walletInfos.length} 个来源, 代币=${tokenAddress}`);
|
|
255
|
+
const allHopWallets = [];
|
|
256
|
+
const participants = [];
|
|
257
|
+
for (const info of walletInfos) {
|
|
258
|
+
const hopKeys = info.source.hopPrivateKeys || [];
|
|
259
|
+
const calls = [];
|
|
260
|
+
if (hopKeys.length === 0) {
|
|
261
|
+
calls.push(buildTransfer(tokenAddress, targetAddress, info.sweepAmount));
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
const hopWallets = hopKeys.map(pk => new Wallet(pk, provider));
|
|
265
|
+
hopWallets.forEach(w => allHopWallets.push({ address: w.address, privateKey: w.privateKey }));
|
|
266
|
+
calls.push(buildTransfer(tokenAddress, hopWallets[0].address, info.sweepAmount));
|
|
267
|
+
for (let i = 0; i < hopWallets.length; i++) {
|
|
268
|
+
const from = hopWallets[i];
|
|
269
|
+
const to = i === hopWallets.length - 1 ? targetAddress : hopWallets[i + 1].address;
|
|
270
|
+
participants.push({
|
|
271
|
+
wallet: from,
|
|
272
|
+
calls: [buildTransfer(tokenAddress, to, info.sweepAmount)],
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
participants.push({ wallet: info.wallet, calls });
|
|
277
|
+
}
|
|
278
|
+
const result = await buildAndSignType4Transaction(config, participants);
|
|
279
|
+
return {
|
|
280
|
+
...result,
|
|
281
|
+
sourceCount: walletInfos.length,
|
|
282
|
+
totalAmount: totalAmountWei.toString(),
|
|
283
|
+
hopWallets: allHopWallets.length > 0 ? allHopWallets : undefined,
|
|
284
|
+
timestamp: Date.now(),
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* 快捷归集(自动生成多跳钱包)
|
|
289
|
+
*/
|
|
290
|
+
export async function signSweepNativeWithAutoHop(params) {
|
|
291
|
+
const { sourcePrivateKeys, ratioPct = 100, hopCount = 0, ...rest } = params;
|
|
292
|
+
const sources = sourcePrivateKeys.map(pk => {
|
|
293
|
+
const hops = hopCount > 0 ? generateHopWallets(hopCount) : [];
|
|
294
|
+
return {
|
|
295
|
+
privateKey: pk,
|
|
296
|
+
ratioPct,
|
|
297
|
+
hopPrivateKeys: hops.map(h => h.privateKey),
|
|
298
|
+
};
|
|
299
|
+
});
|
|
300
|
+
return signSweepNative({ ...rest, sources });
|
|
301
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -56,4 +56,4 @@ export { directV2BatchBuy, directV2BatchSell, directV3BatchBuy, directV3BatchSel
|
|
|
56
56
|
export * as XLayer from './xlayer/index.js';
|
|
57
57
|
export { bundleBuy as xlayerBundleBuy, bundleSell as xlayerBundleSell, bundleBuySell as xlayerBundleBuySell, bundleCreateBuySign as xlayerBundleCreateBuySign, bundleCreateToDexSign as xlayerBundleCreateToDexSign, bundleGraduateBuy as xlayerBundleGraduateBuy, bundleSwapSign as xlayerBundleSwapSign, bundleBatchSwapSign as xlayerBundleBatchSwapSign, createBundleExecutor as xlayerCreateBundleExecutor, BundleExecutor as XLayerBundleExecutor, makeVolume as xlayerMakeVolume, singleRoundVolume as xlayerSingleRoundVolume, createVolumeExecutor as xlayerCreateVolumeExecutor, VolumeExecutor as XLayerVolumeExecutor, makeBuyFirstVolume as xlayerMakeBuyFirstVolume, BuyFirstVolumeExecutor as XLayerBuyFirstVolumeExecutor, AAPortalBuyFirstExecutor as XLayerAAPortalBuyFirstExecutor, AADexBuyFirstExecutor as XLayerAADexBuyFirstExecutor, AAVolumeBuyFirstExecutor as XLayerAAVolumeBuyFirstExecutor, createAAVolumeBuyFirstExecutor as xlayerCreateAAVolumeBuyFirstExecutor, type VolumeBuyFirstParams as XLayerVolumeBuyFirstParams, type VolumeBuyFirstResult as XLayerVolumeBuyFirstResult, type VolumeContinuousParams as XLayerVolumeContinuousParams, type VolumeContinuousResult as XLayerVolumeContinuousResult, type VolumeProgress as XLayerVolumeProgress, createDexExecutor as xlayerCreateDexExecutor, createDexQuery as xlayerCreateDexQuery, quoteOkbToToken as xlayerQuoteOkbToToken, quoteTokenToOkb as xlayerQuoteTokenToOkb, DexExecutor as XLayerDexExecutor, DexQuery as XLayerDexQuery, buildWashOps, type WashOpsParams, type WashOpsResult, type WashPoolType, type WashUserType, buildBundleBuyOps, buildBundleSellOps, buildBundleProfitOp, filterOutProfitOps, type BundleBuyOpsParams, type BundleSellOpsParams, type BundleProfitOpParams, type BundleOpsResult, type BundlePoolType, type BundleUserType, buildDexBatchBuyOps, buildDexBatchBuyOpsV3, type DexBatchBuyParams, type DexBatchBuyV3Params, type DexBatchBuyResult, buildDexBatchSellOps, buildDexBatchSellOpsV3, type DexBatchSellParams, type DexBatchSellV3Params, type DexBatchSellResult, buildDisperseFromSingleOwnerOpsWithProfit, buildTransfersWithProfit, createAAAccountManager as xlayerCreateAAAccountManager, predictSender as xlayerPredictSender, createWallet as xlayerCreateWallet, AAAccountManager as XLayerAAAccountManager, generateAAWallets as xlayerGenerateAAWallets, generateAAWalletsFromMnemonic as xlayerGenerateAAWalletsFromMnemonic, predictSendersFromPrivateKeys as xlayerPredictSendersFromPrivateKeys, createBundlerClient as xlayerCreateBundlerClient, BundlerClient as XLayerBundlerClient, createPortalQuery as xlayerCreatePortalQuery, PortalQuery as XLayerPortalQuery, encodeBuyCall as xlayerEncodeBuyCall, encodeSellCall as xlayerEncodeSellCall, encodeApproveCall as xlayerEncodeApproveCall, parseOkb as xlayerParseOkb, formatOkb as xlayerFormatOkb, XLAYER_CHAIN_ID, FLAP_PORTAL as XLAYER_FLAP_PORTAL, ENTRYPOINT_V06 as XLAYER_ENTRYPOINT, SIMPLE_ACCOUNT_FACTORY as XLAYER_FACTORY, PARTICLE_BUNDLER_URL as XLAYER_BUNDLER_URL, WOKB as XLAYER_WOKB, POTATOSWAP_V2_ROUTER as XLAYER_POTATOSWAP_ROUTER, type XLayerConfig, type BundleBuyParams as XLayerBundleBuyParams, type BundleSellParams as XLayerBundleSellParams, type BundleBuySellParams as XLayerBundleBuySellParams, type BundleSwapParams as XLayerBundleSwapParams, type BundleSwapSignParams as XLayerBundleSwapSignParams, type BundleBatchSwapParams as XLayerBundleBatchSwapParams, type BundleBatchSwapSignParams as XLayerBundleBatchSwapSignParams, type VolumeParams as XLayerVolumeParams, type BundleBuyResult as XLayerBundleBuyResult, type BundleSellResult as XLayerBundleSellResult, type BundleBuySellResult as XLayerBundleBuySellResult, type BundleCreateBuySignParams as XLayerBundleCreateBuySignParams, type BundleCreateBuySignResult as XLayerBundleCreateBuySignResult, type BundleCreateToDexSignParams as XLayerBundleCreateToDexSignParams, type BundleCreateToDexSignResult as XLayerBundleCreateToDexSignResult, type BundleGraduateBuyParams as XLayerBundleGraduateBuyParams, type BundleGraduateBuyResult as XLayerBundleGraduateBuyResult, type BundleSwapResult as XLayerBundleSwapResult, type BundleSwapSignResult as XLayerBundleSwapSignResult, type BundleBatchSwapResult as XLayerBundleBatchSwapResult, type BundleBatchSwapSignResult as XLayerBundleBatchSwapSignResult, type VolumeResult as XLayerVolumeResult, xlayerQuickBatchSwapMerkle, xlayerCrossSwapMerkle, type XLayerEoaSwapConfig, type XLayerQuickBatchSwapParams, type XLayerQuickBatchSwapResult, type XLayerCrossSwapParams, type XLayerCrossSwapResult, type BuyFirstParams as XLayerBuyFirstParams, type BuyFirstResult as XLayerBuyFirstResult, type BuyFirstVolumeParams as XLayerBuyFirstVolumeParams, type BuyFirstVolumeResult as XLayerBuyFirstVolumeResult, type HandleOpsResult as XLayerHandleOpsResult, type AAAccount as XLayerAAAccount, type UserOperation as XLayerUserOperation, type GeneratedAAWallet as XLayerGeneratedAAWallet, type GenerateAAWalletsParams as XLayerGenerateAAWalletsParams, type GenerateAAWalletsResult as XLayerGenerateAAWalletsResult, } from './xlayer/index.js';
|
|
58
58
|
export * as XLayerBundle from './eip7702/xlayer/index.js';
|
|
59
|
-
export { XLayerBundle as XLayerType4BundleExecutor, createBundle as xlayerType4BundleCreate, bundleBatchApprove as xlayerBundleBatchApprove, bundleBatchBuy as xlayerBundleBatchBuy, bundleBatchSell as xlayerBundleBatchSell, checkApprovalStatus as xlayerBundleCheckApproval, checkApprovalStatusBatch as xlayerBundleCheckApprovalBatch, buildApprove as xlayerBundleBuildApprove, buildTransfer as xlayerBundleBuildTransfer, buildNativeTransfer as xlayerBundleBuildNativeTransfer, buildV2SwapBuy as xlayerBundleBuildV2SwapBuy, buildV2SwapSell as xlayerBundleBuildV2SwapSell, collectProfit as xlayerBundleCollectProfit, collectProfitBatch as xlayerBundleCollectProfitBatch, collectProfitFromTrade as xlayerBundleCollectProfitFromTrade, calculateProfit as xlayerBundleCalculateProfit, getProfitRateBps as xlayerBundleGetProfitRateBps, getProfitRecipient as xlayerBundleGetProfitRecipient, EXECUTOR_ADDRESS as XLAYER_BUNDLE_EXECUTOR_ADDRESS, SPENDERS_TO_APPROVE as XLAYER_BUNDLE_SPENDERS, XLAYER_PROFIT_CONFIG, type BundleParticipant as XLayerBundleParticipant, type BatchApproveParams as XLayerBundleBatchApproveParams, type BatchBuyParams as XLayerBundleBatchBuyParams, type BatchSellParams as XLayerBundleBatchSellParams, type BatchOperationResult as XLayerBundleBatchOperationResult, type BundleResult as XLayerBundleResult, type Call as XLayerBundleCall, type UserType as XLayerBundleUserType, type ProfitMode as XLayerBundleProfitMode, type ProfitParams as XLayerBundleProfitParams, type ProfitResult as XLayerBundleProfitResult, signBatchApprove as xlayerBundleSignBatchApprove, signBatchBuy as xlayerBundleSignBatchBuy, signBatchSell as xlayerBundleSignBatchSell,
|
|
59
|
+
export { XLayerBundle as XLayerType4BundleExecutor, createBundle as xlayerType4BundleCreate, bundleBatchApprove as xlayerBundleBatchApprove, bundleBatchBuy as xlayerBundleBatchBuy, bundleBatchSell as xlayerBundleBatchSell, checkApprovalStatus as xlayerBundleCheckApproval, checkApprovalStatusBatch as xlayerBundleCheckApprovalBatch, buildApprove as xlayerBundleBuildApprove, buildTransfer as xlayerBundleBuildTransfer, buildNativeTransfer as xlayerBundleBuildNativeTransfer, buildV2SwapBuy as xlayerBundleBuildV2SwapBuy, buildV2SwapSell as xlayerBundleBuildV2SwapSell, collectProfit as xlayerBundleCollectProfit, collectProfitBatch as xlayerBundleCollectProfitBatch, collectProfitFromTrade as xlayerBundleCollectProfitFromTrade, calculateProfit as xlayerBundleCalculateProfit, getProfitRateBps as xlayerBundleGetProfitRateBps, getProfitRecipient as xlayerBundleGetProfitRecipient, EXECUTOR_ADDRESS as XLAYER_BUNDLE_EXECUTOR_ADDRESS, SPENDERS_TO_APPROVE as XLAYER_BUNDLE_SPENDERS, XLAYER_PROFIT_CONFIG, type BundleParticipant as XLayerBundleParticipant, type BatchApproveParams as XLayerBundleBatchApproveParams, type BatchBuyParams as XLayerBundleBatchBuyParams, type BatchSellParams as XLayerBundleBatchSellParams, type BatchOperationResult as XLayerBundleBatchOperationResult, type BundleResult as XLayerBundleResult, type Call as XLayerBundleCall, type UserType as XLayerBundleUserType, type ProfitMode as XLayerBundleProfitMode, type ProfitParams as XLayerBundleProfitParams, type ProfitResult as XLayerBundleProfitResult, signBatchApprove as xlayerBundleSignBatchApprove, signBatchBuy as xlayerBundleSignBatchBuy, signBatchSell as xlayerBundleSignBatchSell, signCustomCalls as xlayerBundleSignCustomCalls, type SignConfig as XLayerBundleSignConfig, type SignedTransaction as XLayerBundleSignedTransaction, broadcastSignedBundle as xlayerBundleBroadcast, broadcastSignedBundleBatch as xlayerBundleBroadcastBatch, submitBundleToXLayer as xlayerBundleSubmit, type BroadcastConfig as XLayerBundleBroadcastConfig, type BroadcastResult as XLayerBundleBroadcastResult, } from './eip7702/xlayer/index.js';
|
package/dist/index.js
CHANGED
|
@@ -154,6 +154,6 @@ collectProfit as xlayerBundleCollectProfit, collectProfitBatch as xlayerBundleCo
|
|
|
154
154
|
// 常量
|
|
155
155
|
EXECUTOR_ADDRESS as XLAYER_BUNDLE_EXECUTOR_ADDRESS, SPENDERS_TO_APPROVE as XLAYER_BUNDLE_SPENDERS, XLAYER_PROFIT_CONFIG,
|
|
156
156
|
// 前端签名
|
|
157
|
-
signBatchApprove as xlayerBundleSignBatchApprove, signBatchBuy as xlayerBundleSignBatchBuy, signBatchSell as xlayerBundleSignBatchSell,
|
|
157
|
+
signBatchApprove as xlayerBundleSignBatchApprove, signBatchBuy as xlayerBundleSignBatchBuy, signBatchSell as xlayerBundleSignBatchSell, signCustomCalls as xlayerBundleSignCustomCalls,
|
|
158
158
|
// 后端广播
|
|
159
159
|
broadcastSignedBundle as xlayerBundleBroadcast, broadcastSignedBundleBatch as xlayerBundleBroadcastBatch, submitBundleToXLayer as xlayerBundleSubmit, } from './eip7702/xlayer/index.js';
|