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.
@@ -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
- _Aggregator.traceLog(
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
- _Aggregator.traceLog(params.chain, "error", `swapAndBridge estimateGas失败, rpcUrl=${this.getRpcUrl(params.chain)}, error=${error}`);
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
- _Aggregator.traceLog(params.chain, "log", `swapAndBridge完成, txHash=${receipt.hash}, amountOut=${amountOut}, useBundle=${useBundle}, 总耗时=${Date.now() - startTs}ms`);
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
- _Aggregator.traceLog(params.chain, "error", `swapAndBridge异常, rpcUrl=${this.getRpcUrl(params.chain)}, txHash=${txHash ?? "N/A"}, 总耗时=${Date.now() - startTs}ms, error=${error}`);
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
- _Aggregator.traceLog(params.chain, "log", `multiSwap开始, user=${params.user}, pathsCount=${params.paths.length}, amountInWeis=[${params.amountInWeis.join(",")}], useBundle=${useBundle}`);
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
- _Aggregator.traceLog(params.chain, "error", `multiSwap estimateGas失败, rpcUrl=${this.getRpcUrl(params.chain)}, error=${error}`);
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
- _Aggregator.traceLog(params.chain, "log", `multiSwap完成, txHash=${receipt.hash}, amountOutList=[${amountOutList.join(",")}], useBundle=${useBundle}, 总耗时=${Date.now() - startTs}ms`);
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
- _Aggregator.traceLog(params.chain, "error", `multiSwap异常, rpcUrl=${this.getRpcUrl(params.chain)}, txHash=${txHash ?? "N/A"}, 总耗时=${Date.now() - startTs}ms, error=${error}`);
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
- _Aggregator.traceLog(chain, "log", `广播${label} OK, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
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
- _Aggregator.traceLog(chain, "log", `广播${label} already-known, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
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
- _Aggregator.traceLog(chain, "warn", `广播${label} 失败: ${msg}, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
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
- _Aggregator.traceLog(chain, "log", `${label} 先查到receipt, txHash=${txHash}, block=${receipt.blockNumber}`);
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
- _Aggregator.traceLog(chain, "log", `渠道=单RPC直发, method=${method}, nonce=${txReq.nonce}, gasLimit=${txReq.gasLimit}`);
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
- _Aggregator.traceLog(chain, "log", `单RPC已发送, txHash=${txResponse.hash}, 耗时=${Date.now() - sendTs}ms`);
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
- _Aggregator.traceLog(chain, "log", `单RPC上链确认, txHash=${receipt3.hash}, blockNumber=${receipt3.blockNumber}, 出块时间=${blockTs3}, gasUsed=${receipt3.gasUsed}, status=${receipt3.status}`);
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
- _Aggregator.traceLog(chain, "log", `渠道=单RPC+排序器直发, method=${method}, nonce=${txReq.nonce}, gasLimit=${txReq.gasLimit}`);
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
- _Aggregator.traceLog(chain, "log", `单RPC+排序器并行广播, txHash=${txHash2}`);
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
- _Aggregator.traceLog(
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
- _Aggregator.traceLog(
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
- await this.sendSignedTxToChannels(chain, signedTx, txHash, channels);
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
- _Aggregator.traceLog(
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
- _Aggregator.traceLog(
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
- _Aggregator.traceLog(chain, "log", `Builder[${name}] mev_sendBundle 发送成功, targetBlocks=[${targetBlocks.join(",")}], 耗时=${Date.now() - ts}ms, resp=${JSON.stringify(response.data)}`);
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
- _Aggregator.traceLog(chain, "error", `Builder[${name}] mev_sendBundle 发送失败, targetBlocks=[${targetBlocks.join(",")}], 耗时=${Date.now() - ts}ms, error=${msg}`);
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
- _Aggregator.traceLog(chain, "log", `Builder[${name}] 发送成功, targetBlock=${block}, 耗时=${Date.now() - ts}ms, resp=${JSON.stringify(response.data)}`);
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
- _Aggregator.traceLog(chain, "error", `Builder[${name}] 发送失败, targetBlock=${block}, 耗时=${Date.now() - ts}ms, error=${msg}`);
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
- _Aggregator.traceLog(chain, "log", `Bundle发送完成, 成功=${totalSent}, 失败=${totalFailed}, 总请求=${fireAndForget.length}, 耗时=${Date.now() - sendBundleTs}ms, txHash=${txHash}`);
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
- _Aggregator.traceLog(
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
- _Aggregator.traceLog(chain, "warn", `Bundle未在目标区块上链, txHash=${txHash}, 目标区块=[${targetBlocks.join(",")}], 等待耗时=${Date.now() - waitTs}ms`);
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) {
@@ -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;
@@ -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 {
@@ -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: {
@@ -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;