DeFi API
申购流程

申购流程#

对于申购,流程指引见概述中的申购流程部分。

1. 设置你的环境#

设置环境,详情见导入必要的 Node.js 库

2. 搜索平台信息并获取投资品详情#

2.1 搜索协议下投资品列表概要信息#

以下是一个 Node.js 请求的示例。接口信息看这里

步骤 1:定义参数#

接下来,定义查询授权额度的参数。

const getProtocolListParam = {
  platformName: '',
  platformId: ''
};

步骤 2:定义辅助函数#

定义一个辅助函数,用于与 DeFi API 进行交互。

const getProtocolListRequestUrl = (api, queryParams) => {
  const path = api + '?' + new URLSearchParams(queryParams).toString();
  return {
    apiRequestUrl: exploreBaseUrl + path,
    path: exploreBasePath + path,
  };
};
const getProtocolListData = async () => {
  const { apiRequestUrl, path } = getProtocolListRequestUrl(
    '/protocol/list',
    getProtocolListParam
  );
  return fetch(apiRequestUrl, {
    method: 'GET',
    headers: headersParams,
  })
    .then((res) => res.json())
    .then((res) => {
      return res;
    });
};

步骤 3:获取结果#

提示
获取结果。如果需要跳转到投资品详情网页,请使用结果中的 investmentPageUrlPattern 的值并在占位符填加 investmentId 对应值组成 URL;如果要查询投资品详情 API,用 investmentApiUrlPattern 的值拼接 investmentId 对应值组成 URL。
async function someFunction() {
    const { data: protocolListData } = await getProtocolListData();
    console.log(JSON.stringify(protocolListData));
}
someFunction();

发送交易后,你将收到以下响应:

{
    "code": 0,
    "msg": "",
    "data":
    [
        {
            "platformId": 294,
            "platformName": "SpaceFi",
            "platformWebSite": "https://spacefi.io/",
            "investmentApiUrlPattern": "https://www.okx.com/api/v5/defi/explore/product/detail?investmentId=",
            "investmentPageUrlPattern": "https://www.okx.com/cn/web3/defi/detail/${investmentId}",
            "platformMinInfos":
            [
                {
                    "investmentId": "21010",
                    "protocolId": "207",
                    "network": "ZKSYNC",
                    "chainId": "1"
                },
                {
                    "investmentId": "21011",
                    "protocolId": "207",
                    "network": "ZKSYNC",
                    "chainId": "1"
                }
            ]
        }
    ]
}

2.2 搜索投资品详情信息#

你可以通过上一步获得的 investmentApiUrlPattern 和 investmentId 属性来组成投资品详情的 URL。接口信息参照这里

步骤 1:定义参数#

定义查询授权额度的参数。

const getProductDetailParam = {
  investmentId: '21010',
  investmentCategory: ''
};

步骤 2:定义辅助函数#

定义一个辅助函数,用于与 DeFi API 进行交互。

const getProductDetailRequestUrl = (api, queryParams) => {
  const path = api + '?' + new URLSearchParams(queryParams).toString();
  return {
    apiRequestUrl: exploreBaseUrl + path,
    path: exploreBasePath + path,
  };
};
const getProductDetailData = async () => {
  const { apiRequestUrl, path } = getProductDetailRequestUrl(
    '/product/detail',
    getProductDetailParam
  );
  return fetch(apiRequestUrl, {
    method: 'GET',
    headers: headersParams,
  })
    .then((res) => res.json())
    .then((res) => {
      return res;
    });
};

步骤 3:获取结果#

async function someFunction() {
    const { data: productDetailData } = await getProductDetailData();
    console.log(JSON.stringify(productDetailData));
}
someFunction();

发送交易后,你将收到以下响应:

{
    "code": 0,
    "msg": "",
    "data":
    {
        "investmentId": "21010",
        "investmentName": "USDC-ETH",
        "chainId": "324",
        "rate": "0.06340",
        "investType": "2",
        "platformName": "SpaceFi",
        "platformId": "491",
        "analysisPlatformId": "294",
        "poolVersion": "1",
        "rateType": "1",
        "tvl": "4464444.45647",
        "underlyingToken":
        [
            {
                "tokenSymbol": "USDC",
                "tokenAddress": "0x3355df6d4c9c3035724fd0e3914de96a5a83aaf4",
                "isBaseToken": false
            },
            {
                "tokenSymbol": "ERA_ETH",
                "tokenAddress": "0x0000000000000000000000000000000000000000",
                "isBaseToken": true
            }
        ],
        "isInvestable": true,
        "earnedToken":
        [
            {
                "tokenSymbol": "USDC",
                "tokenAddress": "0x3355df6d4c9c3035724fd0e3914de96a5a83aaf4",
                "isBaseToken": false
            },
            {
                "tokenSymbol": "ERA_ETH",
                "tokenAddress": "0x0000000000000000000000000000000000000000",
                "isBaseToken": true
            }
        ],
        "lpToken":
        [
            {
                "tokenSymbol": "SLP",
                "tokenAddress": "0xd0ce094412898760c2a5e37abec39b0e785b45ae",
                "isBaseToken": false
            }
        ],
        "subscriptionMethod": "2",
        "redeemMethod": "2"
    }
}

3. 查询投资预估收益信息计算#

投资产品的有效数据。你可以通过输入想要投资的金额,得到你预估的投资收益信息。接口详情看这里

步骤 1:定义参数#

接下来,定义计算投资申购收益的参数。

const getSubscribeInfoBody = {
  inputAmount: "1",
  inputTokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
  investmentId: "21200",
  address: "0x7f****da",
  investmentType: "0",
  tokenDecimal: "18",
  isSingle: false
};

步骤 2:定义辅助函数#

定义一个辅助函数,用于与 DeFi API 进行交互。

const getSubscribeInfoData = async () => {
  return fetch(calculatorBaseUrl + '/subscribe-info', {
    method: 'POST',
    headers: headersParams,
    body: JSON.stringify(getSubscribeInfoBody),
  })
    .then((res) => res.json())
    .then((res) => {
      return res;
    });
};

步骤 3:获取结果#

async function someFunction() {
    const { data: subscribeInfoData } = await getSubscribeInfoData();
    console.log(subscribeInfoData);
}

someFunction();

发送交易后,你将收到以下响应:

{
    "code": 0,
    "msg": "",
    "data":
    {
        "investWithTokenList":
        [
            {
                "tokenSymbol": "CORE",
                "tokenName": "Core",
                "tokenAddress": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                "network": "CORE",
                "chainId": "1116",
                "tokenPrecision": "18",
                "isBaseToken": true,
                "coinAmount": "1",
                "currencyAmount": "0.4918"
            }
        ],
        "gainsTokenList":
        [
            {
                "tokenSymbol": "CORE",
                "tokenName": "Core",
                "tokenAddress": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                "network": "CORE",
                "tokenPrecision": "18",
                "coinAmount": "0.00069321843585011",
                "dataType": "0"
            }
        ],
        "approveStatusList":
        [
            {
                "tokenSymbol": "CORE",
                "tokenAddress": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                "network": "CORE",
                "chainId": "1116",
                "tokenPrecision": "18",
                "isNeedApprove": false,
                "approveAddress": "0x0000000000000000000000000000000000001007",
                "orderType": "3"
            }
        ],
        "isSwapInvest": false,
        "estimateGasFee": "99343",
        "isAllowSubscribe": true,
        "validatorName": "OKXEarn"
    }
}

4. 生成用于申购交易的调用数据#

我们进行认购的流程如下:

4.1 申购授权#

以下是一个 Node.js 请求的示例。接口信息看这里

步骤 1:定义参数#

定义授权申购额度的参数。

const userInputList = [
   {
   "chainId": "56",
   "coinAmount": "10",
   "tokenAddress": "0x526a913a7a4518aa2abc3dcd3c46a9c73f40f94a"
   }
   ];
const getTransactionAuthorizationBody = {
  address: '0x7f****da',
  type: '3',
  investmentId: '6925',
  userInputList: userInputList
};

步骤 2:定义辅助函数#

定义一个辅助函数,用于与 DeFi API 进行交互。

const getTransactionAuthorizationData = async () => {
  return fetch(transactionBaseUrl + '/authorization', {
    method: 'POST',
    headers: headersParams,
    body: JSON.stringify(getTransactionAuthorizationBody),
  })
    .then((res) => res.json())
    .then((res) => {
      return res;
    });
};

步骤 3:获取结果#

async function someFunction() {
    const { data: transactionAuthorizationData } = await getTransactionAuthorizationData();
    console.log(transactionAuthorizationData);
}

someFunction();

发送交易后,你将收到以下响应:

{
    "code": 0,
    "msg": "",
    "data":
    {
        "dataList":
        [
            {
                "from": "0x7f4****da",
                "to": "0x52****4a",
                "value": "0x0",
                "serializedData": "0x095ea7b30000000000000000000000002c34a2fb1d0b4f55de51e1d0bdefaddce6b7cdd60000000000000000000000000000000000000000000000008ac7230489e80000",
                "originalData": "{\"methodDefine\":\"approve(address,uint256)\",\"methodId\":\"0x095ea7b3\",\"methodType\":\"METHOD_ID\",\"params\":{\"params\":[\"0x2c34a2fb1d0b4f55de51e1d0bdefaddce6b7cdd6\",\"10000000000000000000\"]},\"useAdapter\":false}",
                "signatureData": "1bca0efbd1c809de94cdd8c924329c7ac79a4d346742de61925e8494f2c84c446bd3cf42b56d690c85ff513beadf46cd18f4e3e74845a92c48451584615f749d1c"
            }
        ]
    }
}

4.2 申购交易#

以下是一个 Node.js 请求的示例。接口详情看这里

步骤 1:定义参数#

定义查询申购投资品的参数。

const userInputList = [
   {
   "coinAmount": "0.6"
   }
   ];
const expectOutputList = [
   {
   "coinAmount": "0.6"
   }
   ];
const getTransactionSubscriptionBody = {
  address: '0x7f****da',
  investmentId: '6925',
  userInputList: userInputList,
  expectOutputList: expectOutputList
};

步骤 2:定义辅助函数#

定义一个辅助函数,用于与 DeFi API 进行交互。

const getTransactionSubscriptionData = async () => {
  return fetch(transactionBaseUrl+'/subscription', {
    method: 'post',
    headers: headersParams,
    body: JSON.stringify(getTransactionSubscriptionBody),
  })
    .then((res) => res.json())
    .then((res) => {
      return res;
    });
};

步骤 3:获取结果#

async function someFunction() {
    const { data: transactionSubscriptionData } = await getTransactionSubscriptionData();
    console.log(transactionSubscriptionData);
}

someFunction();

发送交易后,你将收到以下响应:

{
    "code": 0,
    "msg": "",
    "data":
    {
        "dataList":
        [
            {
                "from": "0x7f****da",
                "to": "0x72****d2",
                "value": "0x0",
                "serializedData": "0x016cba5f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000526a913a7a4518aa2abc3dcd3c46a9c73f40f94a0000000000000000000000000000000000000000000000000853a0d2313c00000000000000000000000000005569e13b1ec4336d17e8f24d892a4a915fc5da9400000000000000000000000000000000000000000000000000000000000000010000000000000000000000004e38a4ad4f210ad5abb2c8f2598706ae8b4a1ce600000000000000000000000000000000000000000000000006f05b59d3b20000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000005569e13b1ec4336d17e8f24d892a4a915fc5da94000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e4c41a3be800000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e38a4ad4f210ad5abb2c8f2598706ae8b4a1ce60000000000000000000000007f429edeff8afc7bb3a2cf7db832fc86f6fa99da00000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000026f700000000000000000000000000000000000000000000000000000000",
                "originalDataClass": "OriginalDataEntrance",
                "originalData": "{\"hexCallData\":\"0x016cba5f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000526a913a7a4518aa2abc3dcd3c46a9c73f40f94a0000000000000000000000000000000000000000000000000853a0d2313c00000000000000000000000000005569e13b1ec4336d17e8f24d892a4a915fc5da9400000000000000000000000000000000000000000000000000000000000000010000000000000000000000004e38a4ad4f210ad5abb2c8f2598706ae8b4a1ce600000000000000000000000000000000000000000000000006f05b59d3b20000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000005569e13b1ec4336d17e8f24d892a4a915fc5da94000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e4c41a3be800000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e38a4ad4f210ad5abb2c8f2598706ae8b4a1ce60000000000000000000000007f429edeff8afc7bb3a2cf7db832fc86f6fa99da00000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000026f700000000000000000000000000000000000000000000000000000000\",\"methodDefine\":\"{\\n\\t\\\"inputs\\\": [{\\n\\t\\t\\\"components\\\": [{\\n\\t\\t\\t\\\"internalType\\\": \\\"struct TokenInInfo\\\",\\n\\t\\t\\t\\\"name\\\": \\\"tokenIn\\\",\\n\\t\\t\\t\\\"type\\\": \\\"tuple[]\\\",\\n\\t\\t\\t\\\"components\\\": [{\\n\\t\\t\\t\\t\\\"internalType\\\": \\\"address\\\",\\n\\t\\t\\t\\t\\\"name\\\": \\\"token\\\",\\n\\t\\t\\t\\t\\\"type\\\": \\\"address\\\"\\n\\t\\t\\t}, {\\n\\t\\t\\t\\t\\\"internalType\\\": \\\"uint256\\\",\\n\\t\\t\\t\\t\\\"name\\\": \\\"amount\\\",\\n\\t\\t\\t\\t\\\"type\\\": \\\"uint256\\\"\\n\\t\\t\\t}, {\\n\\t\\t\\t\\t\\\"internalType\\\": \\\"address\\\",\\n\\t\\t\\t\\t\\\"name\\\": \\\"to\\\",\\n\\t\\t\\t\\t\\\"type\\\": \\\"address\\\"\\n\\t\\t\\t}]\\n\\t\\t}, {\\n\\t\\t\\t\\\"internalType\\\": \\\"struct TokenAmount\\\",\\n\\t\\t\\t\\\"name\\\": \\\"tokenOut\\\",\\n\\t\\t\\t\\\"type\\\": \\\"tuple[]\\\",\\n\\t\\t\\t\\\"components\\\": [{\\n\\t\\t\\t\\t\\\"internalType\\\": \\\"address\\\",\\n\\t\\t\\t\\t\\\"name\\\": \\\"token\\\",\\n\\t\\t\\t\\t\\\"type\\\": \\\"address\\\"\\n\\t\\t\\t}, {\\n\\t\\t\\t\\t\\\"internalType\\\": \\\"uint256\\\",\\n\\t\\t\\t\\t\\\"name\\\": \\\"amount\\\",\\n\\t\\t\\t\\t\\\"type\\\": \\\"uint256\\\"\\n\\t\\t\\t}]\\n\\t\\t}],\\n\\t\\t\\\"internalType\\\": \\\"struct BaseRequest\\\",\\n\\t\\t\\\"name\\\": \\\"request\\\",\\n\\t\\t\\\"type\\\": \\\"tuple\\\"\\n\\t}, {\\n\\t\\t\\\"components\\\": [{\\n\\t\\t\\t\\\"internalType\\\": \\\"address\\\",\\n\\t\\t\\t\\\"name\\\": \\\"target\\\",\\n\\t\\t\\t\\\"type\\\": \\\"address\\\"\\n\\t\\t}, {\\n\\t\\t\\t\\\"internalType\\\": \\\"bytes\\\",\\n\\t\\t\\t\\\"name\\\": \\\"callData\\\",\\n\\t\\t\\t\\\"type\\\": \\\"bytes\\\"\\n\\t\\t}],\\n\\t\\t\\\"internalType\\\": \\\"struct Call\\\",\\n\\t\\t\\\"name\\\": \\\"calls\\\",\\n\\t\\t\\\"type\\\": \\\"tuple[]\\\"\\n\\t}],\\n\\t\\\"name\\\": \\\"execute\\\",\\n\\t\\\"stateMutability\\\": \\\"payable\\\",\\n\\t\\\"type\\\": \\\"function\\\"\\n}\",\"methodId\":\"\",\"methodType\":\"ABI\",\"params\":{\"baseRequest\":{\"tokenIn\":[{\"amount\":600000000000000000,\"to\":\"0x5569e13b1ec4336d17e8f24d892a4a915fc5da94\",\"token\":\"0x526a913a7a4518aa2abc3dcd3c46a9c73f40f94a\"}],\"tokenOut\":[{\"amount\":500000000000000000,\"token\":\"0x4e38a4ad4f210ad5abb2c8f2598706ae8b4a1ce6\"}]},\"operatorDataList\":[{\"adapterOperate\":true,\"call\":{\"calls\":\"xBo76AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATjikrU8hCtWrssjyWYcGrotKHOYAAAAAAAAAAAAAAAB/Qp7e/4r8e7Oiz324MvyG9vqZ2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbwW1nTsgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACb3\",\"callsAsString\":\"0xc41a3be800000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e38a4ad4f210ad5abb2c8f2598706ae8b4a1ce60000000000000000000000007f429edeff8afc7bb3a2cf7db832fc86f6fa99da00000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000026f7\",\"target\":\"0x5569e13b1ec4336d17e8f24d892a4a915fc5da94\"},\"hexCallData\":\"0xc41a3be800000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e38a4ad4f210ad5abb2c8f2598706ae8b4a1ce60000000000000000000000007f429edeff8afc7bb3a2cf7db832fc86f6fa99da00000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000026f7\",\"operateType\":\"DEPOSIT\",\"operatorMethodInfo\":{\"methodDefine\":\"{\\n\\t\\\"inputs\\\": [{\\n\\t\\t\\\"internalType\\\": \\\"address\\\",\\n\\t\\t\\\"name\\\": \\\"pool\\\",\\n\\t\\t\\\"type\\\": \\\"address\\\"\\n\\t}, {\\n\\t\\t\\\"internalType\\\": \\\"struct TokenOutInfo\\\",\\n\\t\\t\\\"name\\\": \\\"tokenOut\\\",\\n\\t\\t\\\"type\\\": \\\"tuple\\\",\\n\\t\\t\\\"components\\\": [{\\n\\t\\t\\t\\t\\\"internalType\\\": \\\"address\\\",\\n\\t\\t\\t\\t\\\"name\\\": \\\"token\\\",\\n\\t\\t\\t\\t\\\"type\\\": \\\"address\\\"\\n\\t\\t\\t}, {\\n\\t\\t\\t\\t\\\"internalType\\\": \\\"address\\\",\\n\\t\\t\\t\\t\\\"name\\\": \\\"toAddress\\\",\\n\\t\\t\\t\\t\\\"type\\\": \\\"address\\\"\\n\\t\\t\\t},\\n\\t\\t\\t{\\n\\t\\t\\t\\t\\\"internalType\\\": \\\"uint256\\\",\\n\\t\\t\\t\\t\\\"name\\\": \\\"minAmount\\\",\\n\\t\\t\\t\\t\\\"type\\\": \\\"uint256\\\"\\n\\t\\t\\t}\\n\\t\\t]\\n\\t}, {\\n\\t\\t\\\"internalType\\\": \\\"bytes\\\",\\n\\t\\t\\\"name\\\": \\\"data\\\",\\n\\t\\t\\\"type\\\": \\\"bytes\\\"\\n\\n\\t}],\\n\\t\\\"name\\\": \\\"deposit\\\",\\n\\t\\\"stateMutability\\\": \\\"payable\\\",\\n\\t\\\"type\\\": \\\"function\\\"\\n}\",\"params\":{\"data\":\"00000000000000000000000000000000000000000000000000000000000026f7\",\"pool\":\"0x0000000000000000000000000000000000000000\",\"tokenOut\":{\"amount\":500000000000000000,\"toAddress\":\"0x7f429edeff8afc7bb3a2cf7db832fc86f6fa99da\",\"token\":\"0x4e38a4ad4f210ad5abb2c8f2598706ae8b4a1ce6\"}}},\"target\":\"0x5569e13b1ec4336d17e8f24d892a4a915fc5da94\"}]},\"useAdapter\":true}",
                "signatureData": "dbfe682a491b31141c99800913c9a052ee8dee122854cb0c459af85fff9f5d571aaf217b3bbbe10b141247bc0327357c3dde2874333f8a4c031d84d31a41ffec1c"
            }
        ]
    }
}

5. 签名和广播#

签名时可以直接使用第三步获得的 serializedData 作为 Call data,也可以由用户通过 originalData 自己拼装 Call data 进行签名广播。EVM 类投资品参考签名示例