UNPKG

web3-react-okx-connector

Version:

Okx wallet injected provider connector for web3-react@v6

249 lines (216 loc) 6.74 kB
import { AbstractConnectorArguments, ConnectorUpdate } from "@web3-react/types"; import { AbstractConnector } from "@web3-react/abstract-connector"; import warning from "tiny-warning"; export type SendReturnResult = { result: any }; export type SendReturn = any; export type Send = ( method: string, params?: any[] ) => Promise<SendReturnResult | SendReturn>; export type SendOld = ({ method, }: { method: string; }) => Promise<SendReturnResult | SendReturn>; const __DEV__ = process.env.NODE_ENV !== "development" ? false : true; function parseSendReturn(sendReturn: SendReturnResult | SendReturn): any { return sendReturn.hasOwnProperty("result") ? sendReturn.result : sendReturn; } export class NoOkxwalletProviderError extends Error { public constructor() { super(); this.name = this.constructor.name; this.message = "No okxwallet provider was found on window.okxwallet."; } } export class UserRejectedRequestError extends Error { public constructor() { super(); this.name = this.constructor.name; this.message = "The user rejected the request."; } } export class OkxConnector extends AbstractConnector { constructor(kwargs: AbstractConnectorArguments) { super(kwargs); this.handleChainChanged = this.handleChainChanged.bind(this); this.handleAccountsChanged = this.handleAccountsChanged.bind(this); this.handleClose = this.handleClose.bind(this); } private handleChainChanged(chainId: string | number): void { if (__DEV__) { console.log("Handling 'chainChanged' event with payload", chainId); } window.location.reload(); this.emitUpdate({ chainId, provider: window.okxwallet }); } private handleAccountsChanged(accounts: string[]): void { if (__DEV__) { console.log("Handling 'accountsChanged' event with payload", accounts); } if (accounts.length === 0) { this.emitDeactivate(); } else { this.emitUpdate({ account: accounts[0] }); } } private handleClose(code: number, reason: string): void { if (__DEV__) { console.log("Handling 'close' event with payload", code, reason); } this.emitDeactivate(); } // if user never connected public async activate(): Promise<ConnectorUpdate> { if (!window.okxwallet) { throw new NoOkxwalletProviderError(); } if (window.okxwallet.on) { window.okxwallet.on("chainChanged", this.handleChainChanged); window.okxwallet.on("accountsChanged", this.handleAccountsChanged); window.okxwallet.on("close", this.handleClose); } if ((window.okxwallet as any).isMetaMask) { (window.okxwallet as any).autoRefreshOnNetworkChange = false; } // try to activate + get account via eth_requestAccounts let account; try { account = await (window.okxwallet.send as Send)( "eth_requestAccounts" ).then((sendReturn) => parseSendReturn(sendReturn)[0]); } catch (error) { if ((error as any).code === 4001) { throw new UserRejectedRequestError(); } warning( false, "eth_requestAccounts was unsuccessful, falling back to enable" ); } // if unsuccessful, try enable if (!account) { // if enable is successful but doesn't return accounts, fall back to getAccount (not happy i have to do this...) account = await window.okxwallet .enable() .then((sendReturn) => sendReturn && parseSendReturn(sendReturn)[0]); } return { provider: window.okxwallet, ...(account ? { account } : {}) }; } public async getProvider(): Promise<any> { return window.okxwallet; } public async getChainId(): Promise<number | string> { if (!window.okxwallet) { throw new NoOkxwalletProviderError(); } let chainId; try { chainId = await (window.okxwallet.send as Send)("eth_chainId").then( parseSendReturn ); } catch { warning( false, "eth_chainId was unsuccessful, falling back to net_version" ); } if (!chainId) { try { chainId = await (window.okxwallet.send as Send)("net_version").then( parseSendReturn ); } catch { warning( false, "net_version was unsuccessful, falling back to net version v2" ); } } if (!chainId) { try { chainId = parseSendReturn( (window.okxwallet.send as SendOld)({ method: "net_version" }) ); } catch { warning( false, "net_version v2 was unsuccessful, falling back to manual matches and static properties" ); } } if (!chainId) { if ((window.okxwallet as any).isDapper) { chainId = parseSendReturn( (window.okxwallet as any).cachedResults.net_version ); } else { chainId = (window.okxwallet as any).chainId || (window.okxwallet as any).netVersion || (window.okxwallet as any).networkVersion || (window.okxwallet as any)._chainId; } } return chainId; } public async getAccount(): Promise<null | string> { if (!window.okxwallet) { throw new NoOkxwalletProviderError(); } let account; try { account = await (window.okxwallet.send as Send)("eth_accounts").then( (sendReturn) => parseSendReturn(sendReturn)[0] ); } catch { warning(false, "eth_accounts was unsuccessful, falling back to enable"); } if (!account) { try { account = await window.okxwallet .enable() .then((sendReturn) => parseSendReturn(sendReturn)[0]); } catch { warning( false, "enable was unsuccessful, falling back to eth_accounts v2" ); } } if (!account) { account = parseSendReturn( (window.okxwallet.send as SendOld)({ method: "eth_accounts" }) )[0]; } return account; } public deactivate() { if (window.okxwallet && window.okxwallet.removeListener) { window.okxwallet.removeListener("chainChanged", this.handleChainChanged); window.okxwallet.removeListener( "accountsChanged", this.handleAccountsChanged ); window.okxwallet.removeListener("close", this.handleClose); } } public async isAuthorized(): Promise<boolean> { if (!window.okxwallet) { return false; } try { return await (window.okxwallet.send as Send)("eth_accounts").then( (sendReturn) => { if (parseSendReturn(sendReturn).length > 0) { return true; } else { return false; } } ); } catch { return false; } } }