refactor(wallets): extract shared quorum member matching (M4-4 part 1/4) - #1997
Conversation
…uorum-members Introduces getQuorumMemberLocator/matchesQuorumMember and the ResolvedQuorumMember type, and rewires WalletFactory.isMatchingQuorumMember onto the shared helper (now also wiping derived key bytes after address comparison). No behavior change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Prompt To Fix All With AI### Issue 1
packages/wallets/src/wallets/wallet-factory.ts:517-534
**Naming inversion at the call site**
The local parameter `candidate` in `isMatchingQuorumMember` is the API-returned member, but it maps to the `member` parameter of `matchesQuorumMember`. Conversely, `method` (the user-supplied config) maps to the function's `candidate` parameter. Because both types resolve to `{ type: string } & Record<string, unknown>`, TypeScript cannot catch a future accidental swap, and the asymmetry makes the relationship between the two functions non-obvious. Adding a brief inline note or renaming the local `candidate` parameter (e.g. `quorumMember`) to reflect its role as the API-returned member would make the call site self-documenting.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "refactor(wallets): extract shared quorum..." | Re-trigger Greptile |
| export type ResolvedQuorumMember = Record<string, unknown> & { | ||
| type: string; | ||
| locator?: string; | ||
| address?: string; | ||
| email?: string; | ||
| phone?: string; | ||
| id?: string; | ||
| name?: string; | ||
| }; |
There was a problem hiding this comment.
Shouldn't this be a discriminated union?
| if (typeof member.locator === "string") { | ||
| return member.locator; | ||
| } |
There was a problem hiding this comment.
How can it not have a locator?
Linear: WAL-11292 · EDD §6.5 · Stacked on M4-3 (#1993) · Part 1/4 of the M4-4 stack (split from #1996)
Summary
Pure refactor + new shared utility, no behavior change. Extracts the quorum-member matching that
WalletFactory.isMatchingQuorumMemberdid inline intosrc/utils/quorum-members.ts, so theuseSignerselection flows (part 4) andSignerManager(part 2) can reuse the exact same per-type semantics:matchesQuorumMember(candidate, member, serverCandidateAddresses)— per-type matching (email normalized, phone exact, external-wallet by address, passkey by id → name → permissive, server by derived addresses incl. legacy). Server derivation is injected so each caller plugs its own provider.getQuorumMemberLocator(member)— API locator when present, derived fallback otherwise.ResolvedQuorumMembertype: API identity fields + index signature admitting runtime fields (serversecret, external-walletonSign, passkey callbacks) that later parts graft on.The factory now delegates to the shared matcher and — the one incidental fix — wipes the derived key bytes after the address comparison (
secureWipe), which the inline version omitted.Testing
quorum-members.test.tsmatcher table (all member types, normalization, permissive passkey, server candidate injection).packages/walletssuite: 708 passed.🤖 Generated with Claude Code