@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.
@@ -2,20 +2,11 @@
2
2
  import {
3
3
  CreateTraceRequest,
4
4
  CreateTraceResponse,
5
- StartSpanRequest,
6
- StartSpanResponse,
7
- FinishSpanRequest,
8
- FinishSpanResponse,
9
- AddSpanEventRequest,
10
- AddSpanEventResponse,
11
- AddSpanErrorRequest,
12
- AddSpanErrorResponse,
13
- AddSpanHintRequest,
14
- AddSpanHintResponse,
15
5
  } from "mirador-gateway-parallax-web/proto/gateway/parallax/v1/parallax_gateway_pb";
16
6
  import { ParallaxGatewayServiceClient } from "mirador-gateway-parallax-web/proto/gateway/parallax/v1/Parallax_gatewayServiceClientPb";
7
+ import { Timestamp } from "google-protobuf/google/protobuf/timestamp_pb";
17
8
 
18
- const GRPC_GATEWAY_API_URL = "https://gateway-parallax-dev.platform.svc.cluster.local:50053";
9
+ const GRPC_GATEWAY_API_URL = "https://parallax-gateway.dev.mirador.org:443";
19
10
 
20
11
  const debugIssue = (trace: string, error: Error) => {
21
12
  // Handle our own debugging / logging here
@@ -176,187 +167,209 @@ class ParallaxClient {
176
167
  }
177
168
 
178
169
  /**
179
- * Create a StartSpanRequest with optional attributes and client metadata
180
- * @param traceId trace id to associate the span with
181
- * @param name name of the span
182
- * @param parentSpanId (optional) create a span off a parent span id
183
- * @param attr (optional) attributes to add to the span
184
- * @param includeClientMeta (optional) flag to include client metadata (ip, browser, os, etc)
185
- * @returns
170
+ * Create a new trace builder
171
+ *
172
+ * Example usage:
173
+ * ```typescript
174
+ * const response = await client.trace("swap_execution")
175
+ * .addAttribute("user", "0xabc...")
176
+ * .addAttribute("slippage_bps", 25)
177
+ * .addTag("dex")
178
+ * .addTag("swap")
179
+ * .addEvent("wallet_connected", { wallet: "MetaMask" })
180
+ * .addEvent("quote_received")
181
+ * .submit("0x123...", "ethereum");
182
+ * ```
183
+ *
184
+ * @param name The name of the trace
185
+ * @param includeClientMeta Optional flag to automatically include client metadata
186
+ * @returns A ParallaxTrace builder instance
186
187
  */
187
- async createStartSpanRequest({ traceId, name, parentSpanId, attr, includeClientMeta = false}: {traceId: string, name: string, parentSpanId?: string, attr?: { [key: string]: string }, includeClientMeta?: boolean}): Promise<StartSpanRequest> {
188
- const startSpanReq = new StartSpanRequest();
189
- startSpanReq.setTraceId(traceId);
190
- startSpanReq.setName(name);
191
- if (parentSpanId) {
192
- startSpanReq.setParentSpanId(parentSpanId);
193
- }
194
- const spanAttrs = startSpanReq.getAttributesMap();
188
+ trace(name: string, includeClientMeta: boolean = false): ParallaxTrace {
189
+ return new ParallaxTrace(this, name, includeClientMeta);
190
+ }
195
191
 
196
- if (attr) {
197
- Object.entries(attr).forEach(([key, value]) => {
198
- if (key.includes('client.')) {
199
- console.warn(`Attribute key "${key}" is reserved for client metadata. It will be prefixed with "custom."`);
200
- } else {
201
- spanAttrs.set(key, typeof value === 'object' ? JSON.stringify(value) : String(value));
202
- }
203
- });
204
- }
205
- try {
206
- if (includeClientMeta) {
207
- const clientMetadata = await this.getClientMetadata();
208
- Object.entries(clientMetadata).forEach(([key, value]) => {
209
- spanAttrs.set(`client.${key}`, value);
210
- });
211
- }
212
- } catch (error) {
213
- console.error('Error gathering client metadata for span:', error);
214
- }
215
- return startSpanReq;
192
+ }
193
+
194
+ /**
195
+ * Builder class for constructing traces with method chaining
196
+ * Automatically handles web-specific features like client metadata
197
+ */
198
+ class ParallaxTrace {
199
+ private name: string;
200
+ private attributes: { [key: string]: string } = {};
201
+ private tags: string[] = [];
202
+ private events: Array<{ eventName: string; details?: string; timestamp: Date }> = [];
203
+ private txHashHint?: {
204
+ txHash: string;
205
+ chainId: string;
206
+ details?: string;
207
+ timestamp: Date;
208
+ };
209
+ private client: ParallaxClient;
210
+ private includeClientMeta: boolean;
211
+
212
+ constructor(client: ParallaxClient, name: string, includeClientMeta: boolean = false) {
213
+ this.client = client;
214
+ this.name = name;
215
+ this.includeClientMeta = includeClientMeta;
216
216
  }
217
217
 
218
218
  /**
219
- * Start a new span within a trace
220
- * @param params Parameters to start a new span
219
+ * Add an attribute to the trace
220
+ * @param key Attribute key
221
+ * @param value Attribute value (will be converted to string)
222
+ * @returns This trace builder for chaining
221
223
  */
222
- async startSpan(params: StartSpanRequest): Promise<StartSpanResponse> {
223
- try {
224
- return await this.client.startSpan(params, null);
225
- } catch (_error) {
226
- debugIssue("startSpan", new Error('Error starting span'));
227
- throw _error;
228
- }
224
+ addAttribute(key: string, value: string | number | boolean): this {
225
+ this.attributes[key] = String(value);
226
+ return this;
229
227
  }
230
228
 
231
229
  /**
232
- * Create a FinishSpanRequest
233
- * @param params Parameters to finish a span - traceId, spanId, status (optional) (success, errorMessage)
234
- * @returns FinishSpanRequest
230
+ * Add multiple attributes to the trace
231
+ * @param attributes Object containing key-value pairs
232
+ * @returns This trace builder for chaining
235
233
  */
236
- createFinishSpanRequest({ traceId, spanId, status }: { traceId: string, spanId: string, status?: { success: boolean, errorMessage: string } }): FinishSpanRequest {
237
- const request = new FinishSpanRequest();
238
- request.setTraceId(traceId);
239
- request.setSpanId(spanId);
240
- if (status !== undefined) {
241
- const spanStatus = new FinishSpanRequest.SpanStatus();
242
- spanStatus.setCode(status.success ? FinishSpanRequest.SpanStatus.StatusCode.STATUS_CODE_OK : FinishSpanRequest.SpanStatus.StatusCode.STATUS_CODE_ERROR);
243
- if (status.errorMessage) {
244
- spanStatus.setMessage(status.errorMessage);
245
- }
246
- request.setStatus(spanStatus);
234
+ addAttributes(attributes: { [key: string]: string | number | boolean }): this {
235
+ for (const [key, value] of Object.entries(attributes)) {
236
+ this.attributes[key] = String(value);
247
237
  }
248
- return request;
238
+ return this;
249
239
  }
250
240
 
251
241
  /**
252
- * Finish a span within a trace
253
- * @param params Parameters to finish a span
242
+ * Add a tag to the trace
243
+ * @param tag Tag to add
244
+ * @returns This trace builder for chaining
254
245
  */
255
- async finishSpan(params: FinishSpanRequest): Promise<FinishSpanResponse> {
256
- try {
257
- return await this.client.finishSpan(params, null);
258
- } catch (_error) {
259
- debugIssue("finishSpan", new Error('Error finishing span'));
260
- throw _error;
261
- }
246
+ addTag(tag: string): this {
247
+ this.tags.push(tag);
248
+ return this;
262
249
  }
263
250
 
264
251
  /**
265
- * Creates the add span event request
266
- * @param params - Parameters to create an AddSpanEventRequest - traceId, spanId, eventName, attr (optional)
267
- * @returns AddSpanEventRequest
252
+ * Add multiple tags to the trace
253
+ * @param tags Array of tags to add
254
+ * @returns This trace builder for chaining
268
255
  */
269
- createAddSpanEventRequest({ traceId, spanId, eventName, attr }: { traceId: string, spanId: string, eventName: string, attr?: { [key: string]: string } }): AddSpanEventRequest {
270
- const request = new AddSpanEventRequest();
271
- request.setTraceId(traceId);
272
- request.setSpanId(spanId);
273
- request.setEventName(eventName);
274
- const eventAttrs = request.getAttributesMap();
275
- if (attr) {
276
- Object.entries(attr).forEach(([key, value]) => {
277
- eventAttrs.set(key, typeof value === 'object' ? JSON.stringify(value) : String(value));
278
- });
279
- }
280
- eventAttrs.set('timestamp', new Date().toISOString());
281
- return request;
256
+ addTags(tags: string[]): this {
257
+ this.tags.push(...tags);
258
+ return this;
282
259
  }
283
260
 
284
261
  /**
285
- * Add an event to a span
286
- * @param params Parameters to add an event to a span
262
+ * Add an event to the trace
263
+ * @param eventName Name of the event
264
+ * @param details Optional details (can be a JSON string or object that will be stringified)
265
+ * @param timestamp Optional timestamp (defaults to current time)
266
+ * @returns This trace builder for chaining
287
267
  */
288
- async addSpanEvent(params: AddSpanEventRequest): Promise<AddSpanEventResponse> {
289
- try {
290
- return await this.client.addSpanEvent(params, null);
291
- } catch (_error) {
292
- debugIssue("addSpanEvent", new Error('Error adding span event'));
293
- throw _error;
294
- }
268
+ addEvent(eventName: string, details?: string | object, timestamp?: Date): this {
269
+ const detailsString = typeof details === 'object' && details !== null
270
+ ? JSON.stringify(details)
271
+ : details;
272
+
273
+ this.events.push({
274
+ eventName,
275
+ details: detailsString,
276
+ timestamp: timestamp || new Date(),
277
+ });
278
+ return this;
295
279
  }
296
280
 
297
281
  /**
298
- * Creates the add span error request
299
- * @param params - params used to generate the error request ( traceid, span id, error message, error type, stack trace)
300
- * @returns AddSpanErrorRequest
282
+ * Set or update the transaction hash hint
283
+ * @param txHash Transaction hash
284
+ * @param chainId Chain ID (e.g., "ethereum", "polygon")
285
+ * @param details Optional details about the transaction
286
+ * @param timestamp Optional timestamp (defaults to current time)
287
+ * @returns This trace builder for chaining
301
288
  */
302
- createAddSpanErrorRequest({ traceId, spanId, errorMessage, errorType, stackTrace }: { traceId: string, spanId: string, errorMessage: string, errorType?: string, stackTrace?: string }): AddSpanErrorRequest {
303
- const request = new AddSpanErrorRequest();
304
- request.setTraceId(traceId);
305
- request.setSpanId(spanId);
306
- request.setMessage(errorMessage);
307
- if (errorType) {
308
- request.setErrorType(errorType);
309
- }
310
- if (stackTrace) {
311
- request.setStackTrace(stackTrace);
312
- }
313
- return request;
289
+ setTxHash(txHash: string, chainId: string, details?: string, timestamp?: Date): this {
290
+ this.txHashHint = {
291
+ txHash,
292
+ chainId,
293
+ details,
294
+ timestamp: timestamp || new Date(),
295
+ };
296
+ return this;
314
297
  }
315
298
 
316
299
  /**
317
- * Add an error to a span
318
- * @param params Parameters to add an error to a span
300
+ * Submit the trace without a transaction hash hint (if not already set via setTxHash)
301
+ * @returns Response from the create trace operation
319
302
  */
320
- async addSpanError(params: AddSpanErrorRequest): Promise<AddSpanErrorResponse> {
321
- try {
322
- return await this.client.addSpanError(params, null);
323
- } catch (_error) {
324
- debugIssue("addSpanError", new Error('Error adding span error'));
325
- throw _error;
326
- }
327
- }
303
+ async submit(): Promise<CreateTraceResponse>;
328
304
 
329
305
  /**
330
- * Creates the add span hint request
331
- * @param params - params used to generate the span hint (trace id, parentSpanId, txHash and chainId)
332
- * @returns AddSpanHintRequest
306
+ * Submit the trace with a transaction hash hint (overrides any previously set via setTxHash)
307
+ * @param txHash Transaction hash
308
+ * @param chainId Chain ID (e.g., "ethereum", "polygon")
309
+ * @param details Optional details about the transaction
310
+ * @returns Response from the create trace operation
333
311
  */
334
- createAddSpanHintRequest({ traceId, parentSpanId, txHash, chainId }: { traceId: string, parentSpanId: string, txHash?: string, chainId?: number }): AddSpanHintRequest {
335
- const hintReq = new AddSpanHintRequest();
336
- hintReq.setTraceId(traceId);
337
- hintReq.setParentSpanId(parentSpanId);
338
-
339
- if (txHash && chainId !== undefined) {
340
- const chainTxReq = new AddSpanHintRequest.ChainTransaction();
341
- chainTxReq.setTxHash(txHash);
342
- chainTxReq.setChainId(chainId);
343
- hintReq.setChainTransaction(chainTxReq);
312
+ async submit(txHash: string, chainId: string, details?: string): Promise<CreateTraceResponse>;
313
+
314
+ async submit(txHash?: string, chainId?: string, details?: string): Promise<CreateTraceResponse> {
315
+ // If txHash and chainId are provided in submit(), they override any previously set txHashHint
316
+ const finalTxHashHint = txHash && chainId ? {
317
+ txHash,
318
+ chainId,
319
+ details,
320
+ timestamp: new Date(),
321
+ } : this.txHashHint;
322
+
323
+ // Build the CreateTraceRequest
324
+ const request = new CreateTraceRequest();
325
+ request.setName(this.name);
326
+ request.setTagsList(this.tags);
327
+
328
+ // Add attributes
329
+ const attrsMap = request.getAttributesMap();
330
+ for (const [key, value] of Object.entries(this.attributes)) {
331
+ attrsMap.set(key, value);
344
332
  }
345
- return hintReq;
346
- }
347
333
 
348
- /**
349
- * Add a hint to a span
350
- * @param params Parameters to add a hint to a span
351
- */
352
- async addSpanHint(params: AddSpanHintRequest): Promise<AddSpanHintResponse> {
353
- try {
354
- return await this.client.addSpanHint(params, null);
355
- } catch (_error) {
356
- debugIssue("addSpanHint", new Error('Error adding span hint'));
357
- throw _error;
334
+ // Add client metadata if requested
335
+ if (this.includeClientMeta) {
336
+ const clientMetadata = await this.client.getClientMetadata();
337
+ for (const [key, value] of Object.entries(clientMetadata)) {
338
+ attrsMap.set(`client.${key}`, value);
339
+ }
358
340
  }
341
+
342
+ // Add events
343
+ const eventsList: CreateTraceRequest.Event[] = [];
344
+ for (const event of this.events) {
345
+ const eventMsg = new CreateTraceRequest.Event();
346
+ eventMsg.setEventName(event.eventName);
347
+ if (event.details) {
348
+ eventMsg.setDetails(event.details);
349
+ }
350
+ const timestamp = new Timestamp();
351
+ timestamp.fromDate(event.timestamp);
352
+ eventMsg.setTimestamp(timestamp);
353
+ eventsList.push(eventMsg);
354
+ }
355
+ request.setEventsList(eventsList);
356
+
357
+ // Add transaction hash hint if present
358
+ if (finalTxHashHint) {
359
+ const txHint = new CreateTraceRequest.TxHashHint();
360
+ txHint.setTxHash(finalTxHashHint.txHash);
361
+ txHint.setChainId(finalTxHashHint.chainId);
362
+ if (finalTxHashHint.details) {
363
+ txHint.setDetails(finalTxHashHint.details);
364
+ }
365
+ const timestamp = new Timestamp();
366
+ timestamp.fromDate(finalTxHashHint.timestamp);
367
+ txHint.setTimestamp(timestamp);
368
+ request.setTxHashHint(txHint);
369
+ }
370
+
371
+ return this.client.createTrace(request);
359
372
  }
360
373
  }
361
374
 
362
- export { ParallaxClient };
375
+ export { ParallaxClient, ParallaxTrace };