Skip to content

Add metamask extension web3 #566

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 40 commits into from
Sep 3, 2021
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
4c8b1c8
added web3source
joelamouche Dec 8, 2020
a98b814
tried fixing dependencies
joelamouche Dec 8, 2020
a956347
removed load event listener and added name
joelamouche Dec 8, 2020
2d44686
add signer to interface
joelamouche Dec 10, 2020
f8c01a2
Merge branch 'master' into jlm-add-metamask-extension-web3
joelamouche Dec 10, 2020
f056a53
added signPayload draft
joelamouche Dec 10, 2020
42bf1fd
lint
joelamouche Dec 10, 2020
966c6db
modified signpayload
joelamouche Dec 10, 2020
b3ff173
switch back to only signRaw
joelamouche Dec 10, 2020
6303215
sync with master and update to new metamask norm
joelamouche May 5, 2021
a1f12b9
add types to injecetd accounts
joelamouche May 6, 2021
e275ad3
update deps
joelamouche May 7, 2021
6ff55de
hash tx and finalize code
joelamouche May 10, 2021
e8dc31c
lint and type
joelamouche May 10, 2021
83b02de
sync with master
joelamouche May 11, 2021
e40bcce
sync with master
joelamouche May 31, 2021
02c1543
iterate on feedback
joelamouche Jun 1, 2021
034ce08
lint index.ts
joelamouche Jun 1, 2021
0ca3c18
prettier lint index.ts
joelamouche Jun 1, 2021
40cc504
Merge branch 'jlm-lint-extension' into jlm-add-metamask-extension-web3
joelamouche Jun 1, 2021
2f590e6
type optional again
joelamouche Jun 1, 2021
786cdb9
Merge branch 'jlm-add-metamask-extension-web3' of github.com:PureStak…
joelamouche Jun 1, 2021
ba312be
removed sigenr from injected account type
joelamouche Jun 21, 2021
6081cef
sync with master
joelamouche Jun 21, 2021
1314d64
lint
joelamouche Jun 21, 2021
26f14eb
sync with master
joelamouche Jul 5, 2021
7bbb18b
wip remove web3
joelamouche Jul 7, 2021
74da34f
remove laod event
joelamouche Jul 8, 2021
3ba0757
sync
joelamouche Jul 12, 2021
e91483f
update packages
joelamouche Jul 23, 2021
d9822ed
Update packages/extension-dapp/src/compat/metaMaskSource.ts
joelamouche Aug 23, 2021
58188be
Update packages/extension-dapp/src/compat/metaMaskSource.ts
joelamouche Aug 23, 2021
a68bc59
filter accounts by type
joelamouche Aug 23, 2021
a312bf4
sync with master
joelamouche Aug 23, 2021
b8ee32c
lint
joelamouche Aug 23, 2021
5d315b3
fix type typing
joelamouche Aug 24, 2021
88b707c
Update packages/extension-dapp/src/index.ts
joelamouche Aug 25, 2021
bbf0627
filter by array of type, instead of single type
joelamouche Aug 25, 2021
3e046a9
sync with master
joelamouche Aug 26, 2021
846d274
sync with master
joelamouche Sep 2, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/extension-base/src/background/handlers/Tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function transformAccounts (accounts: SubjectInfo, anyType = false): InjectedAcc
address,
genesisHash,
name,
type
type: type || undefined
}));
}

Expand Down
4 changes: 3 additions & 1 deletion packages/extension-dapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
"sideEffects": false,
"dependencies": {
"@babel/runtime": "^7.14.6",
"@metamask/detect-provider": "^1.2.0",
"@polkadot/extension-inject": "^0.39.2-0",
"@polkadot/util": "^7.0.2",
"@polkadot/util-crypto": "^7.0.2"
"@polkadot/util-crypto": "^7.0.2",
"web3": "^1.3.0"
},
"peerDependencies": {
"@polkadot/api": "*",
Expand Down
8 changes: 6 additions & 2 deletions packages/extension-dapp/src/compat/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
// Copyright 2019-2021 @polkadot/extension-dapp authors & contributors
// SPDX-License-Identifier: Apache-2.0

import initMetaMaskSource from './metaMaskSource';
import singleSource from './singleSource';

// initialize all the compatibility engines
export default function initCompat (): Promise<boolean> {
return Promise.all([
singleSource()
]).then((): boolean => true);
singleSource(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note-to-self: After this can drop the singleSource. It was always great as a reference, but now that we have a proper reference available here, not needed anymore.

initMetaMaskSource()
]).then((): boolean => {
return true;
});
}
100 changes: 100 additions & 0 deletions packages/extension-dapp/src/compat/metaMaskSource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright 2019-2020 @polkadot/extension-dapp authors & contributors
// SPDX-License-Identifier: Apache-2.0

import type { Injected, InjectedAccount, InjectedWindow } from '@polkadot/extension-inject/types';

import detectEthereumProvider from '@metamask/detect-provider';
import Web3 from 'web3';

import { SignerPayloadRaw, SignerResult } from '@polkadot/types/types';

interface RequestArguments {
method: string;
params?: unknown[];
}

interface EthRpcSubscription {
unsubscribe: () => void
}

interface EthereumProvider {
request: (args: RequestArguments) => Promise<any>;
isMetaMask: boolean;
on: (name: string, cb: any) => EthRpcSubscription;
}

interface Web3Window extends InjectedWindow {
// this is injected by metaMask
ethereum: any;
}

function isMetaMaskProvider (prov: unknown): EthereumProvider {
if (prov !== null) {
return (prov as EthereumProvider);
} else {
throw new Error('Injected provider is not MetaMask');
}
}

// transfor the Web3 accounts into a simple address/name array
function transformAccounts (accounts: string[]): InjectedAccount[] {
return accounts.map((acc, i) => {
return { address: acc, name: 'MetaMask Address #' + i.toString(), type: 'ethereum' };
});
}

// add a compat interface of metaMaskSource to window.injectedWeb3
function injectMetaMaskWeb3 (win: Web3Window): void {
// decorate the compat interface
win.injectedWeb3.Web3Source = {
enable: async (): Promise<Injected> => {
// win.web3 = new Web3(win.ethereum);

const providerRaw: unknown = await detectEthereumProvider({ mustBeMetaMask: true });
const provider: EthereumProvider = isMetaMaskProvider(providerRaw);

await provider.request({ method: 'eth_requestAccounts' });

return {
accounts: {
get: async (): Promise<InjectedAccount[]> => {
return transformAccounts(await provider.request({ method: 'eth_requestAccounts' }));
},
subscribe: (cb: (accounts: InjectedAccount[]) => void): (() => void) => {
const sub = provider.on('accountsChanged', function (accounts: string[]) {
cb(transformAccounts(accounts));
});
// TODO: add onchainchanged

return (): void => {
sub.unsubscribe();
};
}
},
signer: {
signRaw: async (raw: SignerPayloadRaw): Promise<SignerResult> => {
const signature = (await provider.request({ method: 'eth_sign', params: [raw.address, Web3.utils.sha3(raw.data)] })as string);

return { id: 0, signature };
}
}
};
},
version: '0' // TODO: win.ethereum.version
};
}

// returns the MetaMask source instance, as per
// https://github.com/cennznet/singlesource-extension/blob/f7cb35b54e820bf46339f6b88ffede1b8e140de0/react-example/src/App.js#L19
export default function initMetaMaskSource (): Promise<boolean> {
return new Promise((resolve): void => {
const win = window as Window & Web3Window;

if (win.ethereum) {
injectMetaMaskWeb3(win);
resolve(true);
} else {
resolve(false);
}
});
}
18 changes: 8 additions & 10 deletions packages/extension-dapp/src/compat/singleSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ interface SingleWindow extends InjectedWindow {
SingleSource: SingleSource;
}

// transfor the SingleSource accounts into a simple address/name array
// transform the SingleSource accounts into a simple address/name array
function transformAccounts (accounts: SingleSourceAccount[]): InjectedAccount[] {
return accounts.map(({ address, name }): InjectedAccount => ({
address,
Expand Down Expand Up @@ -73,15 +73,13 @@ function injectSingleSource (win: SingleWindow): void {
// https://github.com/cennznet/singlesource-extension/blob/f7cb35b54e820bf46339f6b88ffede1b8e140de0/react-example/src/App.js#L19
export default function initSingleSource (): Promise<boolean> {
return new Promise((resolve): void => {
window.addEventListener('load', (): void => {
const win = window as Window & SingleWindow;
const win = window as Window & SingleWindow;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Believe I commented elsewhere - the original is correct. (All ok, since this will be dropped anyway)


if (win.SingleSource) {
injectSingleSource(win);
resolve(true);
} else {
resolve(false);
}
});
if (win.SingleSource) {
injectSingleSource(win);
resolve(true);
} else {
resolve(false);
}
});
}
Loading