@subwallet/extension-base 1.1.59-0 → 1.1.60-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/background/KoniTypes.d.ts +18 -1
- package/cjs/constants/staking.js +2 -1
- package/cjs/constants/storage.js +4 -2
- package/cjs/koni/api/coingecko.js +58 -15
- package/cjs/koni/api/nft/config.js +26 -22
- package/cjs/koni/background/handlers/Extension.js +130 -122
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +7 -1
- package/cjs/services/chain-service/index.js +6 -1
- package/cjs/services/chain-service/utils/index.js +34 -14
- package/cjs/services/price-service/coingecko.js +54 -35
- package/cjs/services/price-service/index.js +83 -12
- package/cjs/services/setting-service/constants.js +4 -1
- package/cjs/services/storage-service/DatabaseService.js +2 -3
- package/cjs/utils/number.js +84 -1
- package/cjs/utils/staticData/index.js +6 -1
- package/constants/staking.js +2 -1
- package/constants/storage.d.ts +1 -0
- package/constants/storage.js +2 -1
- package/koni/api/coingecko.d.ts +2 -2
- package/koni/api/coingecko.js +58 -15
- package/koni/api/nft/config.js +27 -21
- package/koni/background/handlers/Extension.d.ts +1 -0
- package/koni/background/handlers/Extension.js +7 -0
- package/package.json +7 -6
- package/packageInfo.js +1 -1
- package/services/balance-service/helpers/subscribe/substrate/index.js +8 -2
- package/services/chain-service/index.js +6 -1
- package/services/chain-service/utils/index.d.ts +13 -0
- package/services/chain-service/utils/index.js +32 -14
- package/services/price-service/coingecko.d.ts +3 -2
- package/services/price-service/coingecko.js +50 -32
- package/services/price-service/index.d.ts +7 -2
- package/services/price-service/index.js +85 -15
- package/services/setting-service/constants.d.ts +1 -0
- package/services/setting-service/constants.js +2 -0
- package/services/storage-service/DatabaseService.d.ts +1 -1
- package/services/storage-service/DatabaseService.js +2 -3
- package/utils/number.d.ts +1 -0
- package/utils/number.js +82 -0
- package/utils/staticData/currencySymbol.json +11 -0
- package/utils/staticData/index.d.ts +3 -0
- package/utils/staticData/index.js +4 -0
package/cjs/packageInfo.js
CHANGED
|
@@ -60,7 +60,13 @@ const subscribeSubstrateBalance = async (addresses, chainInfo, assetMap, substra
|
|
|
60
60
|
if (_constants2._BALANCE_CHAIN_GROUP.supportBridged.includes(chain)) {
|
|
61
61
|
unsubBridgedToken = await subscribeBridgedBalance(substrateParams);
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Some substrate chain use evm account format but not have evm connection and support ERC20 contract,
|
|
66
|
+
* so we need to check if the chain is compatible with EVM and support ERC20
|
|
67
|
+
* */
|
|
68
|
+
if ((0, _utils2._isChainEvmCompatible)(chainInfo) && (0, _utils2._getTokenTypesSupportedByChain)(chainInfo).includes(_types._AssetType.ERC20)) {
|
|
69
|
+
// Get sub-token for EVM-compatible chains
|
|
64
70
|
unsubEvmContractToken = (0, _evm.subscribeERC20Interval)({
|
|
65
71
|
...baseParams,
|
|
66
72
|
evmApi: evmApi
|
|
@@ -667,7 +667,12 @@ class ChainService {
|
|
|
667
667
|
this.substrateChainHandler.setSubstrateApi(chainInfo.slug, chainApi);
|
|
668
668
|
}
|
|
669
669
|
}
|
|
670
|
-
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* To check if the chain is EVM chain, we need to check if the chain has evmInfo and evmChainId is not -1
|
|
673
|
+
* (fake evm chain to connect to substrate chain)
|
|
674
|
+
* */
|
|
675
|
+
if (chainInfo.evmInfo !== null && chainInfo.evmInfo !== undefined && chainInfo.evmInfo.evmChainId !== -1) {
|
|
671
676
|
const chainApi = await this.evmChainHandler.initApi(chainInfo.slug, endpoint, {
|
|
672
677
|
providerName,
|
|
673
678
|
onUpdateStatus
|
|
@@ -13,6 +13,7 @@ var _exportNames = {
|
|
|
13
13
|
_isPureSubstrateChain: true,
|
|
14
14
|
_getOriginChainOfAsset: true,
|
|
15
15
|
_getContractAddressOfToken: true,
|
|
16
|
+
_isNativeTokenTransferredByEvm: true,
|
|
16
17
|
_isTokenTransferredByEvm: true,
|
|
17
18
|
_checkSmartContractSupportByChain: true,
|
|
18
19
|
_getTokenOnChainAssetId: true,
|
|
@@ -132,6 +133,7 @@ exports._isLocalToken = _isLocalToken;
|
|
|
132
133
|
exports._isMantaZkAsset = _isMantaZkAsset;
|
|
133
134
|
exports._isNativeToken = _isNativeToken;
|
|
134
135
|
exports._isNativeTokenBySlug = _isNativeTokenBySlug;
|
|
136
|
+
exports._isNativeTokenTransferredByEvm = _isNativeTokenTransferredByEvm;
|
|
135
137
|
exports._isPureEvmChain = _isPureEvmChain;
|
|
136
138
|
exports._isPureSubstrateChain = _isPureSubstrateChain;
|
|
137
139
|
exports._isSmartContractToken = _isSmartContractToken;
|
|
@@ -229,9 +231,27 @@ function _getContractAddressOfToken(tokenInfo) {
|
|
|
229
231
|
var _tokenInfo$metadata;
|
|
230
232
|
return ((_tokenInfo$metadata = tokenInfo.metadata) === null || _tokenInfo$metadata === void 0 ? void 0 : _tokenInfo$metadata.contractAddress) || '';
|
|
231
233
|
}
|
|
232
|
-
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* @function _isNativeTokenTransferredByEvm
|
|
237
|
+
* @description Check if the native token is transferred by EVM, some token is only transferred by Substrate, need to check disableEvmTransfer flag
|
|
238
|
+
* @param {_ChainAsset} tokenInfo - The token info object
|
|
239
|
+
* @returns {boolean} - Return true if the native token can transfer by EVM
|
|
240
|
+
* */
|
|
241
|
+
function _isNativeTokenTransferredByEvm(tokenInfo) {
|
|
233
242
|
var _tokenInfo$metadata2;
|
|
234
|
-
return
|
|
243
|
+
return !((_tokenInfo$metadata2 = tokenInfo.metadata) !== null && _tokenInfo$metadata2 !== void 0 && _tokenInfo$metadata2.disableEvmTransfer);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* @function _isTokenTransferredByEvm
|
|
248
|
+
* @description Check if the token is transferred by EVM
|
|
249
|
+
* @param {_ChainAsset} tokenInfo - The token info object
|
|
250
|
+
* @returns {boolean} - Return true if the token can transfer by EVM
|
|
251
|
+
* */
|
|
252
|
+
function _isTokenTransferredByEvm(tokenInfo) {
|
|
253
|
+
var _tokenInfo$metadata3;
|
|
254
|
+
return !!((_tokenInfo$metadata3 = tokenInfo.metadata) !== null && _tokenInfo$metadata3 !== void 0 && _tokenInfo$metadata3.contractAddress) || _isNativeToken(tokenInfo) && _isNativeTokenTransferredByEvm(tokenInfo);
|
|
235
255
|
}
|
|
236
256
|
function _checkSmartContractSupportByChain(chainInfo, contractType) {
|
|
237
257
|
// EVM chains support smart contract by default so just checking Substrate chains
|
|
@@ -243,16 +263,16 @@ function _checkSmartContractSupportByChain(chainInfo, contractType) {
|
|
|
243
263
|
|
|
244
264
|
// Utils for balance functions
|
|
245
265
|
function _getTokenOnChainAssetId(tokenInfo) {
|
|
246
|
-
var _tokenInfo$
|
|
247
|
-
return ((_tokenInfo$
|
|
266
|
+
var _tokenInfo$metadata4;
|
|
267
|
+
return ((_tokenInfo$metadata4 = tokenInfo.metadata) === null || _tokenInfo$metadata4 === void 0 ? void 0 : _tokenInfo$metadata4.assetId) || '-1';
|
|
248
268
|
}
|
|
249
269
|
function _getTokenOnChainInfo(tokenInfo) {
|
|
250
|
-
var _tokenInfo$
|
|
251
|
-
return (_tokenInfo$
|
|
270
|
+
var _tokenInfo$metadata5;
|
|
271
|
+
return (_tokenInfo$metadata5 = tokenInfo.metadata) === null || _tokenInfo$metadata5 === void 0 ? void 0 : _tokenInfo$metadata5.onChainInfo;
|
|
252
272
|
}
|
|
253
273
|
function _isBridgedToken(tokenInfo) {
|
|
254
|
-
var _tokenInfo$
|
|
255
|
-
return (_tokenInfo$
|
|
274
|
+
var _tokenInfo$metadata6;
|
|
275
|
+
return (_tokenInfo$metadata6 = tokenInfo.metadata) === null || _tokenInfo$metadata6 === void 0 ? void 0 : _tokenInfo$metadata6.isBridged;
|
|
256
276
|
}
|
|
257
277
|
function _getTokenMinAmount(tokenInfo) {
|
|
258
278
|
return tokenInfo.minAmount || '0';
|
|
@@ -407,16 +427,16 @@ function _isXcmPathSupported(originTokenSlug, destinationTokenSlug, assetRefMap)
|
|
|
407
427
|
return assetRef.path === _types._AssetRefPath.XCM;
|
|
408
428
|
}
|
|
409
429
|
function _getXcmAssetType(tokenInfo) {
|
|
410
|
-
var _tokenInfo$
|
|
411
|
-
return ((_tokenInfo$
|
|
430
|
+
var _tokenInfo$metadata7;
|
|
431
|
+
return ((_tokenInfo$metadata7 = tokenInfo.metadata) === null || _tokenInfo$metadata7 === void 0 ? void 0 : _tokenInfo$metadata7.assetType) || '';
|
|
412
432
|
}
|
|
413
433
|
function _getXcmAssetId(tokenInfo) {
|
|
414
|
-
var _tokenInfo$
|
|
415
|
-
return ((_tokenInfo$
|
|
434
|
+
var _tokenInfo$metadata8;
|
|
435
|
+
return ((_tokenInfo$metadata8 = tokenInfo.metadata) === null || _tokenInfo$metadata8 === void 0 ? void 0 : _tokenInfo$metadata8.assetId) || '-1';
|
|
416
436
|
}
|
|
417
437
|
function _getXcmAssetMultilocation(tokenInfo) {
|
|
418
|
-
var _tokenInfo$
|
|
419
|
-
return (_tokenInfo$
|
|
438
|
+
var _tokenInfo$metadata9;
|
|
439
|
+
return (_tokenInfo$metadata9 = tokenInfo.metadata) === null || _tokenInfo$metadata9 === void 0 ? void 0 : _tokenInfo$metadata9.multilocation;
|
|
420
440
|
}
|
|
421
441
|
function _getXcmTransferType(originChainInfo, destinationChainInfo) {
|
|
422
442
|
var _originChainInfo$subs, _destinationChainInfo;
|
|
@@ -4,49 +4,68 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.
|
|
7
|
+
exports.getPriceMap = exports.getExchangeRateMap = void 0;
|
|
8
|
+
var _staticData = require("@subwallet/extension-base/utils/staticData");
|
|
8
9
|
var _axios = _interopRequireDefault(require("axios"));
|
|
9
10
|
// Copyright 2019-2022 @subwallet/extension-koni authors & contributors
|
|
10
11
|
// SPDX-License-Identifier: Apache-2.0
|
|
11
12
|
|
|
13
|
+
const DEFAULT_CURRENCY = 'USD';
|
|
12
14
|
let useBackupApi = false;
|
|
13
|
-
const
|
|
14
|
-
let currency = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'usd';
|
|
15
|
+
const getExchangeRateMap = async () => {
|
|
15
16
|
try {
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
res = await _axios.default.get(`https://api.coingecko.com/api/v3/coins/markets?vs_currency=${currency}&per_page=250&ids=${idStr}`);
|
|
22
|
-
} catch (err) {
|
|
23
|
-
useBackupApi = true;
|
|
17
|
+
const responseDataExchangeRate = (await _axios.default.get('https://api-cache.subwallet.app/exchange-rate')).data || {};
|
|
18
|
+
const exchangeRateMap = Object.keys(responseDataExchangeRate.conversion_rates).reduce((map, exchangeKey) => {
|
|
19
|
+
if (!_staticData.staticData[_staticData.StaticKey.CURRENCY_SYMBOL][exchangeKey]) {
|
|
20
|
+
return map;
|
|
24
21
|
}
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
map[exchangeKey] = {
|
|
23
|
+
exchange: responseDataExchangeRate.conversion_rates[exchangeKey],
|
|
24
|
+
label: _staticData.staticData[_staticData.StaticKey.CURRENCY_SYMBOL][exchangeKey].label
|
|
25
|
+
};
|
|
26
|
+
return map;
|
|
27
|
+
}, {});
|
|
28
|
+
return exchangeRateMap;
|
|
29
|
+
} catch (e) {
|
|
30
|
+
console.warn('Failed to get exchange rate');
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
exports.getExchangeRateMap = getExchangeRateMap;
|
|
35
|
+
const getPriceMap = async function (priceIds) {
|
|
36
|
+
var _rs, _rs2, _rs3;
|
|
37
|
+
let currency = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'USD';
|
|
38
|
+
const idStr = Array.from(priceIds).join(',');
|
|
39
|
+
let rs;
|
|
40
|
+
if (!useBackupApi) {
|
|
41
|
+
try {
|
|
42
|
+
rs = await _axios.default.get(`https://api.coingecko.com/api/v3/coins/markets?vs_currency=${currency.toLowerCase()}&per_page=250&ids=${idStr}`);
|
|
43
|
+
} catch (err) {
|
|
27
44
|
useBackupApi = true;
|
|
28
|
-
res = await _axios.default.get(`https://chain-data.subwallet.app/api/price/get?ids=${idStr}`);
|
|
29
45
|
}
|
|
30
|
-
if (res.status !== 200) {
|
|
31
|
-
console.warn('Failed to get token price');
|
|
32
|
-
}
|
|
33
|
-
const responseData = res.data || [];
|
|
34
|
-
const priceMap = {};
|
|
35
|
-
const price24hMap = {};
|
|
36
|
-
responseData.forEach(val => {
|
|
37
|
-
const currentPrice = val.current_price || 0;
|
|
38
|
-
const price24h = currentPrice - (val.price_change_24h || 0);
|
|
39
|
-
priceMap[val.id] = currentPrice;
|
|
40
|
-
price24hMap[val.id] = price24h;
|
|
41
|
-
});
|
|
42
|
-
return {
|
|
43
|
-
currency,
|
|
44
|
-
priceMap,
|
|
45
|
-
price24hMap
|
|
46
|
-
};
|
|
47
|
-
} catch (err) {
|
|
48
|
-
console.error(err);
|
|
49
|
-
throw err;
|
|
50
46
|
}
|
|
47
|
+
if (useBackupApi || ((_rs = rs) === null || _rs === void 0 ? void 0 : _rs.status) !== 200) {
|
|
48
|
+
useBackupApi = true;
|
|
49
|
+
rs = await _axios.default.get(`https://chain-data.subwallet.app/api/price/get?ids=${idStr}`);
|
|
50
|
+
}
|
|
51
|
+
if (((_rs2 = rs) === null || _rs2 === void 0 ? void 0 : _rs2.status) !== 200) {
|
|
52
|
+
console.warn('Failed to get token price');
|
|
53
|
+
}
|
|
54
|
+
const responseDataPrice = ((_rs3 = rs) === null || _rs3 === void 0 ? void 0 : _rs3.data) || [];
|
|
55
|
+
const currencyData = _staticData.staticData[_staticData.StaticKey.CURRENCY_SYMBOL][currency || DEFAULT_CURRENCY];
|
|
56
|
+
const priceMap = {};
|
|
57
|
+
const price24hMap = {};
|
|
58
|
+
responseDataPrice.forEach(val => {
|
|
59
|
+
const currentPrice = val.current_price || 0;
|
|
60
|
+
const price24h = currentPrice - (val.price_change_24h || 0);
|
|
61
|
+
priceMap[val.id] = currentPrice;
|
|
62
|
+
price24hMap[val.id] = price24h;
|
|
63
|
+
});
|
|
64
|
+
return {
|
|
65
|
+
currency,
|
|
66
|
+
currencyData,
|
|
67
|
+
priceMap,
|
|
68
|
+
price24hMap
|
|
69
|
+
};
|
|
51
70
|
};
|
|
52
|
-
exports.
|
|
71
|
+
exports.getPriceMap = getPriceMap;
|
|
@@ -7,27 +7,88 @@ exports.PriceService = void 0;
|
|
|
7
7
|
var _constants = require("@subwallet/extension-base/constants");
|
|
8
8
|
var _types = require("@subwallet/extension-base/services/base/types");
|
|
9
9
|
var _coingecko = require("@subwallet/extension-base/services/price-service/coingecko");
|
|
10
|
+
var _storage = require("@subwallet/extension-base/storage");
|
|
11
|
+
var _utils = require("@subwallet/extension-base/utils");
|
|
10
12
|
var _promise = require("@subwallet/extension-base/utils/promise");
|
|
13
|
+
var _staticData = require("@subwallet/extension-base/utils/staticData");
|
|
11
14
|
var _rxjs = require("rxjs");
|
|
12
15
|
// Copyright 2019-2022 @subwallet/extension-koni authors & contributors
|
|
13
16
|
// SPDX-License-Identifier: Apache-2.0
|
|
14
17
|
|
|
18
|
+
const DEFAULT_CURRENCY = 'USD';
|
|
15
19
|
const DEFAULT_PRICE_SUBJECT = {
|
|
20
|
+
currency: DEFAULT_CURRENCY,
|
|
16
21
|
ready: false,
|
|
17
|
-
|
|
22
|
+
currencyData: {
|
|
23
|
+
label: 'United States Dollar',
|
|
24
|
+
symbol: DEFAULT_CURRENCY,
|
|
25
|
+
isPrefix: true
|
|
26
|
+
},
|
|
18
27
|
priceMap: {},
|
|
19
|
-
price24hMap: {}
|
|
28
|
+
price24hMap: {},
|
|
29
|
+
exchangeRateMap: {}
|
|
20
30
|
};
|
|
21
31
|
class PriceService {
|
|
22
|
-
priceSubject = new _rxjs.BehaviorSubject(DEFAULT_PRICE_SUBJECT);
|
|
23
32
|
priceIds = new Set();
|
|
24
33
|
constructor(dbService, eventService, chainService) {
|
|
34
|
+
const currency = _storage.SWStorage.instance.getItem(_constants.CURRENCY);
|
|
35
|
+
this.currency = new _rxjs.BehaviorSubject(currency || DEFAULT_CURRENCY);
|
|
36
|
+
this.priceSubject = new _rxjs.BehaviorSubject({
|
|
37
|
+
...DEFAULT_PRICE_SUBJECT,
|
|
38
|
+
currency: this.currency.value
|
|
39
|
+
});
|
|
40
|
+
this.rawPriceSubject = new _rxjs.BehaviorSubject({});
|
|
41
|
+
this.rawExchangeRateMap = new _rxjs.BehaviorSubject({});
|
|
25
42
|
this.status = _types.ServiceStatus.NOT_INITIALIZED;
|
|
26
43
|
this.dbService = dbService;
|
|
27
44
|
this.eventService = eventService;
|
|
28
45
|
this.chainService = chainService;
|
|
46
|
+
const mergeDataSubject = (0, _rxjs.merge)(this.rawPriceSubject, this.rawExchangeRateMap, this.currency);
|
|
47
|
+
const onUpdate = () => {
|
|
48
|
+
(0, _utils.addLazy)('updatePriceData', () => {
|
|
49
|
+
const priceSubjectValue = JSON.parse(JSON.stringify(this.rawPriceSubject.value));
|
|
50
|
+
const exchangeRateMapValue = JSON.parse(JSON.stringify(this.rawExchangeRateMap.value));
|
|
51
|
+
const currencyKey = this.currency.value;
|
|
52
|
+
if (Object.keys(priceSubjectValue).length === 0) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (Object.keys(exchangeRateMapValue).length === 0) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (currencyKey === DEFAULT_CURRENCY) {
|
|
59
|
+
this.priceSubject.next({
|
|
60
|
+
...priceSubjectValue,
|
|
61
|
+
currency: currencyKey,
|
|
62
|
+
exchangeRateMap: exchangeRateMapValue,
|
|
63
|
+
currencyData: _staticData.staticData[_staticData.StaticKey.CURRENCY_SYMBOL][currencyKey]
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
Object.keys(priceSubjectValue.price24hMap).forEach(key => {
|
|
67
|
+
priceSubjectValue.price24hMap[key] *= exchangeRateMapValue[currencyKey].exchange;
|
|
68
|
+
priceSubjectValue.priceMap[key] *= exchangeRateMapValue[currencyKey].exchange;
|
|
69
|
+
});
|
|
70
|
+
this.priceSubject.next({
|
|
71
|
+
...priceSubjectValue,
|
|
72
|
+
currency: currencyKey,
|
|
73
|
+
exchangeRateMap: exchangeRateMapValue,
|
|
74
|
+
currencyData: _staticData.staticData[_staticData.StaticKey.CURRENCY_SYMBOL][currencyKey || DEFAULT_CURRENCY]
|
|
75
|
+
});
|
|
76
|
+
this.dbService.updatePriceStore({
|
|
77
|
+
...priceSubjectValue,
|
|
78
|
+
exchangeRateMap: exchangeRateMapValue
|
|
79
|
+
}).catch(console.error);
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
mergeDataSubject.subscribe(onUpdate);
|
|
29
83
|
this.init().catch(console.error);
|
|
30
84
|
}
|
|
85
|
+
async getTokenPrice(priceIds, currency, resolve, reject) {
|
|
86
|
+
await Promise.all([(0, _coingecko.getExchangeRateMap)(), (0, _coingecko.getPriceMap)(priceIds, currency)]).then(_ref => {
|
|
87
|
+
let [exchangeRateMap, priceMap] = _ref;
|
|
88
|
+
this.rawExchangeRateMap.next(exchangeRateMap);
|
|
89
|
+
this.rawPriceSubject.next(priceMap);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
31
92
|
async getPrice() {
|
|
32
93
|
return Promise.resolve(this.priceSubject.value);
|
|
33
94
|
}
|
|
@@ -38,18 +99,28 @@ class PriceService {
|
|
|
38
99
|
const priceIdList = Object.values(this.chainService.getAssetRegistry()).map(a => a.priceId).filter(a => a);
|
|
39
100
|
return new Set(priceIdList);
|
|
40
101
|
}
|
|
41
|
-
|
|
102
|
+
async setPriceCurrency(newCurrencyCode) {
|
|
103
|
+
if (newCurrencyCode === this.currency.value) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
this.currency.next(newCurrencyCode);
|
|
107
|
+
|
|
108
|
+
// Await 1s to get the latest exchange rate
|
|
109
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
110
|
+
_storage.SWStorage.instance.setItem(_constants.CURRENCY, newCurrencyCode);
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
refreshPriceData(priceIds, resolve, reject) {
|
|
42
114
|
clearTimeout(this.refreshTimeout);
|
|
43
115
|
this.priceIds = priceIds || this.getPriceIds();
|
|
44
116
|
|
|
45
117
|
// Update for tokens price
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}).catch(console.error);
|
|
118
|
+
this.getTokenPrice(this.priceIds, this.priceSubject.value.currency).then(() => {
|
|
119
|
+
resolve && resolve(true);
|
|
120
|
+
}).catch(e => {
|
|
121
|
+
console.error(e);
|
|
122
|
+
reject && reject(false);
|
|
123
|
+
});
|
|
53
124
|
this.refreshTimeout = setTimeout(this.refreshPriceData.bind(this), _constants.CRON_REFRESH_PRICE_INTERVAL);
|
|
54
125
|
}
|
|
55
126
|
async init() {
|
|
@@ -69,7 +140,7 @@ class PriceService {
|
|
|
69
140
|
this.eventService.on('asset.updateState', eventHandler);
|
|
70
141
|
}
|
|
71
142
|
async loadData() {
|
|
72
|
-
const data = await this.dbService.getPriceStore();
|
|
143
|
+
const data = await this.dbService.getPriceStore(this.priceSubject.value.currency);
|
|
73
144
|
this.priceSubject.next(data || DEFAULT_PRICE_SUBJECT);
|
|
74
145
|
}
|
|
75
146
|
async persistData() {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.DEFAULT_UNLOCK_TYPE = exports.DEFAULT_THEME = exports.DEFAULT_SHOW_ZERO_BALANCE = exports.DEFAULT_SHOW_BALANCE = exports.DEFAULT_SETTING = exports.DEFAULT_NOTIFICATION_TYPE = exports.DEFAULT_LANGUAGE = exports.DEFAULT_CHAIN_PATROL_ENABLE = exports.DEFAULT_CAMERA_ENABLE = exports.DEFAULT_AUTO_LOCK_TIME = exports.DEFAULT_ALL_LOGO = void 0;
|
|
6
|
+
exports.DEFAULT_UNLOCK_TYPE = exports.DEFAULT_THEME = exports.DEFAULT_SHOW_ZERO_BALANCE = exports.DEFAULT_SHOW_BALANCE = exports.DEFAULT_SETTING = exports.DEFAULT_NOTIFICATION_TYPE = exports.DEFAULT_LANGUAGE = exports.DEFAULT_CURRENCY = exports.DEFAULT_CHAIN_PATROL_ENABLE = exports.DEFAULT_CAMERA_ENABLE = exports.DEFAULT_AUTO_LOCK_TIME = exports.DEFAULT_ALL_LOGO = void 0;
|
|
7
7
|
var _KoniTypes = require("@subwallet/extension-base/background/KoniTypes");
|
|
8
8
|
var _utils = require("@subwallet/extension-base/utils");
|
|
9
9
|
// Copyright 2019-2022 @subwallet/extension-koni authors & contributors
|
|
@@ -21,6 +21,8 @@ const DEFAULT_CHAIN_PATROL_ENABLE = false;
|
|
|
21
21
|
exports.DEFAULT_CHAIN_PATROL_ENABLE = DEFAULT_CHAIN_PATROL_ENABLE;
|
|
22
22
|
const DEFAULT_LANGUAGE = 'en';
|
|
23
23
|
exports.DEFAULT_LANGUAGE = DEFAULT_LANGUAGE;
|
|
24
|
+
const DEFAULT_CURRENCY = 'usd';
|
|
25
|
+
exports.DEFAULT_CURRENCY = DEFAULT_CURRENCY;
|
|
24
26
|
const DEFAULT_SHOW_ZERO_BALANCE = true;
|
|
25
27
|
exports.DEFAULT_SHOW_ZERO_BALANCE = DEFAULT_SHOW_ZERO_BALANCE;
|
|
26
28
|
const DEFAULT_SHOW_BALANCE = false;
|
|
@@ -31,6 +33,7 @@ const DEFAULT_CAMERA_ENABLE = false;
|
|
|
31
33
|
exports.DEFAULT_CAMERA_ENABLE = DEFAULT_CAMERA_ENABLE;
|
|
32
34
|
const DEFAULT_SETTING = {
|
|
33
35
|
language: DEFAULT_LANGUAGE,
|
|
36
|
+
currency: DEFAULT_CURRENCY,
|
|
34
37
|
browserConfirmationType: DEFAULT_NOTIFICATION_TYPE,
|
|
35
38
|
isShowZeroBalance: DEFAULT_SHOW_ZERO_BALANCE,
|
|
36
39
|
isShowBalance: DEFAULT_SHOW_BALANCE,
|
|
@@ -60,10 +60,9 @@ class DatabaseService {
|
|
|
60
60
|
async updatePriceStore(priceData) {
|
|
61
61
|
await this.stores.price.table.put(priceData);
|
|
62
62
|
}
|
|
63
|
-
async getPriceStore() {
|
|
63
|
+
async getPriceStore(keyData) {
|
|
64
64
|
try {
|
|
65
|
-
|
|
66
|
-
return rs;
|
|
65
|
+
return await this.stores.price.table.get(keyData || 'USD');
|
|
67
66
|
} catch (e) {
|
|
68
67
|
this.logger.error(e);
|
|
69
68
|
return undefined;
|
package/cjs/utils/number.js
CHANGED
|
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.toBNString = exports.formatNumber = exports.balanceFormatter = exports.PREDEFINED_FORMATTER = exports.BN_ZERO = exports.BN_WEI = exports.BN_TEN = exports.BN_ONE = void 0;
|
|
7
|
+
exports.toBNString = exports.formatNumber = exports.balanceNoPrefixFormater = exports.balanceFormatter = exports.PREDEFINED_FORMATTER = exports.BN_ZERO = exports.BN_WEI = exports.BN_TEN = exports.BN_ONE = void 0;
|
|
8
8
|
var _bignumber = _interopRequireDefault(require("bignumber.js"));
|
|
9
9
|
// Copyright 2019-2022 @subwallet/extension-koni authors & contributors
|
|
10
10
|
// SPDX-License-Identifier: Apache-2.0
|
|
@@ -102,6 +102,89 @@ const balanceFormatter = (input, metadata) => {
|
|
|
102
102
|
return int;
|
|
103
103
|
};
|
|
104
104
|
exports.balanceFormatter = balanceFormatter;
|
|
105
|
+
const intToLocaleString = (str, separator) => str.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
|
|
106
|
+
const getNumberSeparators = () => {
|
|
107
|
+
// default
|
|
108
|
+
const res = {
|
|
109
|
+
decimal: '.',
|
|
110
|
+
thousand: ''
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// convert a number formatted according to locale
|
|
114
|
+
const str = parseFloat('1234.56').toLocaleString();
|
|
115
|
+
|
|
116
|
+
// if the resulting number does not contain previous number
|
|
117
|
+
// (i.e. in some Arabic formats), return defaults
|
|
118
|
+
if (!str.match('1')) {
|
|
119
|
+
return res;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// get decimal and thousand separators
|
|
123
|
+
res.decimal = str.replace(/.*4(.*)5.*/, '$1');
|
|
124
|
+
res.thousand = str.replace(/.*1(.*)2.*/, '$1');
|
|
125
|
+
|
|
126
|
+
// return results
|
|
127
|
+
return res;
|
|
128
|
+
};
|
|
129
|
+
const balanceNoPrefixFormater = (input, metadata) => {
|
|
130
|
+
const [int, decimal] = input.split('.');
|
|
131
|
+
const {
|
|
132
|
+
thousand: thousandSeparator
|
|
133
|
+
} = getNumberSeparators();
|
|
134
|
+
const absGteOne = new _bignumber.default(input).abs().gte(1);
|
|
135
|
+
const minNumberFormat = (metadata === null || metadata === void 0 ? void 0 : metadata.minNumberFormat) || 2;
|
|
136
|
+
const maxNumberFormat = (metadata === null || metadata === void 0 ? void 0 : metadata.maxNumberFormat) || 6;
|
|
137
|
+
let _decimal = '';
|
|
138
|
+
if (absGteOne) {
|
|
139
|
+
// Get only minNumberFormat number at decimal
|
|
140
|
+
if (decimal.length <= minNumberFormat) {
|
|
141
|
+
_decimal = decimal;
|
|
142
|
+
} else {
|
|
143
|
+
_decimal = decimal.slice(0, minNumberFormat);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Clear zero number for decimal
|
|
147
|
+
_decimal = clearZero(_decimal);
|
|
148
|
+
} else {
|
|
149
|
+
// Index of cursor
|
|
150
|
+
let index = 0;
|
|
151
|
+
|
|
152
|
+
// Count of not zero number in decimal
|
|
153
|
+
let current = 0;
|
|
154
|
+
|
|
155
|
+
// Find a not zero number in decimal
|
|
156
|
+
let metNotZero = false;
|
|
157
|
+
|
|
158
|
+
// Get at least minNumberFormat number not 0 from index 0
|
|
159
|
+
// If count of 0 number at prefix greater or equal maxNumberFormat should stop and return 0
|
|
160
|
+
|
|
161
|
+
// current === minNumberFormat: get enough number
|
|
162
|
+
// index === decimal.length: end of decimal
|
|
163
|
+
// index === maxNumberFormat: reach limit of 0 number at prefix
|
|
164
|
+
if (decimal) {
|
|
165
|
+
while (current < minNumberFormat && index < decimal.length && (index < maxNumberFormat || metNotZero)) {
|
|
166
|
+
const _char = decimal[index];
|
|
167
|
+
_decimal += _char;
|
|
168
|
+
index++;
|
|
169
|
+
if (_char !== '0') {
|
|
170
|
+
metNotZero = true;
|
|
171
|
+
}
|
|
172
|
+
if (metNotZero) {
|
|
173
|
+
current++;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Clear zero number for decimal
|
|
178
|
+
_decimal = clearZero(_decimal);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const int_ = intToLocaleString(int, thousandSeparator);
|
|
182
|
+
if (_decimal) {
|
|
183
|
+
return `${int_}.${_decimal}`;
|
|
184
|
+
}
|
|
185
|
+
return int_;
|
|
186
|
+
};
|
|
187
|
+
exports.balanceNoPrefixFormater = balanceNoPrefixFormater;
|
|
105
188
|
const PREDEFINED_FORMATTER = {
|
|
106
189
|
balance: balanceFormatter
|
|
107
190
|
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.termAndCondition = exports.staticData = exports.marketingCampaigns = exports.crowdloanFunds = exports.buyTokenConfigs = exports.buyServiceInfos = exports.StaticKey = void 0;
|
|
6
|
+
exports.termAndCondition = exports.staticData = exports.marketingCampaigns = exports.currencySymbol = exports.crowdloanFunds = exports.buyTokenConfigs = exports.buyServiceInfos = exports.StaticKey = void 0;
|
|
7
7
|
var _chainList = require("@subwallet/chain-list");
|
|
8
8
|
// Copyright 2019-2022 @subwallet/extension-base authors & contributors
|
|
9
9
|
// SPDX-License-Identifier: Apache-2.0
|
|
@@ -24,12 +24,16 @@ const marketingCampaigns = require('./marketingCampaigns.json');
|
|
|
24
24
|
// eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-unsafe-assignment
|
|
25
25
|
exports.marketingCampaigns = marketingCampaigns;
|
|
26
26
|
const termAndCondition = require('./termAndCondition.json');
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-unsafe-assignment
|
|
27
28
|
exports.termAndCondition = termAndCondition;
|
|
29
|
+
const currencySymbol = require('./currencySymbol.json');
|
|
30
|
+
exports.currencySymbol = currencySymbol;
|
|
28
31
|
let StaticKey;
|
|
29
32
|
exports.StaticKey = StaticKey;
|
|
30
33
|
(function (StaticKey) {
|
|
31
34
|
StaticKey["BUY_SERVICE_INFOS"] = "buy-service-infos";
|
|
32
35
|
StaticKey["CHAINS"] = "chains";
|
|
36
|
+
StaticKey["CURRENCY_SYMBOL"] = "currency_symbols";
|
|
33
37
|
StaticKey["MARKETING_CAMPAINGS"] = "marketing-campaigns";
|
|
34
38
|
StaticKey["CROWDLOAN_FUNDS"] = "crowdloan-funds";
|
|
35
39
|
StaticKey["TERM_AND_CONDITION"] = "term-and-condition";
|
|
@@ -37,6 +41,7 @@ exports.StaticKey = StaticKey;
|
|
|
37
41
|
})(StaticKey || (exports.StaticKey = StaticKey = {}));
|
|
38
42
|
const staticData = {
|
|
39
43
|
[StaticKey.CHAINS]: Object.values(_chainList.ChainInfoMap),
|
|
44
|
+
[StaticKey.CURRENCY_SYMBOL]: currencySymbol,
|
|
40
45
|
[StaticKey.BUY_SERVICE_INFOS]: buyServiceInfos,
|
|
41
46
|
[StaticKey.CROWDLOAN_FUNDS]: crowdloanFunds,
|
|
42
47
|
[StaticKey.MARKETING_CAMPAINGS]: marketingCampaigns,
|
package/constants/staking.js
CHANGED
package/constants/storage.d.ts
CHANGED
package/constants/storage.js
CHANGED
package/koni/api/coingecko.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { PriceJson } from '@subwallet/extension-base/background/KoniTypes';
|
|
2
|
-
export declare const getTokenPrice: (priceIds:
|
|
1
|
+
import { CurrencyType, PriceJson } from '@subwallet/extension-base/background/KoniTypes';
|
|
2
|
+
export declare const getTokenPrice: (priceIds: Set<string>, currencyCode?: CurrencyType) => Promise<PriceJson>;
|
package/koni/api/coingecko.js
CHANGED
|
@@ -1,29 +1,72 @@
|
|
|
1
1
|
// Copyright 2019-2022 @subwallet/extension-koni authors & contributors
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
+
import { staticData, StaticKey } from '@subwallet/extension-base/utils/staticData';
|
|
4
5
|
import axios from 'axios';
|
|
5
|
-
|
|
6
|
+
let useBackupApi = false;
|
|
7
|
+
export const getTokenPrice = async (priceIds, currencyCode = 'USD') => {
|
|
6
8
|
try {
|
|
7
|
-
|
|
8
|
-
const idStr = priceIds.join(',');
|
|
9
|
-
const
|
|
10
|
-
|
|
9
|
+
var _resMultiPromise$, _resMultiPromise$2;
|
|
10
|
+
const idStr = Array.from(priceIds).join(',');
|
|
11
|
+
const getPriceMap = async () => {
|
|
12
|
+
var _rs, _rs2;
|
|
13
|
+
let rs;
|
|
14
|
+
if (!useBackupApi) {
|
|
15
|
+
try {
|
|
16
|
+
rs = await axios.get(`https://api.coingecko.com/api/v3/coins/markets?vs_currency=${currencyCode.toLowerCase()}&per_page=250&ids=${idStr}`);
|
|
17
|
+
} catch (err) {
|
|
18
|
+
useBackupApi = true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (useBackupApi || ((_rs = rs) === null || _rs === void 0 ? void 0 : _rs.status) !== 200) {
|
|
22
|
+
useBackupApi = true;
|
|
23
|
+
rs = await axios.get(`https://chain-data.subwallet.app/api/price/get?ids=${idStr}`);
|
|
24
|
+
}
|
|
25
|
+
if (((_rs2 = rs) === null || _rs2 === void 0 ? void 0 : _rs2.status) !== 200) {
|
|
26
|
+
console.warn('Failed to get token price');
|
|
27
|
+
}
|
|
28
|
+
return rs;
|
|
29
|
+
};
|
|
30
|
+
const getExchangeRate = async () => {
|
|
31
|
+
var _rs3;
|
|
32
|
+
let rs;
|
|
33
|
+
try {
|
|
34
|
+
rs = await axios.get('https://api-cache.subwallet.app/exchange-rate');
|
|
35
|
+
} catch (e) {
|
|
36
|
+
console.warn('Failed to get exchange rate');
|
|
37
|
+
}
|
|
38
|
+
if (((_rs3 = rs) === null || _rs3 === void 0 ? void 0 : _rs3.status) !== 200) {
|
|
39
|
+
console.warn('Failed to get exchange rate');
|
|
40
|
+
}
|
|
41
|
+
return rs;
|
|
42
|
+
};
|
|
43
|
+
const resMultiPromise = await Promise.all([getPriceMap(), getExchangeRate()]);
|
|
44
|
+
const responseDataPrice = ((_resMultiPromise$ = resMultiPromise[0]) === null || _resMultiPromise$ === void 0 ? void 0 : _resMultiPromise$.data) || [];
|
|
45
|
+
const responseDataExchangeRate = ((_resMultiPromise$2 = resMultiPromise[1]) === null || _resMultiPromise$2 === void 0 ? void 0 : _resMultiPromise$2.data) || {};
|
|
11
46
|
const priceMap = {};
|
|
12
47
|
const price24hMap = {};
|
|
13
|
-
|
|
48
|
+
const exchangeRateMap = Object.keys(responseDataExchangeRate.conversion_rates).reduce((map, exchangeKey) => {
|
|
49
|
+
if (!staticData[StaticKey.CURRENCY_SYMBOL][exchangeKey]) {
|
|
50
|
+
return map;
|
|
51
|
+
}
|
|
52
|
+
map[exchangeKey] = {
|
|
53
|
+
exchange: responseDataExchangeRate.conversion_rates[exchangeKey],
|
|
54
|
+
label: staticData[StaticKey.CURRENCY_SYMBOL][exchangeKey].label
|
|
55
|
+
};
|
|
56
|
+
return map;
|
|
57
|
+
}, {});
|
|
58
|
+
const currencyData = staticData[StaticKey.CURRENCY_SYMBOL][currencyCode];
|
|
59
|
+
responseDataPrice.forEach(val => {
|
|
14
60
|
const currentPrice = val.current_price || 0;
|
|
15
61
|
const price24h = currentPrice - (val.price_change_24h || 0);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// if (inverseMap[val.id]) {
|
|
20
|
-
// priceMap[inverseMap[val.id]] = currentPrice;
|
|
21
|
-
// price24hMap[inverseMap[val.id]] = price24h;
|
|
22
|
-
// }
|
|
62
|
+
const exchangeRate = exchangeRateMap[currencyCode] || 1;
|
|
63
|
+
priceMap[val.id] = currentPrice * exchangeRate.exchange;
|
|
64
|
+
price24hMap[val.id] = price24h * exchangeRate.exchange;
|
|
23
65
|
});
|
|
24
|
-
|
|
25
66
|
return {
|
|
26
|
-
currency,
|
|
67
|
+
currency: currencyCode,
|
|
68
|
+
currencyData,
|
|
69
|
+
exchangeRateMap,
|
|
27
70
|
priceMap,
|
|
28
71
|
price24hMap
|
|
29
72
|
};
|