hermes-swap 0.6.10 → 0.6.11
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 +114 -21
- package/dist/cjs/aggregator.d.ts +2 -0
- package/dist/cjs/index.cjs +3 -0
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/provider.cjs +10 -0
- package/dist/cjs/provider.d.ts +1 -0
- package/dist/esm/aggregator.d.ts +2 -0
- package/dist/esm/aggregator.mjs +383 -281
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.mjs +6 -0
- package/dist/esm/provider.d.ts +1 -0
- package/dist/esm/provider.mjs +23 -0
- package/package.json +1 -1
package/dist/cjs/aggregator.cjs
CHANGED
|
@@ -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(
|
|
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
|
-
|
|
975
|
-
|
|
976
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1136
|
+
if (!settled)
|
|
1137
|
+
await finishWithFallbackCheck();
|
|
1087
1138
|
}, _Aggregator.BUNDLE_INCLUSION_TIMEOUT_MS);
|
|
1088
1139
|
provider.on("block", onBlock);
|
|
1089
1140
|
provider.getBlockNumber().then(
|
|
@@ -1299,7 +1350,7 @@ var _Aggregator = class {
|
|
|
1299
1350
|
}
|
|
1300
1351
|
async submitBundleTx(chain, wallet, txReq, to, data, value, bundleBlockCount, traceReq) {
|
|
1301
1352
|
if (bundleBlockCount == null) {
|
|
1302
|
-
bundleBlockCount = this.
|
|
1353
|
+
bundleBlockCount = this.getDefaultBundleBlockCount(chain);
|
|
1303
1354
|
}
|
|
1304
1355
|
const builderCfg = this.getBuilderConfig(chain);
|
|
1305
1356
|
if (builderCfg.authType === "flashbots" && !this.flashbotSigner) {
|
|
@@ -1354,12 +1405,36 @@ var _Aggregator = class {
|
|
|
1354
1405
|
const ts = Date.now();
|
|
1355
1406
|
try {
|
|
1356
1407
|
const response = await import_axios.default.post(url, body, { headers, timeout: 3e3 });
|
|
1408
|
+
const rpcErrorMessage = _Aggregator.getJsonRpcErrorMessage(response.data);
|
|
1409
|
+
if (rpcErrorMessage) {
|
|
1410
|
+
totalFailed++;
|
|
1411
|
+
this.trace(
|
|
1412
|
+
chain,
|
|
1413
|
+
traceReq,
|
|
1414
|
+
"error",
|
|
1415
|
+
"hermes-submitBundleTx-builder-失败",
|
|
1416
|
+
`Builder[${name}] mev_sendBundle 发送失败, targetBlocks=[${targetBlocks.join(",")}], 耗时=${Date.now() - ts}ms, error=${rpcErrorMessage}, resp=${JSON.stringify(response.data)}`
|
|
1417
|
+
);
|
|
1418
|
+
return;
|
|
1419
|
+
}
|
|
1357
1420
|
totalSent++;
|
|
1358
|
-
this.trace(
|
|
1421
|
+
this.trace(
|
|
1422
|
+
chain,
|
|
1423
|
+
traceReq,
|
|
1424
|
+
"log",
|
|
1425
|
+
"hermes-submitBundleTx-builder-成功",
|
|
1426
|
+
`Builder[${name}] mev_sendBundle 发送成功, targetBlocks=[${targetBlocks.join(",")}], 耗时=${Date.now() - ts}ms, resp=${JSON.stringify(response.data)}`
|
|
1427
|
+
);
|
|
1359
1428
|
} catch (error) {
|
|
1360
1429
|
totalFailed++;
|
|
1361
1430
|
const msg = (error == null ? void 0 : error.response) ? JSON.stringify(error.response.data) : (error == null ? void 0 : error.message) ?? String(error);
|
|
1362
|
-
this.trace(
|
|
1431
|
+
this.trace(
|
|
1432
|
+
chain,
|
|
1433
|
+
traceReq,
|
|
1434
|
+
"error",
|
|
1435
|
+
"hermes-submitBundleTx-builder-失败",
|
|
1436
|
+
`Builder[${name}] mev_sendBundle 发送失败, targetBlocks=[${targetBlocks.join(",")}], 耗时=${Date.now() - ts}ms, error=${msg}`
|
|
1437
|
+
);
|
|
1363
1438
|
}
|
|
1364
1439
|
})()
|
|
1365
1440
|
];
|
|
@@ -1373,6 +1448,18 @@ var _Aggregator = class {
|
|
|
1373
1448
|
const ts = Date.now();
|
|
1374
1449
|
try {
|
|
1375
1450
|
const response = await import_axios.default.post(url, body, { headers, timeout: 3e3 });
|
|
1451
|
+
const rpcErrorMessage = _Aggregator.getJsonRpcErrorMessage(response.data);
|
|
1452
|
+
if (rpcErrorMessage) {
|
|
1453
|
+
totalFailed++;
|
|
1454
|
+
this.trace(
|
|
1455
|
+
chain,
|
|
1456
|
+
traceReq,
|
|
1457
|
+
"error",
|
|
1458
|
+
"hermes-submitBundleTx-builder-失败",
|
|
1459
|
+
`Builder[${name}] 发送失败, targetBlock=${block}, 耗时=${Date.now() - ts}ms, error=${rpcErrorMessage}, resp=${JSON.stringify(response.data)}`
|
|
1460
|
+
);
|
|
1461
|
+
return;
|
|
1462
|
+
}
|
|
1376
1463
|
totalSent++;
|
|
1377
1464
|
this.trace(chain, traceReq, "log", "hermes-submitBundleTx-builder-成功", `Builder[${name}] 发送成功, targetBlock=${block}, 耗时=${Date.now() - ts}ms, resp=${JSON.stringify(response.data)}`);
|
|
1378
1465
|
} catch (error) {
|
|
@@ -1410,13 +1497,7 @@ var _Aggregator = class {
|
|
|
1410
1497
|
`Bundle上链确认, txHash=${receipt.hash}, blockNumber=${receipt.blockNumber}, 出块时间=${blockTs}, gasUsed=${receipt.gasUsed}, 等待耗时=${Date.now() - waitTs}ms`
|
|
1411
1498
|
);
|
|
1412
1499
|
} else {
|
|
1413
|
-
this.trace(
|
|
1414
|
-
chain,
|
|
1415
|
-
traceReq,
|
|
1416
|
-
"warn",
|
|
1417
|
-
"hermes-submitBundleTx-等待结束",
|
|
1418
|
-
`Bundle未在目标区块上链, txHash=${txHash}, 目标区块=[${targetBlocks.join(",")}], 等待耗时=${Date.now() - waitTs}ms`
|
|
1419
|
-
);
|
|
1500
|
+
this.trace(chain, traceReq, "warn", "hermes-submitBundleTx-等待结束", `Bundle未在目标区块上链, txHash=${txHash}, 目标区块=[${targetBlocks.join(",")}], 等待耗时=${Date.now() - waitTs}ms`);
|
|
1420
1501
|
}
|
|
1421
1502
|
return { receipt, txHash, targetBlocks };
|
|
1422
1503
|
}
|
|
@@ -1517,7 +1598,7 @@ var _Aggregator = class {
|
|
|
1517
1598
|
return chain === import_types.ChainNameEnum.ETH && !!this.flashbotSigner;
|
|
1518
1599
|
}
|
|
1519
1600
|
stripCustomFields(txReq, chain) {
|
|
1520
|
-
const defaultBlockCount =
|
|
1601
|
+
const defaultBlockCount = this.getDefaultBundleBlockCount(chain);
|
|
1521
1602
|
const { useBundle, bundleBlockCount = defaultBlockCount, trace, ...pureTxReq } = txReq;
|
|
1522
1603
|
return { pureTxReq, bundleBlockCount: this.normalizeBundleBlockCount(bundleBlockCount) };
|
|
1523
1604
|
}
|
|
@@ -1552,11 +1633,23 @@ var Aggregator = _Aggregator;
|
|
|
1552
1633
|
Aggregator.DEFAULT_ETH_BUILDERS = {
|
|
1553
1634
|
"beaverbuild.org": "https://rpc.beaverbuild.org",
|
|
1554
1635
|
Titan: "https://rpc.titanbuilder.xyz",
|
|
1636
|
+
"Titan-EU": "https://eu.rpc.titanbuilder.xyz",
|
|
1555
1637
|
flashbots: "https://relay.flashbots.net",
|
|
1556
1638
|
// bloXroute: 'https://mev.api.blxrbdn.com', // 旧 api.blxrbdn.com 也行,需配置 Authorization 头
|
|
1557
|
-
|
|
1639
|
+
"Builder+": "https://rpc.btcs.com",
|
|
1640
|
+
// BTCS 官方文档支持 eth_sendBundle
|
|
1641
|
+
turbobuilder: "https://rpc.turbobuilder.xyz",
|
|
1642
|
+
// 官方文档支持 eth_sendBundle
|
|
1643
|
+
lightspeedbuilder: "https://rpc.lightspeedbuilder.info",
|
|
1558
1644
|
// 新增,实测直接可用
|
|
1559
|
-
|
|
1645
|
+
buildernet: "https://rpc.buildernet.org",
|
|
1646
|
+
// Flashbots 生态,使用 eth_sendBundle + X-Flashbots-Signature
|
|
1647
|
+
quasar: "https://rpc.quasar.win",
|
|
1648
|
+
// Quasar 文档支持 eth_sendBundle,认证沿用 X-Flashbots-Signature
|
|
1649
|
+
bananabuild: "https://rpc.bananabuild.org",
|
|
1650
|
+
// 官方文档支持 eth_sendBundle
|
|
1651
|
+
snailbuilder: "https://rpc.snailbuilder.sh"
|
|
1652
|
+
// 官网声明支持 Flashbots 同结构 bundle API
|
|
1560
1653
|
// nfactorial: 'https://rpc.nfactorial.xyz', // 新增,支持 bundle rebate
|
|
1561
1654
|
};
|
|
1562
1655
|
Aggregator.DEFAULT_SEQUENCER_RPC_BY_CHAIN = {
|
package/dist/cjs/aggregator.d.ts
CHANGED
|
@@ -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;
|
package/dist/cjs/index.cjs
CHANGED
package/dist/cjs/index.d.ts
CHANGED
|
@@ -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
|
*/
|
package/dist/cjs/provider.cjs
CHANGED
|
@@ -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:
|
package/dist/cjs/provider.d.ts
CHANGED
|
@@ -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 };
|
package/dist/esm/aggregator.d.ts
CHANGED
|
@@ -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;
|