- 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
- Change from sweep_all to sweep_single to only sweep funds from specific subaddress
- Prevents sweeping funds from other payments in the same account
- Each payment already uses its own subaddress for proper isolation
- Fix critical bug where payments were incorrectly marked as 'swept' when funds were still locked
- Auto-sweep now properly retries until funds unlock (after Monero's 10-block lock time)
- Fix test expectation for expired-refunded status (hyphen not underscore)
When a crypto payment is cancelled, delete the associated invoice and
line items since no actual purchase occurred. Keep the crypto_payment
record for transaction history and audit trails.
This prevents cancelled quotes from cluttering user purchase history.
When a crypto quote is cancelled or becomes non-pending, completely
remove the QR code and payment instructions (amount + address) instead
of just disabling them. This provides cleaner UI for cancelled quotes.
- Add specific messaging for out-of-stock-refunded status (full refund, no fee)
- Add specific messaging for out-of-stock-no-refund status
- Add out-of-stock item to refund policy lists
- Left-align QR code instead of centering it
- Replace old insecure qrcodejs (v1.0.0 from 2013) with QRious v4.0.2 (2017)
- Update crypto checkout template to use QRious API instead of old QRCode.js
- QRious uses canvas element and modern security practices
- Add missing 'refund_amount' and 'reason' fields to test mocks
- Update status expectation from 'confirmed_overpaid' to 'confirmed-overpaid'
to match dash-based enum format