Web app
The frontend is a React + Vite single-page app (web/) with an editorial
"1900 mathematical monograph" design — paper/indigo palette, Fraunces serif
headings, monospace tabular numerals, and a payoff canvas. It is deployed at
bachelier-frontend.vercel.app.
Chain-direct mode
The app reads price / vault / position state in two tiers:
- API mode — if
VITE_API_URLpoints at a deployed REST API, the app uses it for richer history, charts, and trailing APY. - Chain-direct mode — if
VITE_API_URLis unset (the production default), the app reads vault state, the BTC price, and per-user positions straight from a Stacks node via read-only calls (lib/chainRead.ts). No backend required.
This is why the Vercel deployment needs only the static frontend.
Configuration
All env access is centralized in web/src/lib/config.ts:
| Variable | Purpose |
|---|---|
VITE_STACKS_NETWORK | devnet / testnet / mainnet (production defaults to testnet) |
VITE_BACHELIER_DEPLOYER | deployer principal → bakes live contract ids into the bundle |
VITE_API_URL | optional REST API base; unset → chain-direct |
VITE_ENABLE_FAUCET | force-show the mock-token faucet (auto-on when tokens are the mocks) |
Wallet flows
The app uses @stacks/connect v8 and builds every user transaction with
explicit post-conditions (via the Pc fluent builder) so the wallet
guarantees exact token movements:
- Faucet — mints 1 sBTC + 10,000 mock USDC to the connected wallet
(
mint(amount, recipient), allow mode). - Deposit —
deposit(amount, sbtc)withPc.principal(you).willSendEq(amount).ft(sBTC). - Withdraw —
withdraw(shares, sbtc)with a "vault sends ≥ 1 sat" post-condition. - Buy call —
buy-call(contracts, usdc)with awillSendLte(maxPremium)slippage guard (premium × 1.02). - Claim premium, exercise, request/cancel withdraw — corresponding guarded calls.
The browser is the only signer of user-fund transactions; the app never sees a private key.
Try it
- Open the app; the BTC price pill and vault stats populate from the testnet node.
- Connect Leather or Xverse (set to testnet).
- Click Faucet to mint mock sBTC / USDC.
- Deposit sBTC → receive bcSHARE; your position card and the round countdown appear.
The 60 test users performed exactly this deposit flow (scripted with their own keys), so the live vault already shows real collateral and shares.