@cavos/kit 0.0.4 → 0.0.5

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.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { A as AuthProvider, I as Identity, W as WalletRegistry, R as RegisteredWallet, D as DevicePublicKey, a as RecoveryClient, P as PendingDeviceRequest, b as DeviceSigner, c as DeviceSignature, C as ChainAdapter, d as ComputeAddressParams, e as ChainCall, f as PasskeyAssertion, S as StellarNetwork } from './Cavos-x9qFpOvJ.mjs';
2
- export { g as Cavos, h as CavosSolana, i as CavosStellar, j as CavosWallet, k as Chain, l as ConnectOptions, m as ConnectSolanaOptions, n as ConnectStatus, o as ConnectStellarOptions, p as DEVICE_ACCOUNT_PROGRAM_ID, q as DEVICE_ACCOUNT_WASM_HASH, E as EnrolledPasskey, F as FACTORY_CONTRACT_ID, r as InMemoryWalletRegistry, s as InstructionAccount, t as InstructionData, N as NATIVE_SAC_ID, u as NetworkEnv, v as PasskeyApprovable, w as PasskeyEnrollParams, x as PasskeySigner, y as PasskeySignerOptions, z as RecoverSolanaOptions, B as RecoverStellarOptions, G as RecoveryOptions, H as SECP256R1_PROGRAM_ID, J as SOLANA_NETWORKS, K as STELLAR_NETWORKS, L as SolanaAdapter, M as SolanaAdapterOptions, O as SolanaNetwork, Q as SolanaRelayer, T as SolanaRelayerOptions, U as StaticIdentity, V as StellarRelayer, X as StellarRelayerOptions, Y as anchorDiscriminator, Z as approveDeviceEverywhere, _ as base64urlEncode, $ as batchChallenge, a0 as buildSecp256r1Instruction, a1 as compressedPubkey, a2 as encodeLowSSignature, a3 as lowS, a4 as recoverCandidatePublicKeys, a5 as serializeInstructions, a6 as webauthnDigest } from './Cavos-x9qFpOvJ.mjs';
1
+ import { A as AuthProvider, I as Identity, W as WalletRegistry, R as RegisteredWallet, D as DevicePublicKey, a as RecoveryClient, P as PendingDeviceRequest, b as DeviceSigner, c as DeviceSignature, C as ChainAdapter, d as ComputeAddressParams, e as ChainCall, f as PasskeyAssertion, S as StellarNetwork, g as DeviceUnwrapKey } from './Cavos-D20EtgOK.mjs';
2
+ export { h as Cavos, i as CavosSolana, j as CavosStellar, k as CavosWallet, l as Chain, m as ConnectOptions, n as ConnectSolanaOptions, o as ConnectStatus, p as ConnectStellarOptions, q as DEVICE_ACCOUNT_PROGRAM_ID, E as EnrolledPasskey, r as ExecuteOptions, H as HORIZON_URL, s as InMemoryWalletRegistry, t as InstructionAccount, u as InstructionData, L as LocalDeviceUnwrapKey, N as NetworkEnv, v as PasskeyApprovable, w as PasskeyEnrollParams, x as PasskeySigner, y as PasskeySignerOptions, z as RecoverSolanaOptions, B as RecoveryOptions, F as SECP256R1_PROGRAM_ID, G as SOLANA_NETWORKS, J as STELLAR_NETWORKS, K as SolanaAdapter, M as SolanaAdapterOptions, O as SolanaNetwork, Q as SolanaRelayer, T as SolanaRelayerOptions, U as StaticIdentity, V as StellarConnectStatus, X as StellarRelayKind, Y as StellarRelayer, Z as StellarRelayerOptions, _ as XLM_DECIMALS, $ as anchorDiscriminator, a0 as approveDeviceEverywhere, a1 as base64urlEncode, a2 as batchChallenge, a3 as buildSecp256r1Instruction, a4 as compressedPubkey, a5 as deviceSlotId, a6 as encodeLowSSignature, a7 as lowS, a8 as recoverCandidatePublicKeys, a9 as serializeInstructions, aa as webauthnDigest } from './Cavos-D20EtgOK.mjs';
3
3
  import { Signer, ArraySignatureType } from 'starknet';
4
- import { rpc, xdr } from '@stellar/stellar-sdk';
4
+ import { Horizon, Transaction, FeeBumpTransaction, Account, Keypair } from '@stellar/stellar-sdk';
5
5
  import '@solana/web3.js';
6
6
 
7
7
  interface CavosAuthOptions {
@@ -246,13 +246,33 @@ declare class StarknetAdapter implements ChainAdapter {
246
246
  private readonly opts;
247
247
  readonly chain: "starknet";
248
248
  constructor(opts: StarknetAdapterOptions);
249
- computeAddress({ addressSeed, initialSigner, salt }: ComputeAddressParams): string;
250
- /** Single UDC deploy; the constructor registers the first device signer, so
251
- * the account is ready the moment it is deployed (fits the paymaster's
252
- * deploy + execute_from_outside bundle). */
249
+ /**
250
+ * Deterministic address = f(addressSeed) ONLY. The device pubkey is NOT
251
+ * part of the derivation anti-squatting is the integrator's responsibility
252
+ * (keep `appSalt` secret; deploy on first login). This makes the address
253
+ * recomputable by the user from (userId, appSalt) alone, even after losing
254
+ * every device.
255
+ *
256
+ * `initialSigner` in `ComputeAddressParams` is IGNORED on Starknet (kept in
257
+ * the shared type for Solana/Stellar, which still include it).
258
+ */
259
+ computeAddress({ addressSeed, salt }: ComputeAddressParams): string;
260
+ /**
261
+ * UDC deploy call. The constructor takes ONLY the seed — no device pubkey —
262
+ * so the account is born with no signers. The caller MUST follow up with
263
+ * `buildInitialize` in the same multicall (or a separate tx) to register the
264
+ * first device signer; otherwise the account is unusable.
265
+ */
253
266
  buildDeploy(params: ComputeAddressParams): ChainCall[];
254
- /** Constructor calldata: [address_seed, pub_x_low, pub_x_high, pub_y_low, pub_y_high]. */
255
- constructorCalldata(addressSeed: bigint, initialSigner: DevicePublicKey): string[];
267
+ /** Constructor calldata: [address_seed]. Device pubkey is registered post-deploy via initialize. */
268
+ constructorCalldata(addressSeed: bigint): string[];
269
+ /**
270
+ * `initialize` call: registers the first device signer. Callable only while
271
+ * the account has no signers (one-shot). In production this is bundled with
272
+ * the UDC deploy in a single sponsored multicall — see `connectStarknet`.
273
+ * Anti-squatting is NOT enforced on-chain.
274
+ */
275
+ buildInitialize(accountAddress: string, devicePubkey: DevicePublicKey): ChainCall;
256
276
  buildAddSigner(accountAddress: string, signer: DevicePublicKey): ChainCall;
257
277
  buildRemoveSigner(accountAddress: string, signer: DevicePublicKey): ChainCall;
258
278
  isAuthorizedSigner(accountAddress: string, signer: DevicePublicKey): Promise<boolean>;
@@ -313,113 +333,291 @@ declare const UDC_ADDRESS = "0x041a78e741e5af2fec34b695679bc6891742439f7afb8484e
313
333
  * DeviceAccount class hash, per network. Populated from
314
334
  * `account-contracts/starknet/deployments/<network>.json` after declaring.
315
335
  *
316
- * Sepolia re-declared 2026-07-01 with the passkey-approval surface + BATCHED
317
- * multi-chain challenge (one passkey prompt approves a device on all chains).
318
- * Mainnet still runs the prior class (no passkey) until it is re-declared.
336
+ * Sepolia re-declared 2026-07-04:
337
+ * - Deploy attestation REMOVED `initialize` takes only the device pubkey.
338
+ * - `is_valid_signature` returns VALIDATED pre-init so the SNIP-9 outside-
339
+ * execution path (used by the paymaster's `deploy_and_invoke`) can carry
340
+ * the `initialize` call before any signer is registered. `__execute__`
341
+ * still enforces that ONLY `initialize` runs in that state.
342
+ * Mainnet still runs the prior class (with attestation) until it is re-declared.
319
343
  */
320
344
  declare const DEVICE_ACCOUNT_CLASS_HASH: Record<StarknetNetwork, string>;
321
345
 
346
+ /** In-memory shape of the account's control-key envelope. */
347
+ interface AccountEnvelope {
348
+ /** Sealed control seed (`sealControlSeed` output). */
349
+ ct: Uint8Array;
350
+ /** Per-device ECIES DEK-wraps, keyed by device slot id. */
351
+ deviceWraps: Record<string, Uint8Array>;
352
+ /** Passkey-PRF DEK-wrap, if a passkey factor is enrolled. */
353
+ passkeyWrap?: Uint8Array;
354
+ /** Recovery-code DEK-wrap, if the user set one up. */
355
+ recoveryWrap?: Uint8Array;
356
+ }
357
+ /** Serialize an envelope into `MANAGE_DATA` name→value entries (raw bytes). */
358
+ declare function toDataEntries(env: AccountEnvelope): Record<string, Uint8Array>;
359
+ /** Reconstruct an envelope from an account's data entries (name→bytes). */
360
+ declare function fromDataEntries(entries: Record<string, Uint8Array>): AccountEnvelope;
361
+
322
362
  interface StellarAdapterOptions {
323
363
  network: StellarNetwork;
324
- /** RPC override (else the network default). */
325
- rpcUrl?: string;
326
- /** Factory contract id override (else the per-network default). */
327
- factoryId?: string;
328
- /** The device signer that authorizes account operations. */
329
- signer: DeviceSigner;
364
+ /** Horizon URL override (else the per-network default). */
365
+ horizonUrl?: string;
330
366
  }
331
367
  /**
332
- * Stellar / Soroban implementation of the Cavos device-account surface. Unlike
333
- * Starknet (`buildSignature(txHash: bigint)`) the Soroban signing unit is a
334
- * 32-byte Soroban *auth-entry* preimage, so as the Solana adapter did for its
335
- * own model this adapter exposes chain-native methods rather than the generic
336
- * `ChainAdapter` shape. Its job:
337
- * - derive the deterministic account address off-chain (matches the factory),
338
- * - build the factory/account/token invocations as host functions, and
339
- * - sign a Soroban authorization entry with the silent P-256 device key,
340
- * producing the `Vec<DeviceSignature>` ScVal that the contract's
341
- * `__check_auth` verifies.
368
+ * Classic-Stellar (`G…`) multisig account adapter.
369
+ *
370
+ * Unlike the Soroban `StellarAdapter` (contract `C…` accounts authorized by a
371
+ * `__check_auth` device signature) this operates on a *classic* account whose
372
+ * signing is ordinary ed25519 multisig:
373
+ *
374
+ * - the **master** key (deterministic from identity) names the `G…` address and
375
+ * is set to weight 0 at creation powerless afterwards;
376
+ * - the **control** key (random, weight 1, thresholds 1) is the real signer,
377
+ * recovered by decrypting the on-chain envelope (see `envelope.ts`).
378
+ *
379
+ * The adapter builds/read classic transactions and account state via Horizon; it
380
+ * never holds a secret — callers pass in the `Keypair`s to sign with. Gasless
381
+ * submission is a fee-bump whose fee source is the relayer (Phase 3).
342
382
  */
343
383
  declare class StellarAdapter {
344
384
  readonly chain: "stellar";
345
385
  readonly network: StellarNetwork;
346
386
  readonly passphrase: string;
347
- private readonly rpcUrl;
348
- private readonly factoryId;
349
- private readonly signer;
387
+ private readonly horizonUrl;
350
388
  private _server?;
351
389
  constructor(opts: StellarAdapterOptions);
352
- server(): rpc.Server;
353
- private networkId;
390
+ server(): Horizon.Server;
391
+ /** Whether the classic account already exists on-chain. */
392
+ isDeployed(address: string): Promise<boolean>;
393
+ /** Read the account's `MANAGE_DATA` entries as raw bytes (name → value). */
394
+ loadDataEntries(address: string): Promise<Record<string, Uint8Array>>;
395
+ /** Native XLM balance in stroops. Returns 0n if the account doesn't exist. */
396
+ balance(address: string): Promise<bigint>;
354
397
  /**
355
- * Deterministic account address for `(addressSeed, initialSigner)` computed
356
- * off-chain, byte-identical to the factory's on-chain `account_address`.
357
- * `contractId = sha256(HashIdPreimage(networkId, factory, salt))` with
358
- * `salt = sha256(addressSeed || sec1(initialSigner))`.
398
+ * Build the account-creation transaction (source = funder, the relayer or a
399
+ * self-funded keypair):
400
+ * 1. `createAccount` funds the deterministic `G…` master address,
401
+ * 2. `manageData` writes the control-key envelope entries (authorized by the
402
+ * still-weight-1 master),
403
+ * 3. `setOptions` adds the control signer (weight 1), sets all thresholds to
404
+ * 1, and zeroes the master weight — after this the master can never sign.
405
+ *
406
+ * The returned tx must be signed by BOTH the master keypair (for the account's
407
+ * own ops) and the funder (source + fee). Sponsorship of reserves is layered on
408
+ * in Phase 3.
359
409
  */
360
- computeAddress(addressSeed: Uint8Array, initialSigner: DevicePublicKey): string;
361
- /** `salt = sha256(addressSeed(32) || sec1(initialSigner)(65))` — matches the factory. */
362
- accountSalt(addressSeed: Uint8Array, initialSigner: DevicePublicKey): Buffer;
363
- /** Host function: `factory.deploy(address_seed, initial_signer)`. */
364
- buildDeploy(addressSeed: Uint8Array, initialSigner: DevicePublicKey): xdr.HostFunction;
365
- /** Host function: `account.add_signer(new_signer)` (requires device auth). */
366
- buildAddSigner(accountAddress: string, signer: DevicePublicKey): xdr.HostFunction;
367
- /** Host function: `account.remove_signer(signer)` (requires device auth). */
368
- buildRemoveSigner(accountAddress: string, signer: DevicePublicKey): xdr.HostFunction;
369
- /** Host function: `account.add_approver(passkey)` (requires device auth). */
370
- buildAddApprover(accountAddress: string, passkey: DevicePublicKey): xdr.HostFunction;
371
- /** Host function: `account.remove_approver(passkey)` (requires device auth). */
372
- buildRemoveApprover(accountAddress: string, passkey: DevicePublicKey): xdr.HostFunction;
373
- /** This chain's leaf for approving `add_signer(newSigner)` at `nonce`:
374
- * `sha256(sec1(new_signer) || nonce_be8)`. The batch challenge the passkey signs
375
- * is `sha256(concat(leaves))` across chains. */
376
- passkeyLeaf(newSigner: DevicePublicKey, nonce: bigint): Uint8Array;
377
- /** Host function: passkey-authorized `add_signer_via_passkey` (no device auth —
378
- * authorized by the embedded WebAuthn assertion, so any relayer can submit).
379
- * `leaves`/`leafIndex` place this chain's leaf in the multi-chain batch. */
380
- buildAddSignerViaPasskey(accountAddress: string, newSigner: DevicePublicKey, passkey: DevicePublicKey, nonce: bigint, leaves: Uint8Array[], leafIndex: number, assertion: PasskeyAssertion): xdr.HostFunction;
381
- /** Read whether `passkey` is a registered approver (read-only simulation). */
382
- /** True if the account has at least one passkey registered as an approver.
383
- * Reads the contract's `approvers` view and checks the list is non-empty. */
384
- hasPasskeyApprover(accountAddress: string, readSource: string): Promise<boolean>;
385
- isApprover(accountAddress: string, passkey: DevicePublicKey, readSource: string): Promise<boolean>;
386
- /** Read the current passkey-approval nonce (read-only simulation). */
387
- passkeyNonce(accountAddress: string, readSource: string): Promise<bigint>;
388
- /** Host function: SEP-41 `token.transfer(from=account, to, amount)` (device auth). */
389
- buildTransfer(tokenId: string, accountAddress: string, destination: string, amount: bigint): xdr.HostFunction;
410
+ buildCreateTx(params: {
411
+ funder: string;
412
+ masterAddress: string;
413
+ controlAddress: string;
414
+ envelope: AccountEnvelope;
415
+ /** Starting balance in stroops (must cover base reserve + entries). */
416
+ startingBalance: bigint;
417
+ }): Promise<Transaction>;
418
+ /**
419
+ * Build a **sponsored** account-creation transaction whose source is the
420
+ * relayer. Wraps the account setup in `beginSponsoringFutureReserves` /
421
+ * `endSponsoringFutureReserves`, so the relayer (not the user) pays every
422
+ * reserve the account is created with a 0 starting balance and holds no
423
+ * locked XLM of the user's. Ops:
424
+ * 0. beginSponsoringFutureReserves(G) source = relayer
425
+ * 1. createAccount(G, 0) source = relayer
426
+ * 2. manageData(cv:… envelope) source = G (master-signed)
427
+ * 3. setOptions(control signer, master 0) source = G
428
+ * 4. endSponsoringFutureReserves() source = G
429
+ *
430
+ * Signed by the master (for the G ops, while it's still weight 1); the relayer
431
+ * co-signs (source + fee + sponsorship) before submitting.
432
+ */
433
+ buildSponsoredCreateTx(params: {
434
+ relayer: string;
435
+ masterAddress: string;
436
+ controlAddress: string;
437
+ envelope: AccountEnvelope;
438
+ }): Promise<Transaction>;
439
+ /**
440
+ * Build a classic native-XLM payment as an *inner* transaction whose source is
441
+ * the account itself (`G…`), signed by the control key. Wrap it in a fee-bump
442
+ * (see `wrapFeeBump`) so the relayer pays the fee — gasless.
443
+ */
444
+ buildPaymentTx(params: {
445
+ from: string;
446
+ to: string;
447
+ /** Amount in stroops. */
448
+ amount: bigint;
449
+ }): Promise<Transaction>;
390
450
  /**
391
- * Sign a Soroban authorization entry with the silent device key, producing the
392
- * `Vec<DeviceSignature>` the account's `__check_auth` verifies. The device
393
- * signs `sha256(preimage)` (WebCrypto hashes once more internally), which is
394
- * exactly what the contract recomputes. Mutates + returns the entry.
451
+ * Build a data-entry write (e.g. re-wrapping the DEK for a newly approved
452
+ * device) as an inner tx sourced by the account, signed by the control key.
395
453
  */
396
- signAuthEntry(entry: xdr.SorobanAuthorizationEntry, validUntilLedger: number): Promise<xdr.SorobanAuthorizationEntry>;
454
+ buildDataTx(params: {
455
+ account: string;
456
+ entries: Record<string, Uint8Array>;
457
+ }): Promise<Transaction>;
458
+ /**
459
+ * Build a **sponsored** data-entry write whose source is the relayer, so the
460
+ * relayer (not the 0-balance account) pays the reserve of any NEW subentry.
461
+ * Adding a factor (passkey / recovery) or a device slot creates a data entry
462
+ * that needs ~0.5 XLM of reserve; a sponsored account holds no XLM, so — like
463
+ * account creation — the write must be wrapped in begin/endSponsoringFuture
464
+ * reserves with the relayer as sponsor. Ops:
465
+ * 0. beginSponsoringFutureReserves(account) source = relayer
466
+ * 1..n. manageData(cv:…) source = account (control-signed)
467
+ * last. endSponsoringFutureReserves() source = account
468
+ *
469
+ * Signed by the control key (account ops) + the relayer (source + fee + sponsor).
470
+ */
471
+ buildSponsoredDataTx(params: {
472
+ relayer: string;
473
+ account: string;
474
+ entries: Record<string, Uint8Array>;
475
+ }): Promise<Transaction>;
476
+ /** Wrap a control-signed inner tx in a fee-bump whose fee source is `feeSource`
477
+ * (the relayer). The inner tx pays nothing; the relayer pays all fees. */
478
+ wrapFeeBump(inner: Transaction, feeSource: string): FeeBumpTransaction;
479
+ /** Submit a fully-signed classic transaction and return its hash. Throws with
480
+ * the Horizon result codes on failure. */
481
+ submit(tx: Transaction | FeeBumpTransaction): Promise<string>;
482
+ /** Build an `Account` handle for a known address + sequence (avoids a Horizon
483
+ * round-trip when the caller already has the sequence). */
484
+ accountAt(address: string, sequence: string): Account;
485
+ }
486
+
487
+ interface WebCryptoUnwrapKeyOptions {
488
+ /** Storage key for this device's unwrap key (e.g. `${userId}:${appSalt}`). One
489
+ * ECDH key per (this value, browser profile). */
490
+ keyId: string;
491
+ }
492
+ /**
493
+ * Browser `DeviceUnwrapKey`: a non-extractable P-256 **ECDH** key generated with
494
+ * WebCrypto and persisted in IndexedDB. Distinct from `WebCryptoSigner` (an ECDSA
495
+ * signing key) — a signing key can't do ECDH, so the classic-G envelope needs its
496
+ * own key here. The private key never leaves WebCrypto: the account DEK is
497
+ * unwrapped via `deriveBits` (raw ECDH), then AES-GCM in `@noble` on the derived
498
+ * KEK. Per-device, non-syncable → losing the device loses only this convenience
499
+ * factor, never the account (the passkey / recovery factors survive).
500
+ */
501
+ declare class WebCryptoDeviceUnwrapKey implements DeviceUnwrapKey {
502
+ private readonly privateKey;
503
+ private readonly publicRaw;
504
+ readonly keyId: string;
505
+ private constructor();
506
+ /** Create a fresh device unwrap key and persist it. */
507
+ static create(opts: WebCryptoUnwrapKeyOptions): Promise<WebCryptoDeviceUnwrapKey>;
508
+ /** Load an existing device unwrap key, or null if none exists yet. */
509
+ static load(opts: WebCryptoUnwrapKeyOptions): Promise<WebCryptoDeviceUnwrapKey | null>;
510
+ /** Load the device unwrap key, creating one on first use. */
511
+ static loadOrCreate(opts: WebCryptoUnwrapKeyOptions): Promise<WebCryptoDeviceUnwrapKey>;
512
+ publicKeySec1(): Uint8Array;
513
+ slotId(): string;
514
+ unwrap(blob: Uint8Array): Promise<Uint8Array>;
515
+ }
516
+
517
+ /**
518
+ * WebAuthn **PRF** factor for the classic-G envelope.
519
+ *
520
+ * Unlike the Soroban passkey path (which needs an on-chain-verifiable *assertion
521
+ * signature*), the classic-G account only needs a stable 32-byte secret to wrap
522
+ * the DEK — exactly what the WebAuthn PRF extension provides: for a given
523
+ * credential + input salt the authenticator returns the same 32 bytes on every
524
+ * device the passkey syncs to (iCloud Keychain / Google Password Manager), and
525
+ * that secret is derived inside the authenticator and never derivable by Cavos or
526
+ * OAuth. That makes it the ideal synced anchor to approve a new device or recover.
527
+ *
528
+ * `getSecret()` returns the raw PRF output; callers pass it to
529
+ * `derivePasskeyKEK` (via `CavosStellar.enrollPasskey` /
530
+ * `approveThisDeviceWithPasskey`). Keeping this class free of any DEK/KEK logic
531
+ * lets the account class stay runtime-agnostic and unit-testable.
532
+ */
533
+ interface PasskeyPrfOptions {
534
+ /** Relying-Party id (usually the eTLD+1). Defaults to `window.location.hostname`. */
535
+ rpId?: string;
536
+ /** Human-readable RP name shown in the OS passkey UI. */
537
+ rpName?: string;
538
+ }
539
+ interface PasskeyPrfEnrollParams {
540
+ /** Stable user handle for the credential (e.g. the account address or userId). */
541
+ userId: string;
542
+ /** Account name shown in the OS passkey UI (e.g. an email). */
543
+ userName: string;
544
+ displayName?: string;
545
+ }
546
+ declare class PasskeyPrf {
547
+ private readonly rpId;
548
+ private readonly rpName;
549
+ constructor(opts?: PasskeyPrfOptions);
550
+ /** True if this platform advertises a usable passkey (platform authenticator). */
551
+ static isSupported(): Promise<boolean>;
397
552
  /**
398
- * Read a SEP-41 token balance of `account` via a read-only simulation of
399
- * `token.balance(account)`. Returns 0 when the account isn't deployed or holds
400
- * none. `readSource` is any funded G-account (used only for the simulation).
553
+ * Create a new synced, discoverable passkey with the PRF extension enabled, then
554
+ * immediately read its PRF secret. Returns the credential id and the 32-byte
555
+ * secret so the caller can enroll the passkey factor in one step. Some
556
+ * authenticators don't return PRF results on create — in that case `secret` is
557
+ * undefined and the caller should follow up with `getSecret()`.
401
558
  */
402
- readBalance(tokenId: string, account: string, readSource: string): Promise<bigint>;
403
- /** Whether the account contract instance exists on-chain (is deployed). */
404
- isDeployed(accountAddress: string): Promise<boolean>;
559
+ enroll(params: PasskeyPrfEnrollParams): Promise<{
560
+ credentialId: Uint8Array;
561
+ secret?: Uint8Array;
562
+ }>;
405
563
  /**
406
- * Read whether `signer` is a currently-authorized signer of the account, via a
407
- * read-only simulation of `account.is_authorized(signer)`. `readSource` is any
408
- * funded G-account (used only for the simulation's source/sequence).
564
+ * Get the passkey's 32-byte PRF secret. Uses discoverable credentials (no
565
+ * `allowCredentials`), so it works from a brand-new browser the OS shows the
566
+ * synced passkey picker. Throws if the authenticator doesn't support PRF.
409
567
  */
410
- isAuthorizedSigner(accountAddress: string, signer: DevicePublicKey, readSource: string): Promise<boolean>;
568
+ getSecret(): Promise<Uint8Array>;
411
569
  }
412
- /** SEC-1 uncompressed P-256 public key (65 bytes: 0x04 || X || Y). */
413
- declare function sec1Pubkey(pk: DevicePublicKey): Uint8Array;
414
- /** Raw 64-byte `r || s`, normalized to low-S (secp256r1_verify requires it). */
415
- declare function encodeLowSSignature(sig: DeviceSignature): Uint8Array;
570
+
571
+ /**
572
+ * The account's master `Keypair`. Its public key IS the classic `G…` address of
573
+ * the account. Deterministic: same identity → same keypair on every device.
574
+ * Set to weight 0 at creation, so this keypair can never actually authorize a
575
+ * transaction — it only names the account.
576
+ */
577
+ declare function deriveStellarMasterKeypair(identity: IdentityInput): Keypair;
578
+ /**
579
+ * The deterministic `G…` address for an identity, derivable offline from login
580
+ * alone — no chain read, no registry. This is what makes the account
581
+ * self-custodial and backend-free: the address is a pure function of identity.
582
+ */
583
+ declare function deriveStellarAddress(identity: IdentityInput): string;
584
+ /** A freshly generated control key: the real (weight-1) signer of the account.
585
+ * Returns both the `Keypair` and its raw 32-byte seed (the secret that the
586
+ * envelope encrypts). Generated once at account creation, then only ever
587
+ * recovered by decrypting the on-chain envelope. */
588
+ declare function generateControlKey(): {
589
+ keypair: Keypair;
590
+ seed: Uint8Array;
591
+ };
592
+
593
+ /** A DEK-wrap blob: `nonce || AES-GCM(kek, dek)`. Self-contained (nonce inline). */
594
+ type WrappedDEK = Uint8Array;
595
+ /** Fresh 256-bit data-encryption key. One per account, generated at creation. */
596
+ declare function generateDEK(): Uint8Array;
597
+ /** Encrypt the control seed under the DEK → `nonce || ct`. */
598
+ declare function sealControlSeed(controlSeed: Uint8Array, dek: Uint8Array): Uint8Array;
599
+ /** Decrypt the control seed (`nonce || ct`) under the DEK. Throws on tamper. */
600
+ declare function openControlSeed(sealed: Uint8Array, dek: Uint8Array): Uint8Array;
601
+ /** Wrap the DEK under a raw 32-byte KEK → `nonce || AES-GCM(kek, dek)`. */
602
+ declare function wrapDEK(dek: Uint8Array, kek: Uint8Array): WrappedDEK;
603
+ /** Unwrap the DEK from a `nonce || ct` blob under a raw 32-byte KEK. */
604
+ declare function unwrapDEK(wrapped: WrappedDEK, kek: Uint8Array): Uint8Array;
605
+ /** KEK from a human recovery code (PBKDF2-stretched, then HKDF-scoped). The same
606
+ * normalised code yields the same KEK on any device. */
607
+ declare function deriveRecoveryKEK(code: string): Uint8Array;
608
+ /** KEK from a WebAuthn PRF output (32 bytes the authenticator returns for our
609
+ * fixed PRF salt). HKDF-scoped so the raw PRF secret is never used directly. */
610
+ declare function derivePasskeyKEK(prfOutput: Uint8Array): Uint8Array;
416
611
  /**
417
- * The `Vec<DeviceSignature>` ScVal the contract's `__check_auth` decodes. Each
418
- * element is a struct `{ public_key: BytesN<65>, signature: BytesN<64> }`.
419
- * Soroban serializes a struct as a symbol-keyed map sorted by key; `public_key`
420
- * precedes `signature`, so `nativeToScVal` (which sorts) yields the exact layout.
612
+ * ECIES-wrap the DEK to a device's P-256 public key (SEC1 uncompressed, 65
613
+ * bytes). Returns `ephPubCompressed(33) || nonce(12) || ct` self-contained.
614
+ * An ephemeral keypair makes each wrap use a fresh shared secret; the device
615
+ * unwraps with its private scalar. The ephemeral public key is bound into the
616
+ * KEK via the HKDF salt so it can't be swapped.
421
617
  */
422
- declare function deviceSignatureScVal(pubkey: DevicePublicKey, sig: DeviceSignature): xdr.ScVal;
618
+ declare function eciesWrapDEK(dek: Uint8Array, recipientPubSec1: Uint8Array): Uint8Array;
619
+ /** ECIES-unwrap the DEK with the device's private scalar (32 bytes). */
620
+ declare function eciesUnwrapDEK(blob: Uint8Array, recipientPrivScalar: Uint8Array): Uint8Array;
423
621
 
424
622
  /**
425
623
  * Serialize a device signature to the felt array for `tx_info.signature`:
@@ -446,4 +644,4 @@ declare function hexToBytes(hex: string): Uint8Array;
446
644
  /** A felt/bigint -> 32-byte big-endian Uint8Array (the tx-hash width). */
447
645
  declare function bigIntTo32Bytes(value: bigint): Uint8Array;
448
646
 
449
- export { AuthProvider, BackupSigner, CavosAuth, type CavosAuthOptions, ChainAdapter, ChainCall, ComputeAddressParams, DEVICE_ACCOUNT_CLASS_HASH, DevicePublicKey, DeviceSignature, DeviceSigner, HttpRecoveryClient, type HttpRecoveryClientOptions, HttpWalletRegistry, type HttpWalletRegistryOptions, Identity, type IdentityInput, PasskeyAssertion, PendingDeviceRequest, RecoveryClient, RegisteredWallet, STARKNET_NETWORKS, StarknetAdapter, type StarknetAdapterOptions, StarknetDeviceSigner, type StarknetNetwork, StellarAdapter, type StellarAdapterOptions, StellarNetwork, UDC_ADDRESS, WalletRegistry, WebCryptoSigner, type WebCryptoSignerOptions, bigIntTo32Bytes, bytesToBigInt, bytesToHex, deriveAddressSeed, deriveAddressSeedSolana, deriveAddressSeedStellar, deriveBackupKey, deviceSignatureScVal, encodeLowSSignature as encodeStellarLowSSignature, generateRecoveryCode, hexToBytes, recoverYParity, sec1Pubkey, signatureToFelts, u256ToFelts };
647
+ export { type AccountEnvelope, AuthProvider, BackupSigner, CavosAuth, type CavosAuthOptions, ChainAdapter, ChainCall, ComputeAddressParams, DEVICE_ACCOUNT_CLASS_HASH, DevicePublicKey, DeviceSignature, DeviceSigner, DeviceUnwrapKey, HttpRecoveryClient, type HttpRecoveryClientOptions, HttpWalletRegistry, type HttpWalletRegistryOptions, Identity, type IdentityInput, PasskeyAssertion, PasskeyPrf, type PasskeyPrfEnrollParams, type PasskeyPrfOptions, PendingDeviceRequest, RecoveryClient, RegisteredWallet, STARKNET_NETWORKS, StarknetAdapter, type StarknetAdapterOptions, StarknetDeviceSigner, type StarknetNetwork, StellarAdapter, type StellarAdapterOptions, StellarNetwork, UDC_ADDRESS, WalletRegistry, WebCryptoDeviceUnwrapKey, WebCryptoSigner, type WebCryptoSignerOptions, type WebCryptoUnwrapKeyOptions, bigIntTo32Bytes, bytesToBigInt, bytesToHex, deriveAddressSeed, deriveAddressSeedSolana, deriveAddressSeedStellar, deriveBackupKey, derivePasskeyKEK, deriveRecoveryKEK, deriveStellarAddress, deriveStellarMasterKeypair, eciesUnwrapDEK, eciesWrapDEK, fromDataEntries, generateControlKey, generateDEK, generateRecoveryCode, hexToBytes, openControlSeed, recoverYParity, sealControlSeed, signatureToFelts, toDataEntries, u256ToFelts, unwrapDEK, wrapDEK };