# OWallet

## Universal gateway to Web3

OWallet supports all web3 activities on most common liquidity networks, which are

* Bitcoin
* EVM-based: Ethereum, BNB Chain, Oasis / Oasis Sapphire
* Cosmos-based: Oraichain, Osmosis, Injective, Cosmos Hub...
* TVM-based: TRON network

OWallet is forked from Keplr extension and continuously developed by Oraichain Labs.

## OWallet’s key features

* Supports multiple accounts Bitcoin & Cosmos-based & EVM-based networks simultaneously
* Universal swap across various networks
* Portfolio management with cross-chain assets: Multi accounts, Send/Recieve, Price history...
* History of on-chain activities
* Friendly interface on transaction confirmation
* Future support for Ledger hardware wallets;
* Available on mobile apps and web extensions for greater accessibility.

## Useful links

Source code: <https://github.com/oraichain/owallet> (You can create a pull request to add your network.)

OWallet website: [https://owallet.dev](https://owallet.dev/)

Contact: <https://x.com/owallet_dev>


# OWallet Cosmos-based API

{% hint style="info" %}
Since OWallet Extension is forked on [Keplr Wallet](https://github.com/chainapsis/keplr-wallet), its basic API & integration methods are similar to those of Keplr.
{% endhint %}

## How to detect OWallet Extension for Cosmos-based networks

The OWallet object is injected into the `window` object as `window.owallet` or `window.keplr` for backward compatibility with the Keplr Wallet. If it is **undefined**, then you will need to install it on the browser first. Similarly to the Keplr's documentation, there are a few ways to check the object's status:

```javascript
window.onload = async () => {
    if (!window.owallet) {
        alert("Please install owallet extension");
    } else {
        const chainId = "Oraichain";
        await window.owallet.enable(chainId);
    }
}
```

or you can check the browser document's state:

```javascript
function getOWallet(): Promise<OWallet | undefined> {
    if (window.owallet) {
        return window.owallet;
    }
    
    if (document.readyState === "complete") {
        return window.owallet;
    }
    
    return new Promise((resolve) => {
        const documentStateChange = (event: Event) => {
            if (
                event.target &&
                (event.target as Document).readyState === "complete"
            ) {
                resolve(window.owallet);
                document.removeEventListener("readystatechange", documentStateChange);
            }
        };
        
        document.addEventListener("readystatechange", documentStateChange);
    });
}
```

## Features

We share the same features as Keplr's when it comes to the Cosmos-based networks. Hence, the below documentation about the features are brought from the [Keplr Wallet documentation website](https://docs.keplr.app/api/) with slight modifications.

### Using with Typescript

**`window.d.ts`**

```javascript
import { Window as OWalletWindow } from "@owallet/types";

declare global {
  // eslint-disable-next-line @typescript-eslint/no-empty-interface
  interface Window extends OWalletWindow {}
}
```

The `@owallet/types` package has the type definition related to OWallet.\
If you're using TypeScript, run `npm install --save-dev @owallet/types` or `yarn add -D @owallet/types` to install `@owallet/types`.\
Then, you can add the `@owallet/types` window to a global window object and register the OWallet related types.

> Usage of any other packages besides @owallet/types is not recommended.
>
> * Any other packages besides @owallet/types are actively being developed, backward compatibility is not in the scope of support.
> * Since there are active changes being made, documentation is not being updated to the most recent version of the package as of right now. Documentations would be updated as packages get stable.

### Enable Connection

```javascript
enable(chainIds: string | string[]): Promise<void>
```

The `window.owallet.enable(chainIds)` method requests the extension to be unlocked if it's currently locked. If the user hasn't given permission to the webpage, it will ask the user to give permission for the webpage to access OWallet.

`enable` method can receive one or more chain-id as an array. When the array of chain-id is passed, you can request permissions for all chains that have not yet been authorized at once.

If the user cancels the unlock or rejects the permission, an error will be thrown.

### Get Address / Public Key

```javascript
getKey(chainId: string): Promise<{
    // Name of the selected key store.
    name: string;
    algo: string;
    pubKey: Uint8Array;
    address: Uint8Array;
    bech32Address: string;
}>
```

If the webpage has permission and OWallet is unlocked, this function will return the address and public key in the following format:

```javascript
{
    // Name of the selected key store.
    name: string;
    algo: string;
    pubKey: Uint8Array;
    address: Uint8Array;
    bech32Address: string;
    isNanoLedger: boolean;
}
```

It also returns the nickname for the key store currently selected, which should allow the webpage to display the current key store selected to the user in a more convenient mane.\
`isNanoLedger` field in the return type is used to indicate whether the selected account is from the Ledger Nano. Because current Cosmos app in the Ledger Nano doesn't support the direct (protobuf) format msgs, this field can be used to select the amino or direct signer. [Ref](https://github.com/oraichain/owallet-docs/blob/master/owallet/cosmjs.md#types-of-offline-signers)

### Sign Amino

```javascript
signAmino(chainId: string, signer: string, signDoc: StdSignDoc): Promise<AminoSignResponse>
```

Similar to CosmJS `OfflineSigner`'s `signAmino`, but OWallet's `signAmino` takes the chain-id as a required parameter. Signs Amino-encoded `StdSignDoc`.

### Sign Direct / Protobuf

```javascript
signDirect(chainId:string, signer:string, signDoc: {
    /** SignDoc bodyBytes */
    bodyBytes?: Uint8Array | null;

    /** SignDoc authInfoBytes */
    authInfoBytes?: Uint8Array | null;

    /** SignDoc chainId */
    chainId?: string | null;

    /** SignDoc accountNumber */
    accountNumber?: Long | null;
  }): Promise<DirectSignResponse>
```

Similar to CosmJS `OfflineDirectSigner`'s `signDirect`, but OWallet's `signDirect` takes the chain-id as a required parameter. Signs Proto-encoded `StdSignDoc`.

### Request Transaction Broadcasting

```javascript
sendTx(
    chainId: string,
    tx: Uint8Array,
    mode: BroadcastMode
): Promise<Uint8Array>;
```

This function requests OWallet to delegates the broadcasting of the transaction to OWallet's LCD endpoints (rather than the webpage broadcasting the transaction). This method returns the transaction hash if it succeeds to broadcast, if else the method will throw an error. When OWallet broadcasts the transaction, OWallet will send the notification on the transaction's progress.

### Request Signature for Arbitrary Message

```javascript
signArbitrary(
    chainId: string,
    signer: string,
    data: string | Uint8Array
): Promise<StdSignature>;
verifyArbitrary(
    chainId: string,
    signer: string,
    data: string | Uint8Array,
    signature: StdSignature
): Promise<boolean>;
```

This is an experimental implementation of [ADR-36](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-036-arbitrary-signature.md). Use this feature at your own risk.

It's main usage is to prove ownership of an account off-chain, requesting ADR-36 signature using the `signArbitrary` API.

If requested sign doc with the `signAnimo` API with the ADR-36 that OWallet requires instead of using the `signArbitary` API, it would function as `signArbitary`

* Only supports sign doc in the format of Amino. (in the case of protobuf, [ADR-36](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-036-arbitrary-signature.md) requirements aren't fully specified for implementation)
* sign doc message should be single and the message type should be "sign/MsgSignData"
* sign doc "sign/MsgSignData" message should have "signer" and "data" as its value. "data" should be base64 encoded
* sign doc chain\_id should be an empty string("")
* sign doc memo should be an empty string("")
* sign doc account\_number should be "0"
* sign doc sequence should be "0"
* sign doc fee should be `{gas: "0", amount: []}`

When using the `signArbitrary` API, if the `data` parameter type is `string`, the signature page displays as plain text.

Using `verifyArbitrary`, you can verify the results requested by `signArbitrary` API or `signAmino` API that has been requested with the ADR-36 spec standards.

`verifyArbitrary` has been only implemented for simple usage. `verifyArbitrary` returns the result of the verification of the current selected account's sign doc. If the account is not the currently selected account, it would throw an error.

It is recommended to use `verifyADR36Amino` function in the `@owallet/cosmos` package or your own implementation instead of using `verifyArbitrary` API.

### Interaction Options

```javascript
export interface OWalletIntereactionOptions {
  readonly sign?: OWalletSignOptions;
}

export interface OWalletSignOptions {
  readonly preferNoSetFee?: boolean;
  readonly preferNoSetMemo?: boolean;
}
```

If `preferNoSetFee` is set to true, OWallet will prioritize the frontend-suggested fee rather than overriding the tx fee setting of the signing page.

If `preferNoSetMemo` is set to true, OWallet will not override the memo and set fix memo as the front-end set memo.

You can set the values as follows:

```javascript
window.owallet.defaultOptions = {
    sign: {
        preferNoSetFee: true,
        preferNoSetMemo: true,
    }
}
```

### Custom event

**Change Key Store Event**

```javascript
keplr_keystorechange
```

When the user switches their key store/account after the webpage has received the information on the key store/account the key that the webpage is aware of may not match the selected key in OWallet which may cause issues in the interactions.

To prevent this from happening, when the key store/account is changed, OWallet emits a `keplr_keystorechange` event to the webpage's window. You can request the new key/account based on this event listener.

```javascript
window.addEventListener("keplr_keystorechange", () => {
    console.log("Key store in OWallet is changed. You may need to refetch the account info.")
})
```

## CosmJS Integration

Similar to how Keplr [connects with CosmJS](https://docs.keplr.app/api/cosmjs.html), OWallet also uses `OfflineSigner` for Cosmos SDK Launchpad & `OfflineDirectSigner` for Cosmos SDK Stargate.

You can get the signer via:

```javascript
var offlineSigner = window.getOfflineSigner(chainId);
// or
var offlineSigner = await window.getOfflineSignerAuto(chainId);
// or
var offlineSigner = window.getOfflineSignerOnlyAmino(chainId);
```

then you can pass the `offlineSigner` variable into the `SigningCosmosClient`:

```javascript
// Initialize the gaia api with the offline signer that is injected by Keplr extension.
const cosmJS = new SigningCosmosClient(
    "https://rpc.orai.io",
    accounts[0].address,
    offlineSigner,
);
```

## Suggest chain

It works the same as the Keplr's [suggest chain feature](https://docs.keplr.app/api/suggest-chain.html), but with a slight change in the `ChainInfo` interface. We add several more fields to better filter networks within the Cosmos ecosystem.

dApps can request the wallet to add new Cosmos chains that are not supported by default. This allows the wallet to be fully decentralized & permissionless.

Below is the `ChainInfo` interface of the OWallet extension:

```javascript
interface ChainInfo {
    readonly rpc?: string;
    /**
     * evmRpc is only used for EVM-based networks, not Cosmos-based
     */
    readonly evmRpc?: string;
    readonly rpcConfig?: AxiosRequestConfig;
    readonly rest: string;
    readonly restConfig?: AxiosRequestConfig;
    readonly chainId: string;
    readonly chainName: string;
    readonly networkType: NetworkType;
    /**
     * This indicates the type of coin that can be used for stake.
     * You can get actual currency information from Currencies.
     */
    readonly stakeCurrency?: Currency;
    readonly bip44: BIP44;
    readonly alternativeBIP44s?: BIP44[];
    readonly bech32Config?: Bech32Config;
    readonly currencies: AppCurrency[];
    /**
     * This indicates which coin or token can be used for fee to send transaction.
     * You can get actual currency information from Currencies.
     */
    readonly feeCurrencies: Currency[];
    /**
     * This is the coin type in slip-044.
     * This is used for fetching address from ENS if this field is set.
     */
    readonly coinType?: number;
    /**
     * This is used to set the fee of the transaction.
     * If this field is empty, it just use the default gas price step (low: 0.01, average: 0.025, high: 0.04).
     * And, set field's type as primitive number because it is hard to restore the prototype after deserialzing if field's type is `Dec`.
     */
    readonly gasPriceStep?: {
        low: number;
        average: number;
        high: number;
    };
    /**
     * Indicate the features supported by this chain. Ex) cosmwasm, secretwasm ...
     */
    readonly features?: string[];
    /**
     * Shows whether the blockchain is in production phase or beta phase.
     * Major features such as staking and sending are supported on staging blockchains, but without guarantee.
     * If the blockchain is in an early stage, please set it as beta.
     */
    readonly beta?: boolean;
}
```

the suggest chain API is:

```javascript
experimentalSuggestChain(chainInfo: SuggestingChainInfo): Promise<void>
```

Examples:

```javascript
await window.keplr.experimentalSuggestChain({
    chainId: "Oraichain",
    chainName: "Oraichain",
    rpc: "https://rpc.orai.io",
    rest: "https://lcd.orai.io",
    bip44: {
        coinType: 118,
    },
    bech32Config: {
        bech32PrefixAccAddr: "orai",
        bech32PrefixAccPub: "orai" + "pub",
        bech32PrefixValAddr: "orai" + "valoper",
        bech32PrefixValPub: "orai" + "valoperpub",
        bech32PrefixConsAddr: "orai" + "valcons",
        bech32PrefixConsPub: "orai" + "valconspub",
    },
    currencies: [ 
        { 
            coinDenom: "ORAI", 
            coinMinimalDenom: "orai", 
            coinDecimals: 6, 
            coinGeckoId: "orai", 
        }, 
    ],
    feeCurrencies: [
        {
            coinDenom: "ORAI",
            coinMinimalDenom: "orai",
            coinDecimals: 6,
            coinGeckoId: "orai",
        },
    ],
    stakeCurrency: {
        coinDenom: "ORAI",
        coinMinimalDenom: "orai",
        coinDecimals: 6,
        coinGeckoId: "orai",
    },
    gasPriceStep: {
        low: 0.01,
        average: 0.025,
        high: 0.03,
    },
    beta: true,
    features: [
        "stargate",
        "ibc-transfer",
        "cosmwasm"
    ],
});
```


# WIP - OWallet EVM-based API


# OWallet Help Center

This page contains FAQ & contact method to our team

## Contact us

For inquiries of OWallet, reach to us at [@owallet\_dev](https://x.com/owallet_dev)

## WIP - FAQ


# Integration

Guide to adding new blockchain to have OWallet support

## Adding Cosmos-based blockchains

### Chain config

| Property            | Type                                                                                                                                                                                                                |                                                                                                                   Function |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------: |
| rpc                 | `string`                                                                                                                                                                                                            |                                                                                                        RPC of a blockchain |
| rest                | `string`                                                                                                                                                                                                            |                                                                                                        LCD of a blockchain |
| chainId             | `string`                                                                                                                                                                                                            |                                                                                                                   Chain ID |
| chainName           | `string`                                                                                                                                                                                                            |                                                                                                                 Chain Name |
| networkType         | `string`                                                                                                                                                                                                            | Network Type `("cosmos" or "evm")`: To declare whether the network is Cosmos-based or Ethereum Virtual Machine (EVM)-based |
| stakeCurrency       | <p><code>{</code></p><p><code>coinDenom: string, coinMinimalDenom: string, coinDecimals: number, coinGeckoId: string, coinImageUrl: string, gasPriceStep: { low: number, average: number, high: number}}</code></p> |                                                                                                      Native stake currency |
| bip44               | `{ coinType: number}`                                                                                                                                                                                               |                                                                                                               Bip44 config |
| coinType            | `number`                                                                                                                                                                                                            |                                                                        The coin type is usually 118 for Cosmos, 60 for EVM |
| bech32Config        | `Bech32Address.defaultBech32Config(string)`                                                                                                                                                                         |                                                                                                  Config for bech32 address |
| currencies          | `Array<Currency>`                                                                                                                                                                                                   |                                                                                                    Currencies of the chain |
| feeCurrencies       | `Array<Currency>`                                                                                                                                                                                                   |                                                                                                Fee currencies of the chain |
| features            | `Array<Currency>`                                                                                                                                                                                                   |                                              To declare what features this chain have`(ex: ["ibc-transfer", "cosmwasm")])` |
| chainSymbolImageUrl | `string`                                                                                                                                                                                                            |                                                                                                     Chain symbol image URL |
| txExplorer          | `{name: string, txUrl: string, accountUrl: string}`                                                                                                                                                                 |                                                                                                Transaction explorer config |

### How to add a chain into OWallet?

{% hint style="info" %}
**If your chain needs to use special packages, please consider taking a look at the** [**System Desgin** ](broken://pages/uTFPgY1WHY1Db6oFePh4)**section to learn how to implement your chain into OWallet**
{% endhint %}

1. Clone this repo to desired directory

```shell
git clone https://github.com/oraichain/owallet
```

2. Checkout to main

```shell
git checkout main
```

3. Checkout to new branch

```shell
git checkout -b feat/add-new-chain-config
```

4. Create PR into main

### Example

````typescript
```typescript
{
    rpc: "https://rpc.orai.io",
    rest: "https://lcd.orai.io",
    chainId: "Oraichain",
    chainName: "Oraichain",
    networkType: "cosmos",
    stakeCurrency: {
      coinDenom: "ORAI",
      coinMinimalDenom: "orai",
      coinDecimals: 6,
      coinGeckoId: "oraichain-token",
      coinImageUrl:
        "https://s2.coinmarketcap.com/static/img/coins/64x64/7533.png",
      gasPriceStep: {
        low: 0.003,
        average: 0.005,
        high: 0.007,
      },
    },
    bip44: {
      coinType: 118,
    },
    coinType: 118,
    bech32Config: Bech32Address.defaultBech32Config("orai"),
    get currencies() {
      return [
        this.stakeCurrency,
        {
          type: "cw20",
          coinDenom: "AIRI",
          coinMinimalDenom:
            "cw20:orai10ldgzued6zjp0mkqwsv2mux3ml50l97c74x8sg:aiRight Token",
          contractAddress: "orai10ldgzued6zjp0mkqwsv2mux3ml50l97c74x8sg",
          coinDecimals: 6,
          coinGeckoId: "airight",
          coinImageUrl: "https://i.ibb.co/m8mCyMr/airi.png",
        },

        {
          type: "cw20",
          coinDenom: "OCH",
          coinMinimalDenom:
            "cw20:orai1hn8w33cqvysun2aujk5sv33tku4pgcxhhnsxmvnkfvdxagcx0p8qa4l98q:OCH",
          contractAddress:
            "orai1hn8w33cqvysun2aujk5sv33tku4pgcxhhnsxmvnkfvdxagcx0p8qa4l98q",
          coinDecimals: 6,
          coinGeckoId: "och",
          coinImageUrl:
            "https://assets.coingecko.com/coins/images/34236/standard/orchai_logo_white_copy_4x-8_%281%29.png",
        },
        {
          type: "cw20",
          coinDenom: "tBTC",
          coinMinimalDenom:
            "cw20:orai1d2hq8pzf0nswlqhhng95hkfnmgutpmz6g8hd8q7ec9q9pj6t3r2q7vc646:tBTC Token",
          contractAddress:
            "orai1d2hq8pzf0nswlqhhng95hkfnmgutpmz6g8hd8q7ec9q9pj6t3r2q7vc646",
          coinDecimals: 6,
          coinGeckoId: "bitcoin",
          coinImageUrl: "https://i.ibb.co/NVP6CDZ/images-removebg-preview.png",
        },
        {
          type: "cw20",
          coinDenom: "BTC",
          coinMinimalDenom:
            "cw20:orai10g6frpysmdgw5tdqke47als6f97aqmr8s3cljsvjce4n5enjftcqtamzsd:orai BTC Token",
          contractAddress:
            "orai10g6frpysmdgw5tdqke47als6f97aqmr8s3cljsvjce4n5enjftcqtamzsd",
          coinDecimals: 6,
          coinGeckoId: "bitcoin",
          coinImageUrl: "https://i.ibb.co/NVP6CDZ/images-removebg-preview.png",
        },
        {
          type: "cw20",
          coinDenom: "ORAIX",
          coinMinimalDenom:
            "cw20:orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge:OraiDex Token",
          contractAddress: "orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge",
          coinDecimals: 6,
          coinGeckoId: "oraidex",
          coinImageUrl: "https://i.ibb.co/VmMJtf7/oraix.png",
        },
        {
          type: "cw20",
          coinDenom: "USDT",
          coinMinimalDenom:
            "cw20:orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh:Tether",
          contractAddress: "orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh",
          coinDecimals: 6,
          coinGeckoId: "tether",
          coinImageUrl:
            "https://s2.coinmarketcap.com/static/img/coins/64x64/825.png",
        },
        {
          type: "cw20",
          coinDenom: "USDC",
          coinMinimalDenom:
            "cw20:orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd:USDC",
          contractAddress:
            "orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd",
          coinDecimals: 6,
          coinGeckoId: "usd-coin",
          coinImageUrl:
            "https://s2.coinmarketcap.com/static/img/coins/64x64/3408.png",
        },
        {
          type: "cw20",
          coinDenom: "wTRX",
          coinMinimalDenom:
            "cw20:orai1c7tpjenafvgjtgm9aqwm7afnke6c56hpdms8jc6md40xs3ugd0es5encn0:wTRX",
          contractAddress:
            "orai1c7tpjenafvgjtgm9aqwm7afnke6c56hpdms8jc6md40xs3ugd0es5encn0",
          coinDecimals: 6,
          coinGeckoId: "tron",
          coinImageUrl:
            "https://s2.coinmarketcap.com/static/img/coins/64x64/1958.png",
        },
        {
          type: "cw20",
          coinDenom: "INJ",
          coinMinimalDenom:
            "cw20:orai19rtmkk6sn4tppvjmp5d5zj6gfsdykrl5rw2euu5gwur3luheuuusesqn49:INJ",
          contractAddress:
            "orai19rtmkk6sn4tppvjmp5d5zj6gfsdykrl5rw2euu5gwur3luheuuusesqn49",
          coinDecimals: 6,
          coinGeckoId: "injective-protocol",
          coinImageUrl:
            "https://s2.coinmarketcap.com/static/img/coins/64x64/7226.png",
        },
        {
          type: "cw20",
          coinDenom: "KWT",
          coinMinimalDenom:
            "cw20:orai1nd4r053e3kgedgld2ymen8l9yrw8xpjyaal7j5:Kawaii Islands",
          contractAddress: "orai1nd4r053e3kgedgld2ymen8l9yrw8xpjyaal7j5",
          coinDecimals: 6,
          coinGeckoId: "kawaii-islands",
          coinImageUrl:
            "https://s2.coinmarketcap.com/static/img/coins/64x64/12313.png",
        },
        {
          type: "cw20",
          coinDenom: "MILKY",
          coinMinimalDenom:
            "cw20:orai1gzvndtzceqwfymu2kqhta2jn6gmzxvzqwdgvjw:Milky Token",
          contractAddress: "orai1gzvndtzceqwfymu2kqhta2jn6gmzxvzqwdgvjw",
          coinDecimals: 6,
          coinGeckoId: "milky-token",
          coinImageUrl:
            "https://s2.coinmarketcap.com/static/img/coins/64x64/14418.png",
        },
        {
          coinDenom: "WETH",
          coinGeckoId: "weth",
          coinMinimalDenom:
            "cw20:orai1dqa52a7hxxuv8ghe7q5v0s36ra0cthea960q2cukznleqhk0wpnshfegez:WETH",
          type: "cw20",
          contractAddress:
            "orai1dqa52a7hxxuv8ghe7q5v0s36ra0cthea960q2cukznleqhk0wpnshfegez",
          coinDecimals: 6,
          coinImageUrl:
            "https://s2.coinmarketcap.com/static/img/coins/64x64/1027.png",
        },
      ];
    },
    get feeCurrencies() {
      return [this.stakeCurrency];
    },
    features: ["stargate", "ibc-transfer", "cosmwasm", "no-legacy-stdTx"],
    chainSymbolImageUrl: "https://orai.io/images/logos/logomark-dark.png",
    txExplorer: {
      name: "Oraiscan",
      txUrl: "https://scan.orai.io/txs/{txHash}",
      accountUrl: "https://scan.orai.io/account/{address}",
    },
    // beta: true // use v1beta1
  }
```
````

## Adding EVM-based blockchains

### Chain config

| Property            |                                                                                      Type                                                                                     |                                                                                                                   Function |
| ------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -------------------------------------------------------------------------------------------------------------------------: |
| rpc                 |                                                                                    `string`                                                                                   |                                                                                                        RPC of a blockchain |
| chainId             |                                                                                    `string`                                                                                   |                                                                                                                   Chain ID |
| chainName           |                                                                                    `string`                                                                                   |                                                                                                                 Chain Name |
| networkType         |                                                                                    `string`                                                                                   | Network Type `("cosmos" or "evm")`: To declare whether the network is Cosmos-based or Ethereum Virtual Machine (EVM)-based |
| stakeCurrency       | `{coinDenom: string, coinMinimalDenom: string, coinDecimals: number, coinGeckoId: string, coinImageUrl: string, gasPriceStep: { low: number, average: number, high: number}}` |                                                                                                      Native stake currency |
| bip44               |                                                                             `{ coinType: number}`                                                                             |                                                                                                               Bip44 config |
| coinType            |                                                                                    `number`                                                                                   |                                                                        The coin type is usually 118 for Cosmos, 60 for EVM |
| bech32Config        |                                                                  `Bech32Address.defaultBech32Config(string)`                                                                  |                                                                                                  Config for bech32 address |
| currencies          |                                                                               `Array<Currency>`                                                                               |                                                                                                    Currencies of the chain |
| feeCurrencies       |                                                                               `Array<Currency>`                                                                               |                                                                                                Fee currencies of the chain |
| features            |                                                                               `Array<Currency>`                                                                               |                                                                 To declare what features this chain have`(ex: ["isEVM")])` |
| chainSymbolImageUrl |                                                                                    `string`                                                                                   |                                                                                                     Chain symbol image URL |
| txExplorer          |                                                              `{name: string, txUrl: string, accountUrl: string}`                                                              |                                                                                                Transaction explorer config |

### How to add a chain into OWallet?

1. Clone this repo to desired directory

```shell
git clone https://github.com/oraichain/owallet
```

2. Checkout to main

```shell
git checkout main
```

3. Checkout to new branch

```shell
git checkout -b feat/add-new-chain-config
```

4. Create PR into main

**If your chain needs to use special packages, please consider taking a look at the** [**System Desgin** ](broken://pages/uTFPgY1WHY1Db6oFePh4)**section to learn how to implement your chain into OWallet**

### Example

```shell
{
    rpc: "https://rpc.ankr.com/eth",
    rest: "https://rpc.ankr.com/eth",
    chainId: "0x01",
    chainName: "Ethereum",
    bip44: {
      coinType: 60,
    },
    coinType: 60,
    stakeCurrency: {
      coinDenom: "ETH",
      coinMinimalDenom: "eth",
      coinDecimals: 18,
      coinGeckoId: "ethereum",
      coinImageUrl:
        "https://s2.coinmarketcap.com/static/img/coins/64x64/1027.png",
      gasPriceStep: {
        low: 1,
        average: 1.25,
        high: 1.5,
      },
    },
    chainSymbolImageUrl:
      "https://s2.coinmarketcap.com/static/img/coins/64x64/1027.png",
    bech32Config: Bech32Address.defaultBech32Config("evmos"),
    networkType: "evm",
    currencies: [
      {
        coinDenom: "ETH",
        coinMinimalDenom: "eth",
        coinDecimals: 18,
        coinGeckoId: "ethereum",
        coinImageUrl:
          "https://s2.coinmarketcap.com/static/img/coins/64x64/1027.png",
      },
      {
        coinDenom: "OCH",
        coinMinimalDenom:
          "erc20:0x19373EcBB4B8cC2253D70F2a246fa299303227Ba:OCH Token",
        contractAddress: "0x19373EcBB4B8cC2253D70F2a246fa299303227Ba",
        coinDecimals: 18,
        coinGeckoId: "och",
        coinImageUrl:
          "https://assets.coingecko.com/coins/images/34236/standard/orchai_logo_white_copy_4x-8_%281%29.png",
      },
      {
        coinDenom: "ORAI",
        coinMinimalDenom:
          "erc20:0x4c11249814f11b9346808179cf06e71ac328c1b5:Oraichain Token",
        contractAddress: "0x4c11249814f11b9346808179cf06e71ac328c1b5",
        coinDecimals: 18,
        coinGeckoId: "oraichain-token",
        coinImageUrl:
          "https://s2.coinmarketcap.com/static/img/coins/64x64/7533.png",
      },
      {
        coinDenom: "ORAIX",
        coinMinimalDenom:
          "erc20:0x2d869aE129e308F94Cc47E66eaefb448CEe0d03e:ORAIX Token",
        contractAddress: "0x2d869aE129e308F94Cc47E66eaefb448CEe0d03e",
        coinDecimals: 18,
        coinGeckoId: "oraidex",
        coinImageUrl: "https://i.ibb.co/VmMJtf7/oraix.png",
      },
    ],
    get feeCurrencies() {
      return [this.stakeCurrency];
    },

    features: ["ibc-go", "stargate", "isEvm"],
    txExplorer: {
      name: "Etherscan",
      txUrl: "https://etherscan.io/tx/{txHash}",
      accountUrl: "https://etherscan.io/address/{address}",
    },
  }
```


# Technical Overview

## Context Level

![OWallet-Context](https://i.gyazo.com/cfd7f6b47445f76691339e7b1f80b69b.png)

## Core Components Level

![OWallet-Components](https://i.gyazo.com/4aedd5237de889a3603b68b1d24a6914.png)

## On-chain History Backend Design

![OWallet-HistoryBackend](https://i.gyazo.com/1f6f3b78dbd80843dafc54328570baef.png)

## Structure

<table><thead><tr><th width="273">Packages</th><th>Function</th></tr></thead><tbody><tr><td>analytics</td><td>This package is used to analyze user actions by logging event , page view,... Nothing much about it</td></tr><tr><td>background</td><td>This package is used to handle request of provider to sign, request public/private key,...This is one of the most important directories of the project.</td></tr><tr><td>background/chains</td><td>Used to handle messages related to the chain, such as: handleSuggestChainInfoMsg, handleRemoveSuggestedChainInfoMsg,..</td></tr><tr><td>background/interaction</td><td>Used to handle messages related to user interaction, such as: handleApproveInteractionMsg, handleRejectInteractionMsg</td></tr><tr><td>background/keyring</td><td>Used to handle messages related to the keyring,mnemonic, private key/public key and signing request, such as: CreatePrivateKeyMsg, UnlockKeyRingMsg, RequestSignAminoMsg, RequestSignEthereumMsg, CreateLedgerKeyMsg,...</td></tr><tr><td>background/ledger</td><td>Used to handle messages related to the ledger service, such as: getPublicKey, initLedger,..</td></tr><tr><td>background/permission</td><td>Used to handle messages related to the permission and access, such as: handleEnableAccessMsg, handleGetPermissionOriginsMsg,..</td></tr><tr><td>background/persistent-memory</td><td>Used to handle messages related to the persistent memory, such as: handleSetPersistentMemoryMsg</td></tr><tr><td>background/secret-wasm</td><td>Used to handle messages related to the secret-wasm, such as: handleGetPubkeyMsg,handleReqeustEncryptMsg, handleRequestDecryptMsg..</td></tr><tr><td>background/tokens</td><td>Used to handle messages related to the tokens managerment such as: handleGetTokensMsg,handleSuggestTokenMsg, handleAddTokenMsg..</td></tr><tr><td>background/tx</td><td>Used to handle messages related to the transaction, such as: sendTx ,processTxResultNotification</td></tr><tr><td>background/updater</td><td>Used to handle messages related to the chain update, such as: handleTryUpdateChainMsg</td></tr><tr><td>background/utils</td><td>Used to contain helper functions of background</td></tr><tr><td>bitcoin</td><td>This package contain helper function for BTC</td></tr><tr><td>common</td><td>This package is used to handle common function like fetchTx, helper function,..</td></tr><tr><td>common/api</td><td>Used to contain common functions related to api, includes api utils and api services</td></tr><tr><td>common/axios</td><td>Used to contain common functions related to axios package, like fetchAdapter, getResponse, createError, createRequest</td></tr><tr><td>common/denom</td><td>Used to contain common functions related to denom, like DenomHelper</td></tr><tr><td>common/escape</td><td>Used to contain common functions related to escape html</td></tr><tr><td>common/json</td><td>Used to contain common functions related to json, like sortObjectByKey, sortedJsonByKeyStringify</td></tr><tr><td>common/kv-store</td><td>Used to contain common functions related to kv store, like get/set</td></tr><tr><td>common/mobx</td><td>Used to contain common functions related to mobx</td></tr><tr><td>common/tx</td><td>Used to contain common functions related to transaction, like fetchTx, fetchTxPoll</td></tr><tr><td>common/ui-config</td><td>Used to contain common functions related to ui configuration</td></tr><tr><td>common/niversal-swap</td><td>Used to contain common functions related to universal swap feature, like getTransferTokenFee, getSwapToken, getTokenOnSpecificChainId,...</td></tr><tr><td>common/web3</td><td>Used to create Web3Provider</td></tr><tr><td>common/utils</td><td>Used to contain other common functions, mostly about bigInt/amount formatting</td></tr><tr><td>cosmos</td><td>This package is used to handle cosmos function</td></tr><tr><td>cosmos/account</td><td>Used to contain BaseAccount class, which have basic info about cosmos account like address, account number, sequence</td></tr><tr><td>cosmos/adr-36</td><td>Used to contain functions related to ADR36AminoSignDoc, like checkAndValidateADR36AminoSignDoc, makeADR36AminoSignDoc, verifyADR36Amino</td></tr><tr><td>cosmos/bech32</td><td>Used to contain functions related to bech32 address, like shortenAddress,toBech32,...</td></tr><tr><td>cosmos/chain-id</td><td>Used to contain functions related to chain id, like EthermintChainIdHelper,parse,...</td></tr><tr><td>cosmos/signing</td><td>Used to contain functions related to encode signature and pubkey, like encodeSecp256k1Signature,...</td></tr><tr><td>cosmos/stargate</td><td>Used to contain functions related to stargate, like ProtoCodec,ProtoSignDocDecoder,SignDocWrapper...</td></tr><tr><td>cosmos/tx-tracer</td><td>Used to contain functions related to transaction tracer, like sendSubscribeBlockRpc,subscribeMsgByAddress,...</td></tr><tr><td>crypto</td><td>This package is used to generate wallet,encrypt/decrypt,...</td></tr><tr><td>crypto/mnemonic</td><td>Used to contain functions related to mnemonic, like generateWallet,validateMnemonic,generateWalletFromMnemonic...</td></tr><tr><td>crypto/hash</td><td>Used to contain functions related to hash function, like keccak256,truncHashPortion...</td></tr><tr><td>crypto/key</td><td>Used to contain functions related to private key and pubkey,includes PrivKeySecp256k1 class and PubKeySecp256k1 class</td></tr><tr><td>ens</td><td>This package is used to handle ens, like isValidENS, fetchResolverAddress,...</td></tr><tr><td>hooks</td><td>This package is used to contain common hooks</td></tr><tr><td>hooks/address-book</td><td>Used to contain hook related to address book, like useAddressBookConfig</td></tr><tr><td>hooks/ibc</td><td>Used to contain hook related to ibc, like useIBCAmountConfig, useIBCTransferGasConfig, useIBCTransferConfig,...</td></tr><tr><td>hooks/interaction</td><td>Used to contain hook related to Interaction info, like useInteractionInfo</td></tr><tr><td>hooks/register</td><td>Used to contain hook related to register, like useRegisterConfig</td></tr><tr><td>hooks/tx</td><td>Used to contain hook related to transaction, like useFeeEvmConfig, useGasEvmConfig, useGasConfig, useAmountConfig,...</td></tr><tr><td>hooks/universal-swap</td><td>Used to contain hook related to universal swap, like useCoinGeckoPrices, useRelayerFee, useTaxRate,...</td></tr><tr><td>hooks/sign-doc</td><td>Used to contain hook related to sign doc, like useSignDocAmountConfig</td></tr><tr><td>provider</td><td>This package provides functions for dApps to communicate with the background</td></tr><tr><td>provider/core</td><td>Used to contain core functions of wallet injector, like OWallet signDirect, getOfflineSigner, suggestToken,... This is where we create all of the wallet instances that are injected into the dApps.</td></tr><tr><td>provider/cosmjs</td><td>Used to contain cosmjs function, like CosmJSOfflineSignerOnlyAmino class,CosmJSOfflineSigner class,signAmino,signDirect,...</td></tr><tr><td>provider/enigma</td><td>Used to contain engma utils function, like getEnigmaPubKey, enigmaEncrypt, enigmaDecrypt,...</td></tr><tr><td>provider/inject</td><td>Used to create injector, and handle message of dApps like a proxy</td></tr><tr><td>provider/msgs</td><td>Used to create provider messages</td></tr><tr><td>router</td><td>This package is used to routing app message bettween provider and background</td></tr><tr><td>router-extension</td><td>Same with router, but more specified for extension</td></tr><tr><td>router-mock</td><td>Router mockup</td></tr><tr><td>mobile</td><td>This package contain mobile app code</td></tr><tr><td>extension</td><td>This package contain extension app code</td></tr><tr><td>stores</td><td>This package is used to handle store function, includes update/add info chains, tokens, price, query,...Basically, it contain all the functions and property of account, query, chain,...etc that we need and interact with in the app.This is one of the most important directories of the project.</td></tr><tr><td>stores/account</td><td>Account store, used to handle and store all the functions and property related to account, like processSendToken, simulateTx,... it prepare data, create msg and send it into background</td></tr><tr><td>stores/chain</td><td>Chain store, used to handle and store all the functions and property related to chain, like setChainInfo, findCurrency,..</td></tr><tr><td>stores/common</td><td>Used to contain common utils functions of store</td></tr><tr><td>stores/core</td><td>Used to contain core functions of store</td></tr><tr><td>stores/ibc</td><td>Used to contain function of ibc store, like channel, currency-registrar</td></tr><tr><td>stores/price</td><td>Used to contain price store functions and property</td></tr><tr><td>stores/query</td><td>Used to contain query store functions and property, like ObservableQueryAccount, ObservableQueryBalanceNative,...</td></tr><tr><td>types</td><td>This package contain project all kind of types</td></tr><tr><td>unit</td><td>This package contain project unit helper function, like CoinPretty, DecUtils, PricePretty</td></tr><tr><td>proto-types</td><td>For generate package proto types</td></tr><tr><td>wc-client &#x26; wc-qrcode-modal</td><td>For wallet connect(not implemented yet)</td></tr></tbody></table>


# Download

**iOS:** <https://apps.apple.com/us/app/owallet/id1626035069>&#x20;

**Android:** <https://play.google.com/store/apps/details?id=com.io.owallet&hl=vi&gl=US>

**Chrome extension:** <https://chrome.google.com/webstore/detail/owallet/hhejbopdnpbjgomhpmegemnjogflenga>


