@lifi/sdk 1.1.3 → 1.1.6

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 (65) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/cjs/Lifi.d.ts +200 -0
  3. package/dist/cjs/Lifi.js +376 -0
  4. package/dist/cjs/allowance/index.d.ts +22 -0
  5. package/dist/cjs/allowance/index.js +78 -0
  6. package/dist/cjs/allowance/utils.d.ts +14 -0
  7. package/dist/cjs/allowance/utils.js +82 -0
  8. package/dist/cjs/balances/index.d.ts +11 -0
  9. package/dist/cjs/balances/index.js +46 -0
  10. package/dist/cjs/balances/utils.d.ts +5 -0
  11. package/dist/cjs/balances/utils.js +150 -0
  12. package/dist/cjs/connectors.d.ts +6 -0
  13. package/dist/cjs/connectors.js +77 -0
  14. package/dist/cjs/execution/StatusManager.d.ts +65 -0
  15. package/dist/cjs/execution/StatusManager.js +167 -0
  16. package/dist/cjs/execution/StepExecutor.d.ts +15 -0
  17. package/dist/cjs/execution/StepExecutor.js +74 -0
  18. package/dist/cjs/execution/allowance.execute.d.ts +4 -0
  19. package/dist/cjs/execution/allowance.execute.js +97 -0
  20. package/dist/cjs/execution/balanceCheck.execute.d.ts +3 -0
  21. package/dist/cjs/execution/balanceCheck.execute.js +48 -0
  22. package/dist/cjs/execution/bridges/bridge.execute.d.ts +7 -0
  23. package/dist/cjs/execution/bridges/bridge.execute.js +154 -0
  24. package/dist/cjs/execution/exchanges/swap.execute.d.ts +7 -0
  25. package/dist/cjs/execution/exchanges/swap.execute.js +164 -0
  26. package/dist/cjs/execution/index.d.ts +1 -0
  27. package/dist/cjs/execution/index.js +17 -0
  28. package/dist/cjs/execution/stepComparison.d.ts +14 -0
  29. package/dist/cjs/execution/stepComparison.js +46 -0
  30. package/dist/cjs/execution/switchChain.d.ts +16 -0
  31. package/dist/cjs/execution/switchChain.js +58 -0
  32. package/dist/cjs/execution/utils.d.ts +6 -0
  33. package/dist/cjs/execution/utils.js +137 -0
  34. package/dist/cjs/helpers.d.ts +18 -0
  35. package/dist/cjs/helpers.js +54 -0
  36. package/dist/cjs/index.d.ts +6 -0
  37. package/dist/cjs/index.js +27 -0
  38. package/dist/cjs/services/ApiService.d.ts +15 -0
  39. package/dist/cjs/services/ApiService.js +272 -0
  40. package/dist/cjs/services/ChainsService.d.ts +11 -0
  41. package/dist/cjs/services/ChainsService.js +54 -0
  42. package/dist/cjs/services/ConfigService.d.ts +23 -0
  43. package/dist/cjs/services/ConfigService.js +98 -0
  44. package/dist/cjs/typeguards.d.ts +4 -0
  45. package/dist/cjs/typeguards.js +53 -0
  46. package/dist/cjs/types/ERC20.d.ts +22 -0
  47. package/dist/cjs/types/ERC20.js +53 -0
  48. package/dist/cjs/types/index.d.ts +4 -0
  49. package/dist/cjs/types/index.js +22 -0
  50. package/dist/cjs/types/internal.types.d.ts +85 -0
  51. package/dist/cjs/types/internal.types.js +2 -0
  52. package/dist/cjs/utils/errors.d.ts +75 -0
  53. package/dist/cjs/utils/errors.js +115 -0
  54. package/dist/cjs/utils/getProvider.d.ts +3 -0
  55. package/dist/cjs/utils/getProvider.js +11 -0
  56. package/dist/cjs/utils/multicall.d.ts +10 -0
  57. package/dist/cjs/utils/multicall.js +77 -0
  58. package/dist/cjs/utils/multicallAbi.json +313 -0
  59. package/dist/cjs/utils/parseError.d.ts +38 -0
  60. package/dist/cjs/utils/parseError.js +141 -0
  61. package/dist/cjs/utils/preRestart.d.ts +2 -0
  62. package/dist/cjs/utils/preRestart.js +31 -0
  63. package/dist/cjs/utils/utils.d.ts +26 -0
  64. package/dist/cjs/utils/utils.js +120 -0
  65. package/package.json +34 -11
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StatusManager = void 0;
4
+ const types_1 = require("../types");
5
+ const utils_1 = require("../utils/utils");
6
+ const utils_2 = require("./utils");
7
+ /**
8
+ * Manages status updates of a route and provides various functions for tracking processes
9
+ * @param {Route} route The route this StatusManger belongs to.
10
+ * @param {InternalExecutionSettings} settings The ExecutionSettings for this route.
11
+ * @param {InternalUpdateRouteCallback} internalUpdateRouteCallback Internal callback to propage route changes.
12
+ * @return {StatusManager} An instance of StatusManager.
13
+ */
14
+ class StatusManager {
15
+ constructor(route, settings, internalUpdateRouteCallback) {
16
+ this.shouldUpdate = true;
17
+ /**
18
+ * Initializes the execution object of a Step.
19
+ * @param {Step} step The current step in execution
20
+ * @return {Execution} The initialized execution object for this step and a function to update this step
21
+ */
22
+ this.initExecutionObject = (step) => {
23
+ const currentExecution = step.execution || (0, utils_1.deepClone)(types_1.emptyExecution);
24
+ if (!step.execution) {
25
+ step.execution = currentExecution;
26
+ step.execution.status = 'PENDING';
27
+ this.updateStepInRoute(step);
28
+ }
29
+ // Change status to PENDING after resuming from FAILED
30
+ if (currentExecution.status === 'FAILED') {
31
+ currentExecution.status = 'PENDING';
32
+ this.updateStepInRoute(step);
33
+ }
34
+ return currentExecution;
35
+ };
36
+ /**
37
+ * Create and push a new process into the execution.
38
+ * @param {ProcessType} type Type of the process. Used to identify already existing processes.
39
+ * @param {Step} step The step that should contain the new process.
40
+ * @param {Status} status By default created procces is set to the STARTED status. We can override new process with the needed status.
41
+ * @return {Process}
42
+ */
43
+ this.findOrCreateProcess = (type, step, status) => {
44
+ if (!step.execution || !step.execution.process) {
45
+ throw new Error("Execution hasn't been initialized.");
46
+ }
47
+ const process = step.execution.process.find((p) => p.type === type);
48
+ if (process) {
49
+ return process;
50
+ }
51
+ const newProcess = {
52
+ type: type,
53
+ startedAt: Date.now(),
54
+ message: (0, utils_2.getProcessMessage)(type, status !== null && status !== void 0 ? status : 'STARTED'),
55
+ status: status !== null && status !== void 0 ? status : 'STARTED',
56
+ };
57
+ step.execution.process.push(newProcess);
58
+ this.updateStepInRoute(step);
59
+ return newProcess;
60
+ };
61
+ /**
62
+ * Update a process object.
63
+ * @param {Step} step The step where the process should be updated
64
+ * @param {ProcessType} type The process type to update
65
+ * @param {Status} status The status the process gets.
66
+ * @param {object} [params] Additional parameters to append to the process.
67
+ * @return {Process} The update process
68
+ */
69
+ this.updateProcess = (step, type, status, params) => {
70
+ var _a;
71
+ if (!step.execution) {
72
+ throw new Error("Can't update an empty step execution.");
73
+ }
74
+ const currentProcess = (_a = step === null || step === void 0 ? void 0 : step.execution) === null || _a === void 0 ? void 0 : _a.process.find((p) => p.type === type);
75
+ if (!currentProcess) {
76
+ throw new Error("Can't find a process for the given type.");
77
+ }
78
+ switch (status) {
79
+ case 'CANCELLED':
80
+ currentProcess.doneAt = Date.now();
81
+ break;
82
+ case 'FAILED':
83
+ currentProcess.doneAt = Date.now();
84
+ step.execution.status = 'FAILED';
85
+ break;
86
+ case 'DONE':
87
+ currentProcess.doneAt = Date.now();
88
+ break;
89
+ case 'PENDING':
90
+ step.execution.status = 'PENDING';
91
+ break;
92
+ case 'ACTION_REQUIRED':
93
+ step.execution.status = 'ACTION_REQUIRED';
94
+ break;
95
+ case 'CHAIN_SWITCH_REQUIRED':
96
+ step.execution.status = 'CHAIN_SWITCH_REQUIRED';
97
+ break;
98
+ default:
99
+ break;
100
+ }
101
+ currentProcess.status = status;
102
+ currentProcess.message = (0, utils_2.getProcessMessage)(type, status);
103
+ // set extra parameters or overwritte the standard params set in the switch statement
104
+ if (params) {
105
+ for (const [key, value] of Object.entries(params)) {
106
+ currentProcess[key] = value;
107
+ }
108
+ }
109
+ this.updateStepInRoute(step); // updates the step in the route
110
+ return currentProcess;
111
+ };
112
+ /**
113
+ * Remove a process from the execution
114
+ * @param {Step} step The step where the process should be removed from
115
+ * @param {ProcessType} type The process type to remove
116
+ * @return {void}
117
+ */
118
+ this.removeProcess = (step, type) => {
119
+ if (!step.execution) {
120
+ throw new Error("Execution hasn't been initialized.");
121
+ }
122
+ const index = step.execution.process.findIndex((p) => p.type === type);
123
+ step.execution.process.splice(index, 1);
124
+ this.updateStepInRoute(step);
125
+ };
126
+ this.updateStepInRoute = (step) => {
127
+ if (!this.shouldUpdate) {
128
+ return step;
129
+ }
130
+ const stepIndex = this.route.steps.findIndex((routeStep) => routeStep.id === step.id);
131
+ if (stepIndex === -1) {
132
+ throw new Error("Couldn't find a step to update.");
133
+ }
134
+ this.route.steps[stepIndex] = Object.assign(this.route.steps[stepIndex], step);
135
+ this.settings.updateCallback(this.route);
136
+ this.internalUpdateRouteCallback(this.route);
137
+ return this.route.steps[stepIndex];
138
+ };
139
+ this.route = route;
140
+ this.settings = settings;
141
+ this.internalUpdateRouteCallback = internalUpdateRouteCallback;
142
+ }
143
+ /**
144
+ * Updates the execution object of a Step.
145
+ * @param {Step} step The current step in execution
146
+ * @param {Status} status The status for the execution
147
+ * @param {Receipt} receipt Optional. Information about received tokens
148
+ * @return {Step} The step with the updated execution object
149
+ */
150
+ updateExecution(step, status, receipt) {
151
+ if (!step.execution) {
152
+ throw Error("Can't update empty execution.");
153
+ }
154
+ step.execution.status = status;
155
+ if (receipt) {
156
+ step.execution.fromAmount = receipt.fromAmount;
157
+ step.execution.toAmount = receipt.toAmount;
158
+ step.execution.toToken = receipt.toToken;
159
+ }
160
+ this.updateStepInRoute(step);
161
+ return step;
162
+ }
163
+ setShouldUpdate(value) {
164
+ this.shouldUpdate = value;
165
+ }
166
+ }
167
+ exports.StatusManager = StatusManager;
@@ -0,0 +1,15 @@
1
+ import { Signer } from 'ethers';
2
+ import { HaltingSettings, InternalExecutionSettings, Step } from '../types';
3
+ import { StatusManager } from './StatusManager';
4
+ export declare class StepExecutor {
5
+ settings: InternalExecutionSettings;
6
+ statusManager: StatusManager;
7
+ private swapExecutionManager;
8
+ private bridgeExecutionManager;
9
+ executionStopped: boolean;
10
+ constructor(statusManager: StatusManager, settings: InternalExecutionSettings);
11
+ stopStepExecution: (settings?: HaltingSettings) => void;
12
+ executeStep: (signer: Signer, step: Step) => Promise<Step>;
13
+ private executeSwap;
14
+ private executeCross;
15
+ }
@@ -0,0 +1,74 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.StepExecutor = void 0;
13
+ const bridge_execute_1 = require("./bridges/bridge.execute");
14
+ const swap_execute_1 = require("./exchanges/swap.execute");
15
+ const switchChain_1 = require("./switchChain");
16
+ const defaultExecutionHaltSettings = {
17
+ allowUpdates: true,
18
+ };
19
+ class StepExecutor {
20
+ constructor(statusManager, settings) {
21
+ this.swapExecutionManager = new swap_execute_1.SwapExecutionManager();
22
+ this.bridgeExecutionManager = new bridge_execute_1.BridgeExecutionManager();
23
+ this.executionStopped = false;
24
+ this.stopStepExecution = (settings) => {
25
+ const haltingSettings = Object.assign(Object.assign({}, defaultExecutionHaltSettings), settings);
26
+ this.swapExecutionManager.setShouldContinue(false);
27
+ this.bridgeExecutionManager.setShouldContinue(false);
28
+ this.statusManager.setShouldUpdate(haltingSettings.allowUpdates);
29
+ this.executionStopped = true;
30
+ };
31
+ this.executeStep = (signer, step) => __awaiter(this, void 0, void 0, function* () {
32
+ // check if signer is for correct chain
33
+ const updatedSigner = yield (0, switchChain_1.switchChain)(signer, this.statusManager, step, this.settings.switchChainHook, !this.executionStopped);
34
+ if (!updatedSigner) {
35
+ // chain switch was not successful, stop execution here
36
+ return step;
37
+ }
38
+ signer = updatedSigner;
39
+ switch (step.type) {
40
+ case 'lifi':
41
+ case 'cross':
42
+ yield this.executeCross(signer, step);
43
+ break;
44
+ case 'swap':
45
+ yield this.executeSwap(signer, step);
46
+ break;
47
+ default:
48
+ throw new Error('Unsupported step type.');
49
+ }
50
+ return step;
51
+ });
52
+ this.executeSwap = (signer, step) => __awaiter(this, void 0, void 0, function* () {
53
+ const swapParams = {
54
+ signer,
55
+ step,
56
+ settings: this.settings,
57
+ statusManager: this.statusManager,
58
+ };
59
+ return yield this.swapExecutionManager.execute(swapParams);
60
+ });
61
+ this.executeCross = (signer, step) => __awaiter(this, void 0, void 0, function* () {
62
+ const crossParams = {
63
+ signer,
64
+ step,
65
+ settings: this.settings,
66
+ statusManager: this.statusManager,
67
+ };
68
+ return yield this.bridgeExecutionManager.execute(crossParams);
69
+ });
70
+ this.statusManager = statusManager;
71
+ this.settings = settings;
72
+ }
73
+ }
74
+ exports.StepExecutor = StepExecutor;
@@ -0,0 +1,4 @@
1
+ import { Signer } from 'ethers';
2
+ import { Chain, Step, Token } from '../types';
3
+ import { StatusManager } from './StatusManager';
4
+ export declare const checkAllowance: (signer: Signer, step: Step, chain: Chain, token: Token, amount: string, spenderAddress: string, statusManager: StatusManager, infiniteApproval?: boolean, allowUserInteraction?: boolean) => Promise<void>;
@@ -0,0 +1,97 @@
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.checkAllowance = void 0;
16
+ const bignumber_js_1 = __importDefault(require("bignumber.js"));
17
+ const ethers_1 = require("ethers");
18
+ const utils_1 = require("../allowance/utils");
19
+ const getProvider_1 = require("../utils/getProvider");
20
+ const parseError_1 = require("../utils/parseError");
21
+ const checkAllowance = (signer, step, chain, token, amount, spenderAddress, statusManager, infiniteApproval = false, allowUserInteraction = false
22
+ // eslint-disable-next-line max-params
23
+ ) => __awaiter(void 0, void 0, void 0, function* () {
24
+ // Ask user to set allowance
25
+ // -> set currentExecution
26
+ let allowanceProcess = statusManager.findOrCreateProcess('TOKEN_ALLOWANCE', step);
27
+ // -> check allowance
28
+ try {
29
+ if (allowanceProcess.txHash) {
30
+ allowanceProcess = statusManager.updateProcess(step, allowanceProcess.type, 'PENDING');
31
+ yield (0, getProvider_1.getProvider)(signer).waitForTransaction(allowanceProcess.txHash);
32
+ allowanceProcess = statusManager.updateProcess(step, allowanceProcess.type, 'DONE');
33
+ // TODO: Do we need this check?
34
+ }
35
+ else if (allowanceProcess.status === 'DONE') {
36
+ allowanceProcess = statusManager.updateProcess(step, allowanceProcess.type, 'DONE');
37
+ }
38
+ else {
39
+ const approved = yield (0, utils_1.getApproved)(signer, token.address, spenderAddress);
40
+ if (new bignumber_js_1.default(amount).gt(approved)) {
41
+ if (!allowUserInteraction) {
42
+ return;
43
+ }
44
+ const approvalAmount = infiniteApproval
45
+ ? ethers_1.constants.MaxUint256.toString()
46
+ : amount;
47
+ const approveTx = yield (0, utils_1.setApproval)(signer, token.address, spenderAddress, approvalAmount);
48
+ // update currentExecution
49
+ allowanceProcess = statusManager.updateProcess(step, allowanceProcess.type, 'PENDING', {
50
+ txHash: approveTx.hash,
51
+ txLink: chain.metamask.blockExplorerUrls[0] + 'tx/' + approveTx.hash,
52
+ });
53
+ // wait for transcation
54
+ yield approveTx.wait();
55
+ allowanceProcess = statusManager.updateProcess(step, allowanceProcess.type, 'DONE');
56
+ }
57
+ else {
58
+ allowanceProcess = statusManager.updateProcess(step, allowanceProcess.type, 'DONE');
59
+ }
60
+ }
61
+ }
62
+ catch (e) {
63
+ // -> set status
64
+ if (e.code === 'TRANSACTION_REPLACED' && e.replacement) {
65
+ yield transactionReplaced(e.replacement, allowanceProcess, step, chain, statusManager);
66
+ }
67
+ else {
68
+ const error = yield (0, parseError_1.parseError)(e, step, allowanceProcess);
69
+ allowanceProcess = statusManager.updateProcess(step, allowanceProcess.type, 'FAILED', {
70
+ error: {
71
+ message: error.message,
72
+ htmlMessage: error.htmlMessage,
73
+ code: error.code,
74
+ },
75
+ });
76
+ statusManager.updateExecution(step, 'FAILED');
77
+ throw error;
78
+ }
79
+ }
80
+ });
81
+ exports.checkAllowance = checkAllowance;
82
+ const transactionReplaced = (replacementTx, allowanceProcess, step, chain, statusManager) => __awaiter(void 0, void 0, void 0, function* () {
83
+ try {
84
+ allowanceProcess = statusManager.updateProcess(step, allowanceProcess.type, 'PENDING', {
85
+ txHash: replacementTx.hash,
86
+ txLink: chain.metamask.blockExplorerUrls[0] + 'tx/' + replacementTx.hash,
87
+ });
88
+ yield replacementTx.wait();
89
+ allowanceProcess = statusManager.updateProcess(step, allowanceProcess.type, 'DONE');
90
+ }
91
+ catch (e) {
92
+ if (e.code === 'TRANSACTION_REPLACED' && e.replacement) {
93
+ yield transactionReplaced(e.replacement, allowanceProcess, step, chain, statusManager);
94
+ }
95
+ throw e;
96
+ }
97
+ });
@@ -0,0 +1,3 @@
1
+ import { ethers } from 'ethers';
2
+ import { Step } from '..';
3
+ export declare const balanceCheck: (signer: ethers.Signer, step: Step) => Promise<void>;
@@ -0,0 +1,48 @@
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.balanceCheck = void 0;
16
+ const bignumber_js_1 = __importDefault(require("bignumber.js"));
17
+ const balances_1 = __importDefault(require("../balances"));
18
+ 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);
21
+ if (tokenAmount) {
22
+ const currentBalance = new bignumber_js_1.default(tokenAmount.amount).shiftedBy(tokenAmount.decimals);
23
+ const neededBalance = new bignumber_js_1.default(step.action.fromAmount);
24
+ if (currentBalance.lt(neededBalance)) {
25
+ if (neededBalance.multipliedBy(1 - step.action.slippage).lte(currentBalance)) {
26
+ // adjust amount in slippage limits
27
+ step.action.fromAmount = currentBalance.toFixed(0);
28
+ }
29
+ else {
30
+ const neeeded = neededBalance.shiftedBy(-tokenAmount.decimals).toFixed();
31
+ const current = currentBalance
32
+ .shiftedBy(-tokenAmount.decimals)
33
+ .toFixed();
34
+ let errorMessage = `Your ${tokenAmount.symbol} balance is too low, ` +
35
+ `you try to transfer ${neeeded} ${tokenAmount.symbol}, ` +
36
+ `but your wallet only holds ${current} ${tokenAmount.symbol}. ` +
37
+ `No funds have been sent. `;
38
+ if (!currentBalance.isZero()) {
39
+ errorMessage +=
40
+ `If the problem consists, please delete this transfer and ` +
41
+ `start a new one with a maximum of ${current} ${tokenAmount.symbol}.`;
42
+ }
43
+ throw new errors_1.ValidationError('The balance is too low.', errorMessage);
44
+ }
45
+ }
46
+ }
47
+ });
48
+ exports.balanceCheck = balanceCheck;
@@ -0,0 +1,7 @@
1
+ import { Execution } from '@lifi/types';
2
+ import { ExecuteCrossParams } from '../../types';
3
+ export declare class BridgeExecutionManager {
4
+ shouldContinue: boolean;
5
+ setShouldContinue: (val: boolean) => void;
6
+ execute: ({ signer, step, statusManager, settings, }: ExecuteCrossParams) => Promise<Execution>;
7
+ }
@@ -0,0 +1,154 @@
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.BridgeExecutionManager = void 0;
16
+ const ethers_1 = require("ethers");
17
+ const ApiService_1 = __importDefault(require("../../services/ApiService"));
18
+ const ChainsService_1 = __importDefault(require("../../services/ChainsService"));
19
+ const errors_1 = require("../../utils/errors");
20
+ const getProvider_1 = require("../../utils/getProvider");
21
+ const parseError_1 = require("../../utils/parseError");
22
+ const utils_1 = require("../../utils/utils");
23
+ const allowance_execute_1 = require("../allowance.execute");
24
+ const balanceCheck_execute_1 = require("../balanceCheck.execute");
25
+ const stepComparison_1 = require("../stepComparison");
26
+ const switchChain_1 = require("../switchChain");
27
+ const utils_2 = require("../utils");
28
+ class BridgeExecutionManager {
29
+ constructor() {
30
+ this.shouldContinue = true;
31
+ this.setShouldContinue = (val) => {
32
+ this.shouldContinue = val;
33
+ };
34
+ this.execute = ({ signer, step, statusManager, settings, }) => __awaiter(this, void 0, void 0, function* () {
35
+ var _a, _b, _c, _d;
36
+ const { action, estimate } = step;
37
+ step.execution = statusManager.initExecutionObject(step);
38
+ const chainsService = ChainsService_1.default.getInstance();
39
+ const fromChain = yield chainsService.getChainById(action.fromChainId);
40
+ const toChain = yield chainsService.getChainById(action.toChainId);
41
+ // STEP 1: Check Allowance ////////////////////////////////////////////////
42
+ // approval still needed?
43
+ const oldCrossProcess = step.execution.process.find((p) => p.type === 'CROSS_CHAIN');
44
+ if (!(oldCrossProcess === null || oldCrossProcess === void 0 ? void 0 : oldCrossProcess.txHash)) {
45
+ if (action.fromToken.address !== ethers_1.constants.AddressZero) {
46
+ // Check Token Approval only if fromToken is not the native token => no approval needed in that case
47
+ yield (0, allowance_execute_1.checkAllowance)(signer, step, fromChain, action.fromToken, action.fromAmount, estimate.approvalAddress, statusManager, settings.infiniteApproval, this.shouldContinue);
48
+ }
49
+ }
50
+ // STEP 2: Get Transaction ////////////////////////////////////////////////
51
+ let crossChainProcess = statusManager.findOrCreateProcess('CROSS_CHAIN', step);
52
+ try {
53
+ let tx;
54
+ if (crossChainProcess.txHash) {
55
+ // load exiting transaction
56
+ tx = yield (0, getProvider_1.getProvider)(signer).getTransaction(crossChainProcess.txHash);
57
+ }
58
+ else {
59
+ // check balance
60
+ yield (0, balanceCheck_execute_1.balanceCheck)(signer, step);
61
+ // create new transaction
62
+ const personalizedStep = yield (0, utils_1.personalizeStep)(signer, step);
63
+ const updatedStep = yield ApiService_1.default.getStepTransaction(personalizedStep);
64
+ step = Object.assign(Object.assign({}, (yield (0, stepComparison_1.stepComparison)(statusManager, personalizedStep, updatedStep, settings.acceptSlippageUpdateHook, this.shouldContinue))), { execution: step.execution });
65
+ const { transactionRequest } = step;
66
+ if (!transactionRequest) {
67
+ throw new errors_1.TransactionError(errors_1.LifiErrorCode.TransactionUnprepared, 'Unable to prepare transaction.');
68
+ }
69
+ // STEP 3: Send Transaction ///////////////////////////////////////////////
70
+ // make sure that chain is still correct
71
+ const updatedSigner = yield (0, switchChain_1.switchChain)(signer, statusManager, step, settings.switchChainHook, this.shouldContinue);
72
+ if (!updatedSigner) {
73
+ // chain switch was not successful, stop execution here
74
+ return step.execution;
75
+ }
76
+ signer = updatedSigner;
77
+ crossChainProcess = statusManager.updateProcess(step, crossChainProcess.type, 'ACTION_REQUIRED');
78
+ if (!this.shouldContinue) {
79
+ return step.execution;
80
+ }
81
+ tx = yield signer.sendTransaction(transactionRequest);
82
+ // STEP 4: Wait for Transaction ///////////////////////////////////////////
83
+ crossChainProcess = statusManager.updateProcess(step, crossChainProcess.type, 'PENDING', {
84
+ txHash: tx.hash,
85
+ txLink: fromChain.metamask.blockExplorerUrls[0] + 'tx/' + tx.hash,
86
+ });
87
+ }
88
+ yield tx.wait();
89
+ }
90
+ catch (e) {
91
+ if (e.code === 'TRANSACTION_REPLACED' && e.replacement) {
92
+ crossChainProcess = statusManager.updateProcess(step, crossChainProcess.type, 'PENDING', {
93
+ txHash: e.replacement.hash,
94
+ txLink: fromChain.metamask.blockExplorerUrls[0] +
95
+ 'tx/' +
96
+ e.replacement.hash,
97
+ });
98
+ }
99
+ else {
100
+ const error = yield (0, parseError_1.parseError)(e, step, crossChainProcess);
101
+ crossChainProcess = statusManager.updateProcess(step, crossChainProcess.type, 'FAILED', {
102
+ error: {
103
+ message: error.message,
104
+ htmlMessage: error.htmlMessage,
105
+ code: error.code,
106
+ },
107
+ });
108
+ statusManager.updateExecution(step, 'FAILED');
109
+ throw error;
110
+ }
111
+ }
112
+ crossChainProcess = statusManager.updateProcess(step, crossChainProcess.type, 'DONE');
113
+ // STEP 5: Wait for Receiver //////////////////////////////////////
114
+ let receivingChainProcess = statusManager.findOrCreateProcess('RECEIVING_CHAIN', step, 'PENDING');
115
+ let statusResponse;
116
+ try {
117
+ if (!crossChainProcess.txHash) {
118
+ throw new Error('Transaction hash is undefined.');
119
+ }
120
+ statusResponse = yield (0, utils_2.waitForReceivingTransaction)(crossChainProcess.txHash, statusManager, receivingChainProcess.type, step);
121
+ }
122
+ catch (e) {
123
+ receivingChainProcess = statusManager.updateProcess(step, receivingChainProcess.type, 'FAILED', {
124
+ error: {
125
+ code: errors_1.LifiErrorCode.TransactionFailed,
126
+ message: 'Failed while waiting for receiving chain.',
127
+ htmlMessage: (0, parseError_1.getTransactionFailedMessage)(step, crossChainProcess.txLink),
128
+ },
129
+ });
130
+ statusManager.updateExecution(step, 'FAILED');
131
+ throw e;
132
+ }
133
+ receivingChainProcess = statusManager.updateProcess(step, receivingChainProcess.type, 'DONE', {
134
+ substatus: statusResponse.substatus,
135
+ substatusMessage: statusResponse.substatusMessage ||
136
+ (0, utils_2.getSubstatusMessage)(statusResponse.status, statusResponse.substatus),
137
+ txHash: (_a = statusResponse.receiving) === null || _a === void 0 ? void 0 : _a.txHash,
138
+ txLink: toChain.metamask.blockExplorerUrls[0] +
139
+ 'tx/' +
140
+ ((_b = statusResponse.receiving) === null || _b === void 0 ? void 0 : _b.txHash),
141
+ });
142
+ statusManager.updateExecution(step, 'DONE', {
143
+ fromAmount: statusResponse.sending.amount,
144
+ toAmount: (_c = statusResponse.receiving) === null || _c === void 0 ? void 0 : _c.amount,
145
+ toToken: (_d = statusResponse.receiving) === null || _d === void 0 ? void 0 : _d.token,
146
+ gasUsed: statusResponse.sending.gasUsed,
147
+ gasPrice: statusResponse.sending.gasPrice,
148
+ });
149
+ // DONE
150
+ return step.execution;
151
+ });
152
+ }
153
+ }
154
+ exports.BridgeExecutionManager = BridgeExecutionManager;
@@ -0,0 +1,7 @@
1
+ import { Execution } from '@lifi/types';
2
+ import { ExecuteSwapParams } from '../../types';
3
+ export declare class SwapExecutionManager {
4
+ shouldContinue: boolean;
5
+ setShouldContinue: (val: boolean) => void;
6
+ execute: ({ signer, step, statusManager, settings, }: ExecuteSwapParams) => Promise<Execution>;
7
+ }