(Yes, you better believe this was vibe-coded.)
Zec.rocks uses this to make bulk Zcash payments to participants of our node-lauching workshop.
See a demo video of how it is used
A simple, secure web application for sending bulk Zcash transactions with memo support. Built with Flask and vanilla JavaScript for ease of use and deployment.
- RPC Connection Testing - Verify connection to your Zcash node before sending
- Address Dropdown - Automatically fetch addresses with balances from your wallet
- Manual Entry Option - Toggle to manually enter any address
- Bulk Transaction Support - Send to multiple addresses in one operation
- Memo Support - Include memos with each transaction
- Duplicate Prevention - Backend safeguard prevents sending the same transaction twice
- Confirmation Step - Review all transaction details before sending
- Auto Status Checking - Automatically polls and displays TXID when transaction completes
- Error Handling - Detailed error messages with retry option without re-entering data
- Operation ID Lookup - Built-in tool to check status of any previous operation
- Simple CSV Format - Easy to use transaction input format
- Transaction History - SQLite database tracks all sent transactions
- Python 3.7 or higher
- Access to a Zcash node with RPC enabled, accessible to your network
- A Zcash unified or z-address with funds
-
Clone or download this directory
-
Create a Python virtual environment:
python3 -m venv venv
-
Activate the virtual environment:
source venv/bin/activate # On Linux/Mac # OR venv\Scripts\activate # On Windows
-
Install Python dependencies:
pip install -r requirements.txt
-
That's it! No database setup needed - SQLite database is created automatically.
You can verify everything is working by running the test script:
python test_app.pyIf all tests pass, you're ready to go!
The easiest way to run the application:
./start.shThis script will automatically:
- Create a virtual environment if needed
- Install dependencies if needed
- Start the web server
-
Activate the virtual environment (if not already activated):
source venv/bin/activate # On Linux/Mac # OR venv\Scripts\activate # On Windows
-
Start the Flask server:
python app.py
-
Open your browser and navigate to:
http://localhost:3001 -
The application will guide you through 4 simple steps:
- Step 1: Enter RPC credentials and test connection
- Step 2: Select source address (or enter manually) and enter transaction data
- Step 3: Review and confirm
- Step 4: Transaction submitted - the app will automatically check status and display the TXID when ready
The app provides two ways to select your source address:
Dropdown Mode (Default):
- Automatically fetches all addresses with balances from your wallet
- Shows both shielded (π‘οΈ) and transparent (ποΈ) addresses
- Displays balance for each address
- Sorted by balance (highest first)
Manual Entry Mode:
- Click "Manual Entry" button to switch
- Enter any address manually
- Useful for addresses not in the wallet or edge cases
The app includes a Tools section on the first page with useful utilities:
Operation ID Lookup:
- Look up the status of any operation ID from previous transactions
- Enter an operation ID like
opid-4d6b46a2-4c02-4f13-9507-46e0ebdb8da9 - Shows status, TXID (if complete), execution time, and any errors
- No need to keep track manually - just paste the operation ID
If a transaction fails:
- Detailed Error Display: See exactly what went wrong with expandable error details
- Retry Without Re-entry: Click "Go Back & Retry" to return to Step 2 with all your data preserved
- No Lost Work: Your transaction data, addresses, and credentials remain intact
- Start Fresh Option: Or choose "Cancel & Start Over" if you want to begin again
The transaction input uses a simple CSV format:
address,amount,memo
Example:
u1abc123...,10.5,Payment for services
u1def456...,5.0,Monthly reward
u1ghi789...,3.25,Bonus payment
- address - Zcash unified (u1...) or z-address (zs...)
- amount - Amount in ZEC (can be decimal)
- memo - Optional memo text (leave empty if not needed)
You'll need the following information from your Zcash node:
- RPC Host - IP address or hostname (e.g.,
localhostor66.187.65.180) - RPC Port - Usually
8232(mainnet) or18232(testnet) - RPC Username - Set in your
zcash.conf - RPC Password - Set in your
zcash.conf
rpcuser=your_username
rpcpassword=your_secure_password
rpcport=8232
rpcallowip=127.0.0.1
The application calculates a unique hash for each set of transactions. If you try to submit the same transaction twice (same addresses, amounts, and memos), it will be rejected. This prevents accidental double-payments.
- Submit button is disabled after clicking to prevent double-clicks
- Confirmation dialog requires explicit approval
- All transaction details are shown before sending
- All inputs are validated
- RPC errors are caught and displayed
- Transaction history is stored in SQLite database
The application uses SQLite to store transaction history in transactions.db. This file is created automatically on first run.
tx_hash- Unique transaction identifierrecipients_hash- Hash of recipients (for duplicate detection)operation_id- Zcash operation IDtimestamp- When transaction was sentrecipients_json- Full transaction detailstotal_amount- Total amount sent
- Verify your Zcash node is running
- Check RPC credentials in zcash.conf
- Ensure firewall allows connections on RPC port
- Try
curlcommand to test RPC directly:curl --user username:password --data-binary '{"jsonrpc":"1.0","id":"test","method":"getinfo","params":[]}' -H 'content-type:text/plain;' http://localhost:8232/
- Ensure source address has sufficient balance
- Check that address is fully synced
- Verify addresses are valid Zcash addresses
- Check Zcash node logs for errors
This is a safety feature! If you need to send the same amounts to the same addresses again, you can either:
- Change at least one amount or memo slightly
- Wait and verify the previous transaction completed
- Check the database to confirm if it was actually sent
For production use, consider these additional steps:
-
Change the secret key:
export SECRET_KEY="your-random-secure-key-here"
-
Use a production WSGI server:
pip install gunicorn gunicorn -w 4 -b 0.0.0.0:3001 app:app
-
Use HTTPS - Put behind nginx or Apache with SSL certificate
-
Restrict access - Use firewall rules or authentication
-
Backup database - Regularly backup
transactions.db
.
βββ app.py # Flask backend application
βββ templates/
β βββ index.html # Frontend web interface
βββ requirements.txt # Python dependencies
βββ transactions.db # SQLite database (created on first run)
βββ README.md # This file
Free to use and modify as needed.