How to put an item on sale in the Market?

This page describes the flow in putting an item up for sale on the market.

Flow

Context

To be able to sell items on the market, Venly takes the item for sale into custody. This means that Venly moves the NFT from the seller's address to a Venly-owned and managed wallet. At the end of a sale, Venly will correctly move the NFT to the buyers wallet, or return the NFT to the senders wallet when no sale is made.

To be able to move the NFT (from seller's wallet, to in custody, to the buyer's wallet), Venly needs an approval on the (blockchain) contract. So, before an item can be put on the market, an approval and signature flow needs to be done by the seller.

Detailed Steps

1. Create and configure your offer

In the first step you create the Offer that you want to put on sale. Use the Create offer endpoint.

In the offer you have to configure the:

  • The NFT that you want to put on sale

  • The type of the offer: SALE or AUCTION

  • The (starting-)price of the offer

  • (optional) the amount of items for sale in case of fungible items

  • (optional) a specific end date

  • (optional) making the offer private (unlisted on the market)

Once created, you will receive an Offer with state NEW (see Offer states for reference).

Example

Request: Create Offer
POST https://api.venly.market/offers

{
    "type": "SALE",
    "nft":
    {
        "tokenId": "13",
        "address": "0x225f099870ea881f2165a475c2696ecb2d21d0c3",
        "chain": "BSC"
    },
    "sellerAddress": "0x5CF94a2ff1e4B283eb051BB059182F6c32F7D184",
    "privateOffer": false,
    "price": 10,
    "endDate": "2022-09-02T11:40:22.147Z"
}

Response: Create Offer
{
    "success": true,
    "result":
    {
        "id": "1fd99c92-abe4-4ac9-8eac-03233e998768",
        "nft":
        {
            "id": "13",
            "address": "0x225f099870ea881f2165a475c2696ecb2d21d0c3",
            "chain": "BSC",
            "name": "Swordquest House",
            "description": "A fantastic house branded after your favorite Atari game!!",
            "imageUrl": "https://storage-qa.venly.io/applications/05a51091-54b8-43aa-9c12-142e2b3d9c04/ATA+4+Swordquest+House.jpg",
            "url": "https://alphaverse.com/atari/",
            "imagePreviewUrl": "https://storage-qa.venly.io/applications/05a51091-54b8-43aa-9c12-142e2b3d9c04/ATA+4+Swordquest+House.jpg",
            "imageThumbnailUrl": "https://storage-qa.venly.io/applications/05a51091-54b8-43aa-9c12-142e2b3d9c04/ATA+4+Swordquest+House.jpg",
            "animationUrls":
            [],
            "fungible": false,
            "attributes":
            [
                {
                    "type": "system",
                    "name": "tokenTypeId",
                    "value": "13"
                },
                {
                    "type": "property",
                    "name": "maxSupply",
                    "value": "200"
                }
            ],
            "contract":
            {
                "chain": "BSC",
                "address": "0x225f099870ea881f2165a475c2696ecb2d21d0c3",
                "count": 0,
                "name": "AlphaVerse / Atari AlphaVerse",
                "description": "Atari AlphaVerse is a metaverse, part of the AlphaVerse, offering whole experience around the Atari brand.",
                "symbol": "ATAR",
                "url": "https://alphaverse.com/atari/",
                "imageUrl": "https://storage-qa.venly.io/applications/05a51091-54b8-43aa-9c12-142e2b3d9c04/Logo+Atari-AlphaVerse.png",
                "media":
                [
                    {
                        "type": "image",
                        "value": "https://storage-qa.venly.io/applications/05a51091-54b8-43aa-9c12-142e2b3d9c04/Logo+Atari-AlphaVerse.png"
                    }
                ],
                "verified": false,
                "premium": false,
                "categories":
                []
            },
            "collectionIdentifier": "3876696d-b953-483c-89ff-ca41f0b2abe9"
        },
        "sellerId": "4917b6fa-2657-4bdd-b8e8-fa5dd8bd4057",
        "sellerNickname": "Unknown",
        "sellerAddress": "0x5cf94a2ff1e4b283eb051bb059182f6c32f7d184",
        "startDate": "2022-06-02T11:43:16.207344Z",
        "endDate": "2022-09-02T11:40:22.147000Z",
        "type": "SALE",
        "status": "NEW",
        "dataToSign": "1fd99c92-abe4-4ac9-8eac-03233e998768_0x5cf94a2ff1e4b283eb051bb059182f6c32f7d184_0xfCAFfcc7d5e04e6CD016357846570095c3595CE3_13",
        "createdOn": "2022-06-02T11:43:16.208429Z",
        "createdBy": "4917b6fa-2657-4bdd-b8e8-fa5dd8bd4057",
        "modifiedOn": "2022-06-02T11:43:16.208429Z",
        "modifiedBy": "4917b6fa-2657-4bdd-b8e8-fa5dd8bd4057",
        "signed": false,
        "currency": "USDC",
        "privateOffer": false,
        "seller":
        {
            "id": "4917b6fa-2657-4bdd-b8e8-fa5dd8bd4057",
            "nickname": "Unknown"
        },
        "amountPurchased": 0,
        "amountReimbursed": 0,
        "amountTerminated": 0,
        "price": 10,
        "amount": 1,
        "remainingAmount": 1,
        "minBuyAmount": 1
    }
}

2. Retrieve preparation information

The next step in putting your item on sale is for Venly to take the item in custody. To do this, Venly needs approval on the contract of the NFT. This means that a contract call needs to be done.

There are currently however a lot of different ways to get approval on a collection or NFT. This depends on the NFT-ERC standard, the chain, etc.

The help determine which contract call needs to be done. You can call the Get prepared Approve Tx endpoint. This will give all the information needed to execute the necessary contract call.

Moreover, it will also determine if an actual contract call needs to be executed. Some NFT-contracts allow for meta transactions. A meta-transaction allows Venly to perform the contract call itself. This has as advantage that Venly performs the approval-contract call and pays for the necessary GAS-fees. Read more about meta-transactions.

If no meta transaction can be done, it is the user itself that has to execute the approval-contract call. This means that the user needs to pay for the GAS-fees and therefore also needs to have enough ETH, HBAR, BSC, ... to execute the approval-call.

In summary, the Get prepared Approve TX will return one of the following:

  • signableMessages A meta-transaction can be done and Venly will pay the GAS-fee for the approval-transaction. The user only needs to sign a data-object.

  • approvalPreparationTransactions The contract of the NFT does not allow meta-transactions. The user therefore has to execute the approval-contract call themselves and pay for the necessary GAS-fees.

  • empty An approval on the collection was already given in the past. It does not need to be done again. You can immediately go to step 5

Example

Request: Prepare Information
GET https://api.venly.market/offers/03262eaa-8817-4785-817f-523359a526c9/preparation/transactions?walletId=:walletId
Response: Prepare information
{
    "success": true,
    "result": {
        "signableMessages": [
            {
                "walletId": "355351bd-41ae-41fa-8f36-12675f056759",
                "secretType": "MATIC",
                "data": {
                    "types": {
                        "MetaTransaction": [
                            {
                                "type": "uint256",
                                "name": "nonce"
                            },
                            {
                                "type": "address",
                                "name": "from"
                            },
                            {
                                "type": "bytes",
                                "name": "functionSignature"
                            }
                        ],
                        "EIP712Domain": [
                            {
                                "type": "string",
                                "name": "name"
                            },
                            {
                                "type": "string",
                                "name": "version"
                            },
                            {
                                "type": "address",
                                "name": "verifyingContract"
                            },
                            {
                                "type": "bytes32",
                                "name": "salt"
                            }
                        ]
                    },
                    "domain": {
                        "name": "Birds 2",
                        "version": "1",
                        "verifyingContract": "0x004ecbb14bc21e988e859dd96e6759ebae085498",
                        "salt": "0x0000000000000000000000000000000000000000000000000000000000013881"
                    },
                    "primaryType": "MetaTransaction",
                    "message": {
                        "nonce": 0,
                        "from": "0xb538acdcf1ded376f44edfeb5cf6a299314ea36a",
                        "functionSignature": "0xa22cb465000000000000000000000000e885A1cD1b67bDC352A113AB2e6A5Fc6C924F8880000000000000000000000000000000000000000000000000000000000000001"
                    }
                }
            }
        ]
    }
}

Since the response contains a signableMessages , in this case a meta transaction is supported.

3. Approve transaction

Approve transaction only needs to be done when the preparation information returnsapprovalPreparationTransactions as result.

3a. Execute approval transaction on the contract

The user needs to execute the contract call. To do this one of the following methods can be used:

  • Use the Execute a contract call API:

    • You have to ask the user for its Venly-wallet PIN number, whereafter Venly can execute the call on the user's wallet.

  • Use the Widget to execute the contract call.

3b. Approve the transaction on the market

To move forward, the market also needs to know the parameters of the contract call.

Execute the tx Approval call with the transactionHash you got as response of the execute contract call.

4. Approve meta transaction

Approve transaction only needs to be done when the preparation information returns signableMessages as result.

4a. Sign transaction message

In the case of a meta-transaction, no contract call needs to be executed by the user, only a message needs to be signed.

One of the following methods can be used to sign the message:

The message that needs to be signed can be found in the response of the preparation call.

For example: in the respons of the preparation call you will find:

"signableMessages": [ { ...} ]

The entire message block needs to be passed in to the Signatures API (the content of signableMessages). You now use this information to sign a EIP712 message:

{
    "pincode": 121212,
    "signatureRequest":
    {
        "type": "EIP712",

     ... HERE COMES THE CONTENT OF "SIGNABLEMESSAGES" ...
    
    }
}

4b. Approve the meta transaction on the market

To move forward, the market also needs to know the parameters of the contract call.

Execute the (meta) tx Approval call with the r , s, v and signature you got as response of the signature-call (Step 4a). Note that for a meta-transaction the signature parameter that you get as response of the signing step, needs to be transmitted as the functionSignature parameter in the tx-approval step

Example

Request: Sign meta transaction
POST https://api-wallet.venly.io/api/signatures
(NOTE: this request is being send to WALLET)

{
    "pincode": 1234,
    "signatureRequest":
    {
        "type": "EIP712",
        "walletId": "355351bd-41ae-41fa-8f36-12675f056759",
        "secretType": "MATIC",
        "data":
        {
            "types":
            {
                "MetaTransaction":
                [
                    {
                        "type": "uint256",
                        "name": "nonce"
                    },
                    {
                        "type": "address",
                        "name": "from"
                    },
                    {
                        "type": "bytes",
                        "name": "functionSignature"
                    }
                ],
                "EIP712Domain":
                [
                    {
                        "type": "string",
                        "name": "name"
                    },
                    {
                        "type": "string",
                        "name": "version"
                    },
                    {
                        "type": "address",
                        "name": "verifyingContract"
                    },
                    {
                        "type": "bytes32",
                        "name": "salt"
                    }
                ]
            },
            "domain":
            {
                "name": "Birds 2",
                "version": "1",
                "verifyingContract": "0x004ecbb14bc21e988e859dd96e6759ebae085498",
                "salt": "0x0000000000000000000000000000000000000000000000000000000000013881"
            },
            "primaryType": "MetaTransaction",
            "message":
            {
                "nonce": 0,
                "from": "0xb538acdcf1ded376f44edfeb5cf6a299314ea36a",
                "functionSignature": "0xa22cb465000000000000000000000000e885A1cD1b67bDC352A113AB2e6A5Fc6C924F8880000000000000000000000000000000000000000000000000000000000000001"
            }
        }
    }
}
Response: Sign meta transaction
{
    "success": true,
    "result": {
        "type": "HEX_SIGNATURE",
        "r": "0x753edd7051ecefb548dd7f9efeb4ba5278821df6306889539a05a0e379c78c85",
        "s": "0x34d4e1ded2f5985261b375bafba631188f180e0e1a61c4357064b99948da32b5",
        "v": "0x1b",
        "signature": "0x753edd7051ecefb548dd7f9efeb4ba5278821df6306889539a05a0e379c78c8534d4e1ded2f5985261b375bafba631188f180e0e1a61c4357064b99948da32b51b"
    }
}
Request: Send approval
PUT https://api.venly.market/offers/1fd99c92-abe4-4ac9-8eac-03233e998768/metaTxApprove

{
        "r": "0x753edd7051ecefb548dd7f9efeb4ba5278821df6306889539a05a0e379c78c85",
        "s": "0x34d4e1ded2f5985261b375bafba631188f180e0e1a61c4357064b99948da32b5",
        "v": "0x1b",
        "functionSignature": "0xa22cb465000000000000000000000000e885A1cD1b67bDC352A113AB2e6A5Fc6C924F8880000000000000000000000000000000000000000000000000000000000000001"
}

Warning: functionSignature should be extracted from the message that was signed, not the signature of the message itself. See Retrieve Preparation Information -> Response: Prepare information -> result.signableMessages.[].data.message.functionsignature).

Response: Send approval
{
    "success": true,
    "result": {
        "id": "1fd99c92-abe4-4ac9-8eac-03233e998768",
        "nft": {
            "id": "13",
            "address": "0x225f099870ea881f2165a475c2696ecb2d21d0c3",
            "chain": "BSC",
            "name": "Swordquest House",
            "description": "A fantastic house branded after your favorite Atari game!!",
            "imageUrl": "https://storage-qa.venly.io/applications/05a51091-54b8-43aa-9c12-142e2b3d9c04/ATA+4+Swordquest+House.jpg",
            "url": "https://alphaverse.com/atari/",
            "imagePreviewUrl": "https://storage-qa.venly.io/applications/05a51091-54b8-43aa-9c12-142e2b3d9c04/ATA+4+Swordquest+House.jpg",
            "imageThumbnailUrl": "https://storage-qa.venly.io/applications/05a51091-54b8-43aa-9c12-142e2b3d9c04/ATA+4+Swordquest+House.jpg",
            "animationUrls": [],
            "fungible": false,
            "attributes": [
                {
                    "type": "system",
                    "name": "tokenTypeId",
                    "value": "13"
                },
                {
                    "type": "property",
                    "name": "maxSupply",
                    "value": "200"
                }
            ],
            "contract": {
                "chain": "BSC",
                "address": "0x225f099870ea881f2165a475c2696ecb2d21d0c3",
                "count": 0,
                "name": "AlphaVerse / Atari AlphaVerse",
                "description": "Atari AlphaVerse is a metaverse, part of the AlphaVerse, offering whole experience around the Atari brand.",
                "symbol": "ATAR",
                "url": "https://alphaverse.com/atari/",
                "imageUrl": "https://storage-qa.venly.io/applications/05a51091-54b8-43aa-9c12-142e2b3d9c04/Logo+Atari-AlphaVerse.png",
                "media": [
                    {
                        "type": "image",
                        "value": "https://storage-qa.venly.io/applications/05a51091-54b8-43aa-9c12-142e2b3d9c04/Logo+Atari-AlphaVerse.png"
                    }
                ],
                "verified": false,
                "premium": false,
                "categories": []
            },
            "collectionIdentifier": "3876696d-b953-483c-89ff-ca41f0b2abe9"
        },
        "sellerId": "4917b6fa-2657-4bdd-b8e8-fa5dd8bd4057",
        "sellerNickname": "Unknown",
        "sellerAddress": "0x5cf94a2ff1e4b283eb051bb059182f6c32f7d184",
        "startDate": "2022-06-02T11:43:16.207344Z",
        "endDate": "2022-09-02T11:40:22.147000Z",
        "type": "SALE",
        "status": "NEW",
        "dataToSign": "1fd99c92-abe4-4ac9-8eac-03233e998768_0x5cf94a2ff1e4b283eb051bb059182f6c32f7d184_0xfCAFfcc7d5e04e6CD016357846570095c3595CE3_13",
        "txApprove": "0xcf02dfb5699b011b8f3e40cf09cd71fc91e496057c4d2944ef640a894102076a",
        "createdOn": "2022-06-02T11:43:16.208429Z",
        "createdBy": "4917b6fa-2657-4bdd-b8e8-fa5dd8bd4057",
        "modifiedOn": "2022-06-02T11:43:16.368041Z",
        "modifiedBy": "4917b6fa-2657-4bdd-b8e8-fa5dd8bd4057",
        "signed": false,
        "currency": "USDC",
        "privateOffer": false,
        "seller": {
            "id": "4917b6fa-2657-4bdd-b8e8-fa5dd8bd4057",
            "nickname": "Unknown"
        },
        "amountPurchased": 0,
        "amountReimbursed": 0,
        "amountTerminated": 0,
        "price": 10,
        "amount": 1,
        "remainingAmount": 1,
        "minBuyAmount": 1
    }
}

5. Take NFT into custody

By now, Venly has all information to take the NFT into custody. However, to be sure that the user is really requesting a specific NFT to be put on sale, an extra signature is needed.

5a. Sign the offer data

Perform the signature call to sign the Offer.dataToSign data. Or use the Widget to perform this action.

5b. Send the signature to the offer

Perform the Update offer: signature call to update the Offer and let Venly take the NFT into custody.

The status of the Offer will change to INITIATING_OFFER. When the NFT is taken into custody, the Offer will have status READY and is available on the marketplace!

Example

Request: Sign
POST https://api-wallet.venly.io/api/signatures

{
    "pincode" : "1234",
    "signatureRequest" : 
    {
        "type": "MESSAGE",
        "walletId": "355351bd-41ae-41fa-8f36-12675f056759",
        "secretType": "MATIC",
        "data" : "1fd99c92-abe4-4ac9-8eac-03233e998768_0x5cf94a2ff1e4b283eb051bb059182f6c32f7d184_0xfCAFfcc7d5e04e6CD016357846570095c3595CE3_13"
    }
}

Response: Sign
{
    "success": true,
    "result": {
        "type": "HEX_SIGNATURE",
        "r": "0x892b531cf8a2e71bb81fb3cc2c572ff6ecd4987c03c522147f69f7443f962239",
        "s": "0x3cb350a2a0884f20675d9882a0c9dd03ff6eb8a0c7b6273b30790378e722c8e6",
        "v": "0x1b",
        "signature": "0x892b531cf8a2e71bb81fb3cc2c572ff6ecd4987c03c522147f69f7443f9622393cb350a2a0884f20675d9882a0c9dd03ff6eb8a0c7b6273b30790378e722c8e61b"
    }
}
Request: place signature (take NFT in custody / on sale)
PATCH https://api.venly.market/offers/1fd99c92-abe4-4ac9-8eac-03233e99876/signature

{
    "signature": "0x155e3b3c7cb444dcaa353c0d0d28765bd2747fb7deeb9d2c0edad3913c4b5c36571baf054f31e2eeb441acf6d8e605b97c6f34916d4f5874a8b01533beaaf8641c"
}
Response: place signature (take NFT in custody / on sale)
{
    "success": true,
    "result": {
        "id": "d8425b4d-319a-4313-80dc-053894820057",
        "nft": {
            "id": "13",
            "address": "0x225f099870ea881f2165a475c2696ecb2d21d0c3",
            "chain": "BSC",
            "name": "Swordquest House",
            "description": "A fantastic house branded after your favorite Atari game!!",
            "imageUrl": "https://storage-qa.venly.io/applications/05a51091-54b8-43aa-9c12-142e2b3d9c04/ATA+4+Swordquest+House.jpg",
            "url": "https://alphaverse.com/atari/",
            "imagePreviewUrl": "https://storage-qa.venly.io/applications/05a51091-54b8-43aa-9c12-142e2b3d9c04/ATA+4+Swordquest+House.jpg",
            "imageThumbnailUrl": "https://storage-qa.venly.io/applications/05a51091-54b8-43aa-9c12-142e2b3d9c04/ATA+4+Swordquest+House.jpg",
            "animationUrls": [],
            "fungible": false,
            "attributes": [
                {
                    "type": "system",
                    "name": "tokenTypeId",
                    "value": "13"
                },
                {
                    "type": "property",
                    "name": "maxSupply",
                    "value": "200"
                }
            ],
            "contract": {
                "chain": "BSC",
                "address": "0x225f099870ea881f2165a475c2696ecb2d21d0c3",
                "count": 0,
                "name": "AlphaVerse / Atari AlphaVerse",
                "description": "Atari AlphaVerse is a metaverse, part of the AlphaVerse, offering whole experience around the Atari brand.",
                "symbol": "ATAR",
                "url": "https://alphaverse.com/atari/",
                "imageUrl": "https://storage-qa.venly.io/applications/05a51091-54b8-43aa-9c12-142e2b3d9c04/Logo+Atari-AlphaVerse.png",
                "media": [
                    {
                        "type": "image",
                        "value": "https://storage-qa.venly.io/applications/05a51091-54b8-43aa-9c12-142e2b3d9c04/Logo+Atari-AlphaVerse.png"
                    }
                ],
                "verified": false,
                "premium": false,
                "categories": []
            },
            "collectionIdentifier": "3876696d-b953-483c-89ff-ca41f0b2abe9"
        },
        "sellerId": "e38336b6-3307-4737-bf82-3a3a39269147",
        "sellerNickname": "Pieter",
        "sellerAddress": "0x5cf94a2ff1e4b283eb051bb059182f6c32f7d184",
        "startDate": "2022-06-03T15:18:13.992128Z",
        "endDate": "2022-09-02T11:40:22.147000Z",
        "type": "SALE",
        "status": "INITIATING_OFFER",
        "dataToSign": "d8425b4d-319a-4313-80dc-053894820057_0x5cf94a2ff1e4b283eb051bb059182f6c32f7d184_0xfCAFfcc7d5e04e6CD016357846570095c3595CE3_13",
        "createdOn": "2022-06-03T15:18:13.992869Z",
        "createdBy": "e38336b6-3307-4737-bf82-3a3a39269147",
        "modifiedOn": "2022-06-03T15:19:40.208912Z",
        "modifiedBy": "e38336b6-3307-4737-bf82-3a3a39269147",
        "signed": true,
        "currency": "USDC",
        "privateOffer": false,
        "seller": {
            "id": "e38336b6-3307-4737-bf82-3a3a39269147",
            "nickname": "Pieter"
        },
        "amountPurchased": 0,
        "amountReimbursed": 0,
        "amountTerminated": 0,
        "price": 10,
        "amount": 1,
        "remainingAmount": 1,
        "minBuyAmount": 1
    }
}

Last updated