Skip to content

Commit

Permalink
Feature/wallet connect 2.0 (#236)
Browse files Browse the repository at this point in the history
* added walletconnect 2.0 support
  • Loading branch information
poocart authored Oct 3, 2023
1 parent 46ac840 commit e324d3c
Show file tree
Hide file tree
Showing 9 changed files with 1,399 additions and 28 deletions.
1,321 changes: 1,299 additions & 22 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "etherspot",
"version": "1.43.9",
"version": "1.44.0",
"description": "Etherspot SDK",
"keywords": [
"ether",
Expand Down Expand Up @@ -45,6 +45,7 @@
"@etherspot/contracts": "1.9.9",
"@lifi/sdk": "1.6.4",
"@nerdwallet/apollo-cache-policies": "1.2.1",
"@walletconnect/universal-provider": "^2.10.0",
"class-transformer": "0.4.0",
"class-validator": "0.14.0",
"cross-fetch": "3.1.5",
Expand Down
16 changes: 13 additions & 3 deletions src/sdk/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,14 @@ import {
KnownContract,
} from './transactions';
import { State, StateService } from './state';
import { WalletService, isWalletProvider, WalletProviderLike } from './wallet';
import {
WalletService,
isWalletProvider,
WalletProviderLike,
isWalletConnectProvider,
WalletConnect2WalletProvider,
EthereumProvider,
} from './wallet';

/**
* Sdk
Expand All @@ -196,7 +203,10 @@ export class Sdk {
constructor(walletProvider: WalletProviderLike, optionsLike?: EnvNames | SdkOptions) {
let options: SdkOptions = {};

if (!isWalletProvider(walletProvider)) {
let walletConnectProvider;
if (isWalletConnectProvider(walletProvider)) {
walletConnectProvider = new WalletConnect2WalletProvider(walletProvider as EthereumProvider);
} else if (!isWalletProvider(walletProvider)) {
throw new Exception('Invalid wallet provider');
}

Expand Down Expand Up @@ -239,7 +249,7 @@ export class Sdk {

this.services = {
networkService: new NetworkService(networkOptions, networkName),
walletService: new WalletService(walletProvider, {
walletService: new WalletService(walletConnectProvider ?? walletProvider, {
omitProviderNetworkCheck: omitWalletProviderNetworkCheck,
}),
sessionService: new SessionService({
Expand Down
1 change: 1 addition & 0 deletions src/sdk/wallet/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export * from './key.wallet-provider';
export * from './meta-mask.wallet-provider';
export * from './utils';
export * from './wallet-connect.wallet-provider';
export * from './wallet-connect-2.wallet-provider';
export * from './web3.wallet-provider';
export * from './web3eip1193.wallet-provider';
17 changes: 16 additions & 1 deletion src/sdk/wallet/providers/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BytesLike, Wallet } from 'ethers';
import type UniversalProvider from '@walletconnect/universal-provider';
import { UniqueSubject } from '../../common';
import { NetworkNames } from '../../network';

Expand All @@ -25,6 +26,20 @@ export interface Web3eip1193Provider {
request(args: RequestArguments): any;
}

export declare class EthereumProvider {
accounts: string[];
signer: InstanceType<typeof UniversalProvider>;
chainId: number;
request<T = unknown>(args: RequestArguments): Promise<T>;
sendAsync(args: RequestArguments, callback: (error: Error | null, response: any) => void): void;
disconnect(): Promise<void>;
on(event: string, callback: (error: Error | null, payload: any | null) => void): void;
once(event: string, callback: (error: Error | null, payload: any | null) => void): void;
removeListener(event: string, callback: (error: Error | null, payload: any | null) => void): void;
off(event: string, callback: (error: Error | null, payload: any | null) => void): void;
readonly isWalletConnect?: boolean;
}

export interface WalletConnectConnector {
accounts: string[];
chainId: number;
Expand All @@ -36,4 +51,4 @@ export interface WalletLike {
privateKey: string;
}

export type WalletProviderLike = string | WalletLike | WalletProvider;
export type WalletProviderLike = string | WalletLike | WalletProvider | EthereumProvider;
1 change: 1 addition & 0 deletions src/sdk/wallet/providers/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './is-wallet-provider';
export * from './is-wallet-connect-provider';
5 changes: 5 additions & 0 deletions src/sdk/wallet/providers/utils/is-wallet-connect-provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { EthereumProvider, WalletProviderLike } from '../interfaces';

export function isWalletConnectProvider(provider: WalletProviderLike): boolean {
return typeof provider === 'object' && (provider as EthereumProvider)?.isWalletConnect;
}
60 changes: 60 additions & 0 deletions src/sdk/wallet/providers/wallet-connect-2.wallet-provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { BytesLike } from 'ethers';
import { toHex } from '../../common';
import { DynamicWalletProvider } from './dynamic.wallet-provider';
import { EthereumProvider } from './interfaces';

export class WalletConnect2WalletProvider extends DynamicWalletProvider {
constructor(readonly provider: EthereumProvider) {
super('WalletConnect2');

try {
const {
accounts: [address],
chainId,
} = provider;

this.setAddress(address);
this.setNetworkName(chainId);
} catch (err) {
//
}

this.updateSessionHandler = this.updateSessionHandler.bind(this);

provider.on('connect', this.updateSessionHandler);
provider.on('session_event', this.updateSessionHandler);
provider.on('disconnect', () => {
this.setAddress(null);
this.setNetworkName(null);
});
}

async signMessage(message: BytesLike): Promise<string> {
const response = await this.provider.signer.request({
method: 'personal_sign',
params: [toHex(message), this.address],
});

return typeof response === 'string' ? response : null;
}

protected updateSessionHandler(error: Error, payload: { params: { accounts: string[]; chainId: number } }): void {
let address: string = null;
let chainId: number = null;

if (!error) {
try {
({
accounts: [address],
chainId,
} = payload.params[0]);
} catch (err) {
address = null;
chainId = null;
}
}

this.setAddress(address);
this.setNetworkName(chainId);
}
}
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"ES5",
"es2015.collection",
"es2015.iterable"
]
],
"skipLibCheck": true
},
"include": [
"./examples/**/*.ts",
Expand Down

0 comments on commit e324d3c

Please sign in to comment.