How to make a sell programatically

A tutorial on how to make a script for selling NFTs on caviar.

This tutorial assumes you already went through the buying tutorial here. If you haven't read through that tutorial yet I would highly recommend reading it first.

In the previous tutorial we already installed the required dependencies and purchased some BAYCs. Now, let's figure out how to sell those NFTs back into the same pool.

First, create a file called sell.js and then import the dependencies and setup the required interfaces:

const ethers = require("ethers");
const caviarAbi = require("./caviar.abi.json");
const pairAbi = require("./pair.abi.json");
const { Alchemy, Network } = require("alchemy-sdk");
const fetch = require("node-fetch");
require("dotenv").config();

const main = async () => {
  // create the provider to connect to the network
  const provider = new ethers.providers.AlchemyProvider(
    "goerli",
    process.env.ALCHEMY_API_KEY
  );

  // create the signer to sign transactions from a wallet
  const signer = new ethers.Wallet(process.env.PRIVATE_KEY, provider);

  // create the contract instance for caviar
  const GOERLI_CAVIAR_ADDRESS = "0x15B9D8ba57E67D6683f3E7Bec24A32b98a7cdb6b";
  const GOERLI_BAYC_ADDRESS = "0xc1a308d95344716054d4c078831376fc78c4fd72";
  const Caviar = new ethers.Contract(
    GOERLI_CAVIAR_ADDRESS,
    caviarAbi,
    provider
  );

  // fetch the address of the floor pair for BAYC:ETH
  const baycEthPairAddress = await Caviar.pairs(
    GOERLI_BAYC_ADDRESS, // address of the NFT token
    ethers.constants.AddressZero, // address of the base token (address(0) for ETH)
    ethers.constants.HashZero // hash of the merkle root for valid token ids (hash(0) for no merkle root)
  );

  // create the contract instance for the floor BAYC:ETH pair
  const BaycEthPair = new ethers.Contract(baycEthPairAddress, pairAbi, signer);
  console.log("BAYC:ETH pair address:", baycEthPairAddress);

  // fetch the reserves for the BAYC:ETH pair
  const baseTokenReserves = await BaycEthPair.baseTokenReserves();
  const fractionalTokenReserves = await BaycEthPair.fractionalTokenReserves();
};

main();

Now using the xy=k formula and re-implementing the sellQuote logic in the pair contract, we can figure out how much ETH we expect to receive from selling the two BAYCs into the pool. We will use this value as the minimum expected output when submitting the transaction to the pair contract.

Great, now we can fetch the token IDs of the BAYCs that we hold and use them as input to the sell transaction.

To execute the sell, the pair contract must be first approved for spending the BAYCs from your wallet. So on your first sell two transactions must be submitted - one to approve, and one to execute the sell. After you have approved the contract once, it does not need to be done again and you can execute sells directly. We will need the ERC721 ABI to make the approval. Create a file erc721.abi.json and copy and paste the abi from here. And then import it at the top of the file:

Now lets make the approval and swap:

Nice, you just sold two BAYCs. You should see a transaction very similar to this one here. The code for this tutorial is all available on github here. Thanks for reading and feel free to reach out on discord if you have any questions!

Last updated