- Add scan_wallet_for_late_payments() that checks all wallet transactions
- Match transactions to payments by address (DOGE) or subaddress (XMR)
- Process late payments to expired/cancelled quotes automatically
- Add database indexes for efficient payment lookups
- Add comprehensive unit and integration tests
This allows the system to detect and refund payments that arrive after
quotes expire, without actively monitoring every expired payment forever.
- Fix overpayment status transition: set to confirmed-overpaid immediately when detected
- Update status styling: move checkmarks to left, make overpaid-refunded green
- Add invoice links for confirmed payments on crypto quote pages
- Redesign invoice page: cleaner layout, remove redundant fields, move crypto details to bottom
- Update crypto history: confirmed-overpaid-refunded shows View Invoice button
- Remove payment address from invoice for privacy
When overpayment is detected, immediately set status to 'confirmed-overpaid'
regardless of whether the initial refund attempt succeeds. Only transition
to 'confirmed-overpaid-refunded' when refund actually executes successfully.
This ensures payments show the correct status and allows the refund monitoring
system to retry failed refunds when sufficient confirmations are available.
Enhanced logging to clearly distinguish between incoming payment confirmations
and refund transaction confirmations:
- Add "INCOMING" prefix for original payment confirmation updates
- Add "REFUND" prefix for refund transaction confirmation updates
- Include confirmation counts in processing logs (incoming:X/Y, refund:Z)
- Show both confirmation types in status transition logs
- Add "REFUND FULLY CONFIRMED" prefix for completion messages
- Include current confirmation counts in debug messages
- Truncate long transaction hashes for readability
This eliminates confusion between the two separate confirmation tracking
systems and makes crypto payment processing much easier to debug.
Add automatic cleanup of invoices for failed/cancelled crypto payments
while preserving successful transaction records:
- Add delete_invoice_for_terminal_state() function to crypto_watcher.py
- Delete invoices for all terminal states except confirmed/overpaid
- Add STATUS_NO_REFUND to TERMINAL_STATUSES for proper cleanup
- Comprehensive unit and integration tests (22 tests, all passing)
- Graceful error handling for deletion failures
- Database safety guards against deleting Stripe invoices
This ensures failed crypto transactions don't accumulate invoice records
while maintaining audit trail through crypto_payment records.
- Display 'Payment received\!' when payment is first detected
- Show 'Purchase completed\!' when confirmed (with 'Download now\!' for digital products)
- Add specific messages for overpayments, refunds, cancellations and expired quotes
- Track status transitions in session to show messages only on status changes
- Messages will appear on redirect to /u/purchases or /u/crypto-quotes pages
- Make 'Let's go shopping\!' button green on empty cart page
- Change 'Start Shopping' button to blue and link to home page on crypto history
- Remove unnecessary 'No refund address configured' warning from checkout
- Update crypto checkout to link to View Purchases for confirmed payments
- Update crypto checkout to link to View Crypto History for terminal states
- Redirect to /u/purchases when payment is confirmed
- Add missing user and shop parameters to CryptoPayment constructor calls in tests
- Resolves TypeError: missing required positional arguments 'user' and 'shop'
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add terminal -complete status enums for all refund types
- Update crypto watcher to transition refunds to complete status at 10+ confirmations
- Fix cancelled payment quote viewing with proper access control and USD calculation
- Update status mappings and templates to support complete statuses
- Move payment status display to breakdown section in checkout template
- Add View Quote buttons for cancelled and refunded payments
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
STATUS DISPLAY IMPROVEMENTS:
- Set payment status to underpaid-refunded/expired-refunded immediately when refund is determined
- Status now reflects refund eligibility rather than waiting for refund execution
- Added confirmed-overpaid-refunded status mapping for UI display
PAYMENT HISTORY ENHANCEMENTS:
- Added USD conversion display for received amounts using locked exchange rate
- Fixed TypeError by properly handling float * Decimal multiplication in templates
- Added refund_tx_hash to payment data for refund status differentiation
- Show "Refund pending" vs "Refund completed" messages based on refund_tx_hash presence
USER EXPERIENCE IMPROVEMENTS:
- Clear messaging about 10-confirmation requirement for refunds
- Immediate status feedback when underpayment/expired payment is detected
- Proper distinction between refund eligibility and refund completion
- Enhanced refund status explanations with restocking fee information
This ensures users see accurate payment status immediately rather than confusing
"Payment Received" labels when their payment is actually being refunded.
REFUND SAFETY IMPROVEMENTS:
- Refunds now require 10+ confirmations on incoming payment before execution
- Added REFUND_PENDING_STATUSES for continued confirmation monitoring
- Refund-pending payments stay in main queue until fully confirmed
- Automatic retry of failed refunds once confirmations are met
NEW STATUS TRANSITIONS:
- confirmed-overpaid → confirmed-overpaid-refunded (when refund confirms)
- Added refund_confirmations column to track outgoing refund TX status
ENHANCED MONITORING:
- Dual confirmation tracking: incoming payments + outgoing refunds
- Refund retry queue detects when blocked refunds can proceed
- Separate confirmation-only updates for refund-pending payments
- Comprehensive logging for refund delays and confirmations
SECURITY BENEFITS:
- Prevents refunding payments subject to blockchain reorganizations
- Eliminates double-spend attack vectors on underpaid/expired payments
- Ensures refunds only sent for truly irreversible incoming payments
- Maintains customer protection while maximizing merchant security
This resolves the fundamental security issue where refunds could be sent
for payments that might later be reversed due to insufficient confirmations.
- Fix AttributeError by changing payment.crypto_type to payment.coin_type
- Fix Decimal * float error by using Decimal("1e12") instead of 1e12
- Add account-specific balance checking using payment.account_index
- Add comprehensive logging for refund attempts and wallet balance checks
- Update execute_refund to accept payment object for account context
- Ensure refunds are sent from correct account that received the funds
This resolves GroupR's underpayment refund issue and improves the reliability
of the crypto payment rescue system.
- Fix AttributeError: 'CryptoPayment' object has no attribute 'crypto_type'
Changed payment.crypto_type to payment.coin_type in crypto_payment_rescue.py
This was causing crypto watcher to crash on underpayment processing
- Make CryptoPayment.invoice_id nullable for cancelled payments
Updated model and recreated table to allow NULL invoice_id
- Add user_id and shop_id columns to CryptoPayment
Ensures cancelled payments can be filtered by user/shop for history
- Update crypto_quotes_history to show cancelled payments
Uses direct user_id/shop_id filtering instead of JOIN with invoice
- Update crypto_cancel to properly clear invoice reference
Sets invoice_id=None before deleting invoice to avoid foreign key errors
Fixes critical crypto watcher crash that was preventing payment processing
- Use two-column grid: QR code on left, all payment info on right
- Move status, expiry countdown, and payment ID into right column
- Keep payment address and amount at top of right column
- Maintains visual hierarchy with all payment details together
- Buttons remain below in separate grid
- Change from two-column (auto 1fr) to single column (1fr) grid
- Center QR code at top with inline-block display
- Payment instructions below in full width
- Prevents content from overflowing parent grid bounds
- Update JavaScript selector to match new grid structure
- Put QR code and payment instructions in a grid layout
- QR code takes fixed space on left, payment info expands on right
- Use grid-template-columns: auto 1fr for optimal spacing
- Update JavaScript to handle new grid structure when hiding elements
- Add mps-button-red class with #bc2131 color and 0.8 opacity
- Replace inline button styles with CSS classes on crypto checkout
- Use mps-button-green for copy/wallet buttons
- Use mps-button-red for cancel button
- Fix TypeError by converting Decimal fee_buffer to float
- Update JavaScript invoice link to use mps-button-blue class
- Use same fee estimation logic on quote display as during payment creation
- Call estimate_monero_fee_for_quote() for XMR to get doubled fee
- Call estimate_dogecoin_fee_for_quote() for DOGE to get doubled fee
- Fallback to doubled settings value for other coins
- Ensures "Processing Fee (inbound + outbound)" shows correct doubled amount
- Replace flexbox layout with CSS Grid for header section
- Add align-items: start for proper grid alignment
- Add justify-self: end for button positioning
- Add empty div placeholder when no received amount to maintain grid structure
- Ensure all layouts use CSS Grid for consistency
- Add STATUS_NO_REFUND constant to replace STATUS_OUT_OF_STOCK_NO_REFUND
- Add REFUND_REDIRECT_STATUSES enum for JavaScript redirect logic
- Update crypto watcher to set STATUS_NO_REFUND for all no-refund scenarios:
- Expired payments without refund address
- Underpaid payments without refund address
- Out of stock payments without refund address
- Pass refund_redirect_statuses enum from backend to frontend
- Update JavaScript to use enum for crypto quotes redirect logic
- Enhance crypto quotes history to show detailed refund reasons
- Update status display labels and templates
- Add 3-second delay redirect to /cart when quote expires while user is on page
- Provides clear navigation path after expiry warning message
- Prevents users from staying on expired quote pages
- Add shop_id filtering to crypto_quotes_history view
- Only show payments for the current shop context
- Maintains user privacy by filtering cross-shop payments
- Update Monero fee estimation to double the fee (customer pays for both inbound + outbound)
- Update Dogecoin fee estimation to double the fee (customer pays for both inbound + outbound)
- Apply doubling to both dynamic RPC estimates and fallback hardcoded fees
- Update UI to show 'Processing Fee (inbound + outbound)' instead of 'Transaction Fee Buffer'
- Customer now fully covers all transaction processing costs for complete payment flow
- Sweep operations still use single fee estimates since they only do one transaction
- Add redirect logic when status changes from non-confirmed to confirmed
- Only redirect when detected via JavaScript polling, not when browsing to already-confirmed quote
- Uses existing lastKnownStatus tracking to detect legitimate status changes
- 2 second delay to show confirmation message before redirect
- Fixes regression where payments stayed on quote page after confirmation
- Remove pooled_sweep logic from both Monero and Dogecoin sweep functions
- Each payment now swept individually for better accounting and audit trail
- Insufficient balance now returns False to retry later instead of fake pooled_sweep
- Update all tests to expect new behavior (False for insufficient balance)
- Update documentation to reflect 1:1 payment-to-sweep mapping
- Add link to refund address configuration in crypto checkout template
- All crypto watcher tests now passing with new individual sweep logic
- Apply <strong> tags to both labels including the colon for consistency
- Matches the formatting of other payment warning items like 'Overpayment:' and 'Underpayment:'
- Apply conditional font-weight: bold only when status \!= 'out-of-stock-no-refund'
- This makes the out-of-stock-no-refund status appear less emphasized since no refund was possible
- Add fallback to check all account transfers when subaddress filter returns no results
- This helps detect mempool transactions that may not immediately appear in subaddress-filtered queries
- Include both 'in' and 'pool' transfers from get_transfers RPC call
- Filter results to match the specific subaddress we're monitoring
- Addresses issue where mempool transactions are visible in wallet but not detected by watcher
- Add estimate_monero_fee_for_quote() using test transfer with do_not_relay
- Add estimate_dogecoin_fee_for_quote() using estimatesmartfee RPC
- Update Monero quote creation to use dynamic fees instead of hardcoded 0.0001 XMR
- Update Dogecoin quote creation to use dynamic fees instead of hardcoded 0.01 DOGE
- Maintains fallback to hardcoded fees if RPC calls fail
- Should provide more accurate quotes and reduce dust further
- Monero: Use test transfer with do_not_relay=true for exact fee calculation
- Dogecoin: Use estimatesmartfee RPC for current network fee rates
- Replaces hardcoded fee estimates (0.0001 XMR, min_sweep_balance DOGE)
- Should reduce dust amounts by using more accurate fees
- Maintains fallback to hardcoded fees if RPC calls fail
- Remove automatic redirect when payment is confirmed - users must click link
- Add 'Crypto Payment History' link to user settings page
- Users can now view all their crypto payment attempts at /u/crypto-quotes