npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

dodo-bridge-aggregator

v1.0.7

Published

dodo 桥聚合器

Downloads

16

Readme

中文 / English

Table of Contents

TL;DR

This repository contains codes for cross-chain bridges to submit a config file to DODO so as to get your liquidity aggregated by DODO. The config file will include info on API Config and data conversion. Upon completion of config, you could submit via ‘Submit Mergerd Config’ to DODO.

Clone codes

$ git clone https://github.com/DODOEX/dodo-bridge-aggregator.git

Configuration

1. Add config file

$ mkdir src/bridge/[bridgeName]
$ touch src/bridge/[bridgeName]/config.ts

2. Config

a. Prepare config data

Copy the following template to 【src/bridge/[bridgeName]/config.ts】, and then modify accordingly.
There are four functions in the template, including route, buildTransactionData, status, and tokenList. Modify settings to get corresponding responses.
For other parameters, refer to data in 【src/bridge/swft/config.ts, src/bridge/squid/config.ts】.

import { CrossChainBusinessException } from "./../../exception/index";
import {
  CrossChainConfig,
  CrossChainParamsData,
  StatusInfo,
} from "../../types";
import BigNumber from "bignumber.js";

const serverHost = "http://127.0.0.1:8080";
const errorCodes = {
  ERROR: { code: "ERROR", message: "unknown error" },
  SERVICE_UNAVAILABLE: {
    code: "SERVICE_UNAVAILABLE",
    message: "service unavailable",
  },
  // other error code
};
const bridgeNameConfig: CrossChainConfig = {
  name: "bridge_name", // bridge's name
  //  API configuration
  apiInterface: {
    // Route (required)
    route: {
      url: `${serverHost}/api/route`, // API Request URL
      method: "get", // API method ( get/post/put)
      // call this function before execution
      before: async (params: CrossChainParamsData) => {
        const fromAmountUSD = new BigNumber(params.fromAmount)
          .div(10 ** params.fromTokenDecimals)
          .times(params.fromTokenPrice);
        return { fromAmountUSD }; //  The data returned here is available in the "format" function in 'requestMapping' and 'responseMapping'
      },
      // call this function after execution
      after: (err, res) => {
        // need to check if any errors
        if (err) throw new CrossChainBusinessException(errorCodes.ERROR);
        return res;
      },
      // call this function after making API request
      requestAfter: (res) => {
        // check if API request returns a valid or expected response; throw an exception or error if the respons is not normal or expected
        if (res.code !== 200)
          throw new CrossChainBusinessException(errorCodes.ERROR);
        return res.data;
      },
      // Interface request parameter data is put into "requestMapping", and field values are mapped from "CrossChainParamsData" parameters
      requestMapping: {
        fromChain: "fromChainId",
        fromAmount: {
          format: (_, { beforeResult }) => beforeResult.fromAmountUSD,
        },
        toChain: { field: "toChain", type: "string" },
        // other params
      },
      // The interface return data is put into "responseMapping", and the field values are mapped from "interface response data
      responseMapping: {
        depositContract: "data.contractAddress", // deposit contract address
        toAmount: "data.amountOutMin", // amount reaching the receiving chain, unit in gwei
        fee: {
          swapFee: "0", // swap fee (USD)
          destinationGasFee: {
            // receiving chain gas fee (USD)
            format: (route, { crossChainParamsData }) => {
              return new BigNumber(route.data.fee)
                .div(10 ** crossChainParamsData.toTokenDecimals)
                .times(crossChainParamsData.toTokenPrice)
                .toString(10);
            },
          },
          crossChainFee: "0", // cross chain fee (USD)
          otherFee: "0", // other fee (USD)
        },
        // if 'route' returns 'transactionData', the 'buildTransactionData' is not needed
        // transactionData: {
        //     data: 'data.transactionData',
        //     value: 'data.value',
        // },
        // Additional fees deducted from wallet when initiating an onchain transaction (e.g. cross chain bridges may require an upfront fees paid in the sending chain's native token, defined as "otherPayOut")(USD)
        otherPayOut: "0",
        // "Route" API may return data needed for subsequent  actionss, and this data can be stored in "interfaceParamData" section for later use
        interfaceParamData: {
          routeId: "data.routeId",
        },
      },
    },
    // Get Status Interface (required)
    status: {
      url: `${serverHost}/api/status`,
      method: "get",
      requestAfter: (res) => {
        if (res.code !== 200)
          throw new CrossChainBusinessException(errorCodes.ERROR);
        return res.data;
      },
      requestMapping: {
        hash: "fromHash",
        // other params
      },
      responseMapping: {
        toHash: "toHash",
        statusInfo: {
          format: (resResult: any): StatusInfo => {
            const data: StatusInfo = {
              status: "PENDING",
              bridgeResponseResult: resResult,
            };
            if (resResult.status === "success") {
              data.status = "DONE";
            } else if (
              resResult.status === "timeout" ||
              resResult.sourceTxStatus === "error"
            ) {
              data.status = "FAILED";
              data.message = `failed: ${resResult.message}`;
            }
            return data;
          },
        },
      },
    },
    // get information on tokens supporting cross chain transactions (required)
    tokenList: {
      url: `${serverHost}/api/tokens`,
      method: "get",
      requestAfter: (res) => {
        if (res.code !== 200)
          throw new CrossChainBusinessException(errorCodes.ERROR);
        return res.data;
      },
      responseMapping: {
        tokens: {
          format: (tokenResult) => {
            return tokenResult.tokens.map((item: any) => ({
              chainId: Number(item.chainId),
              address: item.address,
              name: item.name,
              symbol: item.symbol,
              decimals: item.decimals,
              logoImg: item.logoImg,
            }));
          },
        },
      },
    },
    buildTransactionData: {
      // API to generate onchain transaction data. If "Route" API doesn't return "transactionData",  need to provide this API (optional)
      url: `${serverHost}/api/buildTransactionData`,
      method: "post",
      headers: { "Content-Type": "application/json" },
      requestAfter: (res) => {
        if (res.code !== 200)
          throw new CrossChainBusinessException(errorCodes.ERROR);
        return res.data;
      },
      requestMapping: {
        // routeId: 'routeId',  // use "route" API to return "interfaceParadData" data.
        routeId: {
          format: (_, { interfaceParamData }) => interfaceParamData.routeId,
        },
        // other params
      },
      responseMapping: {
        data: "data.data",
        value: "data.value",
      },
    },
    createOrder: {
      // Create Order (optional)
      url: `${serverHost}/api/createOrder`,
      method: "post",
      requestAfter: (res) => {
        if (res.code !== 200)
          throw new CrossChainBusinessException(errorCodes.ERROR);
        return res.data;
      },
      requestMapping: {
        routeId: "routeId",
        // other params
      },
      responseMapping: {
        interfaceParamData: {
          orderId: "orderId",
        },
      },
    },
    // Healthcheck API (optional)
    health: {
      url: `${serverHost}/api/health`,
      method: "get",
      requestAfter: (res) => {
        if (res.code !== 0)
          throw new CrossChainBusinessException(errorCodes.SERVICE_UNAVAILABLE);
        return { isAvailable: res.isAvailable, description: res.description };
      },
      responseMapping: {
        isAvailable: "isAvailable",
        description: "description",
      },
    },
  },
  errorCodes, // errors status code
};

export default bridgeNameConfig;

b. Config items

  • name Bridge name
  • apiInterface API interface config API
    • route Route API (required)
      • url URL address (required)
      • method api method: get/post/put (required)
      • headers Request header (optional)
      • before Call this function before execution (optional)
      • after Call this function after execution (optional)
      • requestAfter Call this function after making API request (required)
      • requestMapping API request parameter data
      • responseMapping Data returned as output from API
    • status API to get cross-chain orders status (required)
      ...
    • tokenList API to get information on tokens supporting cross chain transactions (required)
      ...
    • buildTransactionData  API to generate onchain transaction data (optional)
      ...
    • createOrder Create order (optional)
      ...
    • health Health check API (optional)
      ...
  • errorCodes Errors status code

i. route

‘Route’ is used to enquire to get responses such as pricing.

  1. Data request

    Data under default settings for cross-chain requests can be found in ‘CrossChainParamsData’ for configuration. You only need to map these data via ‘requestMapping’.

type CrossChainParamsData = {
  fromChainId: number, // sending chain
  fromAmount: string, // sending amount
  fromTokenAddress: string, // sending token address
  fromTokenDecimals: number, // sending token decimals
  fromTokenPrice: string, // sending token price
  fromPlatformTokenPrice: string,
  toChainId: number, // receiving chain
  toTokenAddress: string, // receiving token address
  toTokenDecimals: number, // receiving token decimals
  toTokenPrice: string, // receiving token price
  fromAddress: string, // sending user address
  toAddress: string, // receiving user address
  slippage: number, // slippage
  fromHash?: string, // sending chain hash
};
  1. Responses

    You need to map the responses in ‘responseMapping’ to return the required fields back to DODO

  • depositContract Deposit contract address
  • toAmount Receiving amount, value in wei
  • fee fees, including swap fees, receiving chain gas fees, cross chain fees, and other fees.
    • swapFee swap fees, value in USD
    • destinationGasFee receiving chain gas fees, value in USD
    • crossChainFee cross chain fees, value in USD
    • otherFee other fees, value in USD
  • otherPayOut Additional fees deducted from wallet when initiating an onchain transaction (e.g. cross chain bridges may require upfront fees paid in sending chain's native token, defined as "otherPayOut")
  • interfaceParamData  "Route" API may return data needed for subsequent actions, and those data can be stored in "interfaceParamData" section for later use

ii. status

To get cross chain orders status

  1. Data request

    Use both ‘CrossChainParamsData’ and ‘interfaceParamsData’ returned from route interface

  2. Responses

    You need to map the responses in ‘responseMapping’ to return the required fields back to DODO

  • toHash receiving chain hash
  • statusInfo Status
    • status Status type
      • PENDING Transaction pending
      • DONE Transaction completed
      • FAILED Transaction failed
      • TRANSFER_REFUNDED Transaction refunded
      • INVALID Data invalid
      • NOT_FOUND Transaction hash couldn’t be found NOT FOUND
    • bridgeResponseResult Responses returned from third party bridges

iii. tokenList

Need responses from third party bridges on tokens supported or available to transact

  1. Data request

    Use ‘CrossChainParamsData’

  2. Responses

    You need to map the responses in ‘responseMapping’ to return the required fields back to DODO

  • tokens Token information
    • chainId Chain ID
    • address Token address
    • name Token name
    • symbol Symbol of the token contract
    • decimalsDecimals of the token contract
    • logoImg Link to token’s logo

iv. buildTransactionData

After getting ‘route’, use ‘buildTransactionData’ to get inputs for sending requests

  1. Data request

    Use both ‘CrossChainParamsData’ and ‘interfaceParamsData’ returned from route interface

  2. Responses

    Return data and value when sending inputs onto chains

  • data Data to be sent onchain
  • value Value to be sent onchain (Hexadecimal)

v. createOrder

After ‘BuildTransaction Data’ interface, call ‘CreateOrder’ to save hash

  1. Data request

    Use both ‘CrossChainParamsData’ and ‘interfaceParamsData’ returned from route interface

  2. Responses

  • interfaceParamData Data can be stored here for later use

vi. health

Call ‘health’ to check services or route is available before calling ‘route’

  1. Data request

    Use ‘CrossChainParamsData’

  2. Responses

    if ‘isAvailable’ returns ‘false’, service is unavailable

  • isAvailable If the service available for use
  • description description

3. Test config

Test configuration settings using method in src/index.ts

1. Test ‘route’ and ’buildTransactionData‘

import {
  buildTransactionData,
  CrossChainParamsData,
  getBridgeConfig,
  getRoute,
} from "../src/index";

const crossChainParamsData: CrossChainParamsData = {
  fromChainId: 56,
  fromAmount: "20000000000000000000",
  fromTokenAddress: "0x55d398326f99059ff775485246999027b3197955",
  fromTokenDecimals: 18,
  fromTokenPrice: "1",
  fromPlatformTokenPrice: "300",
  toChainId: 137,
  toTokenAddress: "0xc2132d05d31c914a87c6611c10748aeb04b58e8f",
  toTokenDecimals: 6,
  toTokenPrice: "1",
  fromAddress: "0xd8C446197cA9eE5b6cFC212460C9C5b621a5e1F2",
  toAddress: "0xd8C446197cA9eE5b6cFC212460C9C5b621a5e1F2",
  slippage: 0.01,
};
const bridgeName = "swft_test";
const swftConfig = await getBridgeConfig(bridgeName);

const routeResult = await getRoute(bridgeName, crossChainParamsData);
console.log("routeResult:", routeResult);
let transactionInfo;
if (swftConfig.apiInterface.buildTransactionData) {
  transactionInfo = await buildTransactionData(
    bridgeName,
    crossChainParamsData,
    routeResult?.interfaceParamData
  );
} else if (routeResult && !routeResult.transactionData) {
  transactionInfo = routeResult.transactionData;
}
console.log("transactionInfo:", transactionInfo);
// Get hash of the onchain transaction after sending data inputs
// wallet.sendTransaction({data:transactionInfo.data,value:transactionInfo.value,...})
// ...

2. Test ‘createOrder‘, ’status‘, ’tokenList‘, ’health’

import { createOrder, getStatus, getTokenList, health } from "../src/index";

const createOrderResult = await createOrder(
  bridgeName,
  crossChainParamsData,
  routeResult?.interfaceParamData
);

const statusResult = await getStatus(
  bridgeName,
  crossChainParamsData,
  routeResult?.interfaceParamData
);

const tokenListResult = await getTokenList(bridgeName, crossChainParamsData);

const healthResult = await health(bridgeName, crossChainParamsData);

4. Submit merged config

Upon completion of configuration, you can submit a merge request with correct configuration information to DODO via https://github.com/DODOEX/dodo-bridge-aggregator/pulls

We will verify your request and proceed to merge, and test in the test environment if data is submitted correctly.