@subwallet/extension-base 0.8.1-wr2x → 0.8.1-wr3

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 (47) hide show
  1. package/background/KoniTypes.d.ts +31 -1
  2. package/background/KoniTypes.js +15 -1
  3. package/background/errors/BalanceError.d.ts +6 -0
  4. package/background/errors/BalanceError.js +33 -0
  5. package/background/handlers/State.js +2 -1
  6. package/cjs/background/KoniTypes.js +18 -2
  7. package/cjs/background/errors/BalanceError.js +39 -0
  8. package/cjs/background/handlers/State.js +2 -1
  9. package/cjs/koni/api/dotsama/balance.js +1 -0
  10. package/cjs/koni/background/handlers/Extension.js +140 -94
  11. package/cjs/koni/background/handlers/State.js +15 -11
  12. package/cjs/services/balance-service/index.js +95 -2
  13. package/cjs/services/chain-service/utils.js +13 -3
  14. package/cjs/services/notification-service/NotificationService.js +23 -1
  15. package/cjs/services/request-service/handler/PopupHandler.js +10 -16
  16. package/cjs/services/request-service/index.js +2 -6
  17. package/cjs/services/setting-service/SettingService.js +2 -1
  18. package/cjs/services/storage-service/DatabaseService.js +3 -2
  19. package/cjs/services/storage-service/db-stores/Balance.js +0 -25
  20. package/cjs/services/transaction-service/index.js +22 -6
  21. package/koni/api/dotsama/balance.d.ts +1 -0
  22. package/koni/api/dotsama/balance.js +1 -1
  23. package/koni/background/handlers/Extension.d.ts +4 -0
  24. package/koni/background/handlers/Extension.js +58 -14
  25. package/koni/background/handlers/State.d.ts +3 -1
  26. package/koni/background/handlers/State.js +15 -11
  27. package/package.json +8 -3
  28. package/services/balance-service/index.d.ts +7 -5
  29. package/services/balance-service/index.js +95 -2
  30. package/services/chain-service/utils.d.ts +1 -1
  31. package/services/chain-service/utils.js +13 -3
  32. package/services/notification-service/NotificationService.d.ts +6 -1
  33. package/services/notification-service/NotificationService.js +23 -1
  34. package/services/request-service/handler/PopupHandler.d.ts +0 -1
  35. package/services/request-service/handler/PopupHandler.js +10 -15
  36. package/services/request-service/index.d.ts +3 -2
  37. package/services/request-service/index.js +2 -6
  38. package/services/setting-service/SettingService.js +2 -1
  39. package/services/storage-service/DatabaseService.d.ts +2 -1
  40. package/services/storage-service/DatabaseService.js +3 -2
  41. package/services/storage-service/db-stores/Balance.js +0 -25
  42. package/services/transaction-service/index.d.ts +3 -1
  43. package/services/transaction-service/index.js +23 -7
  44. package/cjs/background/errors/EvmRpcError.js +0 -21
  45. package/cjs/background/errors/SubWalletProviderError.js +0 -17
  46. package/cjs/constants/ethereum.js +0 -19
  47. package/cjs/utils/eth/parseTransactionData.js +0 -284
@@ -9,7 +9,6 @@ import { createSubscription } from '@subwallet/extension-base/background/handler
9
9
  import { AccountExternalErrorCode, BasicTxErrorType, ChainType, ExternalRequestPromiseStatus, ExtrinsicType, TransferTxErrorType } from '@subwallet/extension-base/background/KoniTypes';
10
10
  import { ALL_ACCOUNT_KEY, ALL_GENESIS_HASH } from '@subwallet/extension-base/constants';
11
11
  import { ALLOWED_PATH } from '@subwallet/extension-base/defaults';
12
- import { getFreeBalance, subscribeFreeBalance } from '@subwallet/extension-base/koni/api/dotsama/balance';
13
12
  import { parseSubstrateTransaction } from '@subwallet/extension-base/koni/api/dotsama/parseTransaction';
14
13
  import { checkReferenceCount, checkSupportTransfer, createTransferExtrinsic } from '@subwallet/extension-base/koni/api/dotsama/transfer';
15
14
  import { getNftTransferExtrinsic, isRecipientSelf } from '@subwallet/extension-base/koni/api/nft/transfer';
@@ -574,6 +573,14 @@ export default class KoniExtension {
574
573
  const transformedAccounts = transformAccounts(storedAccounts);
575
574
  return transformedAccounts.filter(a => !a.isReadOnly).map(a => a.address);
576
575
  }
576
+ isAddressValidWithAuthType(address, accountAuthType) {
577
+ if (accountAuthType === 'substrate') {
578
+ return !isEthereumAddress(address);
579
+ } else if (accountAuthType === 'evm') {
580
+ return isEthereumAddress(address);
581
+ }
582
+ return true;
583
+ }
577
584
  filterAccountsByAccountAuthType(accounts, accountAuthType) {
578
585
  if (accountAuthType === 'substrate') {
579
586
  return accounts.filter(address => !isEthereumAddress(address));
@@ -647,11 +654,15 @@ export default class KoniExtension {
647
654
  _changeAuthorizationPerAcc(address, connectValue, url, callBack) {
648
655
  this.#koniState.getAuthorize(value => {
649
656
  assert(value, 'The source is not known');
650
- value[url].isAllowedMap[address] = connectValue;
651
- console.log('Devbu: ', value);
652
- this.#koniState.setAuthorize(value, () => {
657
+ if (this.isAddressValidWithAuthType(address, value[url].accountAuthType)) {
658
+ value[url].isAllowedMap[address] = connectValue;
659
+ console.log('Devbu: ', value);
660
+ this.#koniState.setAuthorize(value, () => {
661
+ callBack && callBack(value);
662
+ });
663
+ } else {
653
664
  callBack && callBack(value);
654
- });
665
+ }
655
666
  });
656
667
  }
657
668
  _changeAuthorizationBlock(connectValue, id) {
@@ -737,6 +748,12 @@ export default class KoniExtension {
737
748
  });
738
749
  return true;
739
750
  }
751
+ setCamera({
752
+ camera
753
+ }) {
754
+ this.#koniState.setCamera(camera);
755
+ return true;
756
+ }
740
757
  saveBrowserConfirmationType(data, id, port) {
741
758
  const cb = createSubscription(id, port);
742
759
  this.#koniState.setBrowserConfirmationType(data, cb);
@@ -914,7 +931,9 @@ export default class KoniExtension {
914
931
  this.#koniState.getAuthorize(value => {
915
932
  if (value && Object.keys(value).length) {
916
933
  Object.keys(value).forEach(url => {
917
- value[url].isAllowedMap[address] = isAllowed;
934
+ if (this.isAddressValidWithAuthType(address, value[url].accountAuthType)) {
935
+ value[url].isAllowedMap[address] = isAllowed;
936
+ }
918
937
  });
919
938
  this.#koniState.setAuthorize(value);
920
939
  }
@@ -1327,7 +1346,6 @@ export default class KoniExtension {
1327
1346
  } = inputData;
1328
1347
  const [errors,,, tokenInfo] = this.validateTransfer(tokenSlug, from, to, value, transferAll);
1329
1348
  const warnings = [];
1330
- const substrateApiMap = this.#koniState.getSubstrateApiMap();
1331
1349
  const evmApiMap = this.#koniState.getEvmApiMap();
1332
1350
  const chainInfo = this.#koniState.getChainInfo(networkKey);
1333
1351
  const nativeTokenInfo = this.#koniState.getNativeTokenInfo(networkKey);
@@ -1345,10 +1363,10 @@ export default class KoniExtension {
1345
1363
  let transaction;
1346
1364
 
1347
1365
  // Get native token amount
1348
- const freeBalance = await getFreeBalance(networkKey, from, substrateApiMap, evmApiMap, tokenSlug);
1366
+ const freeBalance = await this.#koniState.balanceService.getTokenFreeBalance(from, networkKey, tokenSlug);
1349
1367
  if (isEthereumAddress(from) && isEthereumAddress(to)) {
1350
1368
  chainType = ChainType.EVM;
1351
- const txVal = transferAll ? freeBalance : value || '0';
1369
+ const txVal = transferAll ? freeBalance.value : value || '0';
1352
1370
 
1353
1371
  // Estimate with EVM API
1354
1372
  if (_isTokenEvmSmartContract(tokenInfo)) {
@@ -1371,7 +1389,7 @@ export default class KoniExtension {
1371
1389
 
1372
1390
  // Additional validator
1373
1391
  const additionalValidator = swTran => {
1374
- if (new BN(freeBalance).lt(new BN(transferAmount.value))) {
1392
+ if (new BN(freeBalance.value).lt(new BN(transferAmount.value))) {
1375
1393
  var _swTran$errors;
1376
1394
  (_swTran$errors = swTran.errors) === null || _swTran$errors === void 0 ? void 0 : _swTran$errors.push(new TransactionError(BasicTxErrorType.NOT_ENOUGH_BALANCE));
1377
1395
  }
@@ -1518,17 +1536,25 @@ export default class KoniExtension {
1518
1536
  async validateCustomAsset(data) {
1519
1537
  return await this.#koniState.validateCustomAsset(data);
1520
1538
  }
1539
+ async getAddressFreeBalance({
1540
+ address,
1541
+ networkKey,
1542
+ token
1543
+ }) {
1544
+ return await this.#koniState.balanceService.getTokenFreeBalance(address, networkKey, token);
1545
+ }
1521
1546
  async subscribeAddressFreeBalance({
1522
1547
  address,
1523
1548
  networkKey,
1524
1549
  token
1525
1550
  }, id, port) {
1526
1551
  const cb = createSubscription(id, port);
1527
- this.createUnsubscriptionHandle(id, await subscribeFreeBalance(networkKey, address, this.#koniState.getSubstrateApiMap(), this.#koniState.getEvmApiMap(), token, cb));
1552
+ const [unsub, currentFreeBalance] = await this.#koniState.balanceService.subscribeTokenFreeBalance(address, networkKey, token, cb);
1553
+ this.createUnsubscriptionHandle(id, unsub);
1528
1554
  port.onDisconnect.addListener(() => {
1529
1555
  this.cancelSubscription(id);
1530
1556
  });
1531
- return id;
1557
+ return currentFreeBalance;
1532
1558
  }
1533
1559
  async transferCheckReferenceCount({
1534
1560
  address,
@@ -2695,6 +2721,18 @@ export default class KoniExtension {
2695
2721
  });
2696
2722
  return convertRs(transactionsSubject.getValue());
2697
2723
  }
2724
+ subscribeNotifications(id, port) {
2725
+ const cb = createSubscription(id, port);
2726
+ const notificationSubject = this.#koniState.notificationService.getNotificationSubject();
2727
+ const notificationSubscription = notificationSubject.subscribe(rs => {
2728
+ cb(rs);
2729
+ });
2730
+ port.onDisconnect.addListener(() => {
2731
+ notificationSubscription.unsubscribe();
2732
+ this.cancelSubscription(id);
2733
+ });
2734
+ return notificationSubject.value;
2735
+ }
2698
2736
 
2699
2737
  // --------------------------------------------------------------
2700
2738
  // eslint-disable-next-line @typescript-eslint/require-await
@@ -2743,8 +2781,6 @@ export default class KoniExtension {
2743
2781
  return this.seedCreate(request);
2744
2782
  case 'pri(seed.validate)':
2745
2783
  return this.seedValidate(request);
2746
- case 'pri(settings.notification)':
2747
- return this.#koniState.setNotification(request);
2748
2784
  case 'pri(signing.approve.signature)':
2749
2785
  return this.signingApproveSignature(request);
2750
2786
  case 'pri(signing.cancel)':
@@ -2821,6 +2857,8 @@ export default class KoniExtension {
2821
2857
  return await this.subscribeSettings(id, port);
2822
2858
  case 'pri(settings.saveAccountAllLogo)':
2823
2859
  return this.saveAccountAllLogo(request, id, port);
2860
+ case 'pri(settings.saveCamera)':
2861
+ return this.setCamera(request);
2824
2862
  case 'pri(settings.saveTheme)':
2825
2863
  return this.saveTheme(request, id, port);
2826
2864
  case 'pri(settings.saveBrowserConfirmationType)':
@@ -2903,6 +2941,8 @@ export default class KoniExtension {
2903
2941
  return await this.transferCheckSupporting(request);
2904
2942
  case 'pri(transfer.getExistentialDeposit)':
2905
2943
  return this.transferGetExistentialDeposit(request);
2944
+ case 'pri(freeBalance.get)':
2945
+ return this.getAddressFreeBalance(request);
2906
2946
  case 'pri(freeBalance.subscribe)':
2907
2947
  return this.subscribeAddressFreeBalance(request, id, port);
2908
2948
  case 'pri(subscription.cancel)':
@@ -3030,6 +3070,10 @@ export default class KoniExtension {
3030
3070
  case 'pri(transactions.subscribe)':
3031
3071
  return this.subscribeTransactions(id, port);
3032
3072
 
3073
+ // Notification
3074
+ case 'pri(notifications.subscribe)':
3075
+ return this.subscribeNotifications(id, port);
3076
+
3033
3077
  // Default
3034
3078
  default:
3035
3079
  throw new Error(`Unable to handle message of type ${type}`);
@@ -5,6 +5,7 @@ import { AccountJson, RequestAuthorizeTab, RequestRpcSend, RequestRpcSubscribe,
5
5
  import { BalanceService } from '@subwallet/extension-base/services/balance-service';
6
6
  import { _ChainConnectionStatus, _ChainState, _NetworkUpsertParams, _ValidateCustomAssetRequest } from '@subwallet/extension-base/services/chain-service/types';
7
7
  import { HistoryService } from '@subwallet/extension-base/services/history-service';
8
+ import NotificationService from '@subwallet/extension-base/services/notification-service/NotificationService';
8
9
  import { PriceService } from '@subwallet/extension-base/services/price-service';
9
10
  import { AuthUrls, MetaRequest, SignRequest } from '@subwallet/extension-base/services/request-service/types';
10
11
  import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService';
@@ -41,6 +42,7 @@ export default class KoniState {
41
42
  private stakingRewardSubject;
42
43
  private stakingRewardState;
43
44
  private lazyMap;
45
+ readonly notificationService: NotificationService;
44
46
  private chainService;
45
47
  dbService: DatabaseService;
46
48
  private cron;
@@ -65,7 +67,6 @@ export default class KoniState {
65
67
  rpcSubscribeConnected(_request: null, cb: ProviderInterfaceCallback, port: chrome.runtime.Port): void;
66
68
  rpcUnsubscribe(request: RequestRpcUnsubscribe, port: chrome.runtime.Port): Promise<boolean>;
67
69
  saveMetadata(meta: MetadataDef): void;
68
- setNotification(notification: string): boolean;
69
70
  sign(url: string, request: RequestSign, account: AccountJson): Promise<ResponseSigning>;
70
71
  get authSubjectV2(): BehaviorSubject<import("@subwallet/extension-base/background/types").AuthorizeRequest[]>;
71
72
  generateDefaultBalanceMap(): Record<string, BalanceItem>;
@@ -137,6 +138,7 @@ export default class KoniState {
137
138
  setSettings(settings: UiSettings, callback?: () => void): void;
138
139
  setTheme(theme: ThemeNames, callback?: (settingData: UiSettings) => void): void;
139
140
  setBrowserConfirmationType(browserConfirmationType: BrowserConfirmationType, callback?: (settingData: UiSettings) => void): void;
141
+ setCamera(value: boolean): void;
140
142
  subscribeSettingsSubject(): Subject<RequestSettingsType>;
141
143
  subscribeCurrentAccount(): Subject<CurrentAccountInfo>;
142
144
  getAccountAddress(): Promise<string | null | undefined>;
@@ -7,12 +7,12 @@ import { withErrorLog } from '@subwallet/extension-base/background/handlers/help
7
7
  import { isSubscriptionRunning, unsubscribe } from '@subwallet/extension-base/background/handlers/subscriptions';
8
8
  import { APIItemState, BasicTxErrorType, ChainType, EvmProviderErrorType, ExternalRequestPromiseStatus, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
9
9
  import { ALL_ACCOUNT_KEY, ALL_GENESIS_HASH } from '@subwallet/extension-base/constants';
10
- import { getFreeBalance } from '@subwallet/extension-base/koni/api/dotsama/balance';
11
10
  import { BalanceService } from '@subwallet/extension-base/services/balance-service';
12
11
  import { ChainService } from '@subwallet/extension-base/services/chain-service';
13
12
  import { _PREDEFINED_SINGLE_MODES } from '@subwallet/extension-base/services/chain-service/constants';
14
13
  import { _getEvmChainId, _getSubstrateGenesisHash, _isAssetFungibleToken, _isChainEnabled, _isChainTestNet, _isSubstrateParachain, _parseMetadataForSmartContractAsset } from '@subwallet/extension-base/services/chain-service/utils';
15
14
  import { HistoryService } from '@subwallet/extension-base/services/history-service';
15
+ import NotificationService from '@subwallet/extension-base/services/notification-service/NotificationService';
16
16
  import { PriceService } from '@subwallet/extension-base/services/price-service';
17
17
  import RequestService from '@subwallet/extension-base/services/request-service';
18
18
  import SettingService from '@subwallet/extension-base/services/setting-service/SettingService';
@@ -86,21 +86,19 @@ export default class KoniState {
86
86
  fastInterval: []
87
87
  };
88
88
  lazyMap = {};
89
-
90
- // TODO: consider making chainService public (or getter) and call function directly
91
-
92
89
  ready = false;
93
90
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
94
91
  constructor(providers = {}) {
95
92
  this.providers = providers;
96
93
  this.dbService = new DatabaseService();
94
+ this.notificationService = new NotificationService();
97
95
  this.chainService = new ChainService(this.dbService);
98
96
  this.settingService = new SettingService();
99
- this.requestService = new RequestService(this.chainService);
97
+ this.requestService = new RequestService(this.chainService, this.settingService);
100
98
  this.priceService = new PriceService(this.dbService, this.chainService);
101
- this.balanceService = new BalanceService(getFreeBalance);
99
+ this.balanceService = new BalanceService(this.chainService);
102
100
  this.historyService = new HistoryService(this.dbService, this.chainService);
103
- this.transactionService = new TransactionService(this.chainService, this.requestService, this.balanceService, this.historyService);
101
+ this.transactionService = new TransactionService(this.chainService, this.requestService, this.balanceService, this.historyService, this.notificationService);
104
102
  this.subscription = new KoniSubscription(this, this.dbService);
105
103
  this.cron = new KoniCron(this, this.subscription, this.dbService);
106
104
  this.logger = createLogger('State');
@@ -178,10 +176,6 @@ export default class KoniState {
178
176
  saveMetadata(meta) {
179
177
  this.requestService.saveMetadata(meta);
180
178
  }
181
- setNotification(notification) {
182
- this.requestService.setNotification(notification);
183
- return true;
184
- }
185
179
  sign(url, request, account) {
186
180
  return this.requestService.sign(url, request, account);
187
181
  }
@@ -667,6 +661,16 @@ export default class KoniState {
667
661
  });
668
662
  });
669
663
  }
664
+ setCamera(value) {
665
+ this.settingService.getSettings(settings => {
666
+ const newSettings = {
667
+ ...settings,
668
+ camera: value
669
+ };
670
+ console.log(newSettings, value);
671
+ this.settingService.setSettings(newSettings);
672
+ });
673
+ }
670
674
  subscribeSettingsSubject() {
671
675
  return this.settingService.getSubject();
672
676
  }
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "./cjs/detectPackage.js"
18
18
  ],
19
19
  "type": "module",
20
- "version": "0.8.1-wr2x",
20
+ "version": "0.8.1-wr3",
21
21
  "main": "./cjs/index.js",
22
22
  "module": "./index.js",
23
23
  "types": "./index.d.ts",
@@ -29,6 +29,11 @@
29
29
  "require": "./cjs/index.js",
30
30
  "default": "./index.js"
31
31
  },
32
+ "./background/errors/BalanceError": {
33
+ "types": "./background/errors/BalanceError.d.ts",
34
+ "require": "./cjs/background/errors/BalanceError.js",
35
+ "default": "./background/errors/BalanceError.js"
36
+ },
32
37
  "./background/errors/EvmProviderError": {
33
38
  "types": "./background/errors/EvmProviderError.d.ts",
34
39
  "require": "./cjs/background/errors/EvmProviderError.js",
@@ -1589,7 +1594,7 @@
1589
1594
  "@polkadot/hw-ledger": "^10.1.9",
1590
1595
  "@polkadot/keyring": "^10.2.1",
1591
1596
  "@polkadot/networks": "^10.2.1",
1592
- "@polkadot/phishing": "^0.18.12",
1597
+ "@polkadot/phishing": "^0.20.3",
1593
1598
  "@polkadot/react-identicon": "^2.9.14",
1594
1599
  "@polkadot/react-qr": "^2.9.14",
1595
1600
  "@polkadot/rpc-provider": "^9.10.3",
@@ -1606,7 +1611,7 @@
1606
1611
  "@sora-substrate/type-definitions": "^1.12.4",
1607
1612
  "@subsocial/types": "^0.6.8",
1608
1613
  "@substrate/connect": "^0.7.18",
1609
- "@subwallet/chain-list": "^0.0.13",
1614
+ "@subwallet/chain-list": "^0.0.16",
1610
1615
  "@subwallet/extension-base": "^0.8.1",
1611
1616
  "@subwallet/extension-chains": "^0.8.1",
1612
1617
  "@subwallet/extension-dapp": "^0.8.1",
@@ -1,7 +1,9 @@
1
- import { _EvmApi, _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types';
2
- declare type getFreeBalanceFunc = (chain: string, address: string, substrateApiMap: Record<string, _SubstrateApi>, evmApiMap: Record<string, _EvmApi>, tokenSlug?: string) => Promise<string>;
1
+ import { AmountData, BalanceItem } from '@subwallet/extension-base/background/KoniTypes';
2
+ import { ChainService } from '@subwallet/extension-base/services/chain-service';
3
3
  export declare class BalanceService {
4
- readonly getFreeBalance: getFreeBalanceFunc;
5
- constructor(getFreeBalance: getFreeBalanceFunc);
4
+ private chainService;
5
+ constructor(chainService: ChainService);
6
+ subscribeTokenFreeBalance(address: string, chain: string, tokenSlug: string | undefined, callback?: (rs: AmountData) => void): Promise<[() => void, AmountData]>;
7
+ getTokenFreeBalance(address: string, chain: string, tokenSlug?: string): Promise<AmountData>;
8
+ subscribeBalance(addresses: string[], chains: string[] | null, callback: (rs: BalanceItem) => void): () => void;
6
9
  }
7
- export {};
@@ -1,8 +1,101 @@
1
1
  // Copyright 2019-2022 @subwallet/extension-base authors & contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
+ import { BalanceError } from '@subwallet/extension-base/background/errors/BalanceError';
5
+ import { BalanceErrorType } from '@subwallet/extension-base/background/KoniTypes';
6
+ import { subscribeEVMBalance, subscribeSubstrateBalance } from '@subwallet/extension-base/koni/api/dotsama/balance';
7
+ import { state } from '@subwallet/extension-base/koni/background/handlers';
8
+ import { _PURE_EVM_CHAINS } from '@subwallet/extension-base/services/chain-service/constants';
9
+ import { _getChainNativeTokenSlug, _isChainEvmCompatible, _isPureEvmChain } from '@subwallet/extension-base/services/chain-service/utils';
10
+ import { categoryAddresses } from '@subwallet/extension-base/utils';
4
11
  export class BalanceService {
5
- constructor(getFreeBalance) {
6
- this.getFreeBalance = getFreeBalance;
12
+ constructor(chainService) {
13
+ this.chainService = chainService;
14
+
15
+ // Todo: Load data from db to balanceSubject
16
+ // Todo: Start subscribe balance and data
17
+ // Todo: Listen change and apply to balanceSubject
18
+ // Todo: Active/Chain
19
+ // Todo: Add/remove account
20
+ // Todo: Add new account
21
+ // Todo: Optimize get balance for single account and chain with cache
22
+ // Todo: Move everything of fetching balance to this service
23
+ }
24
+
25
+ async subscribeTokenFreeBalance(address, chain, tokenSlug, callback) {
26
+ const chainInfo = this.chainService.getChainInfoByKey(chain);
27
+ const chainState = this.chainService.getChainStateByKey(chain);
28
+ if (!chainInfo || !chainState || !chainState.active) {
29
+ return Promise.reject(new BalanceError(BalanceErrorType.NETWORK_ERROR, `Chain ${chain} is not active`));
30
+ }
31
+ const tSlug = tokenSlug || _getChainNativeTokenSlug(chainInfo);
32
+ const tokenInfo = this.chainService.getAssetBySlug(tSlug);
33
+ if (!tokenInfo) {
34
+ return Promise.reject(new BalanceError(BalanceErrorType.TOKEN_ERROR, `Token ${tSlug} is not supported`));
35
+ }
36
+ return new Promise((resolve, reject) => {
37
+ let hasError = true;
38
+ const unsub = this.subscribeBalance([address], [chain], rs => {
39
+ if (rs.tokenSlug === tSlug) {
40
+ hasError = false;
41
+ const balance = {
42
+ value: rs.free,
43
+ decimals: tokenInfo.decimals || 0,
44
+ symbol: tokenInfo.symbol
45
+ };
46
+ if (callback) {
47
+ callback(balance);
48
+ } else {
49
+ // Auto unsubscribe if no callback
50
+ unsub();
51
+ }
52
+ resolve([unsub, balance]);
53
+ }
54
+ });
55
+ setTimeout(() => {
56
+ if (hasError) {
57
+ unsub();
58
+ reject(new Error('Get Balance Timeout'));
59
+ }
60
+ }, 9999);
61
+ });
62
+ }
63
+ async getTokenFreeBalance(address, chain, tokenSlug) {
64
+ const [, balance] = await this.subscribeTokenFreeBalance(address, chain, tokenSlug);
65
+ return balance;
66
+ }
67
+ subscribeBalance(addresses, chains, callback) {
68
+ const [substrateAddresses, evmAddresses] = categoryAddresses(addresses);
69
+ const chainInfoMap = this.chainService.getChainInfoMap();
70
+ const chainStateMap = this.chainService.getChainStateMap();
71
+ const substrateApiMap = this.chainService.getSubstrateApiMap();
72
+ const evmApiMap = this.chainService.getEvmApiMap();
73
+
74
+ // Get data from chain or all chains
75
+ const chainList = chains || Object.keys(chainInfoMap);
76
+ // Filter active chain only
77
+ const useChainInfos = chainList.filter(c => chainStateMap[c] && chainStateMap[c].active).map(c => chainInfoMap[c]);
78
+
79
+ // Looping over each chain
80
+ const unsubList = useChainInfos.map(async chainInfo => {
81
+ const chainSlug = chainInfo.slug;
82
+ const useAddresses = _isChainEvmCompatible(chainInfo) ? evmAddresses : substrateAddresses;
83
+ if (_isPureEvmChain(chainInfo)) {
84
+ const nativeTokenInfo = state.getNativeTokenInfo(chainSlug);
85
+ return subscribeEVMBalance(chainSlug, useAddresses, evmApiMap, callback, nativeTokenInfo);
86
+ }
87
+ if (!useAddresses || useAddresses.length === 0 || _PURE_EVM_CHAINS.indexOf(chainSlug) > -1) {
88
+ return undefined;
89
+ }
90
+ const networkAPI = await substrateApiMap[chainSlug].isReady;
91
+ return subscribeSubstrateBalance(useAddresses, chainInfo, chainSlug, networkAPI, evmApiMap, callback);
92
+ });
93
+ return () => {
94
+ unsubList.forEach(subProm => {
95
+ subProm.then(unsub => {
96
+ unsub && unsub();
97
+ }).catch(console.error);
98
+ });
99
+ };
7
100
  }
8
101
  }
@@ -57,7 +57,7 @@ export declare function _getMultiChainAssetSymbol(multiChainAsset: _MultiChainAs
57
57
  export declare function _getAssetOriginChain(assetInfo: _ChainAsset): string;
58
58
  export declare function _getChainName(chainInfo: _ChainInfo): string;
59
59
  export declare function _getAssetDecimals(assetInfo: _ChainAsset): number;
60
- export declare function _getBlockExplorerFromChain(chainInfo: _ChainInfo): string;
60
+ export declare function _getBlockExplorerFromChain(chainInfo: _ChainInfo): string | undefined;
61
61
  export declare function _parseMetadataForSmartContractAsset(contractAddress: string): Record<string, string>;
62
62
  export declare function _isChainTestNet(chainInfo: _ChainInfo): boolean;
63
63
  export declare function _isAssetFungibleToken(chainAsset: _ChainAsset): boolean;
@@ -273,12 +273,22 @@ export function _getAssetDecimals(assetInfo) {
273
273
  return assetInfo.decimals || 0;
274
274
  }
275
275
  export function _getBlockExplorerFromChain(chainInfo) {
276
- var _chainInfo$substrateI12;
276
+ let blockExplorer;
277
277
  if (_isPureEvmChain(chainInfo)) {
278
278
  var _chainInfo$evmInfo4;
279
- return (chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$evmInfo4 = chainInfo.evmInfo) === null || _chainInfo$evmInfo4 === void 0 ? void 0 : _chainInfo$evmInfo4.blockExplorer) || '';
279
+ blockExplorer = chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$evmInfo4 = chainInfo.evmInfo) === null || _chainInfo$evmInfo4 === void 0 ? void 0 : _chainInfo$evmInfo4.blockExplorer;
280
+ } else {
281
+ var _chainInfo$substrateI12;
282
+ blockExplorer = chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$substrateI12 = chainInfo.substrateInfo) === null || _chainInfo$substrateI12 === void 0 ? void 0 : _chainInfo$substrateI12.blockExplorer;
283
+ }
284
+ if (!blockExplorer) {
285
+ return undefined;
286
+ }
287
+ if (blockExplorer !== '' && !blockExplorer.endsWith('/')) {
288
+ return `${blockExplorer}/`;
289
+ } else {
290
+ return blockExplorer;
280
291
  }
281
- return (chainInfo === null || chainInfo === void 0 ? void 0 : (_chainInfo$substrateI12 = chainInfo.substrateInfo) === null || _chainInfo$substrateI12 === void 0 ? void 0 : _chainInfo$substrateI12.blockExplorer) || '';
282
292
  }
283
293
  export function _parseMetadataForSmartContractAsset(contractAddress) {
284
294
  return {
@@ -1,3 +1,8 @@
1
+ import { Notification, NotificationParams } from '@subwallet/extension-base/background/KoniTypes';
2
+ import { BehaviorSubject } from 'rxjs';
1
3
  export default class NotificationService {
2
- static createNotification(title: string, message: string, link?: string): void;
4
+ private notificationSubject;
5
+ getNotificationSubject(): BehaviorSubject<Notification[]>;
6
+ notify(notification: NotificationParams): void;
7
+ static createBrowserNotification(title: string, message: string, link?: string): void;
3
8
  }
@@ -1,9 +1,31 @@
1
1
  // Copyright 2019-2022 @subwallet/extension-base authors & contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
+ import { BehaviorSubject } from 'rxjs';
4
5
  export default class NotificationService {
6
+ notificationSubject = new BehaviorSubject([]);
7
+ getNotificationSubject() {
8
+ return this.notificationSubject;
9
+ }
10
+ notify(notification) {
11
+ const now = new Date().getTime();
12
+ // Get values in last 30 seconds only
13
+ const notifications = this.notificationSubject.value.filter(n => n.id < now - 30000);
14
+
15
+ // Push notification
16
+ notifications.push({
17
+ ...notification,
18
+ id: now
19
+ });
20
+ this.notificationSubject.next(notifications);
21
+ if (notification.notifyViaBrowser) {
22
+ var _notification$action;
23
+ NotificationService.createBrowserNotification(notification.title, notification.message, notification === null || notification === void 0 ? void 0 : (_notification$action = notification.action) === null || _notification$action === void 0 ? void 0 : _notification$action.url);
24
+ }
25
+ }
26
+
5
27
  // Create a new chrome notification with link
6
- static createNotification(title, message, link) {
28
+ static createBrowserNotification(title, message, link) {
7
29
  chrome.notifications.create({
8
30
  type: 'basic',
9
31
  title,
@@ -3,7 +3,6 @@ export default class PopupHandler {
3
3
  #private;
4
4
  constructor(requestService: RequestService);
5
5
  updateIconV2(shouldClose?: boolean): void;
6
- setNotification(notification: string): boolean;
7
6
  get popup(): number[];
8
7
  popupClose(): void;
9
8
  popupOpen(): void;
@@ -2,7 +2,6 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { withErrorLog } from '@subwallet/extension-base/background/handlers/helpers';
5
- import settings from '@polkadot/ui-settings';
6
5
  const NOTIFICATION_URL = chrome.extension.getURL('notification.html');
7
6
  const POPUP_WINDOW_OPTS = {
8
7
  focused: true,
@@ -20,10 +19,17 @@ const NORMAL_WINDOW_OPTS = {
20
19
  };
21
20
  export default class PopupHandler {
22
21
  #requestService;
23
- #notification = settings.notification;
22
+ #notification = 'popup';
24
23
  #windows = [];
25
24
  constructor(requestService) {
26
25
  this.#requestService = requestService;
26
+ const updateNotification = rs => {
27
+ this.#notification = rs.browserConfirmationType;
28
+ };
29
+ requestService.settingService.getSettings(updateNotification);
30
+ requestService.settingService.getSubject().subscribe({
31
+ next: updateNotification
32
+ });
27
33
  }
28
34
  updateIconV2(shouldClose) {
29
35
  const numRequests = this.#requestService.numRequests;
@@ -38,10 +44,6 @@ export default class PopupHandler {
38
44
  this.popupClose();
39
45
  }
40
46
  }
41
- setNotification(notification) {
42
- this.#notification = notification;
43
- return true;
44
- }
45
47
  get popup() {
46
48
  return this.#windows;
47
49
  }
@@ -51,19 +53,12 @@ export default class PopupHandler {
51
53
  }
52
54
  popupOpen() {
53
55
  if (this.#notification !== 'extension') {
54
- if (this.#notification === 'window') {
55
- chrome.windows.create(NORMAL_WINDOW_OPTS, window => {
56
- if (window) {
57
- this.#windows.push(window.id || 0);
58
- }
59
- });
60
- }
61
56
  chrome.windows.getCurrent(win => {
62
57
  const popupOptions = {
63
- ...POPUP_WINDOW_OPTS
58
+ ...(this.#notification === 'window' ? NORMAL_WINDOW_OPTS : POPUP_WINDOW_OPTS)
64
59
  };
65
60
  if (win) {
66
- popupOptions.left = (win.left || 0) + (win.width || 0) - (POPUP_WINDOW_OPTS.width || 0) - 20;
61
+ popupOptions.left = (win.left || 0) + (win.width || 0) - (popupOptions.width || 0) - 20;
67
62
  popupOptions.top = (win.top || 0) + 80;
68
63
  }
69
64
  chrome.windows.create(popupOptions, window => {
@@ -2,16 +2,17 @@ import { AuthRequestV2, ConfirmationDefinitions, ConfirmationsQueue, Confirmatio
2
2
  import { AccountJson, AuthorizeRequest, MetadataRequest, RequestAuthorizeTab, RequestSign, ResponseSigning, SigningRequest } from '@subwallet/extension-base/background/types';
3
3
  import { ChainService } from '@subwallet/extension-base/services/chain-service';
4
4
  import { AuthUrls, MetaRequest } from '@subwallet/extension-base/services/request-service/types';
5
+ import SettingService from '@subwallet/extension-base/services/setting-service/SettingService';
5
6
  import { MetadataDef } from '@subwallet/extension-inject/types';
6
7
  import { BehaviorSubject, Subject } from 'rxjs';
7
8
  import { SignerPayloadJSON } from '@polkadot/types/types/extrinsic';
8
9
  export default class RequestService {
9
10
  #private;
10
- constructor(chainService: ChainService);
11
+ readonly settingService: SettingService;
12
+ constructor(chainService: ChainService, settingService: SettingService);
11
13
  get numAllRequests(): number;
12
14
  updateIconV2(shouldClose?: boolean): void;
13
15
  getAddressList(value?: boolean): Record<string, boolean>;
14
- setNotification(notification: string): boolean;
15
16
  get popup(): number[];
16
17
  popupClose(): void;
17
18
  popupOpen(): void;
@@ -17,8 +17,9 @@ export default class RequestService {
17
17
  #evmRequestHandler;
18
18
 
19
19
  // Common
20
- constructor(chainService) {
20
+ constructor(chainService, settingService) {
21
21
  this.#chainService = chainService;
22
+ this.settingService = settingService;
22
23
  this.#popupHandler = new PopupHandler(this);
23
24
  this.#metadataRequestHandler = new MetadataRequestHandler(this);
24
25
  this.#authRequestHandler = new AuthRequestHandler(this, this.#chainService);
@@ -43,11 +44,6 @@ export default class RequestService {
43
44
  }
44
45
 
45
46
  // Popup
46
-
47
- setNotification(notification) {
48
- this.#popupHandler.setNotification(notification);
49
- return true;
50
- }
51
47
  get popup() {
52
48
  return this.#popupHandler.popup;
53
49
  }
@@ -17,7 +17,8 @@ export default class SettingService {
17
17
  // isShowZeroBalance: true,
18
18
  isShowBalance: false,
19
19
  accountAllLogo: '',
20
- theme: ThemeNames.DARK
20
+ theme: ThemeNames.DARK,
21
+ camera: false
21
22
  });
22
23
  } else {
23
24
  update(value);