Caviar
  • Introduction
  • User Guides
    • Buying and Selling NFTs
    • Creating a New Shared Pool
    • Providing and Removing Liquidity for Shared and Custom Pools
    • Providing and Removing Liquidity for Pure-NFT Pools
    • Changing your NFTs in Pure-NFT Pools
    • Wrapping and Unwrapping NFTs
    • Impermanent Loss
  • Concepts
    • Shared pools
      • Swaps
      • Liquidity
      • Fractionalization
    • Custom pools
      • Swaps
      • Liquidity
      • Change
  • Technical Reference
    • Contract addresses
    • Shared pools
      • High level overview
      • Smart contract API
        • Caviar.sol
        • Pair.sol
        • StolenNftFilterOracle.sol
        • CaviarEthRoyaltyRouter.sol
      • Desirability Classifier
      • How to make a buy programatically
      • How to make a sell programatically
    • Custom pools
      • High level overview
      • Smart contract API
        • EthRouter
        • Factory
        • PrivatePool
        • PrivatePoolMetadata
        • IStolenNftOracle
  • Resources
    • Partners
    • NFT Collection Partnerships
    • Audits
    • Research
    • Where does the yield come from?
Powered by GitBook
On this page
  1. Technical Reference
  2. Shared pools

How to make a buy programatically

A tutorial on how to make a script for buying NFTs on caviar

PreviousDesirability ClassifierNextHow to make a sell programatically

Last updated 2 years ago

For this tutorial we will use the library and to programatically buy a few BAYC NFTs on the goerli testnet. To get goerli ETH you can claim some from .

The first step is to create an empty directory and install the dependencies:

mkdir caviar-swap-example
cd caviar-swap-example
npm init -y
npm install ethers dotenv alchemy-sdk node-fetch@2

Now before we start writing code we also need the required ABI files (caviar.abi.json and pair.abi.json) to interact with the contracts. Those can be found on the . Copy and paste caviar.abi.json and pair.abi.json into the root of caviar-swap-example/.

Great, now we can start actually writing the script. Create a file buy.js and then open it and import the required dependencies along with making an empty entrypoint function called main().

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

const main = async () => {}

main();

Now we need to setup an ethers.js so that we can interact with the chain and send transactions. Inside of the main() function:

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);
};

And then create a .env file with the following content:

ALCHEMY_API_KEY=<your alchemy api key>
PRIVATE_KEY=<your private key>

Now let's fetch the pair contract address for floor BAYC:ETH pair and create a contract instance that we can interact with. We can do this by querying the Caviar factory contract:

const main = async () => {
  /// ... SNIP ... ///

  // 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);
};
const main = async () => {
  /// ... SNIP ... ///

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

  // calculate the amount of ETH to buy 2 BAYCs using xy=k formula
  // 2 BAYCs == 2 * 1e18 fractional tokens
  const AMOUNT_TO_BUY = ethers.BigNumber.from("2").mul(ethers.utils.parseUnits("1", 18));
  const ethCost = AMOUNT_TO_BUY
    .mul(baseTokenReserves)
    .mul("1000")
    .div(fractionalTokenReserves.sub(AMOUNT_TO_BUY).mul("997"))
    .add("1");

  console.log("ETHER cost to buy 2 BAYCs:", ethers.utils.formatEther(ethCost), "ETH");
};
const main = async () => {
  /// ... SNIP ... ///

  // create the alchemy instance
  const alchemy = new Alchemy({
    apiKey: process.env.ALCHEMY_API_KEY,
    network: Network.ETH_GOERLI,
  });

  // fetch some BAYC NFTs that are currently in the pair contract
  const { ownedNfts } = await alchemy.nft.getNftsForOwner(baycEthPairAddress, {
    contractAddresses: [GOERLI_BAYC_ADDRESS],
  });

  const tokenIdsToBuy = [ownedNfts[0].tokenId, ownedNfts[1].tokenId];
  console.log("Token Ids to buy:", tokenIdsToBuy);

  const deadline = parseInt((Date.now() + 1000 * 60 * 60) / 1000);
  console.log("Trade deadline unix timestamp:", deadline);
};

Although you can choose any two NFTs, we will just choose the first two that were returned from the response. Now for the final moment! let's actually submit a transaction to buy:

const main = async () => {
  /// ... SNIP ... //

  // submit the transaction to buy the NFTs
  const tx = await BaycEthPair.nftBuy(tokenIdsToBuy, ethCost, deadline, { value: ethCost });
  console.log("Transaction:", tx);
};

Cool, that's most of the setup out of the way. Now let's query the contract and figure out how much ETH we will have to spend to buy two BAYCs from the pool. To do this we need to query the reserves and implement some logic which is the same as in the pair contract:

So we know how much ETH we will need to spend. All we need to do now is pick some NFTs that we want to buy from the pair. In order to do this we need to find out what NFTs the pair actually holds. This can be done via the :

If all goes well you should have just bought two BAYCs. Here is a link to a transaction I submitted using this script on . Yours should look quite similar except with different token IDs. All of the code for this tutorial is available on . The next step is now to make a sell transaction. The sell tutorial is available .

ethers.js
alchemy
paradigm's faucet
caviar github repository here
signer
xy=k
buyQuote
alchemy NFT API
etherscan
github here
here