PartyLayerDocs
Try Demo

wagmi for Canton developers

If you have built an EVM frontend, you already know most of the shape of a Canton one. This page maps what you know onto what PartyLayer gives you, and then spends most of its length on the places where the analogy stops working, because those are the ones that cost time.

ℹ️ Note
Sources and versions. wagmi hook names were read from wagmi's own hook reference at version 3.7.7, verified 2026-09-03. The version is pinned here because it is the claim on this page most likely to go stale without anything telling us: wagmi renames hooks across majors. Both matter, because wagmi renamed several hooks in v3 and a mapping written from memory would be wrong on the most familiar one: useAccount no longer exists in wagmi. It is useConnection now.

The first thing that will confuse you

PartyLayer has a hook called useAccount. wagmi does not, any more. If you arrive from wagmi v3 expecting useConnection and reach for the name you used in v2, you will find it here and it will work, which is more disorienting than if it were missing. Ours reports the connected party, not an EVM address.

What maps cleanly

Connection and signing are close enough that porting is mechanical.

wagmi 3.7.7PartyLayerNotes
WagmiProvider + createConfigPartyLayerKitOne provider at the root. Adapters replace connectors.
useConnectionuseAccountReports the connected party id, not an address.
useConnectuseConnectSame shape. Takes a wallet id rather than a connector.
useDisconnectuseDisconnectSame.
useConnectorsuseWalletsRegistry-backed rather than statically configured.
useSignMessageuseSignMessageSame intent. Check the base64 note below.
useSendTransactionuseSubmitTransactionSubmits Daml commands, not calldata.
useWaitForTransactionReceiptsubmit resultAwaited in the submit call, not a separate hook.
ConnectButton (RainbowKit)ConnectButtonDrop-in, themeable. See Theming.

Side by side, the connect flow you already know:

typescript
// wagmi 3.x
import { WagmiProvider, createConfig, http } from 'wagmi';
import { useConnection, useConnect } from 'wagmi';

// PartyLayer
import { PartyLayerKit, ConnectButton, useAccount, useConnect } from '@partylayer/react';

function App() {
  return (
    <PartyLayerKit network="devnet">
      <Profile />
      <ConnectButton />
    </PartyLayerKit>
  );
}

function Profile() {
  const { partyId, isConnected } = useAccount();
  if (!isConnected) return null;
  return <span>{partyId}</span>;
}

Where the analogy breaks

These are not gaps waiting to be filled. They follow from Canton being privacy-first and contract-based rather than account-and-storage based, so a hook that papers over them would be lying.

1. There is no useReadContract, because there is no public state

This is the big one. On an EVM chain any client can read any storage slot, which is what makes useReadContract possible without a wallet. On Canton you can only read contracts you are a witness to, and what you are a witness to depends on which party you are. There is no global state to query.

So reads are party-scoped and require a connection. useTokenHoldings, useDamlContract and useLedgerApi all read as the connected party, and a different party running the same code legitimately sees different results. Privacy and reads covers how visibility actually works.

Practical consequence: a landing page that shows chain data before the user connects has no Canton equivalent. Design for connect-first.

2. No ABI. Templates and choices instead

There is no ABI to import and no function selector. A Daml contract is a template instance, and you act on it by exercising a named choice. useChoice is the closest thing to useWriteContract, and the shape it takes is a command, not an encoded call.

3. Contracts are archived and recreated, not mutated

Exercising a choice typically archives the current contract and creates a successor. There is no in-place update, so a contract id is not a stable handle across a state change the way an EVM address is. Code that caches a contract id and reuses it after a write will be holding a reference to an archived contract.

4. useSwitchChain has no working equivalent

Not a design position on our side, a fact about the ecosystem today: every wallet in the registry declares switchNetwork: false, all ten of them. You can see it in the capability matrix on the Canton wallet directory, which is generated from the registry, so if that changes the page changes.

Configure the network on PartyLayerKit and treat it as fixed for the session. A multi-network app mounts per network rather than switching in place.

5. Gas is traffic, and it is priced differently

There is no gas price to estimate and no priority fee to bid. Canton charges for traffic, and the cost of a submission can be read before you submit it rather than estimated. See Performance for the measured side, and the cost hooks for pre-submission estimates. Nothing here corresponds to useEstimateFeesPerGas.

6. A party id is not an address

An EVM address is derived from a keypair, so anyone can compute one offline and it is self-certifying. A Canton party id is allocated on a participant node and carries a namespace. You cannot derive it from a public key alone, and two parties can be backed by the same key material. Treat it as an identifier issued to the user, not as a hash of their key.

7. Some transactions need more than one signature

A Daml choice can require several signatories, which has no EVM single-signer equivalent and is not a multisig contract pattern either: it is in the model. If your app coordinates two parties, read Multi-party patterns before designing the flow, because retrofitting it is expensive.

⚠️ Warning
One porting trap worth naming. Console Wallet base64-encodes a message's UTF-8 bytes before signing, recorded in its registry entry as signMessageBase64: true. If you verify a signature against raw bytes the way you would with personal_sign, it will not match. Per-wallet notes are on the wallet directory.

If you are porting an app

  • Start from Quick Start. The connect layer is the part that ports mechanically, so get it working first and it will feel familiar.
  • Then find every read in your app that runs before connect. Those are the ones that need rethinking, and there are usually more than you expect.
  • Replace ABI-and-selector thinking with template-and-choice thinking before you write the write path. Token transfers is a worked example.
  • Check the wallet directory for what your target wallets actually support through their adapters. Capability flags there map to specific hooks, and several wallets do not implement signing at all.
PreviousGeneric BridgeNextDev & Staging