prividium 0.1.4 → 0.1.6
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 +67 -13
- package/dist/cli/commands/proxy.js +35 -5
- package/dist/cli/server/server.js +14 -5
- package/dist/sdk/create-prividium-client.d.ts +8 -0
- package/dist/sdk/create-prividium-client.js +25 -0
- package/dist/sdk/index.d.ts +1 -0
- package/dist/sdk/index.js +1 -0
- package/dist/sdk/prividium-chain.d.ts +1 -1
- package/dist/sdk/prividium-chain.js +9 -4
- package/dist/sdk/types.d.ts +19 -6
- package/dist/tsconfig.sdk.tsbuildinfo +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -62,16 +62,22 @@ const prividium = createPrividiumChain({
|
|
|
62
62
|
});
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
### 2. Create Viem Client
|
|
65
|
+
### 2. Create Prividium™ Viem Client
|
|
66
66
|
|
|
67
67
|
```typescript
|
|
68
|
+
import { createPrividiumClient } from 'prividium';
|
|
69
|
+
|
|
68
70
|
// The SDK provides a pre-configured transport with automatic auth headers
|
|
69
|
-
const client =
|
|
71
|
+
const client = createPrividiumClient({
|
|
70
72
|
chain: prividium.chain,
|
|
71
|
-
transport: prividium.transport // ✨ Auth headers are automatically included!
|
|
73
|
+
transport: prividium.transport, // ✨ Auth headers are automatically included!
|
|
74
|
+
account: '0x...' // 🔐 Provide user account to make `eth_call`s from that address
|
|
72
75
|
});
|
|
73
76
|
```
|
|
74
77
|
|
|
78
|
+
**Note:** Providing the account is required only for read operations that use `eth_call`. Prividium™ needs to know the
|
|
79
|
+
caller address to enforce permissions correctly.
|
|
80
|
+
|
|
75
81
|
### 3. Authenticate and Use
|
|
76
82
|
|
|
77
83
|
```typescript
|
|
@@ -87,7 +93,35 @@ const balance = await client.getBalance({
|
|
|
87
93
|
});
|
|
88
94
|
```
|
|
89
95
|
|
|
90
|
-
### 4.
|
|
96
|
+
### 4. Reading contract data
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import { createContract } from 'viem';
|
|
100
|
+
// Define contract
|
|
101
|
+
const greeterContract = createContract({
|
|
102
|
+
address: '0x...',
|
|
103
|
+
abi: [
|
|
104
|
+
{
|
|
105
|
+
name: 'getGreeting',
|
|
106
|
+
type: 'function',
|
|
107
|
+
inputs: [],
|
|
108
|
+
outputs: [{ name: '', type: 'string' }],
|
|
109
|
+
stateMutability: 'view'
|
|
110
|
+
}
|
|
111
|
+
],
|
|
112
|
+
client: client
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Read data
|
|
116
|
+
if (!client.account) {
|
|
117
|
+
console.warn('Client account is not set. Connect wallet.');
|
|
118
|
+
} else {
|
|
119
|
+
const greeting = await greeterContract.read.getGreeting();
|
|
120
|
+
console.log('Greeting:', greeting);
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 5. Sending Transactions with Injected Wallets (MetaMask)
|
|
91
125
|
|
|
92
126
|
Before sending transactions through injected wallets, you need to add the Prividium™ network and enable wallet RPC for
|
|
93
127
|
each transaction.
|
|
@@ -121,26 +155,28 @@ const request = await walletClient.prepareTransactionRequest({
|
|
|
121
155
|
}
|
|
122
156
|
],
|
|
123
157
|
functionName: 'setGreeting',
|
|
124
|
-
args: ['Hello, Prividium!']
|
|
158
|
+
args: ['Hello, Prividium!'],
|
|
159
|
+
value: 0n // Optional ETH value to send
|
|
125
160
|
})
|
|
126
161
|
});
|
|
127
162
|
|
|
128
|
-
//
|
|
129
|
-
await prividium.
|
|
163
|
+
// Authorize transaction
|
|
164
|
+
await prividium.authorizeTransaction({
|
|
130
165
|
walletAddress: address,
|
|
131
166
|
contractAddress: greeterContract,
|
|
132
167
|
nonce: Number(request.nonce),
|
|
133
|
-
calldata: request.data
|
|
168
|
+
calldata: request.data,
|
|
169
|
+
value: request.value
|
|
134
170
|
});
|
|
135
171
|
|
|
136
172
|
// Send transaction through MetaMask
|
|
137
173
|
const hash = await walletClient.sendTransaction(request);
|
|
138
174
|
```
|
|
139
175
|
|
|
140
|
-
**Note:** Call `
|
|
141
|
-
hour.
|
|
176
|
+
**Note:** Call `authorizeTransaction(...)` before each transaction. Permission is transaction-specific and expires after
|
|
177
|
+
1 hour.
|
|
142
178
|
|
|
143
|
-
###
|
|
179
|
+
### 6. Setup OAuth Callback Page
|
|
144
180
|
|
|
145
181
|
The SDK requires a callback page to complete the authentication flow securely using `postMessage`. Create a callback
|
|
146
182
|
page at the `redirectUrl` you configured:
|
|
@@ -246,8 +282,8 @@ Opens authentication popup and handles OAuth flow.
|
|
|
246
282
|
|
|
247
283
|
```typescript
|
|
248
284
|
await prividium.authorize({
|
|
249
|
-
popupSize: { w: 600, h: 700 } // Optional custom popup dimensions
|
|
250
|
-
scopes: ['wallet:required', 'network:required']
|
|
285
|
+
popupSize: { w: 600, h: 700 }, // Optional custom popup dimensions
|
|
286
|
+
scopes: ['wallet:required', 'network:required'] // Optional scope requests
|
|
251
287
|
});
|
|
252
288
|
```
|
|
253
289
|
|
|
@@ -307,6 +343,23 @@ handleAuthCallback((error) => {
|
|
|
307
343
|
- Automatically closes popup window on success
|
|
308
344
|
- Calls `onError` if any errors occur
|
|
309
345
|
|
|
346
|
+
### `createPrividiumClient(config)`
|
|
347
|
+
|
|
348
|
+
Creates a viem client.
|
|
349
|
+
|
|
350
|
+
**Parameters:**
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
interface PrividiumClientConfig {
|
|
354
|
+
chain: Chain; // Viem chain configuration
|
|
355
|
+
transport: Transport; // Viem transport with Prividium™ auth headers
|
|
356
|
+
account?: Address; // Optional user account for eth_call operations
|
|
357
|
+
// Other viem client config options...
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
**Returns:** `PublicClient` - Viem client instance.
|
|
362
|
+
|
|
310
363
|
## Advanced Usage
|
|
311
364
|
|
|
312
365
|
### Custom Storage
|
|
@@ -446,6 +499,7 @@ Flags:
|
|
|
446
499
|
- `--host, -h` (string, default `127.0.0.1`): host binded to server. By default only connections comming from local
|
|
447
500
|
device will be accepted. WARNING: Using 0.0.0.0 implies allowing anyone in the local network to use your credentials.
|
|
448
501
|
- `--config-path, -c` (string): Path to the CLI config file.
|
|
502
|
+
- `--unsecure-allow-outside-access`: Needed to expose the proxy to any network (including local network).
|
|
449
503
|
|
|
450
504
|
Environment variables (optional):
|
|
451
505
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { buildServer } from '../server/server.js';
|
|
2
|
+
import { log } from '@clack/prompts';
|
|
3
|
+
import color from 'kleur';
|
|
2
4
|
import { CreationWorkflow } from '../server/connection-workflow.js';
|
|
3
5
|
import { ConfigFile } from '../server/config-file.js';
|
|
4
6
|
import { z } from 'zod';
|
|
@@ -6,6 +8,24 @@ const envSchema = z.object({
|
|
|
6
8
|
PRIVIDIUM_RPC_URL: z.string().optional(),
|
|
7
9
|
USER_PANEL_URL: z.string().optional()
|
|
8
10
|
});
|
|
11
|
+
const DEFAULT_PORT = 24101;
|
|
12
|
+
function checkHostAndPortWarnings(host, port, allowExternalAccess) {
|
|
13
|
+
if (port !== DEFAULT_PORT) {
|
|
14
|
+
log.warn(`Non standard port detected: ${port}. Redirect from prividium auth might not work.`);
|
|
15
|
+
}
|
|
16
|
+
if (host !== '127.0.0.1' && host !== 'localhost') {
|
|
17
|
+
if (!allowExternalAccess) {
|
|
18
|
+
log.error(`${color.bold('ERROR')}: In order to use a host different than local host you need to set --unsecureAllowOutsideAccess flag.`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
if (host === '0.0.0.0') {
|
|
22
|
+
log.warn(`${color.bold('WARNING')}: Your local proxy will be exposed outside your current device.`);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
log.warn(`${color.bold('WARNING')}: Non standard host: ${host}. Your proxy might be open for other devices. Redirect from prividium auth might not work.`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
9
29
|
async function startServer(opts) {
|
|
10
30
|
const config = new ConfigFile(opts.configPath);
|
|
11
31
|
const workflow = new CreationWorkflow(config);
|
|
@@ -18,6 +38,8 @@ async function startServer(opts) {
|
|
|
18
38
|
const app = buildServer({
|
|
19
39
|
prividiumRpcUrl,
|
|
20
40
|
userPanelUrl,
|
|
41
|
+
host: opts.host,
|
|
42
|
+
port: opts.port,
|
|
21
43
|
async onSubmit() {
|
|
22
44
|
await workflow.onSubmit();
|
|
23
45
|
},
|
|
@@ -25,9 +47,10 @@ async function startServer(opts) {
|
|
|
25
47
|
workflow.onMessage(methodName);
|
|
26
48
|
}
|
|
27
49
|
});
|
|
50
|
+
checkHostAndPortWarnings(opts.host, opts.port, opts.allowExternalAccess);
|
|
28
51
|
const serverUrl = await app.listen({
|
|
29
|
-
port:
|
|
30
|
-
host:
|
|
52
|
+
port: opts.port,
|
|
53
|
+
host: opts.host
|
|
31
54
|
});
|
|
32
55
|
await workflow.waitForAuthentication(serverUrl);
|
|
33
56
|
}
|
|
@@ -53,19 +76,26 @@ export const addProxy = (cli) => {
|
|
|
53
76
|
.option('port', {
|
|
54
77
|
alias: ['p'],
|
|
55
78
|
description: 'Port used for local proxy. This has to match with the port configured in your Prividium™ network.',
|
|
56
|
-
default:
|
|
79
|
+
default: DEFAULT_PORT,
|
|
57
80
|
type: 'number'
|
|
58
81
|
})
|
|
59
82
|
.option('host', {
|
|
60
83
|
alias: 'h',
|
|
61
84
|
description: 'Host used for local server. By default traffic from outside localhost is disabled.',
|
|
62
|
-
default: '
|
|
85
|
+
default: 'localhost',
|
|
63
86
|
type: 'string'
|
|
87
|
+
})
|
|
88
|
+
.option('unsecureAllowOutsideAccess', {
|
|
89
|
+
alias: ['unsecure-allow-outside-access'],
|
|
90
|
+
description: 'Allow server to be exposed to the network (accessible by other devices)',
|
|
91
|
+
default: false,
|
|
92
|
+
type: 'boolean'
|
|
64
93
|
}), (args) => startServer({
|
|
65
94
|
rpcUrl: args.rpcUrl,
|
|
66
95
|
userPanelUrl: args.userPanelUrl,
|
|
67
96
|
configPath: args.configPath,
|
|
68
97
|
port: args.port,
|
|
69
|
-
host: args.host
|
|
98
|
+
host: args.host,
|
|
99
|
+
allowExternalAccess: args.unsecureAllowOutsideAccess
|
|
70
100
|
}));
|
|
71
101
|
};
|
|
@@ -5,6 +5,7 @@ import path from 'node:path';
|
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
import { fastifyHttpProxy } from '@fastify/http-proxy';
|
|
7
7
|
import { randomBytes } from 'node:crypto';
|
|
8
|
+
import { log } from '@clack/prompts';
|
|
8
9
|
function fastifyApp() {
|
|
9
10
|
return Fastify().withTypeProvider();
|
|
10
11
|
}
|
|
@@ -17,7 +18,7 @@ export function buildServer(config) {
|
|
|
17
18
|
const app = fastifyApp();
|
|
18
19
|
app.setValidatorCompiler(validatorCompiler);
|
|
19
20
|
const state = randomStateString();
|
|
20
|
-
let
|
|
21
|
+
let accessToken = '';
|
|
21
22
|
app.register(fastifyStatic, { root: path.join(import.meta.dirname, '..', 'static') });
|
|
22
23
|
app.get('/health', async (_req, reply) => {
|
|
23
24
|
return reply.send('ok');
|
|
@@ -49,7 +50,7 @@ export function buildServer(config) {
|
|
|
49
50
|
if (req.body.state !== state) {
|
|
50
51
|
throw new Error('invalid state received');
|
|
51
52
|
}
|
|
52
|
-
|
|
53
|
+
accessToken = req.body.token;
|
|
53
54
|
await config.onSubmit();
|
|
54
55
|
return reply.send('ok');
|
|
55
56
|
});
|
|
@@ -57,6 +58,7 @@ export function buildServer(config) {
|
|
|
57
58
|
upstream: config.prividiumRpcUrl,
|
|
58
59
|
prefix: '/rpc',
|
|
59
60
|
rewritePrefix: '/rpc',
|
|
61
|
+
httpMethods: ['POST'],
|
|
60
62
|
routes: ['/'],
|
|
61
63
|
preValidation: (request, _reply, done) => {
|
|
62
64
|
const method = rpcReqSchema.safeParse(request.body);
|
|
@@ -71,17 +73,24 @@ export function buildServer(config) {
|
|
|
71
73
|
}
|
|
72
74
|
done();
|
|
73
75
|
},
|
|
74
|
-
preHandler: (
|
|
75
|
-
if (
|
|
76
|
+
preHandler: (req, reply, done) => {
|
|
77
|
+
if (accessToken === '') {
|
|
76
78
|
reply.status(500).send('please authenticate first.');
|
|
77
79
|
return;
|
|
78
80
|
}
|
|
81
|
+
const portStr = config.port !== 80 ? `:${config.port}` : '';
|
|
82
|
+
const fullHost = `${config.host}${portStr}`;
|
|
83
|
+
if (req.headers.host && req.headers.host !== fullHost) {
|
|
84
|
+
log.error(`Expected host ${fullHost} but got ${req.headers.host}`);
|
|
85
|
+
reply.status(403).send("host doesn't match");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
79
88
|
return done();
|
|
80
89
|
},
|
|
81
90
|
replyOptions: {
|
|
82
91
|
rewriteRequestHeaders: (_originalReq, headers) => ({
|
|
83
92
|
...headers,
|
|
84
|
-
authorization: `Bearer ${
|
|
93
|
+
authorization: `Bearer ${accessToken}`
|
|
85
94
|
})
|
|
86
95
|
}
|
|
87
96
|
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Account, type Chain, type ClientConfig, type PublicClient, type PublicClientConfig, type RpcSchema, type Transport } from 'viem';
|
|
2
|
+
type PrividiumClientConfig<transport extends Transport = Transport, chain extends Chain | undefined = Chain | undefined, accountOrAddress extends Account | undefined = undefined, rpcSchema extends RpcSchema | undefined = undefined> = PublicClientConfig<transport, chain, accountOrAddress, rpcSchema> & Pick<ClientConfig<transport, chain, accountOrAddress, rpcSchema>, 'account'>;
|
|
3
|
+
/**
|
|
4
|
+
* Creates a Prividium specific Public Client. This client extends the standard Viem Public Client
|
|
5
|
+
* with additional checks required for Prividium operations.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createPrividiumClient<transport extends Transport = Transport, chain extends Chain | undefined = Chain | undefined, accountOrAddress extends Account | undefined = undefined, rpcSchema extends RpcSchema | undefined = undefined>(config: PrividiumClientConfig<transport, chain, accountOrAddress, rpcSchema>): PublicClient<transport, chain, accountOrAddress, rpcSchema>;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createClient, publicActions } from 'viem';
|
|
2
|
+
function prividiumActions(client) {
|
|
3
|
+
return {
|
|
4
|
+
call: (args) => {
|
|
5
|
+
if (!client.account || !client.account.address) {
|
|
6
|
+
throw new Error('RPC method eth_call requires an account to be provided for the client');
|
|
7
|
+
}
|
|
8
|
+
return client.call(args);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Creates a Prividium specific Public Client. This client extends the standard Viem Public Client
|
|
14
|
+
* with additional checks required for Prividium operations.
|
|
15
|
+
*/
|
|
16
|
+
export function createPrividiumClient(config) {
|
|
17
|
+
const { key = 'prividium', name = 'Prividium™ Public Client' } = config;
|
|
18
|
+
const client = createClient({
|
|
19
|
+
...config,
|
|
20
|
+
key,
|
|
21
|
+
name,
|
|
22
|
+
type: 'publicClient'
|
|
23
|
+
});
|
|
24
|
+
return client.extend(publicActions).extend(prividiumActions);
|
|
25
|
+
}
|
package/dist/sdk/index.d.ts
CHANGED
|
@@ -5,3 +5,4 @@ export { LocalStorage, TokenManager } from './storage.js';
|
|
|
5
5
|
export { generateRandomState } from './token-utils.js';
|
|
6
6
|
export { PopupAuth, handleAuthCallback, type AuthCallbackMessage, type OauthScope } from './popup-auth.js';
|
|
7
7
|
export { UNAUTHORIZED_ERROR_CODE, FORBIDDEN_ERROR_CODE } from './rpc-error-codes.js';
|
|
8
|
+
export { createPrividiumClient } from './create-prividium-client.js';
|
package/dist/sdk/index.js
CHANGED
|
@@ -4,3 +4,4 @@ export { LocalStorage, TokenManager } from './storage.js';
|
|
|
4
4
|
export { generateRandomState } from './token-utils.js';
|
|
5
5
|
export { PopupAuth, handleAuthCallback } from './popup-auth.js';
|
|
6
6
|
export { UNAUTHORIZED_ERROR_CODE, FORBIDDEN_ERROR_CODE } from './rpc-error-codes.js';
|
|
7
|
+
export { createPrividiumClient } from './create-prividium-client.js';
|
|
@@ -142,18 +142,23 @@ export function createPrividiumChain(config) {
|
|
|
142
142
|
const result = (await response.json());
|
|
143
143
|
return result.newWalletToken;
|
|
144
144
|
},
|
|
145
|
-
async
|
|
145
|
+
async authorizeTransaction(params) {
|
|
146
146
|
const headers = getAuthHeaders();
|
|
147
147
|
if (!headers) {
|
|
148
148
|
throw new Error('Authentication required. Please call authorize() first.');
|
|
149
149
|
}
|
|
150
|
-
const response = await fetch(`${config.permissionsApiBaseUrl}/api/wallet/
|
|
150
|
+
const response = await fetch(`${config.permissionsApiBaseUrl}/api/wallet/transaction-authorization`, {
|
|
151
151
|
method: 'POST',
|
|
152
152
|
headers: {
|
|
153
153
|
'Content-Type': 'application/json',
|
|
154
154
|
...headers
|
|
155
155
|
},
|
|
156
|
-
body: JSON.stringify(
|
|
156
|
+
body: JSON.stringify({
|
|
157
|
+
...params,
|
|
158
|
+
// Always pass calldata and value, even if undefined
|
|
159
|
+
calldata: params?.calldata ?? '0x',
|
|
160
|
+
value: params.value?.toString() ?? '0'
|
|
161
|
+
})
|
|
157
162
|
});
|
|
158
163
|
if (response.status === 403) {
|
|
159
164
|
tokenManager.clearToken();
|
|
@@ -161,7 +166,7 @@ export function createPrividiumChain(config) {
|
|
|
161
166
|
throw new Error('Authentication required. Please call authorize() first.');
|
|
162
167
|
}
|
|
163
168
|
if (!response.ok) {
|
|
164
|
-
throw new Error(`Failed to
|
|
169
|
+
throw new Error(`Failed to authorize transaction: ${response.status} ${response.statusText}`);
|
|
165
170
|
}
|
|
166
171
|
const result = (await response.json());
|
|
167
172
|
return result;
|
package/dist/sdk/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type Address, type Chain, type Hex, type Transport } from 'viem';
|
|
2
2
|
import { type OauthScope } from './popup-auth.js';
|
|
3
3
|
export interface Storage {
|
|
4
4
|
getItem(key: string): string | null;
|
|
@@ -36,13 +36,26 @@ export interface AddNetworkParams {
|
|
|
36
36
|
};
|
|
37
37
|
blockExplorerUrls?: string[];
|
|
38
38
|
}
|
|
39
|
-
export
|
|
39
|
+
export type AuthorizeTransactionParams = {
|
|
40
40
|
walletAddress: Address;
|
|
41
|
-
|
|
41
|
+
toAddress: Address;
|
|
42
42
|
nonce: number;
|
|
43
43
|
calldata: Hex;
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
value: bigint;
|
|
45
|
+
} | {
|
|
46
|
+
walletAddress: Address;
|
|
47
|
+
toAddress: Address;
|
|
48
|
+
nonce: number;
|
|
49
|
+
calldata: Hex;
|
|
50
|
+
value?: never;
|
|
51
|
+
} | {
|
|
52
|
+
walletAddress: Address;
|
|
53
|
+
toAddress: Address;
|
|
54
|
+
nonce: number;
|
|
55
|
+
calldata?: never;
|
|
56
|
+
value: bigint;
|
|
57
|
+
};
|
|
58
|
+
export interface AuthorizeTransactionResponse {
|
|
46
59
|
message: string;
|
|
47
60
|
activeUntil: string;
|
|
48
61
|
}
|
|
@@ -57,7 +70,7 @@ export interface PrividiumChain {
|
|
|
57
70
|
getWalletToken(): Promise<string>;
|
|
58
71
|
getWalletRpcUrl(): Promise<string>;
|
|
59
72
|
invalidateWalletToken(): Promise<string>;
|
|
60
|
-
|
|
73
|
+
authorizeTransaction(params: AuthorizeTransactionParams): Promise<AuthorizeTransactionResponse>;
|
|
61
74
|
addNetworkToWallet(params?: AddNetworkParams): Promise<void>;
|
|
62
75
|
}
|
|
63
76
|
export interface TokenData {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/error-utils.ts","../src/index.ts","../src/popup-auth.ts","../src/prividium-chain.ts","../src/rpc-error-codes.ts","../src/storage.ts","../src/token-utils.ts","../src/types.ts"],"version":"5.8.3"}
|
|
1
|
+
{"root":["../src/create-prividium-client.ts","../src/error-utils.ts","../src/index.ts","../src/popup-auth.ts","../src/prividium-chain.ts","../src/rpc-error-codes.ts","../src/storage.ts","../src/token-utils.ts","../src/types.ts"],"version":"5.8.3"}
|