Skip to content

Direct Safebox payments

Payment readers now use the Safebox discovery contract. Public NIP-05 responses remain available for older senders and social lookups. Do not change existing NIP-05 wallet mappings until those consumers migrate.

OakGate can receive encrypted Acorn ecash transfers without an active browser or Redis session. A Send payment page also lets a user review an address and amount, then confirm a direct ecash or Lightning payment.

Address discovery and routing

/.well-known/nostr.json?name=handle publishes the chosen social npub. With no social preference it retains the existing Acorn-key mapping and legacy wallet extensions. A social override omits wallet relays and capabilities. Wallet routing always uses the Acorn binding through safebox.json or local registration. LNURL's nostrPubkey remains OakGate's receipt-signing service identity.

OakGate and Safebox Web prefer /.well-known/safebox.json?name=handle for cash and Clear payment delivery. Its explicit wallet key and capabilities take precedence over social NIP-05. There is no NIP-05 wallet fallback. The retired OAKGATE_SAFEBOX_DOMAINS setting is ignored. A 404 or absent cash capability may use ordinary Lightning; Clear requires wallet discovery. Invalid responses and network failures stop preparation rather than downgrading.

Direct delivery uses a relay in OAKGATE_ALLOWED_RELAYS. New receiving relays must be approved by the operator. Mint selection and redemption use Acorn's existing policy: any mint from which Acorn can successfully receive is accepted. OakGate does not add a mint allowlist or restrict direct sends to the bootstrap mint. The bootstrap mint is the default for creating Lightning receiving invoices, not a list of trusted issuers.

When no usable direct route is found, OakGate resolves LNURL and obtains a Lightning invoice before showing confirmation. It checks the mainnet currency, amount and expiry. Description hashes do not block outgoing invoice preparation, matching the receiving compatibility policy. Preparation failures stay on the signed-in Send page with the entered values and selected asset preserved; no payment is submitted until confirmation. The address field accepts Lightning addresses (name@domain), not payment website URLs. When the provider omits commentAllowed or sets it to zero/null, OakGate omits the comment from the invoice request instead of blocking payment. Providers that support comments still receive them within their advertised length limit. Discovery and callback requests require HTTPS, pin a public DNS result to the TLS connection, limit response size, and never follow redirects. No payment is sent during review.

Sender-paid mint fees

For direct Cash sends, the entered amount is the recipient's intended net credit. OakGate asks Acorn for a read-only quote_ecash_transfer(amount) and displays the recipient amount, combined mint fees and total debit before confirmation. All proof selection, mint fee calculations and private-key operations remain in Acorn.

The sender covers both the swap that prepares the token and the recipient's redemption of that token. Acorn chooses denominations so their value minus the NUT-02 redemption fee equals the requested amount. For example, a 6-sat payment with a 1-sat fee per proof can use two 4-sat proofs: the recipient redeems 8 sats and receives 6. If preparation costs 1 sat, the sender's total debit is 9 sats.

OakGate rechecks the quote before claiming the outgoing attempt; Acorn rechecks under its wallet lock and again before the mint swap. A changed quote is never silently accepted. A failure after the attempt is claimed retains the existing uncertain-payment review hold; no automatic retry, second token or Lightning fallback is introduced. Old prepared direct sends require a new confirmation.

Acorn journals sender-paid receipt metadata and settles these receipts individually, so another receipt's fee cannot be charged to them by batch allocation. Actual credit still depends on successful mint redemption and durable proof storage. Fees are based on the mint's advertised keyset rates; a mint changing those rates after dispatch cannot be guaranteed by the sender. Older recipients can redeem the ordinary topped-up Cashu token, but may allocate batch fees differently. Update the receiving Acorn too for the per-receipt accounting guarantee.

Legacy Acorn callers that omit fee_quote retain their existing gross-token behavior. Clear sends, explicit Lightning invoices and Lightning fallback are unchanged. No mint allowlist is added.

Deployment order: commit and push safebox-acorn first, run poetry update safebox-acorn in OakGate, commit the updated poetry.lock with OakGate, then deploy. The image build checks for the new quote API. Local tests with an Acorn source override do not update the locked container dependency.

Receiving and settlement

The background worker scans active Acorns, including users who are signed out or have no current handle. It defaults to a 30-second interval per wallet, processes up to four wallets concurrently, and takes the same owner lease as outgoing and Lightning credit operations. This is prompt background settlement, not a promise of instantaneous settlement: relay/mint availability and queue load still matter.

The adapter first calls sweep_ecash_transfers(finalize=False) to persist incoming receipts through Acorn. It then calls reconcile_continuity_receipts() to redeem tokens through their issuing mints. A receipt is not spendable merely because it arrived: Acorn must successfully redeem it and persist the resulting proofs. Transient failures remain pending for retry, using Acorn's existing receipt handling. Only Acorn writes proofs, receipts, checkpoints, and transaction history. OakGate adds no duplicate credit entry and no separate mint trust policy.

Acorn uses Stroma for gift wrapping and relay transport. Stroma disables timestamp jitter and uses current timestamps for seals and wrappers. The receiver uses Acorn's existing checkpoint and receipt deduplication behavior; it does not introduce a two-day rescan or an alternative Nostr implementation.

Sending, retries, and uncertainty

The Send payment page is available from Balances and Cash transactions. Review shows the address, exact satoshi amount, and selected payment route. Provider fees can apply. Confirmation requires the user's session and CSRF token.

An encrypted SQLite outgoing journal binds a one-shot confirmation to its owner. Confirmation expires after five minutes or invoice expiry, whichever is sooner. A claimed attempt cannot be submitted again by refreshing the page or repeating the request. An uncertain result or a process interruption after claiming blocks new sends for that owner pending operator review. There is deliberately no automatic retry or fallback after an Acorn send starts.

A direct-send result means Acorn returned delivery success; it does not prove recipient redemption. OakGate recipients can settle in the background, while a non-custodial recipient may still need to open their wallet. These direct ecash payments do not create Lightning invoices or NIP-57 zap receipts. Existing Lightning address payments and zaps retain their existing path.

For unresolved payments, retain the journal and inspect native Acorn transaction history, pending mint operations, and recipient receipt evidence. Do not simply delete the local attempt or pay again. Automated operator reconciliation and a user-facing pending-receipts page are not included in this change.

Configuration

OAKGATE_ECASH_RECEIVE_ENABLED=true
OAKGATE_ECASH_POLL_SECONDS=30

The receiver is independent of user login sessions. Disabling it stops background redemption and NIP-05 payment discovery but does not delete received tokens.

Dependencies and deployment

This feature uses Acorn's existing sweep_ecash_transfers, reconcile_continuity_receipts, send_ecash_transfer, and pay_multi_invoice methods. It requires no new Acorn mint-policy API or lockfile update. Stroma already has the required no-jitter behavior and needs no source change.

After committing and pushing OakGate, deploy with ./refresh-app.sh. Verify the NIP-05 response for a connected handle, then test a small payment while the recipient is signed out. A real mint/relay payment is an operator acceptance check; unit tests do not transfer money.

Backups

Back up custody.sqlite3 and the separate custody encryption key as already documented. The database now also contains the encrypted outgoing journal and inbox scheduling state. Incoming receipts and native transaction history remain in the Acorn's relay-backed state. Redis is not the durable payment journal.

For the complete distinction between social identity, direct cash, Lightning, wallet messages and descriptor-based record sharing, see which lookup serves which purpose. The migrated cash reader uses the wallet capability, not LNURL safebox=true.