A Budget is one funded ceiling. In Control Mode that is a ledger record; in escrow mode an on-chain deposit; in card mode a card authorization-backed budget. Everything downstream — streams, vouchers, settlement — is identical across the three, and your instance enforces all of it server-side; the client only speaks the wire.
import { Dynamo, usd, units } from "@dynamoprotocol/sdk";
const dynamo = await Dynamo.open({
coreUrl: process.env.DYNAMO_CORE_URL!,
token: process.env.OWNER_API_TOKEN!,
});
const alice = "0x00000000000000000000000000000000000000A1";
const sleep = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms));
// 1. Fund a ceiling. The cap is the most this session can ever settle.
const budget = await dynamo.openBudget({ funding: "none", cap: usd("10") });
// 2. Fan out. Each stream gets its own hard cap and per-second rate envelope.
const worker = await budget.stream({
to: alice,
rate: units(1_000_000n),
cap: units(3_000_000n),
});
// 3. Meter. Every tick emits a voucher signed by the stream's scoped key
// (held by the core); allowance accrues per second.
await sleep(1_100);
const receipt = await worker.tick(units(800_000n));
if (receipt.voucherSeq < 1) throw new Error("expected a signed voucher");
// 4. Close. Live streams must be revoked first — closing never silently
// kills allowances (fail closed).
await worker.revoke();
const { releasedAmount } = await budget.close();
// 5. Reconcile. The session's billed total must equal settlement-layer truth.
const session = await budget.aggregate();
if (!session.reconciled) throw new Error("engine and settlement layer disagree");
if ((releasedAmount as bigint) + session.totals.settledAmount > 10_000_000n) {
throw new Error("released + settled exceeded the funded ceiling");
}
the funded ceiling — that inequality (the Σ proof) is checked by the engine, re-derivable from the session view, and carried into evidence bundles.
close() refuses while streams arelive; after settlement of the last funded vouchers, the remainder is released to the owner (escrow: on-chain; card: authorization release).
aggregate() is the receipt. One reconciled object: per-stream settled totals, the settlement layer's own record, and reconciled: true only when the two agree to the unit.
openBudget({ meta }) carries client-side annotation only — it never crosses the wire into settlement, vouchers, or fees. Anything that moves money lives in the typed fields.