Commit graph

375 commits

Author SHA1 Message Date
d92d940a44 Remove '💰 Quote Details' heading 2025-09-24 18:15:59 -04:00
633eabfe15 Reorganize crypto checkout template layout
- Move Quote Details section up closer to payment information
- Remove "⚠️ Payment Information" heading
- Keep quote details well-styled for clarity
- Improve visual flow of checkout page
2025-09-24 18:14:42 -04:00
ddab2fadf9 Fix doubled fee display on crypto quote page
- 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
2025-09-24 18:12:20 -04:00
d579af10a9 Remove 'You can start a new checkout from your cart' text from expired quote message 2025-09-24 18:01:06 -04:00
bff5fd49aa Use proper mps-button-small class instead of inline CSS for buttons 2025-09-24 16:58:13 -04:00
506a88faa0 Make View Quote and View Invoice buttons smaller with form-style CSS 2025-09-24 16:57:29 -04:00
2ec9c5fc74 Convert crypto quotes history to use CSS Grid consistently
- 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
2025-09-24 16:55:11 -04:00
eff2808371 Change 'View Payment' to 'View Quote' for pending/received crypto payments 2025-09-24 16:50:33 -04:00
7303ad570f Replace out-of-stock-no-refund with generic no-refund status
- 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
2025-09-24 16:44:18 -04:00
df372a5ea1 Redirect to cart when quote expires on page
- 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
2025-09-24 16:30:06 -04:00
f25404eac3 Filter crypto payment history by shop
- 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
2025-09-24 16:28:30 -04:00
3de1abdd7b Remove target='_blank' from crypto refund address configuration links
- XMR and DOGE refund address setup links now open in same window
- Improves user experience by not opening unwanted new tabs/windows
2025-09-24 16:23:12 -04:00
26c63010ee Apply black formatting to crypto files 2025-09-24 16:13:42 -04:00
4da524965f Double fee estimates to cover both inbound and outbound transaction costs
- 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
2025-09-24 16:10:57 -04:00
cb606256ce Restore automatic redirect on payment confirmation via JavaScript polling
- 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
2025-09-24 16:06:43 -04:00
c3c05796da Remove pooled sweep behavior and implement individual payment sweeping
- 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
2025-09-24 16:03:50 -04:00
de757fdf76 Add bold formatting to 'Out of stock:' and 'Wrong address:' in both refund sections
- Apply <strong> tags to both labels including the colon for consistency
- Matches the formatting of other payment warning items like 'Overpayment:' and 'Underpayment:'
2025-09-24 15:49:07 -04:00
bffc690ecd Remove bold formatting from 'Out of stock:' text in payment warning
- Change '<strong>Out of stock:</strong>' to 'Out of stock:'
- Makes text consistent with other warning items that are not bold
2025-09-24 15:44:48 -04:00
1b0932e8e0 Simplify late payment warning text
- Change 'Late payments after X minutes are kept' to 'Late payments are kept'
- Removes dynamic time calculation and makes message clearer
2025-09-24 15:44:11 -04:00
4d1cddd544 Remove bold formatting from 'Out of Stock' status when no refund address configured
- 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
2025-09-24 15:42:57 -04:00
d292ab88e2 Apply black formatting to crypto files 2025-09-24 15:40:32 -04:00
d3f2c1caa4 Fix Monero mempool detection in crypto watcher
- 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
2025-09-24 15:37:54 -04:00
fa8ca79988 Use dynamic fee estimation for crypto quote creation
- 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
2025-09-24 15:32:42 -04:00
87471f2290 Implement dynamic fee estimation for crypto payments
- 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
2025-09-24 15:28:28 -04:00
e4990a5462 Document Monero RPC get_transfers unlocked field defect
- Add comprehensive documentation of RPC inconsistency
- Include symptoms, impact, workarounds, and references
- Establishes framework for documenting future Monero RPC issues
2025-09-24 15:03:31 -04:00
e9e6aa920b Fix Jinja2 template error - replace moment() with server-side timestamp formatting 2025-09-24 14:34:41 -04:00
1cce8c679e Fix AttributeError: use shop.name instead of shop.display_name 2025-09-24 14:31:36 -04:00
03683d55f5 Remove auto-redirect from crypto payment page and add payment history link
- 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
2025-09-24 14:30:49 -04:00
76c804a3ac Fix sweep logic to use subaddress isolation
- 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
2025-09-24 13:40:36 -04:00
4796d83eae Fix auto-sweep bug for locked Monero funds
- 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)
2025-09-24 13:09:38 -04:00
13eb2abbb2 user experience
modified:   CLAUDE.md
	modified:   make_post_sell/lib/crypto_watcher.py
	modified:   make_post_sell/models/invoice.py
	modified:   make_post_sell/routes.py
	modified:   make_post_sell/scripts/alembic/versions/5bbb5df5bf1b_add_refund_tracking_columns_to_crypto_.py
	modified:   make_post_sell/templates/crypto_checkout.j2
	new file:   make_post_sell/templates/crypto_quotes_history.j2
	modified:   make_post_sell/views/cart.py
	modified:   make_post_sell/views/crypto.py
2025-09-24 12:49:09 -04:00
b352430b63 Delete invoice when crypto payment is cancelled
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.
2025-09-24 11:53:31 -04:00
2c7dd8e6ca Remove QR code and payment instructions when quote is cancelled
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.
2025-09-24 11:51:23 -04:00
7879816143 Remove bold formatting from 'Full refund' text
Remove strong tags from 'full refund' text in out-of-stock messaging
for consistent formatting.
2025-09-24 11:46:40 -04:00
6fa9eed4c9 Update crypto checkout for out-of-stock refund scenarios and left-align QR code
- 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
2025-09-24 11:46:02 -04:00
444f9d2d5f Move QR code above payment amount text
Position QR code directly above the 'Send exactly X XMR to this address'
text for better visual flow and easier wallet scanning.
2025-09-24 11:43:56 -04:00
93b807aab9 Add modern QR code library and update crypto checkout template
- 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
2025-09-24 11:40:20 -04:00
5dc9b0d1bb Add missing fee_amount field to PaymentRescue test mock
The real PaymentRescue.handle_expired_payment() method returns fee_amount
but the test mock was missing this field, causing KeyError in tests.
2025-09-24 11:39:34 -04:00
4a3bf49c24 Fix crypto watcher tests after enum changes and refund tracking
- 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
2025-09-24 11:29:23 -04:00
d4d1ca4bdd Fix UnboundLocalError by removing local time import
The local 'import time' inside a function was shadowing the module-level
time import, causing UnboundLocalError in crypto watcher tests. Use the
existing module-level time import instead.
2025-09-24 10:20:35 -04:00
a2d471e4e8 Add database migration for crypto payment refund tracking columns
Adds refund_reason, refund_tx_hash, and refund_amount columns to the
mps_crypto_payment table to enable comprehensive tracking of refund
operations for out-of-stock scenarios and payment error handling.
2025-09-24 09:57:00 -04:00
c4d9192540 Improve crypto payment handling and out-of-stock refunds
- Add proper inventory checking before crypto payment completion
- Implement sequential (FIFO) crypto payment processing to prevent race conditions
- Add comprehensive out-of-stock refund handling with two statuses:
  - STATUS_OUT_OF_STOCK_REFUNDED: Full refund to customer (no restocking fee)
  - STATUS_OUT_OF_STOCK_NO_REFUND: Sweep to shop when no refund address
- Use sweep_all with subaddr_indices for Monero to ensure complete fund recovery
- Use sendtoaddress with subtractfeefromamount for Dogecoin fee handling
- Add refund tracking fields (refund_reason, refund_tx_hash, refund_amount)
- Update MONERO.rst with subaddress isolation and refund processing documentation
- Ensure action buttons are removed for non-pending crypto quotes to prevent double payments
2025-09-24 09:35:07 -04:00
663c0e9546 Add refund address guards and fix sweep security
- Guard all refund processing with refund_address checks to avoid unnecessary loops
- Replace dangerous sweep_all with exact amount transfers
- Use transfer() with specific amounts instead of sweeping everything
- Prevents stealing funds from other concurrent payments in same account
- Only process refunds when customer has configured a refund address

Performance: Skip expensive refund calculations when no refund address exists
Security: Each payment only touches its own calculated amounts (91% + 9%)
2025-09-23 18:40:10 -04:00
326c79fbda Track restocking fee sweeps separately from refunds
- Customer refunds tracked in refund_* fields (amount, tx_hash, reason)
- Restocking fees tracked in swept_* fields (amount, tx_hash, timestamp)
- Provides complete audit trail: received = refund_amount + swept_amount
- Shop owners can now see exactly how much was collected in restocking fees

For expired payments with restocking fee:
1. First transaction: 91% refunded to customer
2. Second transaction: 9% swept to shop's cold wallet

This gives full transparency into both sides of the refund process.
2025-09-23 18:34:37 -04:00
2d5c2543c9 Use dashes instead of underscores in crypto payment status enums
Change status values from underscore_separated to dash-separated format:
- confirmed_overpaid → confirmed-overpaid
- expired_refunded → expired-refunded
- underpaid_refunded → underpaid-refunded
- out_of_stock_refunded → out-of-stock-refunded

This provides better consistency with web standards and URL-friendly values.
2025-09-23 18:07:48 -04:00
fe94d9d9df Simplify out-of-stock refund statuses and handle expired+out-of-stock
- Remove unnecessary intermediate statuses, keep only STATUS_OUT_OF_STOCK_REFUNDED
- Check inventory when processing expired payments
- Give full refund (no restocking fee) if payment expired AND items are out of stock
- Use refund_reason field to track why refunds were issued

This ensures customers aren't penalized with restocking fees when both
the quote expired AND the items went out of stock.
2025-09-23 18:07:25 -04:00
39a72ec9f8 Implement robust crypto payment processing with inventory checks
- Add inventory availability check before finalizing crypto payments
- Implement full refund without restocking fee for out-of-stock items
- Add new payment statuses: out_of_stock_refund_pending, out_of_stock_refunded
- Process crypto payments in FIFO order (first come, first serve) by creation timestamp
- Add transaction-level savepoints for atomic payment processing
- Refresh payment status before processing to avoid race conditions
- Add refund tracking fields: refund_reason, refund_tx_hash, refund_amount
- Hide credit card button when no active card is configured
- Move checkout confirmation message outside Stripe-specific section
- Clean up pending quotes display (remove redundant labels)

This prevents the Black Friday scenario where multiple customers pay with
different cryptocurrencies for the same limited inventory item. The first
payment to be created will be processed first, and subsequent payments
for out-of-stock items will receive full refunds automatically.
2025-09-23 18:05:04 -04:00
c77bd72a12 Replace crypto payment buttons with invoice link for non-pending statuses
- Remove all action buttons (copy amount/address, open wallet) when payment is no longer pending
- Replace with 'View Invoice' link for confirmed/processing/expired/cancelled payments
- Handle both on page load and dynamically via status polling
- Add invoice_url to crypto status API endpoints
- Prevents double payments by removing all payment options once quote expires or payment is received
2025-09-23 17:55:20 -04:00
bb0a830fd2 Remove success alert popup from crypto payment cancellation
Now silently redirects to cart without showing the 'Payment quote cancelled
successfully' alert popup for better UX.
2025-09-23 16:49:14 -04:00
b63be901f3 Fix cart redirect after crypto payment cancellation
Use simple /cart route which automatically goes to active cart instead of
trying to construct specific cart checkout URL with non-existent cart_id field.
2025-09-23 16:47:54 -04:00