hermes-swap 0.6.1 → 0.6.2
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/cjs/aggregator.cjs +127 -77
- package/dist/cjs/aggregator.d.ts +4 -0
- package/dist/esm/aggregator.d.ts +4 -0
- package/dist/esm/aggregator.mjs +362 -287
- package/package.json +1 -1
package/dist/cjs/aggregator.cjs
CHANGED
|
@@ -174,6 +174,7 @@ var _Aggregator = class {
|
|
|
174
174
|
`swapByPath开始, user=${params.user}, amountIn=${params.amountInWei}, path=[${pathDesc}], useBundle=${useBundle}`
|
|
175
175
|
);
|
|
176
176
|
const startTs = Date.now();
|
|
177
|
+
let txHash;
|
|
177
178
|
try {
|
|
178
179
|
if (useBundle) {
|
|
179
180
|
const { pureTxReq: pureTxReq2, bundleBlockCount } = this.stripCustomFields(txReq, params.chain);
|
|
@@ -181,6 +182,7 @@ var _Aggregator = class {
|
|
|
181
182
|
if (!flashbotsReceipt) {
|
|
182
183
|
throw new Error("Bundle 未在目标区块上链");
|
|
183
184
|
}
|
|
185
|
+
txHash = flashbotsReceipt.hash;
|
|
184
186
|
_Aggregator.traceLog(params.chain, "log", `swapByPath完成(bundle), txHash=${flashbotsReceipt.hash}, amountOut=${flashbotsReceipt.amountOut}, 总耗时=${Date.now() - startTs}ms`);
|
|
185
187
|
return flashbotsReceipt;
|
|
186
188
|
}
|
|
@@ -206,13 +208,14 @@ var _Aggregator = class {
|
|
|
206
208
|
try {
|
|
207
209
|
estimateGas = await aggregator.swap.estimateGas(params.user, params.amountInWei, swapParams, params.minAmountOutList, estimationOverrides);
|
|
208
210
|
} catch (error) {
|
|
209
|
-
_Aggregator.traceLog(params.chain, "error", `swapByPath estimateGas失败, error=${error}`);
|
|
211
|
+
_Aggregator.traceLog(params.chain, "error", `swapByPath estimateGas失败, rpcUrl=${this.getRpcUrl(params.chain)}, error=${error}`);
|
|
210
212
|
throw error;
|
|
211
213
|
}
|
|
212
214
|
txReq = this.resolveGasLimit(txReq, estimateGas);
|
|
213
215
|
txReq = await this.resolveNonce(wallet.provider, wallet.address, txReq);
|
|
214
216
|
txReq = await this.resolvePricing(wallet.provider, txReq);
|
|
215
217
|
const receipt = await this.sendContractTx(params.chain, aggregator, "swap", [params.user, params.amountInWei, swapParams, params.minAmountOutList], txReq);
|
|
218
|
+
txHash = receipt.hash;
|
|
216
219
|
const iface = new import_ethers.ethers.Interface(import_aggregator.default);
|
|
217
220
|
let amountOut = null;
|
|
218
221
|
for (const log of receipt.logs) {
|
|
@@ -240,7 +243,7 @@ var _Aggregator = class {
|
|
|
240
243
|
to: receipt.from
|
|
241
244
|
};
|
|
242
245
|
} catch (error) {
|
|
243
|
-
_Aggregator.traceLog(params.chain, "error", `swapByPath异常, 总耗时=${Date.now() - startTs}ms, error=${error}`);
|
|
246
|
+
_Aggregator.traceLog(params.chain, "error", `swapByPath异常, rpcUrl=${this.getRpcUrl(params.chain)}, txHash=${txHash ?? "N/A"}, 总耗时=${Date.now() - startTs}ms, error=${error}`);
|
|
244
247
|
throw error;
|
|
245
248
|
}
|
|
246
249
|
}
|
|
@@ -279,7 +282,7 @@ var _Aggregator = class {
|
|
|
279
282
|
});
|
|
280
283
|
return this.batchMultiSwap({ chain, users, amountInWeis, paths, minAmountOutLists });
|
|
281
284
|
} catch (error) {
|
|
282
|
-
throw new Error(`aggregator swap error: ${error}`);
|
|
285
|
+
throw new Error(`aggregator swap error: chain=${chain}, rpcUrl=${this.getRpcUrl(chain)}, ${error}`);
|
|
283
286
|
}
|
|
284
287
|
}
|
|
285
288
|
async swapAndBridge(params, txReq = {}) {
|
|
@@ -291,6 +294,7 @@ var _Aggregator = class {
|
|
|
291
294
|
`swapAndBridge开始, user=${params.user}, amountInWeis=[${params.amountInWeis.join(",")}], bridgeType=${params.bridgeType}, destChain=${params.destChain}, useBundle=${useBundle}`
|
|
292
295
|
);
|
|
293
296
|
const startTs = Date.now();
|
|
297
|
+
let txHash;
|
|
294
298
|
try {
|
|
295
299
|
const { pureTxReq, bundleBlockCount } = this.stripCustomFields(txReq, params.chain);
|
|
296
300
|
txReq = pureTxReq;
|
|
@@ -331,7 +335,7 @@ var _Aggregator = class {
|
|
|
331
335
|
try {
|
|
332
336
|
estimateGas = await aggregator.multiSwapAndBridge.estimateGas(...args, estimationOverrides);
|
|
333
337
|
} catch (error) {
|
|
334
|
-
_Aggregator.traceLog(params.chain, "error", `swapAndBridge estimateGas失败, error=${error}`);
|
|
338
|
+
_Aggregator.traceLog(params.chain, "error", `swapAndBridge estimateGas失败, rpcUrl=${this.getRpcUrl(params.chain)}, error=${error}`);
|
|
335
339
|
throw error;
|
|
336
340
|
}
|
|
337
341
|
txReq = this.resolveGasLimit(txReq, estimateGas);
|
|
@@ -341,13 +345,15 @@ var _Aggregator = class {
|
|
|
341
345
|
let receipt;
|
|
342
346
|
if (useBundle) {
|
|
343
347
|
const calldata = iface.encodeFunctionData("multiSwapAndBridge", args);
|
|
344
|
-
const { receipt: flashbotsReceipt, txHash, targetBlocks } = await this.submitBundleTx(params.chain, wallet, txReq, aggregatorAddress, calldata, txReq.value ?? 0n, bundleBlockCount);
|
|
348
|
+
const { receipt: flashbotsReceipt, txHash: bundleTxHash, targetBlocks } = await this.submitBundleTx(params.chain, wallet, txReq, aggregatorAddress, calldata, txReq.value ?? 0n, bundleBlockCount);
|
|
349
|
+
txHash = bundleTxHash;
|
|
345
350
|
if (!flashbotsReceipt) {
|
|
346
|
-
throw new import_types.BundleNotIncludedError(`Bundle 未在目标区块上链, txHash=${
|
|
351
|
+
throw new import_types.BundleNotIncludedError(`Bundle 未在目标区块上链, txHash=${bundleTxHash}, targetBlocks=[${targetBlocks.join(",")}]`, bundleTxHash);
|
|
347
352
|
}
|
|
348
353
|
receipt = flashbotsReceipt;
|
|
349
354
|
} else {
|
|
350
355
|
receipt = await this.sendContractTx(params.chain, aggregator, "multiSwapAndBridge", args, txReq);
|
|
356
|
+
txHash = receipt.hash;
|
|
351
357
|
}
|
|
352
358
|
let receiptUser = null;
|
|
353
359
|
let amountInList = null;
|
|
@@ -387,7 +393,7 @@ var _Aggregator = class {
|
|
|
387
393
|
receipt
|
|
388
394
|
};
|
|
389
395
|
} catch (error) {
|
|
390
|
-
_Aggregator.traceLog(params.chain, "error", `swapAndBridge异常, 总耗时=${Date.now() - startTs}ms, error=${error}`);
|
|
396
|
+
_Aggregator.traceLog(params.chain, "error", `swapAndBridge异常, rpcUrl=${this.getRpcUrl(params.chain)}, txHash=${txHash ?? "N/A"}, 总耗时=${Date.now() - startTs}ms, error=${error}`);
|
|
391
397
|
throw error;
|
|
392
398
|
}
|
|
393
399
|
}
|
|
@@ -400,6 +406,7 @@ var _Aggregator = class {
|
|
|
400
406
|
`multiSwap开始, user=${params.user}, pathsCount=${params.paths.length}, amountInWeis=[${params.amountInWeis.join(",")}], useBundle=${useBundle}`
|
|
401
407
|
);
|
|
402
408
|
const startTs = Date.now();
|
|
409
|
+
let txHash;
|
|
403
410
|
try {
|
|
404
411
|
const { pureTxReq, bundleBlockCount } = this.stripCustomFields(txReq, params.chain);
|
|
405
412
|
txReq = pureTxReq;
|
|
@@ -441,7 +448,7 @@ var _Aggregator = class {
|
|
|
441
448
|
try {
|
|
442
449
|
estimateGas = await aggregator.multiSwap.estimateGas(params.user, params.amountInWeis, swapParamsList, params.minAmountOutLists, params.totalMinAmountOut, estimationOverrides);
|
|
443
450
|
} catch (error) {
|
|
444
|
-
_Aggregator.traceLog(params.chain, "error", `multiSwap estimateGas失败, error=${error}`);
|
|
451
|
+
_Aggregator.traceLog(params.chain, "error", `multiSwap estimateGas失败, rpcUrl=${this.getRpcUrl(params.chain)}, error=${error}`);
|
|
445
452
|
throw error;
|
|
446
453
|
}
|
|
447
454
|
txReq = this.resolveGasLimit(txReq, estimateGas);
|
|
@@ -451,13 +458,15 @@ var _Aggregator = class {
|
|
|
451
458
|
let receipt;
|
|
452
459
|
if (useBundle) {
|
|
453
460
|
const calldata = iface.encodeFunctionData("multiSwap", [params.user, params.amountInWeis, swapParamsList, params.minAmountOutLists, params.totalMinAmountOut]);
|
|
454
|
-
const { receipt: flashbotsReceipt, txHash, targetBlocks } = await this.submitBundleTx(params.chain, wallet, txReq, aggregatorAddress, calldata, txReq.value ?? 0n, bundleBlockCount);
|
|
461
|
+
const { receipt: flashbotsReceipt, txHash: bundleTxHash, targetBlocks } = await this.submitBundleTx(params.chain, wallet, txReq, aggregatorAddress, calldata, txReq.value ?? 0n, bundleBlockCount);
|
|
462
|
+
txHash = bundleTxHash;
|
|
455
463
|
if (!flashbotsReceipt) {
|
|
456
|
-
throw new import_types.BundleNotIncludedError(`Bundle 未在目标区块上链, txHash=${
|
|
464
|
+
throw new import_types.BundleNotIncludedError(`Bundle 未在目标区块上链, txHash=${bundleTxHash}, targetBlocks=[${targetBlocks.join(",")}]`, bundleTxHash);
|
|
457
465
|
}
|
|
458
466
|
receipt = flashbotsReceipt;
|
|
459
467
|
} else {
|
|
460
468
|
receipt = await this.sendContractTx(params.chain, aggregator, "multiSwap", [params.user, params.amountInWeis, swapParamsList, params.minAmountOutLists, params.totalMinAmountOut], txReq);
|
|
469
|
+
txHash = receipt.hash;
|
|
461
470
|
}
|
|
462
471
|
let amountOutList = null;
|
|
463
472
|
for (const log of receipt.logs) {
|
|
@@ -496,7 +505,7 @@ var _Aggregator = class {
|
|
|
496
505
|
receipt
|
|
497
506
|
};
|
|
498
507
|
} catch (error) {
|
|
499
|
-
_Aggregator.traceLog(params.chain, "error", `multiSwap异常, 总耗时=${Date.now() - startTs}ms, error=${error}`);
|
|
508
|
+
_Aggregator.traceLog(params.chain, "error", `multiSwap异常, rpcUrl=${this.getRpcUrl(params.chain)}, txHash=${txHash ?? "N/A"}, 总耗时=${Date.now() - startTs}ms, error=${error}`);
|
|
500
509
|
throw error;
|
|
501
510
|
}
|
|
502
511
|
}
|
|
@@ -508,6 +517,7 @@ var _Aggregator = class {
|
|
|
508
517
|
`batchMultiSwap开始, users=${params.users.length}, pathsCount=${params.paths.length}, amountInWeis=[${params.amountInWeis.join(",")}], useBundle=${useBundle}`
|
|
509
518
|
);
|
|
510
519
|
const startTs = Date.now();
|
|
520
|
+
let txHash;
|
|
511
521
|
try {
|
|
512
522
|
const { pureTxReq, bundleBlockCount } = this.stripCustomFields(txReq, params.chain);
|
|
513
523
|
txReq = pureTxReq;
|
|
@@ -533,7 +543,7 @@ var _Aggregator = class {
|
|
|
533
543
|
try {
|
|
534
544
|
estimateGas = await aggregator.batchMultiSwap.estimateGas(params.users, params.amountInWeis, swapParamsList, params.minAmountOutLists, estimationOverrides);
|
|
535
545
|
} catch (error) {
|
|
536
|
-
_Aggregator.traceLog(params.chain, "error", `batchMultiSwap estimateGas失败, error=${error}`);
|
|
546
|
+
_Aggregator.traceLog(params.chain, "error", `batchMultiSwap estimateGas失败, rpcUrl=${this.getRpcUrl(params.chain)}, error=${error}`);
|
|
537
547
|
throw error;
|
|
538
548
|
}
|
|
539
549
|
txReq = this.resolveGasLimit(txReq, estimateGas);
|
|
@@ -543,13 +553,15 @@ var _Aggregator = class {
|
|
|
543
553
|
let receipt;
|
|
544
554
|
if (useBundle) {
|
|
545
555
|
const calldata = iface.encodeFunctionData("batchMultiSwap", [params.users, params.amountInWeis, swapParamsList, params.minAmountOutLists]);
|
|
546
|
-
const { receipt: flashbotsReceipt, txHash, targetBlocks } = await this.submitBundleTx(params.chain, wallet, txReq, aggregatorAddress, calldata, txReq.value ?? 0n, bundleBlockCount);
|
|
556
|
+
const { receipt: flashbotsReceipt, txHash: bundleTxHash, targetBlocks } = await this.submitBundleTx(params.chain, wallet, txReq, aggregatorAddress, calldata, txReq.value ?? 0n, bundleBlockCount);
|
|
557
|
+
txHash = bundleTxHash;
|
|
547
558
|
if (!flashbotsReceipt) {
|
|
548
|
-
throw new import_types.BundleNotIncludedError(`Bundle 未在目标区块上链, txHash=${
|
|
559
|
+
throw new import_types.BundleNotIncludedError(`Bundle 未在目标区块上链, txHash=${bundleTxHash}, targetBlocks=[${targetBlocks.join(",")}]`, bundleTxHash);
|
|
549
560
|
}
|
|
550
561
|
receipt = flashbotsReceipt;
|
|
551
562
|
} else {
|
|
552
563
|
receipt = await this.sendContractTx(params.chain, aggregator, "batchMultiSwap", [params.users, params.amountInWeis, swapParamsList, params.minAmountOutLists], txReq);
|
|
564
|
+
txHash = receipt.hash;
|
|
553
565
|
}
|
|
554
566
|
let userList = null;
|
|
555
567
|
let amountInList = null;
|
|
@@ -595,7 +607,7 @@ var _Aggregator = class {
|
|
|
595
607
|
receipt
|
|
596
608
|
};
|
|
597
609
|
} catch (error) {
|
|
598
|
-
_Aggregator.traceLog(params.chain, "error", `batchMultiSwap异常, 总耗时=${Date.now() - startTs}ms, error=${error}`);
|
|
610
|
+
_Aggregator.traceLog(params.chain, "error", `batchMultiSwap异常, rpcUrl=${this.getRpcUrl(params.chain)}, txHash=${txHash ?? "N/A"}, 总耗时=${Date.now() - startTs}ms, error=${error}`);
|
|
599
611
|
throw error;
|
|
600
612
|
}
|
|
601
613
|
}
|
|
@@ -630,6 +642,7 @@ var _Aggregator = class {
|
|
|
630
642
|
`bridge开始, user=${params.user}, bridgeType=${params.bridgeType}, token=${params.tokenAddress}, amountInWei=${params.amountInWei}, destChain=${params.destChain}, useBundle=${useBundle}`
|
|
631
643
|
);
|
|
632
644
|
const startTs = Date.now();
|
|
645
|
+
let txHash;
|
|
633
646
|
try {
|
|
634
647
|
const { pureTxReq, bundleBlockCount } = this.stripCustomFields(txReq, params.chain);
|
|
635
648
|
txReq = pureTxReq;
|
|
@@ -661,7 +674,7 @@ var _Aggregator = class {
|
|
|
661
674
|
try {
|
|
662
675
|
estimateGas = await aggregator.bridge.estimateGas(params.user, bridgeArgs, estimationOverrides);
|
|
663
676
|
} catch (error) {
|
|
664
|
-
_Aggregator.traceLog(params.chain, "error", `bridge estimateGas失败, error=${error}`);
|
|
677
|
+
_Aggregator.traceLog(params.chain, "error", `bridge estimateGas失败, rpcUrl=${this.getRpcUrl(params.chain)}, error=${error}`);
|
|
665
678
|
throw error;
|
|
666
679
|
}
|
|
667
680
|
txReq = this.resolveGasLimit(txReq, estimateGas);
|
|
@@ -671,13 +684,15 @@ var _Aggregator = class {
|
|
|
671
684
|
if (useBundle) {
|
|
672
685
|
const iface = new import_ethers.ethers.Interface(import_aggregator.default);
|
|
673
686
|
const calldata = iface.encodeFunctionData("bridge", [params.user, bridgeArgs]);
|
|
674
|
-
const { receipt: flashbotsReceipt, txHash, targetBlocks } = await this.submitBundleTx(params.chain, wallet, txReq, aggregatorAddress, calldata, txReq.value ?? 0n, bundleBlockCount);
|
|
687
|
+
const { receipt: flashbotsReceipt, txHash: bundleTxHash, targetBlocks } = await this.submitBundleTx(params.chain, wallet, txReq, aggregatorAddress, calldata, txReq.value ?? 0n, bundleBlockCount);
|
|
688
|
+
txHash = bundleTxHash;
|
|
675
689
|
if (!flashbotsReceipt) {
|
|
676
|
-
throw new import_types.BundleNotIncludedError(`Bundle 未在目标区块上链, txHash=${
|
|
690
|
+
throw new import_types.BundleNotIncludedError(`Bundle 未在目标区块上链, txHash=${bundleTxHash}, targetBlocks=[${targetBlocks.join(",")}]`, bundleTxHash);
|
|
677
691
|
}
|
|
678
692
|
txReceipt = flashbotsReceipt;
|
|
679
693
|
} else {
|
|
680
694
|
txReceipt = await this.sendContractTx(params.chain, aggregator, "bridge", [params.user, bridgeArgs], txReq);
|
|
695
|
+
txHash = txReceipt.hash;
|
|
681
696
|
}
|
|
682
697
|
_Aggregator.traceLog(
|
|
683
698
|
params.chain,
|
|
@@ -693,7 +708,7 @@ var _Aggregator = class {
|
|
|
693
708
|
to: txReceipt.to ?? ""
|
|
694
709
|
};
|
|
695
710
|
} catch (error) {
|
|
696
|
-
_Aggregator.traceLog(params.chain, "error", `bridge异常, 总耗时=${Date.now() - startTs}ms, error=${error}`);
|
|
711
|
+
_Aggregator.traceLog(params.chain, "error", `bridge异常, rpcUrl=${this.getRpcUrl(params.chain)}, txHash=${txHash ?? "N/A"}, 总耗时=${Date.now() - startTs}ms, error=${error}`);
|
|
697
712
|
throw error;
|
|
698
713
|
}
|
|
699
714
|
}
|
|
@@ -862,14 +877,81 @@ var _Aggregator = class {
|
|
|
862
877
|
}
|
|
863
878
|
return null;
|
|
864
879
|
}
|
|
880
|
+
broadcastToAll(chain, signedTx, txHash, providers) {
|
|
881
|
+
for (const { provider, label } of providers) {
|
|
882
|
+
const sendTs = Date.now();
|
|
883
|
+
provider.broadcastTransaction(signedTx).then(
|
|
884
|
+
() => _Aggregator.traceLog(chain, "log", `广播${label} OK, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`),
|
|
885
|
+
(err) => {
|
|
886
|
+
const msg = (err == null ? void 0 : err.message) ?? String(err);
|
|
887
|
+
if (msg.includes("already known") || msg.includes("nonce too low") || msg.includes("nonce has already been used") || msg.includes("ALREADY_EXISTS") || msg.includes("NONCE_EXPIRED")) {
|
|
888
|
+
_Aggregator.traceLog(chain, "log", `广播${label} already-known, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
|
|
889
|
+
} else {
|
|
890
|
+
_Aggregator.traceLog(chain, "warn", `广播${label} 失败: ${msg}, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
raceForReceipt(chain, txHash, providers, ownedProviders = [], timeoutMs = _Aggregator.TX_CONFIRM_TIMEOUT_MS) {
|
|
897
|
+
return new Promise((resolve, reject) => {
|
|
898
|
+
let settled = false;
|
|
899
|
+
const blockHandlers = [];
|
|
900
|
+
const cleanup = () => {
|
|
901
|
+
for (const { provider, handler } of blockHandlers) {
|
|
902
|
+
provider.off("block", handler);
|
|
903
|
+
}
|
|
904
|
+
for (const p of ownedProviders) {
|
|
905
|
+
try {
|
|
906
|
+
p.destroy();
|
|
907
|
+
} catch {
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
};
|
|
911
|
+
const onFound = (receipt, label) => {
|
|
912
|
+
if (settled)
|
|
913
|
+
return;
|
|
914
|
+
settled = true;
|
|
915
|
+
clearTimeout(timer);
|
|
916
|
+
cleanup();
|
|
917
|
+
_Aggregator.traceLog(chain, "log", `${label} 先查到receipt, txHash=${txHash}, block=${receipt.blockNumber}`);
|
|
918
|
+
resolve(receipt);
|
|
919
|
+
};
|
|
920
|
+
const checkReceipt = (provider, label) => {
|
|
921
|
+
if (settled)
|
|
922
|
+
return;
|
|
923
|
+
provider.getTransactionReceipt(txHash).then(
|
|
924
|
+
(r) => {
|
|
925
|
+
if (r)
|
|
926
|
+
onFound(r, label);
|
|
927
|
+
},
|
|
928
|
+
() => {
|
|
929
|
+
}
|
|
930
|
+
);
|
|
931
|
+
};
|
|
932
|
+
for (const { provider, label } of providers) {
|
|
933
|
+
const handler = () => checkReceipt(provider, label);
|
|
934
|
+
provider.on("block", handler);
|
|
935
|
+
blockHandlers.push({ provider, handler });
|
|
936
|
+
checkReceipt(provider, label);
|
|
937
|
+
}
|
|
938
|
+
const timer = setTimeout(() => {
|
|
939
|
+
if (settled)
|
|
940
|
+
return;
|
|
941
|
+
settled = true;
|
|
942
|
+
cleanup();
|
|
943
|
+
reject(new Error(`Transaction not confirmed within ${timeoutMs}ms: ${txHash}`));
|
|
944
|
+
}, timeoutMs);
|
|
945
|
+
});
|
|
946
|
+
}
|
|
865
947
|
async sendContractTx(chain, contract, method, args, txReq) {
|
|
866
948
|
const extraUrls = this.broadcastRpcsMap.get(chain);
|
|
867
949
|
if (!extraUrls || extraUrls.length === 0) {
|
|
868
950
|
_Aggregator.traceLog(chain, "log", `渠道=单RPC直发, method=${method}, nonce=${txReq.nonce}, gasLimit=${txReq.gasLimit}`);
|
|
869
951
|
const sendTs = Date.now();
|
|
870
|
-
const
|
|
871
|
-
_Aggregator.traceLog(chain, "log", `单RPC已发送, txHash=${
|
|
872
|
-
const receipt2 = await
|
|
952
|
+
const txResponse = await contract[method](...args, txReq);
|
|
953
|
+
_Aggregator.traceLog(chain, "log", `单RPC已发送, txHash=${txResponse.hash}, 耗时=${Date.now() - sendTs}ms`);
|
|
954
|
+
const receipt2 = await txResponse.wait();
|
|
873
955
|
const singleProvider = this.providerClient.getProvider(chain);
|
|
874
956
|
const blockTs2 = await this.getBlockTimestampStr(singleProvider, receipt2.blockNumber);
|
|
875
957
|
_Aggregator.traceLog(chain, "log", `单RPC上链确认, txHash=${receipt2.hash}, blockNumber=${receipt2.blockNumber}, 出块时间=${blockTs2}, gasUsed=${receipt2.gasUsed}`);
|
|
@@ -882,67 +964,30 @@ var _Aggregator = class {
|
|
|
882
964
|
populated.chainId = network.chainId;
|
|
883
965
|
const signedTx = await wallet.signTransaction(populated);
|
|
884
966
|
const txHash = import_ethers.ethers.keccak256(signedTx);
|
|
885
|
-
const
|
|
886
|
-
const currentBlock = await
|
|
967
|
+
const mainProvider = wallet.provider;
|
|
968
|
+
const currentBlock = await mainProvider.getBlockNumber();
|
|
969
|
+
const extraProviders = extraUrls.map((url, i) => ({
|
|
970
|
+
provider: new import_ethers.ethers.JsonRpcProvider(url),
|
|
971
|
+
label: `RPC[${i + 1}/${new URL(url).hostname}]`
|
|
972
|
+
}));
|
|
973
|
+
const allProviders = [
|
|
974
|
+
{ provider: mainProvider, label: "RPC[0/主]" },
|
|
975
|
+
...extraProviders
|
|
976
|
+
];
|
|
977
|
+
const ownedProviders = extraProviders.map((e) => e.provider);
|
|
887
978
|
_Aggregator.traceLog(
|
|
888
979
|
chain,
|
|
889
980
|
"log",
|
|
890
|
-
`渠道=多RPC广播, method=${method}, nonce=${txReq.nonce}, gasLimit=${txReq.gasLimit}, 当前区块=${currentBlock}, 期望上链区块=${currentBlock + 1}, txHash=${txHash}, 主
|
|
981
|
+
`渠道=多RPC广播, method=${method}, nonce=${txReq.nonce}, gasLimit=${txReq.gasLimit}, 当前区块=${currentBlock}, 期望上链区块=${currentBlock + 1}, txHash=${txHash}, RPC数量=${allProviders.length}(主1+副${extraUrls.length})`
|
|
891
982
|
);
|
|
892
|
-
const
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
rpc.broadcastTransaction(signedTx).then(
|
|
897
|
-
() => _Aggregator.traceLog(chain, "log", `广播${label} OK, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`),
|
|
898
|
-
(err) => {
|
|
899
|
-
const msg = (err == null ? void 0 : err.message) ?? String(err);
|
|
900
|
-
if (msg.includes("already known") || msg.includes("nonce too low") || msg.includes("ALREADY_EXISTS") || msg.includes("nonce has already been used")) {
|
|
901
|
-
_Aggregator.traceLog(chain, "log", `广播${label} already known, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
|
|
902
|
-
} else {
|
|
903
|
-
_Aggregator.traceLog(chain, "warn", `广播${label} 失败: ${msg}, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
);
|
|
907
|
-
};
|
|
908
|
-
const mainSendTs = Date.now();
|
|
909
|
-
extraUrls.forEach((url, i) => broadcastToExtra(url, i));
|
|
910
|
-
let txResponse;
|
|
911
|
-
try {
|
|
912
|
-
txResponse = await provider.broadcastTransaction(signedTx);
|
|
913
|
-
_Aggregator.traceLog(chain, "log", `广播主RPC已发送, txHash=${txHash}, 耗时=${Date.now() - mainSendTs}ms`);
|
|
914
|
-
} catch (err) {
|
|
915
|
-
const msg = (err == null ? void 0 : err.message) ?? String(err);
|
|
916
|
-
if (msg.includes("already known") || msg.includes("nonce too low") || msg.includes("ALREADY_EXISTS") || msg.includes("nonce has already been used")) {
|
|
917
|
-
_Aggregator.traceLog(chain, "log", `广播主RPC already known (可能额外RPC已上链), txHash=${txHash}, 耗时=${Date.now() - mainSendTs}ms, 开始轮询receipt`);
|
|
918
|
-
const existingReceipt = await provider.getTransactionReceipt(txHash);
|
|
919
|
-
if (existingReceipt) {
|
|
920
|
-
_Aggregator.traceLog(chain, "log", `交易已上链, txHash=${txHash}, blockNumber=${existingReceipt.blockNumber}`);
|
|
921
|
-
const blockTs2 = await this.getBlockTimestampStr(provider, existingReceipt.blockNumber);
|
|
922
|
-
_Aggregator.traceLog(
|
|
923
|
-
chain,
|
|
924
|
-
"log",
|
|
925
|
-
`多RPC广播上链确认, txHash=${existingReceipt.hash}, blockNumber=${existingReceipt.blockNumber}, 出块时间=${blockTs2}, gasUsed=${existingReceipt.gasUsed}, 总耗时=${Date.now() - mainSendTs}ms`
|
|
926
|
-
);
|
|
927
|
-
return existingReceipt;
|
|
928
|
-
}
|
|
929
|
-
txResponse = await provider.getTransaction(txHash);
|
|
930
|
-
if (!txResponse) {
|
|
931
|
-
throw new Error(`Transaction not found after broadcast error: ${txHash}`);
|
|
932
|
-
}
|
|
933
|
-
} else {
|
|
934
|
-
_Aggregator.traceLog(chain, "error", `广播主RPC失败: ${msg}, txHash=${txHash}, 耗时=${Date.now() - mainSendTs}ms`);
|
|
935
|
-
throw err;
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
const receipt = await txResponse.wait();
|
|
939
|
-
if (!receipt)
|
|
940
|
-
throw new Error(`Transaction receipt is null: ${txHash}`);
|
|
941
|
-
const blockTs = await this.getBlockTimestampStr(provider, receipt.blockNumber);
|
|
983
|
+
const broadcastTs = Date.now();
|
|
984
|
+
this.broadcastToAll(chain, signedTx, txHash, allProviders);
|
|
985
|
+
const receipt = await this.raceForReceipt(chain, txHash, allProviders, ownedProviders);
|
|
986
|
+
const blockTs = await this.getBlockTimestampStr(mainProvider, receipt.blockNumber);
|
|
942
987
|
_Aggregator.traceLog(
|
|
943
988
|
chain,
|
|
944
989
|
"log",
|
|
945
|
-
`多RPC广播上链确认, txHash=${receipt.hash}, blockNumber=${receipt.blockNumber}, 出块时间=${blockTs}, gasUsed=${receipt.gasUsed}, 总耗时=${Date.now() -
|
|
990
|
+
`多RPC广播上链确认, txHash=${receipt.hash}, blockNumber=${receipt.blockNumber}, 出块时间=${blockTs}, gasUsed=${receipt.gasUsed}, 总耗时=${Date.now() - broadcastTs}ms`
|
|
946
991
|
);
|
|
947
992
|
return receipt;
|
|
948
993
|
}
|
|
@@ -1061,7 +1106,7 @@ var _Aggregator = class {
|
|
|
1061
1106
|
try {
|
|
1062
1107
|
estimateGas = await aggregator.swap.estimateGas(params.user, params.amountInWei, swapParams, params.minAmountOutList, estimationOverrides);
|
|
1063
1108
|
} catch (error) {
|
|
1064
|
-
_Aggregator.traceLog(params.chain, "error", `swapByFlashbots estimateGas失败, error=${error}`);
|
|
1109
|
+
_Aggregator.traceLog(params.chain, "error", `swapByFlashbots estimateGas失败, rpcUrl=${this.getRpcUrl(params.chain)}, error=${error}`);
|
|
1065
1110
|
throw error;
|
|
1066
1111
|
}
|
|
1067
1112
|
_Aggregator.traceLog(params.chain, "log", `swapByFlashbots estimateGas=${estimateGas}`);
|
|
@@ -1124,6 +1169,10 @@ var _Aggregator = class {
|
|
|
1124
1169
|
}
|
|
1125
1170
|
return tx;
|
|
1126
1171
|
}
|
|
1172
|
+
getRpcUrl(chain) {
|
|
1173
|
+
var _a;
|
|
1174
|
+
return ((_a = this.config.rpc[chain]) == null ? void 0 : _a.url) ?? "unknown";
|
|
1175
|
+
}
|
|
1127
1176
|
validateParams(params) {
|
|
1128
1177
|
if (!params.chain)
|
|
1129
1178
|
throw new Error("Chain not found");
|
|
@@ -1169,6 +1218,7 @@ Aggregator.DEFAULT_ETH_BUILDERS = {
|
|
|
1169
1218
|
tbuilder: "https://relay.tbuilder.xyz",
|
|
1170
1219
|
bobabuilder: "https://relay.boba-builder.com"
|
|
1171
1220
|
};
|
|
1221
|
+
Aggregator.TX_CONFIRM_TIMEOUT_MS = 12e4;
|
|
1172
1222
|
Aggregator.BUNDLE_POLL_INTERVAL_MS = 500;
|
|
1173
1223
|
Aggregator.BUNDLE_INCLUSION_TIMEOUT_MS = 3e4;
|
|
1174
1224
|
var aggregator_default = Aggregator;
|
package/dist/cjs/aggregator.d.ts
CHANGED
|
@@ -50,9 +50,12 @@ declare class Aggregator {
|
|
|
50
50
|
};
|
|
51
51
|
estimateGas(estimateType: IEstimateType, params: IBridgeParams | ISwapByPathParams | ISwapAndBridgeParams | IBatchMultiSwapParams): Promise<bigint>;
|
|
52
52
|
getAggregatorSupportContracts(chain: ChainNameEnum): Promise<SupportContracts[]>;
|
|
53
|
+
private static readonly TX_CONFIRM_TIMEOUT_MS;
|
|
53
54
|
private static readonly BUNDLE_POLL_INTERVAL_MS;
|
|
54
55
|
private static readonly BUNDLE_INCLUSION_TIMEOUT_MS;
|
|
55
56
|
private waitForBundleInclusion;
|
|
57
|
+
private broadcastToAll;
|
|
58
|
+
private raceForReceipt;
|
|
56
59
|
private sendContractTx;
|
|
57
60
|
private submitBundleTx;
|
|
58
61
|
private swapByFlashbots;
|
|
@@ -60,6 +63,7 @@ declare class Aggregator {
|
|
|
60
63
|
private resolveNonce;
|
|
61
64
|
private resolvePricing;
|
|
62
65
|
private sanitizePricing;
|
|
66
|
+
private getRpcUrl;
|
|
63
67
|
private validateParams;
|
|
64
68
|
private shouldUseBundle;
|
|
65
69
|
private stripCustomFields;
|
package/dist/esm/aggregator.d.ts
CHANGED
|
@@ -50,9 +50,12 @@ declare class Aggregator {
|
|
|
50
50
|
};
|
|
51
51
|
estimateGas(estimateType: IEstimateType, params: IBridgeParams | ISwapByPathParams | ISwapAndBridgeParams | IBatchMultiSwapParams): Promise<bigint>;
|
|
52
52
|
getAggregatorSupportContracts(chain: ChainNameEnum): Promise<SupportContracts[]>;
|
|
53
|
+
private static readonly TX_CONFIRM_TIMEOUT_MS;
|
|
53
54
|
private static readonly BUNDLE_POLL_INTERVAL_MS;
|
|
54
55
|
private static readonly BUNDLE_INCLUSION_TIMEOUT_MS;
|
|
55
56
|
private waitForBundleInclusion;
|
|
57
|
+
private broadcastToAll;
|
|
58
|
+
private raceForReceipt;
|
|
56
59
|
private sendContractTx;
|
|
57
60
|
private submitBundleTx;
|
|
58
61
|
private swapByFlashbots;
|
|
@@ -60,6 +63,7 @@ declare class Aggregator {
|
|
|
60
63
|
private resolveNonce;
|
|
61
64
|
private resolvePricing;
|
|
62
65
|
private sanitizePricing;
|
|
66
|
+
private getRpcUrl;
|
|
63
67
|
private validateParams;
|
|
64
68
|
private shouldUseBundle;
|
|
65
69
|
private stripCustomFields;
|