From f63e4405ea97afc052708fa77383952eca65e2fc Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Sat, 22 Jan 2022 17:33:02 +0800 Subject: [PATCH 1/7] support getAccountInfo for brower ethers --- package.json | 1 + src/client.ts | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/package.json b/package.json index 1d80b18..e24a3b1 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "@truffle/hdwallet-provider": "^1.6.0", "@types/bn.js": "^5.1.0", "bn.js": "^5.2.0", + "ethers": "^5.5.3", "mongodb": "^4.1.4", "substrate-ss58": "^1.0.3", "web3": "1.5.3", diff --git a/src/client.ts b/src/client.ts index ce97635..c07197b 100644 --- a/src/client.ts +++ b/src/client.ts @@ -4,6 +4,7 @@ import { provider } from "web3-core"; import detectEthereumProvider from "@metamask/detect-provider"; import { MetaMaskInpageProvider } from "@metamask/providers"; import BN from "bn.js"; +import { ethers } from "ethers"; import { DelphinusProvider } from "./provider"; @@ -223,6 +224,42 @@ async function withDelphinusWeb3( } } +export abstract class BlockChainClient { + private readonly provider: ethers.providers.JsonRpcProvider; + + constructor(provider: ethers.providers.JsonRpcProvider) { + this.provider = provider; + } + + async getAccountInfo() { + const address = await this.provider.getSigner().getAddress(); + const id = (await this.provider.getNetwork()).chainId; + + return { + address: address, + chainId: id.toString(), + }; + } +} + +class BlockChainClientBrowser extends BlockChainClient { + constructor() { + const provider = new ethers.providers.Web3Provider(window.ethereum as any); + super(provider); + } +} + +export async function withBlockchainClient( + browser: boolean, + cb: (blockchain: BlockChainClient) => Promise +) { + if (!browser) { + throw "not impl"; + } + let client = new BlockChainClientBrowser(); + return await cb(client); +} + export async function withBrowerWeb3( cb: (web3: DelphinusWeb3) => Promise ) { From 36638938358a920095a578d07bfcdd1674f3a80c Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Sat, 22 Jan 2022 19:32:05 +0800 Subject: [PATCH 2/7] support send for ethers client --- src/client.ts | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/client.ts b/src/client.ts index c07197b..e9bed30 100644 --- a/src/client.ts +++ b/src/client.ts @@ -240,6 +240,10 @@ export abstract class BlockChainClient { chainId: id.toString(), }; } + + async send(method: string, params: any[]) { + return this.provider.send(method, params); + } } class BlockChainClientBrowser extends BlockChainClient { @@ -249,14 +253,20 @@ class BlockChainClientBrowser extends BlockChainClient { } } +class BlockChainClientProvider extends BlockChainClient { + constructor(rpcUrl: string) { + const provider = new ethers.providers.JsonRpcProvider(rpcUrl); + super(provider); + } +} + export async function withBlockchainClient( - browser: boolean, - cb: (blockchain: BlockChainClient) => Promise + cb: (blockchain: BlockChainClient) => Promise, + browserOrUrl?: string ) { - if (!browser) { - throw "not impl"; - } - let client = new BlockChainClientBrowser(); + let client = browserOrUrl + ? new BlockChainClientProvider(browserOrUrl) + : new BlockChainClientBrowser(); return await cb(client); } From cdc90bbb56e8656d8158a9e9ba53348c599211fb Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Sat, 22 Jan 2022 22:25:18 +0800 Subject: [PATCH 3/7] refine ethers contract --- src/client.ts | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/client.ts b/src/client.ts index e9bed30..4ff999e 100644 --- a/src/client.ts +++ b/src/client.ts @@ -8,6 +8,22 @@ import { ethers } from "ethers"; import { DelphinusProvider } from "./provider"; +export class DelphinusContractEther { + private contract: ethers.Contract; + + constructor(address: string, jsonABI: any, provider: BlockChainClient) { + this.contract = new ethers.Contract( + address, + jsonABI.abi, + provider.getSignerOrProvider() + ); + } + + async call(method: string, ...args: any[]) { + return await this.contract[method](...args); + } +} + export class DelphinusContract { private readonly contract: Contract; private readonly jsonInterface: any; @@ -233,7 +249,7 @@ export abstract class BlockChainClient { async getAccountInfo() { const address = await this.provider.getSigner().getAddress(); - const id = (await this.provider.getNetwork()).chainId; + const id = this.getChainID(); return { address: address, @@ -241,9 +257,21 @@ export abstract class BlockChainClient { }; } + async getChainID() { + return (await this.provider.getNetwork()).chainId; + } + async send(method: string, params: any[]) { return this.provider.send(method, params); } + + async getContract(address: string, jsonABI: any) { + return new DelphinusContractEther(address, jsonABI, this); + } + + getSignerOrProvider() { + return this.provider.getSigner() || this.provider; + } } class BlockChainClientBrowser extends BlockChainClient { @@ -267,7 +295,7 @@ export async function withBlockchainClient( let client = browserOrUrl ? new BlockChainClientProvider(browserOrUrl) : new BlockChainClientBrowser(); - return await cb(client); + return cb(client); } export async function withBrowerWeb3( From cdff8379c842dcba1d25729e4b3b779ea579138e Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Sun, 23 Jan 2022 15:15:45 +0800 Subject: [PATCH 4/7] add encodeL1 function --- src/client.ts | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/client.ts b/src/client.ts index 4ff999e..a6774c4 100644 --- a/src/client.ts +++ b/src/client.ts @@ -7,6 +7,7 @@ import BN from "bn.js"; import { ethers } from "ethers"; import { DelphinusProvider } from "./provider"; +import { encodeL1address } from "./addresses"; export class DelphinusContractEther { private contract: ethers.Contract; @@ -248,13 +249,7 @@ export abstract class BlockChainClient { } async getAccountInfo() { - const address = await this.provider.getSigner().getAddress(); - const id = this.getChainID(); - - return { - address: address, - chainId: id.toString(), - }; + return await this.provider.getSigner().getAddress(); } async getChainID() { @@ -272,6 +267,21 @@ export abstract class BlockChainClient { getSignerOrProvider() { return this.provider.getSigner() || this.provider; } + + /** + * + * @param address address must start with 0x + * @returns + */ + async encodeL1Address(address: string) { + if (address.substring(0, 2) != "0x") { + throw "address must start with 0x"; + } + + const addressHex = address.substring(2); + const chex = (await this.getChainID()).toString(); + return encodeL1address(addressHex, chex); + } } class BlockChainClientBrowser extends BlockChainClient { From dacb52b104efeaa7effcce4781cb391e67f5ca47 Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Sun, 23 Jan 2022 17:15:03 +0800 Subject: [PATCH 5/7] export address --- src/client.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/client.ts b/src/client.ts index a6774c4..9b18719 100644 --- a/src/client.ts +++ b/src/client.ts @@ -23,6 +23,10 @@ export class DelphinusContractEther { async call(method: string, ...args: any[]) { return await this.contract[method](...args); } + + address() { + return this.contract.address; + } } export class DelphinusContract { From e7675a30c712a96471cebd741d98e1c40f341c89 Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Tue, 1 Feb 2022 11:54:30 +0800 Subject: [PATCH 6/7] support switchnet for ethers --- src/client.ts | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/client.ts b/src/client.ts index 9b18719..de7bacd 100644 --- a/src/client.ts +++ b/src/client.ts @@ -252,6 +252,12 @@ export abstract class BlockChainClient { this.provider = provider; } + abstract switchNet( + switchToChainId: number, + chainName: string, + rpcSource: string + ): Promise; + async getAccountInfo() { return await this.provider.getSigner().getAddress(); } @@ -289,9 +295,54 @@ export abstract class BlockChainClient { } class BlockChainClientBrowser extends BlockChainClient { + private externalProvider: ethers.providers.ExternalProvider; + constructor() { const provider = new ethers.providers.Web3Provider(window.ethereum as any); super(provider); + this.externalProvider = window.ethereum as any; + } + + async switchNet( + switchToChainId: number, + chainName: string, + rpcSource: string + ) { + let currentChainId = await this.getChainID(); + console.log("switch chain", currentChainId, switchToChainId); + if (currentChainId != switchToChainId) { + try { + await this.externalProvider.request!({ + method: "wallet_switchEthereumChain", + params: [{ chainId: switchToChainId }], + }); + } catch (e: any) { + if (e.code == 4902) { + try { + await this.externalProvider.request!({ + method: "wallet_addEthereumChain", + params: [ + { + chainId: switchToChainId, + chainName: chainName, + rpcUrls: [rpcSource], + }, + ], + }); + await this.externalProvider.request!({ + method: "wallet_switchEthereumChain", + params: [{ chainId: switchToChainId }], + }); + } catch (e) { + throw new Error("Add Network Rejected by User."); + } + } else { + throw new Error("Can not switch to chain " + switchToChainId); + } + } + } + currentChainId = await this.getChainID(); + console.log("switched", currentChainId, switchToChainId); } } @@ -300,6 +351,12 @@ class BlockChainClientProvider extends BlockChainClient { const provider = new ethers.providers.JsonRpcProvider(rpcUrl); super(provider); } + + async switchNet( + _switchToChainId: number, + _chainName: string, + _rpcSource: string + ) {} } export async function withBlockchainClient( From 4016ae919f50b07a337426de9b19ee33cca5160a Mon Sep 17 00:00:00 2001 From: Zhang Junyu Date: Tue, 1 Feb 2022 13:01:21 +0800 Subject: [PATCH 7/7] adjust interface --- src/client.ts | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/client.ts b/src/client.ts index de7bacd..65f95a1 100644 --- a/src/client.ts +++ b/src/client.ts @@ -359,13 +359,28 @@ class BlockChainClientProvider extends BlockChainClient { ) {} } +export interface SwitchChainInfo { + chainName: string; + chainId: number; + chainRpcUrl: string; +} + export async function withBlockchainClient( cb: (blockchain: BlockChainClient) => Promise, - browserOrUrl?: string + browserMode: boolean, + specifyChain?: SwitchChainInfo ) { - let client = browserOrUrl - ? new BlockChainClientProvider(browserOrUrl) - : new BlockChainClientBrowser(); + let client = browserMode + ? new BlockChainClientBrowser() + : new BlockChainClientProvider(specifyChain!.chainRpcUrl); + + if (specifyChain) + await client.switchNet( + specifyChain.chainId, + specifyChain.chainName, + specifyChain.chainRpcUrl + ); + return cb(client); }