In this guide, we will show you how to create a listing on OKX or OpenSea. This endpoint only supports one platform in a single request. This process includes:
For the necessary environment, refer to Import necessary Node.js libraries
Step 1: Build header Params. For all other reusable variables, refer to Set up your environment variables
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:1701760147, // 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,
};
Step 2: Use the headersParam and originalMessage as the body and request the create-listing endpoint
return fetch(requestUrl, {method: 'post',headers: headersParams,body: originalMessage}).then((res) => res.json()).then((res) => {return JSON.stringify(res);});
When you do this request, you will get a large payload of data. The main purpose of this is to get the order data below, which can then be used for submitting listings on OKX or OpenSea. Step 3: Pull the order data from the response in Step 1 and assign it to a variable
const contractMessage = {
conduitKey: '0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000',
consideration: [
{
endAmount: '87500000000000',
identifierOrCriteria: '0',
itemType: 0,
recipient: '0xa03bb8d8099c994ed87361f5c9857e13fc7c5ccf',
startAmount: '87500000000000',
token: '0x0000000000000000000000000000000000000000'
},
{
endAmount: '10000000000000',
identifierOrCriteria: '0',
itemType: 0,
recipient: '0x93162ca0806ec2876b7ec12002596e40549c3e02',
startAmount: '10000000000000',
token: '0x0000000000000000000000000000000000000000'
},
{
endAmount: '2500000000000',
identifierOrCriteria: '0',
itemType: 0,
recipient: '0x0000a26b00c1f0df003000390027140000faa719',
startAmount: '2500000000000',
token: '0x0000000000000000000000000000000000000000'
}
],
counter: '948892694796415917080870615203989852295',
endTime: 1701760147,
offer: [
{
endAmount: '1',
identifierOrCriteria: '3518',
itemType: 2,
startAmount: '1',
token: '0x175edb154ed7a0e54410a7f547aaa7e3fbf21a34'
}
],
offerer: '0xa03bb8d8099c994ed87361f5c9857e13fc7c5ccf',
orderType: 0,
salt: '0x0000000000000000000000000000000000000000000000003d0609f530d9214f',
startTime: 1701185619,
totalOriginalConsiderationItems: 3,
zone: '0x0000000000000000000000000000000000000000',
zoneHash: '0x0000000000000000000000000000000000000000000000000000000000000000'
}
Step 1: Gather listing information such as type data, domain data from Part 2 Step 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' }
]
},
});
Step 2: Sign the listing request using your private key. Note: You can use other tools to help you generate signatures using eth_signTypedData_v4
method.
// 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
After that, you will get a signature that is based on the listing and the wallet address which you will use in the next step.
Step 1: Grab the data
from contractMessage
and put it in the payload with order as the key and contractMessage
as the value. Replace the signature and the wallet address and form your submitted listing request.
const submitListingBody = JSON.stringify({
chain: "eth",
walletAddress: '0xa03bb8d...dds'; // this is your wallet address
items: [
{
platform: "opensea",
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"
}
}
]
}
Step 2: Build a new header for the new request
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,
};
Step 3: Do the post request to /submit-listing endpoint
return fetch(requestUrl, {method: 'post', headers: submitListingHeadersParams, body: submitListingBody}).then((res) => res.json()).then((res) => {return res;});
Then, at the end, you should see this message with success equals 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": ""
}