diff --git a/docs/CRYPTO_WATCHER_FLOW.md b/docs/CRYPTO_WATCHER_FLOW.md deleted file mode 100644 index 86499d6..0000000 --- a/docs/CRYPTO_WATCHER_FLOW.md +++ /dev/null @@ -1,345 +0,0 @@ -# Crypto Watcher Mechanism - Complete Flow Documentation - -This document describes the complete flow of the crypto payment watcher system, including all paths for payment processing, duplicate detection, and refund handling. - -```mermaid -flowchart TD - A[Crypto Watcher Starts] --> B[Load Active Crypto Processors] - B --> C[For Each Processor: Scan Wallet] - - C --> D{New Transactions Found?} - D -->|No| E[Sleep 20 seconds] - D -->|Yes| F[Process Each Transaction] - - F --> G[Match Transaction to Payment by Subaddress] - G --> H{Payment Found?} - - H -->|No| I[Log: No matching payment] - H -->|Yes| J[Call process_payment] - - J --> K{Payment Status?} - - K -->|PENDING| L[First Payment Path] - K -->|RECEIVED/CONFIRMED| M[Duplicate Detection Path] - K -->|DOUBLEPAY_REFUND| N[Refund Processing Path] - - subgraph FirstPayment [First Payment Path] - L1[Add transaction amount] - L2[Update tx_hashes with txid] - L3[Update confirmations] - L4{Amount >= Expected AND Confirmations >= Required?} - L5[Status = CONFIRMED] - L6[Status = RECEIVED] - L7[Finalize Invoice - Unlock Products] - L8[Continue Monitoring] - - L1 --> L2 - L2 --> L3 - L3 --> L4 - L4 -->|Yes| L5 - L4 -->|No| L6 - L5 --> L7 - L6 --> L8 - L7 --> L8 - end - - subgraph DuplicateDetection [Duplicate Detection Path] - M1{received_amount > 0 AND new_txids?} - M2[DUPLICATE PAYMENT DETECTED] - M3[Create Duplicate Payment Records] - M4[Set status = STATUS_DOUBLEPAY_REFUND] - M5[Store tx_hashes with duplicate txid] - M6[Update original payment confirmations only] - M7[Scanner will process refunds] - - M1 -->|Yes| M2 - M2 --> M3 - M3 --> M4 - M4 --> M5 - M5 --> M6 - M6 --> M7 - end - - subgraph RefundProcessing [Refund Processing Path] - N1{PaymentRescue available?} - N2[Status = STATUS_NO_REFUND] - N3[Calculate refund amount with 9% fee] - N4[Execute refund transaction] - N5{Refund successful?} - N6[Store refund_tx_hash] - N7[Log refund failure] - N8[Monitor refund confirmations] - N9[Status remains DOUBLEPAY_REFUND] - N10{Refund confirmed?} - N11[Status = STATUS_DOUBLEPAY_REFUND_COMPLETE] - N12[Continue monitoring] - - N1 -->|No| N2 - N1 -->|Yes| N3 - N3 --> N4 - N4 --> N5 - N5 -->|Yes| N6 - N5 -->|No| N7 - N6 --> N8 - N7 --> N9 - N8 --> N10 - N10 -->|Yes| N11 - N10 -->|No| N12 - end - - L --> FirstPayment - M --> DuplicateDetection - N --> RefundProcessing - M1 -->|No| L1 - - E --> C - L8 --> E - M7 --> E - N2 --> E - N9 --> E - N11 --> E - N12 --> E - I --> E -``` - -## Complete Payment Status State Machine - -```mermaid -stateDiagram-v2 - [*] --> PENDING : Payment created - - %% Normal payment flow - PENDING --> RECEIVED : First transaction received - RECEIVED --> CONFIRMED : Sufficient confirmations + exact payment - RECEIVED --> CONFIRMED_OVERPAID : Sufficient confirmations + overpayment - - %% Terminal success states - CONFIRMED --> [*] : Products unlocked - CONFIRMED_OVERPAID --> CONFIRMED_OVERPAID_REFUNDED : Excess refunded - CONFIRMED_OVERPAID_REFUNDED --> [*] : Refund confirmed - - %% Expiration flow - PENDING --> EXPIRED : Quote expires (no payment) - RECEIVED --> EXPIRED : Quote expires (partial payment) - EXPIRED --> EXPIRED_REFUNDED : Late payment arrives + refund sent - EXPIRED_REFUNDED --> EXPIRED_REFUNDED_COMPLETE : Refund confirmed - EXPIRED_REFUNDED_COMPLETE --> [*] - EXPIRED --> [*] : No late payment - - %% Underpayment flow - RECEIVED --> UNDERPAID_REFUNDED : Quote expires + insufficient funds - UNDERPAID_REFUNDED --> UNDERPAID_REFUNDED_COMPLETE : Refund confirmed - UNDERPAID_REFUNDED_COMPLETE --> [*] - - %% Duplicate payment flow - CONFIRMED --> DOUBLEPAY_REFUND : Duplicate payment detected - CONFIRMED_OVERPAID --> DOUBLEPAY_REFUND : Duplicate payment detected - RECEIVED --> DOUBLEPAY_REFUND : Duplicate payment detected - DOUBLEPAY_REFUND --> DOUBLEPAY_REFUND_COMPLETE : Refund confirmed - DOUBLEPAY_REFUND_COMPLETE --> [*] - - %% Out of stock flow - PENDING --> OUT_OF_STOCK_REFUNDED : Product out of stock + payment received - RECEIVED --> OUT_OF_STOCK_REFUNDED : Product out of stock - CONFIRMED --> OUT_OF_STOCK_REFUNDED : Product out of stock after payment - OUT_OF_STOCK_REFUNDED --> OUT_OF_STOCK_REFUNDED_COMPLETE : Refund confirmed - OUT_OF_STOCK_REFUNDED_COMPLETE --> [*] - - %% No refund scenarios - EXPIRED --> NO_REFUND : No refund address configured - UNDERPAID_REFUNDED --> NO_REFUND : Refund failed - DOUBLEPAY_REFUND --> NO_REFUND : Refund failed - OUT_OF_STOCK_REFUNDED --> NO_REFUND : Refund failed - NO_REFUND --> NO_REFUND_COMPLETE : Manual resolution - NO_REFUND_COMPLETE --> [*] - - %% Cancellation flow - PENDING --> CANCELLED : Payment cancelled by user/system - RECEIVED --> CANCELLED : Payment cancelled with refund - CANCELLED --> [*] - - %% Status groupings for processing - state "Active Statuses (Monitored)" as ActiveGroup { - PENDING - RECEIVED - CONFIRMED - CONFIRMED_OVERPAID - NO_REFUND - } - - state "Refund Pending (Confirmation Monitoring)" as RefundGroup { - EXPIRED_REFUNDED - UNDERPAID_REFUNDED - OUT_OF_STOCK_REFUNDED - DOUBLEPAY_REFUND - } - - state "Terminal Statuses (No Processing)" as TerminalGroup { - EXPIRED - EXPIRED_REFUNDED_COMPLETE - UNDERPAID_REFUNDED_COMPLETE - CONFIRMED_OVERPAID_REFUNDED - CANCELLED - OUT_OF_STOCK_REFUNDED_COMPLETE - NO_REFUND_COMPLETE - DOUBLEPAY_REFUND_COMPLETE - } -``` - -## Status Categories and Processing Rules - -### Active Statuses (Actively Monitored) -- **PENDING**: Waiting for first payment -- **RECEIVED**: Has funds, waiting for confirmations -- **CONFIRMED**: Payment complete, products unlocked -- **CONFIRMED_OVERPAID**: Overpaid, products unlocked, excess pending refund -- **NO_REFUND**: Failed refund scenarios, manual intervention needed - -### Refund Pending (Confirmation Monitoring) -- **EXPIRED_REFUNDED**: Late payment refunded with 9% fee -- **UNDERPAID_REFUNDED**: Partial payment refunded with 9% fee -- **OUT_OF_STOCK_REFUNDED**: Out of stock, full refund (no fee) -- **DOUBLEPAY_REFUND**: Duplicate payment refunded with 9% fee - -### Terminal Statuses (No Further Processing) -- **EXPIRED**: Quote expired, no payment received -- **EXPIRED_REFUNDED_COMPLETE**: Late payment refund confirmed -- **UNDERPAID_REFUNDED_COMPLETE**: Partial payment refund confirmed -- **CONFIRMED_OVERPAID_REFUNDED**: Overpayment excess refund confirmed -- **CANCELLED**: Payment cancelled by user/system -- **OUT_OF_STOCK_REFUNDED_COMPLETE**: Out of stock refund confirmed -- **NO_REFUND_COMPLETE**: Manual resolution complete -- **DOUBLEPAY_REFUND_COMPLETE**: Duplicate payment refund confirmed - -## Key Functions and Their Responsibilities - -### Main Processing Loop -- **`crypto_watcher_main()`**: Entry point, coordinates scanning and processing -- **`process_payment()`**: Core payment processing logic -- **`scan_wallet_for_double_or_late_payments()`**: Scanner for missed/duplicate transactions - -### Duplicate Detection -- **`_create_duplicate_payment()`**: Creates separate records for duplicate transactions -- **`_should_process_late_payment()`**: Determines if a transaction should be processed - -### Payment Processing Paths - -#### 1. Normal Payment Path -```python -# New payment to fresh address -status: PENDING → RECEIVED → CONFIRMED -actions: -- Add amount to received_amount -- Update tx_hashes with transaction IDs -- Update confirmation count -- Finalize invoice when confirmed -``` - -#### 2. Duplicate Payment Path (Main Loop) -```python -# Additional payment to already-paid address -if (received_amount > 0 AND new_txids AND status != PENDING): - # Create separate duplicate records - for txid in new_txids: - duplicate = _create_duplicate_payment(original, tx, coin_type) - duplicate.status = STATUS_DOUBLEPAY_REFUND - duplicate.tx_hashes = json.dumps([txid]) - - # Update original payment confirmations only (no new amounts) - original.confirmations = calculate_from_legitimate_txs_only() -``` - -#### 3. Scanner Duplicate Processing -```python -# Scanner finds duplicate transactions -for tx in wallet_transfers: - payment = find_by_subaddress(tx) - if payment.received_amount > 0: # Duplicate - existing = find_duplicate_by_txid(tx.txid) - if not existing: - duplicate = _create_duplicate_payment(payment, tx, coin_type) - else: - duplicate = existing - - # Process refund - process_payment(request, duplicate, [tx], client=refund_client) -``` - -#### 4. Refund Processing Path -```python -# For payments with STATUS_DOUBLEPAY_REFUND -if payment.status == STATUS_DOUBLEPAY_REFUND: - if payment_rescue and payment.refund_address: - refund_amount = received_amount * 0.91 # 9% fee - result = payment_rescue.execute_refund(payment, refund_amount) - if result.success: - payment.refund_tx_hash = result.tx_hash - # Monitor for refund confirmation - else: - # Log failure, retry later - else: - payment.status = STATUS_NO_REFUND -``` - -## Infinite Duplicate Support - -The system now supports unlimited duplicate payments to the same address: - -1. **Payment #1**: Normal processing → CONFIRMED -2. **Payment #2**: Main loop creates duplicate record #1 → Scanner processes refund #1 -3. **Payment #3**: Main loop creates duplicate record #2 → Scanner processes refund #2 -4. **Payment #4**: Main loop creates duplicate record #3 → Scanner processes refund #3 -5. **etc...** - -Each duplicate gets: -- Its own `CryptoPayment` record with unique ID -- Status: `STATUS_DOUBLEPAY_REFUND` -- Individual refund processing -- Separate entry in crypto payments history - -## Error Handling and Edge Cases - -### Double Refund Prevention -- Scanner checks for existing duplicate records by transaction ID -- Only one duplicate record created per transaction -- Refund only processed once per duplicate - -### Confirmation Handling for Duplicates -- Original payment confirmations calculated from legitimate transactions only -- Duplicate transactions don't affect original payment confirmation count -- Original payment can move RECEIVED → CONFIRMED despite having duplicates - -### Missing Transaction Scenarios -- Scanner catches transactions missed by main loop -- Late payments to expired quotes handled separately -- Blockchain reorganizations handled through re-scanning - -## Database Schema Impact - -### CryptoPayment Table Fields Used -- `id`: Unique payment identifier -- `status`: Payment status (see status flow above) -- `received_amount`: Amount received for this specific payment -- `tx_hashes`: JSON array of transaction IDs -- `refund_tx_hash`: Transaction ID of refund (for duplicates) -- `refund_address`: Where to send refund -- `subaddress_index`: Unique address identifier - -### Query Patterns -```sql --- Find payment by subaddress -SELECT * FROM mps_crypto_payment -WHERE coin_type = ? AND account_index = ? AND subaddress_index = ? - --- Find duplicate by transaction ID -SELECT * FROM mps_crypto_payment -WHERE status = 'doublepay-refund' -AND tx_hashes LIKE '%"transaction-id-here"%' - --- Get payment history -SELECT * FROM mps_crypto_payment -WHERE user_id = ? -ORDER BY created_timestamp DESC -``` - -This system ensures that every payment (original and all duplicates) is tracked, processed, and appears in the user's payment history while preventing financial loss through proper duplicate detection and single-refund-per-transaction guarantees. \ No newline at end of file