Skip to content

Developer Quickstart

Kick-start integrations with the Twin.fun bonding curve contract using ethers v6.

Setup

  • Install dependencies (ethers v6 recommended).
  • Configure RPC access for Base Sepolia and/or mainnet deployments.
  • Import the ABI for DigitalTwinSharesV1.

Read Price & Buy (ethers v6)

ts
import { ethers } from "ethers";
import abi from "./DigitalTwinSharesV1.abi.json";

const provider = new ethers.JsonRpcProvider(process.env.RPC_URL!);
const wallet   = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
const addr     = "0x065fb766051c9a212218c9D5e8a9B83fb555C17c"; // Base Sepolia
const c        = new ethers.Contract(addr, abi, wallet);

const id = "0x85f4f72079114bfcac1003134e5424f4"; // bytes16
await (async () => {
  const amount   = 1n;
  const price    = await c.getBuyPrice(id, amount);
  const feeP     = await c.protocolFeePercent();
  const feeS     = await c.subjectFeePercent();
  const protocol = (price * feeP) / (10n ** 18n);
  const subject  = (price * feeS) / (10n ** 18n);
  const value    = price + protocol + subject;
  const tx = await c.buyShares(id, amount, { value });
  await tx.wait();
})();

Sell & Estimate Proceeds

ts
const amount = 1n;
const after  = await c.getSellPriceAfterFee(id, amount);
const tx     = await c.sellShares(id, amount);
await tx.wait();

Common Errors & Fixes

  • Insufficient value: compute getBuyPriceAfterFee and send the exact msg.value.
  • Creation guard: at zero supply, amount must be ≥ minSharesToCreate.
  • Owner required: the twin is pre-claimed; the mapped owner must perform the first buy.

OpenGradient 2025