
Levee
An on-chain wallet that turns planned spending into time-locked funds
Demo
About
Freelancers and gig workers rarely experience income as a steady stream. Three weeks can pass with nothing, followed by two invoices at once. Yet rent, subscriptions, and bills arrive on fixed dates regardless. The real problem is knowing what is genuinely safe to spend today without spending tomorrow's rent. Most financial tools are advisory. They warn you, and you dismiss the warning and spend anyway. The failure is not the maths. It is that nothing stands in the way at the moment the decision is made. An actual levee, the embankment kind, does not persuade water to stay back. It simply does not let it through. This one works the same way with money. People with irregular income already do a version of this by hand, with separate accounts, cash set aside, or fixed deposits. Those work right up until the moment you decide to override them. And no bank budgeting tool reaches on-chain income at all. Define an obligation, such as rent, 0.006 ETH, due on the 25th, and those funds move into a contract that will not release them early. Not to the app, not to an agent, not to you. Your home screen shows one number: what is actually free to spend right now. Try to spend past it and Levee declines, names the obligation protecting the money, and tells you when it unlocks. No transaction is sent. An in-app assistant answers questions about your position in plain language. It reads live contract state for what is spendable right now and indexed history for what has happened over time. It answers only from data it has, and never invents a figure. The same guarantee extends to software. Subscription bots and payment agents do not know what you have set aside, so Levee publishes a spend-check service they can call before spending. They get back a verdict and the specific obligation standing in the way. Every budgeting tool asks you to be disciplined. Levee makes discipline a property of the system instead.
How it's made
Levee is built around a Solidity smart contract deployed on Ethereum Sepolia through Remix. The contract implements four core operations: "deposit", "commit", "spendFree", and "release". "commit" earmarks a portion of the user's balance against a Unix timestamp and label. "release" reverts before the unlock date, making early release impossible regardless of caller, while "spendFree" can access only uncommitted funds. A read-only "canSpend" check runs before spending and returns whether an amount is allowed, along with the earliest-unlocking commitment blocking it. This enables deterministic refusal without submitting a transaction that would revert. Everything else hangs off that one function. "canSpend" drives three separate surfaces: the refusal screen in the app, the assistant's answer when a user asks why they are blocked, and the public endpoint an autonomous agent calls. All three read the same verdict from the same source, so a bot and a human are never told different things about the same wallet. The frontend uses Next.js 16, TypeScript, Tailwind, and viem. Privy handles email and social authentication while creating embedded wallets automatically, so users never need to manage seed phrases or connect external wallets. External wallet connection is deliberately disabled. Without embedded wallets this would be a dapp for people who already own MetaMask, which is the opposite of the intended user. Subgraph Studio indexes the "Deposited", "Committed", "Released", and "Spent" events. Live contract reads answer what can be spent right now; the Subgraph answers what has been committed over time. Without that indexed history the assistant could only read a balance back to you, rather than reason over commitments made and released. The in-app natural-language assistant combines both feeds to answer real-time and historical questions. It operates strictly on supplied data and never fabricates figures. The same pairing powers a public agent endpoint, whose responses include a "sources" field identifying the origin of each result. The endpoint is documented through OpenAPI and published through a Bazantic gateway with a Recipe explaining when and why an autonomous agent should call it, which turned a plain endpoint into a discoverable service rather than something only I knew existed. Two things were genuinely painful to get working. Privy's RPC rejects "wallet_sendTransaction", which is exactly what viem defaults to when the wallet client is created without an explicit account and chain, so every write failed with an opaque "unsupported method" error until both were passed into "createWalletClient" directly. And the Gemini model catalog is inconsistent with its own serving endpoint: "gemini-2.5-flash" is listed as healthy with "generateContent" supported, but calling it 404s, and the error body redirects to a different model. Trusting the error over the catalog was the only way through.