> ## Documentation Index
> Fetch the complete documentation index at: https://docs.boltliquidity.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Sui TypeScript SDK

> Integrate with Bolt's zero slippage execution layer on Sui using TypeScript.

The Bolt TypeScript SDK provides a comprehensive, type-safe interface for integrating with Bolt's zero slippage execution layer on Sui. Query oracle prices, inspect pools, simulate swaps off-chain, and execute trades programmatically.

## Quickstart

<Steps>
  <Step title="Prerequisites">
    Before using the SDK, make sure you have:

    ☑️ Node.js 18+ installed

    ☑️ A Sui-compatible wallet (Sui Wallet, Suiet, etc.) for signing transactions

    ☑️ Access to SUI RPC endpoints: The client uses\
    `https://fullnode.mainnet.sui.io:443` for mainnet and `https://fullnode.testnet.sui.io:443` for testnet by default
  </Step>

  <Step title="Installation">
    <Tabs>
      <Tab title="NPM">
        ```bash theme={null}
        npm install @bolt-liquidity-hq/sui-client
        ```
      </Tab>

      <Tab title="YARN">
        ```bash theme={null}
        yarn add @bolt-liquidity-hq/sui-client
        ```
      </Tab>

      <Tab title="PNPM">
        ```bash theme={null}
        pnpm install @bolt-liquidity-hq/sui-client
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Initialize the Bolt client">
    The SDK supports different environments:

    ```typescript theme={null}
    type Environment = 'mainnet' | 'testnet';
    ```

    <Tabs>
      <Tab title="Mainnet">
        ```typescript theme={null}
        import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';

        const client = new BoltSuiClient();
        ```
      </Tab>

      <Tab title="Testnet">
        ```typescript theme={null}
        import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';

        const client = new BoltSuiClient({
          environment: 'testnet',
        });
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Query all assets">
    ```typescript theme={null}
    // 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"
    ```
  </Step>

  <Step title="Execute a swap">
    ```typescript theme={null}
    // 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',
      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}`);
    ```
  </Step>
</Steps>

***

## API

### Client initialization

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

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

<Accordion title="Advanced client initialization" icon="gear">
  ```typescript theme={null}
  import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';

  // Initialise client with full custom configuration
  const client = new BoltSuiClient({
    environment: 'mainnet',
    customOverride: {
      chainConfig: {
        id: 'sui-mainnet',
        name: 'Sui',
        rpcEndpoint: 'https://fullnode.mainnet.sui.io:443',
      },
      packageId: '0x1234...',
      contracts: {
        oracle: '0xoracle...',
      },
      assetsConfig: {
        '0x2::sui::SUI': {
          symbol: 'SUI',
          name: 'Sui',
          chainId: 'sui-mainnet',
          denom: '0x2::sui::SUI',
          decimals: 9,
          logo: 'https://...',
          coingeckoId: 'sui',
        },
      },
    },
  });
  ```

  **Environment configuration**

  | Parameter   | Type                   | Default   | Description           |
  | ----------- | ---------------------- | --------- | --------------------- |
  | environment | `mainnet` \| `testnet` | `mainnet` | Network to connect to |

  **Override chain configuration**

  | Parameter               | Type     | Default (mainnet)                                                          | Default (testnet)                                                          | Description               |
  | ----------------------- | -------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------------------- |
  | chainConfig.id          | `string` | 101                                                                        | `103`                                                                      | Chain identifier          |
  | chainConfig.name        | `string` | SUI                                                                        | `SUITestnet`                                                               | Human-readable chain name |
  | chainConfig.rpcEndpoint | `string` | [https://fullnode.mainnet.sui.io:443](https://fullnode.mainnet.sui.io:443) | [https://fullnode.testnet.sui.io:443](https://fullnode.testnet.sui.io:443) | RPC endpoint URL          |

  **Override Bolt package ID**

  | Parameter | Type     | Default (mainnet)                                                    | Description              |
  | --------- | -------- | -------------------------------------------------------------------- | ------------------------ |
  | packageId | `string` | `0x0c6b6b0ec858d76381f7f5f787eb8cd6479d65df24ca6f726e9ae246d4ace339` | Bolt protocol package ID |

  **Override Outpost contract address**

  | Parameter        | Type     | Default (mainnet)                                                    | Description             |
  | ---------------- | -------- | -------------------------------------------------------------------- | ----------------------- |
  | contracts.oracle | `string` | `0xfa3975b98f3d0e3df18ed88ae6e69db31836b3f4212df02fae144b1e5a89ca8e` | Oracle contract address |

  **Override assets configuration**

  | Parameter    | Type                    | Description                                         |
  | ------------ | ----------------------- | --------------------------------------------------- |
  | assetsConfig | `Record<string, Asset>` | Custom asset configurations indexed by denomination |

  ```typescript theme={null}
  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
  };
  ```

  **Override SUI client**

  | Parameter | Type      | Description                                                 |
  | --------- | --------- | ----------------------------------------------------------- |
  | suiClient | SuiClient | Pre-existing SuiClient instance for blockchain interactions |

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

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

  const client = new BoltSuiClient({
    suiClient: customSuiClient
  });
  ```
</Accordion>

***

### Get oracle config

<Info>
  `getOracleConfig()`

  Retrieves the current configuration settings from the Bolt Oracle smart contract on Sui. This configuration governs how price feeds are managed, including update thresholds, expiration times, and administrative settings.
</Info>

<Tabs>
  <Tab title="Method Signature">
    ```typescript theme={null}
    async getOracleConfig(): Promise<OracleConfig>
    ```
  </Tab>

  <Tab title="Returns">
    ```typescript theme={null}
    type OracleConfig = {
      admin: Address;                    // Sui address authorised to update oracle settings and prices
      priceThresholdRatio: string;       // Minimum price change ratio required for updates (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)
    };
    ```
  </Tab>
</Tabs>

**Usage example**

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

const client = new BoltSuiClient();

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

<AccordionGroup>
  <Accordion title="How to cache Oracle config (best practice)">
    ```typescript theme={null}
    // 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;
    }
    ```
  </Accordion>

  <Accordion title="How to monitor for price updates">
    ```typescript theme={null}
    async function monitorOracleConfig() {
      const config = await client.getOracleConfig();

      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
    }
    ```
  </Accordion>
</AccordionGroup>

***

### Query prices and assets

<Info>
  `getAssets() `

  Retrieves all unique assets available in the Bolt execution layer by querying oracle asset pairs and enriching them with additional metadata from the client's asset configuration.
</Info>

<Tabs>
  <Tab title="Method Signature">
    ```typescript theme={null}
    async getAssets(): Promise<Asset[]>
    ```
  </Tab>

  <Tab title="Returns">
    ```typescript theme={null}
    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
    };
    ```
  </Tab>
</Tabs>

**Usage example**

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

const client = new BoltSuiClient();

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

***

<Info>
  `getAllOracleAssetPairs()`

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

<Tabs>
  <Tab title="Method Signature">
    ```typescript theme={null}
    async getAllOracleAssetPairs(): Promise<OracleAssetPair[]>
    ```
  </Tab>

  <Tab title="Returns">
    ```typescript theme={null}
    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
    };
    ```
  </Tab>
</Tabs>

**Usage example**

```typescript theme={null}
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)`);
});
```

***

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

<Tabs>
  <Tab title="Method Signature">
    ```typescript theme={null}
    async getAllPrices(): Promise<Price[]>
    ```
  </Tab>

  <Tab title="Returns">
    ```typescript theme={null}
    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
    };
    ```
  </Tab>
</Tabs>

**Usage example**

```typescript theme={null}
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)}`);
});
```

***

<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 authorised price feeders and validated against configured thresholds.
</Info>

<Tabs>
  <Tab title="Method Signature">
    ```typescript theme={null}
    async getPrice(baseDenom: string, quoteDenom: string): Promise<InvertiblePrice>
    ```
  </Tab>

  <Tab title="Returns">
    ```typescript theme={null}
    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
    };
    ```
  </Tab>
</Tabs>

**Usage example**

```typescript theme={null}
// Get SUI/USDC price
const price = await client.getPrice(
  '0x2::sui::SUI',
  '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::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

<Info>
  `getPoolBaseLiquidity() `

  Queries the router smart contract to retrieve the total base asset liquidity for a specific pool. Fetches current liquidity levels for the base asset in the specified pool.
</Info>

<Tabs>
  <Tab title="Method Signature">
    ```typescript theme={null}
    async getPoolBaseLiquidity(poolContractAddress: string): Promise<BaseLiquidityDetails>
    ```
  </Tab>

  <Tab title="Returns">
    ```typescript theme={null}
    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
    };
    ```
  </Tab>
</Tabs>

**Usage example**

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

const client = new BoltSuiClient();

const poolAddress = "0x...";
const liquidity = await client.getPoolBaseLiquidity(poolAddress);

console.log(`Base liquidity: ${liquidity.baseLiquidity.amount} ${liquidity.baseLiquidity.denom}`);
console.log(`Total shares: ${liquidity.totalShares}`);
```

***

<Info>
  `getAllBaseAssetsLiquidity() `

  Queries the router smart contract to retrieve the base asset liquidity across all pools. Fetches current liquidity levels for all the base assets in their respective pools.
</Info>

<Tabs>
  <Tab title="Method Signature">
    ```typescript theme={null}
    async getAllBaseAssetsLiquidity(): Promise<Record<Address, BaseLiquidityDetails>>
    ```
  </Tab>

  <Tab title="Returns">
    ```typescript theme={null}
    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
    };
    ```
  </Tab>
</Tabs>

**Usage example**

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

const client = new BoltSuiClient();

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

<Info>
  `getAllPools() `

  Queries the router smart contract to retrieve information about all deployed pools with automatic pagination. Fetches a comprehensive list of all pools in the Bolt execution layer.
</Info>

<Tabs>
  <Tab title="Method Signature">
    ```typescript theme={null}
    async getAllPools(): Promise<Pool[]>
    ```
  </Tab>

  <Tab title="Returns">
    ```typescript theme={null}
    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
    };
    ```
  </Tab>
</Tabs>

**Usage example**

```typescript theme={null}
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}`);
```

***

<Info>
  `getPoolConfig() `

  Retrieves the configuration settings of a liquidity pool contract. Queries the contract to fetch its current configuration parameters, including fees, LP settings, and oracle integration.
</Info>

<Tabs>
  <Tab title="Method Signature">
    ```typescript theme={null}
    async getPoolConfig(contractAddress: Address): Promise<PoolConfig>
    ```
  </Tab>

  <Tab title="Returns">
    ```typescript theme={null}
    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 authorised LP Sui addresses
      minBaseOut: string;           // Minimum base asset output amount for trades
    };
    ```
  </Tab>
</Tabs>

**Usage example**

```typescript theme={null}
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);
```

***

<Info>
  `getPoolByDenom() `

  Queries the router smart contract to retrieve pool information for a specific base/quote asset pair on Sui. Fetches pool details for the pool matching the provided asset denominations.
</Info>

<Tabs>
  <Tab title="Method Signature">
    ```typescript theme={null}
    async getPoolByDenom(baseDenom: string, quoteDenom: string): Promise<Pool>
    ```
  </Tab>

  <Tab title="Returns">
    ```typescript theme={null}
    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
    };
    ```
  </Tab>
</Tabs>

**Usage example**

```typescript theme={null}
// Get pool for SUI/USDC 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}`);
});
```

***

<Info>
  `getPoolConfigByDenom() `

  Retrieves pool configuration by base/quote asset pair. This is a convenience function that combines pool lookup and configuration retrieval.
</Info>

<Tabs>
  <Tab title="Method Signature">
    ```typescript theme={null}
    async getPoolConfigByDenom(baseDenom: string, quoteDenom: string): Promise<PoolConfig>
    ```
  </Tab>

  <Tab title="Returns">
    ```typescript theme={null}
    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 authorised LP Sui addresses
      minBaseOut: string;           // Minimum base asset output amount for trades
    };
    ```
  </Tab>
</Tabs>

**Usage example**

```typescript theme={null}
// Get pool configuration for SUI/USDC 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('Authorised LPs:', config.lps.length);
console.log('Min Base Out:', config.minBaseOut);
```

***

### Simulate a swap

<Info>
  `simulateSwap() `

  Simulates a swap operation to calculate the expected output amount without executing the transaction. Performs a dry run taking into account current pool conditions, oracle prices, and fees. Use this for accurate estimates before executing.
</Info>

<Tabs>
  <Tab title="Method Signature">
    ```typescript theme={null}
    async simulateSwap(params: SwapParams): Promise<SimulateSwapResult>
    ```
  </Tab>

  <Tab title="Returns">
    ```typescript theme={null}
    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
      protocolFee: string;           // Protocol fee amount that would be charged
      lpFee: string;                 // LP fee amount that would be charged
      dynamicFeePercentage?: string; // Percentage going to dynamic fees on the Sui Outpost
      totalFees: string;             // Sum of protocolFee and lpFee (dynamic fee distributed between both)
    };
    ```
  </Tab>
</Tabs>

**Usage example**

```typescript theme={null}
// 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",
});

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.dynamicFeePercentage) {
  console.log(`Dynamic fee: ${simulation.dynamicFeePercentage}`);
}
console.log(`Total fees: ${simulation.totalFees}`);
```

***

### Execute a swap

<Info>
  `swap() `

  Executes a token swap transaction on the Bolt execution layer through the router contract. It performs a "swap exact in" operation where you specify exactly how much of the input asset to swap, and receive a variable amount of the output asset based on current pool conditions.
</Info>

<Tabs>
  <Tab title="Method Signature">
    ```typescript theme={null}
    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
      swapType?: 'buy' | 'sell'; // Optional swap type to execute on the pool, defaults to 'buy'
    };
    ```
  </Tab>

  <Tab title="Returns">
    ```typescript theme={null}
    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
    };
    ```
  </Tab>
</Tabs>

### **Usage examples**

<AccordionGroup>
  <Accordion title="Simple swap">
    ```typescript theme={null}
    import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
    import type { Signer } from '@mysten/sui/cryptography';

    const client = new BoltSuiClient();

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

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

      console.log('Swap successful!');
      console.log(`Transaction hash: ${result.txHash}`);
      console.log(`Received: ${result.amountOut} ${result.assetOut}`);
    } catch (error) {
      console.error('Swap failed:', error.message);
    }
    ```
  </Accordion>

  <Accordion title="Swap with minimum amount out limit">
    ```typescript theme={null}
    import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
    import type { Signer } from '@mysten/sui/cryptography';

    const client = new BoltSuiClient();
    const signer: Signer = // ... obtain signer from wallet

    const minimumAmountOut = "1900000"; // Minimum 1.9 USDC (6 decimals)

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

      console.log(`Minimum: ${minimumAmountOut} USDC`);
      console.log(`Received: ${result.amountOut} USDC`);
    } catch (error) {
      console.error('Swap failed:', error.message);
    }
    ```
  </Accordion>

  <Accordion title="Swap with custom receiver">
    ```typescript theme={null}
    import { BoltSuiClient } from '@bolt-liquidity-hq/sui-client';
    import type { Signer } from '@mysten/sui/cryptography';

    const client = new BoltSuiClient();
    const signer: Signer = // ... obtain signer from wallet

    const receiver = "0x..."; // Custom recipient

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

      console.log('Swap successful!');
      console.log(`Transaction hash: ${result.txHash}`);
      console.log(`Sent: ${result.amountOut} ${result.assetOut} to ${receiver}`);
    } catch (error) {
      console.error('Swap failed:', error.message);
    }
    ```
  </Accordion>
</AccordionGroup>

***

### Best practices

<AccordionGroup>
  <Accordion title="Price slippage protection" icon="shield">
    ```typescript theme={null}
    // Always set minimumAmountOut to protect against price variations
    const calculateMinimumOutput = (
      amountIn: string,
      price: string,
      priceSlippageTolerance: number = 0.01
    ) => {
      const expectedOutput = BigNumber(amountIn).multipliedBy(price);

      const slippageMultiplier = new BigNumber(1).minus(priceSlippageTolerance);

      return expectedOutput
        .multipliedBy(slippageMultiplier)
        .toFixed(0, BigNumber.ROUND_DOWN); // return as integer string
    };

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

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

  <Accordion title="Error handling and retries" icon="rotate">
    ```typescript theme={null}
    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(params, signer);

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

  <Accordion title="Gas estimation and optimization" icon="gauge">
    ```typescript theme={null}
    // Get signer from wallet (implementation depends on wallet)
    const signer: Signer = await getSuiWalletSigner();

    const result = await client.estimateSwapGasFees(
      {
        assetIn: "0x2::sui::SUI",
        amountIn: '10000',
        assetOut: "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC"
      },
      signer
    );

    if (result.amount > maxGasBudget) {
      throw new Error('Gas cost exceeds budget');
    }
    ```
  </Accordion>
</AccordionGroup>

***

### Error Handling

| <h4>**Error Type**</h4>    | <h4>**Error Description**</h4> |
| -------------------------- | ------------------------------ |
| **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  |

<CardGroup cols={2}>
  <Card title="Sui Outpost Addresses" icon="map-pin" href="/sui-outpost-addresses">
    Contract addresses for mainnet and testnet.
  </Card>

  <Card title="Off-Chain Quoting" icon="calculator" href="/off-chain-quoting">
    Build price discovery using deterministic quoting.
  </Card>

  <Card title="Contract Math" icon="square-root-variable" href="/contract-math">
    Understand the pricing formula behind simulateSwap().
  </Card>

  <Card title="Pool State Indexing" icon="database" href="/pool-state-indexing">
    Index pool state for real-time integration.
  </Card>
</CardGroup>
