{"_rev":"4-70e960864b002103b5b0225a655e352c","time":{"created":"2026-02-26T08:13:23.199Z","modified":"2026-02-26T08:13:24.156Z","0.0.1":"2025-08-18T05:57:54.343Z","0.1.0":"2026-02-26T08:13:23.626Z"},"_id":"@dezswap/sdk","name":"@dezswap/sdk","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@dezswap/sdk","version":"0.1.0","description":"TypeScript SDK for interacting with Dezswap AMM protocol on XPLA Chain","exports":{".":{"@dezswap/source":"./src/index.ts","types":"./dist/index.d.ts","default":"./dist/index.js"},"./src/*":{"@dezswap/source":"./src/*.ts","types":"./dist/*.d.ts","default":"./dist/*.js"}},"repository":{"type":"git","url":"git+ssh://git@github.com/dezswap/sdk.git"},"keywords":["dezswap","dex","amm","xpla","cosmwasm","defi","typescript"],"author":{"name":"dezswap/engineer"},"bugs":{"url":"https://github.com/dezswap/sdk/issues"},"homepage":"https://github.com/dezswap/sdk#readme","license":"MIT","scripts":{"build":"tsdown","build:types":"pnpm codegen","codegen":"tsx scripts/codegen","g:factory":"cosmwasm-ts-codegen generate --plugin client --schema ./dezswap-contracts/contracts/dezswap_factory/schema --out ./src/generated --name DezswapFactory --no-bundle","g:pair":"cosmwasm-ts-codegen generate --plugin client --schema ./dezswap-contracts/contracts/dezswap_pair/schema --out ./src/generated --name DezswapPair --no-bundle","g:router":"cosmwasm-ts-codegen generate --plugin client --schema ./dezswap-contracts/contracts/dezswap_router/schema --out ./src/generated --name DezswapRouter --no-bundle","g:token":"cosmwasm-ts-codegen generate --plugin client --schema ./dezswap-contracts/contracts/dezswap_token/schema --out ./src/generated --name DezswapToken --no-bundle","test:unit":"vitest run __tests__/**/*.ts --config ./vitest.config.ts","test:integration":"sh scripts/test.sh --config ./vitest.config.ts","test":"pnpm test:unit && pnpm test:integration","test:ci":"pnpm test:unit && sh scripts/test.sh --config ./vitest.ci.config.ts","test:publish":"pnpm test:unit && sh scripts/publish-test.sh --config ./vitest.ci.config.ts","lint":"eslint src/**/*.ts --no-warn-ignored","lint:fix":"eslint src/**/*.ts --fix --no-warn-ignored","format":"prettier --write src/**/*.ts","format:check":"prettier --check src/**/*.ts","typecheck":"tsc -p src/generated/tsconfig.json && tsc -p tsconfig.json --noEmit","prepare":"husky","prepublishOnly":"pnpm test:ci"},"dependencies":{"@chain-registry/v2-types":"^0.53.146","@cosmjs/cosmwasm-stargate":"^0.36.0","@cosmjs/proto-signing":"^0.36.0","@cosmjs/tendermint-rpc":"^0.36.0","@interchainjs/cosmos":"^1.17.5","@interchainjs/cosmos-types":"^1.17.5","@interchainjs/encoding":"^1.17.5","@interchainjs/types":"^1.17.5","@xpla/xplajs":"1.8.0","bignumber.js":"^9.3.1","interchainjs":"^1.17.5","ky":"^1.9.0"},"devDependencies":{"@cosmwasm/ts-codegen":"^1.13.1","@eslint/js":"^9.31.0","@starship-ci/cli":"^3.10.0","@types/node":"^24.3.0","@typescript-eslint/eslint-plugin":"^8.37.0","@typescript-eslint/parser":"^8.37.0","commitizen":"^4.3.1","cz-conventional-changelog":"^3.3.0","dotenv":"^17.2.1","eslint":"^9.31.0","eslint-config-prettier":"^9.1.0","husky":"^9.1.7","prettier":"^3.6.2","rimraf":"^5.0.5","tsdown":"0.14.2","tsx":"^4.20.3","typescript":"^5.8.3","vitest":"^3.2.4"},"config":{"commitizen":{"path":"cz-conventional-changelog"}},"packageManager":"pnpm@10.5.0","engines":{"node":">=20"},"pnpm":{"overrides":{"rolldown":"1.0.0-beta.44"}},"publishConfig":{"access":"public"},"gitHead":"6d4a553ad70ab69af4c40fe17fcc0ad96025881a","_id":"@dezswap/sdk@0.1.0","_nodeVersion":"24.13.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-Gjgeox3b/tycPD4BKCh4Tum7o9OQsSnrHynLqtm5OOV0YcIwLZdaJu9Q+UNYoD+Fy5Sp3to4pbWLHAgBzOtq9A==","shasum":"225ff9ea8b3f2b2cfe98344c8acacfffef265fb0","tarball":"https://registry.npmjs.org/@dezswap/sdk/-/sdk-0.1.0.tgz","fileCount":179,"unpackedSize":798247,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD+8p1fw2UBG8qnX/117mJaq5FdF2gxC+hMYB9YiXFUGAIgP546A9fXaVkSLjthYVW6Vy+W7mhHS3Soj3PyJLuHiyY="}]},"_npmUser":{"name":"jaemin-delightlabs","email":"jaemin@delightlabs.io"},"directories":{},"maintainers":[{"name":"nowooj","email":"joowon@delightlabs.io"},{"name":"jaemin-delightlabs","email":"jaemin@delightlabs.io"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk_0.1.0_1772093603340_0.5612362953431129"},"_hasShrinkwrap":false}},"maintainers":[{"name":"nowooj","email":"joowon@delightlabs.io"},{"name":"jaemin-delightlabs","email":"jaemin@delightlabs.io"}],"description":"TypeScript SDK for interacting with Dezswap AMM protocol on XPLA Chain","homepage":"https://github.com/dezswap/sdk#readme","keywords":["dezswap","dex","amm","xpla","cosmwasm","defi","typescript"],"repository":{"type":"git","url":"git+ssh://git@github.com/dezswap/sdk.git"},"author":{"name":"dezswap/engineer"},"bugs":{"url":"https://github.com/dezswap/sdk/issues"},"license":"MIT","readme":"# @dezswap/sdk\n\nTypeScript SDK for interacting with Dezswap DEX on XPLA Chain, a CosmWasm-based decentralized exchange.\n\n## Installation\n\n```bash\nnpm install @dezswap/sdk\n# or\npnpm add @dezswap/sdk\n```\n\n## Quick Start\n\n### Query Data\n\n```typescript\nimport { DezswapQueryClient, MAINNET_CONFIG } from '@dezswap/sdk'\n\n// Connect to Dezswap on XPLA mainnet\nconst client = await DezswapQueryClient.connectWithConfig(\n  'https://dimension-rpc.xpla.dev',\n  MAINNET_CONFIG\n)\n\n// Query token information\nconst { natives, tokens } = await client.tokens({})\nconsole.log('Native tokens:', natives)\nconsole.log('Available tokens:', tokens)\n\n// Query liquidity pools\nconst pools = await client.pools({ limit: 10 })\nconsole.log('Liquidity pools:', pools)\n```\n\n### Execute Transactions\n\n```typescript\nimport { DezswapClient, DezswapQueryClient, MAINNET_CONFIG } from '@dezswap/sdk'\nimport { DirectSigner } from '@interchainjs/cosmos'\n\n// Create query client first\nconst queryClient = await DezswapQueryClient.connectWithConfig(\n  'https://dimension-rpc.xpla.dev',\n  MAINNET_CONFIG\n)\n\n// Create signing client\nconst signingClient = await DezswapClient.create(directSigner, queryClient)\n\n// Find pair contract address\nconst pairInfo = await queryClient.pair('axpla', tokenAddress)\n\n// Execute swap\nconst result = await signingClient.swap({\n  pairContract: pairInfo.contract_addr,\n  amount: '1000000',\n  offerAsset: 'axpla',\n  fee: {\n    amount: [{ denom: 'axpla', amount: '10000' }],\n    gas: '500000'\n  }\n})\n\nconsole.log('Swap executed:', result)\n```\n\n## API Reference\n\n### DezswapQueryClient\n\nThe main class for querying Dezswap protocol data.\n\n### DezswapClient\n\nThe signing client for executing transactions on Dezswap protocol.\n\n#### Connection\n\n```typescript\nimport { DezswapClient } from '@dezswap/sdk'\nimport { DirectSigner } from '@interchainjs/cosmos'\n\n// Create query client and signing client\nconst queryClient = await DezswapQueryClient.connectWithConfig(rpcUrl, config)\nconst signingClient = await DezswapClient.create(directSigner, queryClient)\n```\n\n#### Transaction Signing\n\n```typescript\n// Sign a transaction\nconst signed = await signingClient.sign({\n  messages: [swapMessage],\n  fee: {\n    amount: [{ denom: 'axpla', amount: '5000' }],\n    gas: '500000'\n  },\n  memo: 'Swap transaction',\n  options: { signerAddress }\n})\n```\n\n#### Transaction Broadcasting\n\n```typescript\n// Broadcast signed transaction\nconst result = await signingClient.broadcast({\n  signed,\n  options: { mode: 'sync' }\n})\n\nconsole.log('Transaction hash:', result.transactionHash)\n```\n\n#### Swap Execution\n\nThe SDK automatically generates `funds` based on the offer asset type:\n- **Native tokens** (like `axpla`): Automatically attaches the specified amount as funds\n- **CW20 tokens** (contract addresses starting with `xpla1...`): No funds needed (uses allowance mechanism)\n\n```typescript\n// Execute swap - funds are automatically generated\nconst swapResult = await signingClient.swap({\n  pairContract: 'xpla1...',  // Pair contract address\n  amount: '1000000',\n  offerAsset: 'axpla',       // Offer asset\n  fee: {\n    amount: [{ denom: 'axpla', amount: '10000' }],\n    gas: '500000'\n  },\n  maxSpread: '0.1',          // 10% max slippage\n  beliefPrice: '1.5'         // Expected price\n})\n\n// Wait for transaction completion\nconst finalResult = await swapResult.wait()\nconsole.log('Swap completed:', finalResult.code === 0)\n```\n\n#### Fee Token Payment\n\nPay transaction fees using any supported CW20 or native token (including IBC tokens) instead of XPLA. The SDK automatically:\n- Estimates gas for both swap and original messages\n- Queries dynamic gas price from the feemarket module\n- Calculates required token amount using reverse simulation\n- Finds optimal route including multi-hop when direct pairs are unavailable\n\n```typescript\n// CW20 token fee payment (amount is auto-calculated)\nconst { messages, fee } = await signingClient.createMsgWithFeeToken({\n  msg: swapMessage,           // Original transaction message\n  feeToken: 'xpla1...'        // CW20 token contract address\n})\n\n// Native token (IBC) fee payment\nconst { messages, fee } = await signingClient.createMsgWithFeeToken({\n  msg: swapMessage,\n  feeToken: 'ibc/27394FB...'  // IBC token denom\n})\n\n// With custom slippage tolerance (default: 1%)\nconst { messages, fee } = await signingClient.createMsgWithFeeToken({\n  msg: swapMessage,\n  feeToken: 'xpla1...',\n  slippageTolerance: 0.05  // 5% slippage for volatile markets\n})\n\n// The result contains:\n// - messages: [swap message, original message]\n// - fee: calculated StdFee with gas and amount\nconsole.log(`Generated ${messages.length} messages`)\nconsole.log(`Fee: ${fee.amount[0].amount} ${fee.amount[0].denom}`)\n\n// Sign and broadcast with the calculated fee\nconst signed = await signingClient.sign({\n  messages,\n  fee,  // Use the calculated fee\n  memo: 'Transaction with fee token payment'\n})\n\nconst result = await signingClient.broadcast({ signed })\n```\n\n#### DezswapQueryClient Connection\n\n```typescript\n// Connect with predefined config\nimport { MAINNET_CONFIG, TESTNET_CONFIG } from '@dezswap/sdk'\n\nconst client = await DezswapQueryClient.connectWithConfig(\n  'https://dimension-rpc.xpla.dev',  // RPC endpoint\n  MAINNET_CONFIG                     // or TESTNET_CONFIG\n)\n\n// Connect with custom config including API integration\nconst customConfig = {\n  factory: { address: 'xpla1...' },\n  router: { address: 'xpla1...' },\n  endpoint: { api: 'https://api-endpoint.com' }  // Optional for market data\n}\nconst client = await DezswapQueryClient.connectWithConfig(rpcUrl, customConfig)\n```\n\n#### Token Queries\n\n```typescript\n// Get all tokens (basic info)\nconst { natives, tokens } = await client.tokens({})\n\n// Get tokens with detailed information\nconst { natives, tokens } = await client.tokens({ detail: true })\n\n// Get tokens with pagination (startAfter uses pair's asset_infos)\nconst { natives, tokens } = await client.tokens({\n  limit: 50,\n  startAfter: [\n    { native_token: { denom: 'axpla' } },\n    { token: { contract_addr: 'xpla1...' } }\n  ]  // [AssetInfo, AssetInfo] tuple representing the last pair\n})\n\n// Get native token decimals\nconst nativeInfo = await client.nativeTokenDecimals({ denom: 'axpla' })\n```\n\n#### Pool Queries\n\n```typescript\n// Get all liquidity pools\nconst pools = await client.pools({})\n\n// Get pools with market data (APR, TVL, volume, fee, price ratio)\nconst poolsWithDetail = await client.pools({ detail: true })\n\n// Get pools with pagination\nconst pools = await client.pools({\n  limit: 20,\n  startAfter: [\n    { native_token: { denom: 'axpla' } },\n    { token: { contract_addr: 'xpla1...' } }\n  ]  // [AssetInfo, AssetInfo] tuple\n})\n\n// Get specific pair information\nconst pairInfo = await client.pair('axpla', tokenAddress)\n\n// Get all pairs\nconst pairs = await client.pairs({ limit: 100 })\n```\n\n#### Route Finding & Swaps\n\n```typescript\n// Find all possible routes between two assets\nconst routes = await client.findRoutes({\n  offerAssetInfo: { native_token: { denom: 'axpla' } },\n  askAssetInfo: { token: { contract_addr: 'xpla1...' } },\n  maxHops: 3\n})\n\nconsole.log(`Found ${routes.length} routes`)\nconsole.log(`First route has ${routes[0].operations.length} operations`)\n\n// Find optimal route with best expected return\nconst optimal = await client.findOptimalRoute({\n  offerAssetInfo: { native_token: { denom: 'axpla' } },\n  askAssetInfo: { token: { contract_addr: 'xpla1...' } },\n  offerAmount: '1000000000000000000', // 1 XPLA (10^18 axpla)\n  maxHops: 3\n})\n\nconsole.log(`Expected output: ${optimal.simulation.resultAmount}`)\nconsole.log(`Route has ${optimal.routes.length} operations`)\n\n// amounts array: input amount for each swap operation (for reference only)\n// Router contract only needs operations + minimum_receive (resultAmount)\nconsole.log(`Input to each operation: ${optimal.simulation.amounts}`)\n\n// Example: Multi-hop swap (XPLA → TokenA → TokenB)\n// amounts = ['1000000', '800000']  ← Input to each operation (reference)\n// resultAmount = '750000'          ← Final output (used as minimum_receive)\n\n// Simulate swap operations\nconst simulation = await client.simulateSwapOperations({\n  offerAmount: '1000000000000000000', // 1 XPLA\n  operations: optimal.routes // optimal.routes is SwapOperation[] type\n})\n\nconsole.log(`Expected output: ${simulation.amount}`)\n\n// Reverse simulate - find required input for desired output\nconst reverseSimulation = await client.reverseSimulateSwapOperations({\n  askAmount: '500000',\n  operations: optimal.routes\n})\n\nconsole.log(`Required input: ${reverseSimulation.amount}`)\n```\n\n#### Configuration Access\n\n```typescript\n// Access factory configuration\nconst config = client.config\nconsole.log('Factory address:', config.factory.address)\nconsole.log('Router address:', config.router.address)\n```\n\n### Network Configurations\n\n#### Mainnet (dimension_37-1)\n```typescript\nimport { MAINNET_CONFIG } from '@dezswap/sdk'\n\nconst RPC_URL = 'https://dimension-rpc.xpla.dev'\nconst client = await DezswapQueryClient.connectWithConfig(RPC_URL, MAINNET_CONFIG)\n\n// With API integration for market data\nconst clientWithApi = await DezswapQueryClient.connectWithConfig(RPC_URL, {\n  ...MAINNET_CONFIG,\n  endpoint: { api: 'https://dimension-api.dezswap.io' }\n})\n```\n\n#### Testnet (cube_47-5)\n```typescript\nimport { TESTNET_CONFIG } from '@dezswap/sdk'\n\nconst RPC_URL = 'https://cube-rpc.xpla.dev'\nconst client = await DezswapQueryClient.connectWithConfig(RPC_URL, TESTNET_CONFIG)\n\n// With API integration for market data\nconst clientWithApi = await DezswapQueryClient.connectWithConfig(RPC_URL, {\n  ...TESTNET_CONFIG,\n  endpoint: { api: 'https://cube-api.dezswap.io' }\n})\n```\n\n### Types\n\n```typescript\n// Token information\ninterface TokenInfo {\n  contract_address: string\n  decimals: number\n  name?: string\n  symbol?: string\n  total_supply?: string\n}\n\n// Asset identifier\ntype AssetInfo =\n  | { native_token: { denom: string } }  // For native tokens like XPLA\n  | { token: { contract_addr: string } } // For CW20 tokens\n\n// Asset information\ninterface Asset {\n  amount: string        // Amount of the asset\n  info: AssetInfo      // Asset identifier (native_token or token)\n}\n\n// Pool information\ninterface PoolInfo {\n  address: string\n  assets: [Asset, Asset]\n  total_share: string\n  // Optional market data (when detail=true)\n  apr?: number\n  fee?: string\n  tvl?: string\n  volume?: string\n  priceRatio?: PriceRatio\n}\n\n// Price ratio information\ninterface PriceRatio {\n  base: string      // Base asset identifier\n  currency: string  // Currency asset identifier  \n  rate: string      // Exchange rate (1 base = rate currency)\n}\n\n// Pair information\ninterface PairInfo {\n  contract_addr: string\n  liquidity_token: string\n  asset_infos: AssetInfo[]\n  asset_decimals: number[]\n}\n\n// Swap input parameters\ninterface SwapInput {\n  pairContract: string         // Pair contract address\n  amount: string               // Offer amount\n  offerAsset: string           // Offer asset identifier\n\n  beliefPrice?: string         // Expected price\n  deadline?: number            // Transaction deadline\n  maxSpread?: string           // Maximum slippage tolerance\n  recipient?: string           // Recipient address\n\n  fee?: number | StdFee | 'auto'  // Fee options\n  memo?: string                // Transaction memo\n}\n\n// Transaction signing parameters\ninterface SignInput {\n  messages: any[]              // Messages to sign\n  fee: StdFee | 'auto'        // Fee or auto estimation\n  memo?: string               // Transaction memo\n  options?: {                 // Signing options\n    signerAddress?: string\n  }\n}\n\n// Broadcasting parameters\ninterface BroadcastInput {\n  signed: CosmosSignedTransaction  // Signed transaction\n  options?: {                      // Broadcast options\n    mode?: 'sync' | 'async' | 'commit'\n  }\n}\n```\n\n## Examples\n\n### Basic Swap Execution (Based on Integration Tests)\n\n```typescript\nimport { DezswapClient, DezswapQueryClient, MAINNET_CONFIG } from '@dezswap/sdk'\nimport { DirectSigner } from '@interchainjs/cosmos'\n\nasync function executeBasicSwap(directSigner: DirectSigner) {\n  // Create clients\n  const queryClient = await DezswapQueryClient.connectWithConfig(\n    'https://dimension-rpc.xpla.dev',\n    MAINNET_CONFIG\n  )\n  const signingClient = await DezswapClient.create(directSigner, queryClient)\n\n  // Find pair contract address (like in tests)\n  const pairInfo = await queryClient.pair('axpla', tokenAddress)\n\n  // Get pool balance before swap for verification\n  const poolsBefore = await queryClient.pools({})\n  const poolBefore = poolsBefore.find(\n    pool => pool.address === pairInfo.contract_addr\n  )\n\n  // Execute swap (exact pattern from test)\n  const swapInput = {\n    pairContract: pairInfo.contract_addr,\n    amount: '10000',\n    fee: {\n      amount: [{ denom: 'axpla', amount: '10000' }],\n      gas: '5000000',\n    },\n    offerAsset: 'axpla',\n  }\n\n  const result = await signingClient.swap(swapInput)\n\n  // Wait for transaction completion\n  const finalResult = await (result as any).wait()\n  if (finalResult.code === 0) {\n    console.log('✅ Swap successful!')\n\n    // Verify pool balance changed\n    const poolsAfter = await queryClient.pools({})\n    const poolAfter = poolsAfter.find(\n      pool => pool.address === pairInfo.contract_addr\n    )\n\n    console.log('Pool balances changed:',\n      poolBefore?.assets[0].amount !== poolAfter?.assets[0].amount)\n  }\n\n  return finalResult\n}\n```\n\n### Transaction Signing (Based on Test Pattern)\n\n```typescript\nimport {\n  DezswapClient,\n  DezswapQueryClient,\n  DezswapPairMsgComposer,\n  MAINNET_CONFIG\n} from '@dezswap/sdk'\nimport { DirectSigner } from '@interchainjs/cosmos'\n\nasync function signSwapTransaction(directSigner: DirectSigner) {\n  const queryClient = await DezswapQueryClient.connectWithConfig(\n    'https://dimension-rpc.xpla.dev',\n    MAINNET_CONFIG\n  )\n  const signingClient = await DezswapClient.create(directSigner, queryClient)\n  const accounts = await directSigner.getAccounts()\n  const signerAddress = accounts[0]?.address!\n\n  // Create message using msg composer (like in tests)\n  const pairMsgComposer = new DezswapPairMsgComposer(\n    signerAddress,\n    validPairContract\n  )\n\n  const swapMsg = pairMsgComposer.swap(\n    {\n      offerAsset: {\n        info: { native_token: { denom: 'axpla' } },\n        amount: '1000',\n      },\n      maxSpread: '0.1',\n    },\n    [{ denom: 'axpla', amount: '1000' }]\n  )\n\n  // Sign transaction\n  const signInput = {\n    messages: [swapMsg],\n    fee: {\n      amount: [{ denom: 'axpla', amount: '5000' }],\n      gas: '5000000',\n    },\n    memo: 'test signing',\n    options: { signerAddress },\n  }\n\n  const result = await signingClient.sign(signInput)\n  console.log('Transaction signed:', !!result.signature)\n\n  return result\n}\n```\n\n### Monitor Transaction Status\n\n```typescript\nasync function monitorSwapTransaction(\n  signingClient: DezswapClient,\n  swapParams: any\n) {\n  console.log('Executing swap...')\n  const result = await signingClient.swap(swapParams)\n\n  console.log('Transaction submitted, waiting for confirmation...')\n  const finalResult = await result.wait()\n\n  if (finalResult.code === 0) {\n    console.log('✅ Swap successful!')\n    console.log('Transaction hash:', finalResult.transactionHash)\n\n    // Parse events for swap details\n    const swapEvents = finalResult.events?.filter(\n      event => event.type === 'wasm'\n    )\n    console.log('Swap events:', swapEvents)\n  } else {\n    console.log('❌ Swap failed!')\n    console.log('Error:', finalResult.rawLog)\n  }\n\n  return finalResult\n}\n```\n\n### Get Pool Analytics with Market Data\n\n```typescript\nimport { DezswapQueryClient, MAINNET_CONFIG } from '@dezswap/sdk'\n\nasync function getPoolAnalytics() {\n  const client = await DezswapQueryClient.connectWithConfig(\n    'https://dimension-rpc.xpla.dev',\n    {\n      ...MAINNET_CONFIG,\n      endpoint: { api: 'https://dimension-api.dezswap.io' }\n    }\n  )\n  \n  // Get all tokens with details\n  const { tokens } = await client.tokens({ detail: true })\n  \n  // Get pools with market data\n  const pools = await client.pools({ detail: true })\n  \n  // Analyze each pool\n  for (const pool of pools) {\n    console.log(`\\n--- Pool: ${pool.address} ---`)\n    console.log(`Assets: ${pool.assets.map(a => a.amount).join(' / ')}`)\n    console.log(`LP Tokens: ${pool.total_share}`)\n    \n    // Market data (only available with API integration)\n    if (pool.apr) console.log(`APR: ${pool.apr}%`)\n    if (pool.tvl) console.log(`TVL: $${pool.tvl}`)\n    if (pool.volume) console.log(`24h Volume: $${pool.volume}`)\n    if (pool.fee) console.log(`Fee: ${pool.fee}`)\n    \n    // Price ratio\n    if (pool.priceRatio) {\n      const { base, currency, rate } = pool.priceRatio\n      console.log(`Price: 1 ${base} = ${rate} ${currency}`)\n    }\n  }\n}\n```\n\n### Find Trading Pairs\n\n```typescript\nasync function findTradingPairs(tokenAddress: string) {\n  const client = await DezswapQueryClient.connectWithConfig(\n    'https://dimension-rpc.xpla.dev',\n    MAINNET_CONFIG\n  )\n  \n  // Get specific pair with native token\n  const nativePair = await client.pair('axpla', tokenAddress)\n  if (nativePair) {\n    console.log('Native pair found:', nativePair.contract_addr)\n  }\n  \n  // Find all pairs containing this token\n  const allPairs = await client.pairs({})\n  const relevantPairs = allPairs.filter(pair => \n    pair.asset_infos.some(asset => \n      'token' in asset && asset.token.contract_addr === tokenAddress\n    )\n  )\n  \n  console.log(`Found ${relevantPairs.length} pairs for token ${tokenAddress}`)\n}\n```\n\n### Monitor Pool Price Changes\n\n```typescript\nasync function monitorPoolPrices() {\n  const client = await DezswapQueryClient.connectWithConfig(\n    'https://dimension-rpc.xpla.dev',\n    {\n      ...MAINNET_CONFIG,\n      endpoint: { api: 'https://dimension-api.dezswap.io' }\n    }\n  )\n  \n  // Get pools with price information\n  const pools = await client.pools({ detail: true, limit: 5 })\n  \n  // Display price ratios\n  pools.forEach(pool => {\n    if (pool.priceRatio) {\n      const { base, currency, rate } = pool.priceRatio\n      console.log(`${pool.address}: 1 ${base} = ${rate} ${currency}`)\n    }\n    \n    if (pool.apr) {\n      console.log(`  APR: ${pool.apr}%`)\n    }\n    \n    if (pool.tvl && pool.volume) {\n      console.log(`  TVL: $${pool.tvl} | Volume: $${pool.volume}`)\n    }\n  })\n}\n```\n\n### Handle API Unavailability\n\n```typescript\nasync function robustPoolQuery() {\n  // Without API endpoint - falls back to contract calls\n  const contractOnlyClient = await DezswapQueryClient.connectWithConfig(\n    'https://dimension-rpc.xpla.dev',\n    MAINNET_CONFIG  // No endpoint.api configured\n  )\n  \n  // This will work but won't include market data\n  const pools = await contractOnlyClient.pools({ detail: true })\n  \n  pools.forEach(pool => {\n    console.log(`Pool: ${pool.address}`)\n    console.log(`Assets: ${pool.assets.length}`)\n    console.log(`LP Supply: ${pool.total_share}`)\n    // apr, tvl, volume, priceRatio will be undefined\n  })\n}\n```\n\n---\n\n## Development\n\nThis section is for contributors and developers working on the SDK itself.\n\n### Prerequisites\n\n- Node.js ≥20.0.0\n- pnpm ≥10.0.0\n- Docker (for integration testing)\n\n### Setup\n\n```bash\n# Clone with submodules\ngit clone --recurse-submodules https://github.com/dezswap/sdk.git\ncd sdk\npnpm install\n\n# Setup Git hooks\npnpm prepare\n```\n\nThe `--recurse-submodules` flag is required to clone the `dezswap-contracts` submodule containing contract schemas.\n\n### Build System\n\nThe SDK uses a dual build system for maximum compatibility:\n\n```bash\n# Full build (ESM + CommonJS)\npnpm build\n\n# Generate contract types  \npnpm build:types\npnpm codegen        # Same as build:types\n```\n\n### Code Generation\n\nGenerate TypeScript clients from CosmWasm contract schemas:\n\n```bash\n# Generate all contract clients\npnpm codegen\n\n# Generate individual contracts\npnpm g:factory      # DezswapFactory\npnpm g:pair         # DezswapPair  \npnpm g:router       # DezswapRouter\npnpm g:token        # DezswapToken\n```\n\n### Testing\n\n#### Prerequisites\n\nDownload contract artifacts before running tests:\n\n```bash\n# Downloads WASM files to artifacts/ directory\nbash download-contracts.sh\n```\n\n#### Running Tests\n\nThe SDK uses Starship for integration testing with a local XPLA blockchain:\n\n```bash\n# Complete test suite with automatic environment management\npnpm test\n\n# Test variants\npnpm test:ci        # CI configuration with vitest.ci.config.ts\npnpm test:publish   # Test with packaged version\n```\n\n#### Manual Environment Control\n\n```bash\n# Start Starship environment\npnpm --filter=sdk-on-starship start\n\n# Stop Starship environment  \npnpm --filter=sdk-on-starship clean\n```\n\n### Development Commands\n\n```bash\n# Code quality\npnpm lint           # ESLint checking\npnpm lint:fix       # Auto-fix linting issues  \npnpm format         # Prettier formatting\npnpm format:check   # Check formatting\npnpm typecheck      # TypeScript type checking\n\n# Contract management\nsh scripts/download-contracts.sh    # Download contract artifacts\n\n# Publishing\npnpm prepublishOnly # Test and build before publishing\n```\n\n### Project Structure\n\n```\nsrc/\n├── generated/          # Auto-generated contract clients\n├── types/             # TypeScript type definitions\n├── constants.ts       # Network configurations\n├── interface.ts       # Public API interface\n├── sdk.ts            # Main SDK implementation\n└── index.ts          # Public exports\n\nscripts/              # Build and automation scripts\n├── build.sh          # Build automation\n├── test.sh           # Test automation\n├── pack.sh           # Package creation\n└── download-contracts.sh  # Contract artifact download\n\nstarship/             # Integration test environment\n├── __tests__/        # Test suites\n├── utils/           # Test utilities\n└── configs/         # Starship configuration\n\ndist/                # Build output (dual ESM + CJS)\n├── *.js            # ES Module files\n├── *.cjs           # CommonJS files  \n├── *.d.ts          # TypeScript declarations\n└── generated/      # Generated contract clients\n```\n\n### Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Run tests: `pnpm test`\n5. Commit with conventional commits format\n6. Open a pull request\n\n### License\n\nMIT License - see [LICENSE](LICENSE) file for details.","readmeFilename":"README.md"}