diff --git a/src/background/providers/MultiWalletProviderProxy.test.ts b/src/background/providers/MultiWalletProviderProxy.test.ts
index eee474bc..1ba269d5 100644
--- a/src/background/providers/MultiWalletProviderProxy.test.ts
+++ b/src/background/providers/MultiWalletProviderProxy.test.ts
@@ -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,
})),
}));
@@ -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' },
},
],
],
@@ -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);
});
@@ -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);
@@ -209,11 +202,11 @@ describe('src/background/providers/MultiWalletProviderProxy', () => {
[
{
index: 0,
- type: 'CORE',
+ info: providerInfo,
},
{
index: 1,
- type: 'METAMASK',
+ info: { ...providerInfo, uuid: 'uuid-2' },
},
],
],
@@ -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);
@@ -261,11 +256,11 @@ describe('src/background/providers/MultiWalletProviderProxy', () => {
[
{
index: 0,
- type: 'CORE',
+ info: providerInfo,
},
{
index: 1,
- type: 'METAMASK',
+ info: { ...providerInfo, uuid: 'uuid-2' },
},
],
],
@@ -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(
@@ -310,11 +307,11 @@ describe('src/background/providers/MultiWalletProviderProxy', () => {
[
{
index: 0,
- type: 'CORE',
+ info: providerInfo,
},
{
index: 1,
- type: 'METAMASK',
+ info: { ...providerInfo, uuid: 'uuid-2' },
},
],
],
@@ -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(
@@ -360,11 +359,11 @@ describe('src/background/providers/MultiWalletProviderProxy', () => {
[
{
index: 0,
- type: 'CORE',
+ info: providerInfo,
},
{
index: 1,
- type: 'METAMASK',
+ info: { ...providerInfo, uuid: 'uuid-2' },
},
],
],
@@ -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,
- });
- });
});
});
diff --git a/src/background/providers/MultiWalletProviderProxy.ts b/src/background/providers/MultiWalletProviderProxy.ts
index 7eb1ce3d..ffc1a330 100644
--- a/src/background/providers/MultiWalletProviderProxy.ts
+++ b/src/background/providers/MultiWalletProviderProxy.ts
@@ -4,13 +4,12 @@ import {
JsonRpcRequestPayload,
JsonRpcResponse,
} from '../connections/dAppConnection/models';
-import { getWalletExtensionType } from './utils/getWalletExtensionType';
import { Maybe } from '@avalabs/core-utils-sdk';
import EventEmitter from 'events';
import { EVMProvider } from '@avalabs/evm-module/dist/provider';
export class MultiWalletProviderProxy extends EventEmitter {
- #_providers: unknown[] = [];
+ #_providers: EVMProvider[] = [];
#isWalletSelected = false;
#defaultProvider;
@@ -64,27 +63,13 @@ export class MultiWalletProviderProxy extends EventEmitter {
});
}
- public addProvider(provider) {
- // the COINBASE collects here the wallets
- if (provider.providerMap) {
- for (const providerProxy of provider.providerMap.values()) {
- if (
- !providerProxy.isAvalanche && // we exclude Core being duplicated
- !this.#_providers.includes(providerProxy)
- ) {
- this.#_providers.push(providerProxy);
- }
- }
- return;
- }
-
- // the coinbase would add another proxy which is useless for us
- if (provider.coinbaseWalletInstalls) {
- return;
- }
+ public addProvider(providerDetail) {
+ const isProviderAdded = this.#_providers.find((provider) => {
+ return provider.info.uuid === providerDetail.info.uuid;
+ });
- if (!this.#_providers.includes(provider)) {
- this.#_providers.push(provider);
+ if (!isProviderAdded) {
+ this.#_providers.push(providerDetail);
}
}
@@ -100,11 +85,9 @@ export class MultiWalletProviderProxy extends EventEmitter {
params: [
// using any since we don't really know what kind of provider they are
this.#_providers.map((p: any, i) => {
- const type = getWalletExtensionType(p);
-
return {
index: i,
- type,
+ info: p.info,
};
}),
],
@@ -266,7 +249,7 @@ export function createMultiWalletProxy(evmProvider: EVMProvider) {
// intercept unknow calls that are meant to be handled by the current provider
// and forward them if needed so that we don't have to implement all the custom
// functions any given wallet provider might expose
- get: (target, prop, receiver) => {
+ get: (_, prop, receiver) => {
// if the proxy has the function call it
if (proxyProvider[prop]) {
return proxyProvider[prop];
@@ -280,7 +263,7 @@ export function createMultiWalletProxy(evmProvider: EVMProvider) {
// check if the request param is an extension defined by the dApp
return Reflect.get(walletProviderExtensions, prop, receiver);
},
- set(obj, prop, value) {
+ set(_, prop, value) {
Reflect.set(walletProviderExtensions, prop, value);
return true;
},
diff --git a/src/background/providers/initializeInpageProvider.test.ts b/src/background/providers/initializeInpageProvider.test.ts
index 8cf42435..06cd4792 100644
--- a/src/background/providers/initializeInpageProvider.test.ts
+++ b/src/background/providers/initializeInpageProvider.test.ts
@@ -59,19 +59,6 @@ describe('src/background/providers/initializeInpageProvider', () => {
expect(windowMock.ethereum).toBe(mockMultiWalletProxy);
});
- it('adds other wallets to proxy when trying to set window.ethereum', () => {
- initializeProvider(connectionMock, 10, windowMock);
-
- const provider2 = { isMetaMask: true };
-
- windowMock.ethereum = provider2;
-
- expect(mockMultiWalletProxy.addProvider).toHaveBeenCalledTimes(1);
- expect(mockMultiWalletProxy.addProvider).toHaveBeenCalledWith(provider2);
-
- expect(windowMock.ethereum).toBe(mockMultiWalletProxy);
- });
-
it('dispatches ethereum#initialized event', () => {
initializeProvider(connectionMock, 10, windowMock);
@@ -132,25 +119,6 @@ describe('src/background/providers/initializeInpageProvider', () => {
});
});
- describe('EIP-5749', () => {
- it('sets window.evmproviders if not defined and adds core', () => {
- const provider = initializeProvider(connectionMock, 10, windowMock);
-
- expect(windowMock.evmproviders).toStrictEqual({ core: provider });
- });
- it('adds Core to window.evmproviders if already defined', () => {
- windowMock.evmproviders = {
- MetaMask: { isMetaMask: true },
- };
- const provider = initializeProvider(connectionMock, 10, windowMock);
-
- expect(windowMock.evmproviders).toStrictEqual({
- MetaMask: { isMetaMask: true },
- core: provider,
- });
- });
- });
-
describe('window.avalanche', () => {
it('creates the window.avalanche object', () => {
const provider = initializeProvider(connectionMock, 10, windowMock);
@@ -183,31 +151,33 @@ describe('src/background/providers/initializeInpageProvider', () => {
it('announces core provider with eip6963:announceProvider', () => {
const provider = initializeProvider(connectionMock, 10, windowMock);
- expect(windowMock.dispatchEvent).toHaveBeenCalledTimes(5);
- expect(windowMock.dispatchEvent.mock.calls[3][0].type).toEqual(
+ expect(windowMock.dispatchEvent).toHaveBeenCalledTimes(4);
+ expect(windowMock.dispatchEvent.mock.calls[2][0].type).toEqual(
'eip6963:announceProvider'
);
- expect(windowMock.dispatchEvent.mock.calls[3][0].detail).toEqual({
- info: provider.info,
- provider: provider,
- });
+ expect(windowMock.dispatchEvent.mock.calls[2][0].detail).toStrictEqual(
+ expect.objectContaining({
+ info: provider.info,
+ provider: provider,
+ })
+ );
});
it('re-announces on eip6963:requestProvider', () => {
initializeProvider(connectionMock, 10, windowMock);
- expect(windowMock.dispatchEvent).toHaveBeenCalledTimes(5);
+ expect(windowMock.dispatchEvent).toHaveBeenCalledTimes(4);
- expect(windowMock.addEventListener).toHaveBeenCalledTimes(2);
+ expect(windowMock.addEventListener).toHaveBeenCalledTimes(3);
expect(windowMock.addEventListener).toHaveBeenCalledWith(
'eip6963:requestProvider',
expect.anything()
);
- windowMock.addEventListener.mock.calls[0][1]();
+ windowMock.addEventListener.mock.calls[1][1]();
- expect(windowMock.dispatchEvent).toHaveBeenCalledTimes(6);
+ expect(windowMock.dispatchEvent).toHaveBeenCalledTimes(5);
- expect(windowMock.dispatchEvent.mock.calls[3][0].type).toEqual(
+ expect(windowMock.dispatchEvent.mock.calls[2][0].type).toEqual(
'eip6963:announceProvider'
);
});
@@ -216,14 +186,7 @@ describe('src/background/providers/initializeInpageProvider', () => {
it('should announce chainagnostic provider with core-wallet:announceProvider', () => {
initializeProvider(connectionMock, 10, windowMock);
- expect(windowMock.dispatchEvent.mock.calls[4][0].type).toEqual(
- 'core-wallet:announceProvider'
- );
- });
- it('should re-announce on core-wallet:requestProvider', () => {
- initializeProvider(connectionMock, 10, windowMock);
-
- expect(windowMock.dispatchEvent.mock.calls[4][0].type).toEqual(
+ expect(windowMock.dispatchEvent.mock.calls[3][0].type).toEqual(
'core-wallet:announceProvider'
);
});
diff --git a/src/background/providers/initializeInpageProvider.ts b/src/background/providers/initializeInpageProvider.ts
index 7cc6c835..d4b76f9d 100644
--- a/src/background/providers/initializeInpageProvider.ts
+++ b/src/background/providers/initializeInpageProvider.ts
@@ -44,10 +44,25 @@ export function initializeProvider(
deleteProperty: () => true,
}
);
+ const multiWalletProxy = createMultiWalletProxy(evmProvider);
+
+ globalObject.addEventListener('eip6963:announceProvider', (event: any) => {
+ multiWalletProxy.addProvider(
+ new Proxy(
+ {
+ info: { ...event.detail.info },
+ ...event.detail.provider,
+ },
+ {
+ deleteProperty: () => true,
+ set: () => true,
+ }
+ )
+ );
+ });
- setGlobalProvider(evmProvider, globalObject);
+ setGlobalProvider(evmProvider, globalObject, multiWalletProxy);
setAvalancheGlobalProvider(evmProvider, globalObject);
- setEvmproviders(evmProvider, globalObject);
announceWalletProvider(evmProvider, globalObject);
announceChainAgnosticProvider(chainAgnosticProvider, globalObject);
@@ -62,23 +77,17 @@ export function initializeProvider(
*/
function setGlobalProvider(
providerInstance: EVMProvider,
- globalObject = window
+ globalObject = window,
+ multiWalletProxy
): void {
try {
- const multiWalletProxy = createMultiWalletProxy(providerInstance);
-
- // if we already have a wallet lets add it
- if (globalObject.ethereum) {
- multiWalletProxy.addProvider(globalObject.ethereum);
- }
-
Object.defineProperty(globalObject, 'ethereum', {
get: () => {
return multiWalletProxy;
},
// in case a wallet tries to overwrite us lets add them to the list
- set: (value) => {
- multiWalletProxy.addProvider(value);
+ set: () => {
+ return multiWalletProxy;
},
});
@@ -129,16 +138,6 @@ function setAvalancheGlobalProvider(
globalObject.dispatchEvent(new Event('avalanche#initialized'));
}
-function setEvmproviders(
- providerInstance: EVMProvider,
- globalObject = window
-): void {
- globalObject.evmproviders = globalObject.evmproviders || {};
- globalObject.evmproviders.core = providerInstance;
-
- globalObject.dispatchEvent(new Event('evmproviders#initialized'));
-}
-
function announceWalletProvider(
providerInstance: EVMProvider,
globalObject = window
diff --git a/src/background/providers/models.ts b/src/background/providers/models.ts
index f338116a..f16f8a4b 100644
--- a/src/background/providers/models.ts
+++ b/src/background/providers/models.ts
@@ -24,6 +24,11 @@ export interface EIP6963ProviderDetail {
provider: Eip1193Provider;
}
+export interface EIP6963AnnounceProviderEvent extends CustomEvent {
+ type: 'eip6963:announceProvider';
+ detail: EIP6963ProviderDetail;
+}
+
export enum EventNames {
CORE_WALLET_ANNOUNCE_PROVIDER = 'core-wallet:announceProvider',
CORE_WALLET_REQUEST_PROVIDER = 'core-wallet:requestProvider',
diff --git a/src/background/providers/utils/getWalletExtensionType.test.ts b/src/background/providers/utils/getWalletExtensionType.test.ts
deleted file mode 100644
index 5ddd50c2..00000000
--- a/src/background/providers/utils/getWalletExtensionType.test.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { WalletExtensionType } from '@src/background/services/web3/models';
-import { getWalletExtensionType } from './getWalletExtensionType';
-
-describe('src/background/providers/utils/getWalletExtensionType', () => {
- it('returns CORE when isAvalanche is true', () => {
- expect(
- getWalletExtensionType({ isAvalanche: true, isMetaMask: true })
- ).toBe(WalletExtensionType.CORE);
- });
-
- it('returns RABBY when isRabby is true', () => {
- expect(getWalletExtensionType({ isRabby: true, isMetaMask: true })).toBe(
- WalletExtensionType.RABBY
- );
- });
-
- it('returns COINBASE when isCoinbaseWallet is true', () => {
- expect(
- getWalletExtensionType({ isCoinbaseWallet: true, isMetaMask: true })
- ).toBe(WalletExtensionType.COINBASE);
- });
-
- it('returns METAMASK when isMetamask is true', () => {
- expect(getWalletExtensionType({ isMetaMask: true })).toBe(
- WalletExtensionType.METAMASK
- );
- });
-
- it('returns UNKNOWN', () => {
- expect(getWalletExtensionType({})).toBe(WalletExtensionType.UNKNOWN);
- });
-});
diff --git a/src/background/providers/utils/getWalletExtensionType.ts b/src/background/providers/utils/getWalletExtensionType.ts
deleted file mode 100644
index ee792659..00000000
--- a/src/background/providers/utils/getWalletExtensionType.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { WalletExtensionType } from '../../services/web3/models';
-
-// using any since we don't really know what properties other wallets define
-export function getWalletExtensionType(provider: any): WalletExtensionType {
- if (provider.isAvalanche) {
- return WalletExtensionType.CORE;
- }
- if (provider.isRabby) {
- return WalletExtensionType.RABBY;
- }
- if (provider.isCoinbaseWallet) {
- return WalletExtensionType.COINBASE;
- }
- if (provider.isMetaMask) {
- return WalletExtensionType.METAMASK;
- }
- return WalletExtensionType.UNKNOWN;
-}
diff --git a/src/background/services/secrets/SecretsService.test.ts b/src/background/services/secrets/SecretsService.test.ts
index 620c20f1..2097786a 100644
--- a/src/background/services/secrets/SecretsService.test.ts
+++ b/src/background/services/secrets/SecretsService.test.ts
@@ -542,7 +542,6 @@ describe('src/background/services/secrets/SecretsService.ts', () => {
const result = await secretsService.getAccountSecrets(
activeAccountData
);
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { ...rest } = secrets.wallets[0];
expect(result).toEqual({
diff --git a/src/background/services/web3/handlers/avalanche_selectWallet.ts b/src/background/services/web3/handlers/avalanche_selectWallet.ts
index 891fb818..249857bd 100644
--- a/src/background/services/web3/handlers/avalanche_selectWallet.ts
+++ b/src/background/services/web3/handlers/avalanche_selectWallet.ts
@@ -26,6 +26,7 @@ export class AvalancheSelectWalletHandler extends DAppRequestHandler {
...request,
displayData: {
options: availableExtensions.map((o) => o.type),
+ info: availableExtensions.map((extension) => extension.info),
},
},
`approve/select-wallet`
diff --git a/src/background/services/web3/models.ts b/src/background/services/web3/models.ts
index 97a308c6..e0425f5e 100644
--- a/src/background/services/web3/models.ts
+++ b/src/background/services/web3/models.ts
@@ -4,4 +4,7 @@ export enum WalletExtensionType {
UNKNOWN = 'UNKNOWN',
RABBY = 'RABBY',
COINBASE = 'COINBASE',
+ PHANTOM = 'PHANTOM',
+ ZERION = 'ZERION',
+ KEPLR = 'KEPLR',
}
diff --git a/src/localization/locales/en/translation.json b/src/localization/locales/en/translation.json
index a2ef4b66..536dd092 100644
--- a/src/localization/locales/en/translation.json
+++ b/src/localization/locales/en/translation.json
@@ -568,6 +568,7 @@
"Operation": "Operation",
"Or": "Or",
"Or click Scan QR Code.": "Or click Scan QR Code.",
+ "Other Wallets": "Other Wallets",
"Outgoing": "Outgoing",
"Owner": "Owner",
"Owners": "Owners",
@@ -915,7 +916,6 @@
"Unknown network fee": "Unknown network fee",
"Unknown sign type": "Unknown sign type",
"Unknown transaction error": "Unknown transaction error",
- "Unknown wallet": "Unknown wallet",
"Unknown website": "Unknown website",
"Unlimited": "Unlimited",
"Unlock": "Unlock",
diff --git a/src/pages/ApproveAction/SelectWallet.tsx b/src/pages/ApproveAction/SelectWallet.tsx
index 7555b755..0efe0804 100644
--- a/src/pages/ApproveAction/SelectWallet.tsx
+++ b/src/pages/ApproveAction/SelectWallet.tsx
@@ -4,7 +4,10 @@ import { useApproveAction } from '@src/hooks/useApproveAction';
import { useGetRequestId } from '@src/hooks/useGetRequestId';
import { useCallback } from 'react';
import { LoadingOverlay } from '../../components/common/LoadingOverlay';
-import { WalletExtensionButton } from '../Wallet/components/WalletExtensionButton';
+import {
+ WalletExtensionButton,
+ CoreExtensionButton,
+} from '../Wallet/components/WalletExtensionButton';
import { Trans } from 'react-i18next';
import { Stack, Typography, WalletIcon } from '@avalabs/core-k2-components';
@@ -46,15 +49,28 @@ export function SelectWallet() {
- {request.displayData.options.map((option, i) => (
+ {request.displayData.info.map((info, index) => {
+ if (info.rdns === 'app.core.extension') {
+ return (
+ {
+ selectWallet(index);
+ }}
+ info={info}
+ />
+ );
+ }
+ return;
+ })}
+ {request.displayData.info.length > 1 && (
{
- selectWallet(i);
+ onClick={(index) => {
+ selectWallet(index);
}}
- type={option}
+ wallets={request.displayData.info}
/>
- ))}
+ )}
);
diff --git a/src/pages/Wallet/components/WalletExtensionButton.tsx b/src/pages/Wallet/components/WalletExtensionButton.tsx
index 475f08b2..a6a2dca6 100644
--- a/src/pages/Wallet/components/WalletExtensionButton.tsx
+++ b/src/pages/Wallet/components/WalletExtensionButton.tsx
@@ -1,74 +1,177 @@
import { useTranslation } from 'react-i18next';
import {
Button,
- CoinbaseWalletIcon,
- CoreIcon,
- MetaMaskIcon,
- WalletIcon,
+ ButtonGroup,
+ ChevronDownIcon,
+ ClickAwayListener,
+ Grow,
+ keyframes,
+ MenuItem,
+ MenuList,
+ Popper,
+ Stack,
+ styled,
+ Typography,
} from '@avalabs/core-k2-components';
import { WalletExtensionType } from '@src/background/services/web3/models';
+import { EIP6963ProviderInfo } from '@avalabs/vm-module-types';
+import { useRef, useState } from 'react';
interface WalletExtensionButtonProps {
- type: WalletExtensionType;
- onClick: () => void;
+ type?: WalletExtensionType;
+ info?: EIP6963ProviderInfo;
+ onClick: (index: number) => void;
+ wallets?: EIP6963ProviderInfo[];
}
-export function WalletExtensionButton({
- type,
- onClick,
-}: WalletExtensionButtonProps) {
- const { t } = useTranslation();
+const flip = keyframes`
+ from {
+ transform: rotateX(0deg);
+ }
- const getWalletDisplayName = (walletType: WalletExtensionType) => {
- switch (walletType) {
- case WalletExtensionType.METAMASK:
- return 'Metamask';
- case WalletExtensionType.COINBASE:
- return 'Coinbase';
- case WalletExtensionType.UNKNOWN:
- default:
- return t('Unknown wallet');
- }
- };
+ to {
+ transform: rotateX(360deg);
+ }
+`;
- const getWalletLogo = (walletType: WalletExtensionType) => {
- switch (walletType) {
- case WalletExtensionType.METAMASK:
- return ;
- case WalletExtensionType.COINBASE:
- return ;
- case WalletExtensionType.UNKNOWN:
- default:
- return ;
+const StyledMenuItem = styled(MenuItem)`
+ img {
+ transition: transform 0.3s ease-in-out;
+ }
+ color: ${({ theme }) => theme.palette.text.secondary};
+ &:hover {
+ color: ${({ theme }) => theme.palette.text.primary};
+ img {
+ animation: ${flip} 0.5s ease-in-out;
}
- };
-
- if (type === WalletExtensionType.CORE) {
- return (
-
- );
}
+`;
+const CoreButton = styled(Button)`
+ img {
+ transition: transform 0.3s ease-in-out;
+ }
+ color: ${({ theme }) => theme.palette.text.secondary};
+ &:hover {
+ color: ${({ theme }) => theme.palette.text.primary};
+ img {
+ animation: ${flip} 0.5s ease-in-out;
+ }
+ }
+`;
+
+const StyledButtonGroup = styled(ButtonGroup)`
+ border-radius: 999px;
+`;
+
+export function CoreExtensionButton({
+ info,
+ onClick,
+}: WalletExtensionButtonProps) {
+ const { t } = useTranslation();
return (
-
+
+ {info?.name || t('Unknown')}
+
+ );
+}
+
+export function WalletExtensionButton({
+ wallets,
+ onClick,
+}: WalletExtensionButtonProps) {
+ const { t } = useTranslation();
+ const toggleButtonRef = useRef();
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
+ return (
+
+ setIsMenuOpen(false)}>
+
+
+
+
+
+
+
);
}