emblem-vault-ai-signers 0.1.8-experimental.0 → 0.1.8-experimental.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 +178 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,6 +20,9 @@ See the Changelog for release details: CHANGELOG.md
|
|
|
20
20
|
npm install emblem-vault-ai-signers
|
|
21
21
|
# and bring your own peers
|
|
22
22
|
npm install ethers viem
|
|
23
|
+
|
|
24
|
+
# Optional: for SDK integration
|
|
25
|
+
npm install emblem-auth-sdk
|
|
23
26
|
```
|
|
24
27
|
|
|
25
28
|
## Usage
|
|
@@ -31,7 +34,11 @@ import { mainnet } from "viem/chains";
|
|
|
31
34
|
import { JsonRpcProvider } from "ethers";
|
|
32
35
|
|
|
33
36
|
const client = createEmblemClient({
|
|
34
|
-
apiKey: "your-x-api-key",
|
|
37
|
+
apiKey: "your-x-api-key", // traditional API key auth
|
|
38
|
+
// OR use JWT authentication (see Authentication section below)
|
|
39
|
+
// jwt: "your-jwt-token",
|
|
40
|
+
// OR use SDK integration
|
|
41
|
+
// sdk: yourAuthSDK,
|
|
35
42
|
// baseUrl: "https://api.emblemvault.ai" // optional (tests use https://dev-api.emblemvault.ai)
|
|
36
43
|
});
|
|
37
44
|
|
|
@@ -66,6 +73,142 @@ const solKit = await client.toSolanaKitSigner();
|
|
|
66
73
|
console.log(solKit.publicKey);
|
|
67
74
|
```
|
|
68
75
|
|
|
76
|
+
## Authentication
|
|
77
|
+
|
|
78
|
+
The library supports multiple authentication methods. You only need to provide **one** of the following:
|
|
79
|
+
|
|
80
|
+
### API Key Authentication (Traditional)
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
const client = createEmblemClient({
|
|
84
|
+
apiKey: "pk_your_api_key_here"
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### JWT Authentication
|
|
89
|
+
|
|
90
|
+
#### Static JWT Token
|
|
91
|
+
```ts
|
|
92
|
+
const client = createEmblemClient({
|
|
93
|
+
jwt: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
#### Dynamic JWT Provider
|
|
98
|
+
For tokens that need refreshing or are fetched asynchronously:
|
|
99
|
+
```ts
|
|
100
|
+
const client = createEmblemClient({
|
|
101
|
+
getJwt: async () => {
|
|
102
|
+
// Fetch from your auth service, refresh if needed
|
|
103
|
+
return await authService.getAccessToken();
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Or synchronous
|
|
108
|
+
const client = createEmblemClient({
|
|
109
|
+
getJwt: () => localStorage.getItem('authToken')
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### SDK Integration
|
|
114
|
+
|
|
115
|
+
If you're using an authentication SDK that manages sessions:
|
|
116
|
+
```ts
|
|
117
|
+
const client = createEmblemClient({
|
|
118
|
+
sdk: myAuthSDK // Must have getSession() method that returns { authToken }
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Example with EmblemAuthSDK:
|
|
122
|
+
import { EmblemAuthSDK } from 'emblem-auth-sdk';
|
|
123
|
+
|
|
124
|
+
const authSDK = new EmblemAuthSDK({
|
|
125
|
+
appId: 'your-app-id',
|
|
126
|
+
apiUrl: 'https://api.emblemvault.ai'
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
const client = createEmblemClient({
|
|
130
|
+
sdk: authSDK // EmblemAuthSDK has getSession() that returns { authToken, user, ... }
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Example with custom auth SDK:
|
|
134
|
+
const client = createEmblemClient({
|
|
135
|
+
sdk: {
|
|
136
|
+
getSession: () => ({
|
|
137
|
+
authToken: auth0.getIdToken(),
|
|
138
|
+
user: { id: '123' }
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Custom Auth Headers
|
|
145
|
+
|
|
146
|
+
For advanced authentication schemes:
|
|
147
|
+
```ts
|
|
148
|
+
const client = createEmblemClient({
|
|
149
|
+
getAuthHeaders: async () => ({
|
|
150
|
+
'Authorization': 'Custom my-custom-token',
|
|
151
|
+
'X-API-Version': '2.0',
|
|
152
|
+
'X-Client-ID': 'my-app'
|
|
153
|
+
})
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Authentication Priority
|
|
158
|
+
|
|
159
|
+
When multiple auth methods are provided, they're used in this order:
|
|
160
|
+
1. `getAuthHeaders()` (highest priority)
|
|
161
|
+
2. `apiKey`
|
|
162
|
+
3. `jwt` / `getJwt()` / `sdk` (lowest priority)
|
|
163
|
+
|
|
164
|
+
### Browser vs Server Usage
|
|
165
|
+
|
|
166
|
+
- **Browser**: JWT/SDK authentication is recommended for client-side apps where users authenticate themselves
|
|
167
|
+
- **Server**: API key authentication is recommended for server-side applications with stored credentials
|
|
168
|
+
|
|
169
|
+
### Complete SDK Integration Example
|
|
170
|
+
|
|
171
|
+
Here's a complete example using the EmblemAuthSDK with the signers library:
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
import { EmblemAuthSDK } from 'emblem-auth-sdk';
|
|
175
|
+
import { createEmblemClient } from 'emblem-vault-ai-signers';
|
|
176
|
+
import { JsonRpcProvider, parseEther } from 'ethers';
|
|
177
|
+
|
|
178
|
+
// 1. Initialize the auth SDK
|
|
179
|
+
const authSDK = new EmblemAuthSDK({
|
|
180
|
+
appId: 'your-app-id',
|
|
181
|
+
apiUrl: 'https://api.emblemvault.ai',
|
|
182
|
+
onSuccess: (session) => {
|
|
183
|
+
console.log('User authenticated:', session.user);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// 2. Create the signer client using the SDK
|
|
188
|
+
const client = createEmblemClient({
|
|
189
|
+
sdk: authSDK // Pass the SDK instance directly
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// 3. Authenticate the user (opens auth modal)
|
|
193
|
+
await authSDK.openAuthModal();
|
|
194
|
+
|
|
195
|
+
// 4. Once authenticated, create wallets/accounts
|
|
196
|
+
const provider = new JsonRpcProvider(process.env.RPC_URL);
|
|
197
|
+
const wallet = await client.toEthersWallet(provider);
|
|
198
|
+
|
|
199
|
+
// 5. Sign and send transactions
|
|
200
|
+
const txHash = await wallet.signAndBroadcast({
|
|
201
|
+
to: "0x...",
|
|
202
|
+
value: parseEther("0.01")
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
The SDK integration automatically handles:
|
|
207
|
+
- JWT token management and refresh
|
|
208
|
+
- Session persistence across page reloads
|
|
209
|
+
- Authentication state management
|
|
210
|
+
- Seamless integration with the signers library
|
|
211
|
+
|
|
69
212
|
## Replace Private Keys (Examples)
|
|
70
213
|
|
|
71
214
|
Below are quick swaps showing how to remove local private keys and route signing through Emblem.
|
|
@@ -175,7 +318,13 @@ console.log(solWeb3.publicKey);
|
|
|
175
318
|
|
|
176
319
|
```ts
|
|
177
320
|
type EmblemRemoteConfig = {
|
|
178
|
-
|
|
321
|
+
// Authentication (pick one method):
|
|
322
|
+
apiKey?: string; // traditional x-api-key header
|
|
323
|
+
jwt?: string; // static JWT for Authorization: Bearer
|
|
324
|
+
getJwt?: () => Promise<string> | string; // dynamic JWT provider
|
|
325
|
+
getAuthHeaders?: () => Promise<Record<string, string>> | Record<string, string>; // custom auth headers
|
|
326
|
+
sdk?: { getSession: () => { authToken?: string } | null }; // SDK integration (e.g., EmblemAuthSDK)
|
|
327
|
+
|
|
179
328
|
baseUrl?: string; // default https://api.emblemvault.ai
|
|
180
329
|
};
|
|
181
330
|
|
|
@@ -200,7 +349,7 @@ Adapters POST to the Emblem API endpoints:
|
|
|
200
349
|
- `POST /sign-typed-message` – `{ vaultId, domain, types, message }`
|
|
201
350
|
- `POST /sign-eth-tx` – `{ vaultId, transaction }` (expects ethers-serializable fields)
|
|
202
351
|
|
|
203
|
-
On first use, both adapters query `
|
|
352
|
+
On first use, both adapters query `POST /vault/info` with authentication headers to obtain:
|
|
204
353
|
|
|
205
354
|
- Vault ID
|
|
206
355
|
- Solana Address
|
|
@@ -222,15 +371,20 @@ This library is designed for environments where **users provide their own API ke
|
|
|
222
371
|
|
|
223
372
|
#### What This Means
|
|
224
373
|
```javascript
|
|
225
|
-
// Users provide their OWN
|
|
374
|
+
// Users provide their OWN credentials to YOUR dApp
|
|
226
375
|
const client = createEmblemClient({
|
|
376
|
+
// Traditional API key
|
|
227
377
|
apiKey: userApiKey, // User's key, not yours
|
|
378
|
+
// OR JWT token from user's authentication
|
|
379
|
+
jwt: userJwtToken, // User's JWT, not yours
|
|
380
|
+
// OR SDK integration
|
|
381
|
+
sdk: userAuthSDK, // User's auth SDK
|
|
228
382
|
baseUrl: "https://api.emblemvault.ai"
|
|
229
383
|
});
|
|
230
384
|
```
|
|
231
385
|
|
|
232
|
-
If a user runs your dApp code, they are trusting it with their
|
|
233
|
-
- Logging API keys
|
|
386
|
+
If a user runs your dApp code, they are trusting it with their authentication credentials and signing authority. There is no way to prevent malicious dApp code from:
|
|
387
|
+
- Logging API keys or JWT tokens
|
|
234
388
|
- Intercepting `fetch()` calls
|
|
235
389
|
- Changing the `baseUrl`
|
|
236
390
|
- Making unauthorized signing requests
|
|
@@ -241,9 +395,10 @@ If a user runs your dApp code, they are trusting it with their API key and signi
|
|
|
241
395
|
|
|
242
396
|
1. **Only use trusted dApps** - Verify the source and reputation
|
|
243
397
|
2. **Review open source code** when possible
|
|
244
|
-
3. **Use separate
|
|
398
|
+
3. **Use separate credentials** for different dApps (API keys, JWT tokens)
|
|
245
399
|
4. **Monitor signing activity** in your Emblem dashboard
|
|
246
|
-
5. **Test with staging
|
|
400
|
+
5. **Test with staging credentials first** before using production
|
|
401
|
+
6. **Understand token expiration** - JWT tokens expire and may need refresh
|
|
247
402
|
|
|
248
403
|
### Best Practices for Implementers
|
|
249
404
|
|
|
@@ -251,16 +406,20 @@ If a user runs your dApp code, they are trusting it with their API key and signi
|
|
|
251
406
|
2. **Document your security model** - Be transparent about API key handling
|
|
252
407
|
3. **Minimize dependencies** - Reduce supply chain attack surface
|
|
253
408
|
4. **Use Content Security Policy** - Add CSP headers to protect against XSS
|
|
254
|
-
5. **Never log or store user
|
|
255
|
-
6. **Implement proper error handling** - Don't expose
|
|
409
|
+
5. **Never log or store user credentials** - Only use API keys/JWTs in-memory for signing
|
|
410
|
+
6. **Implement proper error handling** - Don't expose credentials in error messages
|
|
411
|
+
7. **Handle JWT expiration gracefully** - Implement token refresh when using dynamic JWTs
|
|
412
|
+
8. **Prefer JWT auth for client-side apps** - More secure than exposing long-lived API keys
|
|
256
413
|
|
|
257
414
|
### Server-Side Usage
|
|
258
415
|
|
|
259
416
|
When used server-side (Node.js):
|
|
260
417
|
- Store API keys in environment variables
|
|
261
|
-
- Never expose
|
|
418
|
+
- Never expose credentials to client-side code
|
|
262
419
|
- Use proper access controls and authentication
|
|
263
420
|
- Implement rate limiting if exposing signing endpoints
|
|
421
|
+
- Consider API key auth for server-to-server communication
|
|
422
|
+
- Use JWT auth when proxying user authentication
|
|
264
423
|
|
|
265
424
|
### Development vs Production
|
|
266
425
|
|
|
@@ -273,14 +432,20 @@ const devClient = createEmblemClient({
|
|
|
273
432
|
baseUrl: "https://dev-api.emblemvault.ai"
|
|
274
433
|
});
|
|
275
434
|
|
|
276
|
-
// Production
|
|
435
|
+
// Production with API key
|
|
277
436
|
const prodClient = createEmblemClient({
|
|
278
437
|
apiKey: process.env.PROD_API_KEY,
|
|
279
438
|
baseUrl: "https://api.emblemvault.ai"
|
|
280
439
|
});
|
|
440
|
+
|
|
441
|
+
// Production with JWT (client-side)
|
|
442
|
+
const jwtClient = createEmblemClient({
|
|
443
|
+
getJwt: async () => await auth.getAccessToken(),
|
|
444
|
+
baseUrl: "https://api.emblemvault.ai"
|
|
445
|
+
});
|
|
281
446
|
```
|
|
282
447
|
|
|
283
|
-
|
|
448
|
+
Credentials from one environment do not work in another, providing natural isolation.
|
|
284
449
|
|
|
285
450
|
---
|
|
286
451
|
|