Split messages into pub/pri (#139)

* Split messages into pub/pri

* Cleanup types for contexts

* genesisHash to edit/create

* (Auth|Sign)Request to record (not tuple)

* Align naming with messages

* Pass account with SignRequest

* Ordering

* Ordering
This commit is contained in:
Jaco Greeff 2019-09-06 10:52:57 +02:00 committed by GitHub
parent 251417b50e
commit e20b6e0f16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 158 additions and 142 deletions

View File

@ -22,9 +22,9 @@ function throwError (method: string): never {
// internal helper to map from Array<InjectedAccount> -> Array<InjectedAccountWithMeta>
function mapAccounts (source: string, list: InjectedAccount[]): InjectedAccountWithMeta[] {
return list.map(({ address, name }): InjectedAccountWithMeta => ({
return list.map(({ address, genesisHash, name }): InjectedAccountWithMeta => ({
address,
meta: { name, source }
meta: { genesisHash, name, source }
}));
}

View File

@ -11,12 +11,14 @@ export type Unsubcall = () => void;
export interface InjectedAccount {
address: string;
genesisHash?: string | null;
name?: string;
}
export interface InjectedAccountWithMeta {
address: string;
meta: {
genesisHash?: string | null;
name?: string;
source: string;
};

View File

@ -13,7 +13,7 @@ export default function Authorize (): React.ReactElement<{}> {
return (
<div>
<Header label='authorize' />
{requests.map(([id, request, url], index): React.ReactNode => (
{requests.map(({ id, request, url }, index): React.ReactNode => (
<Request
authId={id}
isFirst={index === 0}

View File

@ -5,7 +5,7 @@
import React, { useContext, useEffect, useState } from 'react';
import { ActionContext, Address, Button, Header, Loading, TextArea } from '../components';
import { createAccount, createSeed } from '../messaging';
import { createAccountSuri, createSeed } from '../messaging';
import { Back, Name, Password } from '../partials';
type Props = {}
@ -26,7 +26,7 @@ export default function Create (): React.ReactElement<Props> {
const onCreate = (): void => {
// this should always be the case
if (name && password && account) {
createAccount(name, password, account.seed)
createAccountSuri(name, password, account.seed)
.then((): void => onAction('/'))
.catch((error: Error) => console.error(error));
}

View File

@ -5,7 +5,7 @@
import React, { useContext, useState } from 'react';
import { ActionContext, Address, Button, Header, TextArea } from '../components';
import { createAccount, validateSeed } from '../messaging';
import { createAccountSuri, validateSeed } from '../messaging';
import { Back, Name, Password } from '../partials';
type Props = {};
@ -25,7 +25,7 @@ export default function Import (): React.ReactElement<Props> {
const onCreate = (): void => {
// this should always be the case
if (name && password && account) {
createAccount(name, password, account.suri)
createAccountSuri(name, password, account.suri)
.then((): void => onAction('/'))
.catch((error: Error) => console.error(error));
}

View File

@ -8,7 +8,7 @@ import React, { useContext } from 'react';
import { createType } from '@polkadot/types';
import { ActionBar, ActionContext, Address, Link } from '../../components';
import { approveSignRequest, cancelSignRequest } from '../../messaging';
import { approveSignPassword, cancelSignRequest } from '../../messaging';
import Details from './Details';
import Unlock from './Unlock';
@ -26,7 +26,7 @@ export default function Request ({ isFirst, request, signId, url }: Props): Reac
.then((): void => onAction())
.catch((error: Error) => console.error(error));
const onSign = (password: string): Promise<void> =>
approveSignRequest(signId, password)
approveSignPassword(signId, password)
.then((): void => onAction());
const blockNumber = createType('BlockNumber', request.blockNumber);
const payload = createType('ExtrinsicPayload', request, { version: request.version });

View File

@ -13,7 +13,7 @@ export default function Signing (): React.ReactElement<{}> {
return (
<div>
<Header label='transactions' />
{requests.map(([id, request, url], index): React.ReactNode => (
{requests.map(({ id, request, url }, index): React.ReactNode => (
<Request
isFirst={index === 0}
key={id}

View File

@ -2,8 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AuthorizeRequest, SigningRequest } from '@polkadot/extension/background/types';
import { InjectedAccount } from '@polkadot/extension-inject/types';
import { AccountJson, AuthorizeRequest, SigningRequest } from '@polkadot/extension/background/types';
import { Prefix } from '@polkadot/util-crypto/address/types';
import React, { useEffect, useState } from 'react';
@ -31,7 +30,7 @@ const { prefix } = settings.get();
setAddressPrefix((prefix === -1 ? 42 : prefix) as Prefix);
export default function Popup (): React.ReactElement<{}> {
const [accounts, setAccounts] = useState<null | InjectedAccount[]>(null);
const [accounts, setAccounts] = useState<null | AccountJson[]>(null);
const [authRequests, setAuthRequests] = useState<null | AuthorizeRequest[]>(null);
const [signRequests, setSignRequests] = useState<null | SigningRequest[]>(null);
const [isWelcomeDone, setWelcomeDone] = useState(false);

View File

@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { InjectedAccount } from '@polkadot/extension-inject/types';
import { AccountJson } from '@polkadot/extension/background/types';
import { Prefix } from '@polkadot/util-crypto/address/types';
import React, { useContext, useEffect, useState } from 'react';
@ -24,7 +24,7 @@ interface Props {
function Address ({ address, children, className, name, theme = 'polkadot' }: Props): React.ReactElement<Props> {
const accounts = useContext(AccountContext);
const [account, setAccount] = useState<InjectedAccount | null>(null);
const [account, setAccount] = useState<AccountJson | null>(null);
const [formatted, setFormatted] = useState<string | null>(null);
useEffect((): void => {

View File

@ -2,19 +2,17 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountsFromCtx, OnActionFromCtx, AuthRequestsFromCtx, SignRequestsFromCtx } from './types';
import { AccountJson, AuthorizeRequest, SigningRequest } from '@polkadot/extension/background/types';
import React from 'react';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const noop = (to?: string): void => {
// do nothing
};
const noop = (to?: string): void => {};
const AccountContext = React.createContext<AccountsFromCtx>([]);
const ActionContext = React.createContext<OnActionFromCtx>(noop);
const AuthorizeContext = React.createContext<AuthRequestsFromCtx>([]);
const SigningContext = React.createContext<SignRequestsFromCtx>([]);
const AccountContext = React.createContext<AccountJson[]>([]);
const ActionContext = React.createContext<(to?: string) => void>(noop);
const AuthorizeContext = React.createContext<AuthorizeRequest[]>([]);
const SigningContext = React.createContext<SigningRequest[]>([]);
export {
AccountContext,

View File

@ -2,13 +2,6 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AuthorizeRequest, SigningRequest } from '@polkadot/extension/background/types';
import { InjectedAccount } from '@polkadot/extension-inject/types';
export type OmitProps<T, K> = Pick<T, Exclude<keyof T, K>>;
export type SubtractProps<T, K> = OmitProps<T, keyof K>;
export type AccountsFromCtx = InjectedAccount[];
export type OnActionFromCtx = (to?: string) => void;
export type AuthRequestsFromCtx = AuthorizeRequest[];
export type SignRequestsFromCtx = SigningRequest[];
export type SubtractProps<T, K> = OmitProps<T, keyof K>;

View File

@ -2,12 +2,11 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AuthorizeRequest, SigningRequest, RequestTypes, MessageTypes, ResponseTypes, SeedLengths, SubscriptionMessageTypes, MessageTypesWithNullRequest, MessageTypesWithNoSubscriptions, MessageTypesWithSubscriptions } from '@polkadot/extension/background/types';
import { AccountJson, AuthorizeRequest, SigningRequest, RequestTypes, MessageTypes, ResponseTypes, SeedLengths, SubscriptionMessageTypes, MessageTypesWithNullRequest, MessageTypesWithNoSubscriptions, MessageTypesWithSubscriptions } from '@polkadot/extension/background/types';
import { KeypairType } from '@polkadot/util-crypto/types';
import extension from 'extensionizer';
import { PORT_POPUP } from '@polkadot/extension/defaults';
import { InjectedAccount } from '@polkadot/extension-inject/types';
interface Handler {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -60,61 +59,61 @@ function sendMessage<TMessageType extends MessageTypes> (message: TMessageType,
}
export async function editAccount (address: string, name: string): Promise<boolean> {
return sendMessage('accounts.edit', { address, name });
return sendMessage('pri(accounts.edit)', { address, name });
}
export async function forgetAccount (address: string): Promise<boolean> {
return sendMessage('accounts.forget', { address });
return sendMessage('pri(accounts.forget)', { address });
}
export async function getAccounts (): Promise<InjectedAccount[]> {
return sendMessage('accounts.list');
export async function getAccounts (): Promise<AccountJson[]> {
return sendMessage('pri(accounts.list)');
}
export async function getAuthRequests (): Promise<AuthorizeRequest[]> {
return sendMessage('authorize.requests');
return sendMessage('pri(authorize.requests)');
}
export async function rejectAuthRequest (id: string): Promise<boolean> {
return sendMessage('authorize.reject', { id });
return sendMessage('pri(authorize.reject)', { id });
}
export async function approveAuthRequest (id: string): Promise<boolean> {
return sendMessage('authorize.approve', { id });
return sendMessage('pri(authorize.approve)', { id });
}
export async function getSignRequests (): Promise<SigningRequest[]> {
return sendMessage('signing.requests');
return sendMessage('pri(signing.requests)');
}
export async function cancelSignRequest (id: string): Promise<boolean> {
return sendMessage('signing.cancel', { id });
return sendMessage('pri(signing.cancel)', { id });
}
export async function approveSignRequest (id: string, password: string): Promise<boolean> {
return sendMessage('signing.approve', { id, password });
export async function approveSignPassword (id: string, password: string): Promise<boolean> {
return sendMessage('pri(signing.approve.password)', { id, password });
}
export async function createAccount (name: string, password: string, suri: string, type?: KeypairType): Promise<boolean> {
return sendMessage('accounts.create', { name, password, suri, type });
export async function createAccountSuri (name: string, password: string, suri: string, type?: KeypairType): Promise<boolean> {
return sendMessage('pri(accounts.create.suri)', { name, password, suri, type });
}
export async function createSeed (length?: SeedLengths, type?: KeypairType): Promise<{ address: string; seed: string }> {
return sendMessage('seed.create', { length, type });
return sendMessage('pri(seed.create)', { length, type });
}
export async function subscribeAccounts (cb: (accounts: InjectedAccount[]) => void): Promise<boolean> {
return sendMessage('accounts.subscribe', null, cb);
export async function subscribeAccounts (cb: (accounts: AccountJson[]) => void): Promise<boolean> {
return sendMessage('pri(accounts.subscribe)', null, cb);
}
export async function subscribeAuthorize (cb: (accounts: AuthorizeRequest[]) => void): Promise<boolean> {
return sendMessage('authorize.subscribe', null, cb);
return sendMessage('pri(authorize.subscribe)', null, cb);
}
export async function subscribeSigning (cb: (accounts: SigningRequest[]) => void): Promise<boolean> {
return sendMessage('signing.subscribe', null, cb);
return sendMessage('pri(signing.subscribe)', null, cb);
}
export async function validateSeed (suri: string, type?: KeypairType): Promise<{ address: string; suri: string }> {
return sendMessage('seed.validate', { suri, type });
return sendMessage('pri(seed.validate)', { suri, type });
}

View File

@ -3,8 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
import { AuthorizeRequest, RequestAccountCreate, RequestAccountEdit, RequestAuthorizeApprove, RequestAuthorizeReject, RequestSigningApprove, RequestSigningCancel, RequestSeedCreate, ResponseSeedCreate, RequestSeedValidate, ResponseSeedValidate, RequestAccountForget, SigningRequest, RequestTypes, ResponseTypes, MessageTypes } from '../types';
import { InjectedAccount } from '@polkadot/extension-inject/types';
import { AccountJson, AuthorizeRequest, RequestAccountCreateSuri, RequestAccountEdit, RequestAuthorizeApprove, RequestAuthorizeReject, RequestSigningApprovePassword, RequestSigningCancel, RequestSeedCreate, ResponseSeedCreate, RequestSeedValidate, ResponseSeedValidate, RequestAccountForget, SigningRequest, RequestTypes, ResponseTypes, MessageTypes } from '../types';
import keyring from '@polkadot/ui-keyring';
import accountsObservable from '@polkadot/ui-keyring/observable/accounts';
@ -18,8 +17,8 @@ import { createSubscription, unsubscribe } from './subscriptions';
const SEED_DEFAULT_LENGTH = 12;
const SEED_LENGTHS = [12, 24];
function transformAccounts (accounts: SubjectInfo): InjectedAccount[] {
return Object.values(accounts).map(({ json }): InjectedAccount => ({ ...json, name: json.meta && json.meta.name }));
function transformAccounts (accounts: SubjectInfo): AccountJson[] {
return Object.values(accounts).map(({ json }): AccountJson => json);
}
export default class Extension {
@ -29,8 +28,8 @@ export default class Extension {
this.state = state;
}
private accountsCreate ({ name, password, suri, type }: RequestAccountCreate): boolean {
keyring.addUri(suri, password, { name }, type);
private accountsCreateSuri ({ genesisHash, name, password, suri, type }: RequestAccountCreateSuri): boolean {
keyring.addUri(suri, password, { genesisHash, name }, type);
return true;
}
@ -51,13 +50,13 @@ export default class Extension {
return true;
}
private accountsList (): InjectedAccount[] {
private accountsList (): AccountJson[] {
return transformAccounts(accountsObservable.subject.getValue());
}
// FIXME This looks very much like what we have in Tabs
private accountsSubscribe (id: string, port: chrome.runtime.Port): boolean {
const cb = createSubscription<'accounts.subscribe'>(id, port);
const cb = createSubscription<'pri(accounts.subscribe)'>(id, port);
const subscription = accountsObservable.subject.subscribe((accounts: SubjectInfo): void =>
cb(transformAccounts(accounts))
);
@ -100,7 +99,7 @@ export default class Extension {
// FIXME This looks very much like what we have in accounts
private authorizeSubscribe (id: string, port: chrome.runtime.Port): boolean {
const cb = createSubscription<'authorize.subscribe'>(id, port);
const cb = createSubscription<'pri(authorize.subscribe)'>(id, port);
const subscription = this.state.authSubject.subscribe((requests: AuthorizeRequest[]): void =>
cb(requests)
);
@ -134,7 +133,7 @@ export default class Extension {
};
}
private signingApprove ({ id, password }: RequestSigningApprove): boolean {
private signingApprovePassword ({ id, password }: RequestSigningApprovePassword): boolean {
const queued = this.state.getSignRequest(id);
assert(queued, 'Unable to find request');
@ -181,7 +180,7 @@ export default class Extension {
// FIXME This looks very much like what we have in authorization
private signingSubscribe (id: string, port: chrome.runtime.Port): boolean {
const cb = createSubscription<'signing.subscribe'>(id, port);
const cb = createSubscription<'pri(signing.subscribe)'>(id, port);
const subscription = this.state.signSubject.subscribe((requests: SigningRequest[]): void =>
cb(requests)
);
@ -194,57 +193,57 @@ export default class Extension {
return true;
}
public handle<TMessageType extends MessageTypes> (id: string, type: TMessageType, request: RequestTypes[TMessageType], port: chrome.runtime.Port): Promise<ResponseTypes[keyof ResponseTypes]> {
return new Promise((resolve, reject): void => {
switch (type) {
case 'authorize.approve':
return resolve(this.authorizeApprove(request as RequestAuthorizeApprove));
// Weird thought, the eslint override is not needed in Tabs
// eslint-disable-next-line @typescript-eslint/require-await
public async handle<TMessageType extends MessageTypes> (id: string, type: TMessageType, request: RequestTypes[TMessageType], port: chrome.runtime.Port): Promise<ResponseTypes[keyof ResponseTypes]> {
switch (type) {
case 'pri(authorize.approve)':
return this.authorizeApprove(request as RequestAuthorizeApprove);
case 'authorize.reject':
return resolve(this.authorizeReject(request as RequestAuthorizeApprove));
case 'pri(authorize.reject)':
return this.authorizeReject(request as RequestAuthorizeApprove);
case 'authorize.requests':
return resolve(this.authorizeRequests());
case 'pri(authorize.requests)':
return this.authorizeRequests();
case 'authorize.subscribe':
return resolve(this.authorizeSubscribe(id, port));
case 'pri(authorize.subscribe)':
return this.authorizeSubscribe(id, port);
case 'accounts.create':
return resolve(this.accountsCreate(request as RequestAccountCreate));
case 'pri(accounts.create.suri)':
return this.accountsCreateSuri(request as RequestAccountCreateSuri);
case 'accounts.forget':
return resolve(this.accountsForget(request as RequestAccountForget));
case 'pri(accounts.forget)':
return this.accountsForget(request as RequestAccountForget);
case 'accounts.edit':
return resolve(this.accountsEdit(request as RequestAccountEdit));
case 'pri(accounts.edit)':
return this.accountsEdit(request as RequestAccountEdit);
case 'accounts.list':
return resolve(this.accountsList());
case 'pri(accounts.list)':
return this.accountsList();
case 'accounts.subscribe':
return resolve(this.accountsSubscribe(id, port));
case 'pri(accounts.subscribe)':
return this.accountsSubscribe(id, port);
case 'seed.create':
return resolve(this.seedCreate(request as RequestSeedCreate));
case 'pri(seed.create)':
return this.seedCreate(request as RequestSeedCreate);
case 'seed.validate':
return resolve(this.seedValidate(request as RequestSeedValidate));
case 'pri(seed.validate)':
return this.seedValidate(request as RequestSeedValidate);
case 'signing.approve':
return resolve(this.signingApprove(request as RequestSigningApprove));
case 'pri(signing.approve.password)':
return this.signingApprovePassword(request as RequestSigningApprovePassword);
case 'signing.cancel':
return resolve(this.signingCancel(request as RequestSigningCancel));
case 'pri(signing.cancel)':
return this.signingCancel(request as RequestSigningCancel);
case 'signing.requests':
return resolve(this.signingRequests());
case 'pri(signing.requests)':
return this.signingRequests();
case 'signing.subscribe':
return resolve(this.signingSubscribe(id, port));
case 'pri(signing.subscribe)':
return this.signingSubscribe(id, port);
default:
return reject(new Error(`Unable to handle message of type ${type}`));
}
});
default:
throw new Error(`Unable to handle message of type ${type}`);
}
}
}

View File

@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AuthorizeRequest, RequestAuthorizeTab, RequestExtrinsicSign, ResponseExtrinsicSign, SigningRequest } from '../types';
import { AccountJson, AuthorizeRequest, RequestAuthorizeTab, RequestExtrinsicSign, ResponseExtrinsicSign, SigningRequest } from '../types';
import extension from 'extensionizer';
import { BehaviorSubject } from 'rxjs';
@ -26,6 +26,7 @@ type AuthUrls = Record<string, {
}>;
interface SignRequest {
account: AccountJson;
id: string;
request: RequestExtrinsicSign;
resolve: (result: ResponseExtrinsicSign) => void;
@ -71,13 +72,13 @@ export default class State {
public get allAuthRequests (): AuthorizeRequest[] {
return Object
.values(this._authRequests)
.map(({ id, request, url }): AuthorizeRequest => [id, request, url]);
.map(({ id, request, url }): AuthorizeRequest => ({ id, request, url }));
}
public get allSignRequests (): SigningRequest[] {
return Object
.values(this._signRequests)
.map(({ id, request, url }): SigningRequest => [id, request, url]);
.map(({ account, id, request, url }): SigningRequest => ({ account, id, request, url }));
}
private popupClose (): void {
@ -210,11 +211,12 @@ export default class State {
return this._signRequests[id];
}
public signQueue (url: string, request: RequestExtrinsicSign): Promise<ResponseExtrinsicSign> {
public signQueue (url: string, request: RequestExtrinsicSign, account: AccountJson): Promise<ResponseExtrinsicSign> {
const id = getId();
return new Promise((resolve, reject): void => {
this._signRequests[id] = {
account,
id,
request,
resolve: this.signComplete(id, resolve),

View File

@ -3,8 +3,8 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { InjectedAccount } from '@polkadot/extension-inject/types';
import { RequestAuthorizeTab, RequestExtrinsicSign, ResponseExtrinsicSign, RequestTypes, ResponseTypes, MessageTypes } from '../types';
import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
import { RequestAuthorizeTab, RequestExtrinsicSign, ResponseExtrinsicSign, RequestTypes, ResponseTypes, MessageTypes } from '../types';
import keyring from '@polkadot/ui-keyring';
import accountsObservable from '@polkadot/ui-keyring/observable/accounts';
@ -14,8 +14,8 @@ import State from './State';
import { createSubscription, unsubscribe } from './subscriptions';
function transformAccounts (accounts: SubjectInfo): InjectedAccount[] {
return Object.values(accounts).map(({ json: { address, meta: { name } } }): InjectedAccount => ({
address, name
return Object.values(accounts).map(({ json: { address, meta: { genesisHash, name } } }): InjectedAccount => ({
address, genesisHash, name
}));
}
@ -37,7 +37,7 @@ export default class Tabs {
// FIXME This looks very much like what we have in Extension
private accountsSubscribe (url: string, id: string, port: chrome.runtime.Port): boolean {
const cb = createSubscription<'accounts.subscribe'>(id, port);
const cb = createSubscription<'pub(accounts.subscribe)'>(id, port);
const subscription = accountsObservable.subject.subscribe((accounts: SubjectInfo): void =>
cb(transformAccounts(accounts))
);
@ -56,25 +56,25 @@ export default class Tabs {
assert(pair, 'Unable to find keypair');
return this.state.signQueue(url, request);
return this.state.signQueue(url, request, { address, ...pair.meta });
}
public async handle<TMessageType extends MessageTypes> (id: string, type: TMessageType, request: RequestTypes[TMessageType], url: string, port: chrome.runtime.Port): Promise<ResponseTypes[keyof ResponseTypes]> {
if (type !== 'authorize.tab') {
if (type !== 'pub(authorize.tab)') {
this.state.ensureUrlAuthorized(url);
}
switch (type) {
case 'authorize.tab':
case 'pub(authorize.tab)':
return this.authorize(url, request as RequestAuthorizeTab);
case 'accounts.list':
case 'pub(accounts.list)':
return this.accountsList(url);
case 'accounts.subscribe':
case 'pub(accounts.subscribe)':
return this.accountsSubscribe(url, id, port);
case 'extrinsic.sign':
case 'pub(extrinsic.sign)':
return this.extrinsicSign(url, request as RequestExtrinsicSign);
default:

View File

@ -14,33 +14,55 @@ type NoUndefinedValues<T> = {
[K in KeysWithDefinedValues<T>]: T[K]
};
type IsNull<T, K extends keyof T> = { [K1 in Exclude<keyof T, K>]: T[K1] } & T[K] extends null ? K : never
type NullKeys<T> = { [K in keyof T]: IsNull<T, K> }[keyof T]
type IsNull<T, K extends keyof T> = { [K1 in Exclude<keyof T, K>]: T[K1] } & T[K] extends null ? K : never;
type NullKeys<T> = { [K in keyof T]: IsNull<T, K> }[keyof T];
export type SeedLengths = 12 | 24;
export type AuthorizeRequest = [string, RequestAuthorizeTab, string];
export type SigningRequest = [string, RequestExtrinsicSign, string];
export interface AccountJson {
address: string;
genesisHash?: string | null;
isExternal?: boolean;
name?: string;
}
export interface AuthorizeRequest {
id: string;
request: RequestAuthorizeTab;
url: string;
}
export interface SigningRequest {
account: AccountJson;
id: string;
request: RequestExtrinsicSign;
url: string;
}
// [MessageType]: [RequestType, ResponseType, SubscriptionMessageType?]
export interface RequestSignatures {
'accounts.create': [RequestAccountCreate, boolean];
'accounts.edit': [RequestAccountEdit, boolean];
'accounts.forget': [RequestAccountForget, boolean];
'accounts.list': [RequestAccountList, InjectedAccount[]];
'accounts.subscribe': [RequestAccountSubscribe, boolean, InjectedAccount[]];
'authorize.tab': [RequestAuthorizeTab, null];
'authorize.approve': [RequestAuthorizeApprove, boolean];
'authorize.reject': [RequestAuthorizeReject, boolean];
'authorize.requests': [RequestAuthorizeRequests, AuthorizeRequest[]];
'authorize.subscribe': [RequestAuthorizeSubscribe, boolean, AuthorizeRequest[]];
'extrinsic.sign': [RequestExtrinsicSign, ResponseExtrinsicSign];
'seed.create': [RequestSeedCreate, ResponseSeedCreate];
'seed.validate': [RequestSeedValidate, ResponseSeedValidate];
'signing.approve': [RequestSigningApprove, boolean];
'signing.cancel': [RequestSigningCancel, boolean];
'signing.requests': [RequestSigningRequests, SigningRequest[]];
'signing.subscribe': [RequestSigningSubscribe, boolean, SigningRequest[]];
// private/internal requests, i.e. from a popup
'pri(accounts.create.suri)': [RequestAccountCreateSuri, boolean];
'pri(accounts.edit)': [RequestAccountEdit, boolean];
'pri(accounts.forget)': [RequestAccountForget, boolean];
'pri(accounts.list)': [RequestAccountList, AccountJson[]];
'pri(accounts.subscribe)': [RequestAccountSubscribe, boolean, AccountJson[]];
'pri(authorize.approve)': [RequestAuthorizeApprove, boolean];
'pri(authorize.reject)': [RequestAuthorizeReject, boolean];
'pri(authorize.requests)': [RequestAuthorizeRequests, AuthorizeRequest[]];
'pri(authorize.subscribe)': [RequestAuthorizeSubscribe, boolean, AuthorizeRequest[]];
'pri(seed.create)': [RequestSeedCreate, ResponseSeedCreate];
'pri(seed.validate)': [RequestSeedValidate, ResponseSeedValidate];
'pri(signing.approve.password)': [RequestSigningApprovePassword, boolean];
'pri(signing.cancel)': [RequestSigningCancel, boolean];
'pri(signing.requests)': [RequestSigningRequests, SigningRequest[]];
'pri(signing.subscribe)': [RequestSigningSubscribe, boolean, SigningRequest[]];
// public/external requests, i.e. from a page
'pub(accounts.list)': [RequestAccountList, InjectedAccount[]];
'pub(accounts.subscribe)': [RequestAccountSubscribe, boolean, InjectedAccount[]];
'pub(authorize.tab)': [RequestAuthorizeTab, null];
'pub(extrinsic.sign)': [RequestExtrinsicSign, ResponseExtrinsicSign];
}
export type MessageTypes = keyof RequestSignatures;
@ -76,8 +98,9 @@ export type RequestAuthorizeRequests = null;
export type RequestAuthorizeSubscribe = null;
export interface RequestAccountCreate {
export interface RequestAccountCreateSuri {
name: string;
genesisHash?: string | null;
password: string;
suri: string;
type?: KeypairType;
@ -85,6 +108,7 @@ export interface RequestAccountCreate {
export interface RequestAccountEdit {
address: string;
genesisHash?: string | null;
name: string;
}
@ -98,7 +122,7 @@ export type RequestAccountSubscribe = null;
export type RequestExtrinsicSign = SignerPayloadJSON;
export interface RequestSigningApprove {
export interface RequestSigningApprovePassword {
id: string;
password: string;
}

View File

@ -13,12 +13,12 @@ export default class Accounts implements InjectedAccounts {
}
public get (): Promise<InjectedAccount[]> {
return sendRequest('accounts.list');
return sendRequest('pub(accounts.list)');
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public subscribe (cb: (accounts: InjectedAccount[]) => any): Unsubcall {
sendRequest('accounts.subscribe', null, cb)
sendRequest('pub(accounts.subscribe)', null, cb)
.catch((error: Error) => console.error(error));
return (): void => {

View File

@ -19,7 +19,7 @@ export default class Signer implements SignerInterface {
public async signPayload (payload: SignerPayloadJSON): Promise<SignerResult> {
const id = ++nextId;
const result = await sendRequest('extrinsic.sign', payload);
const result = await sendRequest('pub(extrinsic.sign)', payload);
// we add an internal id (number) - should have a mapping from the
// extension id (string) -> internal id (number) if we wish to provide

View File

@ -52,13 +52,13 @@ function sendMessage<TMessageType extends MessageTypes> (message: TMessageType,
// the enable function, called by the dapp to allow access
async function enable (origin: string): Promise<Injected> {
await sendMessage('authorize.tab', { origin });
await sendMessage('pub(authorize.tab)', { origin });
return new Injected(sendMessage);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function handleResponse<TMessageType extends MessageTypes> (data: TransportResponseMessage<TMessageType> & {subscription?: any}): void {
function handleResponse<TMessageType extends MessageTypes> (data: TransportResponseMessage<TMessageType> & { subscription?: any }): void {
const handler = handlers[data.id];
if (!handler) {