four-flap-meme-sdk 1.2.91 → 1.2.92
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/contracts/tm-bundle-merkle/index.d.ts +1 -1
- package/dist/contracts/tm-bundle-merkle/index.js +3 -1
- package/dist/contracts/tm-bundle-merkle/submit.d.ts +87 -0
- package/dist/contracts/tm-bundle-merkle/submit.js +187 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/package.json +1 -1
|
@@ -9,5 +9,5 @@ export { fourPrivateBuyMerkle, fourPrivateSellMerkle, fourBatchPrivateBuyMerkle,
|
|
|
9
9
|
export { disperseWithBundleMerkle, sweepWithBundleMerkle } from './utils.js';
|
|
10
10
|
export { fourPancakeProxyBatchBuyMerkle, fourPancakeProxyBatchSellMerkle, approveFourPancakeProxy, approveFourPancakeProxyBatch } from './pancake-proxy.js';
|
|
11
11
|
export { approveFourTokenManagerBatch, type ApproveFourTokenManagerBatchParams, type ApproveFourTokenManagerBatchResult } from './approve-tokenmanager.js';
|
|
12
|
-
export { submitBundleToMerkle, submitMultipleBundles, submitMultipleBundlesParallel, type MerkleSubmitConfig, type SubmitBundleResult } from './submit.js';
|
|
12
|
+
export { submitBundleToMerkle, submitMultipleBundles, submitMultipleBundlesParallel, type MerkleSubmitConfig, type SubmitBundleResult, submitDirectToRpc, submitDirectToRpcParallel, type DirectSubmitConfig, type DirectSubmitResult, type DirectTxResult } from './submit.js';
|
|
13
13
|
export { fourBundleBuyFirstMerkle, type FourBundleBuyFirstSignParams, type FourBuyFirstSignConfig, type FourBuyFirstResult } from './swap-buy-first.js';
|
|
@@ -16,6 +16,8 @@ export { fourPancakeProxyBatchBuyMerkle, fourPancakeProxyBatchSellMerkle, approv
|
|
|
16
16
|
// TokenManager 授权方法
|
|
17
17
|
export { approveFourTokenManagerBatch } from './approve-tokenmanager.js';
|
|
18
18
|
// Bundle提交方法(服务器端使用)
|
|
19
|
-
export { submitBundleToMerkle, submitMultipleBundles, submitMultipleBundlesParallel
|
|
19
|
+
export { submitBundleToMerkle, submitMultipleBundles, submitMultipleBundlesParallel,
|
|
20
|
+
// ✅ Monad 等链的逐笔广播方法
|
|
21
|
+
submitDirectToRpc, submitDirectToRpcParallel } from './submit.js';
|
|
20
22
|
// 先买后卖换手方法
|
|
21
23
|
export { fourBundleBuyFirstMerkle } from './swap-buy-first.js';
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* 独立的Bundle提交方法
|
|
3
3
|
*
|
|
4
4
|
* 用于服务器端接收前端构建的签名交易后,提交到Merkle
|
|
5
|
+
* 以及 Monad 等不支持 Bundle 的链的逐笔广播
|
|
5
6
|
*/
|
|
6
7
|
/**
|
|
7
8
|
* 精简的Merkle提交配置(只包含提交需要的字段)
|
|
@@ -86,3 +87,89 @@ export declare function submitMultipleBundles(bundles: string[][], config: Merkl
|
|
|
86
87
|
* @returns Bundle提交结果数组
|
|
87
88
|
*/
|
|
88
89
|
export declare function submitMultipleBundlesParallel(bundles: string[][], config: MerkleSubmitConfig): Promise<SubmitBundleResult[]>;
|
|
90
|
+
/**
|
|
91
|
+
* 逐笔广播配置(用于不支持 Bundle 的链,如 Monad)
|
|
92
|
+
*/
|
|
93
|
+
export interface DirectSubmitConfig {
|
|
94
|
+
/** RPC URL(必需) */
|
|
95
|
+
rpcUrl: string;
|
|
96
|
+
/** 链ID(可选,默认143=Monad) */
|
|
97
|
+
chainId?: number;
|
|
98
|
+
/** 链名称(可选,用于日志) */
|
|
99
|
+
chainName?: string;
|
|
100
|
+
/** 是否等待交易确认(可选,默认false) */
|
|
101
|
+
waitForConfirmation?: boolean;
|
|
102
|
+
/** 确认超时时间ms(可选,默认30000) */
|
|
103
|
+
confirmationTimeout?: number;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* 单笔交易结果
|
|
107
|
+
*/
|
|
108
|
+
export interface DirectTxResult {
|
|
109
|
+
/** 交易索引 */
|
|
110
|
+
index: number;
|
|
111
|
+
/** 是否成功 */
|
|
112
|
+
success: boolean;
|
|
113
|
+
/** 交易哈希(成功时返回) */
|
|
114
|
+
txHash?: string;
|
|
115
|
+
/** 错误信息(失败时返回) */
|
|
116
|
+
error?: string;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* 逐笔广播提交结果
|
|
120
|
+
*/
|
|
121
|
+
export interface DirectSubmitResult {
|
|
122
|
+
/** 提交状态:至少有一笔成功则为true */
|
|
123
|
+
code: boolean;
|
|
124
|
+
/** 交易总数 */
|
|
125
|
+
totalTransactions: number;
|
|
126
|
+
/** 成功数量 */
|
|
127
|
+
successCount: number;
|
|
128
|
+
/** 失败数量 */
|
|
129
|
+
failedCount: number;
|
|
130
|
+
/** 交易哈希列表(成功的交易) */
|
|
131
|
+
txHashes: string[];
|
|
132
|
+
/** 每笔交易的详细结果 */
|
|
133
|
+
results: DirectTxResult[];
|
|
134
|
+
/** 错误摘要(如果有失败) */
|
|
135
|
+
errorSummary?: string;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* 逐笔广播到 RPC(用于不支持 Bundle 的链,如 Monad)
|
|
139
|
+
*
|
|
140
|
+
* 这个方法接收前端构建和签名好的交易,逐笔广播到 RPC 节点
|
|
141
|
+
*
|
|
142
|
+
* @param signedTransactions 签名后的交易数组
|
|
143
|
+
* @param config 直接广播配置
|
|
144
|
+
* @returns 广播结果
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```typescript
|
|
148
|
+
* // 服务器端代码(Monad 链)
|
|
149
|
+
* import { submitDirectToRpc } from 'four-flap-meme-sdk';
|
|
150
|
+
*
|
|
151
|
+
* const result = await submitDirectToRpc(signedTransactions, {
|
|
152
|
+
* rpcUrl: 'https://rpc-mainnet.monadinfra.com',
|
|
153
|
+
* chainId: 143,
|
|
154
|
+
* chainName: 'MONAD'
|
|
155
|
+
* });
|
|
156
|
+
*
|
|
157
|
+
* if (result.code) {
|
|
158
|
+
* console.log('✅ 广播成功:', result.successCount, '/', result.totalTransactions);
|
|
159
|
+
* console.log('交易哈希:', result.txHashes);
|
|
160
|
+
* } else {
|
|
161
|
+
* console.error('❌ 全部广播失败:', result.errorSummary);
|
|
162
|
+
* }
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
export declare function submitDirectToRpc(signedTransactions: string[], config: DirectSubmitConfig): Promise<DirectSubmitResult>;
|
|
166
|
+
/**
|
|
167
|
+
* 并行逐笔广播到 RPC(速度更快,但可能有 nonce 冲突)
|
|
168
|
+
*
|
|
169
|
+
* ⚠️ 注意:仅适用于不同钱包的交易,同一钱包的多笔交易应使用顺序广播
|
|
170
|
+
*
|
|
171
|
+
* @param signedTransactions 签名后的交易数组
|
|
172
|
+
* @param config 直接广播配置
|
|
173
|
+
* @returns 广播结果
|
|
174
|
+
*/
|
|
175
|
+
export declare function submitDirectToRpcParallel(signedTransactions: string[], config: DirectSubmitConfig): Promise<DirectSubmitResult>;
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
* 独立的Bundle提交方法
|
|
3
3
|
*
|
|
4
4
|
* 用于服务器端接收前端构建的签名交易后,提交到Merkle
|
|
5
|
+
* 以及 Monad 等不支持 Bundle 的链的逐笔广播
|
|
5
6
|
*/
|
|
6
7
|
import { MerkleClient } from '../../clients/merkle.js';
|
|
8
|
+
import { ethers } from 'ethers';
|
|
7
9
|
/**
|
|
8
10
|
* 提交已签名的交易到Merkle(服务器端使用)
|
|
9
11
|
*
|
|
@@ -109,3 +111,188 @@ export async function submitMultipleBundlesParallel(bundles, config) {
|
|
|
109
111
|
const promises = bundles.map(signedTransactions => submitBundleToMerkle(signedTransactions, config));
|
|
110
112
|
return await Promise.all(promises);
|
|
111
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* 逐笔广播到 RPC(用于不支持 Bundle 的链,如 Monad)
|
|
116
|
+
*
|
|
117
|
+
* 这个方法接收前端构建和签名好的交易,逐笔广播到 RPC 节点
|
|
118
|
+
*
|
|
119
|
+
* @param signedTransactions 签名后的交易数组
|
|
120
|
+
* @param config 直接广播配置
|
|
121
|
+
* @returns 广播结果
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```typescript
|
|
125
|
+
* // 服务器端代码(Monad 链)
|
|
126
|
+
* import { submitDirectToRpc } from 'four-flap-meme-sdk';
|
|
127
|
+
*
|
|
128
|
+
* const result = await submitDirectToRpc(signedTransactions, {
|
|
129
|
+
* rpcUrl: 'https://rpc-mainnet.monadinfra.com',
|
|
130
|
+
* chainId: 143,
|
|
131
|
+
* chainName: 'MONAD'
|
|
132
|
+
* });
|
|
133
|
+
*
|
|
134
|
+
* if (result.code) {
|
|
135
|
+
* console.log('✅ 广播成功:', result.successCount, '/', result.totalTransactions);
|
|
136
|
+
* console.log('交易哈希:', result.txHashes);
|
|
137
|
+
* } else {
|
|
138
|
+
* console.error('❌ 全部广播失败:', result.errorSummary);
|
|
139
|
+
* }
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
export async function submitDirectToRpc(signedTransactions, config) {
|
|
143
|
+
const totalTransactions = signedTransactions?.length ?? 0;
|
|
144
|
+
// 验证输入
|
|
145
|
+
if (!signedTransactions || signedTransactions.length === 0) {
|
|
146
|
+
return {
|
|
147
|
+
code: false,
|
|
148
|
+
totalTransactions: 0,
|
|
149
|
+
successCount: 0,
|
|
150
|
+
failedCount: 0,
|
|
151
|
+
txHashes: [],
|
|
152
|
+
results: [],
|
|
153
|
+
errorSummary: 'signedTransactions cannot be empty'
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if (!config.rpcUrl) {
|
|
157
|
+
return {
|
|
158
|
+
code: false,
|
|
159
|
+
totalTransactions,
|
|
160
|
+
successCount: 0,
|
|
161
|
+
failedCount: totalTransactions,
|
|
162
|
+
txHashes: [],
|
|
163
|
+
results: [],
|
|
164
|
+
errorSummary: 'rpcUrl is required in config'
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
const chainId = config.chainId ?? 143;
|
|
168
|
+
const chainName = config.chainName ?? 'MONAD';
|
|
169
|
+
// 创建 Provider
|
|
170
|
+
const provider = new ethers.JsonRpcProvider(config.rpcUrl, {
|
|
171
|
+
chainId,
|
|
172
|
+
name: chainName
|
|
173
|
+
});
|
|
174
|
+
const results = [];
|
|
175
|
+
const txHashes = [];
|
|
176
|
+
const errors = [];
|
|
177
|
+
// 逐笔广播
|
|
178
|
+
for (let i = 0; i < signedTransactions.length; i++) {
|
|
179
|
+
const signedTx = signedTransactions[i];
|
|
180
|
+
try {
|
|
181
|
+
// 广播交易
|
|
182
|
+
const txResponse = await provider.broadcastTransaction(signedTx);
|
|
183
|
+
results.push({
|
|
184
|
+
index: i,
|
|
185
|
+
success: true,
|
|
186
|
+
txHash: txResponse.hash
|
|
187
|
+
});
|
|
188
|
+
txHashes.push(txResponse.hash);
|
|
189
|
+
console.log(`✅ [${chainName}] 交易 ${i + 1}/${totalTransactions} 广播成功: ${txResponse.hash}`);
|
|
190
|
+
// 如果需要等待确认
|
|
191
|
+
if (config.waitForConfirmation) {
|
|
192
|
+
try {
|
|
193
|
+
const receipt = await provider.waitForTransaction(txResponse.hash, 1, config.confirmationTimeout ?? 30000);
|
|
194
|
+
if (receipt && receipt.status === 0) {
|
|
195
|
+
console.warn(`⚠️ [${chainName}] 交易 ${txResponse.hash} 执行失败(已上链但状态为0)`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
catch (waitError) {
|
|
199
|
+
console.warn(`⚠️ [${chainName}] 等待交易确认超时: ${txResponse.hash}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
const errorMessage = error?.message || String(error);
|
|
205
|
+
results.push({
|
|
206
|
+
index: i,
|
|
207
|
+
success: false,
|
|
208
|
+
error: errorMessage
|
|
209
|
+
});
|
|
210
|
+
errors.push(`交易 ${i + 1}: ${errorMessage}`);
|
|
211
|
+
console.error(`❌ [${chainName}] 交易 ${i + 1}/${totalTransactions} 广播失败:`, errorMessage);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const successCount = txHashes.length;
|
|
215
|
+
const failedCount = totalTransactions - successCount;
|
|
216
|
+
return {
|
|
217
|
+
code: successCount > 0,
|
|
218
|
+
totalTransactions,
|
|
219
|
+
successCount,
|
|
220
|
+
failedCount,
|
|
221
|
+
txHashes,
|
|
222
|
+
results,
|
|
223
|
+
errorSummary: errors.length > 0 ? errors.join('; ') : undefined
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* 并行逐笔广播到 RPC(速度更快,但可能有 nonce 冲突)
|
|
228
|
+
*
|
|
229
|
+
* ⚠️ 注意:仅适用于不同钱包的交易,同一钱包的多笔交易应使用顺序广播
|
|
230
|
+
*
|
|
231
|
+
* @param signedTransactions 签名后的交易数组
|
|
232
|
+
* @param config 直接广播配置
|
|
233
|
+
* @returns 广播结果
|
|
234
|
+
*/
|
|
235
|
+
export async function submitDirectToRpcParallel(signedTransactions, config) {
|
|
236
|
+
const totalTransactions = signedTransactions?.length ?? 0;
|
|
237
|
+
if (!signedTransactions || signedTransactions.length === 0) {
|
|
238
|
+
return {
|
|
239
|
+
code: false,
|
|
240
|
+
totalTransactions: 0,
|
|
241
|
+
successCount: 0,
|
|
242
|
+
failedCount: 0,
|
|
243
|
+
txHashes: [],
|
|
244
|
+
results: [],
|
|
245
|
+
errorSummary: 'signedTransactions cannot be empty'
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
if (!config.rpcUrl) {
|
|
249
|
+
return {
|
|
250
|
+
code: false,
|
|
251
|
+
totalTransactions,
|
|
252
|
+
successCount: 0,
|
|
253
|
+
failedCount: totalTransactions,
|
|
254
|
+
txHashes: [],
|
|
255
|
+
results: [],
|
|
256
|
+
errorSummary: 'rpcUrl is required in config'
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
const chainId = config.chainId ?? 143;
|
|
260
|
+
const chainName = config.chainName ?? 'MONAD';
|
|
261
|
+
const provider = new ethers.JsonRpcProvider(config.rpcUrl, {
|
|
262
|
+
chainId,
|
|
263
|
+
name: chainName
|
|
264
|
+
});
|
|
265
|
+
// 并行广播
|
|
266
|
+
const broadcastPromises = signedTransactions.map(async (signedTx, i) => {
|
|
267
|
+
try {
|
|
268
|
+
const txResponse = await provider.broadcastTransaction(signedTx);
|
|
269
|
+
return {
|
|
270
|
+
index: i,
|
|
271
|
+
success: true,
|
|
272
|
+
txHash: txResponse.hash
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
return {
|
|
277
|
+
index: i,
|
|
278
|
+
success: false,
|
|
279
|
+
error: error?.message || String(error)
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
const results = await Promise.all(broadcastPromises);
|
|
284
|
+
const txHashes = results.filter(r => r.success && r.txHash).map(r => r.txHash);
|
|
285
|
+
const errors = results.filter(r => !r.success).map(r => `交易 ${r.index + 1}: ${r.error}`);
|
|
286
|
+
const successCount = txHashes.length;
|
|
287
|
+
const failedCount = totalTransactions - successCount;
|
|
288
|
+
console.log(`📤 [${chainName}] 并行广播完成: ${successCount}/${totalTransactions} 成功`);
|
|
289
|
+
return {
|
|
290
|
+
code: successCount > 0,
|
|
291
|
+
totalTransactions,
|
|
292
|
+
successCount,
|
|
293
|
+
failedCount,
|
|
294
|
+
txHashes,
|
|
295
|
+
results,
|
|
296
|
+
errorSummary: errors.length > 0 ? errors.join('; ') : undefined
|
|
297
|
+
};
|
|
298
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -42,3 +42,4 @@ export { fourBundleBuyFirstMerkle, type FourBuyFirstConfig, type FourBundleBuyFi
|
|
|
42
42
|
export { flapBundleBuyFirstMerkle, type FlapBuyFirstSignConfig, type FlapBuyFirstConfig, type FlapBundleBuyFirstSignParams, type FlapBundleBuyFirstParams, type FlapBuyFirstResult } from './flap/portal-bundle-merkle/swap-buy-first.js';
|
|
43
43
|
export { pancakeBundleBuyFirstMerkle, type PancakeBuyFirstSignConfig, type PancakeBuyFirstConfig, type PancakeBundleBuyFirstSignParams, type PancakeBundleBuyFirstParams, type PancakeBuyFirstResult } from './pancake/bundle-buy-first.js';
|
|
44
44
|
export { PROFIT_CONFIG } from './utils/constants.js';
|
|
45
|
+
export { submitDirectToRpc, submitDirectToRpcParallel, type DirectSubmitConfig, type DirectSubmitResult, type DirectTxResult } from './contracts/tm-bundle-merkle/submit.js';
|
package/dist/index.js
CHANGED
|
@@ -62,3 +62,5 @@ export { flapBundleBuyFirstMerkle } from './flap/portal-bundle-merkle/swap-buy-f
|
|
|
62
62
|
export { pancakeBundleBuyFirstMerkle } from './pancake/bundle-buy-first.js';
|
|
63
63
|
// ✅ 硬编码利润配置(统一管理)
|
|
64
64
|
export { PROFIT_CONFIG } from './utils/constants.js';
|
|
65
|
+
// ✅ Monad 等不支持 Bundle 的链:逐笔 RPC 广播方法(服务器端使用)
|
|
66
|
+
export { submitDirectToRpc, submitDirectToRpcParallel } from './contracts/tm-bundle-merkle/submit.js';
|