Skip to content
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

feat: add createExternalExtensionProvider #152

Merged
merged 4 commits into from
May 3, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
150 changes: 0 additions & 150 deletions index.d.ts

This file was deleted.

1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports = {
// statements: 100,
// },
// },
setupFilesAfterEnv: ['./jest.setup.js'],
moduleFileExtensions: ['js'],
silent: true,
testEnvironment: 'jsdom',
Expand Down
1 change: 1 addition & 0 deletions jest.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Object.assign(global, require('jest-chrome'));
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,16 @@
"dependencies": {
"@metamask/object-multiplex": "^1.1.0",
"@metamask/safe-event-emitter": "^2.0.0",
"@types/chrome": "^0.0.136",
"detect-browser": "^5.2.0",
"eth-rpc-errors": "^4.0.2",
"extension-port-stream": "^2.0.1",
"fast-deep-equal": "^2.0.1",
"is-stream": "^2.0.0",
"json-rpc-engine": "^6.1.0",
"json-rpc-middleware-stream": "^3.0.0",
"pump": "^3.0.0"
"pump": "^3.0.0",
"webextension-polyfill-ts": "^0.25.0"
},
"devDependencies": {
"@metamask/eslint-config": "^6.0.0",
Expand All @@ -58,13 +62,14 @@
"@typescript-eslint/eslint-plugin": "^4.10.0",
"@typescript-eslint/parser": "^4.10.0",
"eslint": "^7.15.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-jest": "^23.18.0",
"eslint-plugin-json": "^2.0.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.4.0",
"eslint-config-prettier": "^8.1.0",
"jest": "^26.6.3",
"jest-chrome": "^0.7.1",
"prettier": "^2.2.1",
"typescript": "^4.1.3"
}
Expand Down
4 changes: 2 additions & 2 deletions src/BaseProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export interface BaseProviderState {
export interface JsonRpcConnection {
events: SafeEventEmitter;
middleware: JsonRpcMiddleware<unknown, unknown>;
stream: _Readable.Duplex;
stream: Duplex;
}

export default class BaseProvider extends SafeEventEmitter {
Expand Down Expand Up @@ -112,7 +112,7 @@ export default class BaseProvider extends SafeEventEmitter {
* listeners. Default: 100
*/
constructor(
connectionStream: typeof Duplex,
connectionStream: Duplex,
{
jsonRpcStreamName = 'metamask-provider',
logger = console,
Expand Down
2 changes: 1 addition & 1 deletion src/MetaMaskInpageProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export default class MetaMaskInpageProvider extends BaseProvider {
* send page metadata. Default: true
*/
constructor(
connectionStream: typeof Duplex,
connectionStream: Duplex,
{
jsonRpcStreamName = 'metamask-provider',
logger = console,
Expand Down
34 changes: 34 additions & 0 deletions src/createMetaMaskExternalExtensionProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import PortStream from 'extension-port-stream';
import { detect } from 'detect-browser';
import { Runtime } from 'webextension-polyfill-ts';
import MetaMaskInpageProvider from './MetaMaskInpageProvider';
import config from './external-extension-config.json';

const browser = detect();

export default function createMetaMaskExternalExtensionProvider() {
let provider;
try {
const currentMetaMaskId = getMetaMaskId();
const metamaskPort = chrome.runtime.connect(
currentMetaMaskId,
) as Runtime.Port;
Copy link
Contributor Author

@shanejonas shanejonas Apr 30, 2021

Choose a reason for hiding this comment

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

I have to cast this to play nicely with the webextension-polyfill-ts type that extension-port-stream uses, doesnt seem to match exactly to the type chrome.runtime.connect returns which is a chrome.runtime.Port

Copy link
Member

Choose a reason for hiding this comment

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

Makes sense. Port- and stream-related types seem to be incompatible 100% of the time.

const pluginStream = new PortStream(metamaskPort);
provider = new MetaMaskInpageProvider(pluginStream);
} catch (e) {
console.dir(`Metamask connect error `, e);
throw e;
}
return provider;
}

function getMetaMaskId() {
switch (browser?.name) {
case 'chrome':
return config.CHROME_ID;
case 'firefox':
return config.FIREFOX_ID;
default:
return config.CHROME_ID;
}
}
4 changes: 4 additions & 0 deletions src/external-extension-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"CHROME_ID": "nkbihfbeogaeaoehlefnkodbefgpgknn",
"FIREFOX_ID": "[email protected]"
}
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import MetaMaskInpageProvider from './MetaMaskInpageProvider';
import createMetaMaskExternalExtensionProvider from './createMetaMaskExternalExtensionProvider';
import BaseProvider from './BaseProvider';
import {
initializeProvider,
Expand All @@ -12,4 +13,5 @@ export {
BaseProvider,
setGlobalProvider,
shimWeb3,
createMetaMaskExternalExtensionProvider,
};
2 changes: 1 addition & 1 deletion src/initializeInpageProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface InitializeProviderOptions extends MetaMaskInpageProviderOptions {
/**
* The stream used to connect to the wallet.
*/
connectionStream: typeof Duplex;
connectionStream: Duplex;

/**
* Whether the provider should be set as window.ethereum.
Expand Down
34 changes: 34 additions & 0 deletions test/createMetaMaskExternalExtensionProvider.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const {
createMetaMaskExternalExtensionProvider,
MetaMaskInpageProvider,
} = require('../dist');

describe('createMetaMaskExternalExtensionProvider', () => {
beforeAll(() => {
global.chrome.runtime.connect.mockImplementation(() => {
return {
onMessage: {
addListener: jest.fn(),
},
onDisconnect: {
addListener: jest.fn(),
},
postMessage: jest.fn(),
};
});
});
afterAll(() => {
jest.restoreAllMocks();
});
it('can be called and not throw', () => {
expect(() => createMetaMaskExternalExtensionProvider()).not.toThrow();
});
it('calls connect', () => {
createMetaMaskExternalExtensionProvider();
expect(global.chrome.runtime.connect).toHaveBeenCalled();
});
it('returns a MetaMaskInpageProvider', () => {
const results = createMetaMaskExternalExtensionProvider();
expect(results).toBeInstanceOf(MetaMaskInpageProvider);
});
});
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"esModuleInterop": true,
"module": "CommonJS",
"moduleResolution": "node",
"resolveJsonModule": true,
"outDir": "dist",
"sourceMap": true,
"strict": true,
Expand Down
Loading