Allow for unsubscribe on account subscriptions (#1067)
* Allow for unsubscribe on account subscriptions * CHANGELOG * Adjust * Adjust
This commit is contained in:
parent
2d09932ca1
commit
a7f27ac4b6
13
CHANGELOG.md
13
CHANGELOG.md
@ -1,5 +1,18 @@
|
||||
# CHANGELOG
|
||||
|
||||
## master
|
||||
|
||||
Contributed:
|
||||
|
||||
- Account selection/management for authorized sites (Thanks to https://github.com/Tbaut)
|
||||
- UI icon & cursor adjustments for authorization (Thanks to https://github.com/roiLeo)
|
||||
|
||||
Changes:
|
||||
|
||||
- Allow for unsubscribe handling on account subscriptions
|
||||
- Add error handling for user-supplied account callbacks
|
||||
|
||||
|
||||
## 0.44.1 Jun 6, 2022
|
||||
|
||||
**Important** CHANGELOG entries are a rollup of details since last publish to the stores
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
// Copyright 2019-2022 @polkadot/extension authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { Subscription } from 'rxjs';
|
||||
import type { InjectedAccount, InjectedMetadataKnown, MetadataDef, ProviderMeta } from '@polkadot/extension-inject/types';
|
||||
import type { KeyringPair } from '@polkadot/keyring/types';
|
||||
import type { JsonRpcResponse } from '@polkadot/rpc-provider/types';
|
||||
import type { SignerPayloadJSON, SignerPayloadRaw } from '@polkadot/types/types';
|
||||
import type { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
|
||||
import type { MessageTypes, RequestAccountList, RequestAuthorizeTab, RequestRpcSend, RequestRpcSubscribe, RequestRpcUnsubscribe, RequestTypes, ResponseRpcListProviders, ResponseSigning, ResponseTypes, SubscriptionMessageTypes } from '../types';
|
||||
import type { MessageTypes, RequestAccountList, RequestAccountUnsubscribe, RequestAuthorizeTab, RequestRpcSend, RequestRpcSubscribe, RequestRpcUnsubscribe, RequestTypes, ResponseRpcListProviders, ResponseSigning, ResponseTypes, SubscriptionMessageTypes } from '../types';
|
||||
|
||||
import { PHISHING_PAGE_REDIRECT } from '@polkadot/extension-base/defaults';
|
||||
import { canDerive } from '@polkadot/extension-base/utils';
|
||||
@ -21,6 +22,11 @@ import { withErrorLog } from './helpers';
|
||||
import State, { AuthResponse } from './State';
|
||||
import { createSubscription, unsubscribe } from './subscriptions';
|
||||
|
||||
interface AccountSub {
|
||||
subscription: Subscription;
|
||||
url: string;
|
||||
}
|
||||
|
||||
function transformAccounts (accounts: SubjectInfo, anyType = false): InjectedAccount[] {
|
||||
return Object
|
||||
.values(accounts)
|
||||
@ -36,6 +42,8 @@ function transformAccounts (accounts: SubjectInfo, anyType = false): InjectedAcc
|
||||
}
|
||||
|
||||
export default class Tabs {
|
||||
readonly #accountSubs: Record<string, AccountSub> = {};
|
||||
|
||||
readonly #state: State;
|
||||
|
||||
constructor (state: State) {
|
||||
@ -65,21 +73,37 @@ export default class Tabs {
|
||||
return this.filterForAuthorizedAccounts(transformedAccounts, url);
|
||||
}
|
||||
|
||||
private accountsSubscribeAuthorized (url: string, id: string, port: chrome.runtime.Port): boolean {
|
||||
const cb = createSubscription<'pub(accounts.subscribeAuthorized)'>(id, port);
|
||||
const subscription = accountsObservable.subject.subscribe((accounts: SubjectInfo): void => {
|
||||
const transformedAccounts = transformAccounts(accounts);
|
||||
private accountsSubscribeAuthorized (url: string, id: string, port: chrome.runtime.Port): string {
|
||||
const cb = createSubscription<'pub(accounts.subscribe)'>(id, port);
|
||||
|
||||
return cb(
|
||||
this.filterForAuthorizedAccounts(transformedAccounts, url)
|
||||
);
|
||||
});
|
||||
this.#accountSubs[id] = {
|
||||
subscription: accountsObservable.subject.subscribe((accounts: SubjectInfo): void => {
|
||||
const transformedAccounts = transformAccounts(accounts);
|
||||
|
||||
cb(this.filterForAuthorizedAccounts(transformedAccounts, url));
|
||||
}),
|
||||
url
|
||||
};
|
||||
|
||||
port.onDisconnect.addListener((): void => {
|
||||
unsubscribe(id);
|
||||
subscription.unsubscribe();
|
||||
this.accountsUnsubscribe(url, { id });
|
||||
});
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
private accountsUnsubscribe (url: string, { id }: RequestAccountUnsubscribe): boolean {
|
||||
const sub = this.#accountSubs[id];
|
||||
|
||||
if (!sub || sub.url !== url) {
|
||||
return false;
|
||||
}
|
||||
|
||||
delete this.#accountSubs[id];
|
||||
|
||||
unsubscribe(id);
|
||||
sub.subscription.unsubscribe();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -199,12 +223,15 @@ export default class Tabs {
|
||||
case 'pub(authorize.tab)':
|
||||
return this.authorize(url, request as RequestAuthorizeTab);
|
||||
|
||||
case 'pub(accounts.listAuthorized)':
|
||||
case 'pub(accounts.list)':
|
||||
return this.accountsListAuthorized(url, request as RequestAccountList);
|
||||
|
||||
case 'pub(accounts.subscribeAuthorized)':
|
||||
case 'pub(accounts.subscribe)':
|
||||
return this.accountsSubscribeAuthorized(url, id, port);
|
||||
|
||||
case 'pub(accounts.unsubscribe)':
|
||||
return this.accountsUnsubscribe(url, request as RequestAccountUnsubscribe);
|
||||
|
||||
case 'pub(bytes.sign)':
|
||||
return this.bytesSign(url, request as SignerPayloadRaw);
|
||||
|
||||
|
||||
@ -116,8 +116,9 @@ export interface RequestSignatures {
|
||||
'pri(signing.requests)': [RequestSigningSubscribe, boolean, SigningRequest[]];
|
||||
'pri(window.open)': [AllowedPath, boolean];
|
||||
// public/external requests, i.e. from a page
|
||||
'pub(accounts.listAuthorized)': [RequestAccountList, InjectedAccount[]];
|
||||
'pub(accounts.subscribeAuthorized)': [RequestAccountSubscribe, boolean, InjectedAccount[]];
|
||||
'pub(accounts.list)': [RequestAccountList, InjectedAccount[]];
|
||||
'pub(accounts.subscribe)': [RequestAccountSubscribe, string, InjectedAccount[]];
|
||||
'pub(accounts.unsubscribe)': [RequestAccountUnsubscribe, boolean];
|
||||
'pub(authorize.tab)': [RequestAuthorizeTab, Promise<AuthResponse>];
|
||||
'pub(bytes.sign)': [SignerPayloadRaw, ResponseSigning];
|
||||
'pub(extrinsic.sign)': [SignerPayloadJSON, ResponseSigning];
|
||||
@ -260,6 +261,10 @@ export interface RequestAccountList {
|
||||
|
||||
export type RequestAccountSubscribe = null;
|
||||
|
||||
export interface RequestAccountUnsubscribe {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface RequestRpcSend {
|
||||
method: string;
|
||||
params: unknown[];
|
||||
|
||||
@ -13,15 +13,21 @@ export default class Accounts implements InjectedAccounts {
|
||||
}
|
||||
|
||||
public get (anyType?: boolean): Promise<InjectedAccount[]> {
|
||||
return sendRequest('pub(accounts.listAuthorized)', { anyType });
|
||||
return sendRequest('pub(accounts.list)', { anyType });
|
||||
}
|
||||
|
||||
public subscribe (cb: (accounts: InjectedAccount[]) => unknown): Unsubcall {
|
||||
sendRequest('pub(accounts.subscribeAuthorized)', null, cb)
|
||||
.catch((error: Error) => console.error(error));
|
||||
let id: string | null = null;
|
||||
|
||||
sendRequest('pub(accounts.subscribe)', null, cb)
|
||||
.then((subId): void => {
|
||||
id = subId;
|
||||
})
|
||||
.catch(console.error);
|
||||
|
||||
return (): void => {
|
||||
// FIXME we need the ability to unsubscribe
|
||||
id && sendRequest('pub(accounts.unsubscribe)', { id })
|
||||
.catch(console.error);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user