Skip to content

Testing with @stellar-passkey/core

The kit ships a mock-mode adapter so downstream adopters can unit- test code that consumes the SDK without standing up a Soroban RPC, deploying a real wallet contract, or driving navigator.credentials.* through a virtual authenticator.

ts
import { createMockKit } from "@stellar-passkey/core";

const kit = createMockKit({ rpId: "your-app.example" });

// 1) Register a synthetic passkey. The seed is deterministic — same
//    seed → same P-256 keypair → same mock contract id.
const { contractId, credential } = await kit.createPasskey({
  seed: new Uint8Array(32).fill(7),
  userName: "alice",
});

// 2) Sign an unsigned Soroban tx envelope. The mock kit uses the same
//    `signTransaction` from the live SDK — only the WebAuthn signer is
//    replaced with a synthetic P-256 ECDSA over the auth-entry
//    preimage. The on-chain `__check_auth` verifier sees a
//    byte-identical Signature ScVal to a real Touch ID ceremony.
const { signedTxXdr, signerAddress } = await kit.signTransaction(
  unsignedXdr,
  { contractId, credentialId: credential.id, latestLedger: 1_000_000 },
);

// 3) Recover every session held in memory.
const sessions = await kit.recoverPasskey();

What's mocked

  • navigator.credentials.create / navigator.credentials.get — the mock kit never touches the WebAuthn API. The synthetic signer derives a P-256 keypair from a seed via @noble/curves.
  • Soroban RPC — connectPasskey / recoverPasskey resolve from the in-memory map; there is zero outbound network I/O.
  • DeployerCallbackscreatePasskey does not call out to a deployer. A mock C-address is derived deterministically from the public key.

What's not mocked

  • The auth-entry signing pipeline — DER ↔ raw conversion, low-S normalisation, the Signature ScVal layout — uses the live signTransaction / signAuthEntry from ./sign.ts. Bugs in that path show up identically in mock-mode tests and on testnet.
  • Apple's high-S quirk. Virtual authenticators (including this mock signer) use deterministic nonces and never emit high-S. To exercise the normalizeLowS path, use the pinned fixtures in tests/fixtures/apple-high-s/ (YK-274).

Gate

The mock kit's unit test (packages/core/src/mock.test.ts) asserts:

  1. createPasskeysignTransactionrecoverPasskey round-trips without throwing.
  2. globalThis.fetch is never called (the test patches it with a throwing spy).
  3. Two calls to createPasskey with the same seed produce the same contract id (determinism).

The full pnpm -F @stellar-passkey/core test run including the mock tests completes in ≤ 500ms on a modern laptop — well under the 2-second YK-269 ceiling.

When to reach for the live kit instead

Use the live kit (the package's default barrel exports) for:

  • Integration tests that need a real __check_auth round-trip — see the YK-266 fixture-tx path in apps/demo for the canonical setup.
  • Anything that exercises DeployerCallbacks (the real network surface lives on the consumer's side of that seam).
  • Browser-side smoke / Playwright tests with a CDP virtual authenticator — apps/smoke and apps/demo's default tab show the pattern.

MIT — SCF-43 RFP submission (2026). Status: pre-1.0.