The Ultimate API Guide

DEX Infrastructure for Your App

Master our liquidity aggregator. From simple token discovery to complex on-chain transaction execution.

Live Playground

Edit the code on the left to customize the swap widget. The preview updates instantly.
The swap uses your partner API and handles ERC‑20 approvals automatically.

const SwapWidget = () => {
  const [tokens, setTokens] = React.useState([]);
  const [fromToken, setFromToken] = React.useState(null);
  const [toToken, setToToken] = React.useState(null);
  const [amount, setAmount] = React.useState('');
  const [quote, setQuote] = React.useState(null);
  const [loading, setLoading] = React.useState(false);
  const [txHash, setTxHash] = React.useState(null);
  const [error, setError] = React.useState(null);
  const [approving, setApproving] = React.useState(false);
  const [approvalTx, setApprovalTx] = React.useState(null);

  const provider = ethers && window.ethereum
    ? new ethers.providers.Web3Provider(window.ethereum)
    : null;

  React.useEffect(() => {
    fetch('https://litvmswap.com/api/partner/tokens')
      .then(r => r.json())
      .then(data => {
        setTokens(data.tokens);
        if (data.tokens.length >= 2) {
          setFromToken(data.tokens[0]);
          setToToken(data.tokens[1]);
        }
      });
  }, []);

  React.useEffect(() => {
    if (!fromToken || !toToken || !amount || isNaN(amount) || Number(amount) <= 0) {
      setQuote(null);
      return;
    }
    setLoading(true);
    fetch('https://litvmswap.com/api/partner/quote?fromToken=' + fromToken.address + '&toToken=' + toToken.address + '&amount=' + amount + '&partnerFeeBps=10')
      .then(r => r.json())
      .then(setQuote)
      .catch(setError)
      .finally(() => setLoading(false));
  }, [fromToken, toToken, amount]);

  const handleApprove = async () => {
    if (!provider || !quote) return;
    setError(null);
    setApproving(true);
    try {
      await window.ethereum.request({ method: 'eth_requestAccounts' });
      const signer = provider.getSigner();
      const erc20 = new ethers.Contract(
        fromToken.address,
        ['function approve(address spender, uint256 amount) returns (bool)'],
        signer
      );
      const decimals = fromToken.decimals || 18;
      const amountWei = ethers.utils.parseUnits(amount, decimals);
      const tx = await erc20.approve(quote.spender, amountWei);
      setApprovalTx(tx.hash);
      await tx.wait();
      setApprovalTx('confirmed');
    } catch (e) {
      setError(e.message);
    } finally {
      setApproving(false);
    }
  };

  const startSwap = async () => {
    if (!provider || !quote) return;
    setError(null);
    try {
      await window.ethereum.request({ method: 'eth_requestAccounts' });
      const signer = provider.getSigner();
      const userAddress = await signer.getAddress();

      const response = await fetch('https://litvmswap.com/api/partner/swap', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          fromToken: fromToken.address,
          toToken: toToken.address,
          amount: amount,
          userAddress: userAddress,
          referrerAddress: 'YOUR_WALLET_ADDRESS',  // EDIT THIS
          partnerFeeBps: 10
        })
      });
      const data = await response.json();
      if (data.error) throw new Error(data.error);

      const tx = await signer.sendTransaction(data.transaction);
      setTxHash(tx.hash);
      await tx.wait();
      setTxHash('confirmed: ' + tx.hash);
    } catch (e) {
      setError(e.message);
    }
  };

  const isNativeToken = (token) => {
    if (token.isNative !== undefined) return token.isNative;
    return token.address.toLowerCase() === '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
  };
  const needsApproval = quote && fromToken && !isNativeToken(fromToken);

  return React.createElement('div', { style: styles.widget },
    React.createElement('h3', { style: styles.title }, 'âš¡ LitVMSwap'),
    React.createElement('div', { style: styles.row },
      React.createElement('div', { style: styles.tokenBox },
        React.createElement('span', { style: styles.label }, 'From'),
        React.createElement('select', {
          style: styles.select,
          value: fromToken?.address || '',
          onChange: e => setFromToken(tokens.find(t => t.address === e.target.value))
        }, tokens.map(t => React.createElement('option', { key: t.address, value: t.address }, t.symbol)))
      ),
      React.createElement('div', { style: styles.swapIcon }, '⇄'),
      React.createElement('div', { style: styles.tokenBox },
        React.createElement('span', { style: styles.label }, 'To'),
        React.createElement('select', {
          style: styles.select,
          value: toToken?.address || '',
          onChange: e => setToToken(tokens.find(t => t.address === e.target.value))
        }, tokens.map(t => React.createElement('option', { key: t.address, value: t.address }, t.symbol)))
      )
    ),
    React.createElement('input', {
      type: 'number',
      placeholder: '0.0',
      style: styles.input,
      value: amount,
      onChange: e => setAmount(e.target.value)
    }),
    React.createElement('div', { style: styles.quoteRow },
      React.createElement('span', null, loading ? 'Loading...' : quote ? quote.toAmount + ' ' + toToken?.symbol : '0'),
      React.createElement('span', { style: styles.fee }, 'Fee 0.1%')
    ),
    needsApproval && quote && React.createElement('button', {
      style: { ...styles.button, ...(approving ? styles.disabled : {}) },
      onClick: handleApprove,
      disabled: approving
    }, approving ? 'Approving...' : approvalTx === 'confirmed' ? 'Approved ✅' : 'Approve ' + fromToken.symbol),
    React.createElement('button', {
      style: { ...styles.button, ...(loading || !quote ? styles.disabled : {}) },
      onClick: startSwap,
      disabled: loading || !quote || (needsApproval && approvalTx !== 'confirmed')
    }, txHash ? (txHash.startsWith('confirmed') ? 'Swapped 🎉' : 'Swapping...') : 'Swap'),
    error && React.createElement('div', { style: styles.error }, error),
    txHash && React.createElement('div', { style: styles.txLink }, 'Tx: ' + txHash)
  );
};

const styles = {
  widget: { background: '#0A0A0F', borderRadius: 24, padding: 24, maxWidth: 380, margin: '0 auto', color: 'white', fontFamily: 'Inter, sans-serif', border: '1px solid #2A2A3C', boxShadow: '0 20px 60px rgba(0,0,0,0.5)' },
  title: { margin: '0 0 20px 0', fontSize: 22, fontWeight: 700, textAlign: 'center' },
  row: { display: 'flex', gap: 8, marginBottom: 16, alignItems: 'center' },
  tokenBox: { flex: 1 },
  label: { fontSize: 12, color: '#888', display: 'block', marginBottom: 4 },
  select: { width: '100%', padding: '10px 12px', background: '#14141E', border: '1px solid #2A2A3C', borderRadius: 12, color: 'white', fontSize: 14, outline: 'none' },
  swapIcon: { fontSize: 20, color: '#489bfb', cursor: 'pointer' },
  input: { width: '100%', padding: '14px 16px', background: '#14141E', border: '1px solid #2A2A3C', borderRadius: 12, color: 'white', fontSize: 18, marginBottom: 12, outline: 'none' },
  quoteRow: { display: 'flex', justifyContent: 'space-between', fontSize: 14, padding: '0 4px', marginBottom: 20, color: '#AAA' },
  fee: { color: '#489bfb' },
  button: { width: '100%', padding: '14px', border: 'none', borderRadius: 14, fontWeight: 700, fontSize: 16, cursor: 'pointer', marginBottom: 8, background: 'linear-gradient(135deg, #489bfb, #1abde6)', color: 'white', transition: '0.2s' },
  disabled: { opacity: 0.5, cursor: 'not-allowed' },
  error: { marginTop: 12, color: '#ff4d4f', fontSize: 13, textAlign: 'center' },
  txLink: { marginTop: 8, fontSize: 12, color: '#489bfb', wordBreak: 'break-all', textAlign: 'center' }
};

render(React.createElement(SwapWidget));

How to use this playground

  • Connect Wallet: Use the RainbowKit button in the header – the widget automatically picks up your connected wallet.
  • Select Tokens: Choose any pair from the list provided by our /tokens API.
  • Enter Amount: Type the amount of the from token.
  • Approve (if needed): For ERC‑20 tokens, click Approve to allow the swap contract to spend your tokens. Native zkLTC skips this step.
  • Swap: Click Swap to execute the transaction – the swap uses our /quote and /swap endpoints.
  • Edit Code: The left editor contains the full widget code. Change the referrer address ('YOUR_WALLET_ADDRESS') to your partner wallet to earn fees.
  • Learn & Build: Study the code to understand how to integrate our API into your own dApp.