@miradorlabs/parallax-web 1.0.4 → 1.0.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/dist/index.umd.js CHANGED
@@ -1057,7 +1057,8 @@
1057
1057
  var f, obj = {
1058
1058
  name: jspb.Message.getFieldWithDefault(msg, 1, ""),
1059
1059
  attributesMap: (f = msg.getAttributesMap()) ? f.toObject(includeInstance, undefined) : [],
1060
- tagsList: (f = jspb.Message.getRepeatedField(msg, 3)) == null ? undefined : f
1060
+ tagsList: (f = jspb.Message.getRepeatedField(msg, 3)) == null ? undefined : f,
1061
+ startTime: (f = msg.getStartTime()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f)
1061
1062
  };
1062
1063
 
1063
1064
  if (includeInstance) {
@@ -1108,6 +1109,11 @@
1108
1109
  var value = /** @type {string} */ (reader.readString());
1109
1110
  msg.addTags(value);
1110
1111
  break;
1112
+ case 4:
1113
+ var value = new google_protobuf_timestamp_pb.Timestamp;
1114
+ reader.readMessage(value,google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader);
1115
+ msg.setStartTime(value);
1116
+ break;
1111
1117
  default:
1112
1118
  reader.skipField();
1113
1119
  break;
@@ -1155,6 +1161,14 @@
1155
1161
  f
1156
1162
  );
1157
1163
  }
1164
+ f = message.getStartTime();
1165
+ if (f != null) {
1166
+ writer.writeMessage(
1167
+ 4,
1168
+ f,
1169
+ google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter
1170
+ );
1171
+ }
1158
1172
  };
1159
1173
 
1160
1174
 
@@ -1236,6 +1250,43 @@
1236
1250
  };
1237
1251
 
1238
1252
 
1253
+ /**
1254
+ * optional google.protobuf.Timestamp start_time = 4;
1255
+ * @return {?proto.google.protobuf.Timestamp}
1256
+ */
1257
+ proto.gateway.parallax.v1.CreateTraceRequest.prototype.getStartTime = function() {
1258
+ return /** @type{?proto.google.protobuf.Timestamp} */ (
1259
+ jspb.Message.getWrapperField(this, google_protobuf_timestamp_pb.Timestamp, 4));
1260
+ };
1261
+
1262
+
1263
+ /**
1264
+ * @param {?proto.google.protobuf.Timestamp|undefined} value
1265
+ * @return {!proto.gateway.parallax.v1.CreateTraceRequest} returns this
1266
+ */
1267
+ proto.gateway.parallax.v1.CreateTraceRequest.prototype.setStartTime = function(value) {
1268
+ return jspb.Message.setWrapperField(this, 4, value);
1269
+ };
1270
+
1271
+
1272
+ /**
1273
+ * Clears the message field making it undefined.
1274
+ * @return {!proto.gateway.parallax.v1.CreateTraceRequest} returns this
1275
+ */
1276
+ proto.gateway.parallax.v1.CreateTraceRequest.prototype.clearStartTime = function() {
1277
+ return this.setStartTime(undefined);
1278
+ };
1279
+
1280
+
1281
+ /**
1282
+ * Returns whether this field is set.
1283
+ * @return {boolean}
1284
+ */
1285
+ proto.gateway.parallax.v1.CreateTraceRequest.prototype.hasStartTime = function() {
1286
+ return jspb.Message.getField(this, 4) != null;
1287
+ };
1288
+
1289
+
1239
1290
 
1240
1291
 
1241
1292
 
@@ -1269,7 +1320,8 @@
1269
1320
  proto.gateway.parallax.v1.CreateTraceResponse.toObject = function(includeInstance, msg) {
1270
1321
  var f, obj = {
1271
1322
  status: (f = msg.getStatus()) && proto_common_v1_status_pb.ResponseStatus.toObject(includeInstance, f),
1272
- traceId: jspb.Message.getFieldWithDefault(msg, 2, "")
1323
+ traceId: jspb.Message.getFieldWithDefault(msg, 2, ""),
1324
+ rootSpanId: jspb.Message.getFieldWithDefault(msg, 3, "")
1273
1325
  };
1274
1326
 
1275
1327
  if (includeInstance) {
@@ -1315,6 +1367,10 @@
1315
1367
  var value = /** @type {string} */ (reader.readString());
1316
1368
  msg.setTraceId(value);
1317
1369
  break;
1370
+ case 3:
1371
+ var value = /** @type {string} */ (reader.readString());
1372
+ msg.setRootSpanId(value);
1373
+ break;
1318
1374
  default:
1319
1375
  reader.skipField();
1320
1376
  break;
@@ -1359,6 +1415,13 @@
1359
1415
  f
1360
1416
  );
1361
1417
  }
1418
+ f = message.getRootSpanId();
1419
+ if (f.length > 0) {
1420
+ writer.writeString(
1421
+ 3,
1422
+ f
1423
+ );
1424
+ }
1362
1425
  };
1363
1426
 
1364
1427
 
@@ -1417,6 +1480,24 @@
1417
1480
  };
1418
1481
 
1419
1482
 
1483
+ /**
1484
+ * optional string root_span_id = 3;
1485
+ * @return {string}
1486
+ */
1487
+ proto.gateway.parallax.v1.CreateTraceResponse.prototype.getRootSpanId = function() {
1488
+ return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, ""));
1489
+ };
1490
+
1491
+
1492
+ /**
1493
+ * @param {string} value
1494
+ * @return {!proto.gateway.parallax.v1.CreateTraceResponse} returns this
1495
+ */
1496
+ proto.gateway.parallax.v1.CreateTraceResponse.prototype.setRootSpanId = function(value) {
1497
+ return jspb.Message.setProto3StringField(this, 3, value);
1498
+ };
1499
+
1500
+
1420
1501
 
1421
1502
 
1422
1503
 
@@ -1451,7 +1532,7 @@
1451
1532
  var f, obj = {
1452
1533
  name: jspb.Message.getFieldWithDefault(msg, 1, ""),
1453
1534
  traceId: jspb.Message.getFieldWithDefault(msg, 2, ""),
1454
- parentSpanId: (f = jspb.Message.getField(msg, 3)) == null ? undefined : f,
1535
+ parentSpanId: jspb.Message.getFieldWithDefault(msg, 3, ""),
1455
1536
  attributesMap: (f = msg.getAttributesMap()) ? f.toObject(includeInstance, undefined) : [],
1456
1537
  startTime: (f = msg.getStartTime()) && google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f)
1457
1538
  };
@@ -1556,8 +1637,8 @@
1556
1637
  f
1557
1638
  );
1558
1639
  }
1559
- f = /** @type {string} */ (jspb.Message.getField(message, 3));
1560
- if (f != null) {
1640
+ f = message.getParentSpanId();
1641
+ if (f.length > 0) {
1561
1642
  writer.writeString(
1562
1643
  3,
1563
1644
  f
@@ -1628,25 +1709,7 @@
1628
1709
  * @return {!proto.gateway.parallax.v1.StartSpanRequest} returns this
1629
1710
  */
1630
1711
  proto.gateway.parallax.v1.StartSpanRequest.prototype.setParentSpanId = function(value) {
1631
- return jspb.Message.setField(this, 3, value);
1632
- };
1633
-
1634
-
1635
- /**
1636
- * Clears the field making it undefined.
1637
- * @return {!proto.gateway.parallax.v1.StartSpanRequest} returns this
1638
- */
1639
- proto.gateway.parallax.v1.StartSpanRequest.prototype.clearParentSpanId = function() {
1640
- return jspb.Message.setField(this, 3, undefined);
1641
- };
1642
-
1643
-
1644
- /**
1645
- * Returns whether this field is set.
1646
- * @return {boolean}
1647
- */
1648
- proto.gateway.parallax.v1.StartSpanRequest.prototype.hasParentSpanId = function() {
1649
- return jspb.Message.getField(this, 3) != null;
1712
+ return jspb.Message.setProto3StringField(this, 3, value);
1650
1713
  };
1651
1714
 
1652
1715
 
@@ -4693,6 +4756,339 @@
4693
4756
  }
4694
4757
  }
4695
4758
 
4759
+ /**
4760
+ * Parallax Service - Transaction Tracing for Web Applications
4761
+ * Creates individual traces for each transaction and tracks them through their lifecycle
4762
+ *
4763
+ * This service provides a simplified interface for tracking transactions with automatic
4764
+ * client metadata collection and lifecycle management.
4765
+ */
4766
+ class ParallaxService {
4767
+ constructor() {
4768
+ Object.defineProperty(this, "client", {
4769
+ enumerable: true,
4770
+ configurable: true,
4771
+ writable: true,
4772
+ value: null
4773
+ });
4774
+ Object.defineProperty(this, "activeTransactions", {
4775
+ enumerable: true,
4776
+ configurable: true,
4777
+ writable: true,
4778
+ value: new Map()
4779
+ });
4780
+ // Client will be initialized lazily
4781
+ }
4782
+ /**
4783
+ * Initialize the Parallax client (lazy initialization)
4784
+ * @param apiKey - Optional API key for authentication
4785
+ * @param gatewayUrl - Optional custom gateway URL
4786
+ */
4787
+ _ensureClient(apiKey, gatewayUrl) {
4788
+ if (this.client)
4789
+ return;
4790
+ // Determine gateway URL based on environment if not provided
4791
+ let url = gatewayUrl;
4792
+ if (!url && typeof window !== 'undefined') {
4793
+ const isDevelopment = window.location.hostname === 'localhost' ||
4794
+ window.location.hostname === '127.0.0.1';
4795
+ url = isDevelopment
4796
+ ? `${window.location.protocol}//${window.location.host}/parallax-gateway`
4797
+ : 'https://gateway-parallax-dev.mirador.org';
4798
+ }
4799
+ this.client = new ParallaxClient(apiKey || '', url);
4800
+ console.log('[ParallaxService] Client initialized with URL:', url);
4801
+ }
4802
+ /**
4803
+ * Start a new transaction trace
4804
+ * Called when user initiates a transaction
4805
+ *
4806
+ * Note: Since createTrace now automatically creates a root span, we don't need
4807
+ * to call startSpan separately. The rootSpanId from the response is the parent span.
4808
+ *
4809
+ * @param txData - Transaction data
4810
+ * @param name - Name for the trace (e.g., 'SendingTrace', 'SwappingTrace')
4811
+ * @param options - Optional configuration (apiKey, gatewayUrl, includeClientMeta)
4812
+ * @returns Promise with traceId, rootSpanId, and txId
4813
+ */
4814
+ async startTransactionTrace(txData, name = 'WalletTransaction', options) {
4815
+ this._ensureClient(options?.apiKey, options?.gatewayUrl);
4816
+ if (!this.client) {
4817
+ throw new Error('Failed to initialize Parallax client');
4818
+ }
4819
+ try {
4820
+ const txId = `tx_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
4821
+ const timestamp = new Date().toISOString();
4822
+ // Create trace attributes
4823
+ const traceAttributes = {
4824
+ transactionId: txId,
4825
+ walletAddress: txData.walletAddress || txData.from,
4826
+ network: txData.network || 'Unknown',
4827
+ transactionStart: timestamp,
4828
+ from: txData.from,
4829
+ to: txData.to,
4830
+ value: txData.value,
4831
+ };
4832
+ // Add any additional transaction data
4833
+ if (txData.additionalData) {
4834
+ Object.entries(txData.additionalData).forEach(([key, value]) => {
4835
+ traceAttributes[key] = typeof value === 'object' ? JSON.stringify(value) : String(value);
4836
+ });
4837
+ }
4838
+ // Create a trace for this transaction
4839
+ const createTraceReq = await this.client.createTraceRequest({
4840
+ name: name,
4841
+ attr: traceAttributes,
4842
+ tags: ['transaction', 'wallet', txData.network || 'unknown'],
4843
+ includeClientMeta: options?.includeClientMeta ?? true,
4844
+ });
4845
+ const traceResponse = await this.client.createTrace(createTraceReq);
4846
+ const traceId = traceResponse.getTraceId();
4847
+ const rootSpanId = traceResponse.getRootSpanId();
4848
+ // Store transaction info
4849
+ this.activeTransactions.set(txId, {
4850
+ traceId,
4851
+ rootSpanId,
4852
+ spanId: rootSpanId, // Use rootSpanId as the main span for this transaction
4853
+ timestamp,
4854
+ txHash: null,
4855
+ from: txData.from,
4856
+ to: txData.to,
4857
+ network: txData.network,
4858
+ });
4859
+ console.log('[ParallaxService] Transaction trace started:', {
4860
+ txId,
4861
+ traceId,
4862
+ rootSpanId,
4863
+ from: txData.from,
4864
+ to: txData.to,
4865
+ });
4866
+ // Add initial event to the root span
4867
+ await this.addTransactionEvent(txId, 'transaction_initiated', {
4868
+ from: txData.from,
4869
+ to: txData.to,
4870
+ value: txData.value,
4871
+ timestamp,
4872
+ });
4873
+ return { traceId, rootSpanId, txId };
4874
+ }
4875
+ catch (error) {
4876
+ console.error('[ParallaxService] Failed to start transaction trace:', error);
4877
+ throw error;
4878
+ }
4879
+ }
4880
+ /**
4881
+ * Associate a transaction hash with an existing trace
4882
+ * Called when the transaction hash is available after signing/sending
4883
+ *
4884
+ * @param txId - Transaction identifier returned from startTransactionTrace
4885
+ * @param txHash - Blockchain transaction hash
4886
+ * @param chainId - Chain ID
4887
+ */
4888
+ async associateTransactionHash(txId, txHash, chainId) {
4889
+ const txInfo = this.activeTransactions.get(txId);
4890
+ if (!txInfo) {
4891
+ console.warn(`[ParallaxService] Transaction ${txId} not found in active transactions`);
4892
+ return;
4893
+ }
4894
+ if (!this.client) {
4895
+ console.warn('[ParallaxService] Client not initialized');
4896
+ return;
4897
+ }
4898
+ try {
4899
+ // Update stored tx info
4900
+ txInfo.txHash = txHash;
4901
+ this.activeTransactions.set(txId, txInfo);
4902
+ // Add chain hint to correlate with blockchain events
4903
+ const hintReq = this.client.createAddSpanHintRequest({
4904
+ traceId: txInfo.traceId,
4905
+ parentSpanId: txInfo.rootSpanId,
4906
+ txHash: txHash,
4907
+ chainId: chainId,
4908
+ });
4909
+ await this.client.addSpanHint(hintReq);
4910
+ // Add event for transaction sent
4911
+ await this.addTransactionEvent(txId, 'transaction_hash_available', {
4912
+ txHash,
4913
+ chainId: chainId.toString(),
4914
+ timestamp: new Date().toISOString(),
4915
+ });
4916
+ console.log('[ParallaxService] Transaction hash associated with trace:', {
4917
+ txId,
4918
+ txHash,
4919
+ traceId: txInfo.traceId,
4920
+ });
4921
+ }
4922
+ catch (error) {
4923
+ console.error('[ParallaxService] Failed to associate transaction hash:', error);
4924
+ }
4925
+ }
4926
+ /**
4927
+ * Add an event to a transaction trace
4928
+ *
4929
+ * @param txId - Transaction identifier
4930
+ * @param eventName - Event name
4931
+ * @param attributes - Event attributes
4932
+ */
4933
+ async addTransactionEvent(txId, eventName, attributes = {}) {
4934
+ const txInfo = this.activeTransactions.get(txId);
4935
+ if (!txInfo) {
4936
+ console.warn(`[ParallaxService] Transaction ${txId} not found. Cannot add event '${eventName}'`);
4937
+ return;
4938
+ }
4939
+ if (!this.client || !txInfo.spanId) {
4940
+ console.warn('[ParallaxService] Client not initialized or span not available');
4941
+ return;
4942
+ }
4943
+ try {
4944
+ // Convert attributes to plain object with string values
4945
+ const eventAttributes = {};
4946
+ Object.entries(attributes).forEach(([key, value]) => {
4947
+ eventAttributes[key] = typeof value === 'object' ? JSON.stringify(value) : String(value);
4948
+ });
4949
+ const request = this.client.createAddSpanEventRequest({
4950
+ traceId: txInfo.traceId,
4951
+ spanId: txInfo.spanId,
4952
+ eventName: eventName,
4953
+ attr: eventAttributes,
4954
+ });
4955
+ await this.client.addSpanEvent(request);
4956
+ }
4957
+ catch (error) {
4958
+ console.error(`[ParallaxService] Failed to add transaction event '${eventName}':`, error);
4959
+ }
4960
+ }
4961
+ /**
4962
+ * Add an error to a transaction trace
4963
+ * Creates a proper span error event in Parallax
4964
+ *
4965
+ * @param txId - Transaction identifier
4966
+ * @param error - Error object or message
4967
+ * @param errorType - Type/category of error (e.g., 'TransactionError', 'NetworkError', 'UserRejection')
4968
+ */
4969
+ async addTransactionError(txId, error, errorType = 'TransactionError') {
4970
+ const txInfo = this.activeTransactions.get(txId);
4971
+ if (!txInfo) {
4972
+ console.warn(`[ParallaxService] Transaction ${txId} not found. Cannot add error.`);
4973
+ return;
4974
+ }
4975
+ if (!this.client || !txInfo.spanId) {
4976
+ console.warn('[ParallaxService] Client not initialized or span not available');
4977
+ return;
4978
+ }
4979
+ try {
4980
+ // Extract error message and stack trace
4981
+ let errorMessage = '';
4982
+ let stackTrace;
4983
+ if (error instanceof Error) {
4984
+ errorMessage = error.message;
4985
+ stackTrace = error.stack;
4986
+ }
4987
+ else {
4988
+ errorMessage = String(error);
4989
+ }
4990
+ const request = this.client.createAddSpanErrorRequest({
4991
+ traceId: txInfo.traceId,
4992
+ spanId: txInfo.spanId,
4993
+ errorMessage: errorMessage,
4994
+ errorType: errorType,
4995
+ stackTrace: stackTrace,
4996
+ });
4997
+ await this.client.addSpanError(request);
4998
+ console.log('[ParallaxService] Transaction error added to trace:', {
4999
+ txId,
5000
+ errorType,
5001
+ message: error instanceof Error ? error.message : String(error),
5002
+ });
5003
+ }
5004
+ catch (err) {
5005
+ console.error('[ParallaxService] Failed to add transaction error:', err);
5006
+ }
5007
+ }
5008
+ /**
5009
+ * Finish a transaction trace
5010
+ * Called when transaction is confirmed or permanently failed
5011
+ *
5012
+ * @param txId - Transaction identifier
5013
+ * @param options - Finish options (success, error message)
5014
+ */
5015
+ async finishTransactionTrace(txId, options = { success: true }) {
5016
+ const txInfo = this.activeTransactions.get(txId);
5017
+ if (!txInfo) {
5018
+ console.warn(`[ParallaxService] Transaction ${txId} not found. Cannot finish.`);
5019
+ return;
5020
+ }
5021
+ if (!this.client || !txInfo.spanId) {
5022
+ console.warn('[ParallaxService] Client not initialized or span not available');
5023
+ return;
5024
+ }
5025
+ try {
5026
+ // Add final event
5027
+ await this.addTransactionEvent(txId, options.success ? 'transaction_completed' : 'transaction_failed', {
5028
+ success: options.success.toString(),
5029
+ error: options.error || '',
5030
+ duration: (Date.now() - new Date(txInfo.timestamp).getTime()).toString(),
5031
+ timestamp: new Date().toISOString(),
5032
+ });
5033
+ // Finish the span
5034
+ const request = this.client.createFinishSpanRequest({
5035
+ traceId: txInfo.traceId,
5036
+ spanId: txInfo.spanId,
5037
+ status: {
5038
+ success: options.success,
5039
+ errorMessage: options.error || '',
5040
+ },
5041
+ });
5042
+ await this.client.finishSpan(request);
5043
+ console.log('[ParallaxService] Transaction trace finished:', {
5044
+ txId,
5045
+ traceId: txInfo.traceId,
5046
+ success: options.success,
5047
+ txHash: txInfo.txHash,
5048
+ });
5049
+ // Remove from active transactions
5050
+ this.activeTransactions.delete(txId);
5051
+ }
5052
+ catch (error) {
5053
+ console.error('[ParallaxService] Failed to finish transaction trace:', error);
5054
+ }
5055
+ }
5056
+ /**
5057
+ * Get info about an active transaction
5058
+ *
5059
+ * @param txId - Transaction identifier
5060
+ * @returns Transaction info or null if not found
5061
+ */
5062
+ getTransactionInfo(txId) {
5063
+ return this.activeTransactions.get(txId) || null;
5064
+ }
5065
+ /**
5066
+ * Get all active transactions
5067
+ *
5068
+ * @returns Array of active transaction info
5069
+ */
5070
+ getAllActiveTransactions() {
5071
+ return Array.from(this.activeTransactions.entries()).map(([txId, info]) => ({
5072
+ txId,
5073
+ ...info,
5074
+ }));
5075
+ }
5076
+ /**
5077
+ * Get the ParallaxClient instance for advanced usage
5078
+ * @param apiKey - Optional API key
5079
+ * @param gatewayUrl - Optional gateway URL
5080
+ */
5081
+ getClient(apiKey, gatewayUrl) {
5082
+ this._ensureClient(apiKey, gatewayUrl);
5083
+ if (!this.client) {
5084
+ throw new Error('Failed to initialize Parallax client');
5085
+ }
5086
+ return this.client;
5087
+ }
5088
+ }
5089
+ // Export singleton instance
5090
+ const parallaxService = new ParallaxService();
5091
+
4696
5092
  exports.AddSpanErrorRequest = parallax_gateway_pbExports.AddSpanErrorRequest;
4697
5093
  exports.AddSpanErrorResponse = parallax_gateway_pbExports.AddSpanErrorResponse;
4698
5094
  exports.AddSpanEventRequest = parallax_gateway_pbExports.AddSpanEventRequest;
@@ -4705,8 +5101,10 @@
4705
5101
  exports.FinishSpanResponse = parallax_gateway_pbExports.FinishSpanResponse;
4706
5102
  exports.GrpcWebRpc = GrpcWebRpc;
4707
5103
  exports.ParallaxClient = ParallaxClient;
5104
+ exports.ParallaxService = ParallaxService;
4708
5105
  exports.StartSpanRequest = parallax_gateway_pbExports.StartSpanRequest;
4709
5106
  exports.StartSpanResponse = parallax_gateway_pbExports.StartSpanResponse;
5107
+ exports.parallaxService = parallaxService;
4710
5108
 
4711
5109
  }));
4712
5110
  //# sourceMappingURL=index.umd.js.map