Delete CRYPTO_WATCHER_FLOW.md
This commit is contained in:
parent
29baa1bb73
commit
86fdab0f3a
1 changed files with 0 additions and 345 deletions
|
|
@ -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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue