Split trading

Split trading allows the SDK to split your trade across multiple DEXs to achieve better rates. This is particularly useful for large trades where a single DEX might not have sufficient liquidity.

Basic Split Trade

Enable split trading for potentially better rates.

basic-split.js
const { MoroBestRate } = require('@moromoro/moro-sdk')
const { ethers } = require('ethers')

async function splitTradeExample() {
  const provider = new ethers.providers.JsonRpcProvider(
    'https://rpc.hyperliquid.xyz/evm'
  )
  const signer = new ethers.Wallet(process.env.PRIVATE_KEY, provider)
  const moroClient = new MoroBestRate(provider, 'hyperevm')

  const HYPE = '0x5555555555555555555555555555555555555555'
  const USDT = '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb'
  const amountIn = ethers.utils.parseUnits('100', 18) // Large amount
  const gasPrice = ethers.BigNumber.from('5000000000')

  // Get quote with split enabled
  const quote = await moroClient.getQuote(
    HYPE,
    USDT,
    amountIn,
    gasPrice,
    { enableSplit: true } // Enable split trading
  )

  console.log('Quote type:', quote.type)

  if (quote.type === 'split') {
    console.log('Trade will be split across', quote.paths.length, 'paths')
    console.log('Volume distribution:', quote.volumns)

    // Display each path
    quote.paths.forEach((path, i) => {
      console.log(`\nPath ${i + 1}:`)
      console.log('- Volume:', quote.volumns[i] + '%')
      console.log('- Routes:', path.routes.map(r => r.name).join(' -> '))
      console.log('- Tokens:', path.tokens.length)
    })
  }

  // Execute split trade
  const minOut = ethers.BigNumber.from(quote.amountOut).mul(99).div(100)
  const tx = await moroClient.swap(
    signer,
    HYPE,
    USDT,
    amountIn,
    minOut,
    quote
  )

  await tx.wait()
  console.log('✓ Split trade completed')
}

splitTradeExample()

Comparing Single vs Split Trade

Compare rates between single path and split trading.

compare-single-vs-split.js
const { MoroBestRate } = require('@moromoro/moro-sdk')
const { ethers } = require('ethers')

async function compareSingleVsSplit() {
  const provider = new ethers.providers.JsonRpcProvider(
    'https://rpc.hyperliquid.xyz/evm'
  )
  const moroClient = new MoroBestRate(provider, 'hyperevm')

  const HYPE = '0x5555555555555555555555555555555555555555'
  const USDT = '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb'
  const amountIn = ethers.utils.parseUnits('100', 18)
  const gasPrice = ethers.BigNumber.from('5000000000')

  // Get single path quote
  console.log('Getting single path quote...')
  const singleQuote = await moroClient.getQuote(
    HYPE,
    USDT,
    amountIn,
    gasPrice,
    { enableSplit: false }
  )

  console.log('Single path:')
  console.log('- Amount out:', ethers.utils.formatUnits(singleQuote.amountOut, 6), 'USDT')
  console.log('- Type:', singleQuote.type)

  // Get split quote
  console.log('\nGetting split quote...')
  const splitQuote = await moroClient.getQuote(
    HYPE,
    USDT,
    amountIn,
    gasPrice,
    { enableSplit: true }
  )

  console.log('Split trade:')
  console.log('- Amount out:', ethers.utils.formatUnits(splitQuote.amountOut, 6), 'USDT')
  console.log('- Type:', splitQuote.type)

  if (splitQuote.type === 'split') {
    console.log('- Number of paths:', splitQuote.paths.length)
  }

  // Calculate improvement
  const singleAmount = parseFloat(ethers.utils.formatUnits(singleQuote.amountOut, 6))
  const splitAmount = parseFloat(ethers.utils.formatUnits(splitQuote.amountOut, 6))
  const improvement = ((splitAmount - singleAmount) / singleAmount * 100).toFixed(2)

  console.log('\nComparison:')
  console.log('- Improvement:', improvement + '%')
  console.log('- Better option:', splitAmount > singleAmount ? 'Split' : 'Single')
}

compareSingleVsSplit()

Inspecting Split Paths

Detailed inspection of split trade paths.

inspect-split-paths.js
const { MoroBestRate } = require('@moromoro/moro-sdk')
const { ethers } = require('ethers')

async function inspectSplitPaths() {
  const provider = new ethers.providers.JsonRpcProvider(
    'https://rpc.hyperliquid.xyz/evm'
  )
  const moroClient = new MoroBestRate(provider, 'hyperevm')

  const HYPE = '0x5555555555555555555555555555555555555555'
  const USDT = '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb'
  const amountIn = ethers.utils.parseUnits('100', 18)
  const gasPrice = ethers.BigNumber.from('5000000000')

  const quote = await moroClient.getQuote(
    HYPE,
    USDT,
    amountIn,
    gasPrice,
    { enableSplit: true }
  )

  if (quote.type !== 'split') {
    console.log('Trade is not split')
    return
  }

  console.log('=== Split Trade Analysis ===\n')
  console.log('Total paths:', quote.paths.length)
  console.log('Total output:', ethers.utils.formatUnits(quote.amountOut, 6), 'USDT')
  console.log('Block number:', quote.blockNumber)

  quote.paths.forEach((path, index) => {
    console.log(`\n--- Path ${index + 1} ---`)
    console.log('Volume allocation:', quote.volumns[index] + '%')
    console.log('Deposit address:', quote.depositAddresses[index])
    console.log('Number of hops:', path.routes.length)

    console.log('\nRoute details:')
    path.routes.forEach((route, i) => {
      console.log(`  Hop ${i + 1}:`)
      console.log(`    - DEX: ${route.name}`)
      console.log(`    - Address: ${route.address}`)
      console.log(`    - Model: ${route.model}`)
      console.log(`    - Gas: ${route.gas}`)
    })

    console.log('\nToken path:')
    path.tokens.forEach((token, i) => {
      console.log(`  ${i}: ${token}`)
    })
  })

  console.log('\n=== Gas Fees ===')
  console.log(JSON.stringify(quote.gasFees, null, 2))
}

inspectSplitPaths()

Large Trade with Split

Example of a large trade benefiting from split trading.

large-trade.js
const { MoroBestRate } = require('@moromoro/moro-sdk')
const { ethers } = require('ethers')

async function largeTrade() {
  const provider = new ethers.providers.JsonRpcProvider(
    'https://rpc.hyperliquid.xyz/evm'
  )
  const signer = new ethers.Wallet(process.env.PRIVATE_KEY, provider)
  const moroClient = new MoroBestRate(provider, 'hyperevm')

  const HYPE = '0x5555555555555555555555555555555555555555'
  const USDT = '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb'

  // Large trade amount
  const amountIn = ethers.utils.parseUnits('1000', 18) // 1000 HYPE
  const gasPrice = ethers.BigNumber.from('5000000000')

  console.log('Executing large trade of', ethers.utils.formatEther(amountIn), 'HYPE')

  // Always use split for large trades
  const quote = await moroClient.getQuote(
    HYPE,
    USDT,
    amountIn,
    gasPrice,
    { enableSplit: true }
  )

  console.log('\nQuote details:')
  console.log('- Expected output:', ethers.utils.formatUnits(quote.amountOut, 6), 'USDT')

  if (quote.type === 'split') {
    console.log('- Split across', quote.paths.length, 'paths')
    console.log('- Distribution:', quote.volumns.map(v => v + '%').join(', '))

    // Calculate effective price
    const inputAmount = parseFloat(ethers.utils.formatEther(amountIn))
    const outputAmount = parseFloat(ethers.utils.formatUnits(quote.amountOut, 6))
    const pricePerHYPE = outputAmount / inputAmount

    console.log('- Effective price:', pricePerHYPE.toFixed(4), 'USDT per HYPE')
  }

  // Use tighter slippage for large trades (0.5%)
  const minOut = ethers.BigNumber.from(quote.amountOut).mul(995).div(1000)
  console.log('- Minimum output (0.5% slippage):', ethers.utils.formatUnits(minOut, 6), 'USDT')

  // Execute
  const tx = await moroClient.swap(
    signer,
    HYPE,
    USDT,
    amountIn,
    minOut,
    quote
  )

  console.log('\nTransaction:', tx.hash)
  const receipt = await tx.wait()
  console.log('✓ Large trade completed in block', receipt.blockNumber)
}

largeTrade()

Optimal Split Configuration

Customize split trading parameters for better performance.

optimized-split.js
const { MoroBestRate } = require('@moromoro/moro-sdk')
const { ethers } = require('ethers')

async function optimizedSplitTrading() {
  const provider = new ethers.providers.JsonRpcProvider(
    'https://rpc.hyperliquid.xyz/evm'
  )

  // Configure with custom split parameters
  const moroClient = new MoroBestRate(provider, 'hyperevm', {
    maxCandidatePathsCount: 30,  // Increase for more path options
    maxCallsPerFetch: 100        // Batch size for RPC calls
  })

  const HYPE = '0x5555555555555555555555555555555555555555'
  const USDT = '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb'
  const amountIn = ethers.utils.parseUnits('500', 18)
  const gasPrice = ethers.BigNumber.from('5000000000')

  console.log('Getting optimized split quote...')

  const startTime = Date.now()
  const quote = await moroClient.getQuote(
    HYPE,
    USDT,
    amountIn,
    gasPrice,
    { enableSplit: true }
  )
  const endTime = Date.now()

  console.log('Quote generated in', endTime - startTime, 'ms')
  console.log('Amount out:', ethers.utils.formatUnits(quote.amountOut, 6), 'USDT')

  if (quote.type === 'split') {
    console.log('Optimized across', quote.paths.length, 'paths')
  }
}

optimizedSplitTrading()

Handling Split Trade Failures

Error handling specific to split trades.

robust-split-trade.js
const { MoroBestRate } = require('@moromoro/moro-sdk')
const { ethers } = require('ethers')

async function robustSplitTrade() {
  const provider = new ethers.providers.JsonRpcProvider(
    'https://rpc.hyperliquid.xyz/evm'
  )
  const signer = new ethers.Wallet(process.env.PRIVATE_KEY, provider)
  const moroClient = new MoroBestRate(provider, 'hyperevm')

  const HYPE = '0x5555555555555555555555555555555555555555'
  const USDT = '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb'
  const amountIn = ethers.utils.parseUnits('100', 18)
  const gasPrice = ethers.BigNumber.from('5000000000')

  try {
    // Try split trade first
    console.log('Attempting split trade...')
    const splitQuote = await moroClient.getQuote(
      HYPE,
      USDT,
      amountIn,
      gasPrice,
      { enableSplit: true }
    )

    const minOut = ethers.BigNumber.from(splitQuote.amountOut).mul(99).div(100)
    const tx = await moroClient.swap(
      signer,
      HYPE,
      USDT,
      amountIn,
      minOut,
      splitQuote
    )

    await tx.wait()
    console.log('✓ Split trade successful')

  } catch (error) {
    console.log('Split trade failed:', error.message)
    console.log('Falling back to single path trade...')

    try {
      // Fallback to single path
      const singleQuote = await moroClient.getQuote(
        HYPE,
        USDT,
        amountIn,
        gasPrice,
        { enableSplit: false }
      )

      const minOut = ethers.BigNumber.from(singleQuote.amountOut)
        .mul(98)
        .div(100) // More slippage for fallback

      const tx = await moroClient.swap(
        signer,
        HYPE,
        USDT,
        amountIn,
        minOut,
        singleQuote
      )

      await tx.wait()
      console.log('✓ Fallback single trade successful')

    } catch (fallbackError) {
      console.error('Both split and single trades failed')
      throw fallbackError
    }
  }
}

robustSplitTrade()

Analyzing Split Efficiency

Analyze whether split trading provides value.

analyze-split-efficiency.js
async function analyzeSplitEfficiency(amountIn) {
  const provider = new ethers.providers.JsonRpcProvider(
    'https://rpc.hyperliquid.xyz/evm'
  )
  const moroClient = new MoroBestRate(provider, 'hyperevm')

  const HYPE = '0x5555555555555555555555555555555555555555'
  const USDT = '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb'
  const gasPrice = ethers.BigNumber.from('5000000000')

  // Get both quotes
  const [singleQuote, splitQuote] = await Promise.all([
    moroClient.getQuote(HYPE, USDT, amountIn, gasPrice, { enableSplit: false }),
    moroClient.getQuote(HYPE, USDT, amountIn, gasPrice, { enableSplit: true })
  ])

  const singleOut = parseFloat(ethers.utils.formatUnits(singleQuote.amountOut, 6))
  const splitOut = parseFloat(ethers.utils.formatUnits(splitQuote.amountOut, 6))

  const improvement = ((splitOut - singleOut) / singleOut * 100).toFixed(4)

  console.log({
    amountIn: ethers.utils.formatEther(amountIn),
    singlePathOutput: singleOut,
    splitPathOutput: splitOut,
    improvement: improvement + '%',
    worthSplitting: parseFloat(improvement) > 0.1 // 0.1% threshold
  })

  return parseFloat(improvement)
}

// Test different amounts
async function testDifferentAmounts() {
  const amounts = [
    ethers.utils.parseUnits('10', 18),
    ethers.utils.parseUnits('50', 18),
    ethers.utils.parseUnits('100', 18),
    ethers.utils.parseUnits('500', 18),
    ethers.utils.parseUnits('1000', 18)
  ]

  for (const amount of amounts) {
    console.log('\n=== Testing amount:', ethers.utils.formatEther(amount), 'HYPE ===')
    await analyzeSplitEfficiency(amount)
  }
}

testDifferentAmounts()

When to Use Split Trading

General guidelines:

when-to-use-split.js
function shouldUseSplit(amountInUSD) {
  // Rule of thumb for when to enable split trading
  if (amountInUSD < 100) {
    return false  // Small trades: gas cost may outweigh benefits
  } else if (amountInUSD < 1000) {
    return true   // Medium trades: likely beneficial
  } else {
    return true   // Large trades: almost always beneficial
  }
}

// Usage
const amountIn = ethers.utils.parseUnits('100', 18)
const hypePrice = 2.50  // USD
const tradeValueUSD = parseFloat(ethers.utils.formatEther(amountIn)) * hypePrice

const enableSplit = shouldUseSplit(tradeValueUSD)
console.log('Trade value:', tradeValueUSD, 'USD')
console.log('Use split trading:', enableSplit)

const quote = await moroClient.getQuote(
  HYPE,
  USDT,
  amountIn,
  gasPrice,
  { enableSplit }
)

See Also