Skip to main content

Get started in three steps

Integrate the dKit API into your application with this quick guide.

Step 1: Get Your First Quote

Start by requesting a swap quote to see available routes and prices.
curl --location 'https://api.dkit.xyz/v1/quote' \
--header 'Content-Type: application/json' \
--header 'api-key: 86c3fc76-25c8-455c-8d6d-0ecea88d0f6e' \
--data '{
    "sellAsset": "ZEC.ZEC",
    "sellAmount": "2",
    "buyAsset": "ETH.ETH",
    "slippage": 1,
    "affiliate": "eld",
    "affiliateFee": 88,
    "includeTx": true,
    "providers": [
        "MAYACHAIN"
    ],
    "sourceAddress": "t1Tmw3syVocrsRUDuCq7jteVjMSNfwpgz88",
    "destinationAddress": "0x817bFA97Cc8E5Bfa499D401f43E3087B07AE96f9"
}'

Step 2: Execute the Swap

Use the transaction details from the quote to execute the swap on-chain.
  • Native Transaction
  • EVM Transaction
For native cross-chain swaps (e.g., BTC to ETH via THORChain):
const route = quote.routes[0]; // Select best route

// Send native transaction to the inbound address with memo
const tx = {
  to: route.inboundAddress,
  value: sellAmount,
  memo: route.memo // Required for THORChain/Maya
};

// Execute with your wallet
const txHash = await wallet.sendTransaction(tx);

Step 3: Track the Swap

Monitor your swap progress in real-time.
const trackSwap = async (txHash, chainId, quoteId, routeIndex) => {
  const response = await fetch('https://api.dkit.xyz/v1/track', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': '86c3fc76-25c8-455c-8d6d-0ecea88d0f6e'
    },
    body: JSON.stringify({
      hash: txHash,
      chainId: chainId,
      quoteId: quoteId,
      routeIndex: routeIndex
    })
  });
  
  const tracking = await response.json();
  
  if (tracking.success) {
    console.log(`Status: ${tracking.data.trackingStatus}`);
    
    // Check if complete
    if (tracking.data.trackingStatus === 'completed') {
      console.log(`Output tx: ${tracking.data.trackMeta.outputTxHash}`);
    }
  }
  
  return tracking;
};

// Poll for updates
const pollStatus = async (params) => {
  let status = 'not_started';
  
  while (status !== 'completed' && status !== 'refunded') {
    const result = await trackSwap(params);
    
    if (result.success) {
      status = result.data.trackingStatus;
      console.log(`Current status: ${status}`);
    }
    
    await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds
  }
};

Complete Example

Here’s a complete example that ties everything together:
async function performSwap() {
  try {
    // 1. Get quote
    const quote = await fetch('https://api.dkit.xyz/v1/quote', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        sellAsset: 'ETH.ETH',
        buyAsset: 'BTC.BTC',
        sellAmount: '1.0',
        sourceAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8',
        destinationAddress: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
        slippage: 3
      })
    }).then(r => r.json());
    
    console.log(`Got ${quote.routes.length} routes`);
    
    // 2. Select best route
    const route = quote.routes[0];
    console.log(`Best route: ${route.providers.join(' → ')}`);
    console.log(`Expected output: ${route.expectedBuyAmount} sats`);
    
    // 3. Execute swap (implementation depends on your wallet)
    const txHash = await executeSwap(route);
    console.log(`Transaction sent: ${txHash}`);
    
    // 4. Track the swap
    let tracking;
    do {
      tracking = await fetch('https://api.dkit.xyz/v1/track', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          hash: txHash,
          chainId: '1', // Ethereum mainnet
          quoteId: quote.quoteId,
          routeIndex: 0
        })
      }).then(r => r.json());
      
      if (tracking.success) {
        console.log(`Status: ${tracking.data.trackingStatus}`);
        
        if (tracking.data.isStreaming) {
          const progress = tracking.data.streamingProgress;
          console.log(`Streaming: ${progress.percentage}% complete`);
        }
      }
      
      await new Promise(r => setTimeout(r, 5000)); // Wait 5 seconds
      
    } while (
      tracking.success && 
      !['completed', 'refunded'].includes(tracking.data.trackingStatus)
    );
    
    if (tracking.data.trackingStatus === 'completed') {
      console.log('Swap completed successfully!');
      console.log(`Output tx: ${tracking.data.trackMeta.outputTxHash}`);
    }
    
  } catch (error) {
    console.error('Swap failed:', error);
  }
}

Next Steps

Common Integration Patterns

// MetaMask example
const executeEVMSwap = async (route) => {
  const accounts = await ethereum.request({ 
    method: 'eth_requestAccounts' 
  });
  
  const tx = {
    from: accounts[0],
    to: route.targetAddress || route.inboundAddress,
    value: route.tx?.value || '0x0',
    data: route.tx?.data || route.memo || '0x'
  };
  
  return await ethereum.request({
    method: 'eth_sendTransaction',
    params: [tx]
  });
};
const swapWithRetry = async (params, maxRetries = 3) => {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const quote = await getQuote(params);
      
      if (quote.routes.length > 0) {
        return await executeSwap(quote.routes[0]);
      }
      
      // Check provider errors
      if (quote.providerErrors) {
        const retriable = quote.providerErrors.some(e => 
          e.errorCode === 'RATE_LIMITED' || 
          e.errorCode === 'PROVIDER_UNAVAILABLE'
        );
        
        if (!retriable) throw new Error('No routes available');
      }
      
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
    }
  }
};
// Convert human-readable amounts to base units
const toBaseUnits = (amount, decimals) => {
  const factor = BigInt(10 ** decimals);
  const [whole, fraction = ''] = amount.split('.');
  const fractionPadded = fraction.padEnd(decimals, '0').slice(0, decimals);
  return (BigInt(whole) * factor + BigInt(fractionPadded)).toString();
};

// Convert base units to human-readable
const fromBaseUnits = (amount, decimals) => {
  const value = BigInt(amount);
  const factor = BigInt(10 ** decimals);
  const whole = value / factor;
  const remainder = value % factor;
  
  if (remainder === 0n) return whole.toString();
  
  const fraction = remainder.toString().padStart(decimals, '0');
  return `${whole}.${fraction.replace(/0+$/, '')}`;
};
I