@stellar-expert/tx-meta-effects-parser 8.3.3 → 8.4.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.
@@ -1,335 +1,335 @@
1
- const {StrKey} = require('@stellar/stellar-base')
2
- const {TxMetaEffectParserError, UnexpectedTxMetaChangeError} = require('../errors')
3
- const {
4
- xdrParseAsset,
5
- xdrParseAccountAddress,
6
- xdrParseClaimant,
7
- xdrParsePrice,
8
- xdrParseSignerKey
9
- } = require('./tx-xdr-parser-utils')
10
- const {generateContractStateEntryHash, generateContractCodeEntryHash} = require('./ledger-key')
11
-
12
- /**
13
- * @typedef {{}} ParsedLedgerEntryMeta
14
- * @property {'account'|'trustline'|'offer'|'data'|'liquidityPool'|'claimableBalance'|'contractData'|'contractCode'|'ttl'} type - Ledger entry type
15
- * @property {'created'|'updated'|'removed'|'restored'} action - Ledger modification action
16
- * @property {{}} before - Ledger entry state before changes applied
17
- * @property {{}} after - Ledger entry state after changes application
18
- */
19
-
20
- /**
21
- * @param {LedgerEntryChange[]} ledgerEntryChanges
22
- * @param {Set<string>} [filter]
23
- * @return {ParsedLedgerEntryMeta[]}
24
- */
25
- function parseLedgerEntryChanges(ledgerEntryChanges, filter = undefined) {
26
- const changes = []
27
- let state
28
- let containsTtl = false
29
- for (let i = 0; i < ledgerEntryChanges.length; i++) {
30
- const entry = ledgerEntryChanges[i]
31
- const type = entry._value._arm || entry._value._attributes.data._arm
32
- if (filter && !filter.has(type)) //skip filtered ledger entry types
33
- continue
34
- const action = entry._arm
35
- const stateData = parseEntry(entry, action)
36
- if (stateData === undefined)
37
- continue
38
- const change = {action, type}
39
- switch (action) {
40
- case 'state':
41
- state = stateData
42
- continue
43
- case 'created':
44
- if (type === 'contractCode')
45
- continue //processed in operation handler
46
- change.before = null
47
- change.after = stateData
48
- change.type = stateData.entry
49
- break
50
- case 'updated':
51
- change.before = state
52
- change.after = stateData
53
- change.type = stateData.entry
54
- break
55
- case 'restored':
56
- change.before = stateData
57
- change.after = stateData
58
- change.type = stateData.entry
59
- state = change.after
60
- break
61
- case 'removed':
62
- if (!state && type === 'ttl')
63
- continue //skip expiration processing for now
64
- change.before = state
65
- change.after = null
66
- change.type = state.entry
67
- break
68
- default:
69
- throw new TxMetaEffectParserError(`Unknown change entry type: ${action}`)
70
- }
71
- if (change.type === 'ttl') {
72
- containsTtl = true
73
- }
74
- changes.push(change)
75
- }
76
- if (containsTtl) { //put ttl entries into the end of array
77
- changes.sort((a, b) =>
78
- a.type !== 'ttl' && b.type === 'ttl' ?
79
- -1 : 0)
80
- }
81
- return changes
82
- }
83
-
84
- function parseEntry(entry, actionType) {
85
- if (actionType === 'removed')
86
- return null
87
- const value = entry.value()
88
- const parsed = parseEntryData(value.data())
89
- if (parsed === null)
90
- return null
91
- //parsed.modified = entry.lastModifiedLedgerSeq()
92
- return parseLedgerEntryExt(parsed, value)
93
- }
94
-
95
- function parseEntryData(data) {
96
- const updatedEntryType = data.arm()
97
- switch (updatedEntryType) {
98
- case 'account':
99
- return parseAccountEntry(data)
100
- case 'trustline':
101
- case 'trustLine':
102
- return parseTrustlineEntry(data)
103
- case 'offer':
104
- return parseOfferEntry(data)
105
- case 'data':
106
- case 'datum':
107
- return parseDataEntry(data)
108
- case 'claimableBalance':
109
- return parseClaimableBalanceEntry(data)
110
- case 'liquidityPool':
111
- return parseLiquidityPoolEntry(data)
112
- case 'contractData':
113
- return parseContractData(data)
114
- case 'contractCode':
115
- return parseContractCode(data)
116
- case 'ttl':
117
- return parseTtl(data)
118
- default:
119
- throw new TxMetaEffectParserError(`Unknown meta entry type: ${updatedEntryType}`)
120
- }
121
- }
122
-
123
- function parseLedgerEntryExt(data, entry) {
124
- const v1 = entry.ext()?.v1()
125
- if (v1) {
126
- const sponsor = v1.sponsoringId()
127
- if (sponsor) {
128
- data.sponsor = xdrParseAccountAddress(sponsor)
129
- }
130
- }
131
- return data
132
- }
133
-
134
- function parseAccountEntry(value) {
135
- const accountEntryXdr = value.value()
136
- const data = {
137
- entry: 'account',
138
- address: xdrParseAccountAddress(accountEntryXdr.accountId()),
139
- sequence: accountEntryXdr.seqNum().toString(),
140
- balance: accountEntryXdr.balance().toString(),
141
- homeDomain: accountEntryXdr.homeDomain().toString('UTF8'),
142
- inflationDest: xdrParseAccountAddress(accountEntryXdr.inflationDest()),
143
- flags: accountEntryXdr.flags(),
144
- signers: accountEntryXdr.signers().map(signer => ({
145
- key: xdrParseSignerKey(signer.key()),
146
- weight: signer.weight()
147
- }))
148
- }
149
- const thresholds = accountEntryXdr.thresholds()
150
- data.thresholds = thresholds.slice(1).join()
151
- data.masterWeight = thresholds[0]
152
- const extV1 = accountEntryXdr.ext()?.v1()
153
- if (extV1) {
154
- const extV2 = extV1.ext()?.v2()
155
- if (extV2) {
156
- const sponsoringIDs = extV2.signerSponsoringIDs()
157
- if (sponsoringIDs.length > 0) {
158
- for (let i = 0; i < data.signers.length; i++) {
159
- const sponsor = sponsoringIDs[i]
160
- if (sponsor) { //attach sponsors directly to the signers
161
- data.signers[i].sponsor = xdrParseAccountAddress(sponsor)
162
- }
163
- }
164
- }
165
- }
166
- }
167
- //ignored fields: numSubEntries, extV1.liabilities, extV2.numSponsored, extV2.numSponsoring, extV3.seqLedger, extv3.seqTime
168
- return data
169
- }
170
-
171
- function parseTrustlineEntry(value) {
172
- const trustlineEntryXdr = value.value()
173
- const trustlineAsset = trustlineEntryXdr.asset()
174
- const trustlineType = trustlineAsset.switch()
175
- let asset
176
- switch (trustlineType.value) {
177
- case 0:
178
- case 1:
179
- case 2:
180
- asset = xdrParseAsset(trustlineAsset)
181
- break
182
- case 3:
183
- asset = StrKey.encodeLiquidityPool(trustlineEntryXdr.asset().liquidityPoolId())
184
- break
185
- default:
186
- throw new TxMetaEffectParserError(`Unsupported trustline type ` + trustlineType)
187
- }
188
- const data = {
189
- entry: 'trustline',
190
- account: xdrParseAccountAddress(trustlineEntryXdr.accountId()),
191
- asset,
192
- balance: trustlineEntryXdr.balance().toString(),
193
- limit: trustlineEntryXdr.limit().toString(),
194
- flags: trustlineEntryXdr.flags()
195
- }
196
-
197
- /*
198
- //ignored
199
- const extV1 = trustlineEntryXdr.ext()?.v1()
200
- if (extV1) {
201
- const liabilities = extV1.liabilities()
202
- data.buying_liabilities = liabilities.buying().toString()
203
- data.selling_liabilities = liabilities.selling().toString()
204
- }*/
205
-
206
- return data
207
- }
208
-
209
- function parseDataEntry(value) {
210
- const dataEntryXdr = value.value()
211
- return {
212
- entry: 'data',
213
- account: xdrParseAccountAddress(dataEntryXdr.accountId()),
214
- name: dataEntryXdr.dataName().toString(),
215
- value: dataEntryXdr.dataValue().toString('base64')
216
- }
217
- }
218
-
219
- function parseLiquidityPoolEntry(value) {
220
- const liquidityPoolEntryXdr = value.value()
221
- const body = liquidityPoolEntryXdr.body().value()
222
- const params = body.params()
223
- return {
224
- entry: 'liquidityPool',
225
- pool: StrKey.encodeLiquidityPool(liquidityPoolEntryXdr.liquidityPoolId()),
226
- asset: [xdrParseAsset(params.assetA()), xdrParseAsset(params.assetB())],
227
- fee: params.fee(),
228
- amount: [body.reserveA().toString(), body.reserveB().toString()],
229
- shares: body.totalPoolShares().toString(),
230
- accounts: body.poolSharesTrustLineCount().low
231
- }
232
- }
233
-
234
- function parseOfferEntry(value) {
235
- const offerEntryXdr = value.value()
236
- const rprice = offerEntryXdr.price()
237
- const data = {
238
- entry: 'offer',
239
- id: offerEntryXdr.offerId().toString(),
240
- account: xdrParseAccountAddress(offerEntryXdr.sellerId()),
241
- asset: [xdrParseAsset(offerEntryXdr.selling()), xdrParseAsset(offerEntryXdr.buying())],
242
- amount: offerEntryXdr.amount().toString(),
243
- price: xdrParsePrice(rprice),
244
- rprice: rprice._attributes,
245
- flags: offerEntryXdr.flags()
246
- }
247
- return data
248
- }
249
-
250
- function parseClaimableBalanceEntry(value) {
251
- const claimableBalanceXdr = value.value()
252
- const data = {
253
- balanceId: StrKey.encodeClaimableBalance(claimableBalanceXdr.balanceId().value()),
254
- entry: 'claimableBalance',
255
- asset: xdrParseAsset(claimableBalanceXdr.asset()),
256
- amount: claimableBalanceXdr.amount().toString(),
257
- claimants: claimableBalanceXdr.claimants().map(claimant => xdrParseClaimant(claimant))
258
- }
259
- const extV1 = claimableBalanceXdr.ext()?.v1()
260
- if (extV1) {
261
- data.flags = extV1.flags()
262
- }
263
- return data
264
- }
265
-
266
- function parseContractData(value) {
267
- const data = value.value()
268
- const owner = parseStateOwnerDataAddress(data.contract())
269
-
270
- const valueAttr = data.val()
271
- const entry = {
272
- entry: 'contractData',
273
- owner,
274
- key: data.key().toXDR('base64'),
275
- value: valueAttr.toXDR('base64'),
276
- durability: data.durability().name,
277
- keyHash: generateContractStateEntryHash(data)
278
- }
279
- if (data.key().switch()?.name === 'scvLedgerKeyContractInstance' && entry.durability === 'persistent') {
280
- entry.durability = 'instance'
281
- const instance = valueAttr.instance()._attributes
282
- const type = instance.executable._switch.name
283
- switch (type) {
284
- case 'contractExecutableStellarAsset':
285
- entry.kind = 'fromAsset'
286
- if (instance.storage?.length) { //if not -- the asset has been created "fromAddress" - no metadata in this case
287
- const metaArgs = instance.storage[0]._attributes
288
- if (metaArgs.key._value.toString() !== 'METADATA')
289
- throw new TxMetaEffectParserError('Unexpected asset initialization metadata')
290
- entry.asset = xdrParseAsset(metaArgs.val._value[1]._attributes.val._value.toString())
291
- }
292
- break
293
- case 'contractExecutableWasm':
294
- entry.kind = 'wasm'
295
- entry.wasmHash = instance.executable.wasmHash().toString('hex')
296
- break
297
- default:
298
- throw new TxMetaEffectParserError('Unsupported executable type: ' + type)
299
- }
300
- if (instance.storage?.length) {
301
- entry.storage = instance.storage.map(entry => ({
302
- key: entry.key().toXDR('base64'),
303
- val: entry.val().toXDR('base64')
304
- }))
305
- }
306
- }
307
- return entry
308
- }
309
-
310
- function parseTtl(data) {
311
- const attrs = data._value._attributes
312
- return {
313
- entry: 'ttl',
314
- keyHash: attrs.keyHash.toString('hex'),
315
- ttl: attrs.liveUntilLedgerSeq
316
- }
317
- }
318
-
319
- function parseStateOwnerDataAddress(contract) {
320
- if (contract.switch().name === 'scAddressTypeContract')
321
- return StrKey.encodeContract(contract.contractId())
322
- return xdrParseAccountAddress(contract.accountId())
323
- }
324
-
325
- function parseContractCode(value) {
326
- const contract = value.value()
327
- const hash = contract.hash()
328
- return {
329
- entry: 'contractCode',
330
- hash: hash.toString('hex'),
331
- keyHash: generateContractCodeEntryHash(hash)
332
- }
333
- }
334
-
1
+ const {StrKey} = require('@stellar/stellar-base')
2
+ const {TxMetaEffectParserError, UnexpectedTxMetaChangeError} = require('../errors')
3
+ const {
4
+ xdrParseAsset,
5
+ xdrParseAccountAddress,
6
+ xdrParseClaimant,
7
+ xdrParsePrice,
8
+ xdrParseSignerKey
9
+ } = require('./tx-xdr-parser-utils')
10
+ const {generateContractStateEntryHash, generateContractCodeEntryHash} = require('./ledger-key')
11
+
12
+ /**
13
+ * @typedef {{}} ParsedLedgerEntryMeta
14
+ * @property {'account'|'trustline'|'offer'|'data'|'liquidityPool'|'claimableBalance'|'contractData'|'contractCode'|'ttl'} type - Ledger entry type
15
+ * @property {'created'|'updated'|'removed'|'restored'} action - Ledger modification action
16
+ * @property {{}} before - Ledger entry state before changes applied
17
+ * @property {{}} after - Ledger entry state after changes application
18
+ */
19
+
20
+ /**
21
+ * @param {LedgerEntryChange[]} ledgerEntryChanges
22
+ * @param {Set<string>} [filter]
23
+ * @return {ParsedLedgerEntryMeta[]}
24
+ */
25
+ function parseLedgerEntryChanges(ledgerEntryChanges, filter = undefined) {
26
+ const changes = []
27
+ let state
28
+ let containsTtl = false
29
+ for (let i = 0; i < ledgerEntryChanges.length; i++) {
30
+ const entry = ledgerEntryChanges[i]
31
+ const type = entry._value._arm || entry._value._attributes.data._arm
32
+ if (filter && !filter.has(type)) //skip filtered ledger entry types
33
+ continue
34
+ const action = entry._arm
35
+ const stateData = parseEntry(entry, action)
36
+ if (stateData === undefined)
37
+ continue
38
+ const change = {action, type}
39
+ switch (action) {
40
+ case 'state':
41
+ state = stateData
42
+ continue
43
+ case 'created':
44
+ if (type === 'contractCode')
45
+ continue //processed in operation handler
46
+ change.before = null
47
+ change.after = stateData
48
+ change.type = stateData.entry
49
+ break
50
+ case 'updated':
51
+ change.before = state
52
+ change.after = stateData
53
+ change.type = stateData.entry
54
+ break
55
+ case 'restored':
56
+ change.before = stateData
57
+ change.after = stateData
58
+ change.type = stateData.entry
59
+ state = change.after
60
+ break
61
+ case 'removed':
62
+ if (!state && type === 'ttl')
63
+ continue //skip expiration processing for now
64
+ change.before = state
65
+ change.after = null
66
+ change.type = state.entry
67
+ break
68
+ default:
69
+ throw new TxMetaEffectParserError(`Unknown change entry type: ${action}`)
70
+ }
71
+ if (change.type === 'ttl') {
72
+ containsTtl = true
73
+ }
74
+ changes.push(change)
75
+ }
76
+ if (containsTtl) { //put ttl entries into the end of array
77
+ changes.sort((a, b) =>
78
+ a.type !== 'ttl' && b.type === 'ttl' ?
79
+ -1 : 0)
80
+ }
81
+ return changes
82
+ }
83
+
84
+ function parseEntry(entry, actionType) {
85
+ if (actionType === 'removed')
86
+ return null
87
+ const value = entry.value()
88
+ const parsed = parseEntryData(value.data())
89
+ if (parsed === null)
90
+ return null
91
+ //parsed.modified = entry.lastModifiedLedgerSeq()
92
+ return parseLedgerEntryExt(parsed, value)
93
+ }
94
+
95
+ function parseEntryData(data) {
96
+ const updatedEntryType = data.arm()
97
+ switch (updatedEntryType) {
98
+ case 'account':
99
+ return parseAccountEntry(data)
100
+ case 'trustline':
101
+ case 'trustLine':
102
+ return parseTrustlineEntry(data)
103
+ case 'offer':
104
+ return parseOfferEntry(data)
105
+ case 'data':
106
+ case 'datum':
107
+ return parseDataEntry(data)
108
+ case 'claimableBalance':
109
+ return parseClaimableBalanceEntry(data)
110
+ case 'liquidityPool':
111
+ return parseLiquidityPoolEntry(data)
112
+ case 'contractData':
113
+ return parseContractData(data)
114
+ case 'contractCode':
115
+ return parseContractCode(data)
116
+ case 'ttl':
117
+ return parseTtl(data)
118
+ default:
119
+ throw new TxMetaEffectParserError(`Unknown meta entry type: ${updatedEntryType}`)
120
+ }
121
+ }
122
+
123
+ function parseLedgerEntryExt(data, entry) {
124
+ const v1 = entry.ext()?.v1()
125
+ if (v1) {
126
+ const sponsor = v1.sponsoringId()
127
+ if (sponsor) {
128
+ data.sponsor = xdrParseAccountAddress(sponsor)
129
+ }
130
+ }
131
+ return data
132
+ }
133
+
134
+ function parseAccountEntry(value) {
135
+ const accountEntryXdr = value.value()
136
+ const data = {
137
+ entry: 'account',
138
+ address: xdrParseAccountAddress(accountEntryXdr.accountId()),
139
+ sequence: accountEntryXdr.seqNum().toString(),
140
+ balance: accountEntryXdr.balance().toString(),
141
+ homeDomain: accountEntryXdr.homeDomain().toString('UTF8'),
142
+ inflationDest: xdrParseAccountAddress(accountEntryXdr.inflationDest()),
143
+ flags: accountEntryXdr.flags(),
144
+ signers: accountEntryXdr.signers().map(signer => ({
145
+ key: xdrParseSignerKey(signer.key()),
146
+ weight: signer.weight()
147
+ }))
148
+ }
149
+ const thresholds = accountEntryXdr.thresholds()
150
+ data.thresholds = thresholds.slice(1).join()
151
+ data.masterWeight = thresholds[0]
152
+ const extV1 = accountEntryXdr.ext()?.v1()
153
+ if (extV1) {
154
+ const extV2 = extV1.ext()?.v2()
155
+ if (extV2) {
156
+ const sponsoringIDs = extV2.signerSponsoringIDs()
157
+ if (sponsoringIDs.length > 0) {
158
+ for (let i = 0; i < data.signers.length; i++) {
159
+ const sponsor = sponsoringIDs[i]
160
+ if (sponsor) { //attach sponsors directly to the signers
161
+ data.signers[i].sponsor = xdrParseAccountAddress(sponsor)
162
+ }
163
+ }
164
+ }
165
+ }
166
+ }
167
+ //ignored fields: numSubEntries, extV1.liabilities, extV2.numSponsored, extV2.numSponsoring, extV3.seqLedger, extv3.seqTime
168
+ return data
169
+ }
170
+
171
+ function parseTrustlineEntry(value) {
172
+ const trustlineEntryXdr = value.value()
173
+ const trustlineAsset = trustlineEntryXdr.asset()
174
+ const trustlineType = trustlineAsset.switch()
175
+ let asset
176
+ switch (trustlineType.value) {
177
+ case 0:
178
+ case 1:
179
+ case 2:
180
+ asset = xdrParseAsset(trustlineAsset)
181
+ break
182
+ case 3:
183
+ asset = StrKey.encodeLiquidityPool(trustlineEntryXdr.asset().liquidityPoolId())
184
+ break
185
+ default:
186
+ throw new TxMetaEffectParserError(`Unsupported trustline type ` + trustlineType)
187
+ }
188
+ const data = {
189
+ entry: 'trustline',
190
+ account: xdrParseAccountAddress(trustlineEntryXdr.accountId()),
191
+ asset,
192
+ balance: trustlineEntryXdr.balance().toString(),
193
+ limit: trustlineEntryXdr.limit().toString(),
194
+ flags: trustlineEntryXdr.flags()
195
+ }
196
+
197
+ /*
198
+ //ignored
199
+ const extV1 = trustlineEntryXdr.ext()?.v1()
200
+ if (extV1) {
201
+ const liabilities = extV1.liabilities()
202
+ data.buying_liabilities = liabilities.buying().toString()
203
+ data.selling_liabilities = liabilities.selling().toString()
204
+ }*/
205
+
206
+ return data
207
+ }
208
+
209
+ function parseDataEntry(value) {
210
+ const dataEntryXdr = value.value()
211
+ return {
212
+ entry: 'data',
213
+ account: xdrParseAccountAddress(dataEntryXdr.accountId()),
214
+ name: dataEntryXdr.dataName().toString(),
215
+ value: dataEntryXdr.dataValue().toString('base64')
216
+ }
217
+ }
218
+
219
+ function parseLiquidityPoolEntry(value) {
220
+ const liquidityPoolEntryXdr = value.value()
221
+ const body = liquidityPoolEntryXdr.body().value()
222
+ const params = body.params()
223
+ return {
224
+ entry: 'liquidityPool',
225
+ pool: StrKey.encodeLiquidityPool(liquidityPoolEntryXdr.liquidityPoolId()),
226
+ asset: [xdrParseAsset(params.assetA()), xdrParseAsset(params.assetB())],
227
+ fee: params.fee(),
228
+ amount: [body.reserveA().toString(), body.reserveB().toString()],
229
+ shares: body.totalPoolShares().toString(),
230
+ accounts: body.poolSharesTrustLineCount().low
231
+ }
232
+ }
233
+
234
+ function parseOfferEntry(value) {
235
+ const offerEntryXdr = value.value()
236
+ const rprice = offerEntryXdr.price()
237
+ const data = {
238
+ entry: 'offer',
239
+ id: offerEntryXdr.offerId().toString(),
240
+ account: xdrParseAccountAddress(offerEntryXdr.sellerId()),
241
+ asset: [xdrParseAsset(offerEntryXdr.selling()), xdrParseAsset(offerEntryXdr.buying())],
242
+ amount: offerEntryXdr.amount().toString(),
243
+ price: xdrParsePrice(rprice),
244
+ rprice: rprice._attributes,
245
+ flags: offerEntryXdr.flags()
246
+ }
247
+ return data
248
+ }
249
+
250
+ function parseClaimableBalanceEntry(value) {
251
+ const claimableBalanceXdr = value.value()
252
+ const data = {
253
+ balanceId: StrKey.encodeClaimableBalance(claimableBalanceXdr.balanceId().value()),
254
+ entry: 'claimableBalance',
255
+ asset: xdrParseAsset(claimableBalanceXdr.asset()),
256
+ amount: claimableBalanceXdr.amount().toString(),
257
+ claimants: claimableBalanceXdr.claimants().map(claimant => xdrParseClaimant(claimant))
258
+ }
259
+ const extV1 = claimableBalanceXdr.ext()?.v1()
260
+ if (extV1) {
261
+ data.flags = extV1.flags()
262
+ }
263
+ return data
264
+ }
265
+
266
+ function parseContractData(value) {
267
+ const data = value.value()
268
+ const owner = parseStateOwnerDataAddress(data.contract())
269
+
270
+ const valueAttr = data.val()
271
+ const entry = {
272
+ entry: 'contractData',
273
+ owner,
274
+ key: data.key().toXDR('base64'),
275
+ value: valueAttr.toXDR('base64'),
276
+ durability: data.durability().name,
277
+ keyHash: generateContractStateEntryHash(data)
278
+ }
279
+ if (data.key().switch()?.name === 'scvLedgerKeyContractInstance' && entry.durability === 'persistent') {
280
+ entry.durability = 'instance'
281
+ const instance = valueAttr.instance()._attributes
282
+ const type = instance.executable._switch.name
283
+ switch (type) {
284
+ case 'contractExecutableStellarAsset':
285
+ entry.kind = 'fromAsset'
286
+ if (instance.storage?.length) { //if not -- the asset has been created "fromAddress" - no metadata in this case
287
+ const metaArgs = instance.storage[0]._attributes
288
+ if (metaArgs.key._value.toString() !== 'METADATA')
289
+ throw new TxMetaEffectParserError('Unexpected asset initialization metadata')
290
+ entry.asset = xdrParseAsset(metaArgs.val._value[1]._attributes.val._value.toString())
291
+ }
292
+ break
293
+ case 'contractExecutableWasm':
294
+ entry.kind = 'wasm'
295
+ entry.wasmHash = instance.executable.wasmHash().toString('hex')
296
+ break
297
+ default:
298
+ throw new TxMetaEffectParserError('Unsupported executable type: ' + type)
299
+ }
300
+ if (instance.storage?.length) {
301
+ entry.storage = instance.storage.map(entry => ({
302
+ key: entry.key().toXDR('base64'),
303
+ val: entry.val().toXDR('base64')
304
+ }))
305
+ }
306
+ }
307
+ return entry
308
+ }
309
+
310
+ function parseTtl(data) {
311
+ const attrs = data._value._attributes
312
+ return {
313
+ entry: 'ttl',
314
+ keyHash: attrs.keyHash.toString('hex'),
315
+ ttl: attrs.liveUntilLedgerSeq
316
+ }
317
+ }
318
+
319
+ function parseStateOwnerDataAddress(contract) {
320
+ if (contract.switch().name === 'scAddressTypeContract')
321
+ return StrKey.encodeContract(contract.contractId())
322
+ return xdrParseAccountAddress(contract.accountId())
323
+ }
324
+
325
+ function parseContractCode(value) {
326
+ const contract = value.value()
327
+ const hash = contract.hash()
328
+ return {
329
+ entry: 'contractCode',
330
+ hash: hash.toString('hex'),
331
+ keyHash: generateContractCodeEntryHash(hash)
332
+ }
333
+ }
334
+
335
335
  module.exports = {parseLedgerEntryChanges}