@waaskey/sdk 0.4.2 → 0.6.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/dist/index.d.ts CHANGED
@@ -699,9 +699,46 @@ declare class MemoryPrimeStore implements PrimePoolStore {
699
699
  interface PrimeGenerator {
700
700
  pregeneratePrimes(curve: MpcCurve): Promise<string>;
701
701
  }
702
+ /**
703
+ * A claim on pooled primes (#83).
704
+ *
705
+ * A keygen that fails — a server timeout, a dropped relay — used to take its primes out of the
706
+ * pool and never give them back, so every retry paid another full safe-prime generation: 5–10
707
+ * minutes of CPU in single-threaded WASM, right after something had already gone wrong. A lease
708
+ * makes the ownership explicit: primes leave the pool for good only when a ceremony actually
709
+ * derived key material from them.
710
+ */
711
+ interface PrimeLease {
712
+ /** The primes to hand the ceremony. */
713
+ readonly primes: string;
714
+ /**
715
+ * The ceremony derived key material from these — they are spent and must never be reused.
716
+ */
717
+ consume(): void;
718
+ /**
719
+ * The ceremony did not complete: put them back for the retry.
720
+ *
721
+ * Returning primes a failed ceremony may have already published an `N` for is a deliberate
722
+ * call, not an oversight. The private halves never left the device; a party that re-runs with
723
+ * the same Paillier key is in the same position as one that simply has not refreshed its aux
724
+ * info yet, which is the normal state between refreshes. The alternative — burning another
725
+ * full generation on every retry — is a cost users actually pay.
726
+ */
727
+ release(): Promise<void>;
728
+ }
702
729
  interface PrimePoolOptions {
703
730
  /** How many spare primes to keep cached per curve. Default 2. */
704
731
  targetSize?: number;
732
+ /**
733
+ * How many primes to generate at once when refilling. Default 1.
734
+ *
735
+ * Nothing in one prime search depends on another, so a worker-backed core can fill the pool in
736
+ * parallel and turn `targetSize` full generations of wall-clock into roughly one (#109). The
737
+ * default stays 1 because on a core that generates INLINE there are no cores to spare: the
738
+ * searches share the calling thread, so raising this would not finish sooner and would only
739
+ * delay the first prime becoming usable. Raise it when the core is worker-backed.
740
+ */
741
+ concurrency?: number;
705
742
  /** Persistence for the pool. Defaults to an in-memory store. */
706
743
  store?: PrimePoolStore;
707
744
  /**
@@ -719,6 +756,7 @@ declare class PrimePool {
719
756
  private readonly store;
720
757
  private readonly targetSize;
721
758
  private readonly autoRefill;
759
+ private readonly concurrency;
722
760
  /** Per-curve in-flight refill, so concurrent calls don't over-generate. */
723
761
  private readonly refilling;
724
762
  constructor(core: PrimeGenerator, options?: PrimePoolOptions);
@@ -735,6 +773,14 @@ declare class PrimePool {
735
773
  * is worker-backed).
736
774
  */
737
775
  take(curve: MpcCurve): Promise<string>;
776
+ /**
777
+ * Claim primes as a LEASE, so a failed ceremony gives them back (#83).
778
+ *
779
+ * Prefer this over {@link take} anywhere the primes feed a ceremony that can fail: `take` hands
780
+ * them over unconditionally, and a keygen that dies on a relay timeout then costs the next
781
+ * attempt a full generation it did not need to pay.
782
+ */
783
+ borrow(curve: MpcCurve): Promise<PrimeLease>;
738
784
  }
739
785
 
740
786
  /**
@@ -861,7 +907,7 @@ declare class IndexedDbKeyValueStore implements KeyValueStore {
861
907
  * (`{ statusCode, message, error }`) to a code; orchestration failures (device keygen,
862
908
  * missing share, cancellation) use the SDK-side codes.
863
909
  */
864
- type WaaskeyErrorCode = 'unauthorized' | 'forbidden' | 'not_found' | 'validation' | 'conflict' | 'rate_limited' | 'server_error' | 'network' | 'unsupported_chain' | 'provider_error' | 'device_core_required' | 'keygen_failed' | 'sign_failed' | 'reshare_failed' | 'reshare_pubkey_mismatch' | 'share_not_found' | 'recovery_failed' | 'invalid_recovery_code' | 'backup_failed' | 'wallet_activation_timeout' | 'sign_ceremony_timeout' | 'unauthenticated' | 'firebase_not_enabled' | 'mfa_required' | 'no_member' | 'unsupported' | 'aborted' | 'unknown';
910
+ type WaaskeyErrorCode = 'unauthorized' | 'forbidden' | 'not_found' | 'validation' | 'conflict' | 'rate_limited' | 'server_error' | 'network' | 'unsupported_chain' | 'provider_error' | 'device_core_required' | 'device_store_required' | 'keygen_failed' | 'sign_failed' | 'reshare_failed' | 'reshare_pubkey_mismatch' | 'share_not_found' | 'recovery_failed' | 'invalid_recovery_code' | 'backup_failed' | 'wallet_activation_timeout' | 'sign_ceremony_timeout' | 'unauthenticated' | 'firebase_not_enabled' | 'mfa_required' | 'no_member' | 'unsupported' | 'permission_expired' | 'permission_revoked' | 'permission_scope' | 'permission_value_exceeded' | 'permission_exhausted' | 'permission_rate_limited' | 'permission_request_timeout' | 'permission_declined' | 'aborted' | 'unknown';
865
911
  interface WaaskeyErrorOptions {
866
912
  /** HTTP status, when the error originates from an API response. */
867
913
  status?: number;
@@ -935,6 +981,14 @@ interface WaaskeyOptions {
935
981
  baseUrl: string;
936
982
  /** Custom fetch implementation (e.g. for non-browser runtimes). Defaults to global `fetch`. */
937
983
  fetch?: typeof fetch;
984
+ /**
985
+ * Where a permission request sends the user to answer it — the wallet that holds their key (#113).
986
+ *
987
+ * Required only by `sessionKeys.request`, and deliberately not defaulted: which wallet is "the"
988
+ * wallet is a product decision (your own app, waaskey mobile, the extension), and guessing it
989
+ * would send users somewhere that cannot answer.
990
+ */
991
+ walletUrl?: string;
938
992
  /**
939
993
  * Device-party MPC core (e.g. `WasmMpcCore`). Required to create a wallet — the
940
994
  * device runs its half of the keygen ceremony with this.
@@ -945,6 +999,15 @@ interface WaaskeyOptions {
945
999
  * `EncryptedShareStore.browser(secret)`). Required to create a wallet.
946
1000
  */
947
1001
  shareStore?: ShareStore;
1002
+ /**
1003
+ * Where this client's stable **device id** is persisted (e.g. `new IndexedDbKeyValueStore()`).
1004
+ * Required to act as a member DEVICE — registering, and joining a member-bound wallet's
1005
+ * ceremonies as `member:<membershipId>:<deviceId>`.
1006
+ *
1007
+ * Deliberately NOT the sealed share store: the device id is public (it is in every party role),
1008
+ * and sealing it would make it unavailable before unlock — exactly when registration needs it.
1009
+ */
1010
+ deviceStore?: KeyValueStore;
948
1011
  /**
949
1012
  * Optional pool of pre-generated Paillier primes (`new PrimePool(mpc)`). When set,
950
1013
  * `wallets.prewarm(chain)` fills it off the hot path and `wallets.create` claims from
@@ -1003,6 +1066,15 @@ interface CreateWalletOptions {
1003
1066
  activationTimeoutMs?: number;
1004
1067
  /** Poll interval while waiting for activation, ms. Default 1000. */
1005
1068
  pollIntervalMs?: number;
1069
+ /**
1070
+ * What the backup ended up enrolled with (#105) — called once, before `create` resolves.
1071
+ *
1072
+ * The app needs this to say the right thing: a passkey-guarded wallet must NOT be shown a
1073
+ * "write this code down" screen for a code nobody will ever ask for, and a code-guarded one must.
1074
+ * Guessing from device capability is not enough, because enrolment can fall back for reasons the
1075
+ * app cannot see.
1076
+ */
1077
+ onRecoveryEnrolled?: (enrolment: RecoveryEnrolment) => void;
1006
1078
  /**
1007
1079
  * Recovery-backup material for a **non-custodial** `[device, server, user_backup]` create (#351/#78):
1008
1080
  * REQUIRED when the returned ceremony carries a `user_backup` party ({@link WalletCeremony.additionalParties}).
@@ -1024,6 +1096,28 @@ interface CreateWalletOptions {
1024
1096
  * secret and never leaves the device (only its SHA-256 is enrolled), so a lost code is an
1025
1097
  * unrecoverable backup.
1026
1098
  */
1099
+ /**
1100
+ * Produces a passkey PRF credential for recovery enrolment, or `undefined` when this device cannot
1101
+ * (no platform authenticator, no PRF extension, the user declined).
1102
+ *
1103
+ * A function rather than a class so a React Native or a test caller can supply one without the
1104
+ * browser WebAuthn surface; `PasskeyPrfSecretProvider.enroll` fits it directly.
1105
+ */
1106
+ type PasskeyEnroller = () => Promise<{
1107
+ secret: string;
1108
+ salt: string;
1109
+ credentialId: string;
1110
+ } | undefined>;
1111
+ /** Which factor ended up guarding the backup, and why (#105). */
1112
+ interface RecoveryEnrolment {
1113
+ /**
1114
+ * The strong factor that was enrolled. `recovery_code` means the user MUST be shown their code;
1115
+ * `passkey` means they must not be told to write down a code they will never be asked for.
1116
+ */
1117
+ strongFactor: 'passkey' | 'recovery_code';
1118
+ /** Why the passkey was not used. Absent when it was. */
1119
+ fallbackReason?: 'no_passkey_enroller' | 'device_cannot_prf' | 'enrolment_failed';
1120
+ }
1027
1121
  interface WalletBackupParams {
1028
1122
  /** High-entropy recovery code that seals the user_backup share. Show it to the user once — it is the only key to the backup and never leaves the client. */
1029
1123
  recoveryCode: string;
@@ -1033,6 +1127,17 @@ interface WalletBackupParams {
1033
1127
  email: string;
1034
1128
  /** Extra factor enrolments beyond the standard three. */
1035
1129
  extraFactors?: FactorEnrollment[];
1130
+ /**
1131
+ * Enrol a passkey INSTEAD of the recovery code when this device can produce a PRF — the #511
1132
+ * default (waas-backend#511), made automatic here rather than left as an opt-in (#105).
1133
+ *
1134
+ * Called once during `create`. Return the credential to enrol it as the strong factor; return
1135
+ * `undefined` (or throw) and the recovery code is used instead. A device without PRF is a
1136
+ * permanent property of that device, not a user error, so the fallback is silent — but which of
1137
+ * the two was enrolled is reported through `onRecoveryEnrolled`, because it decides whether the
1138
+ * app must tell the user to write a code down.
1139
+ */
1140
+ passkeyEnroller?: PasskeyEnroller;
1036
1141
  /**
1037
1142
  * A passkey PRF secret to ALSO wrap the backup key with (#510) — pass what
1038
1143
  * `PasskeyPrfSecretProvider.enroll()` returned. The backup then opens with either the passkey or the
@@ -1066,6 +1171,42 @@ interface WalletBackupParams {
1066
1171
  interface JoinCeremonyOptions {
1067
1172
  /** Cancel the join (roster ack + the relay keygen ceremony). */
1068
1173
  signal?: AbortSignal;
1174
+ /**
1175
+ * Which of the member's devices is joining (#54). Required when the member holds several — the
1176
+ * backend cannot guess which one, and the share is sealed under this device's own key.
1177
+ * Defaults to the client's stored device id when a `deviceStore` is configured.
1178
+ */
1179
+ deviceId?: string;
1180
+ }
1181
+ /**
1182
+ * One of a member's registered devices (#53). Mirrors the backend `IMemberDevice`.
1183
+ */
1184
+ interface Device {
1185
+ /** Registry id — what {@link Devices.revoke} takes (NOT the client-generated `deviceId`). */
1186
+ id: string;
1187
+ /** The owning member seat. */
1188
+ membershipId: string;
1189
+ /** The client-generated stable id this device is known by in party roles. */
1190
+ deviceId: string;
1191
+ /** Human-friendly label, e.g. "Chrome on MacBook Pro". */
1192
+ label: string;
1193
+ createdAt: string;
1194
+ /** Last re-registration; null until the device re-registers after creation. */
1195
+ lastSeenAt: string | null;
1196
+ /** The device's X25519 encryption public key (32-byte hex), when it registered one. */
1197
+ encryptionPublicKey?: string | null;
1198
+ }
1199
+ /** What {@link Devices.register} sends. */
1200
+ interface DeviceRegistration {
1201
+ /** Human-friendly label shown in device pickers and the dashboard. */
1202
+ label: string;
1203
+ /** Override the stored id — for a caller with no `deviceStore` of its own. */
1204
+ deviceId?: string;
1205
+ /**
1206
+ * This device's X25519 encryption public key (32-byte non-zero hex). Dealers seal reshare
1207
+ * sub-shares and FROST round-2 packages to it, so a device that will hold a share needs one.
1208
+ */
1209
+ encryptionPublicKey?: string;
1069
1210
  }
1070
1211
  /** Options for `wallets.joinSignCeremony(...)` (#349). */
1071
1212
  interface JoinSignCeremonyOptions {
@@ -1075,6 +1216,11 @@ interface JoinSignCeremonyOptions {
1075
1216
  readyTimeoutMs?: number;
1076
1217
  /** Poll interval while waiting for the quorum, ms. Default 1000. */
1077
1218
  pollIntervalMs?: number;
1219
+ /**
1220
+ * Which of the member's devices is signing (#54) — it must be the device whose share this
1221
+ * client holds. Defaults to the client's stored device id when a `deviceStore` is configured.
1222
+ */
1223
+ deviceId?: string;
1078
1224
  }
1079
1225
  /**
1080
1226
  * A WebAuthn assertion attached for passkey step-up (issue #21/#39) — the structural
@@ -1760,6 +1906,17 @@ interface RegisterRecoveryParams {
1760
1906
  email: string;
1761
1907
  /** Extra factor enrolments beyond the standard three. */
1762
1908
  extraFactors?: FactorEnrollment[];
1909
+ /**
1910
+ * Enrol a passkey INSTEAD of the recovery code when this device can produce a PRF — the #511
1911
+ * default (waas-backend#511), made automatic here rather than left as an opt-in (#105).
1912
+ *
1913
+ * Called once during `create`. Return the credential to enrol it as the strong factor; return
1914
+ * `undefined` (or throw) and the recovery code is used instead. A device without PRF is a
1915
+ * permanent property of that device, not a user error, so the fallback is silent — but which of
1916
+ * the two was enrolled is reported through `onRecoveryEnrolled`, because it decides whether the
1917
+ * app must tell the user to write a code down.
1918
+ */
1919
+ passkeyEnroller?: PasskeyEnroller;
1763
1920
  /**
1764
1921
  * A passkey PRF secret to ALSO wrap the backup key with (#510) — pass what
1765
1922
  * `PasskeyPrfSecretProvider.enroll()` returned. The backup then opens with either the passkey or the
@@ -2051,6 +2208,18 @@ interface Member {
2051
2208
  totpEnabled: boolean;
2052
2209
  createdAt: string;
2053
2210
  }
2211
+ /**
2212
+ * A team member as the members roster returns them (#57) — the login identity plus the
2213
+ * per-membership capability a creator picks share-holders by.
2214
+ */
2215
+ interface TeamMember extends Member {
2216
+ /**
2217
+ * Whether this membership may hold a wallet key share (#342). Defaults from the role
2218
+ * (owner/admin true, member false) and is togglable by a manager — so it is NOT derivable from
2219
+ * `role`, and guessing it in a picker offers users a choice the backend will refuse.
2220
+ */
2221
+ canHoldShare: boolean;
2222
+ }
2054
2223
  /**
2055
2224
  * A held org-member bearer session (mirrors the backend `FirebaseAuthResponse`). Returned by
2056
2225
  * {@link Members.loginWithFirebase} and held by the client so member-scoped calls authenticate with
@@ -2069,6 +2238,169 @@ interface MemberSession {
2069
2238
  member: Member;
2070
2239
  }
2071
2240
 
2241
+ /** A granted session key, as the API lists it (#112). */
2242
+ interface SessionKey {
2243
+ id: string;
2244
+ walletId: string;
2245
+ /** Compressed secp256k1 public key of the key; the private half never leaves the grantee. */
2246
+ publicKey: string;
2247
+ permissions: {
2248
+ allowedContracts?: string[];
2249
+ allowedSelectors?: string[];
2250
+ /** Per-call value cap (hex wei). */
2251
+ maxValueWei?: string;
2252
+ /** Lifetime call budget — how much the grant is worth in total. */
2253
+ maxCalls?: number;
2254
+ allowedChains?: string[];
2255
+ /** Length of the rate window in seconds; set whenever a per-period cap is (#538). */
2256
+ periodSeconds?: number;
2257
+ /** Calls allowed within one period — a rate, on top of the lifetime `maxCalls`. */
2258
+ maxCallsPerPeriod?: number;
2259
+ /** Total value allowed within one period (hex wei). */
2260
+ maxValueWeiPerPeriod?: string;
2261
+ };
2262
+ expiresAt: string;
2263
+ /**
2264
+ * What this permission is for, in the granter's words (#534).
2265
+ *
2266
+ * Metadata only — it takes no part in any authorization decision. Without it a client can list a
2267
+ * permission by its public key alone, which tells a user nothing about which grant they are
2268
+ * about to revoke.
2269
+ */
2270
+ label?: string | null;
2271
+ /**
2272
+ * The registered app that asked for this permission, when one did (#539).
2273
+ *
2274
+ * An id, not a name: resolve it through `waaskey.sessionKeys.requester(id)` and read its
2275
+ * `status` — only a `verified` requester may be presented to a user as identity.
2276
+ */
2277
+ requesterId?: string | null;
2278
+ /** The sponsorship policy funding this permission's gas (#539). */
2279
+ paymasterPolicyId?: string | null;
2280
+ /** Whether the wallet's owner has answered the request for this permission (#553). */
2281
+ grantStatus?: PermissionGrantStatus;
2282
+ /** When they approved it; null while pending or after a refusal. */
2283
+ approvedAt?: string | null;
2284
+ callsUsed: number;
2285
+ /** Start of the rate window the usage below is counted in; null until the first call. */
2286
+ periodStartedAt?: string | null;
2287
+ /** Calls spent in the current period — stale once that period has lapsed. */
2288
+ periodCallsUsed?: number;
2289
+ /** Value spent in the current period, decimal wei — stale once that period has lapsed. */
2290
+ periodValueWeiUsed?: string;
2291
+ active: boolean;
2292
+ createdAt: string;
2293
+ }
2294
+ /** What a session key needs to act: the permission, the account, and the call. */
2295
+ interface SessionKeySendParams {
2296
+ /** Id of the granted session key (the API knows its public half). */
2297
+ sessionKeyId: string;
2298
+ /** The session key's PRIVATE key (hex). Never sent anywhere — it signs locally. */
2299
+ privateKey: string;
2300
+ /** Smart account the operation is for. */
2301
+ sender: string;
2302
+ /** waas chain id, e.g. `evm:1`. */
2303
+ chainId: string;
2304
+ /** ABI-encoded `execute` calldata of the call. */
2305
+ callData: string;
2306
+ /** Target contract — checked against the key's allowlist. */
2307
+ contract: string;
2308
+ /** 4-byte selector — checked against the key's allowlist. */
2309
+ selector: string;
2310
+ /** Call value in wei (hex) — checked against the key's cap. */
2311
+ valueWei: string;
2312
+ /** Account nonce; the server resolves the current one when omitted. */
2313
+ nonce?: string;
2314
+ }
2315
+ /** What the bundler accepted. */
2316
+ interface SessionKeySendResult {
2317
+ userOpHash: string;
2318
+ }
2319
+ /** The scope an app asks a user for (#113). Every bound is optional; omitting one asks for no limit. */
2320
+ interface PermissionScope {
2321
+ /** Contracts the key may call; omitted = any. */
2322
+ allowedContracts?: string[];
2323
+ /** 4-byte selectors it may call; omitted = any. */
2324
+ allowedSelectors?: string[];
2325
+ /** Chains it may act on (waas ids, e.g. `evm:1`); omitted = any. */
2326
+ allowedChains?: string[];
2327
+ /** Per-call value cap (hex wei). */
2328
+ maxValueWei?: string;
2329
+ /** Lifetime call budget — how much the grant is worth in total. */
2330
+ maxCalls?: number;
2331
+ /** Length of the rate window in seconds; required with either per-period cap. */
2332
+ periodSeconds?: number;
2333
+ /** Calls allowed within one period — a rate, on top of `maxCalls`. */
2334
+ maxCallsPerPeriod?: number;
2335
+ /** Total value allowed within one period (hex wei). */
2336
+ maxValueWeiPerPeriod?: string;
2337
+ }
2338
+ /** What an app asks for when it requests a permission (#113). */
2339
+ interface PermissionRequestParams {
2340
+ /** The wallet being asked. */
2341
+ walletId: string;
2342
+ /** The scope wanted. The user may narrow it; they can never widen it. */
2343
+ scope: PermissionScope;
2344
+ /** When it should expire. */
2345
+ expiresAt: Date | string;
2346
+ /** What it is for, in words the user will read. */
2347
+ label?: string;
2348
+ /** The registered app doing the asking — the wallet shows its proven domain. */
2349
+ requesterId?: string;
2350
+ /** Sponsorship policy funding its gas, when the app pays. */
2351
+ paymasterPolicyId?: string;
2352
+ }
2353
+ /**
2354
+ * A permission that has been asked for and not yet answered.
2355
+ *
2356
+ * `privateKey` never leaves the caller: the SDK generated the pair locally and registered only the
2357
+ * public half, so nothing secret is on the wire, in the link, or in the wallet.
2358
+ */
2359
+ interface PermissionRequest {
2360
+ /** Id of the pending grant — poll it, and use it to sign once approved. */
2361
+ sessionKeyId: string;
2362
+ /** The private half, held only here. Store it as you would any signing key. */
2363
+ privateKey: string;
2364
+ /** Its public half, which is what the API was told. */
2365
+ publicKey: string;
2366
+ /** Where to send the user to answer: open it, or render it as a QR code. */
2367
+ url: string;
2368
+ /** Whether an answer is still outstanding — `approved` already for a wallet with no owner to ask. */
2369
+ status: PermissionGrantStatus;
2370
+ }
2371
+ /**
2372
+ * An app that may ask a user for a permission (#539).
2373
+ *
2374
+ * `name` and `iconUrl` are what the app CLAIMS about itself and are never verified; `origin` is the
2375
+ * only part that can carry trust, and only when `status` is `verified` — meaning that domain
2376
+ * published a document naming the tenant. A consent screen that shows an unproven domain as proven
2377
+ * is worse than one that shows nothing.
2378
+ */
2379
+ interface AppRequester {
2380
+ id: string;
2381
+ /** The https origin that identifies the app. */
2382
+ origin: string;
2383
+ /** Claimed by the app; never verified. */
2384
+ name: string;
2385
+ /** Claimed by the app; never verified. */
2386
+ iconUrl?: string | null;
2387
+ status: 'pending' | 'verified' | 'failed';
2388
+ /** When the domain last proved the claim; null until it has. */
2389
+ verifiedAt?: string | null;
2390
+ /** Why the last check failed — what the app's operator has to fix. */
2391
+ lastFailure?: string | null;
2392
+ }
2393
+ /** Whether the wallet's owner has answered a permission request. */
2394
+ type PermissionGrantStatus = 'pending' | 'approved' | 'declined';
2395
+ /** The answer to a permission request, and what was actually granted (#113). */
2396
+ interface PermissionDecision {
2397
+ status: PermissionGrantStatus;
2398
+ /** The permission as it now stands — the scope the user accepted, which may be narrower than asked. */
2399
+ key: SessionKey;
2400
+ /** True when the user accepted less than was asked for, so an app can adapt instead of failing opaquely. */
2401
+ narrowed: boolean;
2402
+ }
2403
+
2072
2404
  /**
2073
2405
  * Embedded end-user authentication (#6) — Privy-style login that maps an end-user to a
2074
2406
  * non-custodial wallet, distinct from the dashboard member auth. The developer's API key
@@ -2150,6 +2482,86 @@ interface PasskeyCeremony {
2150
2482
  get(options: unknown): Promise<unknown>;
2151
2483
  }
2152
2484
 
2485
+ /**
2486
+ * This browser (or Node process) as a **member device** (#53) — the client half of the
2487
+ * per-membership device registry the multi-device wallet model is built on.
2488
+ *
2489
+ * A member-bound wallet gives each device its OWN share, and the parties are named
2490
+ * `member:<membershipId>:<deviceId>`. That only works if a device can say which one it is,
2491
+ * consistently, across reloads — so the id is minted once and persisted, never derived from
2492
+ * anything the browser may change (a user agent, an install id, a session).
2493
+ *
2494
+ * The id is **not a secret and not a credential**: it appears verbatim in the protocol roles every
2495
+ * other party sees, and holding it grants nothing. What proves the device is the share it holds and
2496
+ * the member session it registered under. Which is why it is kept in a plain
2497
+ * {@link KeyValueStore} rather than the sealed share store — sealing a public identifier would only
2498
+ * make it unavailable before unlock, when registration needs it most.
2499
+ *
2500
+ * Every call here is MEMBER-scoped (`Authorization: Bearer <member access token>`, or the ambient
2501
+ * dashboard cookie): a device belongs to a member seat, not to a tenant API key.
2502
+ */
2503
+ declare class Devices {
2504
+ private readonly http;
2505
+ private readonly store?;
2506
+ constructor(http: HttpClient, store?: KeyValueStore | undefined);
2507
+ /**
2508
+ * This device's stable id, minting and persisting one on first use.
2509
+ *
2510
+ * A caller with no configured store must pass its own id to {@link register} — an id that is
2511
+ * regenerated per call is worse than none: the registry would fill with orphan devices and none
2512
+ * of them would match the share this browser actually holds.
2513
+ *
2514
+ * @throws {WaaskeyError} `device_store_required` — no store configured to persist the id.
2515
+ */
2516
+ deviceId(): Promise<string>;
2517
+ /**
2518
+ * The persisted device id, or `undefined` when this client has never minted one.
2519
+ *
2520
+ * Read-only on purpose: it is how other resources DEFAULT to this device without minting an
2521
+ * identity as a side effect of joining a ceremony. A silently minted id would be one this
2522
+ * device never registered and holds no share for.
2523
+ */
2524
+ stored(): Promise<string | undefined>;
2525
+ /**
2526
+ * Register (or re-register) this device under the caller's member seat.
2527
+ *
2528
+ * Idempotent by `deviceId`: the backend upserts, so calling it on every start refreshes
2529
+ * `lastSeenAt` and rotates the encryption public key without creating a second device. That
2530
+ * matters — a duplicate device would appear in the picker as a share-holder candidate that holds
2531
+ * nothing.
2532
+ *
2533
+ * `encryptionPublicKey` is this device's X25519 key; dealers seal reshare sub-shares and FROST
2534
+ * round-2 packages to it, so a device that will hold a share should register one.
2535
+ */
2536
+ register(registration: DeviceRegistration, signal?: AbortSignal): Promise<Device>;
2537
+ /** The caller's own registered devices — this one and their others. */
2538
+ list(signal?: AbortSignal): Promise<Device[]>;
2539
+ /**
2540
+ * The caller's devices, each marked whether it is THIS client (#57).
2541
+ *
2542
+ * A device-management UI cannot work this out on its own: the registry returns a member's
2543
+ * devices with no notion of who is asking, and the only thing that distinguishes this browser is
2544
+ * the id stored here. Getting it wrong is not cosmetic — "revoke" next to the wrong row revokes
2545
+ * the device the user is standing on, and the backend will happily do it.
2546
+ *
2547
+ * Every device reads as "not this one" when this client has no stored id, which is the honest
2548
+ * answer: it has no identity to match against.
2549
+ */
2550
+ mine(signal?: AbortSignal): Promise<Array<Device & {
2551
+ isThisDevice: boolean;
2552
+ }>>;
2553
+ /**
2554
+ * Revoke one of the caller's own devices by its registry id (not its `deviceId`).
2555
+ *
2556
+ * The backend tombstones any live shares it holds, and REFUSES (409) when that would strand a
2557
+ * wallet mid-keygen or drop an active wallet below its signing threshold — losing the ability to
2558
+ * sign is not something a device-management action gets to do quietly.
2559
+ */
2560
+ revoke(id: string, signal?: AbortSignal): Promise<void>;
2561
+ /** Forget this browser's device id, so the next {@link deviceId} mints a new one. */
2562
+ forget(): Promise<void>;
2563
+ }
2564
+
2153
2565
  /**
2154
2566
  * Org-member (dashboard "plane B") authentication — a bearer member login for a NON-browser
2155
2567
  * consumer (a Node app, or the browser extension via the SDK) that cannot carry the ambient
@@ -2193,6 +2605,31 @@ declare class Members {
2193
2605
  restore(session: MemberSession): void;
2194
2606
  /** Clear the held member session (sign out); member calls fall back to the cookie path afterwards. */
2195
2607
  memberSignOut(): void;
2608
+ /**
2609
+ * The tenant's team members, optionally narrowed to the share-holder-eligible roster (#57) —
2610
+ * what a wallet creator picks share-holders from.
2611
+ *
2612
+ * `canHoldShare` is a per-membership capability, not part of the login identity, so it is only
2613
+ * on this view: the session's own `member` does not carry it (see {@link eligibility}).
2614
+ */
2615
+ list(options?: {
2616
+ canHoldShare?: boolean;
2617
+ }, signal?: AbortSignal): Promise<TeamMember[]>;
2618
+ /**
2619
+ * Whether the logged-in member may hold a wallet key share, and who else may — one call, because
2620
+ * a device-picker UI needs both at once.
2621
+ *
2622
+ * It reads the roster to answer a question about the caller because the member session does not
2623
+ * carry `canHoldShare` (the backend's session view is the login identity, `IMember`). Worth
2624
+ * knowing rather than hiding: a UI that offers "hold a share on this device" to an ineligible
2625
+ * member produces a create that the backend refuses at binding time, after the user has chosen.
2626
+ *
2627
+ * @throws {WaaskeyError} `unauthorized` — no member session is held.
2628
+ */
2629
+ eligibility(signal?: AbortSignal): Promise<{
2630
+ canHoldShare: boolean;
2631
+ eligible: TeamMember[];
2632
+ }>;
2196
2633
  }
2197
2634
 
2198
2635
  /**
@@ -2356,6 +2793,108 @@ declare class Reshare {
2356
2793
  */
2357
2794
  declare function epochShareKey(walletId: string, keyEpoch: number): string;
2358
2795
 
2796
+ /**
2797
+ * The `sessionKeys` resource — exercise a delegated permission (#112).
2798
+ *
2799
+ * A session key is a scoped, time-limited signer the wallet granted: it may call certain contracts,
2800
+ * certain selectors, up to a value, a bounded number of times. Creating and revoking one has been
2801
+ * possible for a while; USING one had no client at all, which is what this closes.
2802
+ *
2803
+ * Two credentials are involved and they are not interchangeable — the surprise everyone hits once:
2804
+ *
2805
+ * * the **API key** on the client, which must carry the `SIGN` scope: the session private key
2806
+ * alone does not reach the API;
2807
+ * * the **session private key**, which never leaves the caller and is what actually authorizes the
2808
+ * operation on-chain.
2809
+ */
2810
+ declare class SessionKeys {
2811
+ private readonly http;
2812
+ private readonly walletUrl?;
2813
+ constructor(http: HttpClient, walletUrl?: string | undefined);
2814
+ /**
2815
+ * Ask a user for a permission, and get back a link to send them to (#113).
2816
+ *
2817
+ * The keypair is generated HERE and only its public half is registered, so nothing secret ever
2818
+ * travels: not in the request, not in the link, not through the wallet. The private key in the
2819
+ * result is the app's to keep — there is no way to retrieve it later, by design.
2820
+ *
2821
+ * The link is where the user answers. Open it, or render it as a QR code for a wallet on another
2822
+ * device. Then wait for the answer with {@link waitForDecision}.
2823
+ *
2824
+ * @example
2825
+ * ```ts
2826
+ * const req = await waaskey.sessionKeys.request({
2827
+ * walletId, label: 'Dungeon Quest — one battle',
2828
+ * scope: { allowedContracts: [game], maxCalls: 50, periodSeconds: 3600, maxCallsPerPeriod: 10 },
2829
+ * expiresAt: new Date(Date.now() + 24 * 3600_000),
2830
+ * });
2831
+ * showQrCode(req.url);
2832
+ * const { status, key, narrowed } = await waaskey.sessionKeys.waitForDecision(req.sessionKeyId);
2833
+ * ```
2834
+ */
2835
+ request(params: PermissionRequestParams, signal?: AbortSignal): Promise<PermissionRequest>;
2836
+ /** One permission as it now stands — including whether its owner has answered yet. */
2837
+ get(sessionKeyId: string, signal?: AbortSignal): Promise<SessionKey>;
2838
+ /**
2839
+ * The app that asked for a permission — who it says it is, and whether its domain proved it.
2840
+ *
2841
+ * A wallet rendering a consent screen needs this, and hand-rolling the call is how a client ends
2842
+ * up showing `name` without `status` beside it — which reads as verified whether or not it is.
2843
+ */
2844
+ requester(requesterId: string, signal?: AbortSignal): Promise<AppRequester>;
2845
+ /**
2846
+ * Wait for the user to answer a permission request (#113).
2847
+ *
2848
+ * Polls, rather than waiting on a redirect back: a user who answers on their phone, or closes the
2849
+ * tab, or takes a minute to read the screen would otherwise strand the app with no answer at all.
2850
+ *
2851
+ * Returns as soon as the wallet's owner has decided — `declined` is an answer, not an error, and
2852
+ * is returned rather than thrown so the app can say something useful. A request that is never
2853
+ * answered times out, which IS an error: it is indistinguishable from a user who walked away.
2854
+ *
2855
+ * `narrowed` says the user accepted less than was asked (they may narrow, never widen), so an app
2856
+ * can adapt to the smaller scope instead of failing opaquely on the first call outside it.
2857
+ */
2858
+ waitForDecision(sessionKeyId: string, options?: WaitForDecisionOptions): Promise<PermissionDecision>;
2859
+ /** The tenant's active session keys, newest first (optionally for one wallet). */
2860
+ list(walletId?: string, signal?: AbortSignal): Promise<SessionKey[]>;
2861
+ /**
2862
+ * Sign a call with a session key and submit it as a UserOperation.
2863
+ *
2864
+ * The op is prepared server-side first, because its gas and paymaster fields are part of what the
2865
+ * signature covers: signing a locally-guessed op would produce a signature for an operation the
2866
+ * bundler never sees. Those exact fields are then sent back with the signature, so what was
2867
+ * signed is what is submitted.
2868
+ *
2869
+ * @example
2870
+ * ```ts
2871
+ * const { userOpHash } = await waaskey.sessionKeys.send({
2872
+ * sessionKeyId, privateKey, // the granted permission
2873
+ * sender, chainId: 'evm:1', // the smart account it acts for
2874
+ * callData, contract, selector, valueWei: '0x0',
2875
+ * });
2876
+ * ```
2877
+ */
2878
+ send(params: SessionKeySendParams, signal?: AbortSignal): Promise<SessionKeySendResult>;
2879
+ }
2880
+ /**
2881
+ * Sign a UserOperation hash the way a SimpleAccount verifies it: over the EIP-191 personal-sign
2882
+ * form, not the raw hash. The account contract recovers from
2883
+ * `userOpHash.toEthSignedMessageHash()`, so anything else is a signature the chain rejects — and
2884
+ * the API now rejects it earlier, which is the same answer sooner.
2885
+ */
2886
+ declare function signUserOpHash(userOpHash: string, privateKey: string): string;
2887
+ /** How long to wait for an answer, and how often to look. */
2888
+ interface WaitForDecisionOptions {
2889
+ /** Give up after this long. Default 5 minutes. */
2890
+ timeoutMs?: number;
2891
+ /** How often to ask. Default every 2 seconds. */
2892
+ pollMs?: number;
2893
+ signal?: AbortSignal;
2894
+ /** The scope that was asked for; supply it to learn whether the user narrowed it. */
2895
+ asked?: PermissionScope;
2896
+ }
2897
+
2359
2898
  /** Device-party dependencies a {@link Wallet} needs to co-sign an ed25519 (FROST) transaction locally. */
2360
2899
  interface WalletDeviceDeps {
2361
2900
  mpc?: MpcCore;
@@ -2524,6 +3063,8 @@ interface WalletsDeps {
2524
3063
  primePool?: PrimePool;
2525
3064
  /** Optional analytics emitter for wallet lifecycle events. */
2526
3065
  analytics?: Analytics;
3066
+ /** This client's device identity (#53) — supplies the default `deviceId` for member ceremonies. */
3067
+ devices?: Devices;
2527
3068
  }
2528
3069
  /**
2529
3070
  * The `wallets` resource: create and load wallets, plus the approver actions
@@ -2694,6 +3235,8 @@ declare class Wallets {
2694
3235
  * it unjoined would hang the whole ceremony, so failing loud beats silently deadlocking.
2695
3236
  */
2696
3237
  private runSecpKeygen;
3238
+ /** The `[device, server, user_backup]` ceremony itself — see {@link runSecpKeygen} for why the primes are leased. */
3239
+ private runNonCustodialKeygen;
2697
3240
  /**
2698
3241
  * Register a sealed user_backup {@link RecoveryRegisterPayload} server-side, with a small bounded retry
2699
3242
  * on TRANSIENT failures (network / 5xx / rate-limit) — a flaky moment must not cost the backup. A
@@ -2776,14 +3319,30 @@ declare class Wallets {
2776
3319
  /** Poll the wallet until keygen completes (ACTIVE), or throw on failure/timeout. */
2777
3320
  private waitUntilActive;
2778
3321
  /** Poll the member's own sign ceremony until the t-of-n quorum is fixed AND this member is selected, or throw on timeout. */
3322
+ /**
3323
+ * The device id to act as: an explicit one, else the client's stored id, else none.
3324
+ *
3325
+ * `undefined` is a legitimate answer, not a failure — a single-device member and every existing
3326
+ * consumer built before per-device shares work exactly as they did, on the un-suffixed key and
3327
+ * the un-parameterised endpoints.
3328
+ */
3329
+ private resolveDeviceId;
2779
3330
  private waitUntilReady;
2780
3331
  }
2781
3332
  /**
2782
3333
  * Storage key for a member-bound wallet's per-member share (#349) — distinct from the embedded
2783
3334
  * flow's bare `walletId` key ({@link Wallet}'s single device share), since several members' shares
2784
3335
  * for the SAME wallet may live in one {@link ShareStore} (e.g. a shared device, or a test harness).
3336
+ *
3337
+ * With `deviceId` (#54) the key is per DEVICE as well: one member may hold DISTINCT shares of the
3338
+ * same wallet across their own devices (browser, phone), and a device must only ever read its own.
3339
+ *
3340
+ * Without it the key keeps its original shape, and that is not a convenience — a share sealed under
3341
+ * the old key by an earlier SDK version is still in the user's browser, and a key change that could
3342
+ * not find it would look exactly like a lost wallet. Same reasoning as `epochShareKey` keeping
3343
+ * epoch 1 on the bare wallet id.
2785
3344
  */
2786
- declare function memberShareKey(walletId: string, membershipId: string): string;
3345
+ declare function memberShareKey(walletId: string, membershipId: string, deviceId?: string): string;
2787
3346
  /**
2788
3347
  * Storage key for a non-custodial wallet's PENDING user_backup backup (#351/#78) — the sealed
2789
3348
  * {@link RecoveryRegisterPayload} ciphertext {@link Wallets.create} persists before registering it
@@ -2823,8 +3382,12 @@ declare class Waaskey {
2823
3382
  readonly auth: Auth;
2824
3383
  /** The `members` resource — org-member (dashboard "plane B") bearer login for headless consumers. */
2825
3384
  readonly members: Members;
3385
+ /** The `devices` resource — this client as a member DEVICE that can hold an MPC share (#53). */
3386
+ readonly devices: Devices;
2826
3387
  /** The `onramp` resource — fund the wallet with fiat via a provider on-ramp. */
2827
3388
  readonly onramp: Onramp;
3389
+ /** The `sessionKeys` resource — act with a delegated, scoped permission (#112). */
3390
+ readonly sessionKeys: SessionKeys;
2828
3391
  /** Default fetch used by the optional {@link broadcast} helper (from `WaaskeyOptions.fetch`). */
2829
3392
  private readonly defaultFetch?;
2830
3393
  constructor(options: WaaskeyOptions);
@@ -3034,6 +3597,93 @@ declare function passkeyFactorEnrollment(credentialId: string): FactorEnrollment
3034
3597
  */
3035
3598
  declare function passkeyFactorVerification(challenge: string, options?: SigningAssertionOptions): Promise<FactorVerification>;
3036
3599
 
3600
+ /** How an envelope's secret is wrapped. Both may be present — either one opens it. */
3601
+ type UnlockMethod = 'passkey_prf' | 'passphrase';
3602
+ /** One wrapped copy of the secret. Every field here is NON-secret and safe to store beside the data. */
3603
+ interface UnlockKeyWrap {
3604
+ method: UnlockMethod;
3605
+ /** The secret, sealed under the key this method derives. */
3606
+ wrapped: string;
3607
+ /** Base64 salt: the PBKDF2 salt for a passphrase, the PRF evaluation salt for a passkey. */
3608
+ salt: string;
3609
+ /** Which passkey to authenticate with (`passkey_prf` only). */
3610
+ credentialId?: string;
3611
+ }
3612
+ /** A secret that several methods can unlock. */
3613
+ interface SecretEnvelope {
3614
+ wraps: UnlockKeyWrap[];
3615
+ }
3616
+ /** A passkey PRF secret — the exact shape `PasskeyPrfSecretProvider` returns. */
3617
+ interface PasskeyUnlockKey {
3618
+ /** Base64 PRF output. Never persisted. */
3619
+ secret: string;
3620
+ /** Base64 PRF evaluation salt — non-secret, stored with the wrap so it can be replayed. */
3621
+ salt: string;
3622
+ credentialId: string;
3623
+ }
3624
+ /**
3625
+ * A local **unlock envelope**: one secret, wrapped once per method the user enrolled (#52 B4).
3626
+ *
3627
+ * A browser member device seals its key share at rest under a secret, and that secret has to come
3628
+ * from the user on every unlock — never from storage, or a stolen browser profile carries the key to
3629
+ * its own ciphertext. Two things can supply it, and neither is good enough alone:
3630
+ *
3631
+ * - a **passkey** (WebAuthn PRF) — nothing to remember, but not every browser implements PRF, and a
3632
+ * lost device takes the only key with it;
3633
+ * - a **passphrase** — works everywhere and moves between browsers, but is one more thing to know.
3634
+ *
3635
+ * So the secret is not derived from either. It is random, and each method wraps a copy of it. Any
3636
+ * enrolled method opens the envelope, a method can be added later without re-sealing anything the
3637
+ * secret protects, and losing one method is not losing the wallet — which is the whole reason the
3638
+ * same shape already backs the recovery backup (`recovery-envelope.ts`).
3639
+ *
3640
+ * Nothing here is secret at rest: the wraps, salts and credential id yield nothing without the
3641
+ * authenticator or the passphrase.
3642
+ */
3643
+ declare function newUnlockSecret(): string;
3644
+ /**
3645
+ * Wrap `secret` for the given methods. At least one is required — an envelope nothing can open is
3646
+ * a wallet nobody can use.
3647
+ *
3648
+ * @throws {WaaskeyError} `validation` — no method supplied.
3649
+ */
3650
+ declare function sealSecret(secret: string, methods: {
3651
+ passphrase?: string;
3652
+ passkey?: PasskeyUnlockKey;
3653
+ }): Promise<SecretEnvelope>;
3654
+ /**
3655
+ * Add (or replace) one method on an existing envelope, so a user can enrol a passphrase on a
3656
+ * device that already unlocks by passkey — or the reverse — without touching what the secret seals.
3657
+ *
3658
+ * Replacing rather than appending is deliberate: two wraps of the same method are two passphrases
3659
+ * that both work, one of which the user does not know they set.
3660
+ */
3661
+ declare function addMethod(envelope: SecretEnvelope, secret: string, method: {
3662
+ passphrase?: string;
3663
+ passkey?: PasskeyUnlockKey;
3664
+ }): Promise<SecretEnvelope>;
3665
+ /**
3666
+ * Drop a method. Refuses to remove the last one — an envelope with no wraps is a share nobody,
3667
+ * including its owner, can ever open again.
3668
+ *
3669
+ * @throws {WaaskeyError} `validation` — removing this method would leave nothing.
3670
+ */
3671
+ declare function removeMethod(envelope: SecretEnvelope, method: UnlockMethod): SecretEnvelope;
3672
+ /**
3673
+ * Open the envelope with whatever the user has.
3674
+ *
3675
+ * A passkey is preferred when both are available and enrolled: it is the path with nothing to type.
3676
+ *
3677
+ * @throws {WaaskeyError} `unauthorized` — nothing supplied matches an enrolled method, or the
3678
+ * passphrase is wrong.
3679
+ */
3680
+ declare function openSecret(envelope: SecretEnvelope, opener: {
3681
+ passphrase?: string;
3682
+ passkeySecret?: string;
3683
+ }): Promise<string>;
3684
+ /** Which methods this envelope accepts — what an unlock screen offers. */
3685
+ declare function enrolledMethods(envelope: SecretEnvelope): UnlockMethod[];
3686
+
3037
3687
  /**
3038
3688
  * **Optional** client-side broadcast helper.
3039
3689
  *
@@ -3182,4 +3832,4 @@ declare class PasskeyPrfSecretProvider {
3182
3832
  }): Promise<PasskeyPrfResult>;
3183
3833
  }
3184
3834
 
3185
- export { Analytics, type AnalyticsEvent, type AnalyticsEventType, type AnalyticsSink, Auth, type Balance, Balances, type BroadcastOptions, type BroadcastResult, CLIENT_WASM_VERSION, type CeremonyParams, type Chain, type ChainConfig, type ChainProvider, type ClientWasmLoader, type ClientWasmModule, type CreateMemberWalletParams, type CreateWalletOptions, type CreateWalletParams, type CreateWalletResponse, type CustodyKind, type CustodyType, type DeviceCompleteReshareParams, type DeviceCompleteReshareResult, type DeviceKeygenParams, type DeviceKeygenResult, type DeviceReshareAssembleParams, type DeviceReshareAssembleResult, type DeviceReshareMaterial, type DeviceSignParams, type DeviceSignResult, type EddsaAssembleRequest, type EddsaCeremonyParams, type EddsaKeygenParams, type EddsaKeygenResult, type EddsaSendSession, type EddsaSignParams, type EddsaSignResult, type EmailStartResult, type EmbeddedSession, EncryptedShareStore, type EndUser, EvmRpcProvider, type FactorEnrollment, type FactorVerification, type FirebaseAuthRequest, HttpAnalyticsSink, IndexedDbKeyValueStore, type JoinCeremonyOptions, type JoinSignCeremonyOptions, type KeyValueStore, type Member, type MemberCeremony, type MemberCeremonyJoinResponse, type MemberCeremonyParams, type MemberKeygenParams, type MemberRole, type MemberSession, type MemberSignCeremony, type MemberSignParams, Members, type MembershipScope, MemoryKeyValueStore, MemoryPrimeStore, type MpcCore, type MpcCurve, Onramp, type OnrampWidgetParams, type OnrampWidgetUrl, type Page, type PageQuery, type PasskeyAssertionJSON, type PasskeyBackupKey, type PasskeyCeremony, type PasskeyPrfEnrollOptions, type PasskeyPrfResult, PasskeyPrfSecretProvider, type PrfCeremony, PrimePool, type PrimePoolOptions, type PrimePoolStore, type RecoverParams, type RecoverSignParams, type RecoverWalletResponse, Recovery, type RecoveryBackupEnvelope, type RecoveryChallengeResponse, type RecoveryFactor, type RecoveryKeyWrap, type RecoveryRetrieveResponse, type RecoveryShareInfo, type RegisterRecoveryParams, Reshare, type ReshareAssemblyMaterial, type ReshareCeremony, type ReshareCompletionCeremony, type ReshareCompletionParams, type ReshareCompletionResult, type ReshareRotateParams, type ReshareRotateResult, type ReshareWalletResponse, type SendOptions, type SendParams, type SendResult, type ShareStore, type SignMessageResponse, type SignOptions, type SignRequestsQuery, type SignSessionResponse, type Signature, type SignatureKind, type SigningAssertionCeremony, type SigningAssertionOptions, type SigningRequestResponse, type SigningRequestStatus, type StepUpChallengeResponse, type StepUpOperation, type TokenBalanceOptions, type TxStatus, type VerifiedWasmLoaderOptions, Waaskey, WaaskeyError, type WaaskeyErrorCode, type WaaskeyErrorOptions, type WaaskeyOptions, Wallet, type WalletActionType, type WalletBackupParams, type WalletCeremony, type WalletCurve, type WalletData, type WalletShareholder, type WalletStatus, Wallets, WasmMpcCore, broadcast, createVerifiedClientWasmLoader, epochShareKey, formatUnits, generateRecoveryCode, getSigningAssertion, isNonCustodial, isPasskeyAssertionSupported, isPasskeySupported, isPrfSupported, loadClientWasm, memberShareKey, openRecoveryBackup, passkeyFactorEnrollment, passkeyFactorVerification, sealRecoveryBackup, userBackupPendingKey, validateCustodyPolicy, verifyWasmIntegrity };
3835
+ export { Analytics, type AnalyticsEvent, type AnalyticsEventType, type AnalyticsSink, type AppRequester, Auth, type Balance, Balances, type BroadcastOptions, type BroadcastResult, CLIENT_WASM_VERSION, type CeremonyParams, type Chain, type ChainConfig, type ChainProvider, type ClientWasmLoader, type ClientWasmModule, type CreateMemberWalletParams, type CreateWalletOptions, type CreateWalletParams, type CreateWalletResponse, type CustodyKind, type CustodyType, type Device, type DeviceCompleteReshareParams, type DeviceCompleteReshareResult, type DeviceKeygenParams, type DeviceKeygenResult, type DeviceRegistration, type DeviceReshareAssembleParams, type DeviceReshareAssembleResult, type DeviceReshareMaterial, type DeviceSignParams, type DeviceSignResult, Devices, type EddsaAssembleRequest, type EddsaCeremonyParams, type EddsaKeygenParams, type EddsaKeygenResult, type EddsaSendSession, type EddsaSignParams, type EddsaSignResult, type EmailStartResult, type EmbeddedSession, EncryptedShareStore, type EndUser, EvmRpcProvider, type FactorEnrollment, type FactorVerification, type FirebaseAuthRequest, HttpAnalyticsSink, IndexedDbKeyValueStore, type JoinCeremonyOptions, type JoinSignCeremonyOptions, type KeyValueStore, type Member, type MemberCeremony, type MemberCeremonyJoinResponse, type MemberCeremonyParams, type MemberKeygenParams, type MemberRole, type MemberSession, type MemberSignCeremony, type MemberSignParams, Members, type MembershipScope, MemoryKeyValueStore, MemoryPrimeStore, type MpcCore, type MpcCurve, Onramp, type OnrampWidgetParams, type OnrampWidgetUrl, type Page, type PageQuery, type PasskeyAssertionJSON, type PasskeyBackupKey, type PasskeyCeremony, type PasskeyEnroller, type PasskeyPrfEnrollOptions, type PasskeyPrfResult, PasskeyPrfSecretProvider, type PasskeyUnlockKey, type PermissionDecision, type PermissionGrantStatus, type PermissionRequest, type PermissionRequestParams, type PermissionScope, type PrfCeremony, type PrimeLease, PrimePool, type PrimePoolOptions, type PrimePoolStore, type RecoverParams, type RecoverSignParams, type RecoverWalletResponse, Recovery, type RecoveryBackupEnvelope, type RecoveryChallengeResponse, type RecoveryEnrolment, type RecoveryFactor, type RecoveryKeyWrap, type RecoveryRetrieveResponse, type RecoveryShareInfo, type RegisterRecoveryParams, Reshare, type ReshareAssemblyMaterial, type ReshareCeremony, type ReshareCompletionCeremony, type ReshareCompletionParams, type ReshareCompletionResult, type ReshareRotateParams, type ReshareRotateResult, type ReshareWalletResponse, type SecretEnvelope, type SendOptions, type SendParams, type SendResult, SessionKeys, type ShareStore, type SignMessageResponse, type SignOptions, type SignRequestsQuery, type SignSessionResponse, type Signature, type SignatureKind, type SigningAssertionCeremony, type SigningAssertionOptions, type SigningRequestResponse, type SigningRequestStatus, type StepUpChallengeResponse, type StepUpOperation, type TeamMember, type TokenBalanceOptions, type TxStatus, type UnlockKeyWrap, type UnlockMethod, type VerifiedWasmLoaderOptions, Waaskey, WaaskeyError, type WaaskeyErrorCode, type WaaskeyErrorOptions, type WaaskeyOptions, type WaitForDecisionOptions, Wallet, type WalletActionType, type WalletBackupParams, type WalletCeremony, type WalletCurve, type WalletData, type WalletShareholder, type WalletStatus, Wallets, WasmMpcCore, addMethod, broadcast, createVerifiedClientWasmLoader, enrolledMethods, epochShareKey, formatUnits, generateRecoveryCode, getSigningAssertion, isNonCustodial, isPasskeyAssertionSupported, isPasskeySupported, isPrfSupported, loadClientWasm, memberShareKey, newUnlockSecret, openRecoveryBackup, openSecret, passkeyFactorEnrollment, passkeyFactorVerification, removeMethod, sealRecoveryBackup, sealSecret, signUserOpHash, userBackupPendingKey, validateCustodyPolicy, verifyWasmIntegrity };