# How to make a buy programatically

For this tutorial we will use the [ethers.js](https://github.com/ethers-io/ethers.js/) library and [alchemy](https://www.alchemy.com/) to programatically buy a few BAYC NFTs on the goerli testnet. To get goerli ETH you can claim some from [paradigm's faucet](https://faucet.paradigm.xyz/).

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 [caviar github repository here](https://github.com/outdoteth/caviar/tree/main/abis). 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()`.

```javascript
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 [signer](https://docs.ethers.org/v5/api/signer/) so that we can interact with the chain and send transactions. Inside of the `main()` function:

```javascript
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:

```properties
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:

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

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 [xy=k](https://medium.com/phoenix-finance/understanding-the-xyk-model-of-pooled-liquidity-7340fdc20d9c) logic which is the same as [buyQuote](https://github.com/outdoteth/caviar/blob/main/src/Pair.sol#L410) in the pair contract:

```javascript
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");
};
```

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 [alchemy NFT API](https://www.alchemy.com/nft-api):

```javascript
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:

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

If all goes well you should have just bought two BAYCs. Here is a link to a transaction I submitted using this script on [etherscan](https://goerli.etherscan.io/tx/0xf5f8dd498eadbe6bba39e31c92a02cd8cd79235c33f576199a6c35bd87d8fa8a). Yours should look quite similar except with different token IDs. All of the code for this tutorial is available on [github here](https://github.com/outdoteth/caviar-swap-example). The next step is now to make a sell transaction. The sell tutorial is available [here](https://docs.caviar.sh/technical-reference/shared-pools/how-to-make-a-sell-programatically).
