diff --git a/README.md b/README.md index 9c1a938..9d68e85 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,21 @@ carries the full merchant surface: invoice automatically. - **Hosted checkout:** a zero-JS `/pay/` page (server-rendered Askama + one CSS file + a server-generated QR SVG at ECC level H with an - optional GoblinPay-mark center logo), live status via ``, - and a manual slatepack fallback (paste S1 -> offline `receive_tx` -> copy the - S2 back) on every page. The same renderer serves embedded and hosted use. + optional GoblinPay-mark center logo) with live status via + ``. It offers two first-class ways to pay: + - **Goblin Wallet (Nostr):** scan the `nprofile` QR (or copy it) and the + payment auto-receives over Nostr. + - **Slatepack (`grin1`):** pay from any Grin wallet, no Nostr needed. The + page shows the wallet's stable index-0 Slatepack address (`grin1...`) plus + its QR and the exact amount to send. The payer sends that amount to the + address using their wallet's Slatepack/file method, pastes the resulting S1 + into the page (offline `receive_tx`), then copies the returned S2 back into + their wallet to finalize and broadcast it. There is no Tor listener; the + `grin1` address is stable and reused across invoices, and the existing + invoice matcher and on-chain confirmation handle the received payment like + any other. The Slatepack option only appears when a wallet is loaded. + + The same renderer serves embedded and hosted use. - **Per-user endpubs:** an admin assigns one receiving identity per user (a derived child keyed by `(user_id, epoch)`; only public keys and the rotation clock are stored, never private keys), with optional rolling rotation diff --git a/crates/gp-server/src/checkout.rs b/crates/gp-server/src/checkout.rs index ba691fe..d860038 100644 --- a/crates/gp-server/src/checkout.rs +++ b/crates/gp-server/src/checkout.rs @@ -1,13 +1,15 @@ //! The hosted, zero-JS checkout: the `/pay/` page (shared renderer for -//! embedded and hosted use), its live status, and the manual-slatepack -//! fallback. +//! embedded and hosted use), its live status, and the Slatepack receive flow. //! -//! The page shows the amount, a server-generated QR SVG of the recipient -//! `nprofile`, the `nprofile`/`npub` strings, live status via a -//! `` while open, and a ` +
+

Pay with Goblin Wallet

+
{{ info.qr_svg|safe }}
+

Scan with your Goblin Wallet, or copy the address below.

+ + +
-
- Can't scan? Pay manually with a slatepack - {% if wallet_available %} + {% if let Some(grin1) = info.slatepack_address %} +
+

Pay by Slatepack (grin1)

+

Pay from any Grin wallet, no Nostr needed. Send {{ info.amount_display }} to the address below.

+ {% if let Some(grin1_qr) = info.slatepack_qr_svg %}
{{ grin1_qr|safe }}
{% endif %} + +
    -
  1. In your wallet, send {{ info.amount_display }} using the manual / slatepack option.
  2. -
  3. Paste the generated S1 slatepack below and submit.
  4. -
  5. Copy the response slatepack we return, back into your wallet to finalize and post.
  6. +
  7. In your Grin wallet, send {{ info.amount_display }} to this address using the Slatepack / file method, then paste the Slatepack it produces below.
  8. +
  9. The pasted S1 Slatepack is received here and a response Slatepack is returned.
  10. +
  11. Paste that response back into your wallet to finalize and broadcast it, which completes the payment.
- +
- {% else %} -

Manual receive is unavailable on this instance.

- {% endif %} -
+ + {% endif %} {% endif %} {% if let Some(memo) = info.memo %}

{{ memo }}

{% endif %} diff --git a/templates/pay_result.html b/templates/pay_result.html index ff44e64..5fa9949 100644 --- a/templates/pay_result.html +++ b/templates/pay_result.html @@ -16,7 +16,7 @@
  1. Select all of the text above and copy it.
  2. -
  3. Paste it back into your wallet to finalize the transaction.
  4. +
  5. Paste it back into your wallet to finalize and broadcast the transaction; this completes the payment.
  6. Your wallet posts it to the chain; GoblinPay confirms it on receipt.
{% endif %}