@lifi/sdk 1.1.3 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -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,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.revokeTokenApproval = exports.approveToken = exports.bulkGetTokenApproval = exports.getTokenApproval = void 0;
|
|
16
|
+
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
17
|
+
const ethers_1 = require("ethers");
|
|
18
|
+
const helpers_1 = require("../helpers");
|
|
19
|
+
const utils_1 = require("../utils/utils");
|
|
20
|
+
const utils_2 = require("./utils");
|
|
21
|
+
const getTokenApproval = (signer, token, approvalAddress) => __awaiter(void 0, void 0, void 0, function* () {
|
|
22
|
+
// native token don't need approval
|
|
23
|
+
if ((0, utils_1.isNativeTokenAddress)(token.address)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const approved = yield (0, utils_2.getApproved)(signer, token.address, approvalAddress);
|
|
27
|
+
return approved.toString();
|
|
28
|
+
});
|
|
29
|
+
exports.getTokenApproval = getTokenApproval;
|
|
30
|
+
const bulkGetTokenApproval = (signer, tokenData) => __awaiter(void 0, void 0, void 0, function* () {
|
|
31
|
+
// filter out native tokens
|
|
32
|
+
const filteredTokenData = tokenData.filter(({ token }) => !(0, utils_1.isNativeTokenAddress)(token.address));
|
|
33
|
+
// group by chain
|
|
34
|
+
const tokenDataByChain = (0, utils_2.groupByChain)(filteredTokenData);
|
|
35
|
+
const approvalPromises = Object.keys(tokenDataByChain).map((chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
36
|
+
const parsedChainId = Number.parseInt(chainId);
|
|
37
|
+
// get allowances for current chain and token list
|
|
38
|
+
return (0, utils_2.getAllowanceViaMulticall)(signer, parsedChainId, tokenDataByChain[parsedChainId]);
|
|
39
|
+
}));
|
|
40
|
+
const approvalsByChain = yield Promise.all(approvalPromises);
|
|
41
|
+
const approvals = approvalsByChain.flat();
|
|
42
|
+
return tokenData.map(({ token }) => {
|
|
43
|
+
// native token don't need approval
|
|
44
|
+
if ((0, utils_1.isNativeTokenAddress)(token.address)) {
|
|
45
|
+
return { token, approval: undefined };
|
|
46
|
+
}
|
|
47
|
+
const approved = approvals.find((approval) => (0, helpers_1.isSameToken)(approval.token, token));
|
|
48
|
+
return { token, approval: approved === null || approved === void 0 ? void 0 : approved.approvedAmount.toString() };
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
exports.bulkGetTokenApproval = bulkGetTokenApproval;
|
|
52
|
+
const approveToken = ({ signer, token, approvalAddress, amount, infiniteApproval = false, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
53
|
+
// native token don't need approval
|
|
54
|
+
if ((0, utils_1.isNativeTokenAddress)(token.address)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const approvedAmount = yield (0, utils_2.getApproved)(signer, token.address, approvalAddress);
|
|
58
|
+
if (new bignumber_js_1.default(amount).gt(approvedAmount)) {
|
|
59
|
+
const approvalAmount = infiniteApproval
|
|
60
|
+
? ethers_1.constants.MaxUint256.toString()
|
|
61
|
+
: amount;
|
|
62
|
+
const approveTx = yield (0, utils_2.setApproval)(signer, token.address, approvalAddress, approvalAmount);
|
|
63
|
+
yield approveTx.wait();
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
exports.approveToken = approveToken;
|
|
67
|
+
const revokeTokenApproval = ({ signer, token, approvalAddress, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
68
|
+
// native token don't need approval
|
|
69
|
+
if ((0, utils_1.isNativeTokenAddress)(token.address)) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const approvedAmount = yield (0, utils_2.getApproved)(signer, token.address, approvalAddress);
|
|
73
|
+
if (!approvedAmount.isZero()) {
|
|
74
|
+
const approveTx = yield (0, utils_2.setApproval)(signer, token.address, approvalAddress, '0');
|
|
75
|
+
yield approveTx.wait();
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
exports.revokeTokenApproval = revokeTokenApproval;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ChainId, Token } from '@lifi/types';
|
|
2
|
+
import BigNumber from 'bignumber.js';
|
|
3
|
+
import { ContractTransaction, Signer } from 'ethers';
|
|
4
|
+
import { RevokeTokenData } from '../types';
|
|
5
|
+
export declare const getApproved: (signer: Signer, tokenAddress: string, contractAddress: string) => Promise<BigNumber>;
|
|
6
|
+
export declare const setApproval: (signer: Signer, tokenAddress: string, contractAddress: string, amount: string) => Promise<ContractTransaction>;
|
|
7
|
+
export declare const getAllowanceViaMulticall: (signer: Signer, chainId: ChainId, tokenData: RevokeTokenData[]) => Promise<{
|
|
8
|
+
token: Token;
|
|
9
|
+
approvalAddress: string;
|
|
10
|
+
approvedAmount: BigNumber;
|
|
11
|
+
}[]>;
|
|
12
|
+
export declare const groupByChain: (tokenDataList: RevokeTokenData[]) => {
|
|
13
|
+
[chainId: number]: RevokeTokenData[];
|
|
14
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
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.groupByChain = exports.getAllowanceViaMulticall = exports.setApproval = exports.getApproved = void 0;
|
|
16
|
+
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
17
|
+
const ethers_1 = require("ethers");
|
|
18
|
+
const ChainsService_1 = __importDefault(require("../services/ChainsService"));
|
|
19
|
+
const types_1 = require("../types");
|
|
20
|
+
const errors_1 = require("../utils/errors");
|
|
21
|
+
const multicall_1 = require("../utils/multicall");
|
|
22
|
+
const getApproved = (signer, tokenAddress, contractAddress) => __awaiter(void 0, void 0, void 0, function* () {
|
|
23
|
+
const signerAddress = yield signer.getAddress();
|
|
24
|
+
const erc20 = new ethers_1.Contract(tokenAddress, types_1.ERC20_ABI, signer);
|
|
25
|
+
try {
|
|
26
|
+
const approved = yield erc20.allowance(signerAddress, contractAddress);
|
|
27
|
+
return new bignumber_js_1.default(approved.toString());
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
return new bignumber_js_1.default(0);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
exports.getApproved = getApproved;
|
|
34
|
+
const setApproval = (signer, tokenAddress, contractAddress, amount) => {
|
|
35
|
+
const erc20 = new ethers_1.Contract(tokenAddress, types_1.ERC20_ABI, signer);
|
|
36
|
+
return erc20.approve(contractAddress, amount);
|
|
37
|
+
};
|
|
38
|
+
exports.setApproval = setApproval;
|
|
39
|
+
const getAllowanceViaMulticall = (signer, chainId, tokenData) => __awaiter(void 0, void 0, void 0, function* () {
|
|
40
|
+
const chainsService = ChainsService_1.default.getInstance();
|
|
41
|
+
const chain = yield chainsService.getChainById(chainId);
|
|
42
|
+
if (!chain.multicallAddress) {
|
|
43
|
+
throw new errors_1.ServerError(`No multicall address configured for chainId ${chainId}.`);
|
|
44
|
+
}
|
|
45
|
+
const ownerAddress = yield signer.getAddress();
|
|
46
|
+
const calls = [];
|
|
47
|
+
tokenData.map(({ token, approvalAddress }) => {
|
|
48
|
+
calls.push({
|
|
49
|
+
address: token.address,
|
|
50
|
+
name: 'allowance',
|
|
51
|
+
params: [ownerAddress, approvalAddress],
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
const result = yield (0, multicall_1.fetchDataUsingMulticall)(calls, types_1.ERC20_ABI, chainId, chain.multicallAddress);
|
|
55
|
+
if (!result.length) {
|
|
56
|
+
throw new errors_1.ServerError(`Couldn't load allowance from chainId ${chainId} using multicall.`);
|
|
57
|
+
}
|
|
58
|
+
const parsedResult = result.map(({ data }) => {
|
|
59
|
+
var _a;
|
|
60
|
+
return ({
|
|
61
|
+
approvalAmount: (_a = data) !== null && _a !== void 0 ? _a : new bignumber_js_1.default(0),
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
return tokenData.map(({ token, approvalAddress }, i) => ({
|
|
65
|
+
token,
|
|
66
|
+
approvalAddress,
|
|
67
|
+
approvedAmount: parsedResult[i].approvalAmount,
|
|
68
|
+
}));
|
|
69
|
+
});
|
|
70
|
+
exports.getAllowanceViaMulticall = getAllowanceViaMulticall;
|
|
71
|
+
const groupByChain = (tokenDataList) => {
|
|
72
|
+
// group by chain
|
|
73
|
+
const tokenDataByChain = {};
|
|
74
|
+
tokenDataList.forEach((tokenData) => {
|
|
75
|
+
if (!tokenDataByChain[tokenData.token.chainId]) {
|
|
76
|
+
tokenDataByChain[tokenData.token.chainId] = [];
|
|
77
|
+
}
|
|
78
|
+
tokenDataByChain[tokenData.token.chainId].push(tokenData);
|
|
79
|
+
});
|
|
80
|
+
return tokenDataByChain;
|
|
81
|
+
};
|
|
82
|
+
exports.groupByChain = groupByChain;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Token, TokenAmount } from '@lifi/types';
|
|
2
|
+
declare const _default: {
|
|
3
|
+
getTokenBalance: (walletAddress: string, token: Token) => Promise<TokenAmount | null>;
|
|
4
|
+
getTokenBalances: (walletAddress: string, tokens: Token[]) => Promise<TokenAmount[]>;
|
|
5
|
+
getTokenBalancesForChains: (walletAddress: string, tokensByChain: {
|
|
6
|
+
[chainId: number]: Token[];
|
|
7
|
+
}) => Promise<{
|
|
8
|
+
[chainId: number]: TokenAmount[];
|
|
9
|
+
}>;
|
|
10
|
+
};
|
|
11
|
+
export default _default;
|
|
@@ -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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const utils_1 = __importDefault(require("./utils"));
|
|
16
|
+
const getTokenBalance = (walletAddress, token) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
|
+
const tokenAmounts = yield getTokenBalances(walletAddress, [token]);
|
|
18
|
+
return tokenAmounts.length ? tokenAmounts[0] : null;
|
|
19
|
+
});
|
|
20
|
+
const getTokenBalances = (walletAddress, tokens) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
|
+
// split by chain
|
|
22
|
+
const tokensByChain = {};
|
|
23
|
+
tokens.forEach((token) => {
|
|
24
|
+
if (!tokensByChain[token.chainId]) {
|
|
25
|
+
tokensByChain[token.chainId] = [];
|
|
26
|
+
}
|
|
27
|
+
tokensByChain[token.chainId].push(token);
|
|
28
|
+
});
|
|
29
|
+
const tokenAmountsByChain = yield getTokenBalancesForChains(walletAddress, tokensByChain);
|
|
30
|
+
return Object.values(tokenAmountsByChain).flat();
|
|
31
|
+
});
|
|
32
|
+
const getTokenBalancesForChains = (walletAddress, tokensByChain) => __awaiter(void 0, void 0, void 0, function* () {
|
|
33
|
+
const tokenAmountsByChain = {};
|
|
34
|
+
const promises = Object.keys(tokensByChain).map((chainIdStr) => __awaiter(void 0, void 0, void 0, function* () {
|
|
35
|
+
const chainId = parseInt(chainIdStr);
|
|
36
|
+
const tokenAmounts = yield utils_1.default.getBalances(walletAddress, tokensByChain[chainId]);
|
|
37
|
+
tokenAmountsByChain[chainId] = tokenAmounts;
|
|
38
|
+
}));
|
|
39
|
+
yield Promise.allSettled(promises);
|
|
40
|
+
return tokenAmountsByChain;
|
|
41
|
+
});
|
|
42
|
+
exports.default = {
|
|
43
|
+
getTokenBalance,
|
|
44
|
+
getTokenBalances,
|
|
45
|
+
getTokenBalancesForChains,
|
|
46
|
+
};
|
|
@@ -0,0 +1,150 @@
|
|
|
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
|
+
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
16
|
+
const ethers_1 = require("ethers");
|
|
17
|
+
const connectors_1 = require("../connectors");
|
|
18
|
+
const multicall_1 = require("../utils/multicall");
|
|
19
|
+
const utils_1 = require("../utils/utils");
|
|
20
|
+
const balanceAbi = [
|
|
21
|
+
{
|
|
22
|
+
constant: true,
|
|
23
|
+
inputs: [{ name: 'who', type: 'address' }],
|
|
24
|
+
name: 'balanceOf',
|
|
25
|
+
outputs: [{ name: '', type: 'uint256' }],
|
|
26
|
+
payable: false,
|
|
27
|
+
stateMutability: 'view',
|
|
28
|
+
type: 'function',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
constant: true,
|
|
32
|
+
inputs: [{ name: 'addr', type: 'address' }],
|
|
33
|
+
name: 'getEthBalance',
|
|
34
|
+
outputs: [{ name: 'balance', type: 'uint256' }],
|
|
35
|
+
payable: false,
|
|
36
|
+
stateMutability: 'view',
|
|
37
|
+
type: 'function',
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
const getBalances = (walletAddress, tokens) => __awaiter(void 0, void 0, void 0, function* () {
|
|
41
|
+
if (tokens.length === 0) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
const { chainId } = tokens[0];
|
|
45
|
+
tokens.forEach((token) => {
|
|
46
|
+
if (token.chainId !== chainId) {
|
|
47
|
+
// eslint-disable-next-line no-console
|
|
48
|
+
console.warn(`Requested tokens have to be on same chain.`);
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
if ((yield (0, connectors_1.getMulticallAddress)(chainId)) && tokens.length > 1) {
|
|
53
|
+
return getBalancesFromProviderUsingMulticall(walletAddress, tokens);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
return getBalancesFromProvider(walletAddress, tokens);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
const getBalancesFromProviderUsingMulticall = (walletAddress, tokens) => __awaiter(void 0, void 0, void 0, function* () {
|
|
60
|
+
// Configuration
|
|
61
|
+
const { chainId } = tokens[0];
|
|
62
|
+
const multicallAddress = yield (0, connectors_1.getMulticallAddress)(chainId);
|
|
63
|
+
if (!multicallAddress) {
|
|
64
|
+
throw new Error('No multicallAddress found for the given chain.');
|
|
65
|
+
}
|
|
66
|
+
return executeMulticall(walletAddress, tokens, multicallAddress, chainId);
|
|
67
|
+
});
|
|
68
|
+
const executeMulticall = (walletAddress, tokens, multicallAddress, chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
69
|
+
// Collect calls we want to make
|
|
70
|
+
const calls = [];
|
|
71
|
+
tokens.map((token) => {
|
|
72
|
+
if ((0, utils_1.isZeroAddress)(token.address)) {
|
|
73
|
+
calls.push({
|
|
74
|
+
address: multicallAddress,
|
|
75
|
+
name: 'getEthBalance',
|
|
76
|
+
params: [walletAddress],
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
calls.push({
|
|
81
|
+
address: token.address,
|
|
82
|
+
name: 'balanceOf',
|
|
83
|
+
params: [walletAddress],
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
const res = yield fetchViaMulticall(calls, balanceAbi, chainId, multicallAddress);
|
|
88
|
+
if (!res.length) {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
return tokens.map((token, i) => {
|
|
92
|
+
const amount = new bignumber_js_1.default(res[i].amount.toString() || '0')
|
|
93
|
+
.shiftedBy(-token.decimals)
|
|
94
|
+
.toFixed();
|
|
95
|
+
return Object.assign(Object.assign({}, token), { amount: amount || '0', blockNumber: res[i].blockNumber });
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
const fetchViaMulticall = (calls, abi, chainId, multicallAddress) => __awaiter(void 0, void 0, void 0, function* () {
|
|
99
|
+
const result = yield (0, multicall_1.fetchDataUsingMulticall)(calls, abi, chainId, multicallAddress);
|
|
100
|
+
return result.map(({ data, blockNumber }) => ({
|
|
101
|
+
amount: data ? data : new bignumber_js_1.default(0),
|
|
102
|
+
blockNumber,
|
|
103
|
+
}));
|
|
104
|
+
});
|
|
105
|
+
const getBalancesFromProvider = (walletAddress, tokens) => __awaiter(void 0, void 0, void 0, function* () {
|
|
106
|
+
const chainId = tokens[0].chainId;
|
|
107
|
+
const rpc = yield (0, connectors_1.getRpcProvider)(chainId);
|
|
108
|
+
const tokenAmountPromises = tokens.map((token) => __awaiter(void 0, void 0, void 0, function* () {
|
|
109
|
+
let amount = '0';
|
|
110
|
+
let blockNumber;
|
|
111
|
+
try {
|
|
112
|
+
const balance = yield getBalanceFromProvider(walletAddress, token.address, chainId, rpc);
|
|
113
|
+
amount = new bignumber_js_1.default(balance.amount.toString())
|
|
114
|
+
.shiftedBy(-token.decimals)
|
|
115
|
+
.toString();
|
|
116
|
+
blockNumber = balance.blockNumber;
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
// eslint-disable-next-line no-console
|
|
120
|
+
console.warn(e);
|
|
121
|
+
}
|
|
122
|
+
return Object.assign(Object.assign({}, token), { amount,
|
|
123
|
+
blockNumber });
|
|
124
|
+
}));
|
|
125
|
+
return Promise.all(tokenAmountPromises);
|
|
126
|
+
});
|
|
127
|
+
const getBalanceFromProvider = (walletAddress, assetId, chainId, provider) => __awaiter(void 0, void 0, void 0, function* () {
|
|
128
|
+
const blockNumber = yield getCurrentBlockNumber(chainId);
|
|
129
|
+
let balance;
|
|
130
|
+
if ((0, utils_1.isZeroAddress)(assetId)) {
|
|
131
|
+
balance = yield provider.getBalance(walletAddress, blockNumber);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
const contract = new ethers_1.ethers.Contract(assetId, ['function balanceOf(address owner) view returns (uint256)'], provider);
|
|
135
|
+
balance = yield contract.balanceOf(walletAddress, {
|
|
136
|
+
blockTag: blockNumber,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
amount: balance,
|
|
141
|
+
blockNumber,
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
const getCurrentBlockNumber = (chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
145
|
+
const rpc = yield (0, connectors_1.getRpcProvider)(chainId);
|
|
146
|
+
return rpc.getBlockNumber();
|
|
147
|
+
});
|
|
148
|
+
exports.default = {
|
|
149
|
+
getBalances,
|
|
150
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ChainId } from './types';
|
|
2
|
+
import { FallbackProvider } from '@ethersproject/providers';
|
|
3
|
+
export declare const getRpcUrl: (chainId: ChainId, archive?: boolean) => Promise<string>;
|
|
4
|
+
export declare const getRpcUrls: (chainId: ChainId, archive?: boolean) => Promise<string[]>;
|
|
5
|
+
export declare const getRpcProvider: (chainId: number, archive?: boolean) => Promise<FallbackProvider>;
|
|
6
|
+
export declare const getMulticallAddress: (chainId: ChainId) => Promise<string | undefined>;
|
|
@@ -0,0 +1,77 @@
|
|
|
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.getMulticallAddress = exports.getRpcProvider = exports.getRpcUrls = exports.getRpcUrl = void 0;
|
|
16
|
+
const ethers_1 = require("ethers");
|
|
17
|
+
const _1 = require(".");
|
|
18
|
+
const types_1 = require("./types");
|
|
19
|
+
const ConfigService_1 = __importDefault(require("./services/ConfigService"));
|
|
20
|
+
// cached providers
|
|
21
|
+
const chainProviders = {};
|
|
22
|
+
// Archive RPC Provider
|
|
23
|
+
const archiveRpcs = {
|
|
24
|
+
[types_1.ChainId.ETH]: 'https://speedy-nodes-nyc.moralis.io/5ed6053dc39eba789ff466c9/eth/mainnet/archive',
|
|
25
|
+
[types_1.ChainId.BSC]: 'https://speedy-nodes-nyc.moralis.io/5ed6053dc39eba789ff466c9/bsc/mainnet/archive',
|
|
26
|
+
[types_1.ChainId.POL]: 'https://speedy-nodes-nyc.moralis.io/5ed6053dc39eba789ff466c9/polygon/mainnet/archive',
|
|
27
|
+
[types_1.ChainId.FTM]: 'https://speedy-nodes-nyc.moralis.io/5ed6053dc39eba789ff466c9/fantom/mainnet',
|
|
28
|
+
};
|
|
29
|
+
// RPC Urls
|
|
30
|
+
const getRpcUrl = (chainId, archive = false) => __awaiter(void 0, void 0, void 0, function* () {
|
|
31
|
+
const rpcUrls = yield (0, exports.getRpcUrls)(chainId, archive);
|
|
32
|
+
return rpcUrls[0];
|
|
33
|
+
});
|
|
34
|
+
exports.getRpcUrl = getRpcUrl;
|
|
35
|
+
const getRpcUrls = (chainId, archive = false) => __awaiter(void 0, void 0, void 0, function* () {
|
|
36
|
+
if (archive && archiveRpcs[chainId]) {
|
|
37
|
+
return [archiveRpcs[chainId]];
|
|
38
|
+
}
|
|
39
|
+
const configService = ConfigService_1.default.getInstance();
|
|
40
|
+
const config = yield configService.getConfigAsync();
|
|
41
|
+
return config.rpcs[chainId];
|
|
42
|
+
});
|
|
43
|
+
exports.getRpcUrls = getRpcUrls;
|
|
44
|
+
const getRandomProvider = (providerList) => {
|
|
45
|
+
const index = (0, _1.getRandomNumber)(0, providerList.length - 1);
|
|
46
|
+
return providerList[index];
|
|
47
|
+
};
|
|
48
|
+
// Provider
|
|
49
|
+
const getRpcProvider = (chainId, archive = false) => __awaiter(void 0, void 0, void 0, function* () {
|
|
50
|
+
if (archive && archiveRpcs[chainId]) {
|
|
51
|
+
// return archive PRC, but don't cache it
|
|
52
|
+
return new ethers_1.providers.FallbackProvider([
|
|
53
|
+
new ethers_1.providers.StaticJsonRpcProvider(yield (0, exports.getRpcUrl)(chainId, archive), chainId),
|
|
54
|
+
]);
|
|
55
|
+
}
|
|
56
|
+
if (!chainProviders[chainId]) {
|
|
57
|
+
chainProviders[chainId] = [];
|
|
58
|
+
const urls = yield (0, exports.getRpcUrls)(chainId, archive);
|
|
59
|
+
urls.forEach((url) => {
|
|
60
|
+
chainProviders[chainId].push(new ethers_1.providers.FallbackProvider([
|
|
61
|
+
new ethers_1.providers.StaticJsonRpcProvider(url, chainId),
|
|
62
|
+
]));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
if (!chainProviders[chainId].length) {
|
|
66
|
+
throw new _1.ServerError(`Unable to configure provider for chain ${chainId}`);
|
|
67
|
+
}
|
|
68
|
+
return getRandomProvider(chainProviders[chainId]);
|
|
69
|
+
});
|
|
70
|
+
exports.getRpcProvider = getRpcProvider;
|
|
71
|
+
// Multicall
|
|
72
|
+
const getMulticallAddress = (chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
73
|
+
const configService = ConfigService_1.default.getInstance();
|
|
74
|
+
const config = yield configService.getConfigAsync();
|
|
75
|
+
return config.multicallAddresses[chainId];
|
|
76
|
+
});
|
|
77
|
+
exports.getMulticallAddress = getMulticallAddress;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Execution, InternalExecutionSettings, Process, ProcessType, Route, Status, Step, Token } from '../types';
|
|
2
|
+
interface Receipt {
|
|
3
|
+
fromAmount?: string;
|
|
4
|
+
toAmount?: string;
|
|
5
|
+
toToken?: Token;
|
|
6
|
+
gasUsed?: string;
|
|
7
|
+
gasPrice?: string;
|
|
8
|
+
}
|
|
9
|
+
declare type InternalUpdateRouteCallback = (route: Route) => void;
|
|
10
|
+
declare type OptionalParameters = Partial<Pick<Process, 'doneAt' | 'failedAt' | 'txHash' | 'txLink' | 'error' | 'substatus' | 'substatusMessage'>>;
|
|
11
|
+
/**
|
|
12
|
+
* Manages status updates of a route and provides various functions for tracking processes
|
|
13
|
+
* @param {Route} route The route this StatusManger belongs to.
|
|
14
|
+
* @param {InternalExecutionSettings} settings The ExecutionSettings for this route.
|
|
15
|
+
* @param {InternalUpdateRouteCallback} internalUpdateRouteCallback Internal callback to propage route changes.
|
|
16
|
+
* @return {StatusManager} An instance of StatusManager.
|
|
17
|
+
*/
|
|
18
|
+
export declare class StatusManager {
|
|
19
|
+
private readonly route;
|
|
20
|
+
private readonly settings;
|
|
21
|
+
private readonly internalUpdateRouteCallback;
|
|
22
|
+
private shouldUpdate;
|
|
23
|
+
constructor(route: Route, settings: InternalExecutionSettings, internalUpdateRouteCallback: InternalUpdateRouteCallback);
|
|
24
|
+
/**
|
|
25
|
+
* Initializes the execution object of a Step.
|
|
26
|
+
* @param {Step} step The current step in execution
|
|
27
|
+
* @return {Execution} The initialized execution object for this step and a function to update this step
|
|
28
|
+
*/
|
|
29
|
+
initExecutionObject: (step: Step) => Execution;
|
|
30
|
+
/**
|
|
31
|
+
* Updates the execution object of a Step.
|
|
32
|
+
* @param {Step} step The current step in execution
|
|
33
|
+
* @param {Status} status The status for the execution
|
|
34
|
+
* @param {Receipt} receipt Optional. Information about received tokens
|
|
35
|
+
* @return {Step} The step with the updated execution object
|
|
36
|
+
*/
|
|
37
|
+
updateExecution(step: Step, status: Status, receipt?: Receipt): Step;
|
|
38
|
+
/**
|
|
39
|
+
* Create and push a new process into the execution.
|
|
40
|
+
* @param {ProcessType} type Type of the process. Used to identify already existing processes.
|
|
41
|
+
* @param {Step} step The step that should contain the new process.
|
|
42
|
+
* @param {Status} status By default created procces is set to the STARTED status. We can override new process with the needed status.
|
|
43
|
+
* @return {Process}
|
|
44
|
+
*/
|
|
45
|
+
findOrCreateProcess: (type: ProcessType, step: Step, status?: Status) => Process;
|
|
46
|
+
/**
|
|
47
|
+
* Update a process object.
|
|
48
|
+
* @param {Step} step The step where the process should be updated
|
|
49
|
+
* @param {ProcessType} type The process type to update
|
|
50
|
+
* @param {Status} status The status the process gets.
|
|
51
|
+
* @param {object} [params] Additional parameters to append to the process.
|
|
52
|
+
* @return {Process} The update process
|
|
53
|
+
*/
|
|
54
|
+
updateProcess: (step: Step, type: ProcessType, status: Status, params?: OptionalParameters) => Process;
|
|
55
|
+
/**
|
|
56
|
+
* Remove a process from the execution
|
|
57
|
+
* @param {Step} step The step where the process should be removed from
|
|
58
|
+
* @param {ProcessType} type The process type to remove
|
|
59
|
+
* @return {void}
|
|
60
|
+
*/
|
|
61
|
+
removeProcess: (step: Step, type: ProcessType) => void;
|
|
62
|
+
updateStepInRoute: (step: Step) => Step;
|
|
63
|
+
setShouldUpdate(value: boolean): void;
|
|
64
|
+
}
|
|
65
|
+
export {};
|