paritytech / paritytech/dotns

[Bug]: The UI wallet store discards permission results and never revalidates per-account state

Open
#228 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

dotns-sdk P2 type: bug
Dominant language
Solidity
Stars
4
Forks
2
Avg merge
1d 18h
Merged PRs (30d)
24

Description

Component

Other

Priority

P2

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
  1. Decline the ChainSubmit prompt, then attempt any write. The timeline stays on "Signing" with no error; the rejection appears only in the console.
  2. With a session established, force a host reconnect, then attempt a write. It is signed with the pre-reconnect signer.
  3. 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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in packages/ui/src/store/useWalletStore.ts, tracing requestWritePermissions, ensureSignerReady, ensureReady, the connection subscription, and handleDisconnect. Then inspect services/AppInitializer.ts, components/RegisterModal.vue, and components/WalletButton.vue for derived state and reconnect behavior. Done means failed grants surface a permission error, account or provider changes refresh state, disconnect clears transaction status, and the header can reconnect.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.