wallet-sdk PR5b: cashu send + receive ops#1124
Closed
orveth wants to merge 1 commit into
Closed
Conversation
Sub-slice 3b of @agicash/wallet-sdk, stacked on PR5a (#1123). Lifts the cashu service primitives framework-free + wires CashuSendOps/CashuReceiveOps into Sdk.create, replacing PR2's cashu stub. Services (re-housed from app/features/{send,receive}/*, dropping the useX() React factories; near-verbatim logic; DB reservation / CONCURRENCY_ERROR guards + wallet.restore recovery preserved): - cashu-send-quote-service / cashu-send-swap-service (incl. reverse, decision 8) - cashu-receive-quote-service / cashu-receive-swap-service - cashu-receive-quote-core (NUT-20 locking, framework-free in master) - the four SDK-owned repos over the SDK Supabase client + Encryption Supporting: - Encryption gains the encrypt half (encrypt/encryptBatch/decrypt) the write path needs (PR5a shipped decrypt-only); + OpenSecret encryption-public-key and cashu-locking xPub/private-key methods. - lib-cashu-quotes / lib-cashu-crypto / lib-lnurl single-source re-exports; tsconfig maps ~/* so the re-housed zod schemas resolve their own imports. - SdkError.code is now optional (defaults to the subclass name) so the lifted services construct DomainError(msg) verbatim; UniqueConstraintError added. executeQuote is a documented NotImplementedError stub here — the orchestrator state machine (the six React useProcess*Tasks hooks → framework-free, mint-WS managers, classify-body relocation) is the heaviest net-new construct and is deferred to the orchestrator sub-slice (PR5d) per the build plan; PR5b ships the idempotent primitives it sequences. receiveToken is likewise a stub at the public surface (the claim FLOW + cross-account melt-then-mint ride with PR5d + transfers); the same-mint receive-swap primitive it builds on is shipped+tested. Tests: service idempotency/concurrency guards, reverse (reversedTransactionId tagging), the LNURL ln-address fold, repo CONCURRENCY_ERROR/UniqueConstraint mapping. Full CI gate green locally (tsc, biome format+lint, bun --filter='*' test: wallet-sdk 203 / web-wallet 133, 0 fail). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
Contributor
Author
|
Superseded by the reactive design-B stack (SDK #1129-#1138 + lib-extract #1140-#1143). This no-cache stack was the reference substrate the reactive PRs were built from (~90% reused, reads adapted to Query); it was never reviewed/merged, so nothing is lost. Closing as superseded — branch retained for reference. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Sub-slice 3b of
@agicash/wallet-sdk, stacked on PR5a (#1123). Lifts the cashu protocol service primitives framework-free and wiresCashuSendOps/CashuReceiveOpsintoSdk.create, replacing PR2's cashu stub. The wallets are live as of PR5a (ExtendedCashuWallethandle +LiveAccountHandleResolver); this slice drives the mint over them.Implemented
Service primitives (re-housed from
app/features/{send,receive}/*, dropping theuseX()React factories; near-verbatim logic; the DB reservation /CONCURRENCY_ERRORguards +wallet.restorerecovery — the stale-proof protection — preserved):cashu-send-quote-service(lightning send:getLightningQuote/createSendQuote/initiateSend/markSendQuoteAsPending/completeSendQuote/failSendQuote/expireSendQuote)cashu-send-swap-service(token send +reverse, decision 8 — a new cashu receive-swap taggedreversedTransactionId)cashu-receive-quote-service(+cashu-receive-quote-core: NUT-20 quote-locking, framework-free in master)cashu-receive-swap-service(same-mint token claim)Encryption(encrypt-on-write / decrypt-on-read of the jsonb + proof ciphertext; account-returning RPCs use an injected resolver-backed account mapper)Public ops (
domains/cashu.ts):createLightningQuote(with the LNURL ln-address→bolt11 fold internal to quote creation, per the contract —getInvoiceFromLud16),createTokenQuote,failQuote,reverse,get; receivecreateLightningQuote(+BUY_CASHAPPpurpose),get.Supporting:
Encryptiongains the encrypt half (encrypt/encryptBatch/decrypt) the write path needs (PR5a shipped decrypt-only, explicitly deferring this); + OpenSecretgetEncryptionPublicKeyHexand cashu-locking xPub / private-key methods.lib-cashu-quotes/lib-cashu-crypto/lib-lnurlsingle-source re-exports (the established pattern); the packagetsconfig.jsonmaps~/*→apps/web-wallet/app/*so the re-housed zod schemas resolve their own imports one level deeper than PR5a's leaf-only re-exports.SdkError.codeis now optional (defaults to the subclass name) so the lifted services constructnew DomainError(msg)verbatim;UniqueConstraintErroradded (the double-claim DB guard).Deferred (and why)
executeQuote— documentedNotImplementedErrorstub. Per the build plan (§1 + §4), the unifiedexecuteQuoteorchestrator is the single biggest net-new construct: a framework-free state machine that absorbs master's six React-residentuseProcess*Taskshooks (each a TanStack mutation + retry/MintOperationErrorbranch + a live mint-WS*SubscriptionManager) and drives UNPAID→PENDING→PAID off DB state, plus theclassify()-body relocation. The plan keeps that state-machine core as its own reviewable unit; PR5b ships the idempotent primitives it sequences (initiateSend/markSendQuoteAsPending/completeSendQuote/failSendQuote+ the swap/claim services). → the orchestrator sub-slice (PR5d).receiveToken— stub at the public surface. The same-mint receive-swap primitive (CashuReceiveSwapService.create, withcompleteSwap's double-claimwallet.restorerecovery) is shipped + tested. What the public method additionally needs — destination-account resolution, same-vs-cross routing, the cross-account melt-then-mint quote path, and the result-surface reconciliation (a same-mint claim yields a swap, but the declared result is a quote) — is orchestrated over account/user services + exchange-rate fetches not yet in the SDK, and rides with PR5d + transfers. Stubbed with no side effects rather than half-driving a claim.listPendingis not public (decision) — kept as service-internalgetUnresolved/getPendinghelpers for the future orchestrator.Tests
Service idempotency / concurrency guards (no-op + state-guard branches),
reverse(reversedTransactionIdtagging), the LNURL fold (bolt11 passthrough vs ln-address resolution vs LNURL error →DomainErrorvs amount-required), repoCONCURRENCY_ERROR→ConcurrencyErrorand23505→UniqueConstraintErrormapping, plus theexecuteQuote/receiveTokendeferred-stub contract. Wallet / mint / repos / LNURL are mocked.CI gate (local)
tsc --noEmit✓ ·biome format(check) ✓ ·biome lint✓ ·bun --filter='*' run test✓ — wallet-sdk 203 pass / 0 fail, web-wallet 133 pass / 0 fail.🤖 Generated with Claude Code