@subwallet/extension-base 1.2.12-0 → 1.2.14-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.
Files changed (53) hide show
  1. package/background/errors/SwapError.js +5 -1
  2. package/cjs/background/errors/SwapError.js +5 -1
  3. package/cjs/core/logic-validation/swap.js +56 -3
  4. package/cjs/koni/api/nft/config.js +28 -18
  5. package/cjs/packageInfo.js +1 -1
  6. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +1 -1
  7. package/cjs/services/balance-service/transfer/xcm/utils.js +2 -2
  8. package/cjs/services/chain-service/constants.js +1 -1
  9. package/cjs/services/chain-service/handler/SubstrateApi.js +6 -0
  10. package/cjs/services/chain-service/handler/SubstrateChainHandler.js +1 -1
  11. package/cjs/services/chain-service/index.js +18 -5
  12. package/cjs/services/migration-service/scripts/databases/ReloadMetadata.js +35 -0
  13. package/cjs/services/migration-service/scripts/index.js +4 -2
  14. package/cjs/services/storage-service/db-stores/BaseStore.js +4 -0
  15. package/cjs/services/swap-service/handler/asset-hub/handler.js +343 -0
  16. package/cjs/services/swap-service/handler/asset-hub/index.js +12 -0
  17. package/cjs/services/swap-service/handler/asset-hub/router.js +93 -0
  18. package/cjs/services/swap-service/handler/asset-hub/utils.js +158 -0
  19. package/cjs/services/swap-service/index.js +10 -1
  20. package/cjs/services/swap-service/utils.js +10 -1
  21. package/cjs/types/swap/index.js +5 -1
  22. package/core/logic-validation/swap.d.ts +3 -1
  23. package/core/logic-validation/swap.js +55 -4
  24. package/koni/api/nft/config.js +28 -18
  25. package/package.json +36 -11
  26. package/packageInfo.js +1 -1
  27. package/services/balance-service/helpers/subscribe/substrate/index.js +1 -1
  28. package/services/balance-service/transfer/xcm/utils.js +2 -2
  29. package/services/chain-service/constants.js +1 -1
  30. package/services/chain-service/handler/SubstrateApi.js +6 -0
  31. package/services/chain-service/handler/SubstrateChainHandler.js +1 -1
  32. package/services/chain-service/index.js +18 -5
  33. package/services/migration-service/scripts/databases/ReloadMetadata.d.ts +5 -0
  34. package/services/migration-service/scripts/databases/ReloadMetadata.js +27 -0
  35. package/services/migration-service/scripts/index.js +4 -2
  36. package/services/storage-service/db-stores/BaseStore.d.ts +3 -0
  37. package/services/storage-service/db-stores/BaseStore.js +4 -0
  38. package/services/swap-service/handler/asset-hub/handler.d.ts +31 -0
  39. package/services/swap-service/handler/asset-hub/handler.js +335 -0
  40. package/services/swap-service/handler/asset-hub/index.d.ts +1 -0
  41. package/services/swap-service/handler/asset-hub/index.js +4 -0
  42. package/services/swap-service/handler/asset-hub/router.d.ts +16 -0
  43. package/services/swap-service/handler/asset-hub/router.js +85 -0
  44. package/services/swap-service/handler/asset-hub/utils.d.ts +18 -0
  45. package/services/swap-service/handler/asset-hub/utils.js +133 -0
  46. package/services/swap-service/index.js +10 -1
  47. package/services/swap-service/utils.d.ts +1 -0
  48. package/services/swap-service/utils.js +9 -1
  49. package/types/swap/index.d.ts +15 -2
  50. package/types/swap/index.js +5 -1
  51. /package/cjs/services/migration-service/scripts/{ClearMetadataDatabase.js → databases/ClearMetadataDatabase.js} +0 -0
  52. /package/services/migration-service/scripts/{ClearMetadataDatabase.d.ts → databases/ClearMetadataDatabase.d.ts} +0 -0
  53. /package/services/migration-service/scripts/{ClearMetadataDatabase.js → databases/ClearMetadataDatabase.js} +0 -0
@@ -0,0 +1,343 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.AssetHubSwapHandler = void 0;
8
+ var _SwapError = require("@subwallet/extension-base/background/errors/SwapError");
9
+ var _TransactionError = require("@subwallet/extension-base/background/errors/TransactionError");
10
+ var _KoniTypes = require("@subwallet/extension-base/background/KoniTypes");
11
+ var _swap = require("@subwallet/extension-base/core/logic-validation/swap");
12
+ var _xcm = require("@subwallet/extension-base/services/balance-service/transfer/xcm");
13
+ var _utils = require("@subwallet/extension-base/services/chain-service/utils");
14
+ var _utils2 = require("@subwallet/extension-base/services/swap-service/utils");
15
+ var _serviceBase = require("@subwallet/extension-base/types/service-base");
16
+ var _swap2 = require("@subwallet/extension-base/types/swap");
17
+ var _bignumber = _interopRequireDefault(require("bignumber.js"));
18
+ var _baseHandler = require("../base-handler");
19
+ var _router = require("./router");
20
+ // Copyright 2019-2022 @subwallet/extension-base
21
+ // SPDX-License-Identifier: Apache-2.0
22
+
23
+ const PAH_LOW_LIQUIDITY_THRESHOLD = 0.15;
24
+ class AssetHubSwapHandler {
25
+ isReady = false;
26
+ constructor(chainService, balanceService, chain) {
27
+ const chainInfo = chainService.getChainInfoByKey(chain);
28
+ const providerSlug = chain === 'statemint' ? _swap2.SwapProviderId.POLKADOT_ASSET_HUB : chain === 'statemine' ? _swap2.SwapProviderId.KUSAMA_ASSET_HUB : _swap2.SwapProviderId.ROCOCO_ASSET_HUB;
29
+ this.swapBaseHandler = new _baseHandler.SwapBaseHandler({
30
+ balanceService,
31
+ chainService,
32
+ providerName: chainInfo.name,
33
+ providerSlug
34
+ });
35
+ this.providerSlug = providerSlug;
36
+ this.chain = chain;
37
+ }
38
+ get chainService() {
39
+ return this.swapBaseHandler.chainService;
40
+ }
41
+ get balanceService() {
42
+ return this.swapBaseHandler.balanceService;
43
+ }
44
+ get providerInfo() {
45
+ return this.swapBaseHandler.providerInfo;
46
+ }
47
+ get name() {
48
+ return this.swapBaseHandler.name;
49
+ }
50
+ get slug() {
51
+ return this.swapBaseHandler.slug;
52
+ }
53
+ async init() {
54
+ const chainState = this.chainService.getChainStateByKey(this.chain);
55
+ if (!chainState.active) {
56
+ await this.chainService.enableChain(this.chain);
57
+ }
58
+ const substrateApi = this.chainService.getSubstrateApi(this.chain);
59
+ await substrateApi.api.isReady;
60
+ this.router = new _router.AssetHubRouter(this.chain, this.chainService);
61
+ this.isReady = true;
62
+ }
63
+ async getXcmStep(params) {
64
+ const bnAmount = new _bignumber.default(params.request.fromAmount);
65
+ const fromAsset = this.chainService.getAssetBySlug(params.request.pair.from);
66
+ const fromAssetBalance = await this.balanceService.getTransferableBalance(params.request.address, fromAsset.originChain, fromAsset.slug);
67
+ const bnFromAssetBalance = new _bignumber.default(fromAssetBalance.value);
68
+ if (bnFromAssetBalance.gte(bnAmount)) {
69
+ return undefined; // enough balance, no need to xcm
70
+ }
71
+
72
+ const alternativeAssetSlug = (0, _utils2.getSwapAlternativeAsset)(params.request.pair);
73
+ if (!alternativeAssetSlug) {
74
+ return undefined;
75
+ }
76
+ const alternativeAsset = this.chainService.getAssetBySlug(alternativeAssetSlug);
77
+ const alternativeAssetBalance = await this.balanceService.getTransferableBalance(params.request.address, alternativeAsset.originChain, alternativeAsset.slug);
78
+ const bnAlternativeAssetBalance = new _bignumber.default(alternativeAssetBalance.value);
79
+ if (bnAlternativeAssetBalance.lte(0)) {
80
+ return undefined;
81
+ }
82
+ try {
83
+ const alternativeChainInfo = this.chainService.getChainInfoByKey(alternativeAsset.originChain);
84
+ const step = {
85
+ metadata: {
86
+ sendingValue: bnAmount.toString(),
87
+ originTokenInfo: alternativeAsset,
88
+ destinationTokenInfo: fromAsset
89
+ },
90
+ name: `Transfer ${alternativeAsset.symbol} from ${alternativeChainInfo.name}`,
91
+ type: _serviceBase.CommonStepType.XCM
92
+ };
93
+ const xcmOriginSubstrateApi = await this.chainService.getSubstrateApi(alternativeAsset.originChain).isReady;
94
+ const xcmTransfer = await (0, _xcm.createXcmExtrinsic)({
95
+ originTokenInfo: alternativeAsset,
96
+ destinationTokenInfo: fromAsset,
97
+ sendingValue: bnAmount.toString(),
98
+ recipient: params.request.address,
99
+ chainInfoMap: this.chainService.getChainInfoMap(),
100
+ substrateApi: xcmOriginSubstrateApi
101
+ });
102
+ const _xcmFeeInfo = await xcmTransfer.paymentInfo(params.request.address);
103
+ const xcmFeeInfo = _xcmFeeInfo.toPrimitive();
104
+ const fee = {
105
+ feeComponent: [{
106
+ feeType: _swap2.SwapFeeType.NETWORK_FEE,
107
+ amount: Math.round(xcmFeeInfo.partialFee * 1.2).toString(),
108
+ tokenSlug: (0, _utils._getChainNativeTokenSlug)(alternativeChainInfo)
109
+ }],
110
+ defaultFeeToken: (0, _utils._getChainNativeTokenSlug)(alternativeChainInfo),
111
+ feeOptions: [(0, _utils._getChainNativeTokenSlug)(alternativeChainInfo)]
112
+ };
113
+ return [step, fee];
114
+ } catch (e) {
115
+ return undefined;
116
+ }
117
+ }
118
+ async getSubmitStep(params) {
119
+ if (params.selectedQuote) {
120
+ const submitStep = {
121
+ name: 'Swap',
122
+ type: _swap2.SwapStepType.SWAP
123
+ };
124
+ return Promise.resolve([submitStep, params.selectedQuote.feeInfo]);
125
+ }
126
+ return Promise.resolve(undefined);
127
+ }
128
+ generateOptimalProcess(params) {
129
+ return this.swapBaseHandler.generateOptimalProcess(params, [this.getXcmStep, this.getSubmitStep]);
130
+ }
131
+ async getSwapQuote(request) {
132
+ const fromAsset = this.chainService.getAssetBySlug(request.pair.from);
133
+ const toAsset = this.chainService.getAssetBySlug(request.pair.to);
134
+ const fromChain = this.chainService.getChainInfoByKey(fromAsset.originChain);
135
+ const fromChainNativeTokenSlug = (0, _utils._getChainNativeTokenSlug)(fromChain);
136
+ if (!this.isReady || !this.router) {
137
+ return new _SwapError.SwapError(_swap2.SwapErrorType.UNKNOWN);
138
+ }
139
+ const earlyValidation = await this.validateSwapRequest(request);
140
+ if (earlyValidation.error) {
141
+ const metadata = earlyValidation.metadata;
142
+ return (0, _swap._getEarlyAssetHubValidationError)(earlyValidation.error, metadata);
143
+ }
144
+ try {
145
+ const paths = this.router.buildPath(request.pair);
146
+ const amountOut = earlyValidation.metadata.toAmount;
147
+ const toAmount = new _bignumber.default(amountOut);
148
+ const minReceive = toAmount.times(1 - request.slippage).integerValue(_bignumber.default.ROUND_DOWN);
149
+ const extrinsic = await this.router.buildSwapExtrinsic(paths, request.address, request.fromAmount, minReceive.toString());
150
+ const paymentInfo = await extrinsic.paymentInfo(request.address);
151
+ const networkFee = {
152
+ tokenSlug: fromChainNativeTokenSlug,
153
+ amount: paymentInfo.partialFee.toString(),
154
+ feeType: _swap2.SwapFeeType.NETWORK_FEE
155
+ };
156
+ const feeTokenOptions = [fromChainNativeTokenSlug];
157
+ const selectedFeeToken = fromChainNativeTokenSlug;
158
+ const priceImpactPct = earlyValidation.metadata.priceImpactPct || '0';
159
+ return {
160
+ pair: request.pair,
161
+ fromAmount: request.fromAmount,
162
+ toAmount: toAmount.toString(),
163
+ rate: (0, _utils2.convertSwapRate)(earlyValidation.metadata.quoteRate, fromAsset, toAsset),
164
+ provider: this.providerInfo,
165
+ aliveUntil: +Date.now() + (_utils2.SWAP_QUOTE_TIMEOUT_MAP[this.slug] || _utils2.SWAP_QUOTE_TIMEOUT_MAP.default),
166
+ feeInfo: {
167
+ feeComponent: [networkFee],
168
+ defaultFeeToken: fromChainNativeTokenSlug,
169
+ feeOptions: feeTokenOptions,
170
+ // TODO: enable fee options
171
+ selectedFeeToken
172
+ },
173
+ isLowLiquidity: Math.abs(parseFloat(priceImpactPct)) >= PAH_LOW_LIQUIDITY_THRESHOLD,
174
+ route: {
175
+ path: paths.map(asset => asset.slug)
176
+ }
177
+ };
178
+ } catch (e) {
179
+ return new _SwapError.SwapError(_swap2.SwapErrorType.ERROR_FETCHING_QUOTE);
180
+ }
181
+ }
182
+ async handleXcmStep(params) {
183
+ const pair = params.quote.pair;
184
+ const alternativeAssetSlug = (0, _utils2.getSwapAlternativeAsset)(pair);
185
+ const originAsset = this.chainService.getAssetBySlug(alternativeAssetSlug);
186
+ const destinationAsset = this.chainService.getAssetBySlug(pair.from);
187
+ const substrateApi = this.chainService.getSubstrateApi(originAsset.originChain);
188
+ const chainApi = await substrateApi.isReady;
189
+ const destinationAssetBalance = await this.balanceService.getTransferableBalance(params.address, destinationAsset.originChain, destinationAsset.slug);
190
+ const xcmFee = params.process.totalFee[params.currentStep];
191
+ const bnAmount = new _bignumber.default(params.quote.fromAmount);
192
+ const bnDestinationAssetBalance = new _bignumber.default(destinationAssetBalance.value);
193
+ let bnTotalAmount = bnAmount.minus(bnDestinationAssetBalance);
194
+ if ((0, _utils._isNativeToken)(originAsset)) {
195
+ const bnXcmFee = new _bignumber.default(xcmFee.feeComponent[0].amount); // xcm fee is paid in native token but swap token is not always native token
196
+
197
+ bnTotalAmount = bnTotalAmount.plus(bnXcmFee);
198
+ }
199
+ const xcmTransfer = await (0, _xcm.createXcmExtrinsic)({
200
+ originTokenInfo: originAsset,
201
+ destinationTokenInfo: destinationAsset,
202
+ sendingValue: bnTotalAmount.toString(),
203
+ recipient: params.address,
204
+ chainInfoMap: this.chainService.getChainInfoMap(),
205
+ substrateApi: chainApi
206
+ });
207
+ const xcmData = {
208
+ originNetworkKey: originAsset.originChain,
209
+ destinationNetworkKey: destinationAsset.originChain,
210
+ from: params.address,
211
+ to: params.address,
212
+ value: bnTotalAmount.toString(),
213
+ tokenSlug: originAsset.slug,
214
+ showExtraWarning: true
215
+ };
216
+ return {
217
+ txChain: originAsset.originChain,
218
+ extrinsic: xcmTransfer,
219
+ transferNativeAmount: (0, _utils._isNativeToken)(originAsset) ? bnTotalAmount.toString() : '0',
220
+ extrinsicType: _KoniTypes.ExtrinsicType.TRANSFER_XCM,
221
+ chainType: _KoniTypes.ChainType.SUBSTRATE,
222
+ txData: xcmData
223
+ };
224
+ }
225
+ async handleSubmitStep(params) {
226
+ var _this$router;
227
+ const fromAsset = this.chainService.getAssetBySlug(params.quote.pair.from);
228
+ const txData = {
229
+ provider: this.providerInfo,
230
+ quote: params.quote,
231
+ address: params.address,
232
+ slippage: params.slippage,
233
+ process: params.process
234
+ };
235
+ const paths = params.quote.route.path.map(slug => this.chainService.getAssetBySlug(slug));
236
+ const {
237
+ fromAmount,
238
+ toAmount
239
+ } = params.quote;
240
+ const minReceive = new _bignumber.default(1 - params.slippage).times(toAmount).integerValue(_bignumber.default.ROUND_DOWN);
241
+ const extrinsic = await ((_this$router = this.router) === null || _this$router === void 0 ? void 0 : _this$router.buildSwapExtrinsic(paths, params.address, fromAmount, minReceive.toString()));
242
+ return {
243
+ txChain: fromAsset.originChain,
244
+ txData,
245
+ extrinsic,
246
+ transferNativeAmount: (0, _utils._isNativeToken)(fromAsset) ? params.quote.fromAmount : '0',
247
+ // todo
248
+ extrinsicType: _KoniTypes.ExtrinsicType.SWAP,
249
+ chainType: _KoniTypes.ChainType.SUBSTRATE
250
+ };
251
+ }
252
+ handleSwapProcess(params) {
253
+ const {
254
+ currentStep,
255
+ process
256
+ } = params;
257
+ const type = process.steps[currentStep].type;
258
+ switch (type) {
259
+ case _serviceBase.CommonStepType.XCM:
260
+ return this.handleXcmStep(params);
261
+ case _swap2.SwapStepType.SWAP:
262
+ return this.handleSubmitStep(params);
263
+ default:
264
+ return Promise.reject(new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.UNSUPPORTED));
265
+ }
266
+ }
267
+ async validateSwapStep(params, isXcmOk, stepIndex) {
268
+ // check swap quote timestamp
269
+ // check balance to pay transaction fee
270
+ // check balance against spending amount
271
+ if (!params.selectedQuote) {
272
+ return Promise.resolve([new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.INTERNAL_ERROR)]);
273
+ }
274
+ const selectedQuote = params.selectedQuote;
275
+ const currentTimestamp = +Date.now();
276
+ if (selectedQuote.aliveUntil <= currentTimestamp) {
277
+ return Promise.resolve([new _TransactionError.TransactionError(_swap2.SwapErrorType.QUOTE_TIMEOUT)]);
278
+ }
279
+ const stepFee = params.process.totalFee[stepIndex].feeComponent;
280
+ const networkFee = stepFee.find(fee => fee.feeType === _swap2.SwapFeeType.NETWORK_FEE);
281
+ if (!networkFee) {
282
+ return Promise.resolve([new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.INTERNAL_ERROR)]);
283
+ }
284
+ const fromAsset = this.chainService.getAssetBySlug(params.selectedQuote.pair.from);
285
+ const feeTokenInfo = this.chainService.getAssetBySlug(networkFee.tokenSlug);
286
+ const feeTokenChain = this.chainService.getChainInfoByKey(feeTokenInfo.originChain);
287
+ const {
288
+ fromAmount,
289
+ minSwap
290
+ } = params.selectedQuote;
291
+ const [feeTokenBalance, fromAssetBalance] = await Promise.all([this.balanceService.getTransferableBalance(params.address, feeTokenInfo.originChain, feeTokenInfo.slug), this.balanceService.getTransferableBalance(params.address, fromAsset.originChain, fromAsset.slug)]);
292
+ const balanceError = (0, _swap._validateBalanceToSwapOnAssetHub)(fromAsset, feeTokenInfo, feeTokenChain, networkFee.amount, fromAssetBalance.value, feeTokenBalance.value, fromAmount, isXcmOk, minSwap);
293
+ if (balanceError) {
294
+ return Promise.resolve([balanceError]);
295
+ }
296
+ if (!params.recipient) {
297
+ return Promise.resolve([]);
298
+ }
299
+ const toAsset = this.chainService.getAssetBySlug(params.selectedQuote.pair.to);
300
+ const toAssetChain = this.chainService.getChainInfoByKey(toAsset.originChain);
301
+ const recipientError = (0, _swap._validateSwapRecipient)(toAssetChain, params.recipient);
302
+ if (recipientError) {
303
+ return Promise.resolve([recipientError]);
304
+ }
305
+ return Promise.resolve([]);
306
+ }
307
+ async validateSwapProcess(params) {
308
+ const amount = params.selectedQuote.fromAmount;
309
+ const bnAmount = new _bignumber.default(amount);
310
+ if (bnAmount.lte(0)) {
311
+ return [new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.INVALID_PARAMS, 'Amount must be greater than 0')];
312
+ }
313
+ let isXcmOk = false;
314
+ for (const [index, step] of params.process.steps.entries()) {
315
+ const getErrors = async () => {
316
+ switch (step.type) {
317
+ case _serviceBase.CommonStepType.DEFAULT:
318
+ return Promise.resolve([]);
319
+ case _serviceBase.CommonStepType.XCM:
320
+ return this.swapBaseHandler.validateXcmStep(params, index);
321
+ case _swap2.SwapStepType.SWAP:
322
+ return this.validateSwapStep(params, isXcmOk, index);
323
+ default:
324
+ return Promise.reject(new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.UNSUPPORTED));
325
+ }
326
+ };
327
+ const errors = await getErrors();
328
+ if (errors.length) {
329
+ return errors;
330
+ } else if (step.type === _serviceBase.CommonStepType.XCM) {
331
+ isXcmOk = true;
332
+ }
333
+ }
334
+ return [];
335
+ }
336
+ validateSwapRequest(request) {
337
+ if (!this.isReady || !this.router) {
338
+ throw new _SwapError.SwapError(_swap2.SwapErrorType.ERROR_FETCHING_QUOTE);
339
+ }
340
+ return this.router.earlyValidateSwapValidation(request);
341
+ }
342
+ }
343
+ exports.AssetHubSwapHandler = AssetHubSwapHandler;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "AssetHubSwapHandler", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _handler.AssetHubSwapHandler;
10
+ }
11
+ });
12
+ var _handler = require("./handler");
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.AssetHubRouter = void 0;
8
+ var _utils = require("@subwallet/extension-base/services/chain-service/utils");
9
+ var _utils2 = require("@subwallet/extension-base/services/swap-service/handler/asset-hub/utils");
10
+ var _swap = require("@subwallet/extension-base/types/swap");
11
+ var _bignumber = _interopRequireDefault(require("bignumber.js"));
12
+ // Copyright 2019-2022 @subwallet/extension-base
13
+ // SPDX-License-Identifier: Apache-2.0
14
+
15
+ class AssetHubRouter {
16
+ constructor(chain, chainService) {
17
+ this.chain = chain;
18
+ this.chainService = chainService;
19
+ }
20
+ get substrateApi() {
21
+ return this.chainService.getSubstrateApi(this.chain);
22
+ }
23
+ get nativeToken() {
24
+ return this.chainService.getNativeTokenInfo(this.chain);
25
+ }
26
+ buildPath(pair) {
27
+ // const nativeToken = this.nativeToken;
28
+ // const nativeTokenSlug = nativeToken.slug;
29
+
30
+ const assetFrom = this.chainService.getAssetBySlug(pair.from);
31
+ const assetTo = this.chainService.getAssetBySlug(pair.to);
32
+ return [assetFrom, assetTo];
33
+ // if (pair.from === nativeTokenSlug || pair.to === nativeTokenSlug) {
34
+ // return [assetFrom, assetTo];
35
+ // } else {
36
+ // return [assetFrom, nativeToken, assetTo];
37
+ // }
38
+ }
39
+
40
+ async earlyValidateSwapValidation(request) {
41
+ const substrateApi = await this.substrateApi.isReady;
42
+ const paths = this.buildPath(request.pair);
43
+ const api = await substrateApi.api.isReady;
44
+ const amount = request.fromAmount;
45
+ const reserves = await (0, _utils2.getReserveForPath)(api, paths);
46
+ const amounts = (0, _utils2.estimateTokensForPath)(amount, reserves);
47
+ const marketRate = (0, _utils2.estimateRateForPath)(reserves);
48
+ const marketRateAfter = (0, _utils2.estimateRateAfter)(amount, reserves);
49
+ const priceImpactPct = (0, _utils2.estimatePriceImpactPct)(marketRate, marketRateAfter);
50
+ const errors = [];
51
+
52
+ // Check liquidity
53
+ const liquidityError = (0, _utils2.checkLiquidityForPath)(amounts, reserves);
54
+ if (liquidityError) {
55
+ errors.push(liquidityError);
56
+ }
57
+
58
+ // Check amount token in pool after swap
59
+ const minAmounts = paths.map(asset => (0, _utils._getTokenMinAmount)(asset));
60
+ const minAmountAfterSwapError = (0, _utils2.checkMinAmountForPath)(reserves, amounts, minAmounts);
61
+ if (minAmountAfterSwapError) {
62
+ errors.push(minAmountAfterSwapError);
63
+ }
64
+ const bnAmount = new _bignumber.default(request.fromAmount);
65
+ if (bnAmount.lte(0)) {
66
+ errors.push(_swap.SwapErrorType.AMOUNT_CANNOT_BE_ZERO);
67
+ }
68
+ const metadata = {
69
+ chain: this.chainService.getChainInfoByKey(this.chain),
70
+ toAmount: amounts[amounts.length - 1],
71
+ quoteRate: marketRate,
72
+ priceImpactPct: priceImpactPct
73
+ };
74
+ return {
75
+ error: errors[0],
76
+ metadata
77
+ };
78
+ }
79
+ async estimateAmountOut(pair, amountIn) {
80
+ const substrateApi = await this.substrateApi.isReady;
81
+ const paths = this.buildPath(pair);
82
+ const api = await substrateApi.api.isReady;
83
+ const reserves = await (0, _utils2.getReserveForPath)(api, paths);
84
+ const amounts = (0, _utils2.estimateTokensForPath)(amountIn, reserves);
85
+ return amounts[amounts.length - 1];
86
+ }
87
+ async buildSwapExtrinsic(path, recipient, amountIn, amountOutMin) {
88
+ const substrateApi = await this.substrateApi.isReady;
89
+ const api = await substrateApi.api.isReady;
90
+ return (0, _utils2.buildSwapExtrinsic)(api, path, recipient, amountIn, amountOutMin);
91
+ }
92
+ }
93
+ exports.AssetHubRouter = AssetHubRouter;
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.getReserveForPool = exports.getReserveForPath = exports.estimateTokensForPool = exports.estimateTokensForPath = exports.estimateRateForPath = exports.estimateRateAfter = exports.estimatePriceImpactPct = exports.estimateActualRate = exports.checkMinAmountForPool = exports.checkMinAmountForPath = exports.checkLiquidityForPool = exports.checkLiquidityForPath = exports.buildSwapExtrinsic = exports._getPoolInfo = void 0;
8
+ var _utils = require("@subwallet/extension-base/services/chain-service/utils");
9
+ var _swap = require("@subwallet/extension-base/types/swap");
10
+ var _bignumber = _interopRequireDefault(require("bignumber.js"));
11
+ // Copyright 2019-2022 @subwallet/extension-base
12
+ // SPDX-License-Identifier: Apache-2.0
13
+
14
+ const _getPoolInfo = async (api, asset1, asset2) => {
15
+ const assetLocation1 = (0, _utils._getXcmAssetMultilocation)(asset1);
16
+ const assetLocation2 = (0, _utils._getXcmAssetMultilocation)(asset2);
17
+ const rs = await api.call.assetConversionApi.getReserves(assetLocation1, assetLocation2);
18
+ if (!rs) {
19
+ return ['0', '0'];
20
+ }
21
+ const [balanceAsset1, balanceAsset2] = rs.unwrapOrDefault();
22
+ return [balanceAsset1.toString(), balanceAsset2.toString()];
23
+ };
24
+ exports._getPoolInfo = _getPoolInfo;
25
+ const getReserveForPool = async (api, asset1, asset2) => {
26
+ let [balanceAsset1, balanceAsset2] = await _getPoolInfo(api, asset1, asset2);
27
+ if (balanceAsset1 !== '0' && balanceAsset2 !== '0') {
28
+ return [balanceAsset1, balanceAsset2];
29
+ } else {
30
+ [balanceAsset2, balanceAsset1] = await _getPoolInfo(api, asset2, asset1);
31
+ return [balanceAsset1, balanceAsset2];
32
+ }
33
+ };
34
+ exports.getReserveForPool = getReserveForPool;
35
+ const getReserveForPath = async (api, paths) => {
36
+ const pairs = [];
37
+ for (let i = 0; i < paths.length - 1; i++) {
38
+ const asset1 = paths[i];
39
+ const asset2 = paths[i + 1];
40
+ pairs.push([asset1, asset2]);
41
+ }
42
+ return await Promise.all(pairs.map(async _ref => {
43
+ let [asset1, asset2] = _ref;
44
+ return getReserveForPool(api, asset1, asset2);
45
+ }));
46
+ };
47
+ exports.getReserveForPath = getReserveForPath;
48
+ const estimateTokensForPool = (amount, reserves) => {
49
+ if (amount === '0') {
50
+ return '0';
51
+ }
52
+ return new _bignumber.default(amount).times(reserves[1]).div(reserves[0]).integerValue(_bignumber.default.ROUND_DOWN).toString();
53
+ };
54
+ exports.estimateTokensForPool = estimateTokensForPool;
55
+ const estimateTokensForPath = (amount, reserves) => {
56
+ const result = [amount];
57
+ for (let i = 0; i < reserves.length; i++) {
58
+ const reserve = reserves[i];
59
+ const currentAmount = result[i];
60
+ const nextAmount = estimateTokensForPool(currentAmount, reserve);
61
+ result.push(nextAmount);
62
+ }
63
+ return result;
64
+ };
65
+ exports.estimateTokensForPath = estimateTokensForPath;
66
+ const estimateRateForPath = reserves => {
67
+ let result = new _bignumber.default(1);
68
+ for (const reserve of reserves) {
69
+ result = result.times(reserve[0]).div(reserve[1]);
70
+ }
71
+ return result.toString();
72
+ };
73
+ exports.estimateRateForPath = estimateRateForPath;
74
+ const estimateActualRate = (amount, reserves) => {
75
+ let result = new _bignumber.default(1);
76
+ const m = new _bignumber.default(amount);
77
+
78
+ // Currently support for direct path swap only
79
+ for (const reserve of reserves) {
80
+ const x = new _bignumber.default(reserve[0]);
81
+ const y = new _bignumber.default(reserve[1]);
82
+ result = result.times(x.plus(m)).div(y);
83
+ }
84
+ return result.toString();
85
+ };
86
+ exports.estimateActualRate = estimateActualRate;
87
+ const estimateRateAfter = (amount, reserves) => {
88
+ const m = new _bignumber.default(amount);
89
+ const reserve = reserves[0];
90
+ const x = new _bignumber.default(reserve[0]);
91
+ const y = new _bignumber.default(reserve[1]);
92
+ const n = y.multipliedBy(m).div(x.plus(m));
93
+ const result = x.plus(m).div(y.minus(n));
94
+ return result.toString();
95
+ };
96
+ exports.estimateRateAfter = estimateRateAfter;
97
+ const estimatePriceImpactPct = (marketRate, marketRateAfter) => {
98
+ const bnMarketRate = new _bignumber.default(marketRate);
99
+ const bnActualRate = new _bignumber.default(marketRateAfter);
100
+ return new _bignumber.default(1).minus(bnMarketRate.div(bnActualRate)).multipliedBy(100).toString();
101
+ };
102
+ exports.estimatePriceImpactPct = estimatePriceImpactPct;
103
+ const checkLiquidityForPool = (amount, reserve1, reserve2) => {
104
+ if (new _bignumber.default(reserve1).eq('0') || new _bignumber.default(reserve2).eq('0')) {
105
+ return _swap.SwapErrorType.ASSET_NOT_SUPPORTED;
106
+ } else if (new _bignumber.default(reserve1).lt(amount)) {
107
+ return _swap.SwapErrorType.NOT_ENOUGH_LIQUIDITY;
108
+ }
109
+ return undefined;
110
+ };
111
+ exports.checkLiquidityForPool = checkLiquidityForPool;
112
+ const checkLiquidityForPath = (amounts, reserves) => {
113
+ for (let i = 0; i < reserves.length; i++) {
114
+ const amount = amounts[i];
115
+ const [reserve1, reserve2] = reserves[i];
116
+ const error = checkLiquidityForPool(amount, reserve1, reserve2);
117
+ if (error) {
118
+ return error;
119
+ }
120
+ }
121
+ return undefined;
122
+ };
123
+
124
+ // Swap from asset1 to asset2
125
+ exports.checkLiquidityForPath = checkLiquidityForPath;
126
+ const checkMinAmountForPool = (reserve1, reserve2, amount1, amount2, minAmount1, minAmount2) => {
127
+ const newReserve1 = new _bignumber.default(reserve1).plus(amount1);
128
+ const newReserve2 = new _bignumber.default(reserve2).minus(amount2);
129
+ if (newReserve1.lt(minAmount1) || newReserve2.lt(minAmount2)) {
130
+ return _swap.SwapErrorType.MAKE_POOL_NOT_ENOUGH_EXISTENTIAL_DEPOSIT;
131
+ }
132
+ return undefined;
133
+ };
134
+ exports.checkMinAmountForPool = checkMinAmountForPool;
135
+ const checkMinAmountForPath = (reserves, amounts, minAmounts) => {
136
+ for (let i = 0; i < reserves.length; i++) {
137
+ const [amount1, amount2] = amounts.slice(i, 2);
138
+ const [minAmount1, minAmount2] = minAmounts.slice(i, 2);
139
+ const [reserve1, reserve2] = reserves[i];
140
+ const error = checkMinAmountForPool(reserve1, reserve2, amount1, amount2, minAmount1, minAmount2);
141
+ if (error) {
142
+ return error;
143
+ }
144
+ }
145
+ return undefined;
146
+ };
147
+
148
+ // Build extrinsic for swap
149
+ exports.checkMinAmountForPath = checkMinAmountForPath;
150
+ const buildSwapExtrinsic = function (api, paths, recipient, amountIn, amountOutMin) {
151
+ let keepAlive = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true;
152
+ const pathsInfo = paths.map(asset => {
153
+ const multilocation = (0, _utils._getXcmAssetMultilocation)(asset);
154
+ return api.createType('MultiLocation', multilocation).toU8a();
155
+ });
156
+ return api.tx.assetConversion.swapExactTokensForTokens(pathsInfo, amountIn, amountOutMin, recipient, keepAlive);
157
+ };
158
+ exports.buildSwapExtrinsic = buildSwapExtrinsic;
@@ -8,6 +8,7 @@ var _SwapError = require("@subwallet/extension-base/background/errors/SwapError"
8
8
  var _TransactionError = require("@subwallet/extension-base/background/errors/TransactionError");
9
9
  var _KoniTypes = require("@subwallet/extension-base/background/KoniTypes");
10
10
  var _types = require("@subwallet/extension-base/services/base/types");
11
+ var _assetHub = require("@subwallet/extension-base/services/swap-service/handler/asset-hub");
11
12
  var _chainflipHandler = require("@subwallet/extension-base/services/swap-service/handler/chainflip-handler");
12
13
  var _hydradxHandler = require("@subwallet/extension-base/services/swap-service/handler/hydradx-handler");
13
14
  var _utils = require("@subwallet/extension-base/services/swap-service/utils");
@@ -97,7 +98,6 @@ class SwapService {
97
98
  request,
98
99
  selectedQuote: swapQuoteResponse.optimalQuote
99
100
  });
100
- console.log('optimalProcess', optimalProcess);
101
101
  return {
102
102
  process: optimalProcess,
103
103
  quote: swapQuoteResponse
@@ -147,6 +147,15 @@ class SwapService {
147
147
  case _swap.SwapProviderId.HYDRADX_MAINNET:
148
148
  this.handlers[providerId] = new _hydradxHandler.HydradxHandler(this.chainService, this.state.balanceService, false);
149
149
  break;
150
+ case _swap.SwapProviderId.POLKADOT_ASSET_HUB:
151
+ this.handlers[providerId] = new _assetHub.AssetHubSwapHandler(this.chainService, this.state.balanceService, 'statemint');
152
+ break;
153
+ case _swap.SwapProviderId.KUSAMA_ASSET_HUB:
154
+ this.handlers[providerId] = new _assetHub.AssetHubSwapHandler(this.chainService, this.state.balanceService, 'statemine');
155
+ break;
156
+ case _swap.SwapProviderId.ROCOCO_ASSET_HUB:
157
+ this.handlers[providerId] = new _assetHub.AssetHubSwapHandler(this.chainService, this.state.balanceService, 'rococo_assethub');
158
+ break;
150
159
  default:
151
160
  throw new Error('Unsupported provider');
152
161
  }
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports._PROVIDER_TO_SUPPORTED_PAIR_MAP = exports.SWAP_QUOTE_TIMEOUT_MAP = exports.CHAIN_FLIP_TESTNET_EXPLORER = exports.CHAIN_FLIP_SUPPORTED_TESTNET_MAPPING = exports.CHAIN_FLIP_SUPPORTED_TESTNET_ASSET_MAPPING = exports.CHAIN_FLIP_SUPPORTED_MAINNET_MAPPING = exports.CHAIN_FLIP_SUPPORTED_MAINNET_ASSET_MAPPING = exports.CHAIN_FLIP_MAINNET_EXPLORER = void 0;
8
8
  exports.calculateSwapRate = calculateSwapRate;
9
+ exports.convertSwapRate = convertSwapRate;
9
10
  exports.getSwapAltToken = getSwapAltToken;
10
11
  exports.getSwapAlternativeAsset = getSwapAlternativeAsset;
11
12
  var _swap = require("@chainflip/sdk/swap");
@@ -53,7 +54,10 @@ const _PROVIDER_TO_SUPPORTED_PAIR_MAP = {
53
54
  [_swap2.SwapProviderId.HYDRADX_MAINNET]: [_chainList.COMMON_CHAIN_SLUGS.HYDRADX],
54
55
  [_swap2.SwapProviderId.HYDRADX_TESTNET]: [_chainList.COMMON_CHAIN_SLUGS.HYDRADX_TESTNET],
55
56
  [_swap2.SwapProviderId.CHAIN_FLIP_MAINNET]: [_chainList.COMMON_CHAIN_SLUGS.POLKADOT, _chainList.COMMON_CHAIN_SLUGS.ETHEREUM],
56
- [_swap2.SwapProviderId.CHAIN_FLIP_TESTNET]: [_chainList.COMMON_CHAIN_SLUGS.CHAINFLIP_POLKADOT, _chainList.COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA]
57
+ [_swap2.SwapProviderId.CHAIN_FLIP_TESTNET]: [_chainList.COMMON_CHAIN_SLUGS.CHAINFLIP_POLKADOT, _chainList.COMMON_CHAIN_SLUGS.ETHEREUM_SEPOLIA],
58
+ [_swap2.SwapProviderId.POLKADOT_ASSET_HUB]: [_chainList.COMMON_CHAIN_SLUGS.POLKADOT_ASSET_HUB],
59
+ [_swap2.SwapProviderId.KUSAMA_ASSET_HUB]: [_chainList.COMMON_CHAIN_SLUGS.KUSAMA_ASSET_HUB],
60
+ [_swap2.SwapProviderId.ROCOCO_ASSET_HUB]: [_chainList.COMMON_CHAIN_SLUGS.ROCOCO_ASSET_HUB]
57
61
  };
58
62
  exports._PROVIDER_TO_SUPPORTED_PAIR_MAP = _PROVIDER_TO_SUPPORTED_PAIR_MAP;
59
63
  function getSwapAlternativeAsset(swapPair) {
@@ -70,4 +74,9 @@ function calculateSwapRate(fromAmount, toAmount, fromAsset, toAsset) {
70
74
  const decimalDiff = (0, _utils._getAssetDecimals)(toAsset) - (0, _utils._getAssetDecimals)(fromAsset);
71
75
  const bnRate = bnFromAmount.div(bnToAmount);
72
76
  return 1 / bnRate.times(10 ** decimalDiff).toNumber();
77
+ }
78
+ function convertSwapRate(rate, fromAsset, toAsset) {
79
+ const decimalDiff = (0, _utils._getAssetDecimals)(toAsset) - (0, _utils._getAssetDecimals)(fromAsset);
80
+ const bnRate = new _bignumber.default(rate);
81
+ return bnRate.times(10 ** decimalDiff).pow(-1).toNumber();
73
82
  }