UNPKG

@kaiachain/web3js-ext

Version:
154 lines (133 loc) 5.07 kB
import { AsyncNamespaceApi, rpcSendFunction, asyncOpenApi } from "@kaiachain/js-ext-core"; // @ts-ignore: package @kaiachain/web3rpc has no .d.ts file. import * as web3rpc from "@kaiachain/web3rpc"; import { Web3 } from "web3"; import { Web3Context, Web3ContextInitOptions, isSupportedProvider } from "web3-core"; import { ResponseError, ProviderError } from "web3-errors"; import { RegisteredSubscription } from "web3-eth"; import { EthExecutionAPI, SupportedProviders, } from "web3-types"; import * as utils from "web3-utils"; import { context_accounts } from "./accounts/index.js"; import { context_getProtocolVersion, context_sendSignedTransaction, context_sendTransaction, context_signTransaction, } from "./eth/index.js"; import { KaiaWeb3EthInterface } from "./index.js"; // Follow the Web3 class from the web3/src/web3.ts // with slight difference in the web3.eth property. export class KlaytnWeb3 extends Web3Context<EthExecutionAPI, RegisteredSubscription> { // Static properties analogous to Web3 class public static version = Web3.version; public static utils = Web3.utils; public static modules = Web3.modules; // Properties analogous to Web3 class public utils: typeof utils; public eth: KaiaWeb3EthInterface; // Additional RPC namespaces public admin: AsyncNamespaceApi; public debug: AsyncNamespaceApi; public governance: AsyncNamespaceApi; public klay: AsyncNamespaceApi; public kaia: AsyncNamespaceApi; public net: AsyncNamespaceApi; public personal: AsyncNamespaceApi; public txpool: AsyncNamespaceApi; // The inner Web3 instance that provides the base implementation. // KlaytnWeb3 will delegate most of its methods to this instance. private _web3: Web3; public constructor( providerOrContext?: | string | SupportedProviders<EthExecutionAPI> | Web3ContextInitOptions<EthExecutionAPI>, ) { // Call super() like original Web3.constructor() does const contextInitOptions = getContextInitOptions(providerOrContext); super(contextInitOptions); // Create inner Web3 object this._web3 = new Web3(providerOrContext); // Expose required properties from inner Web3 object this.utils = this._web3.utils; // Override web3.eth.accounts methods const accounts = context_accounts(this); this.eth = { ...this._web3.eth, accounts: accounts } as KaiaWeb3EthInterface; this._accountProvider = accounts as any; // inevitable conflict in signTransaction types this._wallet = accounts.wallet; // Override web3.eth RPC method wrappers. See web3-eth/src/web3_eth.ts:Web3Eth // Note that other web3.eth methods should just calling eth_ RPCs to Klaytn node. this.eth.getProtocolVersion = context_getProtocolVersion(this._web3); this.eth.sendTransaction = context_sendTransaction(this._web3); this.eth.sendSignedTransaction = context_sendSignedTransaction(this._web3); this.eth.signTransaction = context_signTransaction(this._web3); // Attach additional RPC namespaces. const send = this.makeSendFunction(); const { AdminApi, DebugApi, GovernanceApi, KlayApi, NetApi, PersonalApi, TxpoolApi } = web3rpc this.admin = asyncOpenApi(send, AdminApi); this.debug = asyncOpenApi(send, DebugApi); this.governance = asyncOpenApi(send, GovernanceApi); this.klay = asyncOpenApi(send, KlayApi); this.kaia = asyncOpenApi(send, KlayApi); this.net = asyncOpenApi(send, NetApi); this.personal = asyncOpenApi(send, PersonalApi); this.txpool = asyncOpenApi(send, TxpoolApi); } private makeSendFunction(): rpcSendFunction { if (!this.provider) { return async (_method: string, _params: any[]): Promise<any> => { throw new ProviderError("no provider set"); }; } return async (method: string, params: any[]): Promise<any> => { const response = await this.provider?.request({ jsonrpc: "2.0", id: "1", method: method, params: params, }); if (response?.error) { throw new ResponseError(response); } else { return response?.result; } }; } } // Parse providerOrContext into Web3ContextInitOptions. // See web3/src/web3.ts:Web3 function getContextInitOptions( providerOrContext?: | string | SupportedProviders<EthExecutionAPI> | Web3ContextInitOptions<EthExecutionAPI>, ) { // Because console.warn will be printed in `this._web3 = new Web3(..)`, we omit here. // if (...) { console.warn('NOTE: web3.js is running without provider...'); } let contextInitOptions: Web3ContextInitOptions<EthExecutionAPI> = {}; if ( typeof providerOrContext === "string" || isSupportedProvider(providerOrContext as SupportedProviders) ) { contextInitOptions.provider = providerOrContext as | undefined | string | SupportedProviders; } else if (providerOrContext) { contextInitOptions = providerOrContext as Web3ContextInitOptions; } else { contextInitOptions = {}; } return contextInitOptions; }