Sprey Processing verification — 2026-09-14
This checkpoint records behavior directly verified on 2026-09-14 on the live Sprey Processing deployment.
Backup checkpoint
Section titled “Backup checkpoint”Before continuing the hosted-access and email/onboarding changes, a fresh Hetzner backup was created for sprey-btcpay and reached Available status.
This backup is the immediate rollback point for the configuration changes recorded below.
Bitcoin on-chain E2E
Section titled “Bitcoin on-chain E2E”A real invoice was created in the Sprey Processing Store for:
Amount: 8.10 USDInvoice ID: 59eMfkorwybs34GKbcbuU54Item description: BTC E2E testBTC amount due: 0.00010436 BTCBTC/USD rate at invoice creation: 77,618.30 USDThe invoice used the BTCPay-generated Bitcoin on-chain destination:
bc1q40xhmuk6pfel8zyg8n5ssk4dxfzmlh7szgez4xThe payment was sent from OKX over Bitcoin mainnet. OKX charged a withdrawal fee of 0.000015 BTC, while the invoice destination received the exact requested amount of 0.00010436 BTC.
The observed BTCPay lifecycle was:
10:00 invoice created10:15 invoice expired10:19 payment received10:19 status: Expired (paid late)10:19 invoice_paidAfterExpiration10:20 1 / 1 confirmation10:20 invoice_paymentSettledVerified events included:
invoice_receivedPayment (1002);invoice_paidAfterExpiration (1009);invoice_paymentSettled (1014).
The on-chain payment record showed:
Payment method: BTC-CHAINPaid: 0.00010436 BTCConfirmations: 1 / 1This verifies the real payment path:
OKX -> Bitcoin mainnet -> BTCPay / Sprey Processing invoice -> exact amount detected -> required confirmation reached -> payment settledThe payment arrived after the original invoice expiry, but BTCPay correctly associated it with the invoice, marked it as paid late, and settled it after the required confirmation.
Invoice-expiry adjustment
Section titled “Invoice-expiry adjustment”The test demonstrated that the previous 15 minutes invoice expiry can be too short for real exchange withdrawals. The Store invoice expiry was therefore changed to:
45 minutesThe following related settings were left unchanged:
Underpayment tolerance: 0%Minimum acceptable BOLT11 expiration time for refunds: 30 daysPayment invalid if confirmation fails after invoice expiration: 1440 minutesSettlement requirement: at least 1 confirmationBTC on-chain E2E: VERIFIED.
Hosted subscription E2E — USDt on TRON
Section titled “Hosted subscription E2E — USDt on TRON”A real Starter subscription checkout was paid with USDt on TRON.
Verified behavior:
- BTCPay received the exact USDt amount;
- TRON payment confirmations were observed;
- the invoice reached
Settledand completed; - a subscriber was created;
- the hosted-access subscription became active.
This closed the first real Tether USDt settlement path for the reference deployment.
USDt on TRON E2E: VERIFIED.
USDt on Ethereum E2E
Section titled “USDt on Ethereum E2E”A second real hosted-subscription payment was completed with USDt on Ethereum.
The test was intentionally combined with a second clean hosted-user onboarding flow so that one payment verified both the Ethereum payment rail and corrected account setup behavior.
Verified behavior:
- checkout exposed
USDT-ETHEREUM; - the exact invoice amount was received;
- BTCPay produced a successful payment receipt showing
USDT-ETHEREUM; - the hosted subscription became active;
- the new server user was created;
- the user completed email confirmation, password setup, login, and Store creation successfully;
- the same user subsequently completed the normal password-reset flow successfully.
After testing, the Starter Plan price was returned to the production value of $18.99 per month.
USDt on Ethereum E2E: VERIFIED.
USDt on Polygon E2E
Section titled “USDt on Polygon E2E”A separate real invoice was paid with USDt on Polygon.
Verified behavior:
- checkout exposed
USDT-POLYGON; - the exact invoice amount was received;
- BTCPay displayed the successful payment receipt with payment method
USDT-POLYGON.
With this checkpoint, the installed Tether USDt plugin has real paid-invoice verification on all three currently exposed Sprey networks:
- TRON;
- Ethereum;
- Polygon.
USDt on Polygon E2E: VERIFIED.
Merchant-controlled wallet balance confirmation
Section titled “Merchant-controlled wallet balance confirmation”After the BTCPay payment tests, balances were checked independently through the merchant-controlled Tether WDK CLI wallet.
The observed balances matched the real test payments exactly:
Bitcoin index 4 0.00010436 BTCTRON index 0 9.99 USDTEthereum index 0 1.89 USDTPolygon index 0 1.17 USDT0For Polygon, the current WDK CLI token registry exposes Tether as usdt0 / USDT0; both token spellings returned the same 1.17 USDT0 balance.
This provides an independent wallet-side confirmation that the merchant-controlled destinations received the funds observed by BTCPay. The Bitcoin result also confirms that the WDK-derived BIP84 account used by BTCPay watch-only observation contains the exact real test payment at derived address index 4.
Sparrow confirmation
Section titled “Sparrow confirmation”The merchant-side Sparrow wallet Sprey Processing WDK BTC was then allowed to load its transaction history. Sparrow independently found the same confirmed Bitcoin payment:
Balance: 10,436 satsMempool: 0 satsTransactions: 1The incoming transaction value was 10,436 sats, exactly equal to 0.00010436 BTC reported by WDK at index 4 and by BTCPay for the settled invoice.
The first Sparrow view showed 0 sats because its network/backend connection was disabled. After enabling the connection and allowing history loading to finish, Sparrow displayed the confirmed transaction and correct balance. This was a connectivity state, not a wallet/xpub/derivation mismatch.
The Bitcoin payment is therefore independently consistent across all three layers:
BTCPay settled invoice =WDK BTC index 4 balance =Sparrow confirmed balance / UTXO =0.00010436 BTC / 10,436 satsOn Windows, successful WDK balance output was followed by this process-shutdown assertion on several commands:
Assertion failed: !(handle->flags & UV_HANDLE_CLOSING), file src\win\async.c, line 94The assertion occurred after the requested balances had already been returned. It is recorded as a CLI/runtime issue to track separately and did not prevent the observed balance checks from completing.
Hosted-user onboarding root cause and fix
Section titled “Hosted-user onboarding root cause and fix”The first paid hosted user was created successfully by Monetization but did not receive a usable account-setup path. The user existed, the subscription was active, and SMTP delivery worked, but the account had no password and the expected onboarding message did not arrive.
The relevant BTCPay Server 2.4.4 flow was reviewed. The important behavior is:
- Monetization creates the new server user without a password;
- this flow is not an administrator invitation, so the
User: Invitationserver email rule is not the normal trigger; - when
Email confirmation requiredis disabled, this passwordless Monetization user has no automatic confirmation/setup step; - the normal forgot-password flow is not a substitute for the initial passwordless account setup.
The verified server policy is therefore:
Enable public user registration ONEmail confirmation required ONAdmin must approve new users OFFStore owners can add users without invitation OFFNon-admins can access the User Creation API OFFRegister page redirect URL /monetization/new-userMaximum Stores per non-admin user 3Non-admins can use Internal Lightning Node OFFNon-admins can create Hot Wallets OFFNon-admins can create Cold Wallets OFFWith Email confirmation required = ON, the second clean user followed the expected flow:
subscription checkout | vpayment settles | vsubscriber + server user created | vConfirm your email address | vset password | vlogin | vcreate StoreThe second user then successfully used the standard password-reset email as well.
Email rules
Section titled “Email rules”Server SMTP was re-tested by sending a real test email to the hosted-user mailbox. Delivery succeeded, confirming that the earlier onboarding problem was not SMTP transport or mailbox delivery.
The custom Store-level WH-SubscriberActivated welcome email was removed after the corrected server confirmation flow was verified. Sending both messages immediately after checkout duplicated onboarding and risked unnecessary email noise.
The current responsibility split is:
- server email handles account confirmation and password establishment;
- subscription email rules are reserved for actual subscription lifecycle information such as reminders or expiry state.
Internal test users
Section titled “Internal test users”Two hosted test users are intentionally retained:
- the original control user created before email confirmation was required; its password was set manually and its email remains unconfirmed;
- the clean reference user created after the corrected email-confirmation policy was enabled; its email is confirmed.
Both now have:
Bypass monetization for this user = ONThey therefore remain available for regression and customer-journey testing without requiring repeated paid subscriptions or fake commercial Lifetime plans.
Keeping the users different is intentional: the first preserves the pre-fix control case, while the second is the clean reference for the corrected onboarding flow.
Store website and invoice redirect
Section titled “Store website and invoice redirect”The Sprey Processing Store Website setting was changed from:
https://sprey.win/to:
https://pay.sprey.win/A newly created invoice immediately showed:
Redirect Url: https://pay.sprey.win/This confirms that ordinary Store invoices inherit the customer return destination from the Store Website setting. The customer-facing return action now returns to Sprey Processing rather than the general marketing site.
Checkout payment-timing notice
Section titled “Checkout payment-timing notice”A customer-facing timing note was added to the Sprey Processing checkout footer after the real late-BTC-payment test and the invoice-expiry adjustment.
The current English text is:
Your exchange rate is locked for 45 minutes. Late payments are monitored for up to 24 hours and processed once confirmed.
The notice intentionally reflects the Store’s current operational settings:
Invoice expiry / rate-lock window: 45 minutesPost-expiry monitoring/invalid window: 1440 minutes (24 hours)Settlement requirement: at least 1 confirmationThe wording is informational rather than a guarantee that every late payment can be accepted under all conditions. Its purpose is to make the configured timing behavior visible to the customer before leaving the checkout page.
Receipt follow-up
Section titled “Receipt follow-up”BTCPay’s built-in successful-payment receipt page was verified during the Ethereum and Polygon tests. It includes the amount paid, payment method, payment destination, date, and a printable receipt view.
A remaining UX task is to determine the cleanest upstream-compatible way to deliver or link this receipt to the customer automatically without duplicating unnecessary email traffic.
Lightning status and plugin cleanup
Section titled “Lightning status and plugin cleanup”Lightning is not marked production-verified by this checkpoint.
The evaluation produced the following decisions:
- Flint was removed from the Store after the test wallet was confirmed empty;
- the server-side-seed model used by Flint is not the preferred long-term Sprey ownership boundary;
- Boltz was tested indirectly through the SamRock dependency, but
api.boltz.exchange:443timed out from both the reference host and an external client; - Boltz/Liquid was not selected as the primary Sprey Lightning path;
- SamRock Protocol was evaluated but was not selected as the target integration for WDK Spark or hosted-client Lightning;
- SamRock Protocol and Boltz were uninstalled after evaluation;
- Nostr remains installed for NIP-05, zaps and future Nostr Wallet Connect use cases;
- Tether USDt remains installed as the verified stablecoin payment plugin;
- Satoshi Tickets is installed as an optional merchant-app/plugin for event-ticketing tests under
Sprey Labs; - Stripe is installed as an optional client-facing fiat payment integration; it is not part of Sprey’s core payment rail and is not configured as Sprey’s own merchant account.
Current installed-plugin baseline:
Nostr 1.1.21.0Satoshi Tickets 1.5.0.0Stripe 1.0.13.0Tether USDt 0.6.1.0The current role split is:
Core / verified payment plugin Tether USDt
Standards / optional Lightning-Nostr integration Nostr
Optional merchant app / Labs use case Satoshi Tickets
Optional client fiat integration StripeThe product direction remains external/client-controlled Lightning rather than a shared Sprey custodial wallet or shared internal Lightning node. NWC is a preferred standards-based direction for compatible external wallets. Direct WDK Spark integration remains future adapter/integration work rather than a currently verified BTCPay backend.
Sprey Processing / Sprey Labs Store separation
Section titled “Sprey Processing / Sprey Labs Store separation”A separate Store named Sprey Labs was created to keep experimental merchant apps, plugins and UX checks out of the production/reference Store.
The Store-role split is now:
Sprey Processing production/reference Store -> monetization -> ordinary invoices -> verified payment rails -> email / receipt / redirect behavior -> API / webhooks and core Processing behavior
Sprey Labs feature and plugin test bench -> Pay Button -> Crowdfund -> Point of Sale -> Satoshi Tickets -> Nostr and other optional merchant apps -> future plugin/app experiments
Internal user Stores customer-regression layer -> non-admin UX -> client-visible permissions and limits -> customer Store creation/configuration behaviorSprey Labs was created without wallets configured initially. The rule is to avoid attaching real payment destinations unless a specific end-to-end test requires them. Configuration-only behavior should be verified without unnecessary payment-wallet coupling; real settlement should be added only for the exact flow being tested.
This separation also reflects BTCPay’s own warning that Pay Button is intended for tips/donations rather than general e-commerce and should preferably be isolated from a commercial Store.
Merchant-app exploration status
Section titled “Merchant-app exploration status”The following merchant entry points/apps are now explicitly in the verification queue, primarily under Sprey Labs unless the test is specifically about customer/non-admin behavior:
- Pay Button;
- Point of Sale;
- Crowdfund;
- Payment Requests;
- Satoshi Tickets.
Pay Button configuration was opened and its available modes were confirmed, including fixed/custom/slider amount options, email notifications, browser redirect, IPN, generated embed code, shareable link and LNURL. It is not yet marked end-to-end verified.
Satoshi Tickets was installed and its event-creation flow was inspected. It exposes virtual-event configuration, description, event URL/location, post-purchase redirect, image, dates, currency and optional reminder email/template fields. No ticket-purchase E2E is claimed yet.
Stripe is installed so that supported client merchants can optionally connect their own Stripe accounts for fiat acceptance alongside crypto. No Stripe merchant configuration or Stripe payment E2E is claimed for Sprey itself.
End-of-day verified state
Section titled “End-of-day verified state”Verified on the live reference deployment:
- real BTC on-chain payment observation and settlement;
- 45-minute invoice expiry;
- real USDt settlement on TRON;
- real USDt settlement on Ethereum;
- real USDt settlement on Polygon;
- independent WDK wallet-side confirmation of the exact BTC, TRON USDt, Ethereum USDt, and Polygon USDt balances received during the real tests;
- independent Sparrow confirmation of the same
10,436 satsBitcoin payment; - real paid hosted-subscription activation;
- email-confirmation onboarding for passwordless Monetization users;
- password setup, login, Store creation, and password reset for the clean hosted test user;
- server SMTP delivery;
- production Starter price restored to
$18.99/month; - Store Website and new-invoice redirect set to
https://pay.sprey.win/; - customer-facing checkout timing notice added for the 45-minute rate-lock and 24-hour late-payment monitoring behavior;
- both internal regression users set to bypass monetization;
- Lightning experiment cleanup completed: SamRock and Boltz removed, Nostr retained;
- current installed-plugin baseline recorded as Nostr, Satoshi Tickets, Stripe and Tether USDt;
Sprey Labscreated as a separate merchant-app/plugin test bench.
Still pending before the admin/reference Processing setup is considered finished:
- customer receipt delivery/linking UX;
- remaining subscription lifecycle email checks;
- final external-Lightning/NWC policy and a future verified Lightning E2E when a suitable client-controlled backend is selected;
- verification of Pay Button, Point of Sale, Crowdfund, Payment Requests and Satoshi Tickets one flow at a time;
- final consolidation into
products/sprey-processing.mdafter configuration and verification work is complete.