wallet-sdk PR4: accounts + scan#1122
Conversation
Implements AccountsDomain + ScanDomain (Slice 2 of the no-cache contract), replacing PR2's NotImplemented stubs and wiring them into Sdk.create. AccountsDomain (list/get/getDefault/add/setDefault/getBalance/suggestFor): - account-repository over the SDK-owned Supabase client (re-housed from account-repository.ts + account-service.ts + account-hooks.ts, framework-free) - db-account row types + dbAccountToAccount mapper (lifted from agicash-db/database.ts + json-models, hand-written rows as in db-user.ts) - setDefault writes the per-currency default-account column on wallet.users - getBalance = the verbatim pure getAccountBalance (cashu proof sum / spark balance) - suggestFor: NET-NEW pure logic generalizing findMatchingOfferOrGiftCardAccount + online filter + default fallback; cheap-first, no cross-protocol cost comparison ScanDomain (parse): re-houses master classifyInput (kind only: bolt11 | ln-address | cashu-token); bolt11/cashu/lnurl decode libs are SDK-internal; unrecognised input throws DomainError (contract types parse as non-null). WALLET HANDLE DEFERRED to Slice 3 per the build plan: an account's live `wallet` handle (ExtendedCashuWallet/BreezSdk) + decrypted cashu proofs are entangled in master's toAccount with the heavy networked mint/Breez init + the shared/encryption subsystem, all assigned to Slice 3. An AccountHandleResolver seam is injected into the repository; the Slice-2 DeferredAccountHandleResolver maps the DB fields and leaves the live handle a lazy throwing stub. PR1 placeholders (ExtendedCashuWallet/BreezSdk/ SparkNetwork) are KEPT. Tests: scan parse cases, suggestFor branches (online/currency/balance/ranking/ fallback/receive), account-repository (get/getAllActive/add error paths) with a fake Supabase client, db-account mapper + guards + deferred-handle stub, account-balance. +74 tests (64 -> 138); full CI gate green (both packages test, tsc, biome lint+format). 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. |
There was a problem hiding this comment.
I'd say these and similar tests are trivial and thus useless
| getCashuUnit, | ||
| normalizeMintUrl, | ||
| } from '../../../../apps/web-wallet/app/lib/cashu/utils'; | ||
| export { sumProofs } from '../../../../apps/web-wallet/app/lib/cashu/proof'; |
There was a problem hiding this comment.
package should never import from the app. these utils, if they will only be used by sdk should be moved to sdk or if used in other places too where importing sdk does not make sense, they can be moved to separate package
| * @throws Error if the update fails (e.g. the DB constraint that a default currency must | ||
| * have a default account set). | ||
| */ | ||
| async setDefaultAccount( |
There was a problem hiding this comment.
why is this needed when it doesn't exist in the web wallets user-repository?
|
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. |
PR4 of the
@agicash/wallet-sdkstack — stacked on PR3 (#1121). Implements Slice 2 (accounts + scan) of the no-cache contract, replacing PR2'sNotImplementedstubs and wiring the real domains intoSdk.create.What's implemented (vs stubbed)
AccountsDomain(src/domains/accounts.ts) —list/get/getDefault/add/setDefault/getBalance/suggestFor:src/internal/account-repository.ts—get/getAllActive/addover the SDK-owned Supabase client (re-housed framework-free from masteraccount-repository.ts+account-service.ts+account-hooks.ts).src/internal/db-account.ts— thewallet.accounts/cashu_proofsrow types + thedetailsjson-model schemas +isCashuAccount/isSparkAccountguards +dbAccountToAccountmapper (lifted fromagicash-db/database.ts+json-models/*; rows hand-written as in PR3'sdb-user.ts).setDefaultwrites the per-currency default-account column onwallet.users(one default per currency, BTC+USD).getBalance= the verbatim puregetAccountBalance(src/internal/account-balance.ts: cashu proof sum / spark balance).suggestFor(src/internal/suggest-account.ts) — NET-NEW + PURE over the passed-in accounts: generalizes master'sfindMatchingOfferOrGiftCardAccount+ anisOnlinefilter + a default-account fallback. Cheap-first (purpose priority → balance → age); no cross-protocol cost comparison. Handles send / receive / token-receive intents.ScanDomain(src/domains/scan.ts) —parse(input)re-houses masterclassifyInputreturning the KIND only (bolt11|ln-address|cashu-token), no merchant/contact info (decision 3). The bolt11 / cashu-token / lnurl decode libs are SDK-internal (src/internal/lib-scan.ts). Unrecognised input throwsDomainError(the contract typesparseas non-null, unlike master'snull).allowLocalhostis a constructor option (defaultfalse) replacing master'simport.meta.env.MODEgate.Wallet handle: DEFERRED to Slice 3 (per the build plan)
The build plan assigns the live
wallethandle construction (ExtendedCashuWalletvia the networked mint init /BreezSdkvia@agicash/breez-sdk-spark) to Slice 3 ("THE HEAVY one"). In master,account-repository.toAccountbuilds the live handle and decrypts cashu proofs together, usingshared/cashu+shared/spark+shared/encryption— all Slice-3 subsystems (the mint init is a 10s-timeout networked keyset/key fetch; proof decryption needs the OpenSecret-derived encryption key + ECIES).So this PR keeps PR1's
ExtendedCashuWallet/BreezSdk/SparkNetworkplaceholders and introduces an explicit seam —AccountHandleResolver(src/internal/account-handle-resolver.ts) — injected into the repository. The Slice-2DeferredAccountHandleResolvermaps the DB fields Slice 2 owns and leaves the live handle a lazy stub that throwsNotImplementedErroron any use (the account's plain DB fields stay fully usable;isOnline=false, cashuproofs=[], sparkbalance=nulluntil Slice 3). Slice 3 swaps in the real resolver with no change to the repository. This keeps the PR small and the boundary auditable.Tests (+74; 64 → 138, both packages green)
scan.test.ts— parse cases (cashu A/B/URL/prefix, bolt11 decode + prefixes, ln-address lowercase + localhost policy, unrecognised →DomainError, priority).suggest-account.test.ts— every branch: online filter, BTC currency filter, balance split, ranking (purpose/balance/age, cashu+spark mix), default fallback, receive/token-receive.account-repository.test.ts—get/getAllActive/add(insert-row shape + 409/LIMIT_REACHED/generic error paths) over a fake Supabase client.db-account.test.ts— guards, mapper (cashu/spark/unknown), forward-compat with a fake Slice-3 resolver, deferred-handle-throws.account-balance.test.ts+accounts.test.ts(domain over fakes).CI gate (run locally, all green)
biome format --write packages/wallet-sdk→ no fixes; rootbun --filter='*' run test→ wallet-sdk 138 pass / 0 fail, web-wallet 133 pass / 0 fail (exit 0); packagetsc --noEmit,biome format(check),biome lint→ all pass. Framework-free constraint verified (no react/@TanStack in the package or its transitive lib re-exports).🤖 Generated with Claude Code