@pezkuwi/extension-base 0.62.8 → 0.62.12
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/LICENSE +201 -0
- package/background/RequestBytesSign.js +12 -0
- package/background/RequestExtrinsicSign.js +11 -0
- package/background/handlers/Extension.js +489 -0
- package/background/handlers/State.js +478 -0
- package/background/handlers/Tabs.js +195 -0
- package/{build/background → background}/handlers/helpers.js +1 -3
- package/background/handlers/index.js +40 -0
- package/background/handlers/subscriptions.js +18 -0
- package/background/index.js +1 -0
- package/bundle.js +1 -0
- package/cjs/background/RequestBytesSign.d.ts +12 -0
- package/cjs/background/RequestBytesSign.js +15 -0
- package/cjs/background/RequestExtrinsicSign.d.ts +12 -0
- package/cjs/background/RequestExtrinsicSign.js +14 -0
- package/cjs/background/handlers/Extension.d.ts +49 -0
- package/cjs/background/handlers/Extension.js +492 -0
- package/cjs/background/handlers/State.d.ts +96 -0
- package/cjs/background/handlers/State.js +482 -0
- package/cjs/background/handlers/Tabs.d.ts +25 -0
- package/cjs/background/handlers/Tabs.js +199 -0
- package/cjs/background/handlers/helpers.d.ts +1 -0
- package/cjs/background/handlers/helpers.js +14 -0
- package/cjs/background/handlers/index.d.ts +3 -0
- package/cjs/background/handlers/index.js +46 -0
- package/cjs/background/handlers/subscriptions.d.ts +3 -0
- package/cjs/background/handlers/subscriptions.js +22 -0
- package/cjs/background/index.d.ts +1 -0
- package/cjs/background/index.js +7 -0
- package/cjs/background/types.d.ts +343 -0
- package/cjs/background/types.js +2 -0
- package/cjs/bundle.d.ts +1 -0
- package/cjs/bundle.js +5 -0
- package/cjs/defaults.js +16 -0
- package/cjs/index.js +4 -0
- package/cjs/package.json +3 -0
- package/cjs/packageDetect.d.ts +1 -0
- package/cjs/packageDetect.js +8 -0
- package/cjs/packageInfo.js +4 -0
- package/cjs/page/Accounts.js +24 -0
- package/cjs/page/Injected.js +25 -0
- package/cjs/page/Metadata.js +15 -0
- package/cjs/page/PostMessageProvider.js +135 -0
- package/cjs/page/Signer.js +29 -0
- package/cjs/page/index.js +52 -0
- package/cjs/page/types.js +2 -0
- package/cjs/stores/Accounts.js +21 -0
- package/cjs/stores/Base.js +70 -0
- package/cjs/stores/Metadata.js +13 -0
- package/cjs/stores/index.js +8 -0
- package/cjs/types.js +2 -0
- package/cjs/utils/canDerive.js +6 -0
- package/cjs/utils/getId.js +8 -0
- package/cjs/utils/index.js +5 -0
- package/{build → cjs}/utils/portUtils.d.ts +0 -1
- package/cjs/utils/portUtils.js +49 -0
- package/defaults.d.ts +9 -0
- package/{src/defaults.ts → defaults.js} +2 -15
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +464 -10
- package/packageDetect.d.ts +1 -0
- package/{build/packageDetect.js → packageDetect.js} +0 -4
- package/packageInfo.d.ts +6 -0
- package/packageInfo.js +1 -0
- package/page/Accounts.d.ts +7 -0
- package/page/Accounts.js +21 -0
- package/page/Injected.d.ts +13 -0
- package/{build/page → page}/Injected.js +10 -10
- package/page/Metadata.d.ts +7 -0
- package/page/Metadata.js +12 -0
- package/page/PostMessageProvider.d.ts +63 -0
- package/page/PostMessageProvider.js +132 -0
- package/page/Signer.d.ts +8 -0
- package/page/Signer.js +26 -0
- package/page/index.d.ts +16 -0
- package/page/index.js +45 -0
- package/page/types.d.ts +6 -0
- package/page/types.js +1 -0
- package/stores/Accounts.d.ts +6 -0
- package/stores/Accounts.js +17 -0
- package/stores/Base.d.ts +9 -0
- package/stores/Base.js +67 -0
- package/stores/Metadata.d.ts +5 -0
- package/stores/Metadata.js +9 -0
- package/{src/stores/index.ts → stores/index.d.ts} +0 -3
- package/{build/stores → stores}/index.js +0 -2
- package/types.d.ts +9 -0
- package/types.js +1 -0
- package/utils/canDerive.d.ts +2 -0
- package/{build/utils → utils}/canDerive.js +0 -2
- package/utils/getId.d.ts +1 -0
- package/utils/getId.js +5 -0
- package/utils/index.d.ts +1 -0
- package/utils/index.js +1 -0
- package/utils/portUtils.d.ts +13 -0
- package/utils/portUtils.js +43 -0
- package/build/background/RequestBytesSign.js +0 -15
- package/build/background/RequestExtrinsicSign.js +0 -14
- package/build/background/handlers/Extension.js +0 -645
- package/build/background/handlers/State.js +0 -732
- package/build/background/handlers/Tabs.js +0 -313
- package/build/background/handlers/index.js +0 -45
- package/build/background/handlers/subscriptions.js +0 -22
- package/build/background/index.js +0 -3
- package/build/background/types.js +0 -3
- package/build/bundle.js +0 -3
- package/build/defaults.js +0 -17
- package/build/index.js +0 -5
- package/build/packageInfo.js +0 -4
- package/build/page/Accounts.js +0 -26
- package/build/page/Metadata.js +0 -17
- package/build/page/PostMessageProvider.js +0 -234
- package/build/page/Signer.js +0 -92
- package/build/page/index.js +0 -102
- package/build/page/types.js +0 -3
- package/build/stores/Accounts.js +0 -83
- package/build/stores/Base.js +0 -250
- package/build/stores/Metadata.js +0 -29
- package/build/types.js +0 -3
- package/build/utils/getId.js +0 -7
- package/build/utils/index.js +0 -3
- package/build/utils/portUtils.js +0 -106
- package/src/background/RequestBytesSign.ts +0 -28
- package/src/background/RequestExtrinsicSign.ts +0 -22
- package/src/background/handlers/Extension.spec.ts +0 -478
- package/src/background/handlers/Extension.ts +0 -690
- package/src/background/handlers/State.ts +0 -664
- package/src/background/handlers/Tabs.ts +0 -289
- package/src/background/handlers/helpers.ts +0 -14
- package/src/background/handlers/index.ts +0 -60
- package/src/background/handlers/subscriptions.ts +0 -32
- package/src/background/index.ts +0 -4
- package/src/background/types.ts +0 -432
- package/src/bundle.ts +0 -4
- package/src/index.ts +0 -7
- package/src/packageDetect.ts +0 -14
- package/src/packageInfo.ts +0 -6
- package/src/page/Accounts.ts +0 -33
- package/src/page/Injected.ts +0 -33
- package/src/page/Metadata.ts +0 -22
- package/src/page/PostMessageProvider.ts +0 -182
- package/src/page/Signer.ts +0 -45
- package/src/page/index.ts +0 -89
- package/src/page/types.ts +0 -10
- package/src/stores/Accounts.ts +0 -28
- package/src/stores/Base.ts +0 -93
- package/src/stores/Metadata.ts +0 -17
- 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/src/utils/portUtils.ts +0 -65
- package/tsconfig.build.json +0 -16
- package/tsconfig.build.tsbuildinfo +0 -1
- package/tsconfig.spec.json +0 -18
- package/tsconfig.spec.tsbuildinfo +0 -1
- /package/{build/background → background}/RequestBytesSign.d.ts +0 -0
- /package/{build/background → background}/RequestExtrinsicSign.d.ts +0 -0
- /package/{build/background → background}/handlers/Extension.d.ts +0 -0
- /package/{build/background → background}/handlers/State.d.ts +0 -0
- /package/{build/background → background}/handlers/Tabs.d.ts +0 -0
- /package/{build/background → background}/handlers/helpers.d.ts +0 -0
- /package/{build/background → background}/handlers/index.d.ts +0 -0
- /package/{build/background → background}/handlers/subscriptions.d.ts +0 -0
- /package/{build/background → background}/index.d.ts +0 -0
- /package/{build/background → background}/types.d.ts +0 -0
- /package/{build/packageDetect.d.ts → background/types.js} +0 -0
- /package/{build/bundle.d.ts → bundle.d.ts} +0 -0
- /package/{build → cjs}/defaults.d.ts +0 -0
- /package/{build → cjs}/index.d.ts +0 -0
- /package/{build → cjs}/packageInfo.d.ts +0 -0
- /package/{build → cjs}/page/Accounts.d.ts +0 -0
- /package/{build → cjs}/page/Injected.d.ts +0 -0
- /package/{build → cjs}/page/Metadata.d.ts +0 -0
- /package/{build → cjs}/page/PostMessageProvider.d.ts +0 -0
- /package/{build → cjs}/page/Signer.d.ts +0 -0
- /package/{build → cjs}/page/index.d.ts +0 -0
- /package/{build → cjs}/page/types.d.ts +0 -0
- /package/{build → cjs}/stores/Accounts.d.ts +0 -0
- /package/{build → cjs}/stores/Base.d.ts +0 -0
- /package/{build → cjs}/stores/Metadata.d.ts +0 -0
- /package/{build → cjs}/stores/index.d.ts +0 -0
- /package/{build → cjs}/types.d.ts +0 -0
- /package/{build → cjs}/utils/canDerive.d.ts +0 -0
- /package/{build → cjs}/utils/getId.d.ts +0 -0
- /package/{build → cjs}/utils/index.d.ts +0 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { assert } from '@pezkuwi/util';
|
|
2
|
+
import { PORT_EXTENSION } from '../../defaults.js';
|
|
3
|
+
import Extension from './Extension.js';
|
|
4
|
+
import State from './State.js';
|
|
5
|
+
import Tabs from './Tabs.js';
|
|
6
|
+
export { withErrorLog } from './helpers.js';
|
|
7
|
+
const state = new State();
|
|
8
|
+
await state.init();
|
|
9
|
+
const extension = new Extension(state);
|
|
10
|
+
const tabs = new Tabs(state);
|
|
11
|
+
export default function handler({ id, message, request }, port, extensionPortName = PORT_EXTENSION) {
|
|
12
|
+
const isExtension = !port || port?.name === extensionPortName;
|
|
13
|
+
const sender = port?.sender;
|
|
14
|
+
if (!isExtension && !sender) {
|
|
15
|
+
throw new Error('Unable to extract message sender');
|
|
16
|
+
}
|
|
17
|
+
const from = isExtension
|
|
18
|
+
? 'extension'
|
|
19
|
+
: sender?.url || sender?.tab?.url || '<unknown>';
|
|
20
|
+
const source = `${from}: ${id}: ${message}`;
|
|
21
|
+
console.log(` [in] ${source}`); // :: ${JSON.stringify(request)}`);
|
|
22
|
+
const promise = isExtension
|
|
23
|
+
? extension.handle(id, message, request, port)
|
|
24
|
+
: tabs.handle(id, message, request, from, port);
|
|
25
|
+
promise
|
|
26
|
+
.then((response) => {
|
|
27
|
+
console.log(`[out] ${source}`); // :: ${JSON.stringify(response)}`);
|
|
28
|
+
// between the start and the end of the promise, the user may have closed
|
|
29
|
+
// the tab, in which case port will be undefined
|
|
30
|
+
assert(port, 'Port has been disconnected');
|
|
31
|
+
port.postMessage({ id, response });
|
|
32
|
+
})
|
|
33
|
+
.catch((error) => {
|
|
34
|
+
console.log(`[err] ${source}:: ${error.message}`);
|
|
35
|
+
// only send message back to port if it's still connected
|
|
36
|
+
if (port) {
|
|
37
|
+
port.postMessage({ error: error.message, id });
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const subscriptions = {};
|
|
2
|
+
export function createSubscription(id, port) {
|
|
3
|
+
subscriptions[id] = port;
|
|
4
|
+
return (subscription) => {
|
|
5
|
+
if (subscriptions[id]) {
|
|
6
|
+
port.postMessage({ id, subscription });
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export function unsubscribe(id) {
|
|
11
|
+
if (subscriptions[id]) {
|
|
12
|
+
console.log(`Unsubscribing from ${id}`);
|
|
13
|
+
delete subscriptions[id];
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
console.error(`Unable to unsubscribe from ${id}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as handlers, withErrorLog } from './handlers/index.js';
|
package/bundle.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { packageInfo } from './packageInfo.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { KeyringPair } from '@pezkuwi/keyring/types';
|
|
2
|
+
import type { TypeRegistry } from '@pezkuwi/types';
|
|
3
|
+
import type { SignerPayloadRaw } from '@pezkuwi/types/types';
|
|
4
|
+
import type { HexString } from '@pezkuwi/util/types';
|
|
5
|
+
import type { RequestSign } from './types.js';
|
|
6
|
+
export default class RequestBytesSign implements RequestSign {
|
|
7
|
+
readonly payload: SignerPayloadRaw;
|
|
8
|
+
constructor(payload: SignerPayloadRaw);
|
|
9
|
+
sign(_registry: TypeRegistry, pair: KeyringPair): {
|
|
10
|
+
signature: HexString;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const util_1 = require("@pezkuwi/util");
|
|
4
|
+
class RequestBytesSign {
|
|
5
|
+
payload;
|
|
6
|
+
constructor(payload) {
|
|
7
|
+
this.payload = payload;
|
|
8
|
+
}
|
|
9
|
+
sign(_registry, pair) {
|
|
10
|
+
return {
|
|
11
|
+
signature: (0, util_1.u8aToHex)(pair.sign((0, util_1.u8aWrapBytes)(this.payload.data)))
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.default = RequestBytesSign;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { KeyringPair } from '@pezkuwi/keyring/types';
|
|
2
|
+
import type { TypeRegistry } from '@pezkuwi/types';
|
|
3
|
+
import type { SignerPayloadJSON } from '@pezkuwi/types/types';
|
|
4
|
+
import type { HexString } from '@pezkuwi/util/types';
|
|
5
|
+
import type { RequestSign } from './types.js';
|
|
6
|
+
export default class RequestExtrinsicSign implements RequestSign {
|
|
7
|
+
readonly payload: SignerPayloadJSON;
|
|
8
|
+
constructor(payload: SignerPayloadJSON);
|
|
9
|
+
sign(registry: TypeRegistry, pair: KeyringPair): {
|
|
10
|
+
signature: HexString;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class RequestExtrinsicSign {
|
|
4
|
+
payload;
|
|
5
|
+
constructor(payload) {
|
|
6
|
+
this.payload = payload;
|
|
7
|
+
}
|
|
8
|
+
sign(registry, pair) {
|
|
9
|
+
return registry
|
|
10
|
+
.createType('ExtrinsicPayload', this.payload, { version: this.payload.version })
|
|
11
|
+
.sign(pair);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.default = RequestExtrinsicSign;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { MessageTypes, RequestTypes, ResponseType } from '../types.js';
|
|
2
|
+
import type State from './State.js';
|
|
3
|
+
export default class Extension {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(state: State);
|
|
6
|
+
private transformAccounts;
|
|
7
|
+
private accountsCreateExternal;
|
|
8
|
+
private accountsCreateHardware;
|
|
9
|
+
private accountsCreateSuri;
|
|
10
|
+
private accountsChangePassword;
|
|
11
|
+
private accountsEdit;
|
|
12
|
+
private accountsExport;
|
|
13
|
+
private accountsBatchExport;
|
|
14
|
+
private accountsForget;
|
|
15
|
+
private refreshAccountPasswordCache;
|
|
16
|
+
private accountsShow;
|
|
17
|
+
private accountsTie;
|
|
18
|
+
private accountsValidate;
|
|
19
|
+
private accountsSubscribe;
|
|
20
|
+
private authorizeApprove;
|
|
21
|
+
private authorizeUpdate;
|
|
22
|
+
private getAuthList;
|
|
23
|
+
private authorizeSubscribe;
|
|
24
|
+
private metadataApprove;
|
|
25
|
+
private metadataGet;
|
|
26
|
+
private metadataList;
|
|
27
|
+
private metadataReject;
|
|
28
|
+
private metadataSubscribe;
|
|
29
|
+
private jsonRestore;
|
|
30
|
+
private batchRestore;
|
|
31
|
+
private jsonGetAccountInfo;
|
|
32
|
+
private seedCreate;
|
|
33
|
+
private seedValidate;
|
|
34
|
+
private signingApprovePassword;
|
|
35
|
+
private signingApproveSignature;
|
|
36
|
+
private signingCancel;
|
|
37
|
+
private signingIsLocked;
|
|
38
|
+
private signingSubscribe;
|
|
39
|
+
private windowOpen;
|
|
40
|
+
private derive;
|
|
41
|
+
private derivationValidate;
|
|
42
|
+
private derivationCreate;
|
|
43
|
+
private removeAuthorization;
|
|
44
|
+
private rejectAuthRequest;
|
|
45
|
+
private cancelAuthRequest;
|
|
46
|
+
private updateCurrentTabs;
|
|
47
|
+
private getConnectedTabsUrl;
|
|
48
|
+
handle<TMessageType extends MessageTypes>(id: string, type: TMessageType, request: RequestTypes[TMessageType], port?: chrome.runtime.Port): Promise<ResponseType<TMessageType>>;
|
|
49
|
+
}
|
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const defaults_1 = require("@pezkuwi/extension-base/defaults");
|
|
4
|
+
const extension_chains_1 = require("@pezkuwi/extension-chains");
|
|
5
|
+
const types_1 = require("@pezkuwi/types");
|
|
6
|
+
const ui_keyring_1 = require("@pezkuwi/ui-keyring");
|
|
7
|
+
const accounts_1 = require("@pezkuwi/ui-keyring/observable/accounts");
|
|
8
|
+
const util_1 = require("@pezkuwi/util");
|
|
9
|
+
const util_crypto_1 = require("@pezkuwi/util-crypto");
|
|
10
|
+
const helpers_js_1 = require("./helpers.js");
|
|
11
|
+
const subscriptions_js_1 = require("./subscriptions.js");
|
|
12
|
+
const SEED_DEFAULT_LENGTH = 12;
|
|
13
|
+
const SEED_LENGTHS = [12, 15, 18, 21, 24];
|
|
14
|
+
const ETH_DERIVE_DEFAULT = "/m/44'/60'/0'/0/0";
|
|
15
|
+
function getSuri(seed, type) {
|
|
16
|
+
return type === 'ethereum'
|
|
17
|
+
? `${seed}${ETH_DERIVE_DEFAULT}`
|
|
18
|
+
: seed;
|
|
19
|
+
}
|
|
20
|
+
function isJsonPayload(value) {
|
|
21
|
+
return value.genesisHash !== undefined;
|
|
22
|
+
}
|
|
23
|
+
class Extension {
|
|
24
|
+
#cachedUnlocks;
|
|
25
|
+
#state;
|
|
26
|
+
constructor(state) {
|
|
27
|
+
this.#cachedUnlocks = {};
|
|
28
|
+
this.#state = state;
|
|
29
|
+
}
|
|
30
|
+
transformAccounts(accounts) {
|
|
31
|
+
return Object.values(accounts).map(({ json: { address, meta }, type }) => ({
|
|
32
|
+
address,
|
|
33
|
+
isDefaultAuthSelected: this.#state.defaultAuthAccountSelection.includes(address),
|
|
34
|
+
...meta,
|
|
35
|
+
type
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
accountsCreateExternal({ address, genesisHash, name }) {
|
|
39
|
+
ui_keyring_1.keyring.addExternal(address, { genesisHash, name });
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
accountsCreateHardware({ accountIndex, address, addressOffset, genesisHash, hardwareType, name, type }) {
|
|
43
|
+
ui_keyring_1.keyring.addHardware(address, hardwareType, { accountIndex, addressOffset, genesisHash, name, type });
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
accountsCreateSuri({ genesisHash, name, password, suri, type }) {
|
|
47
|
+
ui_keyring_1.keyring.addUri(getSuri(suri, type), password, { genesisHash, name }, type);
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
accountsChangePassword({ address, newPass, oldPass }) {
|
|
51
|
+
const pair = ui_keyring_1.keyring.getPair(address);
|
|
52
|
+
(0, util_1.assert)(pair, 'Unable to find pair');
|
|
53
|
+
try {
|
|
54
|
+
if (!pair.isLocked) {
|
|
55
|
+
pair.lock();
|
|
56
|
+
}
|
|
57
|
+
pair.decodePkcs8(oldPass);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
throw new Error('oldPass is invalid');
|
|
61
|
+
}
|
|
62
|
+
ui_keyring_1.keyring.encryptAccount(pair, newPass);
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
accountsEdit({ address, name }) {
|
|
66
|
+
const pair = ui_keyring_1.keyring.getPair(address);
|
|
67
|
+
(0, util_1.assert)(pair, 'Unable to find pair');
|
|
68
|
+
ui_keyring_1.keyring.saveAccountMeta(pair, { ...pair.meta, name });
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
accountsExport({ address, password }) {
|
|
72
|
+
return { exportedJson: ui_keyring_1.keyring.backupAccount(ui_keyring_1.keyring.getPair(address), password) };
|
|
73
|
+
}
|
|
74
|
+
async accountsBatchExport({ addresses, password }) {
|
|
75
|
+
return {
|
|
76
|
+
exportedJson: await ui_keyring_1.keyring.backupAccounts(addresses, password)
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
async accountsForget({ address }) {
|
|
80
|
+
const authorizedAccountsDiff = [];
|
|
81
|
+
// cycle through authUrls and prepare the array of diff
|
|
82
|
+
Object.entries(this.#state.authUrls).forEach(([url, urlInfo]) => {
|
|
83
|
+
// Note that urlInfo.authorizedAccounts may be undefined if this website entry
|
|
84
|
+
// was created before the "account authorization per website" functionality was introduced
|
|
85
|
+
if (urlInfo.authorizedAccounts?.includes(address)) {
|
|
86
|
+
authorizedAccountsDiff.push([url, urlInfo.authorizedAccounts.filter((previousAddress) => previousAddress !== address)]);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
await this.#state.updateAuthorizedAccounts(authorizedAccountsDiff);
|
|
90
|
+
// cycle through default account selection for auth and remove any occurrence of the account
|
|
91
|
+
const newDefaultAuthAccounts = this.#state.defaultAuthAccountSelection.filter((defaultSelectionAddress) => defaultSelectionAddress !== address);
|
|
92
|
+
await this.#state.updateDefaultAuthAccounts(newDefaultAuthAccounts);
|
|
93
|
+
ui_keyring_1.keyring.forgetAccount(address);
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
refreshAccountPasswordCache(pair) {
|
|
97
|
+
const { address } = pair;
|
|
98
|
+
const savedExpiry = this.#cachedUnlocks[address] || 0;
|
|
99
|
+
const remainingTime = savedExpiry - Date.now();
|
|
100
|
+
if (remainingTime < 0) {
|
|
101
|
+
this.#cachedUnlocks[address] = 0;
|
|
102
|
+
pair.lock();
|
|
103
|
+
return 0;
|
|
104
|
+
}
|
|
105
|
+
return remainingTime;
|
|
106
|
+
}
|
|
107
|
+
accountsShow({ address, isShowing }) {
|
|
108
|
+
const pair = ui_keyring_1.keyring.getPair(address);
|
|
109
|
+
(0, util_1.assert)(pair, 'Unable to find pair');
|
|
110
|
+
ui_keyring_1.keyring.saveAccountMeta(pair, { ...pair.meta, isHidden: !isShowing });
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
accountsTie({ address, genesisHash }) {
|
|
114
|
+
const pair = ui_keyring_1.keyring.getPair(address);
|
|
115
|
+
(0, util_1.assert)(pair, 'Unable to find pair');
|
|
116
|
+
ui_keyring_1.keyring.saveAccountMeta(pair, { ...pair.meta, genesisHash });
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
accountsValidate({ address, password }) {
|
|
120
|
+
try {
|
|
121
|
+
ui_keyring_1.keyring.backupAccount(ui_keyring_1.keyring.getPair(address), password);
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
accountsSubscribe(id, port) {
|
|
129
|
+
const cb = (0, subscriptions_js_1.createSubscription)(id, port);
|
|
130
|
+
const subscription = accounts_1.accounts.subject.subscribe((accounts) => cb(this.transformAccounts(accounts)));
|
|
131
|
+
port.onDisconnect.addListener(() => {
|
|
132
|
+
(0, subscriptions_js_1.unsubscribe)(id);
|
|
133
|
+
subscription.unsubscribe();
|
|
134
|
+
});
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
authorizeApprove({ authorizedAccounts, id }) {
|
|
138
|
+
const queued = this.#state.getAuthRequest(id);
|
|
139
|
+
(0, util_1.assert)(queued, 'Unable to find request');
|
|
140
|
+
const { resolve } = queued;
|
|
141
|
+
resolve({ authorizedAccounts, result: true });
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
async authorizeUpdate({ authorizedAccounts, url }) {
|
|
145
|
+
return await this.#state.updateAuthorizedAccounts([[url, authorizedAccounts]]);
|
|
146
|
+
}
|
|
147
|
+
getAuthList() {
|
|
148
|
+
return { list: this.#state.authUrls };
|
|
149
|
+
}
|
|
150
|
+
// FIXME This looks very much like what we have in accounts
|
|
151
|
+
authorizeSubscribe(id, port) {
|
|
152
|
+
const cb = (0, subscriptions_js_1.createSubscription)(id, port);
|
|
153
|
+
const subscription = this.#state.authSubject.subscribe((requests) => cb(requests));
|
|
154
|
+
port.onDisconnect.addListener(() => {
|
|
155
|
+
(0, subscriptions_js_1.unsubscribe)(id);
|
|
156
|
+
subscription.unsubscribe();
|
|
157
|
+
});
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
async metadataApprove({ id }) {
|
|
161
|
+
const queued = this.#state.getMetaRequest(id);
|
|
162
|
+
(0, util_1.assert)(queued, 'Unable to find request');
|
|
163
|
+
const { request, resolve } = queued;
|
|
164
|
+
await this.#state.saveMetadata(request);
|
|
165
|
+
resolve(true);
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
metadataGet(genesisHash) {
|
|
169
|
+
return this.#state.knownMetadata.find((result) => result.genesisHash === genesisHash) || null;
|
|
170
|
+
}
|
|
171
|
+
metadataList() {
|
|
172
|
+
return this.#state.knownMetadata;
|
|
173
|
+
}
|
|
174
|
+
metadataReject({ id }) {
|
|
175
|
+
const queued = this.#state.getMetaRequest(id);
|
|
176
|
+
(0, util_1.assert)(queued, 'Unable to find request');
|
|
177
|
+
const { reject } = queued;
|
|
178
|
+
reject(new Error('Rejected'));
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
metadataSubscribe(id, port) {
|
|
182
|
+
const cb = (0, subscriptions_js_1.createSubscription)(id, port);
|
|
183
|
+
const subscription = this.#state.metaSubject.subscribe((requests) => cb(requests));
|
|
184
|
+
port.onDisconnect.addListener(() => {
|
|
185
|
+
(0, subscriptions_js_1.unsubscribe)(id);
|
|
186
|
+
subscription.unsubscribe();
|
|
187
|
+
});
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
jsonRestore({ file, password }) {
|
|
191
|
+
try {
|
|
192
|
+
ui_keyring_1.keyring.restoreAccount(file, password);
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
throw new Error(error.message);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
batchRestore({ file, password }) {
|
|
199
|
+
try {
|
|
200
|
+
ui_keyring_1.keyring.restoreAccounts(file, password);
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
throw new Error(error.message);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
jsonGetAccountInfo(json) {
|
|
207
|
+
try {
|
|
208
|
+
const { address, meta: { genesisHash, name }, type } = ui_keyring_1.keyring.createFromJson(json);
|
|
209
|
+
return {
|
|
210
|
+
address,
|
|
211
|
+
genesisHash,
|
|
212
|
+
name,
|
|
213
|
+
type
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
catch (e) {
|
|
217
|
+
console.error(e);
|
|
218
|
+
throw new Error(e.message);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
seedCreate({ length = SEED_DEFAULT_LENGTH, seed: _seed, type }) {
|
|
222
|
+
const seed = _seed || (0, util_crypto_1.mnemonicGenerate)(length);
|
|
223
|
+
return {
|
|
224
|
+
address: ui_keyring_1.keyring.createFromUri(getSuri(seed, type), {}, type).address,
|
|
225
|
+
seed
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
seedValidate({ suri, type }) {
|
|
229
|
+
const { phrase } = (0, util_crypto_1.keyExtractSuri)(suri);
|
|
230
|
+
if ((0, util_1.isHex)(phrase)) {
|
|
231
|
+
(0, util_1.assert)((0, util_1.isHex)(phrase, 256), 'Hex seed needs to be 256-bits');
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
// sadly isHex detects as string, so we need a cast here
|
|
235
|
+
(0, util_1.assert)(SEED_LENGTHS.includes((phrase).split(' ').length), `Mnemonic needs to contain ${SEED_LENGTHS.join(', ')} words`);
|
|
236
|
+
(0, util_1.assert)((0, util_crypto_1.mnemonicValidate)(phrase), 'Not a valid mnemonic seed');
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
address: ui_keyring_1.keyring.createFromUri(getSuri(suri, type), {}, type).address,
|
|
240
|
+
suri
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
signingApprovePassword({ id, password, savePass }) {
|
|
244
|
+
const queued = this.#state.getSignRequest(id);
|
|
245
|
+
(0, util_1.assert)(queued, 'Unable to find request');
|
|
246
|
+
const { reject, request, resolve } = queued;
|
|
247
|
+
const pair = ui_keyring_1.keyring.getPair(queued.account.address);
|
|
248
|
+
if (!pair) {
|
|
249
|
+
reject(new Error('Unable to find pair'));
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
this.refreshAccountPasswordCache(pair);
|
|
253
|
+
// if the keyring pair is locked, the password is needed
|
|
254
|
+
if (pair.isLocked && !password) {
|
|
255
|
+
reject(new Error('Password needed to unlock the account'));
|
|
256
|
+
}
|
|
257
|
+
if (pair.isLocked) {
|
|
258
|
+
pair.decodePkcs8(password);
|
|
259
|
+
}
|
|
260
|
+
// construct a new registry (avoiding pollution), between requests
|
|
261
|
+
let registry;
|
|
262
|
+
const { payload } = request;
|
|
263
|
+
if (isJsonPayload(payload)) {
|
|
264
|
+
// Get the metadata for the genesisHash
|
|
265
|
+
const metadata = this.#state.knownMetadata.find(({ genesisHash }) => genesisHash === payload.genesisHash);
|
|
266
|
+
if (metadata) {
|
|
267
|
+
// we have metadata, expand it and extract the info/registry
|
|
268
|
+
const expanded = (0, extension_chains_1.metadataExpand)(metadata, false);
|
|
269
|
+
registry = expanded.registry;
|
|
270
|
+
registry.setSignedExtensions(payload.signedExtensions, expanded.definition.userExtensions);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
// we have no metadata, create a new registry
|
|
274
|
+
registry = new types_1.TypeRegistry();
|
|
275
|
+
registry.setSignedExtensions(payload.signedExtensions);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
// for non-payload, just create a registry to use
|
|
280
|
+
registry = new types_1.TypeRegistry();
|
|
281
|
+
}
|
|
282
|
+
const result = request.sign(registry, pair);
|
|
283
|
+
if (savePass) {
|
|
284
|
+
// unlike queued.account.address the following
|
|
285
|
+
// address is encoded with the default prefix
|
|
286
|
+
// which what is used for password caching mapping
|
|
287
|
+
this.#cachedUnlocks[pair.address] = Date.now() + defaults_1.PASSWORD_EXPIRY_MS;
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
pair.lock();
|
|
291
|
+
}
|
|
292
|
+
resolve({
|
|
293
|
+
id,
|
|
294
|
+
...result
|
|
295
|
+
});
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
signingApproveSignature({ id, signature, signedTransaction }) {
|
|
299
|
+
const queued = this.#state.getSignRequest(id);
|
|
300
|
+
(0, util_1.assert)(queued, 'Unable to find request');
|
|
301
|
+
const { resolve } = queued;
|
|
302
|
+
resolve({ id, signature, signedTransaction });
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
signingCancel({ id }) {
|
|
306
|
+
const queued = this.#state.getSignRequest(id);
|
|
307
|
+
(0, util_1.assert)(queued, 'Unable to find request');
|
|
308
|
+
const { reject } = queued;
|
|
309
|
+
reject(new Error('Cancelled'));
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
signingIsLocked({ id }) {
|
|
313
|
+
const queued = this.#state.getSignRequest(id);
|
|
314
|
+
(0, util_1.assert)(queued, 'Unable to find request');
|
|
315
|
+
const address = queued.request.payload.address;
|
|
316
|
+
const pair = ui_keyring_1.keyring.getPair(address);
|
|
317
|
+
(0, util_1.assert)(pair, 'Unable to find pair');
|
|
318
|
+
const remainingTime = this.refreshAccountPasswordCache(pair);
|
|
319
|
+
return {
|
|
320
|
+
isLocked: pair.isLocked,
|
|
321
|
+
remainingTime
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
// FIXME This looks very much like what we have in authorization
|
|
325
|
+
signingSubscribe(id, port) {
|
|
326
|
+
const cb = (0, subscriptions_js_1.createSubscription)(id, port);
|
|
327
|
+
const subscription = this.#state.signSubject.subscribe((requests) => cb(requests));
|
|
328
|
+
port.onDisconnect.addListener(() => {
|
|
329
|
+
(0, subscriptions_js_1.unsubscribe)(id);
|
|
330
|
+
subscription.unsubscribe();
|
|
331
|
+
});
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
windowOpen(path) {
|
|
335
|
+
const url = `${chrome.runtime.getURL('index.html')}#${path}`;
|
|
336
|
+
if (!defaults_1.ALLOWED_PATH.includes(path)) {
|
|
337
|
+
console.error('Not allowed to open the url:', url);
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
(0, helpers_js_1.withErrorLog)(() => chrome.tabs.create({ url }));
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
343
|
+
derive(parentAddress, suri, password, metadata) {
|
|
344
|
+
const parentPair = ui_keyring_1.keyring.getPair(parentAddress);
|
|
345
|
+
try {
|
|
346
|
+
parentPair.decodePkcs8(password);
|
|
347
|
+
}
|
|
348
|
+
catch {
|
|
349
|
+
throw new Error('invalid password');
|
|
350
|
+
}
|
|
351
|
+
try {
|
|
352
|
+
return parentPair.derive(suri, metadata);
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
throw new Error(`"${suri}" is not a valid derivation path`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
derivationValidate({ parentAddress, parentPassword, suri }) {
|
|
359
|
+
const childPair = this.derive(parentAddress, suri, parentPassword, {});
|
|
360
|
+
return {
|
|
361
|
+
address: childPair.address,
|
|
362
|
+
suri
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
derivationCreate({ genesisHash, name, parentAddress, parentPassword, password, suri }) {
|
|
366
|
+
const childPair = this.derive(parentAddress, suri, parentPassword, {
|
|
367
|
+
genesisHash,
|
|
368
|
+
name,
|
|
369
|
+
parentAddress,
|
|
370
|
+
suri
|
|
371
|
+
});
|
|
372
|
+
ui_keyring_1.keyring.addPair(childPair, password);
|
|
373
|
+
return true;
|
|
374
|
+
}
|
|
375
|
+
async removeAuthorization(url) {
|
|
376
|
+
const remAuth = await this.#state.removeAuthorization(url);
|
|
377
|
+
return { list: remAuth };
|
|
378
|
+
}
|
|
379
|
+
// Reject the authorization request and add the URL to the authorized list with no keys.
|
|
380
|
+
// The site will not prompt for re-authorization on future visits.
|
|
381
|
+
rejectAuthRequest(id) {
|
|
382
|
+
const queued = this.#state.getAuthRequest(id);
|
|
383
|
+
(0, util_1.assert)(queued, 'Unable to find request');
|
|
384
|
+
const { reject } = queued;
|
|
385
|
+
reject(new Error('Rejected'));
|
|
386
|
+
}
|
|
387
|
+
// Cancel the authorization request and do not add the URL to the authorized list.
|
|
388
|
+
// The site will prompt for authorization on future visits.
|
|
389
|
+
cancelAuthRequest(id) {
|
|
390
|
+
const queued = this.#state.getAuthRequest(id);
|
|
391
|
+
(0, util_1.assert)(queued, 'Unable to find request');
|
|
392
|
+
const { reject } = queued;
|
|
393
|
+
reject(new Error('Cancelled'));
|
|
394
|
+
}
|
|
395
|
+
updateCurrentTabs({ urls }) {
|
|
396
|
+
this.#state.updateCurrentTabsUrl(urls);
|
|
397
|
+
}
|
|
398
|
+
getConnectedTabsUrl() {
|
|
399
|
+
return this.#state.getConnectedTabsUrl();
|
|
400
|
+
}
|
|
401
|
+
// Weird thought, the eslint override is not needed in Tabs
|
|
402
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
403
|
+
async handle(id, type, request, port) {
|
|
404
|
+
switch (type) {
|
|
405
|
+
case 'pri(authorize.approve)':
|
|
406
|
+
return this.authorizeApprove(request);
|
|
407
|
+
case 'pri(authorize.list)':
|
|
408
|
+
return this.getAuthList();
|
|
409
|
+
case 'pri(authorize.remove)':
|
|
410
|
+
return this.removeAuthorization(request);
|
|
411
|
+
case 'pri(authorize.reject)':
|
|
412
|
+
return this.rejectAuthRequest(request);
|
|
413
|
+
case 'pri(authorize.cancel)':
|
|
414
|
+
return this.cancelAuthRequest(request);
|
|
415
|
+
case 'pri(authorize.requests)':
|
|
416
|
+
return port && this.authorizeSubscribe(id, port);
|
|
417
|
+
case 'pri(authorize.update)':
|
|
418
|
+
return this.authorizeUpdate(request);
|
|
419
|
+
case 'pri(accounts.create.external)':
|
|
420
|
+
return this.accountsCreateExternal(request);
|
|
421
|
+
case 'pri(accounts.create.hardware)':
|
|
422
|
+
return this.accountsCreateHardware(request);
|
|
423
|
+
case 'pri(accounts.create.suri)':
|
|
424
|
+
return this.accountsCreateSuri(request);
|
|
425
|
+
case 'pri(accounts.changePassword)':
|
|
426
|
+
return this.accountsChangePassword(request);
|
|
427
|
+
case 'pri(accounts.edit)':
|
|
428
|
+
return this.accountsEdit(request);
|
|
429
|
+
case 'pri(accounts.export)':
|
|
430
|
+
return this.accountsExport(request);
|
|
431
|
+
case 'pri(accounts.batchExport)':
|
|
432
|
+
return this.accountsBatchExport(request);
|
|
433
|
+
case 'pri(accounts.forget)':
|
|
434
|
+
return this.accountsForget(request);
|
|
435
|
+
case 'pri(accounts.show)':
|
|
436
|
+
return this.accountsShow(request);
|
|
437
|
+
case 'pri(accounts.subscribe)':
|
|
438
|
+
return port && this.accountsSubscribe(id, port);
|
|
439
|
+
case 'pri(accounts.tie)':
|
|
440
|
+
return this.accountsTie(request);
|
|
441
|
+
case 'pri(accounts.validate)':
|
|
442
|
+
return this.accountsValidate(request);
|
|
443
|
+
case 'pri(metadata.approve)':
|
|
444
|
+
return await this.metadataApprove(request);
|
|
445
|
+
case 'pri(metadata.get)':
|
|
446
|
+
return this.metadataGet(request);
|
|
447
|
+
case 'pri(metadata.list)':
|
|
448
|
+
return this.metadataList();
|
|
449
|
+
case 'pri(metadata.reject)':
|
|
450
|
+
return this.metadataReject(request);
|
|
451
|
+
case 'pri(metadata.requests)':
|
|
452
|
+
return port && this.metadataSubscribe(id, port);
|
|
453
|
+
case 'pri(activeTabsUrl.update)':
|
|
454
|
+
return this.updateCurrentTabs(request);
|
|
455
|
+
case 'pri(connectedTabsUrl.get)':
|
|
456
|
+
return this.getConnectedTabsUrl();
|
|
457
|
+
case 'pri(derivation.create)':
|
|
458
|
+
return this.derivationCreate(request);
|
|
459
|
+
case 'pri(derivation.validate)':
|
|
460
|
+
return this.derivationValidate(request);
|
|
461
|
+
case 'pri(json.restore)':
|
|
462
|
+
return this.jsonRestore(request);
|
|
463
|
+
case 'pri(json.batchRestore)':
|
|
464
|
+
return this.batchRestore(request);
|
|
465
|
+
case 'pri(json.account.info)':
|
|
466
|
+
return this.jsonGetAccountInfo(request);
|
|
467
|
+
case 'pri(ping)':
|
|
468
|
+
return Promise.resolve(true);
|
|
469
|
+
case 'pri(seed.create)':
|
|
470
|
+
return this.seedCreate(request);
|
|
471
|
+
case 'pri(seed.validate)':
|
|
472
|
+
return this.seedValidate(request);
|
|
473
|
+
case 'pri(settings.notification)':
|
|
474
|
+
return this.#state.setNotification(request);
|
|
475
|
+
case 'pri(signing.approve.password)':
|
|
476
|
+
return this.signingApprovePassword(request);
|
|
477
|
+
case 'pri(signing.approve.signature)':
|
|
478
|
+
return this.signingApproveSignature(request);
|
|
479
|
+
case 'pri(signing.cancel)':
|
|
480
|
+
return this.signingCancel(request);
|
|
481
|
+
case 'pri(signing.isLocked)':
|
|
482
|
+
return this.signingIsLocked(request);
|
|
483
|
+
case 'pri(signing.requests)':
|
|
484
|
+
return port && this.signingSubscribe(id, port);
|
|
485
|
+
case 'pri(window.open)':
|
|
486
|
+
return this.windowOpen(request);
|
|
487
|
+
default:
|
|
488
|
+
throw new Error(`Unable to handle message of type ${type}`);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
exports.default = Extension;
|