@subwallet/extension-base 1.1.11-1 → 1.1.12-1
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 +16 -6
- package/background/types.d.ts +4 -2
- package/cjs/koni/api/staking/bonding/utils.js +2 -1
- package/cjs/koni/api/tokens/evm/transfer.js +10 -4
- package/cjs/koni/background/handlers/Extension.js +33 -11
- package/cjs/koni/background/handlers/State.js +1 -1
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/chain-service/constants.js +10 -2
- package/cjs/services/chain-service/handler/EvmApi.js +24 -12
- package/cjs/services/keyring-service/index.js +33 -1
- package/cjs/services/notification-service/NotificationService.js +2 -1
- package/cjs/services/request-service/constants.js +11 -2
- package/cjs/services/request-service/handler/AuthRequestHandler.js +20 -1
- package/cjs/services/request-service/handler/EvmRequestHandler.js +2 -1
- package/cjs/services/setting-service/SettingService.js +5 -1
- package/cjs/services/transaction-service/index.js +124 -55
- package/cjs/utils/lazy.js +20 -6
- package/koni/api/staking/bonding/utils.js +2 -1
- package/koni/api/tokens/evm/transfer.d.ts +1 -1
- package/koni/api/tokens/evm/transfer.js +11 -5
- package/koni/background/handlers/Extension.d.ts +2 -0
- package/koni/background/handlers/Extension.js +33 -11
- package/koni/background/handlers/State.js +1 -1
- package/package.json +10 -8
- package/packageInfo.js +1 -1
- package/page/SubWalleEvmProvider.d.ts +1 -1
- package/services/chain-service/constants.d.ts +6 -0
- package/services/chain-service/constants.js +6 -0
- package/services/chain-service/handler/EvmApi.js +24 -12
- package/services/keyring-service/index.d.ts +4 -1
- package/services/keyring-service/index.js +33 -1
- package/services/notification-service/NotificationService.js +2 -1
- package/services/request-service/constants.d.ts +1 -0
- package/services/request-service/constants.js +9 -1
- package/services/request-service/handler/AuthRequestHandler.js +21 -2
- package/services/request-service/handler/EvmRequestHandler.js +2 -1
- package/services/setting-service/SettingService.js +5 -1
- package/services/transaction-service/index.d.ts +1 -0
- package/services/transaction-service/index.js +116 -48
- package/utils/lazy.d.ts +1 -1
- package/utils/lazy.js +20 -7
|
@@ -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
|
-
|
|
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,
|
|
@@ -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(
|
|
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) {
|
|
@@ -11,13 +11,17 @@ export default class SettingService {
|
|
|
11
11
|
passPhishingStore = new PassPhishingStore();
|
|
12
12
|
constructor() {
|
|
13
13
|
let old = localStorage.getItem(LANGUAGE) || 'en';
|
|
14
|
-
|
|
14
|
+
const updateLanguage = ({
|
|
15
15
|
language
|
|
16
16
|
}) => {
|
|
17
17
|
if (language !== old) {
|
|
18
18
|
old = language;
|
|
19
19
|
i18n.changeLanguage(language).catch(console.error);
|
|
20
20
|
}
|
|
21
|
+
};
|
|
22
|
+
this.getSettings(updateLanguage);
|
|
23
|
+
this.settingsStore.getSubject().subscribe({
|
|
24
|
+
next: updateLanguage
|
|
21
25
|
});
|
|
22
26
|
}
|
|
23
27
|
getSubject() {
|
|
@@ -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
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
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
|
-
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
// Emit signed event
|
|
748
|
-
emitter.emit('signed', eventData);
|
|
737
|
+
const web3Api = this.chainService.getEvmApi(chain).api;
|
|
749
738
|
|
|
750
|
-
|
|
751
|
-
|
|
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
|
-
|
|
754
|
-
|
|
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
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
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
|
-
}
|
|
769
|
-
|
|
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
|
-
}
|
|
843
|
+
}
|
|
844
|
+
}).catch(e => {
|
|
773
845
|
this.removeTransaction(id);
|
|
774
|
-
eventData.errors.push(new TransactionError(BasicTxErrorType.
|
|
846
|
+
eventData.errors.push(new TransactionError(BasicTxErrorType.UNABLE_TO_SIGN, t(e.message)));
|
|
775
847
|
emitter.emit('error', eventData);
|
|
776
|
-
}
|
|
777
|
-
}
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
}
|