
MelodyPay
Air-gapped hardware wallet for sending EVM payments securely over sound.
Demo
About
MelodyPay : Air-Gapped Acoustic Hardware Wallet MelodyPay is an air-gapped payment system that replaces QR codes, NFC, and Bluetooth with sound. A merchant's phone plays an audio invoice. A custom offline hardware wallet hears it, shows the payment details on screen, and waits for a physical button press before signing anything. The signed authorization plays back as audio, the receiver's web terminal picks it up, and transaction settles on-chain seconds later. No gas token needed on the customer's end, no internet connection required on the wallet's end. The problem: every existing in-person crypto payment method has a hole in it. QR codes can be overlaid or spoofed and need good lighting and a clean camera. NFC needs special reader hardware and is vulnerable to relay attacks. Bluetooth and Wi-Fi bring a whole software stack's worth of remote exploits along with them. And most flows still assume the customer is holding gas tokens and has a live data connection at checkout, which is where a lot of transactions quietly fail. Here's how MelodyPay avoids all of that: Acoustic transport: Payloads move as FSK-modulated audio via ggwave , no radios involved. Reed-Solomon error correction handles noisy environments, and a simple framed protocol (64-byte frames, 300ms silence between bursts) keeps the two sides in sync. The hardware wallet: A custom ESP32-S3 board with Wi-Fi and Bluetooth stripped out at compile time, so there's no radio stack to exploit even in theory. Signing requires a physical button on a GPIO interrupt, not a software command, so nothing can trigger a signature remotely. Every transaction is shown in full on a small OLED screen before signing: amount, recipient, nonce, no hidden fields. Gasless settlement. The wallet signs EIP-712 authorizations under EIP-3009 (ReceiveWithAuthorization) for USDC on Arc Testnet. The merchant's terminal submits the transaction and covers gas, so the customer never needs a gas token or a live connection. Merchant identity. Merchants register a subname like cafe.melodypay.eth through a custom registrar contract on Sepolia. The web terminal resolves it to a checksummed address via Viem and shows both before generating an invoice, and pulls routing config from ENS text records instead of a centralized API. The terminal. A browser-based PWA using the Web Audio API, so any phone or laptop becomes a POS terminal with no app install and no private key on the merchant's side. A companion CLI (built with terminui) gives real-time balance monitoring across chains and diagnostics for connected wallets.
How it's made
MelodyPay sends payments as sound instead of over a network. `ggwave` handles FSK modulation across carrier tones between 1875 Hz and 2187 Hz, with both the ESP32-S3 firmware and the browser's Web Audio API locked so the two sides stay in sync. Every packet carries Reed-Solomon error correction, so demodulation holds up even in a noisy room. Packets are framed as fixed 64-byte blocks, sent in chunks with 300ms of silence between bursts so transmitting and listening never overlap. A full transaction is four messages: the wallet announces its address, the receiver terminal broadcasts the invoice (chain ID, recipient, amount, expiry, nonce), the wallet broadcasts the signed authorization once the button is pressed, and the terminal confirms the on-chain settlement back to the wallet. On the hardware side, the ESP32-S3's two cores split by function : Core 0 handles I2S DMA audio and FSK synthesis in real time, Core 1 handles crypto, the keystore, button debouncing, and the OLED. The mic, amp, and display run on I2S and I2C, and the confirmation button sits on a dedicated GPIO interrupt. Wi-Fi and Bluetooth are disabled in `sdkconfig`, so the drivers never make it into the compiled binary : there's no radio stack on the device to attack. For settlement, we implemented EIP-3009's `ReceiveWithAuthorization` against Arc Testnet's USDC contract. Since there's no Web3 library for a microcontroller, we wrote our own EIP-712 signer in C: it encodes the authorization struct, hashes it with an embedded Keccak-256, and signs it using Trezor-crypto's secp256k1. The wallet signs entirely offline; the merchant's terminal submits the transaction and covers the gas. For merchant identity, we deployed a custom ENSv2 subname registrar on Sepolia, so merchants register names like `cafe.melodypay.eth` instead of showing a raw address. The terminal resolves the name via Viem, reads routing config from ENS text records, and shows both the name and the checksummed address before generating an invoice. On security: payloads never carry keys or credentials, and each authorization has a random nonce with a 60-second expiry, so a recorded chime is useless once it lapses. Replay is blocked three ways : the contract marks each nonce used on-chain, the receiver keeps its own dedup table, and expired authorizations are rejected before either check runs. There's no radio stack in the firmware, so there's no wireless attack surface at all. The firmware only parses native transfers or EIP-3009 structs, so blind signing of arbitrary calldata isn't possible, and the full amount and recipient always render on the OLED from RAM. Signing only runs after a real hardware interrupt from the button, so no software or serial command can trigger it. And the serial protocol only exposes capability status and chain config , nothing in the firmware can read or export a key. A few build details worth mentioning: the mic and speaker sit close together on the same board, so we added a squelch routine that mutes the mic's DMA channel during transmission and unmutes it with a short decay buffer after, keeping the speaker's own output out of the mic. The operator CLI talks to the hardware over raw USB serial at 115200 baud, built with `terminui` instead of a heavier framework, with private keys never touching the serial line.