@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 +21 -0
- package/README.md +134 -0
- package/dist/index.d.mts +447 -0
- package/dist/index.d.ts +447 -0
- package/dist/index.js +636 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +619 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +55 -0
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
|
+
[](https://www.npmjs.com/package/@partylayer/adapter-send)
|
|
8
|
+
[](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
|
package/dist/index.d.mts
ADDED
|
@@ -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 };
|