Skip to content

Decide how close canton-connect's hook results sit to wagmi's #52

Description

@fernandomg

User story / Problem statement

canton-connect is described as wagmi-style, and at the level that matters most it is: the hook
names and the split of responsibility match, so a developer arriving from wagmi knows which hook to
reach for. Each hook's JSDoc now names its wagmi counterpart (usePartyuseAccount,
useExecuteuseWriteContract + useWaitForTransactionReceipt, and so on).

The resemblance stops at the return shapes. wagmi's mutation hooks are wrappers around TanStack
Query's useMutation, so they return mutate / mutateAsync / isPending / data / status /
failureCount / reset. Ours resolve plain promises and return domain-named fields:
isSigning, isExecuting, signature, lastTx. Someone with wagmi muscle memory reaches for
isPending and data and doesn't find them.

That is a real papercut, but the fix has two very different sizes, and conflating them is how this
turns into an accidental architecture change.

Proposed solution

Level 1 — align the vocabulary. No new dependency.

Rename the status flags to wagmi's uniform isPending (replacing isSigning and isExecuting),
and keep error and reset, which already match. This is a pure rename of the public surface,
free right now because the package has no consumers.

Deliberately not proposed: renaming the payloads to data. useSignMessage().signature is
clearer than data, and useExecute().lastTx is not wagmi's data at all — see below. Adopting
data everywhere buys canonicality at the cost of saying less. Worth arguing either way, which is
why it is an open question rather than an acceptance criterion.

Level 2 — actually adopt TanStack Query. New peer dependency, consumer-visible.

This is what would make the hooks genuinely wagmi-shaped: useMutation under the covers, so
mutate/mutateAsync/status/failureCount come for free, plus useQuery for reads. It also
requires every consumer to wrap the app in a QueryClientProvider and pulls the package's users
into a specific data-layer choice — a heavy import for a package whose stated value is being thin
and cheap to delete once the SDK ships hooks of its own.

Recommendation: do Level 1 if the papercut is worth a rename; hold Level 2 until the package
grows a read surface.
TanStack Query earns its keep on cached, refetchable, deduplicated
queries. Today this package has three write-shaped operations (sign, execute, ledger call) and two
context reads (party, status), and mutations don't cache. The moment useLedger becomes typed
cached reads — ACS queries, balances, listAccounts — the calculus flips and Level 2 becomes the
obvious answer rather than ceremony.

One Canton-specific reason not to force the fit. wagmi's mutations model one request producing
one result. useExecute().lastTx models a wallet-pushed lifecycle — pending → signed → executed
or failed — arriving as txChanged events after the call resolves. wagmi's nearest equivalent
splits that across useWriteContract (submit) and useWaitForTransactionReceipt (one receipt at
the end); it has no concept of a status stream from the wallet. Mapping lastTx onto data would
misrepresent it. Whatever shape this lands on, the tx lifecycle stays a first-class field of its
own.

Acceptance criteria

  • isSigning and isExecuting become isPending, uniformly across the hooks that have a
    pending state
  • The open question is decided and recorded: domain-named payloads (signature, lastTx) or
    wagmi's generic data
  • Each hook's JSDoc states plainly where its result shape diverges from its wagmi counterpart,
    so the counterpart line can't be read as a promise of drop-in compatibility
  • README.md's hook table matches whatever is decided
  • A decision is recorded on Level 2 — adopt TanStack Query, or defer with the trigger written
    down (the first cached read the package needs)
  • lastTx keeps its own field regardless, with the reason recorded: it is an event stream, not
    a mutation result

Out of scope

  • Adding @tanstack/react-query as a dependency in this issue. If Level 2 wins, it gets its own
    issue with the QueryClientProvider requirement spelled out for consumers.
  • Renaming the hooks themselves. The names already match wagmi and are not in question.

Metadata

Metadata

Assignees

Labels

area: connectcanton-connect: hooks, adapters, session, SDK facadeenhancementNew feature or requestpriority: lowNice to have, can wait

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions