hermes-swap 0.1.9 → 0.2.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.
- package/dist/cjs/index.d.ts +8 -2
- package/dist/cjs/index.js +257 -6
- package/dist/cjs/types.d.ts +27 -1
- package/dist/cjs/types.js +3 -1
- package/dist/esm/index.d.ts +8 -2
- package/dist/esm/index.js +843 -262
- package/dist/esm/types.d.ts +27 -1
- package/dist/esm/types.js +4 -1
- package/package.json +3 -1
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
import type { IExpectParams, ISwapParams, IBridgeParams, ISwapAndBridgeParams, IReceipt, IConfig, IExpectPayload, IRouterPath, SupportContracts } from './types.js';
|
|
1
|
+
import type { IExpectParams, IBatchMultiSwapParams, IBatchExpectParams, ISwapParams, IBridgeParams, IBatchReceipt, ISwapAndBridgeParams, IReceipt, IConfig, IExpectPayload, IRouterPath, SupportContracts } 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 { IExpectParams, ISwapParams, IBridgeParams, ISwapAndBridgeParams, IReceipt, IConfig, IExpectPayload, IRouterPath, SupportContracts };
|
|
4
|
+
export type { IExpectParams, IBatchMultiSwapParams, IBatchExpectParams, IBatchReceipt, ISwapParams, IBridgeParams, ISwapAndBridgeParams, IReceipt, IConfig, IExpectPayload, IRouterPath, SupportContracts, };
|
|
5
5
|
export { ChainNameEnum, AddressConst, DexType, BridgeType, IEstimateType, LayerZeroV1ChainIdMap, LayerZeroV1ChainNameMap, LayerZeroV2ChainIdMap, LayerZeroV2ChainNameMap };
|
|
6
6
|
declare class Hermes {
|
|
7
7
|
private config;
|
|
8
8
|
private providerMap;
|
|
9
9
|
private walletMap;
|
|
10
10
|
private quoterAddressMap;
|
|
11
|
+
private flashbotSigner;
|
|
11
12
|
private aggregatorAddressMap;
|
|
12
13
|
private executor;
|
|
13
14
|
constructor(config: IConfig);
|
|
14
15
|
expectPriorityLocal(params: IExpectParams): Promise<bigint>;
|
|
15
16
|
expect(params: IExpectParams): Promise<bigint>;
|
|
17
|
+
batchMultiExpect(params: IBatchExpectParams): Promise<bigint[]>;
|
|
16
18
|
swap(params: ISwapParams, txReq?: TransactionRequest): Promise<IReceipt>;
|
|
19
|
+
batchMultiSwap(params: IBatchMultiSwapParams, txReq?: TransactionRequest): Promise<IBatchReceipt>;
|
|
20
|
+
swapByFlashbots(params: ISwapParams, txReq?: TransactionRequest, _targetBlockNumber?: number): Promise<IReceipt | null>;
|
|
17
21
|
/**
|
|
18
22
|
* 生成 swap 的 calldata
|
|
19
23
|
*/
|
|
@@ -41,8 +45,10 @@ declare class Hermes {
|
|
|
41
45
|
value: bigint;
|
|
42
46
|
};
|
|
43
47
|
private resolveGasLimit;
|
|
48
|
+
private sendBundle;
|
|
44
49
|
private resolveNonce;
|
|
45
50
|
private resolvePricing;
|
|
51
|
+
private signRequestBody;
|
|
46
52
|
private sanitizePricing;
|
|
47
53
|
private checkIsEnoughToken;
|
|
48
54
|
private validateParams;
|
package/dist/cjs/index.js
CHANGED
|
@@ -44,6 +44,7 @@ __export(src_exports, {
|
|
|
44
44
|
module.exports = __toCommonJS(src_exports);
|
|
45
45
|
var import_types = require("./types.js");
|
|
46
46
|
var import_ethers = require("ethers");
|
|
47
|
+
var import_axios = __toESM(require("axios"));
|
|
47
48
|
var import_quoter = __toESM(require("./abis/quoter.js"));
|
|
48
49
|
var import_aggregator = __toESM(require("./abis/aggregator.js"));
|
|
49
50
|
var Hermes = class {
|
|
@@ -54,6 +55,7 @@ var Hermes = class {
|
|
|
54
55
|
this.aggregatorAddressMap = /* @__PURE__ */ new Map();
|
|
55
56
|
this.config = config;
|
|
56
57
|
this.executor = config.executor;
|
|
58
|
+
this.flashbotSigner = new import_ethers.ethers.Wallet(config.flashbotSigner);
|
|
57
59
|
if (!config.hermesSignalDomain || config.hermesSignalDomain === "") {
|
|
58
60
|
this.config.hermesSignalDomain = "http://127.0.0.1:3002";
|
|
59
61
|
} else {
|
|
@@ -113,6 +115,41 @@ var Hermes = class {
|
|
|
113
115
|
}
|
|
114
116
|
return amountOutList[amountOutList.length - 1];
|
|
115
117
|
}
|
|
118
|
+
async batchMultiExpect(params) {
|
|
119
|
+
const provider = this.providerMap.get(params.chain);
|
|
120
|
+
if (!provider) {
|
|
121
|
+
throw new Error(`Chain: ${params.chain} provider is undefined`);
|
|
122
|
+
}
|
|
123
|
+
if (params.amountInWei.length !== params.path.length) {
|
|
124
|
+
throw new Error("amountInWei length must match path length");
|
|
125
|
+
}
|
|
126
|
+
const address = this.getQuoterAddress(params.chain);
|
|
127
|
+
if (!address) {
|
|
128
|
+
throw new Error(`Quoter address not found for chain: ${params.chain}`);
|
|
129
|
+
}
|
|
130
|
+
const quoter = new import_ethers.Contract(address, import_quoter.default, provider);
|
|
131
|
+
const quoteParamsArr = params.path.map(
|
|
132
|
+
(path) => path.map((p) => ({
|
|
133
|
+
dexType: p.dexType,
|
|
134
|
+
pool: p.poolAddress,
|
|
135
|
+
fromCoin: p.fromCoinAddress,
|
|
136
|
+
toCoin: p.toCoinAddress,
|
|
137
|
+
extra: p.extra || "0x"
|
|
138
|
+
}))
|
|
139
|
+
);
|
|
140
|
+
const amountOutListArr = await quoter.batchMultiQuote.staticCall(params.amountInWei, quoteParamsArr, {
|
|
141
|
+
from: this.config.executor
|
|
142
|
+
});
|
|
143
|
+
if (!amountOutListArr.length) {
|
|
144
|
+
throw new Error("No expect result return from smart contract");
|
|
145
|
+
}
|
|
146
|
+
return amountOutListArr.map((list) => {
|
|
147
|
+
if (!list.length) {
|
|
148
|
+
throw new Error("No expect result return from smart contract");
|
|
149
|
+
}
|
|
150
|
+
return list[list.length - 1];
|
|
151
|
+
});
|
|
152
|
+
}
|
|
116
153
|
async swap(params, txReq = {}) {
|
|
117
154
|
this.validateParams(params);
|
|
118
155
|
if (!params.path.length) {
|
|
@@ -169,10 +206,178 @@ var Hermes = class {
|
|
|
169
206
|
amountOut,
|
|
170
207
|
hash: receipt.hash,
|
|
171
208
|
from: receipt.from,
|
|
172
|
-
to: receipt.from
|
|
173
|
-
logs: receipt.logs
|
|
209
|
+
to: receipt.from
|
|
174
210
|
};
|
|
175
211
|
}
|
|
212
|
+
async batchMultiSwap(params, txReq = {}) {
|
|
213
|
+
const provider = this.providerMap.get(params.chain);
|
|
214
|
+
const wallet = this.walletMap.get(params.chain);
|
|
215
|
+
if (!wallet || !provider) {
|
|
216
|
+
throw new Error(`sdk不支持的链: ${params.chain}`);
|
|
217
|
+
}
|
|
218
|
+
if (params.amountInWeis.length !== params.paths.length) {
|
|
219
|
+
throw new Error("传入参数数量不正确");
|
|
220
|
+
}
|
|
221
|
+
const aggregatorAddress = this.getAggregatorAddress(params.chain);
|
|
222
|
+
const aggregator = new import_ethers.Contract(aggregatorAddress, import_aggregator.default, wallet);
|
|
223
|
+
const swapParamsList = params.paths.map(
|
|
224
|
+
(path) => path.map((pathItem) => ({
|
|
225
|
+
dexType: pathItem.dexType,
|
|
226
|
+
pool: pathItem.poolAddress,
|
|
227
|
+
fromCoin: pathItem.fromCoinAddress,
|
|
228
|
+
toCoin: pathItem.toCoinAddress,
|
|
229
|
+
extra: pathItem.extra ?? "0x"
|
|
230
|
+
}))
|
|
231
|
+
);
|
|
232
|
+
let estimateGas;
|
|
233
|
+
const { gasLimit: _ignore, ...estimationOverrides } = txReq;
|
|
234
|
+
try {
|
|
235
|
+
estimateGas = await aggregator.batchMultiSwap.estimateGas(params.users, params.amountInWeis, swapParamsList, params.minAmountOutLists, estimationOverrides);
|
|
236
|
+
} catch (error) {
|
|
237
|
+
console.warn("Aggregator estimateGas.swap failed", error);
|
|
238
|
+
throw error;
|
|
239
|
+
}
|
|
240
|
+
txReq = this.resolveGasLimit(txReq, estimateGas);
|
|
241
|
+
txReq = await this.resolveNonce(wallet.provider, wallet.address, txReq);
|
|
242
|
+
txReq = await this.resolvePricing(wallet.provider, txReq);
|
|
243
|
+
let txResponse = await aggregator.batchMultiSwap(params.users, params.amountInWeis, swapParamsList, params.minAmountOutLists, estimationOverrides);
|
|
244
|
+
const receipt = await txResponse.wait();
|
|
245
|
+
const iface = new import_ethers.ethers.Interface(import_aggregator.default);
|
|
246
|
+
let userList = null;
|
|
247
|
+
let amountInList = null;
|
|
248
|
+
let amountOutList = null;
|
|
249
|
+
for (const log of receipt.logs) {
|
|
250
|
+
if (log.address.toLowerCase() === aggregatorAddress.toLowerCase()) {
|
|
251
|
+
try {
|
|
252
|
+
const parsed = iface.parseLog(log);
|
|
253
|
+
if (parsed && parsed.name === "MultiSwapped" && parsed.args) {
|
|
254
|
+
userList = parsed.args.userList;
|
|
255
|
+
amountInList = parsed.args.amountInList;
|
|
256
|
+
amountOutList = parsed.args.amountOutList;
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
} catch {
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (!userList || !amountInList || !amountOutList) {
|
|
264
|
+
throw new Error(`MultiSwapped event not found: ${receipt.hash}`);
|
|
265
|
+
}
|
|
266
|
+
if (userList.length !== params.users.length || amountOutList.length !== params.users.length) {
|
|
267
|
+
throw new Error(`MultiSwapped event length mismatch: ${receipt.hash}`);
|
|
268
|
+
}
|
|
269
|
+
return {
|
|
270
|
+
hash: receipt.hash,
|
|
271
|
+
from: receipt.from,
|
|
272
|
+
to: receipt.to ?? null,
|
|
273
|
+
userResults: params.users.map((user, i) => {
|
|
274
|
+
var _a, _b;
|
|
275
|
+
const path = params.paths[i];
|
|
276
|
+
const fromTokenAddress = ((_a = path == null ? void 0 : path[0]) == null ? void 0 : _a.fromCoinAddress) ?? "";
|
|
277
|
+
const toTokenAddress = ((_b = path == null ? void 0 : path[path.length - 1]) == null ? void 0 : _b.toCoinAddress) ?? "";
|
|
278
|
+
return {
|
|
279
|
+
user,
|
|
280
|
+
amountIn: amountInList[i],
|
|
281
|
+
amountOut: amountOutList[i],
|
|
282
|
+
fromToken: fromTokenAddress,
|
|
283
|
+
toToken: toTokenAddress
|
|
284
|
+
};
|
|
285
|
+
})
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
async swapByFlashbots(params, txReq = {}, _targetBlockNumber) {
|
|
289
|
+
const provider = this.providerMap.get(params.chain);
|
|
290
|
+
const wallet = this.walletMap.get(params.chain);
|
|
291
|
+
if (!wallet || !provider) {
|
|
292
|
+
throw new Error(`sdk不支持的链: ${params.chain}`);
|
|
293
|
+
}
|
|
294
|
+
const aggregatorAddress = this.getAggregatorAddress(params.chain);
|
|
295
|
+
const aggregator = new import_ethers.Contract(aggregatorAddress, import_aggregator.default, wallet);
|
|
296
|
+
const swapParams = params.path.map((pathItem) => ({
|
|
297
|
+
dexType: pathItem.dexType,
|
|
298
|
+
pool: pathItem.poolAddress,
|
|
299
|
+
fromCoin: pathItem.fromCoinAddress,
|
|
300
|
+
toCoin: pathItem.toCoinAddress,
|
|
301
|
+
extra: pathItem.extra ?? "0x"
|
|
302
|
+
}));
|
|
303
|
+
let estimateGas;
|
|
304
|
+
const { gasLimit: _ignore, ...estimationOverrides } = txReq;
|
|
305
|
+
try {
|
|
306
|
+
estimateGas = await aggregator.swap.estimateGas(params.user, params.amountInWei, swapParams, params.minAmountOutList, estimationOverrides);
|
|
307
|
+
} catch (error) {
|
|
308
|
+
console.warn("Aggregator estimateGas.swap failed", error);
|
|
309
|
+
throw error;
|
|
310
|
+
}
|
|
311
|
+
txReq = this.resolveGasLimit(txReq, estimateGas);
|
|
312
|
+
txReq = await this.resolveNonce(wallet.provider, wallet.address, txReq);
|
|
313
|
+
txReq = await this.resolvePricing(wallet.provider, txReq);
|
|
314
|
+
this.validateParams(params);
|
|
315
|
+
const swapCallData = this.genSwapCalldata(params);
|
|
316
|
+
const baseTx = {
|
|
317
|
+
from: wallet.address,
|
|
318
|
+
to: swapCallData.to,
|
|
319
|
+
nonce: txReq.nonce,
|
|
320
|
+
value: import_ethers.ethers.parseEther("0"),
|
|
321
|
+
maxFeePerGas: txReq.maxFeePerGas,
|
|
322
|
+
maxPriorityFeePerGas: txReq.maxPriorityFeePerGas,
|
|
323
|
+
chainId: 1,
|
|
324
|
+
data: swapCallData.data,
|
|
325
|
+
gasLimit: txReq.gasLimit
|
|
326
|
+
};
|
|
327
|
+
const signTx = await wallet.signTransaction(baseTx);
|
|
328
|
+
const rawTxs = [signTx];
|
|
329
|
+
const txHashes = rawTxs.map((tx) => import_ethers.ethers.keccak256(tx));
|
|
330
|
+
txHashes.forEach((hash, i) => {
|
|
331
|
+
console.log(`Transaction ${i + 1}: ${hash}`);
|
|
332
|
+
});
|
|
333
|
+
let targetBlock;
|
|
334
|
+
if (_targetBlockNumber) {
|
|
335
|
+
targetBlock = _targetBlockNumber;
|
|
336
|
+
} else {
|
|
337
|
+
targetBlock = await provider.getBlockNumber() + 1;
|
|
338
|
+
}
|
|
339
|
+
const resultPromise = new Promise((resolve) => {
|
|
340
|
+
const onBlock = async (blockNumber) => {
|
|
341
|
+
if (blockNumber < targetBlock) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
provider.off("block", onBlock);
|
|
345
|
+
const receipts = await Promise.all(txHashes.map((hash) => provider.getTransactionReceipt(hash)));
|
|
346
|
+
const receipt = receipts.find((r) => r && r.blockNumber === targetBlock) ?? null;
|
|
347
|
+
if (!receipt) {
|
|
348
|
+
resolve(null);
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
const fromTokenAddress = params.path[0].fromCoinAddress;
|
|
352
|
+
const toTokenAddress = params.path[params.path.length - 1].toCoinAddress;
|
|
353
|
+
const iface = new import_ethers.ethers.Interface(import_aggregator.default);
|
|
354
|
+
let amountOut = null;
|
|
355
|
+
for (const log of receipt.logs) {
|
|
356
|
+
if (log.address.toLowerCase() === aggregatorAddress.toLowerCase()) {
|
|
357
|
+
try {
|
|
358
|
+
const parsed = iface.parseLog(log);
|
|
359
|
+
if (parsed && parsed.name === "Swapped" && parsed.args && parsed.args.amountOut !== void 0) {
|
|
360
|
+
amountOut = parsed.args.amountOut;
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
} catch {
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
resolve({
|
|
368
|
+
fromToken: fromTokenAddress,
|
|
369
|
+
toToken: toTokenAddress,
|
|
370
|
+
amountOut,
|
|
371
|
+
hash: receipt.hash,
|
|
372
|
+
from: receipt.from,
|
|
373
|
+
to: receipt.to
|
|
374
|
+
});
|
|
375
|
+
};
|
|
376
|
+
provider.on("block", onBlock);
|
|
377
|
+
});
|
|
378
|
+
await this.sendBundle(rawTxs, targetBlock, this.flashbotSigner);
|
|
379
|
+
return resultPromise;
|
|
380
|
+
}
|
|
176
381
|
/**
|
|
177
382
|
* 生成 swap 的 calldata
|
|
178
383
|
*/
|
|
@@ -273,8 +478,7 @@ var Hermes = class {
|
|
|
273
478
|
amountOut: params.amountInWei,
|
|
274
479
|
hash: txReceipt.hash,
|
|
275
480
|
from: txReceipt.from,
|
|
276
|
-
to: txReceipt.to
|
|
277
|
-
logs: txReceipt.logs
|
|
481
|
+
to: txReceipt.to
|
|
278
482
|
};
|
|
279
483
|
}
|
|
280
484
|
async estimateBridgeFee(params) {
|
|
@@ -357,8 +561,7 @@ var Hermes = class {
|
|
|
357
561
|
amountOut: outputAmountWei,
|
|
358
562
|
hash: txReceipt.hash,
|
|
359
563
|
from: txReceipt.from,
|
|
360
|
-
to: txReceipt.to
|
|
361
|
-
logs: txReceipt.logs
|
|
564
|
+
to: txReceipt.to
|
|
362
565
|
};
|
|
363
566
|
}
|
|
364
567
|
async estimateGas(estimateType, params) {
|
|
@@ -524,6 +727,47 @@ var Hermes = class {
|
|
|
524
727
|
// 上浮30%
|
|
525
728
|
};
|
|
526
729
|
}
|
|
730
|
+
async sendBundle(rawTxs, targetBlock, signer) {
|
|
731
|
+
console.log(`
|
|
732
|
+
--- Sending Bundle for Block ${targetBlock} ---`);
|
|
733
|
+
const body = {
|
|
734
|
+
jsonrpc: "2.0",
|
|
735
|
+
id: 1,
|
|
736
|
+
method: "eth_sendBundle",
|
|
737
|
+
params: [
|
|
738
|
+
{
|
|
739
|
+
txs: rawTxs,
|
|
740
|
+
blockNumber: `0x${targetBlock.toString(16)}`
|
|
741
|
+
}
|
|
742
|
+
]
|
|
743
|
+
};
|
|
744
|
+
const signature = await this.signRequestBody(body, signer);
|
|
745
|
+
const headers = {
|
|
746
|
+
"Content-Type": "application/json",
|
|
747
|
+
"X-Flashbots-Signature": signature
|
|
748
|
+
};
|
|
749
|
+
const BUILDERS = {
|
|
750
|
+
"beaverbuild.org": "https://rpc.beaverbuild.org",
|
|
751
|
+
Titan: "https://rpc.titanbuilder.xyz",
|
|
752
|
+
flashbots: "https://relay.flashbots.net",
|
|
753
|
+
// For simulation and sending
|
|
754
|
+
bloXroute: "rpc-builder.blxrbdn.com"
|
|
755
|
+
};
|
|
756
|
+
const builderEntries = Object.entries(BUILDERS);
|
|
757
|
+
let count = 0;
|
|
758
|
+
const promises = builderEntries.map(async ([name, url]) => {
|
|
759
|
+
try {
|
|
760
|
+
const response = await import_axios.default.post(url, body, { headers });
|
|
761
|
+
count++;
|
|
762
|
+
console.log(`[${count}/${builderEntries.length}] Sent to ${name}:`, response.data);
|
|
763
|
+
} catch (error) {
|
|
764
|
+
count++;
|
|
765
|
+
const msg = (error == null ? void 0 : error.response) ? error.response.data : (error == null ? void 0 : error.message) ?? error;
|
|
766
|
+
console.error(`[${count}/${builderEntries.length}] Error sending to ${name}:`, msg);
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
await Promise.all(promises);
|
|
770
|
+
}
|
|
527
771
|
async resolveNonce(provider, from, tx) {
|
|
528
772
|
if (tx.nonce != null)
|
|
529
773
|
return tx;
|
|
@@ -548,6 +792,13 @@ var Hermes = class {
|
|
|
548
792
|
}
|
|
549
793
|
return tx;
|
|
550
794
|
}
|
|
795
|
+
async signRequestBody(body, signer) {
|
|
796
|
+
const bodyJson = JSON.stringify(body);
|
|
797
|
+
const encoder = new TextEncoder();
|
|
798
|
+
const requestBodyHash = import_ethers.ethers.keccak256(encoder.encode(bodyJson));
|
|
799
|
+
const signature = await signer.signMessage(requestBodyHash);
|
|
800
|
+
return `${signer.address}:${signature}`;
|
|
801
|
+
}
|
|
551
802
|
sanitizePricing(tx) {
|
|
552
803
|
if (tx.maxFeePerGas != null || tx.maxPriorityFeePerGas != null) {
|
|
553
804
|
const { gasPrice, ...rest } = tx;
|
package/dist/cjs/types.d.ts
CHANGED
|
@@ -5,12 +5,18 @@ export interface IConfig {
|
|
|
5
5
|
quoterAddress: Record<string, string>;
|
|
6
6
|
aggregatorAddress: Record<string, string>;
|
|
7
7
|
hermesSignalDomain?: string;
|
|
8
|
+
flashbotSigner: string;
|
|
8
9
|
}
|
|
9
10
|
export interface IExpectParams {
|
|
10
11
|
chain: ChainNameEnum;
|
|
11
12
|
amountInWei: bigint;
|
|
12
13
|
path: IRouterPath[];
|
|
13
14
|
}
|
|
15
|
+
export interface IBatchExpectParams {
|
|
16
|
+
chain: ChainNameEnum;
|
|
17
|
+
amountInWei: bigint[];
|
|
18
|
+
path: IRouterPath[][];
|
|
19
|
+
}
|
|
14
20
|
export interface ISwapParams {
|
|
15
21
|
user: string;
|
|
16
22
|
chain: ChainNameEnum;
|
|
@@ -18,6 +24,13 @@ export interface ISwapParams {
|
|
|
18
24
|
path: IRouterPath[];
|
|
19
25
|
minAmountOutList: bigint[];
|
|
20
26
|
}
|
|
27
|
+
export interface IBatchMultiSwapParams {
|
|
28
|
+
users: string[];
|
|
29
|
+
chain: ChainNameEnum;
|
|
30
|
+
amountInWeis: bigint[];
|
|
31
|
+
paths: IRouterPath[][];
|
|
32
|
+
minAmountOutLists: bigint[][];
|
|
33
|
+
}
|
|
21
34
|
export interface IBridgeParams {
|
|
22
35
|
chain: ChainNameEnum;
|
|
23
36
|
user: string;
|
|
@@ -51,7 +64,18 @@ export interface IReceipt {
|
|
|
51
64
|
hash: string;
|
|
52
65
|
from: string;
|
|
53
66
|
to: string;
|
|
54
|
-
|
|
67
|
+
}
|
|
68
|
+
export interface IBatchReceipt {
|
|
69
|
+
hash: string;
|
|
70
|
+
from: string;
|
|
71
|
+
to: string | null;
|
|
72
|
+
userResults: Array<{
|
|
73
|
+
user: string;
|
|
74
|
+
amountIn: bigint;
|
|
75
|
+
amountOut: bigint;
|
|
76
|
+
fromToken: string;
|
|
77
|
+
toToken: string;
|
|
78
|
+
}>;
|
|
55
79
|
}
|
|
56
80
|
export interface ICalldata {
|
|
57
81
|
to: string;
|
|
@@ -103,6 +127,7 @@ export declare enum DexType {
|
|
|
103
127
|
CURVE128 = "curve128",
|
|
104
128
|
CURVE256 = "curve256",
|
|
105
129
|
CAMELOTV2 = "camelotv2",
|
|
130
|
+
CAMELOTV3 = "camelotv3",
|
|
106
131
|
PANCAKEV2 = "pancakev2",
|
|
107
132
|
AERODROME = "aerodrome",
|
|
108
133
|
PANCAKEV3 = "pancakev3",
|
|
@@ -405,6 +430,7 @@ export declare const AddressConst: {
|
|
|
405
430
|
};
|
|
406
431
|
xaut: {
|
|
407
432
|
avax: string;
|
|
433
|
+
arb: string;
|
|
408
434
|
};
|
|
409
435
|
link: {
|
|
410
436
|
eth: string;
|
package/dist/cjs/types.js
CHANGED
|
@@ -39,6 +39,7 @@ var DexType = /* @__PURE__ */ ((DexType2) => {
|
|
|
39
39
|
DexType2["CURVE128"] = "curve128";
|
|
40
40
|
DexType2["CURVE256"] = "curve256";
|
|
41
41
|
DexType2["CAMELOTV2"] = "camelotv2";
|
|
42
|
+
DexType2["CAMELOTV3"] = "camelotv3";
|
|
42
43
|
DexType2["PANCAKEV2"] = "pancakev2";
|
|
43
44
|
DexType2["AERODROME"] = "aerodrome";
|
|
44
45
|
DexType2["PANCAKEV3"] = "pancakev3";
|
|
@@ -340,7 +341,8 @@ var AddressConst = {
|
|
|
340
341
|
avax: "0x6EDac263561DA41aDe155a992759260FAFb87B43"
|
|
341
342
|
},
|
|
342
343
|
xaut: {
|
|
343
|
-
avax: "0x2775d5105276781B4b85bA6eA6a6653bEeD1dd32"
|
|
344
|
+
avax: "0x2775d5105276781B4b85bA6eA6a6653bEeD1dd32",
|
|
345
|
+
arb: "0x40461291347e1eCbb09499F3371D3f17f10d7159"
|
|
344
346
|
},
|
|
345
347
|
link: {
|
|
346
348
|
eth: "0x514910771AF9Ca656af840dff83E8264EcF986CA"
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
import type { IExpectParams, ISwapParams, IBridgeParams, ISwapAndBridgeParams, IReceipt, IConfig, IExpectPayload, IRouterPath, SupportContracts } from './types.js';
|
|
1
|
+
import type { IExpectParams, IBatchMultiSwapParams, IBatchExpectParams, ISwapParams, IBridgeParams, IBatchReceipt, ISwapAndBridgeParams, IReceipt, IConfig, IExpectPayload, IRouterPath, SupportContracts } 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 { IExpectParams, ISwapParams, IBridgeParams, ISwapAndBridgeParams, IReceipt, IConfig, IExpectPayload, IRouterPath, SupportContracts };
|
|
4
|
+
export type { IExpectParams, IBatchMultiSwapParams, IBatchExpectParams, IBatchReceipt, ISwapParams, IBridgeParams, ISwapAndBridgeParams, IReceipt, IConfig, IExpectPayload, IRouterPath, SupportContracts, };
|
|
5
5
|
export { ChainNameEnum, AddressConst, DexType, BridgeType, IEstimateType, LayerZeroV1ChainIdMap, LayerZeroV1ChainNameMap, LayerZeroV2ChainIdMap, LayerZeroV2ChainNameMap };
|
|
6
6
|
declare class Hermes {
|
|
7
7
|
private config;
|
|
8
8
|
private providerMap;
|
|
9
9
|
private walletMap;
|
|
10
10
|
private quoterAddressMap;
|
|
11
|
+
private flashbotSigner;
|
|
11
12
|
private aggregatorAddressMap;
|
|
12
13
|
private executor;
|
|
13
14
|
constructor(config: IConfig);
|
|
14
15
|
expectPriorityLocal(params: IExpectParams): Promise<bigint>;
|
|
15
16
|
expect(params: IExpectParams): Promise<bigint>;
|
|
17
|
+
batchMultiExpect(params: IBatchExpectParams): Promise<bigint[]>;
|
|
16
18
|
swap(params: ISwapParams, txReq?: TransactionRequest): Promise<IReceipt>;
|
|
19
|
+
batchMultiSwap(params: IBatchMultiSwapParams, txReq?: TransactionRequest): Promise<IBatchReceipt>;
|
|
20
|
+
swapByFlashbots(params: ISwapParams, txReq?: TransactionRequest, _targetBlockNumber?: number): Promise<IReceipt | null>;
|
|
17
21
|
/**
|
|
18
22
|
* 生成 swap 的 calldata
|
|
19
23
|
*/
|
|
@@ -41,8 +45,10 @@ declare class Hermes {
|
|
|
41
45
|
value: bigint;
|
|
42
46
|
};
|
|
43
47
|
private resolveGasLimit;
|
|
48
|
+
private sendBundle;
|
|
44
49
|
private resolveNonce;
|
|
45
50
|
private resolvePricing;
|
|
51
|
+
private signRequestBody;
|
|
46
52
|
private sanitizePricing;
|
|
47
53
|
private checkIsEnoughToken;
|
|
48
54
|
private validateParams;
|