plan to add state to accounts for expiring and soft deleting#960
plan to add state to accounts for expiring and soft deleting#960
state to accounts for expiring and soft deleting#960Conversation
Two bugs with v2 keysets: getDecodedToken fails without keyset IDs for resolution, and re-encoded tokens have truncated IDs that can't be looked up. Fix uses dependency-injected keyset resolver with cache-first strategy, plus raw token string passthrough in paste/scan.
- extractCashuTokenString validates via getTokenMetadata (not just regex) - extractCashuToken uses try/catch like cashu.me for v2 detection - Preserves immediate validation UX in paste/scan handlers
4 tasks: token functions + tests, resolver factory, paste/scan handlers, route clientLoaders. Includes v2-specific tests with round-trip verification.
Design doc for adding active/expired/deleted lifecycle to wallet.accounts. Covers DB migration (enum, transition trigger, partial unique index, RLS, pg_cron auto-expiry), app-layer changes, and data flow diagrams. For review/discussion before implementation.
|
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. |
No longer needed — account state lifecycle replaces this approach.
Client-side expiry in upsert_user_with_accounts transitions stale accounts before returning them. pg_cron remains as background cleanup for offline users.
Each DB function's WHERE clause only matches valid source states. soft_delete_account gains AND state != 'deleted' guard.
|
|
||
| ### 6. Realtime handling for deleted accounts | ||
|
|
||
| The `ACCOUNT_UPDATED` handler must detect `state === 'deleted'` in the broadcast payload and call `accountCache.remove(id)` rather than `accountCache.update(account)`. |
There was a problem hiding this comment.
I'm not sure if this makes sense because of what claude said in 1, but I'll look more when I build
| ### Soft delete DB function | ||
|
|
||
| ```sql | ||
| create or replace function "wallet"."soft_delete_account"(p_account_id uuid) |
There was a problem hiding this comment.
should it be called soft delete or just delete?
| if not found then | ||
| raise exception | ||
| using | ||
| hint = 'NOT_FOUND', |
There was a problem hiding this comment.
if not found because account is already deleted should this return a different error message that its already deleted?
|
|
||
| This runs inside the existing transaction, before the `accounts_with_proofs` CTE that fetches accounts. The client receives already-expired accounts with `state = 'expired'` — no second round-trip needed. | ||
|
|
||
| ### pg_cron job for auto-expiry |
There was a problem hiding this comment.
I was thinking we should keep this around for when the user doesn't open the app for a long time, but do you think its needed
| ### `gift-cards.tsx` -- Simplify filter | ||
|
|
||
| ```typescript | ||
| function useActiveOffers() { |
There was a problem hiding this comment.
this is from code I haven't committed yet btw
state to accounts for expiring and soft deleting
Summary
Design spec for adding
active → expired → deletedlifecycle towallet.accounts. For review/discussion before implementation.active → expiredhourly whenexpires_atpassesstate = 'active'so expired/deleted accounts don't block new ones at the same mintWhat this enables
Open questions
No code changes — spec only.