Component
Other
Priority
P1
What happened?
Three defects in packages/ui/src/store/useWalletStore.ts with one root cause: state is captured at connect and never revalidated, and grant results are discarded.
Grants are requested and ignored. ensureSignerReady:279 discards the ensureChainSubmit() boolean, and requestWritePermissions:87-94 swallows both a non-Allocated result and a throw. A signer is returned either way. The store's comment at :112-113 records the consequence: the host then rejects every write with PermissionDenied, "often as a silent hang".
The signer is a connect-time snapshot. injected (:179) is never replaced, and the subscription at :224-228 reacts only to status === "disconnected". The SDK's attemptReconnect builds a new provider and new accounts and returns to connected, which goes unnoticed, and ensureReady:252 refuses to refresh because injected is still non-null. Later writes sign with a dead signer.
Derived state is never refreshed. userPopState is written only at services/AppInitializer.ts:34-38, and components RegisterModal.vue:391-411 gates requirementMet on it, so after an account switch or reconnect a verified user's Register button is disabled with no explanation while the search panel still offers it. handleDisconnect:207-218 also leaves transactionStatus set, wedging the timeline mid-flight under a "Not signed in" header.
There is no recovery path: connectWallet() is reachable only from two docs demos, and components/WalletButton.vue:17-20 no action, so a page reload is the only way back.
Expected behavior
- A denied or failed grant fails the write with a message naming the missing permission, instead of submitting and hanging.
- The store keys on account and provider identity rather than connection status alone, and refreshes the signer and any per-account derived state when either changes.
- Disconnect resets transaction state.
- The header offers a way to reconnect without reloading.
Reproduction
- Decline the ChainSubmit prompt, then attempt any write. The timeline stays on "Signing" with no error; the rejection appears only in the console.
- With a session established, force a host reconnect, then attempt a write. It is signed with the pre-reconnect signer.
- Switch account in the host, then open the register modal for a name requiring PoP. Register is disabled even for a verified account.
Additional context
Related to #227: a failed personhood read also yields NoStatus through safeRead, so the disabled Register button has two possible causes. This issue covers the not-refetched half.
Component
Other
Priority
P1
What happened?
Three defects in
packages/ui/src/store/useWalletStore.tswith one root cause: state is captured at connect and never revalidated, and grant results are discarded.Grants are requested and ignored.
ensureSignerReady:279discards theensureChainSubmit()boolean, andrequestWritePermissions:87-94swallows both a non-Allocatedresult and a throw. A signer is returned either way. The store's comment at:112-113records the consequence: the host then rejects every write with PermissionDenied, "often as a silent hang".The signer is a connect-time snapshot.
injected(:179) is never replaced, and the subscription at:224-228reacts only tostatus === "disconnected". The SDK'sattemptReconnectbuilds a new provider and new accounts and returns toconnected, which goes unnoticed, andensureReady:252refuses to refresh becauseinjectedis still non-null. Later writes sign with a dead signer.Derived state is never refreshed.
userPopStateis written only atservices/AppInitializer.ts:34-38, andcomponents RegisterModal.vue:391-411gatesrequirementMeton it, so after an account switch or reconnect a verified user's Register button is disabled with no explanation while the search panel still offers it.handleDisconnect:207-218also leavestransactionStatusset, wedging the timeline mid-flight under a "Not signed in" header.There is no recovery path:
connectWallet()is reachable only from two docs demos, andcomponents/WalletButton.vue:17-20no action, so a page reload is the only way back.Expected behavior
Reproduction
Additional context
Related to #227: a failed personhood read also yields
NoStatusthroughsafeRead, so the disabled Register button has two possible causes. This issue covers the not-refetched half.