@kasflow/passkey-wallet 0.1.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/README.md ADDED
@@ -0,0 +1,308 @@
1
+ # @kasflow/passkey-wallet
2
+
3
+ Passkey-powered wallet SDK for [Kaspa blockchain](https://kaspa.org). Create and manage Kaspa wallets using device biometrics (Face ID, Touch ID, Windows Hello, etc.) with no seed phrases to remember.
4
+
5
+ ## Features
6
+
7
+ - **Passkey Authentication**: Secure wallet access using WebAuthn/FIDO2 device biometrics
8
+ - **Transaction Support**: Full send/receive functionality with automatic UTXO management
9
+ - **Type-Safe**: Complete TypeScript definitions for all APIs
10
+ - **Network Agnostic**: Works with mainnet and testnet
11
+ - **Modern Browser APIs**: Uses Web Crypto API and IndexedDB for secure key storage
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @kasflow/passkey-wallet
17
+ # or
18
+ pnpm add @kasflow/passkey-wallet
19
+ # or
20
+ yarn add @kasflow/passkey-wallet
21
+ ```
22
+
23
+ That's it - all dependencies are bundled.
24
+
25
+ ## Quick Start
26
+
27
+ ### Create a New Wallet
28
+
29
+ ```typescript
30
+ import { PasskeyWallet } from '@kasflow/passkey-wallet';
31
+
32
+ // Create a new passkey-protected wallet
33
+ const result = await PasskeyWallet.create({
34
+ name: 'My Kaspa Wallet',
35
+ network: 'testnet-11' // or 'mainnet'
36
+ });
37
+
38
+ if (result.success) {
39
+ const wallet = result.data;
40
+ console.log('Wallet Address:', wallet.getAddress());
41
+ } else {
42
+ console.error('Failed to create wallet:', result.error);
43
+ }
44
+ ```
45
+
46
+ ### Unlock an Existing Wallet
47
+
48
+ ```typescript
49
+ import { PasskeyWallet } from '@kasflow/passkey-wallet';
50
+
51
+ // Unlock using biometric authentication
52
+ const result = await PasskeyWallet.unlock();
53
+
54
+ if (result.success) {
55
+ const wallet = result.data;
56
+ console.log('Welcome back! Address:', wallet.getAddress());
57
+ }
58
+ ```
59
+
60
+ ### Connect and Get Balance
61
+
62
+ ```typescript
63
+ // Connect to the Kaspa network
64
+ await wallet.connect();
65
+
66
+ // Get balance (in sompi - smallest unit)
67
+ const balance = await wallet.getBalance();
68
+ console.log('Available:', balance.available);
69
+ console.log('Total:', balance.total);
70
+ ```
71
+
72
+ ### Send KAS
73
+
74
+ ```typescript
75
+ import { kasStringToSompi } from '@kasflow/passkey-wallet';
76
+
77
+ // Recommended: Send with per-transaction biometric authentication
78
+ const result = await wallet.sendWithAuth({
79
+ to: 'kaspatest:qz7ulu4c25dh7fzec9zjyrmlhnkzrg4wmf89q7gzr3gfrsj3uz6xjceef60sd',
80
+ amount: kasStringToSompi('1.5'), // Converts "1.5" to sompi
81
+ });
82
+
83
+ console.log('Transaction ID:', result.transactionId);
84
+ console.log('Fee paid:', result.fee);
85
+
86
+ // Alternative: Send without additional authentication (uses session keys)
87
+ const result2 = await wallet.send({
88
+ to: 'kaspatest:qz...',
89
+ amount: kasStringToSompi('1.0'),
90
+ });
91
+ ```
92
+
93
+ ### Sign Messages
94
+
95
+ ```typescript
96
+ // Sign a message with the wallet's private key
97
+ const signature = wallet.signMessage('Hello Kaspa!');
98
+ console.log('Signature:', signature);
99
+ ```
100
+
101
+ ## API Reference
102
+
103
+ ### PasskeyWallet Class
104
+
105
+ #### Static Methods
106
+
107
+ | Method | Description |
108
+ |--------|-------------|
109
+ | `PasskeyWallet.isSupported()` | Check if passkeys are supported in this browser |
110
+ | `PasskeyWallet.exists()` | Check if a wallet already exists in storage |
111
+ | `PasskeyWallet.create(options)` | Create a new passkey-protected wallet |
112
+ | `PasskeyWallet.unlock(options)` | Unlock an existing wallet with biometrics |
113
+ | `PasskeyWallet.delete()` | Delete the wallet from storage (irreversible!) |
114
+
115
+ #### Instance Methods
116
+
117
+ | Method | Description |
118
+ |--------|-------------|
119
+ | `wallet.getAddress()` | Get the wallet's Kaspa address |
120
+ | `wallet.getPublicKey()` | Get the public key as hex string |
121
+ | `wallet.getNetwork()` | Get the current network ID |
122
+ | `wallet.connect(options?)` | Connect to the Kaspa network |
123
+ | `wallet.disconnectNetwork()` | Disconnect from the network |
124
+ | `wallet.getBalance()` | Get wallet balance (requires connection) |
125
+ | `wallet.send(options)` | Send KAS to an address |
126
+ | `wallet.sendWithAuth(options)` | Send with per-transaction biometric auth (recommended) |
127
+ | `wallet.estimateFee(options)` | Estimate transaction fee |
128
+ | `wallet.signMessage(message)` | Sign a message |
129
+ | `wallet.on(handler)` | Subscribe to wallet events |
130
+ | `wallet.disconnect()` | Disconnect wallet and clear keys from memory |
131
+
132
+ ### Unit Conversion
133
+
134
+ ```typescript
135
+ import {
136
+ kasStringToSompi, // "1.5" => 150000000n
137
+ sompiToKasString, // 150000000n => "1.5"
138
+ sompiToKas, // 150000000n => 1.5 (number)
139
+ kasToSompi, // 1.5 => 150000000n
140
+ formatKas, // 150000000n => "1.5" (formatted)
141
+ SOMPI_PER_KAS, // 100_000_000n
142
+ } from '@kasflow/passkey-wallet';
143
+ ```
144
+
145
+ ### Address Validation
146
+
147
+ ```typescript
148
+ import {
149
+ isValidAddress,
150
+ parseAddress,
151
+ getNetworkFromAddress,
152
+ } from '@kasflow/passkey-wallet';
153
+
154
+ // Validate an address
155
+ if (isValidAddress('kaspa:qz...')) {
156
+ console.log('Valid address!');
157
+ }
158
+
159
+ // Parse address components
160
+ const parsed = parseAddress('kaspa:qz...');
161
+ console.log(parsed.prefix); // 'kaspa'
162
+ console.log(parsed.payload); // Uint8Array
163
+
164
+ // Get network from address
165
+ const network = getNetworkFromAddress('kaspatest:qz...');
166
+ console.log(network); // 'testnet-11'
167
+ ```
168
+
169
+ ### Events
170
+
171
+ ```typescript
172
+ // Subscribe to wallet events
173
+ const unsubscribe = wallet.on((event) => {
174
+ switch (event.type) {
175
+ case 'connected':
176
+ console.log('Connected:', event.address);
177
+ break;
178
+ case 'disconnected':
179
+ console.log('Disconnected');
180
+ break;
181
+ case 'balance_updated':
182
+ console.log('Balance:', event.balance);
183
+ break;
184
+ case 'transaction_sent':
185
+ console.log('TX sent:', event.txId);
186
+ break;
187
+ }
188
+ });
189
+
190
+ // Later: unsubscribe
191
+ unsubscribe();
192
+ ```
193
+
194
+ ## Advanced Usage
195
+
196
+ ### Direct RPC Access
197
+
198
+ ```typescript
199
+ import { KaspaRpc } from '@kasflow/passkey-wallet';
200
+
201
+ const rpc = new KaspaRpc();
202
+ await rpc.connect({ network: 'testnet-11' });
203
+
204
+ // Get network info
205
+ const info = await rpc.getNetworkInfo();
206
+ console.log('Block count:', info.blockCount);
207
+
208
+ // Get UTXOs for any address
209
+ const utxos = await rpc.getUtxos('kaspatest:qz...');
210
+ ```
211
+
212
+ ### Transaction Building
213
+
214
+ ```typescript
215
+ import {
216
+ buildTransactions,
217
+ signTransactions,
218
+ submitTransactions
219
+ } from '@kasflow/passkey-wallet';
220
+
221
+ // Build transactions manually
222
+ const { transactions, summary } = await buildTransactions(
223
+ utxos,
224
+ [{ address: 'kaspatest:qz...', amount: 100000000n }],
225
+ changeAddress,
226
+ 100000n, // priority fee
227
+ 'testnet-11'
228
+ );
229
+
230
+ // Sign them
231
+ const signed = signTransactions(transactions, privateKeyHex);
232
+
233
+ // Submit
234
+ const txIds = await submitTransactions(signed, rpc);
235
+ ```
236
+
237
+ ### WASM SDK Access
238
+
239
+ ```typescript
240
+ import {
241
+ RpcClient,
242
+ Resolver,
243
+ Generator,
244
+ PrivateKey
245
+ } from '@kasflow/passkey-wallet';
246
+
247
+ // Direct access to kaspa-wasm32-sdk types
248
+ const privateKey = new PrivateKey('...');
249
+ const address = privateKey.toAddress('testnet-11');
250
+ ```
251
+
252
+ ## Network Configuration
253
+
254
+ | Network | ID | Address Prefix |
255
+ |---------|-----|----------------|
256
+ | Mainnet | `mainnet` | `kaspa:` |
257
+ | Testnet 10 | `testnet-10` | `kaspatest:` |
258
+ | Testnet 11 | `testnet-11` | `kaspatest:` |
259
+
260
+ ```typescript
261
+ import { NETWORK_ID, DEFAULT_NETWORK } from '@kasflow/passkey-wallet';
262
+
263
+ console.log(NETWORK_ID.MAINNET); // 'mainnet'
264
+ console.log(NETWORK_ID.TESTNET_11); // 'testnet-11'
265
+ console.log(DEFAULT_NETWORK); // 'testnet-11'
266
+ ```
267
+
268
+ ## Security
269
+
270
+ ### How It Works
271
+
272
+ 1. **Passkey Registration**: A WebAuthn credential is created and tied to device biometrics
273
+ 2. **Deterministic Derivation**: Kaspa keys are derived from the passkey's public key using SHA-256
274
+ 3. **No Key Storage**: Private keys are never stored - they're re-derived on each unlock
275
+ 4. **Multi-Device Sync**: Same wallet on any device where the passkey syncs (iCloud Keychain, Google Password Manager)
276
+
277
+ ### Security Considerations
278
+
279
+ - No seed phrases or passwords - authentication is biometric only
280
+ - Private keys exist only in memory during operations, never persisted
281
+ - Keys are deterministically derived, so the same passkey always produces the same wallet
282
+ - All cryptographic operations happen locally in the browser
283
+
284
+ ### Browser Requirements
285
+
286
+ - WebAuthn support (all modern browsers)
287
+ - Platform authenticator (Touch ID, Face ID, Windows Hello, etc.)
288
+ - Secure context (HTTPS or localhost)
289
+
290
+ ## Development
291
+
292
+ ```bash
293
+ # Install dependencies
294
+ pnpm install
295
+
296
+ # Type check
297
+ pnpm typecheck
298
+
299
+ # Run tests
300
+ pnpm test
301
+
302
+ # Build
303
+ pnpm build
304
+ ```
305
+
306
+ ## License
307
+
308
+ MIT