hermes-swap 0.6.10 → 0.7.0

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.
@@ -132,6 +132,15 @@ var _Aggregator = class {
132
132
  }
133
133
  throw new Error(`No builder config for chain: ${chain}`);
134
134
  }
135
+ getDefaultBundleBlockCount(chain) {
136
+ if (!chain)
137
+ return 1;
138
+ if (this.builderConfigMap.has(chain))
139
+ return 3;
140
+ if (chain === import_types.ChainNameEnum.ETH && this.flashbotSigner)
141
+ return 3;
142
+ return 1;
143
+ }
135
144
  getSequencerRpcs(config) {
136
145
  const merged = {
137
146
  ..._Aggregator.DEFAULT_SEQUENCER_RPC_BY_CHAIN
@@ -175,6 +184,16 @@ var _Aggregator = class {
175
184
  ]
176
185
  };
177
186
  }
187
+ static getJsonRpcErrorMessage(data) {
188
+ var _a;
189
+ if (!(data == null ? void 0 : data.error))
190
+ return null;
191
+ if (typeof data.error === "string")
192
+ return data.error;
193
+ if (typeof ((_a = data.error) == null ? void 0 : _a.message) === "string")
194
+ return data.error.message;
195
+ return JSON.stringify(data.error);
196
+ }
178
197
  async sendBundle(chain, rawTxs, targetBlock, signer) {
179
198
  const builderCfg = this.getBuilderConfig(chain);
180
199
  const body = this.buildBundleRequestBody(builderCfg, rawTxs, targetBlock);
@@ -190,6 +209,14 @@ var _Aggregator = class {
190
209
  const ts = Date.now();
191
210
  try {
192
211
  const response = await import_axios.default.post(url, body, { headers });
212
+ const rpcErrorMessage = _Aggregator.getJsonRpcErrorMessage(response.data);
213
+ if (rpcErrorMessage) {
214
+ failed++;
215
+ const detail2 = `[FAIL] ${name}: ${rpcErrorMessage}`;
216
+ details.push(detail2);
217
+ _Aggregator.traceLog(chain, "error", `Builder[${name}] 发送失败, targetBlock=${targetBlock}, 耗时=${Date.now() - ts}ms, error=${rpcErrorMessage}, resp=${JSON.stringify(response.data)}`);
218
+ return;
219
+ }
193
220
  sent++;
194
221
  const detail = `[OK] ${name}`;
195
222
  details.push(detail);
@@ -555,7 +582,14 @@ var _Aggregator = class {
555
582
  }
556
583
  receipt = flashbotsReceipt;
557
584
  } else {
558
- receipt = await this.sendContractTx(params.chain, aggregator, "multiSwap", [params.user, params.amountInWeis, swapParamsList, params.minAmountOutLists, params.totalMinAmountOut], txReq, traceReq);
585
+ receipt = await this.sendContractTx(
586
+ params.chain,
587
+ aggregator,
588
+ "multiSwap",
589
+ [params.user, params.amountInWeis, swapParamsList, params.minAmountOutLists, params.totalMinAmountOut],
590
+ txReq,
591
+ traceReq
592
+ );
559
593
  txHash = receipt.hash;
560
594
  }
561
595
  let amountOutList = null;
@@ -971,9 +1005,12 @@ var _Aggregator = class {
971
1005
  const block = await provider.getBlock(blockNumber, true);
972
1006
  if (!block)
973
1007
  return false;
974
- if (block.transactions.some((hash) => hash === txHash))
975
- return true;
976
- return block.prefetchedTransactions.some((tx) => tx.hash === txHash);
1008
+ const normalizedHash = txHash.toLowerCase();
1009
+ const transactions = block.prefetchedTransactions ?? block.transactions;
1010
+ return transactions.some((tx) => {
1011
+ const hash = typeof tx === "string" ? tx : tx.hash;
1012
+ return (hash == null ? void 0 : hash.toLowerCase()) === normalizedHash;
1013
+ });
977
1014
  } catch {
978
1015
  return false;
979
1016
  }
@@ -1019,10 +1056,23 @@ var _Aggregator = class {
1019
1056
  cleanup();
1020
1057
  resolve(receipt);
1021
1058
  };
1059
+ const finishWithFallbackCheck = async () => {
1060
+ if (settled)
1061
+ return;
1062
+ try {
1063
+ const receipt = await provider.getTransactionReceipt(txHash);
1064
+ if (receipt && targetBlockSet.has(receipt.blockNumber)) {
1065
+ finish(receipt);
1066
+ return;
1067
+ }
1068
+ } catch {
1069
+ }
1070
+ finish(null);
1071
+ };
1022
1072
  const scheduleInspect = (fromBlock, toBlock) => {
1023
1073
  if (fromBlock > toBlock) {
1024
1074
  if (checkedBlocks.size === targetBlockSet.size && lastObservedBlock >= maxTargetBlock) {
1025
- finish(null);
1075
+ finishWithFallbackCheck();
1026
1076
  }
1027
1077
  return;
1028
1078
  }
@@ -1052,7 +1102,7 @@ var _Aggregator = class {
1052
1102
  return;
1053
1103
  }
1054
1104
  if (checkedBlocks.size === targetBlockSet.size && lastObservedBlock >= maxTargetBlock) {
1055
- finish(null);
1105
+ finishWithFallbackCheck();
1056
1106
  }
1057
1107
  };
1058
1108
  const onBlock = (blockNumber) => {
@@ -1065,7 +1115,7 @@ var _Aggregator = class {
1065
1115
  }
1066
1116
  if (fromBlock > toBlock) {
1067
1117
  if (checkedBlocks.size === targetBlockSet.size && lastObservedBlock >= maxTargetBlock) {
1068
- finish(null);
1118
+ finishWithFallbackCheck();
1069
1119
  }
1070
1120
  return;
1071
1121
  }
@@ -1083,7 +1133,8 @@ var _Aggregator = class {
1083
1133
  const toBlock = Math.min(latestBlock, maxTargetBlock);
1084
1134
  scheduleInspect(sortedTargetBlocks[0], toBlock);
1085
1135
  await inspectionChain;
1086
- finish(null);
1136
+ if (!settled)
1137
+ await finishWithFallbackCheck();
1087
1138
  }, _Aggregator.BUNDLE_INCLUSION_TIMEOUT_MS);
1088
1139
  provider.on("block", onBlock);
1089
1140
  provider.getBlockNumber().then(
@@ -1102,31 +1153,66 @@ var _Aggregator = class {
1102
1153
  );
1103
1154
  });
1104
1155
  }
1105
- async sendSignedTxToChannels(chain, signedTx, txHash, channels, traceReq) {
1106
- const results = await Promise.all(
1107
- channels.map(async ({ label, send }) => {
1108
- var _a, _b, _c, _d, _e;
1156
+ async sendSignedTxToChannels(chain, signedTx, txHash, channels, traceReq, abortSignal) {
1157
+ return await new Promise((resolve, reject) => {
1158
+ let settled = false;
1159
+ let finishedCount = 0;
1160
+ const failures = [];
1161
+ const cleanup = () => {
1162
+ abortSignal == null ? void 0 : abortSignal.removeEventListener("abort", onAbort);
1163
+ };
1164
+ const finishResolve = () => {
1165
+ if (settled)
1166
+ return;
1167
+ settled = true;
1168
+ cleanup();
1169
+ resolve();
1170
+ };
1171
+ const finishReject = () => {
1172
+ if (settled)
1173
+ return;
1174
+ settled = true;
1175
+ cleanup();
1176
+ const detail = failures.map((result) => `${result.label}: ${result.msg ?? "unknown error"}`).join("; ");
1177
+ reject(new Error(`All broadcast channels failed for ${txHash}: ${detail}`));
1178
+ };
1179
+ const onAbort = () => {
1180
+ finishResolve();
1181
+ };
1182
+ if (abortSignal == null ? void 0 : abortSignal.aborted) {
1183
+ finishResolve();
1184
+ return;
1185
+ }
1186
+ abortSignal == null ? void 0 : abortSignal.addEventListener("abort", onAbort, { once: true });
1187
+ for (const { label, send } of channels) {
1109
1188
  const sendTs = Date.now();
1110
- try {
1111
- await send();
1112
- this.trace(chain, traceReq, "log", "hermes-broadcast-channel-成功", `广播${label} OK, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
1113
- return { label, ok: true };
1114
- } catch (err) {
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);
1116
- if (_Aggregator.isBenignBroadcastError(msg)) {
1117
- this.trace(chain, traceReq, "log", "hermes-broadcast-channel-已存在", `广播${label} already-known, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
1118
- return { label, ok: true };
1189
+ send(abortSignal).then(
1190
+ () => {
1191
+ if (settled || (abortSignal == null ? void 0 : abortSignal.aborted))
1192
+ return;
1193
+ this.trace(chain, traceReq, "log", "hermes-broadcast-channel-成功", `广播${label} OK, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
1194
+ finishResolve();
1195
+ },
1196
+ (err) => {
1197
+ var _a, _b, _c, _d, _e;
1198
+ if (settled || (abortSignal == null ? void 0 : abortSignal.aborted))
1199
+ return;
1200
+ 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);
1201
+ if (_Aggregator.isBenignBroadcastError(msg)) {
1202
+ this.trace(chain, traceReq, "log", "hermes-broadcast-channel-已存在", `广播${label} already-known, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
1203
+ finishResolve();
1204
+ return;
1205
+ }
1206
+ this.trace(chain, traceReq, "warn", "hermes-broadcast-channel-失败", `广播${label} 失败: ${msg}, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
1207
+ failures.push({ label, msg });
1208
+ finishedCount += 1;
1209
+ if (finishedCount === channels.length) {
1210
+ finishReject();
1211
+ }
1119
1212
  }
1120
- this.trace(chain, traceReq, "warn", "hermes-broadcast-channel-失败", `广播${label} 失败: ${msg}, txHash=${txHash}, 耗时=${Date.now() - sendTs}ms`);
1121
- return { label, ok: false, msg };
1122
- }
1123
- })
1124
- );
1125
- if (results.some((result) => result.ok)) {
1126
- return;
1127
- }
1128
- const detail = results.map((result) => `${result.label}: ${result.msg ?? "unknown error"}`).join("; ");
1129
- throw new Error(`All broadcast channels failed for ${txHash}: ${detail}`);
1213
+ );
1214
+ }
1215
+ });
1130
1216
  }
1131
1217
  raceForReceipt(chain, txHash, providers, ownedProviders = [], timeoutMs = _Aggregator.TX_CONFIRM_TIMEOUT_MS, traceReq) {
1132
1218
  return new Promise((resolve, reject) => {
@@ -1186,9 +1272,9 @@ var _Aggregator = class {
1186
1272
  return null;
1187
1273
  return {
1188
1274
  label: `Sequencer[${new URL(sequencerUrl).hostname}]`,
1189
- send: async () => {
1275
+ send: async (signal) => {
1190
1276
  var _a;
1191
- const resp = await import_axios.default.post(sequencerUrl, { jsonrpc: "2.0", id: 1, method: "eth_sendRawTransaction", params: [signedTx] }, { timeout: 5e3 });
1277
+ const resp = await import_axios.default.post(sequencerUrl, { jsonrpc: "2.0", id: 1, method: "eth_sendRawTransaction", params: [signedTx] }, { timeout: 5e3, signal });
1192
1278
  if ((_a = resp.data) == null ? void 0 : _a.error) {
1193
1279
  throw new Error(resp.data.error.message ?? JSON.stringify(resp.data.error));
1194
1280
  }
@@ -1237,10 +1323,17 @@ var _Aggregator = class {
1237
1323
  const providers = [{ provider: mainProvider2, label: "RPC[0/主]" }];
1238
1324
  const sequencerChannel2 = this.buildSequencerChannel(chain, signedTx2);
1239
1325
  const channels2 = [...providers.map(({ provider, label }) => ({ label, send: () => provider.broadcastTransaction(signedTx2) })), ...sequencerChannel2 ? [sequencerChannel2] : []];
1240
- const receiptPromise2 = this.raceForReceipt(chain, txHash2, providers, [], _Aggregator.TX_CONFIRM_TIMEOUT_MS, traceReq);
1241
- await this.sendSignedTxToChannels(chain, signedTx2, txHash2, channels2, traceReq);
1326
+ const broadcastAbortController2 = new AbortController();
1327
+ const receiptPromise2 = this.raceForReceipt(chain, txHash2, providers, [], _Aggregator.TX_CONFIRM_TIMEOUT_MS, traceReq).finally(() => {
1328
+ broadcastAbortController2.abort();
1329
+ });
1330
+ const broadcastPromise2 = this.sendSignedTxToChannels(chain, signedTx2, txHash2, channels2, traceReq, broadcastAbortController2.signal);
1242
1331
  this.trace(chain, traceReq, "log", "hermes-sendContractTx-等待确认", `并行广播后开始等待确认, txHash=${txHash2}`);
1243
- const receipt2 = await receiptPromise2;
1332
+ const receipt2 = await Promise.race([
1333
+ receiptPromise2,
1334
+ broadcastPromise2.then(() => new Promise(() => {
1335
+ }))
1336
+ ]);
1244
1337
  const blockTs2 = await this.getBlockTimestampStr(mainProvider2, receipt2.blockNumber);
1245
1338
  this.trace(
1246
1339
  chain,
@@ -1279,11 +1372,18 @@ var _Aggregator = class {
1279
1372
  const broadcastTs = Date.now();
1280
1373
  const sequencerChannel = this.buildSequencerChannel(chain, signedTx);
1281
1374
  const channels = [...allProviders.map(({ provider, label }) => ({ label, send: () => provider.broadcastTransaction(signedTx) })), ...sequencerChannel ? [sequencerChannel] : []];
1282
- const receiptPromise = this.raceForReceipt(chain, txHash, allProviders, ownedProviders, _Aggregator.TX_CONFIRM_TIMEOUT_MS, traceReq);
1375
+ const broadcastAbortController = new AbortController();
1376
+ const receiptPromise = this.raceForReceipt(chain, txHash, allProviders, ownedProviders, _Aggregator.TX_CONFIRM_TIMEOUT_MS, traceReq).finally(() => {
1377
+ broadcastAbortController.abort();
1378
+ });
1379
+ const broadcastPromise = this.sendSignedTxToChannels(chain, signedTx, txHash, channels, traceReq, broadcastAbortController.signal);
1283
1380
  this.trace(chain, traceReq, "log", "hermes-sendContractTx-RPC发送前", `多RPC广播准备发送, txHash=${txHash}`);
1284
- await this.sendSignedTxToChannels(chain, signedTx, txHash, channels, traceReq);
1285
1381
  this.trace(chain, traceReq, "log", "hermes-sendContractTx-等待确认", `多RPC广播后开始等待确认, txHash=${txHash}`);
1286
- const receipt = await receiptPromise;
1382
+ const receipt = await Promise.race([
1383
+ receiptPromise,
1384
+ broadcastPromise.then(() => new Promise(() => {
1385
+ }))
1386
+ ]);
1287
1387
  const blockTs = await this.getBlockTimestampStr(mainProvider, receipt.blockNumber);
1288
1388
  this.trace(
1289
1389
  chain,
@@ -1299,7 +1399,7 @@ var _Aggregator = class {
1299
1399
  }
1300
1400
  async submitBundleTx(chain, wallet, txReq, to, data, value, bundleBlockCount, traceReq) {
1301
1401
  if (bundleBlockCount == null) {
1302
- bundleBlockCount = this.builderConfigMap.has(chain) ? 3 : 1;
1402
+ bundleBlockCount = this.getDefaultBundleBlockCount(chain);
1303
1403
  }
1304
1404
  const builderCfg = this.getBuilderConfig(chain);
1305
1405
  if (builderCfg.authType === "flashbots" && !this.flashbotSigner) {
@@ -1342,6 +1442,7 @@ var _Aggregator = class {
1342
1442
  let totalSent = 0;
1343
1443
  let totalFailed = 0;
1344
1444
  const signer = builderCfg.authType === "flashbots" ? this.flashbotSigner : void 0;
1445
+ const builderAbortController = new AbortController();
1345
1446
  const fireAndForget = builderEntries.flatMap(([name, url]) => {
1346
1447
  if (name === "flashbots" && builderCfg.authType === "flashbots" && signer) {
1347
1448
  return [
@@ -1353,13 +1454,43 @@ var _Aggregator = class {
1353
1454
  };
1354
1455
  const ts = Date.now();
1355
1456
  try {
1356
- const response = await import_axios.default.post(url, body, { headers, timeout: 3e3 });
1457
+ const response = await import_axios.default.post(url, body, { headers, timeout: 3e3, signal: builderAbortController.signal });
1458
+ if (builderAbortController.signal.aborted)
1459
+ return;
1460
+ const rpcErrorMessage = _Aggregator.getJsonRpcErrorMessage(response.data);
1461
+ if (rpcErrorMessage) {
1462
+ totalFailed++;
1463
+ this.trace(
1464
+ chain,
1465
+ traceReq,
1466
+ "error",
1467
+ "hermes-submitBundleTx-builder-失败",
1468
+ `Builder[${name}] mev_sendBundle 发送失败, targetBlocks=[${targetBlocks.join(",")}], 耗时=${Date.now() - ts}ms, error=${rpcErrorMessage}, resp=${JSON.stringify(response.data)}`
1469
+ );
1470
+ return;
1471
+ }
1357
1472
  totalSent++;
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)}`);
1473
+ if (builderAbortController.signal.aborted)
1474
+ return;
1475
+ this.trace(
1476
+ chain,
1477
+ traceReq,
1478
+ "log",
1479
+ "hermes-submitBundleTx-builder-成功",
1480
+ `Builder[${name}] mev_sendBundle 发送成功, targetBlocks=[${targetBlocks.join(",")}], 耗时=${Date.now() - ts}ms, resp=${JSON.stringify(response.data)}`
1481
+ );
1359
1482
  } catch (error) {
1483
+ if (builderAbortController.signal.aborted)
1484
+ return;
1360
1485
  totalFailed++;
1361
1486
  const msg = (error == null ? void 0 : error.response) ? JSON.stringify(error.response.data) : (error == null ? void 0 : error.message) ?? String(error);
1362
- this.trace(chain, traceReq, "error", "hermes-submitBundleTx-builder-失败", `Builder[${name}] mev_sendBundle 发送失败, targetBlocks=[${targetBlocks.join(",")}], 耗时=${Date.now() - ts}ms, error=${msg}`);
1487
+ this.trace(
1488
+ chain,
1489
+ traceReq,
1490
+ "error",
1491
+ "hermes-submitBundleTx-builder-失败",
1492
+ `Builder[${name}] mev_sendBundle 发送失败, targetBlocks=[${targetBlocks.join(",")}], 耗时=${Date.now() - ts}ms, error=${msg}`
1493
+ );
1363
1494
  }
1364
1495
  })()
1365
1496
  ];
@@ -1372,34 +1503,63 @@ var _Aggregator = class {
1372
1503
  }
1373
1504
  const ts = Date.now();
1374
1505
  try {
1375
- const response = await import_axios.default.post(url, body, { headers, timeout: 3e3 });
1506
+ const response = await import_axios.default.post(url, body, { headers, timeout: 3e3, signal: builderAbortController.signal });
1507
+ if (builderAbortController.signal.aborted)
1508
+ return;
1509
+ const rpcErrorMessage = _Aggregator.getJsonRpcErrorMessage(response.data);
1510
+ if (rpcErrorMessage) {
1511
+ totalFailed++;
1512
+ this.trace(
1513
+ chain,
1514
+ traceReq,
1515
+ "error",
1516
+ "hermes-submitBundleTx-builder-失败",
1517
+ `Builder[${name}] 发送失败, targetBlock=${block}, 耗时=${Date.now() - ts}ms, error=${rpcErrorMessage}, resp=${JSON.stringify(response.data)}`
1518
+ );
1519
+ return;
1520
+ }
1376
1521
  totalSent++;
1522
+ if (builderAbortController.signal.aborted)
1523
+ return;
1377
1524
  this.trace(chain, traceReq, "log", "hermes-submitBundleTx-builder-成功", `Builder[${name}] 发送成功, targetBlock=${block}, 耗时=${Date.now() - ts}ms, resp=${JSON.stringify(response.data)}`);
1378
1525
  } catch (error) {
1526
+ if (builderAbortController.signal.aborted)
1527
+ return;
1379
1528
  totalFailed++;
1380
1529
  const msg = (error == null ? void 0 : error.response) ? JSON.stringify(error.response.data) : (error == null ? void 0 : error.message) ?? String(error);
1381
1530
  this.trace(chain, traceReq, "error", "hermes-submitBundleTx-builder-失败", `Builder[${name}] 发送失败, targetBlock=${block}, 耗时=${Date.now() - ts}ms, error=${msg}`);
1382
1531
  }
1383
1532
  });
1384
1533
  });
1385
- const abortController = new AbortController();
1386
- const inclusionPromise = this.waitForBundleInclusion(provider, txHash, targetBlocks, abortController.signal);
1534
+ const inclusionAbortController = new AbortController();
1535
+ const inclusionPromise = this.waitForBundleInclusion(provider, txHash, targetBlocks, inclusionAbortController.signal).finally(() => {
1536
+ builderAbortController.abort();
1537
+ });
1387
1538
  const waitTs = Date.now();
1388
1539
  this.trace(chain, traceReq, "log", "hermes-submitBundleTx-RPC发送前", `Bundle 请求开始发送, txHash=${txHash}, targetBlocks=[${targetBlocks.join(",")}]`);
1389
- const [receipt] = await Promise.all([
1390
- inclusionPromise,
1391
- Promise.all(fireAndForget).then(() => {
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
- );
1399
- if (totalSent === 0)
1400
- abortController.abort();
1401
- })
1540
+ const sendPromise = Promise.all(fireAndForget).then(() => {
1541
+ this.trace(
1542
+ chain,
1543
+ traceReq,
1544
+ "log",
1545
+ "hermes-submitBundleTx-RPC已发送",
1546
+ `Bundle发送完成, 成功=${totalSent}, 失败=${totalFailed}, 总请求=${fireAndForget.length}, 耗时=${Date.now() - sendBundleTs}ms, txHash=${txHash}`
1547
+ );
1548
+ return { totalSent, totalFailed };
1549
+ });
1550
+ const firstResult = await Promise.race([
1551
+ inclusionPromise.then((receipt2) => ({ kind: "receipt", receipt: receipt2 })),
1552
+ sendPromise.then((summary) => ({ kind: "sendDone", summary }))
1402
1553
  ]);
1554
+ let receipt;
1555
+ if (firstResult.kind === "receipt") {
1556
+ receipt = firstResult.receipt;
1557
+ } else {
1558
+ if (firstResult.summary.totalSent === 0) {
1559
+ inclusionAbortController.abort();
1560
+ }
1561
+ receipt = await inclusionPromise;
1562
+ }
1403
1563
  if (receipt) {
1404
1564
  const blockTs = await this.getBlockTimestampStr(provider, receipt.blockNumber);
1405
1565
  this.trace(
@@ -1410,13 +1570,7 @@ var _Aggregator = class {
1410
1570
  `Bundle上链确认, txHash=${receipt.hash}, blockNumber=${receipt.blockNumber}, 出块时间=${blockTs}, gasUsed=${receipt.gasUsed}, 等待耗时=${Date.now() - waitTs}ms`
1411
1571
  );
1412
1572
  } else {
1413
- this.trace(
1414
- chain,
1415
- traceReq,
1416
- "warn",
1417
- "hermes-submitBundleTx-等待结束",
1418
- `Bundle未在目标区块上链, txHash=${txHash}, 目标区块=[${targetBlocks.join(",")}], 等待耗时=${Date.now() - waitTs}ms`
1419
- );
1573
+ this.trace(chain, traceReq, "warn", "hermes-submitBundleTx-等待结束", `Bundle未在目标区块上链, txHash=${txHash}, 目标区块=[${targetBlocks.join(",")}], 等待耗时=${Date.now() - waitTs}ms`);
1420
1574
  }
1421
1575
  return { receipt, txHash, targetBlocks };
1422
1576
  }
@@ -1517,7 +1671,7 @@ var _Aggregator = class {
1517
1671
  return chain === import_types.ChainNameEnum.ETH && !!this.flashbotSigner;
1518
1672
  }
1519
1673
  stripCustomFields(txReq, chain) {
1520
- const defaultBlockCount = chain && this.builderConfigMap.has(chain) ? 3 : 1;
1674
+ const defaultBlockCount = this.getDefaultBundleBlockCount(chain);
1521
1675
  const { useBundle, bundleBlockCount = defaultBlockCount, trace, ...pureTxReq } = txReq;
1522
1676
  return { pureTxReq, bundleBlockCount: this.normalizeBundleBlockCount(bundleBlockCount) };
1523
1677
  }
@@ -1552,11 +1706,22 @@ var Aggregator = _Aggregator;
1552
1706
  Aggregator.DEFAULT_ETH_BUILDERS = {
1553
1707
  "beaverbuild.org": "https://rpc.beaverbuild.org",
1554
1708
  Titan: "https://rpc.titanbuilder.xyz",
1709
+ "Titan-EU": "https://eu.rpc.titanbuilder.xyz",
1555
1710
  flashbots: "https://relay.flashbots.net",
1556
1711
  // bloXroute: 'https://mev.api.blxrbdn.com', // 旧 api.blxrbdn.com 也行,需配置 Authorization 头
1557
- lightspeedbuilder: "https://rpc.lightspeedbuilder.info"
1712
+ "Builder+": "https://rpc.btcs.com",
1713
+ // BTCS 官方文档支持 eth_sendBundle
1714
+ // turbobuilder: 'https://rpc.turbobuilder.xyz', // 官方文档支持 eth_sendBundle
1715
+ lightspeedbuilder: "https://rpc.lightspeedbuilder.info",
1558
1716
  // 新增,实测直接可用
1559
- // buildernet: 'https://rpc.buildernet.org', // 新增,Flashbots 生态,需签名头(同 flashbots 格式)
1717
+ buildernet: "https://rpc.buildernet.org",
1718
+ // Flashbots 生态,使用 eth_sendBundle + X-Flashbots-Signature
1719
+ quasar: "https://rpc.quasar.win",
1720
+ // Quasar 文档支持 eth_sendBundle,认证沿用 X-Flashbots-Signature
1721
+ bananabuild: "https://rpc.bananabuild.org",
1722
+ // 官方文档支持 eth_sendBundle
1723
+ snailbuilder: "https://rpc.snailbuilder.sh"
1724
+ // 官网声明支持 Flashbots 同结构 bundle API
1560
1725
  // nfactorial: 'https://rpc.nfactorial.xyz', // 新增,支持 bundle rebate
1561
1726
  };
1562
1727
  Aggregator.DEFAULT_SEQUENCER_RPC_BY_CHAIN = {
@@ -26,9 +26,11 @@ declare class Aggregator {
26
26
  getAggregatorAddress(chain: ChainNameEnum): string;
27
27
  signRequestBody(body: unknown, signer: ethers.Wallet): Promise<string>;
28
28
  private getBuilderConfig;
29
+ private getDefaultBundleBlockCount;
29
30
  private getSequencerRpcs;
30
31
  private buildBundleRequestBody;
31
32
  private buildFlashbotsMevBundleRequestBody;
33
+ private static getJsonRpcErrorMessage;
32
34
  sendBundle(chain: ChainNameEnum, rawTxs: string[], targetBlock: number, signer?: ethers.Wallet): Promise<{
33
35
  sent: number;
34
36
  failed: number;
@@ -125,6 +125,9 @@ var Hermes = class {
125
125
  async getQuoterSupportContracts(chain) {
126
126
  return this.quoterClient.getQuoterSupportContracts(chain);
127
127
  }
128
+ destroy() {
129
+ this.providerClient.destroy();
130
+ }
128
131
  /**
129
132
  * 生成 swapAndBridge 的 calldata
130
133
  */
@@ -56,6 +56,7 @@ declare class Hermes {
56
56
  estimateGas(estimateType: IEstimateType, params: IBridgeParams | ISwapByPathParams | ISwapAndBridgeParams | IBatchMultiSwapParams): Promise<bigint>;
57
57
  getAggregatorSupportContracts(chain: ChainNameEnum): Promise<SupportContracts[]>;
58
58
  getQuoterSupportContracts(chain: ChainNameEnum): Promise<SupportContracts[]>;
59
+ destroy(): void;
59
60
  /**
60
61
  * 生成 swapAndBridge 的 calldata
61
62
  */
@@ -62,6 +62,16 @@ var Provider = class {
62
62
  }
63
63
  return this.walletMap.get(chain);
64
64
  }
65
+ destroy() {
66
+ var _a;
67
+ for (const provider of this.providerMap.values()) {
68
+ const rpcProvider = provider;
69
+ try {
70
+ (_a = rpcProvider.destroy) == null ? void 0 : _a.call(rpcProvider);
71
+ } catch {
72
+ }
73
+ }
74
+ }
65
75
  };
66
76
  var provider_default = Provider;
67
77
  // Annotate the CommonJS export names for ESM import in node:
@@ -8,6 +8,7 @@ declare class Provider {
8
8
  getProvider(chain: ChainNameEnum): ethers.Provider;
9
9
  checkIsEnoughToken(fromTokenAddress: string, userAddress: string, amountInWei: bigint, aggregatorAddress: string, wallet: ethers.Wallet): Promise<void>;
10
10
  getWallet(chain: ChainNameEnum): ethers.Wallet;
11
+ destroy(): void;
11
12
  }
12
13
  export default Provider;
13
14
  export { Provider };
@@ -36,7 +36,9 @@ var import_lz_definitions = require("@layerzerolabs/lz-definitions");
36
36
  var DexType = /* @__PURE__ */ ((DexType2) => {
37
37
  DexType2["FX"] = "f(x)";
38
38
  DexType2["UNISWAPV2"] = "uniswapv2";
39
+ DexType2["SUSHIV2"] = "sushiv2";
39
40
  DexType2["UNISWAPV3"] = "uniswapv3";
41
+ DexType2["SUSHIV3"] = "sushiv3";
40
42
  DexType2["UNISWAPV4"] = "uniswapv4";
41
43
  DexType2["CURVE128"] = "curve128";
42
44
  DexType2["CURVE256"] = "curve256";
@@ -58,6 +60,58 @@ var DexType = /* @__PURE__ */ ((DexType2) => {
58
60
  DexType2["BLACKHOLEV3"] = "blackholev3";
59
61
  DexType2["BLACKHOLEV2"] = "blackholev2";
60
62
  DexType2["FLUID"] = "fluid";
63
+ DexType2["BANCOR"] = "bancor";
64
+ DexType2["ERC4626"] = "erc4626";
65
+ DexType2["DODOV2"] = "dodo-v2";
66
+ DexType2["AERODROMEV3"] = "aerodrome_v3";
67
+ DexType2["ALGEBRAINTEGRAL"] = "algebra_integral";
68
+ DexType2["AMBIENT"] = "ambient";
69
+ DexType2["ANGSTROM"] = "angstrom";
70
+ DexType2["APESWAP"] = "apeswap";
71
+ DexType2["ARCHLYV2"] = "archly_v2";
72
+ DexType2["BALANCER"] = "balancer";
73
+ DexType2["BALANCERV2"] = "balancer_v2";
74
+ DexType2["BALANCERV3"] = "balancer_v3";
75
+ DexType2["BANCORV2"] = "bancor_v2";
76
+ DexType2["BANCORV3"] = "bancor_v3";
77
+ DexType2["BASIN"] = "basin";
78
+ DexType2["BUNNIV2"] = "bunni_v2";
79
+ DexType2["CURVELENDINGPOOLS"] = "curve_lending_pools";
80
+ DexType2["CURVEMETAPOOL"] = "curve_metapool";
81
+ DexType2["CURVESTABLESWAP"] = "curve_stable_swap";
82
+ DexType2["CURVESTABLESWAPNG"] = "curve_stable_swap_ng";
83
+ DexType2["CURVETRICRYPTO"] = "curve_tricrypto";
84
+ DexType2["CURVETRICRYPTONG"] = "curve_tricrypto_ng";
85
+ DexType2["CURVETWOCRYPTO"] = "curve_twocrypto";
86
+ DexType2["CYPHERV2"] = "cypher_v2";
87
+ DexType2["DEFIPLAZA"] = "defiplaza";
88
+ DexType2["DFXV2"] = "dfx_v2";
89
+ DexType2["DODOV1"] = "dodo_v1";
90
+ DexType2["EKUBO"] = "ekubo";
91
+ DexType2["EMPIREDEX"] = "empiredex";
92
+ DexType2["EULERSWAP"] = "eulerswap";
93
+ DexType2["FLUIDDEXLITE"] = "fluid_dex_lite";
94
+ DexType2["FLUIDDEXT1"] = "fluid_dex_t1";
95
+ DexType2["INTEGRAL"] = "integral";
96
+ DexType2["JOEV2"] = "joe_v2";
97
+ DexType2["KYBERSWAPCLASSIC"] = "kyberswap_classic";
98
+ DexType2["KYBERSWAPELASTIC"] = "kyberswap_elastic";
99
+ DexType2["LISTADEX"] = "lista_dex";
100
+ DexType2["LUASWAP"] = "luaswap";
101
+ DexType2["MAVERICKV2"] = "maverick_v2";
102
+ DexType2["MOONISWAP"] = "mooniswap";
103
+ DexType2["PENDLEV2"] = "pendle_v2";
104
+ DexType2["RINGSWAP"] = "ring_swap";
105
+ DexType2["SADDLEFINANCE"] = "saddle_finance";
106
+ DexType2["SHIBASWAPV1"] = "shibaswap_v1";
107
+ DexType2["SMARDEX"] = "smardex";
108
+ DexType2["SOLIDLYV3"] = "solidly_v3";
109
+ DexType2["STABULL"] = "stabull";
110
+ DexType2["SUPERNOVABASIC"] = "supernova_basic";
111
+ DexType2["SWAPR"] = "swapr";
112
+ DexType2["UNISWAPV1"] = "uniswap_v1";
113
+ DexType2["WOMBAT"] = "wombat";
114
+ DexType2["YIELDBASIS"] = "yield_basis";
61
115
  return DexType2;
62
116
  })(DexType || {});
63
117
  var IEstimateType = /* @__PURE__ */ ((IEstimateType2) => {
@@ -172,7 +172,9 @@ export interface IHermesSignalQuoteBestData {
172
172
  export declare enum DexType {
173
173
  FX = "f(x)",
174
174
  UNISWAPV2 = "uniswapv2",
175
+ SUSHIV2 = "sushiv2",
175
176
  UNISWAPV3 = "uniswapv3",
177
+ SUSHIV3 = "sushiv3",
176
178
  UNISWAPV4 = "uniswapv4",
177
179
  CURVE128 = "curve128",
178
180
  CURVE256 = "curve256",
@@ -193,7 +195,59 @@ export declare enum DexType {
193
195
  SHADOWV2 = "shadowv2",
194
196
  BLACKHOLEV3 = "blackholev3",
195
197
  BLACKHOLEV2 = "blackholev2",
196
- FLUID = "fluid"
198
+ FLUID = "fluid",
199
+ BANCOR = "bancor",
200
+ ERC4626 = "erc4626",
201
+ DODOV2 = "dodo-v2",
202
+ AERODROMEV3 = "aerodrome_v3",
203
+ ALGEBRAINTEGRAL = "algebra_integral",
204
+ AMBIENT = "ambient",
205
+ ANGSTROM = "angstrom",
206
+ APESWAP = "apeswap",
207
+ ARCHLYV2 = "archly_v2",
208
+ BALANCER = "balancer",
209
+ BALANCERV2 = "balancer_v2",
210
+ BALANCERV3 = "balancer_v3",
211
+ BANCORV2 = "bancor_v2",
212
+ BANCORV3 = "bancor_v3",
213
+ BASIN = "basin",
214
+ BUNNIV2 = "bunni_v2",
215
+ CURVELENDINGPOOLS = "curve_lending_pools",
216
+ CURVEMETAPOOL = "curve_metapool",
217
+ CURVESTABLESWAP = "curve_stable_swap",
218
+ CURVESTABLESWAPNG = "curve_stable_swap_ng",
219
+ CURVETRICRYPTO = "curve_tricrypto",
220
+ CURVETRICRYPTONG = "curve_tricrypto_ng",
221
+ CURVETWOCRYPTO = "curve_twocrypto",
222
+ CYPHERV2 = "cypher_v2",
223
+ DEFIPLAZA = "defiplaza",
224
+ DFXV2 = "dfx_v2",
225
+ DODOV1 = "dodo_v1",
226
+ EKUBO = "ekubo",
227
+ EMPIREDEX = "empiredex",
228
+ EULERSWAP = "eulerswap",
229
+ FLUIDDEXLITE = "fluid_dex_lite",
230
+ FLUIDDEXT1 = "fluid_dex_t1",
231
+ INTEGRAL = "integral",
232
+ JOEV2 = "joe_v2",
233
+ KYBERSWAPCLASSIC = "kyberswap_classic",
234
+ KYBERSWAPELASTIC = "kyberswap_elastic",
235
+ LISTADEX = "lista_dex",
236
+ LUASWAP = "luaswap",
237
+ MAVERICKV2 = "maverick_v2",
238
+ MOONISWAP = "mooniswap",
239
+ PENDLEV2 = "pendle_v2",
240
+ RINGSWAP = "ring_swap",
241
+ SADDLEFINANCE = "saddle_finance",
242
+ SHIBASWAPV1 = "shibaswap_v1",
243
+ SMARDEX = "smardex",
244
+ SOLIDLYV3 = "solidly_v3",
245
+ STABULL = "stabull",
246
+ SUPERNOVABASIC = "supernova_basic",
247
+ SWAPR = "swapr",
248
+ UNISWAPV1 = "uniswap_v1",
249
+ WOMBAT = "wombat",
250
+ YIELDBASIS = "yield_basis"
197
251
  }
198
252
  export declare enum IEstimateType {
199
253
  BRIDGE = "bridge",