hermes-swap 0.0.23 → 0.0.25

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.
@@ -1,7 +1,7 @@
1
1
  import type { IExpectParams, ISwapParams, IBridgeParams, ISwapAndBridgeParams, IReceipt, IConfig, IExpectPayload, IRouterPath } from './types.js';
2
- import { ChainNameEnum, AddressConst, DexType } from './types.js';
2
+ import { ChainNameEnum, AddressConst, DexType, BridgeType } from './types.js';
3
3
  export type { IExpectParams, ISwapParams, IBridgeParams, ISwapAndBridgeParams, IReceipt, IConfig, IExpectPayload, IRouterPath };
4
- export { ChainNameEnum, AddressConst, DexType };
4
+ export { ChainNameEnum, AddressConst, DexType, BridgeType };
5
5
  declare class Hermes {
6
6
  private config;
7
7
  private providerMap;
@@ -11,9 +11,24 @@ declare class Hermes {
11
11
  constructor(config: IConfig);
12
12
  expect(params: IExpectParams): Promise<bigint>;
13
13
  swap(params: ISwapParams): Promise<IReceipt>;
14
+ /**
15
+ * 生成 swap 的 calldata
16
+ */
17
+ genSwapCalldata(params: ISwapParams): {
18
+ to: string;
19
+ data: string;
20
+ };
14
21
  bridge(params: IBridgeParams): Promise<IReceipt>;
15
22
  estimateBridgeFee(params: IBridgeParams): Promise<bigint>;
16
23
  swapAndBridge(params: ISwapAndBridgeParams): Promise<IReceipt>;
24
+ /**
25
+ * 生成 swapAndBridge 的 calldata
26
+ */
27
+ genSwapAndBridgeCalldata(params: ISwapAndBridgeParams): {
28
+ to: string;
29
+ data: string;
30
+ value: bigint;
31
+ };
17
32
  private checkIsEnoughToken;
18
33
  private validateParams;
19
34
  private getQuoterAddress;
package/dist/cjs/index.js CHANGED
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  var src_exports = {};
31
31
  __export(src_exports, {
32
32
  AddressConst: () => import_types.AddressConst,
33
+ BridgeType: () => import_types.BridgeType,
33
34
  ChainNameEnum: () => import_types.ChainNameEnum,
34
35
  DexType: () => import_types.DexType,
35
36
  Hermes: () => Hermes,
@@ -79,8 +80,11 @@ var Hermes = class {
79
80
  toCoin: p.toCoinAddress,
80
81
  extra: p.extra || "0x"
81
82
  }));
82
- const amountOutList = await quoter.multiQuote(params.amountInWei, quoteParams);
83
- return amountOutList.length ? amountOutList[amountOutList.length - 1] : BigInt(0);
83
+ const amountOutList = await quoter.multiQuote.staticCall(params.amountInWei, quoteParams, { from: wallet.address });
84
+ if (!amountOutList.length) {
85
+ throw new Error("No expect result return from smart contract");
86
+ }
87
+ return amountOutList[amountOutList.length - 1];
84
88
  }
85
89
  async swap(params) {
86
90
  this.validateParams(params);
@@ -108,13 +112,11 @@ var Hermes = class {
108
112
  throw new Error("Insufficient balance for swap");
109
113
  }
110
114
  const currentAllowance = await erc20.allowance(params.user, aggregatorAddress);
111
- console.log(currentAllowance);
112
115
  if (currentAllowance < params.amountInWei) {
113
116
  throw new Error("Insufficient allowance token amount for swap");
114
117
  }
115
118
  try {
116
119
  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
120
  } catch (error) {
119
121
  console.warn("Aggregator estimateGas.swap failed", error);
120
122
  throw error;
@@ -127,7 +129,6 @@ var Hermes = class {
127
129
  throw error;
128
130
  }
129
131
  const receipt = await txResponse.wait();
130
- console.log(`Swap transaction mined in block ${receipt.blockNumber} (tx: ${receipt.hash})`);
131
132
  const iface = new import_ethers.ethers.Interface(import_aggregator.default);
132
133
  let amountOut = params.amountInWei;
133
134
  for (const log of receipt.logs) {
@@ -152,6 +153,29 @@ var Hermes = class {
152
153
  logs: receipt.logs
153
154
  };
154
155
  }
156
+ /**
157
+ * 生成 swap 的 calldata
158
+ */
159
+ genSwapCalldata(params) {
160
+ this.validateParams(params);
161
+ if (!params.path || params.path.length === 0) {
162
+ throw new Error("Swap path not provided");
163
+ }
164
+ const aggregatorAddress = this.getAggregatorAddress(params.chain);
165
+ const swapParams = params.path.map((pathItem) => ({
166
+ dexType: pathItem.dexType,
167
+ pool: pathItem.poolAddress,
168
+ fromCoin: pathItem.fromCoinAddress,
169
+ toCoin: pathItem.toCoinAddress,
170
+ extra: pathItem.extra ?? "0x"
171
+ }));
172
+ const iface = new import_ethers.ethers.Interface(import_aggregator.default);
173
+ const calldata = iface.encodeFunctionData("swap", [params.user, params.amountInWei, swapParams, params.minAmountOutList]);
174
+ return {
175
+ to: aggregatorAddress,
176
+ data: calldata
177
+ };
178
+ }
155
179
  async bridge(params) {
156
180
  this.validateParams(params);
157
181
  const aggregatorAddress = this.getAggregatorAddress(params.chain);
@@ -235,17 +259,93 @@ var Hermes = class {
235
259
  }
236
260
  async swapAndBridge(params) {
237
261
  this.validateParams(params);
262
+ const aggregatorAddress = this.getAggregatorAddress(params.chain);
263
+ const wallet = this.walletMap.get(params.chain);
264
+ if (!wallet) {
265
+ throw new Error(`Wallet not configured for chain: ${params.chain}`);
266
+ }
267
+ const fromCoinAddress = params.path[0].fromCoinAddress;
268
+ if (fromCoinAddress && fromCoinAddress !== import_ethers.ethers.ZeroAddress) {
269
+ await this.checkIsEnoughToken(fromCoinAddress, params.user, params.amountInWei, aggregatorAddress, wallet);
270
+ }
271
+ const swapParams = params.path.map((pathItem) => ({
272
+ dexType: pathItem.dexType,
273
+ pool: pathItem.poolAddress,
274
+ fromCoin: pathItem.fromCoinAddress,
275
+ toCoin: pathItem.toCoinAddress,
276
+ extra: pathItem.extra ?? "0x"
277
+ }));
278
+ const bridgeArgs = {
279
+ bridge: params.bridgeType,
280
+ token: params.tokenAddress,
281
+ amount: params.amountInWei,
282
+ bridgeAddress: params.bridgeAddress,
283
+ destChain: params.destChain,
284
+ destUser: params.destUser,
285
+ extra: params.extra ?? "0x"
286
+ };
287
+ const txOverrides = {
288
+ from: wallet.address,
289
+ value: params.bridgeFee
290
+ };
291
+ const aggregator = new import_ethers2.Contract(aggregatorAddress, import_aggregator.default, wallet);
292
+ try {
293
+ await aggregator.swapAndBridge.estimateGas(params.user, params.amountInWei, swapParams, params.minAmountOutList, bridgeArgs, txOverrides);
294
+ } catch (error) {
295
+ console.error("Bridge gas estimation reverted", error);
296
+ throw error;
297
+ }
298
+ let txResponse;
299
+ try {
300
+ txResponse = await aggregator.swapAndBridge(params.user, params.amountInWei, swapParams, params.minAmountOutList, bridgeArgs, txOverrides);
301
+ } catch (error) {
302
+ console.error("Aggregator swap and bridge transaction failed", error);
303
+ throw error;
304
+ }
238
305
  const receipt = {
239
306
  fromToken: params.path[0].fromCoinAddress,
240
307
  toToken: params.path[params.path.length - 1].toCoinAddress,
241
308
  amountOut: params.minAmountOutList[params.minAmountOutList.length - 1],
242
- hash: "",
243
- from: "",
244
- to: "",
245
- logs: []
309
+ hash: txResponse.hash,
310
+ from: txResponse.from,
311
+ to: txResponse.to,
312
+ logs: txResponse.logs
246
313
  };
247
314
  return Promise.resolve(receipt);
248
315
  }
316
+ /**
317
+ * 生成 swapAndBridge 的 calldata
318
+ */
319
+ genSwapAndBridgeCalldata(params) {
320
+ this.validateParams(params);
321
+ if (!params.path || params.path.length === 0) {
322
+ throw new Error("Swap path not provided");
323
+ }
324
+ const aggregatorAddress = this.getAggregatorAddress(params.chain);
325
+ const swapParams = params.path.map((pathItem) => ({
326
+ dexType: pathItem.dexType,
327
+ pool: pathItem.poolAddress,
328
+ fromCoin: pathItem.fromCoinAddress,
329
+ toCoin: pathItem.toCoinAddress,
330
+ extra: pathItem.extra ?? "0x"
331
+ }));
332
+ const bridgeParam = {
333
+ bridge: params.bridgeType,
334
+ token: params.tokenAddress,
335
+ amount: params.amountInWei,
336
+ bridgeAddress: params.bridgeAddress,
337
+ destChain: params.destChain,
338
+ destUser: params.destUser,
339
+ extra: params.extra ?? "0x"
340
+ };
341
+ const iface = new import_ethers.ethers.Interface(import_aggregator.default);
342
+ const calldata = iface.encodeFunctionData("swapAndBridge", [params.user, params.amountInWei, swapParams, params.minAmountOutList, bridgeParam]);
343
+ return {
344
+ to: aggregatorAddress,
345
+ data: calldata,
346
+ value: params.bridgeFee
347
+ };
348
+ }
249
349
  async checkIsEnoughToken(fromTokenAddress, userAddress, amountInWei, aggregatorAddress, wallet) {
250
350
  const erc20 = new import_ethers2.Contract(fromTokenAddress, ["function balanceOf(address) view returns (uint256)", "function allowance(address, address) view returns (uint256)"], wallet);
251
351
  const userBalance = await erc20.balanceOf(userAddress);
@@ -284,6 +384,7 @@ var src_default = Hermes;
284
384
  // Annotate the CommonJS export names for ESM import in node:
285
385
  0 && (module.exports = {
286
386
  AddressConst,
387
+ BridgeType,
287
388
  ChainNameEnum,
288
389
  DexType,
289
390
  Hermes
@@ -90,6 +90,10 @@ export declare enum DexType {
90
90
  CURVE128 = "curve128",
91
91
  CURVE256 = "curve256"
92
92
  }
93
+ export declare enum BridgeType {
94
+ LAYERZEROV1 = "layerzero_v1",
95
+ LAYERZEROV2 = "layerzero_v2"
96
+ }
93
97
  export declare enum ChainNameEnum {
94
98
  ETH = "ETH",// Ethereum Mainnet
95
99
  ARB = "ARB",// Arbitrum One
@@ -252,15 +256,18 @@ export interface IRpcConfig {
252
256
  export declare const AddressConst: {
253
257
  weth: {
254
258
  eth: string;
259
+ arb: string;
255
260
  };
256
261
  usdt: {
257
262
  eth: string;
258
263
  };
259
264
  feth: {
260
265
  eth: string;
266
+ arb: string;
261
267
  };
262
268
  xeth: {
263
269
  eth: string;
270
+ arb: string;
264
271
  };
265
272
  arb: {
266
273
  arb: string;
package/dist/cjs/types.js CHANGED
@@ -20,6 +20,7 @@ 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
  });
@@ -31,6 +32,11 @@ var DexType = /* @__PURE__ */ ((DexType2) => {
31
32
  DexType2["CURVE256"] = "curve256";
32
33
  return DexType2;
33
34
  })(DexType || {});
35
+ var BridgeType = /* @__PURE__ */ ((BridgeType2) => {
36
+ BridgeType2["LAYERZEROV1"] = "layerzero_v1";
37
+ BridgeType2["LAYERZEROV2"] = "layerzero_v2";
38
+ return BridgeType2;
39
+ })(BridgeType || {});
34
40
  var ChainNameEnum = /* @__PURE__ */ ((ChainNameEnum2) => {
35
41
  ChainNameEnum2["ETH"] = "ETH";
36
42
  ChainNameEnum2["ARB"] = "ARB";
@@ -189,17 +195,20 @@ var ChainNameEnum = /* @__PURE__ */ ((ChainNameEnum2) => {
189
195
  })(ChainNameEnum || {});
190
196
  var AddressConst = {
191
197
  weth: {
192
- eth: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
198
+ eth: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
199
+ arb: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"
193
200
  },
194
201
  usdt: {
195
202
  eth: ""
196
203
  },
197
204
  // fx
198
205
  feth: {
199
- eth: "0x53805A76E1f5ebbFE7115F16f9c87C2f7e633726"
206
+ eth: "0x53805A76E1f5ebbFE7115F16f9c87C2f7e633726",
207
+ arb: "0xc608Dfb90A430Df79a8a1eDBC8be7f1A0Eb4E763"
200
208
  },
201
209
  xeth: {
202
- eth: "0xe063F04f280c60aECa68b38341C2eEcBeC703ae2"
210
+ eth: "0xe063F04f280c60aECa68b38341C2eEcBeC703ae2",
211
+ arb: "0x55380fe7A1910dFf29A47B622057ab4139DA42C5"
203
212
  },
204
213
  arb: {
205
214
  arb: "0x912CE59144191C1204E64559FE8253a0e49E6548"
@@ -211,6 +220,7 @@ var AddressConst = {
211
220
  // Annotate the CommonJS export names for ESM import in node:
212
221
  0 && (module.exports = {
213
222
  AddressConst,
223
+ BridgeType,
214
224
  ChainNameEnum,
215
225
  DexType
216
226
  });
@@ -1,7 +1,7 @@
1
1
  import type { IExpectParams, ISwapParams, IBridgeParams, ISwapAndBridgeParams, IReceipt, IConfig, IExpectPayload, IRouterPath } from './types.js';
2
- import { ChainNameEnum, AddressConst, DexType } from './types.js';
2
+ import { ChainNameEnum, AddressConst, DexType, BridgeType } from './types.js';
3
3
  export type { IExpectParams, ISwapParams, IBridgeParams, ISwapAndBridgeParams, IReceipt, IConfig, IExpectPayload, IRouterPath };
4
- export { ChainNameEnum, AddressConst, DexType };
4
+ export { ChainNameEnum, AddressConst, DexType, BridgeType };
5
5
  declare class Hermes {
6
6
  private config;
7
7
  private providerMap;
@@ -11,9 +11,24 @@ declare class Hermes {
11
11
  constructor(config: IConfig);
12
12
  expect(params: IExpectParams): Promise<bigint>;
13
13
  swap(params: ISwapParams): Promise<IReceipt>;
14
+ /**
15
+ * 生成 swap 的 calldata
16
+ */
17
+ genSwapCalldata(params: ISwapParams): {
18
+ to: string;
19
+ data: string;
20
+ };
14
21
  bridge(params: IBridgeParams): Promise<IReceipt>;
15
22
  estimateBridgeFee(params: IBridgeParams): Promise<bigint>;
16
23
  swapAndBridge(params: ISwapAndBridgeParams): Promise<IReceipt>;
24
+ /**
25
+ * 生成 swapAndBridge 的 calldata
26
+ */
27
+ genSwapAndBridgeCalldata(params: ISwapAndBridgeParams): {
28
+ to: string;
29
+ data: string;
30
+ value: bigint;
31
+ };
17
32
  private checkIsEnoughToken;
18
33
  private validateParams;
19
34
  private getQuoterAddress;
package/dist/esm/index.js CHANGED
@@ -15,7 +15,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
15
15
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
16
16
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
17
17
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
18
- import { ChainNameEnum, AddressConst, DexType } from "./types.js";
18
+ import { ChainNameEnum, AddressConst, DexType, BridgeType } from "./types.js";
19
19
  import { ethers } from 'ethers';
20
20
  import { Contract } from 'ethers';
21
21
  import QuoterAbi from "./abis/quoter.js";
@@ -23,7 +23,7 @@ import AggregatorAbi from "./abis/aggregator.js";
23
23
 
24
24
  // 导出所有类型定义,方便用户使用
25
25
 
26
- export { ChainNameEnum, AddressConst, DexType };
26
+ export { ChainNameEnum, AddressConst, DexType, BridgeType };
27
27
  var Hermes = /*#__PURE__*/function () {
28
28
  function Hermes(config) {
29
29
  _classCallCheck(this, Hermes);
@@ -90,11 +90,19 @@ var Hermes = /*#__PURE__*/function () {
90
90
  };
91
91
  });
92
92
  _context.next = 10;
93
- return quoter.multiQuote(params.amountInWei, quoteParams);
93
+ return quoter.multiQuote.staticCall(params.amountInWei, quoteParams, {
94
+ from: wallet.address
95
+ });
94
96
  case 10:
95
97
  amountOutList = _context.sent;
96
- return _context.abrupt("return", amountOutList.length ? amountOutList[amountOutList.length - 1] : BigInt(0));
97
- case 12:
98
+ if (amountOutList.length) {
99
+ _context.next = 13;
100
+ break;
101
+ }
102
+ throw new Error('No expect result return from smart contract');
103
+ case 13:
104
+ return _context.abrupt("return", amountOutList[amountOutList.length - 1]);
105
+ case 14:
98
106
  case "end":
99
107
  return _context.stop();
100
108
  }
@@ -156,93 +164,90 @@ var Hermes = /*#__PURE__*/function () {
156
164
  return erc20.allowance(params.user, aggregatorAddress);
157
165
  case 19:
158
166
  currentAllowance = _context2.sent;
159
- console.log(currentAllowance);
160
167
  if (!(currentAllowance < params.amountInWei)) {
161
- _context2.next = 23;
168
+ _context2.next = 22;
162
169
  break;
163
170
  }
164
171
  throw new Error('Insufficient allowance token amount for swap');
165
- case 23:
166
- _context2.prev = 23;
167
- _context2.next = 26;
172
+ case 22:
173
+ _context2.prev = 22;
174
+ _context2.next = 25;
168
175
  return aggregator.getFunction('swap').estimateGas(params.user, params.amountInWei, swapParams, params.minAmountOutList, {
169
176
  from: wallet.address
170
177
  });
171
- case 26:
178
+ case 25:
172
179
  gas = _context2.sent;
173
- console.log("Estimated gas for swap: ".concat(BigInt(gas).toString()));
174
- _context2.next = 34;
180
+ _context2.next = 32;
175
181
  break;
176
- case 30:
177
- _context2.prev = 30;
178
- _context2.t0 = _context2["catch"](23);
182
+ case 28:
183
+ _context2.prev = 28;
184
+ _context2.t0 = _context2["catch"](22);
179
185
  console.warn('Aggregator estimateGas.swap failed', _context2.t0);
180
186
  throw _context2.t0;
181
- case 34:
182
- _context2.prev = 34;
183
- _context2.next = 37;
187
+ case 32:
188
+ _context2.prev = 32;
189
+ _context2.next = 35;
184
190
  return aggregator.getFunction('swap')(params.user, params.amountInWei, swapParams, params.minAmountOutList, {
185
191
  from: wallet.address
186
192
  });
187
- case 37:
193
+ case 35:
188
194
  txResponse = _context2.sent;
189
- _context2.next = 44;
195
+ _context2.next = 42;
190
196
  break;
191
- case 40:
192
- _context2.prev = 40;
193
- _context2.t1 = _context2["catch"](34);
197
+ case 38:
198
+ _context2.prev = 38;
199
+ _context2.t1 = _context2["catch"](32);
194
200
  console.error('Aggregator swap transaction failed', _context2.t1);
195
201
  throw _context2.t1;
196
- case 44:
197
- _context2.next = 46;
202
+ case 42:
203
+ _context2.next = 44;
198
204
  return txResponse.wait();
199
- case 46:
205
+ case 44:
200
206
  receipt = _context2.sent;
201
- console.log("Swap transaction mined in block ".concat(receipt.blockNumber, " (tx: ").concat(receipt.hash, ")"));
202
207
  iface = new ethers.Interface(AggregatorAbi);
203
208
  amountOut = params.amountInWei;
204
209
  _iterator = _createForOfIteratorHelper(receipt.logs);
205
- _context2.prev = 51;
210
+ _context2.prev = 48;
206
211
  _iterator.s();
207
- case 53:
212
+ case 50:
208
213
  if ((_step = _iterator.n()).done) {
209
- _context2.next = 67;
214
+ _context2.next = 64;
210
215
  break;
211
216
  }
212
217
  log = _step.value;
213
218
  if (!(log.address.toLowerCase() === aggregatorAddress.toLowerCase())) {
214
- _context2.next = 65;
219
+ _context2.next = 62;
215
220
  break;
216
221
  }
217
- _context2.prev = 56;
222
+ _context2.prev = 53;
218
223
  parsed = iface.parseLog(log);
219
224
  if (!(parsed && parsed.name === 'Swapped' && parsed.args && parsed.args.amountOut !== undefined)) {
220
- _context2.next = 61;
225
+ _context2.next = 58;
221
226
  break;
222
227
  }
223
228
  amountOut = parsed.args.amountOut;
224
- return _context2.abrupt("break", 67);
225
- case 61:
226
- _context2.next = 65;
229
+ return _context2.abrupt("break", 64);
230
+ case 58:
231
+ _context2.next = 62;
227
232
  break;
228
- case 63:
229
- _context2.prev = 63;
230
- _context2.t2 = _context2["catch"](56);
231
- case 65:
232
- _context2.next = 53;
233
+ case 60:
234
+ _context2.prev = 60;
235
+ _context2.t2 = _context2["catch"](53);
236
+ case 62:
237
+ _context2.next = 50;
233
238
  break;
234
- case 67:
235
- _context2.next = 72;
239
+ case 64:
240
+ _context2.next = 69;
236
241
  break;
242
+ case 66:
243
+ _context2.prev = 66;
244
+ _context2.t3 = _context2["catch"](48);
245
+ _iterator.e(_context2.t3);
237
246
  case 69:
238
247
  _context2.prev = 69;
239
- _context2.t3 = _context2["catch"](51);
240
- _iterator.e(_context2.t3);
241
- case 72:
242
- _context2.prev = 72;
243
248
  _iterator.f();
244
- return _context2.finish(72);
245
- case 75:
249
+ return _context2.finish(69);
250
+ case 72:
246
251
  return _context2.abrupt("return", {
247
252
  fromToken: fromTokenAddress,
248
253
  toToken: toTokenAddress,
@@ -252,17 +257,50 @@ var Hermes = /*#__PURE__*/function () {
252
257
  to: receipt.from,
253
258
  logs: receipt.logs
254
259
  });
255
- case 76:
260
+ case 73:
256
261
  case "end":
257
262
  return _context2.stop();
258
263
  }
259
- }, _callee2, this, [[23, 30], [34, 40], [51, 69, 72, 75], [56, 63]]);
264
+ }, _callee2, this, [[22, 28], [32, 38], [48, 66, 69, 72], [53, 60]]);
260
265
  }));
261
266
  function swap(_x2) {
262
267
  return _swap.apply(this, arguments);
263
268
  }
264
269
  return swap;
265
270
  }()
271
+ /**
272
+ * 生成 swap 的 calldata
273
+ */
274
+ }, {
275
+ key: "genSwapCalldata",
276
+ value: function genSwapCalldata(params) {
277
+ this.validateParams(params);
278
+ if (!params.path || params.path.length === 0) {
279
+ throw new Error('Swap path not provided');
280
+ }
281
+ var aggregatorAddress = this.getAggregatorAddress(params.chain);
282
+
283
+ // 准备 swap 参数
284
+ var swapParams = params.path.map(function (pathItem) {
285
+ var _pathItem$extra2;
286
+ return {
287
+ dexType: pathItem.dexType,
288
+ pool: pathItem.poolAddress,
289
+ fromCoin: pathItem.fromCoinAddress,
290
+ toCoin: pathItem.toCoinAddress,
291
+ extra: (_pathItem$extra2 = pathItem.extra) !== null && _pathItem$extra2 !== void 0 ? _pathItem$extra2 : '0x'
292
+ };
293
+ });
294
+
295
+ // 使用 ethers Interface 编码 calldata
296
+ // 参数顺序: user, amountIn, swapParams, minAmountOutList
297
+ var iface = new ethers.Interface(AggregatorAbi);
298
+ var calldata = iface.encodeFunctionData('swap', [params.user, params.amountInWei, swapParams, params.minAmountOutList]);
299
+ return {
300
+ to: aggregatorAddress,
301
+ data: calldata
302
+ };
303
+ }
266
304
  }, {
267
305
  key: "bridge",
268
306
  value: function () {
@@ -427,32 +465,147 @@ var Hermes = /*#__PURE__*/function () {
427
465
  key: "swapAndBridge",
428
466
  value: function () {
429
467
  var _swapAndBridge = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(params) {
430
- var receipt;
468
+ var _params$extra3;
469
+ var aggregatorAddress, wallet, fromCoinAddress, swapParams, bridgeArgs, txOverrides, aggregator, txResponse, receipt;
431
470
  return _regeneratorRuntime().wrap(function _callee5$(_context5) {
432
471
  while (1) switch (_context5.prev = _context5.next) {
433
472
  case 0:
434
473
  this.validateParams(params);
474
+
475
+ // call the aggregator swap and bridge
476
+ aggregatorAddress = this.getAggregatorAddress(params.chain);
477
+ wallet = this.walletMap.get(params.chain);
478
+ if (wallet) {
479
+ _context5.next = 5;
480
+ break;
481
+ }
482
+ throw new Error("Wallet not configured for chain: ".concat(params.chain));
483
+ case 5:
484
+ fromCoinAddress = params.path[0].fromCoinAddress;
485
+ if (!(fromCoinAddress && fromCoinAddress !== ethers.ZeroAddress)) {
486
+ _context5.next = 9;
487
+ break;
488
+ }
489
+ _context5.next = 9;
490
+ return this.checkIsEnoughToken(fromCoinAddress, params.user, params.amountInWei, aggregatorAddress, wallet);
491
+ case 9:
492
+ // 准备合约参数
493
+ swapParams = params.path.map(function (pathItem) {
494
+ var _pathItem$extra3;
495
+ return {
496
+ dexType: pathItem.dexType,
497
+ pool: pathItem.poolAddress,
498
+ fromCoin: pathItem.fromCoinAddress,
499
+ toCoin: pathItem.toCoinAddress,
500
+ extra: (_pathItem$extra3 = pathItem.extra) !== null && _pathItem$extra3 !== void 0 ? _pathItem$extra3 : '0x'
501
+ };
502
+ });
503
+ bridgeArgs = {
504
+ bridge: params.bridgeType,
505
+ token: params.tokenAddress,
506
+ amount: params.amountInWei,
507
+ bridgeAddress: params.bridgeAddress,
508
+ destChain: params.destChain,
509
+ destUser: params.destUser,
510
+ extra: (_params$extra3 = params.extra) !== null && _params$extra3 !== void 0 ? _params$extra3 : '0x'
511
+ };
512
+ txOverrides = {
513
+ from: wallet.address,
514
+ value: params.bridgeFee
515
+ }; // simulate
516
+ aggregator = new Contract(aggregatorAddress, AggregatorAbi, wallet);
517
+ _context5.prev = 13;
518
+ _context5.next = 16;
519
+ return aggregator.swapAndBridge.estimateGas(params.user, params.amountInWei, swapParams, params.minAmountOutList, bridgeArgs, txOverrides);
520
+ case 16:
521
+ _context5.next = 22;
522
+ break;
523
+ case 18:
524
+ _context5.prev = 18;
525
+ _context5.t0 = _context5["catch"](13);
526
+ console.error('Bridge gas estimation reverted', _context5.t0);
527
+ throw _context5.t0;
528
+ case 22:
529
+ _context5.prev = 22;
530
+ _context5.next = 25;
531
+ return aggregator.swapAndBridge(params.user, params.amountInWei, swapParams, params.minAmountOutList, bridgeArgs, txOverrides);
532
+ case 25:
533
+ txResponse = _context5.sent;
534
+ _context5.next = 32;
535
+ break;
536
+ case 28:
537
+ _context5.prev = 28;
538
+ _context5.t1 = _context5["catch"](22);
539
+ console.error('Aggregator swap and bridge transaction failed', _context5.t1);
540
+ throw _context5.t1;
541
+ case 32:
435
542
  receipt = {
436
543
  fromToken: params.path[0].fromCoinAddress,
437
544
  toToken: params.path[params.path.length - 1].toCoinAddress,
438
545
  amountOut: params.minAmountOutList[params.minAmountOutList.length - 1],
439
- hash: '',
440
- from: '',
441
- to: '',
442
- logs: []
546
+ hash: txResponse.hash,
547
+ from: txResponse.from,
548
+ to: txResponse.to,
549
+ logs: txResponse.logs
443
550
  };
444
551
  return _context5.abrupt("return", Promise.resolve(receipt));
445
- case 3:
552
+ case 34:
446
553
  case "end":
447
554
  return _context5.stop();
448
555
  }
449
- }, _callee5, this);
556
+ }, _callee5, this, [[13, 18], [22, 28]]);
450
557
  }));
451
558
  function swapAndBridge(_x5) {
452
559
  return _swapAndBridge.apply(this, arguments);
453
560
  }
454
561
  return swapAndBridge;
455
562
  }()
563
+ /**
564
+ * 生成 swapAndBridge 的 calldata
565
+ */
566
+ }, {
567
+ key: "genSwapAndBridgeCalldata",
568
+ value: function genSwapAndBridgeCalldata(params) {
569
+ var _params$extra4;
570
+ this.validateParams(params);
571
+ if (!params.path || params.path.length === 0) {
572
+ throw new Error('Swap path not provided');
573
+ }
574
+ var aggregatorAddress = this.getAggregatorAddress(params.chain);
575
+
576
+ // 准备 swap 参数
577
+ var swapParams = params.path.map(function (pathItem) {
578
+ var _pathItem$extra4;
579
+ return {
580
+ dexType: pathItem.dexType,
581
+ pool: pathItem.poolAddress,
582
+ fromCoin: pathItem.fromCoinAddress,
583
+ toCoin: pathItem.toCoinAddress,
584
+ extra: (_pathItem$extra4 = pathItem.extra) !== null && _pathItem$extra4 !== void 0 ? _pathItem$extra4 : '0x'
585
+ };
586
+ });
587
+
588
+ // 准备 bridge 参数(对应合约中的 BridgeParam struct)
589
+ var bridgeParam = {
590
+ bridge: params.bridgeType,
591
+ token: params.tokenAddress,
592
+ amount: params.amountInWei,
593
+ bridgeAddress: params.bridgeAddress,
594
+ destChain: params.destChain,
595
+ destUser: params.destUser,
596
+ extra: (_params$extra4 = params.extra) !== null && _params$extra4 !== void 0 ? _params$extra4 : '0x'
597
+ };
598
+
599
+ // 使用 ethers Interface 编码 calldata
600
+ // 参数顺序: user, amountIn, swapParams, minAmountOutList, bridgeParam
601
+ var iface = new ethers.Interface(AggregatorAbi);
602
+ var calldata = iface.encodeFunctionData('swapAndBridge', [params.user, params.amountInWei, swapParams, params.minAmountOutList, bridgeParam]);
603
+ return {
604
+ to: aggregatorAddress,
605
+ data: calldata,
606
+ value: params.bridgeFee
607
+ };
608
+ }
456
609
  }, {
457
610
  key: "checkIsEnoughToken",
458
611
  value: function () {
@@ -90,6 +90,10 @@ export declare enum DexType {
90
90
  CURVE128 = "curve128",
91
91
  CURVE256 = "curve256"
92
92
  }
93
+ export declare enum BridgeType {
94
+ LAYERZEROV1 = "layerzero_v1",
95
+ LAYERZEROV2 = "layerzero_v2"
96
+ }
93
97
  export declare enum ChainNameEnum {
94
98
  ETH = "ETH",// Ethereum Mainnet
95
99
  ARB = "ARB",// Arbitrum One
@@ -252,15 +256,18 @@ export interface IRpcConfig {
252
256
  export declare const AddressConst: {
253
257
  weth: {
254
258
  eth: string;
259
+ arb: string;
255
260
  };
256
261
  usdt: {
257
262
  eth: string;
258
263
  };
259
264
  feth: {
260
265
  eth: string;
266
+ arb: string;
261
267
  };
262
268
  xeth: {
263
269
  eth: string;
270
+ arb: string;
264
271
  };
265
272
  arb: {
266
273
  arb: string;
package/dist/esm/types.js CHANGED
@@ -5,6 +5,11 @@ export var DexType = /*#__PURE__*/function (DexType) {
5
5
  DexType["CURVE256"] = "curve256";
6
6
  return DexType;
7
7
  }({});
8
+ export var BridgeType = /*#__PURE__*/function (BridgeType) {
9
+ BridgeType["LAYERZEROV1"] = "layerzero_v1";
10
+ BridgeType["LAYERZEROV2"] = "layerzero_v2";
11
+ return BridgeType;
12
+ }({});
8
13
  export var ChainNameEnum = /*#__PURE__*/function (ChainNameEnum) {
9
14
  ChainNameEnum["ETH"] = "ETH";
10
15
  ChainNameEnum["ARB"] = "ARB";
@@ -163,17 +168,20 @@ export var ChainNameEnum = /*#__PURE__*/function (ChainNameEnum) {
163
168
  }({}); // BEVM
164
169
  export var AddressConst = {
165
170
  weth: {
166
- eth: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'
171
+ eth: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
172
+ arb: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1'
167
173
  },
168
174
  usdt: {
169
175
  eth: ''
170
176
  },
171
177
  // fx
172
178
  feth: {
173
- eth: '0x53805A76E1f5ebbFE7115F16f9c87C2f7e633726'
179
+ eth: '0x53805A76E1f5ebbFE7115F16f9c87C2f7e633726',
180
+ arb: '0xc608Dfb90A430Df79a8a1eDBC8be7f1A0Eb4E763'
174
181
  },
175
182
  xeth: {
176
- eth: '0xe063F04f280c60aECa68b38341C2eEcBeC703ae2'
183
+ eth: '0xe063F04f280c60aECa68b38341C2eEcBeC703ae2',
184
+ arb: '0x55380fe7A1910dFf29A47B622057ab4139DA42C5'
177
185
  },
178
186
  arb: {
179
187
  arb: '0x912CE59144191C1204E64559FE8253a0e49E6548'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hermes-swap",
3
- "version": "0.0.23",
3
+ "version": "0.0.25",
4
4
  "description": "A TypeScript utility library for swap and bridge",
5
5
  "type": "module",
6
6
  "main": "dist/esm/index.js",