Commit graph

365 commits

Author SHA1 Message Date
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
93f41294a4 Fix crypto payment cancellation
- Add CSRF token requirement to cancel endpoint for security
- Include CSRF token in crypto checkout template
- Add better error handling and debugging for cancel requests
2025-09-23 16:45:46 -04:00
54da2d726d Improve crypto payment UX and fix layout issues
- Remove all flex layouts and replace with CSS Grid for consistent styling
- Move pending crypto quotes section to bottom of confirmation page
- Update button text to use "confirm checkout" terminology
- Add crypto payment cancellation with redirect to active cart
- Remove cancel buttons from confirmation page to reduce clutter
- Implement smart redirect URLs for completed crypto payments
2025-09-23 16:41:04 -04:00
4be33ee528 Apply black code formatting to crypto watcher fix 2025-09-23 16:04:12 -04:00
457b13eef1 Fix crypto watcher crash by adding missing app property to ShopContextRequestWrapper
The wrapper class wasn't properly exposing the app attribute needed for email
sending during payment finalization. This caused AttributeError crashes when
processing real payments. Added explicit app property to ensure proper access.
2025-09-23 16:02:15 -04:00
72ac3d29ca Fix crypto sync status detection with proper imports
The sync status request methods were failing due to relative import errors
when trying to import crypto clients. Changed to absolute imports to resolve:
- "attempted relative import beyond top-level package" errors
- Monero and Dogecoin sync status now properly detected
- Payment method availability correctly reflects wallet/node sync status

This restores the intended functionality where crypto payment buttons only
appear when the underlying nodes/wallets are fully synchronized.
2025-09-23 15:33:19 -04:00
45dca33b65 Fix Monero sync detection for remote nodes and apply code formatting
- Change Monero is_synced() to simple height > 0 check for remote nodes
- Update get_sync_status() to return appropriate status for remote node setup
- Fixes false "syncing" status when using upstream Monero nodes
- Apply black code formatting for consistency

This preserves the sync status detection functionality while fixing
issues with remote Monero node deployments.
2025-09-23 15:29:12 -04:00
fbc0b55dc3 Add sync status checks for crypto payment methods
Crypto payment buttons now only appear when nodes are fully synced,
preventing failed payments due to incomplete blockchain synchronization.

- Add is_synced() and get_sync_status() methods to MoneroClient and DogecoinClient
- Add request.monero_synced and request.dogecoin_synced request methods
- Update payment visibility logic to require both enabled AND synced status
- Add helpful sync status messages in checkout template when nodes are syncing
- Prevent customer frustration from unsynchronized payment processing

Payment method visibility now requires:
1. App globally enabled
2. Shop has cold wallet configured
3. RPC accessible and responsive
4. Node/wallet fully synchronized
2025-09-23 15:01:49 -04:00
171fc916b7 Fix auto-sweep database persistence bug
Auto-sweep functions were not persisting swept_tx_hash to database because
the modified crypto_payment objects weren't being added to the session.

- Add dbsession parameter to auto_sweep_payment functions
- Add explicit dbsession.add(crypto_payment) calls when sweep succeeds
- Update tests to verify swept_tx_hash is set and payment added to session
- Fix existing tests to work with new function signatures

This resolves the issue where swept payments had NULL swept_tx_hash despite
successful fund transfers, which caused infinite processing loops.
2025-09-23 13:46:45 -04:00
b2a47f6789 Move crypto documentation to docs directory
- Move CRYPTO.rst to docs/CRYPTO.rst
- Move CRYPTO_PROBLEMS.rst to docs/CRYPTO_PROBLEMS.rst

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-23 13:21:15 -04:00
3d2554373b Remove Monero documentation from README
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-23 13:17:30 -04:00