State machines anchored to Bitcoin.
A web contract separates logic from data. The contract defines rules in any language. The state, ledger, and trail are always JSON — universal, language-agnostic, verifiable.
| Layer | File | Mutable? | Role |
|---|---|---|---|
| Contract | contract.json + source |
No | Rules & transition logic (immutable once deployed) |
| State | state.json |
Yes | Current values, updated each transition |
| Ledger | ledger.json |
Yes | Balance tracking (webledgers) |
| Trail | blocktrail | Append | Bitcoin-anchored audit log (blocktrails) |
The contract declares its profile, language, and source. The logic lives in a separate file.
{
"@context": "https://webcontracts.org/v1",
"type": "WebContract",
"profile": "amm.v1",
"id": "pool-tbtc3-tbtc4",
"language": "javascript",
"source": "amm.js",
"created": 1741737600
}The source file exports transition functions. Each takes (state, params, ledger) and returns { state, effects }:
// amm.js
export function swap(state, params, ledger) {
const { sender, sell, amount } = params
const buy = state.pair.find(u => u !== sell)
const rIn = state.reserves[sell], rOut = state.reserves[buy]
const amtAfterFee = amount * (1 - state.fee)
const out = Math.floor((rOut * amtAfterFee) / (rIn + amtAfterFee))
return {
state: {
...state,
reserves: { [sell]: rIn + amount, [buy]: rOut - out },
k: (rIn + amount) * (rOut - out),
},
effects: [
{ op: 'debit', who: sender, currency: sell, amount },
{ op: 'credit', who: sender, currency: buy, amount: out },
]
}
}The contract logic is pluggable. The pod needs an executor for the language.
| Language | Runtime |
|---|---|
| JavaScript | Native on Node.js pods |
| Solidity | Via solc / EVM in WASM |
| Python | Via sandboxed runtime |
The interface is always the same: (state, params, ledger) → { state, effects }.
Pure data — no logic. Current values plus a hash chain for verification.
{
"contract": "pool-tbtc3-tbtc4",
"seq": 5,
"prev": "a1b2c3d4e5f6...",
"updated": 1741737600,
"pair": ["tbtc3", "tbtc4"],
"reserves": { "tbtc3": 5000, "tbtc4": 10000 },
"k": 50000000,
"fee": 0.003,
"totalShares": 1000,
"lpShares": { "did:nostr:abc123...": 1000 }
}Each transition increments seq and sets prev to SHA-256 of the previous state (JCS-canonicalized). This hash chain is anchored to Bitcoin via blocktrails.
Transition functions return an effects array. The executor applies these against the webledger atomically.
{ op: "credit", who, currency, amount }— add to balance{ op: "debit", who, currency, amount }— subtract from balance{ op: "transfer", from, to, currency, amount }— atomic move
The contract never touches the ledger directly. It declares intent; the executor enforces it.
Web contracts use a trust but verify model:
- Executor — runs the contract source, validates transitions, updates state + ledger + trail atomically. Any server or local process that can run the contract language.
- Client — submits transitions. Can optionally run the contract source locally to preview results before submitting.
- Verifier — anyone. Download the contract source, replay the state chain from genesis, check each
prevhash, verify the blocktrail against Bitcoin. If the executor cheated, the chain breaks.
No consensus mechanism. No global blockchain. The executor is efficient (single process), and the hash chain + Bitcoin trail provides cryptographic tamper evidence.
| Profile | Description | Transitions |
|---|---|---|
amm.v1 |
Automated market maker (x * y = k) | swap, add-liquidity, remove-liquidity |
escrow.v1 |
Two-party escrow with arbiter | fund, release, dispute, resolve, refund |
sale.v1 |
Fixed-price token sale | buy, close |
subscription.v1 |
Recurring payment agreement | pay, pause, resume, cancel |
Parties are identified by did:nostr:<pubkey>. Authentication uses NIP-98 HTTP auth.
Works for humans (NIP-07 browser extensions) and AI agents (stored keys) alike.
Web contracts are transport-agnostic. The four files can live anywhere:
| Host | Example |
|---|---|
| Solid pod | Full integration — auth, ledger, and trail built in |
| Web server | Any HTTP server with a contract executor |
| Git repo | State as commits, trail as tags |
| Local directory | Agent runs executor locally, syncs state |
When served over HTTP:
PUT /contracts/{id}/contract.json — deploy contract
GET /contracts/{id}/state.json — read current state
POST /contracts/{id}/ — submit a transition
GET /contracts/{id}/trail.json — read audit trail
- JavaScript Solid Server — implements payment and AMM profiles
- Web Ledgers — balance tracking spec
- Blocktrails — Bitcoin anchoring spec
- NIP-98 — HTTP authentication
MIT