# RPC API

TokenPocket Extension uses the [ethereum.request(args)](https://help.tokenpocket.pro/developer-en/extension-wallet/ethereum-provider-api#ethereum-request-args) to wrap an RPC API.

The API is based on an interface exposed by all Ethereum clients, along with a growing number of methods that may or may not be supported by other wallets.

{% hint style="success" %}
Tip

All RPC method requests can return errors. Make sure to handle errors for every call to ethereum.request(args)
{% endhint %}

### **Ethereum JSON-RPC Methods**

For the Ethereum JSON-RPC API, please see the [Ethereum wiki](https://eth.wiki/json-rpc/API#json-rpc-methods)

**​​**Important methods from this API include:

* [`eth_accounts`](https://eth.wiki/json-rpc/API#eth_accounts)
* [`eth_call`](https://eth.wiki/json-rpc/API#eth_call)
* [`eth_getBalance`](https://eth.wiki/json-rpc/API#eth_getbalance)
* [`eth_sendTransaction`](https://eth.wiki/json-rpc/API#eth_sendtransaction)
* [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)

### **Restricted Methods**

TokenPocket Extension introduced Web3.0 Wallet Permissions via EIP-2255. In this permissions system, each RPC method is either restricted or unrestricted. If a method is restricted, the caller must have the corresponding permission in order to call it. Unrestricted methods, meanwhile, have no corresponding permission. Some of them still rely upon permissions to succeed though (e.g., the signing methods require that you have the eth\_accounts permission for the signer account), and some require confirmation by the user (e.g., wallet\_addEthereumChain).

Under the hood, permissions are plain, JSON-compatible objects, with a number of fields that are mostly used internally by TokenPocket Extension. The following interface lists the fields that may be of interest to consumers:

```typescript
interface Web3WalletPermission {
  // The name of the method corresponding to the permission
  parentCapability: string;

  // The date the permission was granted, in UNIX epoch time
  date?: number;
}
```

If you're interested in learning more about the theory behind this capability-inspired permissions system, we encourage you to take a look at [EIP-2255](https://eips.ethereum.org/EIPS/eip-2255)

#### `eth_requestAccounts` <a href="#eth-requestaccounts" id="eth-requestaccounts"></a>

{% hint style="success" %}
EIP-1102

This method is specified by [EIP-1102](https://eips.ethereum.org/EIPS/eip-1102). It is equivalent to the deprecated ethereum.enable() provider API method.

Under the hood, it calls wallet\_requestPermissions for the eth\_accounts permission. Since eth\_accounts is currently the only permission, this method is all you need for now.
{% endhint %}

**Returns**

`string[]`- An array of a single, hexadecimal Ethereum address string.

**Description**

Requests that the user provides an Ethereum address to be identified by. Returns a Promise that resolves to an array of a single Ethereum address string. If the user denies the request, the Promise will reject with a 4001 error.

The request causes a TokenPocket Extension pop-up to appear. You should only request the user's accounts in response to user action, such as a button click. You should always disable the button that caused the request to be dispatched, while the request is still pending.

**Example**

```javascript
document.getElementById('connectButton', connect);

function connect() {
  ethereum
    .request({ method: 'eth_requestAccounts' })
    .then(handleAccountsChanged)
    .catch((error) => {
      if (error.code === 4001) {
        // EIP-1193 userRejectedRequest error
        console.log('Please connect to TokenPocket Extension.');
      } else {
        console.error(error);
      }
    });
}
```

#### `wallet_getPermissions` <a href="#wallet-getpermissions" id="wallet-getpermissions"></a>

{% hint style="success" %}
Platform Availability

This RPC method is not yet available in TokenPocket Extension Mobile.
{% endhint %}

**Returns**

`Web3WalletPermission[]`- An array of the caller's permissions.

**Description**

Gets the caller's current permissions. Returns a Promise that resolves to an array of Web3.0 Wallet Permission objects. If the caller has no permissions, the array will be empty.

#### `wallet_requestPermissions` <a href="#wallet-requestpermissions" id="wallet-requestpermissions"></a>

{% hint style="success" %}
Platform Availability

This RPC method is not yet available in TokenPocket Extension Mobile.
{% endhint %}

**Parameters**

* `Array`
  1. `RequestedPermissions`- The requested permissions.

```javascript
interface RequestedPermissions {
  [methodName: string]: {}; // an empty object, for future extensibility
}
```

**Returns**

`Web3WalletPermission[]`- An array of the caller's permissions.

**Description**

Requests the given permissions from the user. Returns a Promise that resolves to a non-empty array of Web3.0WalletPermission objects, corresponding to the caller's current permissions. If the user denies the request, the Promise will reject with a 4001 error.

The request causes a TokenPocket Extension popup to appear. You should only request permissions in response to user action, such as a button click.

**Example**

```javascript
document.getElementById('requestPermissionsButton', requestPermissions);

function requestPermissions() {
  ethereum
    .request({
      method: 'wallet_requestPermissions',
      params: [{ eth_accounts: {} }],
    })
    .then((permissions) => {
      const accountsPermission = permissions.find(
        (permission) => permission.parentCapability === 'eth_accounts'
      );
      if (accountsPermission) {
        console.log('eth_accounts permission successfully requested!');
      }
    })
    .catch((error) => {
      if (error.code === 4001) {
        // EIP-1193 userRejectedRequest error
        console.log('Permissions needed to continue.');
      } else {
        console.error(error);
      }
    });
}
```

### **Unrestricted Methods**

#### `eth_decrypt` <a href="#eth-decrypt" id="eth-decrypt"></a>

{% hint style="success" %}
Platform Availability

This RPC method is not yet available in TokenPocket Extension Mobile.
{% endhint %}

**Parameters**

* `Array`
  1. `string`-  An encrypted message.
  2. `string`- The address of the Ethereum account that can decrypt the message.

**Returns**

`string`- The decrypted message.

**Description**

Requests that TokenPocket Extension decrypts the given encrypted message. The message must have been encrypted using the public encryption key of the given Ethereum address. Returns a Promise that resolves to the decrypted message, or rejects if the decryption attempt fails.

See eth\_getEncryptionPublicKey for more information.

**Example**

```javascript
ethereum
  .request({
    method: 'eth_decrypt',
    params: [encryptedMessage, accounts[0]],
  })
  .then((decryptedMessage) =>
    console.log('The decrypted message is:', decryptedMessage)
  )
  .catch((error) => console.log(error.message));
```

#### `eth_getEncryptionPublicKey` <a href="#eth-getencryptionpublickey" id="eth-getencryptionpublickey"></a>

{% hint style="success" %}
Platform Availability

This RPC method is not yet available in TokenPocket Extension Mobile.
{% endhint %}

**Parameters**

* `Array`
  1. `string`- The address of the Ethereum account whose encryption key should be retrieved.

**Returns**

`string`- The public encryption key of the specified Ethereum account.

**Description**

Requests that the user shares their public encryption key. Returns a Promise that resolves to the public encryption key, or rejects if the user denies the request.

The public key is computed from entropy associated with the specified user account, using the[ nacl](https://github.com/dchest/tweetnacl-js) implementation of the X25519\_XSalsa20\_Poly1305 algorithm.

**Example**

```javascript
let encryptionPublicKey;

ethereum
  .request({
    method: 'eth_getEncryptionPublicKey',
    params: [accounts[0]], // you must have access to the specified account
  })
  .then((result) => {
    encryptionPublicKey = result;
  })
  .catch((error) => {
    if (error.code === 4001) {
      // EIP-1193 userRejectedRequest error
      console.log("We can't encrypt anything without the key.");
    } else {
      console.error(error);
    }
  });
```

**Encrypting**

```javascript
const ethUtil = require('ethereumjs-util');
const sigUtil = require('@metamask/eth-sig-util');

const encryptedMessage = ethUtil.bufferToHex(
  Buffer.from(
    JSON.stringify(
      sigUtil.encrypt({
        publicKey: encryptionPublicKey,
        data: 'hello world!',
        version: 'x25519-xsalsa20-poly1305',
      })
    ),
    'utf8'
  )
);
```

#### `wallet_addEthereumChain` <a href="#wallet-addethereumchain" id="wallet-addethereumchain"></a>

{% hint style="success" %}
EIP-3085

This method is specified by [EIP-3085](https://eips.ethereum.org/EIPS/eip-3085)
{% endhint %}

**Parameters**

* `Array`
  1. `AddEthereumChainParameter`- Metadata about the chain that will be added to TokenPocket Extension.

For the `rpcUrls` and `blockExplorerUrls` arrays, at least one element is required, and only the first element will be used.

```javascript
interface AddEthereumChainParameter {
  chainId: string; // A 0x-prefixed hexadecimal string
  chainName: string;
  nativeCurrency: {
    name: string;
    symbol: string; // 2-6 characters long
    decimals: 18;
  };
  rpcUrls: string[];
  blockExplorerUrls?: string[];
  iconUrls?: string[]; // Currently ignored.
}
```

**Returns**

`null`- The method returns null if the request was successful, and an error otherwise.

**Description**

Creates a confirmation asking the user to add the specified chain to TokenPocket Extension. The user may choose to switch to the chain once it has been added.

As with any method that causes a confirmation to appear, `wallet_addEthereumChain` should only be called as a result of direct user action, such as the click of a button.

TokenPocket Extension stringently validates the parameters for this method, and will reject the request if any parameter is incorrectly formatted.

* If the RPC endpoint doesn't respond to RPC calls.
* If the RPC endpoint returns a different chain ID when eth\_chainId is called.
* If the chain ID corresponds to any default TokenPocket Extension chains.

TokenPocket Extension does not yet support chains with native currencies that do not have 18 decimals, but may do so in the future.

**`Useage with wallet_switchEthereumChain`**

We recommend using this method with [wallet\_addEthereumChain](#wallet-addethereumchain)：

```javascript
try {
  await ethereum.request({
    method: 'wallet_switchEthereumChain',
    params: [{ chainId: '0xf00' }],
  });
} catch (switchError) {
  // This error code indicates that the chain has not been added to TokenPocket Extension.
  if (switchError.code === 4902) {
    try {
      await ethereum.request({
        method: 'wallet_addEthereumChain',
        params: [
          {
            chainId: '0xf00',
            chainName: '...',
            rpcUrls: ['https://...'] /* ... */,
          },
        ],
      });
    } catch (addError) {
      // handle "add" error
    }
  }
  // handle other "switch" errors
}
```

#### `wallet_switchEthereumChain` <a href="#wallet-switchethereumchain" id="wallet-switchethereumchain"></a>

{% hint style="success" %}
EIP-3326

​This method is specified by[ EIP-3326](https://ethereum-magicians.org/t/eip-3326-wallet-switchethereumchain/5471)
{% endhint %}

**Parameters**

* `Array`
  1. `SwitchEthereumChainParameter`- Metadata about the chain that TokenPocket Extension will switch to.

```javascript
interface SwitchEthereumChainParameter {
  chainId: string; // A 0x-prefixed hexadecimal string
}
```

#### `Returns`

`null`- The method returns null if the request was successful, and an error otherwise.

If the error code (error.code) is 4902, then the requested chain has not been added by TokenPocket Extension, and you have to request to add it via [wallet\_addEthereumChain](#wallet-addethereumchain).

**Description**

{% hint style="success" %}
Tip

See [above](#wallet-switchethereumchain) for how to use this method with wallet\_addEthereumChain
{% endhint %}

Creates a confirmation asking the user to switch to the chain with the specified chainId.

As with any method that causes a confirmation to appear, `wallet_switchEthereumChain` should only be called as a result of a direct user action, such as the click of a button.&#x20;

TokenPocket Extension will automatically reject the request under the following circumstances:

* If the chain ID is malformed
* If the chain with the specified chain ID has not been added to TokenPocket Extension

#### `wallet_registerOnboarding` <a href="#wallet-registeronboarding" id="wallet-registeronboarding"></a>

{% hint style="success" %}
Tip

As an API consumer, you are unlikely to have to call this method yourself.
{% endhint %}

**Returns**

`boolean` - `true` if the request was successful, `false` otherwise.

**Description**

Registers the requesting site with TokenPocket Extension as the initiator of onboarding. Returns a Promise that resolves to true, or rejects if there's an error.

This method is intended to be called after TokenPocket Extension has been installed, but before the TokenPocket Extension onboarding has been completed. You can use this method to inform TokenPocket Extension that you were the one that suggested installing TokenPocket Extension. This lets TokenPocket Extension redirect the user back to your site after onboarding has been completed.

#### `wallet_watchAsset` <a href="#wallet-watchasset" id="wallet-watchasset"></a>

{% hint style="success" %}
EIP-747

This method is specified by [EIP-747](https://eips.ethereum.org/EIPS/eip-747)
{% endhint %}

**Parameters**

* `WatchAssetParams`- The metadata of the asset to watch.

```javascript
interface WatchAssetParams {
  type: 'ERC20'; // In the future, other standards will be supported
  options: {
    address: string; // The address of the token contract
    'symbol': string; // A ticker symbol or shorthand, up to 5 characters
    decimals: number; // The number of token decimals
    image: string; // A string url of the token logo
  };
}
```

#### Returns

`boolean` - `true` if the token was added, `false` otherwise.

**Description**

Requests that the user tracks the token in TokenPocket Extension. Returns a boolean indicating if the token was successfully added.

Most Ethereum wallets support some set of tokens, usually from a centrally curated registry of tokens. wallet\_watchAsset enables Web3.0 application developers to ask their users to track tokens in their wallets, at runtime. Once added, the token is indistinguishable from those added via legacy methods, such as a centralized registry.

**Example**

```javascript
ethereum
  .request({
    method: 'wallet_watchAsset',
    params: {
      type: 'ERC20',
      options: {
        address: '0xb60e8dd61c5d32be8058bb8eb970870f07233155',
        symbol: 'FOO',
        decimals: 18,
        image: 'https://foo.io/token-image.svg',
      },
    },
  })
  .then((success) => {
    if (success) {
      console.log('FOO successfully added to wallet!');
    } else {
      throw new Error('Something went wrong.');
    }
  })
  .catch(console.error);
```
