DEX API

使用 Widget#

本文将告诉你如何将功能强大的欧易 Widget 与你的产品进行整合,让你只需 30 分钟即可搭建一个高效交易界面!

安装#

yarn add @okxweb3/dex-widget
// or
npm install @okxweb3/dex-widget
// or
pnpm add @okxweb3/dex-widget

快速开始#

下方的例子将向你演示如何在一个 React 项目中使用 @okxweb3/dex-widget。你还可以通过此链接查看更多例子。

实际 Demo:https://okx.github.io/dex-widget/

import React, { useRef, useEffect } from 'react';
import ReactDOM from 'react-dom/client';

import { createOkxSwapWidget } from '@okxweb3/dex-widget';

function App() {
  const widgetRef = useRef();

  useEffect(() => {
    const params = {
      width: 375,
      providerType: 'EVM',
    };
    const provider = window.ethereum;

    const listeners = [
      {
        event: 'ON_CONNECT_WALLET',
        handler: () => {
          provider.enable();
        },
      },
    ];

    const instance = createOkxSwapWidget(widgetRef.current, {
      params,
      provider,
      listeners,
    });
    return () => {
      instance.destroy();
    };
  }, []);

  return <div ref={widgetRef} />;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

钱包提供方#

如果需要连接钱包,你可以从你的应用中传递钱包提供方信息。同时添加 ON_CONNECT_WALLET 事件,即可无缝连接并使用 Widget。

  • 如果提供方是在 Ethereum 或其他 EVM 网络上,它必须要符合 EIP-1193 才能创建交易界面。
  • 如果提供方是在 Solana 网络上,它必须从你的应用中传递钱包提供方的信息,例如 window.solana 或 window.okexchain.solana。
import { createOkxSwapWidget, ProviderType } from '@okxweb3/dex-widget';

const widgetEthInstance = createOkxSwapWidget(
  document.getElementById('widget'),
  {
    params: {
      providerType: ProviderType.EVM,
    },
    provider: window.ethereum, // e.g. window.okexchain
  }
);

const widgetSolanaInstance = createOkxSwapWidget(
  document.getElementById('widget'),
  {
    params: {
      providerType: ProviderType.SOLANA,
    },
    provider: window.solana, // window.okexchain.solana
  }
);

Rainbow 连接钱包组件的示例可参考这个链接

参数#

下方表格内是对 Params 的描述。

参数类型默认值描述
widthnumber450用 css 值 (px) 表示的 Widget 宽度。如果未设置宽度,则宽度的展示样式为:>767px 显示为 450 px, <768 px 显示为 100%, < 375 px 则显示为 375 px。
themeTHEMElight兑换 Widget 提供默认的日间、夜间主题选项。你可以按下方示例来切换 Widget 的主题。
langstringen_us你可以调整 Widget 所使用的语言,请在多语言配置部分了解更多细节信息。
tradeTypeTradeTypeauto交易的类型,可以是“swap”、“bridge”,或“auto”。注意:“自动”包含“swap”和“bridge”。
chainIdsArray<string>[]承载单链兑换的区块链的 ID,请在 ChainId 配置部分查看你可选的所有网络。
feeConfigIFeeConfig{}你可以选择在 Widget 中为所有交易类型设置一个费率,请在自定义费率部分了解详情。
tokenPairITokenPair{}你所设定使用的兑换默认代币对,请在默认币对配置部分了解详情。
bridgeTokenPairITokenPair{}你所设定使用的跨链默认代币对,请在默认币对配置部分了解详情。
providerTypeProviderType' 'ProviderType 是和提供方一致的类型参数,例如,如果提供方是 Solana,那么 providerType 就会是 SOLANA。

类型描述#

interface IFeeConfig {
    [key: string]: {
        feePercent?: string | number;
        referrerAddress?: {
            [key: string]: {
                feePercent: string | number;
            };
        };
    };
}

interface ITokenPair {
    fromChain: string | number;
    toChain: string | number;
    fromToken?: string;
    toToken?: string;
}

enum ProviderType {
    EVM = 'EVM',
    SOLANA = 'SOLANA',
    WALLET_CONNECT = 'WALLET_CONNECT',
}

enum TradeType {
    SWAP = 'swap',
    BRIDGE = 'bridge',
    AUTO = 'auto',
}

enum THEME {
    LIGHT = 'light',
    DARK = 'dark',
}

多语言配置#

lang描述
en_usEnglish,默认
zh_cn简体中文
zh_tw繁體中文
fr_frFrançais (Afrique)
id_idBahasa Indonesia
ru_ruРусский
tr_trTürkçe
vi_vnTiếng Việt
de_deDeutsch
it_itItaliano
pl_plPolski
pt_ptPortuguês (Portugal)
es_esEspañol (España)
pt_brPortuguês (Brasil)
es_419Español (Latinoamérica)
cs_czČeština
ro_roRomână
uk_uaУкраїнська
ar_ehالعربية
nl_nlNederlands

ChainId 配置#

网络ChainId主网币合约地址
Ethereum10xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
zkSync Era3240xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
Optimism100xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
Polygon1370xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
Avalanche C431140xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
Arbitrum421610xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
Linea591440xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
Base84530xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
Mantle50000xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
Scroll5343520xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
X layer1960xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
Blast814570xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
BNB Chain560xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
Solana50111111111111111111111111111111111

默认币对配置#

tokenPair: 如果没有配置,则单链兑换将默认设置在 Ethereum 网络,且 fromToken 为 ETH,toToken 为 USDC。

bridgeTokenPair: 如果没有配置,则跨链兑换将默认设置为从 Ethereum 跨链至 BNB Chain,且 fromToken 为 ETH,toToken 为 BNB。

import React, { useEffect, useRef } from 'react';
import {
  OkxSwapWidgetParams,
  ProviderType,
  TradeType,
} from '@okxweb3/dex-widget';

const provider = window.ethereum;

export function EvmWidget() {
  const widgetRef = useRef();

  const params = {
    chainIds: ['1', '10'],
    lang: 'zh_cn',
    providerType: ProviderType.EVM,
    theme: 'dark',
    tradeType: TradeType.AUTO,
    tokenPair: {
      fromChain: 1, //ETH
      toChain: 1, // ETH
      fromToken: '0xdac17f958d2ee523a2206206994597c13d831ec7', // USDT
      toToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // ETH
    },
    bridgeTokenPair: {
      fromChain: 1, //ETH
      toChain: 56, // BNB
      fromToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // ETH
      toToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // BNB
    },
  };
  const initialConfig = {
    params,
    provider,
    listeners: [
      {
        event: 'ON_CONNECT_WALLET',
        handler: (token, preToken) => {
          provider.enable();
        },
      },
    ],
  };

  useEffect(() => {
    const widgetHandler = createOkxSwapWidget(widgetRef.current, initialConfig);

    return () => {
      widgetHandler?.destroy();
    };
  }, []);

  return <div ref={widgetRef} />;
}
参数类型描述
fromChainStringfromToken 所属的源链 ID (例如,1:Ethereum,可在 ChainId 配置部分查看所有已支持的网络和对应的链 ID)。
fromTokenString试图卖出的代币的合约地址,例如 ETH:0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE。如果 fromToken 是某一区块链的主网币,请查看链 ID 以获取合约地址。
toChainStringtoToken 所属的目标链 ID (例如,1:Ethereum,可在 ChainId 配置部分查看所有已支持的网络和对应的链 ID)。
toTokenString试图卖出的代币的合约地址,例如 USDC:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48。如果 toToken 是某一区块链的主网币,请查看链 ID 以获取合约地址。

自定义费率#

添加下列参数后,你即可启用 feeConfig 在你的用户在各个网络上执行交易时,通过 Widget 收取手续费:

你需要声明 chainId、feePercent 和 referrerAddress。

在 Ethereum 和其他 EVM 网络,设置 feePercent 和 referrerAddress 即可收取手续费。

在 Solana 网络,SOL 和 SPL 代币的分佣有些不同。SOL 分佣使用的是钱包地址,而 SPL 代币分佣使用的是代币账号。

你可以添加 feePercent 以调整 referrerAddress 所收到的分佣的费率。

// EVM feeConfig example
feeConfig: {
    [chainId]: {
        referrerAddress: 'xxx',
        feePercent: [0-3],
    }
}

// Solana feeConfig example

feeConfig: {
    [chainId]: {
        feePercent: [0-3],
        referrerAddress: {
          [tokenContractA]: {
            referrerAccount: 'account/abc',
            feePercent: '1',
          },
          [tokenContractB]: {
            referrerAccount: 'account/abc',
            feePercent: '2',
          }
        }
    }
}

// Full Example
feeConfig: {
  1: {// Ethereum chainId
    feePercent: 3, // The percentage of Fee
    referrerAddress: '0x38a3b108eb2b97c307bf5788909f8c12afd0cd6b', // eth address that receives the fee
  },
  56: { // Bnb Chain chainId
    feePercent: 3, //
    referrerAddress: '0x38a3b108eb2b97c307bf5788909f8c12afd0cd6b', // bnb address that receives the fee
  },
  501: { // solana chainId
    referrerAddress: {
      '11111111111111111111111111111111': { //solana SOL contract address
        account: '6rocMMKG1DNg93RDfVL2xVdrA5nbAT8cFMbdvVTHUF4m',
        feePercent: 1,
      },
      EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v: { //solana USDC contract address
        account: 'C6XW7mFvCuVxYFTi9zTQrUcwkvhfGYAvuosXz6pLDZsa', //solana USDC token account that receives the fee
        feePercent: 1,
      },
      JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN: { //solana JUP contract address
        account: 'Ezq6jTC3CwnsXDSdtgy8Sa4xi1iA6fxuEeXxWFPLG9sc', //solana JUP token account that receives the fee
        feePercent: 1,
      },
    },
  },
  8453: {
    feePercent: 3,
    referrerAddress: '0x38a3b108eb2b97c307bf5788909f8c12afd0cd6b',
  },
}

feePercent#

发送给分佣地址的 fromTokenAmount 的百分比。剩余的代币数量将被设置为卖出数量。费率用基点 (BPS) 计算,一个基点等于 0.01% (万分之一)。费率不能超过 3% (300 BPS)。

referrerAddress#

referrerAddress 是接收手续费的地址。

请确保接收手续费的地址存在于参数表中所定义的对应网络之上。

Widget 更新#

updateParams#

可更新的属性:theme、lang、width

// 1. Create and initialize the widget
const widgetHandler = createOkxSwapWidget(container, initialConfig);

// 2. Update the widget's parameters (e.g., change theme or size)
widgetHandler.updateParams({
  width: 700,
  theme: 'light',
  lang: 'tr_tr',
});

updateProvider#

Widget 支持 EVM 和 Solana。当从 EVM 切换到 Solana 时,请记得更新相应的 Widget 提供方,反之亦然。

如果首次渲染时没有传递提供方信息,并想要 Widget 响应钱包绑定,就需要调用 updateProvider。

// 3. Update the provider if the user connects a different wallet, EVM => SOLANA
widgetHandler.updateProvider(window.solana, ProviderType.SOLANA);
// SOLANA => EVM
// widgetHandler.updateProvider(window.ethereum, ProviderType.EVM);

updateListeners#

你可以更新 Widget 监听的事件。

// 4. Modify event listeners to handle new types of events
widgetHandler.updateListeners([
  {
    event: OkxEvents.ON_FROM_CHAIN_CHANGE,
    handler: (payload) => {
      //
    },
  },
]);
  • Listeners 主要用于监听 Widget 向外部暴露的接口,通过不同事件进行定制化处理。而 updateListeners 则用于在切换链后更新定制化处理。
  • 通过添加事件监听器,可以捕获并处理从 iframe 中传递出来的事件数据。这些数据通常是 iframe 内部发生的事件或状态变化,并通过事件传递到外部页面。
  • 接收到的数据可以根据需求进行灵活处理和操作。这意味着你可以根据传递的数据类型或内容,执行不同的逻辑或更新界面元素。
  • 通过 updateListeners 方法,你可以为不同类型的事件 (如 OkxEvents.ON_FROM_CHAIN_CHANGE) 添加处理函数。当事件触发时,处理函数会接收到相关的 payload 数据,以便你进一步操作。

destroy#

当清除 Widget 模块时,调用此方法

const widgetHandler = createOkxSwapWidget(container, initialConfig);

widgetHandler.destory();

注意:#

  • 每当你刷新和更新时,请确保调用 destroy 方法来清除先前绑定的事件,以避免出现重复订单请求。

事件监听#

Widget 为 ON_CONNECT_WALLET 和 ON_FROM_CHAIN_CHANGE 提供事件监听。

  • ON_CONNECT_WALLET:当 Widget 未连接钱包并点击了连接钱包按钮时触发此事件。
  • ON_FROM_CHAIN_CHANGE: 当 fromChain 发生变化时会触发此事件。

使用方法如下:

import {createOkxSwapWidget, OkxSwapWidgetParams, OkxEventListeners, OkxEvents} from '@cowprotocol/widget-lib'

const params: OkxSwapWidgetParams = {
    // ...
}

const listeners: OkxEventListeners = [
    {
        event: OkxEvents.ON_CONNECT_WALLET,
        handler: () => {
            // open connect wallet method, eg openConnectModal of the rainbow kit.
            window.ethereum.enable()
        }
    },
    {
        event: OkxEvents.ON_FROM_CHAIN_CHANGE,
        handler: (token) => {
            //
        }
    },
]

const { updateListeners } = createCowSwapWidget(container, { params, listeners, provider })