@waaskey/sdk 0.3.1 → 0.4.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.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { PublicKeyCredentialCreationOptionsJSON, PublicKeyCredentialRequestOptionsJSON, AuthenticationResponseJSON } from '@simplewebauthn/browser';
1
+ import { PublicKeyCredentialRequestOptionsJSON, AuthenticationResponseJSON, PublicKeyCredentialCreationOptionsJSON } from '@simplewebauthn/browser';
2
2
 
3
3
  /** Thin typed HTTP client over fetch — the single place requests are issued. */
4
4
  declare class HttpClient {
@@ -245,7 +245,11 @@ interface DeviceSignParams extends CeremonyParams {
245
245
  }
246
246
  /** Result of the device half of sign. */
247
247
  interface DeviceSignResult {
248
- /** The cggmp24 signature (JSON). */
248
+ /**
249
+ * The signature as LOW-S–normalized compact `r ‖ s` hex (128 chars, no `0x`) — byte-identical to
250
+ * what the platform's own party produces, so the backend can cross-check the two before embedding
251
+ * one into a transaction, and chain adapters can slice `r`/`s` by offset.
252
+ */
249
253
  signature: string;
250
254
  }
251
255
  /**
@@ -266,8 +270,50 @@ interface DeviceReshareAssembleParams {
266
270
  wallet: unknown;
267
271
  /** One Feldman-commitments object per dealer (the broadcast set), opaque JSON. */
268
272
  commitments: unknown[];
269
- /** This device's private sub-share from each dealer, one per dealer, opaque JSON. */
273
+ /**
274
+ * This device's SEALED sub-share from each dealer, one per dealer — hex ciphertext, opened with
275
+ * {@link encryptionSecret} before the core verifies and assembles it.
276
+ */
270
277
  subShares: unknown[];
278
+ /**
279
+ * This holder's X25519 SECRET key (32-byte hex) — the counterpart of the public key the dealers
280
+ * sealed to, and the only thing that can open {@link subShares}.
281
+ *
282
+ * Required: dealers seal every sub-share (waas-core #365 M-A), so an assemble without it cannot
283
+ * even parse its inputs. SECRET — never log it.
284
+ */
285
+ encryptionSecret: string;
286
+ }
287
+ /**
288
+ * Parameters for the device's reshare **deal** stage ({@link MpcCore.runReshareDeal}) — the OLD
289
+ * holder's half, computed locally from its current share. Pure: no relay, no rounds.
290
+ */
291
+ interface DeviceReshareDealParams {
292
+ curve: MpcCurve;
293
+ /** This holder's CURRENT (old-epoch) key share JSON. Secret — never log it. */
294
+ share: string;
295
+ /** Keygen indices of the authorising old quorum, from the ceremony plan. */
296
+ quorumIndices: number[];
297
+ /** New share preimages `I'` (32-byte big-endian hex scalars), new-holder order. */
298
+ newPreimages: string[];
299
+ /** The new signing threshold `t'`. */
300
+ newThreshold: number;
301
+ /**
302
+ * Each NEW holder's X25519 PUBLIC key (32-byte hex), in new-holder order. The dealer seals
303
+ * sub-share `k` to `recipientPubkeys[k]`, so only ciphertext leaves the device.
304
+ */
305
+ recipientPubkeys: string[];
306
+ }
307
+ /**
308
+ * Result of the device reshare **deal** — what the ceremony expects back: the PUBLIC commitments
309
+ * to broadcast and one SEALED sub-share per new holder. No plaintext sub-share is ever produced
310
+ * outside the core.
311
+ */
312
+ interface DeviceReshareDealResult {
313
+ /** The dealer's public Feldman commitments (opaque JSON) — broadcast to every new holder. */
314
+ commitments: unknown;
315
+ /** One sealed sub-share (hex ciphertext) per NEW holder, in new-holder order. */
316
+ sealedSubShares: string[];
271
317
  }
272
318
  /**
273
319
  * Result of the device reshare **assemble** — the bare NEW-epoch core. It cannot sign yet
@@ -437,6 +483,12 @@ interface MpcCore {
437
483
  * it (the web wasm needs a `--features reshare` build).
438
484
  */
439
485
  runReshareAssemble?(params: DeviceReshareAssembleParams): Promise<DeviceReshareAssembleResult>;
486
+ /**
487
+ * Deal this holder's contribution to a reshare (#488) — the OLD-holder stage, pure and local.
488
+ * Optional: only a core built with the reshare capability implements it (the web wasm needs a
489
+ * `--features reshare` build).
490
+ */
491
+ runReshareDeal?(params: DeviceReshareDealParams): Promise<DeviceReshareDealResult>;
440
492
  /**
441
493
  * Complete a reshared bare core into a signable share by running the aux-info ceremony over the
442
494
  * NEW committee (#318 / #95). Relay-driven, mirroring keygen's aux phase. Optional: only a core
@@ -485,6 +537,11 @@ interface ClientWasmModule {
485
537
  * Synchronous in the core (no relay); the SDK awaits it uniformly.
486
538
  */
487
539
  reshareAssemble?(paramsJson: string): unknown | Promise<unknown>;
540
+ /**
541
+ * Device reshare **deal** — the old holder's local contribution; returns
542
+ * `{ commitments_json, sealed_sub_shares_hex }`. Present only in a `--features reshare` build.
543
+ */
544
+ reshareDeal?(paramsJson: string): unknown | Promise<unknown>;
488
545
  /**
489
546
  * Device **complete-reshare** — run the aux ceremony over the new committee and return the
490
547
  * signable share as `{ keyshare_json, shared_public_key_json }`. Present only in a
@@ -533,6 +590,7 @@ declare class WasmMpcCore implements MpcCore {
533
590
  runSign(params: DeviceSignParams): Promise<DeviceSignResult>;
534
591
  pregeneratePrimes(curve: MpcCurve): Promise<string>;
535
592
  runReshareAssemble(params: DeviceReshareAssembleParams): Promise<DeviceReshareAssembleResult>;
593
+ runReshareDeal(params: DeviceReshareDealParams): Promise<DeviceReshareDealResult>;
536
594
  runCompleteReshare(params: DeviceCompleteReshareParams): Promise<DeviceCompleteReshareResult>;
537
595
  runMemberKeygen(params: MemberKeygenParams): Promise<DeviceKeygenResult>;
538
596
  runMemberSign(params: MemberSignParams): Promise<DeviceSignResult>;
@@ -570,7 +628,7 @@ declare class WasmMpcCore implements MpcCore {
570
628
  * exact, optional peer dependency in `package.json` — so an app that installs `@waaskey/client-wasm`
571
629
  * alongside the SDK runs the real ed25519 create/send path end to end.
572
630
  */
573
- declare const CLIENT_WASM_VERSION = "0.2.1";
631
+ declare const CLIENT_WASM_VERSION = "0.2.2";
574
632
  /**
575
633
  * Verify the integrity of raw wasm bytes against an expected **SHA-384** hash, in
576
634
  * Subresource-Integrity (`sha384-<base64>`) form (issue #40).
@@ -865,8 +923,16 @@ type CustodyType = 'embedded' | 'shared' | 'self_custody';
865
923
  interface WaaskeyOptions {
866
924
  /** Publishable API key issued from the Waaskey dashboard. */
867
925
  apiKey: string;
868
- /** API base URL. Defaults to the Waaskey production API. */
869
- baseUrl?: string;
926
+ /**
927
+ * API base URL — REQUIRED, with no default.
928
+ *
929
+ * There used to be one (`https://api.waaskey.com`), and it does not resolve: every consumer that
930
+ * omitted this got an NXDOMAIN on its first call and a `network` error with nothing pointing at the
931
+ * cause. A default that cannot work is worse than none, because it moves the failure from the
932
+ * constructor — where the fix is obvious — to every request. When a public hostname exists, the
933
+ * default can come back.
934
+ */
935
+ baseUrl: string;
870
936
  /** Custom fetch implementation (e.g. for non-browser runtimes). Defaults to global `fetch`. */
871
937
  fetch?: typeof fetch;
872
938
  /**
@@ -967,6 +1033,17 @@ interface WalletBackupParams {
967
1033
  email: string;
968
1034
  /** Extra factor enrolments beyond the standard three. */
969
1035
  extraFactors?: FactorEnrollment[];
1036
+ /**
1037
+ * A passkey PRF secret to ALSO wrap the backup key with (#510) — pass what
1038
+ * `PasskeyPrfSecretProvider.enroll()` returned. The backup then opens with either the passkey or the
1039
+ * recovery code, so a forgotten code is no longer a lost wallet. Omit to keep the recovery code as
1040
+ * the only key.
1041
+ */
1042
+ passkey?: {
1043
+ secret: string;
1044
+ salt: string;
1045
+ credentialId: string;
1046
+ };
970
1047
  }
971
1048
  /** Options for `wallets.joinCeremony(...)` (#349). */
972
1049
  interface JoinCeremonyOptions {
@@ -1140,6 +1217,10 @@ interface WalletData {
1140
1217
  custodyKinds: CustodyKind[];
1141
1218
  /** Count of {@link custodyKinds} entries the platform itself holds (`platform_signer` + `platform_recovery`). */
1142
1219
  platformShareCount: number;
1220
+ /** The wallet's key epoch: 1 at creation, bumped by every reshare. The public key and address are unchanged across one. */
1221
+ keyEpoch: number;
1222
+ /** True while a reshared committee still needs its aux material regenerated — the wallet cannot sign until it clears. */
1223
+ reshareAuxPending: boolean;
1143
1224
  /**
1144
1225
  * The wallet's custody attestation (#293): `embedded` when `platformShareCount >= threshold`
1145
1226
  * (platform alone is custodial-capable — the default 2-of-3), `self_custody` when
@@ -1299,24 +1380,33 @@ interface SendResult {
1299
1380
  * signing quorum roster (`roles` in `participants` order) and the WHOLE `message` bytes (ed25519 signs
1300
1381
  * the message, not a digest).
1301
1382
  */
1302
- interface EddsaSendSession {
1383
+ interface SendSessionResponse {
1303
1384
  /** The pending signing-activity row id — echoed back to the ASSEMBLE phase to finalize the signed tx. */
1304
1385
  txId: string;
1305
1386
  /** Relay websocket URL the device connects to. */
1306
1387
  relayUrl: string;
1307
1388
  /** Relay session id shared by the device + server parties. */
1308
1389
  sessionId: string;
1309
- /** The FROST signing quorum's relay roles, in `participants` order (`roles[i]` `participants[i]`), e.g. `['device','server']`. */
1390
+ /** The wallet's curve it decides which payload field below is populated and how `participants` is numbered. */
1391
+ curve: WalletCurve;
1392
+ /** The signing quorum's relay roles, in `participants` order (`roles[i]` ↔ `participants[i]`), e.g. `['device','server']`. */
1310
1393
  roles: string[];
1311
- /** The 1-based FROST identifiers of the quorum, parallel to {@link roles} (e.g. `[1, 2]`). */
1394
+ /**
1395
+ * The quorum's party identifiers, parallel to {@link roles} — **numbered per curve**: ed25519
1396
+ * (FROST) uses 1-based identifiers (`[1, 2]`), secp256k1 (cggmp24) 0-based keygen indices (`[0, 1]`).
1397
+ */
1312
1398
  participants: number[];
1313
1399
  /** This device's own 0-based slot into {@link roles} (its position in the quorum). */
1314
1400
  signerPosition: number;
1315
- /** The raw message bytes to sign, hex (`0x` prefix optional) the chain adapter's serialized tx message. */
1316
- message: string;
1401
+ /** The raw message bytes to sign, hex **ed25519 only** (FROST signs the message, not a hash). */
1402
+ message?: string;
1403
+ /** The 32-byte tx digest to sign, hex — **secp256k1 only** (cggmp24 signs a digest). */
1404
+ digest?: string;
1317
1405
  /** Short-lived relay token (JWT) the device presents to join this session; present only when relay auth is enabled. */
1318
1406
  relayToken?: string;
1319
1407
  }
1408
+ /** @deprecated Use {@link SendSessionResponse} — the shape is curve-agnostic (secp256k1 + ed25519). */
1409
+ type EddsaSendSession = SendSessionResponse;
1320
1410
  /** Body of the ASSEMBLE phase (`POST …/send-session/:txId/assemble`) — the aggregated ed25519 signature the backend embeds into the wire tx (backend `AssembleEddsaTxRequest`). */
1321
1411
  interface EddsaAssembleRequest {
1322
1412
  /** The 64-byte RFC 8032 ed25519 signature (hex) the device + server co-produced. */
@@ -1521,36 +1611,55 @@ interface OnrampWidgetUrl {
1521
1611
  /** ISO timestamp when the signed URL expires, if applicable. */
1522
1612
  expiresAt?: string;
1523
1613
  }
1524
- /** The recovery factors a wallet enrols (backend `RecoveryFactor`). */
1525
- type RecoveryFactor = 'recovery_code' | 'totp' | 'email_otp';
1526
1614
  /**
1527
- * Enrolment of one factor at register time (backend `FactorEnrollment`).
1615
+ * The recovery factors a wallet enrols (backend `RecoveryFactor`).
1616
+ *
1617
+ * `passkey` is enrolled INSTEAD of `recovery_code` when the product wants a recovery flow with nothing
1618
+ * to remember (#510). Note the gate is an AND of every enrolled factor, not M-of-N — so enrolling a
1619
+ * passkey makes that passkey required. Passkeys sync across a user's devices where a written code does
1620
+ * not, which is what makes the trade reasonable, but it is a trade.
1621
+ */
1622
+ type RecoveryFactor = 'recovery_code' | 'totp' | 'email_otp' | 'passkey';
1623
+ /**
1624
+ * Enrolment of one factor at register time (backend `FactorEnrollmentDto`).
1625
+ *
1626
+ * The wire field is `credential` for EVERY factor — the API's DTO declares exactly
1627
+ * `{ type, credential }` and its validation pipe rejects any other property.
1528
1628
  *
1529
1629
  * Contract A: the recovery code is a client-side **sealing secret** and must never
1530
- * reach the server, so the `recovery_code` factor enrols `credentialHash` (the
1531
- * lowercase-hex SHA-256 of the code), never the code itself. `totp` / `email_otp`
1532
- * enrol their non-sealing `credential` (base32 secret / email) as before.
1630
+ * reach the server, so for `recovery_code` the `credential` carries the lowercase-hex
1631
+ * SHA-256 of the code, never the code itself (the SDK hashes it in
1632
+ * {@link buildRecoveryRegistration}). `totp` / `email_otp` enrol their non-sealing
1633
+ * credential (base32 secret / email address) verbatim.
1533
1634
  */
1534
1635
  interface FactorEnrollment {
1535
1636
  type: RecoveryFactor;
1536
- /** totp → base32 secret; email_otp → email address. Omitted for `recovery_code`. */
1537
- credential?: string;
1538
- /** recovery_codelowercase-hex SHA-256 of the recovery code (the raw code never leaves the client). */
1539
- credentialHash?: string;
1637
+ /**
1638
+ * recovery_code → lowercase-hex SHA-256 of the code; totp → base32 secret; email_otp → email address;
1639
+ * passkeythe base64url credential id of an ALREADY-registered passkey (public, not a secret)
1640
+ * build it with `passkeyFactorEnrollment`.
1641
+ */
1642
+ credential: string;
1540
1643
  }
1541
1644
  /**
1542
- * One factor's proof at recovery time (backend `FactorVerification`).
1645
+ * One factor's proof at recovery time (backend `FactorVerificationDto`).
1646
+ *
1647
+ * The wire field is `token` for EVERY factor — the API's DTO declares exactly
1648
+ * `{ type, token }` and its validation pipe rejects any other property.
1543
1649
  *
1544
- * Contract A: `recovery_code` proves possession with `credentialHash` (the same
1545
- * SHA-256 the server stored), never the plaintext code — the server compares the
1546
- * hash in constant time and can never derive the code to unseal the ciphertext.
1650
+ * Contract A: a `recovery_code` proof is sent as the same lowercase-hex SHA-256 the
1651
+ * server stored, never the plaintext code — the server compares the hash in constant
1652
+ * time and can never derive the code to unseal the ciphertext. Callers pass the
1653
+ * PLAINTEXT code here; the SDK hashes it before the request leaves the device.
1547
1654
  */
1548
1655
  interface FactorVerification {
1549
1656
  type: RecoveryFactor;
1550
- /** totp → current 6-digit OTP; email_otp → the emailed OTP. Omitted for `recovery_code`. */
1551
- token?: string;
1552
- /** recovery_codelowercase-hex SHA-256 of the code (matches the enrolled hash). */
1553
- credentialHash?: string;
1657
+ /**
1658
+ * recovery_code → the plaintext code (the SDK sends its SHA-256); totp → current 6-digit OTP;
1659
+ * email_otpthe emailed OTP; passkey a WebAuthn assertion as JSON, which no user can type —
1660
+ * build it with `passkeyFactorVerification`.
1661
+ */
1662
+ token: string;
1554
1663
  }
1555
1664
  /** A registered recovery record's metadata (backend `RecoveryShareResponse`). */
1556
1665
  interface RecoveryShareInfo {
@@ -1558,22 +1667,51 @@ interface RecoveryShareInfo {
1558
1667
  walletId: string;
1559
1668
  factors: RecoveryFactor[];
1560
1669
  createdAt: string;
1670
+ /** Which key-wrapping methods are enrolled — a single entry means a single point of failure. */
1671
+ wrapMethods?: ('passkey_prf' | 'passphrase')[];
1561
1672
  }
1562
1673
  /** Response to initiating a recovery session (backend `RecoveryChallengeResponse`). */
1563
1674
  interface RecoveryChallengeResponse {
1564
1675
  challengeId: string;
1565
1676
  requiredFactors: RecoveryFactor[];
1677
+ /**
1678
+ * The WebAuthn challenge to sign, present only when a `passkey` factor is enrolled (#510). Server-random
1679
+ * and single-use with this session — feed it to `passkeyFactorVerification`.
1680
+ */
1681
+ passkeyChallenge?: string;
1682
+ }
1683
+ /**
1684
+ * How the key that opens a backup was wrapped (backend `RecoveryKeyWrap`, #510).
1685
+ *
1686
+ * The share is sealed under a data key; that key is wrapped once per method, and every wrapping opens
1687
+ * the SAME share — so losing one path is survivable. Everything here is safe for the server to hold:
1688
+ * a wrapped key is noise without its key-encryption key, and those live only inside the user's
1689
+ * authenticator or in the user's head.
1690
+ */
1691
+ interface RecoveryKeyWrap {
1692
+ /** `passkey_prf` — key from a WebAuthn PRF output; `passphrase` — key from the recovery code. */
1693
+ method: 'passkey_prf' | 'passphrase';
1694
+ /** The data key, wrapped under this method's key-encryption key. */
1695
+ wrapped: string;
1696
+ /** Salt to reproduce that key-encryption key (the PRF evaluation salt, or the KDF salt). */
1697
+ salt: string;
1698
+ /** For `passkey_prf`: which credential to assert. */
1699
+ credentialId?: string;
1566
1700
  }
1567
1701
  /** Encrypted share returned after verifying factors (backend `RecoveryRetrieveResponse`). */
1568
1702
  interface RecoveryRetrieveResponse {
1569
1703
  id: string;
1570
1704
  ciphertext: string;
1705
+ /** Wrapped copies of the key that opens `ciphertext`. Empty for a backup registered before #510. */
1706
+ keyWraps?: RecoveryKeyWrap[];
1571
1707
  }
1572
1708
  /** Result of device-loss recovery — factors verified + shares rotated (backend `RecoverWalletResponse`). */
1573
1709
  interface RecoverWalletResponse {
1574
1710
  recovered: boolean;
1575
1711
  id: string;
1576
1712
  ciphertext: string;
1713
+ /** Wrapped copies of the key that opens `ciphertext`. Empty for a backup registered before #510. */
1714
+ keyWraps?: RecoveryKeyWrap[];
1577
1715
  refreshedAt: string;
1578
1716
  }
1579
1717
  /** Parameters for `recovery.register(...)`. */
@@ -1588,6 +1726,17 @@ interface RegisterRecoveryParams {
1588
1726
  email: string;
1589
1727
  /** Extra factor enrolments beyond the standard three. */
1590
1728
  extraFactors?: FactorEnrollment[];
1729
+ /**
1730
+ * A passkey PRF secret to ALSO wrap the backup key with (#510) — pass what
1731
+ * `PasskeyPrfSecretProvider.enroll()` returned. The backup then opens with either the passkey or the
1732
+ * recovery code, so a forgotten code is no longer a lost wallet. Omit to keep the recovery code as
1733
+ * the only key.
1734
+ */
1735
+ passkey?: {
1736
+ secret: string;
1737
+ salt: string;
1738
+ credentialId: string;
1739
+ };
1591
1740
  }
1592
1741
  /** Parameters for `recovery.recover(...)` / `recovery.retrieveShare(...)`. */
1593
1742
  interface RecoverParams {
@@ -1595,8 +1744,18 @@ interface RecoverParams {
1595
1744
  challengeId: string;
1596
1745
  /** One verification per enrolled factor. */
1597
1746
  verifications: FactorVerification[];
1598
- /** The recovery code — decrypts the retrieved share client-side. */
1599
- recoveryCode: string;
1747
+ /**
1748
+ * The recovery code — opens the retrieved share client-side. Optional only when `passkeySecret` is
1749
+ * supplied AND the backup was registered with a passkey wrap (#510); one of the two is required, and
1750
+ * a backup registered before #510 accepts nothing but the code.
1751
+ */
1752
+ recoveryCode?: string;
1753
+ /**
1754
+ * A passkey PRF output (base64) to open the backup with instead of the code (#510) — pass the
1755
+ * `secret` from `PasskeyPrfSecretProvider.unlock(credentialId, { salt })`, using the `salt` and
1756
+ * `credentialId` the backup's `keyWraps` carry. Never sent to the server.
1757
+ */
1758
+ passkeySecret?: string;
1600
1759
  }
1601
1760
  /**
1602
1761
  * Parameters for `wallets.recoverSign(...)` — the device-loss RECOVERY CO-SIGN of a non-custodial
@@ -1658,6 +1817,96 @@ interface ReshareCompletionCeremony {
1658
1817
  /** Short-lived relay token (JWT) the device presents to join the reshare-aux session; present only when relay auth is enabled. */
1659
1818
  relayToken?: string;
1660
1819
  }
1820
+ /**
1821
+ * A client-dealt reshare ceremony the backend opened (`POST /v1/wallets/:id/reshare-embedded`) — the
1822
+ * client's whole instruction set for its half: who deals, the committee being rotated onto, where each
1823
+ * sub-share must be sealed, and the coordination preimages both stages must agree on.
1824
+ */
1825
+ interface ReshareCeremony {
1826
+ id: string;
1827
+ walletId: string;
1828
+ status: string;
1829
+ curve: WalletCurve;
1830
+ /** OLD party indices of the authorising quorum — passed to the deal unchanged. */
1831
+ quorumIndices: number[];
1832
+ /** The OLD authorising quorum (this client's party plus the platform's). */
1833
+ dealers: {
1834
+ role: string;
1835
+ index: number;
1836
+ }[];
1837
+ /** The NEW ordered party roles, length `n'`. */
1838
+ newParties: string[];
1839
+ /** The NEW signing threshold `t'`. */
1840
+ newThreshold: number;
1841
+ /**
1842
+ * The NEW per-party custody kinds, parallel to {@link newParties}. This is what tells the client
1843
+ * which holders are ITS to assemble and acknowledge — the role names cannot, since the platform's
1844
+ * party is `server` on an embedded committee and `platform` on a member one.
1845
+ */
1846
+ newCustodyKinds: CustodyKind[];
1847
+ /** Each NEW holder's X25519 recipient pubkey (32-byte hex), parallel to {@link newParties}. */
1848
+ recipientPubkeys: string[];
1849
+ /** Fresh 32-byte-hex coordination preimages, one per NEW holder. */
1850
+ newPreimages: string[];
1851
+ /** The NEW key epoch the reshared shares are inserted under. */
1852
+ keyEpoch: number;
1853
+ expiresAt: string;
1854
+ }
1855
+ /** One client holder's assemble material (`GET …/reshare-drop/:ceremonyId/assembly?role=…`). */
1856
+ interface ReshareAssemblyMaterial {
1857
+ ceremonyId: string;
1858
+ walletId: string;
1859
+ status: string;
1860
+ curve: WalletCurve;
1861
+ /** This holder's 0-based position in the new committee. */
1862
+ newPosition: number;
1863
+ newThreshold: number;
1864
+ newPreimages: string[];
1865
+ /** The unchanged `WalletPublicInfo` JSON. */
1866
+ wallet: unknown;
1867
+ /** The wallet's public key — every assembled share must reproduce it. */
1868
+ expectedPublicKey: string;
1869
+ /** One Feldman-commitments object per dealer, in dealer order. */
1870
+ commitments: unknown[];
1871
+ /** This holder's SEALED sub-share from each dealer, parallel to {@link commitments}. */
1872
+ subShares: string[];
1873
+ }
1874
+ /** Parameters for `reshare.rotate(...)` — the committee to move the wallet onto. */
1875
+ interface ReshareRotateParams {
1876
+ /** The new ordered party roles. Omit to re-issue the current committee at a new epoch. */
1877
+ parties?: string[];
1878
+ /** The new signing threshold `t'`. Omit to keep the current one. */
1879
+ threshold?: number;
1880
+ /** The new per-party custody kinds, parallel to {@link parties}. Omit to derive from role names. */
1881
+ custodyKinds?: CustodyKind[];
1882
+ /**
1883
+ * Accept a committee with no user-held backup on a wallet that has one. Refused by default —
1884
+ * the address would not change, so nothing would show that the wallet had stopped being recoverable.
1885
+ */
1886
+ acknowledgeBackupLoss?: boolean;
1887
+ /**
1888
+ * The user's EXISTING recovery code. Required when the new committee keeps a `user_backup` holder:
1889
+ * that holder's new share is re-sealed under it so the wallet's backup survives the rotation. The
1890
+ * code never leaves the device — only the sealed ciphertext is sent.
1891
+ */
1892
+ recoveryCode?: string;
1893
+ }
1894
+ /** Result of `reshare.rotate(...)` — the ceremony the client drove, and what it produced locally. */
1895
+ interface ReshareRotateResult {
1896
+ walletId: string;
1897
+ ceremonyId: string;
1898
+ /** The ceremony's terminal status — `complete` once the last acknowledgement drove the cutover. */
1899
+ status: string;
1900
+ /** The wallet's NEW key epoch. */
1901
+ keyEpoch: number;
1902
+ /** The client-held holders this device assembled, in new-committee order. */
1903
+ assembledRoles: string[];
1904
+ /**
1905
+ * The wallet's public key, verified UNCHANGED by every assembled share — the funds-safety invariant
1906
+ * of a reshare.
1907
+ */
1908
+ sharedPublicKey: string;
1909
+ }
1661
1910
  /** Parameters for `reshare.complete(...)` — everything the device needs to finish its NEW-epoch share. */
1662
1911
  interface ReshareCompletionParams {
1663
1912
  /** Assemble material from the reshare response ({@link ReshareWalletResponse.deviceMaterial}). */
@@ -1999,6 +2248,36 @@ declare class Reshare {
1999
2248
  private readonly http;
2000
2249
  private readonly deps;
2001
2250
  constructor(http: HttpClient, deps?: ReshareDeps);
2251
+ /**
2252
+ * Rotate the wallet onto a NEW committee, keeping its address, and drive this device's whole half of
2253
+ * the ceremony (#488).
2254
+ *
2255
+ * The client is not a bystander here: the platform holds ONE share and cannot reach the threshold, so
2256
+ * without this device's deal there is no ceremony at all.
2257
+ *
2258
+ * 1. Open the ceremony with the committee asked for (an empty request re-issues the current one).
2259
+ * 2. DEAL from this device's current-epoch share — pure and local; every sub-share leaves sealed.
2260
+ * 3. For each CLIENT-held new holder — identified by custody KIND, never by role name — fetch its
2261
+ * material and assemble its new-epoch core locally, refusing any share that reproduces a different
2262
+ * public key.
2263
+ * 4. Acknowledge each one. The `user_backup` holder's ack carries its new share re-sealed under the
2264
+ * user's EXISTING recovery code, so the wallet's no-lock-out property survives the rotation; the
2265
+ * last acknowledgement drives the backend's atomic cutover.
2266
+ *
2267
+ * The assembled cores are BARE (no aux): the wallet is `reshareAuxPending` until aux-completion, which
2268
+ * is {@link complete}'s job — and which re-assembles from the material itself, so nothing here needs
2269
+ * to be kept on the device between the two. Nothing here can leave the device worse off — the old-epoch share is
2270
+ * untouched, and a ceremony that fails cuts nothing over.
2271
+ */
2272
+ rotate(walletId: string, params?: ReshareRotateParams, options?: {
2273
+ signal?: AbortSignal;
2274
+ }): Promise<ReshareRotateResult>;
2275
+ /**
2276
+ * Re-seal the new `user_backup` core under the user's EXISTING recovery code. The code never leaves
2277
+ * the device — only the ciphertext does — which is the same trust model registration has, and the
2278
+ * reason the server cannot check WHICH code sealed it.
2279
+ */
2280
+ private sealBackup;
2002
2281
  /**
2003
2282
  * Complete this device's share for a device-retaining reshare and make the wallet signable on the
2004
2283
  * device under the new epoch.
@@ -2088,14 +2367,35 @@ declare class Wallet {
2088
2367
  */
2089
2368
  sign(digest: string, options?: SignOptions): Promise<string>;
2090
2369
  /**
2091
- * Start this device's half of a secp sign ceremony when the wallet's sign quorum requires it.
2092
- * The quorum is the first `threshold` roles of the wallet's party list (#292) — for the default
2093
- * `[device, server, recovery]`/2 that is `[device, server]`, so the device MUST be online and
2094
- * co-signing. Returns `undefined` when the quorum is platform-only (or the wallet is not secp) —
2095
- * the POST then completes alone, unchanged. A device-present quorum without the device deps or
2096
- * stored share fails fast with a typed error instead of a guaranteed server-side timeout.
2370
+ * The roles that will actually sign the first `threshold` of the wallet's party list (#292),
2371
+ * mirroring the signer's own derivation. `undefined` when the topology is unknown (a legacy
2372
+ * wallet record), which callers treat as "let the server decide".
2373
+ */
2374
+ private signQuorum;
2375
+ /**
2376
+ * Everything this device needs to join a ceremony, resolved BEFORE one is started (#89): the MPC
2377
+ * core, the routed-sign capability a >2-party quorum needs, and the stored key share.
2378
+ *
2379
+ * Each failure is a typed error thrown straight to the caller, and the ordering is the point: a
2380
+ * device that cannot co-sign must never leave the platform party waiting on the relay for a
2381
+ * counterpart that will never arrive. That wait ends at the party-runner timeout (~210s) and
2382
+ * reaches the caller as an opaque 5xx — minutes after a knowable, local cause.
2383
+ */
2384
+ private loadDeviceParty;
2385
+ /**
2386
+ * Normalize a sign-session descriptor into the shared {@link DeviceCeremony}. The 2-party roster
2387
+ * comes from the descriptor's own `role`/`peerRole` (authoritative — the relay token is bound to
2388
+ * that role); a larger quorum carries no server-sent roster, so the wallet's own party slice — the
2389
+ * same slice the signer derives — supplies it.
2097
2390
  */
2098
- private startDeviceCoSign;
2391
+ private toSignCeremony;
2392
+ /**
2393
+ * Run this device's half of a started ceremony. A 2-party quorum uses the plain single-peer
2394
+ * transport; anything larger MUST be roster-routed, or the transport attributes every inbound
2395
+ * message to the one configured peer and the protocol aborts on the third party's first message
2396
+ * (waas-core#131).
2397
+ */
2398
+ private runDeviceSign;
2099
2399
  /**
2100
2400
  * Send a transaction from this wallet. The platform builds the chain-specific transaction
2101
2401
  * and co-signs it with the 2-of-3 MPC quorum, returning the **signed raw transaction**.
@@ -2111,13 +2411,34 @@ declare class Wallet {
2111
2411
  * server-side). Alternatively supply a pre-built assertion via `options.passkeyAssertion`.
2112
2412
  */
2113
2413
  send(params: SendParams, options?: SendOptions): Promise<SendResult>;
2414
+ /**
2415
+ * Device-co-signed send for a secp wallet — the cggmp24 counterpart of {@link sendEd25519}:
2416
+ *
2417
+ * 1. **START** (`POST …/send-session`): the platform runs the transfer gates, builds the unsigned
2418
+ * tx, puts its own party on the relay in the background, and returns the 32-byte digest plus
2419
+ * the relay coordination. It does NOT wait for the ceremony.
2420
+ * 2. **CO-SIGN**: this device runs its half over the relay with its stored share; cggmp24 hands
2421
+ * the completed signature to both parties.
2422
+ * 3. **ASSEMBLE** (`POST …/send-session/:txId/assemble`): the platform verifies the signature
2423
+ * (recovers to the wallet key AND equals its own party's) and embeds it into the wire tx.
2424
+ *
2425
+ * Every device-side precondition is resolved BEFORE the START (see {@link loadDeviceParty}), so a
2426
+ * device that cannot co-sign costs nothing: no tx is built and no platform party is left waiting.
2427
+ *
2428
+ * **A co-sign that fails after a successful START rejects with its typed error.** START is not the
2429
+ * commit point — it yields an *unsigned* tx and a pending session, and nothing broadcastable exists
2430
+ * until ASSEMBLE returns a `signedTx` — so there is no result to salvage by swallowing the failure,
2431
+ * and no fallback to `POST /send` (the platform cannot reach the threshold on this wallet alone, so
2432
+ * a retry there would only hang). The backend expires the abandoned session and fails the tx row.
2433
+ */
2434
+ private sendWithDevice;
2114
2435
  /**
2115
2436
  * Device-co-signed send for an ed25519 (FROST) wallet (#110) — the browser holds the device FROST
2116
2437
  * share and co-signs 2-party with the backend `server` party over the relay:
2117
2438
  *
2118
2439
  * 1. **START** (`POST …/send-session`): the backend builds the unsigned tx (chain adapter), starts
2119
2440
  * its server FROST party on the relay in the background, and returns the raw `message` bytes to
2120
- * sign + the relay coordination ({@link EddsaSendSession}).
2441
+ * sign + the relay coordination ({@link SendSessionResponse}).
2121
2442
  * 2. **CO-SIGN**: the device runs `signEddsa` over the relay with its stored `{keyPackage,
2122
2443
  * publicKeyPackage}` share; the two parties aggregate the RFC 8032 signature (returned locally).
2123
2444
  * 3. **ASSEMBLE** (`POST …/send-session/:txId/assemble`): the backend embeds the aggregated
@@ -2373,11 +2694,13 @@ declare class Wallets {
2373
2694
  */
2374
2695
  recoverSign(walletId: string, params: RecoverSignParams, options?: SignOptions): Promise<string>;
2375
2696
  /**
2376
- * Retrieve the sealed `user_backup` ciphertext via the recovery gate ({@link fetchRecoveryCiphertext}),
2377
- * mapping a "no recovery share registered" (404) to the actionable `share_not_found` this wallet has no
2378
- * client-held `user_backup` backup to co-sign with (its device-loss recovery is the custodial path instead).
2697
+ * Retrieve the sealed `user_backup` backup via the recovery gate ({@link fetchRecoveryBackup}) — the
2698
+ * ciphertext AND its key wraps (#510), since a backup registered with a passkey is an envelope and
2699
+ * the wraps are what open it. Maps a "no recovery share registered" (404) to the actionable
2700
+ * `share_not_found` — this wallet has no client-held `user_backup` backup to co-sign with (its
2701
+ * device-loss recovery is the custodial path instead).
2379
2702
  */
2380
- private fetchUserBackupCiphertext;
2703
+ private fetchUserBackup;
2381
2704
  /**
2382
2705
  * Run one or more device keygen parties (each `mpc.runKeygen`), concurrently, mapping any failure to a
2383
2706
  * single `keygen_failed`. Used for both the single `device` party and the two-party non-custodial
@@ -2428,6 +2751,7 @@ declare function userBackupPendingKey(walletId: string): string;
2428
2751
  *
2429
2752
  * const waaskey = new Waaskey({
2430
2753
  * apiKey: process.env.WAASKEY_PUBLISHABLE_KEY!,
2754
+ * baseUrl: process.env.WAASKEY_API_URL!,
2431
2755
  * mpc: new WasmMpcCore(loadClientWasm),
2432
2756
  * shareStore: EncryptedShareStore.browser(sessionSecret),
2433
2757
  * });
@@ -2440,7 +2764,7 @@ declare class Waaskey {
2440
2764
  readonly wallets: Wallets;
2441
2765
  /** The `recovery` resource — multi-factor, client-encrypted wallet recovery. */
2442
2766
  readonly recovery: Recovery;
2443
- /** The `reshare` resource — device-side completion of a device-retaining reshare (#318). */
2767
+ /** The `reshare` resource — this device's half of a committee rotation (#488) and the aux-completion that follows (#318). */
2444
2768
  readonly reshare: Reshare;
2445
2769
  /** The `balances` resource — client-side balance reads from a chain provider (no backend). */
2446
2770
  readonly balances: Balances;
@@ -2490,6 +2814,175 @@ declare function isNonCustodial(wallet: Pick<WalletData, 'platformShareCount' |
2490
2814
  */
2491
2815
  declare function validateCustodyPolicy(params: Pick<CreateWalletParams, 'threshold' | 'parties' | 'custodyKinds' | 'custodyType'>): void;
2492
2816
 
2817
+ /** A backup blob plus the wrapped copies of the key that opens it. */
2818
+ interface RecoveryBackupEnvelope {
2819
+ /** The share, sealed under a random data key. Opaque to the server. */
2820
+ ciphertext: string;
2821
+ /** One wrapped copy of that data key per enrolled method. */
2822
+ keyWraps: RecoveryKeyWrap[];
2823
+ }
2824
+ /** A passkey PRF secret to wrap the backup key with — the exact shape `PasskeyPrfSecretProvider` returns. */
2825
+ interface PasskeyBackupKey {
2826
+ /** Base64 PRF output (32 bytes). Never persisted, never sent to the server. */
2827
+ secret: string;
2828
+ /** Base64 PRF evaluation salt — non-secret, stored with the wrap so it can be reproduced. */
2829
+ salt: string;
2830
+ /** The credential whose PRF derives this key, so recovery asserts the right passkey. */
2831
+ credentialId: string;
2832
+ }
2833
+ /**
2834
+ * Seal a share into an envelope: a random data key encrypts the share, and that data key is wrapped
2835
+ * once per method (#510 / waas-backend#510).
2836
+ *
2837
+ * The point of the indirection is that EVERY wrapping opens the SAME share. A user whose passkey is
2838
+ * gone still has the recovery code; a user who never wrote the code down still has the passkey. Sealing
2839
+ * the share directly under one secret — which is what this SDK did before — makes losing that one
2840
+ * secret the same as losing the wallet.
2841
+ *
2842
+ * The recovery-code wrap is always produced: it is the path that works on any device, in any browser,
2843
+ * with no authenticator support. The passkey wrap is added when the caller supplies a PRF secret.
2844
+ *
2845
+ * Nothing here is decryptable server-side. The server receives the ciphertext, the wrapped keys, their
2846
+ * salts and a credential id — none of which yields a key-encryption key. That is what keeps the
2847
+ * platform below the signing threshold; a change that lets the server derive one would quietly make a
2848
+ * non-custodial wallet custodial.
2849
+ */
2850
+ declare function sealRecoveryBackup(share: string, recoveryCode: string, passkey?: PasskeyBackupKey): Promise<RecoveryBackupEnvelope>;
2851
+ /**
2852
+ * Open an envelope with whichever key the user still has.
2853
+ *
2854
+ * A passkey secret is preferred when one is supplied and the enrollment carries a matching wrap —
2855
+ * that is the path with nothing to remember. Otherwise the recovery code opens it.
2856
+ *
2857
+ * A blob registered before envelopes existed arrives with NO wraps; that case is handled by the
2858
+ * caller ({@link Recovery}), which falls back to opening the ciphertext with the recovery code
2859
+ * directly. Deciding by `keyWraps.length` rather than by sniffing the blob's shape keeps the two
2860
+ * formats from ever being confused for one another.
2861
+ */
2862
+ declare function openRecoveryBackup(envelope: RecoveryBackupEnvelope, opener: {
2863
+ recoveryCode?: string;
2864
+ passkeySecret?: string;
2865
+ }): Promise<string>;
2866
+
2867
+ /**
2868
+ * Passkey step-up signing assertion (Pattern B).
2869
+ *
2870
+ * The backend accepts an optional `passkeyAssertion` (`AuthenticationResponseJSON`)
2871
+ * on sign/send/recover DTOs and verifies it server-side. This module runs the
2872
+ * WebAuthn assertion over a **server-issued one-time challenge** and returns the
2873
+ * typed `AuthenticationResponseJSON` ready to be included in the POST body.
2874
+ *
2875
+ * ### Challenge (issue #39 — replay-safe)
2876
+ * The challenge is a random nonce the **server** mints (via a step-up challenge
2877
+ * endpoint), NOT a value derived from the request payload. `Wallet.sign`/`send`
2878
+ * fetch it, run the assertion over it, and echo its `challengeId` on the request;
2879
+ * the server verifies the assertion against the stored challenge and **burns** it,
2880
+ * so a captured assertion cannot be replayed for a later identical payload.
2881
+ *
2882
+ * ### Wiring in Wallet
2883
+ * ```ts
2884
+ * // In wallet.sign() (handled by Wallet.resolveStepUp):
2885
+ * const { challengeId, challenge } = await http.request('POST', '/v1/wallets/${id}/stepup/challenge', { operation: 'sign' });
2886
+ * const assertion = await getSigningAssertion(challenge, { credentialId });
2887
+ * await http.request('POST', '/v1/wallets/${id}/sign', { message, passkeyAssertion: assertion, passkeyChallengeId: challengeId });
2888
+ *
2889
+ * // Caller opts in:
2890
+ * await wallet.sign(digest, { requirePasskey: true });
2891
+ * ```
2892
+ */
2893
+
2894
+ /**
2895
+ * Returns `true` if the current runtime has WebAuthn available — i.e. the SDK
2896
+ * can attempt a passkey assertion. Use this as a fast pre-flight before calling
2897
+ * `getSigningAssertion()` when you want to show/hide a "sign with passkey" button.
2898
+ */
2899
+ declare function isPasskeyAssertionSupported(): boolean;
2900
+ /**
2901
+ * Override the WebAuthn `credentials.get` call. Useful for React Native (native
2902
+ * passkey module) or unit tests (mock the assertion response).
2903
+ */
2904
+ interface SigningAssertionCeremony {
2905
+ get(options: PublicKeyCredentialRequestOptionsJSON): Promise<AuthenticationResponseJSON>;
2906
+ }
2907
+ /** Options for `getSigningAssertion()`. */
2908
+ interface SigningAssertionOptions {
2909
+ /**
2910
+ * Restrict the assertion to a specific credential. Pass the `credentialId`
2911
+ * that was enrolled (e.g. from `PasskeyPrfSecretProvider.enroll()`). When
2912
+ * omitted the browser presents all resident credentials for the RP.
2913
+ */
2914
+ credentialId?: string;
2915
+ /**
2916
+ * Fully qualified domain name of the relying party. Defaults to the current
2917
+ * origin's hostname in the browser.
2918
+ */
2919
+ rpId?: string;
2920
+ /**
2921
+ * Custom ceremony implementation (for React Native or tests).
2922
+ */
2923
+ ceremony?: SigningAssertionCeremony;
2924
+ }
2925
+ /**
2926
+ * Run a WebAuthn assertion over a **server-issued one-time `challenge`** and return
2927
+ * the typed `AuthenticationResponseJSON` to attach as `passkeyAssertion` in the
2928
+ * request body.
2929
+ *
2930
+ * @param challenge — the base64url one-time challenge nonce from the server's
2931
+ * step-up challenge endpoint ({@link StepUpChallengeResponse.challenge}). It is
2932
+ * passed to the authenticator verbatim; the server verifies the assertion against
2933
+ * the stored challenge and burns it, so the assertion cannot be replayed.
2934
+ * @param options — optional ceremony override and credential hint.
2935
+ *
2936
+ * @throws `WaaskeyError('unsupported')` when WebAuthn is not available in this runtime.
2937
+ * @throws `WaaskeyError('aborted')` when the user cancels the authenticator prompt.
2938
+ */
2939
+ declare function getSigningAssertion(challenge: string, options?: SigningAssertionOptions): Promise<AuthenticationResponseJSON>;
2940
+
2941
+ /**
2942
+ * The `passkey` recovery factor (waas-backend#510) — proving possession of a registered passkey
2943
+ * instead of typing a recovery code.
2944
+ *
2945
+ * This is what lets an app offer `{passkey, totp, email_otp}`: three factors, none of them a secret
2946
+ * the user has to remember. The PRF wrap protects the backup blob at rest, but the blob is only
2947
+ * released once every enrolled factor verifies, so as long as the only strong factor was a memorized
2948
+ * code, the code stayed mandatory.
2949
+ *
2950
+ * The factor's token is a WebAuthn assertion, not a value a person can type — which is why an app
2951
+ * needs this helper rather than an input field.
2952
+ */
2953
+ /**
2954
+ * Enrol a registered passkey as a recovery factor.
2955
+ *
2956
+ * The `credential` is the credential id, which is public and useless on its own — the private key
2957
+ * never leaves the authenticator. The credential must ALREADY be registered with the platform: the
2958
+ * server refuses an unknown id, because a factor that can never be satisfied is a lock-out the user
2959
+ * would discover only while recovering from a device they no longer have.
2960
+ */
2961
+ declare function passkeyFactorEnrollment(credentialId: string): FactorEnrollment;
2962
+ /**
2963
+ * Produce the `passkey` factor's proof for a recovery challenge.
2964
+ *
2965
+ * Pass the `passkeyChallenge` the challenge endpoint issued for THIS session: the server checks the
2966
+ * assertion against those exact bytes and consumes them, so an assertion captured from an earlier
2967
+ * attempt is worthless. The assertion travels as JSON in the factor's `token`, which is the only value
2968
+ * property the API's factor DTO accepts.
2969
+ *
2970
+ * ```ts
2971
+ * const { challengeId, requiredFactors, passkeyChallenge } = await waaskey.recovery.challenge(walletId);
2972
+ * const verifications = [
2973
+ * await passkeyFactorVerification(passkeyChallenge!),
2974
+ * { type: 'totp', token: code },
2975
+ * { type: 'email_otp', token: otp },
2976
+ * ];
2977
+ * await waaskey.recovery.recover(walletId, { challengeId, verifications, passkeySecret });
2978
+ * ```
2979
+ *
2980
+ * @throws `WaaskeyError('unsupported')` when WebAuthn is unavailable in this runtime (pass a
2981
+ * `ceremony` for React Native or tests).
2982
+ * @throws `WaaskeyError('aborted')` when the user cancels the authenticator prompt.
2983
+ */
2984
+ declare function passkeyFactorVerification(challenge: string, options?: SigningAssertionOptions): Promise<FactorVerification>;
2985
+
2493
2986
  /**
2494
2987
  * **Optional** client-side broadcast helper.
2495
2988
  *
@@ -2638,78 +3131,4 @@ declare class PasskeyPrfSecretProvider {
2638
3131
  }): Promise<PasskeyPrfResult>;
2639
3132
  }
2640
3133
 
2641
- /**
2642
- * Passkey step-up signing assertion (Pattern B).
2643
- *
2644
- * The backend accepts an optional `passkeyAssertion` (`AuthenticationResponseJSON`)
2645
- * on sign/send/recover DTOs and verifies it server-side. This module runs the
2646
- * WebAuthn assertion over a **server-issued one-time challenge** and returns the
2647
- * typed `AuthenticationResponseJSON` ready to be included in the POST body.
2648
- *
2649
- * ### Challenge (issue #39 — replay-safe)
2650
- * The challenge is a random nonce the **server** mints (via a step-up challenge
2651
- * endpoint), NOT a value derived from the request payload. `Wallet.sign`/`send`
2652
- * fetch it, run the assertion over it, and echo its `challengeId` on the request;
2653
- * the server verifies the assertion against the stored challenge and **burns** it,
2654
- * so a captured assertion cannot be replayed for a later identical payload.
2655
- *
2656
- * ### Wiring in Wallet
2657
- * ```ts
2658
- * // In wallet.sign() (handled by Wallet.resolveStepUp):
2659
- * const { challengeId, challenge } = await http.request('POST', '/v1/wallets/${id}/stepup/challenge', { operation: 'sign' });
2660
- * const assertion = await getSigningAssertion(challenge, { credentialId });
2661
- * await http.request('POST', '/v1/wallets/${id}/sign', { message, passkeyAssertion: assertion, passkeyChallengeId: challengeId });
2662
- *
2663
- * // Caller opts in:
2664
- * await wallet.sign(digest, { requirePasskey: true });
2665
- * ```
2666
- */
2667
-
2668
- /**
2669
- * Returns `true` if the current runtime has WebAuthn available — i.e. the SDK
2670
- * can attempt a passkey assertion. Use this as a fast pre-flight before calling
2671
- * `getSigningAssertion()` when you want to show/hide a "sign with passkey" button.
2672
- */
2673
- declare function isPasskeyAssertionSupported(): boolean;
2674
- /**
2675
- * Override the WebAuthn `credentials.get` call. Useful for React Native (native
2676
- * passkey module) or unit tests (mock the assertion response).
2677
- */
2678
- interface SigningAssertionCeremony {
2679
- get(options: PublicKeyCredentialRequestOptionsJSON): Promise<AuthenticationResponseJSON>;
2680
- }
2681
- /** Options for `getSigningAssertion()`. */
2682
- interface SigningAssertionOptions {
2683
- /**
2684
- * Restrict the assertion to a specific credential. Pass the `credentialId`
2685
- * that was enrolled (e.g. from `PasskeyPrfSecretProvider.enroll()`). When
2686
- * omitted the browser presents all resident credentials for the RP.
2687
- */
2688
- credentialId?: string;
2689
- /**
2690
- * Fully qualified domain name of the relying party. Defaults to the current
2691
- * origin's hostname in the browser.
2692
- */
2693
- rpId?: string;
2694
- /**
2695
- * Custom ceremony implementation (for React Native or tests).
2696
- */
2697
- ceremony?: SigningAssertionCeremony;
2698
- }
2699
- /**
2700
- * Run a WebAuthn assertion over a **server-issued one-time `challenge`** and return
2701
- * the typed `AuthenticationResponseJSON` to attach as `passkeyAssertion` in the
2702
- * request body.
2703
- *
2704
- * @param challenge — the base64url one-time challenge nonce from the server's
2705
- * step-up challenge endpoint ({@link StepUpChallengeResponse.challenge}). It is
2706
- * passed to the authenticator verbatim; the server verifies the assertion against
2707
- * the stored challenge and burns it, so the assertion cannot be replayed.
2708
- * @param options — optional ceremony override and credential hint.
2709
- *
2710
- * @throws `WaaskeyError('unsupported')` when WebAuthn is not available in this runtime.
2711
- * @throws `WaaskeyError('aborted')` when the user cancels the authenticator prompt.
2712
- */
2713
- declare function getSigningAssertion(challenge: string, options?: SigningAssertionOptions): Promise<AuthenticationResponseJSON>;
2714
-
2715
- 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 PasskeyCeremony, type PasskeyPrfEnrollOptions, type PasskeyPrfResult, PasskeyPrfSecretProvider, type PrfCeremony, PrimePool, type PrimePoolOptions, type PrimePoolStore, type RecoverParams, type RecoverSignParams, type RecoverWalletResponse, Recovery, type RecoveryChallengeResponse, type RecoveryFactor, type RecoveryRetrieveResponse, type RecoveryShareInfo, type RegisterRecoveryParams, Reshare, type ReshareCompletionCeremony, type ReshareCompletionParams, type ReshareCompletionResult, 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, userBackupPendingKey, validateCustodyPolicy, verifyWasmIntegrity };
3134
+ 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 };