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

# Archway TypeScript SDK

> Install, configure, and build with the Bolt CosmWasm client on Archway. Full API reference with types and methods.

A type-safe CosmWasm client for interacting with Bolt's zero slippage execution layer on Archway. Query oracle prices, inspect pool state, 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
    * An Archway-compatible wallet (Keplr, Leap, etc.) for signing transactions
    * Access to Archway RPC endpoints (the client uses `https://rpc.mainnet.archway.io` for mainnet and `https://rpc.constantine.archway.io` for testnet by default)
  </Step>

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

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

      <Tab title="PNPM">
        ```bash theme={null}
        pnpm add @bolt-liquidity-hq/cosmwasm-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 { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';

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

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

        const client = new BoltCosmWasmClient({
          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 archAsset = assets.find((a) => a.symbol === 'ARCH');
    console.log(`ARCH denom: ${archAsset?.denom}`); // "aarch"
    ```
  </Step>

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

***

## API

### Client initialization

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

// Initialise client
const client = new BoltCosmWasmClient({
  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 { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';

  // Initialise client with full custom configuration
  const customClient = new BoltCosmWasmClient({
    customOverride: {
      chainConfig: {
        id: 'archway-custom-1',
        name: 'Archway Custom',
        rpcEndpoint: 'https://custom-rpc.example.com',
        restEndpoint: 'https://custom-rest.example.com'
      },
      contracts: {
        oracle: 'archway1custom_oracle...',
        router: 'archway1custom_router...'
      },
      nativeTokenDenom: 'aarch',
      assetsConfig: {
        'aarch': {
          symbol: 'ARCH',
          name: 'Archway',
          chainId: 'archway-custom-1',
          denom: 'aarch',
          decimals: 18,
          logo: 'https://example.com/arch.png',
          coingeckoId: 'archway'
        }
      }
    }
  });
  ```

  **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 | archway-1                                                          | constantine-3                                                              | Chain identifier          |
  | chainConfig.name         | string | Archway                                                            | Archway Testnet                                                            | Human-readable chain name |
  | chainConfig.rpcEndpoint  | string | [https://rpc.mainnet.archway.io/](https://rpc.mainnet.archway.io/) | [https://rpc.constantine.archway.io/](https://rpc.constantine.archway.io/) | RPC endpoint URL          |
  | chainConfig.restEndpoint | string | [https://api.mainnet.archway.io/](https://api.mainnet.archway.io/) | [https://api.constantine.archway.io/](https://api.constantine.archway.io/) | REST endpoint URL         |

  **Override Outpost contract addresses**

  | Parameter        | Type   | Description             |
  | ---------------- | ------ | ----------------------- |
  | contracts.oracle | string | Oracle contract address |
  | contracts.router | string | Router contract address |

  **Override native token denomination**

  | Parameter        | Type   | Description                                  |
  | ---------------- | ------ | -------------------------------------------- |
  | nativeTokenDenom | string | Native token denomination (default: `aarch`) |

  **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., 'ARCH', 'USDC')
    name: string;          // Full asset name (e.g., 'Archway', 'Circle USDC')
    chainId: string;       // Chain identifier
    denom: string;         // Asset denomination
    decimals: number;      // Number of decimal places
    logo?: string;         // Optional logo URL
    coingeckoId?: string;  // Optional CoinGecko identifier
  };
  ```

  **Override clients**

  | Parameter             | Type                                              | Description                                                              |
  | --------------------- | ------------------------------------------------- | ------------------------------------------------------------------------ |
  | cosmWasmClient        | `CosmWasmClient` \| `ArchwayClient`               | Pre-existing query client instance for blockchain interactions           |
  | signer                | `OfflineSigner`                                   | Pre-existing signer                                                      |
  | signingCosmWasmClient | `SigningCosmWasmClient` \| `SigningArchwayClient` | Pre-existing signing client instance for signing blockchain transactions |

  ```typescript theme={null}
  import { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';
  import { CosmWasmClient } from '@cosmjs/cosmwasm-stargate';

  // Create custom CosmWasm client with specific configuration
  const customCosmWasmClient = CosmWasmClient.connect('https://custom-rpc.example.com');

  const client = new BoltCosmWasmClient({
    cosmWasmClient: customCosmWasmClient
  });
  ```
</Accordion>

***

### Get oracle config

<Info>
  `getOracleConfig() `retrieves the current configuration settings from the Bolt Oracle smart contract on Archway. 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;                    // Archway 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 { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';

const client = new BoltCosmWasmClient();

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., "ARCH", "USDC")
      name: string;          // Full asset name (e.g., "Archway", "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 { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';

const client = new BoltCosmWasmClient();

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

***

<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., "ARCH", "ATOM")
      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 authorized 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 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

<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 { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';

const client = new BoltCosmWasmClient();

const poolAddress = "archway1f1e...";
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 { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';

const client = new BoltCosmWasmClient();

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

<Info>
  `getRouterConfig()` queries the router smart contract to retrieve its current configuration settings. The Router is the entry-point contract unique to the Archway deployment that governs how swaps are executed, fees are collected, and new pools are deployed.
</Info>

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

  <Tab title="Returns">
    ```typescript theme={null}
    type RouterConfig = {
      admin: string;                      // Address with administrative privileges
      defaultPriceOracleContract: string;  // Default price oracle contract address
      defaultProtocolFeeRecipient: string; // 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%)
    };
    ```
  </Tab>
</Tabs>

**Usage example**

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

<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 on Archway.
</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 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 archPools = allPools.filter(pool =>
  pool.baseDenom === "aarch"
);
console.log(`ARCH pools found: ${archPools.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;  // Price oracle contract used by this pool
      protocolFeeRecipient: string; // 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 addresses
      minBaseOut: string;           // Minimum base asset output amount for trades
    };
    ```
  </Tab>
</Tabs>

**Usage example**

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

***

<Info>
  `getPoolByDenom()` queries the router smart contract to retrieve pool information for a specific base asset on Archway. Fetches pool details for the pool matching the provided asset denomination.
</Info>

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

  <Tab title="Returns">
    ```typescript theme={null}
    type Pool = {
      poolAddress: string;   // Contract address 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 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}`);
});
```

***

<Info>
  `getPoolConfigByDenom()` retrieves pool configuration by base asset denomination. 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): Promise<PoolConfig>
    ```
  </Tab>

  <Tab title="Returns">
    ```typescript theme={null}
    type PoolConfig = {
      priceOracleContract: string;  // Price oracle contract used by this pool
      protocolFeeRecipient: string; // 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 addresses
      minBaseOut: string;           // Minimum base asset output amount for trades
    };
    ```
  </Tab>
</Tabs>

**Usage example**

```typescript theme={null}
// Get pool configuration for ATOM base asset
const config = await client.getPoolConfigByDenom('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

<Info>
  `simulateSwap()` simulates a swap operation to calculate the expected output amount without executing the transaction. Performs a dry run that takes 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 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
      totalFees: string;             // Sum of protocolFee and lpFee (dynamic fee distributed between both)
    };
    ```
  </Tab>
</Tabs>

**Usage example**

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

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

**Usage examples**

<AccordionGroup>
  <Accordion title="Simple swap">
    ```typescript theme={null}
    import { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';
    import { OfflineSigner } from '@cosmjs/proto-signing';

    const client = new BoltCosmWasmClient();

    const signer: OfflineSigner = // ... obtain signer from wallet or mnemonic

    try {
      const result = await client.swap({
        assetIn: "aarch",
        amountIn: "1000000000000000000", // 1 ARCH (18 decimals)
        assetOut: "ibc/43897B9739BD63E3A08A88191999C632E052724AB96BD4C74AE31375C991F48D", // USDC IBC denom
        minimumAmountOut: '1900000', // Minimum 1.9 USDC (6 decimals)
        receiver: "archway1..." // Optional custom receiver
      }, 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 { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';
    import { OfflineSigner } from '@cosmjs/proto-signing';

    const client = new BoltCosmWasmClient();

    const signer: OfflineSigner = // ... obtain signer from wallet or mnemonic

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

    try {
      const result = await client.swap({
        assetIn: "aarch",
        amountIn: "1000000000000000000", // 1 ARCH (18 decimals)
        assetOut: "ibc/43897B9739BD63E3A08A88191999C632E052724AB96BD4C74AE31375C991F48D", // USDC IBC denom
        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 { BoltCosmWasmClient } from '@bolt-liquidity-hq/cosmwasm-client';
    import { OfflineSigner } from '@cosmjs/proto-signing';

    const client = new BoltCosmWasmClient();

    const signer: OfflineSigner = // ... obtain signer from wallet or mnemonic

    const receiver = "archway1e1f1..."; // Custom recipient

    try {
      const result = await client.swap({
        assetIn: "aarch",
        amountIn: "1000000000000000000", // 1 ARCH (18 decimals)
        assetOut: "ibc/43897B9739BD63E3A08A88191999C632E052724AB96BD4C74AE31375C991F48D", // USDC IBC denom
        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}
    import { OfflineSigner } from '@cosmjs/proto-signing';

    const signer: OfflineSigner = // ... obtain signer from wallet or mnemonic
    const result = await client.estimateSwapGasFees(
      {
        assetIn: "aarch",
        amountIn: "1000000000000000000", // 1 ARCH (18 decimals)
        assetOut: "ibc/43897B9739BD63E3A08A88191999C632E052724AB96BD4C74AE31375C991F48D", // USDC IBC denom
      },
      signer
    );

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

***

### Error handling

| <h4>**Error**</h4>     | <h4>Cause</h4>                   | <h4>Fix</h4>                           |
| ---------------------- | -------------------------------- | -------------------------------------- |
| NotFoundError          | Asset, pool, or oracle not found | Verify denoms and pool addresses       |
| InvalidParameterError  | Bad address or negative amount   | Validate inputs before calling         |
| InvalidObjectError     | Object does not exist on-chain   | Confirm addresses and network          |
| InvalidTypeError       | Type mismatch in params          | Ensure denoms and amounts are strings  |
| MissingParameterError  | Required field omitted           | Provide all non-optional fields        |
| TransactionFailedError | On-chain execution failed        | Check gas, inventory, oracle freshness |
| ParseError             | Failed to deserialise data       | Retry or switch RPC endpoint           |

***

<CardGroup cols={2}>
  <Card title="Archway Outpost Addresses" icon="map-pin" href="/archway-outpost-addresses">
    Contract addresses for mainnet and testnet.
  </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>

  <Card title="Contact The Team" icon="comment" href="/contact">
    Questions about routing, integration, or execution strategy? Reach out.
  </Card>
</CardGroup>
