API Integration

Usage

We have given a detailed description of the method of using the inquiry API in the developer management platform. Please register the developer portal to obtain the access method of the API.

API Usage Examples#

DODO Example

Data returned from the DODO-API can be directly used to execute token transactions in the contract. However, if you wish to use your own contract, encapsulate and send data to execute token transactions, you can refer to the following code sample: DODOApiEncapsulation.sol

Node.js Example#

const axios = require("axios").default;
const { ethers } = require("ethers");
const erc20ABI = require("./erc20.json");

const privateKey = env.YOUR_PK;
const apiKey = env.YOUR_API_KEY;
// please remember keep your wallet private key safe and split it from source code repo in your project
// this is just for demo usage.
const rpcUrl = "https://bsc-dataseed.binance.org";

const rpcProvider = new ethers.providers.JsonRpcProvider(rpcUrl);

const wallet = new ethers.Wallet(privateKey, rpcProvider);

const dodoAPI = "https://api.dodoex.io/route-service/developer/getdodoroute";

const checkAllowance = async (
  tokenAddress,
  targetAddress,
  userAddress,
  fromAmount
) => {
  const erc20Contract = new ethers.Contract(
    tokenAddress,
    erc20ABI,
    rpcProvider
  );
  const allowance = await erc20Contract.allowance(userAddress, targetAddress);
  console.log(
    "allowance > fromAmount => ",
    allowance.toString(),
    fromAmount,
    allowance.gt(`${fromAmount}`)
  );
  return allowance.gt(`${fromAmount}`);
};

const doApprove = async (
  tokenAddress,
  targetAddress,
  userAddress,
  fromAmount
) => {
  const erc20Contract = new ethers.Contract(
    tokenAddress,
    erc20ABI,
    rpcProvider
  );
  await erc20Contract.approve(targetAddress, fromAmount);
};

const doSwap = async (txObj) => {
  const result = await wallet.sendTransaction(txObj);
  console.log(
    "txHash => ",
    result,
    `\nopen https://bscscan.com/tx/${result.hash} check result.`
  );
  return result;
};

const testFlight = () => {
  const fromTokenAddress = "0x67ee3Cb086F8a16f34beE3ca72FAD36F7Db929e2";
  const toTokenAddress = "0x55d398326f99059ff775485246999027b3197955";
  const fromAmount = 0.3 * 1e18;
  axios
    .get(dodoAPI, {
      headers: {
        "User-Agent": "DODO-Example",
      },
      params: {
        // DODO
        fromTokenAddress: fromTokenAddress,
        fromTokenDecimals: 18,
        // USDT
        toTokenAddress: toTokenAddress,
        toTokenDecimals: 6,
        // amount with decimal
        fromAmount: fromAmount,
        slippage: 1,
        userAddr: wallet.address,
        // BSC chain id is 56
        chainId: 56,
        rpc: rpcUrl,
        apikey: apiKey,
      },
    })
    .then(async function (response) {
      console.log("response data => ", response.data);
      if (response.data.status === 200) {
        const routeObj = response.data.data;
        // check allowance first
        const targetAddress = routeObj.targetApproveAddr;
        // allowance should greater than fromAmount
        const hasApproved = await checkAllowance(
          fromTokenAddress,
          targetAddress,
          wallet.address,
          fromAmount
        );

        if (!hasApproved) {
          await doApprove(
            fromTokenAddress,
            targetAddress,
            wallet.address,
            fromAmount
          );
        }

        const gasLimit = await wallet.estimateGas({
          to: routeObj.to,
          data: routeObj.data,
          value: 0, // if fromToken is eth or bnb or ht, value should be fromAmount
        });
        console.log("gasLimit => ", gasLimit);

        const gasPrice = await wallet.getGasPrice();
        console.log("gasPrice => ", gasPrice);

        const nonce = await wallet.getTransactionCount();
        console.log("nonce => ", nonce);

        const tx = {
          from: wallet.address,
          to: routeObj.to,
          value: 0, // if fromToken is eth or bnb or ht, value should be fromAmount
          nonce: nonce,
          gasLimit: ethers.utils.hexlify(gasLimit),
          gasPrice: ethers.utils.hexlify(gasPrice),
        };

        await doSwap(tx);
      }
    })
    .catch(function (error) {
      console.log(error);
    })
    .then(function () {
      console.log("Swap Done.");
    });
};

testFlight();

Solidity Example#

/*
    Copyright 2021 DODO ZOO.
    SPDX-License-Identifier: Apache-2.0
*/

pragma solidity 0.6.9;

import {IERC20} from "./intf/IERC20.sol";
import {SafeERC20} from "./lib/SafeERC20.sol";

contract DODOApiEncapsulation {
    using SafeERC20 for IERC20;

    address constant _ETH_ADDRESS_ = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;


    receive() external payable {}

    //Compatible with ETH=>ERC20, ERC20=>ETH
    function useDodoApiData(
        address fromToken,
        address toToken,
        uint256 fromAmount,
        address dodoApprove, // targetApproveAddr
        address dodoProxy, // to (DODOV2Proxy or DODORouteProxy,should not be fixed)
        bytes memory dodoApiData // data
    )
        external
        payable
    {
        if (fromToken != _ETH_ADDRESS_) {
            IERC20(fromToken).transferFrom(msg.sender, address(this), fromAmount);
            _generalApproveMax(fromToken, dodoApprove, fromAmount);
        } else {
            require(fromAmount == msg.value);
        }

        (bool success, ) = dodoProxy.call{value: fromToken == _ETH_ADDRESS_ ? fromAmount : 0}(dodoApiData);
        require(success, "API_SWAP_FAILED");

        uint256 returnAmount = _generalBalanceOf(toToken, address(this));

        _generalTransfer(toToken, msg.sender, returnAmount);
    }


    function _generalApproveMax(
        address token,
        address to,
        uint256 amount
    ) internal {
        uint256 allowance = IERC20(token).allowance(address(this), to);
        if (allowance < amount) {
            if (allowance > 0) {
                IERC20(token).safeApprove(to, 0);
            }
            IERC20(token).safeApprove(to, uint256(-1));
        }
    }

    function _generalTransfer(
        address token,
        address payable to,
        uint256 amount
    ) internal {
        if (amount > 0) {
            if (token == _ETH_ADDRESS_) {
                to.transfer(amount);
            } else {
                IERC20(token).safeTransfer(to, amount);
            }
        }
    }

    function _generalBalanceOf(
        address token,
        address who
    ) internal view returns (uint256) {
        if (token == _ETH_ADDRESS_ ) {
            return who.balance;
        } else {
            return IERC20(token).balanceOf(who);
        }
    }

}