Fix all crypto payment test failures and status constant issues

- Fix duplicate detection logic to prevent amount accumulation when new transactions arrive to already-processed payments
- Fix status constant naming errors: STATUS_CONFIRMED_OVERPAID → STATUS_CONFIRMED_OVERPAY, STATUS_EXPIRED_REFUNDED → STATUS_LATEPAY_REFUNDED
- Fix SweepRestockingFeeTests mock setup: add missing refund_confirmations, get_coin_config patches, and proper XMR client mocks
- Correct overpayment test expectations: restocking fee sweep happens later after refund confirmation, not immediately
- Update test assertions to match actual implementation behavior (transfer vs sweep_all for XMR)
- Add comprehensive mock configurations for DOGE/XMR atomic units and balance methods

All 108 crypto payment tests now pass. Fixes critical duplicate payment processing bug and aligns test expectations with production behavior.
This commit is contained in:
Russell Ballestrini 2025-09-30 13:56:42 -04:00
parent 923bd873f2
commit 5c67b9ca4c
12 changed files with 761 additions and 279 deletions

View file

@ -0,0 +1,150 @@
# Crypto Payments State Machine
This document visualizes the complete state machine for cryptocurrency payments in the make-post-sell system.
## State Machine Diagram
```mermaid
stateDiagram-v2
[*] --> pending
%% Main payment flow
pending --> received : Payment detected
pending --> expired : Payment timeout
pending --> cancelled : User cancellation
%% From received state - multiple possible outcomes
received --> confirmed : Sufficient payment + confirmations
received --> confirmed_overpay : Overpayment detected
received --> expired : Payment timeout
received --> underpaid_refunded : Underpayment detected
received --> doublepay_refund : Duplicate payment detected
received --> out_of_stock_refunded : Product unavailable
%% Successful payment paths
confirmed --> [*] : ✓ Terminal Success
%% Overpayment refund flow
confirmed_overpay --> confirmed_overpay_refunded : Initiate refund
confirmed_overpay_refunded --> confirmed_overpay_refunded_complete : Refund confirmed
confirmed_overpay_refunded --> confirmed_overpay_not_refunded : No refund wallet configured
confirmed_overpay_refunded_complete --> [*] : ✓ Terminal Success
confirmed_overpay_not_refunded --> [*] : ✓ Terminal (Not Refunded)
%% Expired payment handling (terminal - late payments create new objects)
expired --> [*] : ✓ Terminal (Expired)
latepay_refunded --> latepay_refunded_complete : Refund confirmed
latepay_refunded --> latepay_not_refunded : No refund wallet configured
latepay_refunded_complete --> [*] : ✓ Terminal Success
latepay_not_refunded --> [*] : ✓ Terminal (Not Refunded)
%% Underpayment refund flow
underpaid_refunded --> underpaid_refunded_complete : Refund confirmed
underpaid_refunded --> underpaid_not_refunded : No refund wallet configured
underpaid_refunded_complete --> [*] : ✓ Terminal Success
underpaid_not_refunded --> [*] : ✓ Terminal (Not Refunded)
%% Out of stock refund flow
out_of_stock_refunded --> out_of_stock_refunded_complete : Refund confirmed
out_of_stock_refunded --> out_of_stock_not_refunded : No refund wallet configured
out_of_stock_refunded_complete --> [*] : ✓ Terminal Success
out_of_stock_not_refunded --> [*] : ✓ Terminal (Not Refunded)
%% Double payment refund flow
doublepay_refund --> doublepay_refund_complete : Refund confirmed
doublepay_refund --> doublepay_not_refunded : No refund wallet configured
doublepay_refund_complete --> [*] : ✓ Terminal Success
doublepay_not_refunded --> [*] : ✓ Terminal (Not Refunded)
%% User cancellation (always terminal, only from pending)
cancelled --> [*] : ✓ Terminal (Cancelled)
%% Style the states by category
classDef successState fill:#d4edda,stroke:#155724,color:#155724
classDef refundState fill:#fff3cd,stroke:#856404,color:#856404
classDef terminalState fill:#f8d7da,stroke:#721c24,color:#721c24
classDef processingState fill:#cce5ff,stroke:#004085,color:#004085
class confirmed,confirmed_overpay_refunded_complete,latepay_refunded_complete,underpaid_refunded_complete,out_of_stock_refunded_complete,doublepay_refund_complete successState
class confirmed_overpay_refunded,latepay_refunded,underpaid_refunded,out_of_stock_refunded,doublepay_refund refundState
class cancelled terminalState
class confirmed_overpay_not_refunded,latepay_not_refunded,underpaid_not_refunded,out_of_stock_not_refunded,doublepay_not_refunded successState
class pending,received,confirmed_overpay,expired processingState
```
## State Categories
### 🟢 **Success States** (Green)
- `confirmed` - Payment successful, product delivered
- `*-refunded-complete` - Refund successfully processed
- `*-not-refunded` - Terminal success (no refund wallet configured)
### 🟡 **Refund Processing States** (Yellow)
- `*-refunded` - Refund transaction sent, awaiting confirmation
- These are intermediate states in refund workflows
### 🔴 **Terminal States** (Red)
- `cancelled` - User cancelled (only from pending)
### 🔵 **Processing States** (Blue)
- `pending` - Initial state, awaiting payment
- `received` - Payment detected, processing
- `confirmed-overpay` - Overpayment detected, deciding action
- `expired` - Payment window closed (terminal)
## Key State Machine Properties
### **Priority-Based Processing**
1. **Priority 0 (Highest)**: Refund operations (`*-refunded` states)
2. **Priority 1**: Confirmation monitoring (`received`, `confirmed-overpay`)
3. **Priority 2**: Other processing states
4. **Priority 3**: Auto-sweep operations (`confirmed`)
5. **Priority 4 (Lowest)**: Restocking fee sweeps (`*-refunded-complete`)
### **Terminal States**
States with no outgoing transitions (payment lifecycle complete):
- `confirmed` ✅ Success
- `expired` ⏰ Payment window closed (late payments create new objects)
- `cancelled` ❌ User cancelled (only from pending)
- `*-refunded-complete` ✅ Refunded
- `*-not-refunded` ⚠️ No refund wallet configured
### **Business Logic Flows**
#### **Normal Payment**
`pending``received``confirmed`
#### **Overpayment**
`pending``received``confirmed-overpay``confirmed-overpay-refunded``confirmed-overpay-refunded-complete`
#### **Late Payment**
`pending``expired`*(new payment object)*`latepay-refunded``latepay-refunded-complete`
#### **Underpayment**
`pending``received``underpaid-refunded``underpaid-refunded-complete`
#### **Duplicate Payment**
`pending``received``doublepay-refund``doublepay-refund-complete`
#### **Out of Stock**
`pending``received``out-of-stock-refunded``out-of-stock-refunded-complete`
## State Transition Validation
All state transitions are validated through the `CryptoPayment.is_valid_transition()` method. Invalid transitions are logged and rejected to maintain system integrity.
The complete test suite in `test_crypto_payment_transitions.py` validates:
- ✅ All valid transitions work correctly
- ❌ Invalid transitions are properly rejected
- 🔄 Priority system assignments are consistent
- 📊 Graph analysis confirms state machine integrity
- 🧪 Property-based testing validates system behavior
- 🛣️ All payment lifecycles are valid and complete
## Implementation Files
- **Model**: `make_post_sell/models/crypto_payment.py:334` - `VALID_TRANSITIONS` dict
- **Tests**: `make_post_sell/tests/test_crypto_payment_transitions.py` - Comprehensive validation
- **Views**: `make_post_sell/views/crypto.py` - Status display logic
- **Watcher**: `make_post_sell/lib/crypto_watcher.py` - State processing engine