title | description |
---|---|
Getting Started: Typescript SDK |
Basic documentation of a Typescript SDK (@skip-router/core) that simplifies the process of interacting with the Skip API |
This document covers the Typescript library Skip provides to wrap the functionality of the Skip API and make it even easier for developers to build applications with it.
Install the library:
npm install @skip-router/core
All integrations start by initializing a SkipRouter client (@skip-router/core.SkipRouter
).
This helper objects wraps interactions with the API and provides useful helper methods for a variety of common actions that depend on inputs or outputs of the API (e.g. querying for assets and chains, constructing a route, constructing + signing a transaction from a message returned by the API)
import { SkipRouter, SKIP_API_URL } from "@skip-router/core";
const client = new SkipRouter({
apiURL: SKIP_API_URL,
getOfflineSigner: async (chainID) => {
return DirectSecp256k1HdWallet.fromMnemonic(MNEMONIC);
},
});
The client constructor takes several optional inputs provided together by the SkipRouterOptions
object:
apiURL
: A URL for interacting with the Skip API (Defaults to the production URL)getOfflineSigner
: A function for getting a"@cosmjs/proto-signing.OfflineSigner
based on a chainID (Defaults to nil)endpointOptions
: An object that you can use to set the RPCs + CosmosSDK REST APIs you want to interact with for each chain (either by providing a map from chain ID to Tendermint RPC + CosmosSDK REST endpoints for each chain or functions that map chainID to endpoint)
Now that your client is initialized, you can use it to query basic information about chains & assets to populate your user interface. For example:
// get a Chain[] of all supported chains
const chains = await client.chains();
const asset_req: AssetRequest = {
chainID: "osmosis-1"
nativeOnly: false,
includeNoMetadataAssets: false
}
const assets = await client.assets(asset_req);
After querying basic information about chains and assets, you can utilize the recommendAssets
method to find the best routes for moving assets between chains. This feature is particularly useful for obtaining recommendations on which unique asset should be received on the destination chain for an optimal user experience. These recommendations are based on factors like liquidity pools, token denominations, and the unique characteristics of each IBC transfer route.
Usage example:
const request = [
{
source_asset_denom: "uusdc",
source_asset_chain_id: "axelar-dojo-1",
dest_chain_id: "cosmoshub-4"
},
{
source_asset_denom: "uusdc",
source_asset_chain_id: "axelar-dojo-1",
dest_chain_id: "osmosis-1"
}
];
const recommendations = await client.recommendAssets(request);
Response example:
{
"recommendations": [],
"recommendation_entries": [
{
"recommendations": [
{
"asset": {
"denom": "ibc/932D6003DA334ECBC5B23A071B4287D0A5CC97331197FE9F1C0689BA002A8421",
"chain_id": "cosmoshub-4",
"origin_denom": "uusdc",
"origin_chain_id": "axelar-dojo-1",
"trace": "transfer/channel-293",
"is_cw20": false,
"is_evm": false,
"symbol": "USDC",
"name": "USDC",
"logo_uri": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/usdc.png",
"decimals": 6,
"description": "Circle's stablecoin on Axelar",
"coingecko_id": "axlusdc",
"recommended_symbol": "USDC.axl"
},
"reason": "MOST_LIQUID"
}
]
},
{
"recommendations": [
{
"asset": {
"denom": "ibc/D189335C6E4A68B513C10AB227BF1C1D38C746766278BA3EEB4FB14124F1D858",
"chain_id": "osmosis-1",
"origin_denom": "uusdc",
"origin_chain_id": "axelar-dojo-1",
"trace": "transfer/channel-208",
"is_cw20": false,
"is_evm": false,
"symbol": "USDC",
"name": "USDC",
"logo_uri": "https://raw.githubusercontent.com/cosmos/chain-registry/master/axelar/images/usdc.png",
"decimals": 6,
"description": "Circle's stablecoin on Axelar",
"coingecko_id": "axlusdc",
"recommended_symbol": "USDC.axl"
},
"reason": "MOST_LIQUID"
}
]
}
]
}
Once your user has selected source and destination tokens and chains, you can use the client to generate a route and quote:
const route = await client.route({
amountIn: AMOUNT_IN,
sourceAssetDenom: SOURCE_DENOM,
sourceAssetChainID: SOURCE_CHAIN_ID,
destAssetDenom: DEST_DENOM,
destAssetChainID: DEST_CHAIN_ID,
cumulativeAffiliateFeeBPS: "0",
});
Once you have a route, you can execute it in a single function call (passing in the route, the user addresses for at least the chains the route includes, and an optional callback function.
For example:
await client.executeRoute({
route,
userAddresses: USER_ADDRESSES,
onTransactionSuccess: async (chainID, txHash, success) => {
console.log(txHash);
},
});
For routes that consist of multiple transactions, this will monitor each transaction until it completes, then generate the transaction for the next step and prompt the user to sign it.
Alternatively, you can use the route to generate, sign, and submit the messages separately -- or use your own solutions for any/all of these steps if you like. See SkipRouter.messages
, SkipRouter.signMultiChainMessageDirect
, and SkipRouter.submitTransaction
for details on these lower-level functions
Once the user has signed a transaction to execute a cross-chain action, you can track it using the SkipRouter
functions:
SkipRouter.trackTransaction
: Requests tracking for a that's already been submitted to the network through an RPC, using the transaction hashSkipRouter.submitTransaction
: Publishes the signed transaction to the network & begins tracking the cross-chain actions this transaction produces
After you've used one of these two functions to kick-off realtime tracking for a cross-chain action, you can request the current status of the transaction using SkipRouter.transactionStatus
.
We also provide a waitForTransaction
helper function that hangs until the entire cross-chain action flow has completed, which you can use instead of configuring your own polling via transactionStatus
Want to help us get better? Have questions or feedback?
You can reach us easily at [email protected] or in our developer support channel on TG