Bolt SUI TypeScript SDK
Integrate with Bolt Liquidity Protocol 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/sui-clientyarn add @bolt-liquidity-hq/cosmwasm-clientpnpm install @bolt-liquidity-hq/sui-clientInitialize the Bolt Client
The SDK supports different environments:
type Environment = 'mainnet' | 'testnet';import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
const client = new BoltSuiClient();import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
const client = new BoltSuiClient({
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 suiAsset = assets.find((a) => a.symbol === 'SUI');
console.log(`SUI type: ${suiAsset?.denom}`); // "0x2::sui::SUI"Execute a swap
// Get signer from wallet (implementation depends on wallet)
const signer: Signer = await getSuiWalletSigner();
// Execute a swap: exactly 1 SUI for USDC
const result = await client.swap({
assetIn: '0x2::sui::SUI',
amountIn: '1000000000', // 1 SUI (9 decimals)
assetOut: '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC', // USDC
minimumAmountOut: '1900000', // Minimum 1.9 USDC (6 decimals)
}, signer);
console.log(`Swapped 1 SUI for ${result.amountOut} USDC`);
console.log(`Transaction digest: ${result.txHash}`);
console.log(`Gas cost: ${result.txOutput.effects.gasUsed.computationCost}`);
console.log(`Status: ${result.txOutput.effects.status.status}`);API
Client Initialization
import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
// Initialize client
const client = new BoltSuiClient({
environment: 'mainnet', // 'testnet' | 'mainnet'
customOverride: {
chainConfig: {
rpcEndpoint: 'https://my-custom-rpc-endpoint...', // Remove this if you want to use the 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 Sui 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 { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
// Initialize client
const client = new BoltSuiClient();
// 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 { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
const client = new BoltSuiClient();
// 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 suiAsset = assets.find((a) => a.symbol === 'SUI');
console.log(`SUI type: ${suiAsset?.denom}`); // "0x2::sui::SUI"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 SUI/USDC price
const price = await client.getPrice(
'0x2::sui::SUI',
'0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC' // USDC
);
console.log(`SUI/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 { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
const client = new BoltSuiClient();
// Get base asset liquidity of a Pool by contract address
const poolAddress = "0x...";
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 { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
const client = new BoltSuiClient();
// 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 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 suiPools = allPools.filter(pool =>
pool.baseDenom === "0x2::sui::SUI"
);
console.log(`SUI pools found: ${suiPools.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 = "0x1234567890abcdef...";
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, quoteDenom: 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 USDC/SUI pair on the Bolt Sui Outpost
const pool = await client.getPoolByDenom('0x2::sui::SUI', '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC');
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 getPoolConfigByDenom(baseDenom: string, quoteDenom: 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 for USDC/SUI pair on the Bolt Sui Outpost
const config = await client.getPoolConfigByDenom('0x2::sui::SUI', '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC');
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 SUI for USDC
const simulation = await client.simulateSwap({
assetIn: "0x2::sui::SUI",
amountIn: "1000000000", // 1 SUI (9 decimals)
assetOut: "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC", // 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<SuiTransactionBlockResponse>>
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<SuiTransactionBlockResponse> = {
txOutput: SuiTransactionBlockResponse; // 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