Extension Wallet
Integration
Cosmos Chains
React Hook

React hook

Installation

The Cosmostation wallet hook package lives in npm. To install the latest stable version, run the following command:

npm install @cosmostation/use-wallets

Or if you're using yarn:

yarn add @cosmostation/use-wallets

CosmosProvider

Components that use cosmos wallet state need CosmosProvider to appear somewhere in the parent tree. A good place to put this is in your root component:

example
import { CosmosProvider } from '@cosmostation/use-wallets';
 
function App() {
  return (
    <CosmosProvider>
      <MyApp />
    </CosmosProvider>
  );
}

useCosmosWallets

With useCosmosWallets, you can select a list of wallets, the wallet you are currently using, and the wallet you want to use. The wallet list is automatically inserted in extensions.

If you would like to add a wallet, click here

selectWallet

example
import { useCosmosWallets } from '@cosmostation/use-wallets';
 
function Connect() {
  const { cosmosWallets, selectWallet } = useCosmosWallets();
 
  return (
    <div>
      {cosmosWallets.map((wallet) => (
        <button
          onClick={() => {
            selectWallet(wallet.id);
          }}
          key={wallet.id}
        >
          <img src={wallet.logo} alt={wallet.name} width={40} height={40} /> {wallet.name}
        </button>
      ))}
    </div>
  );
}

addChain

example
import { useCosmosWallets } from '@cosmostation/use-wallets';
 
function AddCustomChain() {
  const { currentWallet } = useCosmosWallets();
 
  return (
    <div>
      <button
        onClick={() => {
          try {
            if (!currentWallet) {
              throw new Error('No Selected Wallet');
            }
 
            await currentWallet.methods.addChain({
              chain_id: 'custom-chain-1',
              chain_name: 'custom-chain',
              address_prefix: 'custom',
              base_denom: 'ucustom',
              display_denom: 'CUSTOM',
              lcd_url: 'https://rpc.custom-chain.com',
              decimals: 6, // optional
              coin_type: "118'", // optional
            });
          } catch (e) {
            console.log(e.message);
          }
        }}
      >
        Add Custom Chain
      </button>
    </div>
  );
}

useCosmosAccount

With useCosmosAccount, you can get the account information of the wallet you are currently using.

Account

Account automatically requests account information the moment a wallet is selected. If you want to request more manually, you can use 'mutate'.

example
import { useCosmosAccount } from '@cosmostation/use-wallets';
 
export default function Account() {
  const { data, error, mutate } = useCosmosAccount('cosmoshub-4');
 
  useEffect(() => {
    console.log('address', data?.account);
    console.log('error', error);
  }, [data, error]);
 
  return <button onClick={() => mutate()}>Request Account</button>;
}

Methods

the available methods in the selected account. (e.g. sign)

disconnect

example
import { useCosmosAccount } from '@cosmostation/use-wallets';
 
export default function Account() {
  const { data } = useCosmosAccount('cosmoshub-4');
 
  return <button onClick={() => data?.method.disconnect()}>Disconnect</button>;
}

signAmino

example
import { useCosmosAccount } from '@cosmostation/use-wallets';
 
export default function SignAmino() {
  const { data } = useCosmosAccount('cosmoshub-4');
 
  const sendExampleDoc = {
    // ...
  };
 
  return (
    <button
      onClick={async () => {
        try {
          if (!data) {
            throw new Error('No data');
          }
 
          console.dir(await data?.methods.signAmino(sendExampleDoc), { depth: 100 });
        } catch (e) {
          console.log(e.message);
        }
      }}
    >
      Sign Amino
    </button>
  );
}

signDirect

example
import { useCosmosAccount } from '@cosmostation/use-wallets';
 
export default function SignDirect() {
  const { data } = useCosmosAccount('cosmoshub-4');
 
  const sendExampleDoc = {
    // ...
  };
 
  return (
    <button
      onClick={async () => {
        try {
          if (!data) {
            throw new Error('No data');
          }
 
          const result = await data.methods.signDirect(sendExampleDoc);
 
          console.dir(result, { depth: 100 });
        } catch (e) {
          console.log(e.message);
        }
      }}
    >
      Sign Direct
    </button>
  );
}

signAndSendTransaction

A method that combines sign and send using signDirect
Receives message as json and automates creation of protobuf

JSON e.g.

example
import { useCosmosAccount } from '@cosmostation/use-wallets';
 
export default function SignAndSendTransaction() {
  const { data } = useCosmosAccount('cosmoshub-4');
 
  return (
    <Button
      onClick={async () => {
        try {
          if (!data) {
            throw new Error('No data');
          }
 
          console.dir(
            await data?.methods.signAndSendTransaction({
              messages: [
                {
                  type_url: '/cosmos.bank.v1beta1.MsgSend',
                  value: {
                    from_address: data?.account.address,
                    to_address: data?.account.address,
                    amount: [
                      {
                        denom: 'uatom',
                        amount: '1',
                      },
                    ],
                  },
                },
              ],
              memo: 'Test (Sign And Send Transaction)',
            }),
            { depth: 100 },
          );
        } catch (e) {
          console.log(e.message);
        }
      }}
    >
      Sign And Send Transaction
    </Button>
  );
}
🚫
The actual transaction is executed. If you don't want to, don't sign.


signMessage

sign arbitrary bytes

example
import { useCosmosAccount } from '@cosmostation/use-wallets';
 
export default function SignAndSendTransaction() {
  const { data } = useCosmosAccount('cosmoshub-4');
 
  return (
    <Button
      onClick={async () => {
        try {
          if (!data) {
            throw new Error('No data');
          }
 
          if (!data.methods.signMessage) {
            throw new Error('No signMessage method');
          }
 
          const message = '(test) sign message';
 
          console.dir(await data.methods.signMessage(message));
        } catch (e) {
          console.log(e.message);
        }
      }}
    >
      Sign Message
    </Button>
  );
}

verifyMessage

verify arbitrary bytes

example
import { useCosmosAccount } from '@cosmostation/use-wallets';
 
export default function SignAndSendTransaction() {
  const { data } = useCosmosAccount('cosmoshub-4');
 
  return (
    <Button
      onClick={async () => {
        try {
          if (!data) {
            throw new Error('No data');
          }
 
          if (!data.methods.signMessage) {
            throw new Error('No signMessage method');
          }
 
          if (!data.methods.verifyMessage) {
            throw new Error('No verifyMessage method');
          }
 
          const message = '(test) sign message';
 
          const response = await data.methods.signMessage(message);
 
          const verify = await data.methods.verifyMessage(message, response.signature);
 
          console.log(verify ? 'verified' : 'not verified');
        } catch (e) {
          console.log(e.message);
        }
      }}
    >
      Verify Message
    </Button>
  );
}

Type

Account

interface Account {
  data?: {
    account: CosmosAccount;
    methods: CosmosMethods;
  };
  error?: string;
  mutate: () => void;
}

CosmosAccount

interface CosmosAccount {
  address: string;
  public_key: {
    type: CosmosPublicKeyType;
    value: string;
  };
  name?: string;
  is_ledger?: boolean;
}

CosmosPublicKeyType

type CosmosPublicKeyType = 'secp256k1' | 'ethsecp256k1';

CosmosMethods

interface CosmosMethods {
  signAndSendTransaction: (
    props: SignAndSendTransactionProps,
    options?: SignOptions,
  ) => Promise<CosmosSendTransactionResponse>;
  signAmino: (
    document: CosmosSignAminoDoc,
    options?: SignOptions,
  ) => Promise<CosmosSignAminoResponse>;
  signDirect: (
    document: CosmosSignDirectDoc,
    options?: SignOptions,
  ) => Promise<CosmosSignDirectResponse>;
  sendTransaction: (
    tx_bytes: Uint8Array | string,
    mode?: number,
  ) => Promise<CosmosSendTransactionResponse>;
  getSupportedChainIds: () => Promise<string[]>;
  signMessage?: (message: string, signer: string) => Promise<CosmosSignMessageResponse>;
  verifyMessage?: (message: string, signature: string) => Promise<boolean>;
}

CosmosSignAminoDoc

interface CosmosSignAminoDoc {
  sequence: string;
  account_number: string;
  fee: {
    amount?: {
      denom: string;
      amount: string;
    }[];
    gas: string;
  };
  memo: string;
  msgs: {
    type: string;
    value: any;
  }[];
}

CosmosSignAminoResponse

interface CosmosSignAminoResponse {
  signature: string;
  signed_doc: any;
}

CosmosSignDirectDoc

interface CosmosSignDirectDoc {
  account_number: string;
  body_bytes: string | Uint8Array;
  auth_info_bytes: string | Uint8Array;
}

CosmosSignDirectResponse

interface CosmosSignDirectResponse {
  signature: string;
  signed_doc: CosmosSignedDoc;
}

SignAndSendTransactionProps

interface CosmosSignAndSendTransactionProps {
  messages: Message[];
  memo?: string;
  fee?: Fee;
  sequence?: number;
  lcd_url?: string;
  fee_denom?: string;
  gas_rate?: number;
  payer?: string;
  granter?: string;
}
 
interface CosmosMessage {
  type_url: string;
  value?: unknown;
}

CosmosFee

interface CosmosFee {
  amount: Amount[];
  gas_limit: number;
  payer?: string;
  granter?: string;
}
 
interface CosmosAmount {
  denom: string;
  amount: number;
}