@subwallet/extension-base 1.0.2-2 → 1.0.3-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 +56 -40
- package/background/KoniTypes.js +11 -9
- package/background/errors/TransactionError.js +25 -1
- package/background/types.d.ts +10 -5
- package/cjs/background/KoniTypes.js +11 -9
- package/cjs/background/errors/TransactionError.js +24 -0
- package/cjs/constants/index.js +8 -26
- package/cjs/koni/api/dotsama/balance.js +49 -224
- package/cjs/koni/api/dotsama/transfer.js +34 -39
- package/cjs/koni/api/nft/acala_nft/index.js +7 -7
- package/cjs/koni/api/nft/bit.country/index.js +7 -6
- package/cjs/koni/api/nft/evm_nft/index.js +8 -3
- package/cjs/koni/api/nft/index.js +3 -6
- package/cjs/koni/api/nft/karura_nft/index.js +7 -6
- package/cjs/koni/api/nft/rmrk_nft/index.js +11 -1
- package/cjs/koni/api/nft/statemine_nft/index.js +7 -6
- package/cjs/koni/api/nft/unique_nft/index.js +5 -1
- package/cjs/koni/api/nft/wasm_nft/index.js +170 -111
- package/cjs/koni/api/nft/wasm_nft/utils.js +11 -7
- package/cjs/koni/api/staking/bonding/amplitude.js +13 -9
- package/cjs/koni/api/staking/bonding/astar.js +15 -13
- package/cjs/koni/api/staking/bonding/index.js +22 -10
- package/cjs/koni/api/staking/bonding/paraChain.js +85 -2
- package/cjs/koni/api/staking/bonding/relayChain.js +122 -16
- package/cjs/koni/api/staking/bonding/utils.js +27 -8
- package/cjs/koni/api/tokens/wasm/index.js +5 -4
- package/cjs/koni/api/tokens/wasm/utils.js +63 -0
- package/cjs/koni/api/xcm/polkadotXcm.js +1 -1
- package/cjs/koni/api/xcm/utils.js +18 -13
- package/cjs/koni/api/xcm/xTokens.js +1 -1
- package/cjs/koni/api/xcm/xcmPallet.js +9 -6
- package/cjs/koni/background/cron.js +171 -61
- package/cjs/koni/background/handlers/Extension.js +391 -207
- package/cjs/koni/background/handlers/State.js +49 -34
- package/cjs/koni/background/handlers/Tabs.js +50 -17
- package/cjs/koni/background/subscription.js +53 -28
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/base/types.js +20 -0
- package/cjs/services/chain-service/handler/SubstrateChainHandler.js +13 -8
- package/cjs/services/chain-service/index.js +73 -49
- package/cjs/services/event-service/index.js +5 -1
- package/cjs/services/event-service/types.js +11 -1
- package/cjs/services/history-service/index.js +101 -50
- package/cjs/services/history-service/subsquid-multi-chain-history.js +13 -10
- package/cjs/services/keyring-service/index.js +11 -13
- package/cjs/services/migration-service/scripts/MigrateImportedToken.js +2 -1
- package/cjs/services/price-service/coingecko.js +0 -1
- package/cjs/services/price-service/index.js +71 -24
- package/cjs/services/request-service/handler/AuthRequestHandler.js +13 -7
- package/cjs/services/request-service/handler/EvmRequestHandler.js +8 -12
- package/cjs/services/request-service/index.js +14 -5
- package/cjs/services/storage-service/DatabaseService.js +66 -34
- package/cjs/services/storage-service/db-stores/Nft.js +7 -15
- package/cjs/services/storage-service/db-stores/Transaction.js +6 -10
- package/cjs/services/transaction-service/event-parser/index.js +20 -48
- package/cjs/services/transaction-service/index.js +104 -48
- package/cjs/services/transaction-service/utils.js +10 -8
- package/cjs/utils/address.js +10 -1
- package/cjs/utils/index.js +9 -15
- package/cjs/utils/promise.js +26 -0
- package/constants/index.d.ts +7 -13
- package/constants/index.js +7 -13
- package/koni/api/dotsama/balance.d.ts +0 -1
- package/koni/api/dotsama/balance.js +22 -197
- package/koni/api/dotsama/transfer.js +11 -16
- package/koni/api/nft/acala_nft/index.js +7 -7
- package/koni/api/nft/bit.country/index.js +7 -6
- package/koni/api/nft/evm_nft/index.js +7 -3
- package/koni/api/nft/index.d.ts +1 -2
- package/koni/api/nft/index.js +3 -6
- package/koni/api/nft/karura_nft/index.js +7 -6
- package/koni/api/nft/nft.d.ts +1 -0
- package/koni/api/nft/rmrk_nft/index.js +11 -1
- package/koni/api/nft/statemine_nft/index.js +7 -6
- package/koni/api/nft/unique_nft/index.js +5 -1
- package/koni/api/nft/wasm_nft/index.d.ts +0 -2
- package/koni/api/nft/wasm_nft/index.js +168 -109
- package/koni/api/nft/wasm_nft/utils.d.ts +7 -5
- package/koni/api/nft/wasm_nft/utils.js +7 -5
- package/koni/api/staking/bonding/amplitude.d.ts +0 -1
- package/koni/api/staking/bonding/amplitude.js +15 -10
- package/koni/api/staking/bonding/astar.js +8 -6
- package/koni/api/staking/bonding/index.d.ts +4 -1
- package/koni/api/staking/bonding/index.js +23 -13
- package/koni/api/staking/bonding/paraChain.d.ts +3 -0
- package/koni/api/staking/bonding/paraChain.js +86 -5
- package/koni/api/staking/bonding/relayChain.d.ts +5 -1
- package/koni/api/staking/bonding/relayChain.js +121 -18
- package/koni/api/staking/bonding/utils.d.ts +3 -2
- package/koni/api/staking/bonding/utils.js +27 -9
- package/koni/api/tokens/wasm/index.js +5 -4
- package/koni/api/tokens/wasm/utils.d.ts +6 -0
- package/koni/api/tokens/wasm/utils.js +54 -0
- package/koni/api/xcm/polkadotXcm.js +2 -2
- package/koni/api/xcm/utils.d.ts +5 -6
- package/koni/api/xcm/utils.js +15 -10
- package/koni/api/xcm/xTokens.js +2 -2
- package/koni/api/xcm/xcmPallet.js +10 -9
- package/koni/background/cron.d.ts +6 -1
- package/koni/background/cron.js +172 -62
- package/koni/background/handlers/Extension.d.ts +9 -3
- package/koni/background/handlers/Extension.js +306 -126
- package/koni/background/handlers/State.d.ts +5 -6
- package/koni/background/handlers/State.js +51 -34
- package/koni/background/handlers/Tabs.js +50 -17
- package/koni/background/subscription.d.ts +2 -0
- package/koni/background/subscription.js +51 -29
- package/package.json +29 -14
- package/packageInfo.js +1 -1
- package/services/base/types.d.ts +34 -0
- package/services/base/types.js +15 -0
- package/services/chain-service/handler/SubstrateChainHandler.js +14 -9
- package/services/chain-service/helper/psp22_abi.json +1041 -881
- package/services/chain-service/helper/psp34_abi.json +2963 -1807
- package/services/chain-service/index.d.ts +5 -2
- package/services/chain-service/index.js +68 -45
- package/services/chain-service/types.d.ts +1 -0
- package/services/event-service/index.js +5 -1
- package/services/event-service/types.d.ts +5 -9
- package/services/event-service/types.js +4 -1
- package/services/history-service/index.d.ts +28 -7
- package/services/history-service/index.js +101 -50
- package/services/history-service/subsquid-multi-chain-history.js +16 -12
- package/services/keyring-service/index.d.ts +4 -2
- package/services/keyring-service/index.js +11 -13
- package/services/migration-service/scripts/MigrateImportedToken.js +2 -1
- package/services/price-service/coingecko.js +0 -1
- package/services/price-service/index.d.ts +22 -1
- package/services/price-service/index.js +71 -24
- package/services/request-service/handler/AuthRequestHandler.d.ts +3 -1
- package/services/request-service/handler/AuthRequestHandler.js +13 -7
- package/services/request-service/handler/EvmRequestHandler.js +8 -12
- package/services/request-service/index.d.ts +3 -1
- package/services/request-service/index.js +14 -5
- package/services/storage-service/DatabaseService.d.ts +2 -0
- package/services/storage-service/DatabaseService.js +66 -34
- package/services/storage-service/db-stores/Nft.d.ts +2 -2
- package/services/storage-service/db-stores/Nft.js +7 -14
- package/services/storage-service/db-stores/Transaction.d.ts +2 -0
- package/services/storage-service/db-stores/Transaction.js +6 -10
- package/services/transaction-service/event-parser/index.js +21 -49
- package/services/transaction-service/index.d.ts +2 -0
- package/services/transaction-service/index.js +86 -32
- package/services/transaction-service/types.d.ts +2 -0
- package/services/transaction-service/utils.js +10 -8
- package/utils/address.d.ts +3 -0
- package/utils/address.js +8 -1
- package/utils/index.d.ts +2 -2
- package/utils/index.js +7 -13
- package/utils/promise.d.ts +6 -0
- package/utils/promise.js +20 -0
|
@@ -5,7 +5,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.PriceService = void 0;
|
|
7
7
|
var _constants = require("@subwallet/extension-base/constants");
|
|
8
|
+
var _types = require("@subwallet/extension-base/services/base/types");
|
|
8
9
|
var _coingecko = require("@subwallet/extension-base/services/price-service/coingecko");
|
|
10
|
+
var _promise = require("@subwallet/extension-base/utils/promise");
|
|
9
11
|
var _rxjs = require("rxjs");
|
|
10
12
|
// Copyright 2019-2022 @subwallet/extension-koni authors & contributors
|
|
11
13
|
// SPDX-License-Identifier: Apache-2.0
|
|
@@ -20,34 +22,14 @@ class PriceService {
|
|
|
20
22
|
priceSubject = new _rxjs.BehaviorSubject(DEFAULT_PRICE_SUBJECT);
|
|
21
23
|
priceIds = new Set();
|
|
22
24
|
constructor(dbService, eventService, chainService) {
|
|
25
|
+
this.status = _types.ServiceStatus.NOT_INITIALIZED;
|
|
23
26
|
this.dbService = dbService;
|
|
24
27
|
this.eventService = eventService;
|
|
25
28
|
this.chainService = chainService;
|
|
26
|
-
|
|
27
|
-
// Fetch data from storage
|
|
28
|
-
this.getPrice().catch(console.error);
|
|
29
|
-
const eventHandler = () => {
|
|
30
|
-
const newPriceIds = this.getPriceIds();
|
|
31
|
-
|
|
32
|
-
// Compare two set newPriceIds and this.priceIds
|
|
33
|
-
if (newPriceIds.size !== this.priceIds.size || !Array.from(newPriceIds).every(v => this.priceIds.has(v))) {
|
|
34
|
-
this.priceIds = newPriceIds;
|
|
35
|
-
this.refreshPriceData(this.priceIds);
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
this.eventService.waitAssetReady.then(() => {
|
|
39
|
-
this.refreshPriceData();
|
|
40
|
-
this.eventService.on('asset.enable', eventHandler);
|
|
41
|
-
this.eventService.on('asset.update', eventHandler);
|
|
42
|
-
}).catch(console.error);
|
|
29
|
+
this.init().catch(console.error);
|
|
43
30
|
}
|
|
44
31
|
async getPrice() {
|
|
45
|
-
|
|
46
|
-
if (!isReady) {
|
|
47
|
-
const data = await this.dbService.getPriceStore();
|
|
48
|
-
this.priceSubject.next(data || DEFAULT_PRICE_SUBJECT);
|
|
49
|
-
}
|
|
50
|
-
return this.priceSubject.value;
|
|
32
|
+
return Promise.resolve(this.priceSubject.value);
|
|
51
33
|
}
|
|
52
34
|
getPriceSubject() {
|
|
53
35
|
return this.priceSubject;
|
|
@@ -68,9 +50,74 @@ class PriceService {
|
|
|
68
50
|
ready: true
|
|
69
51
|
});
|
|
70
52
|
this.dbService.updatePriceStore(rs).catch(console.error);
|
|
71
|
-
console.log('Get Token Price From CoinGecko');
|
|
72
53
|
}).catch(console.error);
|
|
73
54
|
this.refreshTimeout = setTimeout(this.refreshPriceData.bind(this), _constants.CRON_REFRESH_PRICE_INTERVAL);
|
|
74
55
|
}
|
|
56
|
+
async init() {
|
|
57
|
+
this.status = _types.ServiceStatus.INITIALIZING;
|
|
58
|
+
// Fetch data from storage
|
|
59
|
+
await this.loadData();
|
|
60
|
+
const eventHandler = () => {
|
|
61
|
+
const newPriceIds = this.getPriceIds();
|
|
62
|
+
|
|
63
|
+
// Compare two set newPriceIds and this.priceIds
|
|
64
|
+
if (newPriceIds.size !== this.priceIds.size || !Array.from(newPriceIds).every(v => this.priceIds.has(v))) {
|
|
65
|
+
this.priceIds = newPriceIds;
|
|
66
|
+
this.refreshPriceData(this.priceIds);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
await this.eventService.waitAssetReady;
|
|
70
|
+
this.status = _types.ServiceStatus.INITIALIZED;
|
|
71
|
+
this.eventService.on('asset.updateState', eventHandler);
|
|
72
|
+
this.eventService.on('asset.updateState', eventHandler);
|
|
73
|
+
}
|
|
74
|
+
async loadData() {
|
|
75
|
+
const data = await this.dbService.getPriceStore();
|
|
76
|
+
this.priceSubject.next(data || DEFAULT_PRICE_SUBJECT);
|
|
77
|
+
}
|
|
78
|
+
async persistData() {
|
|
79
|
+
await this.dbService.updatePriceStore(this.priceSubject.value).catch(console.error);
|
|
80
|
+
}
|
|
81
|
+
startPromiseHandler = (0, _promise.createPromiseHandler)();
|
|
82
|
+
async start() {
|
|
83
|
+
console.debug('Start price service');
|
|
84
|
+
try {
|
|
85
|
+
this.startPromiseHandler = (0, _promise.createPromiseHandler)();
|
|
86
|
+
this.status = _types.ServiceStatus.STARTING;
|
|
87
|
+
await this.startCron();
|
|
88
|
+
this.status = _types.ServiceStatus.STARTED;
|
|
89
|
+
this.startPromiseHandler.resolve();
|
|
90
|
+
} catch (e) {
|
|
91
|
+
this.startPromiseHandler.reject(e);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async startCron() {
|
|
95
|
+
this.refreshPriceData();
|
|
96
|
+
return Promise.resolve();
|
|
97
|
+
}
|
|
98
|
+
stopPromiseHandler = (0, _promise.createPromiseHandler)();
|
|
99
|
+
async stop() {
|
|
100
|
+
console.debug('Stop price service');
|
|
101
|
+
try {
|
|
102
|
+
this.status = _types.ServiceStatus.STOPPING;
|
|
103
|
+
this.stopPromiseHandler = (0, _promise.createPromiseHandler)();
|
|
104
|
+
await this.stopCron();
|
|
105
|
+
await this.persistData();
|
|
106
|
+
this.status = _types.ServiceStatus.STOPPED;
|
|
107
|
+
this.stopPromiseHandler.resolve();
|
|
108
|
+
} catch (e) {
|
|
109
|
+
this.stopPromiseHandler.reject(e);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
stopCron() {
|
|
113
|
+
clearTimeout(this.refreshTimeout);
|
|
114
|
+
return Promise.resolve(undefined);
|
|
115
|
+
}
|
|
116
|
+
waitForStarted() {
|
|
117
|
+
return this.startPromiseHandler.promise;
|
|
118
|
+
}
|
|
119
|
+
waitForStopped() {
|
|
120
|
+
return this.stopPromiseHandler.promise;
|
|
121
|
+
}
|
|
75
122
|
}
|
|
76
123
|
exports.PriceService = PriceService;
|
|
@@ -10,7 +10,6 @@ var _constants = require("@subwallet/extension-base/services/request-service/con
|
|
|
10
10
|
var _Authorize = _interopRequireDefault(require("@subwallet/extension-base/stores/Authorize"));
|
|
11
11
|
var _utils2 = require("@subwallet/extension-base/utils");
|
|
12
12
|
var _getId = require("@subwallet/extension-base/utils/getId");
|
|
13
|
-
var _accounts = require("@subwallet/ui-keyring/observable/accounts");
|
|
14
13
|
var _rxjs = require("rxjs");
|
|
15
14
|
var _util = require("@polkadot/util");
|
|
16
15
|
var _utilCrypto = require("@polkadot/util-crypto");
|
|
@@ -27,7 +26,8 @@ class AuthRequestHandler {
|
|
|
27
26
|
authorizeUrlSubject = new _rxjs.Subject();
|
|
28
27
|
evmChainSubject = new _rxjs.Subject();
|
|
29
28
|
authSubjectV2 = new _rxjs.BehaviorSubject([]);
|
|
30
|
-
constructor(requestService, chainService) {
|
|
29
|
+
constructor(requestService, chainService, keyringService) {
|
|
30
|
+
this.keyringService = keyringService;
|
|
31
31
|
this.#requestService = requestService;
|
|
32
32
|
this.#chainService = chainService;
|
|
33
33
|
}
|
|
@@ -38,7 +38,7 @@ class AuthRequestHandler {
|
|
|
38
38
|
}
|
|
39
39
|
getAddressList() {
|
|
40
40
|
let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
41
|
-
const addressList = Object.keys(
|
|
41
|
+
const addressList = Object.keys(this.keyringService.accounts);
|
|
42
42
|
return addressList.reduce((addressList, v) => ({
|
|
43
43
|
...addressList,
|
|
44
44
|
[v]: value
|
|
@@ -95,11 +95,11 @@ class AuthRequestHandler {
|
|
|
95
95
|
const chainInfoMaps = this.#chainService.getChainInfoMap();
|
|
96
96
|
const chainStateMap = this.#chainService.getChainStateMap();
|
|
97
97
|
let defaultChain = options.defaultChain;
|
|
98
|
-
|
|
98
|
+
let needEnableChains = [];
|
|
99
99
|
if (options.url) {
|
|
100
100
|
const domain = (0, _utils2.getDomainFromUrl)(options.url);
|
|
101
101
|
const predefinedSupportChains = _constants.PREDEFINED_CHAIN_DAPP_CHAIN_MAP[domain];
|
|
102
|
-
if (predefinedSupportChains) {
|
|
102
|
+
if (!defaultChain && predefinedSupportChains) {
|
|
103
103
|
defaultChain = predefinedSupportChains[0];
|
|
104
104
|
options.autoActive && needEnableChains.push(...predefinedSupportChains);
|
|
105
105
|
}
|
|
@@ -112,11 +112,17 @@ class AuthRequestHandler {
|
|
|
112
112
|
return (_chainStateMap$chain$ = chainStateMap[chain.slug]) === null || _chainStateMap$chain$ === void 0 ? void 0 : _chainStateMap$chain$.active;
|
|
113
113
|
})) || evmChains[0];
|
|
114
114
|
if (options.autoActive) {
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
var _chainInfo;
|
|
116
|
+
if (!needEnableChains.includes((_chainInfo = chainInfo) === null || _chainInfo === void 0 ? void 0 : _chainInfo.slug)) {
|
|
117
|
+
var _chainInfo2;
|
|
118
|
+
needEnableChains.push((_chainInfo2 = chainInfo) === null || _chainInfo2 === void 0 ? void 0 : _chainInfo2.slug);
|
|
117
119
|
}
|
|
118
120
|
}
|
|
119
121
|
}
|
|
122
|
+
needEnableChains = needEnableChains.filter(slug => {
|
|
123
|
+
var _chainStateMap$slug;
|
|
124
|
+
return !((_chainStateMap$slug = chainStateMap[slug]) !== null && _chainStateMap$slug !== void 0 && _chainStateMap$slug.active);
|
|
125
|
+
});
|
|
120
126
|
needEnableChains.length > 0 && this.#chainService.enableChains(needEnableChains);
|
|
121
127
|
return chainInfo;
|
|
122
128
|
}
|
|
@@ -76,16 +76,7 @@ class EvmRequestHandler {
|
|
|
76
76
|
});
|
|
77
77
|
this.confirmationsQueueSubject.next(confirmations);
|
|
78
78
|
if (!isInternal) {
|
|
79
|
-
|
|
80
|
-
const popupList = this.#requestService.popup;
|
|
81
|
-
if (this.#requestService.popup.length > 0) {
|
|
82
|
-
// eslint-disable-next-line no-void
|
|
83
|
-
void chrome.windows.update(popupList[0], {
|
|
84
|
-
focused: true
|
|
85
|
-
});
|
|
86
|
-
} else {
|
|
87
|
-
this.#requestService.popupOpen();
|
|
88
|
-
}
|
|
79
|
+
this.#requestService.popupOpen();
|
|
89
80
|
}
|
|
90
81
|
this.#requestService.updateIconV2();
|
|
91
82
|
return promise;
|
|
@@ -136,7 +127,8 @@ class EvmRequestHandler {
|
|
|
136
127
|
data: (0, _ethereumjsUtil.toBuffer)(config.data)
|
|
137
128
|
};
|
|
138
129
|
const common = _common.default.custom({
|
|
139
|
-
chainId: config.chainId
|
|
130
|
+
chainId: config.chainId,
|
|
131
|
+
defaultHardfork: 'petersburg'
|
|
140
132
|
});
|
|
141
133
|
|
|
142
134
|
// @ts-ignore
|
|
@@ -149,11 +141,15 @@ class EvmRequestHandler {
|
|
|
149
141
|
const {
|
|
150
142
|
estimateGas,
|
|
151
143
|
from,
|
|
152
|
-
|
|
144
|
+
gas,
|
|
145
|
+
gasPrice,
|
|
146
|
+
value
|
|
153
147
|
} = transaction;
|
|
154
148
|
const pair = _uiKeyring.default.getPair(from);
|
|
155
149
|
const params = {
|
|
156
150
|
...transaction,
|
|
151
|
+
gas: (0, _eth.anyNumberToBN)(gas).toNumber(),
|
|
152
|
+
value: (0, _eth.anyNumberToBN)(value).toNumber(),
|
|
157
153
|
gasPrice: (0, _eth.anyNumberToBN)(gasPrice).toNumber(),
|
|
158
154
|
gasLimit: (0, _eth.anyNumberToBN)(estimateGas).toNumber()
|
|
159
155
|
// nonce: await web3.eth.getTransactionCount(from) // Todo: fill this value from transaction service
|
|
@@ -10,7 +10,6 @@ var _EvmRequestHandler = _interopRequireDefault(require("@subwallet/extension-ba
|
|
|
10
10
|
var _MetadataRequestHandler = _interopRequireDefault(require("@subwallet/extension-base/services/request-service/handler/MetadataRequestHandler"));
|
|
11
11
|
var _PopupHandler = _interopRequireDefault(require("@subwallet/extension-base/services/request-service/handler/PopupHandler"));
|
|
12
12
|
var _SubstrateRequestHandler = _interopRequireDefault(require("@subwallet/extension-base/services/request-service/handler/SubstrateRequestHandler"));
|
|
13
|
-
var _accounts = require("@subwallet/ui-keyring/observable/accounts");
|
|
14
13
|
// Copyright 2019-2022 @subwallet/extension-base authors & contributors
|
|
15
14
|
// SPDX-License-Identifier: Apache-2.0
|
|
16
15
|
|
|
@@ -24,12 +23,13 @@ class RequestService {
|
|
|
24
23
|
#evmRequestHandler;
|
|
25
24
|
|
|
26
25
|
// Common
|
|
27
|
-
constructor(chainService, settingService) {
|
|
26
|
+
constructor(chainService, settingService, keyringService) {
|
|
27
|
+
this.keyringService = keyringService;
|
|
28
28
|
this.#chainService = chainService;
|
|
29
29
|
this.settingService = settingService;
|
|
30
30
|
this.#popupHandler = new _PopupHandler.default(this);
|
|
31
31
|
this.#metadataRequestHandler = new _MetadataRequestHandler.default(this);
|
|
32
|
-
this.#authRequestHandler = new _AuthRequestHandler.default(this, this.#chainService);
|
|
32
|
+
this.#authRequestHandler = new _AuthRequestHandler.default(this, this.#chainService, this.keyringService);
|
|
33
33
|
this.#substrateRequestHandler = new _SubstrateRequestHandler.default(this);
|
|
34
34
|
this.#evmRequestHandler = new _EvmRequestHandler.default(this);
|
|
35
35
|
|
|
@@ -44,7 +44,7 @@ class RequestService {
|
|
|
44
44
|
}
|
|
45
45
|
getAddressList() {
|
|
46
46
|
let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
47
|
-
const addressList = Object.keys(
|
|
47
|
+
const addressList = Object.keys(this.keyringService.accounts);
|
|
48
48
|
return addressList.reduce((addressList, v) => ({
|
|
49
49
|
...addressList,
|
|
50
50
|
[v]: value
|
|
@@ -59,7 +59,16 @@ class RequestService {
|
|
|
59
59
|
this.#popupHandler.popupClose();
|
|
60
60
|
}
|
|
61
61
|
popupOpen() {
|
|
62
|
-
|
|
62
|
+
// Not open new popup and use existed
|
|
63
|
+
const popupList = this.#popupHandler.popup;
|
|
64
|
+
if (popupList && popupList.length > 0) {
|
|
65
|
+
var _chrome$windows$updat;
|
|
66
|
+
(_chrome$windows$updat = chrome.windows.update(popupList[0], {
|
|
67
|
+
focused: true
|
|
68
|
+
})) === null || _chrome$windows$updat === void 0 ? void 0 : _chrome$windows$updat.catch(console.error);
|
|
69
|
+
} else {
|
|
70
|
+
this.#popupHandler.popupOpen();
|
|
71
|
+
}
|
|
63
72
|
}
|
|
64
73
|
|
|
65
74
|
// Metadata
|
|
@@ -10,6 +10,7 @@ var _databases = _interopRequireDefault(require("@subwallet/extension-base/servi
|
|
|
10
10
|
var _dbStores = require("@subwallet/extension-base/services/storage-service/db-stores");
|
|
11
11
|
var _ChainStakingMetadata = _interopRequireDefault(require("@subwallet/extension-base/services/storage-service/db-stores/ChainStakingMetadata"));
|
|
12
12
|
var _NominatorMetadata = _interopRequireDefault(require("@subwallet/extension-base/services/storage-service/db-stores/NominatorMetadata"));
|
|
13
|
+
var _utils = require("@subwallet/extension-base/utils");
|
|
13
14
|
var _util = require("@polkadot/util");
|
|
14
15
|
// Copyright 2019-2022 @subwallet/extension-base authors & contributors
|
|
15
16
|
// SPDX-License-Identifier: Apache-2.0
|
|
@@ -54,7 +55,8 @@ class DatabaseService {
|
|
|
54
55
|
}
|
|
55
56
|
async updateBalanceStore(address, item) {
|
|
56
57
|
if (item.state === _KoniTypes.APIItemState.READY) {
|
|
57
|
-
this.logger.log(`Updating balance for [${item.tokenSlug}]`);
|
|
58
|
+
// this.logger.log(`Updating balance for [${item.tokenSlug}]`);
|
|
59
|
+
|
|
58
60
|
return this.stores.balance.upsert({
|
|
59
61
|
address,
|
|
60
62
|
...item
|
|
@@ -69,14 +71,16 @@ class DatabaseService {
|
|
|
69
71
|
// Crowdloan
|
|
70
72
|
async updateCrowdloanStore(chain, address, item) {
|
|
71
73
|
if (item.state === _KoniTypes.APIItemState.READY && item.contribute !== '0') {
|
|
72
|
-
this.logger.log(`Updating crowdloan for [${chain}]`);
|
|
74
|
+
// this.logger.log(`Updating crowdloan for [${chain}]`);
|
|
75
|
+
|
|
73
76
|
return this.stores.crowdloan.upsert({
|
|
74
77
|
chain,
|
|
75
78
|
address,
|
|
76
79
|
...item
|
|
77
80
|
});
|
|
78
81
|
} else {
|
|
79
|
-
this.logger.debug(`Removing crowdloan for [${chain}]`);
|
|
82
|
+
// this.logger.debug(`Removing crowdloan for [${chain}]`);
|
|
83
|
+
|
|
80
84
|
return this.stores.crowdloan.deleteByChainAndAddress(chain, address);
|
|
81
85
|
}
|
|
82
86
|
}
|
|
@@ -84,22 +88,23 @@ class DatabaseService {
|
|
|
84
88
|
// Staking
|
|
85
89
|
async updateStaking(chain, address, item) {
|
|
86
90
|
if (item.state === _KoniTypes.APIItemState.READY) {
|
|
87
|
-
this.logger.log(`Updating staking for [${chain}]`);
|
|
91
|
+
// this.logger.log(`Updating staking for [${chain}]`);
|
|
92
|
+
|
|
88
93
|
return this.stores.staking.upsert(item);
|
|
89
94
|
}
|
|
90
95
|
}
|
|
91
96
|
async getStakings(addresses, chains) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return
|
|
97
|
+
// this.logger.log('Get Stakings: ', stakings);
|
|
98
|
+
|
|
99
|
+
return this.stores.staking.getStakings(addresses, chains);
|
|
95
100
|
}
|
|
96
101
|
async getStakingsByChains(chains) {
|
|
97
102
|
return this.stores.staking.getStakingsByChains(chains);
|
|
98
103
|
}
|
|
99
104
|
async getPooledStakings(addresses, chainHashes) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return
|
|
105
|
+
// this.logger.log('Get Pooled Stakings: ', stakings);
|
|
106
|
+
|
|
107
|
+
return this.stores.staking.getPooledStakings(addresses, chainHashes);
|
|
103
108
|
}
|
|
104
109
|
subscribeStaking(addresses, chainList, callback) {
|
|
105
110
|
this.stakingSubscription && this.stakingSubscription.unsubscribe();
|
|
@@ -121,18 +126,28 @@ class DatabaseService {
|
|
|
121
126
|
|
|
122
127
|
// Transaction histories
|
|
123
128
|
async getHistories(query) {
|
|
124
|
-
|
|
125
|
-
this.logger.log('Get histories: ', histories);
|
|
126
|
-
return histories;
|
|
129
|
+
return this.stores.transaction.queryHistory(query);
|
|
127
130
|
}
|
|
128
131
|
async upsertHistory(histories) {
|
|
129
|
-
this.logger.log('Updating transaction histories');
|
|
130
|
-
|
|
132
|
+
// this.logger.log('Updating transaction histories');
|
|
133
|
+
const cleanedHistory = histories.filter(x => x && x.address && x.chain && x.extrinsicHash);
|
|
134
|
+
return this.stores.transaction.bulkUpsert(cleanedHistory);
|
|
135
|
+
}
|
|
136
|
+
async updateHistoryByNewExtrinsicHash(extrinsicHash, updateData) {
|
|
137
|
+
// this.logger.log('Updating transaction histories');
|
|
138
|
+
const canUpdate = updateData && extrinsicHash;
|
|
139
|
+
if (!canUpdate) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
return this.stores.transaction.updateWithQuery({
|
|
143
|
+
extrinsicHash
|
|
144
|
+
}, updateData);
|
|
131
145
|
}
|
|
132
146
|
|
|
133
147
|
// NFT Collection
|
|
134
148
|
async addNftCollection(collection) {
|
|
135
|
-
this.logger.log(`Updating NFT collection for [${collection.chain}]`);
|
|
149
|
+
// this.logger.log(`Updating NFT collection for [${collection.chain}]`);
|
|
150
|
+
|
|
136
151
|
return this.stores.nftCollection.upsert(collection);
|
|
137
152
|
}
|
|
138
153
|
async deleteNftCollection(chain, collectionId) {
|
|
@@ -151,13 +166,22 @@ class DatabaseService {
|
|
|
151
166
|
});
|
|
152
167
|
return this.nftSubscription;
|
|
153
168
|
}
|
|
169
|
+
async cleanUpNft(chain, owner, collectionIds, nftIds, ownNothing) {
|
|
170
|
+
if (ownNothing) {
|
|
171
|
+
return this.stores.nft.deleteNftsByChainAndOwner(chain, (0, _utils.reformatAddress)(owner, 42));
|
|
172
|
+
}
|
|
173
|
+
const result = await this.stores.nft.cleanUpNfts(chain, (0, _utils.reformatAddress)(owner, 42), collectionIds, nftIds);
|
|
174
|
+
result > 0 && console.debug(`Cleaned up ${result} NFTs on chain ${chain} for owner ${(0, _utils.reformatAddress)(owner, 42)}`, collectionIds, nftIds);
|
|
175
|
+
return result;
|
|
176
|
+
}
|
|
154
177
|
async getNft(addresses, chainHashes) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return
|
|
178
|
+
// this.logger.log('Get NFTs: ', nfts);
|
|
179
|
+
|
|
180
|
+
return this.stores.nft.getNft(addresses, chainHashes);
|
|
158
181
|
}
|
|
159
182
|
async addNft(address, nft) {
|
|
160
|
-
this.logger.log(`Updating NFT for [${nft.chain}]`);
|
|
183
|
+
// this.logger.log(`Updating NFT for [${nft.chain}]`);
|
|
184
|
+
|
|
161
185
|
return this.stores.nft.upsert({
|
|
162
186
|
...nft,
|
|
163
187
|
address
|
|
@@ -167,47 +191,54 @@ class DatabaseService {
|
|
|
167
191
|
return this.stores.nft.deleteNftItem(chain, addresses, nftItem);
|
|
168
192
|
}
|
|
169
193
|
removeNfts(chain, address, collectionId, nftIds) {
|
|
170
|
-
this.logger.log(`Remove NFTs [${nftIds.join(', ')}]`);
|
|
194
|
+
// this.logger.log(`Remove NFTs [${nftIds.join(', ')}]`);
|
|
195
|
+
|
|
171
196
|
return this.stores.nft.removeNfts(chain, address, collectionId, nftIds);
|
|
172
197
|
}
|
|
173
198
|
|
|
174
199
|
// Chain
|
|
175
200
|
async updateChainStore(item) {
|
|
176
|
-
this.logger.log(`Updating storageInfo for chain [${item.slug}]`);
|
|
201
|
+
// this.logger.log(`Updating storageInfo for chain [${item.slug}]`);
|
|
202
|
+
|
|
177
203
|
return this.stores.chain.upsert(item);
|
|
178
204
|
}
|
|
179
205
|
async bulkUpdateChainStore(data) {
|
|
180
|
-
this.logger.log('Bulk updating ChainStore');
|
|
206
|
+
// this.logger.log('Bulk updating ChainStore');
|
|
207
|
+
|
|
181
208
|
return this.stores.chain.bulkUpsert(data);
|
|
182
209
|
}
|
|
183
210
|
async removeFromChainStore(chains) {
|
|
184
|
-
this.logger.log('Bulk removing ChainStore');
|
|
211
|
+
// this.logger.log('Bulk removing ChainStore');
|
|
212
|
+
|
|
185
213
|
return this.stores.chain.removeChains(chains);
|
|
186
214
|
}
|
|
187
215
|
async getAllChainStore() {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
return
|
|
216
|
+
// this.logger.log('Get all chains: ', allChains);
|
|
217
|
+
|
|
218
|
+
return this.stores.chain.getAll();
|
|
191
219
|
}
|
|
192
220
|
|
|
193
221
|
// Asset
|
|
194
222
|
async updateAssetStore(item) {
|
|
195
|
-
this.logger.log(`Updating storageInfo for chainAsset [${item.originChain}]`);
|
|
223
|
+
// this.logger.log(`Updating storageInfo for chainAsset [${item.originChain}]`);
|
|
224
|
+
|
|
196
225
|
return this.stores.asset.upsert(item);
|
|
197
226
|
}
|
|
198
227
|
async getAllAssetStore() {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
return
|
|
228
|
+
// this.logger.log('Get all stored assets: ', allAssets);
|
|
229
|
+
|
|
230
|
+
return this.stores.asset.getAll();
|
|
202
231
|
}
|
|
203
232
|
async removeFromAssetStore(items) {
|
|
204
|
-
this.logger.log('Bulk removing AssetStore');
|
|
233
|
+
// this.logger.log('Bulk removing AssetStore');
|
|
234
|
+
|
|
205
235
|
return this.stores.asset.removeAssets(items);
|
|
206
236
|
}
|
|
207
237
|
|
|
208
238
|
// Staking
|
|
209
239
|
async updateChainStakingMetadata(item) {
|
|
210
|
-
this.logger.log('Update ChainStakingMetadata: ', item.chain);
|
|
240
|
+
// this.logger.log('Update ChainStakingMetadata: ', item.chain);
|
|
241
|
+
|
|
211
242
|
return this.stores.chainStakingMetadata.upsert(item);
|
|
212
243
|
}
|
|
213
244
|
async getChainStakingMetadata() {
|
|
@@ -218,7 +249,8 @@ class DatabaseService {
|
|
|
218
249
|
return this.stores.chainStakingMetadata.getByChainAndType(chain, type);
|
|
219
250
|
}
|
|
220
251
|
async updateNominatorMetadata(item) {
|
|
221
|
-
this.logger.log('Update NominatorMetadata: ', item.address, item.chain);
|
|
252
|
+
// this.logger.log('Update NominatorMetadata: ', item.address, item.chain);
|
|
253
|
+
|
|
222
254
|
return this.stores.nominatorMetadata.upsert(item);
|
|
223
255
|
}
|
|
224
256
|
async getNominatorMetadata() {
|
|
@@ -24,25 +24,17 @@ class NftStore extends _BaseStoreWithAddressAndChain.default {
|
|
|
24
24
|
let chainList = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
25
25
|
return (0, _dexie.liveQuery)(() => this.getNft(addresses, chainList));
|
|
26
26
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
};
|
|
33
|
-
if (!collection && nftIds && nftIds.length) {
|
|
34
|
-
return this.logger.warn('Missing collection id');
|
|
35
|
-
}
|
|
36
|
-
if (collection) {
|
|
37
|
-
conditions.collectionId = collection;
|
|
38
|
-
}
|
|
39
|
-
return this.table.where(conditions).and(item => !nftIds.some(nft => nft === item.id)).delete();
|
|
27
|
+
cleanUpNfts(chain, address, collectionIds, nftIds) {
|
|
28
|
+
return this.table.where({
|
|
29
|
+
address,
|
|
30
|
+
chain
|
|
31
|
+
}).and(nft => !collectionIds.includes(nft.collectionId) || collectionIds.includes(nft.collectionId) && !nftIds.includes(nft.id)).delete();
|
|
40
32
|
}
|
|
41
|
-
|
|
33
|
+
deleteNftsByChainAndOwner(chain, address) {
|
|
42
34
|
return this.table.where({
|
|
43
35
|
address,
|
|
44
36
|
chain
|
|
45
|
-
}).
|
|
37
|
+
}).delete();
|
|
46
38
|
}
|
|
47
39
|
deleteNftByAddress(addresses) {
|
|
48
40
|
return this.table.where('address').anyOfIgnoreCase(addresses).delete();
|
|
@@ -36,16 +36,12 @@ class TransactionStore extends _BaseStoreWithAddressAndChain.default {
|
|
|
36
36
|
}
|
|
37
37
|
async bulkUpsert(records) {
|
|
38
38
|
await this.table.bulkPut(records);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// }).filter((item) => (item.origin === 'app' && record.origin !== 'app'))
|
|
46
|
-
// .delete();
|
|
47
|
-
// }));
|
|
48
|
-
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
async updateWithQuery(query, update) {
|
|
42
|
+
await this.table.where(query).modify(record => {
|
|
43
|
+
return Object.assign(record, update);
|
|
44
|
+
});
|
|
49
45
|
return true;
|
|
50
46
|
}
|
|
51
47
|
}
|
|
@@ -10,43 +10,28 @@ var _utils = require("@subwallet/extension-base/services/chain-service/utils");
|
|
|
10
10
|
// SPDX-License-Identifier: Apache-2.0
|
|
11
11
|
|
|
12
12
|
function parseXcmEventLogs(historyItem, eventLogs, chain, sendingTokenInfo, chainInfo) {
|
|
13
|
-
let isFeeUseMainTokenSymbol = true;
|
|
14
13
|
for (let index = 0; index < eventLogs.length; index++) {
|
|
15
14
|
const record = eventLogs[index];
|
|
16
|
-
if (['karura', 'acala', 'acala_testnet'].includes(chain) && sendingTokenInfo && !(0, _utils._isNativeToken)(sendingTokenInfo)) {
|
|
17
|
-
if (record.event.section === 'currencies' && record.event.method.toLowerCase() === 'transferred') {
|
|
18
|
-
if (index === 0) {
|
|
19
|
-
var _record$event$data$;
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
21
|
-
historyItem.fee = {
|
|
22
|
-
value: ((_record$event$data$ = record.event.data[3]) === null || _record$event$data$ === void 0 ? void 0 : _record$event$data$.toString()) || '0',
|
|
23
|
-
symbol: sendingTokenInfo.symbol,
|
|
24
|
-
decimals: (0, _utils._getAssetDecimals)(sendingTokenInfo)
|
|
25
|
-
};
|
|
26
|
-
isFeeUseMainTokenSymbol = false;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
15
|
const {
|
|
31
16
|
decimals: nativeDecimals,
|
|
32
17
|
symbol: nativeSymbol
|
|
33
18
|
} = (0, _utils._getChainNativeTokenBasicInfo)(chainInfo);
|
|
34
|
-
if (
|
|
35
|
-
var _record$event$data
|
|
36
|
-
if ((_record$event$data$
|
|
37
|
-
var _record$event$data$
|
|
19
|
+
if (record.event.section === 'balances' && record.event.method.toLowerCase() === 'withdraw') {
|
|
20
|
+
var _record$event$data$;
|
|
21
|
+
if ((_record$event$data$ = record.event.data[1]) !== null && _record$event$data$ !== void 0 && _record$event$data$.toString()) {
|
|
22
|
+
var _record$event$data$2;
|
|
38
23
|
historyItem.fee = {
|
|
39
|
-
value: (_record$event$data$
|
|
24
|
+
value: (_record$event$data$2 = record.event.data[1]) === null || _record$event$data$2 === void 0 ? void 0 : _record$event$data$2.toString(),
|
|
40
25
|
symbol: nativeSymbol,
|
|
41
26
|
decimals: nativeDecimals
|
|
42
27
|
};
|
|
43
28
|
}
|
|
44
|
-
} else if (
|
|
45
|
-
var _record$event$data$
|
|
46
|
-
if ((_record$event$data$
|
|
47
|
-
var _record$event$data$
|
|
29
|
+
} else if (record.event.section === 'tokens' && record.event.method.toLowerCase() === 'withdrawn') {
|
|
30
|
+
var _record$event$data$3;
|
|
31
|
+
if (!historyItem.fee && (_record$event$data$3 = record.event.data[2]) !== null && _record$event$data$3 !== void 0 && _record$event$data$3.toString()) {
|
|
32
|
+
var _record$event$data$4;
|
|
48
33
|
historyItem.fee = {
|
|
49
|
-
value: (_record$event$data$
|
|
34
|
+
value: (_record$event$data$4 = record.event.data[2]) === null || _record$event$data$4 === void 0 ? void 0 : _record$event$data$4.toString(),
|
|
50
35
|
symbol: nativeSymbol,
|
|
51
36
|
decimals: nativeDecimals
|
|
52
37
|
};
|
|
@@ -55,28 +40,15 @@ function parseXcmEventLogs(historyItem, eventLogs, chain, sendingTokenInfo, chai
|
|
|
55
40
|
}
|
|
56
41
|
}
|
|
57
42
|
function parseTransferEventLogs(historyItem, eventLogs, chain, sendingTokenInfo, chainInfo) {
|
|
58
|
-
let isFeeUseMainTokenSymbol = true;
|
|
59
43
|
for (let index = 0; index < eventLogs.length; index++) {
|
|
60
44
|
const record = eventLogs[index];
|
|
61
|
-
if (['
|
|
62
|
-
if (record.event.section === 'currencies' && record.event.method.toLowerCase() === 'transferred') {
|
|
63
|
-
if (index === 0) {
|
|
64
|
-
var _record$event$data$6;
|
|
65
|
-
historyItem.fee = {
|
|
66
|
-
value: ((_record$event$data$6 = record.event.data[3]) === null || _record$event$data$6 === void 0 ? void 0 : _record$event$data$6.toString()) || '0',
|
|
67
|
-
symbol: sendingTokenInfo.symbol,
|
|
68
|
-
decimals: (0, _utils._getAssetDecimals)(sendingTokenInfo)
|
|
69
|
-
};
|
|
70
|
-
isFeeUseMainTokenSymbol = false;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
} else if (['genshiro_testnet', 'genshiro', 'equilibrium_parachain'].includes(chain) && sendingTokenInfo) {
|
|
45
|
+
if (['genshiro_testnet', 'genshiro', 'equilibrium_parachain'].includes(chain) && sendingTokenInfo) {
|
|
74
46
|
if (record.event.section === 'transactionPayment' && record.event.method.toLowerCase() === 'transactionfeepaid') {
|
|
75
|
-
var _record$event$data$
|
|
76
|
-
if ((_record$event$data$
|
|
77
|
-
var _record$event$data$
|
|
47
|
+
var _record$event$data$5;
|
|
48
|
+
if ((_record$event$data$5 = record.event.data[1]) !== null && _record$event$data$5 !== void 0 && _record$event$data$5.toString()) {
|
|
49
|
+
var _record$event$data$6;
|
|
78
50
|
historyItem.fee = {
|
|
79
|
-
value: ((_record$event$data$
|
|
51
|
+
value: ((_record$event$data$6 = record.event.data[1]) === null || _record$event$data$6 === void 0 ? void 0 : _record$event$data$6.toString()) || '0',
|
|
80
52
|
symbol: sendingTokenInfo.symbol,
|
|
81
53
|
decimals: (0, _utils._getAssetDecimals)(sendingTokenInfo)
|
|
82
54
|
};
|
|
@@ -87,13 +59,13 @@ function parseTransferEventLogs(historyItem, eventLogs, chain, sendingTokenInfo,
|
|
|
87
59
|
decimals: nativeDecimals,
|
|
88
60
|
symbol: nativeSymbol
|
|
89
61
|
} = (0, _utils._getChainNativeTokenBasicInfo)(chainInfo);
|
|
90
|
-
if (
|
|
91
|
-
var _record$event$data$
|
|
92
|
-
if ((_record$event$data$
|
|
93
|
-
var _record$event$data$
|
|
62
|
+
if (record.event.section === 'balances' && record.event.method.toLowerCase() === 'withdraw') {
|
|
63
|
+
var _record$event$data$7;
|
|
64
|
+
if ((_record$event$data$7 = record.event.data[1]) !== null && _record$event$data$7 !== void 0 && _record$event$data$7.toString()) {
|
|
65
|
+
var _record$event$data$8;
|
|
94
66
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
95
67
|
historyItem.fee = {
|
|
96
|
-
value: ((_record$event$data$
|
|
68
|
+
value: ((_record$event$data$8 = record.event.data[1]) === null || _record$event$data$8 === void 0 ? void 0 : _record$event$data$8.toString()) || '0',
|
|
97
69
|
symbol: nativeSymbol,
|
|
98
70
|
decimals: nativeDecimals
|
|
99
71
|
};
|