React SDK: subscription primitive for account-state updates driven by external consumers
- Dominant language
- TypeScript
- Stars
- 1
- Forks
- 21
- Avg merge
- 12h 14m
- Merged PRs (30d)
- 41
Description
## Context
`@miden-sdk/react` exposes [`useWaitForCommit`](https://github.com/0xMiden/miden-client) to wait on transactions submitted *by the local client*. There is no equivalent hook for the case where:
- The local WebClient **tracks** an account (network-mode or public), but
- A state change is driven by a transaction the **local client never submitted or saw** — e.g. a note consumed by the network operator, or a note consumed by a different client whose effect we care about.
A concrete example lives in the [Miden frontend template](https://github.com/0xMiden/frontend-template) — `src/hooks/useIncrementCounter.ts`:
1. The user submits an increment note via the MidenFi wallet (so the local WebClient never gets the tx into its log).
2. The network operator picks up the note (`NoteAttachment::newNetworkAccountTarget`) and executes it against the counter account.
3. The frontend needs to observe the counter's storage-map value changing.
Because step 1 bypasses the local client and step 2 happens remotely, `useWaitForCommit` cannot help. The template currently works around this with a fixed-interval poll (2.5 s, 30 s timeout) that calls `client.syncState()` + reads the storage map in a loop, which is wasteful and bounded by an arbitrary timeout.
## Proposal
Add a React-SDK-level primitive along the lines of:
```ts
// Resolves when the account's digest (or a specified storage slot/map entry) changes
// past the given baseline, or rejects on timeout/unsubscribe.
const { promise, unsubscribe } = useWaitForAccountUpdate(accountId, {
baselineDigest, // optional: what we consider \"old\"
slot, // optional: narrow to a specific storage slot / map key
timeoutMs,
});
```
or a lower-level observable:
```ts
const stream = client.subscribeAccountUpdates(accountId);
for await (const update of stream) { ... }
```
Implementation could be internal to the WebClient — e.g. a Dexie observable on the local store (as suggested by @evanmarshall in 0xMiden/miden-client#467), or a push-based subscription once [`#467`](https://github.com/0xMiden/miden-client/issues/467) lands an event-listener framework in the Rust core.
## Relation to 0xMiden/miden-client#467
[#467](https://github.com/0xMiden/miden-client/issues/467) tracks the general \"allow users to react to events\" design in the Rust client. This issue is narrower and targeted at the **React / WebClient** layer: exposing an idiomatic hook/API for the frontend use case above. Depending on scoping, this can either:
- Land as a thin wrapper over whatever 0xMiden/miden-client#467 produces, or
- Ship independently as a WebClient-only primitive (e.g. via Dexie observables on the IndexedDB store), since the WebClient has specific ergonomics and need not wait on the full Rust-side redesign.
## Acceptance criteria
- Frontend code no longer needs a fixed-interval poll loop to observe externally-driven account-state updates.
- The primitive correctly fires when either (a) the network operator consumes a note targeting the tracked account, or (b) any other external client submits a tx that updates the tracked account.
- Cleanly cancellable (component unmount, route change) without leaking timers/listeners.
## Workaround reference
For context, the workaround code + inline rationale:
https://github.com/0xMiden/frontend-template/blob/main/src/hooks/useIncrementCounter.ts
Contributor guide
Research direction
Look at the existing `useWaitForCommit` hook in the React SDK and the WebClient's internal store (likely using Dexie/IndexedDB). Examine the workaround in the frontend-template's `useIncrementCounter.ts`. The goal is to create a new hook or subscription primitive that observes external account-state changes. Start by understanding how the client tracks accounts and syncs state (`client.syncState()`). 'Done' means the frontend template can replace its polling loop with the new primitive.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- nodejs, react, typescript
- Domain
- api, frontend, tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100