@subwallet/extension-base 1.1.11-0 → 1.1.11-2

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 (31) hide show
  1. package/background/KoniTypes.d.ts +16 -6
  2. package/background/types.d.ts +4 -2
  3. package/cjs/koni/api/staking/bonding/utils.js +2 -1
  4. package/cjs/koni/background/handlers/Extension.js +32 -10
  5. package/cjs/koni/background/handlers/State.js +1 -1
  6. package/cjs/packageInfo.js +1 -1
  7. package/cjs/services/keyring-service/index.js +33 -1
  8. package/cjs/services/notification-service/NotificationService.js +2 -1
  9. package/cjs/services/request-service/constants.js +11 -2
  10. package/cjs/services/request-service/handler/AuthRequestHandler.js +20 -1
  11. package/cjs/services/request-service/handler/EvmRequestHandler.js +2 -1
  12. package/cjs/services/transaction-service/index.js +124 -55
  13. package/cjs/utils/lazy.js +20 -6
  14. package/koni/api/staking/bonding/utils.js +2 -1
  15. package/koni/background/handlers/Extension.d.ts +2 -0
  16. package/koni/background/handlers/Extension.js +32 -10
  17. package/koni/background/handlers/State.js +1 -1
  18. package/package.json +9 -7
  19. package/packageInfo.js +1 -1
  20. package/page/SubWalleEvmProvider.d.ts +1 -1
  21. package/services/keyring-service/index.d.ts +4 -1
  22. package/services/keyring-service/index.js +33 -1
  23. package/services/notification-service/NotificationService.js +2 -1
  24. package/services/request-service/constants.d.ts +1 -0
  25. package/services/request-service/constants.js +9 -1
  26. package/services/request-service/handler/AuthRequestHandler.js +21 -2
  27. package/services/request-service/handler/EvmRequestHandler.js +2 -1
  28. package/services/transaction-service/index.d.ts +1 -0
  29. package/services/transaction-service/index.js +116 -48
  30. package/utils/lazy.d.ts +1 -1
  31. package/utils/lazy.js +20 -7
@@ -7,7 +7,7 @@ import { _CHAIN_VALIDATION_ERROR } from '@subwallet/extension-base/services/chai
7
7
  import { _ChainState, _EvmApi, _NetworkUpsertParams, _SubstrateApi, _ValidateCustomAssetRequest, _ValidateCustomAssetResponse, EnableChainParams, EnableMultiChainParams } from '@subwallet/extension-base/services/chain-service/types';
8
8
  import { SWTransactionResponse, SWTransactionResult } from '@subwallet/extension-base/services/transaction-service/types';
9
9
  import { WalletConnectNotSupportRequest, WalletConnectSessionRequest } from '@subwallet/extension-base/services/wallet-connect-service/types';
10
- import { InjectedAccount, MetadataDefBase } from '@subwallet/extension-inject/types';
10
+ import { InjectedAccount, InjectedAccountWithMeta, MetadataDefBase } from '@subwallet/extension-inject/types';
11
11
  import { KeyringPair$Json, KeyringPair$Meta } from '@subwallet/keyring/types';
12
12
  import { KeyringOptions } from '@subwallet/ui-keyring/options/types';
13
13
  import { KeyringAddress, KeyringPairs$Json } from '@subwallet/ui-keyring/types';
@@ -701,6 +701,12 @@ export interface RequestEditContactAccount {
701
701
  export interface RequestDeleteContactAccount {
702
702
  address: string;
703
703
  }
704
+ export interface RequestAddInjectedAccounts {
705
+ accounts: InjectedAccountWithMeta[];
706
+ }
707
+ export interface RequestRemoveInjectedAccounts {
708
+ addresses: string[];
709
+ }
704
710
  export declare enum ExternalRequestPromiseStatus {
705
711
  PENDING = 0,
706
712
  REJECTED = 1,
@@ -924,6 +930,7 @@ export interface EvmSendTransactionRequest extends TransactionConfig, EvmSignReq
924
930
  parseData: EvmTransactionData;
925
931
  isToContract: boolean;
926
932
  }
933
+ export declare type EvmWatchTransactionRequest = EvmSendTransactionRequest;
927
934
  export interface ConfirmationsQueueItemOptions {
928
935
  requiredPassword?: boolean;
929
936
  address?: string;
@@ -981,6 +988,7 @@ export interface ConfirmationDefinitions {
981
988
  switchNetworkRequest: [ConfirmationsQueueItem<SwitchNetworkRequest>, ConfirmationResult<boolean>];
982
989
  evmSignatureRequest: [ConfirmationsQueueItem<EvmSignatureRequest>, ConfirmationResult<string>];
983
990
  evmSendTransactionRequest: [ConfirmationsQueueItem<EvmSendTransactionRequest>, ConfirmationResult<string>];
991
+ evmWatchTransactionRequest: [ConfirmationsQueueItem<EvmWatchTransactionRequest>, ConfirmationResult<string>];
984
992
  }
985
993
  export declare type ConfirmationType = keyof ConfirmationDefinitions;
986
994
  export declare type ConfirmationsQueue = {
@@ -1603,30 +1611,32 @@ export interface KoniRequestSignatures {
1603
1611
  'pri(authorize.forgetAllSite)': [null, boolean, AuthUrls];
1604
1612
  'pri(authorize.rejectV2)': [RequestAuthorizeReject, boolean];
1605
1613
  'pri(authorize.cancelV2)': [RequestAuthorizeCancel, boolean];
1606
- 'pri(seed.createV2)': [RequestSeedCreateV2, ResponseSeedCreateV2];
1607
1614
  'pri(seed.validateV2)': [RequestSeedValidateV2, ResponseSeedValidateV2];
1608
1615
  'pri(privateKey.validateV2)': [RequestSeedValidateV2, ResponsePrivateKeyValidateV2];
1616
+ 'pri(accounts.checkPublicAndSecretKey)': [RequestCheckPublicAndSecretKey, ResponseCheckPublicAndSecretKey];
1617
+ 'pri(seed.createV2)': [RequestSeedCreateV2, ResponseSeedCreateV2];
1609
1618
  'pri(accounts.create.suriV2)': [RequestAccountCreateSuriV2, ResponseAccountCreateSuriV2];
1610
1619
  'pri(accounts.create.externalV2)': [RequestAccountCreateExternalV2, AccountExternalError[]];
1611
1620
  'pri(accounts.create.hardwareV2)': [RequestAccountCreateHardwareV2, boolean];
1612
1621
  'pri(accounts.create.hardwareMultiple)': [RequestAccountCreateHardwareMultiple, boolean];
1613
1622
  'pri(accounts.create.withSecret)': [RequestAccountCreateWithSecretKey, ResponseAccountCreateWithSecretKey];
1623
+ 'pri(accounts.inject.add)': [RequestAddInjectedAccounts, boolean];
1624
+ 'pri(accounts.inject.remove)': [RequestRemoveInjectedAccounts, boolean];
1614
1625
  'pri(derivation.createV2)': [RequestDeriveCreateV2, boolean];
1615
1626
  'pri(json.restoreV2)': [RequestJsonRestoreV2, void];
1616
1627
  'pri(json.batchRestoreV2)': [RequestBatchRestoreV2, void];
1617
1628
  'pri(accounts.exportPrivateKey)': [RequestAccountExportPrivateKey, ResponseAccountExportPrivateKey];
1618
- 'pri(accounts.checkPublicAndSecretKey)': [RequestCheckPublicAndSecretKey, ResponseCheckPublicAndSecretKey];
1619
1629
  'pri(accounts.subscribeWithCurrentAddress)': [RequestAccountSubscribe, AccountsWithCurrentAddress, AccountsWithCurrentAddress];
1620
- 'pri(accounts.subscribeAccountsInputAddress)': [RequestAccountSubscribe, string, OptionInputAddress];
1621
- 'pri(accounts.saveRecent)': [RequestSaveRecentAccount, KeyringAddress];
1622
- 'pri(accounts.get.meta)': [RequestAccountMeta, ResponseAccountMeta];
1623
1630
  'pri(accounts.updateCurrentAddress)': [string, boolean];
1624
1631
  'pri(currentAccount.saveAddress)': [RequestCurrentAccountAddress, CurrentAccountInfo];
1632
+ 'pri(accounts.get.meta)': [RequestAccountMeta, ResponseAccountMeta];
1633
+ 'pri(accounts.saveRecent)': [RequestSaveRecentAccount, KeyringAddress];
1625
1634
  'pri(accounts.subscribeAddresses)': [null, AddressBookInfo, AddressBookInfo];
1626
1635
  'pri(accounts.editContact)': [RequestEditContactAccount, boolean];
1627
1636
  'pri(accounts.deleteContact)': [RequestDeleteContactAccount, boolean];
1628
1637
  'pri(accounts.resolveDomainToAddress)': [ResolveDomainRequest, string | undefined];
1629
1638
  'pri(accounts.resolveAddressToDomain)': [ResolveAddressToDomainRequest, string | undefined];
1639
+ 'pri(accounts.subscribeAccountsInputAddress)': [RequestAccountSubscribe, string, OptionInputAddress];
1630
1640
  'pri(settings.changeBalancesVisibility)': [null, boolean];
1631
1641
  'pri(settings.subscribe)': [null, UiSettings, UiSettings];
1632
1642
  'pri(settings.getLogoMaps)': [null, AllLogoMap];
@@ -31,17 +31,19 @@ export interface AbstractAddressJson extends KeyringPair$Meta {
31
31
  export interface AccountJson extends AbstractAddressJson {
32
32
  accountIndex?: number;
33
33
  addressOffset?: number;
34
+ availableGenesisHashes?: string[];
34
35
  genesisHash?: string | null;
35
36
  isExternal?: boolean;
36
37
  isHardware?: boolean;
37
38
  isHidden?: boolean;
39
+ isInjected?: boolean;
38
40
  isMasterAccount?: boolean;
39
41
  isMasterPassword?: boolean;
40
42
  isReadOnly?: boolean;
43
+ originGenesisHash?: string | null;
41
44
  parentAddress?: string;
45
+ source?: string;
42
46
  suri?: string;
43
- originGenesisHash?: string | null;
44
- availableGenesisHashes?: string[];
45
47
  }
46
48
  export interface AddressJson extends AbstractAddressJson {
47
49
  isRecent?: boolean;
@@ -33,6 +33,7 @@ var _astar = require("@subwallet/extension-base/koni/api/staking/bonding/astar")
33
33
  var _constants = require("@subwallet/extension-base/services/chain-service/constants");
34
34
  var _utils = require("@subwallet/extension-base/services/chain-service/utils");
35
35
  var _utils2 = require("@subwallet/extension-base/utils");
36
+ var _number = require("@subwallet/extension-base/utils/number");
36
37
  var _i18next = require("i18next");
37
38
  var _util = require("@polkadot/util");
38
39
  // Copyright 2019-2022 @subwallet/extension-koni authors & contributors
@@ -285,7 +286,7 @@ function getValidatorLabel(chain) {
285
286
  }
286
287
  const getMinStakeErrorMessage = (chainInfo, bnMinStake) => {
287
288
  const tokenInfo = (0, _utils._getChainNativeTokenBasicInfo)(chainInfo);
288
- const number = bnMinStake.div(new _util.BN(10).pow(new _util.BN(tokenInfo.decimals))).toString();
289
+ const number = (0, _number.formatNumber)(bnMinStake.toString(), tokenInfo.decimals || 0, _number.balanceFormatter);
289
290
  return (0, _i18next.t)('Insufficient stake. Please stake at least {{number}} {{tokenSymbol}} to get rewards', {
290
291
  replace: {
291
292
  tokenSymbol: tokenInfo.symbol,
@@ -2775,15 +2775,19 @@ class KoniExtension {
2775
2775
  if (createNew) {
2776
2776
  const pairs = _uiKeyring.keyring.getPairs();
2777
2777
  for (const pair of pairs) {
2778
- const meta = {
2779
- ...pair.meta,
2780
- isMasterPassword: false
2781
- };
2782
- if (!meta.originGenesisHash) {
2783
- meta.genesisHash = '';
2778
+ if (pair.meta.isInjected) {
2779
+ // Empty
2780
+ } else {
2781
+ const meta = {
2782
+ ...pair.meta,
2783
+ isMasterPassword: false
2784
+ };
2785
+ if (!meta.originGenesisHash) {
2786
+ meta.genesisHash = '';
2787
+ }
2788
+ pair.setMeta(meta);
2789
+ _uiKeyring.keyring.saveAccountMeta(pair, pair.meta);
2784
2790
  }
2785
- pair.setMeta(meta);
2786
- _uiKeyring.keyring.saveAccountMeta(pair, pair.meta);
2787
2791
  }
2788
2792
  }
2789
2793
  _uiKeyring.keyring.changeMasterPassword(newPassword, oldPassword);
@@ -2889,7 +2893,7 @@ class KoniExtension {
2889
2893
  }
2890
2894
  }
2891
2895
 
2892
- /// Signing external request
2896
+ /// Signing substrate request
2893
2897
  signingApprovePasswordV2(_ref70) {
2894
2898
  let {
2895
2899
  id
@@ -3573,6 +3577,16 @@ class KoniExtension {
3573
3577
  return await (0, _domain.resolveAzeroAddressToDomain)(request.address, request.chain, chainApi.api);
3574
3578
  }
3575
3579
 
3580
+ /// Inject account
3581
+ addInjects(request) {
3582
+ this.#koniState.keyringService.addInjectAccounts(request.accounts);
3583
+ return true;
3584
+ }
3585
+ removeInjects(request) {
3586
+ this.#koniState.keyringService.removeInjectAccounts(request.addresses);
3587
+ return true;
3588
+ }
3589
+
3576
3590
  // --------------------------------------------------------------
3577
3591
  // eslint-disable-next-line @typescript-eslint/require-await
3578
3592
  async handle(id, type, request, port) {
@@ -3725,7 +3739,7 @@ class KoniExtension {
3725
3739
  case 'pri(transaction.history.getSubscription)':
3726
3740
  return await this.subscribeHistory(id, port);
3727
3741
 
3728
- /// Account management
3742
+ /* Account management */
3729
3743
  // Add account
3730
3744
  case 'pri(accounts.create.suriV2)':
3731
3745
  return await this.accountsCreateSuriV2(request);
@@ -3788,6 +3802,14 @@ class KoniExtension {
3788
3802
  case 'pri(accounts.resolveAddressToDomain)':
3789
3803
  return await this.resolveAddressByDomain(request);
3790
3804
 
3805
+ // Inject account
3806
+ case 'pri(accounts.inject.add)':
3807
+ return this.addInjects(request);
3808
+ case 'pri(accounts.inject.remove)':
3809
+ return this.removeInjects(request);
3810
+
3811
+ /* Account management */
3812
+
3791
3813
  // ChainService
3792
3814
  case 'pri(chainService.subscribeChainInfoMap)':
3793
3815
  return this.subscribeChainInfoMap(id, port);
@@ -1565,7 +1565,7 @@ class KoniState {
1565
1565
  });
1566
1566
  }
1567
1567
  async resetWallet(resetAll) {
1568
- this.keyringService.resetWallet(resetAll);
1568
+ await this.keyringService.resetWallet(resetAll);
1569
1569
  this.requestService.resetWallet();
1570
1570
  this.transactionService.resetWallet();
1571
1571
  await this.dbService.resetWallet(resetAll);
@@ -13,6 +13,6 @@ const packageInfo = {
13
13
  name: '@subwallet/extension-base',
14
14
  path: typeof __dirname === 'string' ? __dirname : 'auto',
15
15
  type: 'cjs',
16
- version: '1.1.11-0'
16
+ version: '1.1.11-2'
17
17
  };
18
18
  exports.packageInfo = packageInfo;
@@ -8,6 +8,7 @@ var _constants = require("@subwallet/extension-base/constants");
8
8
  var _stores = require("@subwallet/extension-base/stores");
9
9
  var _uiKeyring = require("@subwallet/ui-keyring");
10
10
  var _rxjs = require("rxjs");
11
+ var _util = require("@polkadot/util");
11
12
  // Copyright 2019-2022 @subwallet/extension-base
12
13
  // SPDX-License-Identifier: Apache-2.0
13
14
 
@@ -98,8 +99,39 @@ class KeyringService {
98
99
  _uiKeyring.keyring.lockAll();
99
100
  this.updateKeyringState();
100
101
  }
101
- resetWallet(resetAll) {
102
+
103
+ /* Inject */
104
+
105
+ addInjectAccounts(accounts) {
106
+ _uiKeyring.keyring.addInjects(accounts.map(account => {
107
+ const name = account.meta.name || (0, _util.stringShorten)(account.address);
108
+
109
+ // TODO: Add if need
110
+ // name = name.concat(' (', account.meta.source, ')');
111
+
112
+ return {
113
+ ...account,
114
+ meta: {
115
+ ...account.meta,
116
+ name: name
117
+ }
118
+ };
119
+ }));
120
+ }
121
+ removeInjectAccounts(addresses) {
122
+ _uiKeyring.keyring.removeInjects(addresses);
123
+ }
124
+
125
+ /* Inject */
126
+
127
+ /* Reset */
128
+ async resetWallet(resetAll) {
102
129
  _uiKeyring.keyring.resetWallet(resetAll);
130
+ await new Promise(resolve => {
131
+ setTimeout(() => {
132
+ resolve();
133
+ }, 500);
134
+ });
103
135
  this.updateKeyringState();
104
136
  this.currentAccountSubject.next({
105
137
  address: _constants.ALL_ACCOUNT_KEY,
@@ -32,7 +32,8 @@ class NotificationService {
32
32
 
33
33
  // Create a new chrome notification with link
34
34
  static createBrowserNotification(title, message, link) {
35
- chrome.notifications.create({
35
+ var _chrome, _chrome$notifications;
36
+ (_chrome = chrome) === null || _chrome === void 0 ? void 0 : (_chrome$notifications = _chrome.notifications) === null || _chrome$notifications === void 0 ? void 0 : _chrome$notifications.create({
36
37
  type: 'basic',
37
38
  title,
38
39
  message,
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.PREDEFINED_CHAIN_DAPP_CHAIN_MAP = exports.EXTENSION_REQUEST_URL = void 0;
6
+ exports.WEB_APP_URL = exports.PREDEFINED_CHAIN_DAPP_CHAIN_MAP = exports.EXTENSION_REQUEST_URL = void 0;
7
7
  // Copyright 2019-2022 @subwallet/extension-base authors & contributors
8
8
  // SPDX-License-Identifier: Apache-2.0
9
9
 
@@ -14,4 +14,13 @@ const PREDEFINED_CHAIN_DAPP_CHAIN_MAP = {
14
14
  'apps.moonbeam.network': ['moonbeam', 'moonriver'],
15
15
  'app.stellaswap.com': ['moonbeam']
16
16
  };
17
- exports.PREDEFINED_CHAIN_DAPP_CHAIN_MAP = PREDEFINED_CHAIN_DAPP_CHAIN_MAP;
17
+ exports.PREDEFINED_CHAIN_DAPP_CHAIN_MAP = PREDEFINED_CHAIN_DAPP_CHAIN_MAP;
18
+ const WEB_APP_URL = [
19
+ /// Web app
20
+ 'localhost:9000',
21
+ // Local
22
+ 'subwallet-webapp.pages.dev',
23
+ // Pull request build
24
+ 'web.subwallet.app' // Production
25
+ ];
26
+ exports.WEB_APP_URL = WEB_APP_URL;
@@ -221,7 +221,7 @@ class AuthRequestHandler {
221
221
  }
222
222
  const idStr = (0, _utils2.stripUrl)(url);
223
223
  // Do not enqueue duplicate authorization requests.
224
- const isDuplicate = Object.values(this.#authRequestsV2).some(request => request.idStr === idStr);
224
+ const isDuplicate = Object.values(this.#authRequestsV2).some(_request => _request.idStr === idStr && _request.accountAuthType === request.accountAuthType);
225
225
  (0, _util.assert)(!isDuplicate, 'The source {{url}} has a pending authorization request'.replace('{{url}}', url));
226
226
  const existedAuth = authList[idStr];
227
227
  const existedAccountAuthType = existedAuth === null || existedAuth === void 0 ? void 0 : existedAuth.accountAuthType;
@@ -250,6 +250,25 @@ class AuthRequestHandler {
250
250
  // Prevent appear confirmation popup
251
251
  return false;
252
252
  }
253
+ } else {
254
+ // Auto auth for web app
255
+
256
+ // Ignore white list
257
+ const isWhiteList = _constants.WEB_APP_URL.some(url => idStr.includes(url)) && false;
258
+ if (isWhiteList) {
259
+ const isAllowedMap = this.getAddressList(true);
260
+ authList[(0, _utils2.stripUrl)(url)] = {
261
+ count: 0,
262
+ id: idStr,
263
+ isAllowed: true,
264
+ isAllowedMap,
265
+ origin,
266
+ url,
267
+ accountAuthType: 'both'
268
+ };
269
+ this.setAuthorize(authList);
270
+ return true;
271
+ }
253
272
  }
254
273
  return new Promise((resolve, reject) => {
255
274
  const id = (0, _getId.getId)();
@@ -28,7 +28,8 @@ class EvmRequestHandler {
28
28
  addTokenRequest: {},
29
29
  switchNetworkRequest: {},
30
30
  evmSignatureRequest: {},
31
- evmSendTransactionRequest: {}
31
+ evmSendTransactionRequest: {},
32
+ evmWatchTransactionRequest: {}
32
33
  });
33
34
  confirmationsPromiseMap = {};
34
35
  constructor(requestService) {
@@ -34,6 +34,7 @@ var _util = require("@polkadot/util");
34
34
 
35
35
  class TransactionService {
36
36
  transactionSubject = new _rxjs.BehaviorSubject({});
37
+ watchTransactionSubscribes = {};
37
38
  get transactions() {
38
39
  return this.transactionSubject.getValue();
39
40
  }
@@ -716,6 +717,7 @@ class TransactionService {
716
717
  payload.from = address;
717
718
  }
718
719
  const isExternal = !!account.isExternal;
720
+ const isInjected = !!account.isInjected;
719
721
 
720
722
  // generate hashPayload for EVM transaction
721
723
  payload.hashPayload = this.generateHashPayload(chain, payload);
@@ -736,73 +738,140 @@ class TransactionService {
736
738
  warnings: [],
737
739
  extrinsicHash: id
738
740
  };
739
- this.requestService.addConfirmation(id, url || _constants3.EXTENSION_REQUEST_URL, 'evmSendTransactionRequest', payload, {}).then(async _ref7 => {
740
- let {
741
- isApproved,
742
- payload
743
- } = _ref7;
744
- if (isApproved) {
745
- let signedTransaction;
746
- if (!payload) {
747
- throw new _EvmProviderError.EvmProviderError(_KoniTypes.EvmProviderErrorType.UNAUTHORIZED, (0, _i18next.t)('Failed to sign'));
748
- }
749
- const web3Api = this.chainService.getEvmApi(chain).api;
750
- if (!isExternal) {
751
- signedTransaction = payload;
752
- } else {
753
- const signed = (0, _mergeTransactionAndSignature.mergeTransactionAndSignature)(txObject, payload);
754
- const recover = web3Api.eth.accounts.recoverTransaction(signed);
755
- if (recover.toLowerCase() !== account.address.toLowerCase()) {
756
- throw new _EvmProviderError.EvmProviderError(_KoniTypes.EvmProviderErrorType.UNAUTHORIZED, (0, _i18next.t)('Wrong signature. Please sign with the account you use in dApp'));
741
+ if (isInjected) {
742
+ this.requestService.addConfirmation(id, url || _constants3.EXTENSION_REQUEST_URL, 'evmWatchTransactionRequest', payload, {}).then(async _ref7 => {
743
+ let {
744
+ isApproved,
745
+ payload
746
+ } = _ref7;
747
+ if (isApproved) {
748
+ if (!payload) {
749
+ throw new _EvmProviderError.EvmProviderError(_KoniTypes.EvmProviderErrorType.UNAUTHORIZED, 'Bad signature');
757
750
  }
758
- signedTransaction = signed;
759
- }
751
+ const web3Api = this.chainService.getEvmApi(chain).api;
760
752
 
761
- // Emit signed event
762
- emitter.emit('signed', eventData);
753
+ // Emit signed event
754
+ emitter.emit('signed', eventData);
755
+ eventData.nonce = txObject.nonce;
756
+ eventData.startBlock = (await web3Api.eth.getBlockNumber()) - 3;
757
+ // Add start info
758
+ emitter.emit('send', eventData); // This event is needed after sending transaction with queue
763
759
 
764
- // Send transaction
765
- this.handleTransactionTimeout(emitter, eventData);
766
-
767
- // Add start info
768
- eventData.nonce = txObject.nonce;
769
- eventData.startBlock = await web3Api.eth.getBlockNumber();
770
- emitter.emit('send', eventData); // This event is needed after sending transaction with queue
771
- signedTransaction && web3Api.eth.sendSignedTransaction(signedTransaction).once('transactionHash', hash => {
772
- eventData.extrinsicHash = hash;
760
+ const txHash = payload;
761
+ eventData.extrinsicHash = txHash;
773
762
  emitter.emit('extrinsicHash', eventData);
774
- }).once('receipt', rs => {
775
- eventData.extrinsicHash = rs.transactionHash;
776
- eventData.blockHash = rs.blockHash;
777
- eventData.blockNumber = rs.blockNumber;
778
- emitter.emit('success', eventData);
779
- }).once('error', e => {
780
- eventData.errors.push(new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.SEND_TRANSACTION_FAILED, (0, _i18next.t)(e.message)));
763
+ this.watchTransactionSubscribes[id] = new Promise((resolve, reject) => {
764
+ // eslint-disable-next-line prefer-const
765
+ let subscribe;
766
+ const onComplete = () => {
767
+ var _subscribe, _subscribe$unsubscrib, _subscribe$unsubscrib2;
768
+ (_subscribe = subscribe) === null || _subscribe === void 0 ? void 0 : (_subscribe$unsubscrib = _subscribe.unsubscribe) === null || _subscribe$unsubscrib === void 0 ? void 0 : (_subscribe$unsubscrib2 = _subscribe$unsubscrib.call(_subscribe)) === null || _subscribe$unsubscrib2 === void 0 ? void 0 : _subscribe$unsubscrib2.then(console.debug).catch(console.debug);
769
+ delete this.watchTransactionSubscribes[id];
770
+ };
771
+ const onSuccess = rs => {
772
+ if (rs) {
773
+ eventData.extrinsicHash = rs.transactionHash;
774
+ eventData.blockHash = rs.blockHash;
775
+ eventData.blockNumber = rs.blockNumber;
776
+ emitter.emit('success', eventData);
777
+ onComplete();
778
+ resolve();
779
+ }
780
+ };
781
+ const onError = error => {
782
+ if (error) {
783
+ // TODO: Change type and message
784
+ eventData.errors.push(new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.UNABLE_TO_SEND, error.message));
785
+ emitter.emit('error', eventData);
786
+ onComplete();
787
+ reject(error);
788
+ }
789
+ };
790
+ const onCheck = () => {
791
+ web3Api.eth.getTransactionReceipt(txHash).then(onSuccess).catch(onError);
792
+ };
793
+ subscribe = web3Api.eth.subscribe('newBlockHeaders', onCheck);
794
+ });
795
+ } else {
796
+ this.removeTransaction(id);
797
+ eventData.errors.push(new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.USER_REJECT_REQUEST));
781
798
  emitter.emit('error', eventData);
782
- }).catch(e => {
783
- eventData.errors.push(new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.UNABLE_TO_SEND, (0, _i18next.t)(e.message)));
799
+ }
800
+ }).catch(e => {
801
+ this.removeTransaction(id);
802
+ // TODO: Change type
803
+ eventData.errors.push(new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.UNABLE_TO_SIGN, e.message));
804
+ emitter.emit('error', eventData);
805
+ });
806
+ } else {
807
+ this.requestService.addConfirmation(id, url || _constants3.EXTENSION_REQUEST_URL, 'evmSendTransactionRequest', payload, {}).then(async _ref8 => {
808
+ let {
809
+ isApproved,
810
+ payload
811
+ } = _ref8;
812
+ if (isApproved) {
813
+ let signedTransaction;
814
+ if (!payload) {
815
+ throw new _EvmProviderError.EvmProviderError(_KoniTypes.EvmProviderErrorType.UNAUTHORIZED, (0, _i18next.t)('Failed to sign'));
816
+ }
817
+ const web3Api = this.chainService.getEvmApi(chain).api;
818
+ if (!isExternal) {
819
+ signedTransaction = payload;
820
+ } else {
821
+ const signed = (0, _mergeTransactionAndSignature.mergeTransactionAndSignature)(txObject, payload);
822
+ const recover = web3Api.eth.accounts.recoverTransaction(signed);
823
+ if (recover.toLowerCase() !== account.address.toLowerCase()) {
824
+ throw new _EvmProviderError.EvmProviderError(_KoniTypes.EvmProviderErrorType.UNAUTHORIZED, (0, _i18next.t)('Wrong signature. Please sign with the account you use in dApp'));
825
+ }
826
+ signedTransaction = signed;
827
+ }
828
+
829
+ // Emit signed event
830
+ emitter.emit('signed', eventData);
831
+
832
+ // Send transaction
833
+ this.handleTransactionTimeout(emitter, eventData);
834
+
835
+ // Add start info
836
+ eventData.nonce = txObject.nonce;
837
+ eventData.startBlock = await web3Api.eth.getBlockNumber();
838
+ emitter.emit('send', eventData); // This event is needed after sending transaction with queue
839
+ signedTransaction && web3Api.eth.sendSignedTransaction(signedTransaction).once('transactionHash', hash => {
840
+ eventData.extrinsicHash = hash;
841
+ emitter.emit('extrinsicHash', eventData);
842
+ }).once('receipt', rs => {
843
+ eventData.extrinsicHash = rs.transactionHash;
844
+ eventData.blockHash = rs.blockHash;
845
+ eventData.blockNumber = rs.blockNumber;
846
+ emitter.emit('success', eventData);
847
+ }).once('error', e => {
848
+ eventData.errors.push(new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.SEND_TRANSACTION_FAILED, (0, _i18next.t)(e.message)));
849
+ emitter.emit('error', eventData);
850
+ }).catch(e => {
851
+ eventData.errors.push(new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.UNABLE_TO_SEND, (0, _i18next.t)(e.message)));
852
+ emitter.emit('error', eventData);
853
+ });
854
+ } else {
855
+ this.removeTransaction(id);
856
+ eventData.errors.push(new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.USER_REJECT_REQUEST));
784
857
  emitter.emit('error', eventData);
785
- });
786
- } else {
858
+ }
859
+ }).catch(e => {
787
860
  this.removeTransaction(id);
788
- eventData.errors.push(new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.USER_REJECT_REQUEST));
861
+ eventData.errors.push(new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.UNABLE_TO_SIGN, (0, _i18next.t)(e.message)));
789
862
  emitter.emit('error', eventData);
790
- }
791
- }).catch(e => {
792
- this.removeTransaction(id);
793
- eventData.errors.push(new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.UNABLE_TO_SIGN, (0, _i18next.t)(e.message)));
794
- emitter.emit('error', eventData);
795
- });
863
+ });
864
+ }
796
865
  return emitter;
797
866
  }
798
- signAndSendSubstrateTransaction(_ref8) {
867
+ signAndSendSubstrateTransaction(_ref9) {
799
868
  let {
800
869
  address,
801
870
  chain,
802
871
  id,
803
872
  transaction,
804
873
  url
805
- } = _ref8;
874
+ } = _ref9;
806
875
  const emitter = new _eventemitter.default();
807
876
  const eventData = {
808
877
  id,
@@ -848,20 +917,20 @@ class TransactionService {
848
917
  eventData.extrinsicHash = txState.txHash.toHex();
849
918
  eventData.eventLogs = txState.events;
850
919
  // TODO: push block hash and block number into eventData
851
- txState.events.filter(_ref9 => {
920
+ txState.events.filter(_ref10 => {
852
921
  let {
853
922
  event: {
854
923
  section
855
924
  }
856
- } = _ref9;
925
+ } = _ref10;
857
926
  return section === 'system';
858
- }).forEach(_ref10 => {
927
+ }).forEach(_ref11 => {
859
928
  let {
860
929
  event: {
861
930
  method,
862
931
  data: [error]
863
932
  }
864
- } = _ref10;
933
+ } = _ref11;
865
934
  if (method === 'ExtrinsicFailed') {
866
935
  eventData.errors.push(new _TransactionError.TransactionError(_KoniTypes.BasicTxErrorType.SEND_TRANSACTION_FAILED, error.toString()));
867
936
  emitter.emit('error', eventData);
package/cjs/utils/lazy.js CHANGED
@@ -20,6 +20,7 @@ function removeLazy(key) {
20
20
  function addLazy(key, callback) {
21
21
  let lazyTime = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 300;
22
22
  let maxLazyTime = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 3000;
23
+ let fireOnFirst = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
23
24
  const existed = lazyMap[key];
24
25
  const now = new Date().getTime();
25
26
  if (existed) {
@@ -42,11 +43,24 @@ function addLazy(key, callback) {
42
43
  }, lazyTime);
43
44
  }
44
45
  } else {
45
- // Fire callback immediately in the first time
46
- callback();
47
- lazyMap[key] = {
48
- callback,
49
- lastFire: now
50
- };
46
+ if (fireOnFirst) {
47
+ // Fire callback immediately in the first time
48
+ callback();
49
+ lazyMap[key] = {
50
+ callback,
51
+ lastFire: now
52
+ };
53
+ } else {
54
+ lazyMap[key] = {
55
+ callback,
56
+ lastFire: now
57
+ };
58
+ lazyMap[key].timeout = setTimeout(() => {
59
+ // This will be fire in the last call of lazy thread
60
+ callback();
61
+ lazyMap[key].lastFire = new Date().getTime();
62
+ removeLazy(key);
63
+ }, lazyTime);
64
+ }
51
65
  }
52
66
  }
@@ -6,6 +6,7 @@ import { getAstarWithdrawable } from '@subwallet/extension-base/koni/api/staking
6
6
  import { _KNOWN_CHAIN_INFLATION_PARAMS, _STAKING_CHAIN_GROUP, _SUBSTRATE_DEFAULT_INFLATION_PARAMS } from '@subwallet/extension-base/services/chain-service/constants';
7
7
  import { _getChainNativeTokenBasicInfo } from '@subwallet/extension-base/services/chain-service/utils';
8
8
  import { detectTranslate, parseRawNumber, reformatAddress } from '@subwallet/extension-base/utils';
9
+ import { balanceFormatter, formatNumber } from '@subwallet/extension-base/utils/number';
9
10
  import { t } from 'i18next';
10
11
  import { BN, BN_BILLION, BN_HUNDRED, BN_MILLION, BN_THOUSAND, BN_ZERO, bnToU8a, stringToU8a, u8aConcat } from '@polkadot/util';
11
12
  export let PalletParachainStakingRequestType;
@@ -254,7 +255,7 @@ export function getValidatorLabel(chain) {
254
255
  }
255
256
  export const getMinStakeErrorMessage = (chainInfo, bnMinStake) => {
256
257
  const tokenInfo = _getChainNativeTokenBasicInfo(chainInfo);
257
- const number = bnMinStake.div(new BN(10).pow(new BN(tokenInfo.decimals))).toString();
258
+ const number = formatNumber(bnMinStake.toString(), tokenInfo.decimals || 0, balanceFormatter);
258
259
  return t('Insufficient stake. Please stake at least {{number}} {{tokenSymbol}} to get rewards', {
259
260
  replace: {
260
261
  tokenSymbol: tokenInfo.symbol,
@@ -210,5 +210,7 @@ export default class KoniExtension {
210
210
  private findRawMetadata;
211
211
  private resolveDomainByAddress;
212
212
  private resolveAddressByDomain;
213
+ private addInjects;
214
+ private removeInjects;
213
215
  handle<TMessageType extends MessageTypes>(id: string, type: TMessageType, request: RequestTypes[TMessageType], port: chrome.runtime.Port): Promise<ResponseType<TMessageType>>;
214
216
  }
@@ -2700,15 +2700,19 @@ export default class KoniExtension {
2700
2700
  if (createNew) {
2701
2701
  const pairs = keyring.getPairs();
2702
2702
  for (const pair of pairs) {
2703
- const meta = {
2704
- ...pair.meta,
2705
- isMasterPassword: false
2706
- };
2707
- if (!meta.originGenesisHash) {
2708
- meta.genesisHash = '';
2703
+ if (pair.meta.isInjected) {
2704
+ // Empty
2705
+ } else {
2706
+ const meta = {
2707
+ ...pair.meta,
2708
+ isMasterPassword: false
2709
+ };
2710
+ if (!meta.originGenesisHash) {
2711
+ meta.genesisHash = '';
2712
+ }
2713
+ pair.setMeta(meta);
2714
+ keyring.saveAccountMeta(pair, pair.meta);
2709
2715
  }
2710
- pair.setMeta(meta);
2711
- keyring.saveAccountMeta(pair, pair.meta);
2712
2716
  }
2713
2717
  }
2714
2718
  keyring.changeMasterPassword(newPassword, oldPassword);
@@ -2810,7 +2814,7 @@ export default class KoniExtension {
2810
2814
  }
2811
2815
  }
2812
2816
 
2813
- /// Signing external request
2817
+ /// Signing substrate request
2814
2818
  signingApprovePasswordV2({
2815
2819
  id
2816
2820
  }) {
@@ -3473,6 +3477,16 @@ export default class KoniExtension {
3473
3477
  return await resolveAzeroAddressToDomain(request.address, request.chain, chainApi.api);
3474
3478
  }
3475
3479
 
3480
+ /// Inject account
3481
+ addInjects(request) {
3482
+ this.#koniState.keyringService.addInjectAccounts(request.accounts);
3483
+ return true;
3484
+ }
3485
+ removeInjects(request) {
3486
+ this.#koniState.keyringService.removeInjectAccounts(request.addresses);
3487
+ return true;
3488
+ }
3489
+
3476
3490
  // --------------------------------------------------------------
3477
3491
  // eslint-disable-next-line @typescript-eslint/require-await
3478
3492
  async handle(id, type, request, port) {
@@ -3625,7 +3639,7 @@ export default class KoniExtension {
3625
3639
  case 'pri(transaction.history.getSubscription)':
3626
3640
  return await this.subscribeHistory(id, port);
3627
3641
 
3628
- /// Account management
3642
+ /* Account management */
3629
3643
  // Add account
3630
3644
  case 'pri(accounts.create.suriV2)':
3631
3645
  return await this.accountsCreateSuriV2(request);
@@ -3688,6 +3702,14 @@ export default class KoniExtension {
3688
3702
  case 'pri(accounts.resolveAddressToDomain)':
3689
3703
  return await this.resolveAddressByDomain(request);
3690
3704
 
3705
+ // Inject account
3706
+ case 'pri(accounts.inject.add)':
3707
+ return this.addInjects(request);
3708
+ case 'pri(accounts.inject.remove)':
3709
+ return this.removeInjects(request);
3710
+
3711
+ /* Account management */
3712
+
3691
3713
  // ChainService
3692
3714
  case 'pri(chainService.subscribeChainInfoMap)':
3693
3715
  return this.subscribeChainInfoMap(id, port);
@@ -1539,7 +1539,7 @@ export default class KoniState {
1539
1539
  });
1540
1540
  }
1541
1541
  async resetWallet(resetAll) {
1542
- this.keyringService.resetWallet(resetAll);
1542
+ await this.keyringService.resetWallet(resetAll);
1543
1543
  this.requestService.resetWallet();
1544
1544
  this.transactionService.resetWallet();
1545
1545
  await this.dbService.resetWallet(resetAll);
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "./cjs/detectPackage.js"
18
18
  ],
19
19
  "type": "module",
20
- "version": "1.1.11-0",
20
+ "version": "1.1.11-2",
21
21
  "main": "./cjs/index.js",
22
22
  "module": "./index.js",
23
23
  "types": "./index.d.ts",
@@ -1222,12 +1222,12 @@
1222
1222
  "@sora-substrate/type-definitions": "^1.17.7",
1223
1223
  "@substrate/connect": "^0.7.26",
1224
1224
  "@subwallet/chain-list": "0.2.13",
1225
- "@subwallet/extension-base": "^1.1.11-0",
1226
- "@subwallet/extension-chains": "^1.1.11-0",
1227
- "@subwallet/extension-dapp": "^1.1.11-0",
1228
- "@subwallet/extension-inject": "^1.1.11-0",
1229
- "@subwallet/keyring": "^0.0.10",
1230
- "@subwallet/ui-keyring": "^0.0.10",
1225
+ "@subwallet/extension-base": "^1.1.11-2",
1226
+ "@subwallet/extension-chains": "^1.1.11-2",
1227
+ "@subwallet/extension-dapp": "^1.1.11-2",
1228
+ "@subwallet/extension-inject": "^1.1.11-2",
1229
+ "@subwallet/keyring": "^0.1.1",
1230
+ "@subwallet/ui-keyring": "^0.1.1",
1231
1231
  "@walletconnect/sign-client": "^2.8.4",
1232
1232
  "@walletconnect/types": "^2.8.4",
1233
1233
  "@walletconnect/utils": "^2.8.4",
@@ -1256,6 +1256,8 @@
1256
1256
  "web3": "^1.10.0",
1257
1257
  "web3-core": "^1.10.0",
1258
1258
  "web3-core-helpers": "^1.10.0",
1259
+ "web3-core-subscriptions": "1.10.0",
1260
+ "web3-eth": "1.10.0",
1259
1261
  "web3-eth-contract": "^1.10.0",
1260
1262
  "web3-utils": "^1.10.0"
1261
1263
  }
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.11-0'
10
+ version: '1.1.11-2'
11
11
  };
@@ -16,7 +16,7 @@ export declare class SubWalletEvmProvider extends SafeEventEmitter implements Ev
16
16
  get connected(): boolean;
17
17
  isConnected(): boolean;
18
18
  protected subscribeExtensionEvents(): void;
19
- enable(): Promise<unknown>;
19
+ enable(): Promise<string[]>;
20
20
  on(eventName: string | symbol, listener: (...args: any[]) => void): this;
21
21
  once(eventName: string | symbol, listener: (...args: any[]) => void): this;
22
22
  request<T>({ method, params }: RequestArguments): Promise<T>;
@@ -1,5 +1,6 @@
1
1
  import { CurrentAccountInfo, KeyringState } from '@subwallet/extension-base/background/KoniTypes';
2
2
  import { EventService } from '@subwallet/extension-base/services/event-service';
3
+ import { InjectedAccountWithMeta } from '@subwallet/extension-inject/types';
3
4
  import { SubjectInfo } from '@subwallet/ui-keyring/observable/types';
4
5
  import { BehaviorSubject } from 'rxjs';
5
6
  export declare class KeyringService {
@@ -19,5 +20,7 @@ export declare class KeyringService {
19
20
  get currentAccount(): CurrentAccountInfo;
20
21
  setCurrentAccount(currentAccountData: CurrentAccountInfo): void;
21
22
  lock(): void;
22
- resetWallet(resetAll: boolean): void;
23
+ addInjectAccounts(accounts: InjectedAccountWithMeta[]): void;
24
+ removeInjectAccounts(addresses: string[]): void;
25
+ resetWallet(resetAll: boolean): Promise<void>;
23
26
  }
@@ -5,6 +5,7 @@ import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants';
5
5
  import { CurrentAccountStore } from '@subwallet/extension-base/stores';
6
6
  import { keyring } from '@subwallet/ui-keyring';
7
7
  import { BehaviorSubject } from 'rxjs';
8
+ import { stringShorten } from '@polkadot/util';
8
9
  export class KeyringService {
9
10
  currentAccountStore = new CurrentAccountStore();
10
11
  currentAccountSubject = new BehaviorSubject({
@@ -91,8 +92,39 @@ export class KeyringService {
91
92
  keyring.lockAll();
92
93
  this.updateKeyringState();
93
94
  }
94
- resetWallet(resetAll) {
95
+
96
+ /* Inject */
97
+
98
+ addInjectAccounts(accounts) {
99
+ keyring.addInjects(accounts.map(account => {
100
+ const name = account.meta.name || stringShorten(account.address);
101
+
102
+ // TODO: Add if need
103
+ // name = name.concat(' (', account.meta.source, ')');
104
+
105
+ return {
106
+ ...account,
107
+ meta: {
108
+ ...account.meta,
109
+ name: name
110
+ }
111
+ };
112
+ }));
113
+ }
114
+ removeInjectAccounts(addresses) {
115
+ keyring.removeInjects(addresses);
116
+ }
117
+
118
+ /* Inject */
119
+
120
+ /* Reset */
121
+ async resetWallet(resetAll) {
95
122
  keyring.resetWallet(resetAll);
123
+ await new Promise(resolve => {
124
+ setTimeout(() => {
125
+ resolve();
126
+ }, 500);
127
+ });
96
128
  this.updateKeyringState();
97
129
  this.currentAccountSubject.next({
98
130
  address: ALL_ACCOUNT_KEY,
@@ -26,7 +26,8 @@ export default class NotificationService {
26
26
 
27
27
  // Create a new chrome notification with link
28
28
  static createBrowserNotification(title, message, link) {
29
- chrome.notifications.create({
29
+ var _chrome, _chrome$notifications;
30
+ (_chrome = chrome) === null || _chrome === void 0 ? void 0 : (_chrome$notifications = _chrome.notifications) === null || _chrome$notifications === void 0 ? void 0 : _chrome$notifications.create({
30
31
  type: 'basic',
31
32
  title,
32
33
  message,
@@ -1,2 +1,3 @@
1
1
  export declare const EXTENSION_REQUEST_URL = "extension";
2
2
  export declare const PREDEFINED_CHAIN_DAPP_CHAIN_MAP: Record<string, string[]>;
3
+ export declare const WEB_APP_URL: string[];
@@ -6,4 +6,12 @@ export const PREDEFINED_CHAIN_DAPP_CHAIN_MAP = {
6
6
  'portal.astar.network': ['astar', 'astarEvm'],
7
7
  'apps.moonbeam.network': ['moonbeam', 'moonriver'],
8
8
  'app.stellaswap.com': ['moonbeam']
9
- };
9
+ };
10
+ export const WEB_APP_URL = [
11
+ /// Web app
12
+ 'localhost:9000',
13
+ // Local
14
+ 'subwallet-webapp.pages.dev',
15
+ // Pull request build
16
+ 'web.subwallet.app' // Production
17
+ ];
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import { _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils';
5
- import { PREDEFINED_CHAIN_DAPP_CHAIN_MAP } from '@subwallet/extension-base/services/request-service/constants';
5
+ import { PREDEFINED_CHAIN_DAPP_CHAIN_MAP, WEB_APP_URL } from '@subwallet/extension-base/services/request-service/constants';
6
6
  import AuthorizeStore from '@subwallet/extension-base/stores/Authorize';
7
7
  import { getDomainFromUrl, stripUrl } from '@subwallet/extension-base/utils';
8
8
  import { getId } from '@subwallet/extension-base/utils/getId';
@@ -209,7 +209,7 @@ export default class AuthRequestHandler {
209
209
  }
210
210
  const idStr = stripUrl(url);
211
211
  // Do not enqueue duplicate authorization requests.
212
- const isDuplicate = Object.values(this.#authRequestsV2).some(request => request.idStr === idStr);
212
+ const isDuplicate = Object.values(this.#authRequestsV2).some(_request => _request.idStr === idStr && _request.accountAuthType === request.accountAuthType);
213
213
  assert(!isDuplicate, 'The source {{url}} has a pending authorization request'.replace('{{url}}', url));
214
214
  const existedAuth = authList[idStr];
215
215
  const existedAccountAuthType = existedAuth === null || existedAuth === void 0 ? void 0 : existedAuth.accountAuthType;
@@ -235,6 +235,25 @@ export default class AuthRequestHandler {
235
235
  // Prevent appear confirmation popup
236
236
  return false;
237
237
  }
238
+ } else {
239
+ // Auto auth for web app
240
+
241
+ // Ignore white list
242
+ const isWhiteList = WEB_APP_URL.some(url => idStr.includes(url)) && false;
243
+ if (isWhiteList) {
244
+ const isAllowedMap = this.getAddressList(true);
245
+ authList[stripUrl(url)] = {
246
+ count: 0,
247
+ id: idStr,
248
+ isAllowed: true,
249
+ isAllowedMap,
250
+ origin,
251
+ url,
252
+ accountAuthType: 'both'
253
+ };
254
+ this.setAuthorize(authList);
255
+ return true;
256
+ }
238
257
  }
239
258
  return new Promise((resolve, reject) => {
240
259
  const id = getId();
@@ -21,7 +21,8 @@ export default class EvmRequestHandler {
21
21
  addTokenRequest: {},
22
22
  switchNetworkRequest: {},
23
23
  evmSignatureRequest: {},
24
- evmSendTransactionRequest: {}
24
+ evmSendTransactionRequest: {},
25
+ evmWatchTransactionRequest: {}
25
26
  });
26
27
  confirmationsPromiseMap = {};
27
28
  constructor(requestService) {
@@ -19,6 +19,7 @@ export default class TransactionService {
19
19
  private readonly notificationService;
20
20
  private readonly requestService;
21
21
  private readonly transactionSubject;
22
+ private readonly watchTransactionSubscribes;
22
23
  private get transactions();
23
24
  constructor(chainService: ChainService, eventService: EventService, requestService: RequestService, balanceService: BalanceService, historyService: HistoryService, notificationService: NotificationService, databaseService: DatabaseService);
24
25
  private get allTransactions();
@@ -27,6 +27,7 @@ import { BehaviorSubject } from 'rxjs';
27
27
  import { isHex } from '@polkadot/util';
28
28
  export default class TransactionService {
29
29
  transactionSubject = new BehaviorSubject({});
30
+ watchTransactionSubscribes = {};
30
31
  get transactions() {
31
32
  return this.transactionSubject.getValue();
32
33
  }
@@ -703,6 +704,7 @@ export default class TransactionService {
703
704
  payload.from = address;
704
705
  }
705
706
  const isExternal = !!account.isExternal;
707
+ const isInjected = !!account.isInjected;
706
708
 
707
709
  // generate hashPayload for EVM transaction
708
710
  payload.hashPayload = this.generateHashPayload(chain, payload);
@@ -723,62 +725,128 @@ export default class TransactionService {
723
725
  warnings: [],
724
726
  extrinsicHash: id
725
727
  };
726
- this.requestService.addConfirmation(id, url || EXTENSION_REQUEST_URL, 'evmSendTransactionRequest', payload, {}).then(async ({
727
- isApproved,
728
- payload
729
- }) => {
730
- if (isApproved) {
731
- let signedTransaction;
732
- if (!payload) {
733
- throw new EvmProviderError(EvmProviderErrorType.UNAUTHORIZED, t('Failed to sign'));
734
- }
735
- const web3Api = this.chainService.getEvmApi(chain).api;
736
- if (!isExternal) {
737
- signedTransaction = payload;
738
- } else {
739
- const signed = mergeTransactionAndSignature(txObject, payload);
740
- const recover = web3Api.eth.accounts.recoverTransaction(signed);
741
- if (recover.toLowerCase() !== account.address.toLowerCase()) {
742
- throw new EvmProviderError(EvmProviderErrorType.UNAUTHORIZED, t('Wrong signature. Please sign with the account you use in dApp'));
728
+ if (isInjected) {
729
+ this.requestService.addConfirmation(id, url || EXTENSION_REQUEST_URL, 'evmWatchTransactionRequest', payload, {}).then(async ({
730
+ isApproved,
731
+ payload
732
+ }) => {
733
+ if (isApproved) {
734
+ if (!payload) {
735
+ throw new EvmProviderError(EvmProviderErrorType.UNAUTHORIZED, 'Bad signature');
743
736
  }
744
- signedTransaction = signed;
745
- }
746
-
747
- // Emit signed event
748
- emitter.emit('signed', eventData);
737
+ const web3Api = this.chainService.getEvmApi(chain).api;
749
738
 
750
- // Send transaction
751
- this.handleTransactionTimeout(emitter, eventData);
739
+ // Emit signed event
740
+ emitter.emit('signed', eventData);
741
+ eventData.nonce = txObject.nonce;
742
+ eventData.startBlock = (await web3Api.eth.getBlockNumber()) - 3;
743
+ // Add start info
744
+ emitter.emit('send', eventData); // This event is needed after sending transaction with queue
752
745
 
753
- // Add start info
754
- eventData.nonce = txObject.nonce;
755
- eventData.startBlock = await web3Api.eth.getBlockNumber();
756
- emitter.emit('send', eventData); // This event is needed after sending transaction with queue
757
- signedTransaction && web3Api.eth.sendSignedTransaction(signedTransaction).once('transactionHash', hash => {
758
- eventData.extrinsicHash = hash;
746
+ const txHash = payload;
747
+ eventData.extrinsicHash = txHash;
759
748
  emitter.emit('extrinsicHash', eventData);
760
- }).once('receipt', rs => {
761
- eventData.extrinsicHash = rs.transactionHash;
762
- eventData.blockHash = rs.blockHash;
763
- eventData.blockNumber = rs.blockNumber;
764
- emitter.emit('success', eventData);
765
- }).once('error', e => {
766
- eventData.errors.push(new TransactionError(BasicTxErrorType.SEND_TRANSACTION_FAILED, t(e.message)));
749
+ this.watchTransactionSubscribes[id] = new Promise((resolve, reject) => {
750
+ // eslint-disable-next-line prefer-const
751
+ let subscribe;
752
+ const onComplete = () => {
753
+ var _subscribe, _subscribe$unsubscrib, _subscribe$unsubscrib2;
754
+ (_subscribe = subscribe) === null || _subscribe === void 0 ? void 0 : (_subscribe$unsubscrib = _subscribe.unsubscribe) === null || _subscribe$unsubscrib === void 0 ? void 0 : (_subscribe$unsubscrib2 = _subscribe$unsubscrib.call(_subscribe)) === null || _subscribe$unsubscrib2 === void 0 ? void 0 : _subscribe$unsubscrib2.then(console.debug).catch(console.debug);
755
+ delete this.watchTransactionSubscribes[id];
756
+ };
757
+ const onSuccess = rs => {
758
+ if (rs) {
759
+ eventData.extrinsicHash = rs.transactionHash;
760
+ eventData.blockHash = rs.blockHash;
761
+ eventData.blockNumber = rs.blockNumber;
762
+ emitter.emit('success', eventData);
763
+ onComplete();
764
+ resolve();
765
+ }
766
+ };
767
+ const onError = error => {
768
+ if (error) {
769
+ // TODO: Change type and message
770
+ eventData.errors.push(new TransactionError(BasicTxErrorType.UNABLE_TO_SEND, error.message));
771
+ emitter.emit('error', eventData);
772
+ onComplete();
773
+ reject(error);
774
+ }
775
+ };
776
+ const onCheck = () => {
777
+ web3Api.eth.getTransactionReceipt(txHash).then(onSuccess).catch(onError);
778
+ };
779
+ subscribe = web3Api.eth.subscribe('newBlockHeaders', onCheck);
780
+ });
781
+ } else {
782
+ this.removeTransaction(id);
783
+ eventData.errors.push(new TransactionError(BasicTxErrorType.USER_REJECT_REQUEST));
767
784
  emitter.emit('error', eventData);
768
- }).catch(e => {
769
- eventData.errors.push(new TransactionError(BasicTxErrorType.UNABLE_TO_SEND, t(e.message)));
785
+ }
786
+ }).catch(e => {
787
+ this.removeTransaction(id);
788
+ // TODO: Change type
789
+ eventData.errors.push(new TransactionError(BasicTxErrorType.UNABLE_TO_SIGN, e.message));
790
+ emitter.emit('error', eventData);
791
+ });
792
+ } else {
793
+ this.requestService.addConfirmation(id, url || EXTENSION_REQUEST_URL, 'evmSendTransactionRequest', payload, {}).then(async ({
794
+ isApproved,
795
+ payload
796
+ }) => {
797
+ if (isApproved) {
798
+ let signedTransaction;
799
+ if (!payload) {
800
+ throw new EvmProviderError(EvmProviderErrorType.UNAUTHORIZED, t('Failed to sign'));
801
+ }
802
+ const web3Api = this.chainService.getEvmApi(chain).api;
803
+ if (!isExternal) {
804
+ signedTransaction = payload;
805
+ } else {
806
+ const signed = mergeTransactionAndSignature(txObject, payload);
807
+ const recover = web3Api.eth.accounts.recoverTransaction(signed);
808
+ if (recover.toLowerCase() !== account.address.toLowerCase()) {
809
+ throw new EvmProviderError(EvmProviderErrorType.UNAUTHORIZED, t('Wrong signature. Please sign with the account you use in dApp'));
810
+ }
811
+ signedTransaction = signed;
812
+ }
813
+
814
+ // Emit signed event
815
+ emitter.emit('signed', eventData);
816
+
817
+ // Send transaction
818
+ this.handleTransactionTimeout(emitter, eventData);
819
+
820
+ // Add start info
821
+ eventData.nonce = txObject.nonce;
822
+ eventData.startBlock = await web3Api.eth.getBlockNumber();
823
+ emitter.emit('send', eventData); // This event is needed after sending transaction with queue
824
+ signedTransaction && web3Api.eth.sendSignedTransaction(signedTransaction).once('transactionHash', hash => {
825
+ eventData.extrinsicHash = hash;
826
+ emitter.emit('extrinsicHash', eventData);
827
+ }).once('receipt', rs => {
828
+ eventData.extrinsicHash = rs.transactionHash;
829
+ eventData.blockHash = rs.blockHash;
830
+ eventData.blockNumber = rs.blockNumber;
831
+ emitter.emit('success', eventData);
832
+ }).once('error', e => {
833
+ eventData.errors.push(new TransactionError(BasicTxErrorType.SEND_TRANSACTION_FAILED, t(e.message)));
834
+ emitter.emit('error', eventData);
835
+ }).catch(e => {
836
+ eventData.errors.push(new TransactionError(BasicTxErrorType.UNABLE_TO_SEND, t(e.message)));
837
+ emitter.emit('error', eventData);
838
+ });
839
+ } else {
840
+ this.removeTransaction(id);
841
+ eventData.errors.push(new TransactionError(BasicTxErrorType.USER_REJECT_REQUEST));
770
842
  emitter.emit('error', eventData);
771
- });
772
- } else {
843
+ }
844
+ }).catch(e => {
773
845
  this.removeTransaction(id);
774
- eventData.errors.push(new TransactionError(BasicTxErrorType.USER_REJECT_REQUEST));
846
+ eventData.errors.push(new TransactionError(BasicTxErrorType.UNABLE_TO_SIGN, t(e.message)));
775
847
  emitter.emit('error', eventData);
776
- }
777
- }).catch(e => {
778
- this.removeTransaction(id);
779
- eventData.errors.push(new TransactionError(BasicTxErrorType.UNABLE_TO_SIGN, t(e.message)));
780
- emitter.emit('error', eventData);
781
- });
848
+ });
849
+ }
782
850
  return emitter;
783
851
  }
784
852
  signAndSendSubstrateTransaction({
package/utils/lazy.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  export declare function removeLazy(key: string): void;
2
- export declare function addLazy(key: string, callback: () => void, lazyTime?: number, maxLazyTime?: number): void;
2
+ export declare function addLazy(key: string, callback: () => void, lazyTime?: number, maxLazyTime?: number, fireOnFirst?: boolean): void;
package/utils/lazy.js CHANGED
@@ -10,7 +10,7 @@ export function removeLazy(key) {
10
10
  }
11
11
 
12
12
  // Add or update new lazy thread
13
- export function addLazy(key, callback, lazyTime = 300, maxLazyTime = 3000) {
13
+ export function addLazy(key, callback, lazyTime = 300, maxLazyTime = 3000, fireOnFirst = true) {
14
14
  const existed = lazyMap[key];
15
15
  const now = new Date().getTime();
16
16
  if (existed) {
@@ -33,11 +33,24 @@ export function addLazy(key, callback, lazyTime = 300, maxLazyTime = 3000) {
33
33
  }, lazyTime);
34
34
  }
35
35
  } else {
36
- // Fire callback immediately in the first time
37
- callback();
38
- lazyMap[key] = {
39
- callback,
40
- lastFire: now
41
- };
36
+ if (fireOnFirst) {
37
+ // Fire callback immediately in the first time
38
+ callback();
39
+ lazyMap[key] = {
40
+ callback,
41
+ lastFire: now
42
+ };
43
+ } else {
44
+ lazyMap[key] = {
45
+ callback,
46
+ lastFire: now
47
+ };
48
+ lazyMap[key].timeout = setTimeout(() => {
49
+ // This will be fire in the last call of lazy thread
50
+ callback();
51
+ lazyMap[key].lastFire = new Date().getTime();
52
+ removeLazy(key);
53
+ }, lazyTime);
54
+ }
42
55
  }
43
56
  }