Water Dispenser.
A decentralized vending machine.
This project bridges the gap between blockchain payments and physical hardware using the Web Serial API.
It detects USDC payments on Base Mainnet Network, triggers an Arduino Leonardo to dispense exactly 250ml of water, and mints a "Shadow Receipt" NFT to the merchant's vault for on-chain loyalty tracking and future user rewards.
Key Features
- Instantly converts on-chain payments into physical actions (dispensing water).
- Direct communication between the Chrome Browser and Arduino Leonardo.
- Real-time monitoring of the Base blockchain for incoming transactions.
- Mints an NFT receipt to the merchant address containing the payer's data. This creates an on-chain ledger for cashback programs or "Random Rewards" without cluttering the user's wallet.
- React-based interface with QR code generation, payment timers, and fluid success animations.
Operation Flow
1. The app displays a "Pay 0.5 USDC" button. It waits for user interaction via the touchscreen or a physical button connected to the Arduino (sending BUTTON_4_PRESSED). In current version used infrared sensor "Flying Fish" to detect the presence of a paper cup in the tray.
2. Payment Phase
A QR Code is generated with the specific USDC transfer URI.
The app begins polling the blockchain for a transfer of 0.5 USDC to the configured MERCHANT_ADDRESS.
3. Verification
Once a valid transaction hash is detected on Base Network, the payment is confirmed.
4. Dispense
The app sends the RELAY_ON command to the Arduino via USB. The Arduino activates the water pump relay.
The app calls mintReceiptNFT. A "Shadow Receipt" is minted to the Merchant's address, recording the Payer's address for future loyalty rewards.
A success sound plays (alert.wav) and a "filling cup" animation displays on screen.
Components connectioon
How it looks inside the water dispenser
In the current version used Dell Vostro 15' Laptop it mounted inside a wooden cabinet serves as the host for the web applications. Laptop is powered by it's original power supply. Water pump is powered by separate 12V supplier.
Your Arduino must be programmed to handle the following serial protocol at 9600 Baud
Current sketch is here https://github.com/KUNZIT/usdckiosk/blob/main/public/sketch.ino
(Upload it via Arduino IDE)
Browser Setup
Open the app in Google Chrome or Microsoft Edge.
Important: Web Serial requires a secure context (HTTPS) or localhost.
Click "Connect USB" in the top right corner to pair your Arduino Leonardo.
Configuration (CONFIG Object)
You can modify the CONFIG object in PaymentApp.tsx to change pricing or addresses:
const CONFIG = {
MERCHANT_ADDRESS: "0x...", // Where money goes & where NFTs are stored
USDC_CONTRACT_ADDRESS: "0x...", // USDC on Base Mainnet
REQUIRED_AMOUNT: 0.5, // Cost of water⚠️ Troubleshooting
"Web Serial API not supported": Ensure you are using Chrome/Edge. Firefox and Safari do not support this API yet.
Arduino not connecting: Check if another app (like Arduino IDE) is hogging the COM port. The browser needs exclusive access.
Payment not detected: Ensure the user is sending Base USDC, not native ETH, and the amount matches REQUIRED_AMOUNT exactly.
💧 How to Use our Water Dispenser
Dear Customers,
Please follow these steps to get your drinking water:
1. Preparation
Open your crypto wallet (e.g., MetaMask, Coinbase Wallet) on the Base Mainnet. Ensure you have the following minimum amounts:
• 0.5 USDC (on Base network)
• Ethereum (ETH) for gas fees (on Base network)
2. Dispensing Process (Must be completed in 50 seconds)
• Put your paper cup into the dispenser tray.
• A QR code will immediately appear on the display.
• Open the scanning camera in your crypto wallet.
• Scan the QR code quickly.
• A transaction request will appear in your wallet.
• Crucially, confirm that you are transferring EXACTLY 0.5 USDC on the Base Network. (Payments for any other amount will not dispense water.)
3. Complete & Collect
• Wait for the on-screen message: "Here you are".
• Take your cup with water away from the dispenser tray.
⚠️ Important Note on Timing
• The application session duration is 50 seconds. Please be quick to scan the QR code and confirm the transaction in your wallet.
• In case the session expires, or if you experience a network delay and the water is not dispensed after your payment is confirmed, please contact us immediately for a refund.















Comments