@cavos/kit 0.0.1

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/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # @cavos/kit
2
+
3
+ Device-native, verifiable smart accounts. Users get a deterministic wallet bound
4
+ to their identity, controlled by **silent device signers** — non-extractable
5
+ secp256r1 (P-256) keys that live on the device and sign **invisibly** (no passkey,
6
+ no Face ID / Touch ID, no popups). OAuth / email is used only to derive the
7
+ address, never to sign. No exported keys, no MPC, no on-chain JWT/RSA.
8
+
9
+ **Phase 1: Starknet only.** The API is chain-configurable by design so Stellar
10
+ and Solana adapters slot in behind the same `ChainAdapter` interface later.
11
+
12
+ > New package. Does **not** replace `@cavos/react` / `react-native` (legacy
13
+ > OAuth/session-key SDKs), which continue on the old flow.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ npm install @cavos/kit
19
+ ```
20
+
21
+ ## Concepts
22
+
23
+ | Piece | Role |
24
+ |-------|------|
25
+ | `deriveAddressSeed` | Stable `address_seed` from `{ userId, appSalt }`. Identity → wallet, device-independent. |
26
+ | `StarknetAdapter` | Computes the deterministic address, builds deploy/initialize/add/remove calls, serializes signatures. |
27
+ | `WebCryptoSigner` | Browser silent device signer: non-extractable P-256 key in IndexedDB, no UI on sign. |
28
+ | `StarknetDeviceSigner` | Drop-in starknet.js `SignerInterface` backed by a device signer. |
29
+ | `CavosAccount` | High-level facade tying identity + adapter + signer together. |
30
+ | `RecoveryClient` | Interface to the (non-custodial) backend for the email-approval multi-device flow. |
31
+
32
+ ## Quickstart — high-level (Privy-like)
33
+
34
+ One call logs the user in and returns a ready, deployed, gas-sponsored smart
35
+ account controlled by a silent device key. The user only sees the login.
36
+
37
+ ```ts
38
+ import { Cavos, StaticIdentity, CavosPaymaster } from "@cavos/kit";
39
+
40
+ const cavos = await Cavos.connect({
41
+ network: "sepolia",
42
+ appSalt: "my-app",
43
+ // Identity from your login (Cavos-hosted auth lands here; or pass your own userId)
44
+ auth: new StaticIdentity({ userId: user.id, email: user.email }),
45
+ // Gas sponsor — deploy + execute are gasless
46
+ sponsor: new CavosPaymaster({ network: "sepolia", apiKey: process.env.CAVOS_API_KEY! }),
47
+ });
48
+
49
+ console.log(cavos.address); // deterministic; auto-deployed on first connect
50
+ await cavos.execute(calls); // gasless; signed invisibly by the device key
51
+ ```
52
+
53
+ > **Status:** `Cavos.connect` orchestration (auth → device key → address →
54
+ > auto-deploy → execute) is built. Fully-gasless execution needs the contract to
55
+ > add SNIP-6 `is_valid_signature` + SNIP-9 `execute_from_outside_v2` (tracked
56
+ > follow-up) and the Cavos paymaster to support the new class. The self-funded
57
+ > path below is proven on-chain today.
58
+
59
+ ## Quickstart — low-level (Starknet)
60
+
61
+ ```ts
62
+ import {
63
+ CavosAccount, StarknetAdapter, WebCryptoSigner,
64
+ deriveAddressSeed, DEVICE_ACCOUNT_CLASS_HASH,
65
+ } from "@cavos/kit";
66
+
67
+ // 1. Identity (from your OAuth/email login) derives the address. No device key
68
+ // needed for this — the address depends only on identity + salt.
69
+ const identity = { userId: user.id, appSalt: "my-app" };
70
+ const classHash = DEVICE_ACCOUNT_CLASS_HASH.sepolia; // from deployments/sepolia.json
71
+ const address = new StarknetAdapter({ classHash }).computeAddress({
72
+ addressSeed: deriveAddressSeed(identity),
73
+ });
74
+
75
+ // 2. Create/load the SILENT device key (keyed by the address). No prompt, ever.
76
+ const signer = await WebCryptoSigner.loadOrCreate({ keyId: address });
77
+
78
+ // 3. Build the account.
79
+ const adapter = new StarknetAdapter({ classHash, signer });
80
+ const account = new CavosAccount({ identity, adapter, signer });
81
+ console.log(account.address); // deterministic, pre-deploy
82
+
83
+ // 4. Onboarding: deploy + register first signer (route through your paymaster).
84
+ const calls = await account.buildOnboarding(); // [UDC deploy, initialize] — submit atomically
85
+
86
+ // 5. Add another device later (must be self-submitted by an existing signer).
87
+ const addCall = account.buildAddSigner(otherDevicePublicKey);
88
+
89
+ // 6. Submit transactions through a standard starknet.js Account.
90
+ import { Account, RpcProvider } from "starknet";
91
+ import { StarknetDeviceSigner } from "@cavos/kit";
92
+
93
+ const provider = new RpcProvider({ nodeUrl: "https://api.cartridge.gg/x/starknet/sepolia" });
94
+ const snAccount = new Account(provider, account.address, new StarknetDeviceSigner(signer), "1");
95
+ await snAccount.execute(someCalls); // signed silently; DeviceAccount validates on-chain
96
+ ```
97
+
98
+ `StarknetDeviceSigner` is a drop-in starknet.js `SignerInterface`, so it also
99
+ plugs into paymaster SDKs (AVNU) for gasless flows. The kit does **not** own gas
100
+ sponsorship — route execution through your paymaster of choice.
101
+
102
+ ## How signing works
103
+
104
+ The device key signs `sha256(tx_hash)` with no user interaction (WebCrypto's
105
+ ECDSA hashes the message internally). The signature is serialized as
106
+ `[r_low, r_high, s_low, s_high, y_parity]` — exactly what
107
+ `DeviceAccount.__validate__` decodes. The contract recomputes `sha256(tx_hash)`,
108
+ normalizes high-s, and recovers the secp256r1 signer. This 5-felt encoding is
109
+ covered by a cross-checked contract test (`test_sdk_signature_payload_authorized`
110
+ in `account-contracts/starknet`).
111
+
112
+ **Security model:** the private key is non-extractable (never visible to JS) and
113
+ device-bound — non-custodial, no MPC, verified on-chain. Because signing is
114
+ silent there is no per-signature user-verification gate (unlike a biometric
115
+ passkey); this is the standard embedded-wallet trade-off. Multi-device + the
116
+ non-custodial recovery relay cover device loss.
117
+
118
+ ## Status (Phase 1)
119
+
120
+ - ✅ Silent secp256r1 device signer (`WebCryptoSigner`) + 5-felt signature
121
+ serialization, cross-checked against the live contract.
122
+ - ✅ Deterministic address, deploy/initialize/add/remove call builders.
123
+ - ✅ `starknet.js` `Account` integration via `StarknetDeviceSigner`.
124
+ - ✅ **Proven on-chain (Sepolia):** silent device key signs a real STRK `approve`,
125
+ the deployed DeviceAccount validates it ([tx](https://sepolia.starkscan.co/tx/0x51e0e961ee535bf3c45ea020b9c258aee544ed18aea57dbbc80767f8e86ab9e)).
126
+ - ✅ `Cavos.connect` orchestration: auth → device key → address → auto-deploy → execute.
127
+ - ✅ `CavosPaymaster` client + `Sponsor` interface (Cavos-hosted gasless).
128
+ - ✅ **Gasless proven on-chain (Sepolia):** relayer-paid `execute_from_outside_v2`,
129
+ authorized solely by the silent device signature, executed a real STRK approve
130
+ ([tx](https://sepolia.starkscan.co/tx/0x05ade4008f4ccbcfe4a7f016c61eb0eb591c8f696db3f5dad6f0db3ea3b5d2e6)).
131
+ - ✅ Contract SNIP-6 `is_valid_signature` + SNIP-9 `execute_from_outside_v2` (OZ SRC9 component).
132
+ - ✅ `CavosAuth` (hosted Google/Apple/email/OTP login, mirroring `@cavos/react`).
133
+ - ✅ Recovery client interface (non-custodial multi-device email-approval flow).
134
+ - 🚧 Cavos paymaster backend must register the new class hash (backend, out of repo).
135
+ - 🚧 Recovery backend service + session keys (Phase 2).
136
+
137
+ ## Demo
138
+
139
+ A runnable end-to-end demo lives in `my-app/app/kit-demo` (Next.js): log in
140
+ (identity only), see the deterministic address, create the silent device key,
141
+ build onboarding calls, sign a tx with zero prompts, and walk the non-custodial
142
+ add-device flow. Run `npm run dev` in `my-app` and open `/kit-demo`.
143
+
144
+ ## Develop
145
+
146
+ ```bash
147
+ npm install
148
+ npm run type-check
149
+ npm test # signature <-> contract payload compatibility
150
+ npm run build # tsup -> dist (cjs + esm + d.ts)
151
+ ```