@cavos/kit 0.0.1
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/README.md +151 -0
- package/dist/chunk-XWBX2ZIO.mjs +1061 -0
- package/dist/chunk-XWBX2ZIO.mjs.map +1 -0
- package/dist/constants-C530TZFF.d.mts +89 -0
- package/dist/constants-C530TZFF.d.ts +89 -0
- package/dist/index.d.mts +529 -0
- package/dist/index.d.ts +529 -0
- package/dist/index.js +1103 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +15 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react/index.d.mts +140 -0
- package/dist/react/index.d.ts +140 -0
- package/dist/react/index.js +2055 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +999 -0
- package/dist/react/index.mjs.map +1 -0
- package/package.json +77 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
import { Account, Signer, ArraySignatureType } from 'starknet';
|
|
2
|
+
import { D as DevicePublicKey, S as StarknetNetwork, a as DeviceSigner, C as ChainCall, b as DeviceSignature, c as ChainAdapter, d as ComputeAddressParams } from './constants-C530TZFF.js';
|
|
3
|
+
export { e as DEVICE_ACCOUNT_CLASS_HASH, f as STARKNET_NETWORKS, U as UDC_ADDRESS } from './constants-C530TZFF.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Identity for a Cavos wallet. Login (email / social / OTP) only ever produces a
|
|
7
|
+
* stable `userId`; that's all the wallet needs to derive its address. Auth never
|
|
8
|
+
* touches signing — the device key does that, silently.
|
|
9
|
+
*
|
|
10
|
+
* Privy-style UX: the user "logs in" and the wallet is provisioned behind the
|
|
11
|
+
* scenes (device key + auto-deployed smart account). The app never handles keys.
|
|
12
|
+
*/
|
|
13
|
+
interface Identity {
|
|
14
|
+
/** Stable, backend-managed user identifier. */
|
|
15
|
+
userId: string;
|
|
16
|
+
/** Optional metadata (email, provider) for display only. */
|
|
17
|
+
email?: string;
|
|
18
|
+
provider?: "google" | "apple" | "email" | "otp" | string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Authenticates a user and returns their stable identity. Implementations:
|
|
22
|
+
* - `CavosAuth` (hosted, mirrors `@cavos/react`: Google/Apple/email/OTP via the
|
|
23
|
+
* Cavos backend) — the default, Privy-like experience.
|
|
24
|
+
* - any custom provider (the app already authenticated the user elsewhere).
|
|
25
|
+
*/
|
|
26
|
+
interface AuthProvider {
|
|
27
|
+
authenticate(): Promise<Identity>;
|
|
28
|
+
}
|
|
29
|
+
/** Trivial provider when the app already has the user's stable id. */
|
|
30
|
+
declare class StaticIdentity implements AuthProvider {
|
|
31
|
+
private readonly identity;
|
|
32
|
+
constructor(identity: Identity);
|
|
33
|
+
authenticate(): Promise<Identity>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Off-chain map of `user_id -> wallet`. Because the account address is
|
|
38
|
+
* `f(identity, first_device_pubkey)` (unforgeable, secure), it is NOT derivable
|
|
39
|
+
* from the identity alone on a new device. The backend is the source of truth
|
|
40
|
+
* for "does this user already have a wallet?" — enabling multi-device:
|
|
41
|
+
*
|
|
42
|
+
* - First device, unknown user -> deploy a new wallet, then `register`.
|
|
43
|
+
* - Same user, new device -> `lookup` returns the existing wallet; the
|
|
44
|
+
* new device is added as a signer (recovery
|
|
45
|
+
* approval), NOT a new wallet.
|
|
46
|
+
*
|
|
47
|
+
* The backend implements this (it already manages the user<->address binding).
|
|
48
|
+
*/
|
|
49
|
+
interface WalletRegistry {
|
|
50
|
+
/** The user's existing wallet, or null if they don't have one yet. */
|
|
51
|
+
lookup(userId: string): Promise<RegisteredWallet | null>;
|
|
52
|
+
/** Record a freshly deployed wallet for the user (first device). */
|
|
53
|
+
register(params: {
|
|
54
|
+
userId: string;
|
|
55
|
+
address: string;
|
|
56
|
+
initialSigner: DevicePublicKey;
|
|
57
|
+
}): Promise<void>;
|
|
58
|
+
/** Note an additional device signer for the user's wallet (after approval). */
|
|
59
|
+
addDevice?(params: {
|
|
60
|
+
userId: string;
|
|
61
|
+
address: string;
|
|
62
|
+
signer: DevicePublicKey;
|
|
63
|
+
}): Promise<void>;
|
|
64
|
+
}
|
|
65
|
+
interface RegisteredWallet {
|
|
66
|
+
address: string;
|
|
67
|
+
/** Public keys of the devices registered on this wallet (if tracked). */
|
|
68
|
+
devices?: DevicePublicKey[];
|
|
69
|
+
}
|
|
70
|
+
/** Simple in-memory registry for demos / tests. */
|
|
71
|
+
declare class InMemoryWalletRegistry implements WalletRegistry {
|
|
72
|
+
private wallets;
|
|
73
|
+
lookup(userId: string): Promise<RegisteredWallet | null>;
|
|
74
|
+
register(params: {
|
|
75
|
+
userId: string;
|
|
76
|
+
address: string;
|
|
77
|
+
initialSigner: DevicePublicKey;
|
|
78
|
+
}): Promise<void>;
|
|
79
|
+
addDevice(params: {
|
|
80
|
+
userId: string;
|
|
81
|
+
address: string;
|
|
82
|
+
signer: DevicePublicKey;
|
|
83
|
+
}): Promise<void>;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Multi-device / recovery flow (roadmap §1.2). A new device requests addition;
|
|
88
|
+
* the backend emails an approval prompt styled as a login request; the user
|
|
89
|
+
* approves on an ALREADY-registered device, which signs `add_signer` for the
|
|
90
|
+
* new pubkey. There is no legacy JWT path — recovery is purely device-signer
|
|
91
|
+
* based.
|
|
92
|
+
*
|
|
93
|
+
* The backend lives outside this repo; this is the client contract the kit
|
|
94
|
+
* speaks to. Provide an implementation (HTTP, etc.) when wiring an app.
|
|
95
|
+
*/
|
|
96
|
+
interface RecoveryClient {
|
|
97
|
+
/**
|
|
98
|
+
* Step 1 (new device): request that this pubkey be added to the user's
|
|
99
|
+
* account. Triggers the approval email. Returns a request id to poll.
|
|
100
|
+
*/
|
|
101
|
+
requestDeviceAddition(params: {
|
|
102
|
+
userId: string;
|
|
103
|
+
accountAddress: string;
|
|
104
|
+
newSigner: DevicePublicKey;
|
|
105
|
+
/** Owner email to send the approval link to (the SDK has it from login). */
|
|
106
|
+
email?: string;
|
|
107
|
+
/** Optional device label (browser/UA) shown in the approval email. */
|
|
108
|
+
deviceLabel?: string;
|
|
109
|
+
}): Promise<{
|
|
110
|
+
requestId: string;
|
|
111
|
+
}>;
|
|
112
|
+
/**
|
|
113
|
+
* Step 3-4 (existing device): fetch a pending addition request so the
|
|
114
|
+
* registered device can approve it by signing `add_signer`.
|
|
115
|
+
*/
|
|
116
|
+
getPendingRequest(requestId: string): Promise<PendingDeviceRequest | null>;
|
|
117
|
+
/** Mark a request approved after the `add_signer` tx is submitted. */
|
|
118
|
+
confirmDeviceAddition(params: {
|
|
119
|
+
requestId: string;
|
|
120
|
+
txHash: string;
|
|
121
|
+
}): Promise<void>;
|
|
122
|
+
}
|
|
123
|
+
interface PendingDeviceRequest {
|
|
124
|
+
requestId: string;
|
|
125
|
+
appId?: string;
|
|
126
|
+
userId: string;
|
|
127
|
+
accountAddress: string;
|
|
128
|
+
newSigner: DevicePublicKey;
|
|
129
|
+
createdAt: string;
|
|
130
|
+
status: "pending" | "approved" | "expired";
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
interface ConnectOptions {
|
|
134
|
+
network: StarknetNetwork;
|
|
135
|
+
/** Authenticated user (pass `identity` directly, or an `auth` provider). */
|
|
136
|
+
auth?: AuthProvider;
|
|
137
|
+
identity?: Identity;
|
|
138
|
+
appSalt: string;
|
|
139
|
+
/**
|
|
140
|
+
* Cavos App ID. When set (with `backendUrl`), the kit uses the hosted
|
|
141
|
+
* WalletRegistry + RecoveryClient by default for real multi-device support.
|
|
142
|
+
*/
|
|
143
|
+
appId?: string;
|
|
144
|
+
/** Cavos backend base URL. Defaults to https://cavos.xyz. */
|
|
145
|
+
backendUrl?: string;
|
|
146
|
+
/**
|
|
147
|
+
* Off-chain user_id -> wallet map. Defaults to the hosted HttpWalletRegistry
|
|
148
|
+
* when `appId` is set, else an in-memory registry (single-device only).
|
|
149
|
+
*/
|
|
150
|
+
registry?: WalletRegistry;
|
|
151
|
+
/**
|
|
152
|
+
* Device-approval relay. Defaults to HttpRecoveryClient when `appId` is set;
|
|
153
|
+
* used to request addition of this device when it isn't an authorized signer.
|
|
154
|
+
*/
|
|
155
|
+
recovery?: RecoveryClient;
|
|
156
|
+
/** Cavos paymaster API key (sponsors deploy + execute). */
|
|
157
|
+
paymasterApiKey: string;
|
|
158
|
+
paymasterUrl?: string;
|
|
159
|
+
rpcUrl?: string;
|
|
160
|
+
classHash?: string;
|
|
161
|
+
/** Override the device signer factory (native / tests); default WebCrypto. */
|
|
162
|
+
createSigner?: (keyId: string) => Promise<DeviceSigner>;
|
|
163
|
+
}
|
|
164
|
+
/** Whether this device can already operate the wallet, or needs to be added. */
|
|
165
|
+
type ConnectStatus = "ready" | "needs-device-approval";
|
|
166
|
+
/** Options for recovering an account after losing every device signer. */
|
|
167
|
+
interface RecoveryOptions {
|
|
168
|
+
/** The recovery code the user stored when they ran setupRecovery. */
|
|
169
|
+
code: string;
|
|
170
|
+
/** Authenticated identity (same user who owns the account). */
|
|
171
|
+
identity: Identity;
|
|
172
|
+
network: StarknetNetwork;
|
|
173
|
+
appSalt: string;
|
|
174
|
+
paymasterApiKey: string;
|
|
175
|
+
appId?: string;
|
|
176
|
+
backendUrl?: string;
|
|
177
|
+
rpcUrl?: string;
|
|
178
|
+
paymasterUrl?: string;
|
|
179
|
+
classHash?: string;
|
|
180
|
+
/** Off-chain user_id -> wallet map. Defaults to the hosted registry. */
|
|
181
|
+
registry?: WalletRegistry;
|
|
182
|
+
/** Override the new device's signer (native / tests); default WebCrypto. */
|
|
183
|
+
createSigner?: (keyId: string) => Promise<DeviceSigner>;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* High-level Cavos wallet. One call logs the user in and returns a ready, gas-
|
|
187
|
+
* sponsored smart account controlled by a silent device key.
|
|
188
|
+
*
|
|
189
|
+
* const cavos = await Cavos.connect({ network, identity, appSalt, registry, paymasterApiKey });
|
|
190
|
+
* if (cavos.status === "ready") await cavos.execute(calls);
|
|
191
|
+
*
|
|
192
|
+
* The account address is `f(identity, device_pubkey)` — unforgeable, so it can't
|
|
193
|
+
* be hijacked. The `registry` recognizes returning users across devices: a new
|
|
194
|
+
* device on an existing account is flagged `needs-device-approval` (add it via
|
|
195
|
+
* an already-registered device) instead of creating a second wallet.
|
|
196
|
+
*/
|
|
197
|
+
declare class Cavos {
|
|
198
|
+
readonly identity: Identity;
|
|
199
|
+
readonly address: string;
|
|
200
|
+
readonly status: ConnectStatus;
|
|
201
|
+
readonly account: Account;
|
|
202
|
+
private readonly adapter;
|
|
203
|
+
private readonly devicePubkey;
|
|
204
|
+
/** Request id of the pending device-addition, when status is needs-device-approval. */
|
|
205
|
+
pendingRequestId: string | null;
|
|
206
|
+
private constructor();
|
|
207
|
+
static connect(opts: ConnectOptions): Promise<Cavos>;
|
|
208
|
+
/** This device's public key (e.g. to request addition to an existing wallet). */
|
|
209
|
+
get publicKey(): DevicePublicKey;
|
|
210
|
+
/** Execute a sponsored (gasless) multicall, signed silently by the device. */
|
|
211
|
+
execute(calls: ChainCall[]): Promise<{
|
|
212
|
+
transactionHash: string;
|
|
213
|
+
}>;
|
|
214
|
+
/** Authorize an additional device signer (sponsored). Self-submitted. */
|
|
215
|
+
addSigner(pubkey: DevicePublicKey): Promise<{
|
|
216
|
+
transactionHash: string;
|
|
217
|
+
}>;
|
|
218
|
+
/**
|
|
219
|
+
* Register a self-custodial backup signer derived from `code`, so the account
|
|
220
|
+
* can be recovered after the user loses every device. Idempotent: if the
|
|
221
|
+
* derived backup key is already an authorised signer, this is a no-op.
|
|
222
|
+
*
|
|
223
|
+
* The code never leaves the device — only its deterministic public key is
|
|
224
|
+
* added on-chain as an ordinary signer. Sponsor this like any other
|
|
225
|
+
* add_signer (gasless). Returns the transaction hash (or undefined when the
|
|
226
|
+
* backup was already set up).
|
|
227
|
+
*/
|
|
228
|
+
setupRecovery(code: string): Promise<{
|
|
229
|
+
transactionHash: string;
|
|
230
|
+
} | undefined>;
|
|
231
|
+
/**
|
|
232
|
+
* Recover an account after losing every device signer. Derives the backup key
|
|
233
|
+
* from `code`, uses it (not the new device key) to sign an `add_signer` for
|
|
234
|
+
* the new device, and returns a ready Cavos bound to the new device. The
|
|
235
|
+
* account address is unchanged.
|
|
236
|
+
*
|
|
237
|
+
* Self-custodial: only someone holding the code (i.e. the rightful owner) can
|
|
238
|
+
* re-derive the backup key. The backend never sees the code.
|
|
239
|
+
*/
|
|
240
|
+
static recover(opts: RecoveryOptions): Promise<Cavos>;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
interface CavosAuthOptions {
|
|
244
|
+
/** Cavos backend base URL. Defaults to the hosted service (same as @cavos/react). */
|
|
245
|
+
backendUrl?: string;
|
|
246
|
+
/** App identifier registered with Cavos (the `appId` from the dashboard). */
|
|
247
|
+
appId?: string;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Hosted login (Privy-like) backed by the Cavos backend — same endpoints
|
|
251
|
+
* `@cavos/react` uses (Google / Apple OAuth + Firebase email OTP). Login only
|
|
252
|
+
* resolves a stable `userId` (the OAuth `sub` claim); it never touches signing.
|
|
253
|
+
* Feed the returned `Identity` to `Cavos.connect`.
|
|
254
|
+
*
|
|
255
|
+
* const auth = new CavosAuth({ appId });
|
|
256
|
+
* // social: open the returned URL; user returns, then:
|
|
257
|
+
* const identity = await auth.handleCallback(window.location.search);
|
|
258
|
+
* // or email OTP:
|
|
259
|
+
* await auth.sendOtp(email); const identity = await auth.verifyOtp(email, code);
|
|
260
|
+
* const cavos = await Cavos.connect({ network, appSalt, identity, paymasterApiKey });
|
|
261
|
+
*
|
|
262
|
+
* Device-signer model note: the backend issues a Cavos JWT (the same one react
|
|
263
|
+
* uses for on-chain RSA verification). Here we only need the stable `sub` claim
|
|
264
|
+
* from it — the RSA/JWKS/nonce machinery react relies on is dead weight for the
|
|
265
|
+
* device model, because the device key (not the JWT) authorizes on-chain calls.
|
|
266
|
+
* We still send a `nonce` (Poseidon over random bytes) since the backend expects
|
|
267
|
+
* it on the request; the value itself is irrelevant to us.
|
|
268
|
+
*/
|
|
269
|
+
declare class CavosAuth implements AuthProvider {
|
|
270
|
+
private readonly opts;
|
|
271
|
+
private readonly backendUrl;
|
|
272
|
+
/** Most recent nonce sent to the backend (for the pending OAuth/OTP request). */
|
|
273
|
+
private pendingNonce;
|
|
274
|
+
private last;
|
|
275
|
+
constructor(opts?: CavosAuthOptions);
|
|
276
|
+
/** Redirect URL for Google login (open it; user returns to your redirectUri). */
|
|
277
|
+
getGoogleOAuthUrl(redirectUri?: string): Promise<string>;
|
|
278
|
+
/** Redirect URL for Apple login. */
|
|
279
|
+
getAppleOAuthUrl(redirectUri?: string): Promise<string>;
|
|
280
|
+
private oauthUrl;
|
|
281
|
+
/**
|
|
282
|
+
* Resolve the identity from an OAuth callback. The auth data is carried in the
|
|
283
|
+
* `auth_data` (or `zk_auth_data`) query param on return. We only extract `sub`.
|
|
284
|
+
*/
|
|
285
|
+
handleCallback(authDataOrSearch: string): Promise<Identity>;
|
|
286
|
+
/** Send a one-time code to an email (Firebase OTP). */
|
|
287
|
+
sendOtp(email: string): Promise<void>;
|
|
288
|
+
/** Send a passwordless magic-link sign-in email (Firebase). */
|
|
289
|
+
sendMagicLink(email: string): Promise<void>;
|
|
290
|
+
/** Verify the OTP and resolve the identity. */
|
|
291
|
+
verifyOtp(email: string, code: string): Promise<Identity>;
|
|
292
|
+
/** AuthProvider: returns the identity resolved by the last login step. */
|
|
293
|
+
authenticate(): Promise<Identity>;
|
|
294
|
+
/**
|
|
295
|
+
* Build an `Identity` from whatever the backend returned. The Cavos backend
|
|
296
|
+
* wraps the user id in a JWT (its `sub` claim); for the device model we only
|
|
297
|
+
* need that stable id — the signature is never checked on-chain.
|
|
298
|
+
*/
|
|
299
|
+
private identityFromAuthData;
|
|
300
|
+
/** Generate (and remember) the nonce the Cavos backend expects on requests. */
|
|
301
|
+
private freshNonce;
|
|
302
|
+
/** Return the pending nonce (for the verify step), clearing it. */
|
|
303
|
+
private consumeNonce;
|
|
304
|
+
private remember;
|
|
305
|
+
private get;
|
|
306
|
+
private post;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* The address seed binds a wallet to a stable, backend-managed user identity.
|
|
311
|
+
* The deterministic account address is derived from this seed + salt ONLY — never
|
|
312
|
+
* from a device pubkey — so the same user resolves to the same wallet on any
|
|
313
|
+
* device. The backend owns the user_id <-> address mapping off-chain.
|
|
314
|
+
*/
|
|
315
|
+
interface IdentityInput {
|
|
316
|
+
/** Stable, backend-managed user identifier (e.g. from email / magic link). */
|
|
317
|
+
userId: string;
|
|
318
|
+
/** Per-app salt, so the same user has distinct wallets across apps. */
|
|
319
|
+
appSalt: string;
|
|
320
|
+
}
|
|
321
|
+
/** Derive the felt `address_seed` passed to the contract constructor. */
|
|
322
|
+
declare function deriveAddressSeed({ userId, appSalt }: IdentityInput): bigint;
|
|
323
|
+
|
|
324
|
+
interface HttpWalletRegistryOptions {
|
|
325
|
+
/** Cavos backend base URL (e.g. https://cavos.xyz). */
|
|
326
|
+
baseUrl: string;
|
|
327
|
+
/** The Cavos App ID — authenticates the SDK calls (verifyAppId). */
|
|
328
|
+
appId: string;
|
|
329
|
+
/** Network the wallet lives on (e.g. "sepolia"). */
|
|
330
|
+
network: string;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* WalletRegistry backed by the Cavos backend (`/api/wallets`). This is the
|
|
334
|
+
* persistent, cross-device source of truth for `user_id -> wallet`. The backend
|
|
335
|
+
* stores authorized device signers in `wallet_devices`; the registry maps a
|
|
336
|
+
* backend `userId` (the OAuth `sub`) onto that wallet row.
|
|
337
|
+
*/
|
|
338
|
+
declare class HttpWalletRegistry implements WalletRegistry {
|
|
339
|
+
private readonly opts;
|
|
340
|
+
constructor(opts: HttpWalletRegistryOptions);
|
|
341
|
+
lookup(userId: string): Promise<RegisteredWallet | null>;
|
|
342
|
+
register(params: {
|
|
343
|
+
userId: string;
|
|
344
|
+
address: string;
|
|
345
|
+
initialSigner: DevicePublicKey;
|
|
346
|
+
}): Promise<void>;
|
|
347
|
+
addDevice?(params: {
|
|
348
|
+
userId: string;
|
|
349
|
+
address: string;
|
|
350
|
+
signer: DevicePublicKey;
|
|
351
|
+
}): Promise<void>;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
interface HttpRecoveryClientOptions {
|
|
355
|
+
/** Cavos backend base URL (e.g. https://cavos.xyz). */
|
|
356
|
+
baseUrl: string;
|
|
357
|
+
/** The Cavos App ID — authenticates SDK calls. */
|
|
358
|
+
appId: string;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* RecoveryClient backed by the Cavos backend's device-approval relay
|
|
362
|
+
* (`/api/devices/request`). The relay holds NO keys — it stores the pending
|
|
363
|
+
* request, emails the wallet owner, and mirrors the on-chain `add_signer` once a
|
|
364
|
+
* registered device confirms.
|
|
365
|
+
*/
|
|
366
|
+
declare class HttpRecoveryClient implements RecoveryClient {
|
|
367
|
+
private readonly opts;
|
|
368
|
+
constructor(opts: HttpRecoveryClientOptions);
|
|
369
|
+
requestDeviceAddition(params: {
|
|
370
|
+
userId: string;
|
|
371
|
+
accountAddress: string;
|
|
372
|
+
newSigner: DevicePublicKey;
|
|
373
|
+
email?: string;
|
|
374
|
+
deviceLabel?: string;
|
|
375
|
+
}): Promise<{
|
|
376
|
+
requestId: string;
|
|
377
|
+
}>;
|
|
378
|
+
getPendingRequest(requestId: string): Promise<PendingDeviceRequest | null>;
|
|
379
|
+
confirmDeviceAddition(params: {
|
|
380
|
+
requestId: string;
|
|
381
|
+
txHash: string;
|
|
382
|
+
}): Promise<void>;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Generate a fresh, human-readable recovery code. The caller MUST present this
|
|
387
|
+
* to the user exactly once and never persist it server-side. ~128 bits of
|
|
388
|
+
* entropy encoded as words from a fixed wordlist (BIP39-style but our own list,
|
|
389
|
+
* so we don't pull a dependency on a BIP39 wordfile).
|
|
390
|
+
*/
|
|
391
|
+
declare function generateRecoveryCode(): string;
|
|
392
|
+
/**
|
|
393
|
+
* Deterministically derive a secp256r1 keypair from a recovery code. Pure
|
|
394
|
+
* function: the same normalised code always yields the same keypair, on any
|
|
395
|
+
* runtime. Returns the raw 32-byte private key (so it can be wrapped in a
|
|
396
|
+
* `BackupSigner` or fed to any chain adapter) plus the public key coordinates
|
|
397
|
+
* the contract stores as an authorised signer.
|
|
398
|
+
*
|
|
399
|
+
* Normalisation trims surrounding whitespace and collapses runs of spaces, so
|
|
400
|
+
* "a b" and "a b" derive the same key regardless of how the code was pasted.
|
|
401
|
+
*/
|
|
402
|
+
declare function deriveBackupKey(code: string): {
|
|
403
|
+
privateKey: Uint8Array;
|
|
404
|
+
publicKey: DevicePublicKey;
|
|
405
|
+
};
|
|
406
|
+
/**
|
|
407
|
+
* A `DeviceSigner` backed by an in-memory backup key derived from a recovery
|
|
408
|
+
* code. Used transiently during recovery to sign the `add_signer` that
|
|
409
|
+
* authorises a new device — it is NOT persisted and should not be reused as a
|
|
410
|
+
* device signer. The key material lives only for the duration of the recovery
|
|
411
|
+
* transaction.
|
|
412
|
+
*/
|
|
413
|
+
declare class BackupSigner implements DeviceSigner {
|
|
414
|
+
private readonly privateKey;
|
|
415
|
+
private readonly publicKeyValue;
|
|
416
|
+
constructor(privateKey: Uint8Array, publicKey: DevicePublicKey);
|
|
417
|
+
/** Build a signer from a recovery code (derive + wrap in one step). */
|
|
418
|
+
static fromCode(code: string): BackupSigner;
|
|
419
|
+
getPublicKey(): Promise<DevicePublicKey>;
|
|
420
|
+
sign(txHash: Uint8Array): Promise<DeviceSignature>;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
interface WebCryptoSignerOptions {
|
|
424
|
+
/**
|
|
425
|
+
* Storage key for the device's private key (e.g. the account address). One
|
|
426
|
+
* silent key per (this value, browser profile).
|
|
427
|
+
*/
|
|
428
|
+
keyId: string;
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Silent, device-bound signer for the browser. Generates a non-extractable
|
|
432
|
+
* secp256r1 (P-256) key via WebCrypto and stores the `CryptoKey` in IndexedDB.
|
|
433
|
+
* The private key is never exposed to JS and signing produces NO UI — there is
|
|
434
|
+
* no passkey, no Face ID / Touch ID prompt. To the user it is invisible; they
|
|
435
|
+
* only ever see the OAuth / email login used to derive their address.
|
|
436
|
+
*/
|
|
437
|
+
declare class WebCryptoSigner implements DeviceSigner {
|
|
438
|
+
private readonly privateKey;
|
|
439
|
+
private readonly publicKey;
|
|
440
|
+
readonly keyId: string;
|
|
441
|
+
private constructor();
|
|
442
|
+
/** Create a fresh device key (first run on this device) and persist it. */
|
|
443
|
+
static create(opts: WebCryptoSignerOptions): Promise<WebCryptoSigner>;
|
|
444
|
+
/** Load an existing device key from storage, or null if none exists yet. */
|
|
445
|
+
static load(opts: WebCryptoSignerOptions): Promise<WebCryptoSigner | null>;
|
|
446
|
+
/** Load the device key, creating one on first use. */
|
|
447
|
+
static loadOrCreate(opts: WebCryptoSignerOptions): Promise<WebCryptoSigner>;
|
|
448
|
+
getPublicKey(): Promise<DevicePublicKey>;
|
|
449
|
+
sign(txHash: Uint8Array): Promise<DeviceSignature>;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
interface StarknetAdapterOptions {
|
|
453
|
+
classHash: string;
|
|
454
|
+
/** Read provider for `isAuthorizedSigner`. Optional for build-only usage. */
|
|
455
|
+
provider?: {
|
|
456
|
+
callContract(call: {
|
|
457
|
+
contractAddress: string;
|
|
458
|
+
entrypoint: string;
|
|
459
|
+
calldata: string[];
|
|
460
|
+
}): Promise<string[]>;
|
|
461
|
+
};
|
|
462
|
+
/** Signer used to sign outgoing transactions. */
|
|
463
|
+
signer?: DeviceSigner;
|
|
464
|
+
}
|
|
465
|
+
/** Starknet implementation of the device-signer account adapter. */
|
|
466
|
+
declare class StarknetAdapter implements ChainAdapter {
|
|
467
|
+
private readonly opts;
|
|
468
|
+
readonly chain: "starknet";
|
|
469
|
+
constructor(opts: StarknetAdapterOptions);
|
|
470
|
+
computeAddress({ addressSeed, initialSigner, salt }: ComputeAddressParams): string;
|
|
471
|
+
/** Single UDC deploy; the constructor registers the first device signer, so
|
|
472
|
+
* the account is ready the moment it is deployed (fits the paymaster's
|
|
473
|
+
* deploy + execute_from_outside bundle). */
|
|
474
|
+
buildDeploy(params: ComputeAddressParams): ChainCall[];
|
|
475
|
+
/** Constructor calldata: [address_seed, pub_x_low, pub_x_high, pub_y_low, pub_y_high]. */
|
|
476
|
+
constructorCalldata(addressSeed: bigint, initialSigner: DevicePublicKey): string[];
|
|
477
|
+
buildAddSigner(accountAddress: string, signer: DevicePublicKey): ChainCall;
|
|
478
|
+
buildRemoveSigner(accountAddress: string, signer: DevicePublicKey): ChainCall;
|
|
479
|
+
isAuthorizedSigner(accountAddress: string, signer: DevicePublicKey): Promise<boolean>;
|
|
480
|
+
buildSignature(txHash: bigint): Promise<string[]>;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* A starknet.js `SignerInterface` backed by a device signer. Extends the base
|
|
485
|
+
* `Signer` so all transaction/declare hash computation (v3) is reused; only the
|
|
486
|
+
* raw hash-signing primitive is overridden to sign silently with the device key.
|
|
487
|
+
*
|
|
488
|
+
* Usage:
|
|
489
|
+
* const account = new Account(provider, address, new StarknetDeviceSigner(device), "1");
|
|
490
|
+
* await account.execute(calls); // DeviceAccount validates the device signature
|
|
491
|
+
*
|
|
492
|
+
* For gasless flows, hand this signer to your paymaster SDK (e.g. AVNU) the same
|
|
493
|
+
* way you would any starknet.js signer.
|
|
494
|
+
*/
|
|
495
|
+
declare class StarknetDeviceSigner extends Signer {
|
|
496
|
+
private readonly device;
|
|
497
|
+
constructor(device: DeviceSigner);
|
|
498
|
+
/** Device accounts are not controlled by a single Stark pubkey. */
|
|
499
|
+
getPubKey(): Promise<string>;
|
|
500
|
+
/** Sign the computed tx hash silently with the device signer. */
|
|
501
|
+
protected signRaw(msgHash: string): Promise<ArraySignatureType>;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Serialize a device signature to the felt array for `tx_info.signature`:
|
|
506
|
+
* [ r_low, r_high, s_low, s_high, y_parity ]
|
|
507
|
+
* exactly what DeviceAccount.__validate__ decodes.
|
|
508
|
+
*/
|
|
509
|
+
declare function signatureToFelts(sig: DeviceSignature): bigint[];
|
|
510
|
+
/**
|
|
511
|
+
* Recover the parity bit of an (r, s) signature over `digest` for a known
|
|
512
|
+
* pubkey. WebCrypto/Secure Enclave don't return a recovery id, so we derive it
|
|
513
|
+
* by trying both candidates and matching the device's public key.
|
|
514
|
+
*/
|
|
515
|
+
declare function recoverYParity(r: bigint, s: bigint, digest: Uint8Array, pubkey: DevicePublicKey): boolean;
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* Low-level encoding helpers shared across the kit.
|
|
519
|
+
*/
|
|
520
|
+
/** Split a u256 into the `[low, high]` felt pair Cairo expects. */
|
|
521
|
+
declare function u256ToFelts(value: bigint): [bigint, bigint];
|
|
522
|
+
/** Big-endian bytes -> bigint. */
|
|
523
|
+
declare function bytesToBigInt(bytes: Uint8Array): bigint;
|
|
524
|
+
declare function bytesToHex(bytes: Uint8Array): string;
|
|
525
|
+
declare function hexToBytes(hex: string): Uint8Array;
|
|
526
|
+
/** A felt/bigint -> 32-byte big-endian Uint8Array (the tx-hash width). */
|
|
527
|
+
declare function bigIntTo32Bytes(value: bigint): Uint8Array;
|
|
528
|
+
|
|
529
|
+
export { type AuthProvider, BackupSigner, Cavos, CavosAuth, type CavosAuthOptions, ChainAdapter, ChainCall, ComputeAddressParams, type ConnectOptions, type ConnectStatus, DevicePublicKey, DeviceSignature, DeviceSigner, HttpRecoveryClient, type HttpRecoveryClientOptions, HttpWalletRegistry, type HttpWalletRegistryOptions, type Identity, type IdentityInput, InMemoryWalletRegistry, type PendingDeviceRequest, type RecoveryClient, type RecoveryOptions, type RegisteredWallet, StarknetAdapter, type StarknetAdapterOptions, StarknetDeviceSigner, StarknetNetwork, StaticIdentity, type WalletRegistry, WebCryptoSigner, type WebCryptoSignerOptions, bigIntTo32Bytes, bytesToBigInt, bytesToHex, deriveAddressSeed, deriveBackupKey, generateRecoveryCode, hexToBytes, recoverYParity, signatureToFelts, u256ToFelts };
|