Skip to main content
These are the methods that wallets should implement to handle Canton transactions and messages via WalletConnect.

Network / Chain Information

  • Namespace: canton
  • CAIP-2: canton:<network-id> (e.g. canton:devnet, canton:production)
  • CAIP-10 Account: canton:<network-id>:<url-encoded-party-id> (e.g. canton:devnet:operator%3A%3A1220abc...)
Unlike most chains, Canton does not have fixed mainnet/testnet identifiers. Network IDs are operator-defined — each wallet is configured with one or more networks, and the network-id used in CAIP-2 identifiers comes from that configuration. dApps should not hardcode specific chain IDs in the session proposal. Instead, request the canton namespace without specifying chains, and work with whatever network the wallet provides in the approved session. The network ID and party ID are available directly from the session’s canton.accounts array as CAIP-10 strings (e.g. canton:production:operator%3A%3A1220abc...). For full network details, use getActiveNetwork.

Registered Methods & Events

const CANTON_WC_METHODS = [
    'canton_prepareSignExecute',
    'listAccounts',
    'getPrimaryAccount',
    'getActiveNetwork',
    'status',
    'ledgerApi',
    'signMessage',
]

const CANTON_WC_EVENTS = ['accountsChanged', 'statusChanged', 'chainChanged']

Auto-Approve vs Manual-Approve

Read-only methods are auto-approved by the wallet. Methods that mutate the ledger or perform sensitive operations require explicit user approval.
MethodApproval
listAccountsAuto-approve
getPrimaryAccountAuto-approve
getActiveNetworkAuto-approve
statusAuto-approve
ledgerApiAuto-approve
canton_prepareSignExecuteManual
signMessageManual

Method Name Mapping (dApp SDK)

The dApp SDK’s WalletConnectTransport maps SDK method names before sending over WC:
SDK methodWC method (on the wire)
prepareExecutecanton_prepareSignExecute
prepareExecuteAndWaitcanton_prepareSignExecute
All other methods (listAccounts, status, ledgerApi, etc.) are sent as-is. Both SDK methods resolve with the same response — over WalletConnect, every submission blocks until the transaction completes.

RPC Methods

canton_prepareSignExecute

Prepare, sign, and execute a Canton ledger transaction. This is the primary method for submitting commands that mutate ledger state. The wallet performs the full prepare → sign → execute cycle and responds when the transaction is complete.

Request

interface PrepareSignExecuteRequest {
    method: 'canton_prepareSignExecute';
    params: PrepareParams;
}

interface PrepareParams {
    commandId?: string;          // auto-generated (UUIDv4) if omitted
    commands?: { [k: string]: unknown };
    actAs?: string[];            // defaults to [primaryWallet.partyId] if omitted
    readAs?: string[];           // defaults to [] if omitted
    disclosedContracts?: Array<{
        templateId?: string;
        contractId?: string;
        createdEventBlob: string;
        synchronizerId?: string;
    }>;
    packageIdSelectionPreference?: string[];
}

Example Request

{
    "topic": "<session-topic>",
    "chainId": "canton:devnet",
    "request": {
        "method": "canton_prepareSignExecute",
        "params": {
            "commands": {
                "0": {
                    "ExerciseCommand": {
                        "templateId": "#<package-id>:Module:Template",
                        "contractId": "00abcdef...",
                        "choice": "Transfer",
                        "choiceArgument": {
                            "receiver": "bob::1220..."
                        }
                    }
                }
            },
            "commandId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
            "actAs": ["operator::1220abc..."],
            "readAs": [],
            "disclosedContracts": [
                {
                    "templateId": "#<package-id>:Module:Template",
                    "contractId": "00abcdef...",
                    "createdEventBlob": "<base64-encoded-blob>",
                    "synchronizerId": "wallet::1220e7b..."
                }
            ],
            "packageIdSelectionPreference": ["<package-id>"]
        }
    }
}

Signing Providers

Wallets support multiple signing backends. The signing provider determines the Ledger API flow used:
ProviderFlow
participantSingle call to POST /v2/commands/submit-and-wait (participant signs internally)
wallet-kernelPOST /v2/interactive-submission/prepare → local Ed25519 sign → POST /v2/interactive-submission/execute
blockdaemonPOST /v2/interactive-submission/prepare → sign via Blockdaemon API → POST /v2/interactive-submission/execute

Success Response

{
    "id": 1234,
    "jsonrpc": "2.0",
    "result": {
        "status": "executed",
        "commandId": "d290f1ee-...",
        "payload": {
            "updateId": "tx-update-id",
            "completionOffset": 42
        }
    }
}

Error Response

{
    "id": 1234,
    "jsonrpc": "2.0",
    "error": {
        "code": 5001,
        "message": "Transaction execution failed: INVALID_ARGUMENT: ..."
    }
}

User Rejected Response

{
    "id": 1234,
    "jsonrpc": "2.0",
    "error": {
        "code": 5000,
        "message": "User rejected"
    }
}

listAccounts

Retrieve all configured wallet accounts.

Request

{
    "topic": "<session-topic>",
    "chainId": "canton:devnet",
    "request": {
        "method": "listAccounts",
        "params": {}
    }
}

Response

{
    "id": 1235,
    "jsonrpc": "2.0",
    "result": [
        {
            "primary": true,
            "partyId": "operator::1220abc...",
            "status": "allocated",
            "hint": "operator",
            "publicKey": "<base64-ed25519-pubkey>",
            "namespace": "1220abc...",
            "networkId": "canton:production",
            "signingProviderId": "participant",
            "disabled": false
        }
    ]
}

Wallet Type

interface Wallet {
    primary: boolean;
    partyId: string;
    status: 'initialized' | 'allocated' | 'removed';
    hint: string;
    publicKey: string;
    namespace: string;
    networkId: string;
    signingProviderId: string;
    externalTxId?: string;
    topologyTransactions?: string;
    disabled?: boolean;
    reason?: string;
}

getPrimaryAccount

Retrieve the primary wallet account (where primary === true).

Request

{
    "topic": "<session-topic>",
    "chainId": "canton:devnet",
    "request": {
        "method": "getPrimaryAccount",
        "params": {}
    }
}

Response

{
    "id": 1236,
    "jsonrpc": "2.0",
    "result": {
        "primary": true,
        "partyId": "operator::1220abc...",
        "status": "allocated",
        "hint": "operator",
        "publicKey": "<base64-ed25519-pubkey>",
        "namespace": "1220abc...",
        "networkId": "canton:production",
        "signingProviderId": "participant"
    }
}

getActiveNetwork

Retrieve the currently active network configuration.

Request

{
    "topic": "<session-topic>",
    "chainId": "canton:devnet",
    "request": {
        "method": "getActiveNetwork",
        "params": {}
    }
}

Response

{
    "id": 1237,
    "jsonrpc": "2.0",
    "result": {
        "networkId": "canton:production",
        "ledgerApi": "http://127.0.0.1:5003"
    }
}

status

Check the wallet’s connectivity to the Canton ledger.

Request

{
    "topic": "<session-topic>",
    "chainId": "canton:devnet",
    "request": {
        "method": "status",
        "params": {}
    }
}

Response (ledger reachable)

{
    "id": 1238,
    "jsonrpc": "2.0",
    "result": {
        "provider": {
            "id": "remote-da",
            "version": "3.4.0",
            "providerType": "remote"
        },
        "connection": {
            "isConnected": true,
            "isNetworkConnected": true
        },
        "network": {
            "networkId": "canton:production",
            "ledgerApi": "http://127.0.0.1:5003"
        }
    }
}

Response (ledger unreachable)

{
    "id": 1238,
    "jsonrpc": "2.0",
    "result": {
        "provider": {
            "id": "remote-da",
            "version": "3.4.0",
            "providerType": "remote"
        },
        "connection": {
            "isConnected": true,
            "isNetworkConnected": false,
            "reason": "Ledger unreachable"
        }
    }
}

ledgerApi

Proxy raw Canton Ledger API requests through the wallet. The wallet authenticates and forwards the request.

Request

interface LedgerApiRequest {
    method: 'ledgerApi';
    params: LedgerApiParams;
}

interface LedgerApiParams {
    requestMethod: 'GET' | 'POST';
    resource: string;
    body?: string | object;
}

Example Request

{
    "topic": "<session-topic>",
    "chainId": "canton:devnet",
    "request": {
        "method": "ledgerApi",
        "params": {
            "requestMethod": "POST",
            "resource": "/v2/state/active-contracts",
            "body": {
                "filter": {
                    "filtersByParty": {
                        "operator::1220abc...": {
                            "cumulative": {
                                "templateFilters": []
                            }
                        }
                    }
                }
            }
        }
    }
}

Response

{
    "id": 1239,
    "jsonrpc": "2.0",
    "result": {
        "response": {
            "version": "3.4.0",
            "features": {}
        }
    }
}
The response field contains the raw Ledger API JSON response as-is.

signMessage

Sign an arbitrary message with the wallet’s Ed25519 private key.

Request

interface SignMessageRequest {
    method: 'signMessage';
    params: {
        message: string;
    };
}

Example Request

{
    "topic": "<session-topic>",
    "chainId": "canton:devnet",
    "request": {
        "method": "signMessage",
        "params": {
            "message": "Please sign this message to verify your identity"
        }
    }
}

Success Response

{
    "id": 1240,
    "jsonrpc": "2.0",
    "result": {
        "signature": "<base64-ed25519-signature>",
        "publicKey": "<base64-ed25519-pubkey>"
    }
}

Events

accountsChanged

Emitted when wallet accounts are added, removed, or modified.
{
    "name": "accountsChanged",
    "data": [
        {
            "primary": true,
            "partyId": "operator::1220abc...",
            "status": "allocated",
            "hint": "operator",
            "publicKey": "...",
            "namespace": "1220abc...",
            "networkId": "canton:production",
            "signingProviderId": "participant"
        }
    ]
}

statusChanged

Emitted when the wallet’s connectivity status changes.
{
    "name": "statusChanged",
    "data": {
        "provider": { "id": "remote-da", "providerType": "remote" },
        "connection": { "isConnected": true, "isNetworkConnected": true },
        "network": { "networkId": "canton:production" }
    }
}

chainChanged

Emitted when the wallet switches to a different network.
{
    "name": "chainChanged",
    "data": {
        "chainId": "canton:production"
    }
}

Session Lifecycle

Pairing

The dApp creates a pairing URI and delivers it to the wallet:
const { uri, approval } = await signClient.connect({
    optionalNamespaces: {
        canton: {
            methods: CANTON_WC_METHODS,
            events: CANTON_WC_EVENTS,
        },
    },
})

Session Approval

The wallet builds approved namespaces including the CAIP-10 account with the URL-encoded partyId:
{
    "canton": {
        "chains": ["canton:devnet"],
        "accounts": ["canton:devnet:operator%3A%3A1220abc..."],
        "methods": ["canton_prepareSignExecute", "listAccounts", "getPrimaryAccount", "getActiveNetwork", "status", "ledgerApi", "signMessage"],
        "events": ["accountsChanged", "statusChanged", "chainChanged"]
    }
}

Error Codes

CodeMeaning
5000User rejected
5001Execution / handler error
5100Canton namespace not found in proposal
6000Wallet disconnected

Notes & Considerations

  • All requests and responses comply with JSON-RPC structure (id, jsonrpc, etc.).
  • Canton uses Ed25519 signing for transaction authentication.
  • The ledgerApi method acts as a transparent proxy — the wallet handles authentication with the Canton Ledger API. Only GET and POST are supported; other HTTP methods will return a 5001 error.
  • Party IDs in CAIP-10 accounts are URL-encoded (e.g. operator::1220abc... becomes operator%3A%3A1220abc...).
  • The canton_prepareSignExecute method always performs the full prepare → sign → execute cycle synchronously, responding only when the transaction is complete.
  • The WC session chainId (e.g. canton:devnet) may differ from the networkId in wallet/network records (e.g. canton:production). The chainId identifies the chain at pairing time, while networkId reflects the wallet’s internal network configuration.