JavaScript / TypeScript

Complete JavaScript/TypeScript integration guide with ethers.js

This guide shows how to integrate DexAggregator API in JavaScript/TypeScript applications using ethers.js.

Prerequisites

npm install ethers@^6.0.0
# or
yarn add ethers@^6.0.0

Quick Setup

1. Install Dependencies

{
  "dependencies": {
    "ethers": "^6.10.0"
  }
}

2. Create DexAggregator Client

// dexAggregatorClient.ts
import { ethers } from 'ethers';

export class DexAggregatorClient {
  private apiUrl: string;
  private provider: ethers.Provider;
  private wallet: ethers.Wallet;

  constructor(
    apiUrl: string,
    rpcUrl: string,
    privateKey: string
  ) {
    this.apiUrl = apiUrl;
    this.provider = new ethers.JsonRpcProvider(rpcUrl);
    this.wallet = new ethers.Wallet(privateKey, this.provider);
  }

  // Build route using API
  async buildRoute(params: BuildRouteParams): Promise<RouteResponse> {
    const response = await fetch(`${this.apiUrl}/api/v1/route/build`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(params),
    });

    const data = await response.json();

    if (data.code !== 0) {
      throw new Error(`API Error: ${data.message}`);
    }

    return data.data;
  }

  // Execute swap
  async executeSwap(
    routeData: RouteResponse,
    orderId: string
  ): Promise<ethers.TransactionReceipt> {
    // 1. Approve token if needed
    if (routeData.value === '0') {
      await this.approveToken(
        routeData.tokenIn,
        routeData.aggregatorAddress,
        routeData.amountIn
      );
    }

    // 2. Execute swap
    const aggregatorABI = [
      'function smartSwapByOrderId(bytes32 orderId, address executor, bytes calldata data) external payable',
    ];

    const aggregator = new ethers.Contract(
      routeData.aggregatorAddress,
      aggregatorABI,
      this.wallet
    );

    const tx = await aggregator.smartSwapByOrderId(
      orderId,
      routeData.executorAddress,
      routeData.executorData,
      {
        value: routeData.value,
        gasLimit: routeData.gas,
      }
    );

    console.log(`Transaction sent: ${tx.hash}`);
    const receipt = await tx.wait();
    console.log(`Transaction confirmed in block ${receipt.blockNumber}`);

    return receipt;
  }

  // Approve ERC20 token
  private async approveToken(
    tokenAddress: string,
    spender: string,
    amount: string
  ): Promise<void> {
    const erc20ABI = [
      'function approve(address spender, uint256 amount) external returns (bool)',
      'function allowance(address owner, address spender) external view returns (uint256)',
    ];

    const token = new ethers.Contract(tokenAddress, erc20ABI, this.wallet);

    // Check current allowance
    const currentAllowance = await token.allowance(
      this.wallet.address,
      spender
    );

    if (BigInt(currentAllowance) >= BigInt(amount)) {
      console.log('Token already approved');
      return;
    }

    // Approve
    console.log('Approving token...');
    const approveTx = await token.approve(spender, amount);
    await approveTx.wait();
    console.log('Token approved');
  }

  // Get contract addresses
  async getContracts(chain: string) {
    const response = await fetch(
      `${this.apiUrl}/api/v1/contracts?chain=${chain}`
    );
    return response.json();
  }

  // Health check
  async healthCheck() {
    const response = await fetch(`${this.apiUrl}/health`);
    return response.json();
  }
}

// Types
export interface BuildRouteParams {
  chain: string;
  tokenIn: string;
  tokenOut: string;
  amountIn: string;
  sender: string;
  recipient: string;
  slippageTolerance?: number;
  deadline?: number;
  includedSources?: string[];
  gasPrice?: string;
}

export interface RouteResponse {
  tokenIn: string;
  tokenOut: string;
  amountIn: string;
  amountOut: string;
  minAmountOut: string;
  gas: string;
  gasPrice: string;
  gasUsd: number;
  amountInUsd: number;
  amountOutUsd: number;
  aggregatorAddress: string;
  executorAddress: string;
  executorData: string;
  value: string;
  swapType: string;
  routeInfo: any;
}

Complete Example: Swap WBNB to USDT

Advanced Features

1. Price Comparison

2. Slippage Monitor

3. Retry Logic with Exponential Backoff

4. Gas Price Optimization

5. Transaction Monitoring

React Integration

Custom Hook

Component Example

Error Handling

Testing

Next Steps

Last updated