@miradorlabs/parallax-web 1.0.4 → 1.0.7

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
@@ -8,190 +8,330 @@ Web browser SDK for the Parallax tracing platform. This package provides a brows
8
8
  npm install @miradorlabs/parallax-web
9
9
  ```
10
10
 
11
- ## Usage
11
+ ## Features
12
+
13
+ - 🚀 **ParallaxService** - High-level API for transaction tracing with automatic lifecycle management
14
+ - 🔧 **ParallaxClient** - Low-level client for advanced use cases
15
+ - 🌐 **Browser-optimized** - Automatic client metadata collection (browser, OS, IP, etc.)
16
+ - ⛓️ **Blockchain integration** - Built-in support for correlating transactions with blockchain events
17
+ - 📦 **TypeScript support** - Full type definitions included
18
+ - 🎯 **Automatic root spans** - Creating a trace now automatically creates a root span
19
+
20
+ ## Quick Start with ParallaxService (Recommended)
21
+
22
+ The `ParallaxService` provides a simplified API for tracking transactions:
23
+
24
+ ```typescript
25
+ import { parallaxService } from '@miradorlabs/parallax-web';
26
+
27
+ // Start tracking a transaction (creates trace + root span automatically)
28
+ const { traceId, rootSpanId, txId } = await parallaxService.startTransactionTrace(
29
+ {
30
+ from: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
31
+ to: '0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199',
32
+ value: '0.1',
33
+ network: 'ethereum',
34
+ walletAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
35
+ },
36
+ 'SendTransaction',
37
+ { includeClientMeta: true } // Automatically collects browser, OS, IP, etc.
38
+ );
39
+
40
+ // Associate the blockchain transaction hash
41
+ await parallaxService.associateTransactionHash(txId, '0xabc123...', 1);
42
+
43
+ // Add events as the transaction progresses
44
+ await parallaxService.addTransactionEvent(txId, 'wallet_signed', {
45
+ timestamp: new Date().toISOString(),
46
+ });
47
+
48
+ // Track errors if they occur
49
+ try {
50
+ // transaction logic
51
+ } catch (error) {
52
+ await parallaxService.addTransactionError(txId, error, 'TransactionError');
53
+ }
54
+
55
+ // Finish the trace when done
56
+ await parallaxService.finishTransactionTrace(txId, { success: true });
57
+ ```
58
+
59
+ ### ParallaxService API
60
+
61
+ #### `startTransactionTrace(txData, name, options)`
62
+
63
+ Starts a new transaction trace with automatic root span creation.
64
+
65
+ **Important:** When you create a trace, a root span is **automatically created** on the backend. You receive a `rootSpanId` in the response - no need to call `startSpan` separately!
66
+
67
+ **Parameters:**
68
+ - `txData`: Transaction details (from, to, value, network, etc.)
69
+ - `name`: Trace name (default: 'WalletTransaction')
70
+ - `options`: Optional configuration
71
+ - `apiKey`: API key for authentication
72
+ - `gatewayUrl`: Custom gateway URL
73
+ - `includeClientMeta`: Include browser/OS metadata (default: true)
74
+
75
+ **Returns:** `{ traceId, rootSpanId, txId }`
76
+
77
+ #### Other Methods
78
+
79
+ - `associateTransactionHash(txId, txHash, chainId)` - Link blockchain transaction
80
+ - `addTransactionEvent(txId, eventName, attributes)` - Add event to trace
81
+ - `addTransactionError(txId, error, errorType)` - Track errors with stack traces
82
+ - `finishTransactionTrace(txId, options)` - Complete the trace
83
+ - `getTransactionInfo(txId)` - Get active transaction info
84
+ - `getAllActiveTransactions()` - List all active transactions
85
+ - `getClient()` - Access underlying ParallaxClient for advanced usage
86
+
87
+ See [PARALLAX_SERVICE_USAGE.md](./PARALLAX_SERVICE_USAGE.md) for comprehensive documentation.
88
+
89
+ ## Advanced Usage with ParallaxClient
90
+
91
+ For more control, use the low-level `ParallaxClient`:
12
92
 
13
93
  ### Basic Setup
14
94
 
15
95
  ```typescript
16
- import { ParallaxClient, CreateTraceRequest } from '@miradorlabs/parallax-web';
96
+ import { ParallaxClient } from '@miradorlabs/parallax-web';
17
97
 
18
- // Initialize the client with your API key
98
+ // Initialize the client
19
99
  const client = new ParallaxClient('your-api-key');
20
100
 
21
101
  // Or with a custom gateway URL
22
102
  const client = new ParallaxClient('your-api-key', 'https://your-gateway.example.com:50053');
23
103
  ```
24
104
 
25
- ### Creating a Trace
105
+ ### Helper Methods
106
+
107
+ The client provides helper methods to create requests easily:
108
+
109
+ #### Creating a Trace
26
110
 
27
111
  ```typescript
28
- import { CreateTraceRequest } from '@miradorlabs/parallax-web';
112
+ // Use the helper method
113
+ const createTraceReq = await client.createTraceRequest({
114
+ name: 'My Application Trace',
115
+ attr: {
116
+ 'project.id': 'my-project',
117
+ 'environment': 'production',
118
+ },
119
+ tags: ['web', 'user-action'],
120
+ includeClientMeta: true, // Includes browser, OS, IP, etc.
121
+ });
122
+
123
+ const traceResponse = await client.createTrace(createTraceReq);
124
+ const traceId = traceResponse.getTraceId();
125
+ const rootSpanId = traceResponse.getRootSpanId(); // Root span automatically created!
126
+ ```
29
127
 
30
- const request = new CreateTraceRequest();
31
- request.setName('My Application Trace');
128
+ #### Starting a Span (Child Span)
32
129
 
33
- // Set attributes using the map
34
- const attributesMap = request.getAttributesMap();
35
- attributesMap.set('project.id', 'my-project');
36
- attributesMap.set('environment', 'production');
130
+ Note: You only need to call `startSpan` if you want to create **child spans**. The root span is automatically created when you create a trace.
37
131
 
38
- request.setTagsList(['web', 'user-action']);
132
+ ```typescript
133
+ // Create a child span under the root span
134
+ const startSpanReq = await client.createStartSpanRequest({
135
+ traceId: traceId,
136
+ name: 'User Login',
137
+ parentSpanId: rootSpanId, // Use root span as parent
138
+ attr: {
139
+ 'user.id': 'user-123',
140
+ 'action': 'login',
141
+ },
142
+ includeClientMeta: false, // Optional
143
+ });
144
+
145
+ const spanResponse = await client.startSpan(startSpanReq);
146
+ const spanId = spanResponse.getSpanId();
147
+ ```
39
148
 
40
- const traceResponse = await client.createTrace(request);
41
- const traceId = traceResponse.getTraceId();
149
+ #### Adding Span Events
150
+
151
+ ```typescript
152
+ const eventReq = client.createAddSpanEventRequest({
153
+ traceId: traceId,
154
+ spanId: spanId,
155
+ eventName: 'User Authenticated',
156
+ attr: {
157
+ 'auth.method': 'oauth',
158
+ 'auth.provider': 'google',
159
+ },
160
+ });
161
+
162
+ await client.addSpanEvent(eventReq);
42
163
  ```
43
164
 
44
- ### Starting a Span
165
+ #### Adding Span Errors
45
166
 
46
167
  ```typescript
47
- import { StartSpanRequest } from '@miradorlabs/parallax-web';
168
+ try {
169
+ // some operation
170
+ } catch (error) {
171
+ const errorReq = client.createAddSpanErrorRequest({
172
+ traceId: traceId,
173
+ spanId: spanId,
174
+ errorMessage: error.message,
175
+ errorType: 'ValidationError',
176
+ stackTrace: error.stack,
177
+ });
178
+
179
+ await client.addSpanError(errorReq);
180
+ }
181
+ ```
48
182
 
49
- const request = new StartSpanRequest();
50
- request.setName('User Login');
51
- request.setTraceId(traceId);
183
+ #### Adding Span Hints (Blockchain Transactions)
52
184
 
53
- // Set attributes using the map
54
- const attributesMap = request.getAttributesMap();
55
- attributesMap.set('user.id', 'user-123');
56
- attributesMap.set('action', 'login');
185
+ ```typescript
186
+ const hintReq = client.createAddSpanHintRequest({
187
+ traceId: traceId,
188
+ parentSpanId: rootSpanId,
189
+ txHash: '0x1234567890abcdef',
190
+ chainId: 1, // Ethereum mainnet
191
+ });
192
+
193
+ await client.addSpanHint(hintReq);
194
+ ```
57
195
 
58
- const spanResponse = await client.startSpan(request);
59
- const spanId = spanResponse.getSpanId();
196
+ #### Finishing a Span
197
+
198
+ ```typescript
199
+ const finishReq = client.createFinishSpanRequest({
200
+ traceId: traceId,
201
+ spanId: spanId,
202
+ status: {
203
+ success: true,
204
+ errorMessage: '', // or error message if failed
205
+ },
206
+ });
207
+
208
+ await client.finishSpan(finishReq);
60
209
  ```
61
210
 
62
- ### Adding Span Events
211
+ ## Complete Example: Transaction Tracking
63
212
 
64
213
  ```typescript
65
- import { AddSpanEventRequest } from '@miradorlabs/parallax-web';
214
+ import { parallaxService } from '@miradorlabs/parallax-web';
66
215
 
67
- const request = new AddSpanEventRequest();
68
- request.setTraceId(traceId);
69
- request.setSpanId(spanId);
70
- request.setEventName('User Authenticated');
216
+ async function handleWalletTransaction(userAddress, recipientAddress, amount) {
217
+ let txId;
71
218
 
72
- const attributesMap = request.getAttributesMap();
73
- attributesMap.set('auth.method', 'oauth');
74
- attributesMap.set('auth.provider', 'google');
219
+ try {
220
+ // 1. Start the trace (automatically creates root span)
221
+ const result = await parallaxService.startTransactionTrace(
222
+ {
223
+ from: userAddress,
224
+ to: recipientAddress,
225
+ value: amount,
226
+ network: 'ethereum',
227
+ walletAddress: userAddress,
228
+ },
229
+ 'SendETH',
230
+ { includeClientMeta: true }
231
+ );
75
232
 
76
- await client.addSpanEvent(request);
77
- ```
233
+ txId = result.txId;
234
+ console.log('Trace started:', result.traceId);
78
235
 
79
- ### Adding Span Errors
236
+ // 2. User signs the transaction
237
+ await parallaxService.addTransactionEvent(txId, 'user_signing', {});
80
238
 
81
- ```typescript
82
- import { AddSpanErrorRequest } from '@miradorlabs/parallax-web';
239
+ const signedTx = await wallet.signTransaction(txData);
83
240
 
84
- const request = new AddSpanErrorRequest();
85
- request.setTraceId(traceId);
86
- request.setSpanId(spanId);
87
- request.setErrorType('ValidationError');
88
- request.setMessage('Invalid email format');
89
- request.setStackTrace(error.stack);
241
+ await parallaxService.addTransactionEvent(txId, 'transaction_signed', {});
90
242
 
91
- const attributesMap = request.getAttributesMap();
92
- attributesMap.set('error.field', 'email');
243
+ // 3. Send to network
244
+ await parallaxService.addTransactionEvent(txId, 'sending_to_network', {});
93
245
 
94
- await client.addSpanError(request);
95
- ```
246
+ const txReceipt = await provider.sendTransaction(signedTx);
96
247
 
97
- ### Adding Span Hints (Blockchain Transactions)
248
+ // 4. Associate the blockchain transaction hash
249
+ await parallaxService.associateTransactionHash(txId, txReceipt.hash, 1);
98
250
 
99
- ```typescript
100
- import { AddSpanHintRequest } from '@miradorlabs/parallax-web';
251
+ // 5. Wait for confirmation
252
+ await parallaxService.addTransactionEvent(txId, 'waiting_confirmation', {
253
+ txHash: txReceipt.hash,
254
+ });
255
+
256
+ await txReceipt.wait();
101
257
 
102
- const chainTx = new AddSpanHintRequest.ChainTransaction();
103
- chainTx.setTxHash('0x1234567890abcdef');
104
- chainTx.setChainId(1); // Ethereum mainnet
258
+ // 6. Success!
259
+ await parallaxService.finishTransactionTrace(txId, { success: true });
260
+ console.log('Transaction completed successfully');
261
+
262
+ } catch (error) {
263
+ console.error('Transaction failed:', error);
105
264
 
106
- const request = new AddSpanHintRequest();
107
- request.setTraceId(traceId);
108
- request.setParentSpanId(spanId);
109
- request.setChainTransaction(chainTx);
265
+ if (txId) {
266
+ await parallaxService.addTransactionError(txId, error, 'TransactionError');
267
+ await parallaxService.finishTransactionTrace(txId, {
268
+ success: false,
269
+ error: error.message,
270
+ });
271
+ }
110
272
 
111
- await client.addSpanHint(request);
273
+ throw error;
274
+ }
275
+ }
112
276
  ```
113
277
 
114
- ### Finishing a Span
278
+ ## Automatic Client Metadata Collection
115
279
 
116
- ```typescript
117
- import { FinishSpanRequest } from '@miradorlabs/parallax-web';
280
+ When `includeClientMeta: true` is set, the SDK automatically collects:
118
281
 
119
- const spanStatus = new FinishSpanRequest.SpanStatus();
120
- spanStatus.setCode(FinishSpanRequest.SpanStatus.StatusCode.STATUS_CODE_OK);
282
+ - **Browser**: Chrome, Firefox, Safari, Edge, etc.
283
+ - **Operating System**: Windows, macOS, Linux, Android, iOS
284
+ - **User Agent**: Full user agent string
285
+ - **Platform**: Browser platform
286
+ - **Language**: Browser language
287
+ - **Screen**: Width and height
288
+ - **Viewport**: Width and height
289
+ - **Timezone**: User's timezone and offset
290
+ - **URL**: Current page URL
291
+ - **Referrer**: Page referrer
292
+ - **IP Address**: Client IP (if not blocked by CSP)
121
293
 
122
- const request = new FinishSpanRequest();
123
- request.setTraceId(traceId);
124
- request.setSpanId(spanId);
125
- request.setStatus(spanStatus);
294
+ All metadata is prefixed with `client.` in trace attributes.
126
295
 
127
- await client.finishSpan(request);
128
- ```
296
+ ## Environment Detection
297
+
298
+ The SDK automatically detects the environment:
129
299
 
130
- ## Complete Example
300
+ - **Localhost/127.0.0.1**: Uses proxy at `${window.location.protocol}//${window.location.host}/parallax-gateway`
301
+ - **Production**: Uses `https://gateway-parallax-dev.mirador.org`
302
+
303
+ Override with the `gatewayUrl` option.
304
+
305
+ ## TypeScript Support
306
+
307
+ Full TypeScript support with exported types:
131
308
 
132
309
  ```typescript
133
- import {
134
- ParallaxClient,
310
+ import type {
135
311
  CreateTraceRequest,
312
+ CreateTraceResponse,
136
313
  StartSpanRequest,
137
- AddSpanEventRequest,
314
+ StartSpanResponse,
138
315
  FinishSpanRequest,
316
+ FinishSpanResponse,
317
+ AddSpanEventRequest,
318
+ AddSpanEventResponse,
319
+ AddSpanErrorRequest,
320
+ AddSpanErrorResponse,
321
+ AddSpanHintRequest,
322
+ AddSpanHintResponse,
139
323
  } from '@miradorlabs/parallax-web';
140
-
141
- async function trackUserAction() {
142
- const client = new ParallaxClient('your-api-key');
143
-
144
- try {
145
- // Create trace
146
- const createTraceReq = new CreateTraceRequest();
147
- createTraceReq.setName('User Purchase Flow');
148
- createTraceReq.getAttributesMap().set('user.id', 'user-123');
149
- createTraceReq.setTagsList(['purchase', 'web']);
150
-
151
- const traceResponse = await client.createTrace(createTraceReq);
152
- const traceId = traceResponse.getTraceId();
153
-
154
- // Start span
155
- const startSpanReq = new StartSpanRequest();
156
- startSpanReq.setName('Checkout Process');
157
- startSpanReq.setTraceId(traceId);
158
- startSpanReq.getAttributesMap().set('cart.items', '3');
159
-
160
- const spanResponse = await client.startSpan(startSpanReq);
161
- const spanId = spanResponse.getSpanId();
162
-
163
- // Add event
164
- const addEventReq = new AddSpanEventRequest();
165
- addEventReq.setTraceId(traceId);
166
- addEventReq.setSpanId(spanId);
167
- addEventReq.setEventName('Payment Initiated');
168
- addEventReq.getAttributesMap().set('payment.method', 'card');
169
-
170
- await client.addSpanEvent(addEventReq);
171
-
172
- // Finish span
173
- const finishSpanReq = new FinishSpanRequest();
174
- finishSpanReq.setTraceId(traceId);
175
- finishSpanReq.setSpanId(spanId);
176
-
177
- const spanStatus = new FinishSpanRequest.SpanStatus();
178
- spanStatus.setCode(FinishSpanRequest.SpanStatus.StatusCode.STATUS_CODE_OK);
179
- finishSpanReq.setStatus(spanStatus);
180
-
181
- await client.finishSpan(finishSpanReq);
182
- } catch (error) {
183
- console.error('Tracing error:', error);
184
- }
185
- }
186
324
  ```
187
325
 
188
326
  ## Browser Compatibility
189
327
 
190
- This SDK uses the Fetch API and is compatible with modern browsers that support:
191
- - ES2020
328
+ This SDK uses modern browser APIs and is compatible with:
329
+
330
+ - ES2020+
192
331
  - Fetch API
193
332
  - Promises
194
333
  - Uint8Array
334
+ - Modern browsers (Chrome, Firefox, Safari, Edge)
195
335
 
196
336
  For older browsers, you may need polyfills.
197
337
 
@@ -199,10 +339,39 @@ For older browsers, you may need polyfills.
199
339
 
200
340
  The package provides multiple module formats:
201
341
 
202
- - **ESM** (`dist/index.esm.js`): For modern bundlers (Webpack, Vite, etc.)
342
+ - **ESM** (`dist/index.esm.js`): For modern bundlers (Webpack, Vite, Rollup)
203
343
  - **UMD** (`dist/index.umd.js`): For browser globals and older module systems
204
344
  - **TypeScript** (`dist/index.d.ts`): Type definitions
205
345
 
346
+ ## Key Differences from Node.js Client
347
+
348
+ The web client (`@miradorlabs/parallax-web`) differs from the Node.js client (`@miradorlabs/parallax`):
349
+
350
+ | Feature | Web Client | Node.js Client |
351
+ |---------|------------|----------------|
352
+ | Transport | gRPC-Web (HTTP/1.1) | gRPC (@grpc/grpc-js) |
353
+ | Protocol | `https://` | `http://` or `https://` |
354
+ | Environment | Browser | Node.js |
355
+ | Protobuf | google-protobuf (classes) | ts-proto (plain objects) |
356
+ | API Style | `.getTraceId()` setters/getters | `.traceId` properties |
357
+ | Client Metadata | Browser-specific | Server-specific |
358
+
359
+ ## Important Update: Automatic Root Span Creation
360
+
361
+ **Breaking Change (v1.0.5+):**
362
+
363
+ When you call `createTrace()`, a root span is now **automatically created** on the backend. The response includes:
364
+ - `traceId`: The trace identifier
365
+ - `rootSpanId`: The automatically created root span ID
366
+
367
+ **You no longer need to:**
368
+ - Call `startSpan()` immediately after `createTrace()`
369
+ - Manually create the first span
370
+
371
+ **When to use `startSpan()`:**
372
+ - Only when you need **child spans** for more detailed tracking
373
+ - Use `rootSpanId` as the `parentSpanId` for child spans
374
+
206
375
  ## Development
207
376
 
208
377
  ### Building
@@ -219,21 +388,18 @@ npm run test:watch
219
388
  npm run test:coverage
220
389
  ```
221
390
 
222
- ### Linting
391
+ ### Publishing
223
392
 
224
393
  ```bash
225
- npm run lint
226
- npm run format
394
+ npm run release:patch # 1.0.x
395
+ npm run release:minor # 1.x.0
396
+ npm run release:major # x.0.0
227
397
  ```
228
398
 
229
- ## Differences from Node.js Client
230
-
231
- The web client differs from `@miradorlabs/parallax` (Node.js) in the following ways:
399
+ ## Documentation
232
400
 
233
- - Uses **gRPC-Web** instead of gRPC (`@grpc/grpc-js`)
234
- - Uses browser **Fetch API** instead of Node.js HTTP
235
- - Uses **https** URLs instead of insecure connections
236
- - Designed for browser environments (no Node.js dependencies)
401
+ - [ParallaxService Usage Guide](./PARALLAX_SERVICE_USAGE.md) - Comprehensive guide for the high-level API
402
+ - [Examples](./examples) - More usage examples
237
403
 
238
404
  ## License
239
405