hermes-swap 0.6.9 → 0.6.10
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 +149 -41
- package/dist/cjs/aggregator.d.ts +2 -0
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/types.d.ts +8 -0
- package/dist/esm/aggregator.d.ts +2 -0
- package/dist/esm/aggregator.mjs +289 -235
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/types.d.ts +8 -0
- package/package.json +1 -1
package/dist/cjs/aggregator.cjs
CHANGED
|
@@ -90,6 +90,20 @@ var _Aggregator = class {
|
|
|
90
90
|
return "unknown";
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
+
emitTrace(txReq, chain, level, stage, message) {
|
|
94
|
+
var _a;
|
|
95
|
+
(_a = txReq == null ? void 0 : txReq.trace) == null ? void 0 : _a.call(txReq, {
|
|
96
|
+
ts: Date.now(),
|
|
97
|
+
chain,
|
|
98
|
+
level,
|
|
99
|
+
stage,
|
|
100
|
+
message
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
trace(chain, txReq, level, stage, message) {
|
|
104
|
+
_Aggregator.traceLog(chain, level, message);
|
|
105
|
+
this.emitTrace(txReq, chain, level, stage, message);
|
|
106
|
+
}
|
|
93
107
|
getAggregator(chain) {
|
|
94
108
|
if (!this.aggregatorMap.has(chain)) {
|
|
95
109
|
throw new Error(`Aggregator not found for chain: ${chain}`);
|
|
@@ -311,10 +325,13 @@ var _Aggregator = class {
|
|
|
311
325
|
}
|
|
312
326
|
async swapAndBridge(params, txReq = {}) {
|
|
313
327
|
var _a, _b;
|
|
328
|
+
const traceReq = txReq;
|
|
314
329
|
const useBundle = this.shouldUseBundle(params.chain, txReq);
|
|
315
|
-
|
|
330
|
+
this.trace(
|
|
316
331
|
params.chain,
|
|
332
|
+
traceReq,
|
|
317
333
|
"log",
|
|
334
|
+
"hermes-swapAndBridge-开始",
|
|
318
335
|
`swapAndBridge开始, user=${params.user}, amountInWeis=[${params.amountInWeis.join(",")}], bridgeType=${params.bridgeType}, destChain=${params.destChain}, useBundle=${useBundle}`
|
|
319
336
|
);
|
|
320
337
|
const startTs = Date.now();
|
|
@@ -357,14 +374,26 @@ var _Aggregator = class {
|
|
|
357
374
|
const { gasLimit: _ignore, ...estimationOverrides } = txReq;
|
|
358
375
|
const args = [params.user, params.amountInWeis, swapParamsList, params.minAmountOutLists, bridgeArgs, params.totalMinAmountOut];
|
|
359
376
|
try {
|
|
377
|
+
this.trace(params.chain, traceReq, "log", "hermes-swapAndBridge-estimateGas-开始", "swapAndBridge estimateGas 开始");
|
|
360
378
|
estimateGas = await aggregator.multiSwapAndBridge.estimateGas(...args, estimationOverrides);
|
|
379
|
+
this.trace(params.chain, traceReq, "log", "hermes-swapAndBridge-estimateGas-完成", `swapAndBridge estimateGas 完成, estimateGas=${estimateGas}`);
|
|
361
380
|
} catch (error) {
|
|
362
|
-
|
|
381
|
+
this.trace(params.chain, traceReq, "error", "hermes-swapAndBridge-estimateGas-失败", `swapAndBridge estimateGas失败, rpcUrl=${this.getRpcUrl(params.chain)}, error=${error}`);
|
|
363
382
|
throw error;
|
|
364
383
|
}
|
|
365
384
|
txReq = this.resolveGasLimit(txReq, estimateGas);
|
|
385
|
+
this.trace(params.chain, traceReq, "log", "hermes-resolveNonce-开始", "swapAndBridge resolveNonce 开始");
|
|
366
386
|
txReq = await this.resolveNonce(wallet.provider, wallet.address, txReq);
|
|
387
|
+
this.trace(params.chain, traceReq, "log", "hermes-resolveNonce-完成", `swapAndBridge resolveNonce 完成, nonce=${txReq.nonce}`);
|
|
388
|
+
this.trace(params.chain, traceReq, "log", "hermes-resolvePricing-开始", "swapAndBridge resolvePricing 开始");
|
|
367
389
|
txReq = await this.resolvePricing(wallet.provider, txReq);
|
|
390
|
+
this.trace(
|
|
391
|
+
params.chain,
|
|
392
|
+
traceReq,
|
|
393
|
+
"log",
|
|
394
|
+
"hermes-resolvePricing-完成",
|
|
395
|
+
`swapAndBridge resolvePricing 完成, gasPrice=${txReq.gasPrice ?? "n/a"}, maxFeePerGas=${txReq.maxFeePerGas ?? "n/a"}, maxPriorityFeePerGas=${txReq.maxPriorityFeePerGas ?? "n/a"}`
|
|
396
|
+
);
|
|
368
397
|
const iface = new import_ethers.ethers.Interface(import_aggregator.default);
|
|
369
398
|
let receipt;
|
|
370
399
|
if (useBundle) {
|
|
@@ -373,7 +402,7 @@ var _Aggregator = class {
|
|
|
373
402
|
receipt: flashbotsReceipt,
|
|
374
403
|
txHash: bundleTxHash,
|
|
375
404
|
targetBlocks
|
|
376
|
-
} = await this.submitBundleTx(params.chain, wallet, txReq, aggregatorAddress, calldata, txReq.value ?? 0n, bundleBlockCount);
|
|
405
|
+
} = await this.submitBundleTx(params.chain, wallet, txReq, aggregatorAddress, calldata, txReq.value ?? 0n, bundleBlockCount, traceReq);
|
|
377
406
|
txHash = bundleTxHash;
|
|
378
407
|
if (!flashbotsReceipt) {
|
|
379
408
|
throw new import_types.BundleNotIncludedError(`Bundle 未在目标区块上链, txHash=${bundleTxHash}, targetBlocks=[${targetBlocks.join(",")}]`, bundleTxHash);
|
|
@@ -383,7 +412,7 @@ var _Aggregator = class {
|
|
|
383
412
|
}
|
|
384
413
|
receipt = flashbotsReceipt;
|
|
385
414
|
} else {
|
|
386
|
-
receipt = await this.sendContractTx(params.chain, aggregator, "multiSwapAndBridge", args, txReq);
|
|
415
|
+
receipt = await this.sendContractTx(params.chain, aggregator, "multiSwapAndBridge", args, txReq, traceReq);
|
|
387
416
|
txHash = receipt.hash;
|
|
388
417
|
}
|
|
389
418
|
let receiptUser = null;
|
|
@@ -411,7 +440,13 @@ var _Aggregator = class {
|
|
|
411
440
|
const fromTokenAddress = ((_a = pathStart == null ? void 0 : pathStart[0]) == null ? void 0 : _a.fromCoinAddress) ?? "";
|
|
412
441
|
const toTokenAddress = ((_b = pathEnd == null ? void 0 : pathEnd[pathEnd.length - 1]) == null ? void 0 : _b.toCoinAddress) ?? "";
|
|
413
442
|
const totalAmountInFromEvent = amountInList.reduce((sum, amount) => sum + amount, 0n);
|
|
414
|
-
|
|
443
|
+
this.trace(
|
|
444
|
+
params.chain,
|
|
445
|
+
traceReq,
|
|
446
|
+
"log",
|
|
447
|
+
"hermes-swapAndBridge-完成",
|
|
448
|
+
`swapAndBridge完成, txHash=${receipt.hash}, amountOut=${amountOut}, useBundle=${useBundle}, 总耗时=${Date.now() - startTs}ms`
|
|
449
|
+
);
|
|
415
450
|
return {
|
|
416
451
|
hash: receipt.hash,
|
|
417
452
|
from: receipt.from,
|
|
@@ -420,14 +455,27 @@ var _Aggregator = class {
|
|
|
420
455
|
receipt
|
|
421
456
|
};
|
|
422
457
|
} catch (error) {
|
|
423
|
-
|
|
458
|
+
this.trace(
|
|
459
|
+
params.chain,
|
|
460
|
+
traceReq,
|
|
461
|
+
"error",
|
|
462
|
+
"hermes-swapAndBridge-异常",
|
|
463
|
+
`swapAndBridge异常, rpcUrl=${this.getRpcUrl(params.chain)}, txHash=${txHash ?? "N/A"}, 总耗时=${Date.now() - startTs}ms, error=${error}`
|
|
464
|
+
);
|
|
424
465
|
throw error;
|
|
425
466
|
}
|
|
426
467
|
}
|
|
427
468
|
async multiSwap(params, txReq = {}) {
|
|
428
469
|
var _a;
|
|
470
|
+
const traceReq = txReq;
|
|
429
471
|
const useBundle = this.shouldUseBundle(params.chain, txReq);
|
|
430
|
-
|
|
472
|
+
this.trace(
|
|
473
|
+
params.chain,
|
|
474
|
+
traceReq,
|
|
475
|
+
"log",
|
|
476
|
+
"hermes-multiSwap-开始",
|
|
477
|
+
`multiSwap开始, user=${params.user}, pathsCount=${params.paths.length}, amountInWeis=[${params.amountInWeis.join(",")}], useBundle=${useBundle}`
|
|
478
|
+
);
|
|
431
479
|
const startTs = Date.now();
|
|
432
480
|
let txHash;
|
|
433
481
|
try {
|
|
@@ -469,14 +517,26 @@ var _Aggregator = class {
|
|
|
469
517
|
let estimateGas;
|
|
470
518
|
const { gasLimit: _ignore, ...estimationOverrides } = txReq;
|
|
471
519
|
try {
|
|
520
|
+
this.trace(params.chain, traceReq, "log", "hermes-multiSwap-estimateGas-开始", "multiSwap estimateGas 开始");
|
|
472
521
|
estimateGas = await aggregator.multiSwap.estimateGas(params.user, params.amountInWeis, swapParamsList, params.minAmountOutLists, params.totalMinAmountOut, estimationOverrides);
|
|
522
|
+
this.trace(params.chain, traceReq, "log", "hermes-multiSwap-estimateGas-完成", `multiSwap estimateGas 完成, estimateGas=${estimateGas}`);
|
|
473
523
|
} catch (error) {
|
|
474
|
-
|
|
524
|
+
this.trace(params.chain, traceReq, "error", "hermes-multiSwap-estimateGas-失败", `multiSwap estimateGas失败, rpcUrl=${this.getRpcUrl(params.chain)}, error=${error}`);
|
|
475
525
|
throw error;
|
|
476
526
|
}
|
|
477
527
|
txReq = this.resolveGasLimit(txReq, estimateGas);
|
|
528
|
+
this.trace(params.chain, traceReq, "log", "hermes-resolveNonce-开始", "multiSwap resolveNonce 开始");
|
|
478
529
|
txReq = await this.resolveNonce(wallet.provider, wallet.address, txReq);
|
|
530
|
+
this.trace(params.chain, traceReq, "log", "hermes-resolveNonce-完成", `multiSwap resolveNonce 完成, nonce=${txReq.nonce}`);
|
|
531
|
+
this.trace(params.chain, traceReq, "log", "hermes-resolvePricing-开始", "multiSwap resolvePricing 开始");
|
|
479
532
|
txReq = await this.resolvePricing(wallet.provider, txReq);
|
|
533
|
+
this.trace(
|
|
534
|
+
params.chain,
|
|
535
|
+
traceReq,
|
|
536
|
+
"log",
|
|
537
|
+
"hermes-resolvePricing-完成",
|
|
538
|
+
`multiSwap resolvePricing 完成, gasPrice=${txReq.gasPrice ?? "n/a"}, maxFeePerGas=${txReq.maxFeePerGas ?? "n/a"}, maxPriorityFeePerGas=${txReq.maxPriorityFeePerGas ?? "n/a"}`
|
|
539
|
+
);
|
|
480
540
|
const iface = new import_ethers.ethers.Interface(import_aggregator.default);
|
|
481
541
|
let receipt;
|
|
482
542
|
if (useBundle) {
|
|
@@ -485,7 +545,7 @@ var _Aggregator = class {
|
|
|
485
545
|
receipt: flashbotsReceipt,
|
|
486
546
|
txHash: bundleTxHash,
|
|
487
547
|
targetBlocks
|
|
488
|
-
} = await this.submitBundleTx(params.chain, wallet, txReq, aggregatorAddress, calldata, txReq.value ?? 0n, bundleBlockCount);
|
|
548
|
+
} = await this.submitBundleTx(params.chain, wallet, txReq, aggregatorAddress, calldata, txReq.value ?? 0n, bundleBlockCount, traceReq);
|
|
489
549
|
txHash = bundleTxHash;
|
|
490
550
|
if (!flashbotsReceipt) {
|
|
491
551
|
throw new import_types.BundleNotIncludedError(`Bundle 未在目标区块上链, txHash=${bundleTxHash}, targetBlocks=[${targetBlocks.join(",")}]`, bundleTxHash);
|
|
@@ -495,7 +555,7 @@ var _Aggregator = class {
|
|
|
495
555
|
}
|
|
496
556
|
receipt = flashbotsReceipt;
|
|
497
557
|
} else {
|
|
498
|
-
receipt = await this.sendContractTx(params.chain, aggregator, "multiSwap", [params.user, params.amountInWeis, swapParamsList, params.minAmountOutLists, params.totalMinAmountOut], txReq);
|
|
558
|
+
receipt = await this.sendContractTx(params.chain, aggregator, "multiSwap", [params.user, params.amountInWeis, swapParamsList, params.minAmountOutLists, params.totalMinAmountOut], txReq, traceReq);
|
|
499
559
|
txHash = receipt.hash;
|
|
500
560
|
}
|
|
501
561
|
let amountOutList = null;
|
|
@@ -513,7 +573,13 @@ var _Aggregator = class {
|
|
|
513
573
|
}
|
|
514
574
|
if (!amountOutList)
|
|
515
575
|
throw new Error(`MultiSwapped event not found: ${receipt.hash}`);
|
|
516
|
-
|
|
576
|
+
this.trace(
|
|
577
|
+
params.chain,
|
|
578
|
+
traceReq,
|
|
579
|
+
"log",
|
|
580
|
+
"hermes-multiSwap-完成",
|
|
581
|
+
`multiSwap完成, txHash=${receipt.hash}, amountOutList=[${amountOutList.join(",")}], useBundle=${useBundle}, 总耗时=${Date.now() - startTs}ms`
|
|
582
|
+
);
|
|
517
583
|
return {
|
|
518
584
|
hash: receipt.hash,
|
|
519
585
|
from: receipt.from,
|
|
@@ -531,7 +597,13 @@ var _Aggregator = class {
|
|
|
531
597
|
receipt
|
|
532
598
|
};
|
|
533
599
|
} catch (error) {
|
|
534
|
-
|
|
600
|
+
this.trace(
|
|
601
|
+
params.chain,
|
|
602
|
+
traceReq,
|
|
603
|
+
"error",
|
|
604
|
+
"hermes-multiSwap-异常",
|
|
605
|
+
`multiSwap异常, rpcUrl=${this.getRpcUrl(params.chain)}, txHash=${txHash ?? "N/A"}, 总耗时=${Date.now() - startTs}ms, error=${error}`
|
|
606
|
+
);
|
|
535
607
|
throw error;
|
|
536
608
|
}
|
|
537
609
|
}
|
|
@@ -1030,22 +1102,22 @@ var _Aggregator = class {
|
|
|
1030
1102
|
);
|
|
1031
1103
|
});
|
|
1032
1104
|
}
|
|
1033
|
-
async sendSignedTxToChannels(chain, signedTx, txHash, channels) {
|
|
1105
|
+
async sendSignedTxToChannels(chain, signedTx, txHash, channels, traceReq) {
|
|
1034
1106
|
const results = await Promise.all(
|
|
1035
1107
|
channels.map(async ({ label, send }) => {
|
|
1036
1108
|
var _a, _b, _c, _d, _e;
|
|
1037
1109
|
const sendTs = Date.now();
|
|
1038
1110
|
try {
|
|
1039
1111
|
await send();
|
|
1040
|
-
|
|
1112
|
+
this.trace(chain, traceReq, "log", "hermes-broadcast-channel-成功", `广播${label} OK, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
|
|
1041
1113
|
return { label, ok: true };
|
|
1042
1114
|
} catch (err) {
|
|
1043
1115
|
const msg = ((_c = (_b = (_a = err == null ? void 0 : err.response) == null ? void 0 : _a.data) == null ? void 0 : _b.error) == null ? void 0 : _c.message) ?? ((_e = (_d = err == null ? void 0 : err.response) == null ? void 0 : _d.data) == null ? void 0 : _e.message) ?? (err == null ? void 0 : err.message) ?? String(err);
|
|
1044
1116
|
if (_Aggregator.isBenignBroadcastError(msg)) {
|
|
1045
|
-
|
|
1117
|
+
this.trace(chain, traceReq, "log", "hermes-broadcast-channel-已存在", `广播${label} already-known, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
|
|
1046
1118
|
return { label, ok: true };
|
|
1047
1119
|
}
|
|
1048
|
-
|
|
1120
|
+
this.trace(chain, traceReq, "warn", "hermes-broadcast-channel-失败", `广播${label} 失败: ${msg}, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
|
|
1049
1121
|
return { label, ok: false, msg };
|
|
1050
1122
|
}
|
|
1051
1123
|
})
|
|
@@ -1056,7 +1128,7 @@ var _Aggregator = class {
|
|
|
1056
1128
|
const detail = results.map((result) => `${result.label}: ${result.msg ?? "unknown error"}`).join("; ");
|
|
1057
1129
|
throw new Error(`All broadcast channels failed for ${txHash}: ${detail}`);
|
|
1058
1130
|
}
|
|
1059
|
-
raceForReceipt(chain, txHash, providers, ownedProviders = [], timeoutMs = _Aggregator.TX_CONFIRM_TIMEOUT_MS) {
|
|
1131
|
+
raceForReceipt(chain, txHash, providers, ownedProviders = [], timeoutMs = _Aggregator.TX_CONFIRM_TIMEOUT_MS, traceReq) {
|
|
1060
1132
|
return new Promise((resolve, reject) => {
|
|
1061
1133
|
let settled = false;
|
|
1062
1134
|
const blockHandlers = [];
|
|
@@ -1077,7 +1149,7 @@ var _Aggregator = class {
|
|
|
1077
1149
|
settled = true;
|
|
1078
1150
|
clearTimeout(timer);
|
|
1079
1151
|
cleanup();
|
|
1080
|
-
|
|
1152
|
+
this.trace(chain, traceReq, "log", "hermes-raceForReceipt-命中receipt", `${label} 先查到receipt, txHash=${txHash}, block=${receipt.blockNumber}`);
|
|
1081
1153
|
resolve(receipt);
|
|
1082
1154
|
};
|
|
1083
1155
|
const checkReceipt = (provider, label) => {
|
|
@@ -1103,6 +1175,7 @@ var _Aggregator = class {
|
|
|
1103
1175
|
return;
|
|
1104
1176
|
settled = true;
|
|
1105
1177
|
cleanup();
|
|
1178
|
+
this.trace(chain, traceReq, "warn", "hermes-raceForReceipt-超时", `Transaction not confirmed within ${timeoutMs}ms: ${txHash}`);
|
|
1106
1179
|
reject(new Error(`Transaction not confirmed within ${timeoutMs}ms: ${txHash}`));
|
|
1107
1180
|
}, timeoutMs);
|
|
1108
1181
|
});
|
|
@@ -1123,26 +1196,35 @@ var _Aggregator = class {
|
|
|
1123
1196
|
}
|
|
1124
1197
|
};
|
|
1125
1198
|
}
|
|
1126
|
-
async sendContractTx(chain, contract, method, args, txReq) {
|
|
1199
|
+
async sendContractTx(chain, contract, method, args, txReq, traceReq) {
|
|
1127
1200
|
const extraUrls = this.broadcastRpcsMap.get(chain);
|
|
1128
1201
|
const hasSequencer = _Aggregator.SEQUENCER_CHAINS.has(chain) && this.sequencerRpcsMap.has(chain);
|
|
1129
1202
|
if (!extraUrls || extraUrls.length === 0) {
|
|
1130
1203
|
if (!hasSequencer) {
|
|
1131
|
-
|
|
1204
|
+
this.trace(chain, traceReq, "log", "hermes-sendContractTx-发出前", `渠道=单RPC直发, method=${method}, nonce=${txReq.nonce}, gasLimit=${txReq.gasLimit}`);
|
|
1132
1205
|
const sendTs = Date.now();
|
|
1206
|
+
this.trace(chain, traceReq, "log", "hermes-sendContractTx-RPC发送前", `单RPC准备发送, method=${method}`);
|
|
1133
1207
|
const txResponse = await contract[method](...args, txReq);
|
|
1134
|
-
|
|
1208
|
+
this.trace(chain, traceReq, "log", "hermes-sendContractTx-RPC已发送", `单RPC已发送, txHash=${txResponse.hash}, 耗时=${Date.now() - sendTs}ms`);
|
|
1209
|
+
this.trace(chain, traceReq, "log", "hermes-sendContractTx-等待确认", `单RPC开始等待上链确认, txHash=${txResponse.hash}`);
|
|
1135
1210
|
const receipt3 = await txResponse.wait();
|
|
1136
1211
|
const singleProvider = this.providerClient.getProvider(chain);
|
|
1137
1212
|
const blockTs3 = await this.getBlockTimestampStr(singleProvider, receipt3.blockNumber);
|
|
1138
|
-
|
|
1213
|
+
this.trace(
|
|
1214
|
+
chain,
|
|
1215
|
+
traceReq,
|
|
1216
|
+
"log",
|
|
1217
|
+
"hermes-sendContractTx-确认完成",
|
|
1218
|
+
`单RPC上链确认, txHash=${receipt3.hash}, blockNumber=${receipt3.blockNumber}, 出块时间=${blockTs3}, gasUsed=${receipt3.gasUsed}, status=${receipt3.status}`
|
|
1219
|
+
);
|
|
1139
1220
|
if (receipt3.status === 0) {
|
|
1140
1221
|
throw new import_types.TransactionRevertedError(receipt3.hash, receipt3.gasUsed);
|
|
1141
1222
|
}
|
|
1142
1223
|
return receipt3;
|
|
1143
1224
|
}
|
|
1144
|
-
|
|
1225
|
+
this.trace(chain, traceReq, "log", "hermes-sendContractTx-发出前", `渠道=单RPC+排序器直发, method=${method}, nonce=${txReq.nonce}, gasLimit=${txReq.gasLimit}`);
|
|
1145
1226
|
const wallet2 = this.providerClient.getWallet(chain);
|
|
1227
|
+
this.trace(chain, traceReq, "log", "hermes-sendContractTx-构建交易", `开始 populateTransaction, method=${method}`);
|
|
1146
1228
|
const populated2 = await contract[method].populateTransaction(...args, txReq);
|
|
1147
1229
|
delete populated2.from;
|
|
1148
1230
|
const network2 = await wallet2.provider.getNetwork();
|
|
@@ -1150,18 +1232,21 @@ var _Aggregator = class {
|
|
|
1150
1232
|
const signedTx2 = await wallet2.signTransaction(populated2);
|
|
1151
1233
|
const txHash2 = import_ethers.ethers.keccak256(signedTx2);
|
|
1152
1234
|
const mainProvider2 = wallet2.provider;
|
|
1153
|
-
|
|
1235
|
+
this.trace(chain, traceReq, "log", "hermes-sendContractTx-RPC发送前", `单RPC+排序器并行广播, txHash=${txHash2}`);
|
|
1154
1236
|
const broadcastTs2 = Date.now();
|
|
1155
1237
|
const providers = [{ provider: mainProvider2, label: "RPC[0/主]" }];
|
|
1156
1238
|
const sequencerChannel2 = this.buildSequencerChannel(chain, signedTx2);
|
|
1157
1239
|
const channels2 = [...providers.map(({ provider, label }) => ({ label, send: () => provider.broadcastTransaction(signedTx2) })), ...sequencerChannel2 ? [sequencerChannel2] : []];
|
|
1158
|
-
const receiptPromise2 = this.raceForReceipt(chain, txHash2, providers);
|
|
1159
|
-
await this.sendSignedTxToChannels(chain, signedTx2, txHash2, channels2);
|
|
1240
|
+
const receiptPromise2 = this.raceForReceipt(chain, txHash2, providers, [], _Aggregator.TX_CONFIRM_TIMEOUT_MS, traceReq);
|
|
1241
|
+
await this.sendSignedTxToChannels(chain, signedTx2, txHash2, channels2, traceReq);
|
|
1242
|
+
this.trace(chain, traceReq, "log", "hermes-sendContractTx-等待确认", `并行广播后开始等待确认, txHash=${txHash2}`);
|
|
1160
1243
|
const receipt2 = await receiptPromise2;
|
|
1161
1244
|
const blockTs2 = await this.getBlockTimestampStr(mainProvider2, receipt2.blockNumber);
|
|
1162
|
-
|
|
1245
|
+
this.trace(
|
|
1163
1246
|
chain,
|
|
1247
|
+
traceReq,
|
|
1164
1248
|
"log",
|
|
1249
|
+
"hermes-sendContractTx-确认完成",
|
|
1165
1250
|
`单RPC+排序器上链确认, txHash=${receipt2.hash}, blockNumber=${receipt2.blockNumber}, 出块时间=${blockTs2}, gasUsed=${receipt2.gasUsed}, status=${receipt2.status}, 总耗时=${Date.now() - broadcastTs2}ms`
|
|
1166
1251
|
);
|
|
1167
1252
|
if (receipt2.status === 0) {
|
|
@@ -1184,21 +1269,27 @@ var _Aggregator = class {
|
|
|
1184
1269
|
}));
|
|
1185
1270
|
const allProviders = [{ provider: mainProvider, label: "RPC[0/主]" }, ...extraProviders];
|
|
1186
1271
|
const ownedProviders = extraProviders.map((e) => e.provider);
|
|
1187
|
-
|
|
1272
|
+
this.trace(
|
|
1188
1273
|
chain,
|
|
1274
|
+
traceReq,
|
|
1189
1275
|
"log",
|
|
1276
|
+
"hermes-sendContractTx-发出前",
|
|
1190
1277
|
`渠道=多RPC广播, method=${method}, nonce=${txReq.nonce}, gasLimit=${txReq.gasLimit}, 当前区块=${currentBlock}, 期望上链区块=${currentBlock + 1}, txHash=${txHash}, RPC数量=${allProviders.length}(主1+副${extraUrls.length})${hasSequencer ? ", +排序器直发" : ""}`
|
|
1191
1278
|
);
|
|
1192
1279
|
const broadcastTs = Date.now();
|
|
1193
1280
|
const sequencerChannel = this.buildSequencerChannel(chain, signedTx);
|
|
1194
1281
|
const channels = [...allProviders.map(({ provider, label }) => ({ label, send: () => provider.broadcastTransaction(signedTx) })), ...sequencerChannel ? [sequencerChannel] : []];
|
|
1195
|
-
const receiptPromise = this.raceForReceipt(chain, txHash, allProviders, ownedProviders);
|
|
1196
|
-
|
|
1282
|
+
const receiptPromise = this.raceForReceipt(chain, txHash, allProviders, ownedProviders, _Aggregator.TX_CONFIRM_TIMEOUT_MS, traceReq);
|
|
1283
|
+
this.trace(chain, traceReq, "log", "hermes-sendContractTx-RPC发送前", `多RPC广播准备发送, txHash=${txHash}`);
|
|
1284
|
+
await this.sendSignedTxToChannels(chain, signedTx, txHash, channels, traceReq);
|
|
1285
|
+
this.trace(chain, traceReq, "log", "hermes-sendContractTx-等待确认", `多RPC广播后开始等待确认, txHash=${txHash}`);
|
|
1197
1286
|
const receipt = await receiptPromise;
|
|
1198
1287
|
const blockTs = await this.getBlockTimestampStr(mainProvider, receipt.blockNumber);
|
|
1199
|
-
|
|
1288
|
+
this.trace(
|
|
1200
1289
|
chain,
|
|
1290
|
+
traceReq,
|
|
1201
1291
|
"log",
|
|
1292
|
+
"hermes-sendContractTx-确认完成",
|
|
1202
1293
|
`多RPC广播上链确认, txHash=${receipt.hash}, blockNumber=${receipt.blockNumber}, 出块时间=${blockTs}, gasUsed=${receipt.gasUsed}, status=${receipt.status}, 总耗时=${Date.now() - broadcastTs}ms`
|
|
1203
1294
|
);
|
|
1204
1295
|
if (receipt.status === 0) {
|
|
@@ -1206,7 +1297,7 @@ var _Aggregator = class {
|
|
|
1206
1297
|
}
|
|
1207
1298
|
return receipt;
|
|
1208
1299
|
}
|
|
1209
|
-
async submitBundleTx(chain, wallet, txReq, to, data, value, bundleBlockCount) {
|
|
1300
|
+
async submitBundleTx(chain, wallet, txReq, to, data, value, bundleBlockCount, traceReq) {
|
|
1210
1301
|
if (bundleBlockCount == null) {
|
|
1211
1302
|
bundleBlockCount = this.builderConfigMap.has(chain) ? 3 : 1;
|
|
1212
1303
|
}
|
|
@@ -1240,9 +1331,11 @@ var _Aggregator = class {
|
|
|
1240
1331
|
const targetBlocks = Array.from({ length: normalizedBundleBlockCount }, (_, i) => currentBlock + 1 + i);
|
|
1241
1332
|
const builderNames = Object.keys(builderCfg.urls);
|
|
1242
1333
|
const builderEntries = Object.entries(builderCfg.urls);
|
|
1243
|
-
|
|
1334
|
+
this.trace(
|
|
1244
1335
|
chain,
|
|
1336
|
+
traceReq,
|
|
1245
1337
|
"log",
|
|
1338
|
+
"hermes-submitBundleTx-发出前",
|
|
1246
1339
|
`渠道=Builder Bundle, authType=${builderCfg.authType}, method=${builderCfg.method ?? "eth_sendBundle"}, nonce=${txReq.nonce}, gasLimit=${txReq.gasLimit}, chainId=${network.chainId}, 当前区块=${currentBlock}, 目标区块=[${targetBlocks.join(",")}], builders=[${builderNames.join(",")}](${builderNames.length}个), txHash=${txHash}`
|
|
1247
1340
|
);
|
|
1248
1341
|
const sendBundleTs = Date.now();
|
|
@@ -1262,11 +1355,11 @@ var _Aggregator = class {
|
|
|
1262
1355
|
try {
|
|
1263
1356
|
const response = await import_axios.default.post(url, body, { headers, timeout: 3e3 });
|
|
1264
1357
|
totalSent++;
|
|
1265
|
-
|
|
1358
|
+
this.trace(chain, traceReq, "log", "hermes-submitBundleTx-builder-成功", `Builder[${name}] mev_sendBundle 发送成功, targetBlocks=[${targetBlocks.join(",")}], 耗时=${Date.now() - ts}ms, resp=${JSON.stringify(response.data)}`);
|
|
1266
1359
|
} catch (error) {
|
|
1267
1360
|
totalFailed++;
|
|
1268
1361
|
const msg = (error == null ? void 0 : error.response) ? JSON.stringify(error.response.data) : (error == null ? void 0 : error.message) ?? String(error);
|
|
1269
|
-
|
|
1362
|
+
this.trace(chain, traceReq, "error", "hermes-submitBundleTx-builder-失败", `Builder[${name}] mev_sendBundle 发送失败, targetBlocks=[${targetBlocks.join(",")}], 耗时=${Date.now() - ts}ms, error=${msg}`);
|
|
1270
1363
|
}
|
|
1271
1364
|
})()
|
|
1272
1365
|
];
|
|
@@ -1281,34 +1374,49 @@ var _Aggregator = class {
|
|
|
1281
1374
|
try {
|
|
1282
1375
|
const response = await import_axios.default.post(url, body, { headers, timeout: 3e3 });
|
|
1283
1376
|
totalSent++;
|
|
1284
|
-
|
|
1377
|
+
this.trace(chain, traceReq, "log", "hermes-submitBundleTx-builder-成功", `Builder[${name}] 发送成功, targetBlock=${block}, 耗时=${Date.now() - ts}ms, resp=${JSON.stringify(response.data)}`);
|
|
1285
1378
|
} catch (error) {
|
|
1286
1379
|
totalFailed++;
|
|
1287
1380
|
const msg = (error == null ? void 0 : error.response) ? JSON.stringify(error.response.data) : (error == null ? void 0 : error.message) ?? String(error);
|
|
1288
|
-
|
|
1381
|
+
this.trace(chain, traceReq, "error", "hermes-submitBundleTx-builder-失败", `Builder[${name}] 发送失败, targetBlock=${block}, 耗时=${Date.now() - ts}ms, error=${msg}`);
|
|
1289
1382
|
}
|
|
1290
1383
|
});
|
|
1291
1384
|
});
|
|
1292
1385
|
const abortController = new AbortController();
|
|
1293
1386
|
const inclusionPromise = this.waitForBundleInclusion(provider, txHash, targetBlocks, abortController.signal);
|
|
1294
1387
|
const waitTs = Date.now();
|
|
1388
|
+
this.trace(chain, traceReq, "log", "hermes-submitBundleTx-RPC发送前", `Bundle 请求开始发送, txHash=${txHash}, targetBlocks=[${targetBlocks.join(",")}]`);
|
|
1295
1389
|
const [receipt] = await Promise.all([
|
|
1296
1390
|
inclusionPromise,
|
|
1297
1391
|
Promise.all(fireAndForget).then(() => {
|
|
1298
|
-
|
|
1392
|
+
this.trace(
|
|
1393
|
+
chain,
|
|
1394
|
+
traceReq,
|
|
1395
|
+
"log",
|
|
1396
|
+
"hermes-submitBundleTx-RPC已发送",
|
|
1397
|
+
`Bundle发送完成, 成功=${totalSent}, 失败=${totalFailed}, 总请求=${fireAndForget.length}, 耗时=${Date.now() - sendBundleTs}ms, txHash=${txHash}`
|
|
1398
|
+
);
|
|
1299
1399
|
if (totalSent === 0)
|
|
1300
1400
|
abortController.abort();
|
|
1301
1401
|
})
|
|
1302
1402
|
]);
|
|
1303
1403
|
if (receipt) {
|
|
1304
1404
|
const blockTs = await this.getBlockTimestampStr(provider, receipt.blockNumber);
|
|
1305
|
-
|
|
1405
|
+
this.trace(
|
|
1306
1406
|
chain,
|
|
1407
|
+
traceReq,
|
|
1307
1408
|
"log",
|
|
1409
|
+
"hermes-submitBundleTx-确认完成",
|
|
1308
1410
|
`Bundle上链确认, txHash=${receipt.hash}, blockNumber=${receipt.blockNumber}, 出块时间=${blockTs}, gasUsed=${receipt.gasUsed}, 等待耗时=${Date.now() - waitTs}ms`
|
|
1309
1411
|
);
|
|
1310
1412
|
} else {
|
|
1311
|
-
|
|
1413
|
+
this.trace(
|
|
1414
|
+
chain,
|
|
1415
|
+
traceReq,
|
|
1416
|
+
"warn",
|
|
1417
|
+
"hermes-submitBundleTx-等待结束",
|
|
1418
|
+
`Bundle未在目标区块上链, txHash=${txHash}, 目标区块=[${targetBlocks.join(",")}], 等待耗时=${Date.now() - waitTs}ms`
|
|
1419
|
+
);
|
|
1312
1420
|
}
|
|
1313
1421
|
return { receipt, txHash, targetBlocks };
|
|
1314
1422
|
}
|
|
@@ -1410,7 +1518,7 @@ var _Aggregator = class {
|
|
|
1410
1518
|
}
|
|
1411
1519
|
stripCustomFields(txReq, chain) {
|
|
1412
1520
|
const defaultBlockCount = chain && this.builderConfigMap.has(chain) ? 3 : 1;
|
|
1413
|
-
const { useBundle, bundleBlockCount = defaultBlockCount, ...pureTxReq } = txReq;
|
|
1521
|
+
const { useBundle, bundleBlockCount = defaultBlockCount, trace, ...pureTxReq } = txReq;
|
|
1414
1522
|
return { pureTxReq, bundleBlockCount: this.normalizeBundleBlockCount(bundleBlockCount) };
|
|
1415
1523
|
}
|
|
1416
1524
|
normalizeBundleBlockCount(bundleBlockCount) {
|
package/dist/cjs/aggregator.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ declare class Aggregator {
|
|
|
16
16
|
private static traceLog;
|
|
17
17
|
private static formatBlockTimestamp;
|
|
18
18
|
private getBlockTimestampStr;
|
|
19
|
+
private emitTrace;
|
|
20
|
+
private trace;
|
|
19
21
|
private static readonly DEFAULT_ETH_BUILDERS;
|
|
20
22
|
private static readonly DEFAULT_SEQUENCER_RPC_BY_CHAIN;
|
|
21
23
|
private static readonly SEQUENCER_CHAINS;
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { HermesTxRequest, IBatchMultiSwapParams, IBatchExpectParams, ISwapByPathParams, IExpectSplitOrderParams, IExpectSplitOrderResp, IBridgeParams, IBatchReceipt, IMultiSwapParams, IBatchMultiSwapAndBridgeParams, ISwapAndBridgeParams, IReceipt, IConfig, IBuilderConfig, IExpectPayload, IRouterPath, SupportContracts, IExpectByPathParams, IHermesSignalResponse, IHermesSignalQuoteBestData, IHermesSignalRoute } from './types.js';
|
|
1
|
+
import type { HermesTxRequest, IHermesExecutionTrace, IBatchMultiSwapParams, IBatchExpectParams, ISwapByPathParams, IExpectSplitOrderParams, IExpectSplitOrderResp, IBridgeParams, IBatchReceipt, IMultiSwapParams, IBatchMultiSwapAndBridgeParams, ISwapAndBridgeParams, IReceipt, IConfig, IBuilderConfig, IExpectPayload, IRouterPath, SupportContracts, IExpectByPathParams, IHermesSignalResponse, IHermesSignalQuoteBestData, IHermesSignalRoute } from './types.js';
|
|
2
2
|
import { ChainNameEnum, AddressConst, DexType, BridgeType, IEstimateType, LayerZeroV1ChainIdMap, LayerZeroV1ChainNameMap, LayerZeroV2ChainIdMap, LayerZeroV2ChainNameMap } from './types.js';
|
|
3
3
|
import { TransactionRequest } from 'ethers';
|
|
4
|
-
export type { HermesTxRequest, IBatchMultiSwapAndBridgeParams, IExpectSplitOrderParams, IExpectSplitOrderResp, IMultiSwapParams, IBatchMultiSwapParams, IBatchExpectParams, IBatchReceipt, ISwapByPathParams as ISwapParams, IBridgeParams, ISwapAndBridgeParams, IReceipt, IConfig, IBuilderConfig, IExpectPayload, IRouterPath, SupportContracts, IHermesSignalResponse, IHermesSignalQuoteBestData, IHermesSignalRoute, };
|
|
4
|
+
export type { HermesTxRequest, IHermesExecutionTrace, IBatchMultiSwapAndBridgeParams, IExpectSplitOrderParams, IExpectSplitOrderResp, IMultiSwapParams, IBatchMultiSwapParams, IBatchExpectParams, IBatchReceipt, ISwapByPathParams as ISwapParams, IBridgeParams, ISwapAndBridgeParams, IReceipt, IConfig, IBuilderConfig, IExpectPayload, IRouterPath, SupportContracts, IHermesSignalResponse, IHermesSignalQuoteBestData, IHermesSignalRoute, };
|
|
5
5
|
import { BundleNotIncludedError, TransactionRevertedError } from './types.js';
|
|
6
6
|
export { ChainNameEnum, AddressConst, DexType, BridgeType, IEstimateType, LayerZeroV1ChainIdMap, LayerZeroV1ChainNameMap, LayerZeroV2ChainIdMap, LayerZeroV2ChainNameMap, BundleNotIncludedError, TransactionRevertedError };
|
|
7
7
|
declare class Hermes {
|
package/dist/cjs/types.d.ts
CHANGED
|
@@ -377,10 +377,18 @@ export interface IRpcConfig {
|
|
|
377
377
|
url: string;
|
|
378
378
|
privateKey?: string;
|
|
379
379
|
}
|
|
380
|
+
export interface IHermesExecutionTrace {
|
|
381
|
+
ts: number;
|
|
382
|
+
chain?: ChainNameEnum;
|
|
383
|
+
level: 'log' | 'warn' | 'error';
|
|
384
|
+
stage: string;
|
|
385
|
+
message: string;
|
|
386
|
+
}
|
|
380
387
|
export type HermesTxRequest = TransactionRequest & {
|
|
381
388
|
useBundle?: boolean;
|
|
382
389
|
/** 尝试的区块数量(1-3),默认1(即仅 +1 区块)。传2则尝试 +1/+2 区块,传3则尝试 +1/+2/+3 区块 */
|
|
383
390
|
bundleBlockCount?: number;
|
|
391
|
+
trace?: (event: IHermesExecutionTrace) => void;
|
|
384
392
|
};
|
|
385
393
|
export declare const AddressConst: {
|
|
386
394
|
weth: {
|
package/dist/esm/aggregator.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ declare class Aggregator {
|
|
|
16
16
|
private static traceLog;
|
|
17
17
|
private static formatBlockTimestamp;
|
|
18
18
|
private getBlockTimestampStr;
|
|
19
|
+
private emitTrace;
|
|
20
|
+
private trace;
|
|
19
21
|
private static readonly DEFAULT_ETH_BUILDERS;
|
|
20
22
|
private static readonly DEFAULT_SEQUENCER_RPC_BY_CHAIN;
|
|
21
23
|
private static readonly SEQUENCER_CHAINS;
|