Getting Started
@skip-go/client is a TypeScript library that streamlines interaction with the Skip Go API, enabling cross-chain swaps and transfers across multiple ecosystems.
Anxious to get started? See a live example of this code in our example app.
Install Library
Install the library using npm or yarn:
Initialize Client
To start integrating with the Skip Go API, initialize a SkipClient
instance. This skipClient
provides helper methods for common actions such as querying assets and chains, constructing routes, and executing transactions.
import { SkipClient } from "@skip-go/client";
const skipClient = new SkipClient({
// Signers will be set up in the following section
});
The SkipClient constructor accepts an optional configuration object of type SkipClientOptions
. Here’s a brief overview:
apiURL?: string
: Override the default API URLendpointOptions?: EndpointOptions
: Provide RPC and REST endpoints for specific chainsaminoTypes?: AminoConverters
: Additional amino types to be for message encodingregistryTypes?: Iterable<[string, GeneratedType]>
: Additional registry types
Setup Signers
To execute transactions, you need to set up signers for the ecosystems you plan to interact with. Below are examples for Cosmos SDK, EVM, and Solana (SVM). Note that for EVM and SVM, you’ll need to install additional libraries.
Signer Setup
Finalizing the Client Initialization
Now, pass the signers and your optional configuration options into your SkipClient
instance:
const skipClient = new SkipClient({
getCosmosSigner,
getEVMSigner,
getSVMSigner,
// ...configOptions,
});
Query Basic Info
With your client initialized, you can query balances, supported chains and assets.
Get a Route
Once you’ve selected your source and destination chains and tokens, you can generate a route and get a quote. See it in context here.
Read more about affiliate fees, Smart Relay and EVM Swaps.
Get Required Addresses
After generating a route, you need to provide user addresses for the required chains. The route.requiredChainAddresses
array lists the chain IDs for which addresses are needed.
Only use addresses your user can sign for. Funds could get stuck in any address you provide, including intermediate chains in certain failure conditions. Ensure your user can sign for each address you provide. See Cross-chain Failure Cases for more details.
We recommend storing the user’s addresses and creating a function like getAddress
that retrieves the address based on the chain ID.
// get user addresses for each requiredChainAddress to execute the route
const userAddresses = await Promise.all(
route.requiredChainAddresses.map(async (chainID) => ({
chainID,
address: await getAddress(chainID),
}))
);
Execute the Route
Once you have a route, you can execute it in a single function call by passing in the route, the user addresses for at least the chains the route includes, and optional callback functions. This also registers the transaction for tracking.
await skipClient.executeRoute({
route,
userAddresses,
// Executes after all of the operations triggered by a user's signature complete.
// For multi-tx routes that require multiple user signatures, this will be called once for each tx in sequence
onTransactionCompleted: async (chainID, txHash, status) => {
console.log(
`Route completed with tx hash: ${txHash} & status: ${status.state}`
);
},
// called after the transaction that the user signs gets broadcast on chain
onTransactionBroadcast: async ({ txHash, chainID }) => {
console.log(`Transaction broadcasted with tx hash: ${txHash}`);
},
// called after the transaction that the user signs is successfully registered for tracking
onTransactionTracked: async ({ txHash, chainID }) => {
console.log(`Transaction tracked with tx hash: ${txHash}`);
},
// called after the user signs a transaction
onTransactionSigned: async ({ txHash, chainID }) => {
console.log(`Transaction signed with tx hash: ${txHash}`);
},
// validate gas balance on each chain
onValidateGasBalance: async ({ chainID, txIndex, status }) => {
console.log(`Validating gas balance for chain ${chainID}...`);
},
});
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, the route object allows you to generate, sign, and submit messages individually. You can also implement your own solutions for any or all of these steps. For more details on these lower-level functions, refer to skipClient.messages
, skipClient.signMultiChainMessageDirect
, and skipClient.submitTransaction
.
Transaction Tracking
Once the user has signed a transaction to execute a cross-chain action, you can track it with:
skipClient.trackTransaction
: Requests tracking for a transaction that’s already been submitted to the network through an RPC, using the transaction hashskipClient.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 skipClient.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
.
Have questions or feedback? Help us get better!
Join our Discord and select the “Skip Go Developer” role to share your questions and feedback.