Executing Trades

rereqs

const OPTION_BOOK = '0xd58b814C7Ce700f251722b5555e25aE0fa8169A1';
const USDC        = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
const YOUR_REFERRER = '0x...'; // unique address for your platform

Why the referrer matters

  • Tags positions created via your platform.

  • Enables client-side filtering for portfolio views.

  • Tracks referral fees in OrderFilled.

Always pass your YOUR_REFERRER as the 3rd arg to fillOrder().

Minimal ABIs (v2)

const OPTION_BOOK_ABI = [
  {
    "inputs":[
      {"components":[
        {"internalType":"address","name":"maker","type":"address"},
        {"internalType":"uint256","name":"orderExpiryTimestamp","type":"uint256"},
        {"internalType":"address","name":"collateral","type":"address"},
        {"internalType":"bool","name":"isCall","type":"bool"},
        {"internalType":"address","name":"priceFeed","type":"address"},
        {"internalType":"address","name":"implementation","type":"address"},
        {"internalType":"bool","name":"isLong","type":"bool"},
        {"internalType":"uint256","name":"maxCollateralUsable","type":"uint256"},
        {"internalType":"uint256[]","name":"strikes","type":"uint256[]"},
        {"internalType":"uint256","name":"expiry","type":"uint256"},
        {"internalType":"uint256","name":"price","type":"uint256"},
        {"internalType":"uint256","name":"numContracts","type":"uint256"},
        {"internalType":"bytes","name":"extraOptionData","type":"bytes"}
      ],"internalType":"struct OptionBook.Order","name":"order","type":"tuple"},
      {"internalType":"bytes","name":"signature","type":"bytes"},
      {"internalType":"address","name":"referrer","type":"address"}
    ],
    "name":"fillOrder","outputs":[{"internalType":"address","name":"optionAddress","type":"address"}],
    "stateMutability":"nonpayable","type":"function"
  },
  {"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"referrer","type":"address"}],"name":"fees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},
  {"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"claimFees","outputs":[],"stateMutability":"nonpayable","type":"function"}
];

const ERC20_ABI = [
  {"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},
  {"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},
  {"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}
];

Trade Flow (ethers v5-style)

async function buyOption(orderData, usdcAmount) {
  const signer = web3Provider.getSigner();
  const user = await signer.getAddress();
  const usdc = new ethers.Contract(USDC, ERC20_ABI, signer);
  const book = new ethers.Contract(OPTION_BOOK, OPTION_BOOK_ABI, signer);

  const required = ethers.utils.parseUnits(String(usdcAmount), 6);
  const bal = await usdc.balanceOf(user);
  if (bal.lt(required)) throw new Error(`Need ${usdcAmount} USDC`);

  const allowance = await usdc.allowance(user, OPTION_BOOK);
  if (allowance.lt(required)) {
    const tx = await usdc.approve(OPTION_BOOK, required);
    await tx.wait();
  }

  const pricePer = Number(orderData.order.price) / 1e8; // USDC/contract
  const contractsToBuy = usdcAmount / pricePer;
  const numContracts = ethers.BigNumber.from(
    Math.floor(contractsToBuy * 1e6).toString() // USDC-scale
  );

  // DO NOT mutate order fields
  const orderParams = {
    maker: orderData.order.maker,
    orderExpiryTimestamp: orderData.order.orderExpiryTimestamp,
    collateral: orderData.order.collateral,
    isCall: orderData.order.isCall,
    priceFeed: orderData.order.priceFeed,
    implementation: orderData.order.implementation,
    isLong: orderData.order.isLong,
    maxCollateralUsable: orderData.order.maxCollateralUsable,
    strikes: orderData.order.strikes,
    expiry: orderData.order.expiry,
    price: orderData.order.price,
    extraOptionData: orderData.order.extraOptionData || "0x",
    numContracts: numContracts.toString()
  };

  const tx = await book.fillOrder(orderParams, orderData.signature, YOUR_REFERRER);
  const receipt = await tx.wait();
  if (receipt.status !== 1) throw new Error('Transaction failed');

  return { txHash: tx.hash, receipt };
}

Notes

  • Never modify order fields (signature will break).

  • USDC is 6 decimals: parseUnits(x, 6).

  • Round down contracts (Math.floor(… * 1e6)).

Last updated