@subwallet/extension-base 1.2.13-0 → 1.2.15-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 (86) 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/core/substrate/nominationpools-pallet.js +2 -1
  5. package/cjs/koni/api/nft/config.js +37 -23
  6. package/cjs/koni/api/nft/index.js +9 -1
  7. package/cjs/koni/api/nft/unique_network_nft/index.js +12 -20
  8. package/cjs/koni/background/handlers/Extension.js +12 -0
  9. package/cjs/packageInfo.js +1 -1
  10. package/cjs/services/balance-service/transfer/xcm/utils.js +2 -2
  11. package/cjs/services/chain-service/constants.js +2 -1
  12. package/cjs/services/chain-service/handler/SubstrateApi.js +6 -0
  13. package/cjs/services/chain-service/health-check/constants/index.js +4 -4
  14. package/cjs/services/chain-service/health-check/utils/asset-info.js +23 -6
  15. package/cjs/services/chain-service/health-check/utils/chain-info.js +25 -2
  16. package/cjs/services/chain-service/health-check/utils/new-utils/asset-asset-validate.js +160 -0
  17. package/cjs/services/chain-service/health-check/utils/new-utils/asset-validate.js +45 -0
  18. package/cjs/services/chain-service/health-check/utils/new-utils/chain-asset-validate.js +73 -0
  19. package/cjs/services/chain-service/health-check/utils/new-utils/chain-validate.js +34 -0
  20. package/cjs/services/chain-service/index.js +47 -5
  21. package/cjs/services/earning-service/handlers/liquid-staking/acala.js +49 -19
  22. package/cjs/services/migration-service/scripts/databases/ReloadMetadata.js +35 -0
  23. package/cjs/services/migration-service/scripts/index.js +4 -2
  24. package/cjs/services/price-service/coingecko.js +57 -32
  25. package/cjs/services/price-service/index.js +30 -11
  26. package/cjs/services/storage-service/db-stores/BaseStore.js +4 -0
  27. package/cjs/services/swap-service/handler/asset-hub/handler.js +343 -0
  28. package/cjs/services/swap-service/handler/asset-hub/index.js +12 -0
  29. package/cjs/services/swap-service/handler/asset-hub/router.js +93 -0
  30. package/cjs/services/swap-service/handler/asset-hub/utils.js +158 -0
  31. package/cjs/services/swap-service/index.js +10 -1
  32. package/cjs/services/swap-service/utils.js +10 -1
  33. package/cjs/types/swap/index.js +5 -1
  34. package/core/logic-validation/swap.d.ts +3 -1
  35. package/core/logic-validation/swap.js +55 -4
  36. package/core/substrate/nominationpools-pallet.js +2 -1
  37. package/koni/api/nft/config.d.ts +1 -0
  38. package/koni/api/nft/config.js +31 -19
  39. package/koni/api/nft/index.js +9 -1
  40. package/koni/api/nft/unique_network_nft/index.js +12 -20
  41. package/koni/background/handlers/Extension.js +12 -0
  42. package/package.json +56 -11
  43. package/packageInfo.js +1 -1
  44. package/services/balance-service/transfer/xcm/utils.js +2 -2
  45. package/services/chain-service/constants.d.ts +1 -0
  46. package/services/chain-service/constants.js +2 -1
  47. package/services/chain-service/handler/SubstrateApi.js +6 -0
  48. package/services/chain-service/health-check/constants/index.js +4 -4
  49. package/services/chain-service/health-check/utils/asset-info.d.ts +1 -0
  50. package/services/chain-service/health-check/utils/asset-info.js +20 -4
  51. package/services/chain-service/health-check/utils/chain-info.d.ts +4 -2
  52. package/services/chain-service/health-check/utils/chain-info.js +20 -0
  53. package/services/chain-service/health-check/utils/new-utils/asset-asset-validate.d.ts +10 -0
  54. package/services/chain-service/health-check/utils/new-utils/asset-asset-validate.js +146 -0
  55. package/services/chain-service/health-check/utils/new-utils/asset-validate.d.ts +3 -0
  56. package/services/chain-service/health-check/utils/new-utils/asset-validate.js +38 -0
  57. package/services/chain-service/health-check/utils/new-utils/chain-asset-validate.d.ts +5 -0
  58. package/services/chain-service/health-check/utils/new-utils/chain-asset-validate.js +64 -0
  59. package/services/chain-service/health-check/utils/new-utils/chain-validate.d.ts +4 -0
  60. package/services/chain-service/health-check/utils/new-utils/chain-validate.js +26 -0
  61. package/services/chain-service/index.js +47 -5
  62. package/services/chain-service/types.d.ts +5 -0
  63. package/services/earning-service/handlers/liquid-staking/acala.js +46 -17
  64. package/services/migration-service/scripts/databases/ReloadMetadata.d.ts +5 -0
  65. package/services/migration-service/scripts/databases/ReloadMetadata.js +27 -0
  66. package/services/migration-service/scripts/index.js +4 -2
  67. package/services/price-service/coingecko.js +54 -32
  68. package/services/price-service/index.js +29 -11
  69. package/services/storage-service/db-stores/BaseStore.d.ts +3 -0
  70. package/services/storage-service/db-stores/BaseStore.js +4 -0
  71. package/services/swap-service/handler/asset-hub/handler.d.ts +31 -0
  72. package/services/swap-service/handler/asset-hub/handler.js +335 -0
  73. package/services/swap-service/handler/asset-hub/index.d.ts +1 -0
  74. package/services/swap-service/handler/asset-hub/index.js +4 -0
  75. package/services/swap-service/handler/asset-hub/router.d.ts +16 -0
  76. package/services/swap-service/handler/asset-hub/router.js +85 -0
  77. package/services/swap-service/handler/asset-hub/utils.d.ts +18 -0
  78. package/services/swap-service/handler/asset-hub/utils.js +133 -0
  79. package/services/swap-service/index.js +10 -1
  80. package/services/swap-service/utils.d.ts +1 -0
  81. package/services/swap-service/utils.js +9 -1
  82. package/types/swap/index.d.ts +15 -2
  83. package/types/swap/index.js +5 -1
  84. /package/cjs/services/migration-service/scripts/{ClearMetadataDatabase.js → databases/ClearMetadataDatabase.js} +0 -0
  85. /package/services/migration-service/scripts/{ClearMetadataDatabase.d.ts → databases/ClearMetadataDatabase.d.ts} +0 -0
  86. /package/services/migration-service/scripts/{ClearMetadataDatabase.js → databases/ClearMetadataDatabase.js} +0 -0
@@ -5,15 +5,25 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.getPriceMap = exports.getExchangeRateMap = void 0;
7
7
  var _staticData = require("@subwallet/extension-base/utils/staticData");
8
+ var _util = require("@polkadot/util");
8
9
  // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
9
10
  // SPDX-License-Identifier: Apache-2.0
10
11
 
11
12
  const DEFAULT_CURRENCY = 'USD';
12
13
  let useBackupApi = false;
13
14
  const getExchangeRateMap = async () => {
15
+ let response;
14
16
  try {
15
- const response = await fetch('https://api-cache.subwallet.app/exchange-rate');
16
- const responseDataExchangeRate = (await response.json()) || {};
17
+ var _response, _response2;
18
+ try {
19
+ response = await fetch('https://api-cache.subwallet.app/exchange-rate');
20
+ } catch (e) {}
21
+ if (((_response = response) === null || _response === void 0 ? void 0 : _response.status) !== 200) {
22
+ try {
23
+ response = await fetch('https://static-cache.subwallet.app/exchange-rate/data.json');
24
+ } catch (e) {}
25
+ }
26
+ const responseDataExchangeRate = (await ((_response2 = response) === null || _response2 === void 0 ? void 0 : _response2.json())) || {};
17
27
  const exchangeRateMap = Object.keys(responseDataExchangeRate.conversion_rates).reduce((map, exchangeKey) => {
18
28
  if (!_staticData.staticData[_staticData.StaticKey.CURRENCY_SYMBOL][exchangeKey]) {
19
29
  return map;
@@ -26,45 +36,60 @@ const getExchangeRateMap = async () => {
26
36
  }, {});
27
37
  return exchangeRateMap;
28
38
  } catch (e) {
29
- console.warn('Failed to get exchange rate');
30
39
  return {};
31
40
  }
32
41
  };
33
42
  exports.getExchangeRateMap = getExchangeRateMap;
34
43
  const getPriceMap = async function (priceIds) {
35
- var _rs, _rs2;
36
44
  let currency = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'USD';
37
45
  const idStr = Array.from(priceIds).join(',');
38
- let rs;
39
- if (!useBackupApi) {
40
- try {
41
- rs = await fetch(`https://api.coingecko.com/api/v3/coins/markets?vs_currency=${currency.toLowerCase()}&per_page=250&ids=${idStr}`);
42
- } catch (err) {
46
+ let response;
47
+ try {
48
+ var _response3, _response5;
49
+ if (!useBackupApi) {
50
+ try {
51
+ response = await fetch(`https://api.coingecko.com/api/v3/coins/markets?vs_currency=${currency.toLowerCase()}&per_page=250&ids=${idStr}`);
52
+ } catch (err) {
53
+ useBackupApi = true;
54
+ }
55
+ }
56
+ if (useBackupApi || ((_response3 = response) === null || _response3 === void 0 ? void 0 : _response3.status) !== 200) {
57
+ var _response4;
43
58
  useBackupApi = true;
59
+ try {
60
+ response = await fetch(`https://api-cache.subwallet.app/api/price/get?ids=${idStr}`);
61
+ } catch (e) {}
62
+ if (((_response4 = response) === null || _response4 === void 0 ? void 0 : _response4.status) !== 200) {
63
+ try {
64
+ response = await fetch('https://static-cache.subwallet.app/price/data.json');
65
+ } catch (e) {}
66
+ }
44
67
  }
68
+ const generateDataPriceRaw = (await ((_response5 = response) === null || _response5 === void 0 ? void 0 : _response5.json())) || [];
69
+ const responseDataPrice = (0, _util.isArray)(generateDataPriceRaw) ? generateDataPriceRaw : Object.entries(generateDataPriceRaw).map(_ref => {
70
+ let [id, value] = _ref;
71
+ return {
72
+ ...value,
73
+ id
74
+ };
75
+ });
76
+ const currencyData = _staticData.staticData[_staticData.StaticKey.CURRENCY_SYMBOL][currency || DEFAULT_CURRENCY];
77
+ const priceMap = {};
78
+ const price24hMap = {};
79
+ responseDataPrice.forEach(val => {
80
+ const currentPrice = val.current_price || 0;
81
+ const price24h = currentPrice - (val.price_change_24h || 0);
82
+ priceMap[val.id] = currentPrice;
83
+ price24hMap[val.id] = price24h;
84
+ });
85
+ return {
86
+ currency,
87
+ currencyData,
88
+ priceMap,
89
+ price24hMap
90
+ };
91
+ } catch (e) {
92
+ return {};
45
93
  }
46
- if (useBackupApi || ((_rs = rs) === null || _rs === void 0 ? void 0 : _rs.status) !== 200) {
47
- useBackupApi = true;
48
- rs = await fetch(`https://chain-data.subwallet.app/api/price/get?ids=${idStr}`);
49
- }
50
- if (((_rs2 = rs) === null || _rs2 === void 0 ? void 0 : _rs2.status) !== 200) {
51
- console.warn('Failed to get token price');
52
- }
53
- const responseDataPrice = (await rs.json()) || [];
54
- const currencyData = _staticData.staticData[_staticData.StaticKey.CURRENCY_SYMBOL][currency || DEFAULT_CURRENCY];
55
- const priceMap = {};
56
- const price24hMap = {};
57
- responseDataPrice.forEach(val => {
58
- const currentPrice = val.current_price || 0;
59
- const price24h = currentPrice - (val.price_change_24h || 0);
60
- priceMap[val.id] = currentPrice;
61
- price24hMap[val.id] = price24h;
62
- });
63
- return {
64
- currency,
65
- currencyData,
66
- priceMap,
67
- price24hMap
68
- };
69
94
  };
70
95
  exports.getPriceMap = getPriceMap;
@@ -9,6 +9,7 @@ var _types = require("@subwallet/extension-base/services/base/types");
9
9
  var _coingecko = require("@subwallet/extension-base/services/price-service/coingecko");
10
10
  var _storage = require("@subwallet/extension-base/storage");
11
11
  var _stores = require("@subwallet/extension-base/stores");
12
+ var _utils = require("@subwallet/extension-base/utils");
12
13
  var _promise = require("@subwallet/extension-base/utils/promise");
13
14
  var _staticData = require("@subwallet/extension-base/utils/staticData");
14
15
  var _rxjs = require("rxjs");
@@ -28,6 +29,9 @@ const DEFAULT_PRICE_SUBJECT = {
28
29
  price24hMap: {},
29
30
  exchangeRateMap: {}
30
31
  };
32
+ const checkFetchSuccess = (obj1, obj2) => {
33
+ return Object.keys(obj1).length > 0 && Object.keys(obj2).length > 0;
34
+ };
31
35
  class PriceService {
32
36
  priceIds = new Set();
33
37
  currency = new _stores.CurrentCurrencyStore();
@@ -49,11 +53,16 @@ class PriceService {
49
53
  this.init().then(() => this.getCurrentCurrency(updateCurrency)).catch(console.error);
50
54
  }
51
55
  async getTokenPrice(priceIds, currency, resolve, reject) {
52
- await Promise.all([(0, _coingecko.getExchangeRateMap)(), (0, _coingecko.getPriceMap)(priceIds, currency)]).then(_ref => {
53
- let [exchangeRateMap, priceMap] = _ref;
54
- this.rawExchangeRateMap.next(exchangeRateMap);
55
- this.rawPriceSubject.next(priceMap);
56
- });
56
+ const getPriceData = async () => {
57
+ await Promise.all([(0, _coingecko.getExchangeRateMap)(), (0, _coingecko.getPriceMap)(priceIds, currency)]).then(_ref => {
58
+ let [exchangeRateMap, priceMap] = _ref;
59
+ if (checkFetchSuccess(priceMap, exchangeRateMap)) {
60
+ this.rawExchangeRateMap.next(exchangeRateMap);
61
+ this.rawPriceSubject.next(priceMap);
62
+ }
63
+ });
64
+ };
65
+ await Promise.race([getPriceData(), (0, _utils.wait)(10 * 1000)]);
57
66
  }
58
67
  getCurrentCurrencySubject() {
59
68
  return this.currency.getSubject();
@@ -89,17 +98,27 @@ class PriceService {
89
98
  })();
90
99
  }
91
100
  async calculatePriceMap(currency) {
92
- const {
101
+ let {
93
102
  price24hMap,
94
103
  priceMap
95
104
  } = this.rawPriceSubject.value;
96
- const exchangeRateData = this.rawExchangeRateMap.value;
105
+ let exchangeRateData = this.rawExchangeRateMap.value;
106
+ const priceStored = await this.dbService.getPriceStore(currency);
97
107
  const currencyKey = currency || DEFAULT_CURRENCY;
98
108
  if (Object.keys(this.rawPriceSubject.value).length === 0) {
99
- return;
109
+ if (priceStored !== null && priceStored !== void 0 && priceStored.exchangeRateMap) {
110
+ exchangeRateData = priceStored.exchangeRateMap;
111
+ }
100
112
  }
101
113
  if (Object.keys(exchangeRateData).length === 0) {
102
- return;
114
+ if (priceStored !== null && priceStored !== void 0 && priceStored.price24hMap) {
115
+ price24hMap = {
116
+ ...priceStored.price24hMap
117
+ };
118
+ priceMap = {
119
+ ...priceStored.priceMap
120
+ };
121
+ }
103
122
  }
104
123
  const finalPriceMap = {
105
124
  priceMap: {
@@ -165,8 +184,8 @@ class PriceService {
165
184
  this.refreshPriceMapByAction();
166
185
  }
167
186
  };
168
- this.getCurrentCurrencySubject().subscribe(currency => {
169
- console.log('Currency changed', currency);
187
+ (0, _rxjs.combineLatest)([this.getCurrentCurrencySubject(), this.rawPriceSubject, this.rawExchangeRateMap]).subscribe(_ref2 => {
188
+ let [currency] = _ref2;
170
189
  this.calculatePriceMap(currency).then(data => {
171
190
  if (data) {
172
191
  this.priceSubject.next(data);
@@ -22,6 +22,10 @@ class BaseStore {
22
22
  bulkUpsert(records) {
23
23
  return this.table.bulkPut(records);
24
24
  }
25
+
26
+ /**
27
+ * @todo Must update, delete function need the key not the record
28
+ * */
25
29
  remove(record) {
26
30
  return this.table.delete(record);
27
31
  }
@@ -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;