@subwallet/extension-base 1.1.58-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.
Files changed (54) hide show
  1. package/background/KoniTypes.d.ts +18 -1
  2. package/cjs/constants/staking.js +2 -1
  3. package/cjs/constants/storage.js +4 -2
  4. package/cjs/koni/api/coingecko.js +58 -15
  5. package/cjs/koni/api/nft/config.js +27 -21
  6. package/cjs/koni/api/staking/bonding/utils.js +7 -3
  7. package/cjs/koni/background/handlers/Extension.js +130 -122
  8. package/cjs/packageInfo.js +1 -1
  9. package/cjs/services/balance-service/helpers/subscribe/substrate/index.js +7 -1
  10. package/cjs/services/chain-service/constants.js +4 -2
  11. package/cjs/services/chain-service/index.js +6 -1
  12. package/cjs/services/chain-service/utils/index.js +34 -14
  13. package/cjs/services/earning-service/constants/chains.js +2 -2
  14. package/cjs/services/earning-service/handlers/native-staking/relay-chain.js +4 -4
  15. package/cjs/services/earning-service/handlers/nomination-pool/index.js +2 -2
  16. package/cjs/services/price-service/coingecko.js +54 -35
  17. package/cjs/services/price-service/index.js +83 -12
  18. package/cjs/services/setting-service/constants.js +4 -1
  19. package/cjs/services/storage-service/DatabaseService.js +2 -3
  20. package/cjs/utils/number.js +84 -1
  21. package/cjs/utils/staticData/index.js +6 -1
  22. package/constants/staking.js +2 -1
  23. package/constants/storage.d.ts +1 -0
  24. package/constants/storage.js +2 -1
  25. package/koni/api/coingecko.d.ts +2 -2
  26. package/koni/api/coingecko.js +58 -15
  27. package/koni/api/nft/config.js +28 -20
  28. package/koni/api/staking/bonding/utils.d.ts +1 -1
  29. package/koni/api/staking/bonding/utils.js +7 -3
  30. package/koni/background/handlers/Extension.d.ts +1 -0
  31. package/koni/background/handlers/Extension.js +7 -0
  32. package/package.json +7 -6
  33. package/packageInfo.js +1 -1
  34. package/services/balance-service/helpers/subscribe/substrate/index.js +8 -2
  35. package/services/chain-service/constants.js +4 -2
  36. package/services/chain-service/index.js +6 -1
  37. package/services/chain-service/utils/index.d.ts +13 -0
  38. package/services/chain-service/utils/index.js +32 -14
  39. package/services/earning-service/constants/chains.js +2 -2
  40. package/services/earning-service/handlers/native-staking/relay-chain.js +4 -4
  41. package/services/earning-service/handlers/nomination-pool/index.js +2 -2
  42. package/services/price-service/coingecko.d.ts +3 -2
  43. package/services/price-service/coingecko.js +50 -32
  44. package/services/price-service/index.d.ts +7 -2
  45. package/services/price-service/index.js +85 -15
  46. package/services/setting-service/constants.d.ts +1 -0
  47. package/services/setting-service/constants.js +2 -0
  48. package/services/storage-service/DatabaseService.d.ts +1 -1
  49. package/services/storage-service/DatabaseService.js +2 -3
  50. package/utils/number.d.ts +1 -0
  51. package/utils/number.js +82 -0
  52. package/utils/staticData/currencySymbol.json +11 -0
  53. package/utils/staticData/index.d.ts +3 -0
  54. package/utils/staticData/index.js +4 -0
@@ -1,27 +1,87 @@
1
1
  // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
- import { CRON_REFRESH_PRICE_INTERVAL } from '@subwallet/extension-base/constants';
4
+ import { CRON_REFRESH_PRICE_INTERVAL, CURRENCY } from '@subwallet/extension-base/constants';
5
5
  import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
6
- import { getTokenPrice } from '@subwallet/extension-base/services/price-service/coingecko';
6
+ import { getExchangeRateMap, getPriceMap } from '@subwallet/extension-base/services/price-service/coingecko';
7
+ import { SWStorage } from '@subwallet/extension-base/storage';
8
+ import { addLazy } from '@subwallet/extension-base/utils';
7
9
  import { createPromiseHandler } from '@subwallet/extension-base/utils/promise';
8
- import { BehaviorSubject } from 'rxjs';
10
+ import { staticData, StaticKey } from '@subwallet/extension-base/utils/staticData';
11
+ import { BehaviorSubject, merge } from 'rxjs';
12
+ const DEFAULT_CURRENCY = 'USD';
9
13
  const DEFAULT_PRICE_SUBJECT = {
14
+ currency: DEFAULT_CURRENCY,
10
15
  ready: false,
11
- currency: 'usd',
16
+ currencyData: {
17
+ label: 'United States Dollar',
18
+ symbol: DEFAULT_CURRENCY,
19
+ isPrefix: true
20
+ },
12
21
  priceMap: {},
13
- price24hMap: {}
22
+ price24hMap: {},
23
+ exchangeRateMap: {}
14
24
  };
15
25
  export class PriceService {
16
- priceSubject = new BehaviorSubject(DEFAULT_PRICE_SUBJECT);
17
26
  priceIds = new Set();
18
27
  constructor(dbService, eventService, chainService) {
28
+ const currency = SWStorage.instance.getItem(CURRENCY);
29
+ this.currency = new BehaviorSubject(currency || DEFAULT_CURRENCY);
30
+ this.priceSubject = new BehaviorSubject({
31
+ ...DEFAULT_PRICE_SUBJECT,
32
+ currency: this.currency.value
33
+ });
34
+ this.rawPriceSubject = new BehaviorSubject({});
35
+ this.rawExchangeRateMap = new BehaviorSubject({});
19
36
  this.status = ServiceStatus.NOT_INITIALIZED;
20
37
  this.dbService = dbService;
21
38
  this.eventService = eventService;
22
39
  this.chainService = chainService;
40
+ const mergeDataSubject = merge(this.rawPriceSubject, this.rawExchangeRateMap, this.currency);
41
+ const onUpdate = () => {
42
+ addLazy('updatePriceData', () => {
43
+ const priceSubjectValue = JSON.parse(JSON.stringify(this.rawPriceSubject.value));
44
+ const exchangeRateMapValue = JSON.parse(JSON.stringify(this.rawExchangeRateMap.value));
45
+ const currencyKey = this.currency.value;
46
+ if (Object.keys(priceSubjectValue).length === 0) {
47
+ return;
48
+ }
49
+ if (Object.keys(exchangeRateMapValue).length === 0) {
50
+ return;
51
+ }
52
+ if (currencyKey === DEFAULT_CURRENCY) {
53
+ this.priceSubject.next({
54
+ ...priceSubjectValue,
55
+ currency: currencyKey,
56
+ exchangeRateMap: exchangeRateMapValue,
57
+ currencyData: staticData[StaticKey.CURRENCY_SYMBOL][currencyKey]
58
+ });
59
+ }
60
+ Object.keys(priceSubjectValue.price24hMap).forEach(key => {
61
+ priceSubjectValue.price24hMap[key] *= exchangeRateMapValue[currencyKey].exchange;
62
+ priceSubjectValue.priceMap[key] *= exchangeRateMapValue[currencyKey].exchange;
63
+ });
64
+ this.priceSubject.next({
65
+ ...priceSubjectValue,
66
+ currency: currencyKey,
67
+ exchangeRateMap: exchangeRateMapValue,
68
+ currencyData: staticData[StaticKey.CURRENCY_SYMBOL][currencyKey || DEFAULT_CURRENCY]
69
+ });
70
+ this.dbService.updatePriceStore({
71
+ ...priceSubjectValue,
72
+ exchangeRateMap: exchangeRateMapValue
73
+ }).catch(console.error);
74
+ });
75
+ };
76
+ mergeDataSubject.subscribe(onUpdate);
23
77
  this.init().catch(console.error);
24
78
  }
79
+ async getTokenPrice(priceIds, currency, resolve, reject) {
80
+ await Promise.all([getExchangeRateMap(), getPriceMap(priceIds, currency)]).then(([exchangeRateMap, priceMap]) => {
81
+ this.rawExchangeRateMap.next(exchangeRateMap);
82
+ this.rawPriceSubject.next(priceMap);
83
+ });
84
+ }
25
85
  async getPrice() {
26
86
  return Promise.resolve(this.priceSubject.value);
27
87
  }
@@ -32,18 +92,28 @@ export class PriceService {
32
92
  const priceIdList = Object.values(this.chainService.getAssetRegistry()).map(a => a.priceId).filter(a => a);
33
93
  return new Set(priceIdList);
34
94
  }
35
- refreshPriceData(priceIds) {
95
+ async setPriceCurrency(newCurrencyCode) {
96
+ if (newCurrencyCode === this.currency.value) {
97
+ return false;
98
+ }
99
+ this.currency.next(newCurrencyCode);
100
+
101
+ // Await 1s to get the latest exchange rate
102
+ await new Promise(resolve => setTimeout(resolve, 300));
103
+ SWStorage.instance.setItem(CURRENCY, newCurrencyCode);
104
+ return true;
105
+ }
106
+ refreshPriceData(priceIds, resolve, reject) {
36
107
  clearTimeout(this.refreshTimeout);
37
108
  this.priceIds = priceIds || this.getPriceIds();
38
109
 
39
110
  // Update for tokens price
40
- getTokenPrice(this.priceIds).then(rs => {
41
- this.priceSubject.next({
42
- ...rs,
43
- ready: true
44
- });
45
- this.dbService.updatePriceStore(rs).catch(console.error);
46
- }).catch(console.error);
111
+ this.getTokenPrice(this.priceIds, this.priceSubject.value.currency).then(() => {
112
+ resolve && resolve(true);
113
+ }).catch(e => {
114
+ console.error(e);
115
+ reject && reject(false);
116
+ });
47
117
  this.refreshTimeout = setTimeout(this.refreshPriceData.bind(this), CRON_REFRESH_PRICE_INTERVAL);
48
118
  }
49
119
  async init() {
@@ -63,7 +133,7 @@ export class PriceService {
63
133
  this.eventService.on('asset.updateState', eventHandler);
64
134
  }
65
135
  async loadData() {
66
- const data = await this.dbService.getPriceStore();
136
+ const data = await this.dbService.getPriceStore(this.priceSubject.value.currency);
67
137
  this.priceSubject.next(data || DEFAULT_PRICE_SUBJECT);
68
138
  }
69
139
  async persistData() {
@@ -5,6 +5,7 @@ export declare const DEFAULT_AUTO_LOCK_TIME = 15;
5
5
  export declare const DEFAULT_UNLOCK_TYPE: WalletUnlockType;
6
6
  export declare const DEFAULT_CHAIN_PATROL_ENABLE = false;
7
7
  export declare const DEFAULT_LANGUAGE: LanguageType;
8
+ export declare const DEFAULT_CURRENCY = "usd";
8
9
  export declare const DEFAULT_SHOW_ZERO_BALANCE = true;
9
10
  export declare const DEFAULT_SHOW_BALANCE = false;
10
11
  export declare const DEFAULT_ALL_LOGO = "";
@@ -9,12 +9,14 @@ export const DEFAULT_AUTO_LOCK_TIME = 15;
9
9
  export const DEFAULT_UNLOCK_TYPE = TARGET_ENV === 'extension' ? WalletUnlockType.ALWAYS_REQUIRED : WalletUnlockType.WHEN_NEEDED;
10
10
  export const DEFAULT_CHAIN_PATROL_ENABLE = false;
11
11
  export const DEFAULT_LANGUAGE = 'en';
12
+ export const DEFAULT_CURRENCY = 'usd';
12
13
  export const DEFAULT_SHOW_ZERO_BALANCE = true;
13
14
  export const DEFAULT_SHOW_BALANCE = false;
14
15
  export const DEFAULT_ALL_LOGO = '';
15
16
  export const DEFAULT_CAMERA_ENABLE = false;
16
17
  export const DEFAULT_SETTING = {
17
18
  language: DEFAULT_LANGUAGE,
19
+ currency: DEFAULT_CURRENCY,
18
20
  browserConfirmationType: DEFAULT_NOTIFICATION_TYPE,
19
21
  isShowZeroBalance: DEFAULT_SHOW_ZERO_BALANCE,
20
22
  isShowBalance: DEFAULT_SHOW_BALANCE,
@@ -42,7 +42,7 @@ export default class DatabaseService {
42
42
  private yieldInfoSubscription;
43
43
  constructor(eventService: EventService);
44
44
  updatePriceStore(priceData: PriceJson): Promise<void>;
45
- getPriceStore(): Promise<PriceJson | undefined>;
45
+ getPriceStore(keyData?: string): Promise<PriceJson | undefined>;
46
46
  getStoredBalance(): Promise<IBalance[]>;
47
47
  updateBalanceStore(item: BalanceItem): Promise<unknown>;
48
48
  updateBulkBalanceStore(items: BalanceItem[]): Promise<unknown>;
@@ -52,10 +52,9 @@ export default class DatabaseService {
52
52
  async updatePriceStore(priceData) {
53
53
  await this.stores.price.table.put(priceData);
54
54
  }
55
- async getPriceStore() {
55
+ async getPriceStore(keyData) {
56
56
  try {
57
- const rs = await this.stores.price.table.get('usd');
58
- return rs;
57
+ return await this.stores.price.table.get(keyData || 'USD');
59
58
  } catch (e) {
60
59
  this.logger.error(e);
61
60
  return undefined;
package/utils/number.d.ts CHANGED
@@ -7,6 +7,7 @@ export interface NumberFormatter {
7
7
  (input: string, metadata?: Record<string, number>): string;
8
8
  }
9
9
  export declare const balanceFormatter: NumberFormatter;
10
+ export declare const balanceNoPrefixFormater: NumberFormatter;
10
11
  export declare const PREDEFINED_FORMATTER: Record<string, NumberFormatter>;
11
12
  export declare const toBNString: (input: string | number | BigNumber, decimal: number) => string;
12
13
  export declare const formatNumber: (input: string | number | BigNumber, decimal: number, formatter?: NumberFormatter, metadata?: Record<string, number>) => string;
package/utils/number.js CHANGED
@@ -90,6 +90,88 @@ export const balanceFormatter = (input, metadata) => {
90
90
  }
91
91
  return int;
92
92
  };
93
+ const intToLocaleString = (str, separator) => str.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
94
+ const getNumberSeparators = () => {
95
+ // default
96
+ const res = {
97
+ decimal: '.',
98
+ thousand: ''
99
+ };
100
+
101
+ // convert a number formatted according to locale
102
+ const str = parseFloat('1234.56').toLocaleString();
103
+
104
+ // if the resulting number does not contain previous number
105
+ // (i.e. in some Arabic formats), return defaults
106
+ if (!str.match('1')) {
107
+ return res;
108
+ }
109
+
110
+ // get decimal and thousand separators
111
+ res.decimal = str.replace(/.*4(.*)5.*/, '$1');
112
+ res.thousand = str.replace(/.*1(.*)2.*/, '$1');
113
+
114
+ // return results
115
+ return res;
116
+ };
117
+ export const balanceNoPrefixFormater = (input, metadata) => {
118
+ const [int, decimal] = input.split('.');
119
+ const {
120
+ thousand: thousandSeparator
121
+ } = getNumberSeparators();
122
+ const absGteOne = new BigNumber(input).abs().gte(1);
123
+ const minNumberFormat = (metadata === null || metadata === void 0 ? void 0 : metadata.minNumberFormat) || 2;
124
+ const maxNumberFormat = (metadata === null || metadata === void 0 ? void 0 : metadata.maxNumberFormat) || 6;
125
+ let _decimal = '';
126
+ if (absGteOne) {
127
+ // Get only minNumberFormat number at decimal
128
+ if (decimal.length <= minNumberFormat) {
129
+ _decimal = decimal;
130
+ } else {
131
+ _decimal = decimal.slice(0, minNumberFormat);
132
+ }
133
+
134
+ // Clear zero number for decimal
135
+ _decimal = clearZero(_decimal);
136
+ } else {
137
+ // Index of cursor
138
+ let index = 0;
139
+
140
+ // Count of not zero number in decimal
141
+ let current = 0;
142
+
143
+ // Find a not zero number in decimal
144
+ let metNotZero = false;
145
+
146
+ // Get at least minNumberFormat number not 0 from index 0
147
+ // If count of 0 number at prefix greater or equal maxNumberFormat should stop and return 0
148
+
149
+ // current === minNumberFormat: get enough number
150
+ // index === decimal.length: end of decimal
151
+ // index === maxNumberFormat: reach limit of 0 number at prefix
152
+ if (decimal) {
153
+ while (current < minNumberFormat && index < decimal.length && (index < maxNumberFormat || metNotZero)) {
154
+ const _char = decimal[index];
155
+ _decimal += _char;
156
+ index++;
157
+ if (_char !== '0') {
158
+ metNotZero = true;
159
+ }
160
+ if (metNotZero) {
161
+ current++;
162
+ }
163
+ }
164
+
165
+ // Clear zero number for decimal
166
+ _decimal = clearZero(_decimal);
167
+ }
168
+ }
169
+ const int_ = intToLocaleString(int, thousandSeparator);
170
+ if (_decimal) {
171
+ return `${int_}.${_decimal}`;
172
+ }
173
+ return int_;
174
+ };
93
175
  export const PREDEFINED_FORMATTER = {
94
176
  balance: balanceFormatter
95
177
  };
@@ -0,0 +1,11 @@
1
+ {
2
+ "USD": {"label": "United States Dollar", "symbol": "USD", "isPrefix": false},
3
+ "BRL": {"label": "Brazilian Real", "symbol": "BRL", "isPrefix": false},
4
+ "CNY": {"label": "Chinese Yuan", "symbol": "CNY", "isPrefix": false},
5
+ "EUR": {"label": "Euro", "symbol": "EUR", "isPrefix": false},
6
+ "GBP": {"label": "British Pound Sterling", "symbol": "GBP", "isPrefix": false},
7
+ "HKD": {"label": "Hong Kong Dollar", "symbol": "HKD", "isPrefix": false},
8
+ "JPY": {"label": "Japanese Yen", "symbol": "JPY", "isPrefix": false},
9
+ "RUB": {"label": "Russian Ruble", "symbol": "RUB", "isPrefix": false},
10
+ "VND": {"label": "Vietnamese Dong", "symbol": "VND", "isPrefix": false}
11
+ }
@@ -3,9 +3,11 @@ export declare const buyTokenConfigs: Record<string, unknown>[];
3
3
  export declare const crowdloanFunds: Record<string, unknown>[];
4
4
  export declare const marketingCampaigns: Record<string, unknown>;
5
5
  export declare const termAndCondition: Record<string, unknown>;
6
+ export declare const currencySymbol: Record<string, unknown>;
6
7
  export declare enum StaticKey {
7
8
  BUY_SERVICE_INFOS = "buy-service-infos",
8
9
  CHAINS = "chains",
10
+ CURRENCY_SYMBOL = "currency_symbols",
9
11
  MARKETING_CAMPAINGS = "marketing-campaigns",
10
12
  CROWDLOAN_FUNDS = "crowdloan-funds",
11
13
  TERM_AND_CONDITION = "term-and-condition",
@@ -13,6 +15,7 @@ export declare enum StaticKey {
13
15
  }
14
16
  export declare const staticData: {
15
17
  chains: import("@subwallet/chain-list/types")._ChainInfo[];
18
+ currency_symbols: Record<string, unknown>;
16
19
  "buy-service-infos": Record<string, unknown>[];
17
20
  "crowdloan-funds": Record<string, unknown>[];
18
21
  "marketing-campaigns": Record<string, unknown>;
@@ -14,10 +14,13 @@ export const crowdloanFunds = require("./crowdloanFunds.json");
14
14
  export const marketingCampaigns = require("./marketingCampaigns.json");
15
15
  // eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-unsafe-assignment
16
16
  export const termAndCondition = require("./termAndCondition.json");
17
+ // eslint-disable-next-line @typescript-eslint/no-var-requires,@typescript-eslint/no-unsafe-assignment
18
+ export const currencySymbol = require("./currencySymbol.json");
17
19
  export let StaticKey;
18
20
  (function (StaticKey) {
19
21
  StaticKey["BUY_SERVICE_INFOS"] = "buy-service-infos";
20
22
  StaticKey["CHAINS"] = "chains";
23
+ StaticKey["CURRENCY_SYMBOL"] = "currency_symbols";
21
24
  StaticKey["MARKETING_CAMPAINGS"] = "marketing-campaigns";
22
25
  StaticKey["CROWDLOAN_FUNDS"] = "crowdloan-funds";
23
26
  StaticKey["TERM_AND_CONDITION"] = "term-and-condition";
@@ -25,6 +28,7 @@ export let StaticKey;
25
28
  })(StaticKey || (StaticKey = {}));
26
29
  export const staticData = {
27
30
  [StaticKey.CHAINS]: Object.values(ChainInfoMap),
31
+ [StaticKey.CURRENCY_SYMBOL]: currencySymbol,
28
32
  [StaticKey.BUY_SERVICE_INFOS]: buyServiceInfos,
29
33
  [StaticKey.CROWDLOAN_FUNDS]: crowdloanFunds,
30
34
  [StaticKey.MARKETING_CAMPAINGS]: marketingCampaigns,