import type { ConnectionInfo } from 'ethers/lib/utils' import type EventEmitter from 'eventemitter3' import type { TypedData as EIP712TypedData } from 'eip-712' import type { ethers } from 'ethers' export type { TypedData as EIP712TypedData } from 'eip-712' /** * Types for request patching methods. Ethereum RPC request is mapped to * the implementation that will replace the original. * If a method is not supported set it to `null` * and the appropriate error will get called. */ export type RequestPatch = { eth_accounts?: | ((args: { baseRequest: EIP1193Provider['request'] }) => Promise) | null eth_getBalance?: | ((args: { baseRequest: EIP1193Provider['request'] }) => Promise) | null eth_requestAccounts?: | ((args: { baseRequest: EIP1193Provider['request'] }) => Promise) | null eth_selectAccounts?: | ((args: { baseRequest: EIP1193Provider['request'] }) => Promise) | null eth_chainId?: | ((args: { baseRequest: EIP1193Provider['request'] }) => Promise) | null eth_signTransaction?: | ((args: { baseRequest: EIP1193Provider['request'] params: EthSignTransactionRequest['params'] }) => Promise) | null eth_sendTransaction?: | ((args: { baseRequest: EIP1193Provider['request'] params: EthSignTransactionRequest['params'] }) => Promise) | null eth_sign?: | ((args: { baseRequest: EIP1193Provider['request'] params: EthSignMessageRequest['params'] }) => Promise) | null personal_sign?: | ((args: { baseRequest: EIP1193Provider['request'] params: PersonalSignMessageRequest['params'] }) => Promise) | null eth_signTypedData?: | ((args: { baseRequest: EIP1193Provider['request'] params: EIP712Request['params'] }) => Promise) | null wallet_switchEthereumChain?: | ((args: { baseRequest: EIP1193Provider['request'] params: EIP3326Request['params'] }) => Promise) | null wallet_addEthereumChain?: | ((args: { baseRequest: EIP1193Provider['request'] params: EIP3085Request['params'] }) => Promise) | null } export interface AppMetadata { /* App name */ name: string /* An SVG icon string or image url, with height set to 100% Note: `icon` is displayed on both mobile AND desktop. If `logo` below is provided then `icon` displays on mobile and `logo` on desktop. */ icon?: string /* SVG logo (icon and text) string or image url, with width set to 100% Note: This will ONLY display on desktop. It is best used with wide format logos. Use `icon` for standard 40x40 icons. */ logo?: string /* Description of app*/ description?: string /* Url to a getting started guide for app */ gettingStartedGuide?: string /* Url that points to more information about app */ explore?: string /** When no injected wallets detected, recommend the user to install some*/ recommendedInjectedWallets?: RecommendedInjectedWallets[] agreement?: TermsOfServiceAgreementOptions | null } export type TermsOfServiceAgreementOptions = { version: string termsUrl?: string privacyUrl?: string } export type RecommendedInjectedWallets = { name: string url: string } /** * A method that takes `WalletHelpers` and * returns an initialised `WalletModule` or array of `WalletModule`s. */ export type WalletInit = ( helpers: WalletHelpers ) => WalletModule | WalletModule[] | null export type WalletHelpers = { device: Device } export interface APIKey { apiKey: string } export type Device = { os: DeviceOS type: DeviceType browser: DeviceBrowser } export type Platform = DeviceOSName | DeviceBrowserName | DeviceType | 'all' export type DeviceOS = { name: DeviceOSName version: string } export type DeviceBrowser = { name: DeviceBrowserName version: string } export type DeviceOSName = | 'Windows Phone' | 'Windows' | 'macOS' | 'iOS' | 'Android' | 'Linux' | 'Chrome OS' export type DeviceBrowserName = | 'Android Browser' | 'Chrome' | 'Chromium' | 'Firefox' | 'Microsoft Edge' | 'Opera' | 'Safari' export type DeviceType = 'desktop' | 'mobile' | 'tablet' export interface WalletModule { // The label of the wallet label: string /** * Gets the icon of the wallet * @returns */ getIcon: () => Promise /** * @returns the wallet interface associated with the module */ getInterface: (helpers: GetInterfaceHelpers) => Promise } export type GetInterfaceHelpers = { chains: Chain[] appMetadata: AppMetadata | null BigNumber: typeof ethers.BigNumber EventEmitter: typeof EventEmitter } export type ChainId = string export type DecimalChainId = number export type RpcUrl = string export type WalletInterface = { provider: EIP1193Provider instance?: unknown } export interface ProviderRpcError extends Error { message: string code: number data?: unknown } export interface ProviderMessage { type: string data: unknown } export interface ProviderInfo { chainId: ChainId } export type AccountAddress = string /** * An array of addresses */ export type ProviderAccounts = AccountAddress[] export type ProviderEvent = | 'connect' | 'disconnect' | 'message' | 'chainChanged' | 'accountsChanged' export interface SimpleEventEmitter { on( event: ProviderEvent, listener: | ConnectListener | DisconnectListener | MessageListener | ChainListener | AccountsListener ): void removeListener( event: ProviderEvent, listener: | ConnectListener | DisconnectListener | MessageListener | ChainListener | AccountsListener ): void } export type ConnectListener = (info: ProviderInfo) => void export type DisconnectListener = (error: ProviderRpcError) => void export type MessageListener = (message: ProviderMessage) => void export type ChainListener = (chainId: ChainId) => void export type AccountsListener = (accounts: ProviderAccounts) => void /** * The hexadecimal representation of the users */ export type Balance = string export interface TransactionObject { data?: string from: string gas?: string gasLimit?: string gasPrice?: string to: string chainId: number value?: string maxFeePerGas?: string maxPriorityFeePerGas?: string nonce?: string } interface BaseRequest { params?: never } export interface EthAccountsRequest extends BaseRequest { method: 'eth_accounts' } export interface EthChainIdRequest extends BaseRequest { method: 'eth_chainId' } export interface EthSignTransactionRequest { method: 'eth_signTransaction' params: [TransactionObject] } type Address = string type Message = string export interface EthSignMessageRequest { method: 'eth_sign' params: [Address, Message] } //https://geth.ethereum.org/docs/rpc/ns-personal#personal_sign export interface PersonalSignMessageRequest { method: 'personal_sign' params: [Message, Address] } // request -> signTypedData_v3` export interface EIP712Request { method: 'eth_signTypedData' params: [Address, EIP712TypedData] } export interface EthBalanceRequest { method: 'eth_getBalance' params: [string, (number | 'latest' | 'earliest' | 'pending')?] } export interface EIP1102Request extends BaseRequest { method: 'eth_requestAccounts' } export interface SelectAccountsRequest extends BaseRequest { method: 'eth_selectAccounts' } export interface EIP3085Request { method: 'wallet_addEthereumChain' params: AddChainParams[] } export interface EIP3326Request { method: 'wallet_switchEthereumChain' params: [{ chainId: ChainId }] } export type AddChainParams = { chainId: ChainId chainName?: string nativeCurrency: { name?: string symbol?: string decimals: number } rpcUrls: string[] } export interface EIP1193Provider extends SimpleEventEmitter { on(event: 'connect', listener: ConnectListener): void on(event: 'disconnect', listener: DisconnectListener): void on(event: 'message', listener: MessageListener): void on(event: 'chainChanged', listener: ChainListener): void on(event: 'accountsChanged', listener: AccountsListener): void request(args: EthAccountsRequest): Promise request(args: EthBalanceRequest): Promise request(args: EIP1102Request): Promise request(args: SelectAccountsRequest): Promise request(args: EIP3326Request): Promise request(args: EIP3085Request): Promise request(args: EthChainIdRequest): Promise request(args: EthSignTransactionRequest): Promise request(args: EthSignMessageRequest): Promise request(args: PersonalSignMessageRequest): Promise request(args: EIP712Request): Promise request(args: { method: string; params?: Array }): Promise disconnect?(): void } export enum ProviderRpcErrorCode { ACCOUNT_ACCESS_REJECTED = 4001, ACCOUNT_ACCESS_ALREADY_REQUESTED = -32002, UNAUTHORIZED = 4100, INVALID_PARAMS = -32602, UNSUPPORTED_METHOD = 4200, DISCONNECTED = 4900, CHAIN_DISCONNECTED = 4901, CHAIN_NOT_ADDED = 4902, DOES_NOT_EXIST = -32601, UNRECOGNIZED_CHAIN_ID = -32603 } export interface Chain { /** * String indicating chain namespace. * Defaults to 'evm' but will allow other chain namespaces in the future */ namespace?: 'evm' /* Hex encoded string, eg '0x1' for Ethereum Mainnet */ id: ChainId /** * Recommended to include. Used for network requests * (eg Alchemy or Infura end point). * PLEASE NOTE: Some wallets require an rpcUrl, label, * and token for actions such as adding a new chain. * It is recommended to include rpcUrl, label, * and token for full functionality. */ rpcUrl?: string /* Recommended to include. Used for display, eg Ethereum Mainnet */ label?: string /* Recommended to include. The native token symbol, eg ETH, BNB, MATIC */ token?: TokenSymbol /** * An optional array of tokens (max of 5) to be available to the dapp in the * app state object per wallet within the wallet account and displayed * in Account Center (if enabled) */ secondaryTokens?: SecondaryTokens[] /** * The color used to represent the chain and * will be used as a background for the icon */ color?: string /* Svg string. The icon to represent the chain */ icon?: string /* Related to ConnectionInfo from 'ethers/lib/utils' */ providerConnectionInfo?: ConnectionInfo /* An optional public RPC used when adding a new chain config to the wallet */ publicRpcUrl?: string /** An optional protected RPC URL - Defaults to Blocknative's private and * protected RPC to allow users to update the chain RPC within their wallet, * specifically for private RPCs that protect user transactions */ protectedRpcUrl?: string /* Also used when adding a new config to the wallet */ blockExplorerUrl?: string } export interface SecondaryTokens { /** * Required - The onchain address of the token associated * with the chain it is entered under */ address: string /** * An optional svg or url string for the icon of the token. * If an svg is used ensure the height/width is set to 100% */ icon?: string } export type ChainWithDecimalId = Omit & { id: DecimalChainId } export type TokenSymbol = string // eg ETH export interface CustomNetwork { networkId: number genesis: GenesisBlock hardforks: Hardfork[] bootstrapNodes: BootstrapNode[] } export interface GenesisBlock { hash: string timestamp: string | null gasLimit: number difficulty: number nonce: string extraData: string stateRoot: string } export interface Hardfork { name: string block: number | null } export interface BootstrapNode { ip: string port: number | string network?: string chainId?: number id: string location: string comment: string } export interface RPCResponse { id: number jsonrpc: string error?: { code: number; message: string } result?: any }