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