---
description: >-
  Integrate with Bolt Liquidity Protocol using TypeScript across multiple
  blockchain networks (Archway, SUI).
---

# Bolt TypeScript SDK

## 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

{% stepper %}
{% step %}
**Prerequisites**

{% tabs %}
{% tab title="SUI Outpost" %}
Before using the SDK, make sure you have:

* [x] Node.js 16+ installed.
* [x] A Sui-compatible wallet (Sui Wallet, Suiet, etc.) for signing transactions.
* [x] Access to SUI RPC endpoints (The client uses by default the public endpoint `https://fullnode.mainnet.sui.io:443` for `mainnet`, and `https://fullnode.testnet.sui.io:443` for `testnet`).
{% endtab %}

{% tab title="Archway Outpost" %}
Before using the SDK, make sure you have:

* [x] Node.js 16+ installed.
* [x] An Archway-compatible wallet (Keplr, Leap, etc.) for signing transactions.
* [x] Access to Archway RPC endpoints (The client uses by default the public endpoint `https://rpc.mainnet.archway.io` for `mainnet`, and `https://rpc.constantine.archway.io` for `testnet`)
{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}
**Installation**

{% tabs %}
{% tab title="SUI Outpost" %}
NPM

```bash
npm install @bolt-liquidity-hq/sui-client
```

Yarn

```bash
yarn install @bolt-liquidity-hq/sui-client
```

PNPM

```bash
pnpm install @bolt-liquidity-hq/sui-client
```
{% endtab %}

{% tab title="Archway Outpost" %}
NPM

```bash
npm add @bolt-liquidity-hq/cosmwasm-client
```

Yarn

```bash
yarn add @bolt-liquidity-hq/cosmwasm-client
```

PNPM

```bash
pnpm add @bolt-liquidity-hq/cosmwasm-client
```
{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}
**Initialize the Bolt Client**

The SDK supports different environments:

```typescript
type Environment = 'mainnet' | 'testnet';
```

{% tabs %}
{% tab title="SUI Outpost" %}
**Mainnet**

```typescript
import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';

const client = new BoltSuiClient();
```

**Testnet**

```typescript
import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';

const client = new BoltSuiClient({
  environment: 'testnet',
});
```
{% endtab %}

{% tab title="Archway Outpost" %}
**Mainnet**

```typescript
import { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';

const client = new BoltCosmWasmClient();
```

**Testnet**

```typescript
import { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';

const client = new BoltCosmWasmClient({
  environment: 'testnet',
});
```
{% endtab %}
{% endtabs %}
{% endstep %}

{% step %}
**Query all assets**

```typescript
// 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"
```
{% endstep %}

{% step %}
**Execute a swap**

{% tabs %}
{% tab title="SUI Outpost" %}
```typescript
import type { Signer } from '@mysten/sui/cryptography';

// 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(signer, {
  assetIn: '0x2::sui::SUI',
  amountIn: '1000000000', // 1 SUI (9 decimals)
  assetOut: '0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN', // USDC
  minimumAmountOut: '1900000', // Minimum 1.9 USDC (6 decimals)
});

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}`);
```
{% endtab %}

{% tab title="Archway Outpost" %}
```typescript
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 SUI for USDC
const result = await client.swap(signer, {
  assetIn: 'aarch',
  amountIn: '1000000000000000000', // 1 ARCH (18 decimals)
  assetOut: 'ibc/43897B9739BD63E3A08A88191999C632E052724AB96BD4C74AE31375C991F48D', // USDC
  minimumAmountOut: '1900000', // Minimum 1.9 USDC (6 decimals)
});

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'}`);
```
{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

## API

### Client Initialization

{% tabs %}
{% tab title="SUI Outpost" %}
```typescript
import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';

// Initialize client
const client = new BoltSuiClient({
  environment: 'testnet', // 'testnet' | 'mainnet'
  customOverride: {
    rpcEndpoint: 'https://my-custom-rpc-endpoint...', // Remove this if you want to use the default public RPC endpoint
  }
});
```
{% endtab %}

{% tab title="Archway Outpost" %}
```typescript
import { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';

// Initialize client
const client = new BoltCosmWasmClient({
  environment: 'testnet', // 'testnet' | 'mainnet'
  customOverride: {
    rpcEndpoint: 'https://my-custom-rpc-endpoint...', // Remove this if you want to use default public RPC endpoint
  }
});
```
{% endtab %}
{% endtabs %}

<details>

<summary>Advanced client initialization</summary>

<pre class="language-typescript"><code class="lang-typescript"><strong>import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
</strong>
// Initialize client
const client = new BoltSuiClient({
  environment: 'testnet',
  customOverride: {
    chainConfig: {
      id: 'sui-mainnet',
      name: 'Sui',
      rpcEndpoint: 'https://fullnode.mainnet.sui.io:443',
    },
    packageId: '0x1234...',
    contracts: {
      oracle: '0xoracle...',
      router: '0xrouter...',
    },
    assetsConfig: {
      '0x2::sui::SUI': {
        symbol: 'SUI',
        name: 'Sui',
        chainId: 'sui-mainnet',
        denom: '0x2::sui::SUI',
        decimals: 9,
        logo: 'https://...',
        coingeckoId: 'sui',
      },
    },
  },
});
</code></pre>

**Environment configuration**

| Parameter   | Type                   | Default   | Description                            |
| ----------- | ---------------------- | --------- | -------------------------------------- |
| environment | `mainnet` \| `testnet` | `mainnet` | Specifies to which network to connect. |

**Override chain configuration**

<table data-full-width="true"><thead><tr><th>Parameter</th><th>Type</th><th>Default (mainnet)</th><th>Default (testnet)</th><th>Description</th></tr></thead><tbody><tr><td>chainConfig.id</td><td><code>string</code></td><td>101</td><td><code>103</code></td><td>Chain identifier</td></tr><tr><td>chainConfig.name</td><td>string</td><td>SUI</td><td><code>SUITestnet</code></td><td>Human-readable chain name</td></tr><tr><td>chainConfig.rpcEndpoint</td><td>string</td><td><a href="https://fullnode.mainnet.sui.io">https://fullnode.mainnet.sui.io:443</a></td><td><a href="https://fullnode.testnet.sui.io">https://fullnode.testnet.sui.io:443</a></td><td>RPC endpoint URL</td></tr></tbody></table>

**Override Outpost contract address**

<table data-full-width="true"><thead><tr><th>Parameter</th><th>Type</th><th>Default (mainnet)</th><th>Default (testnet)</th><th>Description</th></tr></thead><tbody><tr><td>contracts.oracle</td><td><code>string</code></td><td><code class="expression">space.vars.BOLT_SUI_ORACLE_MAINNET</code></td><td><code class="expression">space.vars.BOLT_SUI_ORACLE_TESTNET</code></td><td>Oracle contract address</td></tr><tr><td>contracts.router</td><td>string</td><td><code class="expression">space.vars.BOLT_SUI_ROUTER_MAINNET</code></td><td><code class="expression">space.vars.BOLT_SUI_ROUTER_TESTNET</code></td><td>Router contract address</td></tr></tbody></table>

**Override Bolt package ID**

<table data-full-width="true"><thead><tr><th>Parameter</th><th>Type</th><th>Default (mainnet)</th><th>Default (testnet)</th><th>Description</th></tr></thead><tbody><tr><td>packageId</td><td><code>string</code></td><td><code class="expression">space.vars.BOLT_SUI_PACKAGE_ID_MAINNET</code></td><td><code class="expression">space.vars.BOLT_SUI_PACKAGE_ID_TESTNET</code></td><td>Bolt protocol package ID</td></tr></tbody></table>

**Override assets configuration**

<table data-full-width="true"><thead><tr><th>Parameter</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>assetsConfig</td><td>Record&#x3C;string, Asset></td><td>Custom asset configurations indexed by denomination</td></tr></tbody></table>

{% code title="Asset structure" %}
```typescript
type Asset = {
  symbol: string;        // Asset symbol (e.g., 'SUI', 'USDC')
  name: string;          // Full asset name (e.g., 'Sui', 'Circle USDC')
  chainId: string;       // Chain identifier
  denom: string;         // Asset denomination/address
  decimals: number;      // Number of decimal places
  logo?: string;         // Optional logo URL
  coingeckoId?: string;  // Optional CoinGecko identifier
};
```
{% endcode %}

**Override SUI client**

<table data-full-width="true"><thead><tr><th>Parameter</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>suiClient</td><td>SuiClient</td><td>Pre-existing SuiClient instance to use for blockchain interactions</td></tr></tbody></table>

```typescript
import { SuiClient } from '@mysten/sui/client';

// Create custom Sui client with specific configuration
const customSuiClient = new SuiClient({
  url: 'https://custom-rpc.example.com',
  // Additional Sui client options...
});

const client = new BoltSuiClient({
  suiClient: customSuiClient
});
```

</details>

### Get oracle config

{% hint style="info" %}
**getOracleConfig()**

The `getOracleConfig` method retrieves the current configuration settings from the Bolt Liquidity Protocol's Oracle smart contract on the Sui blockchain. This configuration governs how price feeds are managed, including update thresholds, expiration times, and administrative settings.
{% endhint %}

{% tabs %}
{% tab title="Method Signature" %}
```typescript
async getOracleConfig(): Promise<OracleConfig>
```
{% endtab %}

{% tab title="Returns" %}
Returns a Promise object containing the oracle's configuration parameters:

```typescript
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)
};
```
{% endtab %}
{% endtabs %}

**Usage example**

```typescript
import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';

// Initialize client
const client = new BoltSuiClient({ environment: 'testnet' });

// 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**

<details>

<summary>How to cache Oracle config (best practice)</summary>

```typescript
// Cache configuration for performance
let cachedConfig: OracleConfig | null = null;
let lastFetchTime = 0;
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes

async function getCachedOracleConfig() {
  const now = Date.now();

  if (cachedConfig && (now - lastFetchTime) < CACHE_DURATION) {
    return cachedConfig;
  }

  cachedConfig = await client.getOracleConfig();
  lastFetchTime = now;
  return cachedConfig;
}
```

</details>

<details>

<summary>How to validate Oracle config</summary>

```typescript
async function validateOracleHealth() {
  const config = await client.getOracleConfig();

  const health = {
    hasAdmin: !!config.admin,
    reasonableThreshold: parseFloat(config.priceThresholdRatio) > 0.001,
    reasonableExpiry: config.priceExpireTime?.secs > 300, // > 5 minutes
    isValid: true
  };

  health.isValid = health.hasAdmin && health.reasonableThreshold && health.reasonableExpiry;

  return health;
}
```

</details>

<details>

<summary>How to monitor for price updates</summary>

```typescript
async function monitorOracleConfig() {
  const config = await client.getOracleConfig();

  // Monitor for configuration changes
  setInterval(async () => {
    const newConfig = await client.getOracleConfig();

    if (newConfig.priceThresholdRatio !== config.priceThresholdRatio) {
      console.log('Price threshold changed:', newConfig.priceThresholdRatio);
    }

    if (newConfig.priceExpireTime?.secs !== config.priceExpireTime?.secs) {
      console.log('Price expiry time changed:', newConfig.priceExpireTime?.secs);
    }
  }, 60000); // Check every minute
}
```

</details>

### Query prices and assets

{% hint style="info" %}
getAssets()

Retrieves all unique assets available in the Bolt protocol by querying oracle asset pairs and enriching them with additional metadata from the client's asset configuration.
{% endhint %}

{% tabs %}
{% tab title="Method Signature" %}
```typescript
async getAssets(): Promise<Asset[]>
```
{% endtab %}

{% tab title="Returns" %}
```typescript
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
};
```
{% endtab %}
{% endtabs %}

**Usage example**

```typescript
import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';

const client = new BoltSuiClient({ environment: 'testnet' });

// 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"
```

{% hint style="info" %}
**getAllOracleAssetPairs()**

Queries the oracle smart contract to retrieve all supported asset pairs with automatic pagination handling. Each asset pair represents a base/quote relationship that can be used for price queries and swaps.
{% endhint %}

{% tabs %}
{% tab title="Method Signature" %}
```typescript
async getAllOracleAssetPairs(): Promise<OracleAssetPair[]>
```
{% endtab %}

{% tab title="Returns" %}
```typescript
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
};
```
{% endtab %}
{% endtabs %}

**Usage example**

```typescript
// 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)`);
});
```

{% hint style="info" %}
getAllPrices()

Queries the oracle smart contract to retrieve all available price feeds with automatic pagination. More efficient than making multiple individual price queries when you need prices for multiple pairs.
{% endhint %}

{% tabs %}
{% tab title="Method Signature" %}
```typescript
async getAllPrices(): Promise<Price[]>
```
{% endtab %}

{% tab title="Returns" %}
```typescript
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
};
```
{% endtab %}
{% endtabs %}

**Usage example**

```typescript
// 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)}`);
});
```

{% hint style="info" %}
getPrice()

Queries the oracle smart contract to retrieve the current price for a specific asset pair. Fetches the latest price feed that is updated by authorized price feeders and validated against configured thresholds.
{% endhint %}

{% tabs %}
{% tab title="Method Signature" %}
```typescript
async getPrice(baseDenom: string, quoteDenom: string): Promise<InvertiblePrice>
```
{% endtab %}

{% tab title="Returns" %}
```typescript
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
};
```
{% endtab %}
{% endtabs %}

**Usage example**

```typescript
// Get SUI/USDC price
const price = await client.getPrice(
  '0x2::sui::SUI',
  '0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN' // 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

{% hint style="info" %}
**getAllBaseAssetsLiquidity()**

Queries the router smart contract to retrieve the total base asset liquidity across all pools with automatic pagination. Fetches current liquidity levels for all base assets in their respective pools.
{% endhint %}

{% tabs %}
{% tab title="Method Signature" %}
```typescript
async getAllBaseAssetsLiquidity(): Promise<Record<Address, BaseLiquidityDetails>>
```
{% endtab %}

{% tab title="Returns" %}
```typescript
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
};
```
{% endtab %}
{% endtabs %}

Usage example

```typescript
import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';

const client = new BoltSuiClient({ environment: 'testnet' });

// 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

{% hint style="info" %}
**getRouterConfig()**

Queries the router smart contract to retrieve its current configuration settings. Fetches router's configuration parameters that govern how swaps are executed, fees are collected, and new pools are deployed.
{% endhint %}

{% tabs %}
{% tab title="Method Signature" %}
```typescript
async getRouterConfig(): Promise<RouterConfig>
```
{% endtab %}

{% tab title="Returns" %}
```typescript
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%)
};
```
{% endtab %}
{% endtabs %}

**Usage example**

```typescript
// 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);
```

{% hint style="info" %}
**getAllPools()**

Queries the router smart contract to retrieve information about all deployed pools with automatic pagination. Fetches a comprehensive list of all markets/pools in the Bolt protocol.
{% endhint %}

{% tabs %}
{% tab title="Method Signature" %}
```typescript
async getAllPools(): Promise<Pool[]>
```
{% endtab %}

{% tab title="Returns" %}
```typescript
type Pool = {
  poolAddress: string; // Sui object ID of the market/pool
  baseDenom: string; // Type of the base asset
  quoteDenoms: string[]; // Array of available quote asset types
};
```
{% endtab %}
{% endtabs %}

Usage example

```typescript
// 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}`);
```

{% hint style="info" %}
**getPoolConfig()**

Retrieves the configuration settings for a settlement contract (liquidity pool). Queries a settlement contract to fetch its current configuration parameters including fees, LP settings, and oracle integration.
{% endhint %}

{% tabs %}
{% tab title="Method Signature" %}
```typescript
async getPoolConfig(contractAddress: Address): Promise<PoolConfig>
```
{% endtab %}

{% tab title="Returns" %}
```typescript
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
};
```
{% endtab %}
{% endtabs %}

**Usage example**

```typescript
// 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);
```

{% hint style="info" %}
**getPoolByBaseAsset()**

Queries the router smart contract to retrieve pool information for a specific base asset. Fetches market/pool details for a given base asset type.
{% endhint %}

{% tabs %}
{% tab title="Method Signature" %}
```typescript
async getPoolByBaseAsset(baseDenom: string): Promise<Pool>
```
{% endtab %}

{% tab title="Returns" %}
```typescript
type Pool = {
  poolAddress: string; // Sui object ID of the market/pool
  baseDenom: string; // Type of the base asset
  quoteDenoms: string[]; // Array of available quote asset types
};
```
{% endtab %}
{% endtabs %}

**Usage example**

```typescript
// Get pool for SUI base asset
const pool = await client.getPoolByBaseAsset('0x2::sui::SUI');

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}`);
});
```

{% hint style="info" %}
**getPoolConfigByBaseAsset()**

Retrieves the configuration settings for a settlement contract identified by its base asset type. This is a convenience function that combines pool lookup and configuration retrieval.
{% endhint %}

{% tabs %}
{% tab title="Method Signature" %}
```typescript
async getPoolConfigByBaseAsset(baseDenom: string): Promise<PoolConfig>
```
{% endtab %}

{% tab title="Returns" %}
```typescript
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
};
```
{% endtab %}
{% endtabs %}

**Usage example**

```typescript
// Get pool configuration for SUI base asset
const config = await client.getPoolConfigByBaseAsset('0x2::sui::SUI');

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);
```

### How to execute a swap

{% hint style="info" %}
swap()

The `swap` method executes a token swap transaction on the Bolt Liquidity Protocol through the router contract. It performs a "swap exact in" operation where users specify exactly how much of the input asset they want to swap, and receive a variable amount of the output asset based on current pool conditions.
{% endhint %}

{% tabs %}
{% tab title="Method Signature" %}
```typescript
async swap(signer: Signer, params: SwapParams): 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
};
```
{% endtab %}

{% tab title="Returns" %}
```typescript
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
};
```
{% endtab %}
{% endtabs %}

Basic usage examples

<details>

<summary>Simple swap</summary>

```typescript
import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
import type { Signer } from '@mysten/sui/cryptography';

async function simpleSwap() {
  const client = new BoltSuiClient({ environment: 'testnet' });

  // Get signer from wallet (e.g., Sui Wallet, Suiet, etc.)
  const signer: Signer = // ... obtain signer from wallet

  try {
    const result = await client.swap(signer, {
      assetIn: "0x2::sui::SUI",
      amountIn: "1000000000", // 1 SUI (9 decimals)
      assetOut: "0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN", // USDC
    });

    console.log('Swap successful!');
    console.log(`Transaction hash: ${result.txHash}`);
    console.log(`Received: ${result.amountOut} ${result.assetOut}`);
    console.log(`Gas cost: ${result.txOutput.effects.gasUsed.computationCost}`);
  } catch (error) {
    console.error('Swap failed:', error.message);
  }
}
```

</details>

<details>

<summary>Swap with slippage protection</summary>

```typescript
import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
import type { Signer } from '@mysten/sui/cryptography';

async function swapWithSlippageProtection() {
  const client = new BoltSuiClient({ environment: 'mainnet' });
  const signer: Signer = // ... obtain signer from wallet

  // Get current price to calculate minimum output
  const price = await client.getPrice(
    "0x2::sui::SUI",
    "0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN"
  );

  const amountIn = "1000000000"; // 1 SUI
  const expectedOutput = BigInt(amountIn) * BigInt(price.price) / BigInt(10 ** 9);
  const slippageTolerance = 0.01; // 1%
  const minimumAmountOut = (expectedOutput * BigInt(99) / BigInt(100)).toString();

  const result = await client.swap(signer, {
    assetIn: "0x2::sui::SUI",
    amountIn,
    assetOut: "0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN",
    minimumAmountOut,
  });

  console.log(`Expected: ${expectedOutput} USDC`);
  console.log(`Minimum: ${minimumAmountOut} USDC`);
  console.log(`Received: ${result.amountOut} USDC`);
}
```

</details>

<details>

<summary>Swap with custom receiver</summary>

```typescript
import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
import type { Signer } from '@mysten/sui/cryptography';

async function swapToCustomReceiver() {
  const client = new BoltSuiClient({ environment: 'testnet' });
  const signer: Signer = // ... obtain signer from wallet

  const result = await client.swap(signer, {
    assetIn: "0x2::sui::SUI",
    amountIn: "500000000", // 0.5 SUI
    assetOut: "0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN",
    receiver: "0x9876543210fedcba...", // Custom recipient
  });

  console.log(`Swapped to address: ${result.txOutput.effects.status.status}`);
}
```

</details>

Advanced usage examples

<details>

<summary>Batch swaps with error handling</summary>

```typescript
import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
import type { Signer } from '@mysten/sui/cryptography';

async function batchSwaps() {
  const client = new BoltSuiClient({ environment: 'mainnet' });
  const signer: Signer = // ... obtain signer from wallet

  const swaps = [
    {
      assetIn: "0x2::sui::SUI",
      amountIn: "1000000000",
      assetOut: "0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN",
      description: "SUI to USDC"
    },
    {
      assetIn: "0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN",
      amountIn: "2000000",
      assetOut: "0x2::sui::SUI",
      description: "USDC to SUI"
    }
  ];

  const results = [];

  for (const swap of swaps) {
    try {
      console.log(`Executing: ${swap.description}`);

      const result = await client.swap(signer, swap);

      results.push({
        success: true,
        description: swap.description,
        amountOut: result.amountOut,
        txHash: result.txHash
      });

      console.log(`✅ ${swap.description}: ${result.amountOut}`);

      // Wait between swaps to avoid rate limiting
      await new Promise(resolve => setTimeout(resolve, 2000));

    } catch (error) {
      results.push({
        success: false,
        description: swap.description,
        error: error.message
      });

      console.error(`❌ ${swap.description}: ${error.message}`);
    }
  }

  return results;
}
```

</details>

<details>

<summary>Smart swap with price monitoring</summary>

```typescript
import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
import type { Signer } from '@mysten/sui/cryptography';

class SmartSwap {
  private client: BoltSuiClient;
  private signer: Signer;
  private priceHistory: Map<string, number[]> = new Map();

  constructor(client: BoltSuiClient, signer: Signer) {
    this.client = client;
    this.signer = signer;
  }

  async monitorPrice(baseDenom: string, quoteDenom: string, duration: number = 60000) {
    const startTime = Date.now();
    const prices: number[] = [];

    while (Date.now() - startTime < duration) {
      try {
        const price = await this.client.getPrice(baseDenom, quoteDenom);
        prices.push(parseFloat(price.price));

        await new Promise(resolve => setTimeout(resolve, 5000)); // 5 second intervals
      } catch (error) {
        console.warn('Price monitoring error:', error.message);
      }
    }

    this.priceHistory.set(`${baseDenom}:${quoteDenom}`, prices);
    return this.calculateOptimalSlippage(prices);
  }

  private calculateOptimalSlippage(prices: number[]): number {
    if (prices.length < 2) return 0.01; // Default 1%

    const volatility = Math.std(prices);
    const avgPrice = prices.reduce((a, b) => a + b, 0) / prices.length;
    const volatilityRatio = volatility / avgPrice;

    // Higher volatility = higher slippage tolerance
    return Math.min(Math.max(volatilityRatio * 2, 0.005), 0.05); // 0.5% to 5%
  }

  async executeOptimalSwap(params: SwapParams) {
    // Monitor price for 1 minute
    const slippage = await this.monitorPrice(params.assetIn, params.assetOut, 60000);

    // Get current price
    const price = await this.client.getPrice(params.assetIn, params.assetOut);
    const expectedOutput = BigInt(params.amountIn) * BigInt(price.price) / BigInt(10 ** 9);
    const minimumAmountOut = (expectedOutput * BigInt(Math.floor((1 - slippage) * 1000)) / BigInt(1000)).toString();

    console.log(`Optimal slippage: ${(slippage * 100).toFixed(2)}%`);
    console.log(`Minimum output: ${minimumAmountOut}`);

    return await this.client.swap(this.signer, {
      ...params,
      minimumAmountOut
    });
  }
}

// Usage
const smartSwap = new SmartSwap(client, signer);
const result = await smartSwap.executeOptimalSwap({
  assetIn: "0x2::sui::SUI",
  amountIn: "1000000000",
  assetOut: "0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN"
});
```

</details>

<details>

<summary>DEX aggregator pattern</summary>

```typescript
import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
import type { Signer } from '@mysten/sui/cryptography';

class DexAggregator {
  private client: BoltSuiClient;
  private signer: Signer;

  constructor(client: BoltSuiClient, signer: Signer) {
    this.client = client;
    this.signer = signer;
  }

  async findBestRoute(assetIn: string, assetOut: string, amountIn: string) {
    // Get all pools
    const pools = await this.client.getAllPools();

    // Find pools that support this pair
    const relevantPools = pools.filter(pool =>
      (pool.baseDenom === assetIn && pool.quoteDenoms.includes(assetOut)) ||
      (pool.baseDenom === assetOut && pool.quoteDenoms.includes(assetIn))
    );

    // Get liquidity for each pool
    const liquidity = await this.client.getAllBaseAssetsLiquidity();

    // Calculate expected output for each route
    const routes = await Promise.all(
      relevantPools.map(async pool => {
        try {
          const price = await this.client.getPrice(assetIn, assetOut);
          const expectedOutput = BigInt(amountIn) * BigInt(price.price) / BigInt(10 ** 9);

          return {
            pool,
            expectedOutput: expectedOutput.toString(),
            liquidity: liquidity[pool.baseDenom]?.baseLiquidity.amount || "0"
          };
        } catch {
          return null;
        }
      })
    );

    // Filter out failed routes and sort by expected output
    return routes
      .filter(route => route !== null)
      .sort((a, b) => BigInt(b!.expectedOutput) - BigInt(a!.expectedOutput));
  }

  async executeBestSwap(assetIn: string, assetOut: string, amountIn: string) {
    const routes = await this.findBestRoute(assetIn, assetOut, amountIn);

    if (routes.length === 0) {
      throw new Error('No valid swap routes found');
    }

    const bestRoute = routes[0];
    console.log(`Best route: ${bestRoute.expectedOutput} expected output`);

    // Execute swap with 1% slippage tolerance
    const minimumAmountOut = (BigInt(bestRoute.expectedOutput) * BigInt(99) / BigInt(100)).toString();

    return await this.client.swap(this.signer, {
      assetIn,
      amountIn,
      assetOut,
      minimumAmountOut
    });
  }
}

// Usage
const aggregator = new DexAggregator(client, signer);
const result = await aggregator.executeBestSwap(
  "0x2::sui::SUI",
  "0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN",
  "1000000000"
);
```

</details>

Best practices

<details>

<summary>Slippage protection</summary>

```typescript
// Always set minimumAmountOut to protect against slippage
const calculateMinimumOutput = (amountIn: string, price: string, slippageTolerance: number = 0.01) => {
  const expectedOutput = BigInt(amountIn) * BigInt(price) / BigInt(10 ** 9);
  return (expectedOutput * BigInt(Math.floor((1 - slippageTolerance) * 1000)) / BigInt(1000)).toString();
};

const price = await client.getPrice(assetIn, assetOut);
const minimumAmountOut = calculateMinimumOutput(amountIn, price.price, 0.01); // 1% slippage

const result = await client.swap(signer, {
  assetIn,
  amountIn,
  assetOut,
  minimumAmountOut
});
```

</details>

<details>

<summary>Error handling and retries</summary>

```typescript
async function robustSwap(signer: Signer, params: SwapParams, maxRetries: number = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      console.log(`Swap attempt ${attempt}/${maxRetries}`);

      const result = await client.swap(signer, params);

      console.log(`✅ Swap successful on attempt ${attempt}`);
      return result;

    } catch (error) {
      console.error(`❌ Attempt ${attempt} failed:`, error.message);

      if (attempt === maxRetries) {
        throw new Error(`Swap failed after ${maxRetries} attempts: ${error.message}`);
      }

      // Wait before retry (exponential backoff)
      const delay = Math.pow(2, attempt) * 1000;
      console.log(`Waiting ${delay}ms before retry...`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}
```

</details>

<details>

<summary>Gas estimation and optimization</summary>

```typescript
async function estimateSwapGas(params: SwapParams) {
  // Get current gas price
  const gasPrice = await client.suiClient.getReferenceGasPrice();

  // Estimate gas for swap (this would be implemented when contracts are ready)
  const estimatedGas = 1000000; // Placeholder

  const gasCost = estimatedGas * gasPrice;

  console.log(`Estimated gas cost: ${gasCost} MIST`);
  return gasCost;
}

// Use in swap
const gasCost = await estimateSwapGas(params);
if (gasCost > maxGasBudget) {
  throw new Error('Gas cost exceeds budget');
}
```

</details>

<details>

<summary>Transaction monitoring</summary>

```typescript
async function monitorSwapTransaction(txHash: string) {
  const maxAttempts = 30; // 30 seconds
  let attempts = 0;

  while (attempts < maxAttempts) {
    try {
      const txResponse = await client.suiClient.getTransactionBlock({
        digest: txHash,
        options: { showEffects: true, showEvents: true }
      });

      if (txResponse.effects?.status.status === 'success') {
        console.log('✅ Transaction confirmed successfully');
        return txResponse;
      } else if (txResponse.effects?.status.status === 'failure') {
        throw new Error(`Transaction failed: ${txResponse.effects.status.error}`);
      }

    } catch (error) {
      console.log(`Transaction not yet confirmed (attempt ${attempts + 1}/${maxAttempts})`);
    }

    attempts++;
    await new Promise(resolve => setTimeout(resolve, 1000));
  }

  throw new Error('Transaction monitoring timeout');
}
```

</details>

<details>

<summary>Balance validation</summary>

```typescript
async function validateSwapBalance(signer: Signer, assetIn: string, amountIn: string) {
  const address = await signer.getAddress();

  // Get balance for the specific asset
  const balance = await client.suiClient.getBalance({
    owner: address,
    coinType: assetIn
  });

  const requiredAmount = BigInt(amountIn);
  const currentBalance = BigInt(balance.totalBalance);

  if (currentBalance < requiredAmount) {
    throw new Error(`Insufficient balance: ${currentBalance} < ${requiredAmount}`);
  }

  console.log(`✅ Sufficient balance: ${currentBalance} >= ${requiredAmount}`);
  return true;
}

// Use before swap
await validateSwapBalance(signer, assetIn, amountIn);
const result = await client.swap(signer, params);
```

</details>

## Error Handling

The SDK provides custom error types for better error handling:

* <mark style="color:orange;">**NotFoundError**</mark> - Resource not found
* <mark style="color:orange;">**InvalidParameterError**</mark> - Invalid parameter provided
* <mark style="color:orange;">**InvalidObjectError**</mark> - Invalid object structure
* <mark style="color:orange;">**InvalidTypeError**</mark> - Invalid type provided
* <mark style="color:orange;">**MissingParameterError**</mark> - Required parameter missing
* <mark style="color:orange;">**TransactionFailedError**</mark> - Transaction execution failed
* <mark style="color:orange;">**ParseError**</mark> - Failed to parse response data

## Key Differences between SUI and CosmWasm Client

* **Asset Identification**: Uses Sui type strings (e.g., `0x2::sui::SUI`) instead of denoms
* **Decimals**: SUI uses 9 decimals vs 6 for many CosmWasm assets
* **Transaction Output**: Returns `SuiTransactionBlockResponse` with Sui-specific fields
* **Signer Type**: Uses Sui's `Signer` interface instead of `OfflineSigner`

## SUI-specific Features

#### Object IDs

All contracts and pools are identified by Sui object IDs:

```typescript
const poolAddress = '0x1234abcd...'; // Sui object ID
```

#### Type Arguments

Many functions use Sui's type system:

```typescript
const suiType = '0x2::sui::SUI';
const customCoinType = '0xpackage::module::COIN';
```

#### Gas and Effects

Transaction results include Sui-specific information:

```typescript
const gasUsed = result.txOutput.effects.gasUsed.computationCost;
const status = result.txOutput.effects.status.status;
```

## Resources

<a href="https://urban-train-gg7rnzk.pages.github.io/" class="button primary" data-icon="github">Bolt TS SDK Reference</a>

<a href="https://github.com/phi-labs-ltd/bolt-ts-sdk" class="button secondary" data-icon="github">Github</a>
