@stellar-expert/tx-meta-effects-parser 6.0.3 → 6.1.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stellar-expert/tx-meta-effects-parser",
3
- "version": "6.0.3",
3
+ "version": "6.1.0",
4
4
  "description": "Low-level effects parser for Stellar transaction results and meta XDR",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -9,7 +9,7 @@
9
9
  "author": "team@stellar.expert",
10
10
  "license": "MIT",
11
11
  "peerDependencies": {
12
- "@stellar/stellar-base": "^12.1.0"
12
+ "@stellar/stellar-base": "^12.1.1"
13
13
  },
14
14
  "devDependencies": {
15
15
  "@babel/core": "^7.22.9",
@@ -61,13 +61,13 @@ class EventsAnalyzer {
61
61
  * @private
62
62
  */
63
63
  analyzeDiagnosticEvents() {
64
- const {diagnosticEvents, processSystemEvents} = this.effectsAnalyzer
64
+ const {diagnosticEvents, processSystemEvents, processMetrics, processFailedOpEffects} = this.effectsAnalyzer
65
65
  if (!diagnosticEvents)
66
66
  return
67
67
  const opContractId = this.effectsAnalyzer.retrieveOpContractId()
68
68
  //diagnostic events
69
69
  for (const evt of diagnosticEvents) {
70
- if (!processSystemEvents && !(evt.inSuccessfulContractCall() || this.effectsAnalyzer.processFailedOpEffects))
70
+ if (!processSystemEvents && !(processFailedOpEffects || evt.inSuccessfulContractCall()))
71
71
  continue //throw new UnexpectedTxMetaChangeError({type: 'diagnostic_event', action: 'failed'})
72
72
  //parse event
73
73
  const event = evt.event()
@@ -75,7 +75,7 @@ class EventsAnalyzer {
75
75
  if (contractId && typeof contractId !== 'string') {
76
76
  contractId = StrKey.encodeContract(contractId)
77
77
  }
78
- this.processDiagnosticEvent(event.body().value(), event.type().value, contractId)
78
+ this.processDiagnosticEvent(event._attributes.body._value, event._attributes.type.value, contractId, processMetrics)
79
79
  }
80
80
  }
81
81
 
@@ -83,9 +83,10 @@ class EventsAnalyzer {
83
83
  * @param {xdr.ContractEventV0} body
84
84
  * @param {Number} type
85
85
  * @param {String} contract
86
+ * @param {Boolean} processMetrics
86
87
  * @private
87
88
  */
88
- processDiagnosticEvent(body, type, contract) {
89
+ processDiagnosticEvent(body, type, contract, processMetrics) {
89
90
  const topics = body.topics()
90
91
  if (!topics?.length)
91
92
  return
@@ -121,16 +122,22 @@ class EventsAnalyzer {
121
122
  case 'error':
122
123
  if (type !== EVENT_TYPES.DIAGNOSTIC)
123
124
  return // skip non-diagnostic events
125
+ let code = topics[1].value().value()
126
+ if (code.name) {
127
+ code = code.name
128
+ }
124
129
  this.effectsAnalyzer.addEffect({
125
130
  type: effectTypes.contractError,
126
131
  contract,
127
- code: topics[1].value().value(),
132
+ code,
128
133
  details: processEventBodyValue(body.data())
129
134
  })
130
135
  break
131
136
  case 'core_metrics':
132
137
  if (type !== EVENT_TYPES.DIAGNOSTIC)
133
138
  return // skip non-diagnostic events
139
+ if (!processMetrics)
140
+ return
134
141
  this.effectsAnalyzer.addMetric(contract, xdrParseScVal(topics[1]), parseInt(processEventBodyValue(body.data())))
135
142
  break
136
143
  //handle standard token contract events
@@ -11,7 +11,18 @@ const {UnexpectedTxMetaChangeError, TxMetaEffectParserError} = require('./errors
11
11
  const {generateContractCodeEntryHash} = require('./parser/ledger-key')
12
12
 
13
13
  class EffectsAnalyzer {
14
- constructor({operation, meta, result, network, events, diagnosticEvents, mapSac, processSystemEvents, processFailedOpEffects}) {
14
+ constructor({
15
+ operation,
16
+ meta,
17
+ result,
18
+ network,
19
+ events,
20
+ diagnosticEvents,
21
+ mapSac,
22
+ processSystemEvents,
23
+ processFailedOpEffects,
24
+ processMetrics
25
+ }) {
15
26
  //set execution context
16
27
  if (!operation.source)
17
28
  throw new TxMetaEffectParserError('Operation source is not explicitly defined')
@@ -22,6 +33,7 @@ class EffectsAnalyzer {
22
33
  this.source = this.operation.source
23
34
  this.events = events
24
35
  this.processFailedOpEffects = processFailedOpEffects
36
+ this.processMetrics = processMetrics
25
37
  if (diagnosticEvents?.length) {
26
38
  this.diagnosticEvents = diagnosticEvents
27
39
  if (processSystemEvents) {
@@ -84,6 +96,11 @@ class EffectsAnalyzer {
84
96
  * @readonly
85
97
  */
86
98
  processSystemEvents = false
99
+ /**
100
+ * @type {Boolean}
101
+ * @readonly
102
+ */
103
+ processMetrics = true
87
104
  /**
88
105
  * @type {{}}
89
106
  * @private
@@ -106,6 +123,10 @@ class EffectsAnalyzer {
106
123
  this.processSponsorshipEffects()
107
124
  //calculate minted/burned assets
108
125
  new AssetSupplyAnalyzer(this).analyze()
126
+ //add Soroban op metrics if available
127
+ if (this.metrics) {
128
+ this.addEffect(this.metrics)
129
+ }
109
130
  return this.effects
110
131
  }
111
132
 
@@ -180,7 +201,6 @@ class EffectsAnalyzer {
180
201
  type: effectTypes.contractMetrics,
181
202
  contract
182
203
  }
183
- this.addEffect(metrics)
184
204
  }
185
205
  metrics[metric] = value
186
206
  }
package/src/index.js CHANGED
@@ -19,16 +19,29 @@ const effectTypes = require('./effect-types')
19
19
  * @param {Boolean} [mapSac] - Whether to create a map SAC->Asset
20
20
  * @param {Boolean} [processSystemEvents] - Emit effects for contract errors and resource stats
21
21
  * @param {Boolean} [processFailedOpEffects] - Whether to generate operation effects for failed/rejected transactions
22
+ * @param {Boolean} [processMetrics] - Process invocation metrics emitted by Soroban
22
23
  * @param {Number} [protocol] - Specific Stellar protocol version for the executed transaction
23
24
  * @return {ParsedTxOperationsMetadata}
24
25
  */
25
- function parseTxOperationsMeta({network, tx, result, meta, mapSac = false, processSystemEvents = false, processFailedOpEffects = false, protocol}) {
26
+ function parseTxOperationsMeta({
27
+ network,
28
+ tx,
29
+ result,
30
+ meta,
31
+ mapSac = false,
32
+ processSystemEvents = false,
33
+ processFailedOpEffects = false,
34
+ processMetrics,
35
+ protocol
36
+ }) {
26
37
  if (!network)
27
38
  throw new TypeError(`Network passphrase argument is required.`)
28
39
  if (typeof network !== 'string')
29
40
  throw new TypeError(`Invalid network passphrase: "${network}".`)
30
41
  if (!tx)
31
42
  throw new TypeError(`Transaction envelope argument is required.`)
43
+ if (processMetrics !== false)
44
+ processMetrics = true
32
45
  const isEphemeral = !meta
33
46
  //parse tx, result, and meta xdr
34
47
  try {
@@ -132,10 +145,12 @@ function parseTxOperationsMeta({network, tx, result, meta, mapSac = false, proce
132
145
  const operation = parsedTx.operations[i]
133
146
  if (success || processFailedOpEffects) {
134
147
  const params = {
148
+ network,
135
149
  operation,
136
150
  meta: opMeta[i]?.changes() || [],
137
- result: opResults[i], network,
138
- processFailedOpEffects
151
+ result: opResults[i],
152
+ processFailedOpEffects,
153
+ processMetrics
139
154
  }
140
155
  const isSorobanInvocation = operation.type === 'invokeHostFunction'
141
156
  //only for Soroban contract invocation
@@ -280,8 +280,16 @@ function xdrParseScVal(value, treatBytesAsContractId = false) {
280
280
  case 'contractId':
281
281
  return xdrParseContractAddress(value._value)
282
282
  default:
283
- if (value.switch().name === 'scvVoid') //scVoid
284
- return undefined
283
+ switch (value._switch.name) {
284
+ case 'scvVoid':
285
+ return undefined
286
+ case 'scvContractInstance':
287
+ return '<ContractInstance>'
288
+ case 'scvLedgerKeyContractInstance':
289
+ return '<LedgerKeyContractInstance>'
290
+ case 'scvLedgerKeyNonce':
291
+ return '<LedgerKeyNonce>'
292
+ }
285
293
  throw new TxMetaEffectParserError('Not supported XDR primitive type: ' + value.toXDR ? value.toXDR() : value.toString())
286
294
  }
287
295
  }