@bolt-liquidity-hq/sui-client 0.1.0-beta.26 → 0.1.0-beta.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/lib/client.ts","../src/config/common.ts","../src/config/mainnet.ts","../src/config/testnet.ts","../src/lib/constants/defaults.ts","../src/lib/constants/sui-objects.ts","../src/lib/helpers/bcs-parse.ts","../src/lib/helpers/coin-manager.ts","../src/lib/helpers/queries.ts","../src/lib/helpers/transactions.ts","../src/lib/oracle/parsers.ts","../src/types/bcs.ts","../src/types/oracle.ts","../src/types/router.ts","../src/types/pool.ts","../src/lib/oracle/get-asset-pairs.ts","../src/lib/oracle/get-assets.ts","../src/lib/oracle/get-oracle-config.ts","../src/lib/oracle/get-price.ts","../src/lib/oracle/get-prices.ts","../src/lib/router/estimate-swap-exact-in-gas-fees.ts","../src/lib/settlement/get-pool-base-liquidity.ts","../src/lib/settlement/parsers.ts","../src/lib/settlement/get-pool-config.ts","../src/lib/settlement/get-pool-config-by-denom.ts","../src/lib/router/get-all-base-liquidity.ts","../src/lib/router/get-all-quotes-for-user.ts","../src/lib/router/get-pool-by-denom.ts","../src/lib/router/get-pools.ts","../src/lib/router/get-router-config.ts","../src/lib/router/parsers.ts","../src/lib/router/router-client/RouterClient.ts","../src/lib/router/simulate-swap.ts","../src/lib/router/swap-exact-in.ts"],"sourcesContent":["export { BoltSuiClient } from './lib/client';\n\nexport * from './types';\n","import type {\n Address,\n BaseLiquidityDetails,\n Coin,\n InvertiblePrice,\n OracleAssetPair,\n OracleConfig,\n PoolConfig,\n Pool,\n Price,\n RouterConfig,\n SwapParams,\n SwapResult,\n Contracts,\n AssetsConfig,\n Asset,\n SimulateSwapResult,\n} from '@bolt-liquidity-hq/core';\nimport { BaseClient, MissingParameterError } from '@bolt-liquidity-hq/core';\nimport { SuiClient, type SuiTransactionBlockResponse } from '@mysten/sui/client';\nimport type { Signer } from '@mysten/sui/cryptography';\nimport { normalizeStructTag } from '@mysten/sui/utils';\nimport axios from 'axios';\n\nimport {\n MainnetAssets,\n MainnetChainConfig,\n MainnetContracts,\n MainnetPackageId,\n MainnetPoolGlobalConfigId,\n TestnetAssets,\n TestnetChainConfig,\n TestnetContracts,\n TestnetPoolGlobalConfigId,\n TestnetPackageId,\n MainnetNativeTokenDenom,\n TestnetNativeTokenDenom,\n MainnetPools,\n TestnetConfigUrl,\n} from '../config';\nimport { getAssets, getAssetPairs, getOracleConfig, getPrice, getPrices } from './oracle';\nimport {\n RouterClient,\n estimateSwapExactInGasFees,\n getAllBaseLiquidity,\n getAllQuotesForUser,\n getPoolByDenom,\n getPools,\n getRouterConfig,\n simulateSwap,\n swapExactIn,\n} from './router';\nimport { getPoolBaseLiquidity, getPoolConfig, getPoolConfigByDenom } from './settlement';\nimport type {\n SuiChainConfig,\n SuiClientConfig,\n SuiSwapParams,\n SuiSwapSimulateParams,\n WalletSigner,\n} from '../types';\n\n/**\n * Client implementation for interacting with the Bolt Liquidity Outpost on Sui blockchain.\n *\n * This class extends the abstract {@link BaseClient} to provide Sui-specific functionality\n * for querying and executing transactions on Bolt Protocol's oracle and router smart contracts.\n * It uses SuiTransactionBlockResponse as the transaction output type, providing detailed transaction execution information.\n *\n * @extends {BaseClient<Signer, SuiTransactionBlockResponse>}\n *\n * @group Bolt API Clients\n *\n * @example\n * ```typescript\n * // Create a client for Sui mainnet\n * const client = new BoltSuiClient();\n *\n * // Query oracle prices\n * const price = await client.getPrice(\"0x2::sui::SUI\", \"0xusdcAddress...\");\n *\n * // Execute a swap (requires signer)\n * const signer = // ... get signer from wallet\n * const result = await client.swap({\n * assetIn: \"0x2::sui::SUI\",\n * amountIn: \"1000000000\", // 1 SUI (9 decimals)\n * assetOut: \"0xusdcAddress...\"\n * }, signer);\n * ```\n */\nexport class BoltSuiClient extends BaseClient<Signer, SuiTransactionBlockResponse> {\n /**\n * The Sui-specific chain configuration including RPC endpoint\n */\n public override chainConfig: SuiChainConfig;\n\n /**\n * Package Id for the deployed Bolt contracts on Sui\n */\n public packageId: string;\n\n /**\n * Object Id for the GlobalConfig of the deployed Pool contracts\n */\n public poolGlobalConfigId: string;\n\n /**\n * Cached instance of the Signer for transaction execution\n */\n public signer?: Signer | WalletSigner;\n\n /**\n * Instance of the Sui client to interact with the blockchain\n */\n public suiClient: SuiClient;\n\n /**\n * URL for fetching testnet configuration dynamically.\n * Used to load package IDs, oracle addresses, and asset configurations for testnet environments.\n * @private\n */\n private configFileUrl?: string;\n\n /**\n * Router client instance for managing pool configurations and routing calculations.\n * Handles pool discovery and optimal path finding for swaps.\n */\n public routerClient: RouterClient;\n\n /**\n * Creates a new instance of the BoltSuiClient.\n *\n * The client automatically configures itself based on the specified environment,\n * loading the appropriate contract addresses, chain configuration, native token denomination,\n * and assets from configuration files. For testnet environments, the client can dynamically\n * fetch configuration from a remote URL.\n *\n * @param config - (Optional) Configuration for the client\n * @param config.environment - (Optional) The deployment environment ('mainnet' or 'testnet'). Defaults to 'mainnet'\n * @param config.customOverride - (Optional) Custom overrides for chain configuration, contracts, native token, and assets\n * @param config.customOverride.chainConfig - (Optional) Override chain configuration\n * @param config.customOverride.chainConfig.id - (Optional) Custom chain ID\n * @param config.customOverride.chainConfig.name - (Optional) Custom chain name\n * @param config.customOverride.chainConfig.rpcEndpoint - (Optional) Custom RPC endpoint URL\n * @param config.customOverride.packageId - (Optional) Custom package ID for Bolt contracts\n * @param config.customOverride.poolGlobalConfigId - (Optional) Custom Object ID for the Pool contracts' Global Config\n * @param config.customOverride.contracts - (Optional) Override contract addresses\n * @param config.customOverride.contracts.oracle - (Optional) Custom oracle contract address\n * @param config.customOverride.contracts.router - (Optional) Custom router contract address\n * @param config.customOverride.nativeTokenDenom - (Optional) Custom native token denomination (e.g., \"SUI\")\n * @param config.customOverride.assetsConfig - (Optional) Custom asset configurations indexed by denom\n * @param config.signer - (Optional) Pre-existing Signer for transaction signing\n * @param config.suiClient - (Optional) Pre-existing SuiClient to use for blockchain queries\n *\n * @throws {InvalidObjectError} Thrown when required configuration fields are missing\n *\n * @example\n * ```typescript\n * // Use default configuration (Sui mainnet)\n * const client = new BoltSuiClient();\n *\n * // Use testnet configuration (will fetch config dynamically)\n * const testnetClient = new BoltSuiClient({\n * environment: 'testnet'\n * });\n *\n * // Use custom chain configuration\n * const customClient = new BoltSuiClient({\n * customOverride: {\n * chainConfig: {\n * id: 'sui-custom',\n * name: 'Sui Custom',\n * rpcEndpoint: 'https://custom-rpc.example.com'\n * },\n * packageId: '0xcustom_package_id...',\n * poolGlobalConfigId: '0xcustom_global_config_id...',\n * contracts: {\n * oracle: '0xcustom_oracle...',\n * router: '0xcustom_router...'\n * },\n * nativeTokenDenom: 'SUI',\n * assetsConfig: {\n * '0x2::sui::SUI': {\n * symbol: 'SUI',\n * name: 'Sui',\n * chainId: 'sui-custom',\n * denom: '0x2::sui::SUI',\n * decimals: 9,\n * logo: 'https://example.com/sui.png',\n * coingeckoId: 'sui'\n * }\n * }\n * }\n * });\n *\n * // Use pre-existing Sui client and signer\n * const clientWithCustomClient = new BoltSuiClient({\n * suiClient: mySuiClient,\n * signer: mySigner\n * });\n * ```\n */\n constructor(config?: SuiClientConfig) {\n const { environment = 'mainnet', customOverride, signer, suiClient } = config ?? {};\n\n const isEnvironmentMainnet = environment === 'mainnet';\n const defaultChainConfig: SuiChainConfig = isEnvironmentMainnet\n ? MainnetChainConfig\n : TestnetChainConfig;\n const defaultContracts: Contracts = isEnvironmentMainnet ? MainnetContracts : TestnetContracts;\n const defaultPackageId = isEnvironmentMainnet ? MainnetPackageId : TestnetPackageId;\n const defaultPoolGlobalConfigId = isEnvironmentMainnet\n ? MainnetPoolGlobalConfigId\n : TestnetPoolGlobalConfigId;\n const defaultNativeTokenDenom = isEnvironmentMainnet\n ? MainnetNativeTokenDenom\n : TestnetNativeTokenDenom;\n const assetsConfig: AssetsConfig = isEnvironmentMainnet ? MainnetAssets : TestnetAssets;\n const pools = isEnvironmentMainnet ? MainnetPools : [];\n\n // Apply overrides\n const chainConfig: SuiChainConfig = {\n id: customOverride?.chainConfig?.id ?? defaultChainConfig.id,\n name: customOverride?.chainConfig?.name ?? defaultChainConfig.name,\n rpcEndpoint: customOverride?.chainConfig?.rpcEndpoint ?? defaultChainConfig.rpcEndpoint,\n };\n const packageId = customOverride?.packageId ?? defaultPackageId;\n const poolGlobalConfigId = customOverride?.poolGlobalConfigId ?? defaultPoolGlobalConfigId;\n const contracts: Contracts = {\n oracle: customOverride?.contracts?.oracle ?? defaultContracts.oracle,\n router: customOverride?.contracts?.router ?? defaultContracts.router,\n };\n const nativeTokenDenom = customOverride?.nativeTokenDenom ?? defaultNativeTokenDenom;\n\n for (const item of Object.values(customOverride?.assetsConfig ?? {})) {\n assetsConfig[item.denom] = item;\n }\n\n super({\n customOverride: {\n chainConfig,\n contracts,\n nativeTokenDenom,\n assetsConfig,\n },\n });\n\n this.chainConfig = chainConfig;\n this.packageId = packageId;\n this.poolGlobalConfigId = poolGlobalConfigId;\n this.signer = signer;\n this.suiClient = suiClient ?? new SuiClient({ url: chainConfig.rpcEndpoint });\n this.routerClient = new RouterClient(pools);\n this.configFileUrl = isEnvironmentMainnet ? undefined : TestnetConfigUrl;\n }\n\n /**\n * Gets or sets the signer for transaction execution.\n *\n * This method manages the signer instance used for signing transactions.\n * A signer must be provided either when creating the client, on first call,\n * or to replace the existing signer.\n *\n * @param newSigner - Optional new signer to replace the existing one\n *\n * @returns The current signer instance\n *\n * @throws {MissingParameterError} Thrown when no signer is available and none is provided\n *\n * @example\n * ```typescript\n * // Get the current signer (throws if none exists)\n * const currentSigner = client.getSigner();\n *\n * // Set a new signer\n * const newSigner = // ... obtain signer from wallet\n * const signer = client.getSigner(newSigner);\n * ```\n */\n public getSigner(newSigner?: Signer | WalletSigner): Signer | WalletSigner {\n this.signer = newSigner ?? this.signer;\n\n if (!this.signer) {\n throw new MissingParameterError('signer');\n }\n\n return this.signer;\n }\n\n // The following methods inherit their documentation from BaseClient\n // Only add documentation here if you need to override or add implementation-specific details\n\n /** @inheritdoc */\n public async getOracleConfig(): Promise<OracleConfig> {\n await this.loadConfigFromUrl();\n return await getOracleConfig(this);\n }\n\n /** @inheritdoc */\n async getAllOracleAssetPairs(): Promise<OracleAssetPair[]> {\n await this.loadConfigFromUrl();\n return await getAssetPairs(this);\n }\n\n /** @inheritdoc */\n async getPrice(baseDenom: string, quoteDenom: string): Promise<InvertiblePrice> {\n await this.loadConfigFromUrl();\n return await getPrice(this, baseDenom, quoteDenom);\n }\n\n /** @inheritdoc */\n async getAllPrices(): Promise<Price[]> {\n await this.loadConfigFromUrl();\n return await getPrices(this);\n }\n\n /** @inheritdoc */\n async getRouterConfig(): Promise<RouterConfig> {\n await this.loadConfigFromUrl();\n return await getRouterConfig(this);\n }\n\n /** @inheritdoc */\n async getAllBaseAssetsLiquidity(): Promise<Record<Address, BaseLiquidityDetails>> {\n await this.loadConfigFromUrl();\n return await getAllBaseLiquidity(this);\n }\n\n /** @inheritdoc */\n async getAllQuotesByUser(address: Address): Promise<Record<Address, Coin[]>> {\n await this.loadConfigFromUrl();\n return await getAllQuotesForUser(this, address);\n }\n\n /**\n * @inheritdoc\n *\n * @remarks\n * In the Sui implementation, both `baseDenom` and `quoteDenom` parameters are required.\n * The Sui architecture uses both asset types to uniquely identify pools for specific\n * trading pairs.\n *\n * @throws Will throw an error if no pool exists for the specified base/quote asset pair\n */\n async getPoolByDenom(baseDenom: string, quoteDenom: string): Promise<Pool> {\n await this.loadConfigFromUrl();\n return await getPoolByDenom(this, baseDenom, quoteDenom);\n }\n\n /** @inheritdoc */\n async getAllPools(): Promise<Pool[]> {\n await this.loadConfigFromUrl();\n return await getPools(this);\n }\n\n /** @inheritdoc */\n async getPoolConfig(poolContractAddress: string): Promise<PoolConfig> {\n await this.loadConfigFromUrl();\n return await getPoolConfig(this, poolContractAddress);\n }\n\n /**\n * @inheritdoc\n *\n * @remarks\n * In the Sui implementation, both `baseDenom` and `quoteDenom` parameters are required.\n * The Sui architecture uses both asset types to uniquely identify pools for specific\n * trading pairs.\n *\n * @throws Will throw an error if no pool exists for the specified base/quote asset pair\n */\n async getPoolConfigByDenom(baseDenom: string, quoteDenom: string): Promise<PoolConfig> {\n await this.loadConfigFromUrl();\n return await getPoolConfigByDenom(this, baseDenom, quoteDenom);\n }\n\n /** @inheritdoc */\n async getPoolBaseLiquidity(poolContractAddress: string): Promise<BaseLiquidityDetails> {\n await this.loadConfigFromUrl();\n return await getPoolBaseLiquidity(this, poolContractAddress);\n }\n\n /** @inheritdoc */\n async getAssets(): Promise<Asset[]> {\n await this.loadConfigFromUrl();\n return await getAssets(this);\n }\n\n /**\n * @inheritdoc\n *\n * @example\n * ```typescript\n * // Get signer from wallet (e.g., Sui Wallet, Suiet, etc.)\n * const signer = // ... obtain signer from wallet\n *\n * // Execute swap: 1 SUI for USDC\n * const result = await client.swap({\n * assetIn: \"0x2::sui::SUI\",\n * amountIn: \"1000000000\", // 1 SUI (9 decimals)\n * assetOut: \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\", // USDC address\n * minimumAmountOut: \"1950000\", // Minimum 1.95 USDC expected (6 decimals)\n * receiver: \"0x...\" // Optional custom receiver address\n * swapType: 'buy' | 'sell' // Optional swap type (default is 'buy')\n * }, signer);\n *\n * console.log(`Swap successful!`);\n * console.log(`Transaction digest: ${result.txHash}`);\n * console.log(`Received: ${result.amountOut} ${result.assetOut}`);\n * console.log(`Gas cost: ${result.txOutput.effects.gasUsed.computationCost}`);\n * console.log(`Status: ${result.txOutput.effects.status.status}`);\n * ```\n *\n * @remarks\n * This implementation returns a SuiTransactionBlockResponse as the transaction output,\n * which includes details like gas costs, transaction effects, object changes, and events.\n */\n async swap(\n params: SuiSwapParams,\n signer?: Signer | WalletSigner\n ): Promise<SwapResult<SuiTransactionBlockResponse>> {\n await this.loadConfigFromUrl();\n return await swapExactIn(this, params, signer);\n }\n\n /**\n * @inheritdoc\n *\n * @example\n * ```typescript\n * // Get signer from wallet (e.g., Sui Wallet, Suiet, etc.)\n * const signer = // ... obtain signer from wallet\n *\n * // Estimate gas for swapping 1 SUI to USDC\n * const gasEstimate = await client.estimateSwapGasFees({\n * assetIn: \"0x2::sui::SUI\",\n * amountIn: \"1000000000\", // 1 SUI (9 decimals)\n * assetOut: \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\", // USDC\n * minimumAmountOut: \"1950000\" // Min 1.95 USDC (6 decimals)\n * }, signer, 1.3); // 30% safety margin\n *\n * if (gasEstimate) {\n * console.log(`Estimated gas: ${gasEstimate.amount} ${gasEstimate.denom}`);\n * }\n * ```\n *\n * @remarks\n * - For Sui, gas is always paid in SUI tokens\n * - The returned amount is in MIST (smallest unit, 9 decimals)\n * - Gas estimation uses Sui's dry run transaction capability\n * - The gasAdjustment parameter helps account for variations in actual execution\n * - Sui's gas model includes computation, storage, and storage rebates\n */\n async estimateSwapGasFees(\n params: SwapParams,\n signer?: Signer | WalletSigner,\n gasAdjustment?: number\n ): Promise<Coin | undefined> {\n await this.loadConfigFromUrl();\n return await estimateSwapExactInGasFees(this, params, signer, gasAdjustment);\n }\n\n /** @inheritdoc */\n async simulateSwap(params: SuiSwapSimulateParams): Promise<SimulateSwapResult> {\n return await simulateSwap(this, params);\n }\n\n /**\n * Loads configuration from a remote URL for testnet environments.\n *\n * This method fetches and applies dynamic configuration including:\n * - Package ID for Bolt contracts\n * - Oracle contract address\n * - Pool global configuration ID\n * - Asset mappings and metadata\n * - Pool configurations\n *\n * The method is called automatically before API operations when a config URL is set.\n * After successful loading, the config URL is cleared to prevent redundant fetches.\n *\n * @private\n * @remarks\n * - Only executes if `configFileUrl` is set (typically for testnet)\n * - Updates testnet-specific asset denoms with their actual deployed addresses\n * - Populates the router client's pool configurations\n * - Normalizes struct tags for consistency\n */\n private async loadConfigFromUrl() {\n if (!this.configFileUrl) {\n return;\n }\n\n const response = await axios.get(this.configFileUrl);\n const { package_id, oracle_id, global_config_id, assets, pools } =\n (response.data as {\n package_id: string;\n oracle_id: string;\n global_config_id: string;\n assets: Record<string, string>;\n pools: Array<{ base: string; pool_object_id: string }>;\n }) ?? {};\n\n if (!this.packageId && package_id) {\n this.packageId = package_id;\n }\n\n if (!this.contracts.oracle.trim() && oracle_id) {\n this.contracts.oracle = oracle_id;\n }\n\n if (!this.poolGlobalConfigId && global_config_id) {\n this.poolGlobalConfigId = global_config_id;\n }\n\n for (const item of Object.values(assets)) {\n for (const existingConfig of Object.values(this.assetsConfig)) {\n if (item.endsWith(existingConfig.denom)) {\n this.assetsConfig[item] = {\n ...existingConfig,\n denom: item,\n };\n delete this.assetsConfig[existingConfig.denom];\n break;\n }\n }\n }\n\n if (this.routerClient.pools.length === 0) {\n for (const item of pools) {\n this.routerClient.pools.push({\n poolAddress: item.pool_object_id,\n baseDenom: normalizeStructTag(item.base),\n quoteDenoms: Object.values(assets)\n .map((auxAsset) => normalizeStructTag(auxAsset))\n .filter((auxAsset) => auxAsset !== normalizeStructTag(item.base)),\n });\n }\n }\n\n this.configFileUrl = undefined;\n }\n}\n","import { normalizeStructTag, SUI_TYPE_ARG } from '@mysten/sui/utils';\n\nexport const SUI_TOKEN_DENOM = normalizeStructTag(SUI_TYPE_ARG);\n","import type { AssetsConfig, Contracts, Pool } from '@bolt-liquidity-hq/core';\nimport { SUI_DECIMALS } from '@mysten/sui/utils';\n\nimport { SUI_TOKEN_DENOM } from './common';\nimport type { SuiChainConfig } from '../types';\n\nexport const MainnetChainConfig: SuiChainConfig = {\n name: 'Sui',\n id: '101',\n rpcEndpoint: 'https://fullnode.mainnet.sui.io:443',\n};\n\nexport const MainnetContracts: Contracts = {\n oracle: '0xfa3975b98f3d0e3df18ed88ae6e69db31836b3f4212df02fae144b1e5a89ca8e',\n router: ' ',\n};\n\nexport const MainnetPackageId: string =\n '0x71a61b841cc90a74607e99084e47818a7d1424649f4047ad375d9c2a4111e658';\n\nexport const MainnetPoolGlobalConfigId: string =\n '0x7bcd5035a991f42fa84c5a42216b5638cb3f1a8c4f065063093b0a3d5f165d63';\n\nexport const MainnetNativeTokenDenom: string = SUI_TOKEN_DENOM;\n\nexport const MainnetAssets: AssetsConfig = {\n [SUI_TOKEN_DENOM]: {\n symbol: 'SUI',\n name: 'Sui',\n chainId: '101',\n denom: SUI_TOKEN_DENOM,\n decimals: SUI_DECIMALS,\n logo: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/sui/info/logo.png',\n coingeckoId: 'sui',\n },\n '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC': {\n symbol: 'USDC',\n name: 'Circle USDC',\n chainId: '101',\n denom: '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC',\n decimals: 6,\n logo: 'https://raw.githubusercontent.com/cosmos/chain-registry/refs/heads/master/_non-cosmos/ethereum/images/usdc.png',\n coingeckoId: 'usd-coin',\n },\n '0x356a26eb9e012a68958082340d4c4116e7f55615cf27affcff209cf0ae544f59::wal::WAL': {\n symbol: 'WAL',\n name: 'Walrus',\n chainId: '101',\n denom: '0x356a26eb9e012a68958082340d4c4116e7f55615cf27affcff209cf0ae544f59::wal::WAL',\n decimals: 9,\n logo: 'https://app.lotusfinance.io/images/coins/wal-icon.svg',\n coingeckoId: 'walrus-2',\n },\n '0x375f70cf2ae4c00bf37117d0c85a2c71545e6ee05c4a5c7d282cd66a4504b068::usdt::USDT': {\n symbol: 'suiUSDT',\n name: 'Tether by Sui Bridge',\n chainId: '101',\n denom: '0x375f70cf2ae4c00bf37117d0c85a2c71545e6ee05c4a5c7d282cd66a4504b068::usdt::USDT',\n decimals: 6,\n logo: 'https://raw.githubusercontent.com/cosmos/chain-registry/refs/heads/master/_non-cosmos/ethereum/images/usdt.svg',\n coingeckoId: 'tether',\n },\n};\n\nexport const MainnetPools: Pool[] = [\n {\n poolAddress: '0x21167b2e981e2c0a693afcfe882a3a827d663118e19afcb92e45bfe43fe56278',\n baseDenom: '0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI',\n quoteDenoms: ['0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC'],\n },\n {\n poolAddress: '0x34fcaa553f1185e1c3a05de37b6a4d10c39535d19f9c8581eeae826434602b58',\n baseDenom: '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC',\n quoteDenoms: ['0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI'],\n },\n];\n","import type { AssetsConfig, Contracts } from '@bolt-liquidity-hq/core';\nimport { SUI_DECIMALS } from '@mysten/sui/utils';\n\nimport { SUI_TOKEN_DENOM } from './common';\nimport type { SuiChainConfig } from '../types';\n\nexport const TestnetConfigUrl = 'https://phi-labs-ltd.github.io/sui-outpost/testnet.json';\n\nexport const TestnetChainConfig: SuiChainConfig = {\n name: 'Sui Testnet',\n id: '103',\n rpcEndpoint: 'https://fullnode.testnet.sui.io:443',\n};\n\nexport const TestnetContracts: Contracts = {\n oracle: ' ',\n router: ' ',\n};\n\nexport const TestnetPackageId: string = '';\n\nexport const TestnetPoolGlobalConfigId: string = '';\n\nexport const TestnetNativeTokenDenom: string = SUI_TOKEN_DENOM;\n\nexport const TestnetAssets: AssetsConfig = {\n [SUI_TOKEN_DENOM]: {\n symbol: 'SUI',\n name: 'Sui',\n chainId: '103',\n denom: SUI_TOKEN_DENOM,\n decimals: SUI_DECIMALS,\n logo: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/sui/info/logo.png',\n coingeckoId: 'sui',\n },\n '0xa1ec7fc00a6f40db9693ad1415d0c193ad3906494428cf252621037bd7117e29::usdc::USDC': {\n symbol: 'USDC',\n name: 'Circle USDC',\n chainId: '103',\n denom: '0xa1ec7fc00a6f40db9693ad1415d0c193ad3906494428cf252621037bd7117e29::usdc::USDC',\n decimals: 6,\n logo: 'https://raw.githubusercontent.com/cosmos/chain-registry/refs/heads/master/_non-cosmos/ethereum/images/usdc.png',\n coingeckoId: 'usd-coin',\n },\n '::test_btc::TEST_BTC': {\n symbol: 'TEST_BTC',\n name: 'Test BTC',\n chainId: '103',\n denom: '::test_btc::TEST_BTC',\n decimals: 8,\n logo: 'https://raw.githubusercontent.com/cosmos/chain-registry/refs/heads/master/_non-cosmos/bitcoin/images/btc.svg',\n coingeckoId: 'bitcoin',\n },\n '::test_usdt::TEST_USDT': {\n symbol: 'TEST_USDT',\n name: 'Test USDT',\n chainId: '103',\n denom: '::test_usdt::TEST_USDT',\n decimals: 6,\n logo: 'https://raw.githubusercontent.com/cosmos/chain-registry/refs/heads/master/_non-cosmos/ethereum/images/usdt.svg',\n coingeckoId: 'tether',\n },\n '::test_deep::TEST_DEEP': {\n symbol: 'TEST_DEEP',\n name: 'TEST_DEEP',\n chainId: '103',\n denom: '::test_deep::TEST_DEEP',\n decimals: 6,\n logo: 'https://app.lotusfinance.io/images/coins/deepbook-icon.svg',\n coingeckoId: 'deep',\n },\n '::test_wal::TEST_WAL': {\n symbol: 'TEST_WAL',\n name: 'TEST_WAL',\n chainId: '103',\n denom: '::test_wal::TEST_WAL',\n decimals: 9,\n logo: 'https://app.lotusfinance.io/images/coins/wal-icon.svg',\n coingeckoId: 'walrus-2',\n },\n};\n","export const DEFAULT_PAGINATION_LIMIT = 50;\nexport const BASIS_POINTS = 10000;\n","export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000000000000000000000000000';\n\nexport const SUI_SYSTEM_CLOCK = '0x6';\n\nexport const PRICE_ORACLE_MODULE = 'price_oracle';\n\nexport const ROUTER_MODULE = 'router';\n\nexport const POOL_MODULE = 'pool';\n","import { InvalidObjectError, ParseError } from '@bolt-liquidity-hq/core';\nimport type { BcsType } from '@mysten/bcs';\nimport { bcs } from '@mysten/bcs';\nimport type { DevInspectResults } from '@mysten/sui/client';\n\nimport type { BcsParsed } from '../../types';\n\n/**\n * Extracts raw bytes from a DevInspectResults object at the specified indices.\n *\n * This utility function navigates the nested structure of Sui's DevInspectResults\n * to extract the raw byte array from a specific return value.\n *\n * @param result - The DevInspectResults object returned from a Sui devInspect call\n * @param resultIndex - The index of the result to extract from (defaults to 0)\n * @param returnValueIndex - The index of the return value within the result (defaults to 0)\n *\n * @returns The extracted bytes as a Uint8Array, or null if the specified indices don't exist\n *\n * @example\n * ```typescript\n * const result = await suiClient.devInspectTransactionBlock({...});\n * const bytes = extractBytes(result, 0, 0);\n * if (bytes) {\n * const parsedValue = bcs.u64().parse(bytes);\n * }\n * ```\n */\nexport const extractBytes = (\n result: DevInspectResults,\n resultIndex: number = 0,\n returnValueIndex: number = 0\n): Uint8Array | null => {\n const returnValues = result.results?.[resultIndex]?.returnValues;\n if (!returnValues || !returnValues[returnValueIndex]) {\n return null;\n }\n\n const [bytes] = returnValues[returnValueIndex];\n return new Uint8Array(bytes);\n};\n\n/**\n * A utility class providing static methods for parsing common BCS (Binary Canonical Serialization) types.\n *\n * BCS is the serialization format used by Sui for encoding Move types. This class\n * provides convenient wrappers around the @mysten/bcs library's parsing functions\n * for commonly used primitive and composite types.\n *\n * @example\n * ```typescript\n * // Parse a u64 value\n * const bytes = new Uint8Array([1, 0, 0, 0, 0, 0, 0, 0]);\n * const value = BcsCommonParser.parseU64(bytes); // \"1\"\n *\n * // Parse a vector of strings\n * const vectorBytes = // ... bytes from Sui\n * const strings = BcsCommonParser.parseVector(vectorBytes, bcs.string());\n *\n * // Parse an optional value\n * const optionBytes = // ... bytes from Sui\n * const maybeValue = BcsCommonParser.parseOption(optionBytes, bcs.u32());\n * ```\n */\nexport class BcsCommonParser {\n /**\n * Parses a BCS-encoded unsigned 8-bit integer.\n *\n * @param bytes - The BCS-encoded bytes to parse\n * @returns The parsed u8 value as a number (0-255)\n */\n static parseU8(bytes: Uint8Array): number {\n return bcs.u8().parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded unsigned 16-bit integer.\n *\n * @param bytes - The BCS-encoded bytes to parse\n * @returns The parsed u16 value as a number (0-65535)\n */\n static parseU16(bytes: Uint8Array): number {\n return bcs.u16().parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded unsigned 32-bit integer.\n *\n * @param bytes - The BCS-encoded bytes to parse\n * @returns The parsed u32 value as a number (0-4294967295)\n */\n static parseU32(bytes: Uint8Array): number {\n return bcs.u32().parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded unsigned 64-bit integer.\n *\n * @param bytes - The BCS-encoded bytes to parse\n * @returns The parsed u64 value as a string (to preserve precision)\n *\n * @remarks\n * Returns a string because JavaScript numbers cannot safely represent\n * all 64-bit integer values without loss of precision.\n */\n static parseU64(bytes: Uint8Array): string {\n return bcs.u64().parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded unsigned 128-bit integer.\n *\n * @param bytes - The BCS-encoded bytes to parse\n * @returns The parsed u128 value as a string\n */\n static parseU128(bytes: Uint8Array): string {\n return bcs.u128().parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded unsigned 256-bit integer.\n *\n * @param bytes - The BCS-encoded bytes to parse\n * @returns The parsed u256 value as a string\n */\n static parseU256(bytes: Uint8Array): string {\n return bcs.u256().parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded boolean value.\n *\n * @param bytes - The BCS-encoded bytes to parse\n * @returns The parsed boolean value\n */\n static parseBool(bytes: Uint8Array): boolean {\n return bcs.bool().parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded string.\n *\n * @param bytes - The BCS-encoded bytes to parse\n * @returns The parsed string value\n */\n static parseString(bytes: Uint8Array): string {\n return bcs.string().parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded vector (dynamic array) of elements.\n *\n * @template T - The type of elements in the vector\n * @param bytes - The BCS-encoded bytes to parse\n * @param elementParser - The BCS parser for individual vector elements\n * @returns An array of parsed elements\n *\n * @example\n * ```typescript\n * // Parse a vector of u64 values\n * const numbers = BcsCommonParser.parseVector(bytes, bcs.u64());\n *\n * // Parse a vector of custom structs\n * const customType = bcs.struct('MyStruct', {\n * id: bcs.u64(),\n * name: bcs.string()\n * });\n * const structs = BcsCommonParser.parseVector(bytes, customType);\n * ```\n */\n static parseVector<T>(bytes: Uint8Array, elementParser: BcsType<T>): T[] {\n return bcs.vector(elementParser).parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded Option type (similar to Rust's Option or Move's Option).\n *\n * @template T - The type of the optional value\n * @param bytes - The BCS-encoded bytes to parse\n * @param elementParser - The BCS parser for the optional value if present\n * @returns The parsed value if Some, or null if None\n *\n * @example\n * ```typescript\n * // Parse an optional address\n * const maybeAddress = BcsCommonParser.parseOption(bytes, bcs.string());\n * if (maybeAddress) {\n * console.log(`Address: ${maybeAddress}`);\n * } else {\n * console.log('No address provided');\n * }\n * ```\n */\n static parseOption<T>(bytes: Uint8Array, elementParser: BcsType<T>): T | null {\n return bcs.option(elementParser).parse(bytes);\n }\n}\n\n/**\n * Parses a single return value from a DevInspectResults object using a specified BCS parser.\n *\n * This function combines byte extraction and BCS parsing into a single operation,\n * handling errors appropriately and providing detailed error context.\n *\n * @template T - The expected TypeScript type after parsing\n * @template Input - The input type for the BCS parser (usually the same as T)\n *\n * @param result - The DevInspectResults object from a Sui devInspect call\n * @param bcsType - The BCS parser to use for deserializing the bytes\n * @param resultIndex - The index of the result to parse (defaults to 0)\n * @param returnValueIndex - The index of the return value within the result (defaults to 0)\n *\n * @returns The parsed value of type T\n *\n * @throws {InvalidObjectError} When no bytes are found at the specified indices\n * @throws {ParseError} When BCS parsing fails due to malformed data\n *\n * @example\n * ```typescript\n * // Parse a u64 return value\n * const result = await suiClient.devInspectTransactionBlock({...});\n * const balance = parseDevInspectResult(result, bcs.u64());\n *\n * // Parse a custom struct\n * const PriceInfo = bcs.struct('PriceInfo', {\n * price: bcs.u64(),\n * timestamp: bcs.u64(),\n * });\n * const priceInfo = parseDevInspectResult(result, PriceInfo);\n *\n * // Parse from a specific return value\n * const secondReturnValue = parseDevInspectResult(result, bcs.string(), 0, 1);\n * ```\n */\nexport const parseDevInspectResult = <T, Input>(\n result: DevInspectResults,\n bcsType: BcsType<T, Input>,\n resultIndex: number = 0,\n returnValueIndex: number = 0\n): T => {\n const bytes = extractBytes(result, resultIndex, returnValueIndex);\n if (!bytes) {\n throw new InvalidObjectError('When trying to parse result, no bytes found', {\n bcsType,\n resultIndex,\n returnValueIndex,\n });\n }\n\n try {\n return bcsType.parse(bytes);\n } catch (error) {\n throw new ParseError('DevInspectResult', 'from bcs to a typescript type', {\n error,\n result,\n bcsType,\n resultIndex,\n returnValueIndex,\n });\n }\n};\n\n/**\n * Parses multiple return values from a DevInspectResults object using an array of BCS parsers.\n *\n * This function is useful when a Move function returns multiple values that need to be\n * parsed with different BCS types. It applies each parser in the schema array to the\n * corresponding return value index.\n *\n * @template T - A tuple type representing the array of BCS parsers\n *\n * @param info - The DevInspectResults object from a Sui devInspect call\n * @param schema - An array of BCS parsers, one for each expected return value\n *\n * @returns A tuple containing the parsed values, with types matching the schema\n *\n * @example\n * ```typescript\n * // Parse multiple return values of different types\n * const result = await suiClient.devInspectTransactionBlock({...});\n * const [balance, isActive, userName] = parseMultipleResults(\n * result,\n * [bcs.u64(), bcs.bool(), bcs.string()] as const\n * );\n *\n * // Parse multiple complex types\n * const TokenInfo = bcs.struct('TokenInfo', {\n * symbol: bcs.string(),\n * decimals: bcs.u8(),\n * });\n * const [tokenA, tokenB, liquidityAmount] = parseMultipleResults(\n * result,\n * [TokenInfo, TokenInfo, bcs.u128()] as const\n * );\n * ```\n *\n * @remarks\n * - The function assumes all return values are from the first result (index 0)\n * - Each parser in the schema array corresponds to a return value at the same index\n * - Type safety is preserved through TypeScript's tuple types\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const parseMultipleResults = <T extends readonly BcsType<any>[]>(\n info: DevInspectResults,\n schema: T\n): { [K in keyof T]: BcsParsed<T[K]> } => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return schema.map((bcsType, index) => parseDevInspectResult(info, bcsType, 0, index)) as {\n [K in keyof T]: BcsParsed<T[K]>;\n };\n};\n","import { InsufficientFundsError, MissingParameterError } from '@bolt-liquidity-hq/core';\nimport type { SuiClient, PaginatedCoins, CoinStruct } from '@mysten/sui/client';\nimport type { Argument, Transaction } from '@mysten/sui/transactions';\nimport { normalizeStructTag } from '@mysten/sui/utils';\n\nimport { SUI_TOKEN_DENOM } from '../../config';\n\n/**\n * Configuration options for coin selection algorithms.\n *\n * These options control how the CoinManager selects coins when preparing\n * transactions, allowing optimization for different scenarios.\n */\nexport interface CoinSelectionOptions {\n /**\n * Array of coin object IDs to exclude from selection.\n * Useful for avoiding coins that are locked or reserved for other transactions.\n *\n * @example [\"0x123...\", \"0x456...\"]\n */\n excludeIds?: string[];\n\n /**\n * When true, prefers merging multiple coins even if a single coin could cover the amount.\n * This can help consolidate fragmented coin holdings.\n *\n * @default false\n */\n preferMerge?: boolean;\n\n /**\n * When true, uses the minimum number of coins needed to cover the amount.\n * This preserves coin count but may use larger denominations.\n *\n * @default false\n */\n minimizeInputs?: boolean;\n\n /**\n * When true, allows returning a partial amount if insufficient funds.\n * The result will contain all available coins even if they don't meet the target.\n *\n * @default false\n */\n allowPartial?: boolean;\n}\n\n/**\n * Result of the coin selection process.\n *\n * Contains the selected coins and metadata about what operations\n * are needed to prepare them for the transaction.\n */\nexport interface CoinSelectionResult {\n /**\n * Array of selected coin objects that will be used in the transaction.\n */\n coins: CoinStruct[];\n\n /**\n * Total balance of all selected coins as a string.\n * May exceed the requested amount if exact change isn't available.\n */\n totalBalance: string;\n\n /**\n * Whether the selected coins need to be merged into a single coin.\n * True when multiple coins are selected.\n */\n requiresMerge: boolean;\n\n /**\n * Whether the resulting coin needs to be split to get the exact amount.\n * True when totalBalance exceeds the requested amount.\n */\n requiresSplit: boolean;\n}\n\n/**\n * Manages coin selection and preparation for Sui transactions.\n *\n * The CoinManager class provides utilities for working with coins on the Sui blockchain,\n * including fetching balances, selecting optimal coins for transactions, and preparing\n * coin inputs with automatic merging and splitting as needed.\n *\n * @example\n * ```typescript\n * const coinManager = new CoinManager(suiClient, userAddress);\n *\n * // Get total balance\n * const balance = await coinManager.getTotalBalance(\n * \"0x2::sui::SUI\"\n * );\n *\n * // Select coins for a transaction\n * const selection = await coinManager.selectCoins(\n * \"0x2::sui::SUI\",\n * \"1000000000\", // 1 SUI\n * { minimizeInputs: true }\n * );\n *\n * // Prepare coin input for transaction\n * const tx = new Transaction();\n * const coinInput = await coinManager.prepareCoinInput(\n * tx,\n * \"0x2::sui::SUI\",\n * \"1000000000\"\n * );\n * ```\n *\n * @group Helpers\n */\nexport class CoinManager {\n /**\n * Creates a new CoinManager instance.\n *\n * @param client - The SuiClient instance for blockchain interactions\n * @param defaultOwner - Optional default owner address for coin operations.\n * If not provided, owner must be specified in each method call.\n *\n * @example\n * ```typescript\n * // With default owner\n * const coinManager = new CoinManager(suiClient, \"0x123...\");\n *\n * // Without default owner (must specify in each call)\n * const coinManager = new CoinManager(suiClient);\n * ```\n */\n constructor(\n private client: SuiClient,\n private defaultOwner?: string\n ) {}\n\n /**\n * Fetches all coins of a specific type owned by an address.\n *\n * This method handles pagination automatically to retrieve all coins,\n * regardless of how many exist. Coins are returned in the order\n * provided by the blockchain.\n *\n * @param coinType - The fully qualified type of the coin (e.g., \"0x2::sui::SUI\")\n * @param owner - Optional owner address. Uses defaultOwner if not provided.\n *\n * @returns A promise that resolves to an array of all coins of the specified type\n *\n * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set\n *\n * @example\n * ```typescript\n * // Get all SUI coins\n * const suiCoins = await coinManager.getAllCoins(\"0x2::sui::SUI\");\n * console.log(`Found ${suiCoins.length} SUI coins`);\n *\n * // Get all USDC coins for a specific owner\n * const usdcCoins = await coinManager.getAllCoins(\n * \"0x5d4b...::coin::COIN\",\n * \"0xowner...\"\n * );\n *\n * // Display coin details\n * suiCoins.forEach(coin => {\n * console.log(`Coin ID: ${coin.coinObjectId}`);\n * console.log(`Balance: ${coin.balance}`);\n * });\n * ```\n */\n async getAllCoins(coinType: string, owner?: string): Promise<CoinStruct[]> {\n const ownerAddress = this.getOwnerAddress(owner);\n\n // Fetch all coins with pagination\n const allCoins: CoinStruct[] = [];\n let cursor: string | undefined | null;\n\n do {\n const response: PaginatedCoins = await this.client.getCoins({\n owner: ownerAddress,\n coinType,\n cursor,\n });\n\n allCoins.push(...response.data);\n cursor = response.hasNextPage ? response.nextCursor : undefined;\n } while (cursor);\n\n return allCoins;\n }\n\n /**\n * Resolves the owner address from the provided parameter or default.\n *\n * This is a helper method used internally to ensure an owner address\n * is always available for coin operations.\n *\n * @param owner - Optional owner address to use\n *\n * @returns The resolved owner address\n *\n * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set\n *\n * @example\n * ```typescript\n * // With default owner set\n * const address = coinManager.getOwnerAddress(); // Returns defaultOwner\n *\n * // With explicit owner\n * const address = coinManager.getOwnerAddress(\"0x123...\"); // Returns \"0x123...\"\n *\n * // Without default owner or parameter\n * const address = coinManager.getOwnerAddress(); // Throws MissingParameterError\n * ```\n */\n getOwnerAddress(owner?: string): string {\n const address = owner || this.defaultOwner;\n if (!address) throw new MissingParameterError('owner');\n\n return address;\n }\n\n /**\n * Gets the total balance of a specific coin type for an owner.\n *\n * This method returns the sum of all coins of the specified type,\n * providing a quick way to check if sufficient funds are available\n * without fetching all coin objects.\n *\n * @param coinType - The fully qualified type of the coin (e.g., \"0x2::sui::SUI\")\n * @param owner - Optional owner address. Uses defaultOwner if not provided.\n *\n * @returns A promise that resolves to the total balance as a string\n *\n * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set\n *\n * @example\n * ```typescript\n * // Get SUI balance\n * const suiBalance = await coinManager.getTotalBalance(\"0x2::sui::SUI\");\n * console.log(`Total SUI: ${suiBalance}`);\n *\n * // Get USDC balance for specific owner\n * const usdcBalance = await coinManager.getTotalBalance(\n * \"0x5d4b...::coin::COIN\",\n * \"0xowner...\"\n * );\n *\n * // Convert to decimal for display (assuming 9 decimals for SUI)\n * const suiDecimal = Number(suiBalance) / 1e9;\n * console.log(`${suiDecimal} SUI`);\n * ```\n */\n async getTotalBalance(coinType: string, owner?: string): Promise<string> {\n const ownerAddress = this.getOwnerAddress(owner);\n\n const balance = await this.client.getBalance({\n owner: ownerAddress,\n coinType,\n });\n\n return balance.totalBalance;\n }\n\n /**\n * Asserts that the owner has sufficient balance for a transaction.\n *\n * This is a convenience method that checks the balance and throws\n * a descriptive error if insufficient. Useful for fail-fast validation\n * before attempting complex transaction preparation.\n *\n * @param coinType - The fully qualified type of the coin (e.g., \"0x2::sui::SUI\")\n * @param amount - The required amount as a string\n * @param owner - Optional owner address. Uses defaultOwner if not provided.\n *\n * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set\n * @throws {InsufficientFundsError} When the balance is less than the required amount\n *\n * @example\n * ```typescript\n * try {\n * // Check if user has 1 SUI\n * await coinManager.assertEnoughBalance(\n * \"0x2::sui::SUI\",\n * \"1000000000\" // 1 SUI\n * );\n *\n * // Proceed with transaction\n * console.log(\"Sufficient balance confirmed\");\n * } catch (error) {\n * if (error instanceof InsufficientFundsError) {\n * console.error(`Need ${error.data.amount}, but only have ${error.data.available}`);\n * }\n * }\n * ```\n */\n async assertEnoughBalance(coinType: string, amount: string, owner?: string): Promise<void> {\n const ownerAddress = this.getOwnerAddress(owner);\n\n const totalBalance = await this.getTotalBalance(coinType, owner);\n\n if (BigInt(totalBalance) < BigInt(amount)) {\n throw new InsufficientFundsError(amount, totalBalance, { coinType, amount, ownerAddress });\n }\n }\n\n /**\n * Selects optimal coins to cover a specific amount.\n *\n * This method implements intelligent coin selection algorithms that consider\n * various factors like minimizing inputs, preserving large coins, and\n * avoiding fragmentation. It determines whether merging or splitting is needed.\n *\n * @param coinType - The fully qualified type of the coin (e.g., \"0x2::sui::SUI\")\n * @param amount - The target amount to select for, as a string\n * @param options - Configuration options for the selection algorithm\n * @param owner - Optional owner address. Uses defaultOwner if not provided.\n *\n * @returns A promise that resolves to a CoinSelectionResult with selected coins and metadata\n *\n * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set\n * @throws {InsufficientFundsError} When available coins cannot cover the amount (unless allowPartial is true)\n *\n * @example\n * ```typescript\n * // Basic selection\n * const selection = await coinManager.selectCoins(\n * \"0x2::sui::SUI\",\n * \"1000000000\" // 1 SUI\n * );\n *\n * if (selection.requiresMerge) {\n * console.log(`Need to merge ${selection.coins.length} coins`);\n * }\n * if (selection.requiresSplit) {\n * console.log(`Need to split coin for exact amount`);\n * }\n *\n * // Minimize number of inputs\n * const minimalSelection = await coinManager.selectCoins(\n * \"0x2::sui::SUI\",\n * \"5000000000\",\n * { minimizeInputs: true }\n * );\n *\n * // Exclude specific coins and allow partial\n * const partialSelection = await coinManager.selectCoins(\n * \"0x2::sui::SUI\",\n * \"10000000000\",\n * {\n * excludeIds: [\"0x123...\"],\n * allowPartial: true\n * }\n * );\n * ```\n *\n * @remarks\n * The selection algorithm follows these priorities:\n * 1. Exact match - single coin with exact amount\n * 2. Single coin that covers amount (requires split)\n * 3. Multiple coins (requires merge, possibly split)\n *\n * When minimizeInputs is false, smaller coins are used first to preserve larger ones.\n */\n async selectCoins(\n coinType: string,\n amount: string,\n options: CoinSelectionOptions = {},\n owner?: string\n ): Promise<CoinSelectionResult> {\n const ownerAddress = this.getOwnerAddress(owner);\n const coins = await this.getAllCoins(coinType, owner);\n\n // Filter out excluded coins\n const availableCoins = options.excludeIds\n ? coins.filter((c) => !options.excludeIds?.includes(c.coinObjectId))\n : coins;\n\n if (availableCoins.length === 0) {\n throw new InsufficientFundsError(amount, '0', {\n availableCoins,\n coinType,\n ownerAddress,\n });\n }\n\n const targetAmount = BigInt(amount);\n\n // Sort by balance (largest first)\n availableCoins.sort((a, b) => {\n const diff = BigInt(b.balance) - BigInt(a.balance);\n return diff > 0n ? 1 : diff < 0n ? -1 : 0;\n });\n\n // Check for exact match\n const exactMatch = availableCoins.find((c) => BigInt(c.balance) === targetAmount);\n if (exactMatch) {\n return {\n coins: [exactMatch],\n totalBalance: amount,\n requiresMerge: false,\n requiresSplit: false,\n };\n }\n\n // Check for single coin that can cover amount\n const singleCoin = availableCoins.find((c) => BigInt(c.balance) > targetAmount);\n if (singleCoin && !options.preferMerge) {\n return {\n coins: [singleCoin],\n totalBalance: singleCoin.balance,\n requiresMerge: false,\n requiresSplit: true,\n };\n }\n\n // Need multiple coins\n const selectedCoins: CoinStruct[] = [];\n let totalBalance = 0n;\n\n if (options.minimizeInputs) {\n // Try to minimize number of coins used\n for (const coin of availableCoins) {\n selectedCoins.push(coin);\n totalBalance += BigInt(coin.balance);\n if (totalBalance >= targetAmount) break;\n }\n } else {\n // Use smallest coins first to preserve larger coins\n const sortedAsc = [...availableCoins].sort((a, b) => {\n const diff = BigInt(a.balance) - BigInt(b.balance);\n return diff > 0n ? 1 : diff < 0n ? -1 : 0;\n });\n\n for (const coin of sortedAsc) {\n if (totalBalance >= targetAmount) break;\n selectedCoins.push(coin);\n totalBalance += BigInt(coin.balance);\n }\n }\n\n // Check if we have enough\n if (totalBalance < targetAmount) {\n if (options.allowPartial) {\n return {\n coins: selectedCoins,\n totalBalance: totalBalance.toString(),\n requiresMerge: selectedCoins.length > 1,\n requiresSplit: false,\n };\n }\n\n throw new InsufficientFundsError(amount, totalBalance.toString(), {\n amount,\n coinType,\n totalBalance: totalBalance.toString(),\n ownerAddress,\n });\n }\n\n return {\n coins: selectedCoins,\n totalBalance: totalBalance.toString(),\n requiresMerge: selectedCoins.length > 1,\n requiresSplit: totalBalance > targetAmount,\n };\n }\n\n /**\n * Prepares a coin input for a transaction with automatic merging and splitting.\n *\n * This is the main method for transaction preparation. It handles all the complexity\n * of coin selection, merging multiple coins if needed, and splitting for exact amounts.\n * Special handling is provided for SUI gas coins.\n *\n * @param tx - The Transaction object to add coin operations to\n * @param coinType - The fully qualified type of the coin (e.g., \"0x2::sui::SUI\")\n * @param amount - The exact amount needed for the transaction, as a string\n * @param options - Configuration options for coin selection\n * @param owner - Optional owner address. Uses defaultOwner if not provided.\n *\n * @returns A promise that resolves to an Argument that can be used in Move calls\n *\n * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set\n * @throws {InsufficientFundsError} When available coins cannot cover the amount\n *\n * @example\n * ```typescript\n * const tx = new Transaction();\n *\n * // Prepare exact SUI amount (uses gas coin)\n * const suiCoin = await coinManager.prepareCoinInput(\n * tx,\n * \"0x2::sui::SUI\",\n * \"1000000000\" // 1 SUI\n * );\n *\n * // Prepare custom coin with options\n * const customCoin = await coinManager.prepareCoinInput(\n * tx,\n * \"0x5d4b...::coin::COIN\",\n * \"1000000\", // 1 USDC\n * {\n * minimizeInputs: true,\n * excludeIds: [\"0x123...\"]\n * }\n * );\n *\n * // Use in a Move call\n * tx.moveCall({\n * target: `${packageId}::module::swap`,\n * arguments: [suiCoin, customCoin],\n * });\n * ```\n *\n * @remarks\n * - SUI coins are handled specially by splitting from the gas coin\n * - Single coins matching the exact amount are used directly\n * - Multiple coins are automatically merged\n * - Coins with excess balance are automatically split\n * - The resulting Argument can be used directly in Move calls\n */\n async prepareCoinInput(\n tx: Transaction,\n coinType: string,\n amount: string,\n options: CoinSelectionOptions = {},\n owner?: string\n ): Promise<Argument> {\n const ownerAddress = this.getOwnerAddress(owner);\n\n // Handle SUI specially\n if (normalizeStructTag(coinType) === SUI_TOKEN_DENOM) {\n const [coin] = tx.splitCoins(tx.gas, [amount]);\n return coin;\n }\n\n // Select coins\n const selection = await this.selectCoins(coinType, amount, options, owner);\n\n if (!selection.coins[0]) {\n throw new InsufficientFundsError(amount, '0', {\n coinType,\n amount,\n ownerAddress,\n });\n }\n\n // Single coin, exact amount\n if (selection.coins.length === 1 && !selection.requiresSplit) {\n return tx.object(selection.coins[0].coinObjectId);\n }\n\n // Single coin, needs split\n if (selection.coins.length === 1 && selection.requiresSplit) {\n const [split] = tx.splitCoins(tx.object(selection.coins[0].coinObjectId), [amount]);\n return split;\n }\n\n // Multiple coins, need merge\n const primaryCoin = tx.object(selection.coins[0].coinObjectId);\n const mergeCoins = selection.coins.slice(1).map((c) => tx.object(c.coinObjectId));\n\n tx.mergeCoins(primaryCoin, mergeCoins);\n\n // Split if needed\n if (selection.requiresSplit) {\n const [split] = tx.splitCoins(primaryCoin, [amount]);\n return split;\n }\n\n return primaryCoin;\n }\n}\n","import { type Address, TransactionFailedError, UnexpectedError } from '@bolt-liquidity-hq/core';\nimport type { SerializedBcs } from '@mysten/bcs';\nimport type { DevInspectResults, SuiClient } from '@mysten/sui/client';\nimport { Transaction } from '@mysten/sui/transactions';\n\nimport { ZERO_ADDRESS } from '../constants';\n\n/**\n * Executes a read-only query against a Sui Move function using devInspect.\n *\n * This function allows you to call Move functions without committing a transaction\n * to the blockchain. It's perfect for querying contract state, simulating transactions,\n * or getting computed values from view functions. The devInspect feature runs the\n * transaction in a sandboxed environment and returns the results without any state changes.\n *\n * @param suiClient - The SuiClient instance used to interact with the Sui network\n * @param target - The Move function to call, either as:\n * - A string in the format \"packageId::module::function\"\n * - A tuple of [packageId, module, function]\n * @param args - Optional array of arguments to pass to the Move function. Each argument can be:\n * - A string representing an object ID (will be passed as an object reference)\n * - A SerializedBcs object containing pre-serialized BCS data (will be passed as a pure value)\n * @param typeArguments - Optional array of type arguments for generic Move functions\n * @param senderAddress - Optional sender address for the simulated transaction.\n * Defaults to ZERO_ADDRESS if not provided. Some functions may require a specific\n * sender to check permissions or balances.\n *\n * @returns A promise that resolves to DevInspectResults containing:\n * - effects: Transaction effects showing gas costs and object changes\n * - events: Events that would be emitted by the transaction\n * - results: Array of results with return values from the Move function\n * - error: Any execution errors (if status is not 'success')\n *\n * @throws {TransactionFailedError} When the Move function execution fails\n * @throws {UnexpectedError} When there's a network error or other unexpected failure\n *\n * @example\n * ```typescript\n * // Query a simple getter function\n * const result = await queryDevInspect(\n * suiClient,\n * `${packageId}::oracle::get_price`,\n * [baseAssetId, quoteAssetId]\n * );\n *\n * // Query with type arguments\n * const balanceResult = await queryDevInspect(\n * suiClient,\n * [packageId, \"pool\", \"get_balance\"],\n * [poolObjectId],\n * [\"0x2::sui::SUI\"] // Type argument for the coin type\n * );\n *\n * // Query with serialized BCS arguments\n * const amountBcs = bcs.u64().serialize(1000000).toBytes();\n * const swapResult = await queryDevInspect(\n * suiClient,\n * `${packageId}::router::get_amount_out`,\n * [amountBcs, poolObjectId],\n * undefined,\n * userAddress // Use actual user address for more specific simulation\n * );\n *\n * // Parse the results\n * if (result.effects.status.status === 'success') {\n * const returnValue = result.results?.[0]?.returnValues?.[0];\n * if (returnValue) {\n * const price = bcs.u64().parse(new Uint8Array(returnValue[0]));\n * }\n * }\n * ```\n *\n * @remarks\n * - devInspect is read-only and cannot modify blockchain state\n * - Gas is still calculated but not charged\n * - Object modifications are simulated but not persisted\n * - Some functions may behave differently in devInspect vs actual execution\n * - The ZERO_ADDRESS default sender may not work for functions that check ownership\n */\nexport const queryDevInspect = async (\n suiClient: SuiClient,\n target: string | [string, string, string],\n args?: (SerializedBcs<unknown> | string)[],\n typeArguments?: string[],\n senderAddress?: Address\n): Promise<DevInspectResults> => {\n const tx = new Transaction();\n\n const targetString = Array.isArray(target) ? `${target[0]}::${target[1]}::${target[2]}` : target;\n\n const txArgs = args?.map((item) =>\n typeof item === 'string' ? tx.object(item) : tx.pure(item.toBytes())\n );\n\n tx.moveCall({\n target: targetString,\n arguments: txArgs,\n typeArguments,\n });\n\n try {\n // Use devInspectTransactionBlock to execute without submitting to chain\n const result = await suiClient.devInspectTransactionBlock({\n transactionBlock: tx,\n sender: senderAddress ?? ZERO_ADDRESS,\n });\n\n // Process the results\n if (result.effects.status.status === 'success') {\n return result;\n } else {\n throw new TransactionFailedError('N/A', 'Failed to query smart contract', { result });\n }\n } catch (error) {\n throw UnexpectedError.from(error, 'Failed to query smart contract', {\n target: targetString,\n args,\n typeArguments,\n });\n }\n};\n","import type { Address, Coin } from '@bolt-liquidity-hq/core';\nimport {\n DEFAULT_GAS_ADJUSTMENT,\n NotFoundError,\n TransactionFailedError,\n UnexpectedError,\n} from '@bolt-liquidity-hq/core';\nimport { bcs, type SerializedBcs } from '@mysten/bcs';\nimport type {\n SuiClient,\n SuiTransactionBlockResponse,\n SuiTransactionBlockResponseOptions,\n} from '@mysten/sui/client';\nimport type { Signer } from '@mysten/sui/cryptography';\nimport { Transaction, type TransactionArgument } from '@mysten/sui/transactions';\nimport { SUI_CLOCK_OBJECT_ID } from '@mysten/sui/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport type { BoltSuiClient } from '../client';\nimport { CoinManager } from './coin-manager';\nimport { SUI_TOKEN_DENOM } from '../../config';\nimport { ROUTER_MODULE } from '../constants';\nimport type { SuiSwapParams, WalletSigner } from '../../types';\n\n/**\n * Builds the transaction arguments for a swap operation on the Bolt protocol.\n *\n * This helper function prepares all necessary components for executing a swap transaction,\n * including pool discovery, swap direction determination, coin preparation, and argument\n * serialization. It abstracts the complexity of building swap transactions by handling\n * the differences between sell and buy operations automatically. It supports\n * both SDK signers and wallet signers for broader compatibility.\n *\n * @param client - The BoltSuiClient instance containing configuration and contracts\n * @param swapParams - The swap parameters\n * @param swapParams.assetIn - The type of the asset being sold (e.g., \"0x2::sui::SUI\")\n * @param swapParams.amountIn - The exact amount of input asset to swap (in minimal denomination)\n * @param swapParams.assetOut - The type of the asset being bought\n * @param swapParams.minimumAmountOut - Optional minimum acceptable amount of output asset (as string)\n * @param swapParams.receiver - Optional recipient address for the swapped assets\n * @param swapParams.swapType - Optional swap type (default is 'buy')\n * 'buy' - Buy the assetOut from a pool of assetOut, paying with assetIn\n * 'sell' - Sell the assetIn to a pool of assetIn, receiving assetOut\n * @param signer - Optional signer for the transaction. Can be either:\n * - A Signer instance from Sui SDK (e.g., Ed25519Keypair)\n * - A WalletSigner from wallet adapters (e.g., Sui Wallet, Suiet)\n * If not provided, uses the client's cached signer\n *\n * @returns A promise that resolves to an object containing:\n * - signer: The resolved Signer or WalletSigner instance that will sign the transaction\n * - signerAddress: The address of the signer\n * - target: Tuple of [packageId, module, function] for the Move call\n * - args: Array of prepared transaction arguments\n * - typeArguments: Array of type arguments ordered based on swap direction\n * - tx: The Transaction object with prepared coin operations\n *\n * @throws {NotFoundError} When no pool exists for the specified asset pair\n * @throws {MissingParameterError} When no signer is available\n *\n * @example\n * ```typescript\n * const client = new BoltSuiClient();\n *\n * // Using SDK signer\n * const signer = new Ed25519Keypair();\n *\n * // Build swap transaction arguments\n * const txArgs = await buildSwapTxArgs(\n * client,\n * {\n * assetIn: \"0x2::sui::SUI\",\n * amountIn: \"1000000000\", // 1 SUI\n * assetOut: \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\",\n * minimumAmountOut: \"1950000\" // Min 1.95 USDC\n * swapType: 'buy' // Optional, 'buy' or 'sell' (default is 'buy')\n * },\n * signer\n * );\n *\n * // Using wallet signer\n * const walletSigner = await wallet.getAccount();\n * const walletTxArgs = await buildSwapTxArgs(client, swapParams, walletSigner);\n *\n * // Use the prepared arguments to execute the transaction\n * const result = await signAndExecuteTx(\n * client.suiClient,\n * txArgs.signer,\n * txArgs.target,\n * txArgs.args,\n * txArgs.typeArguments,\n * txArgs.tx\n * );\n * ```\n */\nexport const buildSwapTxArgs = async (\n client: BoltSuiClient,\n swapParams: SuiSwapParams,\n signer?: Signer | WalletSigner\n): Promise<{\n signer: Signer | WalletSigner;\n signerAddress: Address;\n target: [string, string, string];\n args?: (TransactionArgument | SerializedBcs<unknown> | string)[];\n typeArguments?: string[];\n tx?: Transaction;\n}> => {\n const { assetIn, amountIn, assetOut, minimumAmountOut, receiver, swapType = 'buy' } = swapParams;\n const pool = client.routerClient.getPool(assetIn, assetOut, swapType);\n\n if (!pool) {\n throw new NotFoundError(`Pool for the pair ${assetIn}/${assetOut}`);\n }\n\n const FUNCTION_NAME = pool.isInverse ? 'swap_sell' : 'swap_buy';\n\n const finalSigner = client.getSigner(signer);\n\n const tx = new Transaction();\n\n const signerAddress = getSignerAddress(finalSigner);\n\n const coinManager = new CoinManager(client.suiClient, signerAddress);\n\n const coinInput = await coinManager.prepareCoinInput(tx, assetIn, amountIn);\n\n return {\n signer: finalSigner,\n signerAddress,\n target: [client.packageId, ROUTER_MODULE, FUNCTION_NAME],\n args: [\n pool.poolAddress,\n client.contracts.oracle,\n SUI_CLOCK_OBJECT_ID,\n coinInput,\n bcs.u64().serialize(amountIn),\n bcs.option(bcs.u64()).serialize(minimumAmountOut),\n bcs.option(bcs.string()).serialize(receiver),\n ],\n typeArguments: [pool.isInverse ? assetIn : assetOut, pool.isInverse ? assetOut : assetIn],\n tx,\n };\n};\n\n/**\n * Signs and executes a transaction on the Sui blockchain.\n *\n * This function builds, signs, and submits a transaction to the Sui network. It provides\n * a convenient wrapper around the Sui SDK's transaction building and execution flow,\n * handling argument serialization and error cases. It supports both SDK signers\n * and wallet signers, automatically detecting and handling each type appropriately.\n *\n * @param suiClient - The SuiClient instance used to interact with the Sui network\n * @param signer - The signer used to sign the transaction. Can be either:\n * - A Signer instance from Sui SDK (e.g., Ed25519Keypair)\n * - A WalletSigner from wallet adapters (e.g., Sui Wallet, Suiet)\n * @param target - The Move function to call, either as:\n * - A string in the format \"packageId::module::function\"\n * - A tuple of [packageId, module, function]\n * @param args - Optional array of arguments to pass to the Move function. Each argument can be:\n * - A string representing an object ID (will be passed as an object reference)\n * - A SerializedBcs object containing pre-serialized BCS data (will be passed as a pure value)\n * - A TransactionArgument created by the Transaction builder\n * @param typeArguments - Optional array of type arguments for generic Move functions.\n * These are fully qualified type names like \"0x2::sui::SUI\"\n * @param transaction - Optional pre-existing Transaction object to add the Move call to.\n * If not provided, a new Transaction will be created.\n * @param options - Optional response options to specify what data to include in the response\n * (e.g., effects, events, object changes, balance changes)\n *\n * @returns A promise that resolves to SuiTransactionBlockResponse containing:\n * - digest: The transaction digest (hash)\n * - effects: Transaction effects showing gas costs, created/modified/deleted objects\n * - events: Events emitted during transaction execution\n * - objectChanges: Detailed changes to objects (if requested in options)\n * - balanceChanges: Changes to coin balances (if requested in options)\n *\n * @throws {TransactionFailedError} When the Move function execution fails on-chain\n *\n * @remarks\n * The function automatically detects the signer type:\n * - SDK signers use `suiClient.signAndExecuteTransaction()`\n * - Wallet signers use their own `signAndExecuteTransaction()` method and require\n * waiting for the transaction to be confirmed on-chain\n *\n * @example\n * ```typescript\n * // Using SDK signer - simple transfer\n * const result = await signAndExecuteTx(\n * suiClient,\n * keypair,\n * '0x2::coin::transfer',\n * [coinObjectId, recipientAddress],\n * ['0x2::sui::SUI']\n * );\n *\n * // Using wallet signer\n * const walletAccount = await wallet.getAccount();\n * const walletResult = await signAndExecuteTx(\n * suiClient,\n * walletAccount,\n * '0x2::coin::transfer',\n * [coinObjectId, recipientAddress],\n * ['0x2::sui::SUI']\n * );\n *\n * // Call a swap function with serialized amount\n * const amountBcs = bcs.u64().serialize(1000000).toBytes();\n * const swapResult = await signAndExecuteTx(\n * suiClient,\n * signer,\n * [packageId, 'pool', 'swap'],\n * [poolObjectId, amountBcs],\n * ['0x2::sui::SUI', `${packageId}::usdc::USDC`],\n * undefined,\n * {\n * showEffects: true,\n * showEvents: true,\n * showObjectChanges: true\n * }\n * );\n *\n * // Build a complex transaction\n * const tx = new Transaction();\n * const [coin] = tx.splitCoins(tx.gas, [1000000]);\n * await signAndExecuteTx(\n * suiClient,\n * signer,\n * `${packageId}::market::place_order`,\n * [marketId, coin, tx.pure.u64(price)],\n * undefined,\n * tx // Pass the existing transaction\n * );\n *\n * // Handle the response\n * if (result.effects?.status.status === 'success') {\n * console.log('Transaction successful:', result.digest);\n * console.log('Gas used:', result.effects.gasUsed);\n *\n * // Process created objects\n * result.effects.created?.forEach(obj => {\n * console.log('Created object:', obj.reference.objectId);\n * });\n * }\n * ```\n */\nexport const signAndExecuteTx = async (\n suiClient: SuiClient,\n signer: Signer | WalletSigner,\n target: string | [string, string, string],\n args?: (TransactionArgument | SerializedBcs<unknown> | string)[],\n typeArguments?: string[],\n transaction?: Transaction,\n options?: SuiTransactionBlockResponseOptions\n): Promise<SuiTransactionBlockResponse> => {\n const tx = transaction ?? new Transaction();\n\n const targetString = Array.isArray(target) ? `${target[0]}::${target[1]}::${target[2]}` : target;\n\n const txArgs = args?.map((item) =>\n typeof item === 'string' ? tx.object(item) : 'toBytes' in item ? tx.pure(item.toBytes()) : item\n );\n\n tx.moveCall({\n target: targetString,\n arguments: txArgs,\n typeArguments,\n });\n\n if ('toSuiAddress' in signer) {\n const result = await suiClient.signAndExecuteTransaction({\n signer,\n transaction: tx,\n options,\n });\n\n if (result.effects?.status.status === 'success') {\n return result;\n } else {\n throw new TransactionFailedError(result.digest, result.effects?.status.error, { result });\n }\n } else {\n const result = await signer.signAndExecuteTransaction({\n transaction: tx,\n });\n\n if (!result.digest) {\n throw new TransactionFailedError('not found');\n }\n\n const fullTx = await suiClient.waitForTransaction({\n digest: result.digest,\n options,\n });\n\n if (fullTx.effects?.status.status !== 'success') {\n throw new TransactionFailedError(result.digest, fullTx.effects?.status.error, { result });\n }\n\n return fullTx;\n }\n};\n\n/**\n * Estimates the gas price for a transaction on the Sui blockchain.\n *\n * This function builds a transaction and performs a dry run to estimate gas costs\n * without actually executing the transaction on-chain. It returns the gas denomination\n * (always 'SUI' for Sui network) and the estimated amount including the gas adjustment\n * multiplier. The sender address is required for accurate gas estimation as it affects\n * object resolution and gas calculations.\n *\n * @param suiClient - The SuiClient instance used to interact with the Sui network\n * @param senderAddress - The Sui address that would send the transaction. This is used for:\n * - Resolving owned objects in the transaction\n * - Calculating accurate gas costs based on the sender's objects\n * - Setting the transaction sender for the dry run\n * @param target - The Move function to call, either as:\n * - A string in the format \"packageId::module::function\"\n * - A tuple of [packageId, module, function]\n * @param args - Optional array of arguments to pass to the Move function. Each argument can be:\n * - A string representing an object ID (will be passed as an object reference)\n * - A SerializedBcs object containing pre-serialized BCS data (will be passed as a pure value)\n * - A TransactionArgument created by the Transaction builder\n * @param typeArguments - Optional array of type arguments for generic Move functions.\n * These are fully qualified type names like \"0x2::sui::SUI\"\n * @param transaction - Optional pre-existing Transaction object to add the Move call to.\n * If not provided, a new Transaction will be created.\n * @param gasAdjustment - Optional multiplier for gas estimation (default: 1.5). Use higher values for\n * safety margin. For example, 1.5 means 50% buffer above estimated gas.\n *\n * @returns A promise that resolves to a Coin object containing:\n * - denom: The gas denomination (configured SUI token denomination)\n * - amount: The estimated gas amount as a string, including the gas adjustment\n * Returns undefined if estimation fails\n *\n * @remarks\n * - Silent failure returns undefined to allow graceful handling of estimation errors\n *\n * @example\n * ```typescript\n * // Estimate gas for a simple transfer\n * const senderAddress = \"0x123...\";\n * const gasEstimate = await estimateTxGasPrice(\n * suiClient,\n * senderAddress,\n * '0x2::coin::transfer',\n * [coinObjectId, recipientAddress],\n * ['0x2::sui::SUI']\n * );\n * if (gasEstimate) {\n * console.log(`Estimated gas: ${gasEstimate.amount} ${gasEstimate.denom}`);\n * }\n *\n * // Estimate with higher safety margin\n * const safeGasEstimate = await estimateTxGasPrice(\n * suiClient,\n * senderAddress,\n * [packageId, 'pool', 'swap'],\n * [poolObjectId, amountBcs],\n * ['0x2::sui::SUI', `${packageId}::usdc::USDC`],\n * undefined,\n * 2.0 // 100% buffer for complex operations\n * );\n *\n * // Use with existing transaction\n * const tx = new Transaction();\n * const [coin] = tx.splitCoins(tx.gas, [1000000]);\n * const gasPrice = await estimateTxGasPrice(\n * suiClient,\n * senderAddress,\n * `${packageId}::market::place_order`,\n * [marketId, coin, tx.pure.u64(price)],\n * undefined,\n * tx,\n * 1.2\n * );\n * ```\n */\nexport const estimateTxGasPrice = async (\n suiClient: SuiClient,\n senderAddress: Address,\n target: string | [string, string, string],\n args?: (TransactionArgument | SerializedBcs<unknown> | string)[],\n typeArguments?: string[],\n transaction?: Transaction,\n gasAdjustment: number = DEFAULT_GAS_ADJUSTMENT\n): Promise<Coin | undefined> => {\n const tx = transaction ?? new Transaction();\n\n const targetString = Array.isArray(target) ? `${target[0]}::${target[1]}::${target[2]}` : target;\n\n const txArgs = args?.map((item) =>\n typeof item === 'string' ? tx.object(item) : 'toBytes' in item ? tx.pure(item.toBytes()) : item\n );\n\n tx.moveCall({\n target: targetString,\n arguments: txArgs,\n typeArguments,\n });\n\n tx.setSender(senderAddress);\n\n try {\n // Build the transaction\n const transactionBytes = await tx.build({ client: suiClient });\n\n // Perform dry run to estimate gas\n const dryRunResult = await suiClient.dryRunTransactionBlock({\n transactionBlock: transactionBytes,\n });\n\n if (dryRunResult.effects.status.status !== 'success') {\n throw new UnexpectedError(\n `Dry run failed: ${dryRunResult.effects.status.error}`,\n 'Failed to estimate gas',\n {\n target: targetString,\n args,\n typeArguments,\n error: dryRunResult.effects.status.error,\n }\n );\n }\n\n // Extract gas information from the dry run result\n const gasUsed = dryRunResult.effects.gasUsed;\n\n // Calculate total gas cost (computation + storage - storage rebate)\n const totalGasCost = BigNumber(gasUsed.computationCost)\n .plus(gasUsed.storageCost)\n .minus(gasUsed.storageRebate);\n\n // Apply gas adjustment multiplier\n const adjustedGasCost = totalGasCost.times(gasAdjustment);\n\n return {\n denom: SUI_TOKEN_DENOM,\n amount: adjustedGasCost.toFixed(0, BigNumber.ROUND_CEIL),\n };\n } catch {\n return;\n }\n};\n\n/**\n * Extracts the address from either an SDK Signer or a WalletSigner.\n *\n * This utility function provides a unified way to get the address from different\n * signer types used in the Sui ecosystem. It handles the differences between\n * SDK signers (which have a toSuiAddress() method) and wallet signers (which\n * have an address property).\n *\n * @param signer - The signer instance to extract the address from. Can be either:\n * - A Signer from Sui SDK (has toSuiAddress() method)\n * - A WalletSigner from wallet adapters (has address property)\n *\n * @returns The Sui address as a string\n *\n * @throws {NotFoundError} When the signer doesn't have an accessible address\n *\n * @example\n * ```typescript\n * // With SDK signer\n * const keypair = new Ed25519Keypair();\n * const sdkAddress = getSignerAddress(keypair);\n * console.log(sdkAddress); // \"0x...\"\n *\n * // With wallet signer\n * const walletAccount = await wallet.getAccount();\n * const walletAddress = getSignerAddress(walletAccount);\n * console.log(walletAddress); // \"0x...\"\n * ```\n */\nexport const getSignerAddress = (signer: Signer | WalletSigner): string => {\n const address: string | undefined =\n 'address' in signer ? signer.address : signer.toSuiAddress?.();\n\n if (!address) {\n throw new NotFoundError(\"Signer account's address\");\n }\n\n return address;\n};\n","import type {\n InvertiblePrice,\n OracleConfig,\n OracleAssetPair,\n AssetsConfig,\n} from '@bolt-liquidity-hq/core';\nimport { InvalidObjectError } from '@bolt-liquidity-hq/core';\nimport { BigNumber } from 'bignumber.js';\nimport { normalizeStructTag } from '@mysten/sui/utils';\n\nimport type {\n AssetPairsResponseStructOutput,\n AssetPairStructOutput,\n OracleConfigStructOutput,\n PriceDataStructOutput,\n PriceResponseStructOutput,\n} from '../../types';\n\n/**\n * Parses a raw oracle configuration response from the Sui blockchain into a structured OracleConfig object.\n *\n * This function transforms the snake_case properties from the Sui Move contract response\n * into camelCase properties following TypeScript conventions. It also converts the\n * price expiry time from seconds to a structured format with seconds and nanoseconds.\n *\n * @param output - The raw oracle configuration response from the contract query\n * @param output.price_threshold_ratio - The maximum allowed price deviation ratio\n * @param output.default_price_expiry_seconds - The default time in seconds before prices expire\n *\n * @returns A parsed OracleConfig object with:\n * - admin: The admin address of the oracle contract\n * - priceThresholdRatio: The threshold ratio for price updates (e.g., \"0.01\" for 1%)\n * - priceExpireTime: Object with seconds and nanoseconds representing expiry duration\n *\n * @example\n * ```typescript\n * const output = {\n * price_threshold_ratio: \"0.01\",\n * default_price_expiry_seconds: \"3600\" // 1 hour\n * };\n *\n * const config = parseOracleConfigStructOutput(output);\n * console.log(config.admin); // \"0x1234...\"\n * console.log(config.priceThresholdRatio); // \"0.01\"\n * console.log(config.priceExpireTime.secs); // 3600\n * ```\n */\nexport const parseOracleConfigStructOutput = (output: OracleConfigStructOutput): OracleConfig => {\n return {\n // TODO: try to query admin somewhere else? to fill empty value\n admin: '',\n priceThresholdRatio: output.price_threshold_ratio,\n priceExpireTime: {\n secs: Number(output.default_price_expiry_seconds),\n nanos: 0,\n },\n };\n};\n\n/**\n * Parses a single asset pair structure from the Sui oracle contract into an OracleAssetPair object.\n *\n * This function converts the raw asset pair data containing base and quote asset information\n * into a structured format. It can optionally use an assets configuration to provide\n * human-readable names for assets, falling back to extracting names from the asset type string.\n *\n * @param output - The raw asset pair data from the contract\n * @param output.base_name - The name/type of the base asset (e.g., \"SUI\", \"0x2::sui::SUI\")\n * @param output.base_precision - The decimal precision of the base asset (e.g., 9 for SUI)\n * @param output.quote_name - The name/type of the quote asset\n * @param output.quote_precision - The decimal precision of the quote asset\n * @param assetsConfig - Optional configuration mapping asset types to metadata including names\n *\n * @returns An OracleAssetPair object containing:\n * - base: Object with name, symbol (normalized struct tag), and precision for the base asset\n * - quote: Object with name, symbol (normalized struct tag), and precision for the quote asset\n *\n * @example\n * ```typescript\n * const rawPair = {\n * base_name: \"0x2::sui::SUI\",\n * base_precision: 9,\n * quote_name: \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\",\n * quote_precision: 6\n * };\n *\n * const assetsConfig = {\n * \"0x2::sui::SUI\": { name: \"SUI\" },\n * \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\": { name: \"COIN\" }\n * };\n *\n * const pair = parseAssetPairStructOutput(rawPair, assetsConfig);\n * console.log(pair.base.name); // \"SUI\"\n * console.log(pair.base.symbol); // \"0x2::sui::SUI\"\n * console.log(pair.quote.name); // \"COIN\"\n * ```\n */\nexport const parseAssetPairStructOutput = (\n output: AssetPairStructOutput,\n assetsConfig?: AssetsConfig\n): OracleAssetPair => {\n return {\n base: {\n name:\n assetsConfig?.[output.base_name]?.name ??\n output.base_name.match(/([^:]+)$/)?.[1] ??\n output.base_name,\n symbol: normalizeStructTag(output.base_name),\n precision: output.base_precision,\n },\n quote: {\n name:\n assetsConfig?.[output.quote_name]?.name ??\n output.quote_name.match(/([^:]+)$/)?.[1] ??\n output.quote_name,\n symbol: normalizeStructTag(output.quote_name),\n precision: output.quote_precision,\n },\n };\n};\n\n/**\n * Parses a response containing multiple asset pairs from the oracle contract.\n *\n * This function processes an array of asset pairs returned by the oracle's\n * asset_pairs query, where each item contains an 'info' property with the\n * actual pair data. It can optionally use an assets configuration to provide\n * human-readable names for the assets.\n *\n * @param output - Array of objects containing asset pair info\n * @param assetsConfig - Optional configuration mapping asset types to metadata including names\n *\n * @returns An array of parsed OracleAssetPair objects\n *\n * @example\n * ```typescript\n * const output = [\n * { info: { base_name: \"0x2::sui::SUI\", base_precision: 9, quote_name: \"0x5d::coin::COIN\", quote_precision: 6 } },\n * { info: { base_name: \"0xeth::coin::ETH\", base_precision: 18, quote_name: \"0x5d::coin::COIN\", quote_precision: 6 } }\n * ];\n *\n * const assetsConfig = {\n * \"0x2::sui::SUI\": { name: \"SUI\" },\n * \"0xeth::coin::ETH\": { name: \"ETH\" },\n * \"0x5d::coin::COIN\": { name: \"USDC\" }\n * };\n *\n * const pairs = parseAssetPairsResponseStructOutput(output, assetsConfig);\n * console.log(pairs.length); // 2\n * console.log(pairs[0].base.name); // \"SUI\"\n * console.log(pairs[0].base.symbol); // \"0x2::sui::SUI\"\n * ```\n */\nexport const parseAssetPairsResponseStructOutput = (\n output: AssetPairsResponseStructOutput,\n assetsConfig?: AssetsConfig\n): OracleAssetPair[] => {\n return output.map((item) => parseAssetPairStructOutput(item.info, assetsConfig));\n};\n\n/**\n * Parses raw price data from the oracle contract into an InvertiblePrice object.\n *\n * This function converts the price information including the price value and expiry time.\n * The expiry time is converted from milliseconds to nanoseconds for consistency with\n * the broader system's time representation. The base and quote denominations are\n * provided as parameters rather than being included in the output data.\n *\n * @param output - The raw price data from the contract\n * @param output.price - Object containing the price details\n * @param output.price.price - The price value as a string (to maintain precision)\n * @param output.price.expiry - The price expiry time in milliseconds since Unix epoch\n * @param baseDenom - The denomination of the base asset (e.g., \"0x2::sui::SUI\")\n * @param quoteDenom - The denomination of the quote asset (e.g., \"0xusdcAddress...\")\n *\n * @returns An InvertiblePrice object containing:\n * - baseDenom: The denom of the base token (from parameter)\n * - quoteDenom: The denom of the quote token (from parameter)\n * - price: The price value as a string\n * - expiryTime: The expiry time in nanoseconds as a string\n * - isInverse: Boolean flag indicating if the price is inverted or not\n *\n * @example\n * ```typescript\n * const priceData = {\n * price: {\n * price: \"2.5\",\n * expiry: \"1700000000000\" // milliseconds\n * }\n * };\n *\n * const price = parsePriceDataStructOutput(\n * priceData,\n * \"0x2::sui::SUI\",\n * \"0xusdcAddress...\"\n * );\n * console.log(price.price); // \"2.5\"\n * console.log(price.baseDenom); // \"0x2::sui::SUI\"\n * console.log(price.quoteDenom); // \"0xusdcAddress...\"\n * console.log(price.expiryTime); // \"1700000000000000000\" (nanoseconds)\n * ```\n */\nexport const parsePriceDataStructOutput = (\n output: PriceDataStructOutput,\n baseDenom: string,\n quoteDenom: string,\n isInverted?: boolean\n): InvertiblePrice => {\n return {\n baseDenom: baseDenom,\n quoteDenom: quoteDenom,\n price: BigNumber(output.price.price).shiftedBy(-18).toFixed(),\n expiryTime: BigNumber(output.price.expiry).times(1_000_000).toFixed(),\n isInverse: isInverted ?? false,\n };\n};\n\n/**\n * Parses a price response from the oracle contract, extracting the price data if available.\n *\n * This function handles the response from price queries which may or may not contain\n * valid price data. It checks for the presence of pair_data and throws an error\n * if the price is not available. The base and quote denominations must be provided\n * as they are not included in the response data.\n *\n * @param output - The price response from the oracle contract\n * @param output.pair_data - Optional price data for the requested pair\n * @param baseDenom - The denomination of the base asset\n * @param quoteDenom - The denomination of the quote asset\n *\n * @returns An InvertiblePrice object with the parsed price information\n *\n * @throws {InvalidObjectError} When pair_data is not present in the response,\n * indicating that no price is available for the requested pair\n *\n * @example\n * ```typescript\n * // Successful response with price data\n * const output = {\n * pair_data: {\n * price: {\n * price: \"2.5\",\n * expiry: \"1700000000000\"\n * }\n * }\n * };\n *\n * const price = parsePriceResponseStructOutput(\n * output,\n * \"0x2::sui::SUI\",\n * \"0xusdcAddress...\"\n * );\n * console.log(price.price); // \"2.5\"\n *\n * // Response without price data\n * const emptyOutput = { pair_data: null };\n * // This will throw InvalidObjectError\n * ```\n */\nexport const parsePriceResponseStructOutput = (\n output: PriceResponseStructOutput,\n baseDenom: string,\n quoteDenom: string\n): InvertiblePrice => {\n if (!output.pair_data) {\n throw new InvalidObjectError(\"Can't find pair data price\");\n }\n\n return parsePriceDataStructOutput(output.pair_data, baseDenom, quoteDenom, output.is_inverted);\n};\n","import { bcs, BcsType } from '@mysten/bcs';\n\nexport const PaginationStruct = {\n total_count: bcs.u64(),\n has_next_page: bcs.bool(),\n next_cursor: bcs.option(bcs.string()),\n};\n\nexport const BcsAddressType = new BcsType({\n name: 'address',\n\n read(reader) {\n const bytes = new Uint8Array(32);\n for (let i = 0; i < 32; i++) {\n bytes[i] = reader.read8();\n }\n return (\n '0x' +\n Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n );\n },\n\n write(value, writer) {\n // Remove 0x prefix if present\n const hex = value.startsWith('0x') ? value.slice(2) : value;\n // Pad to 64 characters (32 bytes)\n const paddedHex = hex.padStart(64, '0');\n\n for (let i = 0; i < 32; i++) {\n const byte = parseInt(paddedHex.substr(i * 2, 2), 16);\n writer.write8(byte);\n }\n },\n});\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type BcsParsed<T extends BcsType<any, any>> = ReturnType<T['parse']>;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type BcsParsedMultiple<T extends readonly BcsType<any>[]> = {\n [K in keyof T]: BcsParsed<T[K]>;\n};\n","import { bcs } from '@mysten/bcs';\n\nimport { BcsAddressType, type BcsParsed } from './bcs';\n\nexport const OracleConfigStruct = bcs.struct('Config', {\n price_threshold_ratio: bcs.u64(),\n default_price_expiry_seconds: bcs.u64(),\n});\nexport type OracleConfigStructOutput = BcsParsed<typeof OracleConfigStruct>;\n\nexport const AssetPairStruct = bcs.struct('AssetPair', {\n base_name: bcs.string(),\n quote_name: bcs.string(),\n base_precision: bcs.u8(),\n quote_precision: bcs.u8(),\n});\nexport type AssetPairStructOutput = BcsParsed<typeof AssetPairStruct>;\n\nexport const TypeNameStruct = bcs.struct('TypeName', {\n name: bcs.string(),\n});\nexport type TypeNameStructOutput = BcsParsed<typeof TypeNameStruct>;\n\nexport const RawPairStruct = bcs.struct('RawPair', {\n base: TypeNameStruct,\n quote: TypeNameStruct,\n});\nexport type RawPairStructOutput = BcsParsed<typeof RawPairStruct>;\n\nexport const AssetPairResponseStruct = bcs.struct('AssetPairResponse', {\n pair: RawPairStruct,\n info: AssetPairStruct,\n});\nexport type AssetPairResponseStructOutput = BcsParsed<typeof AssetPairResponseStruct>;\n\nexport const AssetPairsResponseStruct = bcs.vector(AssetPairResponseStruct);\nexport type AssetPairsResponseStructOutput = BcsParsed<typeof AssetPairsResponseStruct>;\n\nexport const RawPriceStruct = bcs.struct('RawPrice', {\n price: bcs.u128(),\n expiry: bcs.u64(),\n});\nexport type RawPriceStructOutput = BcsParsed<typeof RawPriceStruct>;\n\nexport const PriceDataStruct = bcs.struct('PriceData', {\n price: RawPriceStruct,\n last_updated_ms: bcs.u64(),\n updater: BcsAddressType,\n});\nexport type PriceDataStructOutput = BcsParsed<typeof PriceDataStruct>;\n\nexport const PriceResponseStruct = bcs.struct('PriceResponse', {\n pair_data: bcs.option(PriceDataStruct),\n is_inverted: bcs.bool(),\n});\nexport type PriceResponseStructOutput = BcsParsed<typeof PriceResponseStruct>;\n","import type { Pool, SwapParams, SwapRequiredParams } from '@bolt-liquidity-hq/core';\nimport { bcs } from '@mysten/bcs';\n\nimport { BcsAddressType, type BcsParsed, PaginationStruct } from './bcs';\n\nexport type SuiSwapSimulateParams = SwapRequiredParams & {\n swapType?: 'buy' | 'sell';\n};\n\nexport type SuiSwapParams = SwapParams & {\n swapType?: 'buy' | 'sell';\n};\n\nexport const RouterConfigStruct = bcs.struct('Config', {\n admin: BcsAddressType,\n default_price_oracle_contract: BcsAddressType,\n default_protocol_fee_recipient: BcsAddressType,\n default_protocol_fee: bcs.u64(),\n default_lp_fee: bcs.u64(),\n});\nexport type RouterConfigStructOutput = BcsParsed<typeof RouterConfigStruct>;\n\nexport const MarketStruct = bcs.struct('Market', {\n base_asset_symbol: bcs.string(),\n quote_assets_symbols: bcs.vector(bcs.string()),\n market_address: bcs.string(),\n is_permissioned: bcs.bool(),\n created_at_ms: bcs.u64(),\n});\nexport type MarketStructOutput = BcsParsed<typeof MarketStruct>;\n\nexport const MarketResponseStruct = bcs.struct('MarketResponse', {\n market: bcs.option(MarketStruct),\n});\nexport type MarketResponseStructOutput = BcsParsed<typeof MarketResponseStruct>;\n\nexport const MarketsResponseStruct = bcs.struct('MarketsResponse', {\n markets: bcs.vector(MarketStruct),\n});\nexport type MarketsResponseStructOutput = BcsParsed<typeof MarketsResponseStruct>;\n\nexport const MarketsResponsePaginatedStruct = bcs.struct('MarketsResponsePaginated', {\n markets: bcs.vector(MarketStruct),\n ...PaginationStruct,\n});\nexport type MarketsResponsePaginatedStructOutput = BcsParsed<typeof MarketsResponsePaginatedStruct>;\n\nexport const SwapSimulationResultStruct = bcs.struct('SwapSimulationResult', {\n base_out: bcs.u64(),\n quote_out: bcs.u64(),\n swap_fee_pct: bcs.u64(),\n dynamic_fee_pct: bcs.u64(),\n ideal_quote_amt: bcs.u128(),\n swap_fee: bcs.u64(),\n lp_fee: bcs.u64(),\n protocol_fee: bcs.u64(),\n price_used: bcs.u128(),\n});\nexport type SwapSimulationResultStructOutput = BcsParsed<typeof SwapSimulationResultStruct>;\n\nexport type RouterPool = Pool & {\n isInverse: boolean;\n};\n","import type { Address } from '@bolt-liquidity-hq/core';\nimport { bcs } from '@mysten/bcs';\n\nimport { BcsAddressType, type BcsParsed } from './bcs';\n\nexport const PoolInfoStruct = bcs.struct('PoolInfo', {\n id: bcs.string(),\n base_liquidity: bcs.u64(),\n net_base_added: bcs.u64(),\n total_lp_shares: bcs.u64(),\n protocol_base_fees: bcs.u64(),\n admin: BcsAddressType,\n is_paused: bcs.bool(),\n});\nexport type PoolInfoStructOutput = BcsParsed<typeof PoolInfoStruct>;\nexport type PoolInfo = {\n id: string;\n baseLiquidity: string;\n netBaseAdded: string;\n totalLpShares: string;\n protocolBaseFees: string;\n admin: Address;\n isPaused: boolean;\n};\n\nexport const PoolConfigStruct = bcs.struct('PoolConfig', {\n swap_fee_pct: bcs.u64(),\n lp_withdrawal_fee_pct: bcs.u64(),\n lp_fee_pct: bcs.u64(),\n max_dynamic_fee: bcs.u64(),\n limit_ratio: bcs.u64(),\n min_base_out: bcs.u64(),\n});\nexport type PoolConfigStructOutput = BcsParsed<typeof PoolConfigStruct>;\n\nexport const ProtocolFeesInfoStruct = bcs.struct('ProtocolFeesInfo', {\n swap_fee_pct: bcs.u64(),\n lp_withdrawal_fee_pct: bcs.u64(),\n});\nexport type ProtocolFeesInfoStructOutput = BcsParsed<typeof ProtocolFeesInfoStruct>;\n\nexport const BaseLiquidityInfoStruct = bcs.struct('BaseLiquidityInfo', {\n base_reserve: bcs.u64(),\n total_lp_shares: bcs.u64(),\n});\nexport type BaseLiquidityInfoStructOutput = BcsParsed<typeof BaseLiquidityInfoStruct>;\n","import type { OracleAssetPair } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\nimport { PRICE_ORACLE_MODULE } from '../constants';\nimport { parseDevInspectResult, queryDevInspect } from '../helpers';\nimport { parseAssetPairsResponseStructOutput } from './parsers';\nimport { AssetPairsResponseStruct } from '../../types';\n\n/**\n * Queries the oracle smart contract to retrieve all supported asset pairs.\n *\n * This function fetches the complete list of trading pairs that the oracle contract\n * supports for price feeds. Each asset pair represents a base/quote relationship\n * that can be used for price queries and swaps within the Bolt protocol.\n *\n * @param client - The BoltSuiClient instance.\n *\n * @returns A promise that resolves to an array of OracleAssetPair objects, each containing:\n * - base: Information about the base asset\n * - name: The full name of the base asset (currently same as symbol)\n * - symbol: The trading symbol (e.g., \"SUI\", \"ETH\")\n * - precision: The number of decimal places for the base asset\n * - quote: Information about the quote asset\n * - name: The full name of the quote asset (currently same as symbol)\n * - symbol: The trading symbol (e.g., \"USDC\", \"USDT\")\n * - precision: The number of decimal places for the quote asset\n *\n * @throws {TransactionFailedError} When the oracle contract query fails, which could happen if:\n * - The oracle contract is not properly initialized\n * - The contract address is incorrect\n * - Network connection issues occur\n * @throws {ParseError} When the response cannot be parsed, indicating:\n * - The contract returned data in an unexpected format\n * - The BCS deserialization failed\n * - The contract ABI has changed\n */\nexport const getAssetPairs = async (client: BoltSuiClient): Promise<OracleAssetPair[]> => {\n /**\n * The Move function name in the oracle module that returns all asset pairs.\n * This function signature in Move:\n * public fun asset_pairs(oracle: &Oracle): AssetPairsResponse\n */\n const ASSET_PAIRS_FUNCTION = 'asset_pairs';\n\n const response = await queryDevInspect(\n client.suiClient,\n [client.packageId, PRICE_ORACLE_MODULE, ASSET_PAIRS_FUNCTION],\n [client.contracts.oracle]\n );\n\n const output = parseDevInspectResult(response, AssetPairsResponseStruct);\n\n return parseAssetPairsResponseStructOutput(output, client.assetsConfig);\n};\n","import type { Asset, OracleAsset } from '@bolt-liquidity-hq/core';\nimport { normalizeStructTag } from '@mysten/sui/utils';\n\nimport type { BoltSuiClient } from '../client';\n\n/**\n * Retrieves all unique assets available in the Bolt protocol by querying oracle asset pairs\n * and enriching them with additional metadata from the client's asset configuration.\n *\n * This function performs the following operations:\n * 1. Fetches all oracle asset pairs from the blockchain\n * 2. Extracts unique assets from both base and quote positions\n * 3. Maps oracle assets to full Asset objects using client configuration\n * 4. Provides fallback values for assets not found in the configuration\n *\n * @param client - The BoltSuiClient instance used to query the blockchain\n * and access asset configuration.\n *\n * @returns A promise that resolves to an array of Asset objects, each containing:\n * - symbol: The asset's trading symbol (e.g., \"SUI\", \"USDC\")\n * - name: The full name of the asset (e.g., \"Sui\", \"USD Coin\")\n * - chainId: The blockchain network identifier (e.g., \"sui-mainnet\")\n * - denom: The chain-specific denomination (e.g., \"0x2::sui::SUI\")\n * - decimals: The number of decimal places for precision\n * - logo: Optional URL to the asset's logo image\n * - coingeckoId: Optional CoinGecko identifier for market data integration\n *\n * @throws {TransactionFailedError} When the oracle contract query fails\n * @throws {ParseError} When the oracle response cannot be properly parsed\n * @throws {UnexpectedError} When network issues prevent the query from completing\n */\nexport const getAssets = async (client: BoltSuiClient): Promise<Asset[]> => {\n // Fetch all trading pairs from the oracle to discover available assets\n const assetPairs = await client.getAllOracleAssetPairs();\n\n /**\n * Map to store unique assets by symbol.\n * This ensures each asset appears only once in the final result,\n * even if it appears in multiple trading pairs.\n */\n const uniqueOracleAssets: Record<string, OracleAsset> = {};\n\n // Extract unique assets from all trading pairs\n for (const item of assetPairs) {\n uniqueOracleAssets[normalizeStructTag(item.base.symbol)] = {\n ...item.base,\n symbol: normalizeStructTag(item.base.symbol),\n };\n uniqueOracleAssets[normalizeStructTag(item.quote.symbol)] = {\n ...item.quote,\n symbol: normalizeStructTag(item.quote.symbol),\n };\n }\n\n return Object.values(uniqueOracleAssets).map(\n (item) =>\n client.assetsConfig[item.symbol] ??\n // Fallback to minimal asset data from oracle\n {\n symbol: item.name,\n name: item.name,\n chainId: client.chainConfig.id,\n denom: normalizeStructTag(item.symbol),\n decimals: item.precision,\n logo: undefined,\n coingeckoId: undefined,\n }\n );\n};\n","import type { OracleConfig } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\nimport { PRICE_ORACLE_MODULE } from '../constants';\nimport { parseDevInspectResult, queryDevInspect } from '../helpers';\nimport { parseOracleConfigStructOutput } from './parsers';\nimport { OracleConfigStruct } from '../../types';\n\n/**\n * Queries the oracle smart contract to retrieve its current configuration settings.\n *\n * This function fetches the oracle's configuration parameters which govern how\n * price feeds are managed, including expiration times, update thresholds, and\n * administrative settings. The configuration is essential for understanding\n * oracle behavior and constraints when working with price feeds.\n *\n * @param client - The BoltSuiClient instance\n *\n * @returns A promise that resolves to an OracleConfig object containing:\n * - admin: The Sui address authorized to update oracle settings and prices\n * - priceThresholdRatio: The minimum price change ratio required for updates\n * (e.g., \"0.01\" means 1% minimum change required)\n * - priceExpireTime: Object with time duration for price validity:\n * - secs: Number of seconds before a price is considered stale\n * - nanos: Additional nanoseconds (always 0 in current implementation)\n *\n * @throws {TransactionFailedError} When the oracle contract query fails, possibly due to:\n * - Invalid oracle contract address\n * - Oracle contract not initialized\n * - Network connectivity issues\n * @throws {ParseError} When the response cannot be parsed, indicating:\n * - Unexpected response format from the contract\n * - BCS deserialization failure\n * - Contract ABI mismatch\n * @throws {InvalidObjectError} When required data is missing from the response\n */\nexport const getOracleConfig = async (client: BoltSuiClient): Promise<OracleConfig> => {\n /**\n * The Move function name in the oracle module that returns configuration.\n * This function signature in Move:\n * public fun config(oracle: &Oracle): OracleConfig\n */\n const CONFIG_FUNCTION = 'config';\n\n const response = await queryDevInspect(\n client.suiClient,\n [client.packageId, PRICE_ORACLE_MODULE, CONFIG_FUNCTION],\n [client.contracts.oracle]\n );\n\n const output = parseDevInspectResult(response, OracleConfigStruct);\n\n return parseOracleConfigStructOutput(output);\n};\n","import type { InvertiblePrice } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\nimport { PRICE_ORACLE_MODULE } from '../constants';\nimport { parseDevInspectResult, queryDevInspect } from '../helpers';\nimport { parsePriceResponseStructOutput } from './parsers';\nimport { PriceResponseStruct } from '../../types';\n\n/**\n * Queries the oracle smart contract to retrieve the current price for a specific asset pair.\n *\n * This function fetches the latest price feed for a given base/quote asset combination\n * from the Bolt oracle. The oracle maintains price feeds that are updated by authorized\n * price feeders and validated against configured thresholds.\n *\n * @param client - The BoltSuiClient instance\n * @param baseDenom - The denomination/type of the base asset in Sui format\n * (e.g., \"0x2::sui::SUI\", \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\")\n * @param quoteDenom - The denomination/type of the quote asset in Sui format\n * Price will be expressed as: 1 base = X quote\n *\n * @returns A promise that resolves to an InvertiblePrice object containing:\n * - baseDenom: The denom of the base token\n * - quoteDenom: The denom of the quote token\n * - price: The current price as a decimal string (e.g., \"2.5\" means 1 base = 2.5 quote)\n * - expiryTime: Unix timestamp in nanoseconds when this price becomes stale\n * - isInverse: Always false in current implementation (price is not inverted)\n *\n * @throws {InvalidObjectError} When the requested asset pair has no price data available,\n * which can occur if:\n * - The pair is not registered in the oracle\n * - The oracle has never received a price for this pair\n * @throws {TransactionFailedError} When the oracle contract query fails due to:\n * - Invalid oracle contract address\n * - Network connectivity issues\n * - Contract execution errors\n * @throws {ParseError} When the response cannot be parsed, indicating:\n * - Unexpected response format\n * - BCS deserialization failure\n */\nexport const getPrice = async (\n client: BoltSuiClient,\n baseDenom: string,\n quoteDenom: string\n): Promise<InvertiblePrice> => {\n /**\n * The Move function name in the oracle module that returns a price for a pair.\n * This function signature in Move:\n * public fun get_price<BaseAsset, QuoteAsset>(\n * oracle: &Oracle\n * ): PriceResponse\n */\n const GET_PRICE_FUNCTION = 'get_price';\n\n const response = await queryDevInspect(\n client.suiClient,\n [client.packageId, PRICE_ORACLE_MODULE, GET_PRICE_FUNCTION],\n [client.contracts.oracle],\n [baseDenom, quoteDenom]\n );\n\n const output = parseDevInspectResult(response, PriceResponseStruct);\n\n return parsePriceResponseStructOutput(output, baseDenom, quoteDenom);\n};\n","import { NotFoundError, type Price } from '@bolt-liquidity-hq/core';\nimport { normalizeStructTag } from '@mysten/sui/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport type { BoltSuiClient } from '../client';\nimport type { RawPairStructOutput, RawPriceStructOutput } from '../../types';\n\n/**\n * Queries the oracle smart contract to retrieve all available price feeds.\n *\n * This function fetches the current prices for all asset pairs supported by the oracle\n * by directly reading the oracle's dynamic fields. It iterates through all stored price\n * entries in the oracle's prices table.\n *\n * @param client - The BoltSuiClient instance\n *\n * @returns A promise that resolves to an array of Price objects, each containing:\n * - baseDenom: The normalized denom of the base token\n * - quoteDenom: The normalized denom of the quote token\n * - price: The current price as a decimal string\n * - expiryTime: Unix timestamp in milliseconds when this price expires\n *\n * @throws {NotFoundError} When:\n * - The oracle object cannot be found at the configured address\n * - The oracle object exists but is not a valid Move object\n * - The prices table cannot be found within the oracle object\n * @throws {TransactionFailedError} When the Sui queries fail due to:\n * - Network connectivity issues\n * - Invalid oracle contract address\n */\nexport const getPrices = async (client: BoltSuiClient): Promise<Price[]> => {\n const oracleObject = await client.suiClient.getObject({\n id: client.contracts.oracle,\n options: { showContent: true },\n });\n\n if (!oracleObject.data?.content || oracleObject.data.content.dataType !== 'moveObject') {\n throw new NotFoundError('Oracle object');\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n const pricesTableId: string | undefined = (oracleObject.data.content.fields as any)?.prices\n ?.fields?.id?.id;\n\n if (!pricesTableId) {\n throw new NotFoundError('Prices table in the Oracle contract');\n }\n\n // Get all prices\n const prices: Price[] = [];\n let cursor = null;\n\n while (true) {\n const dynamicFields = await client.suiClient.getDynamicFields({\n parentId: pricesTableId,\n cursor,\n limit: 50, // Max limit per request\n });\n\n // Batch fetch all field objects in this page\n const fieldPromises = dynamicFields.data.map((field) =>\n client.suiClient.getDynamicFieldObject({\n parentId: pricesTableId,\n name: field.name,\n })\n );\n\n const fieldObjects = await Promise.all(fieldPromises);\n fieldObjects.forEach((obj, index) => {\n if (obj.data?.content?.dataType === 'moveObject') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n const fields = (obj.data.content.fields as any)?.value?.fields?.price?.fields as\n | RawPriceStructOutput\n | undefined;\n const pairKey = dynamicFields.data[index]?.name?.value as RawPairStructOutput | undefined;\n\n if (fields && pairKey) {\n prices.push({\n baseDenom: normalizeStructTag(pairKey.base.name),\n quoteDenom: normalizeStructTag(pairKey.quote.name),\n price: BigNumber(fields.price).shiftedBy(-18).toFixed(),\n expiryTime: fields.expiry,\n });\n }\n }\n });\n\n if (!dynamicFields.hasNextPage) break;\n cursor = dynamicFields.nextCursor;\n }\n\n return prices;\n};\n","import { type Coin, DEFAULT_GAS_ADJUSTMENT, type SwapParams } from '@bolt-liquidity-hq/core';\nimport type { Signer } from '@mysten/sui/cryptography';\n\nimport type { BoltSuiClient } from '../client';\nimport { buildSwapTxArgs, estimateTxGasPrice } from '../helpers';\nimport type { WalletSigner } from '../../types';\n\n/**\n * Estimates the gas fees required for executing a swap transaction on the Sui blockchain.\n *\n * This function simulates a swap transaction to calculate the required gas fees without\n * actually executing the swap. It leverages the buildSwapTxArgs helper to prepare all\n * transaction components, then uses Sui's dry run capability to estimate gas costs in SUI tokens.\n *\n * @param client - The BoltSuiClient instance containing configuration and contracts\n * @param swapParams - The swap parameters\n * @param swapParams.assetIn - The type of the asset being sold (e.g., \"0x2::sui::SUI\")\n * @param swapParams.amountIn - The exact amount of input asset to swap (in minimal denomination)\n * @param swapParams.assetOut - The type of the asset being bought (e.g., \"0x5d...::coin::COIN\")\n * @param swapParams.minimumAmountOut - Optional minimum acceptable amount of output asset.\n * Used for slippage protection in the swap simulation.\n * @param swapParams.receiver - Optional recipient address for the swapped assets.\n * If not provided, defaults to the signer's address.\n * @param signer - Optional signer for the transaction. If not provided,\n * uses the client's cached signer. Required on first call if no cached signer exists.\n * @param gasAdjustment - Multiplier for gas estimation to add safety margin.\n * Defaults to DEFAULT_GAS_ADJUSTMENT (typically 1.5 for 50% buffer).\n *\n * @returns A promise that resolves to:\n * - A Coin object with `amount` (gas fee in MIST) and `denom` (\"0x2::sui::SUI\")\n * - `undefined` if the simulation fails or gas estimation is not supported\n *\n * @throws {NotFoundError} When no pool exists for the specified asset pair\n * @throws {MissingParameterError} When no signer is available\n */\nexport const estimateSwapExactInGasFees = async (\n client: BoltSuiClient,\n swapParams: SwapParams,\n signer?: Signer | WalletSigner,\n gasAdjustment: number = DEFAULT_GAS_ADJUSTMENT\n): Promise<Coin | undefined> => {\n const swapArgs = await buildSwapTxArgs(client, swapParams, signer);\n\n return await estimateTxGasPrice(\n client.suiClient,\n swapArgs.signerAddress,\n swapArgs.target,\n swapArgs.args,\n swapArgs.typeArguments,\n swapArgs.tx,\n gasAdjustment\n );\n};\n","import { type BaseLiquidityDetails, NotFoundError, type Address } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\nimport { POOL_MODULE } from '../constants';\nimport { parseDevInspectResult, queryDevInspect } from '../helpers';\nimport { parseBaseLiquidityInfoStructOutput } from './parsers';\nimport { BaseLiquidityInfoStruct } from '../../types';\n\n/**\n * Fetches the base liquidity details for a specific pool.\n *\n * @param client - The BoltSuiClient instance\n * @param contractAddress - The blockchain address of the pool contract\n *\n * @returns A promise that resolves to the base liquidity details for the pool\n *\n * @throws Will throw an error if no pool exists for the specified asset(s)\n */\nexport const getPoolBaseLiquidity = async (\n client: BoltSuiClient,\n contractAddress: Address\n): Promise<BaseLiquidityDetails> => {\n /**\n * Move function to get pool configuration information.\n * Function signature in Move:\n public fun get_base_liquidity_info<Base>(pool: &LiquidityPool<Base>): BaseLiquidityInfo<Base>\n */\n const GET_BASE_LIQUIDITY_INFO_FUNCTION = 'get_base_liquidity_info';\n\n const pool = client.routerClient.pools.find((item) => item.poolAddress === contractAddress);\n\n if (!pool) {\n throw new NotFoundError(`Pool with the address ${contractAddress}`);\n }\n\n const baseLiquidityInfo = await queryDevInspect(\n client.suiClient,\n [client.packageId, POOL_MODULE, GET_BASE_LIQUIDITY_INFO_FUNCTION],\n [contractAddress],\n [pool.baseDenom]\n );\n\n const output = parseDevInspectResult(baseLiquidityInfo, BaseLiquidityInfoStruct);\n\n return parseBaseLiquidityInfoStructOutput(output, pool.baseDenom);\n};\n","import type { BaseLiquidityDetails, PoolConfig } from '@bolt-liquidity-hq/core';\nimport { BigNumber } from 'bignumber.js';\n\nimport { BASIS_POINTS } from '../constants';\nimport type { RouterClient } from '../router';\nimport type {\n BaseLiquidityInfoStructOutput,\n PoolConfigStructOutput,\n PoolInfo,\n PoolInfoStructOutput,\n} from '../../types';\n\n/**\n * Parses pool configuration from the Sui blockchain into a structured PoolConfig object.\n *\n * This function transforms pool configuration data from the `get_pool_config` Move function response\n * into the standardized format used throughout the SDK.\n *\n * @param routerClient - The RouterClient instance\n * @param poolConfig - The response from the `get_pool_config` Move function containing:\n * - swap_fee_pct: The swap fee in basis points (e.g., 30 = 0.3%)\n * - lp_fee_pct: The liquidity provider fee in basis points (e.g., 20 = 0.2%)\n * - lp_withdrawal_fee_pct: The LP withdrawal fee in basis points\n * - max_dynamic_fee: Maximum dynamic fee adjustment in basis points\n * - limit_ratio: Price limit ratio for dynamic fee calculation\n * - min_base_out: Minimum base asset output amount for trades\n * @param priceOracleContract - The Sui object ID of the price oracle contract used by this pool\n *\n * @returns A parsed PoolConfig object with:\n * - priceOracleContract: Object ID of the price oracle (from parameter)\n * - protocolFeeRecipient: Currently returns '0x' (placeholder until contracts are updated)\n * - protocolFee: The protocol fee percentage as decimal string (swap_fee_pct / 10000)\n * - lpFee: The liquidity provider fee percentage as decimal string (lp_fee_pct / 10000)\n * - allowanceMode: Currently hardcoded to 'allow' (will come from pool config in future)\n * - lps: Array of all pool addresses from the router client\n * - minBaseOut: Minimum base asset output amount from the pool config\n *\n * @example\n * ```typescript\n * // Example with actual data\n * const routerClient = new RouterClient(pools);\n *\n * const poolConfigResponse: PoolConfigStructOutput = {\n * swap_fee_pct: 30, // 30 basis points = 0.3%\n * lp_fee_pct: 20, // 20 basis points = 0.2%\n * lp_withdrawal_fee_pct: 10, // 10 basis points = 0.1%\n * max_dynamic_fee: 50, // 50 basis points = 0.5% max dynamic adjustment\n * limit_ratio: 100, // Price limit ratio\n * min_base_out: \"1000000\" // Minimum base output amount\n * };\n *\n * const oracleAddress = \"0xoracle456...\";\n *\n * const config = parsePoolConfigStructOutput(\n * routerClient,\n * poolConfigResponse,\n * oracleAddress\n * );\n *\n * console.log(config.priceOracleContract); // \"0xoracle456...\"\n * console.log(config.protocolFeeRecipient); // \"0x\"\n * console.log(config.protocolFee); // \"0.003\" (30/10000)\n * console.log(config.lpFee); // \"0.002\" (20/10000)\n * console.log(config.allowanceMode); // \"allow\"\n * console.log(config.lps); // Array of all pool addresses\n * console.log(config.minBaseOut); // \"1000000\"\n * ```\n */\nexport const parsePoolConfigStructOutput = (\n routerClient: RouterClient,\n poolConfig: PoolConfigStructOutput,\n priceOracleContract: string\n): PoolConfig => {\n // TODO: update when contracts are completed\n // Currently using hardcoded values for some fields\n return {\n priceOracleContract,\n protocolFeeRecipient: '0x', // TODO: get real fee recipient\n protocolFee: BigNumber(poolConfig.swap_fee_pct).div(BASIS_POINTS).toFixed(),\n lpFee: BigNumber(poolConfig.lp_fee_pct).div(BASIS_POINTS).toFixed(),\n allowanceMode: 'allow', // Should come from pool config\n lps: routerClient.getPools().map((item) => item.poolAddress),\n minBaseOut: BigNumber(poolConfig.min_base_out).toFixed(),\n };\n};\n\n/**\n * Parses pool information from the Sui blockchain into a structured PoolInfo object.\n *\n * This function transforms pool information data from the `get_pool_info` Move function response\n * into the standardized format used throughout the SDK.\n *\n * @param routerClient - The RouterClient instance\n * @param poolInfo - The response from the `get_pool_info` Move function containing:\n * - id: The Sui object ID of the pool\n * - base_liquidity: The amount of base asset liquidity in the pool\n * - net_base_added: The net amount of base asset added to the pool\n * - total_lp_shares: The total number of liquidity provider shares in the pool\n * - protocol_base_fees: The amount of base asset fees collected by the protocol\n * - admin: The address of the pool admin\n * - is_paused: Whether the pool is paused\n *\n * @returns A parsed PoolConfig object with:\n * - id: The Sui object ID of the pool\n * - baseLiquidity: The amount of base asset liquidity in the pool\n * - netBaseAdded: The net amount of base asset added to the pool\n * - totalLpShares: The total number of liquidity provider shares in the pool\n * - protocolBaseFees: The amount of base asset fees collected by the protocol\n * - admin: The address of the pool admin\n * - isPaused: Whether the pool is paused\n *\n * @example\n * ```typescript\n * // Example with actual data\n * const routerClient = new RouterClient(pools);\n *\n * const poolInfoResponse: PoolInfoStructOutput = {\n * swap_fee_pct: 30, // 30 basis points = 0.3%\n * net_base_added: \"1000000\",\n * total_lp_shares: \"1000000\",\n * protocol_base_fees: \"1000000\",\n * admin: \"0xadmin...\",\n * is_paused: false\n * };\n *\n * const config = parsePoolInfoStructOutput(poolInfoResponse);\n *\n * console.log(config.id); // \"0x1234...\"\n * console.log(config.baseLiquidity); // \"1000000\"\n * console.log(config.netBaseAdded); // \"1000000\"\n * console.log(config.totalLpShares); // \"1000000\"\n * console.log(config.protocolBaseFees); // \"1000000\"\n * console.log(config.admin); // \"0xadmin...\"\n * console.log(config.isPaused); // false\n * ```\n */\nexport const parsePoolInfoStructOutput = (poolInfo: PoolInfoStructOutput): PoolInfo => {\n return {\n id: poolInfo.id,\n baseLiquidity: BigNumber(poolInfo.base_liquidity).toFixed(),\n netBaseAdded: BigNumber(poolInfo.net_base_added).toFixed(),\n totalLpShares: BigNumber(poolInfo.total_lp_shares).toFixed(),\n protocolBaseFees: BigNumber(poolInfo.protocol_base_fees).toFixed(),\n admin: poolInfo.admin,\n isPaused: poolInfo.is_paused,\n };\n};\n\n/**\n * Parses base liquidity details from the pool info response on Sui blockchain into a structured BaseLiquidityDetails object.\n *\n * This function transforms base liquidity details data from the `get_base_liquidity_info` Move function response\n * into the standardized format used throughout the SDK.\n *\n * @param poolInfo - The response from the `get_base_liquidity_info` Move function containing:\n * - base_liquidity: The amount of base asset liquidity in the pool\n * - total_lp_shares: The total number of liquidity provider shares in the pool\n *\n * @returns A parsed BaseLiquidityDetails object with:\n * - baseLiquidity: The amount of base asset liquidity in the pool\n * - totalShares: The total number of liquidity provider shares in the pool\n *\n * @example\n * ```typescript\n * // Example with actual data\n * const poolInfoResponse: PoolInfoStructOutput = {\n * base_liquidity: \"1000000\",\n * total_lp_shares: \"1000000\"\n * };\n *\n * const baseLiquidityDetails = parseBaseLiquidityDetails(poolInfoResponse, \"0x1234...\");\n *\n * console.log(baseLiquidityDetails.baseLiquidity); // \"1000000\"\n * console.log(baseLiquidityDetails.totalShares); // \"1000000\"\n * ```\n */\nexport const parsePoolInfoBaseLiquidityDetails = (\n poolInfo: PoolInfoStructOutput,\n baseDenom: string\n): BaseLiquidityDetails => {\n return {\n baseLiquidity: {\n denom: baseDenom,\n amount: poolInfo.base_liquidity,\n },\n totalShares: poolInfo.total_lp_shares,\n };\n};\n\n/*\n Parses base liquidity details from the Sui blockchain into a structured BaseLiquidityDetails object.\n *\n * This function transforms base liquidity details data from the `get_base_liquidity_info` Move function response\n * into the standardized format used throughout the SDK.\n *\n * @param baseLiquidityInfo - The response from the `get_base_liquidity_info` Move function containing:\n * - base_reserve: The amount of base asset liquidity in the pool\n * - total_lp_shares: The total number of liquidity provider shares in the pool\n *\n * @returns A parsed BaseLiquidityDetails object with:\n * - baseLiquidity: The amount of base asset liquidity in the pool\n * - totalShares: The total number of liquidity provider shares in the pool\n *\n * @example\n * ```typescript\n * // Example with actual data\n * const baseLiquidityInfoResponse: BaseLiquidityInfoStructOutput = {\n * base_reserve: \"1000000\",\n * total_lp_shares: \"1000000\"\n * };\n *\n * const baseLiquidityDetails = parseBaseLiquidityDetails(baseLiquidityInfoResponse, \"0x1234...\");\n *\n * console.log(baseLiquidityDetails.baseLiquidity); // \"1000000\"\n * console.log(baseLiquidityDetails.totalShares); // \"1000000\"\n * ```\n */\nexport const parseBaseLiquidityInfoStructOutput = (\n baseLiquidityInfo: BaseLiquidityInfoStructOutput,\n baseDenom: string\n): BaseLiquidityDetails => {\n return {\n baseLiquidity: {\n denom: baseDenom,\n amount: BigNumber(baseLiquidityInfo.base_reserve).toFixed(),\n },\n totalShares: BigNumber(baseLiquidityInfo.total_lp_shares).toFixed(),\n };\n};\n","import { NotFoundError, type Address, type PoolConfig } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\nimport { POOL_MODULE } from '../constants';\nimport { parseDevInspectResult, queryDevInspect } from '../helpers';\nimport { parsePoolConfigStructOutput } from './parsers';\nimport { PoolConfigStruct } from '../../types';\n\n/**\n * Retrieves the configuration settings and fee information for a specific liquidity pool on Sui.\n *\n * @param client - The BoltSuiClient instance.\n * @param contractAddress - The Sui object ID of the pool contract to query.\n * Must be a valid pool address obtained from router queries.\n *\n * @returns A promise that resolves to a PoolConfig object containing:\n * - priceOracleContract: Object ID of the price oracle used by this pool\n * - protocolFeeRecipient: Address that receives protocol fees from swaps\n * - protocolFee: The protocol fee percentage as decimal string (e.g., \"0.003\" = 0.3%)\n * - lpFee: The liquidity provider fee percentage as decimal string (e.g., \"0.002\" = 0.2%)\n * - allowanceMode: The allowance mode for LP operations (controls who can provide liquidity)\n * - lps: Array of authorized liquidity provider addresses\n * - minBaseOut: Minimum base asset output amount for trades (dust protection)\n *\n * @throws {NotFoundError} When no pool exists with the specified contract address\n * @throws {TransactionFailedError} When the query fails due to:\n * - Invalid pool contract address format\n * - Network connectivity issues\n * - Incorrect type arguments for the pool\n * @throws {ParseError} When the response cannot be parsed, indicating:\n * - Unexpected response format from the query\n * - BCS deserialization failure\n * - Missing required fields in the response\n */\nexport const getPoolConfig = async (\n client: BoltSuiClient,\n contractAddress: Address\n): Promise<PoolConfig> => {\n /**\n * Move function to get pool configuration information.\n * Function signature in Move:\n * public fun get_pool_config<X>(pool: &LiquidityPool<X>): PoolConfig\n */\n const GET_POOL_CONFIG_FUNCTION = 'get_pool_config';\n\n const pool = client.routerClient.pools.find((item) => item.poolAddress === contractAddress);\n\n if (!pool) {\n throw new NotFoundError(`Pool with the address ${contractAddress}`);\n }\n\n const poolConfig = await queryDevInspect(\n client.suiClient,\n [client.packageId, POOL_MODULE, GET_POOL_CONFIG_FUNCTION],\n [contractAddress],\n [pool.baseDenom]\n );\n\n const output = parseDevInspectResult(poolConfig, PoolConfigStruct);\n\n return parsePoolConfigStructOutput(client.routerClient, output, client.contracts.oracle);\n};\n","import type { PoolConfig } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\nimport { getPoolConfig } from './get-pool-config';\nimport { getPoolByDenom } from '../router';\n\n/**\n * Retrieves the configuration settings for a liquidity pool\n * identified by its base and quote asset types.\n *\n * This is a convenience function that combines pool lookup and configuration retrieval.\n * It first finds the pool/market associated with the given base/quote asset pair, then fetches that\n * pool's configuration parameters from its settlement contract. In Sui, settlement\n * contracts manage the actual liquidity and trading logic for each pool, and pools are\n * uniquely identified by both base and quote assets.\n *\n * @param client - The BoltSuiClient instance\n * @param baseDenom - The type of the base asset in Sui format\n * (e.g., \"0x2::sui::SUI\", \"0xaf8cd5edc19c4512f4259f0bee101a40d41ebed738ade5874359610ef8eeced5::coin::COIN\")\n * @param quoteDenom - The type of the quote asset in Sui format\n * (e.g., \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\")\n *\n * @returns A promise that resolves to a PoolConfig object containing:\n * - priceOracleContract: Object ID of the price oracle used by this pool\n * - protocolFeeRecipient: Sui address that receives protocol fees\n * - protocolFee: The protocol fee percentage (as decimal string, e.g., \"0.003\" = 0.3%)\n * - lpFee: The liquidity provider fee percentage (as decimal string, e.g., \"0.002\" = 0.2%)\n * - allowanceMode: The allowance mode for pool operations (controls LP permissions)\n * - lps: Array of authorized liquidity provider Sui addresses\n * - minBaseOut: Minimum base asset output amount for trades (prevents dust trades)\n *\n * @throws {NotFoundError} When no pool exists for the specified base/quote asset pair\n * @throws {TransactionFailedError} When the contract queries fail due to:\n * - Invalid router or settlement contract addresses\n * - Network connectivity issues\n * - Contract not properly initialized\n * @throws {ParseError} When the configuration response cannot be parsed\n */\nexport const getPoolConfigByDenom = async (\n client: BoltSuiClient,\n baseDenom: string,\n quoteDenom: string\n): Promise<PoolConfig> => {\n const pool = await getPoolByDenom(client, baseDenom, quoteDenom);\n\n return await getPoolConfig(client, pool.poolAddress);\n};\n","import { type Address, type BaseLiquidityDetails } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\nimport { getPoolBaseLiquidity } from '../settlement';\n\n/**\n * Queries the router smart contract to retrieve the total base asset liquidity across all pools.\n *\n * This function fetches the current liquidity levels for all base assets in their respective\n * pools. Each pool in the Bolt protocol handles swaps for a specific base asset against\n * multiple quote assets, and this query returns how much of each base asset is currently\n * available in its pool for trading, along with the total shares for each pool.\n *\n * @param client - The BoltSuiClient instance\n *\n * @returns A promise that resolves to a Record mapping pool addresses to BaseLiquidityDetails objects.\n * Each entry represents:\n * - Key: The pool contract address\n * - Value: A BaseLiquidityDetails object containing:\n * - baseLiquidity: A Coin object with:\n * - amount: The quantity of base asset liquidity (as string)\n * - denom: The denomination of the base asset\n * - totalShares: The total number of liquidity shares for the pool (as string)\n *\n * @throws Will throw an error if:\n * - The contract query fails due to network issues\n * - The router contract is not properly initialized\n * ```\n */\nexport const getAllBaseLiquidity = async (\n client: BoltSuiClient\n): Promise<Record<Address, BaseLiquidityDetails>> => {\n const result: Record<Address, BaseLiquidityDetails> = {};\n\n for (const pool of client.routerClient.pools) {\n const baseLiquidity = await getPoolBaseLiquidity(client, pool.poolAddress);\n result[pool.poolAddress] = baseLiquidity;\n }\n\n return result;\n};\n","import { NotImplementedError, type Address, type Coin } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\n\n/**\n * Queries the router smart contract to retrieve all quote asset positions for a specific liquidity provider.\n *\n *\n * Currently not implemented on Sui Client\n *\n * @param client - The BoltSuiClient instance\n */\nexport const getAllQuotesForUser = async (\n _client: BoltSuiClient,\n _lpAddress: Address\n // eslint-disable-next-line @typescript-eslint/require-await\n): Promise<Record<Address, Coin[]>> => {\n throw new NotImplementedError('getRouterConfig on Sui Client');\n};\n","import { NotFoundError, type Pool } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\n\n/**\n * Queries the router client to retrieve pool information for a specific asset pair.\n *\n * This function fetches the market/pool details for a given base/quote asset pair from the client's\n * router instance. In the Bolt protocol on Sui, pools are uniquely identified by both base and quote\n * asset types, allowing for multiple pools with the same base asset but different quote assets.\n * This query returns the pool's object ID and configuration for the specified trading pair.\n *\n * @param client - The BoltSuiClient instance.\n * @param baseDenom - The type of the base asset in Sui format\n * (e.g., \"0x2::sui::SUI\", \"0xaf8cd5edc19c4512f4259f0bee101a40d41ebed738ade5874359610ef8eeced5::coin::COIN\")\n * @param quoteDenom - The type of the quote asset in Sui format\n * (e.g., \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\")\n *\n * @returns A promise that resolves to a Pool object containing:\n * - poolAddress: The Sui object ID of the market/pool\n * - baseDenom: The type of the base asset\n * - quoteDenoms: Array of types for available quote assets (will include the requested quote asset)\n *\n * @throws {NotFoundError} When no pool exists for the specified base/quote asset pair, with a message\n * indicating which assets were requested. This occurs if:\n * - No pool has been created for this specific trading pair\n * - The asset types are not recognized by the router\n * - The pool was removed or not initialized\n */\nexport const getPoolByDenom = async (\n client: BoltSuiClient,\n baseDenom: string,\n quoteDenom: string\n): Promise<Pool> => {\n // eslint-disable-next-line @typescript-eslint/await-thenable\n const result = await client.routerClient.getPool(quoteDenom, baseDenom);\n\n if (!result) {\n throw new NotFoundError('Pool', `Didn't find a pool to swap ${quoteDenom} for ${baseDenom}`);\n }\n\n return result;\n};\n","import type { Pool } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\n\n/**\n * Retrieves information about all available pools from the router client.\n *\n * This function fetches a comprehensive list of all markets/pools configured in the Bolt protocol\n * on Sui through the client's router instance. It provides a complete overview of all trading\n * possibilities within the protocol at once, making it more efficient than querying individual pools.\n *\n * @param client - The BoltSuiClient instance.\n *\n * @returns A promise that resolves to an array of Pool objects, each containing:\n * - poolAddress: The Sui object ID of the market/pool\n * - baseDenom: The type of the base asset for this pool (e.g., \"0x2::sui::SUI\")\n * - quoteDenoms: Array of types for available quote assets that can be traded\n * ```\n */\nexport const getPools = async (client: BoltSuiClient): Promise<Pool[]> => {\n // eslint-disable-next-line @typescript-eslint/await-thenable\n return await client.routerClient.getPools();\n};\n","import { NotImplementedError, type RouterConfig } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\n\n/**\n * Queries the router smart contract to retrieve its current configuration settings.\n *\n * Currently not implemented on Sui Client\n *\n * @param client - The BoltSuiClient instance\n */\n// eslint-disable-next-line @typescript-eslint/require-await\nexport const getRouterConfig = async (_client: BoltSuiClient): Promise<RouterConfig> => {\n throw new NotImplementedError('getRouterConfig on Sui Client');\n};\n","import type { Pool, RouterConfig, SimulateSwapResult } from '@bolt-liquidity-hq/core';\nimport { NotFoundError } from '@bolt-liquidity-hq/core';\nimport { BigNumber } from 'bignumber.js';\n\nimport { BASIS_POINTS } from '../constants';\nimport type {\n MarketResponseStructOutput,\n MarketsResponsePaginatedStructOutput,\n MarketsResponseStructOutput,\n MarketStructOutput,\n RouterConfigStructOutput,\n SwapSimulationResultStructOutput,\n} from '../../types';\n\n/**\n * Parses a raw market structure from the Sui blockchain into a structured Pool object.\n *\n * This function transforms the raw market data returned by the Sui router contract\n * into a standardized Pool format. In the Sui implementation, markets and pools\n * are conceptually the same, representing liquidity pools for base/quote asset pairs.\n *\n * @param output - The raw market data from the Sui contract\n * @param output.market_address - The Sui object ID of the market/pool\n * @param output.base_asset_symbol - The type/symbol of the base asset\n * @param output.quote_assets_symbols - Array of quote asset types/symbols\n *\n * @returns A parsed Pool object containing:\n * - poolAddress: The Sui object ID of the pool\n * - baseDenom: The type of the base asset (e.g., \"0x2::sui::SUI\")\n * - quoteDenoms: Array of available quote asset types\n *\n * @example\n * ```typescript\n * const rawMarket = {\n * market_address: \"0x1234...\",\n * base_asset_symbol: \"0x2::sui::SUI\",\n * quote_assets_symbols: [\"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\"]\n * };\n *\n * const pool = parseMarketStructOutput(rawMarket);\n * console.log(pool.poolAddress); // \"0x1234...\"\n * console.log(pool.baseDenom); // \"0x2::sui::SUI\"\n * console.log(pool.quoteDenoms); // [\"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\"]\n * ```\n */\nexport const parseMarketStructOutput = (output: MarketStructOutput): Pool => {\n return {\n poolAddress: output.market_address,\n baseDenom: output.base_asset_symbol,\n quoteDenoms: output.quote_assets_symbols,\n };\n};\n\n/**\n * Parses a market response that may or may not contain market data.\n *\n * This function handles responses from queries for specific markets, which include\n * an optional market field. If no market is found, it throws an appropriate error.\n *\n * @param output - The market query response from the Sui contract\n * @param output.market - Optional market data if found\n *\n * @returns A parsed Pool object representing the market\n *\n * @throws {NotFoundError} When the market field is null or undefined,\n * indicating the requested market doesn't exist\n *\n * @example\n * ```typescript\n * // Successful response with market data\n * const response = {\n * market: {\n * market_address: \"0x1234...\",\n * base_asset_symbol: \"0x2::sui::SUI\",\n * quote_assets_symbols: [\"0x5d4b...::coin::COIN\"]\n * }\n * };\n * const pool = parseMarketResponseStructOutput(response);\n *\n * // Response without market (will throw)\n * const emptyResponse = { market: null };\n * // Throws NotFoundError\n * ```\n */\nexport const parseMarketResponseStructOutput = (output: MarketResponseStructOutput): Pool => {\n if (!output.market) {\n throw new NotFoundError('Market', undefined, { output });\n }\n\n return parseMarketStructOutput(output.market);\n};\n\n/**\n * Parses a response containing all available markets/pools into an array of Pool objects.\n *\n * This function processes the response from the router's markets query, which returns\n * all active liquidity pools in the Bolt protocol on Sui.\n *\n * @param output - The raw response from the router's markets query\n * @param output.markets - Array of market structures\n *\n * @returns An array of parsed Pool objects, each representing a liquidity pool\n *\n * @example\n * ```typescript\n * const output = {\n * markets: [\n * {\n * market_address: \"0xabc...\",\n * base_asset_symbol: \"0x2::sui::SUI\",\n * quote_assets_symbols: [\"0x5d4b...::coin::COIN\"]\n * },\n * {\n * market_address: \"0xdef...\",\n * base_asset_symbol: \"0xaf8...::coin::COIN\",\n * quote_assets_symbols: [\"0x5d4b...::coin::COIN\", \"0x2::sui::SUI\"]\n * }\n * ]\n * };\n *\n * const pools = parseMarketsResponseStructOutput(output);\n * console.log(pools.length); // 2\n * pools.forEach(pool => {\n * console.log(`Pool for ${pool.baseDenom} at ${pool.poolAddress}`);\n * console.log(`Quote assets: ${pool.quoteDenoms.join(', ')}`);\n * });\n * ```\n */\nexport const parseMarketsResponseStructOutput = (output: MarketsResponseStructOutput): Pool[] => {\n return output.markets.map((item) => parseMarketStructOutput(item));\n};\n\n/**\n * Parses a paginated response containing markets/pools into an array of Pool objects.\n *\n * This function handles paginated market responses, which are used when there are\n * too many markets to return in a single query. It extracts just the market data,\n * leaving pagination handling to the calling function.\n *\n * @param output - The paginated response from the router's markets query\n * @param output.markets - Array of market structures for this page\n * @param output.has_next_page - Whether more pages exist (not used in parser)\n * @param output.next_cursor - Cursor for next page (not used in parser)\n *\n * @returns An array of parsed Pool objects for this page of results\n *\n * @example\n * ```typescript\n * const paginatedOutput = {\n * markets: [\n * {\n * market_address: \"0xabc...\",\n * base_asset_symbol: \"0x2::sui::SUI\",\n * quote_assets_symbols: [\"0x5d4b...::coin::COIN\"]\n * }\n * ],\n * has_next_page: true,\n * next_cursor: \"0xabc...\"\n * };\n *\n * const pools = parseMarketsResponsePaginatedStructOutput(paginatedOutput);\n * console.log(pools.length); // 1 (just this page)\n * ```\n *\n * @see {@link parseMarketsResponseStructOutput} for non-paginated version\n */\nexport const parseMarketsResponsePaginatedStructOutput = (\n output: MarketsResponsePaginatedStructOutput\n): Pool[] => {\n return output.markets.map((item) => parseMarketStructOutput(item));\n};\n\n/**\n * Parses a raw router configuration response from the Sui blockchain into a structured RouterConfig object.\n *\n * This function transforms the snake_case properties from the Sui router contract response\n * into camelCase properties following TypeScript conventions. The router configuration\n * controls global settings for the Bolt protocol on Sui.\n *\n * @param output - The raw router configuration response from the contract query\n * @param output.admin - The Sui address with admin privileges\n * @param output.default_price_oracle_contract - Default oracle object ID for price feeds\n * @param output.default_protocol_fee_recipient - Address that receives protocol fees\n * @param output.default_protocol_fee - Protocol fee as decimal string (e.g., \"0.003\" = 0.3%)\n * @param output.default_lp_fee - LP fee as decimal string (e.g., \"0.002\" = 0.2%)\n *\n * @returns A parsed RouterConfig object with:\n * - admin: The admin address of the router contract\n * - defaultPriceOracleContract: Object ID of the default price oracle\n * - defaultProtocolFeeRecipient: Address that receives protocol fees\n * - defaultProtocolFee: The default protocol fee percentage (as decimal string)\n * - defaultLpFee: The default liquidity provider fee percentage (as decimal string)\n *\n * @example\n * ```typescript\n * const output = {\n * admin: \"0xadmin...\",\n * default_price_oracle_contract: \"0xoracle...\",\n * default_protocol_fee_recipient: \"0xtreasury...\",\n * default_protocol_fee: \"0.003\",\n * default_lp_fee: \"0.002\"\n * };\n *\n * const config = parseRouterConfigStructOutput(output);\n * console.log(config.admin); // \"0xadmin...\"\n * console.log(config.defaultProtocolFee); // \"0.003\" (0.3%)\n * console.log(config.defaultLpFee); // \"0.002\" (0.2%)\n *\n * // Calculate total fees\n * const totalFeePercent = (parseFloat(config.defaultProtocolFee) +\n * parseFloat(config.defaultLpFee)) * 100;\n * console.log(`Total fees: ${totalFeePercent}%`); // \"Total fees: 0.5%\"\n * ```\n */\nexport const parseRouterConfigStructOutput = (output: RouterConfigStructOutput): RouterConfig => {\n return {\n admin: output.admin,\n defaultPriceOracleContract: output.default_price_oracle_contract,\n defaultProtocolFeeRecipient: output.default_protocol_fee_recipient,\n defaultProtocolFee: output.default_protocol_fee,\n defaultLpFee: output.default_lp_fee,\n };\n};\n\n/**\n * Parses a raw swap simulation result from the Sui blockchain into a structured SimulateSwapResult object.\n *\n * This function transforms the raw swap simulation data returned by the Sui router contract\n * into a standardized format. It processes fee information and output amounts from the\n * simulation to provide a comprehensive view of the expected swap outcome.\n *\n * @param output - The raw swap simulation result from the Sui contract containing:\n * - amount_out: The expected amount of output tokens\n * - protocol_fee: The protocol fee amount in output tokens\n * - lp_fee: The liquidity provider fee amount in output tokens\n * - dynamic_fee_pct: Dynamic fee percentage\n * @param poolAddress - The Sui object ID of the pool that would handle this swap\n * @param assetOut - The type/symbol of the output asset (e.g., \"0x2::sui::SUI\")\n *\n * @returns A parsed SimulateSwapResult object containing:\n * - poolAddress: The Sui object ID of the pool handling the swap\n * - amountOut: The expected amount of output tokens (as string)\n * - assetOut: The type of the output asset\n * - protocolFee: The protocol fee amount (as string)\n * - lpFee: The liquidity provider fee amount (as string)\n * - dynamicFeePercentage: Dynamic fee percentage (as string)\n * - totalFees: The sum of protocolFee and lpFee (dynamic fee is distributed between both)\n *\n * @example\n * ```typescript\n * const simulationResult = {\n * amount_out: \"1950000000\",\n * protocol_fee: \"5850000\",\n * lp_fee: \"3900000\",\n * dynamic_fee_pct: \"0.001\"\n * };\n *\n * const result = parseSwapSimulationResultStructOutput(\n * simulationResult,\n * \"0x1234abcd...\",\n * \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\"\n * );\n *\n * console.log(result.poolAddress); // \"0x1234abcd...\"\n * console.log(result.amountOut); // \"1950000000\"\n * console.log(result.assetOut); // \"0x5d4b30...::coin::COIN\"\n * console.log(result.protocolFee); // \"5850000\"\n * console.log(result.lpFee); // \"3900000\"\n * console.log(result.dynamicFeePercentage); // Dynamic fee percentage\n * console.log(result.totalFees); // Sum of protocolFee and lpFee\n * ```\n */\nexport const parseSwapSimulationResultStructOutput = (\n output: SwapSimulationResultStructOutput,\n poolAddress: string,\n assetOut: string\n): SimulateSwapResult => {\n return {\n poolAddress,\n amountOut: output.base_out,\n assetOut,\n protocolFee: output.protocol_fee,\n lpFee: output.lp_fee,\n dynamicFeePercentage: BigNumber(output.dynamic_fee_pct).div(BASIS_POINTS).toFixed(),\n totalFees: output.swap_fee,\n };\n};\n","import type { Pool } from '@bolt-liquidity-hq/core';\nimport { normalizeStructTag } from '@mysten/sui/utils';\n\nimport type { RouterPool } from '../../../types';\n\nexport class RouterClient {\n constructor(public pools: Pool[]) {}\n\n getPool(\n denomIn: string,\n denomOut: string,\n swapType: 'buy' | 'sell' = 'buy'\n ): RouterPool | undefined {\n const normalizedDenomIn = normalizeStructTag(denomIn);\n const normalizedDenomOut = normalizeStructTag(denomOut);\n\n if (swapType === 'sell') {\n // Search by inverse pair\n const inversePairPool: Pool | undefined = this.pools.find(\n (item) =>\n item.baseDenom === normalizedDenomIn && item.quoteDenoms.includes(normalizedDenomOut)\n );\n\n if (inversePairPool) {\n return {\n ...inversePairPool,\n isInverse: true,\n };\n }\n }\n\n // Search by pair\n const directPairPool: Pool | undefined = this.pools.find(\n (item) =>\n item.baseDenom === normalizedDenomOut && item.quoteDenoms.includes(normalizedDenomIn)\n );\n\n if (directPairPool) {\n return {\n ...directPairPool,\n isInverse: false,\n };\n }\n\n if (swapType === 'buy') {\n // Search by inverse pair\n const inversePairPool: Pool | undefined = this.pools.find(\n (item) =>\n item.baseDenom === normalizedDenomIn && item.quoteDenoms.includes(normalizedDenomOut)\n );\n\n if (inversePairPool) {\n return {\n ...inversePairPool,\n isInverse: true,\n };\n }\n }\n\n return;\n }\n\n getPools(): Pool[] {\n return this.pools;\n }\n}\n","import { NotFoundError, type SimulateSwapResult } from '@bolt-liquidity-hq/core';\nimport { bcs } from '@mysten/bcs';\nimport { SUI_CLOCK_OBJECT_ID } from '@mysten/sui/utils';\n\nimport type { BoltSuiClient } from '../client';\nimport { POOL_MODULE } from '../constants';\nimport { parseDevInspectResult, queryDevInspect } from '../helpers';\nimport { parseSwapSimulationResultStructOutput } from './parsers';\nimport { type SuiSwapSimulateParams, SwapSimulationResultStruct } from '../../types';\n\n/**\n * Simulates a swap operation on the Sui blockchain to calculate expected output without executing.\n *\n * This function performs a dry run simulation of swapping an exact amount of input asset\n * for a desired output asset on the Bolt protocol. It automatically determines the correct\n * swap direction (buy or sell) based on the pool configuration and uses Sui's devInspect\n * capability to simulate the transaction without state changes.\n *\n * @param client - The BoltSuiClient instance for blockchain interaction\n * @param params - The swap simulation parameters\n * @param params.assetIn - The type of the input asset to swap from (e.g., \"0x2::sui::SUI\")\n * @param params.amountIn - The exact amount of input asset to simulate swapping (in minimal denomination)\n * @param params.assetOut - The type of the desired output asset (e.g., \"0x5d4b...::coin::COIN\")\n * @param params.swapType - Optional swap type (default is 'buy')\n * 'buy' - Buy the assetOut from a pool of assetOut, paying with assetIn\n * 'sell' - Sell the assetIn to a pool of assetIn, receiving assetOut\n *\n * @returns A promise that resolves to a SimulateSwapResult containing:\n * - poolAddress: The Sui object ID of the pool handling this swap\n * - amountOut: The expected amount of output asset to be received\n * - assetOut: The type of the output asset\n * - protocolFee: The protocol fee amount that would be charged\n * - lpFee: The liquidity provider fee amount that would be charged\n * - dynamicFeePercentage: Dynamic fee percentage\n * - totalFees: The sum of all fees\n *\n * @throws {NotFoundError} When no pool exists for the specified asset pair\n * @throws Will throw if the devInspect simulation fails or returns invalid data\n */\nexport const simulateSwap = async (\n client: BoltSuiClient,\n { assetIn, amountIn, assetOut, swapType }: SuiSwapSimulateParams\n): Promise<SimulateSwapResult> => {\n const pool = client.routerClient.getPool(assetIn, assetOut, swapType);\n\n if (!pool) {\n throw new NotFoundError('Pool', `Didn't find a pool to swap ${assetIn} for ${assetOut}`);\n }\n\n const FUNCTION_NAME = pool.isInverse ? 'simulate_sell_swap' : 'simulate_buy_swap';\n\n const response = await queryDevInspect(\n client.suiClient,\n [client.packageId, POOL_MODULE, FUNCTION_NAME],\n [pool.poolAddress, client.contracts.oracle, SUI_CLOCK_OBJECT_ID, bcs.u64().serialize(amountIn)],\n [pool.isInverse ? assetIn : assetOut, pool.isInverse ? assetOut : assetIn]\n );\n\n const output = parseDevInspectResult(response, SwapSimulationResultStruct);\n\n return parseSwapSimulationResultStructOutput(output, pool.poolAddress, assetOut);\n};\n","import type { SwapResult } from '@bolt-liquidity-hq/core';\nimport type { SuiTransactionBlockResponse } from '@mysten/sui/client';\nimport type { Signer } from '@mysten/sui/cryptography';\n\nimport type { BoltSuiClient } from '../client';\nimport { signAndExecuteTx, buildSwapTxArgs } from '../helpers';\nimport type { SuiSwapParams, WalletSigner } from '../../types';\n\n/**\n * Executes a token swap transaction on the Bolt protocol through the Sui Move router module.\n *\n * This function performs a \"swap exact in\" operation, where the user specifies exactly\n * how much of the input coin they want to swap, and receives a variable amount of the\n * output coin based on current liquidity pool conditions. The function leverages the\n * buildSwapTxArgs helper to prepare the transaction, then executes it on-chain.\n *\n * @param client - The BoltSuiClient instance containing configuration and contracts\n * @param swapParams - The swap configuration parameters\n * @param swapParams.assetIn - The fully qualified type of the input coin being sold\n * (e.g., \"0x2::sui::SUI\", \"0x...::usdc::USDC\")\n * @param swapParams.amountIn - The exact amount of input coin to swap (as string, in base units).\n * For example, \"1000000000\" for 1 SUI (9 decimals)\n * @param swapParams.assetOut - The fully qualified type of the output coin being bought\n * (e.g., \"0x2::sui::SUI\", \"0x...::usdc::USDC\")\n * @param swapParams.minimumAmountOut - Optional minimum acceptable amount of output coin.\n * Transaction will fail if the actual output would be less.\n * Protects against excessive slippage\n * @param swapParams.receiver - Optional recipient address for the swapped coins.\n * If not provided, coins are sent to the signer's address\n * @param swapParams.swapType - Optional swap type (default is 'buy')\n * 'buy' - Buy the assetOut from a pool of assetOut, paying with assetIn\n * 'sell' - Sell the assetIn to a pool of assetIn, receiving assetOut\n * @param signer - Optional Sui signer (e.g., Ed25519Keypair) that will authorize the swap transaction.\n * If not provided, uses the client's cached signer. Must have sufficient balance\n * of the input coin type and SUI for gas fees\n *\n * @returns A promise that resolves to a SwapResult containing:\n * - txOutput: The complete SuiTransactionBlockResponse with transaction details\n * - txHash: The transaction digest for tracking on Sui explorers\n * - amountOut: The actual amount of output coin received (extracted from events, or \"0\" if not found)\n * - assetOut: The output coin type (from the swap parameters)\n *\n * @throws {NotFoundError} When no pool exists for the specified asset pair\n * @throws {TransactionFailedError} When:\n * - The transaction fails on-chain (insufficient balance, slippage, etc.)\n * - The minimum output amount constraint is not satisfied\n * @throws {UnexpectedError} When:\n * - Network connectivity issues occur\n * - Invalid coin types are provided\n * - Coin selection/preparation fails\n * @throws {MissingParameterError} When no signer is available\n */\nexport const swapExactIn = async (\n client: BoltSuiClient,\n swapParams: SuiSwapParams,\n signer?: Signer | WalletSigner\n): Promise<SwapResult<SuiTransactionBlockResponse>> => {\n const swapArgs = await buildSwapTxArgs(client, swapParams, signer);\n\n const txOutput = await signAndExecuteTx(\n client.suiClient,\n swapArgs.signer,\n swapArgs.target,\n swapArgs.args,\n swapArgs.typeArguments,\n swapArgs.tx,\n { showEffects: true, showEvents: true, showBalanceChanges: true }\n );\n\n return {\n txOutput,\n txHash: txOutput.digest,\n amountOut:\n (txOutput.events?.at(0)?.parsedJson as Record<string, string> | undefined)?.['amount_out'] ??\n '0',\n assetOut: swapParams.assetOut,\n };\n};\n"],"mappings":"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","names":["import_core","import_utils","import_utils","import_utils","import_core","import_utils","import_core","import_core","import_bcs","import_transactions","import_utils","import_core","import_bignumber","import_utils","import_bcs","import_bcs","import_bcs","import_bcs","import_utils","import_core","import_utils","import_bignumber","import_core","import_core","import_bignumber","import_core","import_core","import_core","import_core","import_core","import_bignumber","import_utils","import_core","import_bcs","import_utils","axios"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/lib/client.ts","../src/config/common.ts","../src/config/mainnet.ts","../src/config/testnet.ts","../src/lib/constants/defaults.ts","../src/lib/constants/sui-objects.ts","../src/lib/helpers/bcs-parse.ts","../src/lib/helpers/coin-manager.ts","../src/lib/helpers/queries.ts","../src/lib/helpers/transactions.ts","../src/lib/oracle/parsers.ts","../src/types/bcs.ts","../src/types/oracle.ts","../src/types/router.ts","../src/types/pool.ts","../src/lib/oracle/get-asset-pairs.ts","../src/lib/oracle/get-assets.ts","../src/lib/oracle/get-oracle-config.ts","../src/lib/oracle/get-price.ts","../src/lib/oracle/get-prices.ts","../src/lib/router/estimate-swap-exact-in-gas-fees.ts","../src/lib/settlement/get-pool-base-liquidity.ts","../src/lib/settlement/parsers.ts","../src/lib/settlement/get-pool-config.ts","../src/lib/settlement/get-pool-config-by-denom.ts","../src/lib/router/get-all-base-liquidity.ts","../src/lib/router/get-all-quotes-for-user.ts","../src/lib/router/get-pool-by-denom.ts","../src/lib/router/get-all-pools.ts","../src/lib/router/get-router-config.ts","../src/lib/router/parsers.ts","../src/lib/router/router-client/RouterClient.ts","../src/lib/router/simulate-swap.ts","../src/lib/router/swap-exact-in.ts"],"sourcesContent":["export { BoltSuiClient } from './lib/client';\n\nexport * from './types';\n","import type {\n Address,\n BaseLiquidityDetails,\n Coin,\n InvertiblePrice,\n OracleAssetPair,\n OracleConfig,\n PoolConfig,\n Pool,\n Price,\n RouterConfig,\n SwapParams,\n SwapResult,\n Contracts,\n AssetsConfig,\n Asset,\n SimulateSwapResult,\n} from '@bolt-liquidity-hq/core';\nimport { BaseClient, MissingParameterError } from '@bolt-liquidity-hq/core';\nimport { SuiClient, type SuiTransactionBlockResponse } from '@mysten/sui/client';\nimport type { Signer } from '@mysten/sui/cryptography';\nimport { normalizeStructTag } from '@mysten/sui/utils';\nimport axios from 'axios';\n\nimport {\n MainnetAssets,\n MainnetChainConfig,\n MainnetContracts,\n MainnetPackageId,\n MainnetPoolGlobalConfigId,\n TestnetAssets,\n TestnetChainConfig,\n TestnetContracts,\n TestnetPoolGlobalConfigId,\n TestnetPackageId,\n MainnetNativeTokenDenom,\n TestnetNativeTokenDenom,\n MainnetPools,\n TestnetConfigUrl,\n} from '../config';\nimport { getAssets, getAssetPairs, getOracleConfig, getPrice, getPrices } from './oracle';\nimport {\n RouterClient,\n estimateSwapExactInGasFees,\n getAllBaseLiquidity,\n getAllPools,\n getAllQuotesForUser,\n getPoolByDenom,\n getRouterConfig,\n simulateSwap,\n swapExactIn,\n} from './router';\nimport { getPoolBaseLiquidity, getPoolConfig, getPoolConfigByDenom } from './settlement';\nimport type {\n SuiChainConfig,\n SuiClientConfig,\n SuiSwapParams,\n SuiSwapSimulateParams,\n WalletSigner,\n} from '../types';\n\n/**\n * Client implementation for interacting with the Bolt Liquidity Outpost on Sui blockchain.\n *\n * This class extends the abstract {@link BaseClient} to provide Sui-specific functionality\n * for querying and executing transactions on Bolt Protocol's oracle and router smart contracts.\n * It uses SuiTransactionBlockResponse as the transaction output type, providing detailed transaction execution information.\n *\n * @extends {BaseClient<Signer, SuiTransactionBlockResponse>}\n *\n * @group Bolt API Clients\n *\n * @example\n * ```typescript\n * // Create a client for Sui mainnet\n * const client = new BoltSuiClient();\n *\n * // Query oracle prices\n * const price = await client.getPrice(\"0x2::sui::SUI\", \"0xusdcAddress...\");\n *\n * // Execute a swap (requires signer)\n * const signer = // ... get signer from wallet\n * const result = await client.swap({\n * assetIn: \"0x2::sui::SUI\",\n * amountIn: \"1000000000\", // 1 SUI (9 decimals)\n * assetOut: \"0xusdcAddress...\"\n * }, signer);\n * ```\n */\nexport class BoltSuiClient extends BaseClient<Signer, SuiTransactionBlockResponse> {\n /**\n * The Sui-specific chain configuration including RPC endpoint\n */\n public override chainConfig: SuiChainConfig;\n\n /**\n * Package Id for the deployed Bolt contracts on Sui\n */\n public packageId: string;\n\n /**\n * Object Id for the GlobalConfig of the deployed Pool contracts\n */\n public poolGlobalConfigId: string;\n\n /**\n * Cached instance of the Signer for transaction execution\n */\n public signer?: Signer | WalletSigner;\n\n /**\n * Instance of the Sui client to interact with the blockchain\n */\n public suiClient: SuiClient;\n\n /**\n * URL for fetching testnet configuration dynamically.\n * Used to load package IDs, oracle addresses, and asset configurations for testnet environments.\n * @private\n */\n private configFileUrl?: string;\n\n /**\n * Router client instance for managing pool configurations and routing calculations.\n * Handles pool discovery and optimal path finding for swaps.\n */\n public routerClient: RouterClient;\n\n /**\n * Creates a new instance of the BoltSuiClient.\n *\n * The client automatically configures itself based on the specified environment,\n * loading the appropriate contract addresses, chain configuration, native token denomination,\n * and assets from configuration files. For testnet environments, the client can dynamically\n * fetch configuration from a remote URL.\n *\n * @param config - (Optional) Configuration for the client\n * @param config.environment - (Optional) The deployment environment ('mainnet' or 'testnet'). Defaults to 'mainnet'\n * @param config.customOverride - (Optional) Custom overrides for chain configuration, contracts, native token, and assets\n * @param config.customOverride.chainConfig - (Optional) Override chain configuration\n * @param config.customOverride.chainConfig.id - (Optional) Custom chain ID\n * @param config.customOverride.chainConfig.name - (Optional) Custom chain name\n * @param config.customOverride.chainConfig.rpcEndpoint - (Optional) Custom RPC endpoint URL\n * @param config.customOverride.packageId - (Optional) Custom package ID for Bolt contracts\n * @param config.customOverride.poolGlobalConfigId - (Optional) Custom Object ID for the Pool contracts' Global Config\n * @param config.customOverride.contracts - (Optional) Override contract addresses\n * @param config.customOverride.contracts.oracle - (Optional) Custom oracle contract address\n * @param config.customOverride.contracts.router - (Optional) Custom router contract address\n * @param config.customOverride.nativeTokenDenom - (Optional) Custom native token denomination (e.g., \"SUI\")\n * @param config.customOverride.assetsConfig - (Optional) Custom asset configurations indexed by denom\n * @param config.signer - (Optional) Pre-existing Signer for transaction signing\n * @param config.suiClient - (Optional) Pre-existing SuiClient to use for blockchain queries\n *\n * @throws {InvalidObjectError} Thrown when required configuration fields are missing\n *\n * @example\n * ```typescript\n * // Use default configuration (Sui mainnet)\n * const client = new BoltSuiClient();\n *\n * // Use testnet configuration (will fetch config dynamically)\n * const testnetClient = new BoltSuiClient({\n * environment: 'testnet'\n * });\n *\n * // Use custom chain configuration\n * const customClient = new BoltSuiClient({\n * customOverride: {\n * chainConfig: {\n * id: 'sui-custom',\n * name: 'Sui Custom',\n * rpcEndpoint: 'https://custom-rpc.example.com'\n * },\n * packageId: '0xcustom_package_id...',\n * poolGlobalConfigId: '0xcustom_global_config_id...',\n * contracts: {\n * oracle: '0xcustom_oracle...',\n * router: '0xcustom_router...'\n * },\n * nativeTokenDenom: 'SUI',\n * assetsConfig: {\n * '0x2::sui::SUI': {\n * symbol: 'SUI',\n * name: 'Sui',\n * chainId: 'sui-custom',\n * denom: '0x2::sui::SUI',\n * decimals: 9,\n * logo: 'https://example.com/sui.png',\n * coingeckoId: 'sui'\n * }\n * }\n * }\n * });\n *\n * // Use pre-existing Sui client and signer\n * const clientWithCustomClient = new BoltSuiClient({\n * suiClient: mySuiClient,\n * signer: mySigner\n * });\n * ```\n */\n constructor(config?: SuiClientConfig) {\n const { environment = 'mainnet', customOverride, signer, suiClient } = config ?? {};\n\n const isEnvironmentMainnet = environment === 'mainnet';\n const defaultChainConfig: SuiChainConfig = isEnvironmentMainnet\n ? MainnetChainConfig\n : TestnetChainConfig;\n const defaultContracts: Contracts = isEnvironmentMainnet ? MainnetContracts : TestnetContracts;\n const defaultPackageId = isEnvironmentMainnet ? MainnetPackageId : TestnetPackageId;\n const defaultPoolGlobalConfigId = isEnvironmentMainnet\n ? MainnetPoolGlobalConfigId\n : TestnetPoolGlobalConfigId;\n const defaultNativeTokenDenom = isEnvironmentMainnet\n ? MainnetNativeTokenDenom\n : TestnetNativeTokenDenom;\n const assetsConfig: AssetsConfig = isEnvironmentMainnet ? MainnetAssets : TestnetAssets;\n const pools = isEnvironmentMainnet ? MainnetPools : [];\n\n // Apply overrides\n const chainConfig: SuiChainConfig = {\n id: customOverride?.chainConfig?.id ?? defaultChainConfig.id,\n name: customOverride?.chainConfig?.name ?? defaultChainConfig.name,\n rpcEndpoint: customOverride?.chainConfig?.rpcEndpoint ?? defaultChainConfig.rpcEndpoint,\n };\n const packageId = customOverride?.packageId ?? defaultPackageId;\n const poolGlobalConfigId = customOverride?.poolGlobalConfigId ?? defaultPoolGlobalConfigId;\n const contracts: Contracts = {\n oracle: customOverride?.contracts?.oracle ?? defaultContracts.oracle,\n router: customOverride?.contracts?.router ?? defaultContracts.router,\n };\n const nativeTokenDenom = customOverride?.nativeTokenDenom ?? defaultNativeTokenDenom;\n\n for (const item of Object.values(customOverride?.assetsConfig ?? {})) {\n assetsConfig[item.denom] = item;\n }\n\n super({\n customOverride: {\n chainConfig,\n contracts,\n nativeTokenDenom,\n assetsConfig,\n },\n });\n\n this.chainConfig = chainConfig;\n this.packageId = packageId;\n this.poolGlobalConfigId = poolGlobalConfigId;\n this.signer = signer;\n this.suiClient = suiClient ?? new SuiClient({ url: chainConfig.rpcEndpoint });\n this.routerClient = new RouterClient(pools);\n this.configFileUrl = isEnvironmentMainnet ? undefined : TestnetConfigUrl;\n }\n\n /**\n * Gets or sets the signer for transaction execution.\n *\n * This method manages the signer instance used for signing transactions.\n * A signer must be provided either when creating the client, on first call,\n * or to replace the existing signer.\n *\n * @param newSigner - Optional new signer to replace the existing one\n *\n * @returns The current signer instance\n *\n * @throws {MissingParameterError} Thrown when no signer is available and none is provided\n *\n * @example\n * ```typescript\n * // Get the current signer (throws if none exists)\n * const currentSigner = client.getSigner();\n *\n * // Set a new signer\n * const newSigner = // ... obtain signer from wallet\n * const signer = client.getSigner(newSigner);\n * ```\n */\n public getSigner(newSigner?: Signer | WalletSigner): Signer | WalletSigner {\n this.signer = newSigner ?? this.signer;\n\n if (!this.signer) {\n throw new MissingParameterError('signer');\n }\n\n return this.signer;\n }\n\n // The following methods inherit their documentation from BaseClient\n // Only add documentation here if you need to override or add implementation-specific details\n\n /** @inheritdoc */\n public async getOracleConfig(): Promise<OracleConfig> {\n await this.loadConfigFromUrl();\n return await getOracleConfig(this);\n }\n\n /** @inheritdoc */\n async getAllOracleAssetPairs(): Promise<OracleAssetPair[]> {\n await this.loadConfigFromUrl();\n return await getAssetPairs(this);\n }\n\n /** @inheritdoc */\n async getPrice(baseDenom: string, quoteDenom: string): Promise<InvertiblePrice> {\n await this.loadConfigFromUrl();\n return await getPrice(this, baseDenom, quoteDenom);\n }\n\n /** @inheritdoc */\n async getAllPrices(): Promise<Price[]> {\n await this.loadConfigFromUrl();\n return await getPrices(this);\n }\n\n /** @inheritdoc */\n async getRouterConfig(): Promise<RouterConfig> {\n await this.loadConfigFromUrl();\n return await getRouterConfig(this);\n }\n\n /** @inheritdoc */\n async getAllBaseAssetsLiquidity(): Promise<Record<Address, BaseLiquidityDetails>> {\n await this.loadConfigFromUrl();\n return await getAllBaseLiquidity(this);\n }\n\n /** @inheritdoc */\n async getAllQuotesByUser(address: Address): Promise<Record<Address, Coin[]>> {\n await this.loadConfigFromUrl();\n return await getAllQuotesForUser(this, address);\n }\n\n /**\n * @inheritdoc\n *\n * @remarks\n * In the Sui implementation, both `baseDenom` and `quoteDenom` parameters are required.\n * The Sui architecture uses both asset types to uniquely identify pools for specific\n * trading pairs.\n *\n * @throws Will throw an error if no pool exists for the specified base/quote asset pair\n */\n async getPoolByDenom(baseDenom: string, quoteDenom: string): Promise<Pool> {\n await this.loadConfigFromUrl();\n return await getPoolByDenom(this, baseDenom, quoteDenom);\n }\n\n /** @inheritdoc */\n async getAllPools(): Promise<Pool[]> {\n await this.loadConfigFromUrl();\n return await getAllPools(this);\n }\n\n /** @inheritdoc */\n async getPoolConfig(poolContractAddress: string): Promise<PoolConfig> {\n await this.loadConfigFromUrl();\n return await getPoolConfig(this, poolContractAddress);\n }\n\n /**\n * @inheritdoc\n *\n * @remarks\n * In the Sui implementation, both `baseDenom` and `quoteDenom` parameters are required.\n * The Sui architecture uses both asset types to uniquely identify pools for specific\n * trading pairs.\n *\n * @throws Will throw an error if no pool exists for the specified base/quote asset pair\n */\n async getPoolConfigByDenom(baseDenom: string, quoteDenom: string): Promise<PoolConfig> {\n await this.loadConfigFromUrl();\n return await getPoolConfigByDenom(this, baseDenom, quoteDenom);\n }\n\n /** @inheritdoc */\n async getPoolBaseLiquidity(poolContractAddress: string): Promise<BaseLiquidityDetails> {\n await this.loadConfigFromUrl();\n return await getPoolBaseLiquidity(this, poolContractAddress);\n }\n\n /** @inheritdoc */\n async getAssets(): Promise<Asset[]> {\n await this.loadConfigFromUrl();\n return await getAssets(this);\n }\n\n /**\n * @inheritdoc\n *\n * @example\n * ```typescript\n * // Get signer from wallet (e.g., Sui Wallet, Suiet, etc.)\n * const signer = // ... obtain signer from wallet\n *\n * // Execute swap: 1 SUI for USDC\n * const result = await client.swap({\n * assetIn: \"0x2::sui::SUI\",\n * amountIn: \"1000000000\", // 1 SUI (9 decimals)\n * assetOut: \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\", // USDC address\n * minimumAmountOut: \"1950000\", // Minimum 1.95 USDC expected (6 decimals)\n * receiver: \"0x...\" // Optional custom receiver address\n * swapType: 'buy' | 'sell' // Optional swap type (default is 'buy')\n * }, signer);\n *\n * console.log(`Swap successful!`);\n * console.log(`Transaction digest: ${result.txHash}`);\n * console.log(`Received: ${result.amountOut} ${result.assetOut}`);\n * console.log(`Gas cost: ${result.txOutput.effects.gasUsed.computationCost}`);\n * console.log(`Status: ${result.txOutput.effects.status.status}`);\n * ```\n *\n * @remarks\n * This implementation returns a SuiTransactionBlockResponse as the transaction output,\n * which includes details like gas costs, transaction effects, object changes, and events.\n */\n async swap(\n params: SuiSwapParams,\n signer?: Signer | WalletSigner\n ): Promise<SwapResult<SuiTransactionBlockResponse>> {\n await this.loadConfigFromUrl();\n return await swapExactIn(this, params, signer);\n }\n\n /**\n * @inheritdoc\n *\n * @example\n * ```typescript\n * // Get signer from wallet (e.g., Sui Wallet, Suiet, etc.)\n * const signer = // ... obtain signer from wallet\n *\n * // Estimate gas for swapping 1 SUI to USDC\n * const gasEstimate = await client.estimateSwapGasFees({\n * assetIn: \"0x2::sui::SUI\",\n * amountIn: \"1000000000\", // 1 SUI (9 decimals)\n * assetOut: \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\", // USDC\n * minimumAmountOut: \"1950000\" // Min 1.95 USDC (6 decimals)\n * }, signer, 1.3); // 30% safety margin\n *\n * if (gasEstimate) {\n * console.log(`Estimated gas: ${gasEstimate.amount} ${gasEstimate.denom}`);\n * }\n * ```\n *\n * @remarks\n * - For Sui, gas is always paid in SUI tokens\n * - The returned amount is in MIST (smallest unit, 9 decimals)\n * - Gas estimation uses Sui's dry run transaction capability\n * - The gasAdjustment parameter helps account for variations in actual execution\n * - Sui's gas model includes computation, storage, and storage rebates\n */\n async estimateSwapGasFees(\n params: SwapParams,\n signer?: Signer | WalletSigner,\n gasAdjustment?: number\n ): Promise<Coin | undefined> {\n await this.loadConfigFromUrl();\n return await estimateSwapExactInGasFees(this, params, signer, gasAdjustment);\n }\n\n /** @inheritdoc */\n async simulateSwap(params: SuiSwapSimulateParams): Promise<SimulateSwapResult> {\n return await simulateSwap(this, params);\n }\n\n /**\n * Loads configuration from a remote URL for testnet environments.\n *\n * This method fetches and applies dynamic configuration including:\n * - Package ID for Bolt contracts\n * - Oracle contract address\n * - Pool global configuration ID\n * - Asset mappings and metadata\n * - Pool configurations\n *\n * The method is called automatically before API operations when a config URL is set.\n * After successful loading, the config URL is cleared to prevent redundant fetches.\n *\n * @private\n * @remarks\n * - Only executes if `configFileUrl` is set (typically for testnet)\n * - Updates testnet-specific asset denoms with their actual deployed addresses\n * - Populates the router client's pool configurations\n * - Normalizes struct tags for consistency\n */\n private async loadConfigFromUrl() {\n if (!this.configFileUrl) {\n return;\n }\n\n const response = await axios.get(this.configFileUrl);\n const { package_id, oracle_id, global_config_id, assets, pools } =\n (response.data as {\n package_id: string;\n oracle_id: string;\n global_config_id: string;\n assets: Record<string, string>;\n pools: Array<{ base: string; pool_object_id: string }>;\n }) ?? {};\n\n if (!this.packageId && package_id) {\n this.packageId = package_id;\n }\n\n if (!this.contracts.oracle.trim() && oracle_id) {\n this.contracts.oracle = oracle_id;\n }\n\n if (!this.poolGlobalConfigId && global_config_id) {\n this.poolGlobalConfigId = global_config_id;\n }\n\n for (const item of Object.values(assets)) {\n for (const existingConfig of Object.values(this.assetsConfig)) {\n if (item.endsWith(existingConfig.denom)) {\n this.assetsConfig[item] = {\n ...existingConfig,\n denom: item,\n };\n delete this.assetsConfig[existingConfig.denom];\n break;\n }\n }\n }\n\n if (this.routerClient.pools.length === 0) {\n for (const item of pools) {\n this.routerClient.pools.push({\n poolAddress: item.pool_object_id,\n baseDenom: normalizeStructTag(item.base),\n quoteDenoms: Object.values(assets)\n .map((auxAsset) => normalizeStructTag(auxAsset))\n .filter((auxAsset) => auxAsset !== normalizeStructTag(item.base)),\n });\n }\n }\n\n this.configFileUrl = undefined;\n }\n}\n","import { normalizeStructTag, SUI_TYPE_ARG } from '@mysten/sui/utils';\n\nexport const SUI_TOKEN_DENOM = normalizeStructTag(SUI_TYPE_ARG);\n","import type { AssetsConfig, Contracts, Pool } from '@bolt-liquidity-hq/core';\nimport { SUI_DECIMALS } from '@mysten/sui/utils';\n\nimport { SUI_TOKEN_DENOM } from './common';\nimport type { SuiChainConfig } from '../types';\n\nexport const MainnetChainConfig: SuiChainConfig = {\n name: 'Sui',\n id: '101',\n rpcEndpoint: 'https://fullnode.mainnet.sui.io:443',\n};\n\nexport const MainnetContracts: Contracts = {\n oracle: '0xfa3975b98f3d0e3df18ed88ae6e69db31836b3f4212df02fae144b1e5a89ca8e',\n router: ' ',\n};\n\nexport const MainnetPackageId: string =\n '0x71a61b841cc90a74607e99084e47818a7d1424649f4047ad375d9c2a4111e658';\n\nexport const MainnetPoolGlobalConfigId: string =\n '0x7bcd5035a991f42fa84c5a42216b5638cb3f1a8c4f065063093b0a3d5f165d63';\n\nexport const MainnetNativeTokenDenom: string = SUI_TOKEN_DENOM;\n\nexport const MainnetAssets: AssetsConfig = {\n [SUI_TOKEN_DENOM]: {\n symbol: 'SUI',\n name: 'Sui',\n chainId: MainnetChainConfig.id,\n denom: SUI_TOKEN_DENOM,\n decimals: SUI_DECIMALS,\n logo: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/sui/info/logo.png',\n coingeckoId: 'sui',\n },\n '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC': {\n symbol: 'USDC',\n name: 'Circle USDC',\n chainId: MainnetChainConfig.id,\n denom: '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC',\n decimals: 6,\n logo: 'https://raw.githubusercontent.com/cosmos/chain-registry/refs/heads/master/_non-cosmos/ethereum/images/usdc.png',\n coingeckoId: 'usd-coin',\n },\n '0x356a26eb9e012a68958082340d4c4116e7f55615cf27affcff209cf0ae544f59::wal::WAL': {\n symbol: 'WAL',\n name: 'Walrus',\n chainId: MainnetChainConfig.id,\n denom: '0x356a26eb9e012a68958082340d4c4116e7f55615cf27affcff209cf0ae544f59::wal::WAL',\n decimals: 9,\n logo: 'https://app.lotusfinance.io/images/coins/wal-icon.svg',\n coingeckoId: 'walrus-2',\n },\n '0x375f70cf2ae4c00bf37117d0c85a2c71545e6ee05c4a5c7d282cd66a4504b068::usdt::USDT': {\n symbol: 'suiUSDT',\n name: 'Tether by Sui Bridge',\n chainId: MainnetChainConfig.id,\n denom: '0x375f70cf2ae4c00bf37117d0c85a2c71545e6ee05c4a5c7d282cd66a4504b068::usdt::USDT',\n decimals: 6,\n logo: 'https://raw.githubusercontent.com/cosmos/chain-registry/refs/heads/master/_non-cosmos/ethereum/images/usdt.svg',\n coingeckoId: 'tether',\n },\n};\n\nexport const MainnetPools: Pool[] = [\n {\n poolAddress: '0x21167b2e981e2c0a693afcfe882a3a827d663118e19afcb92e45bfe43fe56278',\n baseDenom: '0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI',\n quoteDenoms: ['0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC'],\n },\n {\n poolAddress: '0x34fcaa553f1185e1c3a05de37b6a4d10c39535d19f9c8581eeae826434602b58',\n baseDenom: '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC',\n quoteDenoms: ['0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI'],\n },\n];\n","import type { AssetsConfig, Contracts } from '@bolt-liquidity-hq/core';\nimport { SUI_DECIMALS } from '@mysten/sui/utils';\n\nimport { SUI_TOKEN_DENOM } from './common';\nimport type { SuiChainConfig } from '../types';\n\nexport const TestnetConfigUrl = 'https://phi-labs-ltd.github.io/sui-outpost/testnet.json';\n\nexport const TestnetChainConfig: SuiChainConfig = {\n name: 'Sui Testnet',\n id: '103',\n rpcEndpoint: 'https://fullnode.testnet.sui.io:443',\n};\n\nexport const TestnetContracts: Contracts = {\n oracle: ' ',\n router: ' ',\n};\n\nexport const TestnetPackageId: string = '';\n\nexport const TestnetPoolGlobalConfigId: string = '';\n\nexport const TestnetNativeTokenDenom: string = SUI_TOKEN_DENOM;\n\nexport const TestnetAssets: AssetsConfig = {\n [SUI_TOKEN_DENOM]: {\n symbol: 'SUI',\n name: 'Sui',\n chainId: TestnetChainConfig.id,\n denom: SUI_TOKEN_DENOM,\n decimals: SUI_DECIMALS,\n logo: 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/sui/info/logo.png',\n coingeckoId: 'sui',\n },\n '0xa1ec7fc00a6f40db9693ad1415d0c193ad3906494428cf252621037bd7117e29::usdc::USDC': {\n symbol: 'USDC',\n name: 'Circle USDC',\n chainId: TestnetChainConfig.id,\n denom: '0xa1ec7fc00a6f40db9693ad1415d0c193ad3906494428cf252621037bd7117e29::usdc::USDC',\n decimals: 6,\n logo: 'https://raw.githubusercontent.com/cosmos/chain-registry/refs/heads/master/_non-cosmos/ethereum/images/usdc.png',\n coingeckoId: 'usd-coin',\n },\n '::test_btc::TEST_BTC': {\n symbol: 'TEST_BTC',\n name: 'Test BTC',\n chainId: TestnetChainConfig.id,\n denom: '::test_btc::TEST_BTC',\n decimals: 8,\n logo: 'https://raw.githubusercontent.com/cosmos/chain-registry/refs/heads/master/_non-cosmos/bitcoin/images/btc.svg',\n coingeckoId: 'bitcoin',\n },\n '::test_usdt::TEST_USDT': {\n symbol: 'TEST_USDT',\n name: 'Test USDT',\n chainId: TestnetChainConfig.id,\n denom: '::test_usdt::TEST_USDT',\n decimals: 6,\n logo: 'https://raw.githubusercontent.com/cosmos/chain-registry/refs/heads/master/_non-cosmos/ethereum/images/usdt.svg',\n coingeckoId: 'tether',\n },\n '::test_deep::TEST_DEEP': {\n symbol: 'TEST_DEEP',\n name: 'TEST_DEEP',\n chainId: TestnetChainConfig.id,\n denom: '::test_deep::TEST_DEEP',\n decimals: 6,\n logo: 'https://app.lotusfinance.io/images/coins/deepbook-icon.svg',\n coingeckoId: 'deep',\n },\n '::test_wal::TEST_WAL': {\n symbol: 'TEST_WAL',\n name: 'TEST_WAL',\n chainId: TestnetChainConfig.id,\n denom: '::test_wal::TEST_WAL',\n decimals: 9,\n logo: 'https://app.lotusfinance.io/images/coins/wal-icon.svg',\n coingeckoId: 'walrus-2',\n },\n};\n","export const BASIS_POINTS = 10000;\nexport const DEFAULT_PAGINATION_LIMIT = 50;\nexport const PRICE_PRECISION = 18;\n","export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000000000000000000000000000';\n\nexport const SUI_SYSTEM_CLOCK = '0x6';\n\nexport const PRICE_ORACLE_MODULE = 'price_oracle';\n\nexport const ROUTER_MODULE = 'router';\n\nexport const POOL_MODULE = 'pool';\n","import { InvalidObjectError, ParseError } from '@bolt-liquidity-hq/core';\nimport type { BcsType } from '@mysten/bcs';\nimport { bcs } from '@mysten/bcs';\nimport type { DevInspectResults } from '@mysten/sui/client';\n\nimport type { BcsParsed } from '../../types';\n\n/**\n * Extracts raw bytes from a DevInspectResults object at the specified indices.\n *\n * This utility function navigates the nested structure of Sui's DevInspectResults\n * to extract the raw byte array from a specific return value.\n *\n * @param result - The DevInspectResults object returned from a Sui devInspect call\n * @param resultIndex - The index of the result to extract from (defaults to 0)\n * @param returnValueIndex - The index of the return value within the result (defaults to 0)\n *\n * @returns The extracted bytes as a Uint8Array, or null if the specified indices don't exist\n *\n * @example\n * ```typescript\n * const result = await suiClient.devInspectTransactionBlock({...});\n * const bytes = extractBytes(result, 0, 0);\n * if (bytes) {\n * const parsedValue = bcs.u64().parse(bytes);\n * }\n * ```\n */\nexport const extractBytes = (\n result: DevInspectResults,\n resultIndex: number = 0,\n returnValueIndex: number = 0\n): Uint8Array | null => {\n const returnValues = result.results?.[resultIndex]?.returnValues;\n if (!returnValues || !returnValues[returnValueIndex]) {\n return null;\n }\n\n const [bytes] = returnValues[returnValueIndex];\n return new Uint8Array(bytes);\n};\n\n/**\n * A utility class providing static methods for parsing common BCS (Binary Canonical Serialization) types.\n *\n * BCS is the serialization format used by Sui for encoding Move types. This class\n * provides convenient wrappers around the @mysten/bcs library's parsing functions\n * for commonly used primitive and composite types.\n *\n * @example\n * ```typescript\n * // Parse a u64 value\n * const bytes = new Uint8Array([1, 0, 0, 0, 0, 0, 0, 0]);\n * const value = BcsCommonParser.parseU64(bytes); // \"1\"\n *\n * // Parse a vector of strings\n * const vectorBytes = // ... bytes from Sui\n * const strings = BcsCommonParser.parseVector(vectorBytes, bcs.string());\n *\n * // Parse an optional value\n * const optionBytes = // ... bytes from Sui\n * const maybeValue = BcsCommonParser.parseOption(optionBytes, bcs.u32());\n * ```\n */\nexport class BcsCommonParser {\n /**\n * Parses a BCS-encoded unsigned 8-bit integer.\n *\n * @param bytes - The BCS-encoded bytes to parse\n * @returns The parsed u8 value as a number (0-255)\n */\n static parseU8(bytes: Uint8Array): number {\n return bcs.u8().parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded unsigned 16-bit integer.\n *\n * @param bytes - The BCS-encoded bytes to parse\n * @returns The parsed u16 value as a number (0-65535)\n */\n static parseU16(bytes: Uint8Array): number {\n return bcs.u16().parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded unsigned 32-bit integer.\n *\n * @param bytes - The BCS-encoded bytes to parse\n * @returns The parsed u32 value as a number (0-4294967295)\n */\n static parseU32(bytes: Uint8Array): number {\n return bcs.u32().parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded unsigned 64-bit integer.\n *\n * @param bytes - The BCS-encoded bytes to parse\n * @returns The parsed u64 value as a string (to preserve precision)\n *\n * @remarks\n * Returns a string because JavaScript numbers cannot safely represent\n * all 64-bit integer values without loss of precision.\n */\n static parseU64(bytes: Uint8Array): string {\n return bcs.u64().parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded unsigned 128-bit integer.\n *\n * @param bytes - The BCS-encoded bytes to parse\n * @returns The parsed u128 value as a string\n */\n static parseU128(bytes: Uint8Array): string {\n return bcs.u128().parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded unsigned 256-bit integer.\n *\n * @param bytes - The BCS-encoded bytes to parse\n * @returns The parsed u256 value as a string\n */\n static parseU256(bytes: Uint8Array): string {\n return bcs.u256().parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded boolean value.\n *\n * @param bytes - The BCS-encoded bytes to parse\n * @returns The parsed boolean value\n */\n static parseBool(bytes: Uint8Array): boolean {\n return bcs.bool().parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded string.\n *\n * @param bytes - The BCS-encoded bytes to parse\n * @returns The parsed string value\n */\n static parseString(bytes: Uint8Array): string {\n return bcs.string().parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded vector (dynamic array) of elements.\n *\n * @template T - The type of elements in the vector\n * @param bytes - The BCS-encoded bytes to parse\n * @param elementParser - The BCS parser for individual vector elements\n * @returns An array of parsed elements\n *\n * @example\n * ```typescript\n * // Parse a vector of u64 values\n * const numbers = BcsCommonParser.parseVector(bytes, bcs.u64());\n *\n * // Parse a vector of custom structs\n * const customType = bcs.struct('MyStruct', {\n * id: bcs.u64(),\n * name: bcs.string()\n * });\n * const structs = BcsCommonParser.parseVector(bytes, customType);\n * ```\n */\n static parseVector<T>(bytes: Uint8Array, elementParser: BcsType<T>): T[] {\n return bcs.vector(elementParser).parse(bytes);\n }\n\n /**\n * Parses a BCS-encoded Option type (similar to Rust's Option or Move's Option).\n *\n * @template T - The type of the optional value\n * @param bytes - The BCS-encoded bytes to parse\n * @param elementParser - The BCS parser for the optional value if present\n * @returns The parsed value if Some, or null if None\n *\n * @example\n * ```typescript\n * // Parse an optional address\n * const maybeAddress = BcsCommonParser.parseOption(bytes, bcs.string());\n * if (maybeAddress) {\n * console.log(`Address: ${maybeAddress}`);\n * } else {\n * console.log('No address provided');\n * }\n * ```\n */\n static parseOption<T>(bytes: Uint8Array, elementParser: BcsType<T>): T | null {\n return bcs.option(elementParser).parse(bytes);\n }\n}\n\n/**\n * Parses a single return value from a DevInspectResults object using a specified BCS parser.\n *\n * This function combines byte extraction and BCS parsing into a single operation,\n * handling errors appropriately and providing detailed error context.\n *\n * @template T - The expected TypeScript type after parsing\n * @template Input - The input type for the BCS parser (usually the same as T)\n *\n * @param result - The DevInspectResults object from a Sui devInspect call\n * @param bcsType - The BCS parser to use for deserializing the bytes\n * @param resultIndex - The index of the result to parse (defaults to 0)\n * @param returnValueIndex - The index of the return value within the result (defaults to 0)\n *\n * @returns The parsed value of type T\n *\n * @throws {InvalidObjectError} When no bytes are found at the specified indices\n * @throws {ParseError} When BCS parsing fails due to malformed data\n *\n * @example\n * ```typescript\n * // Parse a u64 return value\n * const result = await suiClient.devInspectTransactionBlock({...});\n * const balance = parseDevInspectResult(result, bcs.u64());\n *\n * // Parse a custom struct\n * const PriceInfo = bcs.struct('PriceInfo', {\n * price: bcs.u64(),\n * timestamp: bcs.u64(),\n * });\n * const priceInfo = parseDevInspectResult(result, PriceInfo);\n *\n * // Parse from a specific return value\n * const secondReturnValue = parseDevInspectResult(result, bcs.string(), 0, 1);\n * ```\n */\nexport const parseDevInspectResult = <T, Input>(\n result: DevInspectResults,\n bcsType: BcsType<T, Input>,\n resultIndex: number = 0,\n returnValueIndex: number = 0\n): T => {\n const bytes = extractBytes(result, resultIndex, returnValueIndex);\n if (!bytes) {\n throw new InvalidObjectError('When trying to parse result, no bytes found', {\n bcsType,\n resultIndex,\n returnValueIndex,\n });\n }\n\n try {\n return bcsType.parse(bytes);\n } catch (error) {\n throw new ParseError('DevInspectResult', 'from bcs to a typescript type', {\n error,\n result,\n bcsType,\n resultIndex,\n returnValueIndex,\n });\n }\n};\n\n/**\n * Parses multiple return values from a DevInspectResults object using an array of BCS parsers.\n *\n * This function is useful when a Move function returns multiple values that need to be\n * parsed with different BCS types. It applies each parser in the schema array to the\n * corresponding return value index.\n *\n * @template T - A tuple type representing the array of BCS parsers\n *\n * @param info - The DevInspectResults object from a Sui devInspect call\n * @param schema - An array of BCS parsers, one for each expected return value\n *\n * @returns A tuple containing the parsed values, with types matching the schema\n *\n * @example\n * ```typescript\n * // Parse multiple return values of different types\n * const result = await suiClient.devInspectTransactionBlock({...});\n * const [balance, isActive, userName] = parseMultipleResults(\n * result,\n * [bcs.u64(), bcs.bool(), bcs.string()] as const\n * );\n *\n * // Parse multiple complex types\n * const TokenInfo = bcs.struct('TokenInfo', {\n * symbol: bcs.string(),\n * decimals: bcs.u8(),\n * });\n * const [tokenA, tokenB, liquidityAmount] = parseMultipleResults(\n * result,\n * [TokenInfo, TokenInfo, bcs.u128()] as const\n * );\n * ```\n *\n * @remarks\n * - The function assumes all return values are from the first result (index 0)\n * - Each parser in the schema array corresponds to a return value at the same index\n * - Type safety is preserved through TypeScript's tuple types\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const parseMultipleResults = <T extends readonly BcsType<any>[]>(\n info: DevInspectResults,\n schema: T\n): { [K in keyof T]: BcsParsed<T[K]> } => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return schema.map((bcsType, index) => parseDevInspectResult(info, bcsType, 0, index)) as {\n [K in keyof T]: BcsParsed<T[K]>;\n };\n};\n","import { InsufficientFundsError, MissingParameterError } from '@bolt-liquidity-hq/core';\nimport type { SuiClient, PaginatedCoins, CoinStruct } from '@mysten/sui/client';\nimport type { Argument, Transaction } from '@mysten/sui/transactions';\nimport { normalizeStructTag } from '@mysten/sui/utils';\n\nimport { SUI_TOKEN_DENOM } from '../../config';\n\n/**\n * Configuration options for coin selection algorithms.\n *\n * These options control how the CoinManager selects coins when preparing\n * transactions, allowing optimization for different scenarios.\n */\nexport interface CoinSelectionOptions {\n /**\n * Array of coin object IDs to exclude from selection.\n * Useful for avoiding coins that are locked or reserved for other transactions.\n *\n * @example [\"0x123...\", \"0x456...\"]\n */\n excludeIds?: string[];\n\n /**\n * When true, prefers merging multiple coins even if a single coin could cover the amount.\n * This can help consolidate fragmented coin holdings.\n *\n * @default false\n */\n preferMerge?: boolean;\n\n /**\n * When true, uses the minimum number of coins needed to cover the amount.\n * This preserves coin count but may use larger denominations.\n *\n * @default false\n */\n minimizeInputs?: boolean;\n\n /**\n * When true, allows returning a partial amount if insufficient funds.\n * The result will contain all available coins even if they don't meet the target.\n *\n * @default false\n */\n allowPartial?: boolean;\n}\n\n/**\n * Result of the coin selection process.\n *\n * Contains the selected coins and metadata about what operations\n * are needed to prepare them for the transaction.\n */\nexport interface CoinSelectionResult {\n /**\n * Array of selected coin objects that will be used in the transaction.\n */\n coins: CoinStruct[];\n\n /**\n * Total balance of all selected coins as a string.\n * May exceed the requested amount if exact change isn't available.\n */\n totalBalance: string;\n\n /**\n * Whether the selected coins need to be merged into a single coin.\n * True when multiple coins are selected.\n */\n requiresMerge: boolean;\n\n /**\n * Whether the resulting coin needs to be split to get the exact amount.\n * True when totalBalance exceeds the requested amount.\n */\n requiresSplit: boolean;\n}\n\n/**\n * Manages coin selection and preparation for Sui transactions.\n *\n * The CoinManager class provides utilities for working with coins on the Sui blockchain,\n * including fetching balances, selecting optimal coins for transactions, and preparing\n * coin inputs with automatic merging and splitting as needed.\n *\n * @example\n * ```typescript\n * const coinManager = new CoinManager(suiClient, userAddress);\n *\n * // Get total balance\n * const balance = await coinManager.getTotalBalance(\n * \"0x2::sui::SUI\"\n * );\n *\n * // Select coins for a transaction\n * const selection = await coinManager.selectCoins(\n * \"0x2::sui::SUI\",\n * \"1000000000\", // 1 SUI\n * { minimizeInputs: true }\n * );\n *\n * // Prepare coin input for transaction\n * const tx = new Transaction();\n * const coinInput = await coinManager.prepareCoinInput(\n * tx,\n * \"0x2::sui::SUI\",\n * \"1000000000\"\n * );\n * ```\n *\n * @group Helpers\n */\nexport class CoinManager {\n /**\n * Creates a new CoinManager instance.\n *\n * @param client - The SuiClient instance for blockchain interactions\n * @param defaultOwner - Optional default owner address for coin operations.\n * If not provided, owner must be specified in each method call.\n *\n * @example\n * ```typescript\n * // With default owner\n * const coinManager = new CoinManager(suiClient, \"0x123...\");\n *\n * // Without default owner (must specify in each call)\n * const coinManager = new CoinManager(suiClient);\n * ```\n */\n constructor(\n private client: SuiClient,\n private defaultOwner?: string\n ) {}\n\n /**\n * Fetches all coins of a specific type owned by an address.\n *\n * This method handles pagination automatically to retrieve all coins,\n * regardless of how many exist. Coins are returned in the order\n * provided by the blockchain.\n *\n * @param coinType - The fully qualified type of the coin (e.g., \"0x2::sui::SUI\")\n * @param owner - Optional owner address. Uses defaultOwner if not provided.\n *\n * @returns A promise that resolves to an array of all coins of the specified type\n *\n * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set\n *\n * @example\n * ```typescript\n * // Get all SUI coins\n * const suiCoins = await coinManager.getAllCoins(\"0x2::sui::SUI\");\n * console.log(`Found ${suiCoins.length} SUI coins`);\n *\n * // Get all USDC coins for a specific owner\n * const usdcCoins = await coinManager.getAllCoins(\n * \"0x5d4b...::coin::COIN\",\n * \"0xowner...\"\n * );\n *\n * // Display coin details\n * suiCoins.forEach(coin => {\n * console.log(`Coin ID: ${coin.coinObjectId}`);\n * console.log(`Balance: ${coin.balance}`);\n * });\n * ```\n */\n async getAllCoins(coinType: string, owner?: string): Promise<CoinStruct[]> {\n const ownerAddress = this.getOwnerAddress(owner);\n\n // Fetch all coins with pagination\n const allCoins: CoinStruct[] = [];\n let cursor: string | undefined | null;\n\n do {\n const response: PaginatedCoins = await this.client.getCoins({\n owner: ownerAddress,\n coinType,\n cursor,\n });\n\n allCoins.push(...response.data);\n cursor = response.hasNextPage ? response.nextCursor : undefined;\n } while (cursor);\n\n return allCoins;\n }\n\n /**\n * Resolves the owner address from the provided parameter or default.\n *\n * This is a helper method used internally to ensure an owner address\n * is always available for coin operations.\n *\n * @param owner - Optional owner address to use\n *\n * @returns The resolved owner address\n *\n * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set\n *\n * @example\n * ```typescript\n * // With default owner set\n * const address = coinManager.getOwnerAddress(); // Returns defaultOwner\n *\n * // With explicit owner\n * const address = coinManager.getOwnerAddress(\"0x123...\"); // Returns \"0x123...\"\n *\n * // Without default owner or parameter\n * const address = coinManager.getOwnerAddress(); // Throws MissingParameterError\n * ```\n */\n getOwnerAddress(owner?: string): string {\n const address = owner || this.defaultOwner;\n if (!address) throw new MissingParameterError('owner');\n\n return address;\n }\n\n /**\n * Gets the total balance of a specific coin type for an owner.\n *\n * This method returns the sum of all coins of the specified type,\n * providing a quick way to check if sufficient funds are available\n * without fetching all coin objects.\n *\n * @param coinType - The fully qualified type of the coin (e.g., \"0x2::sui::SUI\")\n * @param owner - Optional owner address. Uses defaultOwner if not provided.\n *\n * @returns A promise that resolves to the total balance as a string\n *\n * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set\n *\n * @example\n * ```typescript\n * // Get SUI balance\n * const suiBalance = await coinManager.getTotalBalance(\"0x2::sui::SUI\");\n * console.log(`Total SUI: ${suiBalance}`);\n *\n * // Get USDC balance for specific owner\n * const usdcBalance = await coinManager.getTotalBalance(\n * \"0x5d4b...::coin::COIN\",\n * \"0xowner...\"\n * );\n *\n * // Convert to decimal for display (assuming 9 decimals for SUI)\n * const suiDecimal = Number(suiBalance) / 1e9;\n * console.log(`${suiDecimal} SUI`);\n * ```\n */\n async getTotalBalance(coinType: string, owner?: string): Promise<string> {\n const ownerAddress = this.getOwnerAddress(owner);\n\n const balance = await this.client.getBalance({\n owner: ownerAddress,\n coinType,\n });\n\n return balance.totalBalance;\n }\n\n /**\n * Asserts that the owner has sufficient balance for a transaction.\n *\n * This is a convenience method that checks the balance and throws\n * a descriptive error if insufficient. Useful for fail-fast validation\n * before attempting complex transaction preparation.\n *\n * @param coinType - The fully qualified type of the coin (e.g., \"0x2::sui::SUI\")\n * @param amount - The required amount as a string\n * @param owner - Optional owner address. Uses defaultOwner if not provided.\n *\n * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set\n * @throws {InsufficientFundsError} When the balance is less than the required amount\n *\n * @example\n * ```typescript\n * try {\n * // Check if user has 1 SUI\n * await coinManager.assertEnoughBalance(\n * \"0x2::sui::SUI\",\n * \"1000000000\" // 1 SUI\n * );\n *\n * // Proceed with transaction\n * console.log(\"Sufficient balance confirmed\");\n * } catch (error) {\n * if (error instanceof InsufficientFundsError) {\n * console.error(`Need ${error.data.amount}, but only have ${error.data.available}`);\n * }\n * }\n * ```\n */\n async assertEnoughBalance(coinType: string, amount: string, owner?: string): Promise<void> {\n const ownerAddress = this.getOwnerAddress(owner);\n\n const totalBalance = await this.getTotalBalance(coinType, owner);\n\n if (BigInt(totalBalance) < BigInt(amount)) {\n throw new InsufficientFundsError(amount, totalBalance, { coinType, amount, ownerAddress });\n }\n }\n\n /**\n * Selects optimal coins to cover a specific amount.\n *\n * This method implements intelligent coin selection algorithms that consider\n * various factors like minimizing inputs, preserving large coins, and\n * avoiding fragmentation. It determines whether merging or splitting is needed.\n *\n * @param coinType - The fully qualified type of the coin (e.g., \"0x2::sui::SUI\")\n * @param amount - The target amount to select for, as a string\n * @param options - Configuration options for the selection algorithm\n * @param owner - Optional owner address. Uses defaultOwner if not provided.\n *\n * @returns A promise that resolves to a CoinSelectionResult with selected coins and metadata\n *\n * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set\n * @throws {InsufficientFundsError} When available coins cannot cover the amount (unless allowPartial is true)\n *\n * @example\n * ```typescript\n * // Basic selection\n * const selection = await coinManager.selectCoins(\n * \"0x2::sui::SUI\",\n * \"1000000000\" // 1 SUI\n * );\n *\n * if (selection.requiresMerge) {\n * console.log(`Need to merge ${selection.coins.length} coins`);\n * }\n * if (selection.requiresSplit) {\n * console.log(`Need to split coin for exact amount`);\n * }\n *\n * // Minimize number of inputs\n * const minimalSelection = await coinManager.selectCoins(\n * \"0x2::sui::SUI\",\n * \"5000000000\",\n * { minimizeInputs: true }\n * );\n *\n * // Exclude specific coins and allow partial\n * const partialSelection = await coinManager.selectCoins(\n * \"0x2::sui::SUI\",\n * \"10000000000\",\n * {\n * excludeIds: [\"0x123...\"],\n * allowPartial: true\n * }\n * );\n * ```\n *\n * @remarks\n * The selection algorithm follows these priorities:\n * 1. Exact match - single coin with exact amount\n * 2. Single coin that covers amount (requires split)\n * 3. Multiple coins (requires merge, possibly split)\n *\n * When minimizeInputs is false, smaller coins are used first to preserve larger ones.\n */\n async selectCoins(\n coinType: string,\n amount: string,\n options: CoinSelectionOptions = {},\n owner?: string\n ): Promise<CoinSelectionResult> {\n const ownerAddress = this.getOwnerAddress(owner);\n const coins = await this.getAllCoins(coinType, owner);\n\n // Filter out excluded coins\n const availableCoins = options.excludeIds\n ? coins.filter((c) => !options.excludeIds?.includes(c.coinObjectId))\n : coins;\n\n if (availableCoins.length === 0) {\n throw new InsufficientFundsError(amount, '0', {\n availableCoins,\n coinType,\n ownerAddress,\n });\n }\n\n const targetAmount = BigInt(amount);\n\n // Sort by balance (largest first)\n availableCoins.sort((a, b) => {\n const diff = BigInt(b.balance) - BigInt(a.balance);\n return diff > 0n ? 1 : diff < 0n ? -1 : 0;\n });\n\n // Check for exact match\n const exactMatch = availableCoins.find((c) => BigInt(c.balance) === targetAmount);\n if (exactMatch) {\n return {\n coins: [exactMatch],\n totalBalance: amount,\n requiresMerge: false,\n requiresSplit: false,\n };\n }\n\n // Check for single coin that can cover amount\n const singleCoin = availableCoins.find((c) => BigInt(c.balance) > targetAmount);\n if (singleCoin && !options.preferMerge) {\n return {\n coins: [singleCoin],\n totalBalance: singleCoin.balance,\n requiresMerge: false,\n requiresSplit: true,\n };\n }\n\n // Need multiple coins\n const selectedCoins: CoinStruct[] = [];\n let totalBalance = 0n;\n\n if (options.minimizeInputs) {\n // Try to minimize number of coins used\n for (const coin of availableCoins) {\n selectedCoins.push(coin);\n totalBalance += BigInt(coin.balance);\n if (totalBalance >= targetAmount) break;\n }\n } else {\n // Use smallest coins first to preserve larger coins\n const sortedAsc = [...availableCoins].sort((a, b) => {\n const diff = BigInt(a.balance) - BigInt(b.balance);\n return diff > 0n ? 1 : diff < 0n ? -1 : 0;\n });\n\n for (const coin of sortedAsc) {\n if (totalBalance >= targetAmount) break;\n selectedCoins.push(coin);\n totalBalance += BigInt(coin.balance);\n }\n }\n\n // Check if we have enough\n if (totalBalance < targetAmount) {\n if (options.allowPartial) {\n return {\n coins: selectedCoins,\n totalBalance: totalBalance.toString(),\n requiresMerge: selectedCoins.length > 1,\n requiresSplit: false,\n };\n }\n\n throw new InsufficientFundsError(amount, totalBalance.toString(), {\n amount,\n coinType,\n totalBalance: totalBalance.toString(),\n ownerAddress,\n });\n }\n\n return {\n coins: selectedCoins,\n totalBalance: totalBalance.toString(),\n requiresMerge: selectedCoins.length > 1,\n requiresSplit: totalBalance > targetAmount,\n };\n }\n\n /**\n * Prepares a coin input for a transaction with automatic merging and splitting.\n *\n * This is the main method for transaction preparation. It handles all the complexity\n * of coin selection, merging multiple coins if needed, and splitting for exact amounts.\n * Special handling is provided for SUI gas coins.\n *\n * @param tx - The Transaction object to add coin operations to\n * @param coinType - The fully qualified type of the coin (e.g., \"0x2::sui::SUI\")\n * @param amount - The exact amount needed for the transaction, as a string\n * @param options - Configuration options for coin selection\n * @param owner - Optional owner address. Uses defaultOwner if not provided.\n *\n * @returns A promise that resolves to an Argument that can be used in Move calls\n *\n * @throws {MissingParameterError} When owner is not provided and no defaultOwner is set\n * @throws {InsufficientFundsError} When available coins cannot cover the amount\n *\n * @example\n * ```typescript\n * const tx = new Transaction();\n *\n * // Prepare exact SUI amount (uses gas coin)\n * const suiCoin = await coinManager.prepareCoinInput(\n * tx,\n * \"0x2::sui::SUI\",\n * \"1000000000\" // 1 SUI\n * );\n *\n * // Prepare custom coin with options\n * const customCoin = await coinManager.prepareCoinInput(\n * tx,\n * \"0x5d4b...::coin::COIN\",\n * \"1000000\", // 1 USDC\n * {\n * minimizeInputs: true,\n * excludeIds: [\"0x123...\"]\n * }\n * );\n *\n * // Use in a Move call\n * tx.moveCall({\n * target: `${packageId}::module::swap`,\n * arguments: [suiCoin, customCoin],\n * });\n * ```\n *\n * @remarks\n * - SUI coins are handled specially by splitting from the gas coin\n * - Single coins matching the exact amount are used directly\n * - Multiple coins are automatically merged\n * - Coins with excess balance are automatically split\n * - The resulting Argument can be used directly in Move calls\n */\n async prepareCoinInput(\n tx: Transaction,\n coinType: string,\n amount: string,\n options: CoinSelectionOptions = {},\n owner?: string\n ): Promise<Argument> {\n const ownerAddress = this.getOwnerAddress(owner);\n\n // Handle SUI specially\n if (normalizeStructTag(coinType) === SUI_TOKEN_DENOM) {\n const [coin] = tx.splitCoins(tx.gas, [amount]);\n return coin;\n }\n\n // Select coins\n const selection = await this.selectCoins(coinType, amount, options, owner);\n\n if (!selection.coins[0]) {\n throw new InsufficientFundsError(amount, '0', {\n coinType,\n amount,\n ownerAddress,\n });\n }\n\n // Single coin, exact amount\n if (selection.coins.length === 1 && !selection.requiresSplit) {\n return tx.object(selection.coins[0].coinObjectId);\n }\n\n // Single coin, needs split\n if (selection.coins.length === 1 && selection.requiresSplit) {\n const [split] = tx.splitCoins(tx.object(selection.coins[0].coinObjectId), [amount]);\n return split;\n }\n\n // Multiple coins, need merge\n const primaryCoin = tx.object(selection.coins[0].coinObjectId);\n const mergeCoins = selection.coins.slice(1).map((c) => tx.object(c.coinObjectId));\n\n tx.mergeCoins(primaryCoin, mergeCoins);\n\n // Split if needed\n if (selection.requiresSplit) {\n const [split] = tx.splitCoins(primaryCoin, [amount]);\n return split;\n }\n\n return primaryCoin;\n }\n}\n","import { type Address, TransactionFailedError, UnexpectedError } from '@bolt-liquidity-hq/core';\nimport type { SerializedBcs } from '@mysten/bcs';\nimport type { DevInspectResults, SuiClient } from '@mysten/sui/client';\nimport { Transaction } from '@mysten/sui/transactions';\n\nimport { ZERO_ADDRESS } from '../constants';\n\n/**\n * Executes a read-only query against a Sui Move function using devInspect.\n *\n * This function allows you to call Move functions without committing a transaction\n * to the blockchain. It's perfect for querying contract state, simulating transactions,\n * or getting computed values from view functions. The devInspect feature runs the\n * transaction in a sandboxed environment and returns the results without any state changes.\n *\n * @param suiClient - The SuiClient instance used to interact with the Sui network\n * @param target - The Move function to call, either as:\n * - A string in the format \"packageId::module::function\"\n * - A tuple of [packageId, module, function]\n * @param args - Optional array of arguments to pass to the Move function. Each argument can be:\n * - A string representing an object ID (will be passed as an object reference)\n * - A SerializedBcs object containing pre-serialized BCS data (will be passed as a pure value)\n * @param typeArguments - Optional array of type arguments for generic Move functions\n * @param senderAddress - Optional sender address for the simulated transaction.\n * Defaults to ZERO_ADDRESS if not provided. Some functions may require a specific\n * sender to check permissions or balances.\n *\n * @returns A promise that resolves to DevInspectResults containing:\n * - effects: Transaction effects showing gas costs and object changes\n * - events: Events that would be emitted by the transaction\n * - results: Array of results with return values from the Move function\n * - error: Any execution errors (if status is not 'success')\n *\n * @throws {TransactionFailedError} When the Move function execution fails\n * @throws {UnexpectedError} When there's a network error or other unexpected failure\n *\n * @example\n * ```typescript\n * // Query a simple getter function\n * const result = await queryDevInspect(\n * suiClient,\n * `${packageId}::oracle::get_price`,\n * [baseAssetId, quoteAssetId]\n * );\n *\n * // Query with type arguments\n * const balanceResult = await queryDevInspect(\n * suiClient,\n * [packageId, \"pool\", \"get_balance\"],\n * [poolObjectId],\n * [\"0x2::sui::SUI\"] // Type argument for the coin type\n * );\n *\n * // Query with serialized BCS arguments\n * const amountBcs = bcs.u64().serialize(1000000).toBytes();\n * const swapResult = await queryDevInspect(\n * suiClient,\n * `${packageId}::router::get_amount_out`,\n * [amountBcs, poolObjectId],\n * undefined,\n * userAddress // Use actual user address for more specific simulation\n * );\n *\n * // Parse the results\n * if (result.effects.status.status === 'success') {\n * const returnValue = result.results?.[0]?.returnValues?.[0];\n * if (returnValue) {\n * const price = bcs.u64().parse(new Uint8Array(returnValue[0]));\n * }\n * }\n * ```\n *\n * @remarks\n * - devInspect is read-only and cannot modify blockchain state\n * - Gas is still calculated but not charged\n * - Object modifications are simulated but not persisted\n * - Some functions may behave differently in devInspect vs actual execution\n * - The ZERO_ADDRESS default sender may not work for functions that check ownership\n */\nexport const queryDevInspect = async (\n suiClient: SuiClient,\n target: string | [string, string, string],\n args?: (SerializedBcs<unknown> | string)[],\n typeArguments?: string[],\n senderAddress?: Address\n): Promise<DevInspectResults> => {\n const tx = new Transaction();\n\n const targetString = Array.isArray(target) ? `${target[0]}::${target[1]}::${target[2]}` : target;\n\n const txArgs = args?.map((item) =>\n typeof item === 'string' ? tx.object(item) : tx.pure(item.toBytes())\n );\n\n tx.moveCall({\n target: targetString,\n arguments: txArgs,\n typeArguments,\n });\n\n try {\n // Use devInspectTransactionBlock to execute without submitting to chain\n const result = await suiClient.devInspectTransactionBlock({\n transactionBlock: tx,\n sender: senderAddress ?? ZERO_ADDRESS,\n });\n\n // Process the results\n if (result.effects.status.status === 'success') {\n return result;\n } else {\n throw new TransactionFailedError('N/A', 'Failed to query smart contract', { result });\n }\n } catch (error) {\n throw UnexpectedError.from(error, 'Failed to query smart contract', {\n target: targetString,\n args,\n typeArguments,\n });\n }\n};\n","import type { Address, Coin } from '@bolt-liquidity-hq/core';\nimport {\n DEFAULT_GAS_ADJUSTMENT,\n NotFoundError,\n TransactionFailedError,\n UnexpectedError,\n} from '@bolt-liquidity-hq/core';\nimport { bcs, type SerializedBcs } from '@mysten/bcs';\nimport type {\n SuiClient,\n SuiTransactionBlockResponse,\n SuiTransactionBlockResponseOptions,\n} from '@mysten/sui/client';\nimport type { Signer } from '@mysten/sui/cryptography';\nimport { Transaction, type TransactionArgument } from '@mysten/sui/transactions';\nimport { SUI_CLOCK_OBJECT_ID } from '@mysten/sui/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport type { BoltSuiClient } from '../client';\nimport { CoinManager } from './coin-manager';\nimport { SUI_TOKEN_DENOM } from '../../config';\nimport { ROUTER_MODULE } from '../constants';\nimport type { SuiSwapParams, WalletSigner } from '../../types';\n\n/**\n * Builds the transaction arguments for a swap operation on the Bolt protocol.\n *\n * This helper function prepares all necessary components for executing a swap transaction,\n * including pool discovery, swap direction determination, coin preparation, and argument\n * serialization. It abstracts the complexity of building swap transactions by handling\n * the differences between sell and buy operations automatically. It supports\n * both SDK signers and wallet signers for broader compatibility.\n *\n * @param client - The BoltSuiClient instance containing configuration and contracts\n * @param swapParams - The swap parameters\n * @param swapParams.assetIn - The type of the asset being sold (e.g., \"0x2::sui::SUI\")\n * @param swapParams.amountIn - The exact amount of input asset to swap (in minimal denomination)\n * @param swapParams.assetOut - The type of the asset being bought\n * @param swapParams.minimumAmountOut - Optional minimum acceptable amount of output asset (as string)\n * @param swapParams.receiver - Optional recipient address for the swapped assets\n * @param swapParams.swapType - Optional swap type (default is 'buy')\n * 'buy' - Buy the assetOut from a pool of assetOut, paying with assetIn\n * 'sell' - Sell the assetIn to a pool of assetIn, receiving assetOut\n * @param signer - Optional signer for the transaction. Can be either:\n * - A Signer instance from Sui SDK (e.g., Ed25519Keypair)\n * - A WalletSigner from wallet adapters (e.g., Sui Wallet, Suiet)\n * If not provided, uses the client's cached signer\n *\n * @returns A promise that resolves to an object containing:\n * - signer: The resolved Signer or WalletSigner instance that will sign the transaction\n * - signerAddress: The address of the signer\n * - target: Tuple of [packageId, module, function] for the Move call\n * - args: Array of prepared transaction arguments\n * - typeArguments: Array of type arguments ordered based on swap direction\n * - tx: The Transaction object with prepared coin operations\n *\n * @throws {NotFoundError} When no pool exists for the specified asset pair\n * @throws {MissingParameterError} When no signer is available\n *\n * @example\n * ```typescript\n * const client = new BoltSuiClient();\n *\n * // Using SDK signer\n * const signer = new Ed25519Keypair();\n *\n * // Build swap transaction arguments\n * const txArgs = await buildSwapTxArgs(\n * client,\n * {\n * assetIn: \"0x2::sui::SUI\",\n * amountIn: \"1000000000\", // 1 SUI\n * assetOut: \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\",\n * minimumAmountOut: \"1950000\" // Min 1.95 USDC\n * swapType: 'buy' // Optional, 'buy' or 'sell' (default is 'buy')\n * },\n * signer\n * );\n *\n * // Using wallet signer\n * const walletSigner = await wallet.getAccount();\n * const walletTxArgs = await buildSwapTxArgs(client, swapParams, walletSigner);\n *\n * // Use the prepared arguments to execute the transaction\n * const result = await signAndExecuteTx(\n * client.suiClient,\n * txArgs.signer,\n * txArgs.target,\n * txArgs.args,\n * txArgs.typeArguments,\n * txArgs.tx\n * );\n * ```\n */\nexport const buildSwapTxArgs = async (\n client: BoltSuiClient,\n swapParams: SuiSwapParams,\n signer?: Signer | WalletSigner\n): Promise<{\n signer: Signer | WalletSigner;\n signerAddress: Address;\n target: [string, string, string];\n args?: (TransactionArgument | SerializedBcs<unknown> | string)[];\n typeArguments?: string[];\n tx?: Transaction;\n}> => {\n const { assetIn, amountIn, assetOut, minimumAmountOut, receiver, swapType = 'buy' } = swapParams;\n const pool = client.routerClient.getPool(assetIn, assetOut, swapType);\n\n if (!pool) {\n throw new NotFoundError(`Pool for the pair ${assetIn}/${assetOut}`);\n }\n\n const FUNCTION_NAME = pool.isInverse ? 'swap_sell' : 'swap_buy';\n\n const finalSigner = client.getSigner(signer);\n\n const tx = new Transaction();\n\n const signerAddress = getSignerAddress(finalSigner);\n\n const coinManager = new CoinManager(client.suiClient, signerAddress);\n\n const coinInput = await coinManager.prepareCoinInput(tx, assetIn, amountIn);\n\n return {\n signer: finalSigner,\n signerAddress,\n target: [client.packageId, ROUTER_MODULE, FUNCTION_NAME],\n args: [\n pool.poolAddress,\n client.contracts.oracle,\n SUI_CLOCK_OBJECT_ID,\n coinInput,\n bcs.u64().serialize(amountIn),\n bcs.option(bcs.u64()).serialize(minimumAmountOut),\n bcs.option(bcs.string()).serialize(receiver),\n ],\n typeArguments: [pool.isInverse ? assetIn : assetOut, pool.isInverse ? assetOut : assetIn],\n tx,\n };\n};\n\n/**\n * Signs and executes a transaction on the Sui blockchain.\n *\n * This function builds, signs, and submits a transaction to the Sui network. It provides\n * a convenient wrapper around the Sui SDK's transaction building and execution flow,\n * handling argument serialization and error cases. It supports both SDK signers\n * and wallet signers, automatically detecting and handling each type appropriately.\n *\n * @param suiClient - The SuiClient instance used to interact with the Sui network\n * @param signer - The signer used to sign the transaction. Can be either:\n * - A Signer instance from Sui SDK (e.g., Ed25519Keypair)\n * - A WalletSigner from wallet adapters (e.g., Sui Wallet, Suiet)\n * @param target - The Move function to call, either as:\n * - A string in the format \"packageId::module::function\"\n * - A tuple of [packageId, module, function]\n * @param args - Optional array of arguments to pass to the Move function. Each argument can be:\n * - A string representing an object ID (will be passed as an object reference)\n * - A SerializedBcs object containing pre-serialized BCS data (will be passed as a pure value)\n * - A TransactionArgument created by the Transaction builder\n * @param typeArguments - Optional array of type arguments for generic Move functions.\n * These are fully qualified type names like \"0x2::sui::SUI\"\n * @param transaction - Optional pre-existing Transaction object to add the Move call to.\n * If not provided, a new Transaction will be created.\n * @param options - Optional response options to specify what data to include in the response\n * (e.g., effects, events, object changes, balance changes)\n *\n * @returns A promise that resolves to SuiTransactionBlockResponse containing:\n * - digest: The transaction digest (hash)\n * - effects: Transaction effects showing gas costs, created/modified/deleted objects\n * - events: Events emitted during transaction execution\n * - objectChanges: Detailed changes to objects (if requested in options)\n * - balanceChanges: Changes to coin balances (if requested in options)\n *\n * @throws {TransactionFailedError} When the Move function execution fails on-chain\n *\n * @remarks\n * The function automatically detects the signer type:\n * - SDK signers use `suiClient.signAndExecuteTransaction()`\n * - Wallet signers use their own `signAndExecuteTransaction()` method and require\n * waiting for the transaction to be confirmed on-chain\n *\n * @example\n * ```typescript\n * // Using SDK signer - simple transfer\n * const result = await signAndExecuteTx(\n * suiClient,\n * keypair,\n * '0x2::coin::transfer',\n * [coinObjectId, recipientAddress],\n * ['0x2::sui::SUI']\n * );\n *\n * // Using wallet signer\n * const walletAccount = await wallet.getAccount();\n * const walletResult = await signAndExecuteTx(\n * suiClient,\n * walletAccount,\n * '0x2::coin::transfer',\n * [coinObjectId, recipientAddress],\n * ['0x2::sui::SUI']\n * );\n *\n * // Call a swap function with serialized amount\n * const amountBcs = bcs.u64().serialize(1000000).toBytes();\n * const swapResult = await signAndExecuteTx(\n * suiClient,\n * signer,\n * [packageId, 'pool', 'swap'],\n * [poolObjectId, amountBcs],\n * ['0x2::sui::SUI', `${packageId}::usdc::USDC`],\n * undefined,\n * {\n * showEffects: true,\n * showEvents: true,\n * showObjectChanges: true\n * }\n * );\n *\n * // Build a complex transaction\n * const tx = new Transaction();\n * const [coin] = tx.splitCoins(tx.gas, [1000000]);\n * await signAndExecuteTx(\n * suiClient,\n * signer,\n * `${packageId}::market::place_order`,\n * [marketId, coin, tx.pure.u64(price)],\n * undefined,\n * tx // Pass the existing transaction\n * );\n *\n * // Handle the response\n * if (result.effects?.status.status === 'success') {\n * console.log('Transaction successful:', result.digest);\n * console.log('Gas used:', result.effects.gasUsed);\n *\n * // Process created objects\n * result.effects.created?.forEach(obj => {\n * console.log('Created object:', obj.reference.objectId);\n * });\n * }\n * ```\n */\nexport const signAndExecuteTx = async (\n suiClient: SuiClient,\n signer: Signer | WalletSigner,\n target: string | [string, string, string],\n args?: (TransactionArgument | SerializedBcs<unknown> | string)[],\n typeArguments?: string[],\n transaction?: Transaction,\n options?: SuiTransactionBlockResponseOptions\n): Promise<SuiTransactionBlockResponse> => {\n const tx = transaction ?? new Transaction();\n\n const targetString = Array.isArray(target) ? `${target[0]}::${target[1]}::${target[2]}` : target;\n\n const txArgs = args?.map((item) =>\n typeof item === 'string' ? tx.object(item) : 'toBytes' in item ? tx.pure(item.toBytes()) : item\n );\n\n tx.moveCall({\n target: targetString,\n arguments: txArgs,\n typeArguments,\n });\n\n if ('toSuiAddress' in signer) {\n const result = await suiClient.signAndExecuteTransaction({\n signer,\n transaction: tx,\n options,\n });\n\n if (result.effects?.status.status === 'success') {\n return result;\n } else {\n throw new TransactionFailedError(result.digest, result.effects?.status.error, { result });\n }\n } else {\n const result = await signer.signAndExecuteTransaction({\n transaction: tx,\n });\n\n if (!result.digest) {\n throw new TransactionFailedError('not found');\n }\n\n const fullTx = await suiClient.waitForTransaction({\n digest: result.digest,\n options,\n });\n\n if (fullTx.effects?.status.status !== 'success') {\n throw new TransactionFailedError(result.digest, fullTx.effects?.status.error, { result });\n }\n\n return fullTx;\n }\n};\n\n/**\n * Estimates the gas price for a transaction on the Sui blockchain.\n *\n * This function builds a transaction and performs a dry run to estimate gas costs\n * without actually executing the transaction on-chain. It returns the gas denomination\n * (always 'SUI' for Sui network) and the estimated amount including the gas adjustment\n * multiplier. The sender address is required for accurate gas estimation as it affects\n * object resolution and gas calculations.\n *\n * @param suiClient - The SuiClient instance used to interact with the Sui network\n * @param senderAddress - The Sui address that would send the transaction. This is used for:\n * - Resolving owned objects in the transaction\n * - Calculating accurate gas costs based on the sender's objects\n * - Setting the transaction sender for the dry run\n * @param target - The Move function to call, either as:\n * - A string in the format \"packageId::module::function\"\n * - A tuple of [packageId, module, function]\n * @param args - Optional array of arguments to pass to the Move function. Each argument can be:\n * - A string representing an object ID (will be passed as an object reference)\n * - A SerializedBcs object containing pre-serialized BCS data (will be passed as a pure value)\n * - A TransactionArgument created by the Transaction builder\n * @param typeArguments - Optional array of type arguments for generic Move functions.\n * These are fully qualified type names like \"0x2::sui::SUI\"\n * @param transaction - Optional pre-existing Transaction object to add the Move call to.\n * If not provided, a new Transaction will be created.\n * @param gasAdjustment - Optional multiplier for gas estimation (default: 1.5). Use higher values for\n * safety margin. For example, 1.5 means 50% buffer above estimated gas.\n *\n * @returns A promise that resolves to a Coin object containing:\n * - denom: The gas denomination (configured SUI token denomination)\n * - amount: The estimated gas amount as a string, including the gas adjustment\n * Returns undefined if estimation fails\n *\n * @remarks\n * - Silent failure returns undefined to allow graceful handling of estimation errors\n *\n * @example\n * ```typescript\n * // Estimate gas for a simple transfer\n * const senderAddress = \"0x123...\";\n * const gasEstimate = await estimateTxGasPrice(\n * suiClient,\n * senderAddress,\n * '0x2::coin::transfer',\n * [coinObjectId, recipientAddress],\n * ['0x2::sui::SUI']\n * );\n * if (gasEstimate) {\n * console.log(`Estimated gas: ${gasEstimate.amount} ${gasEstimate.denom}`);\n * }\n *\n * // Estimate with higher safety margin\n * const safeGasEstimate = await estimateTxGasPrice(\n * suiClient,\n * senderAddress,\n * [packageId, 'pool', 'swap'],\n * [poolObjectId, amountBcs],\n * ['0x2::sui::SUI', `${packageId}::usdc::USDC`],\n * undefined,\n * 2.0 // 100% buffer for complex operations\n * );\n *\n * // Use with existing transaction\n * const tx = new Transaction();\n * const [coin] = tx.splitCoins(tx.gas, [1000000]);\n * const gasPrice = await estimateTxGasPrice(\n * suiClient,\n * senderAddress,\n * `${packageId}::market::place_order`,\n * [marketId, coin, tx.pure.u64(price)],\n * undefined,\n * tx,\n * 1.2\n * );\n * ```\n */\nexport const estimateTxGasPrice = async (\n suiClient: SuiClient,\n senderAddress: Address,\n target: string | [string, string, string],\n args?: (TransactionArgument | SerializedBcs<unknown> | string)[],\n typeArguments?: string[],\n transaction?: Transaction,\n gasAdjustment: number = DEFAULT_GAS_ADJUSTMENT\n): Promise<Coin | undefined> => {\n const tx = transaction ?? new Transaction();\n\n const targetString = Array.isArray(target) ? `${target[0]}::${target[1]}::${target[2]}` : target;\n\n const txArgs = args?.map((item) =>\n typeof item === 'string' ? tx.object(item) : 'toBytes' in item ? tx.pure(item.toBytes()) : item\n );\n\n tx.moveCall({\n target: targetString,\n arguments: txArgs,\n typeArguments,\n });\n\n tx.setSender(senderAddress);\n\n try {\n // Build the transaction\n const transactionBytes = await tx.build({ client: suiClient });\n\n // Perform dry run to estimate gas\n const dryRunResult = await suiClient.dryRunTransactionBlock({\n transactionBlock: transactionBytes,\n });\n\n if (dryRunResult.effects.status.status !== 'success') {\n throw new UnexpectedError(\n `Dry run failed: ${dryRunResult.effects.status.error}`,\n 'Failed to estimate gas',\n {\n target: targetString,\n args,\n typeArguments,\n error: dryRunResult.effects.status.error,\n }\n );\n }\n\n // Extract gas information from the dry run result\n const gasUsed = dryRunResult.effects.gasUsed;\n\n // Calculate total gas cost (computation + storage - storage rebate)\n const totalGasCost = BigNumber(gasUsed.computationCost)\n .plus(gasUsed.storageCost)\n .minus(gasUsed.storageRebate);\n\n // Apply gas adjustment multiplier\n const adjustedGasCost = totalGasCost.times(gasAdjustment);\n\n return {\n denom: SUI_TOKEN_DENOM,\n amount: adjustedGasCost.toFixed(0, BigNumber.ROUND_CEIL),\n };\n } catch {\n return;\n }\n};\n\n/**\n * Extracts the address from either an SDK Signer or a WalletSigner.\n *\n * This utility function provides a unified way to get the address from different\n * signer types used in the Sui ecosystem. It handles the differences between\n * SDK signers (which have a toSuiAddress() method) and wallet signers (which\n * have an address property).\n *\n * @param signer - The signer instance to extract the address from. Can be either:\n * - A Signer from Sui SDK (has toSuiAddress() method)\n * - A WalletSigner from wallet adapters (has address property)\n *\n * @returns The Sui address as a string\n *\n * @throws {NotFoundError} When the signer doesn't have an accessible address\n *\n * @example\n * ```typescript\n * // With SDK signer\n * const keypair = new Ed25519Keypair();\n * const sdkAddress = getSignerAddress(keypair);\n * console.log(sdkAddress); // \"0x...\"\n *\n * // With wallet signer\n * const walletAccount = await wallet.getAccount();\n * const walletAddress = getSignerAddress(walletAccount);\n * console.log(walletAddress); // \"0x...\"\n * ```\n */\nexport const getSignerAddress = (signer: Signer | WalletSigner): string => {\n const address: string | undefined =\n 'address' in signer ? signer.address : signer.toSuiAddress?.();\n\n if (!address) {\n throw new NotFoundError(\"Signer account's address\");\n }\n\n return address;\n};\n","import type {\n InvertiblePrice,\n OracleConfig,\n OracleAssetPair,\n AssetsConfig,\n} from '@bolt-liquidity-hq/core';\nimport { InvalidObjectError } from '@bolt-liquidity-hq/core';\nimport { BigNumber } from 'bignumber.js';\nimport { normalizeStructTag } from '@mysten/sui/utils';\n\nimport { PRICE_PRECISION } from '../constants';\nimport type {\n AssetPairsResponseStructOutput,\n AssetPairStructOutput,\n OracleConfigStructOutput,\n PriceDataStructOutput,\n PriceResponseStructOutput,\n} from '../../types';\n\n/**\n * Parses a raw oracle configuration response from the Sui blockchain into a structured OracleConfig object.\n *\n * This function transforms the snake_case properties from the Sui Move contract response\n * into camelCase properties following TypeScript conventions. It also converts the\n * price expiry time from seconds to a structured format with seconds and nanoseconds.\n *\n * @param output - The raw oracle configuration response from the contract query\n * @param output.price_threshold_ratio - The maximum allowed price deviation ratio\n * @param output.default_price_expiry_seconds - The default time in seconds before prices expire\n *\n * @returns A parsed OracleConfig object with:\n * - admin: The admin address of the oracle contract\n * - priceThresholdRatio: The threshold ratio for price updates (e.g., \"0.01\" for 1%)\n * - priceExpireTime: Object with seconds and nanoseconds representing expiry duration\n *\n * @example\n * ```typescript\n * const output = {\n * price_threshold_ratio: \"0.01\",\n * default_price_expiry_seconds: \"3600\" // 1 hour\n * };\n *\n * const config = parseOracleConfigStructOutput(output);\n * console.log(config.admin); // \"0x1234...\"\n * console.log(config.priceThresholdRatio); // \"0.01\"\n * console.log(config.priceExpireTime.secs); // 3600\n * ```\n */\nexport const parseOracleConfigStructOutput = (output: OracleConfigStructOutput): OracleConfig => {\n return {\n // TODO: try to query admin somewhere else? to fill empty value\n admin: '',\n priceThresholdRatio: output.price_threshold_ratio,\n priceExpireTime: {\n secs: Number(output.default_price_expiry_seconds),\n nanos: 0,\n },\n };\n};\n\n/**\n * Parses a single asset pair structure from the Sui oracle contract into an OracleAssetPair object.\n *\n * This function converts the raw asset pair data containing base and quote asset information\n * into a structured format. It can optionally use an assets configuration to provide\n * human-readable names for assets, falling back to extracting names from the asset type string.\n *\n * @param output - The raw asset pair data from the contract\n * @param output.base_name - The name/type of the base asset (e.g., \"SUI\", \"0x2::sui::SUI\")\n * @param output.base_precision - The decimal precision of the base asset (e.g., 9 for SUI)\n * @param output.quote_name - The name/type of the quote asset\n * @param output.quote_precision - The decimal precision of the quote asset\n * @param assetsConfig - Optional configuration mapping asset types to metadata including names\n *\n * @returns An OracleAssetPair object containing:\n * - base: Object with name, symbol (normalized struct tag), and precision for the base asset\n * - quote: Object with name, symbol (normalized struct tag), and precision for the quote asset\n *\n * @example\n * ```typescript\n * const rawPair = {\n * base_name: \"0x2::sui::SUI\",\n * base_precision: 9,\n * quote_name: \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\",\n * quote_precision: 6\n * };\n *\n * const assetsConfig = {\n * \"0x2::sui::SUI\": { name: \"SUI\" },\n * \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\": { name: \"COIN\" }\n * };\n *\n * const pair = parseAssetPairStructOutput(rawPair, assetsConfig);\n * console.log(pair.base.name); // \"SUI\"\n * console.log(pair.base.symbol); // \"0x2::sui::SUI\"\n * console.log(pair.quote.name); // \"COIN\"\n * ```\n */\nexport const parseAssetPairStructOutput = (\n output: AssetPairStructOutput,\n assetsConfig?: AssetsConfig\n): OracleAssetPair => {\n return {\n base: {\n name:\n assetsConfig?.[output.base_name]?.name ??\n output.base_name.match(/([^:]+)$/)?.[1] ??\n output.base_name,\n symbol: normalizeStructTag(output.base_name),\n precision: output.base_precision,\n },\n quote: {\n name:\n assetsConfig?.[output.quote_name]?.name ??\n output.quote_name.match(/([^:]+)$/)?.[1] ??\n output.quote_name,\n symbol: normalizeStructTag(output.quote_name),\n precision: output.quote_precision,\n },\n };\n};\n\n/**\n * Parses a response containing multiple asset pairs from the oracle contract.\n *\n * This function processes an array of asset pairs returned by the oracle's\n * asset_pairs query, where each item contains an 'info' property with the\n * actual pair data. It can optionally use an assets configuration to provide\n * human-readable names for the assets.\n *\n * @param output - Array of objects containing asset pair info\n * @param assetsConfig - Optional configuration mapping asset types to metadata including names\n *\n * @returns An array of parsed OracleAssetPair objects\n *\n * @example\n * ```typescript\n * const output = [\n * { info: { base_name: \"0x2::sui::SUI\", base_precision: 9, quote_name: \"0x5d::coin::COIN\", quote_precision: 6 } },\n * { info: { base_name: \"0xeth::coin::ETH\", base_precision: 18, quote_name: \"0x5d::coin::COIN\", quote_precision: 6 } }\n * ];\n *\n * const assetsConfig = {\n * \"0x2::sui::SUI\": { name: \"SUI\" },\n * \"0xeth::coin::ETH\": { name: \"ETH\" },\n * \"0x5d::coin::COIN\": { name: \"USDC\" }\n * };\n *\n * const pairs = parseAssetPairsResponseStructOutput(output, assetsConfig);\n * console.log(pairs.length); // 2\n * console.log(pairs[0].base.name); // \"SUI\"\n * console.log(pairs[0].base.symbol); // \"0x2::sui::SUI\"\n * ```\n */\nexport const parseAssetPairsResponseStructOutput = (\n output: AssetPairsResponseStructOutput,\n assetsConfig?: AssetsConfig\n): OracleAssetPair[] => {\n return output.map((item) => parseAssetPairStructOutput(item.info, assetsConfig));\n};\n\n/**\n * Parses raw price data from the oracle contract into an InvertiblePrice object.\n *\n * This function converts the price information including the price value and expiry time.\n * The expiry time is converted from milliseconds to nanoseconds for consistency with\n * the broader system's time representation. The base and quote denominations are\n * provided as parameters rather than being included in the output data.\n *\n * @param output - The raw price data from the contract\n * @param output.price - Object containing the price details\n * @param output.price.price - The price value as a string (to maintain precision)\n * @param output.price.expiry - The price expiry time in milliseconds since Unix epoch\n * @param baseDenom - The denomination of the base asset (e.g., \"0x2::sui::SUI\")\n * @param quoteDenom - The denomination of the quote asset (e.g., \"0xusdcAddress...\")\n *\n * @returns An InvertiblePrice object containing:\n * - baseDenom: The denom of the base token (from parameter)\n * - quoteDenom: The denom of the quote token (from parameter)\n * - price: The price value as a string\n * - expiryTime: The expiry time in nanoseconds as a string\n * - isInverse: Boolean flag indicating if the price is inverted or not\n *\n * @example\n * ```typescript\n * const priceData = {\n * price: {\n * price: \"2.5\",\n * expiry: \"1700000000000\" // milliseconds\n * }\n * };\n *\n * const price = parsePriceDataStructOutput(\n * priceData,\n * \"0x2::sui::SUI\",\n * \"0xusdcAddress...\"\n * );\n * console.log(price.price); // \"2.5\"\n * console.log(price.baseDenom); // \"0x2::sui::SUI\"\n * console.log(price.quoteDenom); // \"0xusdcAddress...\"\n * console.log(price.expiryTime); // \"1700000000000000000\" (nanoseconds)\n * ```\n */\nexport const parsePriceDataStructOutput = (\n output: PriceDataStructOutput,\n baseDenom: string,\n quoteDenom: string,\n isInverted?: boolean\n): InvertiblePrice => {\n return {\n baseDenom: baseDenom,\n quoteDenom: quoteDenom,\n price: BigNumber(output.price.price).shiftedBy(-PRICE_PRECISION).toFixed(),\n expiryTime: BigNumber(output.price.expiry).times(1_000_000).toFixed(),\n isInverse: isInverted ?? false,\n };\n};\n\n/**\n * Parses a price response from the oracle contract, extracting the price data if available.\n *\n * This function handles the response from price queries which may or may not contain\n * valid price data. It checks for the presence of pair_data and throws an error\n * if the price is not available. The base and quote denominations must be provided\n * as they are not included in the response data.\n *\n * @param output - The price response from the oracle contract\n * @param output.pair_data - Optional price data for the requested pair\n * @param baseDenom - The denomination of the base asset\n * @param quoteDenom - The denomination of the quote asset\n *\n * @returns An InvertiblePrice object with the parsed price information\n *\n * @throws {InvalidObjectError} When pair_data is not present in the response,\n * indicating that no price is available for the requested pair\n *\n * @example\n * ```typescript\n * // Successful response with price data\n * const output = {\n * pair_data: {\n * price: {\n * price: \"2.5\",\n * expiry: \"1700000000000\"\n * }\n * }\n * };\n *\n * const price = parsePriceResponseStructOutput(\n * output,\n * \"0x2::sui::SUI\",\n * \"0xusdcAddress...\"\n * );\n * console.log(price.price); // \"2.5\"\n *\n * // Response without price data\n * const emptyOutput = { pair_data: null };\n * // This will throw InvalidObjectError\n * ```\n */\nexport const parsePriceResponseStructOutput = (\n output: PriceResponseStructOutput,\n baseDenom: string,\n quoteDenom: string\n): InvertiblePrice => {\n if (!output.pair_data) {\n throw new InvalidObjectError(\"Can't find pair data price\");\n }\n\n return parsePriceDataStructOutput(output.pair_data, baseDenom, quoteDenom, output.is_inverted);\n};\n","import { bcs, BcsType } from '@mysten/bcs';\n\nexport const PaginationStruct = {\n total_count: bcs.u64(),\n has_next_page: bcs.bool(),\n next_cursor: bcs.option(bcs.string()),\n};\n\nexport const BcsAddressType = new BcsType({\n name: 'address',\n\n read(reader) {\n const bytes = new Uint8Array(32);\n for (let i = 0; i < 32; i++) {\n bytes[i] = reader.read8();\n }\n return (\n '0x' +\n Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n );\n },\n\n write(value, writer) {\n // Remove 0x prefix if present\n const hex = value.startsWith('0x') ? value.slice(2) : value;\n // Pad to 64 characters (32 bytes)\n const paddedHex = hex.padStart(64, '0');\n\n for (let i = 0; i < 32; i++) {\n const byte = parseInt(paddedHex.substr(i * 2, 2), 16);\n writer.write8(byte);\n }\n },\n});\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type BcsParsed<T extends BcsType<any, any>> = ReturnType<T['parse']>;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type BcsParsedMultiple<T extends readonly BcsType<any>[]> = {\n [K in keyof T]: BcsParsed<T[K]>;\n};\n","import { bcs } from '@mysten/bcs';\n\nimport { BcsAddressType, type BcsParsed } from './bcs';\n\nexport const OracleConfigStruct = bcs.struct('Config', {\n price_threshold_ratio: bcs.u64(),\n default_price_expiry_seconds: bcs.u64(),\n});\nexport type OracleConfigStructOutput = BcsParsed<typeof OracleConfigStruct>;\n\nexport const AssetPairStruct = bcs.struct('AssetPair', {\n base_name: bcs.string(),\n quote_name: bcs.string(),\n base_precision: bcs.u8(),\n quote_precision: bcs.u8(),\n});\nexport type AssetPairStructOutput = BcsParsed<typeof AssetPairStruct>;\n\nexport const TypeNameStruct = bcs.struct('TypeName', {\n name: bcs.string(),\n});\nexport type TypeNameStructOutput = BcsParsed<typeof TypeNameStruct>;\n\nexport const RawPairStruct = bcs.struct('RawPair', {\n base: TypeNameStruct,\n quote: TypeNameStruct,\n});\nexport type RawPairStructOutput = BcsParsed<typeof RawPairStruct>;\n\nexport const AssetPairResponseStruct = bcs.struct('AssetPairResponse', {\n pair: RawPairStruct,\n info: AssetPairStruct,\n});\nexport type AssetPairResponseStructOutput = BcsParsed<typeof AssetPairResponseStruct>;\n\nexport const AssetPairsResponseStruct = bcs.vector(AssetPairResponseStruct);\nexport type AssetPairsResponseStructOutput = BcsParsed<typeof AssetPairsResponseStruct>;\n\nexport const RawPriceStruct = bcs.struct('RawPrice', {\n price: bcs.u128(),\n expiry: bcs.u64(),\n});\nexport type RawPriceStructOutput = BcsParsed<typeof RawPriceStruct>;\n\nexport const PriceDataStruct = bcs.struct('PriceData', {\n price: RawPriceStruct,\n last_updated_ms: bcs.u64(),\n updater: BcsAddressType,\n});\nexport type PriceDataStructOutput = BcsParsed<typeof PriceDataStruct>;\n\nexport const PriceResponseStruct = bcs.struct('PriceResponse', {\n pair_data: bcs.option(PriceDataStruct),\n is_inverted: bcs.bool(),\n});\nexport type PriceResponseStructOutput = BcsParsed<typeof PriceResponseStruct>;\n","import type { Pool, SwapParams, SwapRequiredParams } from '@bolt-liquidity-hq/core';\nimport { bcs } from '@mysten/bcs';\n\nimport { BcsAddressType, type BcsParsed, PaginationStruct } from './bcs';\n\nexport type SuiSwapSimulateParams = SwapRequiredParams & {\n swapType?: 'buy' | 'sell';\n};\n\nexport type SuiSwapParams = SwapParams & {\n swapType?: 'buy' | 'sell';\n};\n\nexport const RouterConfigStruct = bcs.struct('Config', {\n admin: BcsAddressType,\n default_price_oracle_contract: BcsAddressType,\n default_protocol_fee_recipient: BcsAddressType,\n default_protocol_fee: bcs.u64(),\n default_lp_fee: bcs.u64(),\n});\nexport type RouterConfigStructOutput = BcsParsed<typeof RouterConfigStruct>;\n\nexport const MarketStruct = bcs.struct('Market', {\n base_asset_symbol: bcs.string(),\n quote_assets_symbols: bcs.vector(bcs.string()),\n market_address: bcs.string(),\n is_permissioned: bcs.bool(),\n created_at_ms: bcs.u64(),\n});\nexport type MarketStructOutput = BcsParsed<typeof MarketStruct>;\n\nexport const MarketResponseStruct = bcs.struct('MarketResponse', {\n market: bcs.option(MarketStruct),\n});\nexport type MarketResponseStructOutput = BcsParsed<typeof MarketResponseStruct>;\n\nexport const MarketsResponseStruct = bcs.struct('MarketsResponse', {\n markets: bcs.vector(MarketStruct),\n});\nexport type MarketsResponseStructOutput = BcsParsed<typeof MarketsResponseStruct>;\n\nexport const MarketsResponsePaginatedStruct = bcs.struct('MarketsResponsePaginated', {\n markets: bcs.vector(MarketStruct),\n ...PaginationStruct,\n});\nexport type MarketsResponsePaginatedStructOutput = BcsParsed<typeof MarketsResponsePaginatedStruct>;\n\nexport const SwapSimulationResultStruct = bcs.struct('SwapSimulationResult', {\n base_out: bcs.u64(),\n quote_out: bcs.u64(),\n swap_fee_pct: bcs.u64(),\n dynamic_fee_pct: bcs.u64(),\n ideal_quote_amt: bcs.u128(),\n swap_fee: bcs.u64(),\n lp_fee: bcs.u64(),\n protocol_fee: bcs.u64(),\n price_used: bcs.u128(),\n});\nexport type SwapSimulationResultStructOutput = BcsParsed<typeof SwapSimulationResultStruct>;\n\nexport type RouterPool = Pool & {\n isInverse: boolean;\n};\n","import type { Address } from '@bolt-liquidity-hq/core';\nimport { bcs } from '@mysten/bcs';\n\nimport { BcsAddressType, type BcsParsed } from './bcs';\n\nexport const PoolInfoStruct = bcs.struct('PoolInfo', {\n id: bcs.string(),\n base_liquidity: bcs.u64(),\n net_base_added: bcs.u64(),\n total_lp_shares: bcs.u64(),\n protocol_base_fees: bcs.u64(),\n admin: BcsAddressType,\n is_paused: bcs.bool(),\n});\nexport type PoolInfoStructOutput = BcsParsed<typeof PoolInfoStruct>;\nexport type PoolInfo = {\n id: string;\n baseLiquidity: string;\n netBaseAdded: string;\n totalLpShares: string;\n protocolBaseFees: string;\n admin: Address;\n isPaused: boolean;\n};\n\nexport const PoolConfigStruct = bcs.struct('PoolConfig', {\n swap_fee_pct: bcs.u64(),\n lp_withdrawal_fee_pct: bcs.u64(),\n lp_fee_pct: bcs.u64(),\n max_dynamic_fee: bcs.u64(),\n limit_ratio: bcs.u64(),\n min_base_out: bcs.u64(),\n});\nexport type PoolConfigStructOutput = BcsParsed<typeof PoolConfigStruct>;\n\nexport const ProtocolFeesInfoStruct = bcs.struct('ProtocolFeesInfo', {\n swap_fee_pct: bcs.u64(),\n lp_withdrawal_fee_pct: bcs.u64(),\n});\nexport type ProtocolFeesInfoStructOutput = BcsParsed<typeof ProtocolFeesInfoStruct>;\n\nexport const BaseLiquidityInfoStruct = bcs.struct('BaseLiquidityInfo', {\n base_reserve: bcs.u64(),\n total_lp_shares: bcs.u64(),\n});\nexport type BaseLiquidityInfoStructOutput = BcsParsed<typeof BaseLiquidityInfoStruct>;\n","import type { OracleAssetPair } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\nimport { PRICE_ORACLE_MODULE } from '../constants';\nimport { parseDevInspectResult, queryDevInspect } from '../helpers';\nimport { parseAssetPairsResponseStructOutput } from './parsers';\nimport { AssetPairsResponseStruct } from '../../types';\n\n/**\n * Queries the oracle smart contract to retrieve all supported asset pairs.\n *\n * This function fetches the complete list of trading pairs that the oracle contract\n * supports for price feeds. Each asset pair represents a base/quote relationship\n * that can be used for price queries and swaps within the Bolt protocol.\n *\n * @param client - The BoltSuiClient instance.\n *\n * @returns A promise that resolves to an array of OracleAssetPair objects, each containing:\n * - base: Information about the base asset\n * - name: The full name of the base asset (currently same as symbol)\n * - symbol: The trading symbol (e.g., \"SUI\", \"ETH\")\n * - precision: The number of decimal places for the base asset\n * - quote: Information about the quote asset\n * - name: The full name of the quote asset (currently same as symbol)\n * - symbol: The trading symbol (e.g., \"USDC\", \"USDT\")\n * - precision: The number of decimal places for the quote asset\n *\n * @throws {TransactionFailedError} When the oracle contract query fails, which could happen if:\n * - The oracle contract is not properly initialized\n * - The contract address is incorrect\n * - Network connection issues occur\n * @throws {ParseError} When the response cannot be parsed, indicating:\n * - The contract returned data in an unexpected format\n * - The BCS deserialization failed\n * - The contract ABI has changed\n */\nexport const getAssetPairs = async (client: BoltSuiClient): Promise<OracleAssetPair[]> => {\n /**\n * The Move function name in the oracle module that returns all asset pairs.\n * This function signature in Move:\n * public fun asset_pairs(oracle: &Oracle): AssetPairsResponse\n */\n const ASSET_PAIRS_FUNCTION = 'asset_pairs';\n\n const response = await queryDevInspect(\n client.suiClient,\n [client.packageId, PRICE_ORACLE_MODULE, ASSET_PAIRS_FUNCTION],\n [client.contracts.oracle]\n );\n\n const output = parseDevInspectResult(response, AssetPairsResponseStruct);\n\n return parseAssetPairsResponseStructOutput(output, client.assetsConfig);\n};\n","import type { Asset, OracleAsset } from '@bolt-liquidity-hq/core';\nimport { normalizeStructTag } from '@mysten/sui/utils';\n\nimport type { BoltSuiClient } from '../client';\n\n/**\n * Retrieves all unique assets available in the Bolt protocol by querying oracle asset pairs\n * and enriching them with additional metadata from the client's asset configuration.\n *\n * This function performs the following operations:\n * 1. Fetches all oracle asset pairs from the blockchain\n * 2. Extracts unique assets from both base and quote positions\n * 3. Maps oracle assets to full Asset objects using client configuration\n * 4. Provides fallback values for assets not found in the configuration\n *\n * @param client - The BoltSuiClient instance used to query the blockchain\n * and access asset configuration.\n *\n * @returns A promise that resolves to an array of Asset objects, each containing:\n * - symbol: The asset's trading symbol (e.g., \"SUI\", \"USDC\")\n * - name: The full name of the asset (e.g., \"Sui\", \"USD Coin\")\n * - chainId: The blockchain network identifier (e.g., \"sui-mainnet\")\n * - denom: The chain-specific denomination (e.g., \"0x2::sui::SUI\")\n * - decimals: The number of decimal places for precision\n * - logo: Optional URL to the asset's logo image\n * - coingeckoId: Optional CoinGecko identifier for market data integration\n *\n * @throws {TransactionFailedError} When the oracle contract query fails\n * @throws {ParseError} When the oracle response cannot be properly parsed\n * @throws {UnexpectedError} When network issues prevent the query from completing\n */\nexport const getAssets = async (client: BoltSuiClient): Promise<Asset[]> => {\n // Fetch all trading pairs from the oracle to discover available assets\n const assetPairs = await client.getAllOracleAssetPairs();\n\n /**\n * Map to store unique assets by symbol.\n * This ensures each asset appears only once in the final result,\n * even if it appears in multiple trading pairs.\n */\n const uniqueOracleAssets: Record<string, OracleAsset> = {};\n\n // Extract unique assets from all trading pairs\n for (const item of assetPairs) {\n uniqueOracleAssets[normalizeStructTag(item.base.symbol)] = {\n ...item.base,\n symbol: normalizeStructTag(item.base.symbol),\n };\n uniqueOracleAssets[normalizeStructTag(item.quote.symbol)] = {\n ...item.quote,\n symbol: normalizeStructTag(item.quote.symbol),\n };\n }\n\n return Object.values(uniqueOracleAssets).map(\n (item) =>\n client.assetsConfig[item.symbol] ??\n // Fallback to minimal asset data from oracle\n {\n symbol: item.name,\n name: item.name,\n chainId: client.chainConfig.id,\n denom: normalizeStructTag(item.symbol),\n decimals: item.precision,\n logo: undefined,\n coingeckoId: undefined,\n }\n );\n};\n","import type { OracleConfig } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\nimport { PRICE_ORACLE_MODULE } from '../constants';\nimport { parseDevInspectResult, queryDevInspect } from '../helpers';\nimport { parseOracleConfigStructOutput } from './parsers';\nimport { OracleConfigStruct } from '../../types';\n\n/**\n * Queries the oracle smart contract to retrieve its current configuration settings.\n *\n * This function fetches the oracle's configuration parameters which govern how\n * price feeds are managed, including expiration times, update thresholds, and\n * administrative settings. The configuration is essential for understanding\n * oracle behavior and constraints when working with price feeds.\n *\n * @param client - The BoltSuiClient instance\n *\n * @returns A promise that resolves to an OracleConfig object containing:\n * - admin: The Sui address authorized to update oracle settings and prices\n * - priceThresholdRatio: The minimum price change ratio required for updates\n * (e.g., \"0.01\" means 1% minimum change required)\n * - priceExpireTime: Object with time duration for price validity:\n * - secs: Number of seconds before a price is considered stale\n * - nanos: Additional nanoseconds (always 0 in current implementation)\n *\n * @throws {TransactionFailedError} When the oracle contract query fails, possibly due to:\n * - Invalid oracle contract address\n * - Oracle contract not initialized\n * - Network connectivity issues\n * @throws {ParseError} When the response cannot be parsed, indicating:\n * - Unexpected response format from the contract\n * - BCS deserialization failure\n * - Contract ABI mismatch\n * @throws {InvalidObjectError} When required data is missing from the response\n */\nexport const getOracleConfig = async (client: BoltSuiClient): Promise<OracleConfig> => {\n /**\n * The Move function name in the oracle module that returns configuration.\n * This function signature in Move:\n * public fun config(oracle: &Oracle): OracleConfig\n */\n const CONFIG_FUNCTION = 'config';\n\n const response = await queryDevInspect(\n client.suiClient,\n [client.packageId, PRICE_ORACLE_MODULE, CONFIG_FUNCTION],\n [client.contracts.oracle]\n );\n\n const output = parseDevInspectResult(response, OracleConfigStruct);\n\n return parseOracleConfigStructOutput(output);\n};\n","import type { InvertiblePrice } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\nimport { PRICE_ORACLE_MODULE } from '../constants';\nimport { parseDevInspectResult, queryDevInspect } from '../helpers';\nimport { parsePriceResponseStructOutput } from './parsers';\nimport { PriceResponseStruct } from '../../types';\n\n/**\n * Queries the oracle smart contract to retrieve the current price for a specific asset pair.\n *\n * This function fetches the latest price feed for a given base/quote asset combination\n * from the Bolt oracle. The oracle maintains price feeds that are updated by authorized\n * price feeders and validated against configured thresholds.\n *\n * @param client - The BoltSuiClient instance\n * @param baseDenom - The denomination/type of the base asset in Sui format\n * (e.g., \"0x2::sui::SUI\", \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\")\n * @param quoteDenom - The denomination/type of the quote asset in Sui format\n * Price will be expressed as: 1 base = X quote\n *\n * @returns A promise that resolves to an InvertiblePrice object containing:\n * - baseDenom: The denom of the base token\n * - quoteDenom: The denom of the quote token\n * - price: The current price as a decimal string (e.g., \"2.5\" means 1 base = 2.5 quote)\n * - expiryTime: Unix timestamp in nanoseconds when this price becomes stale\n * - isInverse: Always false in current implementation (price is not inverted)\n *\n * @throws {InvalidObjectError} When the requested asset pair has no price data available,\n * which can occur if:\n * - The pair is not registered in the oracle\n * - The oracle has never received a price for this pair\n * @throws {TransactionFailedError} When the oracle contract query fails due to:\n * - Invalid oracle contract address\n * - Network connectivity issues\n * - Contract execution errors\n * @throws {ParseError} When the response cannot be parsed, indicating:\n * - Unexpected response format\n * - BCS deserialization failure\n */\nexport const getPrice = async (\n client: BoltSuiClient,\n baseDenom: string,\n quoteDenom: string\n): Promise<InvertiblePrice> => {\n /**\n * The Move function name in the oracle module that returns a price for a pair.\n * This function signature in Move:\n * public fun get_price<BaseAsset, QuoteAsset>(\n * oracle: &Oracle\n * ): PriceResponse\n */\n const GET_PRICE_FUNCTION = 'get_price';\n\n const response = await queryDevInspect(\n client.suiClient,\n [client.packageId, PRICE_ORACLE_MODULE, GET_PRICE_FUNCTION],\n [client.contracts.oracle],\n [baseDenom, quoteDenom]\n );\n\n const output = parseDevInspectResult(response, PriceResponseStruct);\n\n return parsePriceResponseStructOutput(output, baseDenom, quoteDenom);\n};\n","import { NotFoundError, type Price } from '@bolt-liquidity-hq/core';\nimport { normalizeStructTag } from '@mysten/sui/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport type { BoltSuiClient } from '../client';\nimport type { RawPairStructOutput, RawPriceStructOutput } from '../../types';\n\n/**\n * Queries the oracle smart contract to retrieve all available price feeds.\n *\n * This function fetches the current prices for all asset pairs supported by the oracle\n * by directly reading the oracle's dynamic fields. It iterates through all stored price\n * entries in the oracle's prices table.\n *\n * @param client - The BoltSuiClient instance\n *\n * @returns A promise that resolves to an array of Price objects, each containing:\n * - baseDenom: The normalized denom of the base token\n * - quoteDenom: The normalized denom of the quote token\n * - price: The current price as a decimal string\n * - expiryTime: Unix timestamp in milliseconds when this price expires\n *\n * @throws {NotFoundError} When:\n * - The oracle object cannot be found at the configured address\n * - The oracle object exists but is not a valid Move object\n * - The prices table cannot be found within the oracle object\n * @throws {TransactionFailedError} When the Sui queries fail due to:\n * - Network connectivity issues\n * - Invalid oracle contract address\n */\nexport const getPrices = async (client: BoltSuiClient): Promise<Price[]> => {\n const oracleObject = await client.suiClient.getObject({\n id: client.contracts.oracle,\n options: { showContent: true },\n });\n\n if (!oracleObject.data?.content || oracleObject.data.content.dataType !== 'moveObject') {\n throw new NotFoundError('Oracle object');\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n const pricesTableId: string | undefined = (oracleObject.data.content.fields as any)?.prices\n ?.fields?.id?.id;\n\n if (!pricesTableId) {\n throw new NotFoundError('Prices table in the Oracle contract');\n }\n\n // Get all prices\n const prices: Price[] = [];\n let cursor = null;\n\n while (true) {\n const dynamicFields = await client.suiClient.getDynamicFields({\n parentId: pricesTableId,\n cursor,\n limit: 50, // Max limit per request\n });\n\n // Batch fetch all field objects in this page\n const fieldPromises = dynamicFields.data.map((field) =>\n client.suiClient.getDynamicFieldObject({\n parentId: pricesTableId,\n name: field.name,\n })\n );\n\n const fieldObjects = await Promise.all(fieldPromises);\n fieldObjects.forEach((obj, index) => {\n if (obj.data?.content?.dataType === 'moveObject') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n const fields = (obj.data.content.fields as any)?.value?.fields?.price?.fields as\n | RawPriceStructOutput\n | undefined;\n const pairKey = dynamicFields.data[index]?.name?.value as RawPairStructOutput | undefined;\n\n if (fields && pairKey) {\n prices.push({\n baseDenom: normalizeStructTag(pairKey.base.name),\n quoteDenom: normalizeStructTag(pairKey.quote.name),\n price: BigNumber(fields.price).shiftedBy(-18).toFixed(),\n expiryTime: fields.expiry,\n });\n }\n }\n });\n\n if (!dynamicFields.hasNextPage) break;\n cursor = dynamicFields.nextCursor;\n }\n\n return prices;\n};\n","import { type Coin, DEFAULT_GAS_ADJUSTMENT } from '@bolt-liquidity-hq/core';\nimport type { Signer } from '@mysten/sui/cryptography';\n\nimport type { BoltSuiClient } from '../client';\nimport { buildSwapTxArgs, estimateTxGasPrice } from '../helpers';\nimport type { SuiSwapParams, WalletSigner } from '../../types';\n\n/**\n * Estimates the gas fees required for executing a swap transaction on the Sui blockchain.\n *\n * This function simulates a swap transaction to calculate the required gas fees without\n * actually executing the swap. It leverages the buildSwapTxArgs helper to prepare all\n * transaction components, then uses Sui's dry run capability to estimate gas costs in SUI tokens.\n *\n * @param client - The BoltSuiClient instance containing configuration and contracts\n * @param swapParams - The swap parameters\n * @param swapParams.assetIn - The type of the asset being sold (e.g., \"0x2::sui::SUI\")\n * @param swapParams.amountIn - The exact amount of input asset to swap (in minimal denomination)\n * @param swapParams.assetOut - The type of the asset being bought (e.g., \"0x5d...::coin::COIN\")\n * @param swapParams.minimumAmountOut - Optional minimum acceptable amount of output asset.\n * Used for slippage protection in the swap simulation.\n * @param swapParams.receiver - Optional recipient address for the swapped assets.\n * If not provided, defaults to the signer's address.\n * @param signer - Optional signer for the transaction. If not provided,\n * uses the client's cached signer. Required on first call if no cached signer exists.\n * @param gasAdjustment - Multiplier for gas estimation to add safety margin.\n * Defaults to DEFAULT_GAS_ADJUSTMENT (typically 1.5 for 50% buffer).\n *\n * @returns A promise that resolves to:\n * - A Coin object with `amount` (gas fee in MIST) and `denom` (\"0x2::sui::SUI\")\n * - `undefined` if the simulation fails or gas estimation is not supported\n *\n * @throws {NotFoundError} When no pool exists for the specified asset pair\n * @throws {MissingParameterError} When no signer is available\n */\nexport const estimateSwapExactInGasFees = async (\n client: BoltSuiClient,\n swapParams: SuiSwapParams,\n signer?: Signer | WalletSigner,\n gasAdjustment: number = DEFAULT_GAS_ADJUSTMENT\n): Promise<Coin | undefined> => {\n const swapArgs = await buildSwapTxArgs(client, swapParams, signer);\n\n return await estimateTxGasPrice(\n client.suiClient,\n swapArgs.signerAddress,\n swapArgs.target,\n swapArgs.args,\n swapArgs.typeArguments,\n swapArgs.tx,\n gasAdjustment\n );\n};\n","import { type BaseLiquidityDetails, NotFoundError, type Address } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\nimport { POOL_MODULE } from '../constants';\nimport { parseDevInspectResult, queryDevInspect } from '../helpers';\nimport { parseBaseLiquidityInfoStructOutput } from './parsers';\nimport { BaseLiquidityInfoStruct } from '../../types';\n\n/**\n * Fetches the base liquidity details for a specific pool.\n *\n * @param client - The BoltSuiClient instance\n * @param contractAddress - The blockchain address of the pool contract\n *\n * @returns A promise that resolves to the base liquidity details for the pool\n *\n * @throws Will throw an error if no pool exists for the specified asset(s)\n */\nexport const getPoolBaseLiquidity = async (\n client: BoltSuiClient,\n contractAddress: Address\n): Promise<BaseLiquidityDetails> => {\n /**\n * Move function to get pool configuration information.\n * Function signature in Move:\n public fun get_base_liquidity_info<Base>(pool: &LiquidityPool<Base>): BaseLiquidityInfo<Base>\n */\n const GET_BASE_LIQUIDITY_INFO_FUNCTION = 'get_base_liquidity_info';\n\n const pool = client.routerClient.pools.find((item) => item.poolAddress === contractAddress);\n\n if (!pool) {\n throw new NotFoundError(`Pool with the address ${contractAddress}`);\n }\n\n const baseLiquidityInfo = await queryDevInspect(\n client.suiClient,\n [client.packageId, POOL_MODULE, GET_BASE_LIQUIDITY_INFO_FUNCTION],\n [contractAddress],\n [pool.baseDenom]\n );\n\n const output = parseDevInspectResult(baseLiquidityInfo, BaseLiquidityInfoStruct);\n\n return parseBaseLiquidityInfoStructOutput(output, pool.baseDenom);\n};\n","import type { Address, BaseLiquidityDetails, PoolConfig } from '@bolt-liquidity-hq/core';\nimport { BigNumber } from 'bignumber.js';\n\nimport { BASIS_POINTS } from '../constants';\nimport type {\n BaseLiquidityInfoStructOutput,\n PoolConfigStructOutput,\n PoolInfo,\n PoolInfoStructOutput,\n} from '../../types';\n\n/**\n * Parses pool configuration from the Sui blockchain into a structured PoolConfig object.\n *\n * This function transforms pool configuration data from the `get_pool_config` Move function response\n * into the standardized format used throughout the SDK.\n *\n * @param poolConfig - The response from the `get_pool_config` Move function containing:\n * - swap_fee_pct: The swap fee in basis points (e.g., 30 = 0.3%)\n * - lp_fee_pct: The liquidity provider fee in basis points (e.g., 20 = 0.2%)\n * - lp_withdrawal_fee_pct: The LP withdrawal fee in basis points\n * - max_dynamic_fee: Maximum dynamic fee adjustment in basis points\n * - limit_ratio: Price limit ratio for dynamic fee calculation\n * - min_base_out: Minimum base asset output amount for trades\n * @param priceOracleContract - The Sui object ID of the price oracle contract used by this pool\n *\n * @returns A parsed PoolConfig object with:\n * - priceOracleContract: Object ID of the price oracle (from parameter)\n * - protocolFeeRecipient: Currently returns '0x' (placeholder until contracts are updated)\n * - protocolFee: The protocol fee percentage as decimal string (swap_fee_pct / 10000)\n * - lpFee: The liquidity provider fee percentage as decimal string (lp_fee_pct / 10000)\n * - allowanceMode: Currently hardcoded to 'allow' (will come from pool config in future)\n * - lps: Array of all lp provider addresses\n * - minBaseOut: Minimum base asset output amount from the pool config\n *\n * @example\n * ```typescript\n * // Example with actual data\n *\n * const poolConfigResponse: PoolConfigStructOutput = {\n * swap_fee_pct: 30, // 30 basis points = 0.3%\n * lp_fee_pct: 20, // 20 basis points = 0.2%\n * lp_withdrawal_fee_pct: 10, // 10 basis points = 0.1%\n * max_dynamic_fee: 50, // 50 basis points = 0.5% max dynamic adjustment\n * limit_ratio: 100, // Price limit ratio\n * min_base_out: \"1000000\" // Minimum base output amount\n * };\n *\n * const oracleAddress = \"0xoracle456...\";\n *\n * const config = parsePoolConfigStructOutput(\n * poolConfigResponse,\n * oracleAddress\n * );\n *\n * console.log(config.priceOracleContract); // \"0xoracle456...\"\n * console.log(config.protocolFeeRecipient); // \"0x\"\n * console.log(config.protocolFee); // \"0.003\" (30/10000)\n * console.log(config.lpFee); // \"0.002\" (20/10000)\n * console.log(config.allowanceMode); // \"allow\"\n * console.log(config.lps); // Array of all lp addresses\n * console.log(config.minBaseOut); // \"1000000\"\n * ```\n */\nexport const parsePoolConfigStructOutput = (\n poolConfig: PoolConfigStructOutput,\n priceOracleContract: Address\n): PoolConfig => {\n // TODO: update when contracts are completed\n // Currently using hardcoded values for some fields\n return {\n priceOracleContract,\n protocolFeeRecipient: '0x', // TODO: get real fee recipient\n protocolFee: BigNumber(poolConfig.swap_fee_pct).div(BASIS_POINTS).toFixed(),\n lpFee: BigNumber(poolConfig.lp_fee_pct).div(BASIS_POINTS).toFixed(),\n allowanceMode: 'allow', // Should come from pool config\n lps: [], // TODO: update with lp list\n minBaseOut: BigNumber(poolConfig.min_base_out).toFixed(),\n };\n};\n\n/**\n * Parses pool information from the Sui blockchain into a structured PoolInfo object.\n *\n * This function transforms pool information data from the `get_pool_info` Move function response\n * into the standardized format used throughout the SDK.\n *\n * @param routerClient - The RouterClient instance\n * @param poolInfo - The response from the `get_pool_info` Move function containing:\n * - id: The Sui object ID of the pool\n * - base_liquidity: The amount of base asset liquidity in the pool\n * - net_base_added: The net amount of base asset added to the pool\n * - total_lp_shares: The total number of liquidity provider shares in the pool\n * - protocol_base_fees: The amount of base asset fees collected by the protocol\n * - admin: The address of the pool admin\n * - is_paused: Whether the pool is paused\n *\n * @returns A parsed PoolConfig object with:\n * - id: The Sui object ID of the pool\n * - baseLiquidity: The amount of base asset liquidity in the pool\n * - netBaseAdded: The net amount of base asset added to the pool\n * - totalLpShares: The total number of liquidity provider shares in the pool\n * - protocolBaseFees: The amount of base asset fees collected by the protocol\n * - admin: The address of the pool admin\n * - isPaused: Whether the pool is paused\n *\n * @example\n * ```typescript\n * // Example with actual data\n * const routerClient = new RouterClient(pools);\n *\n * const poolInfoResponse: PoolInfoStructOutput = {\n * swap_fee_pct: 30, // 30 basis points = 0.3%\n * net_base_added: \"1000000\",\n * total_lp_shares: \"1000000\",\n * protocol_base_fees: \"1000000\",\n * admin: \"0xadmin...\",\n * is_paused: false\n * };\n *\n * const config = parsePoolInfoStructOutput(poolInfoResponse);\n *\n * console.log(config.id); // \"0x1234...\"\n * console.log(config.baseLiquidity); // \"1000000\"\n * console.log(config.netBaseAdded); // \"1000000\"\n * console.log(config.totalLpShares); // \"1000000\"\n * console.log(config.protocolBaseFees); // \"1000000\"\n * console.log(config.admin); // \"0xadmin...\"\n * console.log(config.isPaused); // false\n * ```\n */\nexport const parsePoolInfoStructOutput = (poolInfo: PoolInfoStructOutput): PoolInfo => {\n return {\n id: poolInfo.id,\n baseLiquidity: BigNumber(poolInfo.base_liquidity).toFixed(),\n netBaseAdded: BigNumber(poolInfo.net_base_added).toFixed(),\n totalLpShares: BigNumber(poolInfo.total_lp_shares).toFixed(),\n protocolBaseFees: BigNumber(poolInfo.protocol_base_fees).toFixed(),\n admin: poolInfo.admin,\n isPaused: poolInfo.is_paused,\n };\n};\n\n/**\n * Parses base liquidity details from the pool info response on Sui blockchain into a structured BaseLiquidityDetails object.\n *\n * This function transforms base liquidity details data from the `get_base_liquidity_info` Move function response\n * into the standardized format used throughout the SDK.\n *\n * @param poolInfo - The response from the `get_base_liquidity_info` Move function containing:\n * - base_liquidity: The amount of base asset liquidity in the pool\n * - total_lp_shares: The total number of liquidity provider shares in the pool\n *\n * @returns A parsed BaseLiquidityDetails object with:\n * - baseLiquidity: The amount of base asset liquidity in the pool\n * - totalShares: The total number of liquidity provider shares in the pool\n *\n * @example\n * ```typescript\n * // Example with actual data\n * const poolInfoResponse: PoolInfoStructOutput = {\n * base_liquidity: \"1000000\",\n * total_lp_shares: \"1000000\"\n * };\n *\n * const baseLiquidityDetails = parseBaseLiquidityDetails(poolInfoResponse, \"0x1234...\");\n *\n * console.log(baseLiquidityDetails.baseLiquidity); // \"1000000\"\n * console.log(baseLiquidityDetails.totalShares); // \"1000000\"\n * ```\n */\nexport const parsePoolInfoBaseLiquidityDetails = (\n poolInfo: PoolInfoStructOutput,\n baseDenom: string\n): BaseLiquidityDetails => {\n return {\n baseLiquidity: {\n denom: baseDenom,\n amount: poolInfo.base_liquidity,\n },\n totalShares: poolInfo.total_lp_shares,\n };\n};\n\n/*\n Parses base liquidity details from the Sui blockchain into a structured BaseLiquidityDetails object.\n *\n * This function transforms base liquidity details data from the `get_base_liquidity_info` Move function response\n * into the standardized format used throughout the SDK.\n *\n * @param baseLiquidityInfo - The response from the `get_base_liquidity_info` Move function containing:\n * - base_reserve: The amount of base asset liquidity in the pool\n * - total_lp_shares: The total number of liquidity provider shares in the pool\n *\n * @returns A parsed BaseLiquidityDetails object with:\n * - baseLiquidity: The amount of base asset liquidity in the pool\n * - totalShares: The total number of liquidity provider shares in the pool\n *\n * @example\n * ```typescript\n * // Example with actual data\n * const baseLiquidityInfoResponse: BaseLiquidityInfoStructOutput = {\n * base_reserve: \"1000000\",\n * total_lp_shares: \"1000000\"\n * };\n *\n * const baseLiquidityDetails = parseBaseLiquidityDetails(baseLiquidityInfoResponse, \"0x1234...\");\n *\n * console.log(baseLiquidityDetails.baseLiquidity); // \"1000000\"\n * console.log(baseLiquidityDetails.totalShares); // \"1000000\"\n * ```\n */\nexport const parseBaseLiquidityInfoStructOutput = (\n baseLiquidityInfo: BaseLiquidityInfoStructOutput,\n baseDenom: string\n): BaseLiquidityDetails => {\n return {\n baseLiquidity: {\n denom: baseDenom,\n amount: BigNumber(baseLiquidityInfo.base_reserve).toFixed(),\n },\n totalShares: BigNumber(baseLiquidityInfo.total_lp_shares).toFixed(),\n };\n};\n","import { NotFoundError, type Address, type PoolConfig } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\nimport { POOL_MODULE } from '../constants';\nimport { parseDevInspectResult, queryDevInspect } from '../helpers';\nimport { parsePoolConfigStructOutput } from './parsers';\nimport { PoolConfigStruct } from '../../types';\n\n/**\n * Retrieves the configuration settings and fee information for a specific liquidity pool on Sui.\n *\n * @param client - The BoltSuiClient instance.\n * @param contractAddress - The Sui object ID of the pool contract to query.\n * Must be a valid pool address obtained from router queries.\n *\n * @returns A promise that resolves to a PoolConfig object containing:\n * - priceOracleContract: Object ID of the price oracle used by this pool\n * - protocolFeeRecipient: Address that receives protocol fees from swaps\n * - protocolFee: The protocol fee percentage as decimal string (e.g., \"0.003\" = 0.3%)\n * - lpFee: The liquidity provider fee percentage as decimal string (e.g., \"0.002\" = 0.2%)\n * - allowanceMode: The allowance mode for LP operations (controls who can provide liquidity)\n * - lps: Array of authorized liquidity provider addresses\n * - minBaseOut: Minimum base asset output amount for trades (dust protection)\n *\n * @throws {NotFoundError} When no pool exists with the specified contract address\n * @throws {TransactionFailedError} When the query fails due to:\n * - Invalid pool contract address format\n * - Network connectivity issues\n * - Incorrect type arguments for the pool\n * @throws {ParseError} When the response cannot be parsed, indicating:\n * - Unexpected response format from the query\n * - BCS deserialization failure\n * - Missing required fields in the response\n */\nexport const getPoolConfig = async (\n client: BoltSuiClient,\n contractAddress: Address\n): Promise<PoolConfig> => {\n /**\n * Move function to get pool configuration information.\n * Function signature in Move:\n * public fun get_pool_config<X>(pool: &LiquidityPool<X>): PoolConfig\n */\n const GET_POOL_CONFIG_FUNCTION = 'get_pool_config';\n\n const pool = client.routerClient.pools.find((item) => item.poolAddress === contractAddress);\n\n if (!pool) {\n throw new NotFoundError(`Pool with the address ${contractAddress}`);\n }\n\n const poolConfig = await queryDevInspect(\n client.suiClient,\n [client.packageId, POOL_MODULE, GET_POOL_CONFIG_FUNCTION],\n [contractAddress],\n [pool.baseDenom]\n );\n\n const output = parseDevInspectResult(poolConfig, PoolConfigStruct);\n\n return parsePoolConfigStructOutput(output, client.contracts.oracle);\n};\n","import type { PoolConfig } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\nimport { getPoolConfig } from './get-pool-config';\nimport { getPoolByDenom } from '../router';\n\n/**\n * Retrieves the configuration settings for a liquidity pool\n * identified by its base and quote asset types.\n *\n * This is a convenience function that combines pool lookup and configuration retrieval.\n * It first finds the pool/market associated with the given base/quote asset pair, then fetches that\n * pool's configuration parameters from its settlement contract. In Sui, settlement\n * contracts manage the actual liquidity and trading logic for each pool, and pools are\n * uniquely identified by both base and quote assets.\n *\n * @param client - The BoltSuiClient instance\n * @param baseDenom - The type of the base asset in Sui format\n * (e.g., \"0x2::sui::SUI\", \"0xaf8cd5edc19c4512f4259f0bee101a40d41ebed738ade5874359610ef8eeced5::coin::COIN\")\n * @param quoteDenom - The type of the quote asset in Sui format\n * (e.g., \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\")\n *\n * @returns A promise that resolves to a PoolConfig object containing:\n * - priceOracleContract: Object ID of the price oracle used by this pool\n * - protocolFeeRecipient: Sui address that receives protocol fees\n * - protocolFee: The protocol fee percentage (as decimal string, e.g., \"0.003\" = 0.3%)\n * - lpFee: The liquidity provider fee percentage (as decimal string, e.g., \"0.002\" = 0.2%)\n * - allowanceMode: The allowance mode for pool operations (controls LP permissions)\n * - lps: Array of authorized liquidity provider Sui addresses\n * - minBaseOut: Minimum base asset output amount for trades (prevents dust trades)\n *\n * @throws {NotFoundError} When no pool exists for the specified base/quote asset pair\n * @throws {TransactionFailedError} When the contract queries fail due to:\n * - Invalid router or settlement contract addresses\n * - Network connectivity issues\n * - Contract not properly initialized\n * @throws {ParseError} When the configuration response cannot be parsed\n */\nexport const getPoolConfigByDenom = async (\n client: BoltSuiClient,\n baseDenom: string,\n quoteDenom: string\n): Promise<PoolConfig> => {\n const pool = await getPoolByDenom(client, baseDenom, quoteDenom);\n\n return await getPoolConfig(client, pool.poolAddress);\n};\n","import { type Address, type BaseLiquidityDetails } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\nimport { getPoolBaseLiquidity } from '../settlement';\n\n/**\n * Queries the router smart contract to retrieve the total base asset liquidity across all pools.\n *\n * This function fetches the current liquidity levels for all base assets in their respective\n * pools. Each pool in the Bolt protocol handles swaps for a specific base asset against\n * multiple quote assets, and this query returns how much of each base asset is currently\n * available in its pool for trading, along with the total shares for each pool.\n *\n * @param client - The BoltSuiClient instance\n *\n * @returns A promise that resolves to a Record mapping pool addresses to BaseLiquidityDetails objects.\n * Each entry represents:\n * - Key: The pool contract address\n * - Value: A BaseLiquidityDetails object containing:\n * - baseLiquidity: A Coin object with:\n * - amount: The quantity of base asset liquidity (as string)\n * - denom: The denomination of the base asset\n * - totalShares: The total number of liquidity shares for the pool (as string)\n *\n * @throws Will throw an error if:\n * - The contract query fails due to network issues\n * - The router contract is not properly initialized\n * ```\n */\nexport const getAllBaseLiquidity = async (\n client: BoltSuiClient\n): Promise<Record<Address, BaseLiquidityDetails>> => {\n const result: Record<Address, BaseLiquidityDetails> = {};\n\n for (const pool of client.routerClient.pools) {\n const baseLiquidity = await getPoolBaseLiquidity(client, pool.poolAddress);\n result[pool.poolAddress] = baseLiquidity;\n }\n\n return result;\n};\n","import { NotImplementedError, type Address, type Coin } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\n\n/**\n * Queries the router smart contract to retrieve all quote asset positions for a specific liquidity provider.\n *\n *\n * Currently not implemented on Sui Client\n *\n * @param client - The BoltSuiClient instance\n */\nexport const getAllQuotesForUser = async (\n _client: BoltSuiClient,\n _lpAddress: Address\n // eslint-disable-next-line @typescript-eslint/require-await\n): Promise<Record<Address, Coin[]>> => {\n throw new NotImplementedError('getRouterConfig on Sui Client');\n};\n","import { NotFoundError, type Pool } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\n\n/**\n * Queries the router client to retrieve pool information for a specific asset pair.\n *\n * This function fetches the market/pool details for a given base/quote asset pair from the client's\n * router instance. In the Bolt protocol on Sui, pools are uniquely identified by both base and quote\n * asset types, allowing for multiple pools with the same base asset but different quote assets.\n * This query returns the pool's object ID and configuration for the specified trading pair.\n *\n * @param client - The BoltSuiClient instance.\n * @param baseDenom - The type of the base asset in Sui format\n * (e.g., \"0x2::sui::SUI\", \"0xaf8cd5edc19c4512f4259f0bee101a40d41ebed738ade5874359610ef8eeced5::coin::COIN\")\n * @param quoteDenom - The type of the quote asset in Sui format\n * (e.g., \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\")\n *\n * @returns A promise that resolves to a Pool object containing:\n * - poolAddress: The Sui object ID of the market/pool\n * - baseDenom: The type of the base asset\n * - quoteDenoms: Array of types for available quote assets (will include the requested quote asset)\n *\n * @throws {NotFoundError} When no pool exists for the specified base/quote asset pair, with a message\n * indicating which assets were requested. This occurs if:\n * - No pool has been created for this specific trading pair\n * - The asset types are not recognized by the router\n * - The pool was removed or not initialized\n */\nexport const getPoolByDenom = async (\n client: BoltSuiClient,\n baseDenom: string,\n quoteDenom: string\n): Promise<Pool> => {\n // eslint-disable-next-line @typescript-eslint/await-thenable\n const result = await client.routerClient.getPool(quoteDenom, baseDenom);\n\n if (!result) {\n throw new NotFoundError('Pool', `Didn't find a pool to swap ${quoteDenom} for ${baseDenom}`);\n }\n\n return result;\n};\n","import type { Pool } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\n\n/**\n * Retrieves information about all available pools from the router client.\n *\n * This function fetches a comprehensive list of all markets/pools configured in the Bolt protocol\n * on Sui through the client's router instance. It provides a complete overview of all trading\n * possibilities within the protocol at once, making it more efficient than querying individual pools.\n *\n * @param client - The BoltSuiClient instance.\n *\n * @returns A promise that resolves to an array of Pool objects, each containing:\n * - poolAddress: The Sui object ID of the market/pool\n * - baseDenom: The type of the base asset for this pool (e.g., \"0x2::sui::SUI\")\n * - quoteDenoms: Array of types for available quote assets that can be traded\n * ```\n */\nexport const getAllPools = async (client: BoltSuiClient): Promise<Pool[]> => {\n // eslint-disable-next-line @typescript-eslint/await-thenable\n return await client.routerClient.getPools();\n};\n","import { NotImplementedError, type RouterConfig } from '@bolt-liquidity-hq/core';\n\nimport type { BoltSuiClient } from '../client';\n\n/**\n * Queries the router smart contract to retrieve its current configuration settings.\n *\n * Currently not implemented on Sui Client\n *\n * @param client - The BoltSuiClient instance\n */\n// eslint-disable-next-line @typescript-eslint/require-await\nexport const getRouterConfig = async (_client: BoltSuiClient): Promise<RouterConfig> => {\n throw new NotImplementedError('getRouterConfig on Sui Client');\n};\n","import type { Pool, RouterConfig, SimulateSwapResult } from '@bolt-liquidity-hq/core';\nimport { NotFoundError } from '@bolt-liquidity-hq/core';\nimport { BigNumber } from 'bignumber.js';\n\nimport { BASIS_POINTS } from '../constants';\nimport type {\n MarketResponseStructOutput,\n MarketsResponsePaginatedStructOutput,\n MarketsResponseStructOutput,\n MarketStructOutput,\n RouterConfigStructOutput,\n SwapSimulationResultStructOutput,\n} from '../../types';\n\n/**\n * Parses a raw market structure from the Sui blockchain into a structured Pool object.\n *\n * This function transforms the raw market data returned by the Sui router contract\n * into a standardized Pool format. In the Sui implementation, markets and pools\n * are conceptually the same, representing liquidity pools for base/quote asset pairs.\n *\n * @param output - The raw market data from the Sui contract\n * @param output.market_address - The Sui object ID of the market/pool\n * @param output.base_asset_symbol - The type/symbol of the base asset\n * @param output.quote_assets_symbols - Array of quote asset types/symbols\n *\n * @returns A parsed Pool object containing:\n * - poolAddress: The Sui object ID of the pool\n * - baseDenom: The type of the base asset (e.g., \"0x2::sui::SUI\")\n * - quoteDenoms: Array of available quote asset types\n *\n * @example\n * ```typescript\n * const rawMarket = {\n * market_address: \"0x1234...\",\n * base_asset_symbol: \"0x2::sui::SUI\",\n * quote_assets_symbols: [\"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\"]\n * };\n *\n * const pool = parseMarketStructOutput(rawMarket);\n * console.log(pool.poolAddress); // \"0x1234...\"\n * console.log(pool.baseDenom); // \"0x2::sui::SUI\"\n * console.log(pool.quoteDenoms); // [\"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\"]\n * ```\n */\nexport const parseMarketStructOutput = (output: MarketStructOutput): Pool => {\n return {\n poolAddress: output.market_address,\n baseDenom: output.base_asset_symbol,\n quoteDenoms: output.quote_assets_symbols,\n };\n};\n\n/**\n * Parses a market response that may or may not contain market data.\n *\n * This function handles responses from queries for specific markets, which include\n * an optional market field. If no market is found, it throws an appropriate error.\n *\n * @param output - The market query response from the Sui contract\n * @param output.market - Optional market data if found\n *\n * @returns A parsed Pool object representing the market\n *\n * @throws {NotFoundError} When the market field is null or undefined,\n * indicating the requested market doesn't exist\n *\n * @example\n * ```typescript\n * // Successful response with market data\n * const response = {\n * market: {\n * market_address: \"0x1234...\",\n * base_asset_symbol: \"0x2::sui::SUI\",\n * quote_assets_symbols: [\"0x5d4b...::coin::COIN\"]\n * }\n * };\n * const pool = parseMarketResponseStructOutput(response);\n *\n * // Response without market (will throw)\n * const emptyResponse = { market: null };\n * // Throws NotFoundError\n * ```\n */\nexport const parseMarketResponseStructOutput = (output: MarketResponseStructOutput): Pool => {\n if (!output.market) {\n throw new NotFoundError('Market', undefined, { output });\n }\n\n return parseMarketStructOutput(output.market);\n};\n\n/**\n * Parses a response containing all available markets/pools into an array of Pool objects.\n *\n * This function processes the response from the router's markets query, which returns\n * all active liquidity pools in the Bolt protocol on Sui.\n *\n * @param output - The raw response from the router's markets query\n * @param output.markets - Array of market structures\n *\n * @returns An array of parsed Pool objects, each representing a liquidity pool\n *\n * @example\n * ```typescript\n * const output = {\n * markets: [\n * {\n * market_address: \"0xabc...\",\n * base_asset_symbol: \"0x2::sui::SUI\",\n * quote_assets_symbols: [\"0x5d4b...::coin::COIN\"]\n * },\n * {\n * market_address: \"0xdef...\",\n * base_asset_symbol: \"0xaf8...::coin::COIN\",\n * quote_assets_symbols: [\"0x5d4b...::coin::COIN\", \"0x2::sui::SUI\"]\n * }\n * ]\n * };\n *\n * const pools = parseMarketsResponseStructOutput(output);\n * console.log(pools.length); // 2\n * pools.forEach(pool => {\n * console.log(`Pool for ${pool.baseDenom} at ${pool.poolAddress}`);\n * console.log(`Quote assets: ${pool.quoteDenoms.join(', ')}`);\n * });\n * ```\n */\nexport const parseMarketsResponseStructOutput = (output: MarketsResponseStructOutput): Pool[] => {\n return output.markets.map((item) => parseMarketStructOutput(item));\n};\n\n/**\n * Parses a paginated response containing markets/pools into an array of Pool objects.\n *\n * This function handles paginated market responses, which are used when there are\n * too many markets to return in a single query. It extracts just the market data,\n * leaving pagination handling to the calling function.\n *\n * @param output - The paginated response from the router's markets query\n * @param output.markets - Array of market structures for this page\n * @param output.has_next_page - Whether more pages exist (not used in parser)\n * @param output.next_cursor - Cursor for next page (not used in parser)\n *\n * @returns An array of parsed Pool objects for this page of results\n *\n * @example\n * ```typescript\n * const paginatedOutput = {\n * markets: [\n * {\n * market_address: \"0xabc...\",\n * base_asset_symbol: \"0x2::sui::SUI\",\n * quote_assets_symbols: [\"0x5d4b...::coin::COIN\"]\n * }\n * ],\n * has_next_page: true,\n * next_cursor: \"0xabc...\"\n * };\n *\n * const pools = parseMarketsResponsePaginatedStructOutput(paginatedOutput);\n * console.log(pools.length); // 1 (just this page)\n * ```\n *\n * @see {@link parseMarketsResponseStructOutput} for non-paginated version\n */\nexport const parseMarketsResponsePaginatedStructOutput = (\n output: MarketsResponsePaginatedStructOutput\n): Pool[] => {\n return output.markets.map((item) => parseMarketStructOutput(item));\n};\n\n/**\n * Parses a raw router configuration response from the Sui blockchain into a structured RouterConfig object.\n *\n * This function transforms the snake_case properties from the Sui router contract response\n * into camelCase properties following TypeScript conventions. The router configuration\n * controls global settings for the Bolt protocol on Sui.\n *\n * @param output - The raw router configuration response from the contract query\n * @param output.admin - The Sui address with admin privileges\n * @param output.default_price_oracle_contract - Default oracle object ID for price feeds\n * @param output.default_protocol_fee_recipient - Address that receives protocol fees\n * @param output.default_protocol_fee - Protocol fee as decimal string (e.g., \"0.003\" = 0.3%)\n * @param output.default_lp_fee - LP fee as decimal string (e.g., \"0.002\" = 0.2%)\n *\n * @returns A parsed RouterConfig object with:\n * - admin: The admin address of the router contract\n * - defaultPriceOracleContract: Object ID of the default price oracle\n * - defaultProtocolFeeRecipient: Address that receives protocol fees\n * - defaultProtocolFee: The default protocol fee percentage (as decimal string)\n * - defaultLpFee: The default liquidity provider fee percentage (as decimal string)\n *\n * @example\n * ```typescript\n * const output = {\n * admin: \"0xadmin...\",\n * default_price_oracle_contract: \"0xoracle...\",\n * default_protocol_fee_recipient: \"0xtreasury...\",\n * default_protocol_fee: \"0.003\",\n * default_lp_fee: \"0.002\"\n * };\n *\n * const config = parseRouterConfigStructOutput(output);\n * console.log(config.admin); // \"0xadmin...\"\n * console.log(config.defaultProtocolFee); // \"0.003\" (0.3%)\n * console.log(config.defaultLpFee); // \"0.002\" (0.2%)\n *\n * // Calculate total fees\n * const totalFeePercent = (parseFloat(config.defaultProtocolFee) +\n * parseFloat(config.defaultLpFee)) * 100;\n * console.log(`Total fees: ${totalFeePercent}%`); // \"Total fees: 0.5%\"\n * ```\n */\nexport const parseRouterConfigStructOutput = (output: RouterConfigStructOutput): RouterConfig => {\n return {\n admin: output.admin,\n defaultPriceOracleContract: output.default_price_oracle_contract,\n defaultProtocolFeeRecipient: output.default_protocol_fee_recipient,\n defaultProtocolFee: output.default_protocol_fee,\n defaultLpFee: output.default_lp_fee,\n };\n};\n\n/**\n * Parses a raw swap simulation result from the Sui blockchain into a structured SimulateSwapResult object.\n *\n * This function transforms the raw swap simulation data returned by the Sui router contract\n * into a standardized format. It processes fee information and output amounts from the\n * simulation to provide a comprehensive view of the expected swap outcome.\n *\n * @param output - The raw swap simulation result from the Sui contract containing:\n * - amount_out: The expected amount of output tokens\n * - protocol_fee: The protocol fee amount in output tokens\n * - lp_fee: The liquidity provider fee amount in output tokens\n * - dynamic_fee_pct: Dynamic fee percentage\n * @param poolAddress - The Sui object ID of the pool that would handle this swap\n * @param assetOut - The type/symbol of the output asset (e.g., \"0x2::sui::SUI\")\n *\n * @returns A parsed SimulateSwapResult object containing:\n * - poolAddress: The Sui object ID of the pool handling the swap\n * - amountOut: The expected amount of output tokens (as string)\n * - assetOut: The type of the output asset\n * - protocolFee: The protocol fee amount (as string)\n * - lpFee: The liquidity provider fee amount (as string)\n * - dynamicFeePercentage: Dynamic fee percentage (as string)\n * - totalFees: The sum of protocolFee and lpFee (dynamic fee is distributed between both)\n *\n * @example\n * ```typescript\n * const simulationResult = {\n * amount_out: \"1950000000\",\n * protocol_fee: \"5850000\",\n * lp_fee: \"3900000\",\n * dynamic_fee_pct: \"0.001\"\n * };\n *\n * const result = parseSwapSimulationResultStructOutput(\n * simulationResult,\n * \"0x1234abcd...\",\n * \"0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN\"\n * );\n *\n * console.log(result.poolAddress); // \"0x1234abcd...\"\n * console.log(result.amountOut); // \"1950000000\"\n * console.log(result.assetOut); // \"0x5d4b30...::coin::COIN\"\n * console.log(result.protocolFee); // \"5850000\"\n * console.log(result.lpFee); // \"3900000\"\n * console.log(result.dynamicFeePercentage); // Dynamic fee percentage\n * console.log(result.totalFees); // Sum of protocolFee and lpFee\n * ```\n */\nexport const parseSwapSimulationResultStructOutput = (\n output: SwapSimulationResultStructOutput,\n poolAddress: string,\n assetOut: string\n): SimulateSwapResult => {\n return {\n poolAddress,\n amountOut: output.base_out,\n assetOut,\n protocolFee: output.protocol_fee,\n lpFee: output.lp_fee,\n dynamicFeePercentage: BigNumber(output.dynamic_fee_pct).div(BASIS_POINTS).toFixed(),\n totalFees: output.swap_fee,\n };\n};\n","import type { Pool } from '@bolt-liquidity-hq/core';\nimport { normalizeStructTag } from '@mysten/sui/utils';\n\nimport type { RouterPool } from '../../../types';\n\nexport class RouterClient {\n constructor(public pools: Pool[]) {}\n\n getPool(\n denomIn: string,\n denomOut: string,\n swapType: 'buy' | 'sell' = 'buy'\n ): RouterPool | undefined {\n const normalizedDenomIn = normalizeStructTag(denomIn);\n const normalizedDenomOut = normalizeStructTag(denomOut);\n\n if (swapType === 'sell') {\n // Search by inverse pair\n const inversePairPool: Pool | undefined = this.pools.find(\n (item) =>\n item.baseDenom === normalizedDenomIn && item.quoteDenoms.includes(normalizedDenomOut)\n );\n\n if (inversePairPool) {\n return {\n ...inversePairPool,\n isInverse: true,\n };\n }\n }\n\n // Search by pair\n const directPairPool: Pool | undefined = this.pools.find(\n (item) =>\n item.baseDenom === normalizedDenomOut && item.quoteDenoms.includes(normalizedDenomIn)\n );\n\n if (directPairPool) {\n return {\n ...directPairPool,\n isInverse: false,\n };\n }\n\n if (swapType === 'buy') {\n // Search by inverse pair\n const inversePairPool: Pool | undefined = this.pools.find(\n (item) =>\n item.baseDenom === normalizedDenomIn && item.quoteDenoms.includes(normalizedDenomOut)\n );\n\n if (inversePairPool) {\n return {\n ...inversePairPool,\n isInverse: true,\n };\n }\n }\n\n return;\n }\n\n getPools(): Pool[] {\n return this.pools;\n }\n}\n","import { NotFoundError, type SimulateSwapResult } from '@bolt-liquidity-hq/core';\nimport { bcs } from '@mysten/bcs';\nimport { SUI_CLOCK_OBJECT_ID } from '@mysten/sui/utils';\n\nimport type { BoltSuiClient } from '../client';\nimport { POOL_MODULE } from '../constants';\nimport { parseDevInspectResult, queryDevInspect } from '../helpers';\nimport { parseSwapSimulationResultStructOutput } from './parsers';\nimport { type SuiSwapSimulateParams, SwapSimulationResultStruct } from '../../types';\n\n/**\n * Simulates a swap operation on the Sui blockchain to calculate expected output without executing.\n *\n * This function performs a dry run simulation of swapping an exact amount of input asset\n * for a desired output asset on the Bolt protocol. It automatically determines the correct\n * swap direction (buy or sell) based on the pool configuration and uses Sui's devInspect\n * capability to simulate the transaction without state changes.\n *\n * @param client - The BoltSuiClient instance for blockchain interaction\n * @param params - The swap simulation parameters\n * @param params.assetIn - The type of the input asset to swap from (e.g., \"0x2::sui::SUI\")\n * @param params.amountIn - The exact amount of input asset to simulate swapping (in minimal denomination)\n * @param params.assetOut - The type of the desired output asset (e.g., \"0x5d4b...::coin::COIN\")\n * @param params.swapType - Optional swap type (default is 'buy')\n * 'buy' - Buy the assetOut from a pool of assetOut, paying with assetIn\n * 'sell' - Sell the assetIn to a pool of assetIn, receiving assetOut\n *\n * @returns A promise that resolves to a SimulateSwapResult containing:\n * - poolAddress: The Sui object ID of the pool handling this swap\n * - amountOut: The expected amount of output asset to be received\n * - assetOut: The type of the output asset\n * - protocolFee: The protocol fee amount that would be charged\n * - lpFee: The liquidity provider fee amount that would be charged\n * - dynamicFeePercentage: Dynamic fee percentage\n * - totalFees: The sum of all fees\n *\n * @throws {NotFoundError} When no pool exists for the specified asset pair\n * @throws Will throw if the devInspect simulation fails or returns invalid data\n */\nexport const simulateSwap = async (\n client: BoltSuiClient,\n { assetIn, amountIn, assetOut, swapType }: SuiSwapSimulateParams\n): Promise<SimulateSwapResult> => {\n const pool = client.routerClient.getPool(assetIn, assetOut, swapType);\n\n if (!pool) {\n throw new NotFoundError('Pool', `Didn't find a pool to swap ${assetIn} for ${assetOut}`);\n }\n\n const FUNCTION_NAME = pool.isInverse ? 'simulate_sell_swap' : 'simulate_buy_swap';\n\n const response = await queryDevInspect(\n client.suiClient,\n [client.packageId, POOL_MODULE, FUNCTION_NAME],\n [pool.poolAddress, client.contracts.oracle, SUI_CLOCK_OBJECT_ID, bcs.u64().serialize(amountIn)],\n [pool.isInverse ? assetIn : assetOut, pool.isInverse ? assetOut : assetIn]\n );\n\n const output = parseDevInspectResult(response, SwapSimulationResultStruct);\n\n return parseSwapSimulationResultStructOutput(output, pool.poolAddress, assetOut);\n};\n","import type { SwapResult } from '@bolt-liquidity-hq/core';\nimport type { SuiTransactionBlockResponse } from '@mysten/sui/client';\nimport type { Signer } from '@mysten/sui/cryptography';\n\nimport type { BoltSuiClient } from '../client';\nimport { signAndExecuteTx, buildSwapTxArgs } from '../helpers';\nimport type { SuiSwapParams, WalletSigner } from '../../types';\n\n/**\n * Executes a token swap transaction on the Bolt protocol through the Sui Move router module.\n *\n * This function performs a \"swap exact in\" operation, where the user specifies exactly\n * how much of the input coin they want to swap, and receives a variable amount of the\n * output coin based on current liquidity pool conditions. The function leverages the\n * buildSwapTxArgs helper to prepare the transaction, then executes it on-chain.\n *\n * @param client - The BoltSuiClient instance containing configuration and contracts\n * @param swapParams - The swap configuration parameters\n * @param swapParams.assetIn - The fully qualified type of the input coin being sold\n * (e.g., \"0x2::sui::SUI\", \"0x...::usdc::USDC\")\n * @param swapParams.amountIn - The exact amount of input coin to swap (as string, in base units).\n * For example, \"1000000000\" for 1 SUI (9 decimals)\n * @param swapParams.assetOut - The fully qualified type of the output coin being bought\n * (e.g., \"0x2::sui::SUI\", \"0x...::usdc::USDC\")\n * @param swapParams.minimumAmountOut - Optional minimum acceptable amount of output coin.\n * Transaction will fail if the actual output would be less.\n * Protects against excessive slippage\n * @param swapParams.receiver - Optional recipient address for the swapped coins.\n * If not provided, coins are sent to the signer's address\n * @param swapParams.swapType - Optional swap type (default is 'buy')\n * 'buy' - Buy the assetOut from a pool of assetOut, paying with assetIn\n * 'sell' - Sell the assetIn to a pool of assetIn, receiving assetOut\n * @param signer - Optional Sui signer (e.g., Ed25519Keypair) that will authorize the swap transaction.\n * If not provided, uses the client's cached signer. Must have sufficient balance\n * of the input coin type and SUI for gas fees\n *\n * @returns A promise that resolves to a SwapResult containing:\n * - txOutput: The complete SuiTransactionBlockResponse with transaction details\n * - txHash: The transaction digest for tracking on Sui explorers\n * - amountOut: The actual amount of output coin received (extracted from events, or \"0\" if not found)\n * - assetOut: The output coin type (from the swap parameters)\n *\n * @throws {NotFoundError} When no pool exists for the specified asset pair\n * @throws {TransactionFailedError} When:\n * - The transaction fails on-chain (insufficient balance, slippage, etc.)\n * - The minimum output amount constraint is not satisfied\n * @throws {UnexpectedError} When:\n * - Network connectivity issues occur\n * - Invalid coin types are provided\n * - Coin selection/preparation fails\n * @throws {MissingParameterError} When no signer is available\n */\nexport const swapExactIn = async (\n client: BoltSuiClient,\n swapParams: SuiSwapParams,\n signer?: Signer | WalletSigner\n): Promise<SwapResult<SuiTransactionBlockResponse>> => {\n const swapArgs = await buildSwapTxArgs(client, swapParams, signer);\n\n const txOutput = await signAndExecuteTx(\n client.suiClient,\n swapArgs.signer,\n swapArgs.target,\n swapArgs.args,\n swapArgs.typeArguments,\n swapArgs.tx,\n { showEffects: true, showEvents: true, showBalanceChanges: true }\n );\n\n return {\n txOutput,\n txHash: txOutput.digest,\n amountOut:\n (txOutput.events?.at(0)?.parsedJson as Record<string, string> | undefined)?.['amount_out'] ??\n '0',\n assetOut: swapParams.assetOut,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACkBA,IAAAA,gBAAkD;AAClD,oBAA4D;AAE5D,IAAAC,iBAAmC;AACnC,mBAAkB;;;ACtBlB,mBAAiD;AAE1C,IAAM,sBAAkB,iCAAmB,yBAAY;;;ACD9D,IAAAC,gBAA6B;AAKtB,IAAM,qBAAqC;AAAA,EAChD,MAAM;AAAA,EACN,IAAI;AAAA,EACJ,aAAa;AACf;AAEO,IAAM,mBAA8B;AAAA,EACzC,QAAQ;AAAA,EACR,QAAQ;AACV;AAEO,IAAM,mBACX;AAEK,IAAM,4BACX;AAEK,IAAM,0BAAkC;AAExC,IAAM,gBAA8B;AAAA,EACzC,CAAC,eAAe,GAAG;AAAA,IACjB,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS,mBAAmB;AAAA,IAC5B,OAAO;AAAA,IACP,UAAU;AAAA,IACV,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,kFAAkF;AAAA,IAChF,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS,mBAAmB;AAAA,IAC5B,OAAO;AAAA,IACP,UAAU;AAAA,IACV,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,gFAAgF;AAAA,IAC9E,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS,mBAAmB;AAAA,IAC5B,OAAO;AAAA,IACP,UAAU;AAAA,IACV,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,kFAAkF;AAAA,IAChF,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS,mBAAmB;AAAA,IAC5B,OAAO;AAAA,IACP,UAAU;AAAA,IACV,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AACF;AAEO,IAAM,eAAuB;AAAA,EAClC;AAAA,IACE,aAAa;AAAA,IACb,WAAW;AAAA,IACX,aAAa,CAAC,gFAAgF;AAAA,EAChG;AAAA,EACA;AAAA,IACE,aAAa;AAAA,IACb,WAAW;AAAA,IACX,aAAa,CAAC,8EAA8E;AAAA,EAC9F;AACF;;;AC1EA,IAAAC,gBAA6B;AAKtB,IAAM,mBAAmB;AAEzB,IAAM,qBAAqC;AAAA,EAChD,MAAM;AAAA,EACN,IAAI;AAAA,EACJ,aAAa;AACf;AAEO,IAAM,mBAA8B;AAAA,EACzC,QAAQ;AAAA,EACR,QAAQ;AACV;AAEO,IAAM,mBAA2B;AAEjC,IAAM,4BAAoC;AAE1C,IAAM,0BAAkC;AAExC,IAAM,gBAA8B;AAAA,EACzC,CAAC,eAAe,GAAG;AAAA,IACjB,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS,mBAAmB;AAAA,IAC5B,OAAO;AAAA,IACP,UAAU;AAAA,IACV,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,kFAAkF;AAAA,IAChF,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS,mBAAmB;AAAA,IAC5B,OAAO;AAAA,IACP,UAAU;AAAA,IACV,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,wBAAwB;AAAA,IACtB,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS,mBAAmB;AAAA,IAC5B,OAAO;AAAA,IACP,UAAU;AAAA,IACV,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,0BAA0B;AAAA,IACxB,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS,mBAAmB;AAAA,IAC5B,OAAO;AAAA,IACP,UAAU;AAAA,IACV,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,0BAA0B;AAAA,IACxB,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS,mBAAmB;AAAA,IAC5B,OAAO;AAAA,IACP,UAAU;AAAA,IACV,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,wBAAwB;AAAA,IACtB,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,SAAS,mBAAmB;AAAA,IAC5B,OAAO;AAAA,IACP,UAAU;AAAA,IACV,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AACF;;;AChFO,IAAM,eAAe;AAErB,IAAM,kBAAkB;;;ACFxB,IAAM,eAAe;AAIrB,IAAM,sBAAsB;AAE5B,IAAM,gBAAgB;AAEtB,IAAM,cAAc;;;ACR3B,kBAA+C;AAE/C,iBAAoB;AA0Bb,IAAM,eAAe,CAC1B,QACA,cAAsB,GACtB,mBAA2B,MACL;AACtB,QAAM,eAAe,OAAO,UAAU,WAAW,GAAG;AACpD,MAAI,CAAC,gBAAgB,CAAC,aAAa,gBAAgB,GAAG;AACpD,WAAO;AAAA,EACT;AAEA,QAAM,CAAC,KAAK,IAAI,aAAa,gBAAgB;AAC7C,SAAO,IAAI,WAAW,KAAK;AAC7B;AAkMO,IAAM,wBAAwB,CACnC,QACA,SACA,cAAsB,GACtB,mBAA2B,MACrB;AACN,QAAM,QAAQ,aAAa,QAAQ,aAAa,gBAAgB;AAChE,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,+BAAmB,+CAA+C;AAAA,MAC1E;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI;AACF,WAAO,QAAQ,MAAM,KAAK;AAAA,EAC5B,SAAS,OAAO;AACd,UAAM,IAAI,uBAAW,oBAAoB,iCAAiC;AAAA,MACxE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACpQA,IAAAC,eAA8D;AAG9D,IAAAC,gBAAmC;AA6G5B,IAAM,cAAN,MAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBvB,YACU,QACA,cACR;AAFQ;AACA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmCH,MAAM,YAAY,UAAkB,OAAuC;AACzE,UAAM,eAAe,KAAK,gBAAgB,KAAK;AAG/C,UAAM,WAAyB,CAAC;AAChC,QAAI;AAEJ,OAAG;AACD,YAAM,WAA2B,MAAM,KAAK,OAAO,SAAS;AAAA,QAC1D,OAAO;AAAA,QACP;AAAA,QACA;AAAA,MACF,CAAC;AAED,eAAS,KAAK,GAAG,SAAS,IAAI;AAC9B,eAAS,SAAS,cAAc,SAAS,aAAa;AAAA,IACxD,SAAS;AAET,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BA,gBAAgB,OAAwB;AACtC,UAAM,UAAU,SAAS,KAAK;AAC9B,QAAI,CAAC,QAAS,OAAM,IAAI,mCAAsB,OAAO;AAErD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiCA,MAAM,gBAAgB,UAAkB,OAAiC;AACvE,UAAM,eAAe,KAAK,gBAAgB,KAAK;AAE/C,UAAM,UAAU,MAAM,KAAK,OAAO,WAAW;AAAA,MAC3C,OAAO;AAAA,MACP;AAAA,IACF,CAAC;AAED,WAAO,QAAQ;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkCA,MAAM,oBAAoB,UAAkB,QAAgB,OAA+B;AACzF,UAAM,eAAe,KAAK,gBAAgB,KAAK;AAE/C,UAAM,eAAe,MAAM,KAAK,gBAAgB,UAAU,KAAK;AAE/D,QAAI,OAAO,YAAY,IAAI,OAAO,MAAM,GAAG;AACzC,YAAM,IAAI,oCAAuB,QAAQ,cAAc,EAAE,UAAU,QAAQ,aAAa,CAAC;AAAA,IAC3F;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4DA,MAAM,YACJ,UACA,QACA,UAAgC,CAAC,GACjC,OAC8B;AAC9B,UAAM,eAAe,KAAK,gBAAgB,KAAK;AAC/C,UAAM,QAAQ,MAAM,KAAK,YAAY,UAAU,KAAK;AAGpD,UAAM,iBAAiB,QAAQ,aAC3B,MAAM,OAAO,CAAC,MAAM,CAAC,QAAQ,YAAY,SAAS,EAAE,YAAY,CAAC,IACjE;AAEJ,QAAI,eAAe,WAAW,GAAG;AAC/B,YAAM,IAAI,oCAAuB,QAAQ,KAAK;AAAA,QAC5C;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,eAAe,OAAO,MAAM;AAGlC,mBAAe,KAAK,CAAC,GAAG,MAAM;AAC5B,YAAM,OAAO,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,OAAO;AACjD,aAAO,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK;AAAA,IAC1C,CAAC;AAGD,UAAM,aAAa,eAAe,KAAK,CAAC,MAAM,OAAO,EAAE,OAAO,MAAM,YAAY;AAChF,QAAI,YAAY;AACd,aAAO;AAAA,QACL,OAAO,CAAC,UAAU;AAAA,QAClB,cAAc;AAAA,QACd,eAAe;AAAA,QACf,eAAe;AAAA,MACjB;AAAA,IACF;AAGA,UAAM,aAAa,eAAe,KAAK,CAAC,MAAM,OAAO,EAAE,OAAO,IAAI,YAAY;AAC9E,QAAI,cAAc,CAAC,QAAQ,aAAa;AACtC,aAAO;AAAA,QACL,OAAO,CAAC,UAAU;AAAA,QAClB,cAAc,WAAW;AAAA,QACzB,eAAe;AAAA,QACf,eAAe;AAAA,MACjB;AAAA,IACF;AAGA,UAAM,gBAA8B,CAAC;AACrC,QAAI,eAAe;AAEnB,QAAI,QAAQ,gBAAgB;AAE1B,iBAAW,QAAQ,gBAAgB;AACjC,sBAAc,KAAK,IAAI;AACvB,wBAAgB,OAAO,KAAK,OAAO;AACnC,YAAI,gBAAgB,aAAc;AAAA,MACpC;AAAA,IACF,OAAO;AAEL,YAAM,YAAY,CAAC,GAAG,cAAc,EAAE,KAAK,CAAC,GAAG,MAAM;AACnD,cAAM,OAAO,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,OAAO;AACjD,eAAO,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK;AAAA,MAC1C,CAAC;AAED,iBAAW,QAAQ,WAAW;AAC5B,YAAI,gBAAgB,aAAc;AAClC,sBAAc,KAAK,IAAI;AACvB,wBAAgB,OAAO,KAAK,OAAO;AAAA,MACrC;AAAA,IACF;AAGA,QAAI,eAAe,cAAc;AAC/B,UAAI,QAAQ,cAAc;AACxB,eAAO;AAAA,UACL,OAAO;AAAA,UACP,cAAc,aAAa,SAAS;AAAA,UACpC,eAAe,cAAc,SAAS;AAAA,UACtC,eAAe;AAAA,QACjB;AAAA,MACF;AAEA,YAAM,IAAI,oCAAuB,QAAQ,aAAa,SAAS,GAAG;AAAA,QAChE;AAAA,QACA;AAAA,QACA,cAAc,aAAa,SAAS;AAAA,QACpC;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,cAAc,aAAa,SAAS;AAAA,MACpC,eAAe,cAAc,SAAS;AAAA,MACtC,eAAe,eAAe;AAAA,IAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwDA,MAAM,iBACJ,IACA,UACA,QACA,UAAgC,CAAC,GACjC,OACmB;AACnB,UAAM,eAAe,KAAK,gBAAgB,KAAK;AAG/C,YAAI,kCAAmB,QAAQ,MAAM,iBAAiB;AACpD,YAAM,CAAC,IAAI,IAAI,GAAG,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC;AAC7C,aAAO;AAAA,IACT;AAGA,UAAM,YAAY,MAAM,KAAK,YAAY,UAAU,QAAQ,SAAS,KAAK;AAEzE,QAAI,CAAC,UAAU,MAAM,CAAC,GAAG;AACvB,YAAM,IAAI,oCAAuB,QAAQ,KAAK;AAAA,QAC5C;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAGA,QAAI,UAAU,MAAM,WAAW,KAAK,CAAC,UAAU,eAAe;AAC5D,aAAO,GAAG,OAAO,UAAU,MAAM,CAAC,EAAE,YAAY;AAAA,IAClD;AAGA,QAAI,UAAU,MAAM,WAAW,KAAK,UAAU,eAAe;AAC3D,YAAM,CAAC,KAAK,IAAI,GAAG,WAAW,GAAG,OAAO,UAAU,MAAM,CAAC,EAAE,YAAY,GAAG,CAAC,MAAM,CAAC;AAClF,aAAO;AAAA,IACT;AAGA,UAAM,cAAc,GAAG,OAAO,UAAU,MAAM,CAAC,EAAE,YAAY;AAC7D,UAAM,aAAa,UAAU,MAAM,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,YAAY,CAAC;AAEhF,OAAG,WAAW,aAAa,UAAU;AAGrC,QAAI,UAAU,eAAe;AAC3B,YAAM,CAAC,KAAK,IAAI,GAAG,WAAW,aAAa,CAAC,MAAM,CAAC;AACnD,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AACF;;;AC1jBA,IAAAC,eAAsE;AAGtE,0BAA4B;AA4ErB,IAAM,kBAAkB,OAC7B,WACA,QACA,MACA,eACA,kBAC+B;AAC/B,QAAM,KAAK,IAAI,gCAAY;AAE3B,QAAM,eAAe,MAAM,QAAQ,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,KAAK;AAE1F,QAAM,SAAS,MAAM;AAAA,IAAI,CAAC,SACxB,OAAO,SAAS,WAAW,GAAG,OAAO,IAAI,IAAI,GAAG,KAAK,KAAK,QAAQ,CAAC;AAAA,EACrE;AAEA,KAAG,SAAS;AAAA,IACV,QAAQ;AAAA,IACR,WAAW;AAAA,IACX;AAAA,EACF,CAAC;AAED,MAAI;AAEF,UAAM,SAAS,MAAM,UAAU,2BAA2B;AAAA,MACxD,kBAAkB;AAAA,MAClB,QAAQ,iBAAiB;AAAA,IAC3B,CAAC;AAGD,QAAI,OAAO,QAAQ,OAAO,WAAW,WAAW;AAC9C,aAAO;AAAA,IACT,OAAO;AACL,YAAM,IAAI,oCAAuB,OAAO,kCAAkC,EAAE,OAAO,CAAC;AAAA,IACtF;AAAA,EACF,SAAS,OAAO;AACd,UAAM,6BAAgB,KAAK,OAAO,kCAAkC;AAAA,MAClE,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACvHA,IAAAC,eAKO;AACP,IAAAC,cAAwC;AAOxC,IAAAC,uBAAsD;AACtD,IAAAC,gBAAoC;AACpC,uBAA0B;AA8EnB,IAAM,kBAAkB,OAC7B,QACA,YACA,WAQI;AACJ,QAAM,EAAE,SAAS,UAAU,UAAU,kBAAkB,UAAU,WAAW,MAAM,IAAI;AACtF,QAAM,OAAO,OAAO,aAAa,QAAQ,SAAS,UAAU,QAAQ;AAEpE,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,2BAAc,qBAAqB,OAAO,IAAI,QAAQ,EAAE;AAAA,EACpE;AAEA,QAAM,gBAAgB,KAAK,YAAY,cAAc;AAErD,QAAM,cAAc,OAAO,UAAU,MAAM;AAE3C,QAAM,KAAK,IAAI,iCAAY;AAE3B,QAAM,gBAAgB,iBAAiB,WAAW;AAElD,QAAM,cAAc,IAAI,YAAY,OAAO,WAAW,aAAa;AAEnE,QAAM,YAAY,MAAM,YAAY,iBAAiB,IAAI,SAAS,QAAQ;AAE1E,SAAO;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,IACA,QAAQ,CAAC,OAAO,WAAW,eAAe,aAAa;AAAA,IACvD,MAAM;AAAA,MACJ,KAAK;AAAA,MACL,OAAO,UAAU;AAAA,MACjB;AAAA,MACA;AAAA,MACA,gBAAI,IAAI,EAAE,UAAU,QAAQ;AAAA,MAC5B,gBAAI,OAAO,gBAAI,IAAI,CAAC,EAAE,UAAU,gBAAgB;AAAA,MAChD,gBAAI,OAAO,gBAAI,OAAO,CAAC,EAAE,UAAU,QAAQ;AAAA,IAC7C;AAAA,IACA,eAAe,CAAC,KAAK,YAAY,UAAU,UAAU,KAAK,YAAY,WAAW,OAAO;AAAA,IACxF;AAAA,EACF;AACF;AAwGO,IAAM,mBAAmB,OAC9B,WACA,QACA,QACA,MACA,eACA,aACA,YACyC;AACzC,QAAM,KAAK,eAAe,IAAI,iCAAY;AAE1C,QAAM,eAAe,MAAM,QAAQ,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,KAAK;AAE1F,QAAM,SAAS,MAAM;AAAA,IAAI,CAAC,SACxB,OAAO,SAAS,WAAW,GAAG,OAAO,IAAI,IAAI,aAAa,OAAO,GAAG,KAAK,KAAK,QAAQ,CAAC,IAAI;AAAA,EAC7F;AAEA,KAAG,SAAS;AAAA,IACV,QAAQ;AAAA,IACR,WAAW;AAAA,IACX;AAAA,EACF,CAAC;AAED,MAAI,kBAAkB,QAAQ;AAC5B,UAAM,SAAS,MAAM,UAAU,0BAA0B;AAAA,MACvD;AAAA,MACA,aAAa;AAAA,MACb;AAAA,IACF,CAAC;AAED,QAAI,OAAO,SAAS,OAAO,WAAW,WAAW;AAC/C,aAAO;AAAA,IACT,OAAO;AACL,YAAM,IAAI,oCAAuB,OAAO,QAAQ,OAAO,SAAS,OAAO,OAAO,EAAE,OAAO,CAAC;AAAA,IAC1F;AAAA,EACF,OAAO;AACL,UAAM,SAAS,MAAM,OAAO,0BAA0B;AAAA,MACpD,aAAa;AAAA,IACf,CAAC;AAED,QAAI,CAAC,OAAO,QAAQ;AAClB,YAAM,IAAI,oCAAuB,WAAW;AAAA,IAC9C;AAEA,UAAM,SAAS,MAAM,UAAU,mBAAmB;AAAA,MAChD,QAAQ,OAAO;AAAA,MACf;AAAA,IACF,CAAC;AAED,QAAI,OAAO,SAAS,OAAO,WAAW,WAAW;AAC/C,YAAM,IAAI,oCAAuB,OAAO,QAAQ,OAAO,SAAS,OAAO,OAAO,EAAE,OAAO,CAAC;AAAA,IAC1F;AAEA,WAAO;AAAA,EACT;AACF;AA8EO,IAAM,qBAAqB,OAChC,WACA,eACA,QACA,MACA,eACA,aACA,gBAAwB,wCACM;AAC9B,QAAM,KAAK,eAAe,IAAI,iCAAY;AAE1C,QAAM,eAAe,MAAM,QAAQ,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,KAAK;AAE1F,QAAM,SAAS,MAAM;AAAA,IAAI,CAAC,SACxB,OAAO,SAAS,WAAW,GAAG,OAAO,IAAI,IAAI,aAAa,OAAO,GAAG,KAAK,KAAK,QAAQ,CAAC,IAAI;AAAA,EAC7F;AAEA,KAAG,SAAS;AAAA,IACV,QAAQ;AAAA,IACR,WAAW;AAAA,IACX;AAAA,EACF,CAAC;AAED,KAAG,UAAU,aAAa;AAE1B,MAAI;AAEF,UAAM,mBAAmB,MAAM,GAAG,MAAM,EAAE,QAAQ,UAAU,CAAC;AAG7D,UAAM,eAAe,MAAM,UAAU,uBAAuB;AAAA,MAC1D,kBAAkB;AAAA,IACpB,CAAC;AAED,QAAI,aAAa,QAAQ,OAAO,WAAW,WAAW;AACpD,YAAM,IAAI;AAAA,QACR,mBAAmB,aAAa,QAAQ,OAAO,KAAK;AAAA,QACpD;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,UACA,OAAO,aAAa,QAAQ,OAAO;AAAA,QACrC;AAAA,MACF;AAAA,IACF;AAGA,UAAM,UAAU,aAAa,QAAQ;AAGrC,UAAM,mBAAe,4BAAU,QAAQ,eAAe,EACnD,KAAK,QAAQ,WAAW,EACxB,MAAM,QAAQ,aAAa;AAG9B,UAAM,kBAAkB,aAAa,MAAM,aAAa;AAExD,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,gBAAgB,QAAQ,GAAG,2BAAU,UAAU;AAAA,IACzD;AAAA,EACF,QAAQ;AACN;AAAA,EACF;AACF;AA+BO,IAAM,mBAAmB,CAAC,WAA0C;AACzE,QAAM,UACJ,aAAa,SAAS,OAAO,UAAU,OAAO,eAAe;AAE/D,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,2BAAc,0BAA0B;AAAA,EACpD;AAEA,SAAO;AACT;;;AC7dA,IAAAC,eAAmC;AACnC,IAAAC,oBAA0B;AAC1B,IAAAC,gBAAmC;AAwC5B,IAAM,gCAAgC,CAAC,WAAmD;AAC/F,SAAO;AAAA;AAAA,IAEL,OAAO;AAAA,IACP,qBAAqB,OAAO;AAAA,IAC5B,iBAAiB;AAAA,MACf,MAAM,OAAO,OAAO,4BAA4B;AAAA,MAChD,OAAO;AAAA,IACT;AAAA,EACF;AACF;AAwCO,IAAM,6BAA6B,CACxC,QACA,iBACoB;AACpB,SAAO;AAAA,IACL,MAAM;AAAA,MACJ,MACE,eAAe,OAAO,SAAS,GAAG,QAClC,OAAO,UAAU,MAAM,UAAU,IAAI,CAAC,KACtC,OAAO;AAAA,MACT,YAAQ,kCAAmB,OAAO,SAAS;AAAA,MAC3C,WAAW,OAAO;AAAA,IACpB;AAAA,IACA,OAAO;AAAA,MACL,MACE,eAAe,OAAO,UAAU,GAAG,QACnC,OAAO,WAAW,MAAM,UAAU,IAAI,CAAC,KACvC,OAAO;AAAA,MACT,YAAQ,kCAAmB,OAAO,UAAU;AAAA,MAC5C,WAAW,OAAO;AAAA,IACpB;AAAA,EACF;AACF;AAkCO,IAAM,sCAAsC,CACjD,QACA,iBACsB;AACtB,SAAO,OAAO,IAAI,CAAC,SAAS,2BAA2B,KAAK,MAAM,YAAY,CAAC;AACjF;AA4CO,IAAM,6BAA6B,CACxC,QACA,WACA,YACA,eACoB;AACpB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,WAAO,6BAAU,OAAO,MAAM,KAAK,EAAE,UAAU,CAAC,eAAe,EAAE,QAAQ;AAAA,IACzE,gBAAY,6BAAU,OAAO,MAAM,MAAM,EAAE,MAAM,GAAS,EAAE,QAAQ;AAAA,IACpE,WAAW,cAAc;AAAA,EAC3B;AACF;AA4CO,IAAM,iCAAiC,CAC5C,QACA,WACA,eACoB;AACpB,MAAI,CAAC,OAAO,WAAW;AACrB,UAAM,IAAI,gCAAmB,4BAA4B;AAAA,EAC3D;AAEA,SAAO,2BAA2B,OAAO,WAAW,WAAW,YAAY,OAAO,WAAW;AAC/F;;;AC9QA,IAAAC,cAA6B;AAEtB,IAAM,mBAAmB;AAAA,EAC9B,aAAa,gBAAI,IAAI;AAAA,EACrB,eAAe,gBAAI,KAAK;AAAA,EACxB,aAAa,gBAAI,OAAO,gBAAI,OAAO,CAAC;AACtC;AAEO,IAAM,iBAAiB,IAAI,oBAAQ;AAAA,EACxC,MAAM;AAAA,EAEN,KAAK,QAAQ;AACX,UAAM,QAAQ,IAAI,WAAW,EAAE;AAC/B,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,YAAM,CAAC,IAAI,OAAO,MAAM;AAAA,IAC1B;AACA,WACE,OACA,MAAM,KAAK,KAAK,EACb,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAC1C,KAAK,EAAE;AAAA,EAEd;AAAA,EAEA,MAAM,OAAO,QAAQ;AAEnB,UAAM,MAAM,MAAM,WAAW,IAAI,IAAI,MAAM,MAAM,CAAC,IAAI;AAEtD,UAAM,YAAY,IAAI,SAAS,IAAI,GAAG;AAEtC,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,YAAM,OAAO,SAAS,UAAU,OAAO,IAAI,GAAG,CAAC,GAAG,EAAE;AACpD,aAAO,OAAO,IAAI;AAAA,IACpB;AAAA,EACF;AACF,CAAC;;;ACnCD,IAAAC,cAAoB;AAIb,IAAM,qBAAqB,gBAAI,OAAO,UAAU;AAAA,EACrD,uBAAuB,gBAAI,IAAI;AAAA,EAC/B,8BAA8B,gBAAI,IAAI;AACxC,CAAC;AAGM,IAAM,kBAAkB,gBAAI,OAAO,aAAa;AAAA,EACrD,WAAW,gBAAI,OAAO;AAAA,EACtB,YAAY,gBAAI,OAAO;AAAA,EACvB,gBAAgB,gBAAI,GAAG;AAAA,EACvB,iBAAiB,gBAAI,GAAG;AAC1B,CAAC;AAGM,IAAM,iBAAiB,gBAAI,OAAO,YAAY;AAAA,EACnD,MAAM,gBAAI,OAAO;AACnB,CAAC;AAGM,IAAM,gBAAgB,gBAAI,OAAO,WAAW;AAAA,EACjD,MAAM;AAAA,EACN,OAAO;AACT,CAAC;AAGM,IAAM,0BAA0B,gBAAI,OAAO,qBAAqB;AAAA,EACrE,MAAM;AAAA,EACN,MAAM;AACR,CAAC;AAGM,IAAM,2BAA2B,gBAAI,OAAO,uBAAuB;AAGnE,IAAM,iBAAiB,gBAAI,OAAO,YAAY;AAAA,EACnD,OAAO,gBAAI,KAAK;AAAA,EAChB,QAAQ,gBAAI,IAAI;AAClB,CAAC;AAGM,IAAM,kBAAkB,gBAAI,OAAO,aAAa;AAAA,EACrD,OAAO;AAAA,EACP,iBAAiB,gBAAI,IAAI;AAAA,EACzB,SAAS;AACX,CAAC;AAGM,IAAM,sBAAsB,gBAAI,OAAO,iBAAiB;AAAA,EAC7D,WAAW,gBAAI,OAAO,eAAe;AAAA,EACrC,aAAa,gBAAI,KAAK;AACxB,CAAC;;;ACrDD,IAAAC,cAAoB;AAYb,IAAM,qBAAqB,gBAAI,OAAO,UAAU;AAAA,EACrD,OAAO;AAAA,EACP,+BAA+B;AAAA,EAC/B,gCAAgC;AAAA,EAChC,sBAAsB,gBAAI,IAAI;AAAA,EAC9B,gBAAgB,gBAAI,IAAI;AAC1B,CAAC;AAGM,IAAM,eAAe,gBAAI,OAAO,UAAU;AAAA,EAC/C,mBAAmB,gBAAI,OAAO;AAAA,EAC9B,sBAAsB,gBAAI,OAAO,gBAAI,OAAO,CAAC;AAAA,EAC7C,gBAAgB,gBAAI,OAAO;AAAA,EAC3B,iBAAiB,gBAAI,KAAK;AAAA,EAC1B,eAAe,gBAAI,IAAI;AACzB,CAAC;AAGM,IAAM,uBAAuB,gBAAI,OAAO,kBAAkB;AAAA,EAC/D,QAAQ,gBAAI,OAAO,YAAY;AACjC,CAAC;AAGM,IAAM,wBAAwB,gBAAI,OAAO,mBAAmB;AAAA,EACjE,SAAS,gBAAI,OAAO,YAAY;AAClC,CAAC;AAGM,IAAM,iCAAiC,gBAAI,OAAO,4BAA4B;AAAA,EACnF,SAAS,gBAAI,OAAO,YAAY;AAAA,EAChC,GAAG;AACL,CAAC;AAGM,IAAM,6BAA6B,gBAAI,OAAO,wBAAwB;AAAA,EAC3E,UAAU,gBAAI,IAAI;AAAA,EAClB,WAAW,gBAAI,IAAI;AAAA,EACnB,cAAc,gBAAI,IAAI;AAAA,EACtB,iBAAiB,gBAAI,IAAI;AAAA,EACzB,iBAAiB,gBAAI,KAAK;AAAA,EAC1B,UAAU,gBAAI,IAAI;AAAA,EAClB,QAAQ,gBAAI,IAAI;AAAA,EAChB,cAAc,gBAAI,IAAI;AAAA,EACtB,YAAY,gBAAI,KAAK;AACvB,CAAC;;;ACxDD,IAAAC,cAAoB;AAIb,IAAM,iBAAiB,gBAAI,OAAO,YAAY;AAAA,EACnD,IAAI,gBAAI,OAAO;AAAA,EACf,gBAAgB,gBAAI,IAAI;AAAA,EACxB,gBAAgB,gBAAI,IAAI;AAAA,EACxB,iBAAiB,gBAAI,IAAI;AAAA,EACzB,oBAAoB,gBAAI,IAAI;AAAA,EAC5B,OAAO;AAAA,EACP,WAAW,gBAAI,KAAK;AACtB,CAAC;AAYM,IAAM,mBAAmB,gBAAI,OAAO,cAAc;AAAA,EACvD,cAAc,gBAAI,IAAI;AAAA,EACtB,uBAAuB,gBAAI,IAAI;AAAA,EAC/B,YAAY,gBAAI,IAAI;AAAA,EACpB,iBAAiB,gBAAI,IAAI;AAAA,EACzB,aAAa,gBAAI,IAAI;AAAA,EACrB,cAAc,gBAAI,IAAI;AACxB,CAAC;AAGM,IAAM,yBAAyB,gBAAI,OAAO,oBAAoB;AAAA,EACnE,cAAc,gBAAI,IAAI;AAAA,EACtB,uBAAuB,gBAAI,IAAI;AACjC,CAAC;AAGM,IAAM,0BAA0B,gBAAI,OAAO,qBAAqB;AAAA,EACrE,cAAc,gBAAI,IAAI;AAAA,EACtB,iBAAiB,gBAAI,IAAI;AAC3B,CAAC;;;ACRM,IAAM,gBAAgB,OAAO,WAAsD;AAMxF,QAAM,uBAAuB;AAE7B,QAAM,WAAW,MAAM;AAAA,IACrB,OAAO;AAAA,IACP,CAAC,OAAO,WAAW,qBAAqB,oBAAoB;AAAA,IAC5D,CAAC,OAAO,UAAU,MAAM;AAAA,EAC1B;AAEA,QAAM,SAAS,sBAAsB,UAAU,wBAAwB;AAEvE,SAAO,oCAAoC,QAAQ,OAAO,YAAY;AACxE;;;ACpDA,IAAAC,gBAAmC;AA8B5B,IAAM,YAAY,OAAO,WAA4C;AAE1E,QAAM,aAAa,MAAM,OAAO,uBAAuB;AAOvD,QAAM,qBAAkD,CAAC;AAGzD,aAAW,QAAQ,YAAY;AAC7B,2BAAmB,kCAAmB,KAAK,KAAK,MAAM,CAAC,IAAI;AAAA,MACzD,GAAG,KAAK;AAAA,MACR,YAAQ,kCAAmB,KAAK,KAAK,MAAM;AAAA,IAC7C;AACA,2BAAmB,kCAAmB,KAAK,MAAM,MAAM,CAAC,IAAI;AAAA,MAC1D,GAAG,KAAK;AAAA,MACR,YAAQ,kCAAmB,KAAK,MAAM,MAAM;AAAA,IAC9C;AAAA,EACF;AAEA,SAAO,OAAO,OAAO,kBAAkB,EAAE;AAAA,IACvC,CAAC,SACC,OAAO,aAAa,KAAK,MAAM;AAAA,IAE7B;AAAA,MACE,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,SAAS,OAAO,YAAY;AAAA,MAC5B,WAAO,kCAAmB,KAAK,MAAM;AAAA,MACrC,UAAU,KAAK;AAAA,MACf,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,EACN;AACF;;;AChCO,IAAM,kBAAkB,OAAO,WAAiD;AAMrF,QAAM,kBAAkB;AAExB,QAAM,WAAW,MAAM;AAAA,IACrB,OAAO;AAAA,IACP,CAAC,OAAO,WAAW,qBAAqB,eAAe;AAAA,IACvD,CAAC,OAAO,UAAU,MAAM;AAAA,EAC1B;AAEA,QAAM,SAAS,sBAAsB,UAAU,kBAAkB;AAEjE,SAAO,8BAA8B,MAAM;AAC7C;;;ACbO,IAAM,WAAW,OACtB,QACA,WACA,eAC6B;AAQ7B,QAAM,qBAAqB;AAE3B,QAAM,WAAW,MAAM;AAAA,IACrB,OAAO;AAAA,IACP,CAAC,OAAO,WAAW,qBAAqB,kBAAkB;AAAA,IAC1D,CAAC,OAAO,UAAU,MAAM;AAAA,IACxB,CAAC,WAAW,UAAU;AAAA,EACxB;AAEA,QAAM,SAAS,sBAAsB,UAAU,mBAAmB;AAElE,SAAO,+BAA+B,QAAQ,WAAW,UAAU;AACrE;;;AChEA,IAAAC,eAA0C;AAC1C,IAAAC,gBAAmC;AACnC,IAAAC,oBAA0B;AA4BnB,IAAM,YAAY,OAAO,WAA4C;AAC1E,QAAM,eAAe,MAAM,OAAO,UAAU,UAAU;AAAA,IACpD,IAAI,OAAO,UAAU;AAAA,IACrB,SAAS,EAAE,aAAa,KAAK;AAAA,EAC/B,CAAC;AAED,MAAI,CAAC,aAAa,MAAM,WAAW,aAAa,KAAK,QAAQ,aAAa,cAAc;AACtF,UAAM,IAAI,2BAAc,eAAe;AAAA,EACzC;AAGA,QAAM,gBAAqC,aAAa,KAAK,QAAQ,QAAgB,QACjF,QAAQ,IAAI;AAEhB,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,2BAAc,qCAAqC;AAAA,EAC/D;AAGA,QAAM,SAAkB,CAAC;AACzB,MAAI,SAAS;AAEb,SAAO,MAAM;AACX,UAAM,gBAAgB,MAAM,OAAO,UAAU,iBAAiB;AAAA,MAC5D,UAAU;AAAA,MACV;AAAA,MACA,OAAO;AAAA;AAAA,IACT,CAAC;AAGD,UAAM,gBAAgB,cAAc,KAAK;AAAA,MAAI,CAAC,UAC5C,OAAO,UAAU,sBAAsB;AAAA,QACrC,UAAU;AAAA,QACV,MAAM,MAAM;AAAA,MACd,CAAC;AAAA,IACH;AAEA,UAAM,eAAe,MAAM,QAAQ,IAAI,aAAa;AACpD,iBAAa,QAAQ,CAAC,KAAK,UAAU;AACnC,UAAI,IAAI,MAAM,SAAS,aAAa,cAAc;AAEhD,cAAM,SAAU,IAAI,KAAK,QAAQ,QAAgB,OAAO,QAAQ,OAAO;AAGvE,cAAM,UAAU,cAAc,KAAK,KAAK,GAAG,MAAM;AAEjD,YAAI,UAAU,SAAS;AACrB,iBAAO,KAAK;AAAA,YACV,eAAW,kCAAmB,QAAQ,KAAK,IAAI;AAAA,YAC/C,gBAAY,kCAAmB,QAAQ,MAAM,IAAI;AAAA,YACjD,WAAO,6BAAU,OAAO,KAAK,EAAE,UAAU,GAAG,EAAE,QAAQ;AAAA,YACtD,YAAY,OAAO;AAAA,UACrB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,CAAC;AAED,QAAI,CAAC,cAAc,YAAa;AAChC,aAAS,cAAc;AAAA,EACzB;AAEA,SAAO;AACT;;;AC5FA,IAAAC,eAAkD;AAmC3C,IAAM,6BAA6B,OACxC,QACA,YACA,QACA,gBAAwB,wCACM;AAC9B,QAAM,WAAW,MAAM,gBAAgB,QAAQ,YAAY,MAAM;AAEjE,SAAO,MAAM;AAAA,IACX,OAAO;AAAA,IACP,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT;AAAA,EACF;AACF;;;ACpDA,IAAAC,eAAuE;;;ACCvE,IAAAC,oBAA0B;AA+DnB,IAAM,8BAA8B,CACzC,YACA,wBACe;AAGf,SAAO;AAAA,IACL;AAAA,IACA,sBAAsB;AAAA;AAAA,IACtB,iBAAa,6BAAU,WAAW,YAAY,EAAE,IAAI,YAAY,EAAE,QAAQ;AAAA,IAC1E,WAAO,6BAAU,WAAW,UAAU,EAAE,IAAI,YAAY,EAAE,QAAQ;AAAA,IAClE,eAAe;AAAA;AAAA,IACf,KAAK,CAAC;AAAA;AAAA,IACN,gBAAY,6BAAU,WAAW,YAAY,EAAE,QAAQ;AAAA,EACzD;AACF;AAqIO,IAAM,qCAAqC,CAChD,mBACA,cACyB;AACzB,SAAO;AAAA,IACL,eAAe;AAAA,MACb,OAAO;AAAA,MACP,YAAQ,6BAAU,kBAAkB,YAAY,EAAE,QAAQ;AAAA,IAC5D;AAAA,IACA,iBAAa,6BAAU,kBAAkB,eAAe,EAAE,QAAQ;AAAA,EACpE;AACF;;;AD7MO,IAAM,uBAAuB,OAClC,QACA,oBACkC;AAMlC,QAAM,mCAAmC;AAEzC,QAAM,OAAO,OAAO,aAAa,MAAM,KAAK,CAAC,SAAS,KAAK,gBAAgB,eAAe;AAE1F,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,2BAAc,yBAAyB,eAAe,EAAE;AAAA,EACpE;AAEA,QAAM,oBAAoB,MAAM;AAAA,IAC9B,OAAO;AAAA,IACP,CAAC,OAAO,WAAW,aAAa,gCAAgC;AAAA,IAChE,CAAC,eAAe;AAAA,IAChB,CAAC,KAAK,SAAS;AAAA,EACjB;AAEA,QAAM,SAAS,sBAAsB,mBAAmB,uBAAuB;AAE/E,SAAO,mCAAmC,QAAQ,KAAK,SAAS;AAClE;;;AE7CA,IAAAC,eAA6D;AAkCtD,IAAM,gBAAgB,OAC3B,QACA,oBACwB;AAMxB,QAAM,2BAA2B;AAEjC,QAAM,OAAO,OAAO,aAAa,MAAM,KAAK,CAAC,SAAS,KAAK,gBAAgB,eAAe;AAE1F,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,2BAAc,yBAAyB,eAAe,EAAE;AAAA,EACpE;AAEA,QAAM,aAAa,MAAM;AAAA,IACvB,OAAO;AAAA,IACP,CAAC,OAAO,WAAW,aAAa,wBAAwB;AAAA,IACxD,CAAC,eAAe;AAAA,IAChB,CAAC,KAAK,SAAS;AAAA,EACjB;AAEA,QAAM,SAAS,sBAAsB,YAAY,gBAAgB;AAEjE,SAAO,4BAA4B,QAAQ,OAAO,UAAU,MAAM;AACpE;;;ACvBO,IAAM,uBAAuB,OAClC,QACA,WACA,eACwB;AACxB,QAAM,OAAO,MAAM,eAAe,QAAQ,WAAW,UAAU;AAE/D,SAAO,MAAM,cAAc,QAAQ,KAAK,WAAW;AACrD;;;ACjBO,IAAM,sBAAsB,OACjC,WACmD;AACnD,QAAM,SAAgD,CAAC;AAEvD,aAAW,QAAQ,OAAO,aAAa,OAAO;AAC5C,UAAM,gBAAgB,MAAM,qBAAqB,QAAQ,KAAK,WAAW;AACzE,WAAO,KAAK,WAAW,IAAI;AAAA,EAC7B;AAEA,SAAO;AACT;;;ACxCA,IAAAC,gBAA6D;AAYtD,IAAM,sBAAsB,OACjC,SACA,eAEqC;AACrC,QAAM,IAAI,kCAAoB,+BAA+B;AAC/D;;;AClBA,IAAAC,gBAAyC;AA6BlC,IAAM,iBAAiB,OAC5B,QACA,WACA,eACkB;AAElB,QAAM,SAAS,MAAM,OAAO,aAAa,QAAQ,YAAY,SAAS;AAEtE,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,4BAAc,QAAQ,8BAA8B,UAAU,QAAQ,SAAS,EAAE;AAAA,EAC7F;AAEA,SAAO;AACT;;;ACvBO,IAAM,cAAc,OAAO,WAA2C;AAE3E,SAAO,MAAM,OAAO,aAAa,SAAS;AAC5C;;;ACtBA,IAAAC,gBAAuD;AAYhD,IAAM,kBAAkB,OAAO,YAAkD;AACtF,QAAM,IAAI,kCAAoB,+BAA+B;AAC/D;;;ACbA,IAAAC,gBAA8B;AAC9B,IAAAC,oBAA0B;AA8QnB,IAAM,wCAAwC,CACnD,QACA,aACA,aACuB;AACvB,SAAO;AAAA,IACL;AAAA,IACA,WAAW,OAAO;AAAA,IAClB;AAAA,IACA,aAAa,OAAO;AAAA,IACpB,OAAO,OAAO;AAAA,IACd,0BAAsB,6BAAU,OAAO,eAAe,EAAE,IAAI,YAAY,EAAE,QAAQ;AAAA,IAClF,WAAW,OAAO;AAAA,EACpB;AACF;;;AC7RA,IAAAC,gBAAmC;AAI5B,IAAM,eAAN,MAAmB;AAAA,EACxB,YAAmB,OAAe;AAAf;AAAA,EAAgB;AAAA,EAEnC,QACE,SACA,UACA,WAA2B,OACH;AACxB,UAAM,wBAAoB,kCAAmB,OAAO;AACpD,UAAM,yBAAqB,kCAAmB,QAAQ;AAEtD,QAAI,aAAa,QAAQ;AAEvB,YAAM,kBAAoC,KAAK,MAAM;AAAA,QACnD,CAAC,SACC,KAAK,cAAc,qBAAqB,KAAK,YAAY,SAAS,kBAAkB;AAAA,MACxF;AAEA,UAAI,iBAAiB;AACnB,eAAO;AAAA,UACL,GAAG;AAAA,UACH,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAGA,UAAM,iBAAmC,KAAK,MAAM;AAAA,MAClD,CAAC,SACC,KAAK,cAAc,sBAAsB,KAAK,YAAY,SAAS,iBAAiB;AAAA,IACxF;AAEA,QAAI,gBAAgB;AAClB,aAAO;AAAA,QACL,GAAG;AAAA,QACH,WAAW;AAAA,MACb;AAAA,IACF;AAEA,QAAI,aAAa,OAAO;AAEtB,YAAM,kBAAoC,KAAK,MAAM;AAAA,QACnD,CAAC,SACC,KAAK,cAAc,qBAAqB,KAAK,YAAY,SAAS,kBAAkB;AAAA,MACxF;AAEA,UAAI,iBAAiB;AACnB,eAAO;AAAA,UACL,GAAG;AAAA,UACH,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAEA;AAAA,EACF;AAAA,EAEA,WAAmB;AACjB,WAAO,KAAK;AAAA,EACd;AACF;;;ACjEA,IAAAC,gBAAuD;AACvD,IAAAC,eAAoB;AACpB,IAAAC,iBAAoC;AAqC7B,IAAM,eAAe,OAC1B,QACA,EAAE,SAAS,UAAU,UAAU,SAAS,MACR;AAChC,QAAM,OAAO,OAAO,aAAa,QAAQ,SAAS,UAAU,QAAQ;AAEpE,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,4BAAc,QAAQ,8BAA8B,OAAO,QAAQ,QAAQ,EAAE;AAAA,EACzF;AAEA,QAAM,gBAAgB,KAAK,YAAY,uBAAuB;AAE9D,QAAM,WAAW,MAAM;AAAA,IACrB,OAAO;AAAA,IACP,CAAC,OAAO,WAAW,aAAa,aAAa;AAAA,IAC7C,CAAC,KAAK,aAAa,OAAO,UAAU,QAAQ,oCAAqB,iBAAI,IAAI,EAAE,UAAU,QAAQ,CAAC;AAAA,IAC9F,CAAC,KAAK,YAAY,UAAU,UAAU,KAAK,YAAY,WAAW,OAAO;AAAA,EAC3E;AAEA,QAAM,SAAS,sBAAsB,UAAU,0BAA0B;AAEzE,SAAO,sCAAsC,QAAQ,KAAK,aAAa,QAAQ;AACjF;;;ACTO,IAAM,cAAc,OACzB,QACA,YACA,WACqD;AACrD,QAAM,WAAW,MAAM,gBAAgB,QAAQ,YAAY,MAAM;AAEjE,QAAM,WAAW,MAAM;AAAA,IACrB,OAAO;AAAA,IACP,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,EAAE,aAAa,MAAM,YAAY,MAAM,oBAAoB,KAAK;AAAA,EAClE;AAEA,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,SAAS;AAAA,IACjB,WACG,SAAS,QAAQ,GAAG,CAAC,GAAG,aAAoD,YAAY,KACzF;AAAA,IACF,UAAU,WAAW;AAAA,EACvB;AACF;;;AjCYO,IAAM,gBAAN,cAA4B,yBAAgD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgHjF,YAAY,QAA0B;AACpC,UAAM,EAAE,cAAc,WAAW,gBAAgB,QAAQ,UAAU,IAAI,UAAU,CAAC;AAElF,UAAM,uBAAuB,gBAAgB;AAC7C,UAAM,qBAAqC,uBACvC,qBACA;AACJ,UAAM,mBAA8B,uBAAuB,mBAAmB;AAC9E,UAAM,mBAAmB,uBAAuB,mBAAmB;AACnE,UAAM,4BAA4B,uBAC9B,4BACA;AACJ,UAAM,0BAA0B,uBAC5B,0BACA;AACJ,UAAM,eAA6B,uBAAuB,gBAAgB;AAC1E,UAAM,QAAQ,uBAAuB,eAAe,CAAC;AAGrD,UAAM,cAA8B;AAAA,MAClC,IAAI,gBAAgB,aAAa,MAAM,mBAAmB;AAAA,MAC1D,MAAM,gBAAgB,aAAa,QAAQ,mBAAmB;AAAA,MAC9D,aAAa,gBAAgB,aAAa,eAAe,mBAAmB;AAAA,IAC9E;AACA,UAAM,YAAY,gBAAgB,aAAa;AAC/C,UAAM,qBAAqB,gBAAgB,sBAAsB;AACjE,UAAM,YAAuB;AAAA,MAC3B,QAAQ,gBAAgB,WAAW,UAAU,iBAAiB;AAAA,MAC9D,QAAQ,gBAAgB,WAAW,UAAU,iBAAiB;AAAA,IAChE;AACA,UAAM,mBAAmB,gBAAgB,oBAAoB;AAE7D,eAAW,QAAQ,OAAO,OAAO,gBAAgB,gBAAgB,CAAC,CAAC,GAAG;AACpE,mBAAa,KAAK,KAAK,IAAI;AAAA,IAC7B;AAEA,UAAM;AAAA,MACJ,gBAAgB;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAvJH;AAAA;AAAA;AAAA,wBAAgB;AAKhB;AAAA;AAAA;AAAA,wBAAO;AAKP;AAAA;AAAA;AAAA,wBAAO;AAKP;AAAA;AAAA;AAAA,wBAAO;AAKP;AAAA;AAAA;AAAA,wBAAO;AAOP;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAQ;AAMR;AAAA;AAAA;AAAA;AAAA,wBAAO;AAwHL,SAAK,cAAc;AACnB,SAAK,YAAY;AACjB,SAAK,qBAAqB;AAC1B,SAAK,SAAS;AACd,SAAK,YAAY,aAAa,IAAI,wBAAU,EAAE,KAAK,YAAY,YAAY,CAAC;AAC5E,SAAK,eAAe,IAAI,aAAa,KAAK;AAC1C,SAAK,gBAAgB,uBAAuB,SAAY;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBO,UAAU,WAA0D;AACzE,SAAK,SAAS,aAAa,KAAK;AAEhC,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI,oCAAsB,QAAQ;AAAA,IAC1C;AAEA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,kBAAyC;AACpD,UAAM,KAAK,kBAAkB;AAC7B,WAAO,MAAM,gBAAgB,IAAI;AAAA,EACnC;AAAA;AAAA,EAGA,MAAM,yBAAqD;AACzD,UAAM,KAAK,kBAAkB;AAC7B,WAAO,MAAM,cAAc,IAAI;AAAA,EACjC;AAAA;AAAA,EAGA,MAAM,SAAS,WAAmB,YAA8C;AAC9E,UAAM,KAAK,kBAAkB;AAC7B,WAAO,MAAM,SAAS,MAAM,WAAW,UAAU;AAAA,EACnD;AAAA;AAAA,EAGA,MAAM,eAAiC;AACrC,UAAM,KAAK,kBAAkB;AAC7B,WAAO,MAAM,UAAU,IAAI;AAAA,EAC7B;AAAA;AAAA,EAGA,MAAM,kBAAyC;AAC7C,UAAM,KAAK,kBAAkB;AAC7B,WAAO,MAAM,gBAAgB,IAAI;AAAA,EACnC;AAAA;AAAA,EAGA,MAAM,4BAA4E;AAChF,UAAM,KAAK,kBAAkB;AAC7B,WAAO,MAAM,oBAAoB,IAAI;AAAA,EACvC;AAAA;AAAA,EAGA,MAAM,mBAAmB,SAAoD;AAC3E,UAAM,KAAK,kBAAkB;AAC7B,WAAO,MAAM,oBAAoB,MAAM,OAAO;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,eAAe,WAAmB,YAAmC;AACzE,UAAM,KAAK,kBAAkB;AAC7B,WAAO,MAAM,eAAe,MAAM,WAAW,UAAU;AAAA,EACzD;AAAA;AAAA,EAGA,MAAM,cAA+B;AACnC,UAAM,KAAK,kBAAkB;AAC7B,WAAO,MAAM,YAAY,IAAI;AAAA,EAC/B;AAAA;AAAA,EAGA,MAAM,cAAc,qBAAkD;AACpE,UAAM,KAAK,kBAAkB;AAC7B,WAAO,MAAM,cAAc,MAAM,mBAAmB;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,qBAAqB,WAAmB,YAAyC;AACrF,UAAM,KAAK,kBAAkB;AAC7B,WAAO,MAAM,qBAAqB,MAAM,WAAW,UAAU;AAAA,EAC/D;AAAA;AAAA,EAGA,MAAM,qBAAqB,qBAA4D;AACrF,UAAM,KAAK,kBAAkB;AAC7B,WAAO,MAAM,qBAAqB,MAAM,mBAAmB;AAAA,EAC7D;AAAA;AAAA,EAGA,MAAM,YAA8B;AAClC,UAAM,KAAK,kBAAkB;AAC7B,WAAO,MAAM,UAAU,IAAI;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+BA,MAAM,KACJ,QACA,QACkD;AAClD,UAAM,KAAK,kBAAkB;AAC7B,WAAO,MAAM,YAAY,MAAM,QAAQ,MAAM;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA8BA,MAAM,oBACJ,QACA,QACA,eAC2B;AAC3B,UAAM,KAAK,kBAAkB;AAC7B,WAAO,MAAM,2BAA2B,MAAM,QAAQ,QAAQ,aAAa;AAAA,EAC7E;AAAA;AAAA,EAGA,MAAM,aAAa,QAA4D;AAC7E,WAAO,MAAM,aAAa,MAAM,MAAM;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAc,oBAAoB;AAChC,QAAI,CAAC,KAAK,eAAe;AACvB;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,aAAAC,QAAM,IAAI,KAAK,aAAa;AACnD,UAAM,EAAE,YAAY,WAAW,kBAAkB,QAAQ,MAAM,IAC5D,SAAS,QAMJ,CAAC;AAET,QAAI,CAAC,KAAK,aAAa,YAAY;AACjC,WAAK,YAAY;AAAA,IACnB;AAEA,QAAI,CAAC,KAAK,UAAU,OAAO,KAAK,KAAK,WAAW;AAC9C,WAAK,UAAU,SAAS;AAAA,IAC1B;AAEA,QAAI,CAAC,KAAK,sBAAsB,kBAAkB;AAChD,WAAK,qBAAqB;AAAA,IAC5B;AAEA,eAAW,QAAQ,OAAO,OAAO,MAAM,GAAG;AACxC,iBAAW,kBAAkB,OAAO,OAAO,KAAK,YAAY,GAAG;AAC7D,YAAI,KAAK,SAAS,eAAe,KAAK,GAAG;AACvC,eAAK,aAAa,IAAI,IAAI;AAAA,YACxB,GAAG;AAAA,YACH,OAAO;AAAA,UACT;AACA,iBAAO,KAAK,aAAa,eAAe,KAAK;AAC7C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,KAAK,aAAa,MAAM,WAAW,GAAG;AACxC,iBAAW,QAAQ,OAAO;AACxB,aAAK,aAAa,MAAM,KAAK;AAAA,UAC3B,aAAa,KAAK;AAAA,UAClB,eAAW,mCAAmB,KAAK,IAAI;AAAA,UACvC,aAAa,OAAO,OAAO,MAAM,EAC9B,IAAI,CAAC,iBAAa,mCAAmB,QAAQ,CAAC,EAC9C,OAAO,CAAC,aAAa,iBAAa,mCAAmB,KAAK,IAAI,CAAC;AAAA,QACpE,CAAC;AAAA,MACH;AAAA,IACF;AAEA,SAAK,gBAAgB;AAAA,EACvB;AACF;","names":["import_core","import_utils","import_utils","import_utils","import_core","import_utils","import_core","import_core","import_bcs","import_transactions","import_utils","import_core","import_bignumber","import_utils","import_bcs","import_bcs","import_bcs","import_bcs","import_utils","import_core","import_utils","import_bignumber","import_core","import_core","import_bignumber","import_core","import_core","import_core","import_core","import_core","import_bignumber","import_utils","import_core","import_bcs","import_utils","axios"]}