@subwallet/extension-base 1.1.22-0 → 1.1.24-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 +21 -2
- package/cjs/koni/api/dotsama/balance.js +49 -0
- package/cjs/koni/api/dotsama/crowdloan.js +29 -3
- package/cjs/koni/api/dotsama/transfer.js +10 -3
- package/cjs/koni/api/staking/bonding/astar.js +9 -5
- package/cjs/koni/api/xcm/index.js +6 -1
- package/cjs/koni/api/xcm/polkadotXcm.js +1 -3
- package/cjs/koni/api/xcm/xTokens.js +1 -1
- package/cjs/koni/background/handlers/Extension.js +123 -96
- package/cjs/koni/background/handlers/Mobile.js +32 -0
- package/cjs/koni/background/handlers/State.js +15 -7
- package/cjs/koni/background/subscription.js +1 -1
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/chain-service/constants.js +5 -2
- package/cjs/services/chain-service/index.js +18 -0
- package/cjs/services/history-service/helpers/subscan-extrinsic-parser-helper.js +53 -0
- package/cjs/services/history-service/index.js +78 -21
- package/cjs/services/history-service/subscan-history.js +107 -0
- package/cjs/services/storage-service/DatabaseService.js +40 -0
- package/cjs/services/subscan-service/index.js +109 -4
- package/cjs/services/subscan-service/subscan-chain-map.js +82 -8
- package/cjs/utils/index.js +10 -1
- package/koni/api/dotsama/balance.js +49 -0
- package/koni/api/dotsama/crowdloan.d.ts +2 -2
- package/koni/api/dotsama/crowdloan.js +29 -2
- package/koni/api/dotsama/transfer.js +10 -3
- package/koni/api/staking/bonding/astar.js +9 -5
- package/koni/api/xcm/index.js +6 -1
- package/koni/api/xcm/polkadotXcm.js +2 -4
- package/koni/api/xcm/xTokens.js +1 -1
- package/koni/background/handlers/Extension.d.ts +1 -0
- package/koni/background/handlers/Extension.js +26 -0
- package/koni/background/handlers/Mobile.d.ts +5 -1
- package/koni/background/handlers/Mobile.js +31 -0
- package/koni/background/handlers/State.d.ts +1 -0
- package/koni/background/handlers/State.js +17 -9
- package/koni/background/subscription.js +1 -1
- package/package.json +17 -6
- package/packageInfo.js +1 -1
- package/services/chain-service/constants.d.ts +2 -0
- package/services/chain-service/constants.js +5 -3
- package/services/chain-service/index.d.ts +1 -0
- package/services/chain-service/index.js +18 -0
- package/services/history-service/helpers/subscan-extrinsic-parser-helper.d.ts +6 -0
- package/services/history-service/helpers/subscan-extrinsic-parser-helper.js +44 -0
- package/services/history-service/index.d.ts +10 -6
- package/services/history-service/index.js +79 -22
- package/services/history-service/subscan-history.d.ts +5 -0
- package/services/history-service/subscan-history.js +100 -0
- package/services/storage-service/DatabaseService.d.ts +3 -0
- package/services/storage-service/DatabaseService.js +40 -0
- package/services/subscan-service/index.d.ts +10 -2
- package/services/subscan-service/index.js +105 -4
- package/services/subscan-service/subscan-chain-map.d.ts +9 -3
- package/services/subscan-service/subscan-chain-map.js +78 -5
- package/services/subscan-service/types.d.ts +146 -0
- package/utils/index.d.ts +1 -0
- package/utils/index.js +7 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Copyright 2019-2022 @subwallet/extension-koni authors & contributors
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
+
import { createPromiseHandler } from '@subwallet/extension-base/utils/promise';
|
|
4
5
|
const DEFAULT_SERVICE_MAP = {
|
|
5
6
|
subscription: {
|
|
6
7
|
chainRegistry: true,
|
|
@@ -20,6 +21,7 @@ const DEFAULT_SERVICE_MAP = {
|
|
|
20
21
|
export default class Mobile {
|
|
21
22
|
// @ts-ignore
|
|
22
23
|
|
|
24
|
+
restoreHandler = createPromiseHandler();
|
|
23
25
|
constructor(state) {
|
|
24
26
|
this.state = state;
|
|
25
27
|
}
|
|
@@ -92,6 +94,31 @@ export default class Mobile {
|
|
|
92
94
|
restartSubscriptionServices(services) {
|
|
93
95
|
console.log('restartSubscriptionServices');
|
|
94
96
|
}
|
|
97
|
+
async mobileBackup() {
|
|
98
|
+
const indexedDB = await this.state.dbService.exportDB();
|
|
99
|
+
return {
|
|
100
|
+
storage: JSON.stringify(localStorage),
|
|
101
|
+
indexedDB
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
async mobileRestore({
|
|
105
|
+
indexedDB,
|
|
106
|
+
storage
|
|
107
|
+
}) {
|
|
108
|
+
if (storage) {
|
|
109
|
+
const storageData = JSON.parse(storage);
|
|
110
|
+
for (const key in storageData) {
|
|
111
|
+
localStorage.setItem(key, JSON.stringify(storageData[key]));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (indexedDB) {
|
|
115
|
+
await this.state.dbService.importDB(indexedDB);
|
|
116
|
+
}
|
|
117
|
+
this.restoreHandler.resolve();
|
|
118
|
+
}
|
|
119
|
+
waitRestore() {
|
|
120
|
+
return this.restoreHandler.promise;
|
|
121
|
+
}
|
|
95
122
|
|
|
96
123
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
97
124
|
async handle(id, type, request, port) {
|
|
@@ -120,6 +147,10 @@ export default class Mobile {
|
|
|
120
147
|
return this.stopSubscriptionServices(request);
|
|
121
148
|
case 'mobile(subscription.restart)':
|
|
122
149
|
return this.restartSubscriptionServices(request);
|
|
150
|
+
case 'mobile(storage.restore)':
|
|
151
|
+
return this.mobileRestore(request);
|
|
152
|
+
case 'mobile(storage.backup)':
|
|
153
|
+
return this.mobileBackup();
|
|
123
154
|
default:
|
|
124
155
|
throw new Error(`Unable to handle message of type ${type}`);
|
|
125
156
|
}
|
|
@@ -84,6 +84,7 @@ export default class KoniState {
|
|
|
84
84
|
sign(url: string, request: RequestSign, account: AccountJson): Promise<ResponseSigning>;
|
|
85
85
|
get authSubjectV2(): BehaviorSubject<import("@subwallet/extension-base/background/types").AuthorizeRequest[]>;
|
|
86
86
|
generateDefaultBalanceMap(): Record<string, BalanceItem>;
|
|
87
|
+
private afterChainServiceInit;
|
|
87
88
|
init(): Promise<void>;
|
|
88
89
|
initMantaPay(password: string): Promise<void>;
|
|
89
90
|
private startSubscription;
|
|
@@ -23,11 +23,11 @@ import RequestService from '@subwallet/extension-base/services/request-service';
|
|
|
23
23
|
import SettingService from '@subwallet/extension-base/services/setting-service/SettingService';
|
|
24
24
|
import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService';
|
|
25
25
|
import { SubscanService } from '@subwallet/extension-base/services/subscan-service';
|
|
26
|
-
import {
|
|
26
|
+
import { SUBSCAN_API_CHAIN_MAP, SUBSCAN_BALANCE_CHAIN_MAP_REVERSE } from '@subwallet/extension-base/services/subscan-service/subscan-chain-map';
|
|
27
27
|
import TransactionService from '@subwallet/extension-base/services/transaction-service';
|
|
28
28
|
import WalletConnectService from '@subwallet/extension-base/services/wallet-connect-service';
|
|
29
29
|
import AccountRefStore from '@subwallet/extension-base/stores/AccountRef';
|
|
30
|
-
import { stripUrl } from '@subwallet/extension-base/utils';
|
|
30
|
+
import { stripUrl, TARGET_ENV } from '@subwallet/extension-base/utils';
|
|
31
31
|
import { isContractAddress, parseContractInput } from '@subwallet/extension-base/utils/eth/parseTransaction';
|
|
32
32
|
import { createPromiseHandler } from '@subwallet/extension-base/utils/promise';
|
|
33
33
|
import { decodePair } from '@subwallet/keyring/pair/decode';
|
|
@@ -84,14 +84,14 @@ export default class KoniState {
|
|
|
84
84
|
this.eventService = new EventService();
|
|
85
85
|
this.dbService = new DatabaseService(this.eventService);
|
|
86
86
|
this.keyringService = new KeyringService(this.eventService);
|
|
87
|
-
this.subscanService = new SubscanService();
|
|
88
87
|
this.notificationService = new NotificationService();
|
|
89
88
|
this.chainService = new ChainService(this.dbService, this.eventService);
|
|
89
|
+
this.subscanService = new SubscanService(SUBSCAN_API_CHAIN_MAP);
|
|
90
90
|
this.settingService = new SettingService();
|
|
91
91
|
this.requestService = new RequestService(this.chainService, this.settingService, this.keyringService);
|
|
92
92
|
this.priceService = new PriceService(this.dbService, this.eventService, this.chainService);
|
|
93
93
|
this.balanceService = new BalanceService(this.chainService);
|
|
94
|
-
this.historyService = new HistoryService(this.dbService, this.chainService, this.eventService, this.keyringService);
|
|
94
|
+
this.historyService = new HistoryService(this.dbService, this.chainService, this.eventService, this.keyringService, this.subscanService);
|
|
95
95
|
this.transactionService = new TransactionService(this.chainService, this.eventService, this.requestService, this.balanceService, this.historyService, this.notificationService, this.dbService);
|
|
96
96
|
this.walletConnectService = new WalletConnectService(this, this.requestService);
|
|
97
97
|
this.migrationService = new MigrationService(this, this.eventService);
|
|
@@ -102,7 +102,9 @@ export default class KoniState {
|
|
|
102
102
|
this.logger = createLogger('State');
|
|
103
103
|
|
|
104
104
|
// Init state
|
|
105
|
-
|
|
105
|
+
if (TARGET_ENV !== 'mobile') {
|
|
106
|
+
this.init().catch(console.error);
|
|
107
|
+
}
|
|
106
108
|
}
|
|
107
109
|
|
|
108
110
|
// Clone from polkadot.js
|
|
@@ -198,9 +200,13 @@ export default class KoniState {
|
|
|
198
200
|
});
|
|
199
201
|
return balanceMap;
|
|
200
202
|
}
|
|
203
|
+
afterChainServiceInit() {
|
|
204
|
+
this.subscanService.setSubscanChainMap(this.chainService.getSubscanChainMap());
|
|
205
|
+
}
|
|
201
206
|
async init() {
|
|
202
207
|
await this.eventService.waitCryptoReady;
|
|
203
208
|
await this.chainService.init();
|
|
209
|
+
this.afterChainServiceInit();
|
|
204
210
|
await this.migrationService.run();
|
|
205
211
|
this.eventService.emit('chain.ready', true);
|
|
206
212
|
this.onReady();
|
|
@@ -1469,7 +1475,7 @@ export default class KoniState {
|
|
|
1469
1475
|
symbol
|
|
1470
1476
|
}) => {
|
|
1471
1477
|
var _currentAssetSettings;
|
|
1472
|
-
const chain =
|
|
1478
|
+
const chain = SUBSCAN_BALANCE_CHAIN_MAP_REVERSE[network];
|
|
1473
1479
|
const chainInfo = chain ? chainMap[chain] : null;
|
|
1474
1480
|
const balanceIsEmpty = (!balance || balance === '0') && (!locked || locked === '0') && (!bonded || bonded === '0');
|
|
1475
1481
|
|
|
@@ -1478,10 +1484,11 @@ export default class KoniState {
|
|
|
1478
1484
|
return;
|
|
1479
1485
|
}
|
|
1480
1486
|
const tokenKey = `${chain}-${category === 'native' ? 'NATIVE' : 'LOCAL'}-${symbol.toUpperCase()}`;
|
|
1481
|
-
|
|
1487
|
+
const existedKey = Object.keys(assetMap).find(v => v.toLowerCase() === tokenKey.toLowerCase());
|
|
1488
|
+
if (existedKey && !((_currentAssetSettings = currentAssetSettings[existedKey]) !== null && _currentAssetSettings !== void 0 && _currentAssetSettings.visible)) {
|
|
1482
1489
|
needEnableChains.push(chain);
|
|
1483
|
-
needActiveTokens.push(
|
|
1484
|
-
currentAssetSettings[
|
|
1490
|
+
needActiveTokens.push(existedKey);
|
|
1491
|
+
currentAssetSettings[existedKey] = {
|
|
1485
1492
|
visible: true
|
|
1486
1493
|
};
|
|
1487
1494
|
}
|
|
@@ -1553,6 +1560,7 @@ export default class KoniState {
|
|
|
1553
1560
|
this.chainService.resetWallet(resetAll);
|
|
1554
1561
|
await this.walletConnectService.resetWallet(resetAll);
|
|
1555
1562
|
await this.chainService.init();
|
|
1563
|
+
this.afterChainServiceInit();
|
|
1556
1564
|
}
|
|
1557
1565
|
async enableMantaPay(updateStore, address, password, seedPhrase) {
|
|
1558
1566
|
var _this$chainService3, _this$chainService3$m, _this$chainService4, _this$chainService4$m, _this$chainService4$m2, _this$chainService11, _this$chainService11$, _this$chainService11$2;
|
|
@@ -163,7 +163,7 @@ export class KoniSubscription {
|
|
|
163
163
|
initCrowdloanSubscription(addresses, substrateApiMap, onlyRunOnFirstTime) {
|
|
164
164
|
const subscriptionPromise = subscribeCrowdloan(addresses, substrateApiMap, (networkKey, rs) => {
|
|
165
165
|
this.state.setCrowdloanItem(networkKey, rs);
|
|
166
|
-
}
|
|
166
|
+
});
|
|
167
167
|
if (onlyRunOnFirstTime) {
|
|
168
168
|
subscriptionPromise.then(unsub => {
|
|
169
169
|
unsub && unsub();
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"./cjs/detectPackage.js"
|
|
18
18
|
],
|
|
19
19
|
"type": "module",
|
|
20
|
-
"version": "1.1.
|
|
20
|
+
"version": "1.1.24-0",
|
|
21
21
|
"main": "./cjs/index.js",
|
|
22
22
|
"module": "./index.js",
|
|
23
23
|
"types": "./index.d.ts",
|
|
@@ -673,6 +673,16 @@
|
|
|
673
673
|
"require": "./cjs/services/history-service/helpers/recoverHistoryStatus.js",
|
|
674
674
|
"default": "./services/history-service/helpers/recoverHistoryStatus.js"
|
|
675
675
|
},
|
|
676
|
+
"./services/history-service/helpers/subscan-extrinsic-parser-helper": {
|
|
677
|
+
"types": "./services/history-service/helpers/subscan-extrinsic-parser-helper.d.ts",
|
|
678
|
+
"require": "./cjs/services/history-service/helpers/subscan-extrinsic-parser-helper.js",
|
|
679
|
+
"default": "./services/history-service/helpers/subscan-extrinsic-parser-helper.js"
|
|
680
|
+
},
|
|
681
|
+
"./services/history-service/subscan-history": {
|
|
682
|
+
"types": "./services/history-service/subscan-history.d.ts",
|
|
683
|
+
"require": "./cjs/services/history-service/subscan-history.js",
|
|
684
|
+
"default": "./services/history-service/subscan-history.js"
|
|
685
|
+
},
|
|
676
686
|
"./services/history-service/subsquid-multi-chain-history": {
|
|
677
687
|
"types": "./services/history-service/subsquid-multi-chain-history.d.ts",
|
|
678
688
|
"require": "./cjs/services/history-service/subsquid-multi-chain-history.js",
|
|
@@ -1312,11 +1322,11 @@
|
|
|
1312
1322
|
"@reduxjs/toolkit": "^1.9.1",
|
|
1313
1323
|
"@sora-substrate/type-definitions": "^1.17.7",
|
|
1314
1324
|
"@substrate/connect": "^0.7.26",
|
|
1315
|
-
"@subwallet/chain-list": "0.2.
|
|
1316
|
-
"@subwallet/extension-base": "^1.1.
|
|
1317
|
-
"@subwallet/extension-chains": "^1.1.
|
|
1318
|
-
"@subwallet/extension-dapp": "^1.1.
|
|
1319
|
-
"@subwallet/extension-inject": "^1.1.
|
|
1325
|
+
"@subwallet/chain-list": "0.2.26",
|
|
1326
|
+
"@subwallet/extension-base": "^1.1.24-0",
|
|
1327
|
+
"@subwallet/extension-chains": "^1.1.24-0",
|
|
1328
|
+
"@subwallet/extension-dapp": "^1.1.24-0",
|
|
1329
|
+
"@subwallet/extension-inject": "^1.1.24-0",
|
|
1320
1330
|
"@subwallet/keyring": "^0.1.1",
|
|
1321
1331
|
"@subwallet/ui-keyring": "^0.1.1",
|
|
1322
1332
|
"@walletconnect/sign-client": "^2.8.4",
|
|
@@ -1331,6 +1341,7 @@
|
|
|
1331
1341
|
"buffer": "^6.0.3",
|
|
1332
1342
|
"cross-fetch": "^3.1.5",
|
|
1333
1343
|
"dexie": "^3.2.2",
|
|
1344
|
+
"dexie-export-import": "^4.0.7",
|
|
1334
1345
|
"eth-simple-keyring": "^4.2.0",
|
|
1335
1346
|
"ethereumjs-tx": "^2.1.2",
|
|
1336
1347
|
"ethereumjs-util": "^7.1.5",
|
package/packageInfo.js
CHANGED
|
@@ -7,5 +7,5 @@ export const packageInfo = {
|
|
|
7
7
|
name: '@subwallet/extension-base',
|
|
8
8
|
path: (import.meta && import.meta.url) ? new URL(import.meta.url).pathname.substring(0, new URL(import.meta.url).pathname.lastIndexOf('/') + 1) : 'auto',
|
|
9
9
|
type: 'esm',
|
|
10
|
-
version: '1.1.
|
|
10
|
+
version: '1.1.24-0'
|
|
11
11
|
};
|
|
@@ -17,6 +17,7 @@ export declare const _BALANCE_CHAIN_GROUP: {
|
|
|
17
17
|
bifrost: string[];
|
|
18
18
|
statemine: string[];
|
|
19
19
|
kusama: string[];
|
|
20
|
+
centrifuge: string[];
|
|
20
21
|
};
|
|
21
22
|
export declare const _BALANCE_TOKEN_GROUP: {
|
|
22
23
|
crab: string[];
|
|
@@ -71,6 +72,7 @@ export declare const _TRANSFER_CHAIN_GROUP: {
|
|
|
71
72
|
sora_substrate: string[];
|
|
72
73
|
avail: string[];
|
|
73
74
|
pendulum: string[];
|
|
75
|
+
centrifuge: string[];
|
|
74
76
|
};
|
|
75
77
|
export declare const _BALANCE_PARSING_CHAIN_GROUP: {
|
|
76
78
|
bobabeam: string[];
|
|
@@ -30,9 +30,10 @@ export const _BALANCE_CHAIN_GROUP = {
|
|
|
30
30
|
equilibrium_parachain: ['equilibrium_parachain'],
|
|
31
31
|
bifrost: ['bifrost', 'acala', 'karura', 'acala_testnet', 'pioneer', 'bitcountry', 'bifrost_dot', 'hydradx_main', 'pendulum', 'amplitude'],
|
|
32
32
|
statemine: ['statemine', 'astar', 'shiden', 'statemint', 'moonbeam', 'moonbase', 'moonriver', 'crabParachain', 'darwinia2', 'parallel', 'calamari'],
|
|
33
|
-
kusama: ['kusama', 'kintsugi', 'kintsugi_test', 'interlay', 'acala', 'statemint', 'karura', 'bifrost']
|
|
33
|
+
kusama: ['kusama', 'kintsugi', 'kintsugi_test', 'interlay', 'acala', 'statemint', 'karura', 'bifrost'],
|
|
34
|
+
// perhaps there are some runtime updates
|
|
35
|
+
centrifuge: ['centrifuge']
|
|
34
36
|
};
|
|
35
|
-
|
|
36
37
|
export const _BALANCE_TOKEN_GROUP = {
|
|
37
38
|
crab: ['CKTON', 'PKTON'],
|
|
38
39
|
bitcountry: ['BIT']
|
|
@@ -194,7 +195,8 @@ export const _TRANSFER_CHAIN_GROUP = {
|
|
|
194
195
|
riochain: ['riochain'],
|
|
195
196
|
sora_substrate: ['sora_substrate'],
|
|
196
197
|
avail: ['kate', 'goldberg_testnet'],
|
|
197
|
-
pendulum: ['pendulum', 'amplitude', 'amplitude_test']
|
|
198
|
+
pendulum: ['pendulum', 'amplitude', 'amplitude_test'],
|
|
199
|
+
centrifuge: ['centrifuge']
|
|
198
200
|
};
|
|
199
201
|
export const _BALANCE_PARSING_CHAIN_GROUP = {
|
|
200
202
|
bobabeam: ['bobabeam', 'bobabase']
|
|
@@ -113,4 +113,5 @@ export declare class ChainService {
|
|
|
113
113
|
getMetadata(chain: string): import("dexie").PromiseExtended<IMetadataItem | undefined>;
|
|
114
114
|
upsertMetadata(chain: string, metadata: IMetadataItem): import("dexie").PromiseExtended<unknown>;
|
|
115
115
|
getMetadataByHash(hash: string): import("dexie").PromiseExtended<IMetadataItem | undefined>;
|
|
116
|
+
getSubscanChainMap(reverse?: boolean): Record<string, string>;
|
|
116
117
|
}
|
|
@@ -1381,4 +1381,22 @@ export class ChainService {
|
|
|
1381
1381
|
getMetadataByHash(hash) {
|
|
1382
1382
|
return this.dbService.stores.metadata.getMetadataByGenesisHash(hash);
|
|
1383
1383
|
}
|
|
1384
|
+
getSubscanChainMap(reverse) {
|
|
1385
|
+
const result = {};
|
|
1386
|
+
const chainInfoMap = this.getChainInfoMap();
|
|
1387
|
+
Object.values(chainInfoMap).forEach(i => {
|
|
1388
|
+
var _i$extraInfo;
|
|
1389
|
+
if (!((_i$extraInfo = i.extraInfo) !== null && _i$extraInfo !== void 0 && _i$extraInfo.subscanSlug)) {
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
if (!reverse) {
|
|
1393
|
+
var _i$extraInfo2;
|
|
1394
|
+
result[i.slug] = (_i$extraInfo2 = i.extraInfo) === null || _i$extraInfo2 === void 0 ? void 0 : _i$extraInfo2.subscanSlug;
|
|
1395
|
+
} else {
|
|
1396
|
+
var _i$extraInfo3;
|
|
1397
|
+
result[(_i$extraInfo3 = i.extraInfo) === null || _i$extraInfo3 === void 0 ? void 0 : _i$extraInfo3.subscanSlug] = i.slug;
|
|
1398
|
+
}
|
|
1399
|
+
});
|
|
1400
|
+
return result;
|
|
1401
|
+
}
|
|
1384
1402
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes';
|
|
2
|
+
import { ExtrinsicItem } from '@subwallet/extension-base/services/subscan-service/types';
|
|
3
|
+
export declare type ExtrinsicParserFunction = (item: TransactionHistoryItem) => TransactionHistoryItem | null;
|
|
4
|
+
export declare function getExtrinsicParserKey(extrinsicItem: ExtrinsicItem): string;
|
|
5
|
+
export declare const subscanExtrinsicParserMap: Record<string, ExtrinsicParserFunction>;
|
|
6
|
+
export declare const supportedExtrinsicParser: string[];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Copyright 2019-2022 @subwallet/extension-koni authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
5
|
+
import { encodeAddress } from '@polkadot/util-crypto';
|
|
6
|
+
export function getExtrinsicParserKey(extrinsicItem) {
|
|
7
|
+
return `${extrinsicItem.call_module}.${extrinsicItem.call_module_function}`;
|
|
8
|
+
}
|
|
9
|
+
function paramJsonParse(item) {
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(item.data || '[]');
|
|
12
|
+
} catch (e) {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function balanceTransferParserFunction(item) {
|
|
17
|
+
const params = paramJsonParse(item);
|
|
18
|
+
params.forEach(p => {
|
|
19
|
+
if (p.name === 'dest') {
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
21
|
+
const toPublicKey = p.value.id || p.value.Id;
|
|
22
|
+
if (toPublicKey) {
|
|
23
|
+
item.to = encodeAddress(toPublicKey, 42);
|
|
24
|
+
}
|
|
25
|
+
} else if (p.name === 'value') {
|
|
26
|
+
if (item.amount) {
|
|
27
|
+
item.amount.value = p.value;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
item.type = ExtrinsicType.TRANSFER_BALANCE;
|
|
32
|
+
if (!item.to) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
return item;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// todo: will support other type later
|
|
39
|
+
export const subscanExtrinsicParserMap = {
|
|
40
|
+
'balances.transfer': balanceTransferParserFunction,
|
|
41
|
+
'balances.transfer_keep_alive': balanceTransferParserFunction,
|
|
42
|
+
'balances.transfer_allow_death': balanceTransferParserFunction
|
|
43
|
+
};
|
|
44
|
+
export const supportedExtrinsicParser = Object.keys(subscanExtrinsicParserMap);
|
|
@@ -1,24 +1,30 @@
|
|
|
1
1
|
import { TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes';
|
|
2
|
-
import {
|
|
2
|
+
import { PersistDataServiceInterface, ServiceStatus, StoppableServiceInterface } from '@subwallet/extension-base/services/base/types';
|
|
3
3
|
import { ChainService } from '@subwallet/extension-base/services/chain-service';
|
|
4
4
|
import { EventService } from '@subwallet/extension-base/services/event-service';
|
|
5
5
|
import { KeyringService } from '@subwallet/extension-base/services/keyring-service';
|
|
6
6
|
import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService';
|
|
7
|
+
import { SubscanService } from '@subwallet/extension-base/services/subscan-service';
|
|
7
8
|
import { BehaviorSubject } from 'rxjs';
|
|
8
|
-
export declare class HistoryService implements StoppableServiceInterface, PersistDataServiceInterface
|
|
9
|
+
export declare class HistoryService implements StoppableServiceInterface, PersistDataServiceInterface {
|
|
9
10
|
#private;
|
|
10
11
|
private dbService;
|
|
11
12
|
private chainService;
|
|
12
13
|
private eventService;
|
|
13
14
|
private keyringService;
|
|
15
|
+
private subscanService;
|
|
14
16
|
private historySubject;
|
|
15
|
-
constructor(dbService: DatabaseService, chainService: ChainService, eventService: EventService, keyringService: KeyringService);
|
|
17
|
+
constructor(dbService: DatabaseService, chainService: ChainService, eventService: EventService, keyringService: KeyringService, subscanService: SubscanService);
|
|
16
18
|
private fetchPromise;
|
|
17
|
-
private interval;
|
|
18
19
|
private recoverInterval;
|
|
19
20
|
private fetchAndLoadHistories;
|
|
20
21
|
getHistories(): Promise<TransactionHistoryItem<import("@subwallet/extension-base/background/KoniTypes").ExtrinsicType.TRANSFER_BALANCE>[]>;
|
|
21
22
|
getHistorySubject(): Promise<BehaviorSubject<TransactionHistoryItem<import("@subwallet/extension-base/background/KoniTypes").ExtrinsicType.TRANSFER_BALANCE>[]>>;
|
|
23
|
+
private fetchSubscanTransactionHistory;
|
|
24
|
+
subscribeHistories(chain: string, address: string, cb: (items: TransactionHistoryItem[]) => void): {
|
|
25
|
+
unsubscribe: () => void;
|
|
26
|
+
value: TransactionHistoryItem<import("@subwallet/extension-base/background/KoniTypes").ExtrinsicType.TRANSFER_BALANCE>[];
|
|
27
|
+
};
|
|
22
28
|
updateHistories(chain: string, extrinsicHash: string, updateData: Partial<TransactionHistoryItem>): Promise<void>;
|
|
23
29
|
updateHistoryByExtrinsicHash(extrinsicHash: string, updateData: Partial<TransactionHistoryItem>): Promise<void>;
|
|
24
30
|
insertHistories(historyItems: TransactionHistoryItem[]): Promise<void>;
|
|
@@ -27,8 +33,6 @@ export declare class HistoryService implements StoppableServiceInterface, Persis
|
|
|
27
33
|
status: ServiceStatus;
|
|
28
34
|
loadData(): Promise<void>;
|
|
29
35
|
persistData(): Promise<void>;
|
|
30
|
-
startCron(): Promise<void>;
|
|
31
|
-
stopCron(): Promise<void>;
|
|
32
36
|
startRecoverHistories(): Promise<void>;
|
|
33
37
|
stopRecoverHistories(): Promise<void>;
|
|
34
38
|
recoverHistories(): Promise<void>;
|
|
@@ -2,24 +2,32 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
import { ExtrinsicStatus } from '@subwallet/extension-base/background/KoniTypes';
|
|
5
|
-
import { CRON_RECOVER_HISTORY_INTERVAL
|
|
5
|
+
import { CRON_RECOVER_HISTORY_INTERVAL } from '@subwallet/extension-base/constants';
|
|
6
6
|
import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
|
|
7
7
|
import { historyRecover, HistoryRecoverStatus } from '@subwallet/extension-base/services/history-service/helpers/recoverHistoryStatus';
|
|
8
|
+
import { getExtrinsicParserKey } from '@subwallet/extension-base/services/history-service/helpers/subscan-extrinsic-parser-helper';
|
|
9
|
+
import { parseSubscanExtrinsicData, parseSubscanTransferData } from '@subwallet/extension-base/services/history-service/subscan-history';
|
|
10
|
+
import { reformatAddress } from '@subwallet/extension-base/utils';
|
|
8
11
|
import { createPromiseHandler } from '@subwallet/extension-base/utils/promise';
|
|
9
12
|
import { keyring } from '@subwallet/ui-keyring';
|
|
10
13
|
import { BehaviorSubject } from 'rxjs';
|
|
14
|
+
function filterHistoryItemByAddressAndChain(chain, address) {
|
|
15
|
+
return item => {
|
|
16
|
+
return item.chain === chain && item.address === address;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
11
19
|
export class HistoryService {
|
|
12
20
|
historySubject = new BehaviorSubject([]);
|
|
13
21
|
#needRecoveryHistories = {};
|
|
14
|
-
constructor(dbService, chainService, eventService, keyringService) {
|
|
22
|
+
constructor(dbService, chainService, eventService, keyringService, subscanService) {
|
|
15
23
|
this.dbService = dbService;
|
|
16
24
|
this.chainService = chainService;
|
|
17
25
|
this.eventService = eventService;
|
|
18
26
|
this.keyringService = keyringService;
|
|
27
|
+
this.subscanService = subscanService;
|
|
19
28
|
this.init().catch(console.error);
|
|
20
29
|
}
|
|
21
30
|
fetchPromise = null;
|
|
22
|
-
interval = undefined;
|
|
23
31
|
recoverInterval = undefined;
|
|
24
32
|
async fetchAndLoadHistories(addresses) {
|
|
25
33
|
if (!addresses || addresses.length === 0) {
|
|
@@ -60,6 +68,74 @@ export class HistoryService {
|
|
|
60
68
|
await this.getHistories();
|
|
61
69
|
return this.historySubject;
|
|
62
70
|
}
|
|
71
|
+
fetchSubscanTransactionHistory(chain, address) {
|
|
72
|
+
if (!this.subscanService.checkSupportedSubscanChain(chain)) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const chainInfo = this.chainService.getChainInfoByKey(chain);
|
|
76
|
+
const excludeExtrinsicParserKeys = ['balances.transfer_all'];
|
|
77
|
+
|
|
78
|
+
// Note: fetchAllPossibleExtrinsicItems and fetchAllPossibleTransferItems-receive can run parallelly
|
|
79
|
+
// Hover, fetchAllPossibleTransferItems-sent must run after fetchAllPossibleExtrinsicItems,
|
|
80
|
+
// to avoid "duplicate Extrinsic Hash between items" problem
|
|
81
|
+
|
|
82
|
+
this.subscanService.fetchAllPossibleExtrinsicItems(chain, address, extrinsicItems => {
|
|
83
|
+
const result = [];
|
|
84
|
+
extrinsicItems.forEach(x => {
|
|
85
|
+
const item = parseSubscanExtrinsicData(address, x, chainInfo);
|
|
86
|
+
if (item) {
|
|
87
|
+
result.push(item);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
this.addHistoryItems(result).catch(e => {
|
|
91
|
+
console.log('addHistoryItems in fetchAllPossibleExtrinsicItems error', e);
|
|
92
|
+
});
|
|
93
|
+
}).then(extrinsicItems => {
|
|
94
|
+
const excludeTransferExtrinsicHash = [];
|
|
95
|
+
extrinsicItems.forEach(x => {
|
|
96
|
+
if (!excludeExtrinsicParserKeys.includes(getExtrinsicParserKey(x))) {
|
|
97
|
+
excludeTransferExtrinsicHash.push(x.extrinsic_hash);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
this.subscanService.fetchAllPossibleTransferItems(chain, address, 'sent', transferItems => {
|
|
101
|
+
const result = [];
|
|
102
|
+
transferItems.forEach(t => {
|
|
103
|
+
if (!excludeTransferExtrinsicHash.includes(t.hash)) {
|
|
104
|
+
result.push(parseSubscanTransferData(address, t, chainInfo));
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
this.addHistoryItems(result).catch(e => {
|
|
108
|
+
console.log('addHistoryItems in fetchAllPossibleTransferItems-sent error', e);
|
|
109
|
+
});
|
|
110
|
+
}).catch(e => {
|
|
111
|
+
console.log('fetchAllPossibleTransferItems-sent error', e);
|
|
112
|
+
});
|
|
113
|
+
}).catch(e => {
|
|
114
|
+
console.log('fetchAllPossibleExtrinsicItems error', e);
|
|
115
|
+
});
|
|
116
|
+
this.subscanService.fetchAllPossibleTransferItems(chain, address, 'received', transferItems => {
|
|
117
|
+
const result = [];
|
|
118
|
+
transferItems.forEach(t => {
|
|
119
|
+
result.push(parseSubscanTransferData(address, t, chainInfo));
|
|
120
|
+
});
|
|
121
|
+
this.addHistoryItems(result).catch(e => {
|
|
122
|
+
console.log('addHistoryItems in fetchAllPossibleTransferItems-receive error', e);
|
|
123
|
+
});
|
|
124
|
+
}).catch(e => {
|
|
125
|
+
console.log('fetchAllPossibleTransferItems-receive error', e);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
subscribeHistories(chain, address, cb) {
|
|
129
|
+
const _address = reformatAddress(address);
|
|
130
|
+
const subscription = this.historySubject.subscribe(items => {
|
|
131
|
+
cb(items.filter(filterHistoryItemByAddressAndChain(chain, _address)));
|
|
132
|
+
});
|
|
133
|
+
this.fetchSubscanTransactionHistory(chain, _address);
|
|
134
|
+
return {
|
|
135
|
+
unsubscribe: subscription.unsubscribe,
|
|
136
|
+
value: this.historySubject.getValue().filter(filterHistoryItemByAddressAndChain(chain, _address))
|
|
137
|
+
};
|
|
138
|
+
}
|
|
63
139
|
async updateHistories(chain, extrinsicHash, updateData) {
|
|
64
140
|
const existedRecords = await this.dbService.getHistories({
|
|
65
141
|
chain,
|
|
@@ -110,17 +186,6 @@ export class HistoryService {
|
|
|
110
186
|
async persistData() {
|
|
111
187
|
await this.dbService.upsertHistory(this.historySubject.value);
|
|
112
188
|
}
|
|
113
|
-
async startCron() {
|
|
114
|
-
await this.getHistories();
|
|
115
|
-
this.interval = setInterval(() => {
|
|
116
|
-
this.getHistories().catch(console.error);
|
|
117
|
-
}, CRON_REFRESH_HISTORY_INTERVAL);
|
|
118
|
-
}
|
|
119
|
-
stopCron() {
|
|
120
|
-
clearTimeout(this.interval);
|
|
121
|
-
this.fetchPromise = null;
|
|
122
|
-
return Promise.resolve();
|
|
123
|
-
}
|
|
124
189
|
async startRecoverHistories() {
|
|
125
190
|
await this.recoverHistories();
|
|
126
191
|
this.recoverInterval = setInterval(() => {
|
|
@@ -175,12 +240,6 @@ export class HistoryService {
|
|
|
175
240
|
Promise.all([this.eventService.waitKeyringReady, this.eventService.waitChainReady]).then(() => {
|
|
176
241
|
this.getHistories().catch(console.log);
|
|
177
242
|
this.recoverProcessingHistory().catch(console.error);
|
|
178
|
-
this.eventService.on('account.add', () => {
|
|
179
|
-
(async () => {
|
|
180
|
-
await this.stopCron();
|
|
181
|
-
await this.startCron();
|
|
182
|
-
})().catch(console.error);
|
|
183
|
-
});
|
|
184
243
|
this.eventService.on('account.remove', address => {
|
|
185
244
|
this.removeHistoryByAddress(address).catch(console.error);
|
|
186
245
|
});
|
|
@@ -209,7 +268,6 @@ export class HistoryService {
|
|
|
209
268
|
await Promise.all([this.eventService.waitKeyringReady, this.eventService.waitChainReady]);
|
|
210
269
|
this.startPromiseHandler = createPromiseHandler();
|
|
211
270
|
this.status = ServiceStatus.STARTING;
|
|
212
|
-
await this.startCron();
|
|
213
271
|
this.status = ServiceStatus.STARTED;
|
|
214
272
|
this.startPromiseHandler.resolve();
|
|
215
273
|
} catch (e) {
|
|
@@ -225,7 +283,6 @@ export class HistoryService {
|
|
|
225
283
|
this.stopPromiseHandler = createPromiseHandler();
|
|
226
284
|
this.status = ServiceStatus.STOPPING;
|
|
227
285
|
await this.persistData();
|
|
228
|
-
await this.stopCron();
|
|
229
286
|
await this.stopRecoverHistories();
|
|
230
287
|
this.stopPromiseHandler.resolve();
|
|
231
288
|
this.status = ServiceStatus.STOPPED;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { _ChainInfo } from '@subwallet/chain-list/types';
|
|
2
|
+
import { TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes';
|
|
3
|
+
import { ExtrinsicItem, TransferItem } from '@subwallet/extension-base/services/subscan-service/types';
|
|
4
|
+
export declare function parseSubscanExtrinsicData(address: string, extrinsicItem: ExtrinsicItem, chainInfo: _ChainInfo): TransactionHistoryItem | null;
|
|
5
|
+
export declare function parseSubscanTransferData(address: string, transferItem: TransferItem, chainInfo: _ChainInfo): TransactionHistoryItem;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Copyright 2019-2022 @subwallet/extension-koni authors & contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { ChainType, ExtrinsicStatus, ExtrinsicType, TransactionDirection } from '@subwallet/extension-base/background/KoniTypes';
|
|
5
|
+
import { getExtrinsicParserKey, subscanExtrinsicParserMap, supportedExtrinsicParser } from '@subwallet/extension-base/services/history-service/helpers/subscan-extrinsic-parser-helper';
|
|
6
|
+
import { decodeAddress, encodeAddress, isEthereumAddress } from '@polkadot/util-crypto';
|
|
7
|
+
function autoFormatAddress(address) {
|
|
8
|
+
try {
|
|
9
|
+
if (isEthereumAddress(address)) {
|
|
10
|
+
return address;
|
|
11
|
+
} else {
|
|
12
|
+
const decoded = decodeAddress(address);
|
|
13
|
+
return encodeAddress(decoded, 42);
|
|
14
|
+
}
|
|
15
|
+
} catch (e) {
|
|
16
|
+
return '';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function parseSubscanExtrinsicData(address, extrinsicItem, chainInfo) {
|
|
20
|
+
var _chainInfo$substrateI, _chainInfo$evmInfo, _chainInfo$substrateI2, _chainInfo$evmInfo2;
|
|
21
|
+
const extrinsicParserKey = getExtrinsicParserKey(extrinsicItem);
|
|
22
|
+
if (!supportedExtrinsicParser.includes(extrinsicParserKey)) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const chainType = chainInfo.substrateInfo ? ChainType.SUBSTRATE : ChainType.EVM;
|
|
26
|
+
const nativeDecimals = ((_chainInfo$substrateI = chainInfo.substrateInfo) === null || _chainInfo$substrateI === void 0 ? void 0 : _chainInfo$substrateI.decimals) || ((_chainInfo$evmInfo = chainInfo.evmInfo) === null || _chainInfo$evmInfo === void 0 ? void 0 : _chainInfo$evmInfo.decimals) || 18;
|
|
27
|
+
const nativeSymbol = ((_chainInfo$substrateI2 = chainInfo.substrateInfo) === null || _chainInfo$substrateI2 === void 0 ? void 0 : _chainInfo$substrateI2.symbol) || ((_chainInfo$evmInfo2 = chainInfo.evmInfo) === null || _chainInfo$evmInfo2 === void 0 ? void 0 : _chainInfo$evmInfo2.symbol) || '';
|
|
28
|
+
const initData = {
|
|
29
|
+
address,
|
|
30
|
+
origin: 'subscan',
|
|
31
|
+
time: extrinsicItem.block_timestamp * 1000,
|
|
32
|
+
chainType,
|
|
33
|
+
from: address,
|
|
34
|
+
signature: extrinsicItem.signature,
|
|
35
|
+
fromName: undefined,
|
|
36
|
+
direction: TransactionDirection.SEND,
|
|
37
|
+
blockNumber: extrinsicItem.block_num,
|
|
38
|
+
blockHash: '',
|
|
39
|
+
chain: chainInfo.slug,
|
|
40
|
+
type: ExtrinsicType.UNKNOWN,
|
|
41
|
+
to: '',
|
|
42
|
+
toName: undefined,
|
|
43
|
+
extrinsicHash: extrinsicItem.extrinsic_hash,
|
|
44
|
+
amount: {
|
|
45
|
+
value: '0',
|
|
46
|
+
decimals: nativeDecimals,
|
|
47
|
+
symbol: nativeSymbol
|
|
48
|
+
},
|
|
49
|
+
data: extrinsicItem.params,
|
|
50
|
+
fee: {
|
|
51
|
+
value: extrinsicItem.fee,
|
|
52
|
+
decimals: nativeDecimals,
|
|
53
|
+
symbol: nativeSymbol
|
|
54
|
+
},
|
|
55
|
+
status: extrinsicItem.success ? ExtrinsicStatus.SUCCESS : ExtrinsicStatus.FAIL,
|
|
56
|
+
nonce: extrinsicItem.nonce
|
|
57
|
+
};
|
|
58
|
+
try {
|
|
59
|
+
return subscanExtrinsicParserMap[extrinsicParserKey](initData);
|
|
60
|
+
} catch (e) {
|
|
61
|
+
console.log('parseSubscanExtrinsicData error:', e, initData);
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export function parseSubscanTransferData(address, transferItem, chainInfo) {
|
|
66
|
+
var _chainInfo$substrateI3, _chainInfo$evmInfo3, _chainInfo$substrateI4, _chainInfo$evmInfo4;
|
|
67
|
+
const chainType = chainInfo.substrateInfo ? ChainType.SUBSTRATE : ChainType.EVM;
|
|
68
|
+
const nativeDecimals = ((_chainInfo$substrateI3 = chainInfo.substrateInfo) === null || _chainInfo$substrateI3 === void 0 ? void 0 : _chainInfo$substrateI3.decimals) || ((_chainInfo$evmInfo3 = chainInfo.evmInfo) === null || _chainInfo$evmInfo3 === void 0 ? void 0 : _chainInfo$evmInfo3.decimals) || 18;
|
|
69
|
+
const nativeSymbol = ((_chainInfo$substrateI4 = chainInfo.substrateInfo) === null || _chainInfo$substrateI4 === void 0 ? void 0 : _chainInfo$substrateI4.symbol) || ((_chainInfo$evmInfo4 = chainInfo.evmInfo) === null || _chainInfo$evmInfo4 === void 0 ? void 0 : _chainInfo$evmInfo4.symbol) || '';
|
|
70
|
+
const from = autoFormatAddress(transferItem.from);
|
|
71
|
+
const to = autoFormatAddress(transferItem.to);
|
|
72
|
+
return {
|
|
73
|
+
address,
|
|
74
|
+
origin: 'subscan',
|
|
75
|
+
time: transferItem.block_timestamp * 1000,
|
|
76
|
+
chainType,
|
|
77
|
+
from,
|
|
78
|
+
fromName: transferItem.from_account_display.display,
|
|
79
|
+
direction: address === from ? TransactionDirection.SEND : TransactionDirection.RECEIVED,
|
|
80
|
+
blockNumber: transferItem.block_num,
|
|
81
|
+
blockHash: '',
|
|
82
|
+
chain: chainInfo.slug,
|
|
83
|
+
type: ExtrinsicType.TRANSFER_BALANCE,
|
|
84
|
+
to,
|
|
85
|
+
toName: transferItem.to_account_display.display,
|
|
86
|
+
extrinsicHash: transferItem.hash,
|
|
87
|
+
amount: {
|
|
88
|
+
value: transferItem.amount,
|
|
89
|
+
decimals: 0,
|
|
90
|
+
symbol: transferItem.asset_symbol
|
|
91
|
+
},
|
|
92
|
+
fee: {
|
|
93
|
+
value: transferItem.fee,
|
|
94
|
+
decimals: nativeDecimals,
|
|
95
|
+
symbol: nativeSymbol
|
|
96
|
+
},
|
|
97
|
+
status: transferItem.success ? ExtrinsicStatus.SUCCESS : ExtrinsicStatus.FAIL,
|
|
98
|
+
nonce: transferItem.nonce
|
|
99
|
+
};
|
|
100
|
+
}
|