Skip to content

Commit

Permalink
dapp: add availability field to connections
Browse files Browse the repository at this point in the history
Ethereum connections can be available or not. For the moment is
especially the case for the injected provider connection. This adds that
field to all kind of connections. This allows to visually inform the
user that a connection is not available or just hide it.
The field can be statically controlled (e.g. via a configuration option)
or dynamically evaluated (e.g. for the injected provider).
  • Loading branch information
weilbith committed May 10, 2021
1 parent 4d1d75f commit 1b867e8
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { EthereumConnection } from './types';

export class DirectRpcProvider extends EthereumConnection {
public static readonly connection_name = 'direct_rpc_provider';
public static readonly isAvailable = true;
public readonly provider: providers.JsonRpcProvider;
public readonly account: string;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@ export class InjectedProvider extends EthereumConnection {
public readonly provider: providers.JsonRpcProvider;
public readonly account = 0; // Refers to the currently selected account in the wallet.

public static get isAvailable(): boolean {
return !!window.ethereum || !!window.web3;
}

private constructor(injetedProvider: providers.ExternalProvider) {
super();
this.provider = new providers.Web3Provider(injetedProvider);
}

public static async connect(): Promise<InjectedProvider> {
if (!window.ethereum && !window.web3) {
// We can't use the check of the super constructor here, else this function does not work.
if (!InjectedProvider.isAvailable) {
throw new Error('No injected provider is available.');
}

Expand Down
9 changes: 9 additions & 0 deletions raiden-dapp/src/services/ethereum-connection/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,16 @@ import type { providers } from 'ethers';

export abstract class EthereumConnection {
static connection_name: string;
static isAvailable = false;
static connect: (options?: any) => Promise<EthereumConnection>; // eslint-disable-line @typescript-eslint/no-explicit-any
abstract provider: providers.JsonRpcProvider;
abstract account: string | number;

constructor() {
const isAvailable = (this.constructor as typeof EthereumConnection).isAvailable;

if (!isAvailable) {
throw new Error('The connection is not available.');
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { EthereumConnection } from './types';

export class WalletConnect extends EthereumConnection {
public static readonly connection_name = 'wallet_connect';
public static readonly isAvailable = true;
public readonly provider: providers.JsonRpcProvider;
public readonly account = 0; // Refers to the currently selected account in the wallet.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { DirectRpcProvider } from '@/services/ethereum-connection/direct-rpc-provider';

describe('DirectRpcProvider', () => {
test('is always available', () => {
expect(DirectRpcProvider.isAvailable).toBe(true);
});

test('it can connect', async () => {
const options = { rpcUrl: 'https://some.rpc.provider', privateKey: 'privateKey' };
const connection = await DirectRpcProvider.connect(options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,31 @@ jest.mock('ethers', () => {
};
});

const originalWindow = window;

describe('InjectedProvider', () => {
beforeEach(() => {
window = originalWindow;
window.ethereum = undefined;
window.web3 = undefined;
jest.clearAllMocks();
jest.resetAllMocks();
});

test('connect throws error if no injected provider is available', () => {
expect(window.ethereum).toBeUndefined();
expect(window.web3).toBeUndefined();
test('is not available when no injected provider is available', () => {
expect(InjectedProvider.isAvailable).toBe(false);
});

test('is available when ethereum provider is available', () => {
window.ethereum = new MockedJsonRpcProviderWithRequestHandler();

expect(InjectedProvider.isAvailable).toBe(true);
});

test('is available when web3 provider is available', () => {
window.web3 = { currentProvider: new MockedJsonRpcProvider() };

expect(InjectedProvider.isAvailable).toBe(true);
});

test('connect throws error if no injected provider is available', () => {
expect(InjectedProvider.connect()).rejects.toThrow('No injected provider is available.');
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ jest.mock('ethers', () => {
});

describe('WalletConnect', () => {
test('is always available', () => {
expect(WalletConnect.isAvailable).toBe(true);
});

test('fail to connect when none of the options is provided', () => {
expect(WalletConnect.connect({})).rejects.toThrow(
'One of the options RPC URL or Infura Id are required to connect.',
Expand Down

0 comments on commit 1b867e8

Please sign in to comment.