abcwallet-extension-provider-api

ABC Wallet injects a global API into website visited by its users at `window.abc`. This API complies [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193), Ethereum Javascript provider API. We recommend using `@abcwallet/abc-provider` to detect our provider


Keywords
Ethereum, provider, extension, javascript, abcwallet
License
MIT
Install
npm install abcwallet-extension-provider-api@0.1.1

Documentation

ABC Wallet Extension Provider API

ABC Wallet injects a global API into website visited by its users at window.abc. This API complies EIP-1193, Ethereum Javascript provider API. We recommend using abcwallet-extension-provider-api to detect our provider on any platform or browser.

Please download ABC Wallet chrome extension below: ABC Wallet Extension Download

import ABCProvider from 'abcwallet-extension-provider-api'; 
   
const currentProvider = await ABCProvider();
if (currentProvider) {

  await currentProvider.request({ method: 'eth_requestAccounts' });

  const web3 = new Web3(currentProvider);  
  
  const userAccount = await web3.eth.getAccounts();
  const account = userAccount[0];

  const chainId = await web3.eth.getChainId();
  ...
}

Table of Contents

Compatibility

ABC Wallet support multi-chain functionality. At the moment of writing, MetaMask is dominant crypto wallet for Ethereum and Kaikas is for Klaytn.

For Ethereum, EIP-1193 clearly states window.ethereum is not part of the specification, however, to maximize the compatibility, ABC Wallet provider window.abc is also cloned to window.ethereum, and functions like MetaMask.

For Klaytn, although we weren't able to find KIP equivalent or standards. However, Kaikas API documentation specifies window.klaytn as default provider.

For maximum compatibility and user's convenience, we created same APIs compatible on both wallet providers.

Through out this document, you may consider window.abc is linked clone to to window.ethereum and window.klaytn.

Update(Nov. 2022): Please note starting from version 0.00.13, availability of window.ethereum and/or window.klaytn depends by user's option. Unless user have intentionally enabled, these options are OFF by default, resulting window.abc as only provider for ABC Wallet.

Basic Usage

For any non-trivial EVM based web application — a.k.a. dapp, web3 site etc. — to work, you will have to:

  • Detect the provider (window.abc)
  • Detect which network the user is connected to
  • Get the user's account

The snippet at the top of this page is sufficient for detecting the provider.

As a multi-chain supported wallet, ABC Wallet provides multiple ways on accessing provider functions for maximum compatibility, including ethers.

For icons, please refer to /icon directory for right size for your DApp.

We recommend to use convenience library, however, in cases where you need to directly access provider, please check Using the Provider section.

Chain IDs

These are the IDs of the Blockchain networks that ABC Wallet supports by default. Check website ChainList for more.

Hex Decimal Network
0x1 1 Ethereum Main Network (Mainnet)
0x5 5 Goerli Test Network
0x2019 8217 Klaytn Main Network (Cypress)
0x3e9 1001 Klaytn Test Network (Baobab)
0x38 56 Binance Smart Chain Mainnet
0x61 97 Binance Smart Chain Testnet
0x89 137 Matic Main Network
0x13881 80001 Matic Test Network (Mumbai)

Properties

abc.isABC

Note that this property is non-standard.

true if the user has ABC Wallet installed.

abc.chainId

Returns chain ID in hex.

window.abc.chainId;
> "0x89"

abc.networkVersion

These properties can be used to check the current state of the connected user, which can be important things to verify before sending a transaction. Returns decimal Chain ID in string type.

abc.networkVersion;
> "137"

abc.selectedAddress

Returns a hex-prefixed string representing the current user's selected address.

abc.selectedAddress
> "0x0e9bc621207f12ff37589a2f234b7d1a920df135"

Methods

abc.isConnected()

abc.isConnected();
> true

Returns true if the provider is connected to the current chain, and false otherwise.

In addition, ABC Wallet supports own provider abc which works exactly same as ethereum provider.

If the provider is not connected, the page will have to be reloaded in order for connection to be re-established. Please see the connect and disconnect events for more information.

abc.request(args)

interface RequestArguments {
  method: string;
  params?: unknown[] | object;
}

abc.request(args: RequestArguments): Promise<unknown>;

Use request to submit RPC requests to Ethereum via ABC Wallet. It returns a Promise that resolves to the result of the RPC method call.

The params and return value will vary by RPC method. In practice, if a method has any params, they are almost always of type Array<any>.

If the request fails for any reason, the Promise will reject with an RPC Error.

ABC Wallet supports most standardized Ethereum RPC methods, in addition to a number of methods that may not be supported by other wallets. See the ABC Wallet RPC API documentation for details.

Example

params: [
  {
    from: '0x0e9bc621207f12ff37589a2f234b7d1a920df135',
    to: '0xd40e8dd67c5d32be8058bb8eb970870f07244567',
    gas: '0x76c0', // 30400
    gasPrice: '0x9184e72a000', // 10000000000000
    value: '0x9184e72a', // 2441406250
    data: '0xd40e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675',
  },
];

abc
  .request({
    method: 'eth_sendTransaction',
    params,
  })
  .then((result) => {
    // The result varies by RPC method.
    // For example, this method will return a transaction hash hexadecimal string on success.
  })
  .catch((error) => {
    // If the request fails, the Promise will reject with an error.
  });

Events

The ABC Wallet provider implements the Node.js EventEmitter API. This sections details the events emitted via that API. There are innumerable EventEmitter guides elsewhere, but you can listen for events like this:

abc.on('accountsChanged', (accounts) => {
  // Handle the new accounts, or lack thereof.
  // "accounts" will always be an array, but it can be empty.
});

abc.on('chainChanged', (chainId) => {
  // Handle the new chain.
  // Correctly handling chain changes can be complicated.
  // We recommend reloading the page unless you have good reason not to.
  window.location.reload();
});

Also, don't forget to remove listeners once you are done listening to them (for example on component unmount in React):

function handleAccountsChanged(accounts) {
  // ...
}

abc.on('accountsChanged', handleAccountsChanged);

// Later

abc.removeListener('accountsChanged', handleAccountsChanged);

The first argument of the abc.removeListener is the event name and the second argument is the reference to the same function which has passed to abc.on for the event name mentioned in the first argument.

connect

interface ConnectInfo {
  chainId: string;
}

abc.on('connect', handler: (connectInfo: ConnectInfo) => void);

The ABC Wallet provider emits this event when it first becomes able to submit RPC requests to a chain. We recommend using a connect event handler and the abc.isConnected() method in order to determine when/if the provider is connected.

disconnect

abc.on('disconnect', handler: (error: ProviderRpcError) => void);

The ABC Wallet provider emits this event if it becomes unable to submit RPC requests to any chain. In general, this will only happen due to network connectivity issues or some unforeseen error.

Once disconnect has been emitted, the provider will not accept any new requests until the connection to the chain has been re-established, which requires reloading the page. You can also use the ethereum.isConnected() method to determine if the provider is disconnected.

accountsChanged

abc.on('accountsChanged', handler: (accounts: Array<string>) => void);

The ABC Wallet provider emits this event whenever the return value of the eth_accounts RPC method changes. eth_accounts returns an array that is either empty or contains a single account address. The returned address, if any, is the address of the most recently used account that the caller is permitted to access. Callers are identified by their URL origin, which means that all sites with the same origin share the same permissions.

This means that accountsChanged will be emitted whenever the user's exposed account address changes.

chainChanged

abc.on('chainChanged', handler: (chainId: string) => void);

The ABC Wallet provider emits this event when the currently connected chain changes.

All RPC requests are submitted to the currently connected chain. Therefore, it's critical to keep track of the current chain ID by listening for this event.

We strongly recommend reloading the page on chain changes, unless you have good reason not to.

abc.on('chainChanged', (_chainId) => window.location.reload());

message

interface ProviderMessage {
  type: string;
  data: unknown;
}
abc.on('message', handler: (message: ProviderMessage) => void);

The ABC Wallet provider emits this event when it receives some message that the consumer should be notified of. The kind of message is identified by the type string.

RPC subscription updates are a common use case for the message event. For example, if you create a subscription using eth_subscribe, each subscription update will be emitted as a message event with a type of eth_subscription.

Errors

All errors thrown or returned by the ABC Wallet provider follow this interface:

interface ProviderRpcError extends Error {
  message: string;
  code: number;
  data?: unknown;
}

The abc.request(args) method throws errors eagerly. You can often use the error code property to determine why the request failed. Common codes and their meaning include:

  • 4001: The request was rejected by the user
  • 32602: The parameters were invalid
  • 32603: Internal error

For the complete list of errors, please see EIP-1193 and EIP-1474.

The eth-rpc-errors package implements all RPC errors thrown by the ABC Wallet provider, and can help you identify their meaning.

Using the Provider

This snippet explains how to accomplish the three most common requirements for web3 sites:

  • Detect the ABC provider (window.abc)
  • Detect which Network the user is connected to
  • Get the user's account(s)
/*****************************************/
/* Detect the ABC Wallet Ethereum provider */
/*****************************************/

import ABCProvider from 'abcwallet-extension-provider-api';

// this returns the provider, or null if it wasn't detected
const provider = await ABCProvider();

if (provider) {
  startApp(provider); // Initialize your app
} else {
  console.log('Please install ABC Wallet!');
}

function startApp(provider) {
  // If the provider returned by ABCProvider is not the same as
  // window.abc, something is overwriting it, perhaps another wallet.
  if (provider !== window.abc) {
    console.error('Do you have multiple wallets installed?');
  }
  // Access the decentralized web!
}

/**********************************************************/
/* Handle chain (network) and chainChanged (per EIP-1193) */
/**********************************************************/

const chainId = await abc.request({ method: 'eth_chainId' });
handleChainChanged(chainId);

abc.on('chainChanged', handleChainChanged);

function handleChainChanged(_chainId) {
  // We recommend reloading the page, unless you must do otherwise
  window.location.reload();
}

/***********************************************************/
/* Handle user accounts and accountsChanged (per EIP-1193) */
/***********************************************************/

let currentAccount = null;
abc
  .request({ method: 'eth_accounts' })
  .then(handleAccountsChanged)
  .catch((err) => {
    // Some unexpected error.
    // For backwards compatibility reasons, if no accounts are available,
    // eth_accounts will return an empty array.
    console.error(err);
  });

// Note that this event is emitted on page load.
// If the array of accounts is non-empty, you're already
// connected.
abc.on('accountsChanged', handleAccountsChanged);

// For now, 'eth_accounts' will continue to always return an array
function handleAccountsChanged(accounts) {
  if (accounts.length === 0) {
    // ABC Wallet is locked or the user has not connected any accounts
    console.log('Please connect to ABC Wallet.');
  } else if (accounts[0] !== currentAccount) {
    currentAccount = accounts[0];
    // Do any other work!
  }
}

/*********************************************/
/* Access the user's accounts (per EIP-1102) */
/*********************************************/

// You should only attempt to request the user's accounts in response to user
// interaction, such as a button click.
// Otherwise, you popup-spam the user like it's 1999.
// If you fail to retrieve the user's account(s), you should encourage the user
// to initiate the attempt.
document.getElementById('connectButton', connect);

// While you are awaiting the call to eth_requestAccounts, you should disable
// any buttons the user can click to initiate the request.
// ABC Wallet will reject any additional requests while the first is still
// pending.
function connect() {
  abc.request({ method: 'eth_requestAccounts' })
    .then(handleAccountsChanged)
    .catch((err) => {
      if (err.code === 4001) {
        // EIP-1193 userRejectedRequest error
        // If this happens, the user rejected the connection request.
        console.log('Please connect to ABC Wallet.');
      } else {
        console.error(err);
      }
    });
}