emblem-vault-ai-signers 0.1.7 → 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/dist/http.d.ts +2 -2
- package/dist/http.js +24 -6
- package/dist/types.d.ts +18 -3
- package/dist/validation.d.ts +1 -1
- package/dist/validation.js +19 -14
- package/dist/vault.js +4 -4
- package/package.json +3 -2
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
|
|
package/dist/http.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { EmblemRemoteConfig } from "./types.js";
|
|
2
|
-
export declare function emblemPost<T = any>(path: string, body: any,
|
|
3
|
-
export declare function emblemGet<T = any>(path: string,
|
|
2
|
+
export declare function emblemPost<T = any>(path: string, body: any, config: EmblemRemoteConfig): Promise<T>;
|
|
3
|
+
export declare function emblemGet<T = any>(path: string, config: EmblemRemoteConfig): Promise<T>;
|
package/dist/http.js
CHANGED
|
@@ -19,12 +19,30 @@ function sanitizeErrorMessage(status, text) {
|
|
|
19
19
|
}
|
|
20
20
|
return errorMessage;
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
async function resolveAuthHeaders(config) {
|
|
23
|
+
// Priority: custom headers -> apiKey -> jwt/getJwt/sdk
|
|
24
|
+
if (typeof config.getAuthHeaders === 'function') {
|
|
25
|
+
const h = await config.getAuthHeaders();
|
|
26
|
+
if (h && typeof h === 'object')
|
|
27
|
+
return h;
|
|
28
|
+
}
|
|
29
|
+
if (config.apiKey) {
|
|
30
|
+
return { 'x-api-key': config.apiKey };
|
|
31
|
+
}
|
|
32
|
+
const tok = config.jwt ?? (typeof config.getJwt === 'function' ? await config.getJwt() : undefined) ?? (config.sdk?.getSession()?.authToken ?? undefined);
|
|
33
|
+
if (tok) {
|
|
34
|
+
return { 'Authorization': `Bearer ${tok}` };
|
|
35
|
+
}
|
|
36
|
+
throw new Error('No authentication available: provide apiKey, jwt, getJwt(), getAuthHeaders(), or sdk');
|
|
37
|
+
}
|
|
38
|
+
export async function emblemPost(path, body, config) {
|
|
39
|
+
const baseUrl = config.baseUrl ?? "https://api.emblemvault.ai";
|
|
40
|
+
const authHeaders = await resolveAuthHeaders(config);
|
|
23
41
|
const res = await fetch(`${baseUrl}${path}`, {
|
|
24
42
|
method: "POST",
|
|
25
43
|
headers: {
|
|
26
44
|
"content-type": "application/json",
|
|
27
|
-
|
|
45
|
+
...authHeaders,
|
|
28
46
|
},
|
|
29
47
|
body: JSON.stringify(body, (key, value) => typeof value === "bigint" ? value.toString() : value),
|
|
30
48
|
});
|
|
@@ -34,12 +52,12 @@ export async function emblemPost(path, body, { apiKey, baseUrl = "https://api.em
|
|
|
34
52
|
}
|
|
35
53
|
return res.json();
|
|
36
54
|
}
|
|
37
|
-
export async function emblemGet(path,
|
|
55
|
+
export async function emblemGet(path, config) {
|
|
56
|
+
const baseUrl = config.baseUrl ?? "https://api.emblemvault.ai";
|
|
57
|
+
const authHeaders = await resolveAuthHeaders(config);
|
|
38
58
|
const res = await fetch(`${baseUrl}${path}`, {
|
|
39
59
|
method: "GET",
|
|
40
|
-
headers:
|
|
41
|
-
"x-api-key": apiKey,
|
|
42
|
-
},
|
|
60
|
+
headers: authHeaders,
|
|
43
61
|
});
|
|
44
62
|
if (!res.ok) {
|
|
45
63
|
const text = await res.text().catch(() => "");
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
export type Hex = `0x${string}`;
|
|
2
|
+
/** Optional auth providers */
|
|
3
|
+
export type EmblemAuthProvider = {
|
|
4
|
+
/** Static JWT to send as Authorization: Bearer */
|
|
5
|
+
jwt?: string;
|
|
6
|
+
/** Lazy JWT provider */
|
|
7
|
+
getJwt?: () => Promise<string | null | undefined> | string | null | undefined;
|
|
8
|
+
/** Custom headers provider (e.g., Authorization) */
|
|
9
|
+
getAuthHeaders?: () => Promise<Record<string, string>> | Record<string, string>;
|
|
10
|
+
/** SDK-like object exposing getSession() that returns { authToken? } */
|
|
11
|
+
sdk?: {
|
|
12
|
+
getSession: () => {
|
|
13
|
+
authToken?: string | null | undefined;
|
|
14
|
+
} | null | undefined;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
2
17
|
/** Config for Emblem remote signer */
|
|
3
|
-
export type EmblemRemoteConfig = {
|
|
4
|
-
/** x-api-key for your authenticate middleware */
|
|
5
|
-
apiKey
|
|
18
|
+
export type EmblemRemoteConfig = EmblemAuthProvider & {
|
|
19
|
+
/** x-api-key for your authenticate middleware (optional when JWT provided) */
|
|
20
|
+
apiKey?: string;
|
|
6
21
|
/** Base URL for the Emblem signer API */
|
|
7
22
|
baseUrl?: string;
|
|
8
23
|
};
|
package/dist/validation.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export declare function isNodeEnvironment(): boolean;
|
|
|
13
13
|
/**
|
|
14
14
|
* Validate API key format and warn about potential security issues
|
|
15
15
|
*/
|
|
16
|
-
export declare function validateApiKey(apiKey
|
|
16
|
+
export declare function validateApiKey(apiKey?: string, options?: {
|
|
17
17
|
warnOnBrowser?: boolean;
|
|
18
18
|
}): void;
|
|
19
19
|
/**
|
package/dist/validation.js
CHANGED
|
@@ -19,24 +19,20 @@ export function isNodeEnvironment() {
|
|
|
19
19
|
* Validate API key format and warn about potential security issues
|
|
20
20
|
*/
|
|
21
21
|
export function validateApiKey(apiKey, options = {}) {
|
|
22
|
-
if (
|
|
23
|
-
|
|
22
|
+
if (apiKey == null)
|
|
23
|
+
return; // optional
|
|
24
|
+
if (typeof apiKey !== 'string') {
|
|
25
|
+
throw new Error('apiKey must be a string when provided');
|
|
24
26
|
}
|
|
25
27
|
if (apiKey.trim() === '') {
|
|
26
28
|
throw new Error('apiKey cannot be empty or whitespace');
|
|
27
29
|
}
|
|
28
|
-
// Warn if API key looks like it might be exposed in client-side code
|
|
29
30
|
if (options.warnOnBrowser !== false && isBrowserEnvironment()) {
|
|
30
|
-
console.warn('[Emblem Security Warning] API key is being used in a browser environment. '
|
|
31
|
-
'
|
|
32
|
-
'
|
|
33
|
-
'To suppress this warning, pass { warnOnBrowser: false } to createEmblemClient().');
|
|
31
|
+
console.warn('[Emblem Security Warning] API key is being used in a browser environment. '
|
|
32
|
+
+ 'Prefer JWT or a secure server-side usage. '
|
|
33
|
+
+ 'To suppress this warning, pass { warnOnBrowser: false } to createEmblemClient().');
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
if (apiKey.startsWith('pk_') || apiKey.startsWith('sk_')) {
|
|
37
|
-
// Looks like a typical API key format - good
|
|
38
|
-
}
|
|
39
|
-
else if (apiKey.length < 16) {
|
|
35
|
+
if (!apiKey.startsWith('pk_') && !apiKey.startsWith('sk_') && apiKey.length < 16) {
|
|
40
36
|
console.warn('[Emblem Security Warning] API key seems unusually short. Is this correct?');
|
|
41
37
|
}
|
|
42
38
|
}
|
|
@@ -93,7 +89,16 @@ export function toSafeNumber(value, fieldName) {
|
|
|
93
89
|
* Comprehensive configuration validation
|
|
94
90
|
*/
|
|
95
91
|
export function validateConfig(config) {
|
|
96
|
-
// Validate
|
|
92
|
+
// Validate auth: require at least one method (apiKey, jwt, getJwt, getAuthHeaders, sdk)
|
|
93
|
+
const hasApiKey = !!config.apiKey;
|
|
94
|
+
const hasJwt = !!config.jwt;
|
|
95
|
+
const hasGetJwt = typeof config.getJwt === 'function';
|
|
96
|
+
const hasHeaders = typeof config.getAuthHeaders === 'function';
|
|
97
|
+
const hasSdk = !!config.sdk && typeof config.sdk.getSession === 'function';
|
|
98
|
+
if (!hasApiKey && !hasJwt && !hasGetJwt && !hasHeaders && !hasSdk) {
|
|
99
|
+
throw new Error('Authentication required: provide apiKey, jwt, getJwt(), getAuthHeaders(), or sdk');
|
|
100
|
+
}
|
|
101
|
+
// Validate API key if present
|
|
97
102
|
validateApiKey(config.apiKey, { warnOnBrowser: config.warnOnBrowser });
|
|
98
103
|
// Validate baseUrl if provided
|
|
99
104
|
if (config.baseUrl) {
|
|
@@ -104,7 +109,7 @@ export function validateConfig(config) {
|
|
|
104
109
|
console.log('[Emblem Security Debug]', {
|
|
105
110
|
environment: isBrowserEnvironment() ? 'browser' : 'node',
|
|
106
111
|
hasBaseUrl: !!config.baseUrl,
|
|
107
|
-
apiKeyLength: config.apiKey.length,
|
|
112
|
+
apiKeyLength: config.apiKey ? config.apiKey.length : 0,
|
|
108
113
|
timestamp: new Date().toISOString(),
|
|
109
114
|
});
|
|
110
115
|
}
|
package/dist/vault.js
CHANGED
|
@@ -3,17 +3,17 @@ export async function fetchVaultInfo(config) {
|
|
|
3
3
|
// Note: The server only supports POST for /vault/info
|
|
4
4
|
// No need to try GET first, just use POST directly
|
|
5
5
|
const data = await emblemPost("/vault/info", {}, config);
|
|
6
|
-
// Validate response data
|
|
7
|
-
if (!data
|
|
6
|
+
// Validate required response data (vaultId + evmAddress are required for EVM)
|
|
7
|
+
if (!data || !data.vaultId || !data.evmAddress) {
|
|
8
8
|
throw new Error('Invalid vault info response: missing required fields');
|
|
9
9
|
}
|
|
10
|
-
if (!data.evmAddress.startsWith('0x')) {
|
|
10
|
+
if (!String(data.evmAddress).startsWith('0x')) {
|
|
11
11
|
throw new Error('Invalid evmAddress format in response');
|
|
12
12
|
}
|
|
13
13
|
return {
|
|
14
14
|
vaultId: data.vaultId,
|
|
15
15
|
tokenId: data.vaultId,
|
|
16
|
-
address: data.address,
|
|
16
|
+
address: data.address || '', // Solana address may be absent; keep optional
|
|
17
17
|
evmAddress: data.evmAddress,
|
|
18
18
|
created_by: data.created_by,
|
|
19
19
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "emblem-vault-ai-signers",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8-experimental.1",
|
|
4
4
|
"description": "Emblem Vault remote signer adapters for viem and ethers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"test:ci": "vitest run --reporter=default",
|
|
26
26
|
"test:integration": "vitest -c vitest.int.config.ts run --reporter=verbose",
|
|
27
27
|
"test:all": "npm test && npm run test:integration",
|
|
28
|
-
"release:patch": "npm version patch && npm run build && npm run test:all && npm publish"
|
|
28
|
+
"release:patch": "npm version patch && npm run build && npm run test:all && npm publish",
|
|
29
|
+
"release:experimental": "npm version prerelease --preid=experimental && npm run build && npm run test:all && npm publish --tag experimental"
|
|
29
30
|
},
|
|
30
31
|
"keywords": [
|
|
31
32
|
"emblem",
|