prividium 0.17.0 → 0.18.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 +31 -18
- package/bin/cli.js +1 -1
- package/dist/cli/{commands → cli/commands}/config.js +4 -12
- package/dist/cli/cli/commands/proxy.js +255 -0
- package/dist/cli/{commands → cli/commands}/utils/url-config.js +20 -3
- package/dist/cli/{server → cli/server}/config-file.js +28 -8
- package/dist/cli/{server → cli/server}/connection-workflow.js +1 -1
- package/dist/cli/{server → cli/server}/server.js +32 -13
- package/dist/cli/{static → cli/static}/callback.html +1 -1
- package/dist/cli/src/error-utils.js +73 -0
- package/dist/cli/src/memory-storage.js +12 -0
- package/dist/cli/src/rpc-error-codes.js +24 -0
- package/dist/cli/src/siwe-auth.js +70 -0
- package/dist/cli/src/storage.js +142 -0
- package/dist/cli/src/types.js +46 -0
- package/dist/cli/tsconfig.cli.tsbuildinfo +1 -0
- package/dist/sdk/error-utils.d.ts +1 -0
- package/dist/sdk/error-utils.js +20 -6
- package/dist/sdk/popup-auth.d.ts +1 -7
- package/dist/sdk/siwe-auth.d.ts +1 -1
- package/dist/sdk/siwe-auth.js +1 -1
- package/dist/sdk/siwe-chain.d.ts +1 -1
- package/dist/sdk/siwe-chain.js +23 -19
- package/dist/sdk/types.d.ts +1 -1
- package/package.json +2 -2
- package/dist/cli/commands/proxy.js +0 -149
- package/dist/tsconfig.cli.tsbuildinfo +0 -1
- /package/dist/cli/{base-cli.js → cli/base-cli.js} +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/clients/browser-auth.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/clients/http.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/clients/rpc.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/clients/wallet-api.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/constants.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/probes/authentication/authentication.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/probes/authentication/wallet-preconditions.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/probes/authentication.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/probes/bridging/bridging.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/probes/bridging.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/probes/global/input-validation.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/probes/global/reachability.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/probes/global.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/probes/wallet/authenticated-rpc.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/probes/wallet/authorization-and-wallet-rpc.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/probes/wallet-api.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/probes/wallet.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/profile.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/report/build.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/report/render.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/stages.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/types.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor/utils.js +0 -0
- /package/dist/cli/{commands → cli/commands}/doctor.js +0 -0
- /package/dist/cli/{commands → cli/commands}/utils/show-prividium-header.js +0 -0
- /package/dist/cli/{index.js → cli/index.js} +0 -0
- /package/dist/cli/{static → cli/static}/start.html +0 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RPC error codes used in Prividium SDK.
|
|
3
|
+
* Standard codes follow JSON-RPC 2.0 spec, custom codes handle auth/authz.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Internal error (-32603). Standard JSON-RPC 2.0 code for server errors.
|
|
7
|
+
*/
|
|
8
|
+
export const INTERNAL_RPC_ERROR = -32603;
|
|
9
|
+
/**
|
|
10
|
+
* Invalid Request (-32600). Standard JSON-RPC 2.0 code for malformed requests.
|
|
11
|
+
*/
|
|
12
|
+
export const INVALID_REQUEST_ERROR_CODE = -32600;
|
|
13
|
+
/**
|
|
14
|
+
* Invalid params (-32602). Standard JSON-RPC 2.0 code for bad parameters.
|
|
15
|
+
*/
|
|
16
|
+
export const BAD_RPC_PARAMS_ERROR_CODE = -32602;
|
|
17
|
+
/**
|
|
18
|
+
* Unauthorized (-32090). Custom code for authentication failures (no/invalid token).
|
|
19
|
+
*/
|
|
20
|
+
export const UNAUTHORIZED_ERROR_CODE = -32090;
|
|
21
|
+
/**
|
|
22
|
+
* Forbidden (-32001). Custom code for authorization failures (valid token, insufficient permissions).
|
|
23
|
+
*/
|
|
24
|
+
export const FORBIDDEN_ERROR_CODE = -32001;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { extractResponseError } from './error-utils.js';
|
|
3
|
+
const siweMessageResponseSchema = z.object({
|
|
4
|
+
msg: z.string(),
|
|
5
|
+
nonceToken: z.string()
|
|
6
|
+
});
|
|
7
|
+
const siweLoginResponseSchema = z.object({
|
|
8
|
+
token: z.string(),
|
|
9
|
+
expiresAt: z.string()
|
|
10
|
+
});
|
|
11
|
+
const mfaResponseSchema = z.object({
|
|
12
|
+
requiresMfa: z.literal(true)
|
|
13
|
+
});
|
|
14
|
+
export class SiweAuth {
|
|
15
|
+
config;
|
|
16
|
+
constructor(config) {
|
|
17
|
+
this.config = config;
|
|
18
|
+
}
|
|
19
|
+
get address() {
|
|
20
|
+
return this.config.account.address;
|
|
21
|
+
}
|
|
22
|
+
async authorize() {
|
|
23
|
+
// Step 1: Request SIWE message
|
|
24
|
+
const siweResponse = await fetch(new URL('/api/siwe-messages', this.config.prividiumApiBaseUrl), {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
headers: { 'Content-Type': 'application/json' },
|
|
27
|
+
body: JSON.stringify({
|
|
28
|
+
address: this.config.account.address,
|
|
29
|
+
...(this.config.domain && { domain: this.config.domain })
|
|
30
|
+
})
|
|
31
|
+
});
|
|
32
|
+
if (!siweResponse.ok) {
|
|
33
|
+
const detail = await extractResponseError(siweResponse);
|
|
34
|
+
throw new Error(`Failed to get SIWE message: ${detail}`);
|
|
35
|
+
}
|
|
36
|
+
const siweData = siweMessageResponseSchema.parse(await siweResponse.json());
|
|
37
|
+
// Step 2: Sign the message
|
|
38
|
+
const signature = await this.config.account.signMessage({ message: siweData.msg });
|
|
39
|
+
// Step 3: Login
|
|
40
|
+
const loginResponse = await fetch(new URL('/api/auth/login/crypto-native', this.config.prividiumApiBaseUrl), {
|
|
41
|
+
method: 'POST',
|
|
42
|
+
headers: { 'Content-Type': 'application/json' },
|
|
43
|
+
body: JSON.stringify({ message: siweData.msg, signature, nonceToken: siweData.nonceToken })
|
|
44
|
+
});
|
|
45
|
+
if (!loginResponse.ok) {
|
|
46
|
+
const detail = await extractResponseError(loginResponse);
|
|
47
|
+
throw new Error(`SIWE login failed: ${detail}`);
|
|
48
|
+
}
|
|
49
|
+
const loginJson = await loginResponse.json();
|
|
50
|
+
// Check for MFA requirement (admin users with passkeys)
|
|
51
|
+
const mfaParsed = mfaResponseSchema.safeParse(loginJson);
|
|
52
|
+
if (mfaParsed.success) {
|
|
53
|
+
throw new Error('SIWE login requires MFA which is not supported in programmatic auth');
|
|
54
|
+
}
|
|
55
|
+
const loginData = siweLoginResponseSchema.parse(loginJson);
|
|
56
|
+
// Step 4: Store token directly (login response includes expiresAt)
|
|
57
|
+
const tokenData = {
|
|
58
|
+
rawToken: loginData.token,
|
|
59
|
+
expiresAt: new Date(loginData.expiresAt)
|
|
60
|
+
};
|
|
61
|
+
this.config.tokenManager.setTokenDirect(tokenData);
|
|
62
|
+
return tokenData;
|
|
63
|
+
}
|
|
64
|
+
unauthorize() {
|
|
65
|
+
this.config.tokenManager.clearToken();
|
|
66
|
+
}
|
|
67
|
+
isAuthorized() {
|
|
68
|
+
return this.config.tokenManager.isAuthorized();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { addYears } from 'date-fns/addYears';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { STORAGE_KEYS, tokenDataSchema } from './types.js';
|
|
4
|
+
export class LocalStorage {
|
|
5
|
+
getItem(key) {
|
|
6
|
+
if (typeof localStorage === 'undefined') {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
return localStorage.getItem(key);
|
|
10
|
+
}
|
|
11
|
+
setItem(key, value) {
|
|
12
|
+
if (typeof localStorage !== 'undefined') {
|
|
13
|
+
localStorage.setItem(key, value);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
removeItem(key) {
|
|
17
|
+
if (typeof localStorage !== 'undefined') {
|
|
18
|
+
localStorage.removeItem(key);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export class TokenManager {
|
|
23
|
+
storage;
|
|
24
|
+
chainId;
|
|
25
|
+
prividiumApiUrl;
|
|
26
|
+
tokenCache = null;
|
|
27
|
+
onAuthExpiry;
|
|
28
|
+
constructor(storage, chainId, prividiumApiUrl, onAuthExpiry) {
|
|
29
|
+
this.storage = storage;
|
|
30
|
+
this.chainId = chainId;
|
|
31
|
+
this.prividiumApiUrl = prividiumApiUrl;
|
|
32
|
+
this.onAuthExpiry = onAuthExpiry ?? (() => { });
|
|
33
|
+
}
|
|
34
|
+
get tokenKey() {
|
|
35
|
+
return `${STORAGE_KEYS.TOKEN_PREFIX}${this.chainId}`;
|
|
36
|
+
}
|
|
37
|
+
get stateKey() {
|
|
38
|
+
return `${STORAGE_KEYS.STATE_PREFIX}${this.chainId}`;
|
|
39
|
+
}
|
|
40
|
+
getToken() {
|
|
41
|
+
if (this.tokenCache) {
|
|
42
|
+
return this.tokenCache;
|
|
43
|
+
}
|
|
44
|
+
const tokenDataStr = this.storage.getItem(this.tokenKey);
|
|
45
|
+
if (!tokenDataStr) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const tokenData = tokenDataSchema.safeParse(JSON.parse(tokenDataStr));
|
|
50
|
+
if (!tokenData.success) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
if (new Date() > tokenData.data.expiresAt) {
|
|
54
|
+
this.clearToken();
|
|
55
|
+
this.onAuthExpiry();
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
this.tokenCache = tokenData.data;
|
|
59
|
+
return tokenData.data;
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
if (e instanceof SyntaxError) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
throw e;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async getTokenExpiration(token) {
|
|
69
|
+
const currentSessionRes = await fetch(new URL('/api/auth/current-session', this.prividiumApiUrl), {
|
|
70
|
+
headers: {
|
|
71
|
+
authorization: `Bearer ${token}`
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
if (!currentSessionRes.ok) {
|
|
75
|
+
throw new Error('Error accessing prividium api');
|
|
76
|
+
}
|
|
77
|
+
if (currentSessionRes.status === 404) {
|
|
78
|
+
// NOTE: 404 indicates /api/auth/current-session is unavailable (older API),
|
|
79
|
+
// so the token expiration cannot be retrieved. The SDK must defer expiry
|
|
80
|
+
// handling until a 403 response is received; a far-future date prevents
|
|
81
|
+
// premature onExpiry callbacks before validation fails.
|
|
82
|
+
return addYears(new Date(), 100);
|
|
83
|
+
}
|
|
84
|
+
if (!currentSessionRes.ok || currentSessionRes.status !== 200) {
|
|
85
|
+
throw new Error('Error accessing prividium api');
|
|
86
|
+
}
|
|
87
|
+
const schema = z.object({
|
|
88
|
+
expiresAt: z.iso.datetime()
|
|
89
|
+
});
|
|
90
|
+
const parsed = schema.safeParse(await currentSessionRes.json());
|
|
91
|
+
if (!parsed.success) {
|
|
92
|
+
throw new Error('Invalid response from prividium api');
|
|
93
|
+
}
|
|
94
|
+
return new Date(parsed.data.expiresAt);
|
|
95
|
+
}
|
|
96
|
+
async setToken(rawToken) {
|
|
97
|
+
try {
|
|
98
|
+
const expiresAt = await this.getTokenExpiration(rawToken);
|
|
99
|
+
const tokenData = { rawToken, expiresAt };
|
|
100
|
+
this.storage.setItem(this.tokenKey, JSON.stringify(tokenData));
|
|
101
|
+
this.tokenCache = tokenData;
|
|
102
|
+
return tokenData;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
this.clearToken();
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Stores token data directly without fetching expiration from the API.
|
|
111
|
+
* Used by SIWE auth where the login response already includes expiresAt.
|
|
112
|
+
*/
|
|
113
|
+
setTokenDirect(tokenData) {
|
|
114
|
+
this.storage.setItem(this.tokenKey, JSON.stringify(tokenData));
|
|
115
|
+
this.tokenCache = tokenData;
|
|
116
|
+
}
|
|
117
|
+
clearToken() {
|
|
118
|
+
this.tokenCache = null;
|
|
119
|
+
this.storage.removeItem(this.tokenKey);
|
|
120
|
+
}
|
|
121
|
+
isAuthorized() {
|
|
122
|
+
const tokenData = this.getToken();
|
|
123
|
+
if (tokenData === null) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
const isExpired = new Date() > tokenData.expiresAt;
|
|
127
|
+
if (isExpired) {
|
|
128
|
+
this.onAuthExpiry();
|
|
129
|
+
this.clearToken();
|
|
130
|
+
}
|
|
131
|
+
return !isExpired;
|
|
132
|
+
}
|
|
133
|
+
setState(state) {
|
|
134
|
+
this.storage.setItem(this.stateKey, state);
|
|
135
|
+
}
|
|
136
|
+
getState() {
|
|
137
|
+
return this.storage.getItem(this.stateKey);
|
|
138
|
+
}
|
|
139
|
+
clearState() {
|
|
140
|
+
this.storage.removeItem(this.stateKey);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const roleSchema = z.object({
|
|
3
|
+
roleName: z.string()
|
|
4
|
+
});
|
|
5
|
+
export const profileSchema = z.object({
|
|
6
|
+
id: z.string(),
|
|
7
|
+
createdAt: z.coerce.date(),
|
|
8
|
+
displayName: z.string(),
|
|
9
|
+
updatedAt: z.coerce.date(),
|
|
10
|
+
roles: roleSchema.array(),
|
|
11
|
+
wallets: z.unknown().array()
|
|
12
|
+
});
|
|
13
|
+
export const authorizeTransactionResponseSchema = z.object({
|
|
14
|
+
message: z.string(),
|
|
15
|
+
activeUntil: z.string()
|
|
16
|
+
});
|
|
17
|
+
const methodSelectorSchema = z.string().regex(/^0x[0-9a-fA-F]{8}$/, 'Invalid method selector format');
|
|
18
|
+
const addressSchema = z.string().regex(/^0x[0-9a-fA-F]{40}$/i, 'Invalid address format');
|
|
19
|
+
export const contractAbiResponseSchema = z.object({
|
|
20
|
+
contractAddress: addressSchema,
|
|
21
|
+
name: z.string().nullable(),
|
|
22
|
+
abi: z.array(z.record(z.string(), z.unknown())),
|
|
23
|
+
functions: z.array(z.object({
|
|
24
|
+
selector: methodSelectorSchema,
|
|
25
|
+
signature: z.string(),
|
|
26
|
+
name: z.string(),
|
|
27
|
+
accessType: z.enum(['read', 'write'])
|
|
28
|
+
}))
|
|
29
|
+
});
|
|
30
|
+
export const tokenDataSchema = z.object({
|
|
31
|
+
rawToken: z.string(),
|
|
32
|
+
expiresAt: z.coerce.date()
|
|
33
|
+
});
|
|
34
|
+
export const AUTH_ERRORS = {
|
|
35
|
+
INVALID_STATE: 'Invalid state parameter',
|
|
36
|
+
NO_RECEIVED_STATE: 'No state parameter',
|
|
37
|
+
NO_SAVED_STATE: 'No saved state',
|
|
38
|
+
NO_TOKEN: 'No token received',
|
|
39
|
+
EXPIRED_TOKEN: 'Expired token',
|
|
40
|
+
INVALID_JWT: 'Invalid JWT format',
|
|
41
|
+
AUTH_REQUIRED: 'Authentication required'
|
|
42
|
+
};
|
|
43
|
+
export const STORAGE_KEYS = {
|
|
44
|
+
STATE_PREFIX: 'prividium_auth_state_',
|
|
45
|
+
TOKEN_PREFIX: 'prividium_token_'
|
|
46
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["../../cli/base-cli.ts","../../cli/index.ts","../../cli/commands/config.ts","../../cli/commands/doctor.ts","../../cli/commands/proxy.ts","../../cli/commands/doctor/constants.ts","../../cli/commands/doctor/profile.ts","../../cli/commands/doctor/stages.ts","../../cli/commands/doctor/types.ts","../../cli/commands/doctor/utils.ts","../../cli/commands/doctor/clients/browser-auth.ts","../../cli/commands/doctor/clients/http.ts","../../cli/commands/doctor/clients/rpc.ts","../../cli/commands/doctor/clients/wallet-api.ts","../../cli/commands/doctor/probes/authentication.ts","../../cli/commands/doctor/probes/bridging.ts","../../cli/commands/doctor/probes/global.ts","../../cli/commands/doctor/probes/wallet-api.ts","../../cli/commands/doctor/probes/wallet.ts","../../cli/commands/doctor/probes/authentication/authentication.ts","../../cli/commands/doctor/probes/authentication/wallet-preconditions.ts","../../cli/commands/doctor/probes/bridging/bridging.ts","../../cli/commands/doctor/probes/global/input-validation.ts","../../cli/commands/doctor/probes/global/reachability.ts","../../cli/commands/doctor/probes/wallet/authenticated-rpc.ts","../../cli/commands/doctor/probes/wallet/authorization-and-wallet-rpc.ts","../../cli/commands/doctor/report/build.ts","../../cli/commands/doctor/report/render.ts","../../cli/commands/utils/show-prividium-header.ts","../../cli/commands/utils/url-config.ts","../../cli/server/config-file.ts","../../cli/server/connection-workflow.ts","../../cli/server/server.ts"],"version":"5.8.3"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Checks if a Response contains a Prividium unauthorized/forbidden error.
|
|
3
3
|
*/
|
|
4
4
|
export declare function hasPrividiumUnauthorizedError(response: Response): Promise<boolean>;
|
|
5
|
+
export declare function isPrividiumUnauthorizedRpcError(error: unknown): boolean;
|
|
5
6
|
/**
|
|
6
7
|
* Extracts a human-readable error string from a failed HTTP response.
|
|
7
8
|
* Attempts to parse the server's `{ error: { code, message } }` JSON structure,
|
package/dist/sdk/error-utils.js
CHANGED
|
@@ -17,13 +17,27 @@ const apiErrorSchema = z.object({
|
|
|
17
17
|
* Checks if a Response contains a Prividium unauthorized/forbidden error.
|
|
18
18
|
*/
|
|
19
19
|
export async function hasPrividiumUnauthorizedError(response) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
try {
|
|
21
|
+
const clonedResponse = response.clone();
|
|
22
|
+
const parsed = jsonRpcErrorSchema.safeParse(await clonedResponse.json());
|
|
23
|
+
if (parsed.success) {
|
|
24
|
+
return parsed.data.error.code === UNAUTHORIZED_ERROR_CODE;
|
|
25
|
+
}
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function isPrividiumUnauthorizedRpcError(error) {
|
|
33
|
+
if (!error || typeof error !== 'object') {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
const value = error;
|
|
37
|
+
if (value.code === UNAUTHORIZED_ERROR_CODE) {
|
|
38
|
+
return true;
|
|
25
39
|
}
|
|
26
|
-
return
|
|
40
|
+
return isPrividiumUnauthorizedRpcError(value.cause);
|
|
27
41
|
}
|
|
28
42
|
/**
|
|
29
43
|
* Extracts a human-readable error string from a failed HTTP response.
|
package/dist/sdk/popup-auth.d.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import type { TokenManager } from './storage.js';
|
|
2
2
|
import { type PopupOptions } from './types.js';
|
|
3
|
-
|
|
4
|
-
* OAuth scopes that can be requested during authorization
|
|
5
|
-
*
|
|
6
|
-
* - `wallet:required`: Requires user to have at least one wallet associated
|
|
7
|
-
* - `network:required`: Requires user to have wallet connected with correct chain
|
|
8
|
-
*/
|
|
9
|
-
export type OauthScope = 'wallet:required' | 'network:required';
|
|
3
|
+
export type { OauthScope } from './types.js';
|
|
10
4
|
export interface PopupAuthConfig {
|
|
11
5
|
authBaseUrl: string;
|
|
12
6
|
clientId: string;
|
package/dist/sdk/siwe-auth.d.ts
CHANGED
package/dist/sdk/siwe-auth.js
CHANGED
|
@@ -26,7 +26,7 @@ export class SiweAuth {
|
|
|
26
26
|
headers: { 'Content-Type': 'application/json' },
|
|
27
27
|
body: JSON.stringify({
|
|
28
28
|
address: this.config.account.address,
|
|
29
|
-
domain: this.config.domain
|
|
29
|
+
...(this.config.domain && { domain: this.config.domain })
|
|
30
30
|
})
|
|
31
31
|
});
|
|
32
32
|
if (!siweResponse.ok) {
|
package/dist/sdk/siwe-chain.d.ts
CHANGED
package/dist/sdk/siwe-chain.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { http } from 'viem';
|
|
2
2
|
import { buildChainObject, createApiMethods, rpcUrl } from './chain-core.js';
|
|
3
|
-
import { extractResponseError,
|
|
3
|
+
import { extractResponseError, isPrividiumUnauthorizedRpcError } from './error-utils.js';
|
|
4
4
|
import { PrividiumSessionError } from './errors.js';
|
|
5
5
|
import { MemoryStorage } from './memory-storage.js';
|
|
6
6
|
import { SiweAuth } from './siwe-auth.js';
|
|
@@ -112,16 +112,12 @@ export function createPrividiumSiweChain(config) {
|
|
|
112
112
|
return parsed.data;
|
|
113
113
|
}
|
|
114
114
|
// Create transport with auth integration using viem callbacks
|
|
115
|
-
const
|
|
115
|
+
const baseTransport = http(rpcUrl(config.prividiumApiBaseUrl), {
|
|
116
116
|
batch: false,
|
|
117
117
|
fetchOptions: {
|
|
118
118
|
headers: getAuthHeaders() || {}
|
|
119
119
|
},
|
|
120
120
|
onFetchRequest(_request, init) {
|
|
121
|
-
// Don't throw on expired token — let the request go through
|
|
122
|
-
// so onFetchResponse can handle the 401 and trigger reauthentication.
|
|
123
|
-
// Throwing here creates a deadlock: no request is sent, so onFetchResponse
|
|
124
|
-
// (which is the only reauth trigger for RPC calls) never fires.
|
|
125
121
|
const authHeaders = getAuthHeaders();
|
|
126
122
|
if (authHeaders) {
|
|
127
123
|
init.headers = {
|
|
@@ -129,24 +125,32 @@ export function createPrividiumSiweChain(config) {
|
|
|
129
125
|
...authHeaders
|
|
130
126
|
};
|
|
131
127
|
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
const transport = (parameters) => {
|
|
131
|
+
const base = baseTransport(parameters);
|
|
132
|
+
return {
|
|
133
|
+
...base,
|
|
134
|
+
async request(request) {
|
|
135
|
+
await ensureAuthorized();
|
|
136
|
+
try {
|
|
137
|
+
return await base.request(request);
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
if (!isPrividiumUnauthorizedRpcError(error)) {
|
|
141
|
+
throw error;
|
|
139
142
|
}
|
|
140
|
-
|
|
143
|
+
if (!autoReauth) {
|
|
141
144
|
config.onAuthExpiry?.();
|
|
145
|
+
throw error;
|
|
142
146
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
147
|
+
tokenManager.clearToken();
|
|
148
|
+
await reauthenticate();
|
|
149
|
+
return base.request(request);
|
|
146
150
|
}
|
|
147
151
|
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
152
|
+
};
|
|
153
|
+
};
|
|
150
154
|
const apiMethods = createApiMethods({ prividiumApiCall, prividiumApiBaseUrl: config.prividiumApiBaseUrl });
|
|
151
155
|
return {
|
|
152
156
|
chain: buildChainObject(config),
|
package/dist/sdk/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Address, Chain, Hex, Transport } from 'viem';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
|
|
3
|
+
export type OauthScope = 'wallet:required' | 'network:required';
|
|
4
4
|
export interface Storage {
|
|
5
5
|
getItem(key: string): string | null;
|
|
6
6
|
setItem(key: string, value: string): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prividium",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"prividium": "bin/cli.js"
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
],
|
|
25
25
|
"scripts": {
|
|
26
26
|
"build": "tsc -b && pnpm copy-static-files",
|
|
27
|
-
"copy-static-files": "cp -r cli/static dist/cli",
|
|
27
|
+
"copy-static-files": "cp -r cli/static dist/cli/cli",
|
|
28
28
|
"dev": "tsc -b --watch",
|
|
29
29
|
"test": "vitest run",
|
|
30
30
|
"test:watch": "vitest",
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import { log } from '@clack/prompts';
|
|
2
|
-
import color from 'kleur';
|
|
3
|
-
import { CreationWorkflow } from '../server/connection-workflow.js';
|
|
4
|
-
import { buildServer } from '../server/server.js';
|
|
5
|
-
import { gatherUrlConfig } from './utils/url-config.js';
|
|
6
|
-
const DEFAULT_PORT = 24101;
|
|
7
|
-
async function verifyUserPanelUrl(url) {
|
|
8
|
-
try {
|
|
9
|
-
const response = await fetch(url, { signal: AbortSignal.timeout(5000) });
|
|
10
|
-
const html = await response.text();
|
|
11
|
-
const metaMatch = html.match(/<meta\s+name="prividium-component"\s+content="([^"]*)"\s*\/?>/i);
|
|
12
|
-
if (metaMatch?.[1]) {
|
|
13
|
-
const component = metaMatch[1].toLowerCase();
|
|
14
|
-
if (component === 'admin-panel') {
|
|
15
|
-
log.error(`The --user-panel-url appears to point to an Admin Panel, not a User Panel.\n` +
|
|
16
|
-
` Provided URL: ${url}\n\n` +
|
|
17
|
-
`Please provide the User Panel URL instead (typically a different port).`);
|
|
18
|
-
process.exit(1);
|
|
19
|
-
}
|
|
20
|
-
if (component !== 'user-panel') {
|
|
21
|
-
log.warn(`Could not confirm that --user-panel-url points to a Prividium User Panel.\n` +
|
|
22
|
-
` Provided URL: ${url}\n` +
|
|
23
|
-
` Detected component: "${metaMatch[1]}"\n` +
|
|
24
|
-
`Proceeding anyway. If authentication hangs, verify this URL is correct.`);
|
|
25
|
-
}
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
log.warn(`Could not confirm that --user-panel-url points to a Prividium User Panel.\n` +
|
|
29
|
-
` Provided URL: ${url}\n` +
|
|
30
|
-
`Proceeding anyway. If authentication hangs, verify this URL is correct.`);
|
|
31
|
-
}
|
|
32
|
-
catch (error) {
|
|
33
|
-
if (error instanceof TypeError ||
|
|
34
|
-
(error instanceof DOMException && (error.name === 'TimeoutError' || error.name === 'AbortError'))) {
|
|
35
|
-
log.warn(`Could not reach --user-panel-url at ${url}.\n` +
|
|
36
|
-
`Proceeding anyway. If authentication hangs, verify this URL is correct.`);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
throw error;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
function checkHostAndPortWarnings(host, port, allowExternalAccess) {
|
|
43
|
-
if (port !== DEFAULT_PORT) {
|
|
44
|
-
log.warn(`Non standard port detected: ${port}. Redirect from prividium auth might not work.`);
|
|
45
|
-
}
|
|
46
|
-
if (host !== '127.0.0.1' && host !== 'localhost') {
|
|
47
|
-
if (!allowExternalAccess) {
|
|
48
|
-
log.error(`${color.bold('ERROR')}: In order to use a host different than local host you need to set --unsecureAllowOutsideAccess flag.`);
|
|
49
|
-
process.exit(1);
|
|
50
|
-
}
|
|
51
|
-
if (host === '0.0.0.0') {
|
|
52
|
-
log.warn(`${color.bold('WARNING')}: Your local proxy will be exposed outside your current device.`);
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
log.warn(`${color.bold('WARNING')}: Non standard host: ${host}. Your proxy might be open for other devices. Redirect from prividium auth might not work.`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
async function startServer(opts) {
|
|
60
|
-
const workflow = new CreationWorkflow(opts.host, opts.port);
|
|
61
|
-
workflow.start();
|
|
62
|
-
const { prividiumRpcUrl, userPanelUrl } = await gatherUrlConfig({
|
|
63
|
-
configPath: opts.configPath,
|
|
64
|
-
rpcUrl: opts.rpcUrl,
|
|
65
|
-
userPanelUrl: opts.userPanelUrl,
|
|
66
|
-
rpcUrlLabel: 'prividium rpc',
|
|
67
|
-
logProvidedUrls: true
|
|
68
|
-
});
|
|
69
|
-
await verifyUserPanelUrl(userPanelUrl);
|
|
70
|
-
checkHostAndPortWarnings(opts.host, opts.port, opts.allowExternalAccess);
|
|
71
|
-
const app = buildServer({
|
|
72
|
-
prividiumRpcUrl,
|
|
73
|
-
userPanelUrl,
|
|
74
|
-
host: opts.host,
|
|
75
|
-
port: opts.port,
|
|
76
|
-
async onSubmit() {
|
|
77
|
-
await workflow.onSubmit();
|
|
78
|
-
},
|
|
79
|
-
onCall(methodName) {
|
|
80
|
-
workflow.onMessage(methodName);
|
|
81
|
-
},
|
|
82
|
-
onReAuthNeeded() {
|
|
83
|
-
workflow.onMessage(`Please login again: ${serverUrl}`);
|
|
84
|
-
},
|
|
85
|
-
onError: (err) => {
|
|
86
|
-
workflow.onError(err);
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
await app.listen({
|
|
90
|
-
port: opts.port,
|
|
91
|
-
host: opts.host
|
|
92
|
-
});
|
|
93
|
-
const serverUrl = `http://${opts.host}:${opts.port}`;
|
|
94
|
-
await workflow.waitForAuthentication(serverUrl);
|
|
95
|
-
}
|
|
96
|
-
export const addProxy = (cli) => {
|
|
97
|
-
return cli.command('proxy', 'Starts authenticated rpc proxy server', (yargs) => yargs
|
|
98
|
-
.option('rpcUrl', {
|
|
99
|
-
alias: ['rpc-url', 'r'],
|
|
100
|
-
description: 'Specifies target Prividium™ rpc url. These takes precedence over config file and env variable.',
|
|
101
|
-
demandOption: false,
|
|
102
|
-
type: 'string'
|
|
103
|
-
})
|
|
104
|
-
.option('userPanelUrl', {
|
|
105
|
-
alias: ['user-panel-url', 'u'],
|
|
106
|
-
description: 'Specifies url used to log in into the Prividium™ network. Takes precedence over config file and env variable',
|
|
107
|
-
type: 'string'
|
|
108
|
-
})
|
|
109
|
-
.option('configPath', {
|
|
110
|
-
alias: ['c', 'config-path', 'config'],
|
|
111
|
-
description: 'Path for config file. By default config file is stored under user personal folder',
|
|
112
|
-
type: 'string',
|
|
113
|
-
demandOption: false
|
|
114
|
-
})
|
|
115
|
-
.option('port', {
|
|
116
|
-
alias: ['p'],
|
|
117
|
-
description: 'Port used for local proxy. This has to match with the port configured in your Prividium™ network.',
|
|
118
|
-
default: DEFAULT_PORT,
|
|
119
|
-
type: 'number'
|
|
120
|
-
})
|
|
121
|
-
.option('host', {
|
|
122
|
-
alias: 'h',
|
|
123
|
-
description: 'Host used for local server. By default traffic from outside localhost is disabled.',
|
|
124
|
-
default: '127.0.0.1',
|
|
125
|
-
type: 'string'
|
|
126
|
-
})
|
|
127
|
-
.option('unsecureAllowOutsideAccess', {
|
|
128
|
-
alias: ['unsecure-allow-outside-access'],
|
|
129
|
-
description: 'Allow server to be exposed to the network (accessible by other devices)',
|
|
130
|
-
default: false,
|
|
131
|
-
type: 'boolean'
|
|
132
|
-
}), async (args) => {
|
|
133
|
-
try {
|
|
134
|
-
await startServer({
|
|
135
|
-
rpcUrl: args.rpcUrl,
|
|
136
|
-
userPanelUrl: args.userPanelUrl,
|
|
137
|
-
configPath: args.configPath,
|
|
138
|
-
port: args.port,
|
|
139
|
-
host: args.host,
|
|
140
|
-
allowExternalAccess: args.unsecureAllowOutsideAccess
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
catch (error) {
|
|
144
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
145
|
-
console.error(`Prividium proxy failed: ${message}`);
|
|
146
|
-
process.exit(1);
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"root":["../cli/base-cli.ts","../cli/index.ts","../cli/commands/config.ts","../cli/commands/doctor.ts","../cli/commands/proxy.ts","../cli/commands/doctor/constants.ts","../cli/commands/doctor/profile.ts","../cli/commands/doctor/stages.ts","../cli/commands/doctor/types.ts","../cli/commands/doctor/utils.ts","../cli/commands/doctor/clients/browser-auth.ts","../cli/commands/doctor/clients/http.ts","../cli/commands/doctor/clients/rpc.ts","../cli/commands/doctor/clients/wallet-api.ts","../cli/commands/doctor/probes/authentication.ts","../cli/commands/doctor/probes/bridging.ts","../cli/commands/doctor/probes/global.ts","../cli/commands/doctor/probes/wallet-api.ts","../cli/commands/doctor/probes/wallet.ts","../cli/commands/doctor/probes/authentication/authentication.ts","../cli/commands/doctor/probes/authentication/wallet-preconditions.ts","../cli/commands/doctor/probes/bridging/bridging.ts","../cli/commands/doctor/probes/global/input-validation.ts","../cli/commands/doctor/probes/global/reachability.ts","../cli/commands/doctor/probes/wallet/authenticated-rpc.ts","../cli/commands/doctor/probes/wallet/authorization-and-wallet-rpc.ts","../cli/commands/doctor/report/build.ts","../cli/commands/doctor/report/render.ts","../cli/commands/utils/show-prividium-header.ts","../cli/commands/utils/url-config.ts","../cli/server/config-file.ts","../cli/server/connection-workflow.ts","../cli/server/server.ts"],"version":"5.8.3"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|