Subscription process#
For the subscription process, please refer to the subscription flow section in the overview.
1. Set up your environment#
Set up your environment. For details, please refer to the Importing Necessary Node.js Libraries.
2. Search for platform information and get investment product details#
2.1 Search for summary information of investment products under a protocol#
Here is an example of a Node.js request. For interface information, refer to here.
Step 1: Define parameters#
Next, define the parameters for querying the summary information of investment products.
const getProtocolListParam = {
platformName: '',
platformId: ''
};
Step 2: Define helper function#
Define a helper function to interact with the 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;
});
};
Step 3: Get the result#
async function someFunction() {
const { data: protocolListData } = await getProtocolListData();
console.log(JSON.stringify(protocolListData));
}
someFunction();
After sending the transaction, you will receive the following response:
{
"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 Search for investment product details#
You can use the investmentApiUrlPattern and investmentId attributes obtained in the previous step to form the URL for investment product details. Refer to the interface information here.
Step 1: Define parameters#
Define the parameters for querying the investment product details.
const getProductDetailParam = {
investmentId: '21010',
investmentCategory: ''
};
Step 2: Define helper function#
Define a helper function to interact with the 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;
});
};
Step 3: Get the result#
async function someFunction() {
const { data: productDetailData } = await getProductDetailData();
console.log(JSON.stringify(productDetailData));
}
someFunction();
After sending the transaction, you will receive the following response:
{
"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. Query investment estimated earnings calculation#
Retrieve valid data for an investment product. You can input the desired investment amount to obtain the estimated investment earnings information. Refer to the interface details here.
Step 1: Define parameters#
Next, define the parameters for calculating investment subscription earnings.
const getSubscribeInfoBody = {
inputAmount: "1",
inputTokenAddress: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
investmentId: "21200",
address: "0x7f****da",
investmentType: "0",
tokenDecimal: "18",
isSingle: false
};
Step 2: Define helper function#
Define a helper function to interact with the 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;
});
};
Step 3: Get the result#
async function someFunction() {
const { data: subscribeInfoData } = await getSubscribeInfoData();
console.log(subscribeInfoData);
}
someFunction();
After sending the transaction, you will receive the following response:
{
"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. Generate call data for subscription transaction#
The subscription process consists of the following steps:
4.1 Subscription authorization#
Here is an example of a Node.js request. Refer to the interface details here.
Step 1: Define parameters#
Define the parameters for authorizing the subscription amount.
const userInputList = [
{
"chainId": "56",
"coinAmount": "10",
"tokenAddress": "0x526a913a7a4518aa2abc3dcd3c46a9c73f40f94a"
}
];
const getTransactionAuthorizationBody = {
address: '0x7f****da',
type: '3',
investmentId: '6925',
userInputList: userInputList
};
Step 2: Define helper function#
Define a helper function to interact with the 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;
});
};
Step 3: Get the result#
async function someFunction() {
const { data: transactionAuthorizationData } = await getTransactionAuthorizationData();
console.log(transactionAuthorizationData);
}
someFunction();
After sending the transaction, you will receive the following response:
{
"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 Subscription transaction#
Here is an example of a Node.js request. For detailed information about the API, refer to here.
Step 1: Define parameters#
Define the parameters for querying subscription investments.
const userInputList = [
{
"coinAmount": "0.6"
}
];
const expectOutputList = [
{
"coinAmount": "0.6"
}
];
const getTransactionSubscriptionBody = {
address: '0x7f****da',
investmentId: '6925',
userInputList: userInputList,
expectOutputList: expectOutputList
};
Step 2: Define helper function#
Define a helper function to interact with the 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;
});
};
Step 3: Get the result#
async function someFunction() {
const { data: transactionSubscriptionData } = await getTransactionSubscriptionData();
console.log(transactionSubscriptionData);
}
someFunction();
After sending the transaction, you will receive the following response:
{
"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. Signature and broadcasting#
During the signing process, you can directly use the serializedData obtained in step 3 as call data, or you can let users assemble callData using originalData for signing and broadcasting. For EVM-based investments, you can refer to the signature example.