在本指南中,我们将向你展示如何在 OKX 或 OpenSea 平台上创建挂单。该端点在单个请求中仅支持一个平台。此过程包括:
设置环境,详情见导入必要的 Node.js 库
步骤 1:构建标题参数。对于所有其他可重用参数,详情见设置你的环境变量
const requestUrl = 'https://www.okx.com/api/v5/mktplace/nft/markets/create-listing';
const chain = 'eth'; // we will use ethereum as example
const platform = 'okx'; // the platform you want to list on, for opensea use 'opensea'
const originalMessage = JSON.stringify({
chain: chain,
walletAddress: walletAddress,
items:[
{
collectionAddress: '0x175edb154ed7a0e54410a7f547aaa7e3fbf21a34', // the collection of nft you want to list
tokenId: '3518', // the token id of the nft from the collection
price: '100000000000000',
currencyAddress: '0x0000000000000000000000000000000000000000', // ethereum main net token address
count: 1, // number of NFT
validTime: 1701915719, // listing expire time
platform: platform // support opensea or okx only
}
]
});
const headersParams = {
'Content-Type': 'application/json',
'OK-ACCESS-KEY': apiKey,
'OK-ACCESS-SIGN': cryptoJS.enc.Base64.stringify(
cryptoJS.HmacSHA256(timestamp + 'POST' + '/api/v5/mktplace/nft/markets/create-listing' + originalMessage , secretKey)
),
'OK-ACCESS-TIMESTAMP': timestamp,
'OK-ACCESS-PASSPHRASE': passphrase,
};
步骤 2: 使用 headersParam 和 originalMessage 作为请求体,发送 create-listing 接口的请求
return fetch(requestUrl, {method: 'post',headers: headersParams,body: originalMessage}).then((res) => res.json()).then((res) => {return JSON.stringify(res);});
当您进行此请求时获取返回数据。主要目的是获取下面的订单数据,然后可以将其用于在 OKX 或 OpenSea 平台上提交列表。 步骤 3:从第 1 步的响应中提取订单数据并将其赋值给一个变量。
const contractMessage = {
conduitKey: '0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000',
consideration: [
{
endAmount: '900000000000000',
identifierOrCriteria: '0',
itemType: 0,
recipient: '0xa03bb8d8099c994ed87361f5c9857e13fc7c5ccf',
startAmount: '900000000000000',
token: '0x0000000000000000000000000000000000000000'
},
{
endAmount: '100000000000000',
identifierOrCriteria: '0',
itemType: 0,
recipient: '0x93162ca0806ec2876b7ec12002596e40549c3e02',
startAmount: '100000000000000',
token: '0x0000000000000000000000000000000000000000'
}
],
counter: '948892694796415917080870615203989852295',
endTime: 1701915719,
offer: [
{
endAmount: '1',
identifierOrCriteria: '3518',
itemType: 2,
startAmount: '1',
token: '0x175edb154ed7a0e54410a7f547aaa7e3fbf21a34'
}
],
offerer: '0xa03bb8d8099c994ed87361f5c9857e13fc7c5ccf',
orderType: 2,
salt: '0x000000000000000000000000000000000000000000000000aea3b979de6e4aef',
startTime: 1701310920,
totalOriginalConsiderationItems: 2,
zone: '0x2de95b9afd737b0814e5e6013593a9437c5532d5',
zoneHash: '0x0000000000000000000000000000000000000000000000000000000000000000'
}
步骤 1:参考第 2 部分第 2 步收集订单信息
const jsonMessage = JSON.stringify({
domain: {
// Defining the chain aka testnet or Ethereum Main Net
chainId: 1, // 1 for mainnet
// Give a user friendly name to the specific contract you are signing for.
name: "Seaport",
// If name isn't enough add verifying contract to make sure you are establishing contracts with the proper entity
verifyingContract: "0x00000000000000adc04c56bf30ac9d3c0aaf14dc",
// Just let's you know the latest version. Definitely make sure the field name is correct.
version: "1.5",
},
// Defining the message signing data content.
message: contractMessage,
// Refers to the keys of the *types* object below.
primaryType: "OrderComponents",
types: {
ConsiderationItem: [
{ name: 'itemType', type: 'uint8' },
{ name: 'token', type: 'address' },
{ name: 'identifierOrCriteria', type: 'uint256' },
{ name: 'startAmount', type: 'uint256' },
{ name: 'endAmount', type: 'uint256' },
{ name: 'recipient', type: 'address' }
],
OrderComponents: [
{ name: 'offerer', type: 'address' },
{ name: 'zone', type: 'address' },
{ name: 'offer', type: 'OfferItem[]' },
{ name: 'consideration', type: 'ConsiderationItem[]' },
{ name: 'orderType', type: 'uint8' },
{ name: 'startTime', type: 'uint256' },
{ name: 'endTime', type: 'uint256' },
{ name: 'zoneHash', type: 'bytes32' },
{ name: 'salt', type: 'uint256' },
{ name: 'conduitKey', type: 'bytes32' },
{ name: 'counter', type: 'uint256' }
],
EIP712Domain: [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' }
],
OfferItem: [
{ name: 'itemType', type: 'uint8' },
{ name: 'token', type: 'address' },
{ name: 'identifierOrCriteria', type: 'uint256' },
{ name: 'startAmount', type: 'uint256' },
{ name: 'endAmount', type: 'uint256' }
]
},
});
步骤 2:使用您的私钥对订单数据进行签名。注意:您可以使用其他工具来帮助您使用 eth_signTypedData_v4
方法生成签名。
// here we will use okx wallet utils with your private key and the message to do a signature
const param = {
privateKey: privateKey,
data: {
type: 4,
message: jsonMessage
}
};
return wallet.signMessage(param).then(res => console.log(res)); // here you will get a hex signature
之后,您将获得一个基于订单数据和钱包地址的签名,我们将在下一步中使用该签名。
步骤 1:从 contractMessage
中获取 data
并将其放入请求中,以订单为键,contractMessage
为值。替换签名和钱包地址,形成你的 submit listing 请求。
const submitListingBody = JSON.stringify({
chain: "eth",
walletAddress: '0xa03bb8d...dds'; // this is your wallet address
items: [
{
platform: "okx",
signature: "0xf41ef.....9acc727631b", // signature returned #from Create a signature with the order data. Step 2
order: { // put the contractMessage data here
conduitKey: "0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000",
consideration: [
{
endAmount: "1",
identifierOrCriteria: "5313",
itemType: 2,
recipient: "0xa03bb8d8099c994ed87361f5c9857e13fc7c5ccf",
startAmount: "1",
token: "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d"
}
],
counter: "948892694796415917080870615203989852295",
endTime: 1703301107,
offer: [
{
endAmount: "1000000",
identifierOrCriteria: "0",
itemType: 1,
startAmount: "1000000",
token: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
}
],
offerer: "0xa03bb8d8099c994ed87361f5c9857e13fc7c5ccf",
orderType: 0,
salt: "0x0000000000000000000000000000000000000000000000002baea915c4bcf7be",
startTime: 1700709107,
totalOriginalConsiderationItems: 1,
zone: "0x0000000000000000000000000000000000000000",
zoneHash: "0x0000000000000000000000000000000000000000000000000000000000000000"
}
}
]
}
步骤 2: 为新请求构建一个新的标题参数
const submitListingRequestUrl = 'https://www.okx.com/api/v5/mktplace/nft/markets/submit-listing'; // new endpoint for submitting listing
const submitListingTimestamp = date.toISOString();
const submitListingHeadersParams = {
'Content-Type': 'application/json',
'OK-ACCESS-KEY': apiKey,
'OK-ACCESS-SIGN': cryptoJS.enc.Base64.stringify(
cryptoJS.HmacSHA256(submitListingTimestamp + 'POST' + '/api/v5/mktplace/nft/markets/submit-listing' + submitListingBody, secretKey)
),
'OK-ACCESS-TIMESTAMP': submitListingTimestamp,
'OK-ACCESS-PASSPHRASE': passphrase,
};
步骤 3: 发送 POST 请求到 /submit-listing 接口
return fetch(submitListingRequestUrl, {method: 'post', headers: submitListingHeadersParams, body: submitListingBody}).then((res) => res.json()).then((res) => {return res;});
最后,您应该看到成功等于 true 的消息。
{
"code": 0,
"data": {
"results": [
{
"message": "",
"order": {
"conduitKey": "0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000",
"consideration": [
{
"endAmount": "1",
"identifierOrCriteria": "5313",
"itemType": 2,
"recipient": "0xa03bb8d8099c994ed87361f5c9857e13fc7c5ccf",
"startAmount": "1",
"token": "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d"
}
],
"counter": "948892694796415917080870615203989852295",
"endTime": 1703301107,
"offer": [
{
"endAmount": "1000000",
"identifierOrCriteria": "0",
"itemType": 1,
"startAmount": "1000000",
"token": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
}
],
"offerer": "0xa03bb8d8099c994ed87361f5c9857e13fc7c5ccf",
"orderType": 0,
"salt": "0x0000000000000000000000000000000000000000000000002baea915c4bcf7be",
"startTime": 1700709107,
"totalOriginalConsiderationItems": 1,
"zone": "0x0000000000000000000000000000000000000000",
"zoneHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
"platform": "okx",
"signature": "0xf41ef8e......c4a9acc727631b",
"success": true
}
]
},
"msg": ""
}