@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.
Files changed (96) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/Lifi.js +179 -285
  3. package/dist/allowance/index.js +56 -148
  4. package/dist/allowance/utils.js +51 -116
  5. package/dist/balances/index.js +29 -92
  6. package/dist/balances/utils.js +108 -218
  7. package/dist/cjs/Lifi.d.ts +200 -0
  8. package/dist/cjs/Lifi.js +376 -0
  9. package/dist/cjs/allowance/index.d.ts +22 -0
  10. package/dist/cjs/allowance/index.js +78 -0
  11. package/dist/cjs/allowance/utils.d.ts +14 -0
  12. package/dist/cjs/allowance/utils.js +82 -0
  13. package/dist/cjs/balances/index.d.ts +11 -0
  14. package/dist/cjs/balances/index.js +46 -0
  15. package/dist/cjs/balances/utils.d.ts +5 -0
  16. package/dist/cjs/balances/utils.js +150 -0
  17. package/dist/cjs/connectors.d.ts +6 -0
  18. package/dist/cjs/connectors.js +77 -0
  19. package/dist/cjs/execution/StatusManager.d.ts +65 -0
  20. package/dist/cjs/execution/StatusManager.js +167 -0
  21. package/dist/cjs/execution/StepExecutor.d.ts +15 -0
  22. package/dist/cjs/execution/StepExecutor.js +74 -0
  23. package/dist/cjs/execution/allowance.execute.d.ts +4 -0
  24. package/dist/cjs/execution/allowance.execute.js +97 -0
  25. package/dist/cjs/execution/balanceCheck.execute.d.ts +3 -0
  26. package/dist/cjs/execution/balanceCheck.execute.js +48 -0
  27. package/dist/cjs/execution/bridges/bridge.execute.d.ts +7 -0
  28. package/dist/cjs/execution/bridges/bridge.execute.js +154 -0
  29. package/dist/cjs/execution/exchanges/swap.execute.d.ts +7 -0
  30. package/dist/cjs/execution/exchanges/swap.execute.js +164 -0
  31. package/dist/cjs/execution/index.d.ts +1 -0
  32. package/dist/cjs/execution/index.js +17 -0
  33. package/dist/cjs/execution/stepComparison.d.ts +14 -0
  34. package/dist/cjs/execution/stepComparison.js +46 -0
  35. package/dist/cjs/execution/switchChain.d.ts +16 -0
  36. package/dist/cjs/execution/switchChain.js +58 -0
  37. package/dist/cjs/execution/utils.d.ts +6 -0
  38. package/dist/cjs/execution/utils.js +137 -0
  39. package/dist/cjs/helpers.d.ts +18 -0
  40. package/dist/cjs/helpers.js +54 -0
  41. package/dist/cjs/index.d.ts +6 -0
  42. package/dist/cjs/index.js +27 -0
  43. package/dist/cjs/services/ApiService.d.ts +15 -0
  44. package/dist/cjs/services/ApiService.js +272 -0
  45. package/dist/cjs/services/ChainsService.d.ts +11 -0
  46. package/dist/cjs/services/ChainsService.js +54 -0
  47. package/dist/cjs/services/ConfigService.d.ts +23 -0
  48. package/dist/cjs/services/ConfigService.js +98 -0
  49. package/dist/cjs/typeguards.d.ts +4 -0
  50. package/dist/cjs/typeguards.js +53 -0
  51. package/dist/cjs/types/ERC20.d.ts +22 -0
  52. package/dist/cjs/types/ERC20.js +53 -0
  53. package/dist/cjs/types/index.d.ts +4 -0
  54. package/dist/cjs/types/index.js +22 -0
  55. package/dist/cjs/types/internal.types.d.ts +85 -0
  56. package/dist/cjs/types/internal.types.js +2 -0
  57. package/dist/cjs/utils/errors.d.ts +75 -0
  58. package/dist/cjs/utils/errors.js +115 -0
  59. package/dist/cjs/utils/getProvider.d.ts +3 -0
  60. package/dist/cjs/utils/getProvider.js +11 -0
  61. package/dist/cjs/utils/multicall.d.ts +10 -0
  62. package/dist/cjs/utils/multicall.js +77 -0
  63. package/dist/cjs/utils/multicallAbi.json +313 -0
  64. package/dist/cjs/utils/parseError.d.ts +38 -0
  65. package/dist/cjs/utils/parseError.js +141 -0
  66. package/dist/cjs/utils/preRestart.d.ts +2 -0
  67. package/dist/cjs/utils/preRestart.js +31 -0
  68. package/dist/cjs/utils/utils.d.ts +26 -0
  69. package/dist/cjs/utils/utils.js +120 -0
  70. package/dist/connectors.js +50 -133
  71. package/dist/execution/StatusManager.js +34 -41
  72. package/dist/execution/StepExecutor.js +54 -123
  73. package/dist/execution/allowance.execute.js +76 -142
  74. package/dist/execution/balanceCheck.execute.js +29 -74
  75. package/dist/execution/bridges/bridge.execute.js +132 -221
  76. package/dist/execution/exchanges/swap.execute.js +142 -225
  77. package/dist/execution/index.js +1 -17
  78. package/dist/execution/stepComparison.js +22 -61
  79. package/dist/execution/switchChain.js +33 -81
  80. package/dist/execution/utils.js +60 -119
  81. package/dist/helpers.js +15 -53
  82. package/dist/index.js +6 -25
  83. package/dist/services/ApiService.js +248 -385
  84. package/dist/services/ChainsService.js +29 -89
  85. package/dist/services/ConfigService.js +47 -86
  86. package/dist/typeguards.js +13 -21
  87. package/dist/types/ERC20.js +1 -4
  88. package/dist/types/index.js +4 -22
  89. package/dist/types/internal.types.js +1 -2
  90. package/dist/utils/errors.js +47 -93
  91. package/dist/utils/getProvider.js +3 -7
  92. package/dist/utils/multicall.js +61 -117
  93. package/dist/utils/parseError.js +73 -141
  94. package/dist/utils/preRestart.js +14 -21
  95. package/dist/utils/utils.js +47 -130
  96. package/package.json +34 -11
@@ -0,0 +1,376 @@
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 allowance_1 = require("./allowance");
16
+ const balances_1 = __importDefault(require("./balances"));
17
+ const connectors_1 = require("./connectors");
18
+ const StatusManager_1 = require("./execution/StatusManager");
19
+ const StepExecutor_1 = require("./execution/StepExecutor");
20
+ const ApiService_1 = __importDefault(require("./services/ApiService"));
21
+ const ChainsService_1 = __importDefault(require("./services/ChainsService"));
22
+ const ConfigService_1 = __importDefault(require("./services/ConfigService"));
23
+ const typeguards_1 = require("./typeguards");
24
+ const errors_1 = require("./utils/errors");
25
+ const preRestart_1 = require("./utils/preRestart");
26
+ const utils_1 = require("./utils/utils");
27
+ class LIFI {
28
+ constructor(configUpdate) {
29
+ this.activeRouteDictionary = {};
30
+ /**
31
+ * Get the current configuration of the SDK
32
+ * @return {Config} - The config object
33
+ */
34
+ this.getConfig = () => {
35
+ return this.configService.getConfig();
36
+ };
37
+ /**
38
+ * Get the SDK configuration after all setup calls are finished
39
+ * @return {Promise<Config>} - The config object
40
+ */
41
+ this.getConfigAsync = () => {
42
+ return this.configService.getConfigAsync();
43
+ };
44
+ /**
45
+ * Get an instance of a provider for a specific cahin
46
+ * @param {number} chainId - Id of the chain the provider is for
47
+ * @param {boolean} archive - Whether to use an archive provider that is based on a default rpc or not. defaults to false
48
+ * @return {FallbackProvider} The provider for the given chain
49
+ */
50
+ this.getRpcProvider = (chainId, archive = false) => {
51
+ return (0, connectors_1.getRpcProvider)(chainId, archive);
52
+ };
53
+ /**
54
+ * Set a new confuration for the SDK
55
+ * @param {ConfigUpdate} configUpdate - An object containing the configuration fields that should be updated.
56
+ * @return {Config} The renewed config object
57
+ */
58
+ this.setConfig = (configUpdate) => {
59
+ return this.configService.updateConfig(configUpdate);
60
+ };
61
+ /**
62
+ * Get a set of current possibilities based on a request that specifies which chains, exchanges and bridges are preferred or unwanted.
63
+ * @param {PossibilitiesRequest} request - Object defining preferences regarding chain, exchanges and bridges
64
+ * @return {Promise<PossibilitiesResponse>} Object listing current possibilities for any-to-any cross-chain-swaps based on the provided preferences.
65
+ * @throws {LifiError} Throws a LifiError if request fails.
66
+ */
67
+ this.getPossibilities = (request, options) => __awaiter(this, void 0, void 0, function* () {
68
+ return ApiService_1.default.getPossibilities(request, options);
69
+ });
70
+ /**
71
+ * Fetch information about a Token
72
+ * @param {ChainKey | ChainId} chain - Id or key of the chain that contains the token
73
+ * @param {string} token - Address or symbol of the token on the requested chain
74
+ * @throws {LifiError} - Throws a LifiError if request fails
75
+ */
76
+ this.getToken = (chain, token, options) => __awaiter(this, void 0, void 0, function* () {
77
+ return ApiService_1.default.getToken(chain, token, options);
78
+ });
79
+ /**
80
+ * Get a quote for a token transfer
81
+ * @param {QuoteRequest} request - The configuration of the requested quote
82
+ * @throws {LifiError} - Throws a LifiError if request fails
83
+ */
84
+ this.getQuote = (request, options) => __awaiter(this, void 0, void 0, function* () {
85
+ return ApiService_1.default.getQuote(request, options);
86
+ });
87
+ /**
88
+ * Get a quote for a destination contract call
89
+ * @param {ContractCallQuoteRequest} request - The configuration of the requested destination call
90
+ * @throws {LifiError} - Throws a LifiError if request fails
91
+ */
92
+ this.getContractCallQuote = (request, options) => __awaiter(this, void 0, void 0, function* () {
93
+ return ApiService_1.default.getContractCallQuote(request, options);
94
+ });
95
+ /**
96
+ * Check the status of a transfer. For cross chain transfers, the "bridge" parameter is required.
97
+ * @param {GetStatusRequest} request - Configuration of the requested status
98
+ * @throws {LifiError} - Throws a LifiError if request fails
99
+ */
100
+ this.getStatus = (request, options) => __awaiter(this, void 0, void 0, function* () {
101
+ return ApiService_1.default.getStatus(request, options);
102
+ });
103
+ /**
104
+ * Get the available tools to bridge and swap tokens.
105
+ * @param {ToolsRequest?} request - The configuration of the requested tools
106
+ * @returns The tools that are available on the requested chains
107
+ */
108
+ this.getTools = (request, options) => __awaiter(this, void 0, void 0, function* () {
109
+ return ApiService_1.default.getTools(request || {}, options);
110
+ });
111
+ /**
112
+ * Get all known tokens.
113
+ * @param {TokensRequest?} request - The configuration of the requested tokens
114
+ * @returns The tokens that are available on the requested chains
115
+ */
116
+ this.getTokens = (request, options) => __awaiter(this, void 0, void 0, function* () {
117
+ return ApiService_1.default.getTokens(request || {}, options);
118
+ });
119
+ /**
120
+ * Get all available chains
121
+ * @return {Promise<Chain[]>} A list of all available chains
122
+ * @throws {LifiError} Throws a LifiError if request fails.
123
+ */
124
+ this.getChains = () => __awaiter(this, void 0, void 0, function* () {
125
+ return this.chainsService.getChains();
126
+ });
127
+ /**
128
+ * Get a set of routes for a request that describes a transfer of tokens.
129
+ * @param {RoutesRequest} routesRequest - A description of the transfer.
130
+ * @return {Promise<RoutesResponse>} The resulting routes that can be used to realize the described transfer of tokens.
131
+ * @throws {LifiError} Throws a LifiError if request fails.
132
+ */
133
+ this.getRoutes = (request, options) => __awaiter(this, void 0, void 0, function* () {
134
+ return ApiService_1.default.getRoutes(request, options);
135
+ });
136
+ /**
137
+ * Get the transaction data for a single step of a route
138
+ * @param {Step} step - The step object.
139
+ * @return {Promise<Step>} The step populated with the transaction data.
140
+ * @throws {LifiError} Throws a LifiError if request fails.
141
+ */
142
+ this.getStepTransaction = (step, options) => __awaiter(this, void 0, void 0, function* () {
143
+ return ApiService_1.default.getStepTransaction(step, options);
144
+ });
145
+ /**
146
+ * Stops the execution of an active route.
147
+ * @param {Route} route - A route that is currently in execution.
148
+ * @return {Route} The stopped route.
149
+ */
150
+ this.stopExecution = (route) => {
151
+ if (!this.activeRouteDictionary[route.id]) {
152
+ return route;
153
+ }
154
+ for (const executor of this.activeRouteDictionary[route.id].executors) {
155
+ executor.stopStepExecution({ allowUpdates: false });
156
+ }
157
+ delete this.activeRouteDictionary[route.id];
158
+ return route;
159
+ };
160
+ /**
161
+ * Executes a route until a user interaction is necessary (signing transactions, etc.) and then halts until the route is resumed.
162
+ * @param {Route} route - A route that is currently in execution.
163
+ */
164
+ this.moveExecutionToBackground = (route) => {
165
+ if (!this.activeRouteDictionary[route.id]) {
166
+ return;
167
+ }
168
+ for (const executor of this.activeRouteDictionary[route.id].executors) {
169
+ executor.stopStepExecution({ allowUpdates: true });
170
+ }
171
+ };
172
+ /**
173
+ * Execute a route.
174
+ * @param {Signer} signer - The signer required to send the transactions.
175
+ * @param {Route} route - The route that should be executed. Cannot be an active route.
176
+ * @param {ExecutionSettings} settings - An object containing settings and callbacks.
177
+ * @return {Promise<Route>} The executed route.
178
+ * @throws {LifiError} Throws a LifiError if the execution fails.
179
+ */
180
+ this.executeRoute = (signer, route, settings) => __awaiter(this, void 0, void 0, function* () {
181
+ const clonedRoute = (0, utils_1.deepClone)(route); // deep clone to prevent side effects
182
+ // check if route is already running
183
+ if (this.activeRouteDictionary[clonedRoute.id]) {
184
+ // TODO: maybe inform user why nothing happens?
185
+ return clonedRoute;
186
+ }
187
+ return this.executeSteps(signer, clonedRoute, settings);
188
+ });
189
+ /**
190
+ * Resume the execution of a route that has been stopped or had an error while executing.
191
+ * @param {Signer} signer - The signer required to send the transactions.
192
+ * @param {Route} route - The route that is to be executed. Cannot be an active route.
193
+ * @param {ExecutionSettings} settings - An object containing settings and callbacks.
194
+ * @return {Promise<Route>} The executed route.
195
+ * @throws {LifiError} Throws a LifiError if the execution fails.
196
+ */
197
+ this.resumeRoute = (signer, route, settings) => __awaiter(this, void 0, void 0, function* () {
198
+ const clonedRoute = (0, utils_1.deepClone)(route); // deep clone to prevent side effects
199
+ const activeRoute = this.activeRouteDictionary[clonedRoute.id];
200
+ if (activeRoute) {
201
+ const executionHalted = activeRoute.executors.some((executor) => executor.executionStopped);
202
+ if (!executionHalted) {
203
+ return clonedRoute;
204
+ }
205
+ }
206
+ (0, preRestart_1.handlePreRestart)(clonedRoute);
207
+ return this.executeSteps(signer, clonedRoute, settings);
208
+ });
209
+ this.executeSteps = (signer, route, settings) => __awaiter(this, void 0, void 0, function* () {
210
+ const config = this.configService.getConfig();
211
+ const execData = {
212
+ route,
213
+ executors: [],
214
+ settings: Object.assign(Object.assign({}, config.defaultExecutionSettings), settings),
215
+ };
216
+ this.activeRouteDictionary[route.id] = execData;
217
+ const statusManager = new StatusManager_1.StatusManager(route, this.activeRouteDictionary[route.id].settings, (route) => (this.activeRouteDictionary[route.id].route = route));
218
+ // loop over steps and execute them
219
+ for (let index = 0; index < route.steps.length; index++) {
220
+ //check if execution has stopped in meantime
221
+ if (!this.activeRouteDictionary[route.id]) {
222
+ break;
223
+ }
224
+ const step = route.steps[index];
225
+ const previousStep = index !== 0 ? route.steps[index - 1] : undefined;
226
+ // check if step already done
227
+ if (step.execution && step.execution.status === 'DONE') {
228
+ continue;
229
+ }
230
+ // update amount using output of previous execution. In the future this should be handled by calling `updateRoute`
231
+ if (previousStep &&
232
+ previousStep.execution &&
233
+ previousStep.execution.toAmount) {
234
+ step.action.fromAmount = previousStep.execution.toAmount;
235
+ }
236
+ let stepExecutor;
237
+ try {
238
+ stepExecutor = new StepExecutor_1.StepExecutor(statusManager, this.activeRouteDictionary[route.id].settings);
239
+ this.activeRouteDictionary[route.id].executors.push(stepExecutor);
240
+ yield stepExecutor.executeStep(signer, step);
241
+ }
242
+ catch (e) {
243
+ this.stopExecution(route);
244
+ throw e;
245
+ }
246
+ // execution stopped during the current step, we don't want to continue to the next step so we return already
247
+ if (stepExecutor.executionStopped) {
248
+ return route;
249
+ }
250
+ }
251
+ //clean up after execution
252
+ delete this.activeRouteDictionary[route.id];
253
+ return route;
254
+ });
255
+ /**
256
+ * Update the ExecutionSettings for an active route.
257
+ * @param {ExecutionSettings} settings - An object with execution settings.
258
+ * @param {Route} route - The active route that gets the new execution settings.
259
+ * @throws {ValidationError} Throws a ValidationError if parameters are invalid.
260
+ */
261
+ this.updateExecutionSettings = (settings, route) => {
262
+ if (!this.activeRouteDictionary[route.id]) {
263
+ throw new errors_1.ValidationError("Can't set ExecutionSettings for the inactive route.");
264
+ }
265
+ const config = this.configService.getConfig();
266
+ this.activeRouteDictionary[route.id].settings = Object.assign(Object.assign({}, config.defaultExecutionSettings), settings);
267
+ };
268
+ /**
269
+ * Get the list of active routes.
270
+ * @return {Route[]} A list of routes.
271
+ */
272
+ this.getActiveRoutes = () => {
273
+ return Object.values(this.activeRouteDictionary).map((dict) => dict.route);
274
+ };
275
+ /**
276
+ * Return the current route information for given route. The route has to be active.
277
+ * @param {Route} route - A route object.
278
+ * @return {Route} The updated route.
279
+ */
280
+ this.getActiveRoute = (route) => {
281
+ var _a;
282
+ return (_a = this.activeRouteDictionary[route.id]) === null || _a === void 0 ? void 0 : _a.route;
283
+ };
284
+ /**
285
+ * Returns the balances of a specific token a wallet holds across all aggregated chains.
286
+ * @param {string} walletAddress - A wallet address.
287
+ * @param {Token} token - A Token object.
288
+ * @return {Promise<TokenAmount | null>} An object containing the token and the amounts on different chains.
289
+ * @throws {ValidationError} Throws a ValidationError if parameters are invalid.
290
+ */
291
+ this.getTokenBalance = (walletAddress, token) => __awaiter(this, void 0, void 0, function* () {
292
+ if (!walletAddress) {
293
+ throw new errors_1.ValidationError('Missing walletAddress.');
294
+ }
295
+ if (!(0, typeguards_1.isToken)(token)) {
296
+ throw new errors_1.ValidationError(`Invalid token passed: address "${token.address}" on chainId "${token.chainId}"`);
297
+ }
298
+ return balances_1.default.getTokenBalance(walletAddress, token);
299
+ });
300
+ /**
301
+ * Returns the balances for a list tokens a wallet holds across all aggregated chains.
302
+ * @param {string} walletAddress - A wallet address.
303
+ * @param {Token[]} tokens - A list of Token objects.
304
+ * @return {Promise<TokenAmount[]>} A list of objects containing the tokens and the amounts on different chains.
305
+ * @throws {ValidationError} Throws a ValidationError if parameters are invalid.
306
+ */
307
+ this.getTokenBalances = (walletAddress, tokens) => __awaiter(this, void 0, void 0, function* () {
308
+ if (!walletAddress) {
309
+ throw new errors_1.ValidationError('Missing walletAddress.');
310
+ }
311
+ const invalidTokens = tokens.filter((token) => !(0, typeguards_1.isToken)(token));
312
+ if (invalidTokens.length) {
313
+ throw new errors_1.ValidationError(`Invalid token passed: address "${invalidTokens[0].address}" on chainId "${invalidTokens[0].chainId}"`);
314
+ }
315
+ return balances_1.default.getTokenBalances(walletAddress, tokens);
316
+ });
317
+ /**
318
+ * This method queries the balances of tokens for a specific list of chains for a given wallet.
319
+ * @param {string} walletAddress - A walletaddress.
320
+ * @param {{ [chainId: number]: Token[] }} tokensByChain - A list of Token objects organized by chain ids.
321
+ * @return {Promise<{ [chainId: number]: TokenAmount[] }} A list of objects containing the tokens and the amounts on different chains organized by the chosen chains.
322
+ * @throws {ValidationError} Throws a ValidationError if parameters are invalid.
323
+ */
324
+ this.getTokenBalancesForChains = (walletAddress, tokensByChain) => __awaiter(this, void 0, void 0, function* () {
325
+ if (!walletAddress) {
326
+ throw new errors_1.ValidationError('Missing walletAddress.');
327
+ }
328
+ const tokenList = Object.values(tokensByChain).flat();
329
+ const invalidTokens = tokenList.filter((token) => !(0, typeguards_1.isToken)(token));
330
+ if (invalidTokens.length) {
331
+ throw new errors_1.ValidationError(`Invalid token passed: address "${invalidTokens[0].address}" on chainId "${invalidTokens[0].chainId}"`);
332
+ }
333
+ return balances_1.default.getTokenBalancesForChains(walletAddress, tokensByChain);
334
+ });
335
+ /**
336
+ * Get the current approval for a certain token.
337
+ * @param signer - The signer owning the token
338
+ * @param token - The token that should be checked
339
+ * @param approvalAddress - The address that has be approved
340
+ */
341
+ this.getTokenApproval = (signer, token, approvalAddress) => __awaiter(this, void 0, void 0, function* () {
342
+ return (0, allowance_1.getTokenApproval)(signer, token, approvalAddress);
343
+ });
344
+ /**
345
+ * Get the current approval for a list of token / approval address pairs.
346
+ * @param signer - The signer owning the tokens
347
+ * @param tokenData - A list of token and approval address pairs
348
+ */
349
+ this.bulkGetTokenApproval = (signer, tokenData) => __awaiter(this, void 0, void 0, function* () {
350
+ return (0, allowance_1.bulkGetTokenApproval)(signer, tokenData);
351
+ });
352
+ /**
353
+ * Set approval for a certain token and amount.
354
+ * @param { ApproveTokenRequest } request - The approval request
355
+ */
356
+ this.approveToken = (request) => {
357
+ return (0, allowance_1.approveToken)(request);
358
+ };
359
+ /**
360
+ * Revoke approval for a certain token.
361
+ * @param { RevokeApprovalRequest } request - The revoke request
362
+ */
363
+ this.revokeTokenApproval = (request) => {
364
+ return (0, allowance_1.revokeTokenApproval)(request);
365
+ };
366
+ this.configService = ConfigService_1.default.getInstance();
367
+ if (configUpdate) {
368
+ this.configService.updateConfig(configUpdate); // update API urls before we request chains
369
+ }
370
+ this.chainsService = ChainsService_1.default.getInstance();
371
+ this.chainsService.getChains().then((chains) => {
372
+ this.configService.updateChains(chains);
373
+ });
374
+ }
375
+ }
376
+ exports.default = LIFI;
@@ -0,0 +1,22 @@
1
+ import { Token } from '@lifi/types';
2
+ import { Signer } from 'ethers';
3
+ import { RevokeTokenData } from '../types';
4
+ export interface ApproveTokenRequest {
5
+ signer: Signer;
6
+ token: Token;
7
+ approvalAddress: string;
8
+ amount: string;
9
+ infiniteApproval?: boolean;
10
+ }
11
+ export interface RevokeApprovalRequest {
12
+ signer: Signer;
13
+ token: Token;
14
+ approvalAddress: string;
15
+ }
16
+ export declare const getTokenApproval: (signer: Signer, token: Token, approvalAddress: string) => Promise<string | undefined>;
17
+ export declare const bulkGetTokenApproval: (signer: Signer, tokenData: RevokeTokenData[]) => Promise<{
18
+ token: Token;
19
+ approval: string | undefined;
20
+ }[]>;
21
+ export declare const approveToken: ({ signer, token, approvalAddress, amount, infiniteApproval, }: ApproveTokenRequest) => Promise<void>;
22
+ export declare const revokeTokenApproval: ({ signer, token, approvalAddress, }: RevokeApprovalRequest) => Promise<void>;
@@ -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,5 @@
1
+ import { Token, TokenAmount } from '@lifi/types';
2
+ declare const _default: {
3
+ getBalances: (walletAddress: string, tokens: Token[]) => Promise<TokenAmount[]>;
4
+ };
5
+ export default _default;