@lifi/sdk 1.1.4 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/dist/cjs/Lifi.d.ts +200 -0
- package/dist/cjs/Lifi.js +376 -0
- package/dist/cjs/allowance/index.d.ts +22 -0
- package/dist/cjs/allowance/index.js +78 -0
- package/dist/cjs/allowance/utils.d.ts +14 -0
- package/dist/cjs/allowance/utils.js +82 -0
- package/dist/cjs/balances/index.d.ts +11 -0
- package/dist/cjs/balances/index.js +46 -0
- package/dist/cjs/balances/utils.d.ts +5 -0
- package/dist/cjs/balances/utils.js +150 -0
- package/dist/cjs/connectors.d.ts +6 -0
- package/dist/cjs/connectors.js +77 -0
- package/dist/cjs/execution/StatusManager.d.ts +65 -0
- package/dist/cjs/execution/StatusManager.js +167 -0
- package/dist/cjs/execution/StepExecutor.d.ts +15 -0
- package/dist/cjs/execution/StepExecutor.js +74 -0
- package/dist/cjs/execution/allowance.execute.d.ts +4 -0
- package/dist/cjs/execution/allowance.execute.js +97 -0
- package/dist/cjs/execution/balanceCheck.execute.d.ts +3 -0
- package/dist/cjs/execution/balanceCheck.execute.js +48 -0
- package/dist/cjs/execution/bridges/bridge.execute.d.ts +7 -0
- package/dist/cjs/execution/bridges/bridge.execute.js +154 -0
- package/dist/cjs/execution/exchanges/swap.execute.d.ts +7 -0
- package/dist/cjs/execution/exchanges/swap.execute.js +164 -0
- package/dist/cjs/execution/index.d.ts +1 -0
- package/dist/cjs/execution/index.js +17 -0
- package/dist/cjs/execution/stepComparison.d.ts +14 -0
- package/dist/cjs/execution/stepComparison.js +46 -0
- package/dist/cjs/execution/switchChain.d.ts +16 -0
- package/dist/cjs/execution/switchChain.js +58 -0
- package/dist/cjs/execution/utils.d.ts +6 -0
- package/dist/cjs/execution/utils.js +137 -0
- package/dist/cjs/helpers.d.ts +18 -0
- package/dist/cjs/helpers.js +54 -0
- package/dist/cjs/index.d.ts +6 -0
- package/dist/cjs/index.js +27 -0
- package/dist/cjs/services/ApiService.d.ts +15 -0
- package/dist/cjs/services/ApiService.js +272 -0
- package/dist/cjs/services/ChainsService.d.ts +11 -0
- package/dist/cjs/services/ChainsService.js +54 -0
- package/dist/cjs/services/ConfigService.d.ts +23 -0
- package/dist/cjs/services/ConfigService.js +98 -0
- package/dist/cjs/typeguards.d.ts +4 -0
- package/dist/cjs/typeguards.js +53 -0
- package/dist/cjs/types/ERC20.d.ts +22 -0
- package/dist/cjs/types/ERC20.js +53 -0
- package/dist/cjs/types/index.d.ts +4 -0
- package/dist/cjs/types/index.js +22 -0
- package/dist/cjs/types/internal.types.d.ts +85 -0
- package/dist/cjs/types/internal.types.js +2 -0
- package/dist/cjs/utils/errors.d.ts +75 -0
- package/dist/cjs/utils/errors.js +115 -0
- package/dist/cjs/utils/getProvider.d.ts +3 -0
- package/dist/cjs/utils/getProvider.js +11 -0
- package/dist/cjs/utils/multicall.d.ts +10 -0
- package/dist/cjs/utils/multicall.js +77 -0
- package/dist/cjs/utils/multicallAbi.json +313 -0
- package/dist/cjs/utils/parseError.d.ts +38 -0
- package/dist/cjs/utils/parseError.js +141 -0
- package/dist/cjs/utils/preRestart.d.ts +2 -0
- package/dist/cjs/utils/preRestart.js +31 -0
- package/dist/cjs/utils/utils.d.ts +26 -0
- package/dist/cjs/utils/utils.js +120 -0
- 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,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
|
+
}
|