prividium 0.3.1 β†’ 0.5.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 CHANGED
@@ -6,7 +6,8 @@ RPC and manages basic configuration.
6
6
 
7
7
  ## Features
8
8
 
9
- - πŸ” **Popup-based OAuth Authentication** - Secure authentication flow using popup windows
9
+ - πŸ” **Popup-based OAuth Authentication** - Secure authentication flow using popup windows (browser)
10
+ - πŸ”‘ **SIWE Backend Authentication** - Programmatic Sign-In with Ethereum for server-side use (`prividium/siwe`)
10
11
  - πŸ”‘ **JWT Token Management** - Automatic token storage, validation, and expiration handling
11
12
  - 🌐 **Viem Integration** - Drop-in transport for viem clients with automatic auth headers
12
13
  - πŸ› οΈ **CLI Proxy** - Local authenticated JSON-RPC proxy and simple config management
@@ -359,6 +360,72 @@ interface PrividiumClientConfig {
359
360
 
360
361
  **Returns:** `PublicClient` - Viem client instance.
361
362
 
363
+ ## SIWE Backend Authentication
364
+
365
+ For server-side or backend use cases, the SDK provides a separate entry point with programmatic SIWE (Sign-In with
366
+ Ethereum) authentication. Instead of a browser popup, you provide a viem account and the SDK handles the entire flow
367
+ automatically.
368
+
369
+ ### Quick Start (SIWE)
370
+
371
+ ```typescript
372
+ import { createPrividiumSiweChain } from 'prividium/siwe';
373
+ import { privateKeyToAccount } from 'viem/accounts';
374
+
375
+ const account = privateKeyToAccount('0xYOUR_PRIVATE_KEY');
376
+
377
+ const prividium = createPrividiumSiweChain({
378
+ account,
379
+ chain: { id: 7777, name: 'Prividiumβ„’ Chain' },
380
+ prividiumApiBaseUrl: 'https://permissions.prividium.io',
381
+ domain: 'my-backend.example.com',
382
+ onReauthenticate: () => console.log('Session automatically refreshed'),
383
+ onReauthenticateError: (err) => console.error('Re-auth failed:', err)
384
+ });
385
+
386
+ // Authenticate
387
+ await prividium.authorize();
388
+
389
+ // Make authenticated API calls
390
+ const user = await prividium.fetchUser();
391
+
392
+ // Transport automatically reauthenticates on session expiry
393
+ const balance = await client.getBalance({ address: prividium.address });
394
+ ```
395
+
396
+ ### `createPrividiumSiweChain(config)`
397
+
398
+ Creates an SDK instance with programmatic SIWE authentication.
399
+
400
+ **Parameters:**
401
+
402
+ ```typescript
403
+ interface PrividiumSiweConfig {
404
+ chain: Chain; // Viem chain configuration (without rpcUrls)
405
+ prividiumApiBaseUrl: string; // Permissions API service base URL
406
+ account: LocalAccount; // Viem account for signing (e.g. from privateKeyToAccount)
407
+ domain: string; // Domain for SIWE message
408
+ storage?: Storage; // Custom storage (defaults to MemoryStorage)
409
+ autoReauthenticate?: boolean; // Auto-reauth on session expiry (default: true)
410
+ onAuthExpiry?: () => void; // Called when auth expires and reauth is disabled/failed
411
+ onReauthenticate?: () => void; // Called after successful automatic reauthentication
412
+ onReauthenticateError?: (error: Error) => void; // Called when automatic reauthentication fails
413
+ }
414
+ ```
415
+
416
+ **Returns:** `PrividiumSiweChain` - with all the same methods as `PrividiumChain` (except `addNetworkToWallet` which is
417
+ browser-only), plus `address` (the wallet address derived from the account).
418
+
419
+ ### Auto-Reauthentication
420
+
421
+ When `autoReauthenticate` is `true` (default), the SDK automatically handles expired sessions:
422
+
423
+ 1. Before each API call, checks if the session is still valid
424
+ 2. On 401/403 responses, reauthenticates and retries the call once
425
+ 3. Concurrent reauth attempts are deduplicated (only one SIWE flow runs at a time)
426
+
427
+ Disable with `autoReauthenticate: false` to handle expiry manually via `onAuthExpiry`.
428
+
362
429
  ## Advanced Usage
363
430
 
364
431
  ### Custom Storage
@@ -0,0 +1,20 @@
1
+ import type { Chain } from 'viem';
2
+ import { z, type ZodType } from 'zod';
3
+ import { type AuthorizeTransactionParams, type AuthorizeTransactionResponse, type UserProfile } from './types.js';
4
+ export declare function rpcUrl(apiUrl: string): string;
5
+ export declare function walletRpcUrl(apiUrl: string, token: string): string;
6
+ export declare function buildChainObject(config: {
7
+ chain: Omit<Chain, 'rpcUrls'>;
8
+ prividiumApiBaseUrl: string;
9
+ }): Chain;
10
+ export type ApiCaller = <Schema extends ZodType>(schema: Schema, url: string, method: 'GET' | 'POST', body?: string) => Promise<z.infer<Schema>>;
11
+ export declare function createApiMethods(deps: {
12
+ prividiumApiCall: ApiCaller;
13
+ prividiumApiBaseUrl: string;
14
+ }): {
15
+ fetchUser(): Promise<UserProfile>;
16
+ getWalletToken(): Promise<string>;
17
+ getWalletRpcUrl(): Promise<string>;
18
+ invalidateWalletToken(): Promise<string>;
19
+ authorizeTransaction(params: AuthorizeTransactionParams): Promise<AuthorizeTransactionResponse>;
20
+ };
@@ -0,0 +1,50 @@
1
+ import { mainnet } from 'viem/chains';
2
+ import { z } from 'zod';
3
+ import { authorizeTransactionResponseSchema, profileSchema } from './types.js';
4
+ export function rpcUrl(apiUrl) {
5
+ return new URL('/rpc', apiUrl).toString();
6
+ }
7
+ export function walletRpcUrl(apiUrl, token) {
8
+ return new URL(`/rpc/wallet/${token}`, apiUrl).toString();
9
+ }
10
+ export function buildChainObject(config) {
11
+ return {
12
+ ...mainnet,
13
+ ...config.chain,
14
+ id: config.chain.id,
15
+ contracts: {
16
+ ...config.chain.contracts,
17
+ multicall3: undefined // Prividiumβ„’ doesn't support multicall yet
18
+ },
19
+ rpcUrls: { default: { http: [rpcUrl(config.prividiumApiBaseUrl)] } },
20
+ blockExplorers: config.chain.blockExplorers
21
+ };
22
+ }
23
+ export function createApiMethods(deps) {
24
+ const { prividiumApiCall, prividiumApiBaseUrl } = deps;
25
+ return {
26
+ async fetchUser() {
27
+ return await prividiumApiCall(profileSchema, `${prividiumApiBaseUrl}/api/profiles/me`, 'GET');
28
+ },
29
+ async getWalletToken() {
30
+ const { token } = await prividiumApiCall(z.object({ token: z.string() }), `${prividiumApiBaseUrl}/api/wallet/personal-rpc-token`, 'GET');
31
+ return token;
32
+ },
33
+ async getWalletRpcUrl() {
34
+ const walletToken = await this.getWalletToken();
35
+ return walletRpcUrl(prividiumApiBaseUrl, walletToken);
36
+ },
37
+ async invalidateWalletToken() {
38
+ const { newWalletToken } = await prividiumApiCall(z.object({ newWalletToken: z.string(), message: z.string() }), `${prividiumApiBaseUrl}/api/wallet/invalidate`, 'POST');
39
+ return newWalletToken;
40
+ },
41
+ async authorizeTransaction(params) {
42
+ return prividiumApiCall(authorizeTransactionResponseSchema, `${prividiumApiBaseUrl}/api/wallet/transaction-authorization`, 'POST', JSON.stringify({
43
+ ...params,
44
+ // Always pass calldata and value, even if undefined
45
+ calldata: params?.calldata ?? '0x',
46
+ value: params.value?.toString() ?? '0'
47
+ }));
48
+ }
49
+ };
50
+ }
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { UNAUTHORIZED_ERROR_CODE, FORBIDDEN_ERROR_CODE } from './rpc-error-codes.js';
2
+ import { UNAUTHORIZED_ERROR_CODE } from './rpc-error-codes.js';
3
3
  const jsonRpcErrorSchema = z.object({
4
4
  error: z.object({
5
5
  code: z.number(),
@@ -15,7 +15,7 @@ export async function hasPrividiumUnauthorizedError(response) {
15
15
  const parsed = jsonRpcErrorSchema.safeParse(await clonedResponse.json());
16
16
  // { success: false, error: {...} } | { success: true, data: {...} }
17
17
  if (parsed.success) {
18
- return [UNAUTHORIZED_ERROR_CODE, FORBIDDEN_ERROR_CODE].includes(parsed.data.error.code);
18
+ return parsed.data.error.code === UNAUTHORIZED_ERROR_CODE;
19
19
  }
20
20
  return false;
21
21
  }
@@ -0,0 +1,7 @@
1
+ import type { Storage } from './types.js';
2
+ export declare class MemoryStorage implements Storage {
3
+ private store;
4
+ getItem(key: string): string | null;
5
+ setItem(key: string, value: string): void;
6
+ removeItem(key: string): void;
7
+ }
@@ -0,0 +1,12 @@
1
+ export class MemoryStorage {
2
+ store = new Map();
3
+ getItem(key) {
4
+ return this.store.get(key) ?? null;
5
+ }
6
+ setItem(key, value) {
7
+ this.store.set(key, value);
8
+ }
9
+ removeItem(key) {
10
+ this.store.delete(key);
11
+ }
12
+ }
@@ -1,4 +1,4 @@
1
- import { type PrividiumChain, type PrividiumConfig } from './types.js';
1
+ import type { PrividiumChain, PrividiumConfig } from './types.js';
2
2
  declare global {
3
3
  interface Window {
4
4
  ethereum?: {
@@ -1,17 +1,9 @@
1
1
  import { http } from 'viem';
2
- import { mainnet } from 'viem/chains';
3
- import { authorizeTransactionResponseSchema, profileSchema } from './types.js';
4
2
  import { LocalStorage, TokenManager } from './storage.js';
5
3
  import { PopupAuth } from './popup-auth.js';
6
4
  import { hasPrividiumUnauthorizedError } from './error-utils.js';
7
- import { PrividiumSessionError } from './errors';
8
- import { z } from 'zod';
9
- function rpcUrl(apiUrl) {
10
- return new URL('/rpc', apiUrl).toString();
11
- }
12
- function walletRpcUrl(apiUrl, token) {
13
- return new URL(`/rpc/wallet/${token}`, apiUrl).toString();
14
- }
5
+ import { PrividiumSessionError } from './errors.js';
6
+ import { buildChainObject, createApiMethods, rpcUrl } from './chain-core.js';
15
7
  export function createPrividiumChain(config) {
16
8
  if (config.permissionsApiBaseUrl !== undefined) {
17
9
  throw new Error('"permissionsApiBaseUrl" was deprecated. Please use "prividiumApiBaseUrl" instead.');
@@ -46,7 +38,7 @@ export function createPrividiumChain(config) {
46
38
  },
47
39
  ...(body && { body })
48
40
  });
49
- if (response.status === 403 || response.status === 401) {
41
+ if (response.status === 401) {
50
42
  tokenManager.clearToken();
51
43
  config.onAuthExpiry?.();
52
44
  throw new PrividiumSessionError();
@@ -84,18 +76,9 @@ export function createPrividiumChain(config) {
84
76
  }
85
77
  }
86
78
  });
79
+ const apiMethods = createApiMethods({ prividiumApiCall, prividiumApiBaseUrl: config.prividiumApiBaseUrl });
87
80
  return {
88
- chain: {
89
- ...mainnet,
90
- ...config.chain,
91
- id: config.chain.id,
92
- contracts: {
93
- ...config.chain.contracts,
94
- multicall3: undefined // Prividiumβ„’ doesn't support multicall yet
95
- },
96
- rpcUrls: { default: { http: [rpcUrl(config.prividiumApiBaseUrl)] } },
97
- blockExplorers: config.chain.blockExplorers
98
- },
81
+ chain: buildChainObject(config),
99
82
  transport,
100
83
  async authorize(options) {
101
84
  return popupAuth.authorize(options);
@@ -107,29 +90,11 @@ export function createPrividiumChain(config) {
107
90
  return popupAuth.isAuthorized();
108
91
  },
109
92
  getAuthHeaders,
110
- async fetchUser() {
111
- return await prividiumApiCall(profileSchema, `${config.prividiumApiBaseUrl}/api/profiles/me`, 'GET');
112
- },
113
- async getWalletToken() {
114
- const { token } = await prividiumApiCall(z.object({ token: z.string() }), `${config.prividiumApiBaseUrl}/api/wallet/personal-rpc-token`, 'GET');
115
- return token;
116
- },
117
- async getWalletRpcUrl() {
118
- const walletToken = await this.getWalletToken();
119
- return walletRpcUrl(config.prividiumApiBaseUrl, walletToken);
120
- },
121
- async invalidateWalletToken() {
122
- const { newWalletToken } = await prividiumApiCall(z.object({ newWalletToken: z.string(), message: z.string() }), `${config.prividiumApiBaseUrl}/api/wallet/invalidate`, 'POST');
123
- return newWalletToken;
124
- },
125
- async authorizeTransaction(params) {
126
- return prividiumApiCall(authorizeTransactionResponseSchema, `${config.prividiumApiBaseUrl}/api/wallet/transaction-authorization`, 'POST', JSON.stringify({
127
- ...params,
128
- // Always pass calldata and value, even if undefined
129
- calldata: params?.calldata ?? '0x',
130
- value: params.value?.toString() ?? '0'
131
- }));
132
- },
93
+ fetchUser: apiMethods.fetchUser,
94
+ getWalletToken: apiMethods.getWalletToken,
95
+ getWalletRpcUrl: apiMethods.getWalletRpcUrl,
96
+ invalidateWalletToken: apiMethods.invalidateWalletToken,
97
+ authorizeTransaction: apiMethods.authorizeTransaction,
133
98
  async addNetworkToWallet(params) {
134
99
  if (typeof window === 'undefined' || !window.ethereum) {
135
100
  throw new Error('Wallet not detected. Please install a wallet extension to add network.');
@@ -0,0 +1,17 @@
1
+ import type { Address, LocalAccount } from 'viem';
2
+ import type { TokenManager } from './storage.js';
3
+ import type { TokenData } from './types.js';
4
+ export interface SiweAuthConfig {
5
+ account: LocalAccount;
6
+ prividiumApiBaseUrl: string;
7
+ domain: string;
8
+ tokenManager: TokenManager;
9
+ }
10
+ export declare class SiweAuth {
11
+ private config;
12
+ constructor(config: SiweAuthConfig);
13
+ get address(): Address;
14
+ authorize(): Promise<TokenData>;
15
+ unauthorize(): void;
16
+ isAuthorized(): boolean;
17
+ }
@@ -0,0 +1,68 @@
1
+ import { z } from 'zod';
2
+ const siweMessageResponseSchema = z.object({
3
+ msg: z.string()
4
+ });
5
+ const siweLoginResponseSchema = z.object({
6
+ token: z.string(),
7
+ expiresAt: z.string()
8
+ });
9
+ const mfaResponseSchema = z.object({
10
+ requiresMfa: z.literal(true)
11
+ });
12
+ export class SiweAuth {
13
+ config;
14
+ constructor(config) {
15
+ this.config = config;
16
+ }
17
+ get address() {
18
+ return this.config.account.address;
19
+ }
20
+ async authorize() {
21
+ // Step 1: Request SIWE message
22
+ const siweMessageUrl = new URL('/api/siwe-messages', this.config.prividiumApiBaseUrl).toString();
23
+ const siweResponse = await fetch(siweMessageUrl, {
24
+ method: 'POST',
25
+ headers: { 'Content-Type': 'application/json' },
26
+ body: JSON.stringify({
27
+ address: this.config.account.address,
28
+ domain: this.config.domain
29
+ })
30
+ });
31
+ if (!siweResponse.ok) {
32
+ throw new Error(`Failed to get SIWE message: ${siweResponse.status} ${siweResponse.statusText}`);
33
+ }
34
+ const siweData = siweMessageResponseSchema.parse(await siweResponse.json());
35
+ // Step 2: Sign the message
36
+ const signature = await this.config.account.signMessage({ message: siweData.msg });
37
+ // Step 3: Login
38
+ const loginUrl = new URL('/auth/login/crypto-native', this.config.prividiumApiBaseUrl).toString();
39
+ const loginResponse = await fetch(loginUrl, {
40
+ method: 'POST',
41
+ headers: { 'Content-Type': 'application/json' },
42
+ body: JSON.stringify({ message: siweData.msg, signature })
43
+ });
44
+ if (!loginResponse.ok) {
45
+ throw new Error(`SIWE login failed: ${loginResponse.status} ${loginResponse.statusText}`);
46
+ }
47
+ const loginJson = await loginResponse.json();
48
+ // Check for MFA requirement (admin users with passkeys)
49
+ const mfaParsed = mfaResponseSchema.safeParse(loginJson);
50
+ if (mfaParsed.success) {
51
+ throw new Error('SIWE login requires MFA which is not supported in programmatic auth');
52
+ }
53
+ const loginData = siweLoginResponseSchema.parse(loginJson);
54
+ // Step 4: Store token directly (login response includes expiresAt)
55
+ const tokenData = {
56
+ rawToken: loginData.token,
57
+ expiresAt: new Date(loginData.expiresAt)
58
+ };
59
+ this.config.tokenManager.setTokenDirect(tokenData);
60
+ return tokenData;
61
+ }
62
+ unauthorize() {
63
+ this.config.tokenManager.clearToken();
64
+ }
65
+ isAuthorized() {
66
+ return this.config.tokenManager.isAuthorized();
67
+ }
68
+ }
@@ -0,0 +1,28 @@
1
+ import { type Address, type Chain, type LocalAccount, type Transport } from 'viem';
2
+ import type { AuthorizeTransactionParams, AuthorizeTransactionResponse, Storage, TokenData, UserProfile } from './types.js';
3
+ export interface PrividiumSiweConfig {
4
+ chain: Omit<Chain, 'rpcUrls'>;
5
+ prividiumApiBaseUrl: string;
6
+ account: LocalAccount;
7
+ domain: string;
8
+ storage?: Storage;
9
+ autoReauthenticate?: boolean;
10
+ onAuthExpiry?: () => void;
11
+ onReauthenticate?: () => void;
12
+ onReauthenticateError?: (error: Error) => void;
13
+ }
14
+ export interface PrividiumSiweChain {
15
+ chain: Chain;
16
+ transport: Transport;
17
+ address: Address;
18
+ authorize(): Promise<TokenData>;
19
+ unauthorize(): void;
20
+ isAuthorized(): boolean;
21
+ getAuthHeaders(): Record<string, string> | null;
22
+ fetchUser(): Promise<UserProfile>;
23
+ getWalletToken(): Promise<string>;
24
+ getWalletRpcUrl(): Promise<string>;
25
+ invalidateWalletToken(): Promise<string>;
26
+ authorizeTransaction(params: AuthorizeTransactionParams): Promise<AuthorizeTransactionResponse>;
27
+ }
28
+ export declare function createPrividiumSiweChain(config: PrividiumSiweConfig): PrividiumSiweChain;
@@ -0,0 +1,166 @@
1
+ import { http } from 'viem';
2
+ import { TokenManager } from './storage.js';
3
+ import { MemoryStorage } from './memory-storage.js';
4
+ import { SiweAuth } from './siwe-auth.js';
5
+ import { hasPrividiumUnauthorizedError } from './error-utils.js';
6
+ import { PrividiumSessionError } from './errors.js';
7
+ import { buildChainObject, createApiMethods, rpcUrl } from './chain-core.js';
8
+ export function createPrividiumSiweChain(config) {
9
+ const autoReauth = config.autoReauthenticate ?? true;
10
+ const storage = config.storage ?? new MemoryStorage();
11
+ const tokenManager = new TokenManager(storage, config.chain.id, config.prividiumApiBaseUrl, config.onAuthExpiry);
12
+ const siweAuth = new SiweAuth({
13
+ account: config.account,
14
+ prividiumApiBaseUrl: config.prividiumApiBaseUrl,
15
+ domain: config.domain,
16
+ tokenManager
17
+ });
18
+ // Deduplication: only one reauthentication flow at a time
19
+ let reauthPromise = null;
20
+ async function reauthenticate() {
21
+ if (reauthPromise) {
22
+ return reauthPromise;
23
+ }
24
+ reauthPromise = (async () => {
25
+ try {
26
+ const tokenData = await siweAuth.authorize();
27
+ config.onReauthenticate?.();
28
+ return tokenData;
29
+ }
30
+ catch (error) {
31
+ const err = error instanceof Error ? error : new Error(String(error));
32
+ config.onReauthenticateError?.(err);
33
+ throw err;
34
+ }
35
+ finally {
36
+ reauthPromise = null;
37
+ }
38
+ })();
39
+ return reauthPromise;
40
+ }
41
+ async function ensureAuthorized() {
42
+ if (!tokenManager.isAuthorized() && autoReauth) {
43
+ await reauthenticate();
44
+ }
45
+ if (!tokenManager.isAuthorized()) {
46
+ throw new PrividiumSessionError();
47
+ }
48
+ }
49
+ const getAuthHeaders = () => {
50
+ const tokenData = tokenManager.getToken();
51
+ if (!tokenData) {
52
+ return null;
53
+ }
54
+ return {
55
+ Authorization: `Bearer ${tokenData.rawToken}`
56
+ };
57
+ };
58
+ async function prividiumApiCall(schema, url, method, body) {
59
+ await ensureAuthorized();
60
+ const headers = getAuthHeaders();
61
+ if (!headers) {
62
+ throw new PrividiumSessionError();
63
+ }
64
+ const response = await fetch(url, {
65
+ method,
66
+ headers: {
67
+ 'Content-Type': 'application/json',
68
+ ...headers
69
+ },
70
+ ...(body && { body })
71
+ });
72
+ if (response.status === 401) {
73
+ tokenManager.clearToken();
74
+ // Attempt reauthentication and retry once
75
+ if (autoReauth) {
76
+ try {
77
+ await reauthenticate();
78
+ const retryHeaders = getAuthHeaders();
79
+ if (!retryHeaders)
80
+ throw new PrividiumSessionError();
81
+ const retryResponse = await fetch(url, {
82
+ method,
83
+ headers: { 'Content-Type': 'application/json', ...retryHeaders },
84
+ ...(body && { body })
85
+ });
86
+ if (!retryResponse.ok) {
87
+ config.onAuthExpiry?.();
88
+ throw new PrividiumSessionError();
89
+ }
90
+ const parsed = schema.safeParse(await retryResponse.json());
91
+ if (!parsed.success) {
92
+ throw new Error(`Unexpected api response calling ${url}`);
93
+ }
94
+ return parsed.data;
95
+ }
96
+ catch {
97
+ config.onAuthExpiry?.();
98
+ throw new PrividiumSessionError();
99
+ }
100
+ }
101
+ config.onAuthExpiry?.();
102
+ throw new PrividiumSessionError();
103
+ }
104
+ if (!response.ok) {
105
+ throw new Error(`Error calling ${url}: ${response.status} ${response.statusText}`);
106
+ }
107
+ const parsed = schema.safeParse(await response.json());
108
+ if (!parsed.success) {
109
+ throw new Error(`Unexpected api response calling ${url}`);
110
+ }
111
+ return parsed.data;
112
+ }
113
+ // Create transport with auth integration using viem callbacks
114
+ const transport = http(rpcUrl(config.prividiumApiBaseUrl), {
115
+ batch: false,
116
+ fetchOptions: {
117
+ headers: getAuthHeaders() || {}
118
+ },
119
+ onFetchRequest(_request, init) {
120
+ if (!tokenManager.isAuthorized()) {
121
+ throw new PrividiumSessionError();
122
+ }
123
+ init.headers = {
124
+ ...init.headers,
125
+ ...getAuthHeaders()
126
+ };
127
+ },
128
+ onFetchResponse: async (response) => {
129
+ if (await hasPrividiumUnauthorizedError(response)) {
130
+ tokenManager.clearToken();
131
+ if (autoReauth) {
132
+ try {
133
+ await reauthenticate();
134
+ }
135
+ catch {
136
+ config.onAuthExpiry?.();
137
+ }
138
+ }
139
+ else {
140
+ config.onAuthExpiry?.();
141
+ }
142
+ }
143
+ }
144
+ });
145
+ const apiMethods = createApiMethods({ prividiumApiCall, prividiumApiBaseUrl: config.prividiumApiBaseUrl });
146
+ return {
147
+ chain: buildChainObject(config),
148
+ transport,
149
+ address: config.account.address,
150
+ async authorize() {
151
+ return siweAuth.authorize();
152
+ },
153
+ unauthorize() {
154
+ siweAuth.unauthorize();
155
+ },
156
+ isAuthorized() {
157
+ return siweAuth.isAuthorized();
158
+ },
159
+ getAuthHeaders,
160
+ fetchUser: apiMethods.fetchUser,
161
+ getWalletToken: apiMethods.getWalletToken,
162
+ getWalletRpcUrl: apiMethods.getWalletRpcUrl,
163
+ invalidateWalletToken: apiMethods.invalidateWalletToken,
164
+ authorizeTransaction: apiMethods.authorizeTransaction
165
+ };
166
+ }
@@ -0,0 +1,11 @@
1
+ export { createPrividiumSiweChain } from './siwe-chain.js';
2
+ export type { PrividiumSiweConfig, PrividiumSiweChain } from './siwe-chain.js';
3
+ export { SiweAuth } from './siwe-auth.js';
4
+ export type { SiweAuthConfig } from './siwe-auth.js';
5
+ export { MemoryStorage } from './memory-storage.js';
6
+ export { TokenManager } from './storage.js';
7
+ export type { Storage, TokenData } from './types.js';
8
+ export { createPrividiumClient } from './create-prividium-client.js';
9
+ export type { UserProfile, UserRole, AuthorizeTransactionParams, AuthorizeTransactionResponse } from './types.js';
10
+ export { AUTH_ERRORS } from './types.js';
11
+ export { UNAUTHORIZED_ERROR_CODE, FORBIDDEN_ERROR_CODE } from './rpc-error-codes.js';
@@ -0,0 +1,11 @@
1
+ // Core factory + types
2
+ export { createPrividiumSiweChain } from './siwe-chain.js';
3
+ // Auth strategy
4
+ export { SiweAuth } from './siwe-auth.js';
5
+ // Storage (MemoryStorage is the default for SIWE, but expose both + interface)
6
+ export { MemoryStorage } from './memory-storage.js';
7
+ export { TokenManager } from './storage.js';
8
+ // Viem client (reusable with SIWE chain)
9
+ export { createPrividiumClient } from './create-prividium-client.js';
10
+ export { AUTH_ERRORS } from './types.js';
11
+ export { UNAUTHORIZED_ERROR_CODE, FORBIDDEN_ERROR_CODE } from './rpc-error-codes.js';
@@ -16,6 +16,11 @@ export declare class TokenManager {
16
16
  getToken(): TokenData | null;
17
17
  private getTokenExpiration;
18
18
  setToken(rawToken: string): Promise<TokenData>;
19
+ /**
20
+ * Stores token data directly without fetching expiration from the API.
21
+ * Used by SIWE auth where the login response already includes expiresAt.
22
+ */
23
+ setTokenDirect(tokenData: TokenData): void;
19
24
  clearToken(): void;
20
25
  isAuthorized(): boolean;
21
26
  setState(state: string): void;
@@ -106,6 +106,14 @@ export class TokenManager {
106
106
  throw error;
107
107
  }
108
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
+ }
109
117
  clearToken() {
110
118
  this.tokenCache = null;
111
119
  this.storage.removeItem(this.tokenKey);
@@ -1 +1 @@
1
- {"root":["../src/create-prividium-client.ts","../src/error-utils.ts","../src/errors.ts","../src/index.ts","../src/popup-auth.ts","../src/prividium-chain.ts","../src/rpc-error-codes.ts","../src/storage.ts","../src/test-utils.ts","../src/token-utils.ts","../src/types.ts"],"version":"5.8.3"}
1
+ {"root":["../src/chain-core.ts","../src/create-prividium-client.ts","../src/error-utils.ts","../src/errors.ts","../src/index.ts","../src/memory-storage.ts","../src/popup-auth.ts","../src/prividium-chain.ts","../src/rpc-error-codes.ts","../src/siwe-auth.ts","../src/siwe-chain.ts","../src/siwe.ts","../src/storage.ts","../src/test-utils.ts","../src/token-utils.ts","../src/types.ts"],"version":"5.8.3"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prividium",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "bin": {
5
5
  "prividium": "bin/cli.js"
6
6
  },
@@ -8,6 +8,10 @@
8
8
  ".": {
9
9
  "import": "./dist/sdk/index.js",
10
10
  "types": "./dist/sdk/index.d.ts"
11
+ },
12
+ "./siwe": {
13
+ "import": "./dist/sdk/siwe.js",
14
+ "types": "./dist/sdk/siwe.d.ts"
11
15
  }
12
16
  },
13
17
  "license": "MIT OR Apache-2.0",