hermes-swap 0.6.0 → 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 -51
- package/dist/cjs/aggregator.d.ts +4 -0
- package/dist/esm/aggregator.d.ts +4 -0
- package/dist/esm/aggregator.mjs +361 -241
- 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,41 +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")) {
|
|
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
|
-
const txResponse = await provider.broadcastTransaction(signedTx);
|
|
911
|
-
_Aggregator.traceLog(chain, "log", `广播主RPC已发送, txHash=${txHash}, 耗时=${Date.now() - mainSendTs}ms`);
|
|
912
|
-
const receipt = await txResponse.wait();
|
|
913
|
-
if (!receipt)
|
|
914
|
-
throw new Error(`Transaction receipt is null: ${txHash}`);
|
|
915
|
-
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);
|
|
916
987
|
_Aggregator.traceLog(
|
|
917
988
|
chain,
|
|
918
989
|
"log",
|
|
919
|
-
`多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`
|
|
920
991
|
);
|
|
921
992
|
return receipt;
|
|
922
993
|
}
|
|
@@ -1035,7 +1106,7 @@ var _Aggregator = class {
|
|
|
1035
1106
|
try {
|
|
1036
1107
|
estimateGas = await aggregator.swap.estimateGas(params.user, params.amountInWei, swapParams, params.minAmountOutList, estimationOverrides);
|
|
1037
1108
|
} catch (error) {
|
|
1038
|
-
_Aggregator.traceLog(params.chain, "error", `swapByFlashbots estimateGas失败, error=${error}`);
|
|
1109
|
+
_Aggregator.traceLog(params.chain, "error", `swapByFlashbots estimateGas失败, rpcUrl=${this.getRpcUrl(params.chain)}, error=${error}`);
|
|
1039
1110
|
throw error;
|
|
1040
1111
|
}
|
|
1041
1112
|
_Aggregator.traceLog(params.chain, "log", `swapByFlashbots estimateGas=${estimateGas}`);
|
|
@@ -1098,6 +1169,10 @@ var _Aggregator = class {
|
|
|
1098
1169
|
}
|
|
1099
1170
|
return tx;
|
|
1100
1171
|
}
|
|
1172
|
+
getRpcUrl(chain) {
|
|
1173
|
+
var _a;
|
|
1174
|
+
return ((_a = this.config.rpc[chain]) == null ? void 0 : _a.url) ?? "unknown";
|
|
1175
|
+
}
|
|
1101
1176
|
validateParams(params) {
|
|
1102
1177
|
if (!params.chain)
|
|
1103
1178
|
throw new Error("Chain not found");
|
|
@@ -1143,6 +1218,7 @@ Aggregator.DEFAULT_ETH_BUILDERS = {
|
|
|
1143
1218
|
tbuilder: "https://relay.tbuilder.xyz",
|
|
1144
1219
|
bobabuilder: "https://relay.boba-builder.com"
|
|
1145
1220
|
};
|
|
1221
|
+
Aggregator.TX_CONFIRM_TIMEOUT_MS = 12e4;
|
|
1146
1222
|
Aggregator.BUNDLE_POLL_INTERVAL_MS = 500;
|
|
1147
1223
|
Aggregator.BUNDLE_INCLUSION_TIMEOUT_MS = 3e4;
|
|
1148
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;
|