Skip to content

Commit

Permalink
feat: support WalletConnect v2 (#89)
Browse files Browse the repository at this point in the history
* feat: WalletConnect v2

* chore: bump packages

* chore: bump wallet connect

* chore: bump WalletConnect

* chore: rename to WalletConnect

* fix: types

* chore: add modal

* chore: bump packages

* fix: remove solana from rpcMap
  • Loading branch information
chybisov authored Jun 27, 2023
1 parent 159dfe0 commit 5c8cd6d
Show file tree
Hide file tree
Showing 6 changed files with 1,096 additions and 1,529 deletions.
4 changes: 2 additions & 2 deletions packages/wallet-management/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@
"@ethersproject/experimental": "^5.7.0",
"@ethersproject/providers": "^5.7.2",
"@lifi/sdk": "^2.0.1",
"@walletconnect/ethereum-provider": "^1.8.0",
"@walletconnect/web3-provider": "^1.8.0",
"@walletconnect/ethereum-provider": "^2.8.3",
"@walletconnect/modal": "^2.5.4",
"events": "^3.3.0",
"react": "^18.2.0"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ethers } from 'ethers';
import events from 'events';
import type {
AccountData,
InjectedConnectorConstructorArgs,
InjectedConnectorArgs,
Provider,
ProviderConnectInfo,
ProviderRpcError,
Expand All @@ -25,7 +25,7 @@ export class InjectedConnector extends events.EventEmitter implements Wallet {
public installed: () => boolean;

constructor(
constructorArgs: InjectedConnectorConstructorArgs,
constructorArgs: InjectedConnectorArgs,
windowConnector = (window as any).ethereum as Provider,
autoConnect = false,
) {
Expand Down
61 changes: 25 additions & 36 deletions packages/wallet-management/src/connectors/walletConnectConnector.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import { Web3Provider } from '@ethersproject/providers';
import type { StaticToken } from '@lifi/sdk';
import WalletConnectProvider from '@walletconnect/ethereum-provider';
import { ethers } from 'ethers';
import events from 'events';
import type { EventEmitter } from 'node:events';
import type {
AccountData,
Wallet,
WalletConnectConnectorConstructorArgs,
} from '../types';
import type { EthereumProviderOptions } from '@walletconnect/ethereum-provider/dist/types/EthereumProvider';
import { EventEmitter } from 'events';
import type { AccountData, Wallet, WalletConnectConnectorArgs } from '../types';
import {
addChain,
switchChain,
Expand All @@ -18,30 +14,25 @@ export interface MockWalletConnectProvider
extends Omit<WalletConnectProvider, 'on' | 'off' | 'once' | 'removeListener'>,
EventEmitter {}

export class WalletConnectConnector
extends events.EventEmitter
implements Wallet
{
private readonly options?: {
[chainId: number]: string;
};
export class WalletConnectConnector extends EventEmitter implements Wallet {
private readonly options: EthereumProviderOptions;

public provider: MockWalletConnectProvider | undefined;
public provider?: MockWalletConnectProvider;

public walletConnectProvider: WalletConnectProvider | undefined;
public walletConnectProvider?: WalletConnectProvider;

public isActivationInProgress: boolean = false;
public account: AccountData | undefined;
public account?: AccountData;
public name: string;
public icon: string;
public installed: () => boolean;

constructor(constructorArgs: WalletConnectConnectorConstructorArgs) {
constructor(args: WalletConnectConnectorArgs) {
super();
this.options = constructorArgs.rpc;
this.name = constructorArgs.name;
this.icon = constructorArgs.icon;
this.installed = constructorArgs.installed;
this.options = args.options;
this.name = args.name;
this.icon = args.icon;
this.installed = args.installed;
}

private async startListening(): Promise<void> {
Expand All @@ -61,7 +52,7 @@ export class WalletConnectConnector

// Subscribe to session disconnection
this.provider?.on('disconnect', async (code: number, reason: string) => {
await this.calcAccountData();
// await this.calcAccountData();
});
}

Expand All @@ -72,15 +63,16 @@ export class WalletConnectConnector
this.isActivationInProgress = true;

// Reset provider for every connection attempt
const walletConnectProvider = new WalletConnectProvider({
rpc: this.options!,
});
const walletConnectProvider = await WalletConnectProvider.init(
this.options,
);
this.provider =
walletConnectProvider as unknown as MockWalletConnectProvider;
this.walletConnectProvider = walletConnectProvider;

try {
await this.walletConnectProvider?.enable(); // open modal
// Open modal
await this.walletConnectProvider?.enable();
this.startListening();
await this.calcAccountData();
} catch (e) {
Expand All @@ -104,33 +96,30 @@ export class WalletConnectConnector

public async switchChain(chainId: number) {
if (!this.provider) {
throw new Error('provider is not defined.');
throw new Error('Provider is not defined.');
}
return switchChain(this.walletConnectProvider, chainId);
}

public async addChain(chainId: number) {
if (!this.provider) {
throw new Error('provider is not defined.');
throw new Error('Provider is not defined.');
}
return addChain(this.walletConnectProvider, chainId);
}

public async addToken(chainId: number, token: StaticToken) {
if (!this.provider) {
throw new Error('provider is not defined.');
throw new Error('Provider is not defined.');
}
return switchChainAndAddToken(this.walletConnectProvider, chainId, token);
}

private async calcAccountData() {
if (!this.walletConnectProvider) {
throw new Error('provider is not defined.');
throw new Error('Provider is not defined.');
}
const provider = new ethers.providers.Web3Provider(
this.walletConnectProvider!,
'any',
);
const provider = new Web3Provider(this.walletConnectProvider, 'any');

const signer = provider.getSigner();
this.account = {
Expand Down
16 changes: 9 additions & 7 deletions packages/wallet-management/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import type { Signer } from '@ethersproject/abstract-signer';
import type { Web3Provider } from '@ethersproject/providers';
import type { StaticToken } from '@lifi/sdk';
import type EventEmitter from 'node:events';
import type { EthereumProviderOptions } from '@walletconnect/ethereum-provider/dist/types/EthereumProvider';
import type { EventEmitter } from 'events';

export interface ProviderConnectInfo {
readonly chainId: string;
}

export interface ProviderRpcError extends Error {
message: string;
code: number;
Expand All @@ -29,25 +31,25 @@ export interface AccountData {
signer: Signer;
provider: Web3Provider;
}
export interface InjectedConnectorConstructorArgs {

export interface InjectedConnectorArgs {
name: string;
icon: string;
installed: () => boolean;
}
export interface WalletConnectConnectorConstructorArgs {

export interface WalletConnectConnectorArgs {
name: string;
icon: string;
installed: () => boolean;
rpc: {
[chainId: number]: string;
};
options: EthereumProviderOptions;
}

export interface Wallet extends EventEmitter {
name: string;
icon: string;
isActivationInProgress: boolean;
account: AccountData | undefined;
account?: AccountData;
installed: () => boolean;
connect: () => Promise<void>;
autoConnect?: () => Promise<void>;
Expand Down
24 changes: 17 additions & 7 deletions packages/wallet-management/src/wallets.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { supportedChains } from '@lifi/sdk';
import { ChainType, supportedChains } from '@lifi/sdk';
import type { EthereumRpcMap } from '@walletconnect/ethereum-provider/dist/types/EthereumProvider';
import { InjectedConnector } from './connectors/injectedConnector';
import { WalletConnectConnector } from './connectors/walletConnectConnector';
import type { Wallet } from './types';
Expand All @@ -21,14 +22,23 @@ const metamask: Wallet = new InjectedConnector({
});

const walletConnect: Wallet = new WalletConnectConnector({
name: 'Wallet Connect',
name: 'WalletConnect',
installed: () => true,
icon: walletIcons.walletConnect,
rpc: Object.fromEntries(
supportedChains.map((chain) => {
return [chain.id, chain.metamask.rpcUrls[0] || ''];
}),
),
options: {
projectId: '5432e3507d41270bee46b7b85bbc2ef8',
rpcMap: supportedChains.reduce((rpcMap, chain) => {
if (chain.chainType === ChainType.EVM) {
rpcMap[`eip155:${chain.id}`] = chain.metamask.rpcUrls[0] || '';
}
return rpcMap;
}, {} as EthereumRpcMap),
chains: [1],
optionalChains: supportedChains
.filter((chain) => chain.chainType === ChainType.EVM)
.map((chain) => chain.id),
showQrModal: true,
},
});

const frontier: Wallet = new InjectedConnector(
Expand Down
Loading

0 comments on commit 5c8cd6d

Please sign in to comment.