@subwallet/extension-base 0.3.6-0 → 0.3.6-3
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/{build/background → background}/KoniTypes.d.ts +0 -0
- package/{build/background → background}/KoniTypes.js +0 -0
- package/{build/background → background}/RequestBytesSign.d.ts +0 -0
- package/{build/background → background}/RequestBytesSign.js +0 -0
- package/{build/background → background}/RequestExtrinsicSign.d.ts +0 -0
- package/{build/background → background}/RequestExtrinsicSign.js +0 -0
- package/{build/background → background}/handlers/Extension.d.ts +1 -1
- package/{build/background → background}/handlers/Extension.js +2 -2
- package/{build/background → background}/handlers/State.d.ts +0 -0
- package/{build/background → background}/handlers/State.js +0 -0
- package/{build/background → background}/handlers/Tabs.d.ts +0 -0
- package/{build/background → background}/handlers/Tabs.js +0 -0
- package/{build/background → background}/handlers/helpers.d.ts +0 -0
- package/{build/background → background}/handlers/helpers.js +0 -0
- package/{build/background → background}/handlers/index.d.ts +0 -0
- package/{build/background → background}/handlers/index.js +0 -0
- package/{build/background → background}/handlers/subscriptions.d.ts +0 -0
- package/{build/background → background}/handlers/subscriptions.js +0 -0
- package/{build/background → background}/types.d.ts +0 -0
- package/{build/background → background}/types.js +0 -0
- package/{build/bundle.d.ts → bundle.d.ts} +0 -0
- package/{build/bundle.js → bundle.js} +0 -0
- package/{build-cjs → cjs}/background/KoniTypes.js +0 -0
- package/{build-cjs → cjs}/background/RequestBytesSign.js +0 -0
- package/{build-cjs → cjs}/background/RequestExtrinsicSign.js +0 -0
- package/{build/cjs → cjs}/background/handlers/Extension.js +4 -4
- package/{build-cjs → cjs}/background/handlers/State.js +0 -0
- package/{build-cjs → cjs}/background/handlers/Tabs.js +0 -0
- package/{build-cjs → cjs}/background/handlers/helpers.js +0 -0
- package/{build-cjs → cjs}/background/handlers/index.js +0 -0
- package/{build-cjs → cjs}/background/handlers/subscriptions.js +0 -0
- package/{build-cjs → cjs}/background/types.js +0 -0
- package/{build-cjs → cjs}/bundle.js +0 -0
- package/{build-cjs → cjs}/defaults.js +0 -0
- package/{build-cjs → cjs}/detectOther.js +0 -0
- package/{build-cjs → cjs}/detectPackage.js +0 -0
- package/{build-cjs → cjs}/index.js +0 -0
- package/{build/cjs → cjs}/package.json +0 -0
- package/{build-cjs → cjs}/packageInfo.js +1 -1
- package/{build-cjs → cjs}/page/Accounts.js +0 -0
- package/{build-cjs → cjs}/page/Injected.js +0 -0
- package/{build-cjs → cjs}/page/Metadata.js +0 -0
- package/{build-cjs → cjs}/page/PostMessageProvider.js +0 -0
- package/{build-cjs → cjs}/page/Signer.js +0 -0
- package/{build-cjs → cjs}/page/index.js +0 -0
- package/{build-cjs → cjs}/page/types.js +0 -0
- package/{build-cjs → cjs}/stores/Accounts.js +0 -0
- package/{build-cjs → cjs}/stores/Base.js +0 -0
- package/{build-cjs → cjs}/stores/Metadata.js +0 -0
- package/{build-cjs → cjs}/stores/index.js +0 -0
- package/{build-cjs → cjs}/types.js +0 -0
- package/{build-cjs → cjs}/utils/canDerive.js +0 -0
- package/{build-cjs → cjs}/utils/getId.js +0 -0
- package/{build-cjs → cjs}/utils/index.js +0 -0
- package/{build/defaults.d.ts → defaults.d.ts} +0 -0
- package/{build/defaults.js → defaults.js} +0 -0
- package/{build/detectOther.d.ts → detectOther.d.ts} +0 -0
- package/{build/detectOther.js → detectOther.js} +0 -0
- package/{build/detectPackage.d.ts → detectPackage.d.ts} +0 -0
- package/{build/detectPackage.js → detectPackage.js} +0 -0
- package/{build/index.d.ts → index.d.ts} +0 -0
- package/{build/index.js → index.js} +0 -0
- package/package.json +174 -10
- package/{build/packageInfo.d.ts → packageInfo.d.ts} +0 -0
- package/{build/packageInfo.js → packageInfo.js} +1 -1
- package/{build/page → page}/Accounts.d.ts +0 -0
- package/{build/page → page}/Accounts.js +0 -0
- package/{build/page → page}/Injected.d.ts +0 -0
- package/{build/page → page}/Injected.js +0 -0
- package/{build/page → page}/Metadata.d.ts +0 -0
- package/{build/page → page}/Metadata.js +0 -0
- package/{build/page → page}/PostMessageProvider.d.ts +0 -0
- package/{build/page → page}/PostMessageProvider.js +0 -0
- package/{build/page → page}/Signer.d.ts +0 -0
- package/{build/page → page}/Signer.js +0 -0
- package/{build/page → page}/index.d.ts +1 -1
- package/{build/page → page}/index.js +0 -0
- package/{build/page → page}/types.d.ts +0 -0
- package/{build/page → page}/types.js +0 -0
- package/{build/stores → stores}/Accounts.d.ts +0 -0
- package/{build/stores → stores}/Accounts.js +0 -0
- package/{build/stores → stores}/Base.d.ts +0 -0
- package/{build/stores → stores}/Base.js +0 -0
- package/{build/stores → stores}/Metadata.d.ts +0 -0
- package/{build/stores → stores}/Metadata.js +0 -0
- package/{build/stores → stores}/index.d.ts +0 -0
- package/{build/stores → stores}/index.js +0 -0
- package/{build/types.d.ts → types.d.ts} +0 -0
- package/{build/types.js → types.js} +0 -0
- package/{build/utils → utils}/canDerive.d.ts +0 -0
- package/{build/utils → utils}/canDerive.js +0 -0
- package/{build/utils → utils}/getId.d.ts +0 -0
- package/{build/utils → utils}/getId.js +0 -0
- package/{build/utils → utils}/index.d.ts +0 -0
- package/{build/utils → utils}/index.js +0 -0
- package/build/LICENSE +0 -201
- package/build/README.md +0 -10
- package/build/cjs/background/KoniTypes.js +0 -69
- package/build/cjs/background/RequestBytesSign.js +0 -27
- package/build/cjs/background/RequestExtrinsicSign.js +0 -23
- package/build/cjs/background/handlers/State.js +0 -472
- package/build/cjs/background/handlers/Tabs.js +0 -273
- package/build/cjs/background/handlers/helpers.js +0 -20
- package/build/cjs/background/handlers/index.js +0 -60
- package/build/cjs/background/handlers/subscriptions.js +0 -32
- package/build/cjs/background/types.js +0 -1
- package/build/cjs/bundle.js +0 -13
- package/build/cjs/defaults.js +0 -26
- package/build/cjs/detectOther.js +0 -17
- package/build/cjs/detectPackage.js +0 -14
- package/build/cjs/index.js +0 -18
- package/build/cjs/packageInfo.js +0 -16
- package/build/cjs/page/Accounts.js +0 -31
- package/build/cjs/page/Injected.js +0 -30
- package/build/cjs/page/Metadata.js +0 -27
- package/build/cjs/page/PostMessageProvider.js +0 -184
- package/build/cjs/page/Signer.js +0 -44
- package/build/cjs/page/index.js +0 -76
- package/build/cjs/page/types.js +0 -1
- package/build/cjs/stores/Accounts.js +0 -33
- package/build/cjs/stores/Base.js +0 -84
- package/build/cjs/stores/Metadata.js +0 -23
- package/build/cjs/stores/index.js +0 -23
- package/build/cjs/types.js +0 -1
- package/build/cjs/utils/canDerive.js +0 -12
- package/build/cjs/utils/getId.js +0 -16
- package/build/cjs/utils/index.js +0 -13
- package/build/package.json +0 -210
- package/build-cjs/background/handlers/Extension.js +0 -764
- package/src/background/KoniTypes.ts +0 -537
- package/src/background/RequestBytesSign.ts +0 -30
- package/src/background/RequestExtrinsicSign.ts +0 -23
- package/src/background/handlers/Extension.spec.ts +0 -456
- package/src/background/handlers/Extension.ts +0 -627
- package/src/background/handlers/State.ts +0 -513
- package/src/background/handlers/Tabs.ts +0 -223
- package/src/background/handlers/helpers.ts +0 -14
- package/src/background/handlers/index.ts +0 -49
- package/src/background/handlers/subscriptions.ts +0 -30
- package/src/background/types.ts +0 -437
- package/src/bundle.ts +0 -4
- package/src/defaults.ts +0 -24
- package/src/detectOther.ts +0 -8
- package/src/detectPackage.ts +0 -11
- package/src/index.ts +0 -7
- package/src/packageInfo.ts +0 -6
- package/src/page/Accounts.ts +0 -27
- package/src/page/Injected.ts +0 -27
- package/src/page/Metadata.ts +0 -22
- package/src/page/PostMessageProvider.ts +0 -178
- package/src/page/Signer.ts +0 -45
- package/src/page/index.ts +0 -87
- package/src/page/types.ts +0 -10
- package/src/stores/Accounts.ts +0 -24
- package/src/stores/Base.ts +0 -81
- package/src/stores/Metadata.ts +0 -13
- package/src/stores/index.ts +0 -5
- package/src/types.ts +0 -12
- package/src/utils/canDerive.ts +0 -8
- package/src/utils/getId.ts +0 -10
- package/src/utils/index.ts +0 -4
- package/tsconfig.build.json +0 -18
- package/tsconfig.build.tsbuildinfo +0 -1
- package/tsconfig.json +0 -14
|
@@ -1,627 +0,0 @@
|
|
|
1
|
-
// Copyright 2019-2022 @subwallet/extension authors & contributors
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
|
|
4
|
-
import type { MetadataDef } from '@subwallet/extension-inject/types';
|
|
5
|
-
import type { KeyringPair, KeyringPair$Json, KeyringPair$Meta } from '@polkadot/keyring/types';
|
|
6
|
-
import type { SignerPayloadJSON, SignerPayloadRaw } from '@polkadot/types/types';
|
|
7
|
-
import type { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
|
|
8
|
-
import type { KeypairType } from '@polkadot/util-crypto/types';
|
|
9
|
-
import type { AccountJson, AllowedPath, AuthorizeRequest, MessageTypes, MetadataRequest, RequestAccountChangePassword, RequestAccountCreateExternal, RequestAccountCreateHardware, RequestAccountCreateSuri, RequestAccountEdit, RequestAccountExport, RequestAccountForget, RequestAccountShow, RequestAccountTie, RequestAccountValidate, RequestAuthorizeApprove, RequestAuthorizeReject, RequestBatchRestore, RequestDeriveCreate, RequestDeriveValidate, RequestJsonRestore, RequestMetadataApprove, RequestMetadataReject, RequestSeedCreate, RequestSeedValidate, RequestSigningApprovePassword, RequestSigningApproveSignature, RequestSigningCancel, RequestSigningIsLocked, RequestTypes, ResponseAccountExport, ResponseAuthorizeList, ResponseDeriveValidate, ResponseJsonGetAccountInfo, ResponseSeedCreate, ResponseSeedValidate, ResponseSigningIsLocked, ResponseType, SigningRequest } from '../types';
|
|
10
|
-
|
|
11
|
-
import { ALLOWED_PATH, PASSWORD_EXPIRY_MS } from '@subwallet/extension-base/defaults';
|
|
12
|
-
|
|
13
|
-
import { TypeRegistry } from '@polkadot/types';
|
|
14
|
-
import keyring from '@polkadot/ui-keyring';
|
|
15
|
-
import { accounts as accountsObservable } from '@polkadot/ui-keyring/observable/accounts';
|
|
16
|
-
import { assert, isHex } from '@polkadot/util';
|
|
17
|
-
import { keyExtractSuri, mnemonicGenerate, mnemonicValidate } from '@polkadot/util-crypto';
|
|
18
|
-
|
|
19
|
-
import { withErrorLog } from './helpers';
|
|
20
|
-
import State from './State';
|
|
21
|
-
import { createSubscription, unsubscribe } from './subscriptions';
|
|
22
|
-
|
|
23
|
-
type CachedUnlocks = Record<string, number>;
|
|
24
|
-
|
|
25
|
-
export const SEED_DEFAULT_LENGTH = 12;
|
|
26
|
-
export const SEED_LENGTHS = [12, 15, 18, 21, 24];
|
|
27
|
-
|
|
28
|
-
export const ETH_DERIVE_DEFAULT = '/m/44\'/60\'/0\'/0/0';
|
|
29
|
-
|
|
30
|
-
// a global registry to use internally
|
|
31
|
-
const registry = new TypeRegistry();
|
|
32
|
-
|
|
33
|
-
export function getSuri (seed: string, type?: KeypairType): string {
|
|
34
|
-
return type === 'ethereum'
|
|
35
|
-
? `${seed}${ETH_DERIVE_DEFAULT}`
|
|
36
|
-
: seed;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function transformAccounts (accounts: SubjectInfo): AccountJson[] {
|
|
40
|
-
return Object.values(accounts).map(({ json: { address, meta }, type }): AccountJson => ({
|
|
41
|
-
address,
|
|
42
|
-
...meta,
|
|
43
|
-
type
|
|
44
|
-
}));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function isJsonPayload (value: SignerPayloadJSON | SignerPayloadRaw): value is SignerPayloadJSON {
|
|
48
|
-
return (value as SignerPayloadJSON).genesisHash !== undefined;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export default class Extension {
|
|
52
|
-
readonly #cachedUnlocks: CachedUnlocks;
|
|
53
|
-
|
|
54
|
-
readonly #state: State;
|
|
55
|
-
|
|
56
|
-
constructor (state: State) {
|
|
57
|
-
this.#cachedUnlocks = {};
|
|
58
|
-
this.#state = state;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
private accountsCreateExternal ({ address, genesisHash, name }: RequestAccountCreateExternal): boolean {
|
|
62
|
-
keyring.addExternal(address, { genesisHash, name });
|
|
63
|
-
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
private accountsCreateHardware ({ accountIndex, address, addressOffset, genesisHash, hardwareType, name }: RequestAccountCreateHardware): boolean {
|
|
68
|
-
keyring.addHardware(address, hardwareType, { accountIndex, addressOffset, genesisHash, name });
|
|
69
|
-
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
private accountsCreateSuri ({ genesisHash, name, password, suri, type }: RequestAccountCreateSuri): boolean {
|
|
74
|
-
keyring.addUri(getSuri(suri, type), password, { genesisHash, name }, type);
|
|
75
|
-
|
|
76
|
-
return true;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
private accountsChangePassword ({ address, newPass, oldPass }: RequestAccountChangePassword): boolean {
|
|
80
|
-
const pair = keyring.getPair(address);
|
|
81
|
-
|
|
82
|
-
assert(pair, 'Unable to find pair');
|
|
83
|
-
|
|
84
|
-
try {
|
|
85
|
-
if (!pair.isLocked) {
|
|
86
|
-
pair.lock();
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
pair.decodePkcs8(oldPass);
|
|
90
|
-
} catch (error) {
|
|
91
|
-
throw new Error('oldPass is invalid');
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
keyring.encryptAccount(pair, newPass);
|
|
95
|
-
|
|
96
|
-
return true;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
private accountsEdit ({ address, name }: RequestAccountEdit): boolean {
|
|
100
|
-
const pair = keyring.getPair(address);
|
|
101
|
-
|
|
102
|
-
assert(pair, 'Unable to find pair');
|
|
103
|
-
|
|
104
|
-
keyring.saveAccountMeta(pair, { ...pair.meta, name });
|
|
105
|
-
|
|
106
|
-
return true;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
private accountsExport ({ address, password }: RequestAccountExport): ResponseAccountExport {
|
|
110
|
-
return { exportedJson: keyring.backupAccount(keyring.getPair(address), password) };
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// private async accountsBatchExport ({ addresses, password }: RequestAccountBatchExport): Promise<ResponseAccountsExport> {
|
|
114
|
-
// return {
|
|
115
|
-
// exportedJson: await keyring.backupAccounts(addresses, password)
|
|
116
|
-
// };
|
|
117
|
-
// }
|
|
118
|
-
|
|
119
|
-
private accountsForget ({ address }: RequestAccountForget): boolean {
|
|
120
|
-
keyring.forgetAccount(address);
|
|
121
|
-
|
|
122
|
-
return true;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
private refreshAccountPasswordCache (pair: KeyringPair): number {
|
|
126
|
-
const { address } = pair;
|
|
127
|
-
|
|
128
|
-
const savedExpiry = this.#cachedUnlocks[address] || 0;
|
|
129
|
-
const remainingTime = savedExpiry - Date.now();
|
|
130
|
-
|
|
131
|
-
if (remainingTime < 0) {
|
|
132
|
-
this.#cachedUnlocks[address] = 0;
|
|
133
|
-
pair.lock();
|
|
134
|
-
|
|
135
|
-
return 0;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return remainingTime;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
private accountsShow ({ address, isShowing }: RequestAccountShow): boolean {
|
|
142
|
-
const pair = keyring.getPair(address);
|
|
143
|
-
|
|
144
|
-
assert(pair, 'Unable to find pair');
|
|
145
|
-
|
|
146
|
-
keyring.saveAccountMeta(pair, { ...pair.meta, isHidden: !isShowing });
|
|
147
|
-
|
|
148
|
-
return true;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
private accountsTie ({ address, genesisHash }: RequestAccountTie): boolean {
|
|
152
|
-
const pair = keyring.getPair(address);
|
|
153
|
-
|
|
154
|
-
assert(pair, 'Unable to find pair');
|
|
155
|
-
|
|
156
|
-
keyring.saveAccountMeta(pair, { ...pair.meta, genesisHash });
|
|
157
|
-
|
|
158
|
-
return true;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
private accountsValidate ({ address, password }: RequestAccountValidate): boolean {
|
|
162
|
-
try {
|
|
163
|
-
keyring.backupAccount(keyring.getPair(address), password);
|
|
164
|
-
|
|
165
|
-
return true;
|
|
166
|
-
} catch (e) {
|
|
167
|
-
return false;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// FIXME This looks very much like what we have in Tabs
|
|
172
|
-
private accountsSubscribe (id: string, port: chrome.runtime.Port): boolean {
|
|
173
|
-
const cb = createSubscription<'pri(accounts.subscribe)'>(id, port);
|
|
174
|
-
const subscription = accountsObservable.subject.subscribe((accounts: SubjectInfo): void =>
|
|
175
|
-
cb(transformAccounts(accounts))
|
|
176
|
-
);
|
|
177
|
-
|
|
178
|
-
port.onDisconnect.addListener((): void => {
|
|
179
|
-
unsubscribe(id);
|
|
180
|
-
subscription.unsubscribe();
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
return true;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
private authorizeApprove ({ id }: RequestAuthorizeApprove): boolean {
|
|
187
|
-
const queued = this.#state.getAuthRequest(id);
|
|
188
|
-
|
|
189
|
-
assert(queued, 'Unable to find request');
|
|
190
|
-
|
|
191
|
-
const { resolve } = queued;
|
|
192
|
-
|
|
193
|
-
resolve(true);
|
|
194
|
-
|
|
195
|
-
return true;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
private getAuthList (): ResponseAuthorizeList {
|
|
199
|
-
return { list: this.#state.authUrls };
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
private authorizeReject ({ id }: RequestAuthorizeReject): boolean {
|
|
203
|
-
const queued = this.#state.getAuthRequest(id);
|
|
204
|
-
|
|
205
|
-
assert(queued, 'Unable to find request');
|
|
206
|
-
|
|
207
|
-
const { reject } = queued;
|
|
208
|
-
|
|
209
|
-
reject(new Error('Rejected'));
|
|
210
|
-
|
|
211
|
-
return true;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// FIXME This looks very much like what we have in accounts
|
|
215
|
-
private authorizeSubscribe (id: string, port: chrome.runtime.Port): boolean {
|
|
216
|
-
const cb = createSubscription<'pri(authorize.requests)'>(id, port);
|
|
217
|
-
const subscription = this.#state.authSubject.subscribe((requests: AuthorizeRequest[]): void =>
|
|
218
|
-
cb(requests)
|
|
219
|
-
);
|
|
220
|
-
|
|
221
|
-
port.onDisconnect.addListener((): void => {
|
|
222
|
-
unsubscribe(id);
|
|
223
|
-
subscription.unsubscribe();
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
return true;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
private metadataApprove ({ id }: RequestMetadataApprove): boolean {
|
|
230
|
-
const queued = this.#state.getMetaRequest(id);
|
|
231
|
-
|
|
232
|
-
assert(queued, 'Unable to find request');
|
|
233
|
-
|
|
234
|
-
const { request, resolve } = queued;
|
|
235
|
-
|
|
236
|
-
this.#state.saveMetadata(request);
|
|
237
|
-
|
|
238
|
-
resolve(true);
|
|
239
|
-
|
|
240
|
-
return true;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
private metadataGet (genesisHash: string | null): MetadataDef | null {
|
|
244
|
-
return this.#state.knownMetadata.find((result) => result.genesisHash === genesisHash) || null;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
private metadataList (): MetadataDef[] {
|
|
248
|
-
return this.#state.knownMetadata;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
private metadataReject ({ id }: RequestMetadataReject): boolean {
|
|
252
|
-
const queued = this.#state.getMetaRequest(id);
|
|
253
|
-
|
|
254
|
-
assert(queued, 'Unable to find request');
|
|
255
|
-
|
|
256
|
-
const { reject } = queued;
|
|
257
|
-
|
|
258
|
-
reject(new Error('Rejected'));
|
|
259
|
-
|
|
260
|
-
return true;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
private metadataSubscribe (id: string, port: chrome.runtime.Port): boolean {
|
|
264
|
-
const cb = createSubscription<'pri(metadata.requests)'>(id, port);
|
|
265
|
-
const subscription = this.#state.metaSubject.subscribe((requests: MetadataRequest[]): void =>
|
|
266
|
-
cb(requests)
|
|
267
|
-
);
|
|
268
|
-
|
|
269
|
-
port.onDisconnect.addListener((): void => {
|
|
270
|
-
unsubscribe(id);
|
|
271
|
-
subscription.unsubscribe();
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
return true;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
private jsonRestore ({ file, password }: RequestJsonRestore): void {
|
|
278
|
-
try {
|
|
279
|
-
keyring.restoreAccount(file, password);
|
|
280
|
-
} catch (error) {
|
|
281
|
-
throw new Error((error as Error).message);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
private batchRestore ({ file, password }: RequestBatchRestore): void {
|
|
286
|
-
try {
|
|
287
|
-
keyring.restoreAccounts(file, password);
|
|
288
|
-
} catch (error) {
|
|
289
|
-
throw new Error((error as Error).message);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
private jsonGetAccountInfo (json: KeyringPair$Json): ResponseJsonGetAccountInfo {
|
|
294
|
-
try {
|
|
295
|
-
const { address, meta: { genesisHash, name }, type } = keyring.createFromJson(json);
|
|
296
|
-
|
|
297
|
-
return {
|
|
298
|
-
address,
|
|
299
|
-
genesisHash,
|
|
300
|
-
name,
|
|
301
|
-
type
|
|
302
|
-
} as ResponseJsonGetAccountInfo;
|
|
303
|
-
} catch (e) {
|
|
304
|
-
console.error(e);
|
|
305
|
-
throw new Error((e as Error).message);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
private seedCreate ({ length = SEED_DEFAULT_LENGTH, seed: _seed, type }: RequestSeedCreate): ResponseSeedCreate {
|
|
310
|
-
const seed = _seed || mnemonicGenerate(length);
|
|
311
|
-
|
|
312
|
-
return {
|
|
313
|
-
address: keyring.createFromUri(getSuri(seed, type), {}, type).address,
|
|
314
|
-
seed
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
private seedValidate ({ suri, type }: RequestSeedValidate): ResponseSeedValidate {
|
|
319
|
-
const { phrase } = keyExtractSuri(suri);
|
|
320
|
-
|
|
321
|
-
if (isHex(phrase)) {
|
|
322
|
-
assert(isHex(phrase, 256), 'Hex seed needs to be 256-bits');
|
|
323
|
-
} else {
|
|
324
|
-
// sadly isHex detects as string, so we need a cast here
|
|
325
|
-
assert(SEED_LENGTHS.includes((phrase).split(' ').length), `Mnemonic needs to contain ${SEED_LENGTHS.join(', ')} words`);
|
|
326
|
-
assert(mnemonicValidate(phrase), 'Not a valid mnemonic seed');
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
return {
|
|
330
|
-
address: keyring.createFromUri(getSuri(suri, type), {}, type).address,
|
|
331
|
-
suri
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
private signingApprovePassword ({ id, password, savePass }: RequestSigningApprovePassword): boolean {
|
|
336
|
-
const queued = this.#state.getSignRequest(id);
|
|
337
|
-
|
|
338
|
-
assert(queued, 'Unable to find request');
|
|
339
|
-
|
|
340
|
-
const { reject, request, resolve } = queued;
|
|
341
|
-
const pair = keyring.getPair(queued.account.address);
|
|
342
|
-
|
|
343
|
-
// unlike queued.account.address the following
|
|
344
|
-
// address is encoded with the default prefix
|
|
345
|
-
// which what is used for password caching mapping
|
|
346
|
-
const { address } = pair;
|
|
347
|
-
|
|
348
|
-
if (!pair) {
|
|
349
|
-
reject(new Error('Unable to find pair'));
|
|
350
|
-
|
|
351
|
-
return false;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
this.refreshAccountPasswordCache(pair);
|
|
355
|
-
|
|
356
|
-
// if the keyring pair is locked, the password is needed
|
|
357
|
-
if (pair.isLocked && !password) {
|
|
358
|
-
reject(new Error('Password needed to unlock the account'));
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
if (pair.isLocked) {
|
|
362
|
-
pair.decodePkcs8(password);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
const { payload } = request;
|
|
366
|
-
|
|
367
|
-
if (isJsonPayload(payload)) {
|
|
368
|
-
// Get the metadata for the genesisHash
|
|
369
|
-
const currentMetadata = this.#state.knownMetadata.find((meta: MetadataDef) =>
|
|
370
|
-
meta.genesisHash === payload.genesisHash);
|
|
371
|
-
|
|
372
|
-
// set the registry before calling the sign function
|
|
373
|
-
registry.setSignedExtensions(payload.signedExtensions, currentMetadata?.userExtensions);
|
|
374
|
-
|
|
375
|
-
if (currentMetadata) {
|
|
376
|
-
registry.register(currentMetadata?.types);
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
const result = request.sign(registry, pair);
|
|
381
|
-
|
|
382
|
-
if (savePass) {
|
|
383
|
-
this.#cachedUnlocks[address] = Date.now() + PASSWORD_EXPIRY_MS;
|
|
384
|
-
} else {
|
|
385
|
-
pair.lock();
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
resolve({
|
|
389
|
-
id,
|
|
390
|
-
...result
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
return true;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
private signingApproveSignature ({ id, signature }: RequestSigningApproveSignature): boolean {
|
|
397
|
-
const queued = this.#state.getSignRequest(id);
|
|
398
|
-
|
|
399
|
-
assert(queued, 'Unable to find request');
|
|
400
|
-
|
|
401
|
-
const { resolve } = queued;
|
|
402
|
-
|
|
403
|
-
resolve({ id, signature });
|
|
404
|
-
|
|
405
|
-
return true;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
private signingCancel ({ id }: RequestSigningCancel): boolean {
|
|
409
|
-
const queued = this.#state.getSignRequest(id);
|
|
410
|
-
|
|
411
|
-
assert(queued, 'Unable to find request');
|
|
412
|
-
|
|
413
|
-
const { reject } = queued;
|
|
414
|
-
|
|
415
|
-
reject(new Error('Cancelled'));
|
|
416
|
-
|
|
417
|
-
return true;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
private signingIsLocked ({ id }: RequestSigningIsLocked): ResponseSigningIsLocked {
|
|
421
|
-
const queued = this.#state.getSignRequest(id);
|
|
422
|
-
|
|
423
|
-
assert(queued, 'Unable to find request');
|
|
424
|
-
|
|
425
|
-
const address = queued.request.payload.address;
|
|
426
|
-
const pair = keyring.getPair(address);
|
|
427
|
-
|
|
428
|
-
assert(pair, 'Unable to find pair');
|
|
429
|
-
|
|
430
|
-
const remainingTime = this.refreshAccountPasswordCache(pair);
|
|
431
|
-
|
|
432
|
-
return {
|
|
433
|
-
isLocked: pair.isLocked,
|
|
434
|
-
remainingTime
|
|
435
|
-
};
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
// FIXME This looks very much like what we have in authorization
|
|
439
|
-
private signingSubscribe (id: string, port: chrome.runtime.Port): boolean {
|
|
440
|
-
const cb = createSubscription<'pri(signing.requests)'>(id, port);
|
|
441
|
-
const subscription = this.#state.signSubject.subscribe((requests: SigningRequest[]): void =>
|
|
442
|
-
cb(requests)
|
|
443
|
-
);
|
|
444
|
-
|
|
445
|
-
port.onDisconnect.addListener((): void => {
|
|
446
|
-
unsubscribe(id);
|
|
447
|
-
subscription.unsubscribe();
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
return true;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
private windowOpen (path: AllowedPath): boolean {
|
|
454
|
-
const url = `${chrome.extension.getURL('index.html')}#${path}`;
|
|
455
|
-
|
|
456
|
-
if (!ALLOWED_PATH.includes(path)) {
|
|
457
|
-
console.error('Not allowed to open the url:', url);
|
|
458
|
-
|
|
459
|
-
return false;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
withErrorLog(() => chrome.tabs.create({ url }));
|
|
463
|
-
|
|
464
|
-
return true;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
private derive (parentAddress: string, suri: string, password: string, metadata: KeyringPair$Meta): KeyringPair {
|
|
468
|
-
const parentPair = keyring.getPair(parentAddress);
|
|
469
|
-
|
|
470
|
-
try {
|
|
471
|
-
parentPair.decodePkcs8(password);
|
|
472
|
-
} catch (e) {
|
|
473
|
-
throw new Error('invalid password');
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
try {
|
|
477
|
-
return parentPair.derive(suri, metadata);
|
|
478
|
-
} catch (err) {
|
|
479
|
-
throw new Error(`"${suri}" is not a valid derivation path`);
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
private derivationValidate ({ parentAddress, parentPassword, suri }: RequestDeriveValidate): ResponseDeriveValidate {
|
|
484
|
-
const childPair = this.derive(parentAddress, suri, parentPassword, {});
|
|
485
|
-
|
|
486
|
-
return {
|
|
487
|
-
address: childPair.address,
|
|
488
|
-
suri
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
private derivationCreate ({ genesisHash, name, parentAddress, parentPassword, password, suri }: RequestDeriveCreate): boolean {
|
|
493
|
-
const childPair = this.derive(parentAddress, suri, parentPassword, {
|
|
494
|
-
genesisHash,
|
|
495
|
-
name,
|
|
496
|
-
parentAddress,
|
|
497
|
-
suri
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
keyring.addPair(childPair, password);
|
|
501
|
-
|
|
502
|
-
return true;
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
private toggleAuthorization (url: string): ResponseAuthorizeList {
|
|
506
|
-
return { list: this.#state.toggleAuthorization(url) };
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
// Weird thought, the eslint override is not needed in Tabs
|
|
510
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
511
|
-
public async handle<TMessageType extends MessageTypes> (id: string, type: TMessageType, request: RequestTypes[TMessageType], port: chrome.runtime.Port): Promise<ResponseType<TMessageType>> {
|
|
512
|
-
switch (type) {
|
|
513
|
-
case 'pri(authorize.approve)':
|
|
514
|
-
return this.authorizeApprove(request as RequestAuthorizeApprove);
|
|
515
|
-
|
|
516
|
-
case 'pri(authorize.list)':
|
|
517
|
-
return this.getAuthList();
|
|
518
|
-
|
|
519
|
-
case 'pri(authorize.reject)':
|
|
520
|
-
return this.authorizeReject(request as RequestAuthorizeReject);
|
|
521
|
-
|
|
522
|
-
case 'pri(authorize.toggle)':
|
|
523
|
-
return this.toggleAuthorization(request as string);
|
|
524
|
-
|
|
525
|
-
case 'pri(authorize.requests)':
|
|
526
|
-
return this.authorizeSubscribe(id, port);
|
|
527
|
-
|
|
528
|
-
case 'pri(accounts.create.external)':
|
|
529
|
-
return this.accountsCreateExternal(request as RequestAccountCreateExternal);
|
|
530
|
-
|
|
531
|
-
case 'pri(accounts.create.hardware)':
|
|
532
|
-
return this.accountsCreateHardware(request as RequestAccountCreateHardware);
|
|
533
|
-
|
|
534
|
-
case 'pri(accounts.create.suri)':
|
|
535
|
-
return this.accountsCreateSuri(request as RequestAccountCreateSuri);
|
|
536
|
-
|
|
537
|
-
case 'pri(accounts.changePassword)':
|
|
538
|
-
return this.accountsChangePassword(request as RequestAccountChangePassword);
|
|
539
|
-
|
|
540
|
-
case 'pri(accounts.edit)':
|
|
541
|
-
return this.accountsEdit(request as RequestAccountEdit);
|
|
542
|
-
|
|
543
|
-
case 'pri(accounts.export)':
|
|
544
|
-
return this.accountsExport(request as RequestAccountExport);
|
|
545
|
-
|
|
546
|
-
case 'pri(accounts.batchExport)':
|
|
547
|
-
// return this.accountsBatchExport(request as RequestAccountBatchExport);
|
|
548
|
-
// Disable export all util use master password
|
|
549
|
-
return null;
|
|
550
|
-
|
|
551
|
-
case 'pri(accounts.forget)':
|
|
552
|
-
return this.accountsForget(request as RequestAccountForget);
|
|
553
|
-
|
|
554
|
-
case 'pri(accounts.show)':
|
|
555
|
-
return this.accountsShow(request as RequestAccountShow);
|
|
556
|
-
|
|
557
|
-
case 'pri(accounts.subscribe)':
|
|
558
|
-
return this.accountsSubscribe(id, port);
|
|
559
|
-
|
|
560
|
-
case 'pri(accounts.tie)':
|
|
561
|
-
return this.accountsTie(request as RequestAccountTie);
|
|
562
|
-
|
|
563
|
-
case 'pri(accounts.validate)':
|
|
564
|
-
return this.accountsValidate(request as RequestAccountValidate);
|
|
565
|
-
|
|
566
|
-
case 'pri(metadata.approve)':
|
|
567
|
-
return this.metadataApprove(request as RequestMetadataApprove);
|
|
568
|
-
|
|
569
|
-
case 'pri(metadata.get)':
|
|
570
|
-
return this.metadataGet(request as string);
|
|
571
|
-
|
|
572
|
-
case 'pri(metadata.list)':
|
|
573
|
-
return this.metadataList();
|
|
574
|
-
|
|
575
|
-
case 'pri(metadata.reject)':
|
|
576
|
-
return this.metadataReject(request as RequestMetadataReject);
|
|
577
|
-
|
|
578
|
-
case 'pri(metadata.requests)':
|
|
579
|
-
return this.metadataSubscribe(id, port);
|
|
580
|
-
|
|
581
|
-
case 'pri(derivation.create)':
|
|
582
|
-
return this.derivationCreate(request as RequestDeriveCreate);
|
|
583
|
-
|
|
584
|
-
case 'pri(derivation.validate)':
|
|
585
|
-
return this.derivationValidate(request as RequestDeriveValidate);
|
|
586
|
-
|
|
587
|
-
case 'pri(json.restore)':
|
|
588
|
-
return this.jsonRestore(request as RequestJsonRestore);
|
|
589
|
-
|
|
590
|
-
case 'pri(json.batchRestore)':
|
|
591
|
-
return this.batchRestore(request as RequestBatchRestore);
|
|
592
|
-
|
|
593
|
-
case 'pri(json.account.info)':
|
|
594
|
-
return this.jsonGetAccountInfo(request as KeyringPair$Json);
|
|
595
|
-
|
|
596
|
-
case 'pri(seed.create)':
|
|
597
|
-
return this.seedCreate(request as RequestSeedCreate);
|
|
598
|
-
|
|
599
|
-
case 'pri(seed.validate)':
|
|
600
|
-
return this.seedValidate(request as RequestSeedValidate);
|
|
601
|
-
|
|
602
|
-
case 'pri(settings.notification)':
|
|
603
|
-
return this.#state.setNotification(request as string);
|
|
604
|
-
|
|
605
|
-
case 'pri(signing.approve.password)':
|
|
606
|
-
return this.signingApprovePassword(request as RequestSigningApprovePassword);
|
|
607
|
-
|
|
608
|
-
case 'pri(signing.approve.signature)':
|
|
609
|
-
return this.signingApproveSignature(request as RequestSigningApproveSignature);
|
|
610
|
-
|
|
611
|
-
case 'pri(signing.cancel)':
|
|
612
|
-
return this.signingCancel(request as RequestSigningCancel);
|
|
613
|
-
|
|
614
|
-
case 'pri(signing.isLocked)':
|
|
615
|
-
return this.signingIsLocked(request as RequestSigningIsLocked);
|
|
616
|
-
|
|
617
|
-
case 'pri(signing.requests)':
|
|
618
|
-
return this.signingSubscribe(id, port);
|
|
619
|
-
|
|
620
|
-
case 'pri(window.open)':
|
|
621
|
-
return this.windowOpen(request as AllowedPath);
|
|
622
|
-
|
|
623
|
-
default:
|
|
624
|
-
throw new Error(`Unable to handle message of type ${type}`);
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
}
|