@stellar-expert/tx-meta-effects-parser 5.3.0 → 5.5.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 +2 -2
- package/src/aggregation/events-analyzer.js +23 -9
- package/src/effect-types.js +3 -1
- package/src/effects-analyzer.js +26 -2
- package/src/index.js +5 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stellar-expert/tx-meta-effects-parser",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.5.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
|
+
"@stellar/stellar-base": "^12.0.0"
|
|
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} = this.effectsAnalyzer
|
|
64
|
+
const {diagnosticEvents, processSystemEvents} = this.effectsAnalyzer
|
|
65
65
|
if (!diagnosticEvents)
|
|
66
66
|
return
|
|
67
67
|
//diagnostic events
|
|
68
68
|
for (const evt of diagnosticEvents) {
|
|
69
|
-
if (!evt.inSuccessfulContractCall())
|
|
70
|
-
|
|
69
|
+
if (!processSystemEvents && !evt.inSuccessfulContractCall())
|
|
70
|
+
continue //throw new UnexpectedTxMetaChangeError({type: 'diagnostic_event', action: 'failed'})
|
|
71
71
|
//parse event
|
|
72
72
|
const event = evt.event()
|
|
73
73
|
const contractId = event.contractId()
|
|
@@ -90,7 +90,7 @@ class EventsAnalyzer {
|
|
|
90
90
|
if (type !== EVENT_TYPES.DIAGNOSTIC)
|
|
91
91
|
return // skip non-diagnostic events
|
|
92
92
|
const rawArgs = body.data()
|
|
93
|
-
const
|
|
93
|
+
const funcCall = {
|
|
94
94
|
type: effectTypes.contractInvoked,
|
|
95
95
|
contract: xdrParseScVal(topics[1], true),
|
|
96
96
|
function: xdrParseScVal(topics[2]),
|
|
@@ -99,21 +99,35 @@ class EventsAnalyzer {
|
|
|
99
99
|
}
|
|
100
100
|
//add the invocation to the call stack
|
|
101
101
|
if (this.callStack.length) {
|
|
102
|
-
|
|
102
|
+
funcCall.depth = this.callStack.length
|
|
103
103
|
}
|
|
104
|
-
this.callStack.push(
|
|
105
|
-
this.effectsAnalyzer.addEffect(
|
|
104
|
+
this.callStack.push(funcCall)
|
|
105
|
+
this.effectsAnalyzer.addEffect(funcCall)
|
|
106
106
|
break
|
|
107
107
|
case 'fn_return':
|
|
108
108
|
if (type !== EVENT_TYPES.DIAGNOSTIC)
|
|
109
109
|
return // skip non-diagnostic events
|
|
110
110
|
//attach execution result to the contract invocation event
|
|
111
|
-
const
|
|
111
|
+
const lastFuncCall = this.callStack.pop()
|
|
112
112
|
const result = body.data()
|
|
113
113
|
if (result.switch().name !== 'scvVoid') {
|
|
114
|
-
|
|
114
|
+
lastFuncCall.result = result.toXDR('base64')
|
|
115
115
|
}
|
|
116
116
|
break
|
|
117
|
+
case 'error':
|
|
118
|
+
if (type !== EVENT_TYPES.DIAGNOSTIC)
|
|
119
|
+
return // skip non-diagnostic events
|
|
120
|
+
this.effectsAnalyzer.addEffect({
|
|
121
|
+
type: effectTypes.contractError,
|
|
122
|
+
code: topics[1].value().value(),
|
|
123
|
+
details: processEventBodyValue(body.data())
|
|
124
|
+
})
|
|
125
|
+
break
|
|
126
|
+
case 'core_metrics':
|
|
127
|
+
if (type !== EVENT_TYPES.DIAGNOSTIC)
|
|
128
|
+
return // skip non-diagnostic events
|
|
129
|
+
this.effectsAnalyzer.addMetric(xdrParseScVal(topics[1]), parseInt(processEventBodyValue(body.data())))
|
|
130
|
+
break
|
|
117
131
|
//handle standard token contract events
|
|
118
132
|
//see https://github.com/stellar/rs-soroban-sdk/blob/main/soroban-sdk/src/token.rs
|
|
119
133
|
case 'transfer': {
|
package/src/effect-types.js
CHANGED
|
@@ -86,12 +86,14 @@ const effectTypes = {
|
|
|
86
86
|
contractUpdated: 'contractUpdated',
|
|
87
87
|
|
|
88
88
|
contractInvoked: 'contractInvoked',
|
|
89
|
+
contractError: 'contractError',
|
|
89
90
|
|
|
90
91
|
contractDataCreated: 'contractDataCreated',
|
|
91
92
|
contractDataUpdated: 'contractDataUpdated',
|
|
92
93
|
contractDataRemoved: 'contractDataRemoved',
|
|
93
94
|
|
|
94
|
-
contractEvent: 'contractEvent'
|
|
95
|
+
contractEvent: 'contractEvent',
|
|
96
|
+
contractMetrics: 'contractMetrics'
|
|
95
97
|
}
|
|
96
98
|
|
|
97
99
|
module.exports = effectTypes
|
package/src/effects-analyzer.js
CHANGED
|
@@ -9,7 +9,7 @@ const AssetSupplyAnalyzer = require('./aggregation/asset-supply-analyzer')
|
|
|
9
9
|
const {UnexpectedTxMetaChangeError, TxMetaEffectParserError} = require('./errors')
|
|
10
10
|
|
|
11
11
|
class EffectsAnalyzer {
|
|
12
|
-
constructor({operation, meta, result, network, events, diagnosticEvents, mapSac}) {
|
|
12
|
+
constructor({operation, meta, result, network, events, diagnosticEvents, mapSac, processSystemEvents}) {
|
|
13
13
|
//set execution context
|
|
14
14
|
if (!operation.source)
|
|
15
15
|
throw new TxMetaEffectParserError('Operation source is not explicitly defined')
|
|
@@ -21,6 +21,9 @@ class EffectsAnalyzer {
|
|
|
21
21
|
this.events = events
|
|
22
22
|
if (diagnosticEvents?.length) {
|
|
23
23
|
this.diagnosticEvents = diagnosticEvents
|
|
24
|
+
if (processSystemEvents) {
|
|
25
|
+
this.processSystemEvents = true
|
|
26
|
+
}
|
|
24
27
|
}
|
|
25
28
|
this.network = network
|
|
26
29
|
if (mapSac) {
|
|
@@ -69,10 +72,20 @@ class EffectsAnalyzer {
|
|
|
69
72
|
*/
|
|
70
73
|
source = ''
|
|
71
74
|
/**
|
|
72
|
-
* @type {
|
|
75
|
+
* @type {Boolean}
|
|
73
76
|
* @private
|
|
74
77
|
*/
|
|
75
78
|
isContractCall = false
|
|
79
|
+
/**
|
|
80
|
+
* @type {Boolean}
|
|
81
|
+
* @readonly
|
|
82
|
+
*/
|
|
83
|
+
processSystemEvents = false
|
|
84
|
+
/**
|
|
85
|
+
* @type {{}}
|
|
86
|
+
* @private
|
|
87
|
+
*/
|
|
88
|
+
metrics
|
|
76
89
|
|
|
77
90
|
analyze() {
|
|
78
91
|
//find appropriate parser method
|
|
@@ -160,6 +173,17 @@ class EffectsAnalyzer {
|
|
|
160
173
|
}, position)
|
|
161
174
|
}
|
|
162
175
|
|
|
176
|
+
addMetric(metric, value) {
|
|
177
|
+
let {metrics} = this
|
|
178
|
+
if (!metrics) {
|
|
179
|
+
metrics = this.metrics = {
|
|
180
|
+
type: effectTypes.contractMetrics
|
|
181
|
+
}
|
|
182
|
+
this.addEffect(metrics)
|
|
183
|
+
}
|
|
184
|
+
metrics[metric] = value
|
|
185
|
+
}
|
|
186
|
+
|
|
163
187
|
setOptions() {
|
|
164
188
|
const sourceAccount = normalizeAddress(this.source)
|
|
165
189
|
const {before, after} = this.changes.find(ch => ch.type === 'account' && ch.before.address === sourceAccount)
|
package/src/index.js
CHANGED
|
@@ -17,9 +17,11 @@ const effectTypes = require('./effect-types')
|
|
|
17
17
|
* @param {String|Buffer|xdr.TransactionResult} [result] - Base64-encoded tx envelope result
|
|
18
18
|
* @param {String|Buffer|xdr.TransactionMeta} [meta] - Base64-encoded tx envelope meta
|
|
19
19
|
* @param {Boolean} [mapSac] - Whether to create a map SAC->Asset
|
|
20
|
+
* @param {Boolean} [processSystemEvents] - Emit effects for contract errors and resource stats
|
|
21
|
+
* @param {Number} [protocol] - Specific Stellar protocol version for the executed transaction
|
|
20
22
|
* @return {ParsedTxOperationsMetadata}
|
|
21
23
|
*/
|
|
22
|
-
function parseTxOperationsMeta({network, tx, result, meta, mapSac = false}) {
|
|
24
|
+
function parseTxOperationsMeta({network, tx, result, meta, mapSac = false, processSystemEvents = false, protocol}) {
|
|
23
25
|
if (!network)
|
|
24
26
|
throw new TypeError(`Network passphrase argument is required.`)
|
|
25
27
|
if (typeof network !== 'string')
|
|
@@ -112,7 +114,7 @@ function parseTxOperationsMeta({network, tx, result, meta, mapSac = false}) {
|
|
|
112
114
|
effect.source = (before || after).address
|
|
113
115
|
res.effects.push(effect)
|
|
114
116
|
}
|
|
115
|
-
if (isFeeBump && before.balance !== after.balance) { //
|
|
117
|
+
if (isFeeBump && protocol === 20 && before.balance !== after.balance) { //bump fee calculation bug in protocol v20
|
|
116
118
|
const currentFee = BigInt(feeEffect.charged)
|
|
117
119
|
const diff = BigInt(after.balance) - BigInt(before.balance)
|
|
118
120
|
if (diff < currentFee) { // do not allow negative fee
|
|
@@ -138,6 +140,7 @@ function parseTxOperationsMeta({network, tx, result, meta, mapSac = false}) {
|
|
|
138
140
|
params.events = sorobanMeta.events()
|
|
139
141
|
params.diagnosticEvents = sorobanMeta.diagnosticEvents()
|
|
140
142
|
params.mapSac = mapSac
|
|
143
|
+
params.processSystemEvents = processSystemEvents
|
|
141
144
|
}
|
|
142
145
|
const analyzer = new EffectsAnalyzer(params)
|
|
143
146
|
operation.effects = analyzer.analyze()
|