stridejs
v0.15.0
Published
The JavaScript SDK for Stride
Readme
stridejs
Table of Contents
- stridejs
Installation
npm install stridejsBasic Usage
import { StrideClient, DirectSecp256k1HdWallet, GasPrice } from "stridejs";
// Create a wallet from mnemonic
const signer = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, {
prefix: "stride",
});
// Get the address from the wallet
const [{ address }] = await signer.getAccounts();
// Create a StrideClient instance
const client = await StrideClient.create(
"http://stride-rpc.example.com:26657",
signer,
address,
{
gasPrice: GasPrice.fromString("0.025ustrd"),
},
);Integrations
Keplr Wallet
The recommended way of integrating Keplr is by using window.keplr.getOfflineSignerOnlyAmino():
import { StrideClient, sleep, GasPrice } from "stridejs";
while (!window.keplr || !window.keplr?.getOfflineSignerOnlyAmino) {
await sleep(50);
}
const CHAIN_ID = "stride-1";
await window.keplr.enable(CHAIN_ID);
const signer = window.keplr.getOfflineSignerOnlyAmino(CHAIN_ID);
const [{ address }] = await signer.getAccounts();
const stridejs = new StrideClient.create(
"http://stride-rpc.example.com:26657",
signer,
address,
{
gasPrice: GasPrice.fromString("0.025ustrd"),
},
);Links:
- Official Keplr Website »
- Keplr API Docs »
Signer vs SignerAuto vs SignerOnlyAmino
TL;DR:
getOfflineSignerOnlyAmino(): The recommended way. Supports Ledger, has a nice UI.getOfflineSigner(): No Ledger support, ugly UI, can send IBC relayer txs and submit IBC gov proposals.getOfflineSignerAuto(): If Ledger alias forgetOfflineSignerOnlyAmino(), otherwise alias forgetOfflineSigner().
window.keplr.getOfflineSignerOnlyAmino()
Although this is the legacy way of signing transactions on cosmos-sdk chains, it's still the most recommended for connecting to Keplr due to Ledger support & better UI on Keplr.
- 🟩 Looks good on Keplr
- 🟩 Supports users signing with Ledger
- 🟥 Doesn't support signing these transactions:
- Every tx type under
ibc.client,ibc.connectionandibc.channel(meaning IBC relaying, for example with ts-relayer)
- Every tx type under
Note that ibc.applications.transfer.v1.MessageComposer.withTypeUrl.transfer for sending funds across IBC is supported.
window.keplr.getOfflineSigner()
The new way of signing transactions on cosmos-sdk chain, it's more efficient but still doesn't have Ledger support. It's most recommended for usage in apps that don't require signing transactions with Ledger.
- 🟥 Looks bad on Keplr
- 🟥 Doesn't support users signing with Ledger
- 🟩 Supports signing transactions with all types of messages
window.keplr.getOfflineSignerAuto()
If the connected Keplr account uses Ledger, returns window.keplr.getOfflineSignerOnlyAmino().
Otherwise returns window.keplr.getOfflineSigner().
Leap Cosmos Wallet
The recommended way of integrating Leap is by using window.leap.getOfflineSignerAmino():
import { StrideClient, sleep, GasPrice } from "stridejs";
while (!window.leap || !window.leap?.getOfflineSignerOnlyAmino) {
await sleep(50);
}
const CHAIN_ID = "stride-1";
await window.leap.enable(CHAIN_ID);
const signer = window.leap.getOfflineSignerOnlyAmino(CHAIN_ID);
const [{ address }] = await signer.getAccounts();
const stridejs = new StrideClient.create(
"http://stride-rpc.example.com:26657",
signer,
address,
{
gasPrice: GasPrice.fromString("0.025ustrd"),
},
);Links:
- Official Leap Website »
- Leap API Docs »
Ledger
LedgerSigner can be used to sign transactions with a Ledger wallet running the Cosmos app.
import { StrideClient, makeCosmoshubPath, LedgerSigner } from "stridejs";
// NodeJS only
import TransportNodeHid from "@ledgerhq/hw-transport-node-hid";
// Browser only
//import TransportNodeHid from "@ledgerhq/hw-transport-webusb";
const interactiveTimeout = 120_000;
const accountIndex = 0;
const cosmosPath = makeCosmoshubPath(accountIndex);
const ledgerTransport = await TransportNodeHid.create(
interactiveTimeout,
interactiveTimeout,
);
const signer = new LedgerSigner(ledgerTransport, {
testModeAllowed: true,
hdPaths: [cosmosPath],
prefix: "stride",
});
const [{ address }] = await signer.getAccounts();
const stridejs = new StrideClient.create(
"http://stride-rpc.example.com:26657",
signer,
address,
{
gasPrice: GasPrice.fromString("0.025ustrd"),
},
);Links:
@cosmjs/ledger-aminoDocumentation »
StrideClient
Creating a Client
const client = await StrideClient.create(
rpcUrl: string,
signer: OfflineSigner,
address: string,
options?: StrideClientOptions
)Parameters
rpcUrl: URL to the CometBFT RPC endpointsigner: Signer for signing transactionsaddress: Account address that can sign transactionsoptions: Optional configuration object:type StrideClientOptions = { gasPrice?: GasPrice; registry?: Registry; aminoTypes?: AminoTypes; broadcastTimeoutMs?: number; // default: 60_000, broadcastPollIntervalMs?: number; // default: 3_000, resolveIbcResponsesTimeoutMs?: number; // default: 180_000 resolveIbcResponsesCheckIntervalMs?: number; // default: 12_000 };
Properties
class StrideClient {
readonly rpcEndpoint: string;
readonly signer: OfflineSigner;
readonly address: string;
readonly signingStargateClient: SigningStargateClient;
readonly query: QueryClient & AuthExtension & BankExtension & more;
readonly options?: StrideClientOptions;
}Methods
signAndBroadcast
async signAndBroadcast(
messages: readonly EncodeObject[],
fee: StdFee | "auto" | number = "auto", // defaults to "auto" - simulates the tx and uses 1.4 as gas limit multiplier
memo: string = ""
): Promise<DeliverTxResponse & { ibcResponses: Array<Promise<IbcResponse>> }>Signs and broadcasts transaction(s). Returns transaction response with IBC acknowledgements if there are any.
Example:
import { coinsFromString, cosmos, getValueFromEvents, ibc } from "stridejs";
// Send tokens
const sendTx = await client.signAndBroadcast(
[
cosmos.bank.v1beta1.MessageComposer.withTypeUrl.send({
fromAddress: client.address,
toAddress: "stride1...",
amount: coinsFromString("1000000ustrd"),
}),
],
"auto", // automatic gas estimation
);
if (sendTx.code === 0) {
// success
}
// IBC transfer
const ibcTx = await client.signAndBroadcast([
ibc.applications.transfer.v1.MessageComposer.withTypeUrl.transfer({
sourcePort: "transfer",
sourceChannel: "chennel-123",
token: coinFromString("100000ustrd"),
sender: "stride1...",
receiver: "osmo1...",
timeoutHeight: {
revisionNumber: 0n,
revisionHeight: 0n,
},
timeoutTimestamp: `${Math.floor(Date.now() / 1000) + 3 * 60}000000000`, // 3min
memo: "",
}),
// defaults to automatic gas estimation
]);
// Wait for IBC acknowledgements
const ibcAck = await ibcTx.ibcResponses[0];
if (
ibcAck.type === "ack" &&
ibcAck.tx.code === 0 &&
getValueFromEvents(ibcAck.tx.events, "fungible_token_packet.success") ===
"\u0001"
) {
// success
}IBC Types & Functions
IBC Response Types
type IbcResponse = {
type: "ack" | "timeout";
tx: IndexedTx;
};
type IbcTransferPath = {
incomingPortId: string;
incomingChannelId: string;
};IBC Transfer Functions
ibcDenom
function ibcDenom(paths: IbcTransferPath[], coinMinimalDenom: string): string;Computes the IBC denom of a token after being sent through IBC channels.
Example:
// Get STRD denom on Osmosis after transfer through channel-326
const osmoDenom = ibcDenom(
[
{
incomingPortId: "transfer",
incomingChannelId: "channel-326",
},
],
"ustrd",
);
// Get ATOM denom on Stride after transfer through multiple channels
const strideDenom = ibcDenom(
[
{
incomingPortId: "transfer",
incomingChannelId: "channel-0",
},
{
incomingPortId: "transfer",
incomingChannelId: "channel-1",
},
],
"uatom",
);getTxIbcResponses
function getTxIbcResponses(
stargateClient: StargateClient,
txResponse: DeliverTxResponse,
resolveResponsesTimeoutMs?: number,
resolveResponsesCheckIntervalMs?: number,
): Array<Promise<IbcResponse>>;Gets IBC acknowledgements or timeouts for an IBC transaction.
Example:
const tx = await client.signAndBroadcast([ibcTransferMsg], "auto");
const ibcResponses = await Promise.all(tx.ibcResponses);
for (const resp of ibcResponses) {
if (resp.type === "ack") {
console.log("IBC transfer succeeded");
} else {
console.log("IBC transfer reverted due to a timeout");
}
}findIbcResponse
async function findIbcResponse(
stargateClient: StargateClient,
packetSequence: string,
packetSrcChannel: string,
type: "ack" | "timeout" = "ack",
resolveResponsesTimeoutMs: number = 180000,
resolveResponsesCheckIntervalMs: number = 12000,
isDoneObject: { isDone: boolean } = { isDone: false },
): Promise<IbcResponse>;Low-level function to search for a specific IBC response. Usually used through getTxIbcResponses.
getTxIbcResponses
function getTxIbcResponses(
stargateClient: StargateClient,
txResponse: DeliverTxResponse,
resolveResponsesTimeoutMs: number = 180000,
resolveResponsesCheckIntervalMs: number = 12000,
): Array<Promise<IbcResponse>>;This function retrieves IBC acknowledgements or timeouts for a transaction that resulted in sending IBC packets. It returns an array of promises that resolve to IbcResponse objects, which can either be acknowledgements (ack) or timeouts (timeout).
This function is automatically used by StrideClient and is intended to be used with a CosmJS StargateClient, which may be connected to another chain.
Address & Key Functions
Bech32 Functions
convertBech32Prefix
function convertBech32Prefix(address: string, toPrefix: string): string;Converts a bech32 address from one prefix to another.
Example:
// Convert Stride address to Osmosis address
const osmoAddr = convertBech32Prefix("stride1xyz...", "osmo"); // osmo1xyz...
// Convert Stride address to Cosmos Hub address
const cosmosAddr = convertBech32Prefix("stride1xyz...", "cosmos"); // cosmos1xyz...Public Key Functions
pubkeyToAddress
function pubkeyToAddress(pubkey: Uint8Array, prefix: string = "stride"): string;Converts a secp256k1 compressed public key to a bech32 address.
base64PubkeyToAddress
function base64PubkeyToAddress(
pubkey: string,
prefix: string = "stride",
): string;Converts a base64 encoded secp256k1 compressed public key to a bech32 address.
Validator Functions
selfDelegatorAddressToValidatorAddress
function selfDelegatorAddressToValidatorAddress(
selfDelegator: string,
prefix: string = "stride",
): string;Converts a self-delegator address to its validator operator address.
Example:
const valoper = selfDelegatorAddressToValidatorAddress(
"stride1xyz...",
"stride",
); // stridevaloper1xyz...validatorAddressToSelfDelegatorAddress
function validatorAddressToSelfDelegatorAddress(
validator: string,
prefix: string = "stride",
): string;Converts a validator operator address to its self-delegator address.
tendermintPubkeyToValconsAddress
function tendermintPubkeyToValconsAddress(
pubkey: Uint8Array,
prefix: string = "stride",
): string;Converts a Tendermint ed25519 public key to a validator consensus address.
base64TendermintPubkeyToValconsAddress
function base64TendermintPubkeyToValconsAddress(
pubkey: string,
prefix: string = "stride",
): string;Converts a base64 encoded Tendermint ed25519 public key to a validator consensus address.
Coin & Fee Functions
coinFromString
function coinFromString(coinAsString: string): Coin;Converts a string representation of a coin to a Coin object.
Example:
coinFromString("1000ustrd"); // { amount: "1000", denom: "ustrd" }
coinFromString("2.5atom"); // { amount: "2.5", denom: "atom" }
coinFromString(
"1000ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2",
);coinsFromString
function coinsFromString(coinsAsString: string): Coin[];Converts a comma-separated string of coins to an array of Coin objects.
Example:
coinsFromString("1000ustrd,500uatom");
// [
// { amount: "1000", denom: "ustrd" },
// { amount: "500", denom: "uatom" }
// ]feeFromGas
function feeFromGas(gasLimit: number, gasPrice: number = 0.025): StdFee;Creates a StdFee object from gas limit and price.
Example:
feeFromGas(200000);
// {
// amount: [{ amount: "5000", denom: "ustrd" }],
// gas: "200000"
// }Event Functions
getValueFromEvents
function getValueFromEvents(events: readonly Event[], key: string): string;Searches through events to find a specific value based on event type and attribute key.
Example:
const events = [
{
type: "transfer",
attributes: [
{ key: "recipient", value: "stride1..." },
{ key: "amount", value: "1000ustrd" },
],
},
];
getValueFromEvents(events, "transfer.recipient"); // "stride1..."
getValueFromEvents(events, "transfer.amount"); // "1000ustrd"Encoding Functions
Base64
function fromBase64(base64: string): Uint8Array;
function toBase64(data: Uint8Array): string;Convert between base64 strings and Uint8Arrays.
Hex
function fromHex(hex: string): Uint8Array;
function toHex(data: Uint8Array): string;Convert between hex strings and Uint8Arrays.
ASCII
function fromAscii(ascii: string): Uint8Array;
function toAscii(data: Uint8Array): string;Convert between ASCII strings and Uint8Arrays.
UTF8
function fromUtf8(utf8: string): Uint8Array;
function toUtf8(data: Uint8Array): string;Convert between UTF8 strings and Uint8Arrays.
RFC3339 Date
function fromRfc3339(date: string): Date;
function toRfc3339(date: Date): string;Convert between RFC3339 date strings and Date objects.
Helper Functions
decToString
function decToString(dec: number): string;Formats a decimal number to Cosmos SDK decimal string format.
Example:
decToString(0.5); // "0.500000000000000000"
decToString(1.23); // "1.230000000000000000"sleep
function sleep(ms: number): Promise<void>;Utility function to pause execution.
