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

WIP, switch to ethers #8

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
161 changes: 161 additions & 0 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,30 @@ 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";
import { encodeL1address } from "./addresses";

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);
}

address() {
return this.contract.address;
}
}

export class DelphinusContract {
private readonly contract: Contract;
Expand Down Expand Up @@ -223,6 +245,145 @@ async function withDelphinusWeb3<t>(
}
}

export abstract class BlockChainClient {
private readonly provider: ethers.providers.JsonRpcProvider;

constructor(provider: ethers.providers.JsonRpcProvider) {
this.provider = provider;
}

abstract switchNet(
switchToChainId: number,
chainName: string,
rpcSource: string
): Promise<void>;

async getAccountInfo() {
return await this.provider.getSigner().getAddress();
}

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;
}

/**
*
* @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 {
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);
}
}

class BlockChainClientProvider extends BlockChainClient {
constructor(rpcUrl: string) {
const provider = new ethers.providers.JsonRpcProvider(rpcUrl);
super(provider);
}

async switchNet(
_switchToChainId: number,
_chainName: string,
_rpcSource: string
) {}
}

export interface SwitchChainInfo {
chainName: string;
chainId: number;
chainRpcUrl: string;
}

export async function withBlockchainClient<t>(
cb: (blockchain: BlockChainClient) => Promise<t>,
browserMode: boolean,
specifyChain?: SwitchChainInfo
) {
let client = browserMode
? new BlockChainClientBrowser()
: new BlockChainClientProvider(specifyChain!.chainRpcUrl);

if (specifyChain)
await client.switchNet(
specifyChain.chainId,
specifyChain.chainName,
specifyChain.chainRpcUrl
);

return cb(client);
}

export async function withBrowerWeb3<t>(
cb: (web3: DelphinusWeb3) => Promise<t>
) {
Expand Down