Search projects, hackathons, sponsors and tech

    ← All projects

    Tappy

    Tap to approve. An AI agent wallet where every onchain transaction needs a physical NFC tap.

    Demo

    About

    Tappy is a wallet for AI agents that the agent cannot drain. People are starting to hand real money to AI agents so they can buy things, pay for services, and move funds without being asked every time. But an agent can be talked into anything. A prompt injection hidden in a product listing, a web page, or an email can convince it to send the whole balance to an attacker, and it will do so confidently and immediately. The current answer is a policy file: a spending cap, an allowlist, a daily limit. Those help, but they are rules written in advance by someone guessing what will go wrong, and a policy file is not a person. Tappy puts a person back in the loop, physically. The wallet has two keys. The agent holds one. A human holds the other on a device they can put in their pocket, in our case a Flipper Zero. The smart contract executes a transaction only when both keys have signed the exact same transaction. The agent can propose anything it likes and can sign its half instantly, and none of that moves a single wei on its own. You chat with the agent in a normal web app and ask it to buy something, send money, or swap tokens. The agent works out what it wants to do and creates a proposal. That proposal appears on the Flipper's screen with the action, the amount, and who is receiving it. Press OK and the transaction goes to the chain, with the chat updating when it lands. Press Back and nothing happens at all, and the agent is told it was refused. The demo turns on what happens when the agent is compromised. A shop listing in our mock store contains a hidden instruction telling the agent to transfer the entire balance to an attacker's address. The agent does what it was told and proposes the transfer. The proposal shows up on the Flipper like any other, reading SEND, the full balance, to an address the human has never seen. The human presses Back, and the money stays where it was. The agent has exactly three abilities: propose a send, propose a swap, propose a purchase. There is no fourth tool that executes anything, so there is nothing an injection can talk it into that a human does not personally see and approve first. We did not add prompt-injection defenses to the agent, because whether the agent gets fooled does not change what can happen to the money. Around this we built a working demo economy: a chat interface, a wallet dashboard showing both keys and the live balance, a mock shop with items to buy, and a mock exchange to swap against, all deployed on testnet so the transactions are real on-chain calls. A physical NFC tag starts the purchase flow. Tapping a phone to a sticker opens the shop inside the app, so the interaction feels like paying for something in a real place. We chose a Flipper Zero because it has a screen, a button, and a radio, and because many people in this community already own one and enjoy hacking on it. Nothing in the design is tied to it. The same approval step could run on a phone, a hardware wallet, or a keyring NFC tag costing about a dollar. In this version the human key is stored on the laptop that talks to the Flipper, so the Flipper is the physical approval step and not yet the place the key lives. Moving the key onto the device itself is the obvious next step, and we have measured that the hardware can handle the cryptography, but it needs a toolchain we chose not to take on during a one-week build. Everything runs on testnet.

    How it's made

    Tappy is a 2-of-2 wallet for AI agents. The agent holds one key, a human holds the other, and nothing moves until both have signed the same transaction. Other agent wallets stop a runaway agent with a policy file, and a policy file is not a person. The contract is the whole security model in about eighty-five lines of Solidity, built with Foundry on OpenZeppelin's typed-data and signature-recovery libraries. Its one function takes a call plus two signatures, recovers both against a fixed agent address and a fixed human address, and reverts if either fails. Replay protection comes from a monotonic nonce combined with the chain ID and the contract's own address, and every proposal carries a deadline ten minutes out. Anyone can relay the call and pay the gas, because authority lives in the signatures and not in the sender. We left out spending limits and allowlists on purpose. Every competing product has those already, and none of them has a hand. The web app is a T3 stack: Next.js on the App Router, tRPC, Drizzle over Postgres, hosted on Vercel with Supabase behind it. Inside it a model tool-calling loop gives the agent three tools, one each to propose a send, a swap, or a purchase. It has no way to execute anything. Proposals enter a state machine as pending and sit there until a human decides. One library handles typed-data hashing and signing across the server, the laptop bridge and the tests, so the digest comes out the same way everywhere. What made a three-person week work was putting a single interface in front of the human approver, with one method that takes a summary and a timeout and returns a decision. Three things implement it: a mock that auto-approves or asks yes/no in a terminal, the real Flipper, and a future on-device signer. Two thirds of the project was built against the mock, so only one person ever needed the hardware, and plugging the device in changed nothing above it. The hackiest part is how the laptop talks to the Flipper. Its JavaScript engine cannot reach USB at all, since the serial module is wired to the GPIO pins rather than the host connection, so there is no socket to open and no way for a script on the device to receive anything from a computer. The bridge instead drives the Flipper's own command-line interface over the USB virtual COM port and uses its file commands to drop small JSON files onto the SD card. The app on the device polls for an inbox file three times a second, renders four short lines on the 128x64 screen, and writes the answer back to an outbox file. A sequence number makes it idempotent, so re-reading a file cannot double-approve. File-based IPC tunnelled through a serial terminal is an ugly way to do this, and it has been reliable. The hosting forced a similar inversion. Vercel cannot hold an open websocket, so the laptop polls upward twice a second and dials out instead of the server pushing approvals down. That also removes any need for an inbound tunnel to a laptop on hotel wifi. The endpoint takes a bearer token, and it separately recovers the submitted signature against the known human address, so a leaked token still cannot approve something the human never saw. NFC is how a purchase starts. A sticker carries a URL that opens the shop inside the app. Getting it readable on iPhones cost us an hour of confusion. The tag looked correct by every check we knew, Android read it instantly, and iOS did nothing at all. Dumping the raw pages by hand showed the stored address had two schemes in it: the encoding already carries a byte meaning "https", and we had typed the prefix in as well. iOS validates the address before it will show anything, and it reports no error when it throws one away. We now build the payload from the prefix code and a bare hostname. The risk we took most seriously was a byte-level disagreement between the TypeScript and the Solidity over how the signed message is encoded. One wrong hash and every transaction reverts with nothing useful to debug. We froze a shared test vector on day one and made both test suites check it, and nothing merged unless the two languages agreed. We built against a Flipper Zero, though nothing in the design depends on it. The second factor only has to do three things: show a human what is about to happen, take a yes or a no, and produce a signature. The Flipper is a convenient body for that because it has a screen, a button and a radio, and because a lot of this audience already owns one. The same interface could sit behind a phone, a hardware wallet, or a cheap NFC tag on a keyring, where tapping the tag replaces the button press. A tag has no screen, so you lose the ability to see what you are approving before you approve it. That trade buys a second factor costing about a dollar per user. The human key still lives on the laptop in this version, so the Flipper is the physical approval step and not yet the place the key is stored. Signing on the device is feasible, and we measured the curve maths at roughly a tenth to a quarter of a second per signature, but it needs a C toolchain we chose not to fight mid-build. Testnet only.