@stellar-expert/tx-meta-effects-parser 7.0.0-rc.6 → 7.0.0-rc.8

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": "7.0.0-rc.6",
3
+ "version": "7.0.0-rc.8",
4
4
  "description": "Low-level effects parser for Stellar transaction results and meta XDR",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -1,4 +1,4 @@
1
- const {StrKey} = require('@stellar/stellar-base')
1
+ const {StrKey, encodeMuxedAccount, encodeMuxedAccountToAddress} = require('@stellar/stellar-base')
2
2
  const effectTypes = require('../effect-types')
3
3
  const {xdrParseScVal, xdrParseAsset, isContractAddress} = require('../parser/tx-xdr-parser-utils')
4
4
  const {mapSacContract} = require('./sac-contract-mapper')
@@ -146,15 +146,17 @@ class EventsAnalyzer {
146
146
  if (!matchEventTopicsShape(topics, ['address', 'address', 'str?']))
147
147
  return
148
148
  const from = xdrParseScVal(topics[1])
149
- const to = xdrParseScVal(topics[2])
149
+ const receiver = xdrParseScVal(topics[2])
150
+ let to = receiver
151
+ let amount = processEventBodyValue(body.data())
152
+ if (amount.amount !== undefined) {
153
+ if (amount.to_muxed_id && !to.startsWith('M')) {
154
+ to = encodeMuxedAccountToAddress(encodeMuxedAccount(to, amount.to_muxed_id))
155
+ amount = amount.amount
156
+ }
157
+ }
150
158
  if (to === from) //self transfer - nothing happens
151
159
  return // TODO: need additional checks
152
- const amount = processEventBodyValue(body.data())
153
- if (!this.matchInvocationEffect(e =>
154
- (e.function === 'transfer' && matchArrays([from, to, amount], e.args)) ||
155
- (e.function === 'transfer_from' && matchArrays([undefined, from, to, amount], e.args))
156
- ))
157
- return
158
160
  let classicAsset
159
161
  if (topics.length > 3) {
160
162
  classicAsset = xdrParseAsset(xdrParseScVal(topics[3]))
@@ -172,7 +174,7 @@ class EventsAnalyzer {
172
174
  if (isContractAddress(to)) {
173
175
  this.effectsAnalyzer.credit(amount, classicAsset, to)
174
176
  }
175
- if (classicAsset.includes(to)) { //SAC transfer by asset issuer
177
+ if (classicAsset.includes(receiver)) { //SAC transfer by asset issuer
176
178
  this.effectsAnalyzer.burn(classicAsset, amount)
177
179
  }
178
180
  } else { //other cases
@@ -182,14 +184,19 @@ class EventsAnalyzer {
182
184
  }
183
185
  break
184
186
  case 'mint': {
185
- if (!matchEventTopicsShape(topics, ['address', 'address', 'str?']))
187
+ if (!matchEventTopicsShape(topics, ['address', 'address', 'str?']) && !matchEventTopicsShape(topics, ['address', 'str?']))
186
188
  return //throw new Error('Non-standard event')
187
- const to = xdrParseScVal(topics[2])
188
- const amount = processEventBodyValue(body.data())
189
- if (!this.matchInvocationEffect(e => e.function === 'mint' && matchArrays([to, amount], e.args)))
190
- return
191
- if (topics.length > 3) {
192
- mapSacContract(this.effectsAnalyzer, contract, xdrParseAsset(xdrParseScVal(topics[3])))
189
+ let to = xdrParseScVal(topics[topics[2]?._arm === 'address' ? 2 : 1])
190
+ let amount = processEventBodyValue(body.data())
191
+ if (amount.amount !== undefined) {
192
+ if (amount.to_muxed_id && !to.startsWith('M')) {
193
+ to = encodeMuxedAccountToAddress(encodeMuxedAccount(to, amount.to_muxed_id))
194
+ amount = amount.amount
195
+ }
196
+ }
197
+ const last = topics[topics.length - 1]
198
+ if (last._arm === 'str') {
199
+ mapSacContract(this.effectsAnalyzer, contract, xdrParseAsset(xdrParseScVal(last)))
193
200
  }
194
201
  const asset = this.effectsAnalyzer.resolveAsset(contract)
195
202
  this.effectsAnalyzer.mint(asset, amount)
@@ -205,11 +212,6 @@ class EventsAnalyzer {
205
212
  const amount = processEventBodyValue(body.data())
206
213
  if (!amount)
207
214
  return
208
- if (!this.matchInvocationEffect(e =>
209
- (e.function === 'burn' && matchArrays([from, amount], e.args)) ||
210
- (e.function === 'burn_from' && matchArrays([undefined, from, amount], e.args))
211
- ))
212
- return
213
215
  if (topics.length > 2) {
214
216
  mapSacContract(this.effectsAnalyzer, contract, xdrParseAsset(xdrParseScVal(topics[2])))
215
217
  }
@@ -221,12 +223,10 @@ class EventsAnalyzer {
221
223
  }
222
224
  break
223
225
  case 'clawback': {
224
- if (!matchEventTopicsShape(topics, ['address', 'address', 'str?']))
226
+ if (!matchEventTopicsShape(topics, ['address', 'address', 'str?']) && !matchEventTopicsShape(topics, ['address', 'str?']))
225
227
  return //throw new Error('Non-standard event')
226
- const from = xdrParseScVal(topics[2])
228
+ const from = xdrParseScVal(topics[topics[2]?._arm === 'address' ? 2 : 1])
227
229
  const amount = processEventBodyValue(body.data())
228
- if (!this.matchInvocationEffect(e => e.function === 'clawback' && matchArrays([from, amount], e.args)))
229
- return
230
230
  if (topics.length > 3) {
231
231
  mapSacContract(this.effectsAnalyzer, contract, xdrParseAsset(xdrParseScVal(topics[3])))
232
232
  }
@@ -240,15 +240,14 @@ class EventsAnalyzer {
240
240
  return //throw new Error('Non-standard event')
241
241
  const currentAdmin = xdrParseScVal(topics[1])
242
242
  const newAdmin = processEventBodyValue(body.data())
243
- if (!this.matchInvocationEffect(e => e.function === 'set_admin' && matchArrays([currentAdmin, newAdmin], [this.effectsAnalyzer.source, e.args])))
244
- return
245
243
  if (topics.length > 2) {
246
244
  mapSacContract(this.effectsAnalyzer, contract, xdrParseAsset(xdrParseScVal(topics[2])))
247
245
  }
248
246
  this.effectsAnalyzer.setAdmin(contract, newAdmin)
249
247
  }
250
248
  break
251
- /*case 'approve': { //TODO: think about processing this effect
249
+ /*case 'set_authorized':*/ //TODO: think about processing this effects
250
+ /*case 'approve': {
252
251
  if (!matchEventTopicsShape(topics, ['address', 'address', 'str?']))
253
252
  throw new Error('Non-standard event')
254
253
  const from = xdrParseScVal(topics[1])
@@ -260,12 +259,14 @@ class EventsAnalyzer {
260
259
  break*/
261
260
  }
262
261
  }
263
-
264
- matchInvocationEffect(cb) {
265
- return this.effectsAnalyzer.effects.find(e => e.type === effectTypes.contractInvoked && cb(e))
266
- }
267
262
  }
268
263
 
264
+ /**
265
+ * Compare types in the topics array with expected values
266
+ * @param {ScVal[]} topics
267
+ * @param {string[]} shape
268
+ * @return {boolean}
269
+ */
269
270
  function matchEventTopicsShape(topics, shape) {
270
271
  if (topics.length > shape.length + 1)
271
272
  return false
@@ -287,22 +288,12 @@ function matchEventTopicsShape(topics, shape) {
287
288
  return true
288
289
  }
289
290
 
290
- function matchArrays(a, b) {
291
- if (!a || !b)
292
- return false
293
- if (a.length !== b.length)
294
- return false
295
- for (let i = a.length; i--;) {
296
- if (a[i] !== undefined && a[i] !== b[i]) //undefined serves as * substitution
297
- return false
298
- }
299
- return true
300
- }
301
-
291
+ /**
292
+ * Retrieve event body value
293
+ * @param value
294
+ */
302
295
  function processEventBodyValue(value) {
303
296
  const innerValue = value.value()
304
- /*if (innerValue instanceof Array) //handle simple JS arrays
305
- return innerValue.map(xdrParseScVal)*/
306
297
  if (!innerValue) //scVoid
307
298
  return null
308
299
  return xdrParseScVal(value) //other scValue
@@ -24,12 +24,16 @@ function mapSacContract(effectsAnalyzer, contractAddress, classicAsset) {
24
24
  //try to load from cache first
25
25
  const fromCache = sacCache.get(classicAsset + network)
26
26
  if (!fromCache) {
27
- const encodedContract = contractIdFromAsset(toStellarAsset(classicAsset), network)
28
- sacCache.set(classicAsset + network, contractAddress)
29
- if (contractAddress === undefined) {
30
- contractAddress = encodedContract
31
- } else if (encodedContract !== contractAddress)
27
+ try {
28
+ const encodedContract = contractIdFromAsset(toStellarAsset(classicAsset), network)
29
+ sacCache.set(classicAsset + network, contractAddress)
30
+ if (contractAddress === undefined) {
31
+ contractAddress = encodedContract
32
+ } else if (encodedContract !== contractAddress)
33
+ return false
34
+ } catch (e) {
32
35
  return false
36
+ }
33
37
  } else if (contractAddress !== fromCache)
34
38
  return false //check whether validated contract from cache matches the asset
35
39
  if (sacMap) {
@@ -310,6 +310,7 @@ module.exports = {
310
310
  xdrParseAsset,
311
311
  xdrParseAccountAddress,
312
312
  xdrParseContractAddress,
313
+ xdrParseMuxedScAddress,
313
314
  xdrParseClaimant,
314
315
  xdrParseClaimedOffer,
315
316
  xdrParseTradeAtom,