kentucky-signer-viem 0.1.1 → 0.1.3
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 +195 -218
- package/dist/index.d.mts +802 -7
- package/dist/index.d.ts +802 -7
- package/dist/index.js +964 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +955 -37
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.d.mts +61 -3
- package/dist/react/index.d.ts +61 -3
- package/dist/react/index.js +1286 -173
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +1288 -174
- package/dist/react/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/account.ts +111 -22
- package/src/auth.ts +16 -6
- package/src/client.ts +438 -18
- package/src/ephemeral.ts +407 -0
- package/src/index.ts +56 -0
- package/src/react/context.tsx +360 -45
- package/src/react/hooks.ts +11 -0
- package/src/react/index.ts +1 -0
- package/src/secure-client.ts +417 -0
- package/src/types.ts +332 -0
package/README.md
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
# kentucky-signer-viem
|
|
2
2
|
|
|
3
|
-
A custom Viem account integration for the Kentucky Signer service, enabling EVM transaction signing using passkey (WebAuthn) or password authentication.
|
|
3
|
+
A custom Viem account integration for the Kentucky Signer service, enabling EVM transaction signing using passkey (WebAuthn) or password authentication with optional two-factor authentication (TOTP/PIN).
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- Custom Viem
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
7
|
+
- **Custom Viem Account** - Full Viem compatibility for signing transactions, messages, and typed data
|
|
8
|
+
- **Multiple Authentication Methods**
|
|
9
|
+
- Passkey (WebAuthn) for browser environments
|
|
10
|
+
- Password authentication for browser and Node.js
|
|
11
|
+
- JWT token authentication for server environments
|
|
12
|
+
- **Secure Mode** - Ephemeral key signing with client-side key generation
|
|
13
|
+
- **Two-Factor Authentication** - TOTP (authenticator app) and PIN support
|
|
14
|
+
- **Guardian Recovery** - Social recovery with trusted guardians
|
|
15
|
+
- **React Integration** - Hooks and context for easy React app integration
|
|
16
|
+
- **TypeScript Support** - Full type definitions included
|
|
17
|
+
- **Session Management** - Automatic refresh and persistence options
|
|
15
18
|
|
|
16
19
|
## Installation
|
|
17
20
|
|
|
@@ -63,67 +66,36 @@ const hash = await walletClient.sendTransaction({
|
|
|
63
66
|
to: '0x...',
|
|
64
67
|
value: parseEther('0.1'),
|
|
65
68
|
})
|
|
66
|
-
console.log('Transaction hash:', hash)
|
|
67
69
|
```
|
|
68
70
|
|
|
69
|
-
### Password Authentication
|
|
71
|
+
### Password Authentication
|
|
70
72
|
|
|
71
73
|
```typescript
|
|
72
|
-
import { createWalletClient, http, parseEther } from 'viem'
|
|
73
|
-
import { mainnet } from 'viem/chains'
|
|
74
74
|
import {
|
|
75
|
-
createKentuckySignerAccount,
|
|
76
75
|
authenticateWithPassword,
|
|
77
76
|
createAccountWithPassword,
|
|
78
77
|
} from 'kentucky-signer-viem'
|
|
79
78
|
|
|
80
|
-
//
|
|
79
|
+
// Create a new account
|
|
81
80
|
const newAccount = await createAccountWithPassword({
|
|
82
81
|
baseUrl: 'https://signer.example.com',
|
|
83
82
|
password: 'your-secure-password',
|
|
84
83
|
confirmation: 'your-secure-password',
|
|
85
84
|
})
|
|
86
|
-
console.log('Account ID:', newAccount.account_id)
|
|
87
|
-
console.log('EVM Address:', newAccount.addresses.evm)
|
|
88
85
|
|
|
89
|
-
//
|
|
86
|
+
// Or authenticate with existing account
|
|
90
87
|
const session = await authenticateWithPassword({
|
|
91
88
|
baseUrl: 'https://signer.example.com',
|
|
92
|
-
accountId:
|
|
89
|
+
accountId: 'existing_account_id',
|
|
93
90
|
password: 'your-secure-password',
|
|
94
91
|
})
|
|
95
|
-
|
|
96
|
-
// Create Kentucky Signer account
|
|
97
|
-
const account = createKentuckySignerAccount({
|
|
98
|
-
config: {
|
|
99
|
-
baseUrl: 'https://signer.example.com',
|
|
100
|
-
accountId: session.accountId,
|
|
101
|
-
},
|
|
102
|
-
session,
|
|
103
|
-
defaultChainId: 1,
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
// Use with Viem
|
|
107
|
-
const walletClient = createWalletClient({
|
|
108
|
-
account,
|
|
109
|
-
chain: mainnet,
|
|
110
|
-
transport: http('https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY'),
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
const hash = await walletClient.sendTransaction({
|
|
114
|
-
to: '0x...',
|
|
115
|
-
value: parseEther('0.1'),
|
|
116
|
-
})
|
|
117
92
|
```
|
|
118
93
|
|
|
119
94
|
### Node.js (with JWT Token)
|
|
120
95
|
|
|
121
96
|
```typescript
|
|
122
|
-
import { createWalletClient, http, parseEther } from 'viem'
|
|
123
|
-
import { mainnet } from 'viem/chains'
|
|
124
97
|
import { createServerAccount } from 'kentucky-signer-viem'
|
|
125
98
|
|
|
126
|
-
// Create account with existing JWT token
|
|
127
99
|
const account = createServerAccount(
|
|
128
100
|
'https://signer.example.com',
|
|
129
101
|
'account_id_hex',
|
|
@@ -131,18 +103,6 @@ const account = createServerAccount(
|
|
|
131
103
|
'0xYourEvmAddress',
|
|
132
104
|
1 // chainId
|
|
133
105
|
)
|
|
134
|
-
|
|
135
|
-
// Use with Viem
|
|
136
|
-
const walletClient = createWalletClient({
|
|
137
|
-
account,
|
|
138
|
-
chain: mainnet,
|
|
139
|
-
transport: http('https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY'),
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
const hash = await walletClient.sendTransaction({
|
|
143
|
-
to: '0x...',
|
|
144
|
-
value: parseEther('0.1'),
|
|
145
|
-
})
|
|
146
106
|
```
|
|
147
107
|
|
|
148
108
|
## React Integration
|
|
@@ -158,6 +118,7 @@ function App() {
|
|
|
158
118
|
baseUrl="https://signer.example.com"
|
|
159
119
|
defaultChainId={1}
|
|
160
120
|
persistSession={true}
|
|
121
|
+
useEphemeralKeys={true} // Enable secure mode
|
|
161
122
|
>
|
|
162
123
|
<YourApp />
|
|
163
124
|
</KentuckySignerProvider>
|
|
@@ -168,29 +129,24 @@ function App() {
|
|
|
168
129
|
### Authentication Hook
|
|
169
130
|
|
|
170
131
|
```tsx
|
|
171
|
-
import { useKentuckySigner
|
|
132
|
+
import { useKentuckySigner } from 'kentucky-signer-viem/react'
|
|
172
133
|
|
|
173
134
|
function LoginButton() {
|
|
174
|
-
const { isAuthenticated, account } = useKentuckySigner()
|
|
175
|
-
const { login, isLoading, error } = usePasskeyAuth()
|
|
176
|
-
const [accountId, setAccountId] = useState('')
|
|
135
|
+
const { isAuthenticated, account, authenticate, logout } = useKentuckySigner()
|
|
177
136
|
|
|
178
137
|
if (isAuthenticated && account) {
|
|
179
|
-
return
|
|
138
|
+
return (
|
|
139
|
+
<div>
|
|
140
|
+
<span>Connected: {account.address}</span>
|
|
141
|
+
<button onClick={logout}>Logout</button>
|
|
142
|
+
</div>
|
|
143
|
+
)
|
|
180
144
|
}
|
|
181
145
|
|
|
182
146
|
return (
|
|
183
|
-
<
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
value={accountId}
|
|
187
|
-
onChange={(e) => setAccountId(e.target.value)}
|
|
188
|
-
/>
|
|
189
|
-
<button onClick={() => login(accountId)} disabled={isLoading}>
|
|
190
|
-
{isLoading ? 'Authenticating...' : 'Login with Passkey'}
|
|
191
|
-
</button>
|
|
192
|
-
{error && <div className="error">{error.message}</div>}
|
|
193
|
-
</div>
|
|
147
|
+
<button onClick={() => authenticate('account_id')}>
|
|
148
|
+
Login with Passkey
|
|
149
|
+
</button>
|
|
194
150
|
)
|
|
195
151
|
}
|
|
196
152
|
```
|
|
@@ -200,159 +156,166 @@ function LoginButton() {
|
|
|
200
156
|
```tsx
|
|
201
157
|
import { useWalletClient, useIsReady } from 'kentucky-signer-viem/react'
|
|
202
158
|
import { mainnet } from 'viem/chains'
|
|
203
|
-
import { parseEther } from 'viem'
|
|
204
159
|
|
|
205
160
|
function SendTransaction() {
|
|
206
161
|
const isReady = useIsReady()
|
|
207
|
-
const walletClient = useWalletClient({
|
|
208
|
-
chain: mainnet,
|
|
209
|
-
rpcUrl: 'https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY',
|
|
210
|
-
})
|
|
162
|
+
const walletClient = useWalletClient({ chain: mainnet })
|
|
211
163
|
|
|
212
164
|
async function send() {
|
|
213
165
|
if (!walletClient) return
|
|
214
|
-
|
|
215
166
|
const hash = await walletClient.sendTransaction({
|
|
216
167
|
to: '0x...',
|
|
217
168
|
value: parseEther('0.1'),
|
|
218
169
|
})
|
|
219
|
-
console.log('Transaction hash:', hash)
|
|
220
170
|
}
|
|
221
171
|
|
|
222
|
-
return
|
|
223
|
-
<button onClick={send} disabled={!isReady}>
|
|
224
|
-
Send 0.1 ETH
|
|
225
|
-
</button>
|
|
226
|
-
)
|
|
172
|
+
return <button onClick={send} disabled={!isReady}>Send</button>
|
|
227
173
|
}
|
|
228
174
|
```
|
|
229
175
|
|
|
230
|
-
|
|
176
|
+
## Secure Mode (Ephemeral Keys)
|
|
231
177
|
|
|
232
|
-
|
|
233
|
-
import { useSignMessage } from 'kentucky-signer-viem/react'
|
|
234
|
-
|
|
235
|
-
function SignMessageDemo() {
|
|
236
|
-
const { signMessage, isLoading, isAvailable } = useSignMessage()
|
|
237
|
-
const [signature, setSignature] = useState('')
|
|
238
|
-
|
|
239
|
-
async function sign() {
|
|
240
|
-
const sig = await signMessage('Hello, Kentucky Signer!')
|
|
241
|
-
setSignature(sig)
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
return (
|
|
245
|
-
<div>
|
|
246
|
-
<button onClick={sign} disabled={isLoading || !isAvailable}>
|
|
247
|
-
{isLoading ? 'Signing...' : 'Sign Message'}
|
|
248
|
-
</button>
|
|
249
|
-
{signature && <pre>{signature}</pre>}
|
|
250
|
-
</div>
|
|
251
|
-
)
|
|
252
|
-
}
|
|
253
|
-
```
|
|
178
|
+
Secure mode adds an extra layer of security by requiring client-side ephemeral key signatures for all operations:
|
|
254
179
|
|
|
255
|
-
|
|
180
|
+
```typescript
|
|
181
|
+
import { SecureKentuckySignerClient, EphemeralKeyManager } from 'kentucky-signer-viem'
|
|
256
182
|
|
|
257
|
-
|
|
183
|
+
// Create ephemeral key manager
|
|
184
|
+
const keyManager = new EphemeralKeyManager()
|
|
258
185
|
|
|
259
|
-
|
|
186
|
+
// Create secure client
|
|
187
|
+
const secureClient = new SecureKentuckySignerClient({
|
|
188
|
+
baseUrl: 'https://signer.example.com',
|
|
189
|
+
ephemeralKeyManager: keyManager,
|
|
190
|
+
})
|
|
260
191
|
|
|
261
|
-
|
|
192
|
+
// Authenticate with ephemeral key binding
|
|
193
|
+
const session = await authenticateWithPasskey({
|
|
194
|
+
baseUrl: 'https://signer.example.com',
|
|
195
|
+
accountId: 'account_id',
|
|
196
|
+
ephemeralPublicKey: await keyManager.getPublicKey(),
|
|
197
|
+
})
|
|
262
198
|
|
|
263
|
-
|
|
199
|
+
// Create account with secure client
|
|
264
200
|
const account = createKentuckySignerAccount({
|
|
265
|
-
config: {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
},
|
|
269
|
-
session: AuthSession, // Authenticated session
|
|
270
|
-
defaultChainId?: number, // Default chain ID (default: 1)
|
|
271
|
-
onSessionExpired?: () => Promise<AuthSession>, // Session refresh callback
|
|
201
|
+
config: { baseUrl, accountId },
|
|
202
|
+
session,
|
|
203
|
+
secureClient, // Uses ephemeral key signing
|
|
272
204
|
})
|
|
273
205
|
```
|
|
274
206
|
|
|
275
|
-
|
|
207
|
+
## Two-Factor Authentication
|
|
276
208
|
|
|
277
|
-
|
|
209
|
+
### Setup TOTP (Authenticator App)
|
|
278
210
|
|
|
279
211
|
```typescript
|
|
280
|
-
|
|
281
|
-
baseUrl: string, // Kentucky Signer API URL
|
|
282
|
-
accountId: string, // Account ID to authenticate
|
|
283
|
-
rpId?: string, // WebAuthn Relying Party ID
|
|
284
|
-
allowCredentials?: string[], // Allowed credential IDs
|
|
285
|
-
})
|
|
286
|
-
```
|
|
212
|
+
import { KentuckySignerClient } from 'kentucky-signer-viem'
|
|
287
213
|
|
|
288
|
-
|
|
214
|
+
const client = new KentuckySignerClient({ baseUrl })
|
|
289
215
|
|
|
290
|
-
|
|
216
|
+
// Start TOTP setup - returns QR code URI
|
|
217
|
+
const setup = await client.setupTOTP(token)
|
|
218
|
+
console.log('Scan this QR code:', setup.uri)
|
|
219
|
+
console.log('Or enter manually:', setup.secret)
|
|
291
220
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
baseUrl: string, // Kentucky Signer API URL
|
|
295
|
-
accountId: string, // Account ID to authenticate
|
|
296
|
-
password: string, // Account password
|
|
297
|
-
})
|
|
298
|
-
```
|
|
221
|
+
// Enable TOTP with verification code
|
|
222
|
+
await client.enableTOTP('123456', token)
|
|
299
223
|
|
|
300
|
-
|
|
224
|
+
// Check 2FA status
|
|
225
|
+
const status = await client.get2FAStatus(token)
|
|
226
|
+
// { totp_enabled: true, pin_enabled: false, pin_length: 0 }
|
|
227
|
+
```
|
|
301
228
|
|
|
302
|
-
|
|
229
|
+
### Setup PIN
|
|
303
230
|
|
|
304
231
|
```typescript
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
// Returns: { account_id, addresses: { evm, bitcoin, solana } }
|
|
232
|
+
// Setup 4 or 6 digit PIN
|
|
233
|
+
await client.setupPIN('123456', token)
|
|
234
|
+
|
|
235
|
+
// Disable PIN (requires current PIN)
|
|
236
|
+
await client.disablePIN('123456', token)
|
|
311
237
|
```
|
|
312
238
|
|
|
313
|
-
|
|
239
|
+
### Signing with 2FA
|
|
314
240
|
|
|
315
|
-
|
|
241
|
+
When 2FA is enabled, signing operations will automatically prompt for codes:
|
|
316
242
|
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
243
|
+
```tsx
|
|
244
|
+
import { useKentuckySigner } from 'kentucky-signer-viem/react'
|
|
245
|
+
|
|
246
|
+
function App() {
|
|
247
|
+
const { twoFactorPrompt, submit2FA, cancel2FA } = useKentuckySigner()
|
|
248
|
+
|
|
249
|
+
// The 2FA prompt appears automatically when signing requires it
|
|
250
|
+
if (twoFactorPrompt.isVisible) {
|
|
251
|
+
return (
|
|
252
|
+
<TwoFactorModal
|
|
253
|
+
totpRequired={twoFactorPrompt.totpRequired}
|
|
254
|
+
pinRequired={twoFactorPrompt.pinRequired}
|
|
255
|
+
pinLength={twoFactorPrompt.pinLength}
|
|
256
|
+
onSubmit={(codes) => submit2FA(codes)}
|
|
257
|
+
onCancel={() => cancel2FA()}
|
|
258
|
+
/>
|
|
259
|
+
)
|
|
260
|
+
}
|
|
325
261
|
|
|
326
|
-
|
|
262
|
+
return <YourApp />
|
|
263
|
+
}
|
|
264
|
+
```
|
|
327
265
|
|
|
328
|
-
|
|
266
|
+
## Guardian Recovery
|
|
329
267
|
|
|
330
|
-
|
|
268
|
+
Set up trusted guardians for account recovery:
|
|
331
269
|
|
|
332
270
|
```typescript
|
|
333
|
-
const client = new KentuckySignerClient({ baseUrl
|
|
271
|
+
const client = new KentuckySignerClient({ baseUrl })
|
|
334
272
|
|
|
335
|
-
//
|
|
336
|
-
|
|
273
|
+
// Add a guardian
|
|
274
|
+
await client.addGuardian(accountId, {
|
|
275
|
+
guardian_account_id: 'guardian_hex_id',
|
|
276
|
+
label: 'My Friend',
|
|
277
|
+
}, token)
|
|
337
278
|
|
|
338
|
-
//
|
|
339
|
-
const
|
|
279
|
+
// List guardians
|
|
280
|
+
const { guardians } = await client.getGuardians(accountId, token)
|
|
340
281
|
|
|
341
|
-
//
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
)
|
|
282
|
+
// Initiate recovery (when locked out)
|
|
283
|
+
const recovery = await client.initiateRecovery({
|
|
284
|
+
account_id: accountId,
|
|
285
|
+
new_password: 'new-secure-password',
|
|
286
|
+
})
|
|
346
287
|
|
|
347
|
-
//
|
|
348
|
-
|
|
288
|
+
// Guardian approves recovery
|
|
289
|
+
await client.verifyGuardianRecovery({
|
|
290
|
+
recovery_id: recovery.recovery_id,
|
|
291
|
+
guardian_account_id: guardianId,
|
|
292
|
+
signature: guardianSignature,
|
|
293
|
+
}, guardianToken)
|
|
294
|
+
|
|
295
|
+
// Complete recovery after threshold met
|
|
296
|
+
await client.completeRecovery({
|
|
297
|
+
recovery_id: recovery.recovery_id,
|
|
298
|
+
}, token)
|
|
349
299
|
```
|
|
350
300
|
|
|
301
|
+
## API Reference
|
|
302
|
+
|
|
303
|
+
### Core Functions
|
|
304
|
+
|
|
305
|
+
| Function | Description |
|
|
306
|
+
|----------|-------------|
|
|
307
|
+
| `createKentuckySignerAccount(options)` | Create a Viem-compatible account |
|
|
308
|
+
| `createServerAccount(...)` | Create account with JWT token (Node.js) |
|
|
309
|
+
| `authenticateWithPasskey(options)` | Authenticate using WebAuthn |
|
|
310
|
+
| `authenticateWithPassword(options)` | Authenticate using password |
|
|
311
|
+
| `createAccountWithPassword(options)` | Create new account with password |
|
|
312
|
+
| `authenticateWithToken(...)` | Create session from JWT token |
|
|
313
|
+
|
|
351
314
|
### React Hooks
|
|
352
315
|
|
|
353
316
|
| Hook | Description |
|
|
354
317
|
|------|-------------|
|
|
355
|
-
| `useKentuckySigner()` | Access auth state and
|
|
318
|
+
| `useKentuckySigner()` | Access auth state, actions, and 2FA |
|
|
356
319
|
| `useKentuckySignerAccount()` | Get the current account |
|
|
357
320
|
| `useWalletClient(options)` | Create a Viem WalletClient |
|
|
358
321
|
| `usePasskeyAuth()` | Authentication flow with loading state |
|
|
@@ -361,42 +324,39 @@ const info = await client.getAccountInfo(accountId, jwtToken)
|
|
|
361
324
|
| `useIsReady()` | Check if signer is ready |
|
|
362
325
|
| `useAddress()` | Get connected address |
|
|
363
326
|
|
|
364
|
-
###
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
-
|
|
387
|
-
-
|
|
388
|
-
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
},
|
|
398
|
-
})
|
|
399
|
-
```
|
|
327
|
+
### Client Methods
|
|
328
|
+
|
|
329
|
+
#### Authentication
|
|
330
|
+
- `getChallenge(accountId)` - Get WebAuthn challenge
|
|
331
|
+
- `authenticatePasskey(accountId, credential)` - Authenticate with passkey
|
|
332
|
+
- `authenticatePassword(accountId, password)` - Authenticate with password
|
|
333
|
+
- `logout(token)` - Invalidate session
|
|
334
|
+
|
|
335
|
+
#### Signing
|
|
336
|
+
- `signEvmTransaction(request, token)` - Sign EVM transaction hash
|
|
337
|
+
- `signEvmTransactionWith2FA(request, token)` - Sign with 2FA codes
|
|
338
|
+
|
|
339
|
+
#### Account Management
|
|
340
|
+
- `getAccountInfo(accountId, token)` - Get account info
|
|
341
|
+
- `addPassword(accountId, request, token)` - Add password auth
|
|
342
|
+
- `addPasskey(accountId, request, token)` - Add passkey
|
|
343
|
+
- `removePasskey(accountId, credentialId, token)` - Remove passkey
|
|
344
|
+
|
|
345
|
+
#### Two-Factor Authentication
|
|
346
|
+
- `get2FAStatus(token)` - Get 2FA status
|
|
347
|
+
- `setupTOTP(token)` - Start TOTP setup
|
|
348
|
+
- `enableTOTP(code, token)` - Enable TOTP
|
|
349
|
+
- `disableTOTP(code, token)` - Disable TOTP
|
|
350
|
+
- `setupPIN(pin, token)` - Setup PIN
|
|
351
|
+
- `disablePIN(pin, token)` - Disable PIN
|
|
352
|
+
|
|
353
|
+
#### Guardian Recovery
|
|
354
|
+
- `addGuardian(accountId, request, token)` - Add guardian
|
|
355
|
+
- `removeGuardian(accountId, guardianId, token)` - Remove guardian
|
|
356
|
+
- `getGuardians(accountId, token)` - List guardians
|
|
357
|
+
- `initiateRecovery(request)` - Start recovery
|
|
358
|
+
- `verifyGuardianRecovery(request, token)` - Guardian approval
|
|
359
|
+
- `completeRecovery(request, token)` - Complete recovery
|
|
400
360
|
|
|
401
361
|
## Error Handling
|
|
402
362
|
|
|
@@ -407,21 +367,38 @@ try {
|
|
|
407
367
|
await authenticate(accountId)
|
|
408
368
|
} catch (error) {
|
|
409
369
|
if (error instanceof KentuckySignerError) {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
370
|
+
switch (error.code) {
|
|
371
|
+
case 'WEBAUTHN_NOT_AVAILABLE':
|
|
372
|
+
// WebAuthn not supported
|
|
373
|
+
break
|
|
374
|
+
case 'USER_CANCELLED':
|
|
375
|
+
// User cancelled authentication
|
|
376
|
+
break
|
|
377
|
+
case 'SESSION_EXPIRED':
|
|
378
|
+
// JWT token expired
|
|
379
|
+
break
|
|
380
|
+
case '2FA_REQUIRED':
|
|
381
|
+
// 2FA verification needed
|
|
382
|
+
break
|
|
383
|
+
case '2FA_CANCELLED':
|
|
384
|
+
// User cancelled 2FA input
|
|
385
|
+
break
|
|
386
|
+
// ... handle other codes
|
|
387
|
+
}
|
|
413
388
|
}
|
|
414
389
|
}
|
|
415
390
|
```
|
|
416
391
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
-
|
|
422
|
-
-
|
|
423
|
-
-
|
|
424
|
-
-
|
|
392
|
+
## Documentation
|
|
393
|
+
|
|
394
|
+
For detailed documentation, see the [docs](./docs) folder:
|
|
395
|
+
|
|
396
|
+
- [Authentication](./docs/authentication.md) - Passkey, password, and token auth
|
|
397
|
+
- [Secure Mode](./docs/secure-mode.md) - Ephemeral key signing
|
|
398
|
+
- [Two-Factor Authentication](./docs/two-factor-auth.md) - TOTP and PIN setup
|
|
399
|
+
- [Guardian Recovery](./docs/guardian-recovery.md) - Social recovery setup
|
|
400
|
+
- [React Integration](./docs/react-integration.md) - Hooks and context usage
|
|
401
|
+
- [API Reference](./docs/api-reference.md) - Complete API documentation
|
|
425
402
|
|
|
426
403
|
## License
|
|
427
404
|
|