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: CP-9360 wallet selector rework #68

Merged
merged 11 commits into from
Nov 4, 2024
174 changes: 69 additions & 105 deletions src/background/providers/MultiWalletProviderProxy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ import { EIP6963ProviderInfo } from '@avalabs/vm-module-types';

jest.mock('../utils/messaging/AutoPairingPostMessageConnection');
jest.mock('@avalabs/evm-module/dist/provider', () => ({
EVMProvider: jest.fn().mockImplementation(() => ({
isAvalanche: true,
isMetaMask: true,
EVMProvider: jest.fn().mockImplementation(({ info, ...rest }) => ({
isAvalanche: info.uuid ? false : true,
removeAllListeners: jest.fn(),
info: {
...info,
uuid: info.uuid ?? 'default-uuid',
},
...rest,
})),
}));

Expand Down Expand Up @@ -51,97 +55,84 @@ describe('src/background/providers/MultiWalletProviderProxy', () => {
});

describe('addProvider', () => {
it('adds new providers from coinbase proxy', () => {
it('should add new providers', () => {
const provider = new EVMProvider({ info: providerInfo });
const mwpp = new MultiWalletProviderProxy(provider);

expect(mwpp.defaultProvider).toBe(provider);
expect(mwpp.providers).toStrictEqual([provider]);

const mockProvider = {
providerMap: new Map([
['core', provider],
['otherprovider', { isMetaMask: true }],
['thirdprovider', { isRabby: true }],
] as any),
};
const provider2 = new EVMProvider({
info: { ...providerInfo, uuid: 'uuid-2' },
});
const provider3 = new EVMProvider({
info: { ...providerInfo, uuid: 'uuid-3' },
});

mwpp.addProvider(mockProvider);
mwpp.addProvider(provider2);
mwpp.addProvider(provider3);

expect(mwpp.defaultProvider).toBe(provider);
expect(mwpp.providers).toEqual([
mwpp,
{ isMetaMask: true },
{ isRabby: true },
]);

expect((mwpp.providers[0] as any).isMetaMask).toBeTruthy();
expect((mwpp.providers[0] as any).info.uuid).toBe(EVM_PROVIDER_INFO_UUID);
expect((mwpp.providers[1] as any).info.uuid).toBe('uuid-2');
expect((mwpp.providers[2] as any).info.uuid).toBe('uuid-3');
});

it('does not add extra coinbase proxy', () => {
it('should not add a new provider because it has been already registered', () => {
const provider = new EVMProvider({ info: providerInfo });
const mwpp = new MultiWalletProviderProxy(provider);

expect(mwpp.defaultProvider).toBe(provider);
expect(mwpp.providers).toStrictEqual([provider]);

const mockProvider = {
coinbaseWalletInstalls: {},
};

mwpp.addProvider(mockProvider);

expect(mwpp.defaultProvider).toBe(provider);
expect(mwpp.providers).toStrictEqual([provider]);
});

it('adds new provider', () => {
const provider = new EVMProvider({ info: providerInfo });
const mwpp = new MultiWalletProviderProxy(provider);

expect(mwpp.defaultProvider).toBe(provider);
expect(mwpp.providers).toStrictEqual([provider]);

const mockProvider = { isMetaMask: true };

mwpp.addProvider(mockProvider);
const provider2 = new EVMProvider({
info: { ...providerInfo, uuid: 'uuid-2' },
});
const provider3 = new EVMProvider({
info: { ...providerInfo, uuid: 'uuid-2' },
});
mwpp.addProvider(provider2);
mwpp.addProvider(provider3);

expect(mwpp.defaultProvider).toBe(provider);
expect(mwpp.providers).toEqual([mwpp, mockProvider]);
expect(mwpp.providers.length as any).toBe(2);
expect((mwpp.providers[0] as any).info.uuid).toBe(EVM_PROVIDER_INFO_UUID);
expect((mwpp.providers[1] as any).info.uuid).toBe('uuid-2');
});
});

describe('wallet selection', () => {
it('toggles wallet selection on `eth_requestAccounts` call if multiple providers', async () => {
const provider = new EVMProvider({ info: providerInfo });
const provider2 = { isMetaMask: true, request: jest.fn() };
const provider = new EVMProvider({
info: providerInfo,
request: jest.fn().mockResolvedValue(1),
} as any);
const provider2 = new EVMProvider({
info: { ...providerInfo, uuid: 'uuid-2' },
isMetaMask: true,
request: jest.fn().mockResolvedValue(2),
} as any);

const mwpp = new MultiWalletProviderProxy(provider);
mwpp.addProvider(provider2);

// user selects metamask
provider.request = jest.fn().mockResolvedValue(1);
provider2.request.mockResolvedValue(['0x000000']);

const requestAccountsCallback = jest.fn();
mwpp
.request({ method: 'eth_requestAccounts' })
.then(requestAccountsCallback);

expect(requestAccountsCallback).not.toHaveBeenCalled();

expect(provider2.request).not.toHaveBeenCalled();
expect(provider.request).toHaveBeenCalledTimes(1);

expect(provider.request).toHaveBeenCalledWith({
method: 'avalanche_selectWallet',
params: [
[
{
index: 0,
type: 'CORE',
info: providerInfo,
},
{
index: 1,
type: 'METAMASK',
info: { ...providerInfo, uuid: 'uuid-2' },
},
],
],
Expand All @@ -152,10 +143,9 @@ describe('src/background/providers/MultiWalletProviderProxy', () => {
expect(provider2.request).toHaveBeenCalledWith({
method: 'eth_requestAccounts',
});

await new Promise(process.nextTick);
expect(requestAccountsCallback).toHaveBeenCalledTimes(1);
expect(requestAccountsCallback).toHaveBeenCalledWith(['0x000000']);
expect(requestAccountsCallback).toHaveBeenCalledWith(2);
expect(mwpp.defaultProvider).toBe(provider2);
});

Expand Down Expand Up @@ -184,7 +174,10 @@ describe('src/background/providers/MultiWalletProviderProxy', () => {

it('does not toggle wallet selection if wallet is already selected', async () => {
const provider = new EVMProvider({ info: providerInfo });
const provider2 = { isMetaMask: true, request: jest.fn() };
const provider2 = new EVMProvider({
info: { ...providerInfo, uuid: 'uuid-2' },
request: jest.fn(),
} as any);
const mwpp = new MultiWalletProviderProxy(provider);
mwpp.addProvider(provider2);

Expand All @@ -209,11 +202,11 @@ describe('src/background/providers/MultiWalletProviderProxy', () => {
[
{
index: 0,
type: 'CORE',
info: providerInfo,
},
{
index: 1,
type: 'METAMASK',
info: { ...providerInfo, uuid: 'uuid-2' },
},
],
],
Expand All @@ -240,13 +233,15 @@ describe('src/background/providers/MultiWalletProviderProxy', () => {

it('wallet selection works with legacy functions: enable', async () => {
const provider = new EVMProvider({ info: providerInfo });
const provider2 = { isMetaMask: true, enable: jest.fn() };
const provider2 = new EVMProvider({
info: { ...providerInfo, uuid: 'uuid-2' },
enable: jest.fn().mockResolvedValue(['0x000000']),
} as any);
const mwpp = new MultiWalletProviderProxy(provider);
mwpp.addProvider(provider2);

// user selects metamask
provider.request = jest.fn().mockResolvedValue(1);
provider2.enable.mockResolvedValue(['0x000000']);

const requestAccountsCallback = jest.fn();
mwpp.enable().then(requestAccountsCallback);
Expand All @@ -261,11 +256,11 @@ describe('src/background/providers/MultiWalletProviderProxy', () => {
[
{
index: 0,
type: 'CORE',
info: providerInfo,
},
{
index: 1,
type: 'METAMASK',
info: { ...providerInfo, uuid: 'uuid-2' },
},
],
],
Expand All @@ -282,13 +277,15 @@ describe('src/background/providers/MultiWalletProviderProxy', () => {

it('wallet selection works with legacy functions: sendAsync', async () => {
const provider = new EVMProvider({ info: providerInfo });
const provider2 = { isMetaMask: true, request: jest.fn() };
const provider2 = new EVMProvider({
info: { ...providerInfo, uuid: 'uuid-2' },
request: jest.fn().mockResolvedValue(['0x000000']),
} as any);
const mwpp = new MultiWalletProviderProxy(provider);
mwpp.addProvider(provider2);

// user selects metamask
provider.request = jest.fn().mockResolvedValue(1);
provider2.request.mockResolvedValue(['0x000000']);

const requestAccountsCallback = jest.fn();
mwpp.sendAsync(
Expand All @@ -310,11 +307,11 @@ describe('src/background/providers/MultiWalletProviderProxy', () => {
[
{
index: 0,
type: 'CORE',
info: providerInfo,
},
{
index: 1,
type: 'METAMASK',
info: { ...providerInfo, uuid: 'uuid-2' },
},
],
],
Expand All @@ -336,13 +333,15 @@ describe('src/background/providers/MultiWalletProviderProxy', () => {

it('wallet selection works with legacy functions: send with callback', async () => {
const provider = new EVMProvider({ info: providerInfo });
const provider2 = { isMetaMask: true, request: jest.fn() };
const provider2 = new EVMProvider({
info: { ...providerInfo, uuid: 'uuid-2' },
request: jest.fn().mockResolvedValue(['0x000000']),
} as any);
const mwpp = new MultiWalletProviderProxy(provider);
mwpp.addProvider(provider2);

// user selects metamask
provider.request = jest.fn().mockResolvedValue(1);
provider2.request.mockResolvedValue(['0x000000']);

const requestAccountsCallback = jest.fn();
mwpp.send(
Expand All @@ -360,11 +359,11 @@ describe('src/background/providers/MultiWalletProviderProxy', () => {
[
{
index: 0,
type: 'CORE',
info: providerInfo,
},
{
index: 1,
type: 'METAMASK',
info: { ...providerInfo, uuid: 'uuid-2' },
},
],
],
Expand Down Expand Up @@ -418,40 +417,5 @@ describe('src/background/providers/MultiWalletProviderProxy', () => {

expect((mwpp as any).defaultProvider).toBe(provider);
});

it('maintains the providers list properly', () => {
const provider = new EVMProvider({ info: providerInfo });
const mwpp = createMultiWalletProxy(provider);
const fooMock = () => 'bar';
const bizMock = () => 'baz';

const mockProvider = {
providerMap: new Map([
['core', provider],
['otherprovider', { isMetaMask: true, foo: fooMock }],
['thirdprovider', { isRabby: true, biz: bizMock }],
] as any),
};

mwpp.addProvider(mockProvider);

expect((mwpp.providers[0] as any).isMetaMask).toBe(true);
expect((mwpp.providers[0] as any).isAvalanche).toBe(true);
expect((mwpp.providers[0] as any).someUndefinedProperty).toBe(undefined);
expect((mwpp.providers[0] as any)['#isWalletSelected']).toBe(undefined);

expect(mwpp.providers[1] as any).toEqual({
isMetaMask: true,
isAvalanche: undefined,
foo: fooMock,
});

expect(mwpp.providers[2] as any).toEqual({
isMetaMask: undefined,
isAvalanche: undefined,
isRabby: true,
biz: bizMock,
});
});
});
});
Loading
Loading