Skip to content

STRK20 private transfers inside the vault - #45

Merged
adrianvrj merged 4 commits into
mainfrom
feat/strk20-privacy
Oct 20, 2026
Merged

adrianvrj merged 4 commits into
mainfrom
feat/strk20-privacy

Conversation

@adrianvrj

@adrianvrj adrianvrj commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

STRK20 private transfers for Starknet wallets, run inside the Cavos vault.

  • SNIP-44 viewing key (account-leaf-v1) derived from the account's stark key, verified against the spec's normative vectors and 2,000 random cross-checks with Starkzap's implementation.
  • Inside the vault only. The viewing key, notes and witnesses never cross the postMessage boundary (SNIP-44 "Wallet and dapp boundary"). The page never chooses the pool, prover or discovery service: they come from the app's Cavos settings (privacy in /api/vault/policy, keyed sepolia / mainnet).
  • Before every operation the vault reads get_public_key(account) from the pool and refuses if a different key is registered. It never registers a replacement.
  • Submission goes through the paymaster privacy relay (apply_action / invoke_and_apply_action), so the user's account never appears on-chain. Quotes are refused when the fee recipient is not allowed, when the fee exceeds maxFee or the pool's own fee, or when the approval typed data is tampered with.
  • Spends go through the existing vault policy. Deposit, transfer and withdraw ask for confirmation according to the app's limits; unknown tokens are flagged.
  • Page API: CavosStarknet.privacy.{status, balance, register, deposit, transfer, withdraw}.
  • starknet bumped to ^10.5.0. v10 hashes proofFacts into the invoke hash, which proof-carrying transactions need. No other code changed for the bump.
  • Dependency: @starkware-libs/starknet-privacy-sdk is an optional peer dependency, loaded with a dynamic import. It is bundled into the vault IIFE.
    • It is published on GitHub Packages, so .npmrc maps the scope and CI authenticates with GITHUB_TOKEN (packages: read).
    • The vault host bundle grows to about 1.2 MB.

Test plan

  • npx tsc --noEmit
  • npx jest: 447 passed, 2 skipped. Coverage:
    • register → deposit → transfer → balance → withdraw end to end on the SDK's in-memory pool, directly and through the real VaultClient over a MessageChannel;
    • nothing secret crosses the channel (the viewing key and account key are checked in hex, decimal and padded form);
    • relay quote and typed-data tampering is refused;
    • the vault asks for confirmation according to policy.
  • npm run build.
  • Signing on Sepolia through Starkzap with the vault signer, before the privacy work: address equality, paymaster deploy, and a sponsored transfer (0x274c8256…c8296f, SUCCEEDED).
  • A private transfer against the real pool. Pending: the paymaster with privacy support needs to be deployed, along with the cavos-web settings.

Related

  • cavos-labs/paymaster: upstream private transactions plus GasTank charging.
  • cavos-labs/cavos: per-app privacy settings and webhook.

Release

Merging publishes @cavos/kit@0.4.3.

Note for integrators: starknet.js v10's Account no longer extends Provider. Call provider methods through wallet.account.provider.* rather than on wallet.account directly.

Apps that keep the key in the page and want privacy pass privacySdk: () => import("@starkware-libs/starknet-privacy-sdk") together with privacy. The npm entries never import the SDK, so apps that do not use privacy build without it.

SNIP-44 viewing key derived and kept in the vault, the privacy SDK driven there, private operations relayed through the paymaster with policy confirmation, and CavosStarknet.privacy on the page. Moves starknet to ^10.5.0 for proof-carrying transactions.
Bundlers resolve a literal dynamic import even when it is never reached, so every app on @cavos/kit failed to build without the optional SDK installed. The vault script now injects the loader, and page-held keys pass privacySdk with their privacy settings.
@adrianvrj
adrianvrj merged commit 64eadcf into main Oct 20, 2026
2 checks passed
@adrianvrj
adrianvrj deleted the feat/strk20-privacy branch October 20, 2026 15:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant