four-flap-meme-sdk 1.3.7 → 1.3.8

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.
@@ -70,9 +70,9 @@ export interface SendBundleOptions {
70
70
  minTimestamp?: number;
71
71
  /** 最大时间戳 */
72
72
  maxTimestamp?: number;
73
- /** 如果不指定 targetBlock,则使用当前区块 + offset(默认1) */
73
+ /** 如果不指定 targetBlock,则使用当前区块 + offset(默认3) */
74
74
  blockOffset?: number;
75
- /** 最小区块偏移量,用于确保足够的提交时间窗口(默认1) */
75
+ /** 最小区块偏移量,用于确保足够的提交时间窗口(默认3) */
76
76
  minBlockOffset?: number;
77
77
  /** 是否启用自动重试(默认false) */
78
78
  autoRetry?: boolean;
@@ -133,22 +133,32 @@ export class MerkleClient {
133
133
  if (!options.transactions || options.transactions.length === 0) {
134
134
  throw new Error('Transactions array cannot be empty');
135
135
  }
136
+ const minBlockOffset = options.minBlockOffset ?? 3; // 默认至少3个区块的窗口
136
137
  const autoRetry = options.autoRetry ?? false;
137
138
  const maxRetries = options.maxRetries ?? 2;
138
139
  let attempt = 0;
139
140
  let lastError = null;
140
141
  while (attempt <= (autoRetry ? maxRetries : 0)) {
141
142
  try {
143
+ // 实时获取当前区块(每次尝试都重新获取)
144
+ const currentBlock = await this.getBlockNumber();
145
+ // 确定目标区块
142
146
  let targetBlock;
143
- // ✅ 优化:如果已经传入 targetBlock,直接使用,不再查询区块号
144
147
  if (options.targetBlock) {
145
148
  targetBlock = options.targetBlock;
149
+ // 检查目标区块是否已经过期
150
+ if (targetBlock <= currentBlock) {
151
+ if (autoRetry && attempt < maxRetries) {
152
+ attempt++;
153
+ await new Promise(resolve => setTimeout(resolve, 300)); // 短暂延迟
154
+ continue;
155
+ }
156
+ throw new Error(`Target block ${targetBlock} has already passed (current block: ${currentBlock})`);
157
+ }
146
158
  }
147
159
  else {
148
- // 只有在没有传入 targetBlock 时才查询区块号
149
- const currentBlock = await this.getBlockNumber();
150
- const minBlockOffset = options.minBlockOffset ?? 1;
151
- const requestedOffset = options.blockOffset ?? 1;
160
+ // 动态计算:确保至少有 minBlockOffset 个区块的窗口
161
+ const requestedOffset = options.blockOffset ?? 3;
152
162
  const actualOffset = Math.max(requestedOffset, minBlockOffset);
153
163
  targetBlock = currentBlock + actualOffset;
154
164
  }
@@ -161,16 +171,22 @@ export class MerkleClient {
161
171
  minTimestamp: options.minTimestamp,
162
172
  maxTimestamp: options.maxTimestamp,
163
173
  });
164
- // ✅ 优化:并行提取所有交易哈希
165
- const txHashes = options.transactions.map(rawTx => {
174
+ // 提取交易哈希(添加异常处理)
175
+ const txHashes = [];
176
+ for (let i = 0; i < options.transactions.length; i++) {
166
177
  try {
167
- const tx = Transaction.from(rawTx);
168
- return tx.hash || '';
178
+ const tx = Transaction.from(options.transactions[i]);
179
+ if (tx.hash) {
180
+ txHashes.push(tx.hash);
181
+ }
182
+ else {
183
+ txHashes.push('');
184
+ }
169
185
  }
170
- catch {
171
- return '';
186
+ catch (error) {
187
+ txHashes.push('');
172
188
  }
173
- });
189
+ }
174
190
  return {
175
191
  bundleHash,
176
192
  txHashes,
@@ -14,9 +14,9 @@ export interface MerkleSubmitConfig {
14
14
  customRpcUrl?: string;
15
15
  /** 链ID(可选,默认56=BSC) */
16
16
  chainId?: 56 | 1;
17
- /** Bundle区块偏移量(可选,默认1,BSC约3秒后打包) */
17
+ /** Bundle区块偏移量(可选,默认3 */
18
18
  bundleBlockOffset?: number;
19
- /** 最小区块偏移量(可选,默认1) */
19
+ /** 最小区块偏移量(可选,默认3) */
20
20
  minBlockOffset?: number;
21
21
  /** 是否自动重试(可选,默认false) */
22
22
  autoRetryBundle?: boolean;
@@ -6,21 +6,6 @@
6
6
  */
7
7
  import { MerkleClient } from '../../clients/merkle.js';
8
8
  import { ethers } from 'ethers';
9
- // ✅ MerkleClient 缓存,避免重复创建 Provider
10
- const merkleClientCache = new Map();
11
- function getMerkleClient(config) {
12
- const cacheKey = `${config.apiKey}-${config.chainId ?? 56}-${config.customRpcUrl ?? ''}`;
13
- let client = merkleClientCache.get(cacheKey);
14
- if (!client) {
15
- client = new MerkleClient({
16
- apiKey: config.apiKey,
17
- chainId: config.chainId ?? 56,
18
- customRpcUrl: config.customRpcUrl
19
- });
20
- merkleClientCache.set(cacheKey, client);
21
- }
22
- return client;
23
- }
24
9
  /**
25
10
  * 提交已签名的交易到Merkle(服务器端使用)
26
11
  *
@@ -67,14 +52,17 @@ export async function submitBundleToMerkle(signedTransactions, config) {
67
52
  error: 'apiKey is required in config'
68
53
  };
69
54
  }
70
- // ✅ 优化:使用缓存的 MerkleClient,避免重复创建 Provider
71
- const merkle = getMerkleClient(config);
72
- // ✅ 获取 Merkle RPC 当前区块,目标区块 = 当前区块 + 偏移(默认 +1,最快速度)
73
- const currentBlock = await merkle.getBlockNumber();
74
- const targetBlock = currentBlock + (config.bundleBlockOffset ?? 1);
55
+ // 初始化Merkle客户端
56
+ const merkle = new MerkleClient({
57
+ apiKey: config.apiKey,
58
+ chainId: config.chainId ?? 56,
59
+ customRpcUrl: config.customRpcUrl
60
+ });
61
+ // 提交Bundle
75
62
  const bundleResult = await merkle.sendBundle({
76
63
  transactions: signedTransactions,
77
- targetBlock, // 直接指定目标区块,sendBundle 内部不再查询区块号
64
+ blockOffset: config.bundleBlockOffset ?? 3,
65
+ minBlockOffset: config.minBlockOffset ?? 3,
78
66
  autoRetry: config.autoRetryBundle ?? false,
79
67
  maxRetries: config.maxBundleRetries ?? 2
80
68
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.3.7",
3
+ "version": "1.3.8",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",