Send Wallet
Send is a passkey-based Canton wallet that speaks the splice-wallet-kernel OpenRPC contract and announces itself over canton:announceProvider rather than binding the shared window.canton slot. The dApp connection layer is open-sourced as Sigilry; this PartyLayer adapter wraps that contract with the same surface every other Canton wallet uses.
How Send Differs
Installation
Send is delivered as a browser extension. Direct your users to the Send wallet homepage at sigilry.org for current installation instructions before they can connect.
With PartyLayerKit there is no further wiring: Send is served through the CIP-0103 announce path, so it appears in the wallet picker automatically when the user has Send installed. If you build a custom adapter set and want the bespoke SendAdapter explicitly, register it alongside the built-ins:
getBuiltinAdapters() (that returns Console, Loop, Cantor8, and Nightly). By default Send is discovered through the CIP-0103 announce path, so the explicit SendAdapter above is only needed if you want the bespoke adapter instead of the announce path.Connection Flow
End-to-end user experience:
- User clicks Connect with Send.
- Send extension shows its Connect to Site? permission prompt.
- On approval, the OS surfaces a passkey prompt (Touch ID / Face ID).
- Once unlocked, the SDK receives a session containing
partyId,kernelId, and the wallet's public key.
signMessage, submitTransaction) prompts a fresh passkey unlock — this is by design. Send does not cache passkey approval across calls.Reading the Ledger
Send proxies the Canton v2 JSON Ledger API through Sigilry's ledgerApi RPC method. Use useLedgerApi for any read-side query:
For active-contracts queries with eventFormat, see the Wallet Balances guide — Send accepts the same request shape as the other ledger-API-capable adapters.
Token Standard Transfers (CIP-56)
Send signs and submits transactions in a single step via prepareExecuteAndWait. The wallet handles Scan-side coordination, choice context lookup, and passkey signing internally. Adapter consumers call submitTransaction with a JsPrepareSubmissionRequest:
See Token Transfers for the full CIP-56 flow including the Scan /registry/transfer-instruction/v1/transfer-factory endpoint and the choice-context tagged-union shape.
Amulet_Transfer exercise on Splice.Amulet:Amulet throws an actionable error pointing at this page.Capability Matrix
- connect — supported (Sigilry
connectRPC +getPrimaryAccount) - disconnect — supported
- restore — supported (silent
statusprobe; no popup on reload) - signMessage — supported (passkey-signed)
- signTransaction — not supported; fused into
prepareExecute. Calling it throwsCapabilityNotSupportedErrorpointing atsubmitTransaction. - submitTransaction — supported via
prepareExecuteAndWait; receipt populated fromtx.payload.updateId. - ledgerApi — supported (full Sigilry passthrough; matches Console / Nightly).
- events — supported;
txChangedbridged to PartyLayertx:status. - injected: declared as a capability, but Send is discovered and driven over the
canton:announceProviderchannel rather than by binding the sharedwindow.cantonslot.
Network Support
This adapter integrates with Send on canton:mainnet.
localhost:3000 defaults its network label to devnet. That label reflects the demo's configuration — not the actual network the connected wallet sits on. Send's adapter reads the live network via its getActiveNetwork() provider call and reports canton:mainnet when Send is active. dApps that ship to production should configure PartyLayerKit with network="mainnet" when targeting Send.Troubleshooting
- "Send not detected": the extension is missing, or Send did not announce over
canton:announceProviderwithin the detection window. Send announces on its own channel and does not depend on owningwindow.canton; install Send and reload. - "Connection cancelled" — the user dismissed the passkey prompt or the extension popup. Triggering connect again is safe.
- "Authentication Failed: Cannot reach authentication server" — Send's backend at
auth.cantonwallet.comis unreachable. Check network and retry. - "OAuth state mismatch" — stale Send session. Clear cookies for
cantonwallet.comand reconnect. - Transaction errors with hint "Execute Unknown on Unknown" — legacy
Amulet_Transferexercise onSplice.Amulet:Amulet. Migrate to CIP-56TransferFactory_Transfer; see Token Transfers.
Security Notes
- Private keys never leave the extension. Passkey signing happens on the user's device through WebAuthn-PRF; PartyLayer never touches the underlying key material.
- Session JWT is held by the extension. The adapter receives an access token in
status.session.accessTokenfor the lifetime of the connection; PartyLayer's session-persistence layer encrypts state at rest in the dApp's configured storage. - Announce-scoped channel. Send is discovered and every RPC is routed over the dedicated
canton:announceProviderchannel that Send advertises. Because the channel is bound to the announcing extension, the adapter never acts on a foreign provider that happens to ownwindow.canton; if Send does not announce, the adapter cleanly returns not installed and yields to the matching adapter.