emblem-vault-ai-signers 0.1.7 → 0.1.8-experimental.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/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/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.0",
|
|
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",
|