four-flap-meme-sdk 1.7.16 → 1.7.18

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.
@@ -48,7 +48,7 @@ export async function bundleApprove(params) {
48
48
  throw new Error('privateKeys 不能为空');
49
49
  }
50
50
  const provider = getCachedProvider(config?.rpcUrl);
51
- const delegateAddress = config?.delegateAddress ?? UNIFIED_DELEGATE_ADDRESS;
51
+ const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
52
52
  const mainWallet = createWallet(mainPrivateKey, provider);
53
53
  const wallets = privateKeys.map(pk => createWallet(pk, provider));
54
54
  // 检查 mainWallet 是否在 wallets 中
@@ -182,7 +182,7 @@ export async function bundleBuy(params) {
182
182
  throw new Error('privateKeys 和 buyAmounts 长度必须相同');
183
183
  }
184
184
  const provider = getCachedProvider(config?.rpcUrl);
185
- const delegateAddress = config?.delegateAddress ?? UNIFIED_DELEGATE_ADDRESS;
185
+ const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
186
186
  const actualRouter = routerAddress ?? getDefaultRouter(tradeType);
187
187
  // ========================================
188
188
  // 同步操作 - 批量创建钱包和解析金额
@@ -130,7 +130,7 @@ export async function bundleCreateBuy(params) {
130
130
  throw new Error('buyerPrivateKeys 和 buyAmounts 长度必须相同');
131
131
  }
132
132
  const provider = getCachedProvider(config?.rpcUrl);
133
- const delegateAddress = config?.delegateAddress ?? UNIFIED_DELEGATE_ADDRESS;
133
+ const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
134
134
  const delegateInterface = new Interface(UNIFIED_DELEGATE_ABI);
135
135
  // 创建钱包
136
136
  const devWallet = createWallet(devPrivateKey, provider);
@@ -280,7 +280,7 @@ export async function bundleCreateToDex(params) {
280
280
  throw new Error('dexBuyerPrivateKeys 和 dexBuyAmounts 长度必须相同');
281
281
  }
282
282
  const provider = getCachedProvider(config?.rpcUrl);
283
- const delegateAddress = config?.delegateAddress ?? UNIFIED_DELEGATE_ADDRESS;
283
+ const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
284
284
  const delegateInterface = new Interface(UNIFIED_DELEGATE_ABI);
285
285
  // 创建钱包
286
286
  const payerWallet = createWallet(payerPrivateKey, provider);
@@ -428,7 +428,7 @@ export async function bundleCreateToDex(params) {
428
428
  export async function bundleGraduateBuy(params) {
429
429
  const { tokenAddress, privateKeys, payerPrivateKey, amountMode, totalBuyAmount, minAmount, maxAmount, walletAmounts, enableDexBuy = false, extensionData = '0x', curveAddresses, dexAddresses, graduationAmount, config, } = params;
430
430
  const provider = getCachedProvider(config?.rpcUrl);
431
- const delegateAddress = config?.delegateAddress ?? UNIFIED_DELEGATE_ADDRESS;
431
+ const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
432
432
  const delegateInterface = new Interface(UNIFIED_DELEGATE_ABI);
433
433
  // 创建钱包
434
434
  const payerWallet = createWallet(payerPrivateKey, provider);
@@ -193,7 +193,7 @@ function buildSellCalls(wallets, sellAmounts, tokenAddress, tradeType, routerAdd
193
193
  export async function bundleSell(params) {
194
194
  const { mainPrivateKey, privateKeys, sellAmounts, sellPercent, tokenAddress, tokenDecimals = 18, tradeType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, config, } = params;
195
195
  const provider = getCachedProvider(config?.rpcUrl);
196
- const delegateAddress = config?.delegateAddress ?? UNIFIED_DELEGATE_ADDRESS;
196
+ const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
197
197
  const actualRouter = routerAddress ?? getDefaultRouter(tradeType);
198
198
  // ========================================
199
199
  // 同步操作 - 批量创建钱包
@@ -189,7 +189,7 @@ export async function bundleSwap(params) {
189
189
  const { sellerPrivateKey, buyerPrivateKey, tokenAddress, tokenDecimals = 18, sellAmount, hopCount = 2, // ✅ 设为 0 则不多跳,直接 seller → buyer
190
190
  tradeType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, config, } = params;
191
191
  const provider = getCachedProvider(config?.rpcUrl);
192
- const delegateAddress = config?.delegateAddress ?? UNIFIED_DELEGATE_ADDRESS;
192
+ const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
193
193
  const actualRouter = routerAddress ?? getDefaultRouter(tradeType);
194
194
  // ========================================
195
195
  // 同步操作 - 创建钱包
@@ -266,7 +266,7 @@ export async function bundleBatchSwap(params) {
266
266
  const { sellerPrivateKey, buyerPrivateKeys, tokenAddress, tokenDecimals = 18, sellAmount, hopCount = 2, // ✅ 设为 0 则不多跳
267
267
  tradeType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, config, } = params;
268
268
  const provider = getCachedProvider(config?.rpcUrl);
269
- const delegateAddress = config?.delegateAddress ?? UNIFIED_DELEGATE_ADDRESS;
269
+ const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
270
270
  const actualRouter = routerAddress ?? getDefaultRouter(tradeType);
271
271
  // ========================================
272
272
  // 同步操作 - 创建钱包
@@ -58,7 +58,7 @@ export async function disperse(params) {
58
58
  throw new Error('recipients 和 amounts 长度必须相同');
59
59
  }
60
60
  const provider = getCachedProvider(config?.rpcUrl);
61
- const delegateAddress = config?.delegateAddress ?? UNIFIED_DELEGATE_ADDRESS;
61
+ const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
62
62
  const delegateInterface = new ethers.Interface(UNIFIED_DELEGATE_ABI);
63
63
  const mainWallet = createWallet(mainPrivateKey, provider);
64
64
  const isNative = !tokenAddress;
@@ -259,7 +259,7 @@ export async function disperse(params) {
259
259
  export async function sweep(params) {
260
260
  const { targetAddress, sourcePrivateKeys, payerPrivateKey, tokenAddress, tokenDecimals = 18, hopCount = 0, reserveGas = true, percent = 100, config, } = params;
261
261
  const provider = getCachedProvider(config?.rpcUrl);
262
- const delegateAddress = config?.delegateAddress ?? UNIFIED_DELEGATE_ADDRESS;
262
+ const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
263
263
  const delegateInterface = new ethers.Interface(UNIFIED_DELEGATE_ABI);
264
264
  const sourceWallets = sourcePrivateKeys.map(pk => createWallet(pk, provider));
265
265
  const isNative = !tokenAddress;
@@ -520,7 +520,7 @@ export async function pairwiseTransfer(params) {
520
520
  throw new Error('必须提供 amount 或 amounts');
521
521
  })();
522
522
  const provider = getCachedProvider(config?.rpcUrl);
523
- const delegateAddress = config?.delegateAddress ?? UNIFIED_DELEGATE_ADDRESS;
523
+ const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
524
524
  const delegateInterface = new ethers.Interface(UNIFIED_DELEGATE_ABI);
525
525
  const isNative = !tokenAddress;
526
526
  // 创建钱包
@@ -196,11 +196,12 @@ export async function buildEIP7702Transaction(mainWallet, authorizations, calls,
196
196
  const txHash = ethers.keccak256(toSign);
197
197
  const signingKey = new ethers.SigningKey(mainWallet.privateKey);
198
198
  const sig = signingKey.sign(txHash);
199
+ // ✅ 交易签名的 r/s 也需要去除前导零,符合 RLP 规范
199
200
  const signedTxData = [
200
201
  ...txData,
201
202
  bigintToBytes(BigInt(sig.yParity)),
202
- ethers.getBytes(sig.r),
203
- ethers.getBytes(sig.s),
203
+ trimLeadingZeros(ethers.getBytes(sig.r)),
204
+ trimLeadingZeros(ethers.getBytes(sig.s)),
204
205
  ];
205
206
  const signedRlp = rlp.encode(signedTxData);
206
207
  const signedTx = new Uint8Array(1 + signedRlp.length);
@@ -252,11 +253,12 @@ export function buildEIP7702TransactionSync(mainWallet, authorizations, calls, t
252
253
  const txHash = ethers.keccak256(toSign);
253
254
  const signingKey = new ethers.SigningKey(mainWallet.privateKey);
254
255
  const sig = signingKey.sign(txHash);
256
+ // ✅ 交易签名的 r/s 也需要去除前导零,符合 RLP 规范
255
257
  const signedTxData = [
256
258
  ...txData,
257
259
  bigintToBytes(BigInt(sig.yParity)),
258
- ethers.getBytes(sig.r),
259
- ethers.getBytes(sig.s),
260
+ trimLeadingZeros(ethers.getBytes(sig.r)),
261
+ trimLeadingZeros(ethers.getBytes(sig.s)),
260
262
  ];
261
263
  const signedRlp = rlp.encode(signedTxData);
262
264
  const signedTx = new Uint8Array(1 + signedRlp.length);
@@ -42,14 +42,28 @@ export async function washVolume(params) {
42
42
  if (privateKeys.length === 0) {
43
43
  throw new Error('至少需要一个钱包');
44
44
  }
45
+ // ✅ 验证私钥格式
46
+ const validPrivateKeys = privateKeys.filter(pk => {
47
+ const trimmed = (pk || '').trim();
48
+ return trimmed.length >= 64 && (trimmed.startsWith('0x') || /^[0-9a-fA-F]{64}$/.test(trimmed));
49
+ });
50
+ if (validPrivateKeys.length === 0) {
51
+ throw new Error('没有有效的私钥(私钥必须是 0x 开头的 66 位或 64 位十六进制字符串)');
52
+ }
53
+ if (validPrivateKeys.length !== privateKeys.length) {
54
+ console.warn(`[washVolume] 跳过 ${privateKeys.length - validPrivateKeys.length} 个无效私钥`);
55
+ }
56
+ // 使用验证后的私钥
57
+ const actualPrivateKeys = validPrivateKeys;
45
58
  const provider = getCachedProvider(config?.rpcUrl);
46
- const delegateAddress = config?.delegateAddress ?? UNIFIED_DELEGATE_ADDRESS;
59
+ // 空字符串也使用默认值
60
+ const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
47
61
  const delegateInterface = new ethers.Interface(UNIFIED_DELEGATE_ABI);
48
62
  const portalInterface = new ethers.Interface(FLAP_PORTAL_ABI);
49
63
  // 获取实际路由地址
50
64
  const actualRouter = routerAddress ?? getDefaultRouter(poolType);
51
- // 创建钱包
52
- const wallets = privateKeys.map(pk => createWallet(pk, provider));
65
+ // 创建钱包(使用验证后的私钥)
66
+ const wallets = actualPrivateKeys.map(pk => createWallet(pk, provider));
53
67
  const mainWallet = wallets[0];
54
68
  // 计算金额
55
69
  const buyAmountWei = ethers.parseEther(buyAmountPerWallet);
@@ -131,25 +145,50 @@ export async function washVolume(params) {
131
145
  */
132
146
  export async function bundleVolume(params) {
133
147
  const { buyerPrivateKeys, buyAmounts, sellerPrivateKeys, sellAmounts, sellPercent = 100, tokenAddress, tokenDecimals = 18, poolType = 'V3', routerAddress, fee = V3_FEE_TIERS.MEDIUM, config, } = params;
134
- if (buyerPrivateKeys.length !== buyAmounts.length) {
135
- throw new Error('buyerPrivateKeys buyAmounts 长度必须相同');
148
+ // 验证私钥格式的辅助函数
149
+ const isValidPrivateKey = (pk) => {
150
+ const trimmed = (pk || '').trim();
151
+ return trimmed.length >= 64 && (trimmed.startsWith('0x') || /^[0-9a-fA-F]{64}$/.test(trimmed));
152
+ };
153
+ // ✅ 验证买家私钥
154
+ const validBuyerIndices = [];
155
+ const validBuyerPrivateKeys = [];
156
+ const validBuyAmounts = [];
157
+ buyerPrivateKeys.forEach((pk, i) => {
158
+ if (isValidPrivateKey(pk)) {
159
+ validBuyerIndices.push(i);
160
+ validBuyerPrivateKeys.push(pk);
161
+ validBuyAmounts.push(buyAmounts[i] || '0');
162
+ }
163
+ });
164
+ if (validBuyerPrivateKeys.length === 0) {
165
+ throw new Error('没有有效的买家私钥');
166
+ }
167
+ // ✅ 验证卖家私钥
168
+ const validSellerPrivateKeys = sellerPrivateKeys.filter(pk => isValidPrivateKey(pk));
169
+ if (validSellerPrivateKeys.length === 0) {
170
+ throw new Error('没有有效的卖家私钥');
171
+ }
172
+ if (validBuyerPrivateKeys.length !== buyerPrivateKeys.length || validSellerPrivateKeys.length !== sellerPrivateKeys.length) {
173
+ console.warn(`[bundleVolume] 跳过无效私钥: 买家 ${buyerPrivateKeys.length - validBuyerPrivateKeys.length} 个, 卖家 ${sellerPrivateKeys.length - validSellerPrivateKeys.length} 个`);
136
174
  }
137
175
  const provider = getCachedProvider(config?.rpcUrl);
138
- const delegateAddress = config?.delegateAddress ?? UNIFIED_DELEGATE_ADDRESS;
176
+ // 空字符串也使用默认值
177
+ const delegateAddress = (config?.delegateAddress && config.delegateAddress.trim()) || UNIFIED_DELEGATE_ADDRESS;
139
178
  const delegateInterface = new ethers.Interface(UNIFIED_DELEGATE_ABI);
140
179
  const portalInterface = new ethers.Interface(FLAP_PORTAL_ABI);
141
180
  const actualRouter = routerAddress ?? getDefaultRouter(poolType);
142
- // 创建钱包
143
- const buyerWallets = buyerPrivateKeys.map(pk => createWallet(pk, provider));
144
- const sellerWallets = sellerPrivateKeys.map(pk => createWallet(pk, provider));
181
+ // 创建钱包(使用验证后的私钥)
182
+ const buyerWallets = validBuyerPrivateKeys.map(pk => createWallet(pk, provider));
183
+ const sellerWallets = validSellerPrivateKeys.map(pk => createWallet(pk, provider));
145
184
  // 合并所有钱包(去重)
146
185
  const allWalletsMap = new Map();
147
186
  buyerWallets.forEach(w => allWalletsMap.set(w.address.toLowerCase(), w));
148
187
  sellerWallets.forEach(w => allWalletsMap.set(w.address.toLowerCase(), w));
149
188
  const allWallets = Array.from(allWalletsMap.values());
150
189
  const mainWallet = allWallets[0];
151
- // 计算买入金额
152
- const buyAmountsWei = buyAmounts.map(amt => ethers.parseEther(amt));
190
+ // 计算买入金额(使用验证后的金额数组)
191
+ const buyAmountsWei = validBuyAmounts.map(amt => ethers.parseEther(amt));
153
192
  const totalBuyAmount = buyAmountsWei.reduce((sum, amt) => sum + amt, 0n);
154
193
  // 计算利润
155
194
  const profitAmount = calculateProfitAmount(totalBuyAmount);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "four-flap-meme-sdk",
3
- "version": "1.7.16",
3
+ "version": "1.7.18",
4
4
  "description": "SDK for Flap bonding curve and four.meme TokenManager",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",