Compat with other extensions (#36)
This commit is contained in:
parent
0359b7a601
commit
bb99f8a27b
11
packages/extension-dapp/src/compat/index.ts
Normal file
11
packages/extension-dapp/src/compat/index.ts
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2019 @polkadot/extension-dapp authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import singleSource from './singleSource';
|
||||
|
||||
export default function initCompat (): Promise<boolean> {
|
||||
return Promise.all([
|
||||
singleSource()
|
||||
]).then(() => true);
|
||||
}
|
||||
69
packages/extension-dapp/src/compat/singleSource.ts
Normal file
69
packages/extension-dapp/src/compat/singleSource.ts
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright 2019 @polkadot/extension-dapp authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { Signer } from '@polkadot/api/types';
|
||||
import { InjectedAccount, InjectedWindow } from '../types';
|
||||
|
||||
// RxJs interface, only what we need here
|
||||
type Subscriber<T> = {
|
||||
subscribe: (cb: (value: Array<T>) => void) => void
|
||||
};
|
||||
|
||||
type SingleSourceAccount = {
|
||||
address: string,
|
||||
assets: Array<{ assetId: number }>,
|
||||
name: string
|
||||
};
|
||||
|
||||
type SingleSource = {
|
||||
accounts$: Subscriber<SingleSourceAccount>,
|
||||
environment$: Subscriber<string>,
|
||||
signer: Signer
|
||||
};
|
||||
|
||||
type SingleWindow = Window & InjectedWindow & {
|
||||
SingleSource: SingleSource
|
||||
};
|
||||
|
||||
// add a compat interface of SingleSource to window.injectedWeb3
|
||||
function injectSingleSource (win: SingleWindow): void {
|
||||
let accounts: Array<InjectedAccount> = [];
|
||||
|
||||
// we don't yet have an accounts subscribe on the interface, simply get the
|
||||
// accounts and store them, any get will resolve the last found values
|
||||
win.SingleSource.accounts$.subscribe((_accounts) => {
|
||||
accounts = _accounts.map(({ address, name }) => ({
|
||||
address,
|
||||
name
|
||||
}));
|
||||
});
|
||||
|
||||
// decorate the compat interface
|
||||
win.injectedWeb3['SingleSource'] = {
|
||||
enable: async (origin: string) => ({
|
||||
accounts: {
|
||||
get: async () => accounts
|
||||
},
|
||||
signer: win.SingleSource.signer
|
||||
}),
|
||||
version: '0.0.0'
|
||||
};
|
||||
}
|
||||
|
||||
// returns the SingleSource instance, as per
|
||||
// https://github.com/cennznet/singlesource-extension/blob/f7cb35b54e820bf46339f6b88ffede1b8e140de0/react-example/src/App.js#L19
|
||||
export default function initSingleSource (): Promise<boolean> {
|
||||
return new Promise((resolve) => {
|
||||
window.addEventListener('load', () => {
|
||||
const win = window as SingleWindow;
|
||||
|
||||
if (win.SingleSource) {
|
||||
injectSingleSource(win);
|
||||
resolve(true);
|
||||
} else {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -4,11 +4,22 @@
|
||||
|
||||
import { InjectedAccountWithMeta, InjectedExtension, InjectedExtensionInfo, InjectedWindow } from './types';
|
||||
|
||||
// our extension adaptor for other kinds of extensions
|
||||
import compatInjector from './compat';
|
||||
|
||||
// just a helper (otherwise we cast all-over, so shorter and more readable)
|
||||
const injectedWeb3 = (window as InjectedWindow).injectedWeb3 || {};
|
||||
const win = window as InjectedWindow;
|
||||
|
||||
// don't clobber the existing object, but ensure non-undefined
|
||||
win.injectedWeb3 = win.injectedWeb3 || {};
|
||||
|
||||
// true when anything has been injected and is available
|
||||
function web3IsInjected (): boolean {
|
||||
return Object.keys(win.injectedWeb3).length !== 0;
|
||||
}
|
||||
|
||||
// have we found a properly constructed window.injectedWeb3
|
||||
const isWeb3Injected = Object.keys(injectedWeb3).length !== 0;
|
||||
let isWeb3Injected = web3IsInjected();
|
||||
|
||||
// we keep the last promise created around (for queries)
|
||||
let web3EnablePromise: Promise<Array<InjectedExtension>> | null = null;
|
||||
@ -17,29 +28,27 @@ export { isWeb3Injected, web3EnablePromise };
|
||||
|
||||
// enables all the providers found on the injected window interface
|
||||
export function web3Enable (originName: string): Promise<Array<InjectedExtension>> {
|
||||
web3EnablePromise = Promise
|
||||
.all(
|
||||
Object
|
||||
.entries(injectedWeb3)
|
||||
.map(([name, { enable, version }]) =>
|
||||
Promise
|
||||
.all([Promise.resolve({ name, version }), enable(originName)])
|
||||
.catch(() => [{ name, version }, null] as [InjectedExtensionInfo, null])
|
||||
)
|
||||
web3EnablePromise = compatInjector().then(() =>
|
||||
Promise.all(
|
||||
Object.entries(win.injectedWeb3).map(([name, { enable, version }]) =>
|
||||
Promise
|
||||
.all([Promise.resolve({ name, version }), enable(originName)])
|
||||
.catch(() => [{ name, version }, null] as [InjectedExtensionInfo, null])
|
||||
)
|
||||
)
|
||||
.then((values) =>
|
||||
values
|
||||
.filter(([, ext]) => ext !== null)
|
||||
.map(([info, ext]) => ({ ...info, ...ext } as InjectedExtension))
|
||||
values.filter(([, ext]) => ext).map(([info, ext]) => ({ ...info, ...ext } as InjectedExtension))
|
||||
)
|
||||
.catch(() => [] as Array<InjectedExtension>)
|
||||
.then((values) => {
|
||||
const names = values.map(({ name, version }) => `${name}/${version}`);
|
||||
|
||||
isWeb3Injected = web3IsInjected();
|
||||
console.log(`web3Enable: Enabled ${values.length} extensions ${names.join(', ')}`);
|
||||
|
||||
return values;
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
return web3EnablePromise;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user