Module cosmjs

@sei-js/cosmjs

The @sei-js/cosmjs package contains helper functions for wallet connection, transaction signing, RPC querying, and more for those using cosmjs.

When first developing an application on Sei, you must first choose which RPC interface you want to use. This package is designed to work with cosmjs and the Cosmos ecosystem. If you would like to use EVM RPC, you should use the @sei-js/evm package.

When building a dApp on Sei, it is important to understand the Cosmos SDK. Specifically, it is important to know how transactions are structured with different messages, gas fees, and signers. For an in-depth overview of the Cosmos SDK, see the Cosmos SDK documentation.

CosmJS is a JavaScript/TypeScript library for building applications on the Cosmos network. It provides a set of tools for interacting with the Cosmos network, including wallet management, transaction signing, and RPC querying. For more information, see the CosmJS documentation.

yarn add @sei-js/cosmjs

In order to sign and broadcast transactions, you must first connect to a wallet. This package contains helper functions to connect to the Sei wallet extension, or to create a wallet from a seed phrase.

If you prefer to manage wallet connections manually, you can use the native interface of the wallet extension to connect to a wallet. See the Compass documentation for more information on how to connect to a wallet extension.

In some circumstances it is necessary to generate a new wallet or to restore a wallet from a given seed phrase.

import { getHdPath, generateWallet, restoreWallet } from "@sei-js/cosmjs";

const cosmosHdPath = getHdPath(0, 118); // This is the default path for Sei wallets account index 0
const evmHdPath = getHdPath(0, 60); // This is the default path for EVM wallets account index 0

// 12 word mnemonic by default
const generatedWallet = await generateWallet(24, cosmosHdPath);
console.log('generated mnemonic', generatedWallet.mnemonic);

// or restore a wallet given a seed phrase and coin type 60 HD path
const restoredWallet = await restoreWallet(SEED_PHRASE, evmHdPath);
console.log('restored mnemonic', restoredWallet.mnemonic);

Cosmos Kit is a helpful library for connecting to various Sei wallet extensions. It is recommended to use this library and to take advantage of all the useful hooks, utilities, and UI components it provides. For more information, see the Cosmos Kit documentation

import { COSMOS_KIT_ASSET_LIST, PACIFIC_1_SEI_COSMOS_KIT_CHAIN, ATLANTIC_2_SEI_COSMOS_KIT_CHAIN, ARCTIC_1_SEI_COSMOS_KIT_CHAIN } from '@sei-js/cosmjs'
import { wallets } from '@cosmos-kit/keplr';

function CosmosApp() {
return (
<ChainProvider
chains={[PACIFIC_1_SEI_COSMOS_KIT_CHAIN, ATLANTIC_2_SEI_COSMOS_KIT_CHAIN, ARCTIC_1_SEI_COSMOS_KIT_CHAIN]}
assetLists={[COSMOS_KIT_ASSET_LIST]}
wallets={wallets} // whatever wallets you prefer
>
<YourWalletRelatedComponents />
</ChainProvider>
);
}

If you are using a generic wallet like Keplr, you can suggest a chain to the user by using the suggestChain function. This will prompt the user to add the chain to their wallet.

import { getChainSuggest } from '@sei-js/cosmjs';

const chainSuggest = getChainSuggest();
await window.keplr.suggestChain(chainSuggest); // See the Keplr API docs for more information on chain suggestion.

@sei-js contains helper functions to get a SigningStargateClient with default Sei protocol registry and amino types. In order to interact with this, you need a Sei RPC URL from a provider.

import { getSigningStargateClient } from '@sei-js/cosmjs';

// Don't forget to connect if using a wallet extension
// or create a wallet from a mnemonic (See above)
await window.compass.connect(chainId);

const offlineSigner = await window.compass.getOfflineSigner(chainId);

const signingClient = await getSigningStargateClient(RPC_URL, offlineSigner);

Using Custom Registry or Amino Types:

import { Registry } from "@cosmjs/proto-signing";
import { defaultRegistryTypes } from "@cosmjs/stargate";
import { getSigningStargateClient } from '@sei-js/cosmjs';
import { seiprotocol, seiprotocolProtoRegistry } from "@sei-js/proto";

// Set up Sei proto registry
const registry = new Registry([
...defaultRegistryTypes,
...seiprotocolProtoRegistry,
]);

// Create a client with registry
const signingClient = await getSigningStargateClient(RPC_URL, offlineSigner, { registry });

Derives and returns an address for the given private key.

  • Parameters:

    • privateKeyHex (0x{string}): A hex-encoded private key string.
  • Returns: stringr - An address from the given private key.

  • Usage:

import { deriveAddressesFromPrivateKey } from '@sei-js/cosmjs';

const seiAddress = deriveAddressesFromPrivateKey(PRIVATE_KEY);

Creates a hex-encoded ECC KeyPair given a public key.

  • Parameters:

    • pubKey (Uint8Array): A byte array representing a public key.
  • Returns: EllipticCurve.KeyPair - A hex-encoded ECC KeyPair.

  • Usage:

import { pubKeyToKeyPair } from '@sei-js/cosmjs';

const keyPair = pubKeyToKeyPair(new Uint8Array([/* public key bytes */]));
console.log(keyPair);

Converts the given public key to a bytestring.

  • Parameters:

    • pubKey (Uint8Array): The public key to convert.
    • uncompressed? (boolean): Whether the public key should be uncompressed.
  • Returns: Uint8Array - The converted public key as a byte array.

  • Usage:

import { pubKeyToBytes } from '@sei-js/cosmjs';

const bytes = pubKeyToBytes(new Uint8Array([/* public key bytes */]));
console.log(bytes);

Gets the corresponding address from a byte array representing a compressed public key.

  • Parameters:

    • publicKey (Uint8Array): A byte array representing a compressed public key.
  • Returns: string - The corresponding Bech32 address.

  • Usage:

import { compressedPubKeyToAddress } from '@sei-js/cosmjs';

const address = compressedPubKeyToAddress(new Uint8Array([/* public key bytes */]));
console.log(address);

Gets the corresponding SHA-256 hashed address for a given compressed public key.

  • Parameters:

    • compressedPublicKey (Uint8Array): A byte array representing a compressed public key.
  • Returns: Uint8Array - The hashed address.

  • Usage:

import { getAddressHashFromPubKey } from '@sei-js/cosmjs';

const hashedAddress = getAddressHashFromPubKey(new Uint8Array([/* compressed public key */]));
console.log(hashedAddress);

Verifies a digest signed with a private key using the corresponding public key.

  • Parameters:

    • digest (Uint8Array): The digest to verify.
    • signature (Uint8Array): The digital signature.
    • pubKey (Uint8Array): The public key of the signer.
  • Returns: boolean - true if the digest is verified.

  • Usage:

import { verifyDigest32 } from '@sei-js/cosmjs';

const isValid = verifyDigest32(new Uint8Array([/* digest */]), new Uint8Array([/* signature */]), new Uint8Array([/* public key */]));
console.log(isValid);

Checks if a given string is a valid Sei address.

  • Parameters:

    • address (string): The address to verify.
  • Returns: boolean - true if the address is valid.

  • Usage:

import { isValidSeiCosmosAddress } from '@sei-js/cosmjs';

const isValid = isValidSeiCosmosAddress('sei123...');
console.log(isValid);

Shortens a Sei address to display it in the format sei...xxxxx, where xxxxx is the last five characters of the address.

  • Parameters:

    • address (string): The address to truncate.
  • Returns: string - The truncated address.

  • Usage:

import { truncateSeiAddress } from '@sei-js/cosmjs';

const truncated = truncateSeiAddress('sei123456789abcdefghijk');
console.log(truncated);

Converts a given address to Bech32 format.

  • Parameters:

    • address (Uint8Array): The address to convert.
  • Returns: string - The Bech32 formatted address.

  • Usage:

import { toBech32 } from '@sei-js/cosmjs';

const bech32Address = toBech32(new Uint8Array([/* address bytes */]));
console.log(bech32Address);

Returns the SHA-256 encoded hash of the given data.

  • Parameters:

    • data (Uint8Array): The data to encode.
  • Returns: Uint8Array - The SHA-256 encoded hash.

  • Usage:

import { sha256 } from '@sei-js/cosmjs';

const hash = sha256(new Uint8Array([/* data */]));
console.log(hash);

Serializes the given signDoc object.

  • Parameters:

    • signDoc (SignDoc): The SignDoc object to be serialized.
  • Returns: Uint8Array - The serialized SignDoc.

  • Usage:

import { serializeDirectSignDoc } from '@sei-js/cosmjs';

const serialized = serializeDirectSignDoc({ /* SignDoc object */ });
console.log(serialized);

Serializes the given StdSignDoc object.

  • Parameters:

    • signDoc (StdSignDoc): The StdSignDoc object to be serialized.
  • Returns: Uint8Array - The serialized StdSignDoc.

  • Usage:

import { serializeAminoSignDoc } from '@sei-js/cosmjs';

const serialized = serializeAminoSignDoc({ /* StdSignDoc object */ });
console.log(serialized);

Creates a StdSignDoc for an ADR-36 object.

  • Parameters:

    • signer (string): The address of the signer.
    • data (string | Uint8Array): The payload to be signed.
  • Returns: StdSignDoc - A valid ADR-36 StdSignDoc.

  • Usage:

import { makeADR36AminoSignDoc } from '@sei-js/cosmjs';

const signDoc = makeADR36AminoSignDoc('sei123...', 'Hello, Sei!');
console.log(signDoc);

Verifies a StdSignature object against the given signer address and expected message.

  • Parameters:

    • signerAddress (string): The signer's address.
    • expectedMessage (string): The expected message that was signed.
    • signatureToVerify (StdSignature): The StdSignature object to verify.
  • Returns: Promise<boolean> - true if the signature is valid.

  • Usage:

import { verifyArbitrary } from '@sei-js/cosmjs';

const isVerified = await verifyArbitrary('sei123...', 'Hello, Sei!', {
pub_key: { type: 'tendermint/PubKeySecp256k1', value: 'A1B2C3...' },
signature: 'D4E5F6...'
});
console.log(isVerified);
import { calculateFee } from '@cosmjs/stargate';
import { getSigningStargateClient } from '@sei-js/cosmjs';

// Don't forget to connect if using a wallet extension
// or create a wallet from a mnemonic (See above)
await window.compass.connect(chainId);

const offlineSigner = await window.compass.getOfflineSigner(chainId);

const signingClient = await getSigningStargateClient(RPC_URL, offlineSigner);

const fee = calculateFee(100000, "0.1usei");
const amount = { amount: SEND_AMOUNT, denom: TOKEN_DENOM };

const sendResponse = await signingClient.sendTokens(SENDER_ADDRESS, DESTINATION_ADDRESS, [amount], fee);
import { calculateFee } from '@cosmjs/stargate';
import { getSigningStargateClient } from '@sei-js/cosmjs';

// Don't forget to connect if using a wallet extension
// or create a wallet from a mnemonic (See above)
await window.compass.connect(chainId);

const offlineSigner = await window.compass.getOfflineSigner(chainId);

const signingClient = await getSigningStargateClient(RPC_URL, offlineSigner);

const amount = { amount: SEND_AMOUNT, denom: TOKEN_DENOM };

const ibcResponse = await signingClient.sendIbcTokens(SENDER_ADDRESS, DESTINATION_ADDRESSS, amount, 'transfer', CHANNEL_ID, undefined, undefined, fee)

// Create message to place an order
const { placeOrders } = seiprotocol.seichain.dex.MessageComposer.withTypeUrl;
const msg = placeOrders({ contractAddr, creator, funds, orders });
const fee = calculateFee(150000, "0.1usei");

// Sign and broadcast the message
const response = signingClient.signAndBroadcast(firstAccount.address, [msg], fee);

@sei-js contains helper functions to get a CosmWasmClient. Thi should be used for querying smart contracts only. If you need to call a contracts execute msg, see the SigningCosmWasmClient below.

import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
import { getCosmWasmClient } from "@sei-js/cosmjs";

// Create a CosmWasmClient
const cosmWasmClient = await getCosmWasmClient(RPC_URL);

Build the queryMsg according to the contracts specific query specifications. Each contract will define its own queryable state, so check the contract documentation for the correct query message format by examining the contract source code or documentation.

// Create the query msg json based on contract specific query specifications
const queryMsg = {
tokens: {
owner: address,
},
};

// Query a smart contract state
const queryResponse = cosmWasmClient.queryContractSmart(CONTRACT_ADDR, queryMsg);

This package contains helper functions to get a SigningCosmWasmClient with Sei registry and amino types from @sei-js/proto used for smart contract execute messages.

import { getSigningCosmWasmClient } from "@sei-js/cosmjs";

const offlineSigner = await window.compass.getOfflineSigner(chainId);

// Create a CosmWasmClient
const signingCosmWasmClient = await getSigningCosmWasmClient(RPC_URL, offlineSigner);

Build the executeMsg according to the contracts specific specifications. Each contract will define its own execute functions, so check the contract documentation for the correct execute message format by examining the contract source code or documentation.

import { getSigningCosmWasmClient } from "@sei-js/cosmjs";

const offlineSigner = await window.compass.getOfflineSigner(chainId);

// Create a CosmWasmClient
const signingCosmWasmClient = await getSigningCosmWasmClient(RPC_URL, offlineSigner);

// Execute a message on a smart contract
const fee = calculateFee(150000, "0.1usei");
const msg = { mint: {} };

const result = await signingCosmWasmClient.execute(SENDER_ADDRESS, CONTRACT_ADDRESS, msg, fee);

You can validate that a given string is a valid Sei address:

import { isValidSeiAddress } from '@sei-js/cosmjs';

const isValidSeiAddress = isValidSeiAddress(ADDRESS_TO_TEST);

Sometimes it is necessary to prove account ownership without executing anything on chain. To achieve this verification you can use the signArbitrary function in all official Sei wallets to create a StdSignature which can be verified using the verifyArbitrary function from @sei-js/cosmjs

import { verifyArbitrary } from "@sei-js/cosmjs";

const SEI_ADDRESS = "sei1...";
const message = "Message to sign";
const stdSignature = await window.compass.signArbitrary('atlantic-2', SEI_ADDRESS, message); // or FIN_WALLET, KEPLR_WALLET, LEAP_WALLET
const isValid = await verifyArbitrary(SEI_ADDRESS, message, stdSignature);

In order to sign a transaction for a multi-sig transaction you must know the sequence and account number of the multi-sig account on chain. Start by querying that on chain.

import { getStargateClient } from '@sei-js/cosmjs';

const broadcaster = await getStargateClient(rpcUrl);
const multiSigAccount = await broadcaster.getAccount(multiSigAccountAddress);
const multiSigPubkey = account.pubkey as unknown as MultisigThresholdPubkey;

// If the account has not broadcasted any transactions, the pubkey will not be available.
if (!isMultisigThresholdPubkey(multiSigPubkey)) {
console.log('The account address you entered is not a multi-sig account that exists on chain.');
}

Note that if the multi sig account has neither broadcasted a transaction nor received funds, the call to `broadcaster.getAccount(multiSigAccountAddress) will fail since the account information will not exist on chain.

Repeat this step by signing the exact same msg, with the same fee across all the required accounts in the multi-sig.

import { getSigningStargateClient } from '@sei-js/cosmjs';

const offlineAminoSigner = await window.compass.getOfflineSignerAmino(chainId); // Or use another way to get the offline amino signer

const signingClient = await getSigningStargateClient(rpcUrl, offlineAminoSigner); // Or use another way to get a StargateSigningClient

const accounts = await offlineAminoSigner.getAccounts();

const response = await signingClient.sign(accounts[0].address, [YOUR_TX_MSG], YOUR_TX_FEE, '', {
accountNumber: multiSigAccount.accountNumber, // from step 1
sequence: multiSigAccount.sequence, // from step 1
chainId
});

Once all the signatures have been collected, we can broadcast the transaction from the multi-sig account.

const broadcaster = await StargateClient.connect(rpcUrl);
const multiSigAccount = await broadcaster.getAccount(multiSigAccountAddress);
const multiSigPubkey = multiSigAccount.pubkey as unknown as MultisigThresholdPubkey;

const signatures = new Map<string, Uint8Array>([
[firstAddress, firstSignResponse.signatures[0]],
[secondAddress, secondSignResponse.signatures[0]],
// Repeat for however many signatures are required
]);

const multiSignedTxBytes = makeMultisignedTxBytes(
multiSigPubkey,
multiSigAccount.sequence,
TX_FEE,
firstSignResponse.bodyBytes, // or any signature since all signatures sign the same body
signatures
);

const result = await broadcaster.broadcastTx(multiSignedTxBytes);

Clients

getCosmWasmClient
getSigningCosmWasmClient
getSigningStargateClient
getStargateClient

Config

createSeiAminoTypes
createSeiRegistry

Interfaces

ChainConfig
ChainInfo
Currency
FeeCurrency

Utils

compressedPubKeyToAddress
deriveAddressesFromPrivateKey
getAddressHashFromPubKey
isValidSeiCosmosAddress
makeADR36AminoSignDoc
pubKeyToBytes
pubKeyToKeyPair
sha256
toBech32
truncateSeiAddress
verifyArbitrary
verifyDigest32

Wallets (Advanced)

generateWallet
getChainSuggest
getHdPath
restoreWallet