Event Spec
This document defines the event payloads emitted by PartyLayer SDK.
Event System Overview
PartyLayer uses a typed event system for state changes:
Event Types
session:connected
Emitted when a wallet connection is established (new or restored).
Triggered by:
client.connect()success- Session restore on SDK initialization
Metrics mapping:
wallet_connect_success+1sessions_created+1 (new connection only)sessions_restored+1 (restore only)
session:disconnected
Emitted when a wallet is disconnected.
Triggered by:
client.disconnect()call
Metrics mapping:
- No direct metric (tracked as session lifecycle)
session:expired
Emitted when a session expires.
Triggered by:
- Session expiration check in
getActiveSession() - Failed session restore
Metrics mapping:
- No direct metric (tracked as session lifecycle)
tx:status
Emitted when transaction status changes.
Triggered by:
client.signTransaction()→ status: 'pending'client.submitTransaction()→ status: 'submitted'
Metrics mapping:
- No direct metric (transaction counts not tracked for privacy)
registry:status
Emitted when registry status changes.
Triggered by:
- SDK initialization
client.listWallets()call- Registry fetch success/failure
Metrics mapping:
registry_fetch+1 (when source: 'network')registry_cache_hit+1 (when source: 'cache')registry_stale+1 (when stale: true)
error
Emitted when an error occurs during any operation.
Triggered by:
- Any SDK operation failure
Metrics mapping:
error_<code>+1 (e.g.,error_USER_REJECTED)
session:networkMismatch
Emitted when the connected wallet's effective network differs from the dApp's configured network. Emitted under all policies (informational); enforced is true when the active policy (guard or strict) will block.
Triggered by:
- A network mismatch detected at connect or restore time
Metrics mapping:
- No direct metric
wallets:changed
Emitted when the available wallet list changes, currently only from late or inject-time announce discovery.
Triggered by:
- A
canton:announceProviderwallet appearing after the initial list was built
Metrics mapping:
- No direct metric
Event → Metric Mapping Table
Event telemetry bridge
Separately from the increment-based metrics above, every emitted event is forwarded once to the configured telemetry adapter through track(name, properties), from a single central path in the client. The telemetry name is the event's own type string. This is additive: the increment metrics are unchanged, and when no telemetry adapter is configured the bridge is a no-op.
Only privacy-safe, non-identifying properties are sent. Session ids, party ids, transaction hashes, origins, and raw wallet payloads are never included; where an event's only distinguishing field is such an identifier, the property set is empty and the event count itself is the signal.
Privacy Guarantees
Event payloads are designed to be privacy-safe:
Never Included in Events
- Wallet addresses
- Raw party IDs in external payloads
- Transaction payloads
- Signed message content
- User identifiers
Included (Safe)
- Session IDs (random, not user-identifiable)
- Wallet IDs (e.g., 'console', 'loop')
- Network names (e.g., 'devnet', 'mainnet')
- Error codes (generic categories)
- Timestamps
Opt-in (Hashed)
- App identifier (SHA-256 hashed)
- Origin (SHA-256 hashed, if enabled)
Subscribing to Events
Basic Usage
React Integration
Multiple Event Types
Event Handler Best Practices
- Keep handlers fast, Don't block on async operations
- Handle errors, Wrap handlers in try-catch
- Clean up, Always unsubscribe when component unmounts
- Type safety, Use TypeScript for event payload types
Event to lifecycle phase mapping
The observability deliverable names six lifecycle phases: connect, authorize, prepare, submit, confirm, and error. The shipped SDK does not emit six phase named events. It emits the nine domain events above on the PartyLayerEvent union, and the phases are a reading of those events, not a separate event set. This table is the mapping, so an operator instrumenting by phase knows which event to watch.
Phases with no dedicated event. Three of the six phases have no event of their own. They are covered by an existing event, by design.
- authorize is covered by
session:connected. CIP-0103 folds authorization into the connect grant: the wallet's approval to connect is the authorization, so there is no separate authorize step or event. - prepare, submit, and confirm are covered by
tx:status. The kit models the transaction lifecycle as one event whosestatusfield moves through prepared, submitted, and committed, rather than three separately named events.