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.
@@ -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 } from './submit.js';
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';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.2.91",
3
+ "version": "1.2.92",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",