# Crypto Payments State Machine

This document visualizes the complete state machine for cryptocurrency payments in the make-post-sell system, including semantic state groups, business logic rules, and implementation details.

## State Machine Diagram

```mermaid
stateDiagram-v2
    [*] --> pending
    [*] --> doublepay-refunded : Duplicate payment detected
    [*] --> latepay-refunded: Late payment detected
    
    %% Main payment flow
    pending --> received : Payment detected in mempool
    pending --> expired : Payment timeout (never received)
    pending --> cancelled : User cancellation
    
    %% From received state - multiple possible outcomes
    %% NOTE: received payments CANNOT expire (detected in mempool, confirmations tracking)
    received --> confirmed : Sufficient payment + confirmations
    received --> confirmed-overpay : Overpayment detected
    received --> underpaid-refunded : Underpayment detected
    received --> out-of-stock-refunded : Product unavailable
    
    %% Successful payment paths
    confirmed --> confirmed-complete : Swept to cold storage
    confirmed-complete --> [*] : ✓ 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 Success (Not Refunded)
    
    %% Expired payment handling (terminal - late payments create new objects)
    expired --> [*] : ✓ Terminal Failed (Expired)
    
    %% Late payment objects (created separately for payments after expiration)
    latepay-refunded --> latepay-refunded-complete : Refund confirmed
    latepay-refunded --> latepay-not-refunded : No refund wallet configured
    latepay-refunded-complete --> [*] : ✓ Terminal Failed (Refund Complete)
    latepay-not-refunded --> [*] : ✓ Terminal Failed (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 Failed (Refund Complete)
    underpaid-not-refunded --> [*] : ✓ Terminal Failed (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 Failed (Refund Complete)
    out-of-stock-not-refunded --> [*] : ✓ Terminal Failed (Not Refunded)
    
    %% Double payment refund flow
    doublepay-refunded --> doublepay-refunded-complete : Refund confirmed
    doublepay-refunded --> doublepay-not-refunded : No refund wallet configured
    doublepay-refunded-complete --> [*] : ✓ Terminal Failed (Refund Complete)
    doublepay-not-refunded --> [*] : ✓ Terminal Failed (Not Refunded)
    
    %% User cancellation (always terminal, only from pending)
    cancelled --> [*] : ✓ Terminal Failed (Cancelled)
    
    %% Style the states by semantic category
    classDef successState fill:#d4edda,stroke:#155724,color:#155724
    classDef initialWaitingState fill:#e7f3ff,stroke:#0056b3,color:#0056b3
    classDef refundState fill:#fff3cd,stroke:#856404,color:#856404
    classDef failedState fill:#f8d7da,stroke:#721c24,color:#721c24
    classDef processingState fill:#cce5ff,stroke:#004085,color:#004085
    
    %% Successful payments (customer received product)
    class confirmed,confirmed-complete,confirmed-overpay-refunded-complete,confirmed-overpay-not-refunded successState
    
    %% Initial/waiting states (entry points that don't come from 'received')
    class pending,latepay-refunded,doublepay-refunded initialWaitingState
    
    %% Active refund processing states
    class confirmed-overpay-refunded,underpaid-refunded,out-of-stock-refunded refundState
    
    %% Failed payments (customer did not receive product)
    class expired,cancelled,latepay-refunded-complete,latepay-not-refunded,underpaid-refunded-complete,underpaid-not-refunded,out-of-stock-refunded-complete,out-of-stock-not-refunded,doublepay-refunded-complete,doublepay-not-refunded failedState
    
    %% Processing states
    class received,confirmed-overpay processingState
```

## Semantic State Groups

The state machine uses semantic groups to categorize states by business logic purpose. These groups determine invoice handling, priority processing, and system behavior.

### 🔵 **Initial/Waiting States** (Light Blue)
Entry point states that don't transition from `received` - they represent the start of payment flows:

- **`pending`** - Initial state for new payment requests
- **`latepay-refunded`** - Initial state for late payment objects (payments received after expiration)
- **`doublepay-refunded`** - Initial state for duplicate payment objects (separate payment instances)

**Business Logic**: These states represent separate payment flows and are processed with Priority 0-2 depending on their nature.

### 🟢 **Successful Payment States** (Green)
Customer received their product - invoices are preserved:

- **`confirmed`** - Normal successful payment (exact amount, confirmed)
- **`confirmed-complete`** - Confirmed payment that has been swept to cold storage
- **`confirmed-overpay-refunded-complete`** - Overpaid, customer got product + refund
- **`confirmed-overpay-not-refunded`** - Overpaid, customer got product, no refund wallet configured

**Business Logic**: `is_successful_payment() = True`, `should_keep_invoice() = True`

### 🔴 **Failed Payment States** (Red)  
Customer did not receive product - invoices are deleted:

- **`expired`** - Payment window expired before any blockchain detection
- **`cancelled`** - User cancelled payment (only from pending)
- **`*-refunded-complete`** - Failed payments with completed refunds
- **`*-not-refunded`** - Failed payments with no refund wallet configured

**Business Logic**: `is_failed_payment() = True`, `should_keep_invoice() = False`

### 🟡 **Refund Processing States** (Yellow)
Active refund workflows - intermediate states:

- **`confirmed-overpay-refunded`** - Overpayment refund in progress (customer got product)
- **`underpaid-refunded`** - Underpayment refund in progress  
- **`out-of-stock-refunded`** - Out of stock refund in progress
- **Note**: `latepay-refunded` and `doublepay-refunded` are Initial/Waiting states, not regular refund processing

**Business Logic**: Priority 0 processing (highest), actively monitored for confirmation

### 🔵 **Processing States** (Blue)
Active payment processing states:

- **`received`** - Payment detected on blockchain, being processed
- **`confirmed-overpay`** - Overpayment confirmed, deciding refund action

**Business Logic**: Priority 1-3 processing, confirmation monitoring

## Critical State Machine Rules

### **Rule 1: Blockchain Detection is Irreversible**
- ❌ **INVALID**: `received → expired` 
- ✅ **VALID**: `pending → expired`

**Rationale**: Once a payment is detected on the blockchain (`received`), it cannot "expire" - it already exists. Only payments that never arrive can expire.

### **Rule 2: Past-Tense Naming Convention**
All status constants use past-tense naming for consistency:
- ✅ `STATUS_DOUBLEPAY_REFUNDED` (correct)
- ❌ `STATUS_DOUBLEPAY_REFUND` (incorrect - not past tense)

### **Rule 3: Entry Points vs Transitions**
Some states are entry points for new payment objects, not transitions from existing payments:
- `pending` - Entry point for new payments
- `latepay-refunded` - Entry point for late payment objects (created after expiration)
- `doublepay-refunded` - Entry point for duplicate payment objects

### **Rule 4: Invoice Preservation Logic**
```python
should_keep_invoice() = is_successful_payment()
```
- **Keep**: Successful payments (customer got product)
- **Delete**: Failed payments (customer did not get product)

## Priority-Based Processing System

The crypto watcher processes payments by priority to ensure proper fund flow and customer service:

### **Priority 0 (Highest): Customer Refunds** 
- `doublepay-refunded`, `latepay-refunded`, `underpaid-refunded`, `out-of-stock-refunded`
- **Rationale**: Customer service is highest priority

### **Priority 1: New Incoming Payments**
- `received`
- **Rationale**: Process new money quickly for customer experience

### **Priority 2: Other Processing**
- `pending`, monitoring states, intermediate states
- **Rationale**: General processing tasks

### **Priority 3: Auto-Sweep to Shop Owner**
- `confirmed`, `confirmed-overpay`
- **Rationale**: Move confirmed funds to shop owner

### **Priority 4 (Lowest): Restocking Fee Sweeps**
- `*-refunded-complete` states
- **Rationale**: Most dangerous operation, requires high confirmations, done last

## Business Logic Flows

### **Normal Payment Flow**
```
pending → received → confirmed → confirmed-complete ✅
```
Customer pays exact amount, gets product, invoice kept, funds swept to cold storage.

### **Overpayment Flow**
```
pending → received → confirmed-overpay → confirmed-overpay-refunded → confirmed-overpay-refunded-complete ✅
```
Customer overpays, gets product, gets refund, invoice kept.

### **Late Payment Flow**
```
Original: pending → expired ❌
New object: latepay-refunded → latepay-refunded-complete ❌  
```
Original payment expires. Late payment creates new object, gets refunded, invoice deleted.

### **Underpayment Flow**
```
pending → received → underpaid-refunded → underpaid-refunded-complete ❌
```
Customer pays too little, gets refund, no product, invoice deleted.

### **Duplicate Payment Flow**
```
Original: pending → received → confirmed ✅
Duplicate: doublepay-refunded → doublepay-refunded-complete ❌
```
First payment succeeds, duplicate creates separate object and gets refunded.

### **Out of Stock Flow**
```
pending → received → out-of-stock-refunded → out-of-stock-refunded-complete ❌
```
Product unavailable, customer gets refund, no product, invoice deleted.

### **Cancellation Flow**
```
pending → cancelled ❌
```
User cancels before payment detected, invoice deleted.

## Terminal States Analysis

**Successful Terminals** (keep invoice):
- `confirmed` - Normal success (awaiting sweep)
- `confirmed-complete` - Normal success + swept to cold storage
- `confirmed-overpay-refunded-complete` - Overpaid + refunded
- `confirmed-overpay-not-refunded` - Overpaid, no refund wallet

**Failed Terminals** (delete invoice):
- `expired` - Never paid
- `cancelled` - User cancelled  
- `*-refunded-complete` - Failed + refunded
- `*-not-refunded` - Failed, no refund wallet

## State Transition Validation

All transitions are validated via `CryptoPayment.is_valid_transition()`:

```python
VALID_TRANSITIONS = {
    STATUS_PENDING: [STATUS_RECEIVED, STATUS_EXPIRED, STATUS_CANCELLED],
    STATUS_RECEIVED: [
        STATUS_CONFIRMED,
        STATUS_CONFIRMED_OVERPAY,
        # NOTE: STATUS_EXPIRED removed - received payments cannot expire
        STATUS_UNDERPAID_REFUNDED,
        STATUS_DOUBLEPAY_REFUNDED,
        STATUS_OUT_OF_STOCK_REFUNDED,
    ],
    STATUS_CONFIRMED: [STATUS_CONFIRMED_COMPLETE],  # Can transition to complete after sweep
    STATUS_CONFIRMED_COMPLETE: [],  # Terminal - confirmed and swept
    # ... additional transitions
}
```

**Property Testing**: The complete test suite validates:
- ✅ All valid transitions work correctly
- ❌ Invalid transitions are properly rejected  
- 🔄 Priority system assignments are consistent
- 📊 Graph analysis confirms no orphaned states or cycles
- 🧪 Property-based testing validates invariants
- 🛣️ All payment lifecycles reach valid terminal states

## Implementation Details

### **Core Files**
- **Model**: `make_post_sell/models/crypto_payment.py`
  - Line 55: `INITIAL_WAITING_STATUSES` - New semantic group
  - Line 62: `SUCCESSFUL_PAYMENT_STATUSES` - Keep invoices
  - Line 70: `FAILED_PAYMENT_STATUSES` - Delete invoices  
  - Line 386: `VALID_TRANSITIONS` - State transition rules
  - Line 488: `is_successful_payment()` - Business logic helper
  - Line 522: `is_initial_waiting_state()` - New helper method

- **Tests**: `make_post_sell/tests/test_crypto_payment_transitions.py`
  - 21 comprehensive test methods
  - Property-based validation
  - Graph analysis and reachability testing
  - Priority system validation

- **Watcher**: `make_post_sell/lib/crypto_watcher.py`
  - Priority-based processing engine
  - State transition enforcement
  - Invoice deletion logic

- **Views**: `make_post_sell/views/crypto.py`
  - Status display logic
  - User-facing state information

### **Database Schema**
- Payments stored with `status` column containing string constants
- `invoice_id` nullable for proper invoice handling
- `created_timestamp` and `updated_timestamp` for audit trails

### **Testing Coverage**
- **155 total crypto payment tests** all passing
- Unit tests for individual state transitions
- Integration tests for payment flows
- Property-based tests for state machine invariants
- Functional tests for end-to-end payment processing

## Debugging and Monitoring

### **Log Messages**
All state transitions generate structured logs:
```
Payment {id} state transition: {old_status} → {new_status} (context: {context})
```

### **Invalid Transition Handling**
```python
if not payment.is_valid_transition(new_status):
    logger.error(f"Invalid state transition for payment {payment.id}: {payment.status} → {new_status}")
    return False
```

### **Common Issues**
1. **Invalid `received → expired`**: Check if payment was properly detected on blockchain
2. **Priority conflicts**: Verify processing order matches business requirements  
3. **Invoice handling**: Ensure successful payments keep invoices, failed payments delete them
4. **Naming inconsistency**: All status constants must use past-tense naming

This state machine provides a robust, well-tested foundation for cryptocurrency payment processing with clear semantic boundaries and validated state transitions.
