@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.
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "parallax-web-demo",
3
+ "version": "1.0.0",
4
+ "description": "Interactive demo for Parallax Web SDK",
5
+ "type": "module",
6
+ "scripts": {
7
+ "build-sdk": "cd .. && npm run build",
8
+ "build": "npm run build-sdk && rollup -c",
9
+ "proxy": "node proxy-server.js",
10
+ "start": "npm run build && python3 -m http.server 8000",
11
+ "serve": "npm run build && npx http-server -p 8000 -o",
12
+ "dev": "npm run build && npx concurrently \"npm run proxy\" \"npx http-server -p 8000 -o\"",
13
+ "dev:no-proxy": "npm run build && npx http-server -p 8000 -o"
14
+ },
15
+ "keywords": [
16
+ "parallax",
17
+ "demo",
18
+ "web",
19
+ "tracing"
20
+ ],
21
+ "author": "@mirador",
22
+ "license": "ISC",
23
+ "devDependencies": {
24
+ "@rollup/plugin-node-resolve": "^16.0.3",
25
+ "rollup": "^4.53.3"
26
+ },
27
+ "dependencies": {
28
+ "concurrently": "^9.1.0",
29
+ "cors": "^2.8.5",
30
+ "express": "^4.22.1",
31
+ "http-proxy-middleware": "^3.0.3"
32
+ }
33
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Simple Express proxy server to handle CORS issues
3
+ * Proxies gRPC-Web requests to the Parallax Gateway
4
+ */
5
+
6
+ import express from 'express';
7
+ import cors from 'cors';
8
+ import { createProxyMiddleware } from 'http-proxy-middleware';
9
+
10
+ const app = express();
11
+ const PORT = 3001;
12
+
13
+ // Target Parallax Gateway
14
+ const GATEWAY_URL = 'https://parallax-gateway.dev.mirador.org:443';
15
+
16
+ // Enable CORS for all origins (development only)
17
+ app.use(cors({
18
+ origin: '*',
19
+ methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
20
+ allowedHeaders: ['Content-Type', 'x-grpc-web', 'x-user-agent', 'x-api-key'],
21
+ exposedHeaders: ['grpc-status', 'grpc-message'],
22
+ credentials: true
23
+ }));
24
+
25
+ // Health check endpoint (before proxy)
26
+ app.get('/health', (req, res) => {
27
+ res.json({
28
+ status: 'ok',
29
+ proxy: GATEWAY_URL,
30
+ timestamp: new Date().toISOString()
31
+ });
32
+ });
33
+
34
+ // Log all requests
35
+ app.use((req, res, next) => {
36
+ console.log(`[${new Date().toLocaleTimeString()}] ${req.method} ${req.path}`);
37
+ next();
38
+ });
39
+
40
+ // Proxy all other requests to the gateway (gRPC-Web)
41
+ app.use('/', createProxyMiddleware({
42
+ target: GATEWAY_URL,
43
+ changeOrigin: true,
44
+ secure: true,
45
+ ws: false,
46
+ onProxyReq: (proxyReq, req, res) => {
47
+ console.log(` → Proxying to: ${GATEWAY_URL}${req.url}`);
48
+
49
+ // Forward gRPC-Web headers
50
+ if (req.headers['content-type']) {
51
+ proxyReq.setHeader('content-type', req.headers['content-type']);
52
+ }
53
+ if (req.headers['x-grpc-web']) {
54
+ proxyReq.setHeader('x-grpc-web', req.headers['x-grpc-web']);
55
+ }
56
+ if (req.headers['x-user-agent']) {
57
+ proxyReq.setHeader('x-user-agent', req.headers['x-user-agent']);
58
+ }
59
+ },
60
+ onProxyRes: (proxyRes, req, res) => {
61
+ console.log(` ← Response: ${proxyRes.statusCode}`);
62
+ },
63
+ onError: (err, req, res) => {
64
+ console.error('Proxy error:', err.message);
65
+ res.status(500).json({
66
+ error: 'Proxy error',
67
+ message: err.message
68
+ });
69
+ }
70
+ }));
71
+
72
+ app.listen(PORT, () => {
73
+ console.log(`
74
+ ╔════════════════════════════════════════════════════════════╗
75
+ ║ Parallax gRPC-Web Proxy Server ║
76
+ ╟────────────────────────────────────────────────────────────╢
77
+ ║ Proxy running at: http://localhost:${PORT} ║
78
+ ║ Gateway target: ${GATEWAY_URL} ║
79
+ ╟────────────────────────────────────────────────────────────╢
80
+ ║ Usage: ║
81
+ ║ - All gRPC-Web requests are proxied to the gateway ║
82
+ ║ - CORS headers are automatically added ║
83
+ ║ - Health check: http://localhost:${PORT}/health ║
84
+ ╚════════════════════════════════════════════════════════════╝
85
+ `);
86
+ });
@@ -0,0 +1,16 @@
1
+ import resolve from '@rollup/plugin-node-resolve';
2
+
3
+ export default {
4
+ input: 'app.js',
5
+ output: {
6
+ file: 'bundle.js',
7
+ format: 'es',
8
+ sourcemap: true
9
+ },
10
+ plugins: [
11
+ resolve({
12
+ browser: true,
13
+ preferBuiltins: false
14
+ })
15
+ ]
16
+ };
package/index.ts CHANGED
@@ -1,18 +1,11 @@
1
1
  export * from './src/parallax';
2
2
  export { GrpcWebRpc } from './src/grpc';
3
3
 
4
+ // Export ParallaxService
5
+ export { ParallaxService, parallaxService } from './src/parallax/ParallaxService';
6
+
4
7
  // Re-export proto types for convenience
5
8
  export {
6
9
  CreateTraceRequest,
7
10
  CreateTraceResponse,
8
- StartSpanRequest,
9
- StartSpanResponse,
10
- FinishSpanRequest,
11
- FinishSpanResponse,
12
- AddSpanEventRequest,
13
- AddSpanEventResponse,
14
- AddSpanErrorRequest,
15
- AddSpanErrorResponse,
16
- AddSpanHintRequest,
17
- AddSpanHintResponse,
18
11
  } from 'mirador-gateway-parallax-web/proto/gateway/parallax/v1/parallax_gateway_pb';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miradorlabs/parallax-web",
3
- "version": "1.0.4",
3
+ "version": "1.0.7",
4
4
  "description": "Parallax Web Client Side SDK ",
5
5
  "main": "dist/index.umd.js",
6
6
  "module": "dist/index.esm.js",
@@ -25,6 +25,7 @@
25
25
  "@rollup/plugin-commonjs": "^29.0.0",
26
26
  "@rollup/plugin-node-resolve": "^16.0.3",
27
27
  "@rollup/plugin-typescript": "^12.3.0",
28
+ "@types/google-protobuf": "^3.15.12",
28
29
  "@types/jest": "^30.0.0",
29
30
  "@types/node": "^24.10.1",
30
31
  "eslint": "^9.39.1",
@@ -46,7 +47,7 @@
46
47
  "dependencies": {
47
48
  "google-protobuf": "^3.21.4",
48
49
  "grpc-web": "^2.0.2",
49
- "mirador-gateway-parallax-web": "https://storage.googleapis.com/mirador-shd-packages/gateway/parallax/grpc-web/mirador-gateway-parallax-grpc-web-1.0.9.tgz",
50
+ "mirador-gateway-parallax-web": "https://storage.googleapis.com/mirador-shd-packages/gateway/parallax/grpc-web/mirador-gateway-parallax-grpc-web-1.0.11.tgz",
50
51
  "rxjs": "^7.8.2"
51
52
  },
52
53
  "author": "@mirador",
@@ -0,0 +1,296 @@
1
+ /**
2
+ * Parallax Service - Transaction Tracing for Web Applications
3
+ * Creates individual traces for each transaction and tracks them through their lifecycle
4
+ *
5
+ * This service provides a simplified interface for tracking transactions with automatic
6
+ * client metadata collection and lifecycle management.
7
+ */
8
+
9
+ import { ParallaxClient } from './index';
10
+ import type {
11
+ CreateTraceResponse,
12
+ } from 'mirador-gateway-parallax-web/proto/gateway/parallax/v1/parallax_gateway_pb';
13
+
14
+ interface TransactionInfo {
15
+ traceId: string;
16
+ timestamp: string;
17
+ txHash: string | null;
18
+ from?: string;
19
+ to?: string;
20
+ network?: string;
21
+ }
22
+
23
+ interface TransactionData {
24
+ from: string;
25
+ to: string;
26
+ value: string;
27
+ network?: string;
28
+ walletAddress?: string;
29
+ additionalData?: Record<string, any>;
30
+ }
31
+
32
+ interface FinishOptions {
33
+ success: boolean;
34
+ error?: string;
35
+ }
36
+
37
+ export class ParallaxService {
38
+ private client: ParallaxClient | null = null;
39
+ private activeTransactions: Map<string, TransactionInfo> = new Map();
40
+
41
+ constructor() {
42
+ // Client will be initialized lazily
43
+ }
44
+
45
+ /**
46
+ * Initialize the Parallax client (lazy initialization)
47
+ * @param apiKey - Optional API key for authentication
48
+ * @param gatewayUrl - Optional custom gateway URL
49
+ */
50
+ private _ensureClient(apiKey?: string, gatewayUrl?: string): void {
51
+ if (this.client) return;
52
+
53
+ // Determine gateway URL based on environment if not provided
54
+ let url = gatewayUrl;
55
+ if (!url && typeof window !== 'undefined') {
56
+ const isDevelopment =
57
+ window.location.hostname === 'localhost' ||
58
+ window.location.hostname === '127.0.0.1';
59
+
60
+ url = isDevelopment
61
+ ? `${window.location.protocol}//${window.location.host}/parallax-gateway`
62
+ : 'https://gateway-parallax-dev.mirador.org';
63
+ }
64
+
65
+ this.client = new ParallaxClient(apiKey || '', url);
66
+ console.log('[ParallaxService] Client initialized with URL:', url);
67
+ }
68
+
69
+ /**
70
+ * Start a new transaction trace
71
+ * Called when user initiates a transaction
72
+ *
73
+ * Uses the builder pattern to create a trace with events
74
+ *
75
+ * @param txData - Transaction data
76
+ * @param name - Name for the trace (e.g., 'SendingTrace', 'SwappingTrace')
77
+ * @param options - Optional configuration (apiKey, gatewayUrl, includeClientMeta)
78
+ * @returns Promise with traceId, rootSpanId, and txId
79
+ */
80
+ async startTransactionTrace(
81
+ txData: TransactionData,
82
+ name: string = 'WalletTransaction',
83
+ options?: { apiKey?: string; gatewayUrl?: string; includeClientMeta?: boolean }
84
+ ): Promise<{ traceId: string; rootSpanId: string; txId: string }> {
85
+ this._ensureClient(options?.apiKey, options?.gatewayUrl);
86
+
87
+ if (!this.client) {
88
+ throw new Error('Failed to initialize Parallax client');
89
+ }
90
+
91
+ try {
92
+ const txId = `tx_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
93
+ const timestamp = new Date();
94
+
95
+ // Build the trace using the builder pattern
96
+ const builder = this.client
97
+ .trace(name, options?.includeClientMeta ?? true)
98
+ .addAttribute('transactionId', txId)
99
+ .addAttribute('walletAddress', txData.walletAddress || txData.from)
100
+ .addAttribute('network', txData.network || 'Unknown')
101
+ .addAttribute('transactionStart', timestamp.toISOString())
102
+ .addAttribute('from', txData.from)
103
+ .addAttribute('to', txData.to)
104
+ .addAttribute('value', txData.value)
105
+ .addTags(['transaction', 'wallet', txData.network || 'unknown'])
106
+ .addEvent('transaction_initiated', {
107
+ from: txData.from,
108
+ to: txData.to,
109
+ value: txData.value,
110
+ timestamp: timestamp.toISOString(),
111
+ });
112
+
113
+ // Add any additional transaction data as attributes
114
+ if (txData.additionalData) {
115
+ Object.entries(txData.additionalData).forEach(([key, value]) => {
116
+ builder.addAttribute(key, typeof value === 'object' ? JSON.stringify(value) : String(value));
117
+ });
118
+ }
119
+
120
+ // Submit the trace
121
+ const traceResponse: CreateTraceResponse = await builder.submit();
122
+ const traceId = traceResponse.getTraceId();
123
+
124
+ // Store transaction info
125
+ this.activeTransactions.set(txId, {
126
+ traceId,
127
+ timestamp: timestamp.toISOString(),
128
+ txHash: null,
129
+ from: txData.from,
130
+ to: txData.to,
131
+ network: txData.network,
132
+ });
133
+
134
+ console.log('[ParallaxService] Transaction trace started:', {
135
+ txId,
136
+ traceId,
137
+ from: txData.from,
138
+ to: txData.to,
139
+ });
140
+
141
+ return { traceId, rootSpanId: traceId, txId };
142
+ } catch (error) {
143
+ console.error('[ParallaxService] Failed to start transaction trace:', error);
144
+ throw error;
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Associate a transaction hash with an existing trace
150
+ * Called when the transaction hash is available after signing/sending
151
+ *
152
+ * NOTE: This method is deprecated as the new API does not support adding hints to existing traces.
153
+ * Transaction hashes should be provided at trace creation time via the builder's submit(txHash, chainId) method.
154
+ *
155
+ * @param txId - Transaction identifier returned from startTransactionTrace
156
+ * @param txHash - Blockchain transaction hash
157
+ * @param chainId - Chain ID
158
+ * @deprecated Use submit(txHash, chainId) when creating the trace instead
159
+ */
160
+ async associateTransactionHash(txId: string, txHash: string, chainId: number): Promise<void> {
161
+ const txInfo = this.activeTransactions.get(txId);
162
+ if (!txInfo) {
163
+ console.warn(`[ParallaxService] Transaction ${txId} not found in active transactions`);
164
+ return;
165
+ }
166
+
167
+ // Update stored tx info
168
+ txInfo.txHash = txHash;
169
+ this.activeTransactions.set(txId, txInfo);
170
+
171
+ console.warn('[ParallaxService] associateTransactionHash is deprecated. The new API does not support adding transaction hashes after trace creation. Please provide the txHash when creating the trace using submit(txHash, chainId).');
172
+ console.log('[ParallaxService] Transaction hash updated in local cache:', {
173
+ txId,
174
+ txHash,
175
+ traceId: txInfo.traceId,
176
+ });
177
+ }
178
+
179
+ /**
180
+ * Add an event to a transaction trace
181
+ *
182
+ * NOTE: This method is deprecated as the new API does not support adding events to existing traces.
183
+ * Events should be added to the trace builder before calling submit().
184
+ *
185
+ * @param txId - Transaction identifier
186
+ * @param eventName - Event name
187
+ * @param attributes - Event attributes
188
+ * @deprecated Use the trace builder's addEvent() method before calling submit() instead
189
+ */
190
+ async addTransactionEvent(
191
+ txId: string,
192
+ eventName: string,
193
+ attributes: Record<string, any> = {}
194
+ ): Promise<void> {
195
+ const txInfo = this.activeTransactions.get(txId);
196
+ if (!txInfo) {
197
+ console.warn(`[ParallaxService] Transaction ${txId} not found. Cannot add event '${eventName}'`);
198
+ return;
199
+ }
200
+
201
+ console.warn('[ParallaxService] addTransactionEvent is deprecated. The new API does not support adding events after trace creation. Events should be added using the builder pattern before calling submit().');
202
+ }
203
+
204
+ /**
205
+ * Add an error to a transaction trace
206
+ *
207
+ * NOTE: This method is deprecated as the new API does not support adding errors to existing traces.
208
+ * Errors should be added as events to the trace builder before calling submit().
209
+ *
210
+ * @param txId - Transaction identifier
211
+ * @param error - Error object or message
212
+ * @param errorType - Type/category of error (e.g., 'TransactionError', 'NetworkError', 'UserRejection')
213
+ * @deprecated Use the trace builder's addEvent() method to add error events before calling submit() instead
214
+ */
215
+ async addTransactionError(
216
+ txId: string,
217
+ error: Error | string,
218
+ errorType: string = 'TransactionError'
219
+ ): Promise<void> {
220
+ const txInfo = this.activeTransactions.get(txId);
221
+ if (!txInfo) {
222
+ console.warn(`[ParallaxService] Transaction ${txId} not found. Cannot add error.`);
223
+ return;
224
+ }
225
+
226
+ console.warn('[ParallaxService] addTransactionError is deprecated. The new API does not support adding errors after trace creation. Add error events using the builder pattern before calling submit().');
227
+ }
228
+
229
+ /**
230
+ * Finish a transaction trace
231
+ *
232
+ * NOTE: This method is deprecated as the new API does not support span lifecycle management.
233
+ * Traces are completed when submit() is called on the builder.
234
+ *
235
+ * @param txId - Transaction identifier
236
+ * @param options - Finish options (success, error message)
237
+ * @deprecated Traces are automatically completed when submit() is called
238
+ */
239
+ async finishTransactionTrace(txId: string, options: FinishOptions = { success: true }): Promise<void> {
240
+ const txInfo = this.activeTransactions.get(txId);
241
+ if (!txInfo) {
242
+ console.warn(`[ParallaxService] Transaction ${txId} not found. Cannot finish.`);
243
+ return;
244
+ }
245
+
246
+ console.warn('[ParallaxService] finishTransactionTrace is deprecated. The new API does not support span lifecycle. Traces are completed when submit() is called.');
247
+
248
+ console.log('[ParallaxService] Transaction trace marked as finished (local only):', {
249
+ txId,
250
+ traceId: txInfo.traceId,
251
+ success: options.success,
252
+ txHash: txInfo.txHash,
253
+ });
254
+
255
+ // Remove from active transactions
256
+ this.activeTransactions.delete(txId);
257
+ }
258
+
259
+ /**
260
+ * Get info about an active transaction
261
+ *
262
+ * @param txId - Transaction identifier
263
+ * @returns Transaction info or null if not found
264
+ */
265
+ getTransactionInfo(txId: string): TransactionInfo | null {
266
+ return this.activeTransactions.get(txId) || null;
267
+ }
268
+
269
+ /**
270
+ * Get all active transactions
271
+ *
272
+ * @returns Array of active transaction info
273
+ */
274
+ getAllActiveTransactions(): Array<TransactionInfo & { txId: string }> {
275
+ return Array.from(this.activeTransactions.entries()).map(([txId, info]) => ({
276
+ txId,
277
+ ...info,
278
+ }));
279
+ }
280
+
281
+ /**
282
+ * Get the ParallaxClient instance for advanced usage
283
+ * @param apiKey - Optional API key
284
+ * @param gatewayUrl - Optional gateway URL
285
+ */
286
+ getClient(apiKey?: string, gatewayUrl?: string): ParallaxClient {
287
+ this._ensureClient(apiKey, gatewayUrl);
288
+ if (!this.client) {
289
+ throw new Error('Failed to initialize Parallax client');
290
+ }
291
+ return this.client;
292
+ }
293
+ }
294
+
295
+ // Export singleton instance
296
+ export const parallaxService = new ParallaxService();