Skip to content

wallet-sdk PR2: core (Money, errors+classify, events, Sdk shell + wiring)#1120

Closed
orveth wants to merge 2 commits into
sdk/pr1-contractfrom
sdk/pr2-core
Closed

wallet-sdk PR2: core (Money, errors+classify, events, Sdk shell + wiring)#1120
orveth wants to merge 2 commits into
sdk/pr1-contractfrom
sdk/pr2-core

Conversation

@orveth

@orveth orveth commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

PR2 of the @agicash/wallet-sdk build (no-cache contract). Stacked on PR1 (#1119) — base is sdk/pr1-contract. Lands Slice 0 / core on top of PR1's contract types: no domain business logic (those are PR3+).

What this implements (Slice 0)

  • Money — resolved PR1's declare class placeholder. Money is now a real value export, re-exporting the live Money (+ Currency/CurrencyUnit) from apps/web-wallet/app/lib/money via a relative path (single source of truth, zero web churn). lib: ["DOM"] added to the package tsconfig for money.ts's dev-only devtools formatter.
  • Errors + classify — kept the real SdkError/ConcurrencyError/DomainError/NotFoundError; added NotImplementedError (thrown by the stubs). classify(err) → 'transient' | 'permanent' | 'already-resolved' | 'unhandled' is a pure fn (§12, the locked 4-bucket seam): SDK-native errors + cashu-ts MintOperationError/NetworkError/HttpResponseError, mapping NUT codes (11004/11002/20005 → transient per fix(cashu): stop transient outputs-pending (11004) from crashing swap tasks #1115; already-spent/issued/paid/signed → already-resolved; other mint rejections → permanent). The CashuErrorCodes enum is lifted verbatim into src/internal/.
  • Events — real typed TypedEventEmitter<M> (on/once/emit/off/removeAllListeners) backing PR1's public EventEmitter<M> interface (the Sdk exposes the subscribe-only surface; emit/off are internal).
  • Sdk.create + Sdk class — validates config; instantiates the OpenSecret client (configure({apiUrl,clientId})), the SDK-owned Supabase client (schema pinned 'wallet', RLS access token = the OpenSecret JWT via an internal cached/auto-refreshing token provider), threads the storage adapter, builds the event emitter, and wires each domain accessor (auth/user/accounts/cashu/spark/transactions/contacts/transfers/scan/exchangeRate/background) to a stub whose methods throw NotImplementedError. destroy() closes Supabase realtime, clears the token cache + all subscribers (mint-WS/Breez/orchestrator teardown hooks land in S3/S5). clientId auto-generated via crypto.randomUUID() when omitted.

Placeholders resolved vs deferred

  • Resolved now (core): Money (→ real app/lib/money), StorageAdapter (kept structural — see note below), the error classes + classifier, the event emitter.
  • Left for later slices (unchanged PR1 placeholders): ExtendedCashuWallet/BreezSdk (S3), SparkNetwork/Bolt11Invoice/ParsedToken/cashu Proof sub-types (S2/S3), the DB Database types (Supabase client typed loosely now, narrowed when DB types are lifted).

Stubbed for later slices

  • S1 auth + user · S2 accounts + scan · S3 cashu + spark (incl. the executeQuote orchestrator + relocating the classify consumer) · S4 transactions + contacts + transfers · S5 background (leader-election) + realtime→event forwarding. Each stub is a typed seam in src/internal/stub-domains.ts.

Connection-wiring note (needs a decision)

The contract's storage: StorageAdapter + "session-resume via storage adapter" assumed @agicash/opensecret-sdk's pluggable storage. The installed package is @agicash/opensecret, which configures via a module-global configure({apiUrl,clientId}) (no storage param) and persists its own tokens in localStorage (browser-only). So: session resume comes "for free" from the OpenSecret client rehydrating, and the SDK still holds config.storage for the auth slice / future use — but there is no storage-injection seam in the installed package, which means non-browser (MCP/fs) use is not yet possible without the @agicash/opensecret-sdk pluggable-storage work. The StorageAdapter type is kept as PR1's structural shape. Flagged for a follow-up call.

CI (local, package-scoped)

biome format --write packages/wallet-sdk clean; format:check + lint:check + tsc --noEmit all pass. Whole-workspace web-wallet typecheck also passes (Money re-export + tsconfig change cause no regression). A runtime smoke test confirmed: real Money, all 7 classify buckets, Sdk.create wiring, event delivery, stubs throwing NotImplementedError, destroy(), and config validation.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Jun 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agicash Error Error Jun 3, 2026 9:33pm
agicash-root-dir-test Ready Ready Preview, Comment Jun 3, 2026 9:33pm

Request Review

@supabase

supabase Bot commented Jun 3, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project hrebgkfhjpkbxpztqqke because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

…nnection wiring

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
"exclude": ["node_modules"],
"compilerOptions": {
"lib": ["ES2022"],
"lib": ["ES2022", "DOM"],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this needed?

"dependencies": {
"@agicash/opensecret": "catalog:",
"@cashu/cashu-ts": "3.6.1",
"@supabase/supabase-js": "2.95.2",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the idea is to put all libs that are shared by multiple packages/apps in our monorepo to the catalog (@pmilic021 correct me if wrong)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think money needs to be part of sdk. I think we should add antoher package in packgas folder just for the money lib so sdk and whoever else needs it can use it. it's a standalone lib

@orveth

orveth commented Jun 5, 2026

Copy link
Copy Markdown
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.

@orveth orveth closed this Jun 5, 2026
@pmilic021 pmilic021 deleted the sdk/pr2-core branch June 22, 2026 09:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants