Skip to main content

CIP-0103 — dApp API

CIP-0103 is the Canton standard a website uses to talk to a wallet. The machine-readable spec is the sync OpenRPC document in the Splice wallet kernel. This page is the Ekiden reading of that spec: what we implement, and the one method we refuse. Specification: CIP-0103.
Browser discovery: Canton docs — browser extension.
Attach discovery, connect, and submit beside this page.

Discovery

The Canton SDK does not look for window.ekidenWallet or window.canton. It dispatches canton:requestProvider and collects canton:announceProvider for a few hundred milliseconds. Ekiden announces: The SDK’s provider id is browser:ext:ekiden-wallet. A dApp that does not want auto-discovery can register the extension itself:
window.ekidenWallet on the page is only a marker (isEkiden, id, name, version). Call the SDK, not that object.

Wire protocol

Requests and responses are window.postMessage frames. Request:
Success:
Failure uses response.error with { code, message, data? }. Events are the same request frame without id:
Frames whose target is set and is not ekidenWallet are ignored.

Methods

prepareExecute params are a JSON Ledger API prepare body: commands (required), plus optional commandId, actAs, synchronizerId, disclosedContracts. A nested params.params object is flattened.

Events

txChanged.status is pending (approval opened), executed (payload.updateId, payload.completionOffset), or failed (user rejected, or submit failed). Ekiden does not emit a separate signed event; signing and submit are one approval.

Errors

CIP-0103 uses the EIP-1193 / EIP-1474 codes. On the SPLICE_WALLET_* path Ekiden returns: The named Ekiden SDK methods (ekidenWallet.connect, …) still reject with Error.message and no code. ekidenWallet.request uses the codes above.

Gaps

ledgerApi

CIP-0103 says a wallet should proxy the participant JSON Ledger API, authenticated as the connected party, and return the JSON body unchanged. Ekiden does not do that. The extension does not hold a participant token it can safely hand to a website, and it does not forward arbitrary HTTP to a validator. An open proxy would let any connected origin read or write anything that token allows. Use these instead: request("ledgerApi", …) fails with 4200 and data.reason explaining the same limit.

Async API

The remote CIP-0103 variant (userUrl, connected event) is for server-side wallets. Ekiden is in-page and synchronous. There is no userUrl.

signed transaction event

The spec allows txChanged with status: "signed" before submit. Ekiden signs inside prepareExecute and only emits pending, then executed or failed.

Ekiden SDK and CIP-0103 together

@ekidenfi/dapp-sdk is a thin client.
  • Named methods use Ekiden’s own postMessage types (CONNECT, GET_ACTIVE_ACCOUNT, EXECUTE, …). prepareExecute resolves { tx: { status, commandId, payload } }.
  • ekidenWallet.request(method, params) and ekidenWallet.on(event, listener) use the CIP-0103 frames above. request("prepareExecute", body) resolves null.
Prefer the named methods in an Ekiden-only app. Prefer sdk.connect() from @canton-network/dapp-sdk when the app should list every CIP-0103 wallet.