Skip to main content

Deployment

A full deployment is live on Stacks testnet plus a static frontend on Vercel.

Live coordinates

Networktestnet
Deployer / keeper-ownerST1QN0P1MB429DHV28KT68F80621FHE4NE880CBZK
Web appbachelier-frontend.vercel.app
Contracts8 published — see Contracts
Round 1+10% OTM, IV 0.55, ~1 week tenor

The deployer wallet doubles as keeper and owner. Its mnemonic lives only in contracts/settings/.testnet-deployer.json (gitignored, testnet-only). The public record — addresses, txids, round 1 — is committed to contracts/deployments/testnet-deployment.json.

Part A — contracts

One idempotent script generates a wallet, funds it from the Hiro faucet, publishes all 8 contracts in dependency order, wires them, and verifies the on-chain Black–Scholes reference vector equals 42848661381:

cd contracts
pnpm tsx scripts/deploy-testnet.ts

It is safe to re-run: it skips already-deployed contracts and already-applied wiring. The wiring it applies:

  • bcshare-token.set-vault — authorize the vault to mint/burn shares
  • oracle-adapter.set-max-age(u691200) — relax staleness to 8 days (demo)
  • pyth-mock.set-price-now(<live BTC>) — seed a price
  • vault.start-round(u1000, u55000000) — open round 1 (+10% OTM, IV 0.55)

:::note IPv4 gotcha On some networks Node/undici picks an unreachable IPv6 route and fetch hangs with UND_ERR_CONNECT_TIMEOUT. Run the script with NODE_OPTIONS="--dns-result-order=ipv4first". It's idempotent, so just re-run. :::

Baking the deployer into the build

Vite strips process.env from the browser bundle, so the live contract address can't flow in through the shared env() helper at build time. The fix is configWithDeployer() in packages/shared plus a Vite-native override: set VITE_BACHELIER_DEPLOYER=<deployer> and the production bundle compiles in the real addresses. (The shared config also has the placeholder principal replaced with the live deployer, committed to the repo.)

Part B — frontend (Vercel)

The frontend is a static Vite build. Because it consumes @bachelier/shared as TypeScript source through the pnpm workspace, the build needs the whole monorepo context — so the Vercel project's Root Directory is web while install runs at the workspace root.

SettingValue
Root Directoryweb
FrameworkVite
Installpnpm install --no-frozen-lockfile
Buildpnpm build
Outputdist
EnvVITE_STACKS_NETWORK=testnet, VITE_BACHELIER_DEPLOYER=ST1QN0…CBZK

VITE_API_URL is intentionally left unset → the app runs chain-direct (see Web app). No backend is required for the demo.

:::tip Public access New Vercel team projects get "Vercel Authentication" deployment protection by default, which returns 401 to the public. Disable it (project settings → Deployment Protection, or PATCH /v9/projects/{id} with ssoProtection: null) to make the demo URL publicly reachable. :::

Part C — services (optional)

A basic demo doesn't need the backend (round 1 is pre-opened and the oracle is fresh for 8 days). For ongoing operation — keeping rounds live, richer history, trailing APY — run the keeper + indexer + API + Postgres. See Services.

Verification checklist

  • bs-call-price(reference) == 42848661381 — asserted by the deploy script.
  • Oracle returns a fresh price; round 1 is active with a future expiry.
  • The web bundle contains the deployer principal (the address compiles into assets/index-*.js).
  • The 60 test users funded → minted → deposited, all confirmed.