@partylayer/adapter-send 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 PartyLayer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,134 @@
1
+ # @partylayer/adapter-send
2
+
3
+ <div align="center">
4
+
5
+ **Send Canton Wallet adapter for PartyLayer**
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@partylayer/adapter-send.svg?style=flat-square)](https://www.npmjs.com/package/@partylayer/adapter-send)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
9
+
10
+ </div>
11
+
12
+ ---
13
+
14
+ ## Overview
15
+
16
+ Adapter for [Send](https://cantonwallet.com), a passkey-based Canton wallet. Send is delivered as a browser extension that injects a `window.canton` provider following the splice-wallet-kernel OpenRPC contract; the dApp connection layer is open-sourced as [Sigilry](https://sigilry.org).
17
+
18
+ > **Note:** This adapter is included in `@partylayer/sdk` by default. You only need to install it separately if you build a custom adapter list.
19
+
20
+ ---
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ npm install @partylayer/adapter-send
26
+ ```
27
+
28
+ Users connect through a browser extension. Direct them to [sigilry.org](https://sigilry.org) for current installation instructions before they can connect.
29
+
30
+ ---
31
+
32
+ ## Quick start
33
+
34
+ ```tsx
35
+ import { useConnect } from '@partylayer/react';
36
+
37
+ function ConnectWithSend() {
38
+ const { connect, isConnecting } = useConnect();
39
+ return (
40
+ <button onClick={() => connect('send')} disabled={isConnecting}>
41
+ {isConnecting ? 'Connecting…' : 'Connect with Send'}
42
+ </button>
43
+ );
44
+ }
45
+ ```
46
+
47
+ `PartyLayerKit` registers Send automatically — no extra wiring needed.
48
+
49
+ For explicit registration in a custom adapter list:
50
+
51
+ ```ts
52
+ import { createPartyLayer, getBuiltinAdapters, SendAdapter } from '@partylayer/sdk';
53
+
54
+ const client = createPartyLayer({
55
+ network: 'mainnet',
56
+ appName: 'My dApp',
57
+ adapters: [...getBuiltinAdapters(), new SendAdapter()],
58
+ });
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Capabilities
64
+
65
+ | Capability | Send | Notes |
66
+ |---------------------|:----:|----------------------------------------------------------------------------------------|
67
+ | `connect` | ✓ | Sigilry `connect` RPC + `getPrimaryAccount` |
68
+ | `disconnect` | ✓ | — |
69
+ | `restore` | ✓ | Silent `status` probe — no popup on page reload |
70
+ | `signMessage` | ✓ | Passkey-signed (WebAuthn-PRF / Touch ID / Face ID) |
71
+ | `signTransaction` | ✗ | Fused into `prepareExecute`; throws `CapabilityNotSupportedError` pointing at submit |
72
+ | `submitTransaction` | ✓ | Via `prepareExecuteAndWait`; receipt populated from `tx.payload.updateId` |
73
+ | `ledgerApi` | ✓ | Full Sigilry passthrough (matches Console / Nightly) |
74
+ | `events` | ✓ | `txChanged` bridged to PartyLayer `tx:status` |
75
+ | `injected` | ✓ | `window.canton` discovery with registry-driven detection guard |
76
+
77
+ ---
78
+
79
+ ## CIP-0103 compliance
80
+
81
+ `@partylayer/adapter-send` is a CIP-0103 native adapter. It exposes the Send wallet's `window.canton` provider through PartyLayer's standard `WalletAdapter` interface so the same dApp code that talks to any other CIP-0103 wallet (Console, Loop, Nightly, Cantor8) also talks to Send.
82
+
83
+ The adapter:
84
+
85
+ - Maps every Sigilry RPC method (`status`, `connect`, `disconnect`, `getPrimaryAccount`, `signMessage`, `prepareExecute`, `prepareExecuteAndWait`, `ledgerApi`) onto the PartyLayer capability surface declared in `getCapabilities()`.
86
+ - Bridges Send's `txChanged` event into PartyLayer's `tx:status` channel so transaction subscribers receive the same shape regardless of which wallet is connected.
87
+ - Routes structured JSON-RPC errors (4001 user-rejected, 4100/4900/4901 transport, -32601 method-not-supported) onto the canonical PartyLayer error taxonomy (`UserRejectedError`, `TransportError`, `CapabilityNotSupportedError`), so existing error-handling branches in dApp code continue to work without modification.
88
+
89
+ ---
90
+
91
+ ## Detection
92
+
93
+ The Send adapter detects whether the running browser has a compatible Send install via the registry's `providerDetection` rules. The same `window.canton` slot is shared with other splice-wallet-kernel-compatible extensions, so the adapter funnels every RPC call through a guard that verifies the live provider matches Send's detection rule before forwarding.
94
+
95
+ When detection fails — Send is not installed, or another Canton wallet is currently occupying `window.canton` — the adapter raises a typed error consumers can branch on:
96
+
97
+ - `SendNotInstalledError` (subclass of `WalletNotInstalledError`) — surfaced from `detectInstalled()` and from any RPC call when `window.canton` is absent. Carries `details.installUrl` so a dApp can present a single click-through to the Send wallet homepage.
98
+ - `SendKernelMismatchError` (also a subclass of `WalletNotInstalledError`) — surfaced when `window.canton` is present but its identity doesn't match Send. The adapter cleanly returns "not installed" so any other CIP-0103 adapter present in the registry can claim the active provider instead.
99
+ - `SendAuthTimeoutError` — surfaced when Send's authentication backend is unreachable or slow. Carries `details.cause = 'send-auth-timeout'` plus `retry: true` so a dApp can present a "try again" affordance rather than treating the failure as a permanent error.
100
+
101
+ ---
102
+
103
+ ## Compatibility
104
+
105
+ | Requirement | Value |
106
+ |----------------------|--------------------------------------------------------|
107
+ | Browser | Chromium-based browsers with WebAuthn-PRF support |
108
+ | Authentication | Passkey (Touch ID / Face ID / platform authenticator) |
109
+ | Canton network | `canton:mainnet` |
110
+ | `@partylayer/sdk` | `>=0.3.6` |
111
+
112
+ ---
113
+
114
+ ## Send-specific behaviors
115
+
116
+ - **Passkey per signature.** Every `signMessage` and every `submitTransaction` triggers a fresh passkey unlock. Send does not cache passkey approval across calls — by design.
117
+ - **Sign-and-submit are fused.** Send does not expose a standalone `signTransaction` step. The adapter mirrors that: `signTransaction()` throws `CapabilityNotSupportedError` pointing at `submitTransaction()` (`prepareExecuteAndWait` under the hood).
118
+ - **CIP-56 hint.** Submitting a legacy `Amulet_Transfer` exercise on `Splice.Amulet:Amulet` produces an actionable error pointing at the Token Standard `TransferFactory_Transfer` flow. Same hint as the Loop adapter.
119
+
120
+ ---
121
+
122
+ ## References
123
+
124
+ - [Send (cantonwallet.com)](https://cantonwallet.com)
125
+ - [Sigilry — open-source dApp SDK powering Send](https://sigilry.org)
126
+ - [PartyLayer documentation: Send](https://partylayer.xyz/docs/wallets/send)
127
+ - [GitHub Repository](https://github.com/PartyLayer/PartyLayer)
128
+ - [Report issues](https://github.com/PartyLayer/PartyLayer/issues)
129
+
130
+ ---
131
+
132
+ ## License
133
+
134
+ MIT
@@ -0,0 +1,447 @@
1
+ import * as _partylayer_core from '@partylayer/core';
2
+ import { ProviderDetection, WalletAdapter, CapabilityKey, AdapterDetectResult, AdapterContext, PartyId, AdapterConnectResult, Session, PersistedSession, SignMessageParams, SignedMessage, SignTransactionParams, SignedTransaction, SubmitTransactionParams, TxReceipt, LedgerApiParams, LedgerApiResult, AdapterEventName, WalletNotInstalledError, ErrorMappingContext, PartyLayerError } from '@partylayer/core';
3
+
4
+ /**
5
+ * Local Sigilry-shape types.
6
+ *
7
+ * The Send extension speaks the splice-wallet-kernel OpenRPC protocol via
8
+ * `window.canton`. We could pull these definitions from `@sigilry/dapp`,
9
+ * but pinning that dependency would couple us to Sigilry's release cadence
10
+ * and force consumers to install Zod transitively. Instead we model the
11
+ * minimal shapes we actually consume — fields verified against
12
+ * `@sigilry/dapp@1.0.1` `.d.ts` files and live runtime inspection of the
13
+ * extension's provider object.
14
+ */
15
+ /** Methods Send exposes via `window.canton.request({ method, params })`. */
16
+ type SendRpcMethod = 'status' | 'connect' | 'disconnect' | 'isConnected' | 'getActiveNetwork' | 'getPrimaryAccount' | 'listAccounts' | 'prepareExecute' | 'prepareExecuteAndWait' | 'signMessage' | 'ledgerApi';
17
+ /** Events emitted on the provider via `.on(event, listener)`. */
18
+ type SendEventName = 'accountsChanged' | 'txChanged';
19
+ interface SendKernelInfo {
20
+ /** Chrome extension ID for the running wallet kernel. */
21
+ id: string;
22
+ clientType: 'browser' | 'desktop' | 'mobile' | 'remote';
23
+ url?: string;
24
+ userUrl?: string;
25
+ }
26
+ interface SendNetwork {
27
+ networkId: string;
28
+ ledgerApi?: {
29
+ baseUrl: string;
30
+ };
31
+ }
32
+ interface SendStatusResponse {
33
+ kernel: SendKernelInfo;
34
+ isConnected: boolean;
35
+ isNetworkConnected: boolean;
36
+ networkReason?: string;
37
+ network?: SendNetwork;
38
+ session?: {
39
+ accessToken: string;
40
+ userId: string;
41
+ };
42
+ }
43
+ interface SendAccount {
44
+ primary: boolean;
45
+ partyId: string;
46
+ status: 'allocated' | 'initialized' | string;
47
+ hint: string;
48
+ /** Base64 SPKI of the account's P-256 ECDSA public key. */
49
+ publicKey: string;
50
+ namespace: string;
51
+ networkId: string;
52
+ /** Always 'webauthn-prf' for Send today. */
53
+ signingProviderId: string;
54
+ externalTxId?: string;
55
+ topologyTransactions?: string;
56
+ disabled?: boolean;
57
+ reason?: string;
58
+ }
59
+ interface SendDisclosedContract {
60
+ templateId?: string;
61
+ contractId?: string;
62
+ createdEventBlob: string;
63
+ synchronizerId?: string;
64
+ }
65
+ interface SendPrepareSubmissionRequest {
66
+ commandId?: string;
67
+ commands: Record<string, unknown>;
68
+ actAs?: string[];
69
+ readAs?: string[];
70
+ disclosedContracts?: SendDisclosedContract[];
71
+ synchronizerId?: string;
72
+ packageIdSelectionPreference?: string[];
73
+ }
74
+ interface SendTxExecutedEvent {
75
+ status: 'executed';
76
+ commandId: string;
77
+ payload: {
78
+ updateId: string;
79
+ completionOffset: number;
80
+ };
81
+ }
82
+ interface SendPrepareExecuteAndWaitResult {
83
+ tx: SendTxExecutedEvent;
84
+ }
85
+ /** Discriminated union surfaced via the `txChanged` event. */
86
+ type SendTxChangedEvent = {
87
+ status: 'pending';
88
+ commandId: string;
89
+ } | {
90
+ status: 'signed';
91
+ commandId: string;
92
+ payload: {
93
+ signature: string;
94
+ signedBy: string;
95
+ party: string;
96
+ };
97
+ } | SendTxExecutedEvent | {
98
+ status: 'failed';
99
+ commandId: string;
100
+ };
101
+ interface SendLedgerApiRequest {
102
+ requestMethod: 'GET' | 'POST' | 'PUT' | 'DELETE';
103
+ resource: string;
104
+ body?: string;
105
+ headers?: Record<string, string>;
106
+ query?: Record<string, unknown>;
107
+ path?: Record<string, string>;
108
+ }
109
+ interface SendLedgerApiResult {
110
+ /** JSON-encoded response body; preserve verbatim. */
111
+ response: string;
112
+ }
113
+ interface SendSignMessageRequest {
114
+ message: string;
115
+ }
116
+ interface SendSignMessageResult {
117
+ signature: string;
118
+ }
119
+ type SendEventListener = (...args: unknown[]) => void;
120
+ /**
121
+ * The provider injected at `window.canton` by Send.
122
+ *
123
+ * Strictly typed `request()` is intentionally narrowed to the methods
124
+ * Send actually implements — passing any other method name is a compile
125
+ * error here, even though the underlying provider would simply reject it
126
+ * at runtime with `METHOD_NOT_FOUND`.
127
+ */
128
+ interface SendCantonProvider {
129
+ request<M extends SendRpcMethod>(args: SendRpcRequest<M>): Promise<SendRpcResult<M>>;
130
+ on(event: SendEventName, listener: SendEventListener): unknown;
131
+ off?(event: SendEventName, listener: SendEventListener): unknown;
132
+ removeListener?(event: SendEventName, listener: SendEventListener): unknown;
133
+ }
134
+ /** Method-name-keyed map of params + result shapes. */
135
+ interface SendRpcSchemas {
136
+ status: {
137
+ params: void;
138
+ result: SendStatusResponse;
139
+ };
140
+ connect: {
141
+ params: void;
142
+ result: SendStatusResponse;
143
+ };
144
+ disconnect: {
145
+ params: void;
146
+ result: null;
147
+ };
148
+ isConnected: {
149
+ params: void;
150
+ result: SendStatusResponse;
151
+ };
152
+ getActiveNetwork: {
153
+ params: void;
154
+ result: SendNetwork;
155
+ };
156
+ getPrimaryAccount: {
157
+ params: void;
158
+ result: SendAccount;
159
+ };
160
+ listAccounts: {
161
+ params: void;
162
+ result: SendAccount[];
163
+ };
164
+ prepareExecute: {
165
+ params: SendPrepareSubmissionRequest;
166
+ result: null;
167
+ };
168
+ prepareExecuteAndWait: {
169
+ params: SendPrepareSubmissionRequest;
170
+ result: SendPrepareExecuteAndWaitResult;
171
+ };
172
+ signMessage: {
173
+ params: SendSignMessageRequest;
174
+ result: SendSignMessageResult;
175
+ };
176
+ ledgerApi: {
177
+ params: SendLedgerApiRequest;
178
+ result: SendLedgerApiResult;
179
+ };
180
+ }
181
+ /** Method-name → `params` field shape (omitted entirely when params is void). */
182
+ type SendRpcRequest<M extends SendRpcMethod> = SendRpcSchemas[M]['params'] extends void ? {
183
+ method: M;
184
+ params?: undefined;
185
+ } : {
186
+ method: M;
187
+ params: SendRpcSchemas[M]['params'];
188
+ };
189
+ /** Method-name → result type. */
190
+ type SendRpcResult<M extends SendRpcMethod> = SendRpcSchemas[M]['result'];
191
+ declare global {
192
+ interface Window {
193
+ canton?: SendCantonProvider;
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Typed wrapper around the `window.canton` provider exposed by Send.
199
+ *
200
+ * Detection is **registry-driven** via `matchesProviderDetection`. The
201
+ * adapter accepts an optional `ProviderDetection` rule set at construction
202
+ * (sourced from the registry's `providerDetection` field for the Send
203
+ * entry); when omitted, it falls back to `SEND_BUILTIN_DETECTION` which
204
+ * mirrors the canonical registry rule. Every public RPC method goes
205
+ * through `guardedRequest`, which checks the live `status` response
206
+ * against those rules before forwarding the call. The result: if a
207
+ * non-Send wallet is sitting at `window.canton`, every Send call resolves
208
+ * to a `SendKernelMismatchError` (treated by the SDK as "Send is not
209
+ * installed"), and Send only ever acts on its own provider.
210
+ */
211
+
212
+ declare class SendProvider {
213
+ private readonly detection;
214
+ private cachedStatus;
215
+ /**
216
+ * @param detection Optional. Used to match the running `window.canton`
217
+ * provider against Send's identity. When omitted, falls back to
218
+ * `SEND_BUILTIN_DETECTION` (canonical registry rule mirror).
219
+ */
220
+ constructor(detection?: ProviderDetection);
221
+ /**
222
+ * True when `window.canton` is present AND its self-reported status
223
+ * matches Send's detection rules. Performs an actual `status` round-trip
224
+ * on first call and caches the response for subsequent ones.
225
+ */
226
+ isInstalled(): Promise<boolean>;
227
+ /**
228
+ * Synchronous best-effort presence check. Used for fast picker rendering
229
+ * before any async status introspection. May report `true` for a
230
+ * non-Send provider — callers must follow up with `isInstalled()` (or
231
+ * any guarded request) before assuming Send is wired in.
232
+ */
233
+ isPotentiallyAvailable(): boolean;
234
+ /**
235
+ * Read the cached `kernel.id` from the running provider, fetching status
236
+ * on demand. Diagnostic helper kept public for back-compat — detection
237
+ * itself no longer hinges on this single field.
238
+ */
239
+ getKernelId(): Promise<string>;
240
+ /**
241
+ * Read the latest cached status object. Resolves the underlying RPC on
242
+ * demand if no cached value is present.
243
+ */
244
+ getStatus(): Promise<SendStatusResponse>;
245
+ /**
246
+ * Reset the cached status (e.g. after the user uninstalls and reinstalls
247
+ * the extension, or you suspect kernel identity changed mid-session).
248
+ * Kept under both names to avoid breaking existing test imports.
249
+ */
250
+ resetKernelCache(): void;
251
+ resetStatusCache(): void;
252
+ private fetchStatus;
253
+ /** Internal — bypasses the detection guard. */
254
+ private rawRequest;
255
+ /** Public dispatch — guards every call with a registry-driven detection check. */
256
+ private guardedRequest;
257
+ status(): Promise<SendStatusResponse>;
258
+ connect(): Promise<SendStatusResponse>;
259
+ disconnect(): Promise<null>;
260
+ isConnected(): Promise<SendStatusResponse>;
261
+ getActiveNetwork(): Promise<SendNetwork>;
262
+ listAccounts(): Promise<SendAccount[]>;
263
+ getPrimaryAccount(): Promise<SendAccount>;
264
+ signMessage(message: string): Promise<{
265
+ signature: string;
266
+ }>;
267
+ prepareExecute(params: SendPrepareSubmissionRequest): Promise<null>;
268
+ prepareExecuteAndWait(params: SendPrepareSubmissionRequest): Promise<SendPrepareExecuteAndWaitResult>;
269
+ ledgerApi(req: SendLedgerApiRequest): Promise<SendLedgerApiResult>;
270
+ on(event: SendEventName, listener: SendEventListener): void;
271
+ off(event: SendEventName, listener: SendEventListener): void;
272
+ }
273
+
274
+ declare class SendAdapter implements WalletAdapter {
275
+ readonly walletId: _partylayer_core.WalletId;
276
+ readonly name = "Send";
277
+ private readonly provider;
278
+ /**
279
+ * @param options.detection Optional. When supplied, the adapter uses
280
+ * these matcher rules to decide whether the running `window.canton`
281
+ * belongs to Send. Inject this from the registry entry's
282
+ * `providerDetection` field for canonical behaviour. Omitting it
283
+ * falls back to the built-in pattern that mirrors the canonical
284
+ * registry rule (parity is verified by tests).
285
+ * @param options.provider Optional. Pre-built provider instance, used
286
+ * primarily by tests; takes precedence over `options.detection`.
287
+ */
288
+ constructor(options?: {
289
+ detection?: ProviderDetection;
290
+ provider?: SendProvider;
291
+ });
292
+ getCapabilities(): CapabilityKey[];
293
+ detectInstalled(): Promise<AdapterDetectResult>;
294
+ connect(ctx: AdapterContext, _opts?: {
295
+ timeoutMs?: number;
296
+ partyId?: PartyId;
297
+ preferInstalled?: boolean;
298
+ }): Promise<AdapterConnectResult>;
299
+ disconnect(ctx: AdapterContext, _session: Session): Promise<void>;
300
+ restore(ctx: AdapterContext, persisted: PersistedSession): Promise<Session | null>;
301
+ signMessage(ctx: AdapterContext, session: Session, params: SignMessageParams): Promise<SignedMessage>;
302
+ signTransaction(_ctx: AdapterContext, _session: Session, _params: SignTransactionParams): Promise<SignedTransaction>;
303
+ submitTransaction(ctx: AdapterContext, session: Session, params: SubmitTransactionParams): Promise<TxReceipt>;
304
+ ledgerApi(ctx: AdapterContext, session: Session, params: LedgerApiParams): Promise<LedgerApiResult>;
305
+ /**
306
+ * Subscribe to PartyLayer adapter events. Currently bridges only
307
+ * `txStatus` from Send's native `txChanged` event. Other PartyLayer
308
+ * adapter events (`connect` / `disconnect` / `sessionExpired` / `error`)
309
+ * are emitted by the SDK itself, not the wallet, so we no-op them.
310
+ */
311
+ on(event: AdapterEventName, handler: (payload: unknown) => void): () => void;
312
+ }
313
+
314
+ /**
315
+ * Send-specific error helpers.
316
+ *
317
+ * PartyLayer's `ErrorCode` union (in `@partylayer/core/errors.ts`) is the
318
+ * canonical taxonomy. We do NOT introduce new codes here — instead, the
319
+ * Send-specific error classes subclass the closest existing PartyLayer
320
+ * error and carry the diagnostic detail (kernel id, RPC code) in
321
+ * `details`. That way existing telemetry pipelines and `code`-based
322
+ * branches in dApp code continue to work without modification.
323
+ */
324
+
325
+ /** JSON-RPC 2.0 + EIP-1193 error codes Sigilry surfaces. */
326
+ declare const SendRpcErrorCode: {
327
+ readonly PARSE_ERROR: -32700;
328
+ readonly INVALID_REQUEST: -32600;
329
+ readonly METHOD_NOT_FOUND: -32601;
330
+ readonly INVALID_PARAMS: -32602;
331
+ readonly INTERNAL_ERROR: -32603;
332
+ readonly USER_REJECTED: 4001;
333
+ readonly UNAUTHORIZED: 4100;
334
+ readonly UNSUPPORTED_METHOD: 4200;
335
+ readonly DISCONNECTED: 4900;
336
+ readonly CHAIN_DISCONNECTED: 4901;
337
+ readonly INVALID_INPUT: -32000;
338
+ readonly RESOURCE_NOT_FOUND: -32001;
339
+ readonly RESOURCE_UNAVAILABLE: -32002;
340
+ readonly TRANSACTION_REJECTED: -32003;
341
+ readonly METHOD_NOT_SUPPORTED: -32004;
342
+ readonly LIMIT_EXCEEDED: -32005;
343
+ };
344
+ /**
345
+ * Send isn't installed — `window.canton` is unavailable entirely.
346
+ *
347
+ * Subclasses `WalletNotInstalledError` so existing capability gates and
348
+ * UI ("install Send") light up automatically. Carries the install URL in
349
+ * `details` for one-click prompts.
350
+ */
351
+ declare class SendNotInstalledError extends WalletNotInstalledError {
352
+ constructor(reason?: string);
353
+ }
354
+ /**
355
+ * `window.canton` is present but `kernel.id` does not match Send.
356
+ *
357
+ * Treated as "Send not installed" from the SDK's perspective so that
358
+ * other adapters get a chance to claim the active provider — but the
359
+ * runtime kernel id is preserved in `details` for diagnostics.
360
+ *
361
+ * The wording avoids the keywords "rejected"/"denied"/"cancelled" so
362
+ * `mapUnknownErrorToPartyLayerError` won't silently rewrite this as a
363
+ * `UserRejectedError` when re-thrown through error mapping.
364
+ */
365
+ declare class SendKernelMismatchError extends WalletNotInstalledError {
366
+ constructor(actualKernelId: string);
367
+ }
368
+ /**
369
+ * Send's authentication backend (auth.cantonwallet.com) timed out or was
370
+ * otherwise unreachable. This is an external, intermittent issue on
371
+ * Send's side — not a PartyLayer issue, not a wallet-not-installed
372
+ * issue, and not a user rejection. Surfaced as a typed error so the UI
373
+ * can offer a "Try again" affordance + link to Send's status page.
374
+ *
375
+ * Subclasses `WalletNotInstalledError` to reuse the existing core error
376
+ * code (`'WALLET_NOT_INSTALLED'`) without expanding the canonical
377
+ * `ErrorCode` union — but the class identity (`name`) plus
378
+ * `details.cause = 'send-auth-timeout'` give consumers enough signal to
379
+ * route the retry UX without a code-level change.
380
+ */
381
+ declare class SendAuthTimeoutError extends WalletNotInstalledError {
382
+ constructor(originalMessage?: string);
383
+ }
384
+ /**
385
+ * Recognise Send-side authentication-timeout signatures in arbitrary
386
+ * error payloads. Covers the wording variants the Send wallet surfaces
387
+ * today (the wallet UI itself uses both "Authentication timed out" and
388
+ * "Cannot reach authentication server"; the underlying domain
389
+ * `auth.cantonwallet.com` shows up in stack traces / fetch errors when
390
+ * the network is at fault).
391
+ */
392
+ declare function detectSendAuthTimeout(err: unknown): boolean;
393
+ /**
394
+ * Translate a Sigilry RPC error to the closest PartyLayer error class.
395
+ *
396
+ * Falls back to `mapUnknownErrorToPartyLayerError` when the error doesn't
397
+ * carry a recognisable JSON-RPC `code`. Note that `mapUnknownErrorToPartyLayerError`
398
+ * itself rewrites messages containing "rejected"/"denied"/"cancelled" into
399
+ * `UserRejectedError`, so we explicitly route the 4001 code first to make
400
+ * the user-rejection path stable across wording changes in the wallet.
401
+ */
402
+ declare function mapSigilryError(err: unknown, context: ErrorMappingContext): PartyLayerError;
403
+ /**
404
+ * Build a hint string when the developer passes a short-form Canton
405
+ * template ID OR the legacy pre-Token-Standard `Amulet_Transfer` choice.
406
+ *
407
+ * Mirrors `loop-adapter.templateIdHint` so Send produces the same
408
+ * actionable error text for the same payload bug class. Returns an empty
409
+ * string when no problem is detected — callers can append this to a base
410
+ * error message unconditionally.
411
+ */
412
+ declare function templateIdHint(payload: unknown): string;
413
+ /**
414
+ * Bound preview of an arbitrary value for inclusion in error messages.
415
+ * Keeps logs small when a payload is large or contains binary blobs.
416
+ */
417
+ declare function safePreview(value: unknown, maxLen?: number): string;
418
+
419
+ /**
420
+ * Chrome Web Store extension ID for Send Canton Wallet.
421
+ *
422
+ * Kept as a public export for diagnostics and back-compat (downstream
423
+ * consumers still import this constant), but it is **not** the primary
424
+ * detection signal anymore. Detection is registry-driven via
425
+ * `SEND_BUILTIN_DETECTION` below; the kernel.id is one of three matchers
426
+ * (the URL-domain matchers carry stable identity, including for
427
+ * developer-mode builds whose kernel.id varies per install).
428
+ */
429
+ declare const SEND_KERNEL_ID = "ldmohiccoioolenadmogclhoklmanpgi";
430
+ /**
431
+ * Network IDs Send currently supports. Send is mainnet-only as of v0.2.0.
432
+ * Listed in Canton long-form so it stays distinguishable from PartyLayer's
433
+ * generic 'mainnet' alias.
434
+ */
435
+ declare const SEND_SUPPORTED_NETWORKS: readonly ["canton:mainnet"];
436
+ declare const SEND_INSTALL_URL = "https://sigilry.org";
437
+ declare const SEND_HOMEPAGE = "https://cantonwallet.com";
438
+ declare const SEND_DOCS_URL = "https://sigilry.org";
439
+ /**
440
+ * Send signs every transaction via the WebAuthn PRF extension (passkey).
441
+ * Surfaced through session metadata so dApps can adapt copy ("approve in
442
+ * Touch ID / Face ID prompt") rather than show a generic "open extension"
443
+ * hint.
444
+ */
445
+ declare const SEND_SIGNING_METHOD: "webauthn-prf";
446
+
447
+ export { SEND_DOCS_URL, SEND_HOMEPAGE, SEND_INSTALL_URL, SEND_KERNEL_ID, SEND_SIGNING_METHOD, SEND_SUPPORTED_NETWORKS, type SendAccount, SendAdapter, SendAuthTimeoutError, type SendCantonProvider, type SendDisclosedContract, type SendEventListener, type SendEventName, type SendKernelInfo, SendKernelMismatchError, type SendLedgerApiRequest, type SendLedgerApiResult, type SendNetwork, SendNotInstalledError, type SendPrepareExecuteAndWaitResult, type SendPrepareSubmissionRequest, SendProvider, SendRpcErrorCode, type SendRpcMethod, type SendRpcRequest, type SendRpcResult, type SendRpcSchemas, type SendSignMessageRequest, type SendSignMessageResult, type SendStatusResponse, type SendTxChangedEvent, type SendTxExecutedEvent, detectSendAuthTimeout, mapSigilryError, safePreview, templateIdHint };