Bolt Archway TypeScript SDK
Integrate with Bolt Liquidity Protocol on Archway network using TypeScript
Overview
The Bolt TypeScript SDK enables seamless integration with the Bolt Liquidity Protocol across multiple blockchain networks. Built with extensibility in mind, this SDK provides developers with a comprehensive, type-safe interface to access all protocol functionality including price feeds, token swaps, liquidity management, and pool operations.
Quickstart
Prerequisites
Before using the SDK, make sure you have:
Installation
npm install @bolt-liquidity-hq/cosmwasm-clientyarn add @bolt-liquidity-hq/cosmwasm-clientpnpm add @bolt-liquidity-hq/cosmwasm-clientInitialize the Bolt Client
The SDK supports different environments:
type Environment = 'mainnet' | 'testnet';Mainnet
import { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';
const client = new BoltCosmWasmClient();Testnet
import { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';
const client = new BoltCosmWasmClient({
environment: 'testnet',
});Query all assets
// Get all supported assets
const assets = await client.getAssets();
assets.forEach((asset) => {
console.log(`${asset.symbol} (${asset.name}): ${asset.denom}`);
console.log(` Decimals: ${asset.decimals}`);
});
// Find a specific asset
const archAsset = assets.find((a) => a.symbol === 'ARCH');
console.log(`ARCH denom: ${archAsset?.denom}`); // "aarch"Execute a swap
import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing';
// Get signer from wallet (implementation depends on wallet)
const signer = await DirectSecp256k1HdWallet.fromMnemonic("my mnemonic goes here", {
prefix: 'archway',
});
// Execute a swap: exactly 1 ARCH for USDC
const result = await client.swap({
assetIn: 'aarch',
amountIn: '1000000000000000000', // 1 ARCH (18 decimals)
assetOut: 'ibc/43897B9739BD63E3A08A88191999C632E052724AB96BD4C74AE31375C991F48D', // USDC
minimumAmountOut: '1900000', // Minimum 1.9 USDC (6 decimals)
, signer});
console.log(`Swapped 1 ARCH for ${result.amountOut} USDC`);
console.log(`Transaction hash: ${result.txHash}`);
console.log(`Gas cost: ${result.txOutput.gasUsed}`);
console.log(`Status: ${result.txOutput.code === 0 ? 'success' : 'failed'}`);API
Client Initialization
import { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';
// Initialize client
const client = new BoltCosmWasmClient({
environment: 'mainnet', // 'testnet' | 'mainnet'
customOverride: {
chainConfig: {
rpcEndpoint: 'https://my-custom-rpc-endpoint...', // Remove this if you want to use default public RPC endpoint
}
}
});Get oracle config
async getOracleConfig(): Promise<OracleConfig>Returns a Promise object containing the oracle's configuration parameters:
type OracleConfig = {
admin: Address; // The Archway address authorized to update oracle settings and prices
priceThresholdRatio: string; // Minimum price change ratio required for updates (as decimal string)
priceExpireTime: Duration | null; // Time duration before prices become stale
};
type Duration = {
secs: number; // Seconds component
nanos: number; // Nanoseconds component (always 0 in current implementation)
};Usage example
import { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';
// Initialize client
const client = new BoltCosmWasmClient();
// Get oracle configuration
const config = await client.getOracleConfig();
console.log('Oracle Admin:', config.admin);
console.log('Price Threshold:', config.priceThresholdRatio);
console.log('Price Expiry (seconds):', config.priceExpireTime?.secs);Integration Examples
Query prices and assets
async getAssets(): Promise<Asset[]>type Asset = {
symbol: string; // Trading symbol (e.g., "SUI", "USDC")
name: string; // Full asset name (e.g., "Sui", "USD Coin")
chainId: string; // Blockchain network identifier
denom: string; // Chain-specific denomination
decimals: number; // Number of decimal places
logo?: string; // Optional logo URL
coingeckoId?: string; // Optional CoinGecko identifier
};Usage example
import { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';
const client = new BoltCosmWasmClient();
// Get all available assets
const assets = await client.getAssets();
console.log('Available assets:', assets.length);
assets.forEach(asset => {
console.log(`${asset.symbol}: ${asset.name} (${asset.decimals} decimals)`);
});
/ Find a specific asset
const archAsset = assets.find((a) => a.symbol === 'ARCH');
console.log(`ARCH denom: ${archAsset?.denom}`); // "aarch"async getAllOracleAssetPairs(): Promise<OracleAssetPair[]>type OracleAssetPair = {
base: OracleAsset; // Base asset information
quote: OracleAsset; // Quote asset information
};
type OracleAsset = {
name: string; // Asset name (currently same as symbol)
symbol: string; // Trading symbol (e.g., "SUI", "ETH")
precision: number; // Number of decimal places
};Usage example
// Get all supported trading pairs
const assetPairs = await client.getAllOracleAssetPairs();
console.log('Supported trading pairs:', assetPairs.length);
assetPairs.forEach(pair => {
console.log(`${pair.base.symbol}/${pair.quote.symbol} (${pair.base.precision}/${pair.quote.precision} decimals)`);
});async getAllPrices(): Promise<Price[]>type Price = {
assetPair: string; // Currently empty string due to contract limitations
price: string; // Current price as decimal string
expiryTime: string; // Unix timestamp in nanoseconds when price expires
};Usage example
// Get all current prices
const allPrices = await client.getAllPrices();
console.log('Total prices available:', allPrices.length);
allPrices.forEach(price => {
console.log(`Price: ${price.price}, Expires: ${new Date(Number(price.expiryTime) / 1000000)}`);
});async getPrice(baseDenom: string, quoteDenom: string): Promise<InvertiblePrice>type InvertiblePrice = {
assetPair: string; // Trading pair in format "baseDenom:quoteDenom"
price: string; // Current price as decimal string
expiryTime: string; // Unix timestamp in nanoseconds when price expires
isInverse: boolean; // Always false in current implementation
};Usage example
// Get ARCH/USDC price
const price = await client.getPrice(
'aarch',
'ibc/43897B9739BD63E3A08A88191999C632E052724AB96BD4C74AE31375C991F48D' // USDC
);
console.log(`ARCH/USDC Price: ${price.price}`);
console.log(`Expires at: ${new Date(Number(price.expiryTime) / 1000000)}`);
console.log(`Asset Pair: ${price.assetPair}`);Verify pool liquidity
async getPoolBaseLiquidity(poolContractAddress: string): Promise<BaseLiquidityDetails>type BaseLiquidityDetails = {
baseLiquidity: Coin; // Base asset liquidity information
totalShares: string; // Total liquidity shares
};
type Coin = {
amount: string; // Quantity of base asset liquidity
denom: string; // Type of the base asset
};Usage example
import { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';
const client = new BoltCosmWasmClient();
// Get base asset liquidity of a Pool by contract address
const poolAddress = "archway1f1e...";
const liquidity = await client.getAllBaseAssetsLiquidity(poolAddress);
console.log(`Base liquidity: ${liquidity.baseLiquidity.amount} ${liquidity.baseLiquidity.denom}`);
console.log(`Total shares: ${liquidity.totalShares}`);async getAllBaseAssetsLiquidity(): Promise<Record<Address, BaseLiquidityDetails>>type BaseLiquidityDetails = {
baseLiquidity: Coin; // Base asset liquidity information
totalShares: string; // Total liquidity shares
};
type Coin = {
amount: string; // Quantity of base asset liquidity
denom: string; // Type of the base asset
};Usage example
import { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';
const client = new BoltCosmWasmClient();
// Get all base asset liquidity
const liquidity = await client.getAllBaseAssetsLiquidity();
console.log('Base asset liquidity:', Object.keys(liquidity).length);
Object.entries(liquidity).forEach(([denom, details]) => {
console.log(`${denom}: ${details.baseLiquidity.amount} (${details.totalShares} shares)`);
});Get Router contract config
async getRouterConfig(): Promise<RouterConfig>type RouterConfig = {
admin: string; // Sui address with administrative privileges
defaultPriceOracleContract: string; // Object ID of default price oracle
defaultProtocolFeeRecipient: string; // Sui address that receives protocol fees
defaultProtocolFee: string; // Protocol fee percentage (e.g., "0.003" = 0.3%)
defaultLpFee: string; // LP fee percentage (e.g., "0.002" = 0.2%)
};Usage example
// Get router configuration
const config = await client.getRouterConfig();
console.log('Router Admin:', config.admin);
console.log('Price Oracle:', config.defaultPriceOracleContract);
console.log('Protocol Fee Recipient:', config.defaultProtocolFeeRecipient);
console.log('Protocol Fee:', config.defaultProtocolFee);
console.log('LP Fee:', config.defaultLpFee);Get liquidity pools information
async getAllPools(): Promise<Pool[]>type Pool = {
poolAddress: string; // Contract address or Sui object ID of the pool
baseDenom: string; // Type of the base asset
quoteDenoms: string[]; // Array of available quote asset types
};Usage example
// Get all pools
const allPools = await client.getAllPools();
console.log(`Total pools available: ${allPools.length}`);
// Display all pools and their trading pairs
allPools.forEach((pool, index) => {
console.log(`\nPool ${index + 1}: ${pool.poolAddress}`);
console.log(` Base asset: ${pool.baseDenom}`);
console.log(` Quote assets: ${pool.quoteDenoms.length}`);
pool.quoteDenoms.forEach(quote => {
console.log(` - ${quote}`);
});
});
// Find pools for specific base asset
const archPools = allPools.filter(pool =>
pool.baseDenom === "aarch"
);
console.log(`ARCH pools found: ${archPools.length}`);async getPoolConfig(contractAddress: Address): Promise<PoolConfig>type PoolConfig = {
priceOracleContract: string; // Object ID of price oracle used by this pool
protocolFeeRecipient: string; // Sui address that receives protocol fees
protocolFee: string; // Protocol fee percentage (e.g., "0.003" = 0.3%)
lpFee: string; // LP fee percentage (e.g., "0.002" = 0.2%)
allowanceMode: string; // Allowance mode for pool operations
lps: string[]; // Array of authorized LP Sui addresses
minBaseOut: string; // Minimum base asset output amount for trades
};Usage example
// Get pool configuration by contract address
const poolAddress = "archway1f1e...";
const config = await client.getPoolConfig(poolAddress);
console.log('Pool Configuration:');
console.log(' Price Oracle:', config.priceOracleContract);
console.log(' Protocol Fee:', config.protocolFee);
console.log(' LP Fee:', config.lpFee);
console.log(' Allowance Mode:', config.allowanceMode);
console.log(' Min Base Out:', config.minBaseOut);async getPoolByDenom(baseDenom: string): Promise<Pool>type Pool = {
poolAddress: string; // Contract address or Sui object ID of the pool
baseDenom: string; // Type of the base asset
quoteDenoms: string[]; // Array of available quote asset types
};Usage example
// Get pool for ATOM base asset
const pool = await client.getPoolByDenom('ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2');
console.log('Pool Address:', pool.poolAddress);
console.log('Base Asset:', pool.baseDenom);
console.log('Quote Assets:', pool.quoteDenoms.length);
pool.quoteDenoms.forEach(quote => {
console.log(` - ${quote}`);
});async getPooConfigByDenom(baseDenom: string): Promise<PoolConfig>type PoolConfig = {
priceOracleContract: string; // Object ID of price oracle used by this pool
protocolFeeRecipient: string; // Sui address that receives protocol fees
protocolFee: string; // Protocol fee percentage (e.g., "0.003" = 0.3%)
lpFee: string; // LP fee percentage (e.g., "0.002" = 0.2%)
allowanceMode: string; // Allowance mode for pool operations
lps: string[]; // Array of authorized LP Sui addresses
minBaseOut: string; // Minimum base asset output amount for trades
};Usage example
// Get pool configuration for ATOM base asset
const config = await client.getPoolConfigByBaseAsset('ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2');
console.log('Price Oracle:', config.priceOracleContract);
console.log('Protocol Fee Recipient:', config.protocolFeeRecipient);
console.log('Protocol Fee:', config.protocolFee);
console.log('LP Fee:', config.lpFee);
console.log('Allowance Mode:', config.allowanceMode);
console.log('Authorized LPs:', config.lps.length);
console.log('Min Base Out:', config.minBaseOut);Simulate a swap
async simulateSwap(): Promise<SimulateSwapResult>type type SimulateSwapResult = {
poolAddress: string; // Contract address or Sui object ID of the pool
amountOut: string; // Amount expected to be received after the swap
assetOut: string; // Denom of the asset that will be received after the swap
protocolFee: string; // The protocol fee amount that would be charged
lpFee: string; // The liquidity provider fee amount that would be charged
dynamicFeePercentage?: string; // Percentage of the swap that goes to dynamic fees on the Sui Outpost
totalFees: string; // The sum of protocolFee and lpFee (dynamic fee is distributed between both)
}Usage example
// Simulate swapping 1 ARCH for USDC
const simulation = await client.simulateSwap({
assetIn: "aarch",
amountIn: "1000000000000000000", // 1 ARCH (18 decimals)
assetOut: "ibc/43897B9739BD63E3A08A88191999C632E052724AB96BD4C74AE31375C991F48D" // USDC
});
console.log(`Pool: ${simulation.poolAddress}`);
console.log(`Expected output: ${simulation.amountOut} ${simulation.assetOut}`);
console.log(`Protocol fee: ${simulation.protocolFee}`);
console.log(`LP fee: ${simulation.lpFee}`);
if (simulation.dynamicFee) {
console.log(`Dynamic fee: ${simulation.dynamicFee}`);
}
console.log(`Total fees: ${simulation.totalFees}`);How to execute a swap
async swap(params: SwapParams, signer: Signer): Promise<SwapResult<ExecuteResult>>
type SwapParams = {
assetIn: string; // Denomination of the asset being sold
amountIn: string; // Exact amount of input asset to swap (in minimal units)
assetOut: string; // Denomination of the asset being bought
minimumAmountOut?: string; // Optional minimum acceptable amount of output asset
receiver?: Address; // Optional recipient address for swapped assets
};type SwapResult<ExecuteResult> = {
txOutput: ExecuteResult; // Complete transaction response
amountOut: string; // Actual amount of output asset received
assetOut: string; // Output asset denomination
txHash: string; // Transaction hash for tracking
};Basic usage examples
Best practices
Error Handling
The SDK provides custom error types for better error handling:
NotFoundError - Resource not found
InvalidParameterError - Invalid parameter provided
InvalidObjectError - Invalid object structure
InvalidTypeError - Invalid type provided
MissingParameterError - Required parameter missing
TransactionFailedError - Transaction execution failed
ParseError - Failed to parse response data