- Move CRYPTO.rst to docs/CRYPTO.rst - Move CRYPTO_PROBLEMS.rst to docs/CRYPTO_PROBLEMS.rst 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
480 lines
16 KiB
ReStructuredText
480 lines
16 KiB
ReStructuredText
Cryptocurrency Payment System Documentation
|
|
===========================================
|
|
|
|
This document provides detailed information about the cryptocurrency payment system in Make Post Sell, including wallet management, security considerations, and operational procedures.
|
|
|
|
Introduction
|
|
------------
|
|
|
|
The cryptocurrency payment system in Make Post Sell works like a digital cash register that can accept Monero (and eventually other cryptocurrencies). Here's the key concepts:
|
|
|
|
**Why You Can't Use External Wallets (like Cake Wallet):**
|
|
The system needs to generate a unique address for each customer payment (like giving each customer a different invoice number). Only the wallet owner can create these subaddresses, and external wallets can't provide this functionality via API.
|
|
|
|
**How Money Flows:**
|
|
|
|
1. Customer pays → Your hot wallet receives it
|
|
2. Payment is detected and order is fulfilled automatically
|
|
3. You manually move funds to cold storage periodically
|
|
|
|
**Security Reality:**
|
|
|
|
- Your server holds the wallet keys (like leaving cash register unlocked)
|
|
- If server is hacked = funds at risk
|
|
- Best practice: Keep minimal funds, move to cold storage often
|
|
|
|
**The Architecture:**
|
|
|
|
- **monero-wallet-rpc**: The "cash register" software
|
|
- **crypto_watcher**: The "cashier" watching for payments
|
|
- **CryptoPayment**: The "receipt book" tracking who paid what
|
|
|
|
Think of it like running a physical store - you need your own cash register (can't use someone else's), you periodically empty it to a safe (cold wallet), and you keep receipts (database records) of all transactions.
|
|
|
|
Overview
|
|
--------
|
|
|
|
Make Post Sell supports cryptocurrency payments through a modular system designed to handle multiple coins. Currently, Monero (XMR) is implemented, with the architecture ready for Bitcoin, Litecoin, and other cryptocurrencies.
|
|
|
|
Architecture
|
|
------------
|
|
|
|
The crypto payment system consists of several components:
|
|
|
|
1. **CryptoPayment Model** - Database model tracking payment details
|
|
2. **Crypto Client Library** - RPC client for communicating with wallet daemons
|
|
3. **Crypto Views** - Web endpoints for payment flow
|
|
4. **Crypto Watcher** - Background service monitoring blockchain for payments
|
|
5. **Auto-Sweep** - Automatically transfers funds to cold storage after each payment
|
|
|
|
How Payments Work
|
|
-----------------
|
|
|
|
1. Customer selects "Pay with Crypto" at checkout
|
|
2. System generates a unique subaddress for the payment
|
|
3. Current exchange rate is locked for the quote duration
|
|
4. Customer sends payment to the generated address
|
|
5. Crypto watcher monitors for incoming transfers
|
|
6. Order is fulfilled when payment is confirmed
|
|
7. **Funds are immediately swept to shop's cold wallet** (keeps only 0.001 XMR for fees)
|
|
|
|
Per-Shop Wallet Configuration
|
|
-----------------------------
|
|
|
|
Each shop can have its own hot wallet account and cold storage address:
|
|
|
|
1. **Hot Wallet Account**: Automatically assigned when shop configures a cold wallet
|
|
2. **Cold Wallet Address**: Shop owner's secure wallet for receiving swept funds
|
|
|
|
To enable Monero payments for a shop:
|
|
|
|
1. Go to Shop Settings
|
|
2. Enter your cold wallet address in the Monero section
|
|
3. System automatically assigns a unique account index (one-time)
|
|
4. Shop is now ready to accept Monero payments
|
|
|
|
**Changing Cold Wallet Address**:
|
|
|
|
- You can update your cold wallet address anytime
|
|
- Your account index stays the same (no funds lost)
|
|
- Future sweeps will go to the new address
|
|
- Existing balance (0.001 XMR reserve) remains available
|
|
|
|
**Security Design**:
|
|
|
|
- Account indices are hidden from users to prevent confusion
|
|
- Each shop gets one permanent account index (doesn't change with cold wallet updates)
|
|
- Each shop's funds are isolated in separate accounts
|
|
- **Auto-sweep is mandatory** - funds move to cold storage immediately after confirmation
|
|
- Hot wallet never holds more than 0.001 XMR per account
|
|
|
|
Transaction Lifecycle Example
|
|
-----------------------------
|
|
|
|
Let's follow a complete user journey for a $10 digital product purchase:
|
|
|
|
**Customer Journey Begins**
|
|
|
|
**1. Product Discovery**
|
|
- Customer visits shop.example.com
|
|
- Browses products, finds a $10 digital guide
|
|
- Clicks "Add to Cart"
|
|
- Cart shows: 1 item, $10.00
|
|
|
|
**2. Checkout Process**
|
|
- Customer clicks "Checkout"
|
|
- Enters email: customer@email.com
|
|
- Sees payment options: "Pay with Stripe" or "Pay with Monero"
|
|
- Chooses "Pay with Monero"
|
|
|
|
**3. Payment Quote Generation** (T+0 seconds)
|
|
- System fetches current XMR/USD rate: 1 XMR = $300 USD
|
|
- Calculates price: $10 ÷ $300 = 0.03333333 XMR
|
|
- Displays to customer:
|
|
```
|
|
Amount Due: 0.03333333 XMR
|
|
Exchange Rate: $300.00/XMR
|
|
Quote Valid For: 15 minutes
|
|
```
|
|
|
|
**4. Payment Address Generation** (T+1 second)
|
|
- System assigns subaddress from shop's account (e.g., account 5, subaddress 147)
|
|
- Displays QR code and address: 87BqQYkugEzh6Tg3gmfDPD6u7w6rNwJrTZXSdWgMHMfT...
|
|
- CryptoPayment record created:
|
|
- Shop's cold wallet stored for later sweep
|
|
- Expected amount: 0.03333333 XMR
|
|
- Quote expiry timestamp set
|
|
|
|
**5. Customer Sends Payment** (T+2 minutes)
|
|
- Customer opens mobile Monero wallet
|
|
- Scans QR code or copies address
|
|
- Enters amount: 0.03333333 XMR
|
|
- Confirms transaction (network fee ~0.00001 XMR)
|
|
- Transaction broadcasts to Monero network
|
|
|
|
**6. Payment Detection** (T+2-3 minutes)
|
|
- crypto_watcher polls every 20 seconds
|
|
- Detects incoming transaction in mempool
|
|
- Status changes: "pending" → "received"
|
|
- Customer sees: "Payment received! Awaiting 10 confirmations..."
|
|
- Progress bar shows: 0/10 confirmations
|
|
|
|
**7. Confirmation Progress** (T+2 to T+22 minutes)
|
|
- Monero blocks average 2 minutes each
|
|
- Customer refreshes page, sees progress:
|
|
- 2 confirmations (T+6 min): "2/10 confirmations"
|
|
- 5 confirmations (T+12 min): "5/10 confirmations"
|
|
- 8 confirmations (T+18 min): "8/10 confirmations"
|
|
|
|
**8. Payment Fully Confirmed** (T+22 minutes)
|
|
- 10th confirmation reached
|
|
- Status changes: "received" → "confirmed"
|
|
- Customer sees: "Payment confirmed! ✓"
|
|
- Invoice finalized:
|
|
- Digital download link appears
|
|
- Email sent: "Your purchase from Shop Name"
|
|
- Shop owner notified: "New sale: $10.00 (0.03333333 XMR)"
|
|
|
|
**9. Customer Downloads Product** (T+23 minutes)
|
|
- Customer clicks download link
|
|
- Gets their digital guide PDF
|
|
- Happy customer, transaction complete from their perspective
|
|
|
|
**Behind the Scenes - Shop Gets Paid**
|
|
|
|
**10. Automatic Sweep Triggers** (T+22 minutes, 5 seconds)
|
|
- Immediately after confirmation, auto-sweep initiates
|
|
- Balance check: Account 5 has 0.03333333 XMR
|
|
- Sweep calculation: 0.03333333 - 0.001 (keep for fees) = 0.03233333 XMR
|
|
- Transfer initiated to shop's cold wallet: 4A1s7n9...
|
|
|
|
**11. Sweep Complete** (T+24 minutes)
|
|
- Sweep transaction confirmed
|
|
- Hot wallet account 5 balance: 0.001 XMR (ready for next customer)
|
|
- Shop's cold wallet receives: 0.03233333 XMR
|
|
- At $300/XMR, shop owner has $9.70 (after fee reserve)
|
|
|
|
**Total Timeline**:
|
|
- Customer experience: ~23 minutes (browse to download)
|
|
- Full settlement: ~24 minutes (payment to cold storage)
|
|
|
|
**Financial Summary**:
|
|
- Product price: $10.00
|
|
- Customer paid: 0.03333333 XMR ($10.00)
|
|
- Network fee: ~0.00001 XMR ($0.003)
|
|
- Shop received: 0.03233333 XMR ($9.70)
|
|
- Fee reserve kept: 0.001 XMR ($0.30)
|
|
|
|
**Key Points**:
|
|
- Customer experience is smooth - they get their product in ~23 minutes
|
|
- Shop gets paid automatically with no manual intervention
|
|
- Hot wallet exposure: maximum 22 minutes, only 0.033 XMR
|
|
- Each shop's funds stay completely isolated
|
|
- System handles everything: quote, payment detection, fulfillment, sweep
|
|
|
|
**What Could Go Wrong**:
|
|
|
|
1. **Customer Underpays**: Sends 0.03 instead of 0.03333333 XMR
|
|
- Payment detected but never confirms
|
|
- Manual intervention needed or customer adds missing amount
|
|
|
|
2. **Quote Expires**: Customer takes 20 minutes to send
|
|
- Quote expired after 15 minutes
|
|
- Customer needs new quote at potentially different rate
|
|
|
|
3. **Network Congestion**: Monero network is busy
|
|
- Confirmations take 3-4 minutes per block instead of 2
|
|
- Customer waits longer but system handles it
|
|
|
|
4. **Wrong Copy/Paste**: Customer sends to wrong address
|
|
- Funds lost (no recovery possible)
|
|
- Importance of QR codes to avoid this
|
|
|
|
5. **Shop Misconfiguration**: Shop entered wrong cold wallet
|
|
- Sweep succeeds but funds go to wrong wallet
|
|
- Unrecoverable - emphasizes importance of testing
|
|
|
|
Wallet Configuration
|
|
--------------------
|
|
|
|
**Creating a Wallet**
|
|
|
|
For production use, create a dedicated wallet::
|
|
|
|
# Create new wallet
|
|
monero-wallet-cli --generate-new-wallet=/path/to/mps-wallet
|
|
|
|
# IMPORTANT: Save the 25-word mnemonic seed securely!
|
|
# This is your only way to recover funds if the wallet file is lost
|
|
|
|
**Running the Wallet RPC**
|
|
|
|
The wallet must be accessible via RPC. You have two options:
|
|
|
|
**Option 1: Production Setup (Run Your Own Node)**
|
|
|
|
This is the most secure and reliable setup::
|
|
|
|
# Terminal 1: Start your own Monero node (daemon)
|
|
# This downloads ~150GB blockchain and uses P2P to stay synced
|
|
monerod --data-dir=/path/to/blockchain \
|
|
--rpc-bind-ip=127.0.0.1 \
|
|
--rpc-bind-port=18081 \
|
|
--confirm-external-bind
|
|
|
|
# Terminal 2: Start wallet RPC (after daemon syncs)
|
|
monero-wallet-rpc \
|
|
--rpc-bind-ip=127.0.0.1 \
|
|
--rpc-bind-port=18083 \
|
|
--disable-rpc-login \
|
|
--wallet-file=/path/to/mps-wallet \
|
|
--daemon-address=127.0.0.1:18081 \
|
|
--trusted-daemon
|
|
|
|
**Option 2: Development Setup (Use Remote Node)**
|
|
|
|
Quicker to start but less private and relies on external service::
|
|
|
|
monero-wallet-rpc \
|
|
--rpc-bind-ip=127.0.0.1 \
|
|
--rpc-bind-port=18083 \
|
|
--disable-rpc-login \
|
|
--wallet-file=/path/to/mps-wallet \
|
|
--daemon-address=node.moneroworld.com:18089 \
|
|
--trusted-daemon
|
|
|
|
**Using the Makefile**
|
|
|
|
The included Makefile provides convenient targets::
|
|
|
|
# First time setup
|
|
make monero-wallet-create # Create a new wallet
|
|
|
|
# Production (your own node)
|
|
make monero-node # Terminal 1: Start blockchain node
|
|
make monero-wallet # Terminal 2: Start wallet RPC
|
|
|
|
# Development (remote node)
|
|
make monero-wallet-remote # Start wallet with public node
|
|
|
|
# View all options
|
|
make monero-full-stack # Shows complete setup instructions
|
|
|
|
Security notes:
|
|
|
|
- ``--disable-rpc-login`` is safe only when binding to localhost
|
|
- For remote access, use ``--rpc-login username:password``
|
|
- Running your own node ensures privacy and reliability
|
|
- The daemon automatically uses P2P to find peers and stay synchronized
|
|
|
|
**Account Structure**
|
|
|
|
Monero wallets contain multiple accounts, each with many subaddresses:
|
|
|
|
- **Account 0** (default): Main receiving account
|
|
- **Account 1+**: Can be used for organization (optional)
|
|
- **Subaddresses**: Unique addresses generated per payment
|
|
|
|
The ``MPS_MONERO_ACCOUNT_INDEX`` environment variable (default: 0) specifies which account to use.
|
|
|
|
Wallet Management
|
|
-----------------
|
|
|
|
**Checking Balance**
|
|
|
|
View wallet balance and incoming payments::
|
|
|
|
# Via CLI (stop RPC first)
|
|
monero-wallet-cli --wallet-file=/path/to/mps-wallet
|
|
[wallet]: balance
|
|
[wallet]: show_transfers
|
|
|
|
# Via RPC
|
|
curl -X POST http://127.0.0.1:18083/json_rpc -d '
|
|
{
|
|
"jsonrpc":"2.0",
|
|
"id":"0",
|
|
"method":"get_balance",
|
|
"params":{"account_index":0}
|
|
}'
|
|
|
|
**Sending Funds (Hot Wallet Management)**
|
|
|
|
The hot wallet runs as a service with mandatory auto-sweep:
|
|
|
|
1. **Automatic Post-Payment Sweep**:
|
|
|
|
Every confirmed payment triggers an immediate sweep to the shop's cold wallet.
|
|
Only 0.001 XMR remains for future transaction fees.
|
|
|
|
2. **Manual Sweep Commands** (for maintenance/recovery):
|
|
|
|
Make Post Sell includes a ``sweep_to_cold`` command for automated cold storage transfers:
|
|
|
|
**Per-Shop Sweeping**::
|
|
|
|
# Sweep a specific shop's wallet (uses shop's configured cold wallet)
|
|
sweep_to_cold development.ini --shop-id SHOP_UUID --dry-run
|
|
sweep_to_cold development.ini --shop-id SHOP_UUID
|
|
|
|
# Sweep all shops with configured wallets
|
|
sweep_to_cold development.ini --all-shops --dry-run
|
|
sweep_to_cold development.ini --all-shops
|
|
|
|
# Aggressive sweep all shops
|
|
sweep_to_cold development.ini --all-shops --sweep-all
|
|
|
|
**Command Options**:
|
|
|
|
- ``config_uri``: Path to your configuration file (required)
|
|
- ``--shop-id``: Sweep specific shop's wallet using its configured cold address
|
|
- ``--all-shops``: Sweep all shops with configured wallets
|
|
- ``--sweep-all``: Aggressive mode, keep only 0.001 XMR (~7-8 transactions)
|
|
- ``--account-index``: Override wallet account to sweep from (default: shop's configured account)
|
|
- ``--priority``: Transaction priority 0-3, affects fee (default: 1)
|
|
- ``--dry-run``: Check balance without sending funds
|
|
|
|
**Security Notes**:
|
|
|
|
- The cold wallet address should be from a hardware wallet or air-gapped system
|
|
- Test with ``--dry-run`` first to verify balance calculations
|
|
- Monitor the sweep log file for any errors
|
|
- Consider setting up alerts for failed sweeps
|
|
|
|
**Cold Storage Best Practices**
|
|
|
|
1. **Minimize Hot Wallet Exposure**:
|
|
- Keep only enough XMR for daily operations
|
|
- Sweep excess funds to cold storage regularly
|
|
|
|
2. **Hardware Wallet Integration**:
|
|
- Use a hardware wallet (Ledger/Trezor) for cold storage
|
|
- Generate cold storage address offline
|
|
|
|
3. **Multi-signature Setup** (Advanced):
|
|
- Use 2-of-3 multisig for large amounts
|
|
- Requires multiple parties to authorize transfers
|
|
|
|
Security Considerations
|
|
-----------------------
|
|
|
|
**Hot Wallet Risks**
|
|
|
|
The wallet on the server is a "hot wallet" with inherent risks:
|
|
|
|
- Server compromise = potential fund loss
|
|
- No way to use external wallets (Cake Wallet, etc.) due to subaddress generation requirement
|
|
- Must trust the server environment
|
|
|
|
**Mitigation Strategies**
|
|
|
|
1. **Access Controls**:
|
|
|
|
- Restrict RPC to localhost only
|
|
- Use strong authentication if remote access needed
|
|
- Monitor access logs
|
|
|
|
2. **Operational Security**:
|
|
|
|
- Regular security updates
|
|
- Encrypted wallet file storage
|
|
- Secure backup procedures
|
|
- Audit trail for all transfers
|
|
|
|
3. **Monitoring**:
|
|
|
|
- Set up alerts for large incoming payments
|
|
- Monitor wallet balance changes
|
|
- Track unusual access patterns
|
|
|
|
Backup and Recovery
|
|
-------------------
|
|
|
|
**Backup Requirements**
|
|
|
|
1. **Mnemonic Seed** (Critical):
|
|
- 25-word recovery phrase
|
|
- Store offline in multiple secure locations
|
|
- Never store digitally on the server
|
|
|
|
2. **Wallet Files**:
|
|
- Regular backups of wallet file
|
|
- Include wallet.keys file
|
|
- Encrypt backups
|
|
|
|
**Recovery Procedures**
|
|
|
|
From mnemonic seed::
|
|
|
|
monero-wallet-cli --restore-deterministic-wallet
|
|
# Enter 25-word mnemonic
|
|
# Specify restore height to speed up sync
|
|
|
|
From wallet file backup::
|
|
|
|
# Copy wallet and wallet.keys files
|
|
cp backup/mps-wallet* /path/to/
|
|
# Start normally
|
|
|
|
Troubleshooting
|
|
---------------
|
|
|
|
**Common Issues**
|
|
|
|
1. **RPC Connection Failed**:
|
|
- Check monero-wallet-rpc is running
|
|
- Verify firewall allows localhost:18083
|
|
- Check RPC URL in configuration
|
|
|
|
2. **Payments Not Detected**:
|
|
- Ensure crypto_watcher is running
|
|
- Check wallet sync status
|
|
- Verify confirmations requirement
|
|
|
|
3. **Subaddress Generation Fails**:
|
|
- Check wallet is not locked
|
|
- Verify account index exists
|
|
- Ensure RPC has wallet access
|
|
|
|
**Debug Commands**
|
|
|
|
Check wallet sync status::
|
|
|
|
curl -X POST http://127.0.0.1:18083/json_rpc -d '
|
|
{"jsonrpc":"2.0","id":"0","method":"get_height"}'
|
|
|
|
List recent transfers::
|
|
|
|
curl -X POST http://127.0.0.1:18083/json_rpc -d '
|
|
{
|
|
"jsonrpc":"2.0","id":"0","method":"get_transfers",
|
|
"params":{"in":true,"out":true,"pending":true,"failed":true}
|
|
}'
|
|
|
|
|
|
References
|
|
----------
|
|
|
|
- Monero Documentation: https://www.getmonero.org/resources/
|
|
- Monero RPC Documentation: https://www.getmonero.org/resources/developer-guides/wallet-rpc.html
|
|
- Monero Security Best Practices: https://www.getmonero.org/resources/user-guides/securely_purchase.html
|