@lifi/sdk 1.6.4 → 1.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.
Files changed (82) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/Lifi.d.ts +1 -1
  3. package/dist/Lifi.js +5 -5
  4. package/dist/{cjs/execution/allowance.execute.d.ts → allowance/checkAllowance.d.ts} +1 -1
  5. package/dist/{execution/allowance.execute.js → allowance/checkAllowance.js} +1 -0
  6. package/dist/allowance/index.d.ts +2 -22
  7. package/dist/allowance/index.js +2 -68
  8. package/dist/allowance/tokenApproval.d.ts +22 -0
  9. package/dist/allowance/tokenApproval.js +68 -0
  10. package/dist/balance/checkBalance.d.ts +3 -0
  11. package/dist/{execution/balanceCheck.execute.js → balance/checkBalance.js} +12 -6
  12. package/dist/balance/getTokenBalance.d.ts +8 -0
  13. package/dist/{balances/index.js → balance/getTokenBalance.js} +3 -8
  14. package/dist/balance/index.d.ts +2 -0
  15. package/dist/balance/index.js +2 -0
  16. package/dist/{balances → balance}/utils.d.ts +0 -0
  17. package/dist/{balances → balance}/utils.js +1 -1
  18. package/dist/cjs/Lifi.d.ts +1 -1
  19. package/dist/cjs/Lifi.js +28 -5
  20. package/dist/{execution/allowance.execute.d.ts → cjs/allowance/checkAllowance.d.ts} +1 -1
  21. package/dist/cjs/{execution/allowance.execute.js → allowance/checkAllowance.js} +1 -0
  22. package/dist/cjs/allowance/index.d.ts +2 -22
  23. package/dist/cjs/allowance/index.js +15 -75
  24. package/dist/cjs/allowance/tokenApproval.d.ts +22 -0
  25. package/dist/cjs/allowance/tokenApproval.js +78 -0
  26. package/dist/cjs/balance/checkBalance.d.ts +3 -0
  27. package/dist/cjs/{execution/balanceCheck.execute.js → balance/checkBalance.js} +13 -7
  28. package/dist/cjs/balance/getTokenBalance.d.ts +8 -0
  29. package/dist/cjs/{balances/index.js → balance/getTokenBalance.js} +6 -7
  30. package/dist/cjs/balance/index.d.ts +2 -0
  31. package/dist/cjs/balance/index.js +18 -0
  32. package/dist/cjs/{balances → balance}/utils.d.ts +0 -0
  33. package/dist/cjs/{balances → balance}/utils.js +1 -1
  34. package/dist/cjs/execution/{exchanges/swap.execute.d.ts → ExecutionManager.d.ts} +3 -3
  35. package/dist/cjs/execution/{bridges/bridge.execute.js → ExecutionManager.js} +52 -37
  36. package/dist/cjs/execution/StatusManager.d.ts +6 -3
  37. package/dist/cjs/execution/StatusManager.js +1 -3
  38. package/dist/cjs/execution/StepExecutor.d.ts +3 -5
  39. package/dist/cjs/execution/StepExecutor.js +7 -32
  40. package/dist/cjs/execution/stepComparison.d.ts +4 -4
  41. package/dist/cjs/execution/stepComparison.js +11 -7
  42. package/dist/cjs/execution/switchChain.js +1 -1
  43. package/dist/cjs/execution/utils.d.ts +1 -1
  44. package/dist/cjs/execution/utils.js +11 -10
  45. package/dist/cjs/services/ConfigService.js +1 -0
  46. package/dist/cjs/types/internal.types.d.ts +18 -24
  47. package/dist/cjs/utils/errors.d.ts +7 -3
  48. package/dist/cjs/utils/errors.js +9 -2
  49. package/dist/cjs/utils/multicall.d.ts +1 -1
  50. package/dist/cjs/utils/parseError.d.ts +0 -1
  51. package/dist/cjs/utils/parseError.js +1 -7
  52. package/dist/cjs/version.d.ts +1 -1
  53. package/dist/cjs/version.js +1 -1
  54. package/dist/execution/{exchanges/swap.execute.d.ts → ExecutionManager.d.ts} +3 -3
  55. package/dist/execution/{bridges/bridge.execute.js → ExecutionManager.js} +49 -34
  56. package/dist/execution/StatusManager.d.ts +6 -3
  57. package/dist/execution/StatusManager.js +1 -3
  58. package/dist/execution/StepExecutor.d.ts +3 -5
  59. package/dist/execution/StepExecutor.js +7 -32
  60. package/dist/execution/stepComparison.d.ts +4 -4
  61. package/dist/execution/stepComparison.js +12 -8
  62. package/dist/execution/switchChain.js +1 -1
  63. package/dist/execution/utils.d.ts +1 -1
  64. package/dist/execution/utils.js +9 -8
  65. package/dist/services/ConfigService.js +1 -0
  66. package/dist/types/internal.types.d.ts +18 -24
  67. package/dist/utils/errors.d.ts +7 -3
  68. package/dist/utils/errors.js +7 -1
  69. package/dist/utils/multicall.d.ts +1 -1
  70. package/dist/utils/parseError.d.ts +0 -1
  71. package/dist/utils/parseError.js +0 -5
  72. package/dist/version.d.ts +1 -1
  73. package/dist/version.js +1 -1
  74. package/package.json +13 -15
  75. package/dist/balances/index.d.ts +0 -11
  76. package/dist/cjs/balances/index.d.ts +0 -11
  77. package/dist/cjs/execution/balanceCheck.execute.d.ts +0 -3
  78. package/dist/cjs/execution/bridges/bridge.execute.d.ts +0 -7
  79. package/dist/cjs/execution/exchanges/swap.execute.js +0 -152
  80. package/dist/execution/balanceCheck.execute.d.ts +0 -3
  81. package/dist/execution/bridges/bridge.execute.d.ts +0 -7
  82. package/dist/execution/exchanges/swap.execute.js +0 -145
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.revokeTokenApproval = exports.approveToken = exports.bulkGetTokenApproval = exports.getTokenApproval = void 0;
16
+ const bignumber_js_1 = __importDefault(require("bignumber.js"));
17
+ const ethers_1 = require("ethers");
18
+ const helpers_1 = require("../helpers");
19
+ const utils_1 = require("../utils/utils");
20
+ const utils_2 = require("./utils");
21
+ const getTokenApproval = (signer, token, approvalAddress) => __awaiter(void 0, void 0, void 0, function* () {
22
+ // native token don't need approval
23
+ if ((0, utils_1.isNativeTokenAddress)(token.address)) {
24
+ return;
25
+ }
26
+ const approved = yield (0, utils_2.getApproved)(signer, token.address, approvalAddress);
27
+ return approved.toString();
28
+ });
29
+ exports.getTokenApproval = getTokenApproval;
30
+ const bulkGetTokenApproval = (signer, tokenData) => __awaiter(void 0, void 0, void 0, function* () {
31
+ // filter out native tokens
32
+ const filteredTokenData = tokenData.filter(({ token }) => !(0, utils_1.isNativeTokenAddress)(token.address));
33
+ // group by chain
34
+ const tokenDataByChain = (0, utils_2.groupByChain)(filteredTokenData);
35
+ const approvalPromises = Object.keys(tokenDataByChain).map((chainId) => __awaiter(void 0, void 0, void 0, function* () {
36
+ const parsedChainId = Number.parseInt(chainId);
37
+ // get allowances for current chain and token list
38
+ return (0, utils_2.getAllowanceViaMulticall)(signer, parsedChainId, tokenDataByChain[parsedChainId]);
39
+ }));
40
+ const approvalsByChain = yield Promise.all(approvalPromises);
41
+ const approvals = approvalsByChain.flat();
42
+ return tokenData.map(({ token }) => {
43
+ // native token don't need approval
44
+ if ((0, utils_1.isNativeTokenAddress)(token.address)) {
45
+ return { token, approval: undefined };
46
+ }
47
+ const approved = approvals.find((approval) => (0, helpers_1.isSameToken)(approval.token, token));
48
+ return { token, approval: approved === null || approved === void 0 ? void 0 : approved.approvedAmount.toString() };
49
+ });
50
+ });
51
+ exports.bulkGetTokenApproval = bulkGetTokenApproval;
52
+ const approveToken = ({ signer, token, approvalAddress, amount, infiniteApproval = false, }) => __awaiter(void 0, void 0, void 0, function* () {
53
+ // native token don't need approval
54
+ if ((0, utils_1.isNativeTokenAddress)(token.address)) {
55
+ return;
56
+ }
57
+ const approvedAmount = yield (0, utils_2.getApproved)(signer, token.address, approvalAddress);
58
+ if (new bignumber_js_1.default(amount).gt(approvedAmount)) {
59
+ const approvalAmount = infiniteApproval
60
+ ? ethers_1.constants.MaxUint256.toString()
61
+ : amount;
62
+ const approveTx = yield (0, utils_2.setApproval)(signer, token.address, approvalAddress, approvalAmount);
63
+ yield approveTx.wait();
64
+ }
65
+ });
66
+ exports.approveToken = approveToken;
67
+ const revokeTokenApproval = ({ signer, token, approvalAddress, }) => __awaiter(void 0, void 0, void 0, function* () {
68
+ // native token don't need approval
69
+ if ((0, utils_1.isNativeTokenAddress)(token.address)) {
70
+ return;
71
+ }
72
+ const approvedAmount = yield (0, utils_2.getApproved)(signer, token.address, approvalAddress);
73
+ if (!approvedAmount.isZero()) {
74
+ const approveTx = yield (0, utils_2.setApproval)(signer, token.address, approvalAddress, '0');
75
+ yield approveTx.wait();
76
+ }
77
+ });
78
+ exports.revokeTokenApproval = revokeTokenApproval;
@@ -0,0 +1,3 @@
1
+ import { ethers } from 'ethers';
2
+ import { Step } from '..';
3
+ export declare const checkBalance: (signer: ethers.Signer, step: Step, depth?: number) => Promise<void>;
@@ -12,17 +12,23 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.balanceCheck = void 0;
15
+ exports.checkBalance = void 0;
16
16
  const bignumber_js_1 = __importDefault(require("bignumber.js"));
17
- const balances_1 = __importDefault(require("../balances"));
18
17
  const errors_1 = require("../utils/errors");
19
- const balanceCheck = (signer, step) => __awaiter(void 0, void 0, void 0, function* () {
20
- const tokenAmount = yield balances_1.default.getTokenBalance(yield signer.getAddress(), step.action.fromToken);
18
+ const getTokenBalance_1 = require("./getTokenBalance");
19
+ const checkBalance = (signer, step, depth = 0) => __awaiter(void 0, void 0, void 0, function* () {
20
+ const tokenAmount = yield (0, getTokenBalance_1.getTokenBalance)(yield signer.getAddress(), step.action.fromToken);
21
21
  if (tokenAmount) {
22
22
  const currentBalance = new bignumber_js_1.default(tokenAmount.amount).shiftedBy(tokenAmount.decimals);
23
23
  const neededBalance = new bignumber_js_1.default(step.action.fromAmount);
24
24
  if (currentBalance.lt(neededBalance)) {
25
- if (neededBalance.multipliedBy(1 - step.action.slippage).lte(currentBalance)) {
25
+ if (depth <= 3) {
26
+ yield new Promise((resolve) => {
27
+ setTimeout(resolve, 200);
28
+ });
29
+ yield (0, exports.checkBalance)(signer, step, depth + 1);
30
+ }
31
+ else if (neededBalance.multipliedBy(1 - step.action.slippage).lte(currentBalance)) {
26
32
  // adjust amount in slippage limits
27
33
  step.action.fromAmount = currentBalance.toFixed(0);
28
34
  }
@@ -40,9 +46,9 @@ const balanceCheck = (signer, step) => __awaiter(void 0, void 0, void 0, functio
40
46
  `If the problem consists, please delete this transfer and ` +
41
47
  `start a new one with a maximum of ${current} ${tokenAmount.symbol}.`;
42
48
  }
43
- throw new errors_1.ValidationError('The balance is too low.', errorMessage);
49
+ throw new errors_1.BalanceError('The balance is too low.', errorMessage);
44
50
  }
45
51
  }
46
52
  }
47
53
  });
48
- exports.balanceCheck = balanceCheck;
54
+ exports.checkBalance = checkBalance;
@@ -0,0 +1,8 @@
1
+ import { Token, TokenAmount } from '@lifi/types';
2
+ export declare const getTokenBalance: (walletAddress: string, token: Token) => Promise<TokenAmount | null>;
3
+ export declare const getTokenBalances: (walletAddress: string, tokens: Token[]) => Promise<TokenAmount[]>;
4
+ export declare const getTokenBalancesForChains: (walletAddress: string, tokensByChain: {
5
+ [chainId: number]: Token[];
6
+ }) => Promise<{
7
+ [chainId: number]: TokenAmount[];
8
+ }>;
@@ -12,11 +12,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.getTokenBalancesForChains = exports.getTokenBalances = exports.getTokenBalance = void 0;
15
16
  const utils_1 = __importDefault(require("./utils"));
16
17
  const getTokenBalance = (walletAddress, token) => __awaiter(void 0, void 0, void 0, function* () {
17
- const tokenAmounts = yield getTokenBalances(walletAddress, [token]);
18
+ const tokenAmounts = yield (0, exports.getTokenBalances)(walletAddress, [token]);
18
19
  return tokenAmounts.length ? tokenAmounts[0] : null;
19
20
  });
21
+ exports.getTokenBalance = getTokenBalance;
20
22
  const getTokenBalances = (walletAddress, tokens) => __awaiter(void 0, void 0, void 0, function* () {
21
23
  // split by chain
22
24
  const tokensByChain = {};
@@ -26,9 +28,10 @@ const getTokenBalances = (walletAddress, tokens) => __awaiter(void 0, void 0, vo
26
28
  }
27
29
  tokensByChain[token.chainId].push(token);
28
30
  });
29
- const tokenAmountsByChain = yield getTokenBalancesForChains(walletAddress, tokensByChain);
31
+ const tokenAmountsByChain = yield (0, exports.getTokenBalancesForChains)(walletAddress, tokensByChain);
30
32
  return Object.values(tokenAmountsByChain).flat();
31
33
  });
34
+ exports.getTokenBalances = getTokenBalances;
32
35
  const getTokenBalancesForChains = (walletAddress, tokensByChain) => __awaiter(void 0, void 0, void 0, function* () {
33
36
  const tokenAmountsByChain = {};
34
37
  const promises = Object.keys(tokensByChain).map((chainIdStr) => __awaiter(void 0, void 0, void 0, function* () {
@@ -39,8 +42,4 @@ const getTokenBalancesForChains = (walletAddress, tokensByChain) => __awaiter(vo
39
42
  yield Promise.allSettled(promises);
40
43
  return tokenAmountsByChain;
41
44
  });
42
- exports.default = {
43
- getTokenBalance,
44
- getTokenBalances,
45
- getTokenBalancesForChains,
46
- };
45
+ exports.getTokenBalancesForChains = getTokenBalancesForChains;
@@ -0,0 +1,2 @@
1
+ export * from './checkBalance';
2
+ export * from './getTokenBalance';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./checkBalance"), exports);
18
+ __exportStar(require("./getTokenBalance"), exports);
File without changes
@@ -45,7 +45,7 @@ const getBalances = (walletAddress, tokens) => __awaiter(void 0, void 0, void 0,
45
45
  tokens.forEach((token) => {
46
46
  if (token.chainId !== chainId) {
47
47
  // eslint-disable-next-line no-console
48
- console.warn(`Requested tokens have to be on same chain.`);
48
+ console.warn(`Requested tokens have to be on the same chain.`);
49
49
  return [];
50
50
  }
51
51
  });
@@ -1,7 +1,7 @@
1
1
  import { Execution } from '@lifi/types';
2
- import { ExecuteSwapParams } from '../../types';
3
- export declare class SwapExecutionManager {
2
+ import { ExecutionParams } from '../types';
3
+ export declare class ExecutionManager {
4
4
  allowUserInteraction: boolean;
5
5
  allowInteraction: (value: boolean) => void;
6
- execute: ({ signer, step, statusManager, settings, }: ExecuteSwapParams) => Promise<Execution>;
6
+ execute: ({ signer, step, statusManager, settings, }: ExecutionParams) => Promise<Execution>;
7
7
  }
@@ -12,19 +12,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.BridgeExecutionManager = void 0;
16
- const ApiService_1 = __importDefault(require("../../services/ApiService"));
17
- const ChainsService_1 = __importDefault(require("../../services/ChainsService"));
18
- const errors_1 = require("../../utils/errors");
19
- const getProvider_1 = require("../../utils/getProvider");
20
- const parseError_1 = require("../../utils/parseError");
21
- const utils_1 = require("../../utils/utils");
22
- const allowance_execute_1 = require("../allowance.execute");
23
- const balanceCheck_execute_1 = require("../balanceCheck.execute");
24
- const stepComparison_1 = require("../stepComparison");
25
- const switchChain_1 = require("../switchChain");
26
- const utils_2 = require("../utils");
27
- class BridgeExecutionManager {
15
+ exports.ExecutionManager = void 0;
16
+ const allowance_1 = require("../allowance");
17
+ const balance_1 = require("../balance");
18
+ const ApiService_1 = __importDefault(require("../services/ApiService"));
19
+ const ChainsService_1 = __importDefault(require("../services/ChainsService"));
20
+ const errors_1 = require("../utils/errors");
21
+ const getProvider_1 = require("../utils/getProvider");
22
+ const parseError_1 = require("../utils/parseError");
23
+ const utils_1 = require("../utils/utils");
24
+ const stepComparison_1 = require("./stepComparison");
25
+ const switchChain_1 = require("./switchChain");
26
+ const utils_2 = require("./utils");
27
+ class ExecutionManager {
28
28
  constructor() {
29
29
  this.allowUserInteraction = true;
30
30
  this.allowInteraction = (value) => {
@@ -36,19 +36,21 @@ class BridgeExecutionManager {
36
36
  const chainsService = ChainsService_1.default.getInstance();
37
37
  const fromChain = yield chainsService.getChainById(step.action.fromChainId);
38
38
  const toChain = yield chainsService.getChainById(step.action.toChainId);
39
+ const isBridgeExecution = fromChain.id !== toChain.id;
40
+ const currentProcessType = isBridgeExecution ? 'CROSS_CHAIN' : 'SWAP';
39
41
  // STEP 1: Check allowance
40
- const oldCrossProcess = step.execution.process.find((p) => p.type === 'CROSS_CHAIN');
42
+ const existingProcess = step.execution.process.find((p) => p.type === currentProcessType);
41
43
  // Check token approval only if fromToken is not the native token => no approval needed in that case
42
- if (!(oldCrossProcess === null || oldCrossProcess === void 0 ? void 0 : oldCrossProcess.txHash) &&
44
+ if (!(existingProcess === null || existingProcess === void 0 ? void 0 : existingProcess.txHash) &&
43
45
  !(0, utils_1.isZeroAddress)(step.action.fromToken.address)) {
44
- yield (0, allowance_execute_1.checkAllowance)(signer, step, statusManager, settings, fromChain, this.allowUserInteraction);
46
+ yield (0, allowance_1.checkAllowance)(signer, step, statusManager, settings, fromChain, this.allowUserInteraction);
45
47
  }
46
48
  // STEP 2: Get transaction
47
- let crossChainProcess = statusManager.findOrCreateProcess(step, 'CROSS_CHAIN');
48
- if (crossChainProcess.status !== 'DONE') {
49
+ let process = statusManager.findOrCreateProcess(step, currentProcessType);
50
+ if (process.status !== 'DONE') {
49
51
  try {
50
52
  let transaction;
51
- if (crossChainProcess.txHash) {
53
+ if (process.txHash) {
52
54
  // Make sure that the chain is still correct
53
55
  const updatedSigner = yield (0, switchChain_1.switchChain)(signer, statusManager, step, settings.switchChainHook, this.allowUserInteraction);
54
56
  if (!updatedSigner) {
@@ -57,17 +59,18 @@ class BridgeExecutionManager {
57
59
  }
58
60
  signer = updatedSigner;
59
61
  // Load exiting transaction
60
- transaction = yield (0, getProvider_1.getProvider)(signer).getTransaction(crossChainProcess.txHash);
62
+ transaction = yield (0, getProvider_1.getProvider)(signer).getTransaction(process.txHash);
61
63
  }
62
64
  else {
63
- crossChainProcess = statusManager.updateProcess(step, crossChainProcess.type, 'STARTED');
65
+ process = statusManager.updateProcess(step, process.type, 'STARTED');
64
66
  // Check balance
65
- yield (0, balanceCheck_execute_1.balanceCheck)(signer, step);
67
+ yield (0, balance_1.checkBalance)(signer, step);
66
68
  // Create new transaction
67
69
  if (!step.transactionRequest) {
68
70
  const personalizedStep = yield (0, utils_1.personalizeStep)(signer, step);
69
71
  const updatedStep = yield ApiService_1.default.getStepTransaction(personalizedStep);
70
- step = Object.assign(Object.assign({}, (yield (0, stepComparison_1.stepComparison)(statusManager, personalizedStep, updatedStep, settings.acceptSlippageUpdateHook, this.allowUserInteraction))), { execution: step.execution });
72
+ const comparedStep = yield (0, stepComparison_1.stepComparison)(statusManager, personalizedStep, updatedStep, settings, this.allowUserInteraction);
73
+ step = Object.assign(Object.assign({}, comparedStep), { execution: step.execution });
71
74
  }
72
75
  const { transactionRequest } = step;
73
76
  if (!transactionRequest) {
@@ -81,14 +84,14 @@ class BridgeExecutionManager {
81
84
  return step.execution;
82
85
  }
83
86
  signer = updatedSigner;
84
- crossChainProcess = statusManager.updateProcess(step, crossChainProcess.type, 'ACTION_REQUIRED');
87
+ process = statusManager.updateProcess(step, process.type, 'ACTION_REQUIRED');
85
88
  if (!this.allowUserInteraction) {
86
89
  return step.execution;
87
90
  }
88
91
  // Submit the transaction
89
92
  transaction = yield signer.sendTransaction(transactionRequest);
90
93
  // STEP 4: Wait for the transaction
91
- crossChainProcess = statusManager.updateProcess(step, crossChainProcess.type, 'PENDING', {
94
+ process = statusManager.updateProcess(step, process.type, 'PENDING', {
92
95
  txHash: transaction.hash,
93
96
  txLink: fromChain.metamask.blockExplorerUrls[0] +
94
97
  'tx/' +
@@ -96,11 +99,17 @@ class BridgeExecutionManager {
96
99
  });
97
100
  }
98
101
  yield transaction.wait();
99
- crossChainProcess = statusManager.updateProcess(step, crossChainProcess.type, 'DONE');
102
+ process = statusManager.updateProcess(step, process.type, 'PENDING', {
103
+ txHash: transaction.hash,
104
+ txLink: fromChain.metamask.blockExplorerUrls[0] + 'tx/' + transaction.hash,
105
+ });
106
+ if (isBridgeExecution) {
107
+ process = statusManager.updateProcess(step, process.type, 'DONE');
108
+ }
100
109
  }
101
110
  catch (e) {
102
111
  if (e.code === 'TRANSACTION_REPLACED' && e.replacement) {
103
- crossChainProcess = statusManager.updateProcess(step, crossChainProcess.type, 'DONE', {
112
+ process = statusManager.updateProcess(step, process.type, 'DONE', {
104
113
  txHash: e.replacement.hash,
105
114
  txLink: fromChain.metamask.blockExplorerUrls[0] +
106
115
  'tx/' +
@@ -108,8 +117,8 @@ class BridgeExecutionManager {
108
117
  });
109
118
  }
110
119
  else {
111
- const error = yield (0, parseError_1.parseError)(e, step, crossChainProcess);
112
- crossChainProcess = statusManager.updateProcess(step, crossChainProcess.type, 'FAILED', {
120
+ const error = yield (0, parseError_1.parseError)(e, step, process);
121
+ process = statusManager.updateProcess(step, process.type, 'FAILED', {
113
122
  error: {
114
123
  message: error.message,
115
124
  htmlMessage: error.htmlMessage,
@@ -122,14 +131,17 @@ class BridgeExecutionManager {
122
131
  }
123
132
  }
124
133
  // STEP 5: Wait for the receiving chain
125
- let receivingChainProcess = statusManager.findOrCreateProcess(step, 'RECEIVING_CHAIN', 'PENDING');
134
+ const processTxHash = process.txHash;
135
+ if (isBridgeExecution) {
136
+ process = statusManager.findOrCreateProcess(step, 'RECEIVING_CHAIN', 'PENDING');
137
+ }
126
138
  let statusResponse;
127
139
  try {
128
- if (!crossChainProcess.txHash) {
140
+ if (!processTxHash) {
129
141
  throw new Error('Transaction hash is undefined.');
130
142
  }
131
- statusResponse = yield (0, utils_2.waitForReceivingTransaction)(crossChainProcess.txHash, statusManager, receivingChainProcess.type, step);
132
- receivingChainProcess = statusManager.updateProcess(step, receivingChainProcess.type, 'DONE', {
143
+ statusResponse = yield (0, utils_2.waitForReceivingTransaction)(processTxHash, statusManager, process.type, step);
144
+ process = statusManager.updateProcess(step, process.type, 'DONE', {
133
145
  substatus: statusResponse.substatus,
134
146
  substatusMessage: statusResponse.substatusMessage ||
135
147
  (0, utils_2.getSubstatusMessage)(statusResponse.status, statusResponse.substatus),
@@ -142,16 +154,19 @@ class BridgeExecutionManager {
142
154
  fromAmount: statusResponse.sending.amount,
143
155
  toAmount: (_c = statusResponse.receiving) === null || _c === void 0 ? void 0 : _c.amount,
144
156
  toToken: (_d = statusResponse.receiving) === null || _d === void 0 ? void 0 : _d.token,
145
- gasUsed: statusResponse.sending.gasUsed,
157
+ gasAmount: statusResponse.sending.gasAmount,
158
+ gasAmountUSD: statusResponse.sending.gasAmountUSD,
146
159
  gasPrice: statusResponse.sending.gasPrice,
160
+ gasToken: statusResponse.sending.gasToken,
161
+ gasUsed: statusResponse.sending.gasUsed,
147
162
  });
148
163
  }
149
164
  catch (e) {
150
- receivingChainProcess = statusManager.updateProcess(step, receivingChainProcess.type, 'FAILED', {
165
+ process = statusManager.updateProcess(step, process.type, 'FAILED', {
151
166
  error: {
152
167
  code: errors_1.LifiErrorCode.TransactionFailed,
153
168
  message: 'Failed while waiting for receiving chain.',
154
- htmlMessage: (0, parseError_1.getTransactionFailedMessage)(step, crossChainProcess.txLink),
169
+ htmlMessage: (0, parseError_1.getTransactionFailedMessage)(step, process.txLink),
155
170
  },
156
171
  });
157
172
  statusManager.updateExecution(step, 'FAILED');
@@ -163,4 +178,4 @@ class BridgeExecutionManager {
163
178
  });
164
179
  }
165
180
  }
166
- exports.BridgeExecutionManager = BridgeExecutionManager;
181
+ exports.ExecutionManager = ExecutionManager;
@@ -3,11 +3,14 @@ interface Receipt {
3
3
  fromAmount?: string;
4
4
  toAmount?: string;
5
5
  toToken?: Token;
6
- gasUsed?: string;
7
6
  gasPrice?: string;
7
+ gasUsed?: string;
8
+ gasToken?: Token;
9
+ gasAmount?: string;
10
+ gasAmountUSD?: string;
8
11
  }
9
- declare type InternalUpdateRouteCallback = (route: Route) => void;
10
- declare type OptionalParameters = Partial<Pick<Process, 'doneAt' | 'failedAt' | 'txHash' | 'txLink' | 'error' | 'substatus' | 'substatusMessage'>>;
12
+ type InternalUpdateRouteCallback = (route: Route) => void;
13
+ type OptionalParameters = Partial<Pick<Process, 'doneAt' | 'failedAt' | 'txHash' | 'txLink' | 'error' | 'substatus' | 'substatusMessage'>>;
11
14
  /**
12
15
  * Manages status updates of a route and provides various functions for tracking processes
13
16
  * @param {Route} route The route this StatusManger belongs to.
@@ -160,9 +160,7 @@ class StatusManager {
160
160
  }
161
161
  step.execution.status = status;
162
162
  if (receipt) {
163
- step.execution.fromAmount = receipt.fromAmount;
164
- step.execution.toAmount = receipt.toAmount;
165
- step.execution.toToken = receipt.toToken;
163
+ step.execution = Object.assign(Object.assign({}, step.execution), receipt);
166
164
  }
167
165
  this.updateStepInRoute(step);
168
166
  return step;
@@ -1,17 +1,15 @@
1
1
  import { Signer } from 'ethers';
2
2
  import { InteractionSettings, InternalExecutionSettings, Step } from '../types';
3
+ import { ExecutionManager } from './ExecutionManager';
3
4
  import { StatusManager } from './StatusManager';
4
5
  export declare class StepExecutor {
5
- settings: InternalExecutionSettings;
6
+ executionManager: ExecutionManager;
6
7
  statusManager: StatusManager;
7
- private swapExecutionManager;
8
- private bridgeExecutionManager;
8
+ settings: InternalExecutionSettings;
9
9
  allowUserInteraction: boolean;
10
10
  executionStopped: boolean;
11
11
  constructor(statusManager: StatusManager, settings: InternalExecutionSettings);
12
12
  setInteraction: (settings?: InteractionSettings) => void;
13
13
  checkChain: () => never;
14
14
  executeStep: (signer: Signer, step: Step) => Promise<Step>;
15
- private executeSwap;
16
- private executeCross;
17
15
  }
@@ -10,8 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.StepExecutor = void 0;
13
- const bridge_execute_1 = require("./bridges/bridge.execute");
14
- const swap_execute_1 = require("./exchanges/swap.execute");
13
+ const ExecutionManager_1 = require("./ExecutionManager");
15
14
  const switchChain_1 = require("./switchChain");
16
15
  // Please be careful when changing the defaults as it may break the behavior (e.g., background execution)
17
16
  const defaultInteractionSettings = {
@@ -21,15 +20,12 @@ const defaultInteractionSettings = {
21
20
  };
22
21
  class StepExecutor {
23
22
  constructor(statusManager, settings) {
24
- this.swapExecutionManager = new swap_execute_1.SwapExecutionManager();
25
- this.bridgeExecutionManager = new bridge_execute_1.BridgeExecutionManager();
26
23
  this.allowUserInteraction = true;
27
24
  this.executionStopped = false;
28
25
  this.setInteraction = (settings) => {
29
26
  const interactionSettings = Object.assign(Object.assign({}, defaultInteractionSettings), settings);
30
27
  this.allowUserInteraction = interactionSettings.allowInteraction;
31
- this.swapExecutionManager.allowInteraction(interactionSettings.allowInteraction);
32
- this.bridgeExecutionManager.allowInteraction(interactionSettings.allowInteraction);
28
+ this.executionManager.allowInteraction(interactionSettings.allowInteraction);
33
29
  this.statusManager.allowUpdates(interactionSettings.allowUpdates);
34
30
  this.executionStopped = interactionSettings.stopExecution;
35
31
  };
@@ -47,37 +43,16 @@ class StepExecutor {
47
43
  return step;
48
44
  }
49
45
  signer = updatedSigner;
50
- switch (step.type) {
51
- case 'lifi':
52
- case 'cross':
53
- yield this.executeCross(signer, step);
54
- break;
55
- case 'swap':
56
- yield this.executeSwap(signer, step);
57
- break;
58
- default:
59
- throw new Error('Unsupported step type.');
60
- }
61
- return step;
62
- });
63
- this.executeSwap = (signer, step) => {
64
- const swapParams = {
65
- signer,
66
- step,
67
- settings: this.settings,
68
- statusManager: this.statusManager,
69
- };
70
- return this.swapExecutionManager.execute(swapParams);
71
- };
72
- this.executeCross = (signer, step) => {
73
- const crossParams = {
46
+ const parameters = {
74
47
  signer,
75
48
  step,
76
49
  settings: this.settings,
77
50
  statusManager: this.statusManager,
78
51
  };
79
- return this.bridgeExecutionManager.execute(crossParams);
80
- };
52
+ yield this.executionManager.execute(parameters);
53
+ return step;
54
+ });
55
+ this.executionManager = new ExecutionManager_1.ExecutionManager();
81
56
  this.statusManager = statusManager;
82
57
  this.settings = settings;
83
58
  }
@@ -1,9 +1,9 @@
1
1
  import { StatusManager } from '.';
2
- import { AcceptSlippageUpdateHook, Step } from '../types';
2
+ import { InternalExecutionSettings, Step } from '../types';
3
3
  /**
4
- * This method checks whether the new and updated Step meets the required slippage conditions.
4
+ * This method checks whether the new and updated Step meets the required exchange rate conditions.
5
5
  * If yes it returns the updated Step.
6
- * If no and if user interaction is allowed it triggers the acceptSlippageUpdateHook. If no user interaction is allowed it aborts.
6
+ * If no and if user interaction is allowed it triggers the acceptExchangeRateUpdateHook. If no user interaction is allowed it aborts.
7
7
  *
8
8
  * @param statusManager
9
9
  * @param oldStep
@@ -11,4 +11,4 @@ import { AcceptSlippageUpdateHook, Step } from '../types';
11
11
  * @param acceptSlippageUpdateHook
12
12
  * @param allowUserInteraction
13
13
  */
14
- export declare const stepComparison: (statusManager: StatusManager, oldStep: Step, newStep: Step, acceptSlippageUpdateHook: AcceptSlippageUpdateHook, allowUserInteraction: boolean) => Promise<Step>;
14
+ export declare const stepComparison: (statusManager: StatusManager, oldStep: Step, newStep: Step, settings: InternalExecutionSettings, allowUserInteraction: boolean) => Promise<Step>;
@@ -11,12 +11,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.stepComparison = void 0;
13
13
  const errors_1 = require("../utils/errors");
14
- const parseError_1 = require("../utils/parseError");
15
14
  const utils_1 = require("./utils");
16
15
  /**
17
- * This method checks whether the new and updated Step meets the required slippage conditions.
16
+ * This method checks whether the new and updated Step meets the required exchange rate conditions.
18
17
  * If yes it returns the updated Step.
19
- * If no and if user interaction is allowed it triggers the acceptSlippageUpdateHook. If no user interaction is allowed it aborts.
18
+ * If no and if user interaction is allowed it triggers the acceptExchangeRateUpdateHook. If no user interaction is allowed it aborts.
20
19
  *
21
20
  * @param statusManager
22
21
  * @param oldStep
@@ -24,13 +23,16 @@ const utils_1 = require("./utils");
24
23
  * @param acceptSlippageUpdateHook
25
24
  * @param allowUserInteraction
26
25
  */
27
- const stepComparison = (statusManager, oldStep, newStep, acceptSlippageUpdateHook, allowUserInteraction) => __awaiter(void 0, void 0, void 0, function* () {
28
- if ((0, utils_1.updatedStepMeetsSlippageConditions)(oldStep, newStep)) {
26
+ const stepComparison = (statusManager, oldStep, newStep, settings, allowUserInteraction) => __awaiter(void 0, void 0, void 0, function* () {
27
+ var _a;
28
+ // Check if changed exchange rate is in the range of slippage threshold
29
+ if ((0, utils_1.checkStepSlippageThreshold)(oldStep, newStep)) {
29
30
  return statusManager.updateStepInRoute(newStep);
30
31
  }
32
+ const acceptExchangeRateUpdateHook = (_a = settings.acceptExchangeRateUpdateHook) !== null && _a !== void 0 ? _a : settings.acceptSlippageUpdateHook;
31
33
  let allowStepUpdate;
32
34
  if (allowUserInteraction) {
33
- allowStepUpdate = yield acceptSlippageUpdateHook({
35
+ allowStepUpdate = yield acceptExchangeRateUpdateHook({
34
36
  oldToAmount: oldStep.estimate.toAmount,
35
37
  newToAmount: newStep.estimate.toAmount,
36
38
  toToken: newStep.action.toToken,
@@ -39,7 +41,9 @@ const stepComparison = (statusManager, oldStep, newStep, acceptSlippageUpdateHoo
39
41
  });
40
42
  }
41
43
  if (!allowStepUpdate) {
42
- throw new errors_1.TransactionError(errors_1.LifiErrorCode.SlippageNotMet, 'Slippage conditions not met!', (0, parseError_1.getSlippageNotMetMessage)(oldStep));
44
+ // The user declined the new exchange rate, so we are not going to proceed
45
+ throw new errors_1.TransactionError(errors_1.LifiErrorCode.TransactionCanceled, 'Exchange rate has changed!', `Transaction was not sent, your funds are still in your wallet.
46
+ The exchange rate has changed and the previous estimation can not be fulfilled due to value loss.`);
43
47
  }
44
48
  return statusManager.updateStepInRoute(newStep);
45
49
  });
@@ -45,7 +45,7 @@ const switchChain = (signer, statusManager, step, switchChainHook, allowUserInte
45
45
  return updatedSigner;
46
46
  }
47
47
  catch (error) {
48
- switchProcess = statusManager.updateProcess(step, switchProcess.type, 'FAILED', {
48
+ statusManager.updateProcess(step, switchProcess.type, 'FAILED', {
49
49
  error: {
50
50
  message: error.message,
51
51
  code: errors_1.LifiErrorCode.ChainSwitchError,
@@ -3,4 +3,4 @@ import { StatusManager } from '..';
3
3
  export declare function waitForReceivingTransaction(txHash: string, statusManager: StatusManager, processType: ProcessType, step: Step): Promise<StatusResponse>;
4
4
  export declare function getProcessMessage(type: ProcessType, status: Status): string | undefined;
5
5
  export declare function getSubstatusMessage(status: StatusMessage, substatus?: Substatus): string | undefined;
6
- export declare function updatedStepMeetsSlippageConditions(oldStep: Step, newStep: Step): boolean;
6
+ export declare function checkStepSlippageThreshold(oldStep: Step, newStep: Step): boolean;