@lifi/sdk 1.1.2 → 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 +11 -0
- package/dist/Lifi.js +179 -285
- package/dist/allowance/index.js +56 -148
- package/dist/allowance/utils.js +51 -116
- package/dist/balances/index.js +29 -92
- package/dist/balances/utils.js +108 -218
- 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/dist/connectors.js +50 -133
- package/dist/execution/StatusManager.js +34 -41
- package/dist/execution/StepExecutor.js +54 -123
- package/dist/execution/allowance.execute.js +76 -142
- package/dist/execution/balanceCheck.execute.js +29 -74
- package/dist/execution/bridges/bridge.execute.js +132 -221
- package/dist/execution/exchanges/swap.execute.js +142 -225
- package/dist/execution/index.js +1 -17
- package/dist/execution/stepComparison.js +22 -61
- package/dist/execution/switchChain.js +33 -81
- package/dist/execution/utils.js +60 -119
- package/dist/helpers.js +15 -53
- package/dist/index.js +6 -25
- package/dist/services/ApiService.js +248 -385
- package/dist/services/ChainsService.js +29 -89
- package/dist/services/ConfigService.js +47 -86
- package/dist/typeguards.js +13 -21
- package/dist/types/ERC20.js +1 -4
- package/dist/types/index.js +4 -22
- package/dist/types/internal.types.js +1 -2
- package/dist/utils/errors.js +47 -93
- package/dist/utils/getProvider.js +3 -7
- package/dist/utils/multicall.js +61 -117
- package/dist/utils/parseError.js +73 -141
- package/dist/utils/preRestart.js +14 -21
- package/dist/utils/utils.js +47 -130
- package/package.json +34 -11
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
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.SwapExecutionManager = 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 SwapExecutionManager {
|
|
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
|
+
// setup
|
|
36
|
+
var _a, _b, _c, _d;
|
|
37
|
+
const { action, estimate } = step;
|
|
38
|
+
step.execution = statusManager.initExecutionObject(step);
|
|
39
|
+
const chainsService = ChainsService_1.default.getInstance();
|
|
40
|
+
const fromChain = yield chainsService.getChainById(action.fromChainId);
|
|
41
|
+
// Approval
|
|
42
|
+
if (action.fromToken.address !== ethers_1.constants.AddressZero) {
|
|
43
|
+
yield (0, allowance_execute_1.checkAllowance)(signer, step, fromChain, action.fromToken, action.fromAmount, estimate.approvalAddress, statusManager, settings.infiniteApproval, this.shouldContinue);
|
|
44
|
+
}
|
|
45
|
+
// Start Swap
|
|
46
|
+
// -> set step.execution
|
|
47
|
+
let swapProcess = statusManager.findOrCreateProcess('SWAP', step);
|
|
48
|
+
// -> swapping
|
|
49
|
+
let tx;
|
|
50
|
+
try {
|
|
51
|
+
if (swapProcess.txHash) {
|
|
52
|
+
// -> restore existing tx
|
|
53
|
+
tx = yield (0, getProvider_1.getProvider)(signer).getTransaction(swapProcess.txHash);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// -> check balance
|
|
57
|
+
yield (0, balanceCheck_execute_1.balanceCheck)(signer, step);
|
|
58
|
+
// -> get tx from backend
|
|
59
|
+
const personalizedStep = yield (0, utils_1.personalizeStep)(signer, step);
|
|
60
|
+
const updatedStep = yield ApiService_1.default.getStepTransaction(personalizedStep);
|
|
61
|
+
step = Object.assign(Object.assign({}, (yield (0, stepComparison_1.stepComparison)(statusManager, personalizedStep, updatedStep, settings.acceptSlippageUpdateHook, this.shouldContinue))), { execution: step.execution });
|
|
62
|
+
const { transactionRequest } = step;
|
|
63
|
+
if (!transactionRequest) {
|
|
64
|
+
throw new errors_1.TransactionError(errors_1.LifiErrorCode.TransactionUnprepared, 'Unable to prepare transaction.');
|
|
65
|
+
}
|
|
66
|
+
// make sure that chain is still correct
|
|
67
|
+
const updatedSigner = yield (0, switchChain_1.switchChain)(signer, statusManager, step, settings.switchChainHook, this.shouldContinue);
|
|
68
|
+
if (!updatedSigner) {
|
|
69
|
+
// chain switch was not successful, stop execution here
|
|
70
|
+
return step.execution;
|
|
71
|
+
}
|
|
72
|
+
signer = updatedSigner;
|
|
73
|
+
// -> set step.execution
|
|
74
|
+
swapProcess = swapProcess = statusManager.updateProcess(step, swapProcess.type, 'ACTION_REQUIRED');
|
|
75
|
+
if (!this.shouldContinue) {
|
|
76
|
+
return step.execution; // stop before user interaction is needed
|
|
77
|
+
}
|
|
78
|
+
// -> submit tx
|
|
79
|
+
tx = yield signer.sendTransaction(transactionRequest);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
const error = yield (0, parseError_1.parseError)(e, step, swapProcess);
|
|
84
|
+
swapProcess = statusManager.updateProcess(step, swapProcess.type, 'FAILED', {
|
|
85
|
+
error: {
|
|
86
|
+
message: error.message,
|
|
87
|
+
htmlMessage: error.htmlMessage,
|
|
88
|
+
code: error.code,
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
statusManager.updateExecution(step, 'FAILED');
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
// Wait for Transaction
|
|
95
|
+
swapProcess = statusManager.updateProcess(step, swapProcess.type, 'PENDING', {
|
|
96
|
+
txLink: fromChain.metamask.blockExplorerUrls[0] + 'tx/' + tx.hash,
|
|
97
|
+
txHash: tx.hash,
|
|
98
|
+
});
|
|
99
|
+
// -> waiting
|
|
100
|
+
let receipt;
|
|
101
|
+
try {
|
|
102
|
+
receipt = yield tx.wait();
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
// -> set status
|
|
106
|
+
if (e.code === 'TRANSACTION_REPLACED' && e.replacement) {
|
|
107
|
+
receipt = e.replacement;
|
|
108
|
+
swapProcess = statusManager.updateProcess(step, swapProcess.type, 'PENDING', {
|
|
109
|
+
txHash: e.replacement.hash,
|
|
110
|
+
txLink: fromChain.metamask.blockExplorerUrls[0] +
|
|
111
|
+
'tx/' +
|
|
112
|
+
e.replacement.hash,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
const error = yield (0, parseError_1.parseError)(e);
|
|
117
|
+
swapProcess = statusManager.updateProcess(step, swapProcess.type, 'FAILED', {
|
|
118
|
+
error: {
|
|
119
|
+
message: error.message,
|
|
120
|
+
htmlMessage: error.htmlMessage,
|
|
121
|
+
code: error.code,
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
statusManager.updateExecution(step, 'FAILED');
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
let statusResponse;
|
|
129
|
+
try {
|
|
130
|
+
if (!swapProcess.txHash) {
|
|
131
|
+
throw new Error('Transaction hash is undefined.');
|
|
132
|
+
}
|
|
133
|
+
statusResponse = yield (0, utils_2.waitForReceivingTransaction)(swapProcess.txHash, statusManager, swapProcess.type, step);
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
swapProcess = statusManager.updateProcess(step, swapProcess.type, 'FAILED', {
|
|
137
|
+
error: {
|
|
138
|
+
code: errors_1.LifiErrorCode.TransactionFailed,
|
|
139
|
+
message: 'Failed while waiting for receiving chain.',
|
|
140
|
+
htmlMessage: (0, parseError_1.getTransactionFailedMessage)(step, swapProcess.txLink),
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
statusManager.updateExecution(step, 'FAILED');
|
|
144
|
+
throw e;
|
|
145
|
+
}
|
|
146
|
+
swapProcess = statusManager.updateProcess(step, swapProcess.type, 'DONE', {
|
|
147
|
+
txHash: (_a = statusResponse.receiving) === null || _a === void 0 ? void 0 : _a.txHash,
|
|
148
|
+
txLink: fromChain.metamask.blockExplorerUrls[0] +
|
|
149
|
+
'tx/' +
|
|
150
|
+
((_b = statusResponse.receiving) === null || _b === void 0 ? void 0 : _b.txHash),
|
|
151
|
+
});
|
|
152
|
+
statusManager.updateExecution(step, 'DONE', {
|
|
153
|
+
fromAmount: statusResponse.sending.amount,
|
|
154
|
+
toAmount: (_c = statusResponse.receiving) === null || _c === void 0 ? void 0 : _c.amount,
|
|
155
|
+
toToken: (_d = statusResponse.receiving) === null || _d === void 0 ? void 0 : _d.token,
|
|
156
|
+
gasUsed: statusResponse.sending.gasUsed,
|
|
157
|
+
gasPrice: statusResponse.sending.gasPrice,
|
|
158
|
+
});
|
|
159
|
+
// DONE
|
|
160
|
+
return step.execution;
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
exports.SwapExecutionManager = SwapExecutionManager;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './StatusManager';
|
|
@@ -0,0 +1,17 @@
|
|
|
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("./StatusManager"), exports);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { StatusManager } from '.';
|
|
2
|
+
import { AcceptSlippageUpdateHook, Step } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* This method checks whether the new and updated Step meets the required slippage conditions.
|
|
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.
|
|
7
|
+
*
|
|
8
|
+
* @param statusManager
|
|
9
|
+
* @param oldStep
|
|
10
|
+
* @param newStep
|
|
11
|
+
* @param acceptSlippageUpdateHook
|
|
12
|
+
* @param allowUserInteraction
|
|
13
|
+
*/
|
|
14
|
+
export declare const stepComparison: (statusManager: StatusManager, oldStep: Step, newStep: Step, acceptSlippageUpdateHook: AcceptSlippageUpdateHook, allowUserInteraction: boolean) => Promise<Step>;
|
|
@@ -0,0 +1,46 @@
|
|
|
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.stepComparison = void 0;
|
|
13
|
+
const errors_1 = require("../utils/errors");
|
|
14
|
+
const parseError_1 = require("../utils/parseError");
|
|
15
|
+
const utils_1 = require("./utils");
|
|
16
|
+
/**
|
|
17
|
+
* This method checks whether the new and updated Step meets the required slippage conditions.
|
|
18
|
+
* 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.
|
|
20
|
+
*
|
|
21
|
+
* @param statusManager
|
|
22
|
+
* @param oldStep
|
|
23
|
+
* @param newStep
|
|
24
|
+
* @param acceptSlippageUpdateHook
|
|
25
|
+
* @param allowUserInteraction
|
|
26
|
+
*/
|
|
27
|
+
const stepComparison = (statusManager, oldStep, newStep, acceptSlippageUpdateHook, allowUserInteraction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
28
|
+
if ((0, utils_1.updatedStepMeetsSlippageConditions)(oldStep, newStep)) {
|
|
29
|
+
return statusManager.updateStepInRoute(newStep);
|
|
30
|
+
}
|
|
31
|
+
let allowStepUpdate;
|
|
32
|
+
if (allowUserInteraction) {
|
|
33
|
+
allowStepUpdate = yield acceptSlippageUpdateHook({
|
|
34
|
+
oldToAmount: oldStep.estimate.toAmount,
|
|
35
|
+
newToAmount: newStep.estimate.toAmount,
|
|
36
|
+
toToken: newStep.action.toToken,
|
|
37
|
+
oldSlippage: oldStep.action.slippage,
|
|
38
|
+
newSlippage: newStep.action.slippage,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (!allowStepUpdate) {
|
|
42
|
+
throw new errors_1.TransactionError(errors_1.LifiErrorCode.SlippageNotMet, 'Slippage conditions not met!', (0, parseError_1.getSlippageNotMetMessage)(oldStep));
|
|
43
|
+
}
|
|
44
|
+
return statusManager.updateStepInRoute(newStep);
|
|
45
|
+
});
|
|
46
|
+
exports.stepComparison = stepComparison;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Step } from '@lifi/types';
|
|
2
|
+
import { Signer } from 'ethers';
|
|
3
|
+
import { SwitchChainHook } from '../types';
|
|
4
|
+
import { StatusManager } from './StatusManager';
|
|
5
|
+
/**
|
|
6
|
+
* This method checks whether the signer is configured for the correct chain.
|
|
7
|
+
* If yes it returns the signer.
|
|
8
|
+
* If no and if user interaction is allowed it triggers the switchChainHook. If no user interaction is allowed it aborts.
|
|
9
|
+
*
|
|
10
|
+
* @param signer
|
|
11
|
+
* @param statusManager
|
|
12
|
+
* @param step
|
|
13
|
+
* @param switchChainHook
|
|
14
|
+
* @param allowUserInteraction
|
|
15
|
+
*/
|
|
16
|
+
export declare const switchChain: (signer: Signer, statusManager: StatusManager, step: Step, switchChainHook: SwitchChainHook, allowUserInteraction: boolean) => Promise<Signer | undefined>;
|
|
@@ -0,0 +1,58 @@
|
|
|
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.switchChain = void 0;
|
|
13
|
+
const errors_1 = require("../utils/errors");
|
|
14
|
+
/**
|
|
15
|
+
* This method checks whether the signer is configured for the correct chain.
|
|
16
|
+
* If yes it returns the signer.
|
|
17
|
+
* If no and if user interaction is allowed it triggers the switchChainHook. If no user interaction is allowed it aborts.
|
|
18
|
+
*
|
|
19
|
+
* @param signer
|
|
20
|
+
* @param statusManager
|
|
21
|
+
* @param step
|
|
22
|
+
* @param switchChainHook
|
|
23
|
+
* @param allowUserInteraction
|
|
24
|
+
*/
|
|
25
|
+
const switchChain = (signer, statusManager, step, switchChainHook, allowUserInteraction) => __awaiter(void 0, void 0, void 0, function* () {
|
|
26
|
+
// if we are already on the correct chain we can proceed directly
|
|
27
|
+
if ((yield signer.getChainId()) === step.action.fromChainId) {
|
|
28
|
+
return signer;
|
|
29
|
+
}
|
|
30
|
+
// -> set status message
|
|
31
|
+
step.execution = statusManager.initExecutionObject(step);
|
|
32
|
+
statusManager.updateExecution(step, 'CHAIN_SWITCH_REQUIRED');
|
|
33
|
+
let switchProcess = statusManager.findOrCreateProcess('SWITCH_CHAIN', step, 'PENDING');
|
|
34
|
+
if (!allowUserInteraction) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const updatedSigner = yield switchChainHook(step.action.fromChainId);
|
|
39
|
+
const updatedChainId = yield (updatedSigner === null || updatedSigner === void 0 ? void 0 : updatedSigner.getChainId());
|
|
40
|
+
if (updatedChainId !== step.action.fromChainId) {
|
|
41
|
+
throw new errors_1.ProviderError(errors_1.LifiErrorCode.ChainSwitchError, 'Chain switch required.');
|
|
42
|
+
}
|
|
43
|
+
switchProcess = statusManager.updateProcess(step, switchProcess.type, 'DONE');
|
|
44
|
+
statusManager.updateExecution(step, 'PENDING');
|
|
45
|
+
return updatedSigner;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
switchProcess = statusManager.updateProcess(step, switchProcess.type, 'FAILED', {
|
|
49
|
+
error: {
|
|
50
|
+
message: error.message,
|
|
51
|
+
code: error.code,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
statusManager.updateExecution(step, 'FAILED');
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
exports.switchChain = switchChain;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ProcessType, Status, StatusMessage, StatusResponse, Step, Substatus } from '@lifi/types';
|
|
2
|
+
import { StatusManager } from '..';
|
|
3
|
+
export declare function waitForReceivingTransaction(txHash: string, statusManager: StatusManager, processType: ProcessType, step: Step): Promise<StatusResponse>;
|
|
4
|
+
export declare function getProcessMessage(type: ProcessType, status: Status): string | undefined;
|
|
5
|
+
export declare function getSubstatusMessage(status: StatusMessage, substatus?: Substatus): string | undefined;
|
|
6
|
+
export declare function updatedStepMeetsSlippageConditions(oldStep: Step, newStep: Step): boolean;
|