hermes-swap 0.0.22 → 0.0.24

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.
@@ -40,41 +40,22 @@ declare const QuoterAbi: ({
40
40
  inputs: {
41
41
  name: string;
42
42
  type: string;
43
- internalType: string;
44
- components: ({
45
- name: string;
46
- type: string;
47
- internalType: string;
48
- components?: undefined;
49
- } | {
50
- name: string;
51
- type: string;
52
- internalType: string;
53
- components: {
54
- name: string;
55
- type: string;
56
- internalType: string;
57
- }[];
58
- })[];
59
- }[];
60
- outputs: {
61
- name: string;
62
- type: string;
43
+ indexed: boolean;
63
44
  internalType: string;
64
45
  }[];
65
- stateMutability: string;
66
- anonymous?: undefined;
46
+ anonymous: boolean;
47
+ stateMutability?: undefined;
48
+ outputs?: undefined;
67
49
  } | {
68
50
  type: string;
69
51
  name: string;
70
52
  inputs: {
71
53
  name: string;
72
54
  type: string;
73
- indexed: boolean;
74
55
  internalType: string;
75
56
  }[];
76
- anonymous: boolean;
77
57
  stateMutability?: undefined;
78
58
  outputs?: undefined;
59
+ anonymous?: undefined;
79
60
  })[];
80
61
  export default QuoterAbi;
@@ -106,7 +106,7 @@ var QuoterAbi = [
106
106
  internalType: "uint256[][]"
107
107
  }
108
108
  ],
109
- stateMutability: "view"
109
+ stateMutability: "nonpayable"
110
110
  },
111
111
  {
112
112
  type: "function",
@@ -194,7 +194,7 @@ var QuoterAbi = [
194
194
  internalType: "bool"
195
195
  }
196
196
  ],
197
- stateMutability: "view"
197
+ stateMutability: "nonpayable"
198
198
  },
199
199
  {
200
200
  type: "function",
@@ -264,7 +264,7 @@ var QuoterAbi = [
264
264
  internalType: "uint256[]"
265
265
  }
266
266
  ],
267
- stateMutability: "view"
267
+ stateMutability: "nonpayable"
268
268
  },
269
269
  {
270
270
  type: "function",
@@ -328,16 +328,16 @@ var QuoterAbi = [
328
328
  internalType: "uint256"
329
329
  }
330
330
  ],
331
- stateMutability: "view"
331
+ stateMutability: "nonpayable"
332
332
  },
333
333
  {
334
334
  type: "function",
335
335
  name: "quoteBridge",
336
336
  inputs: [
337
337
  {
338
- name: "bridgeParams",
338
+ name: "bridgeParam",
339
339
  type: "tuple",
340
- internalType: "struct BridgeParams",
340
+ internalType: "struct BridgeParam",
341
341
  components: [
342
342
  {
343
343
  name: "bridge",
@@ -345,41 +345,34 @@ var QuoterAbi = [
345
345
  internalType: "string"
346
346
  },
347
347
  {
348
- name: "bridgeParam",
349
- type: "tuple",
350
- internalType: "struct BridgeParam",
351
- components: [
352
- {
353
- name: "token",
354
- type: "address",
355
- internalType: "address"
356
- },
357
- {
358
- name: "amount",
359
- type: "uint256",
360
- internalType: "uint256"
361
- },
362
- {
363
- name: "bridgeAddress",
364
- type: "address",
365
- internalType: "address"
366
- },
367
- {
368
- name: "refundAddress",
369
- type: "address",
370
- internalType: "address"
371
- },
372
- {
373
- name: "destinationChain",
374
- type: "string",
375
- internalType: "string"
376
- },
377
- {
378
- name: "adapterParams",
379
- type: "bytes",
380
- internalType: "bytes"
381
- }
382
- ]
348
+ name: "token",
349
+ type: "address",
350
+ internalType: "address"
351
+ },
352
+ {
353
+ name: "amount",
354
+ type: "uint256",
355
+ internalType: "uint256"
356
+ },
357
+ {
358
+ name: "bridgeAddress",
359
+ type: "address",
360
+ internalType: "address"
361
+ },
362
+ {
363
+ name: "destChain",
364
+ type: "string",
365
+ internalType: "string"
366
+ },
367
+ {
368
+ name: "destUser",
369
+ type: "address",
370
+ internalType: "address"
371
+ },
372
+ {
373
+ name: "extra",
374
+ type: "bytes",
375
+ internalType: "bytes"
383
376
  }
384
377
  ]
385
378
  }
@@ -391,7 +384,7 @@ var QuoterAbi = [
391
384
  internalType: "uint256"
392
385
  }
393
386
  ],
394
- stateMutability: "view"
387
+ stateMutability: "nonpayable"
395
388
  },
396
389
  {
397
390
  type: "function",
@@ -519,6 +512,38 @@ var QuoterAbi = [
519
512
  }
520
513
  ],
521
514
  anonymous: false
515
+ },
516
+ {
517
+ type: "error",
518
+ name: "NotExecutor",
519
+ inputs: [
520
+ {
521
+ name: "caller",
522
+ type: "address",
523
+ internalType: "address"
524
+ },
525
+ {
526
+ name: "executor",
527
+ type: "address",
528
+ internalType: "address"
529
+ }
530
+ ]
531
+ },
532
+ {
533
+ type: "error",
534
+ name: "NotOwner",
535
+ inputs: [
536
+ {
537
+ name: "caller",
538
+ type: "address",
539
+ internalType: "address"
540
+ },
541
+ {
542
+ name: "owner",
543
+ type: "address",
544
+ internalType: "address"
545
+ }
546
+ ]
522
547
  }
523
548
  ];
524
549
  var quoter_default = QuoterAbi;
@@ -12,7 +12,9 @@ declare class Hermes {
12
12
  expect(params: IExpectParams): Promise<bigint>;
13
13
  swap(params: ISwapParams): Promise<IReceipt>;
14
14
  bridge(params: IBridgeParams): Promise<IReceipt>;
15
+ estimateBridgeFee(params: IBridgeParams): Promise<bigint>;
15
16
  swapAndBridge(params: ISwapAndBridgeParams): Promise<IReceipt>;
17
+ private checkIsEnoughToken;
16
18
  private validateParams;
17
19
  private getQuoterAddress;
18
20
  private getAggregatorAddress;
package/dist/cjs/index.js CHANGED
@@ -79,8 +79,11 @@ var Hermes = class {
79
79
  toCoin: p.toCoinAddress,
80
80
  extra: p.extra || "0x"
81
81
  }));
82
- const amountOutList = await quoter.multiQuote(params.amountInWei, quoteParams);
83
- return amountOutList.length ? amountOutList[amountOutList.length - 1] : BigInt(0);
82
+ const amountOutList = await quoter.multiQuote.staticCall(params.amountInWei, quoteParams, { from: wallet.address });
83
+ if (!amountOutList.length) {
84
+ throw new Error("No expect result return from smart contract");
85
+ }
86
+ return amountOutList[amountOutList.length - 1];
84
87
  }
85
88
  async swap(params) {
86
89
  this.validateParams(params);
@@ -108,13 +111,11 @@ var Hermes = class {
108
111
  throw new Error("Insufficient balance for swap");
109
112
  }
110
113
  const currentAllowance = await erc20.allowance(params.user, aggregatorAddress);
111
- console.log(currentAllowance);
112
114
  if (currentAllowance < params.amountInWei) {
113
115
  throw new Error("Insufficient allowance token amount for swap");
114
116
  }
115
117
  try {
116
118
  const gas = await aggregator.getFunction("swap").estimateGas(params.user, params.amountInWei, swapParams, params.minAmountOutList, { from: wallet.address });
117
- console.log(`Estimated gas for swap: ${BigInt(gas).toString()}`);
118
119
  } catch (error) {
119
120
  console.warn("Aggregator estimateGas.swap failed", error);
120
121
  throw error;
@@ -127,7 +128,6 @@ var Hermes = class {
127
128
  throw error;
128
129
  }
129
130
  const receipt = await txResponse.wait();
130
- console.log(`Swap transaction mined in block ${receipt.blockNumber} (tx: ${receipt.hash})`);
131
131
  const iface = new import_ethers.ethers.Interface(import_aggregator.default);
132
132
  let amountOut = params.amountInWei;
133
133
  for (const log of receipt.logs) {
@@ -154,30 +154,153 @@ var Hermes = class {
154
154
  }
155
155
  async bridge(params) {
156
156
  this.validateParams(params);
157
+ const aggregatorAddress = this.getAggregatorAddress(params.chain);
158
+ const wallet = this.walletMap.get(params.chain);
159
+ if (!wallet) {
160
+ throw new Error(`Wallet not configured for chain: ${params.chain}`);
161
+ }
162
+ if (params.tokenAddress && params.tokenAddress !== import_ethers.ethers.ZeroAddress) {
163
+ await this.checkIsEnoughToken(params.tokenAddress, params.user, params.amountInWei, aggregatorAddress, wallet);
164
+ }
165
+ if (params.bridgeFee > 0n) {
166
+ const provider = this.providerMap.get(params.chain);
167
+ if (!provider) {
168
+ throw new Error(`Provider not configured for chain: ${params.chain}`);
169
+ }
170
+ const nativeBalance = await provider.getBalance(params.user);
171
+ if (nativeBalance < params.bridgeFee) {
172
+ throw new Error("Insufficient native balance for bridge fee");
173
+ }
174
+ }
175
+ const aggregator = new import_ethers2.Contract(aggregatorAddress, import_aggregator.default, wallet);
176
+ const bridgeArgs = {
177
+ bridge: params.bridgeType,
178
+ token: params.tokenAddress,
179
+ amount: params.amountInWei,
180
+ bridgeAddress: params.bridgeAddress,
181
+ destChain: params.destChain,
182
+ destUser: params.destUser,
183
+ extra: params.extra ?? "0x"
184
+ };
185
+ const txOverrides = {
186
+ from: wallet.address,
187
+ value: params.bridgeFee
188
+ };
189
+ try {
190
+ await aggregator.bridge.estimateGas(params.user, bridgeArgs, txOverrides);
191
+ } catch (error) {
192
+ console.error("Bridge gas estimation reverted", error);
193
+ throw error;
194
+ }
195
+ let txResponse;
196
+ try {
197
+ txResponse = await aggregator.bridge(params.user, bridgeArgs, txOverrides);
198
+ } catch (error) {
199
+ console.error("Aggregator swap transaction failed", error);
200
+ throw error;
201
+ }
157
202
  const receipt = {
158
203
  fromToken: params.tokenAddress,
159
204
  toToken: params.tokenAddress,
160
205
  amountOut: params.amountInWei,
161
- hash: "",
162
- from: "",
163
- to: "",
164
- logs: []
206
+ hash: txResponse.hash,
207
+ from: txResponse.from,
208
+ to: txResponse.to,
209
+ logs: txResponse.logs
165
210
  };
166
211
  return Promise.resolve(receipt);
167
212
  }
213
+ async estimateBridgeFee(params) {
214
+ this.validateParams(params);
215
+ const wallet = this.walletMap.get(params.chain);
216
+ if (!wallet) {
217
+ throw new Error(`Wallet not configured for chain: ${params.chain}`);
218
+ }
219
+ const address = this.getQuoterAddress(params.chain);
220
+ if (!address) {
221
+ throw new Error(`Quoter address not found for chain: ${params.chain}`);
222
+ }
223
+ const quoter = new import_ethers2.Contract(address, import_quoter.default, wallet);
224
+ const bridgeArgs = {
225
+ bridge: params.bridgeType,
226
+ token: params.tokenAddress,
227
+ amount: params.amountInWei,
228
+ bridgeAddress: params.bridgeAddress,
229
+ destChain: params.destChain,
230
+ destUser: params.destUser,
231
+ extra: params.extra ?? "0x"
232
+ };
233
+ const bridgeFee = await quoter.quoteBridge.staticCall(bridgeArgs, { from: wallet.address });
234
+ return bridgeFee;
235
+ }
168
236
  async swapAndBridge(params) {
169
237
  this.validateParams(params);
238
+ const aggregatorAddress = this.getAggregatorAddress(params.chain);
239
+ const wallet = this.walletMap.get(params.chain);
240
+ if (!wallet) {
241
+ throw new Error(`Wallet not configured for chain: ${params.chain}`);
242
+ }
243
+ const fromCoinAddress = params.path[0].fromCoinAddress;
244
+ if (fromCoinAddress && fromCoinAddress !== import_ethers.ethers.ZeroAddress) {
245
+ await this.checkIsEnoughToken(fromCoinAddress, params.user, params.amountInWei, aggregatorAddress, wallet);
246
+ }
247
+ const swapParams = params.path.map((pathItem) => ({
248
+ dexType: pathItem.dexType,
249
+ pool: pathItem.poolAddress,
250
+ fromCoin: pathItem.fromCoinAddress,
251
+ toCoin: pathItem.toCoinAddress,
252
+ extra: pathItem.extra ?? "0x"
253
+ }));
254
+ const bridgeArgs = {
255
+ bridge: params.bridgeType,
256
+ token: params.tokenAddress,
257
+ amount: params.amountInWei,
258
+ bridgeAddress: params.bridgeAddress,
259
+ destChain: params.destChain,
260
+ destUser: params.destUser,
261
+ extra: params.extra ?? "0x"
262
+ };
263
+ const txOverrides = {
264
+ from: wallet.address,
265
+ value: params.bridgeFee
266
+ };
267
+ const aggregator = new import_ethers2.Contract(aggregatorAddress, import_aggregator.default, wallet);
268
+ try {
269
+ await aggregator.swapAndBridge.estimateGas(params.user, params.amountInWei, swapParams, params.minAmountOutList, bridgeArgs, txOverrides);
270
+ } catch (error) {
271
+ console.error("Bridge gas estimation reverted", error);
272
+ throw error;
273
+ }
274
+ let txResponse;
275
+ try {
276
+ txResponse = await aggregator.swapAndBridge(params.user, params.amountInWei, swapParams, params.minAmountOutList, bridgeArgs, txOverrides);
277
+ } catch (error) {
278
+ console.error("Aggregator swap and bridge transaction failed", error);
279
+ throw error;
280
+ }
170
281
  const receipt = {
171
282
  fromToken: params.path[0].fromCoinAddress,
172
283
  toToken: params.path[params.path.length - 1].toCoinAddress,
173
284
  amountOut: params.minAmountOutList[params.minAmountOutList.length - 1],
174
- hash: "",
175
- from: "",
176
- to: "",
177
- logs: []
285
+ hash: txResponse.hash,
286
+ from: txResponse.from,
287
+ to: txResponse.to,
288
+ logs: txResponse.logs
178
289
  };
179
290
  return Promise.resolve(receipt);
180
291
  }
292
+ async checkIsEnoughToken(fromTokenAddress, userAddress, amountInWei, aggregatorAddress, wallet) {
293
+ const erc20 = new import_ethers2.Contract(fromTokenAddress, ["function balanceOf(address) view returns (uint256)", "function allowance(address, address) view returns (uint256)"], wallet);
294
+ const userBalance = await erc20.balanceOf(userAddress);
295
+ if (userBalance < amountInWei) {
296
+ throw new Error("Insufficient balance token amount");
297
+ }
298
+ const currentAllowance = await erc20.allowance(userAddress, aggregatorAddress);
299
+ console.log(currentAllowance);
300
+ if (currentAllowance < amountInWei) {
301
+ throw new Error("Insufficient allowance token amount");
302
+ }
303
+ }
181
304
  validateParams(params) {
182
305
  if (!params.chain) {
183
306
  throw new Error("Chain not found");
@@ -24,6 +24,8 @@ export interface IBridgeParams {
24
24
  bridgeAddress: string;
25
25
  tokenAddress: string;
26
26
  destChain: string;
27
+ destUser: string;
28
+ bridgeFee: bigint;
27
29
  extra?: BytesLike;
28
30
  }
29
31
  export interface ISwapAndBridgeParams {
@@ -36,6 +38,8 @@ export interface ISwapAndBridgeParams {
36
38
  bridgeAddress: string;
37
39
  tokenAddress: string;
38
40
  destChain: string;
41
+ destUser: string;
42
+ bridgeFee: bigint;
39
43
  extra?: BytesLike;
40
44
  }
41
45
  export interface IReceipt {
@@ -81,7 +85,14 @@ export interface ILog {
81
85
  args: any[];
82
86
  }
83
87
  export declare enum DexType {
84
- FX = "f(x)"
88
+ FX = "f(x)",
89
+ UNISWAPV2 = "uniswapv2",
90
+ CURVE128 = "curve128",
91
+ CURVE256 = "curve256"
92
+ }
93
+ export declare enum BridgeType {
94
+ LAYERZEROV1 = "layerzero_v1",
95
+ LAYERZEROV2 = "layerzero_v2"
85
96
  }
86
97
  export declare enum ChainNameEnum {
87
98
  ETH = "ETH",// Ethereum Mainnet
@@ -245,15 +256,24 @@ export interface IRpcConfig {
245
256
  export declare const AddressConst: {
246
257
  weth: {
247
258
  eth: string;
259
+ arb: string;
248
260
  };
249
261
  usdt: {
250
262
  eth: string;
251
263
  };
252
264
  feth: {
253
265
  eth: string;
266
+ arb: string;
254
267
  };
255
268
  xeth: {
256
269
  eth: string;
270
+ arb: string;
271
+ };
272
+ arb: {
273
+ arb: string;
274
+ };
275
+ usdc: {
276
+ arb: string;
257
277
  };
258
278
  };
259
279
  export interface IExpectPayload {
package/dist/cjs/types.js CHANGED
@@ -20,14 +20,23 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  var types_exports = {};
21
21
  __export(types_exports, {
22
22
  AddressConst: () => AddressConst,
23
+ BridgeType: () => BridgeType,
23
24
  ChainNameEnum: () => ChainNameEnum,
24
25
  DexType: () => DexType
25
26
  });
26
27
  module.exports = __toCommonJS(types_exports);
27
28
  var DexType = /* @__PURE__ */ ((DexType2) => {
28
29
  DexType2["FX"] = "f(x)";
30
+ DexType2["UNISWAPV2"] = "uniswapv2";
31
+ DexType2["CURVE128"] = "curve128";
32
+ DexType2["CURVE256"] = "curve256";
29
33
  return DexType2;
30
34
  })(DexType || {});
35
+ var BridgeType = /* @__PURE__ */ ((BridgeType2) => {
36
+ BridgeType2["LAYERZEROV1"] = "layerzero_v1";
37
+ BridgeType2["LAYERZEROV2"] = "layerzero_v2";
38
+ return BridgeType2;
39
+ })(BridgeType || {});
31
40
  var ChainNameEnum = /* @__PURE__ */ ((ChainNameEnum2) => {
32
41
  ChainNameEnum2["ETH"] = "ETH";
33
42
  ChainNameEnum2["ARB"] = "ARB";
@@ -186,22 +195,32 @@ var ChainNameEnum = /* @__PURE__ */ ((ChainNameEnum2) => {
186
195
  })(ChainNameEnum || {});
187
196
  var AddressConst = {
188
197
  weth: {
189
- eth: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
198
+ eth: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
199
+ arb: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"
190
200
  },
191
201
  usdt: {
192
202
  eth: ""
193
203
  },
194
204
  // fx
195
205
  feth: {
196
- eth: "0x53805A76E1f5ebbFE7115F16f9c87C2f7e633726"
206
+ eth: "0x53805A76E1f5ebbFE7115F16f9c87C2f7e633726",
207
+ arb: "0xc608Dfb90A430Df79a8a1eDBC8be7f1A0Eb4E763"
197
208
  },
198
209
  xeth: {
199
- eth: "0xe063F04f280c60aECa68b38341C2eEcBeC703ae2"
210
+ eth: "0xe063F04f280c60aECa68b38341C2eEcBeC703ae2",
211
+ arb: "0x55380fe7A1910dFf29A47B622057ab4139DA42C5"
212
+ },
213
+ arb: {
214
+ arb: "0x912CE59144191C1204E64559FE8253a0e49E6548"
215
+ },
216
+ usdc: {
217
+ arb: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
200
218
  }
201
219
  };
202
220
  // Annotate the CommonJS export names for ESM import in node:
203
221
  0 && (module.exports = {
204
222
  AddressConst,
223
+ BridgeType,
205
224
  ChainNameEnum,
206
225
  DexType
207
226
  });