@stellar-expert/tx-meta-effects-parser 5.7.0 → 6.0.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
package/src/effect-types.js
CHANGED
|
@@ -81,6 +81,7 @@ const effectTypes = {
|
|
|
81
81
|
signerSponsorshipRemoved: 'signerSponsorshipRemoved',
|
|
82
82
|
|
|
83
83
|
contractCodeUploaded: 'contractCodeUploaded',
|
|
84
|
+
contractCodeRemoved: 'contractCodeRemoved',
|
|
84
85
|
|
|
85
86
|
contractCreated: 'contractCreated',
|
|
86
87
|
contractUpdated: 'contractUpdated',
|
|
@@ -93,7 +94,9 @@ const effectTypes = {
|
|
|
93
94
|
contractDataRemoved: 'contractDataRemoved',
|
|
94
95
|
|
|
95
96
|
contractEvent: 'contractEvent',
|
|
96
|
-
contractMetrics: 'contractMetrics'
|
|
97
|
+
contractMetrics: 'contractMetrics',
|
|
98
|
+
|
|
99
|
+
setTtl: 'setTtl'
|
|
97
100
|
}
|
|
98
101
|
|
|
99
102
|
module.exports = effectTypes
|
package/src/effects-analyzer.js
CHANGED
|
@@ -8,6 +8,7 @@ const EventsAnalyzer = require('./aggregation/events-analyzer')
|
|
|
8
8
|
const AssetSupplyAnalyzer = require('./aggregation/asset-supply-analyzer')
|
|
9
9
|
const {mapSacContract} = require('./aggregation/sac-contract-mapper')
|
|
10
10
|
const {UnexpectedTxMetaChangeError, TxMetaEffectParserError} = require('./errors')
|
|
11
|
+
const {generateContractCodeEntryHash} = require('./parser/ledger-key')
|
|
11
12
|
|
|
12
13
|
class EffectsAnalyzer {
|
|
13
14
|
constructor({operation, meta, result, network, events, diagnosticEvents, mapSac, processSystemEvents, processFailedOpEffects}) {
|
|
@@ -95,16 +96,16 @@ class EffectsAnalyzer {
|
|
|
95
96
|
if (parse) {
|
|
96
97
|
parse.call(this)
|
|
97
98
|
}
|
|
99
|
+
//process Soroban events
|
|
100
|
+
new EventsAnalyzer(this).analyze()
|
|
101
|
+
//process state data changes in the end
|
|
102
|
+
this.processStateChanges()
|
|
98
103
|
//process ledger entry changes
|
|
99
104
|
this.processChanges()
|
|
100
105
|
//handle effects that are processed indirectly
|
|
101
106
|
this.processSponsorshipEffects()
|
|
102
|
-
//process Soroban events
|
|
103
|
-
new EventsAnalyzer(this).analyze()
|
|
104
107
|
//calculate minted/burned assets
|
|
105
108
|
new AssetSupplyAnalyzer(this).analyze()
|
|
106
|
-
//process state data changes in the end
|
|
107
|
-
this.processStateChanges()
|
|
108
109
|
return this.effects
|
|
109
110
|
}
|
|
110
111
|
|
|
@@ -358,13 +359,16 @@ class EffectsAnalyzer {
|
|
|
358
359
|
this.addEffect(effect)
|
|
359
360
|
}
|
|
360
361
|
break
|
|
361
|
-
case 'wasm':
|
|
362
|
+
case 'wasm': {
|
|
363
|
+
const codeHash = hash(value)
|
|
362
364
|
this.addEffect({
|
|
363
365
|
type: effectTypes.contractCodeUploaded,
|
|
364
366
|
wasm: value.toString('base64'),
|
|
365
|
-
wasmHash:
|
|
367
|
+
wasmHash: codeHash.toString('hex'),
|
|
368
|
+
keyHash: generateContractCodeEntryHash(codeHash)
|
|
366
369
|
})
|
|
367
370
|
break
|
|
371
|
+
}
|
|
368
372
|
case 'createContract':
|
|
369
373
|
const preimage = value.contractIdPreimage()
|
|
370
374
|
const executable = value.executable()
|
|
@@ -398,7 +402,7 @@ class EffectsAnalyzer {
|
|
|
398
402
|
default:
|
|
399
403
|
throw new TxMetaEffectParserError('Unknown contract type: ' + executableType)
|
|
400
404
|
}
|
|
401
|
-
this.addEffect(effect)
|
|
405
|
+
this.addEffect(effect, 0)
|
|
402
406
|
break
|
|
403
407
|
default:
|
|
404
408
|
throw new TxMetaEffectParserError('Unknown host function call type: ' + func.arm())
|
|
@@ -422,6 +426,8 @@ class EffectsAnalyzer {
|
|
|
422
426
|
}
|
|
423
427
|
|
|
424
428
|
processDexOperationEffects() {
|
|
429
|
+
if (!this.result)
|
|
430
|
+
return
|
|
425
431
|
//process trades first
|
|
426
432
|
for (const claimedOffer of this.result.claimedOffers) {
|
|
427
433
|
const trade = {
|
|
@@ -763,7 +769,7 @@ class EffectsAnalyzer {
|
|
|
763
769
|
const balanceEffects = this.effects.filter(e => (e.type === effectTypes.accountCredited || e.type === effectTypes.accountDebited) && e.source === account && e.asset === effect.owner)
|
|
764
770
|
if (balanceEffects.length !== 1) //we can set balance only when we found 1-1 mapping, if there are several balance changes, we can't establish balance relation
|
|
765
771
|
return
|
|
766
|
-
if (effect.type === effectTypes.contractDataRemoved) { //balance completely removed
|
|
772
|
+
if (effect.type === effectTypes.contractDataRemoved) { //balance completely removed - this may be a reversible operation if the balance simply expired
|
|
767
773
|
balanceEffects[0].balance = '0'
|
|
768
774
|
return
|
|
769
775
|
}
|
|
@@ -780,8 +786,8 @@ class EffectsAnalyzer {
|
|
|
780
786
|
processContractChanges({action, before, after}) {
|
|
781
787
|
if (action !== 'created' && action !== 'updated')
|
|
782
788
|
throw new UnexpectedTxMetaChangeError({type: 'contract', action})
|
|
783
|
-
const {kind, contract} = after
|
|
784
|
-
|
|
789
|
+
const {kind, owner: contract, keyHash} = after
|
|
790
|
+
let effect = {
|
|
785
791
|
type: effectTypes.contractCreated,
|
|
786
792
|
contract,
|
|
787
793
|
kind
|
|
@@ -791,33 +797,38 @@ class EffectsAnalyzer {
|
|
|
791
797
|
effect.asset = after.asset
|
|
792
798
|
break
|
|
793
799
|
case 'wasm':
|
|
794
|
-
effect.wasmHash = after.
|
|
800
|
+
effect.wasmHash = after.wasmHash
|
|
795
801
|
break
|
|
796
802
|
default:
|
|
797
803
|
throw new TxMetaEffectParserError('Unexpected contract type: ' + kind)
|
|
798
804
|
}
|
|
799
805
|
if (action === 'created') {
|
|
800
|
-
if (this.effects.some(e => e.contract === contract))
|
|
801
|
-
|
|
806
|
+
if (this.effects.some(e => e.type === effectTypes.contractCreated && e.contract === contract)) {
|
|
807
|
+
effect = undefined //skip contract creation effects processed by top-level createContract operation call
|
|
808
|
+
}
|
|
802
809
|
} else if (action === 'updated') {
|
|
803
810
|
effect.type = effectTypes.contractUpdated
|
|
804
|
-
effect.prevWasmHash = before.
|
|
805
|
-
if (before.
|
|
806
|
-
|
|
811
|
+
effect.prevWasmHash = before.wasmHash
|
|
812
|
+
if (before.wasmHash === after.wasmHash) {//skip if hash unchanged
|
|
813
|
+
effect = undefined
|
|
807
814
|
}
|
|
808
|
-
if (before.hash === after.hash) //skip if hash unchanged
|
|
809
|
-
return
|
|
810
815
|
}
|
|
811
|
-
|
|
816
|
+
if (effect) {
|
|
817
|
+
this.addEffect(effect, effect.type === effectTypes.contractCreated ? 0 : undefined)
|
|
818
|
+
}
|
|
819
|
+
if (before?.storage?.length || after?.storage?.length) {
|
|
820
|
+
this.processInstanceDataChanges(before, after)
|
|
821
|
+
}
|
|
812
822
|
}
|
|
813
823
|
|
|
814
824
|
processContractStateEntryChanges({action, before, after}) {
|
|
815
|
-
const {owner, key, durability} = after || before
|
|
825
|
+
const {owner, key, durability, keyHash} = after || before
|
|
816
826
|
const effect = {
|
|
817
827
|
type: '',
|
|
818
828
|
owner,
|
|
829
|
+
key,
|
|
819
830
|
durability,
|
|
820
|
-
|
|
831
|
+
keyHash
|
|
821
832
|
}
|
|
822
833
|
switch (action) {
|
|
823
834
|
case 'created':
|
|
@@ -840,9 +851,27 @@ class EffectsAnalyzer {
|
|
|
840
851
|
this.processContractBalance(effect)
|
|
841
852
|
}
|
|
842
853
|
|
|
854
|
+
processContractCodeChanges({type, action, before, after}) {
|
|
855
|
+
const {hash, keyHash} = after || before
|
|
856
|
+
switch (action) {
|
|
857
|
+
case 'created':
|
|
858
|
+
break //processed separately
|
|
859
|
+
case 'updated':
|
|
860
|
+
break //it doesn't change the state
|
|
861
|
+
case 'removed':
|
|
862
|
+
const effect = {
|
|
863
|
+
type: effectTypes.contractCodeRemoved,
|
|
864
|
+
wasmHash: hash,
|
|
865
|
+
keyHash
|
|
866
|
+
}
|
|
867
|
+
this.addEffect(effect)
|
|
868
|
+
break
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
|
|
843
872
|
processInstanceDataChanges(before, after) {
|
|
844
|
-
const storageBefore = before
|
|
845
|
-
const storageAfter = [...(after
|
|
873
|
+
const storageBefore = before?.storage || []
|
|
874
|
+
const storageAfter = [...(after?.storage || [])]
|
|
846
875
|
for (const {key, val} of storageBefore) {
|
|
847
876
|
let newVal
|
|
848
877
|
for (let i = 0; i < storageAfter.length; i++) {
|
|
@@ -856,7 +885,7 @@ class EffectsAnalyzer {
|
|
|
856
885
|
if (newVal === undefined) { //removed
|
|
857
886
|
const effect = {
|
|
858
887
|
type: effectTypes.contractDataRemoved,
|
|
859
|
-
owner: after
|
|
888
|
+
owner: after?.owner || before.owner,
|
|
860
889
|
key,
|
|
861
890
|
prevValue: val,
|
|
862
891
|
durability: 'instance'
|
|
@@ -869,7 +898,7 @@ class EffectsAnalyzer {
|
|
|
869
898
|
|
|
870
899
|
const effect = {
|
|
871
900
|
type: effectTypes.contractDataUpdated,
|
|
872
|
-
owner: after
|
|
901
|
+
owner: after?.owner || before.owner,
|
|
873
902
|
key,
|
|
874
903
|
value: newVal,
|
|
875
904
|
prevValue: val,
|
|
@@ -881,7 +910,7 @@ class EffectsAnalyzer {
|
|
|
881
910
|
for (const {key, val} of storageAfter) {
|
|
882
911
|
const effect = {
|
|
883
912
|
type: effectTypes.contractDataCreated,
|
|
884
|
-
owner: after
|
|
913
|
+
owner: after?.owner || before.owner,
|
|
885
914
|
key,
|
|
886
915
|
value: val,
|
|
887
916
|
durability: 'instance'
|
|
@@ -890,6 +919,27 @@ class EffectsAnalyzer {
|
|
|
890
919
|
}
|
|
891
920
|
}
|
|
892
921
|
|
|
922
|
+
processTtlChanges({action, before, after}) {
|
|
923
|
+
/*if (action === 'removed')
|
|
924
|
+
throw new UnexpectedTxMetaChangeError({type: 'ttl', action})*/
|
|
925
|
+
const {keyHash, ttl} = after || before
|
|
926
|
+
const stateEffect = this.effects.find(e => e.keyHash === keyHash && e.type !== effectTypes.setTtl)
|
|
927
|
+
const effect = {
|
|
928
|
+
type: effectTypes.setTtl,
|
|
929
|
+
keyHash,
|
|
930
|
+
ttl
|
|
931
|
+
}
|
|
932
|
+
if (stateEffect) {
|
|
933
|
+
if (stateEffect.type.includes('contractCode')) {
|
|
934
|
+
effect.kind = 'contractCode'
|
|
935
|
+
} else if (stateEffect.type.includes('contractData')) {
|
|
936
|
+
effect.kind = 'contractData'
|
|
937
|
+
effect.owner = stateEffect.owner
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
this.addEffect(effect)
|
|
941
|
+
}
|
|
942
|
+
|
|
893
943
|
processChanges() {
|
|
894
944
|
for (const change of this.changes)
|
|
895
945
|
switch (change.type) {
|
|
@@ -912,10 +962,15 @@ class EffectsAnalyzer {
|
|
|
912
962
|
this.processDataEntryChanges(change)
|
|
913
963
|
break
|
|
914
964
|
case 'contractData':
|
|
915
|
-
|
|
965
|
+
if (change.before?.kind || change.after?.kind) {
|
|
966
|
+
this.processContractChanges(change)
|
|
967
|
+
}
|
|
968
|
+
break
|
|
969
|
+
case 'contractCode':
|
|
970
|
+
this.processContractCodeChanges(change)
|
|
916
971
|
break
|
|
917
|
-
case '
|
|
918
|
-
this.
|
|
972
|
+
case 'ttl':
|
|
973
|
+
this.processTtlChanges(change)
|
|
919
974
|
break
|
|
920
975
|
default:
|
|
921
976
|
throw new UnexpectedTxMetaChangeError(change)
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
const {StrKey} = require('@stellar/stellar-base')
|
|
2
|
-
const {TxMetaEffectParserError} = require('../errors')
|
|
2
|
+
const {TxMetaEffectParserError, UnexpectedTxMetaChangeError} = require('../errors')
|
|
3
3
|
const {xdrParseAsset, xdrParseAccountAddress, xdrParseClaimant, xdrParsePrice, xdrParseSignerKey} = require('./tx-xdr-parser-utils')
|
|
4
|
+
const {generateContractStateEntryHash, generateContractCodeEntryHash} = require('./ledger-key')
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @typedef {{}} ParsedLedgerEntryMeta
|
|
7
|
-
* @property {'account'|'trustline'|'offer'|'data'|'liquidityPool'|'claimableBalance'|'contractData'|'contractCode'} type - Ledger entry type
|
|
8
|
+
* @property {'account'|'trustline'|'offer'|'data'|'liquidityPool'|'claimableBalance'|'contractData'|'contractCode'|'ttl'} type - Ledger entry type
|
|
8
9
|
* @property {'created'|'updated'|'removed'} action - Ledger modification action
|
|
9
10
|
* @property {{}} before - Ledger entry state before changes applied
|
|
10
11
|
* @property {{}} after - Ledger entry state after changes application
|
|
@@ -19,35 +20,39 @@ function parseLedgerEntryChanges(ledgerEntryChanges) {
|
|
|
19
20
|
let state
|
|
20
21
|
for (let i = 0; i < ledgerEntryChanges.length; i++) {
|
|
21
22
|
const entry = ledgerEntryChanges[i]
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
const stateData = parseEntry(entry.value(), actionType)
|
|
23
|
+
const action = entry._arm
|
|
24
|
+
const stateData = parseEntry(entry, action)
|
|
25
25
|
if (stateData === undefined)
|
|
26
26
|
continue
|
|
27
|
-
const change = {action
|
|
28
|
-
|
|
27
|
+
const change = {action}
|
|
28
|
+
const type = entry._value._arm
|
|
29
|
+
switch (action) {
|
|
29
30
|
case 'state':
|
|
30
31
|
state = stateData
|
|
31
32
|
continue
|
|
32
33
|
case 'created':
|
|
34
|
+
if (type === 'contractCode')
|
|
35
|
+
continue //processed in operation handler
|
|
33
36
|
change.before = null
|
|
34
37
|
change.after = stateData
|
|
35
38
|
change.type = stateData.entry
|
|
36
39
|
break
|
|
37
40
|
case 'updated':
|
|
41
|
+
if (type === 'contractCode')
|
|
42
|
+
throw new UnexpectedTxMetaChangeError({type, action})
|
|
38
43
|
change.before = state
|
|
39
44
|
change.after = stateData
|
|
40
45
|
change.type = stateData.entry
|
|
41
46
|
break
|
|
42
47
|
case 'removed':
|
|
43
|
-
if (!state &&
|
|
48
|
+
if (!state && type === 'ttl')
|
|
44
49
|
continue //skip expiration processing for now
|
|
45
50
|
change.before = state
|
|
46
51
|
change.after = null
|
|
47
52
|
change.type = state.entry
|
|
48
53
|
break
|
|
49
54
|
default:
|
|
50
|
-
throw new TxMetaEffectParserError(`Unknown change entry type: ${
|
|
55
|
+
throw new TxMetaEffectParserError(`Unknown change entry type: ${action}`)
|
|
51
56
|
}
|
|
52
57
|
changes.push(change)
|
|
53
58
|
state = null
|
|
@@ -57,12 +62,13 @@ function parseLedgerEntryChanges(ledgerEntryChanges) {
|
|
|
57
62
|
|
|
58
63
|
function parseEntry(entry, actionType) {
|
|
59
64
|
if (actionType === 'removed')
|
|
60
|
-
return null
|
|
61
|
-
const
|
|
65
|
+
return null
|
|
66
|
+
const value = entry.value()
|
|
67
|
+
const parsed = parseEntryData(value.data())
|
|
62
68
|
if (parsed === null)
|
|
63
69
|
return null
|
|
64
70
|
//parsed.modified = entry.lastModifiedLedgerSeq()
|
|
65
|
-
return parseLedgerEntryExt(parsed,
|
|
71
|
+
return parseLedgerEntryExt(parsed, value)
|
|
66
72
|
}
|
|
67
73
|
|
|
68
74
|
function parseEntryData(data) {
|
|
@@ -85,9 +91,9 @@ function parseEntryData(data) {
|
|
|
85
91
|
case 'contractData':
|
|
86
92
|
return parseContractData(data)
|
|
87
93
|
case 'contractCode':
|
|
88
|
-
return
|
|
94
|
+
return parseContractCode(data)
|
|
89
95
|
case 'ttl':
|
|
90
|
-
return
|
|
96
|
+
return parseTtl(data)
|
|
91
97
|
default:
|
|
92
98
|
throw new TxMetaEffectParserError(`Unknown meta entry type: ${updatedEntryType}`)
|
|
93
99
|
}
|
|
@@ -240,46 +246,51 @@ function parseContractData(value) {
|
|
|
240
246
|
const owner = parseStateOwnerDataAddress(data.contract())
|
|
241
247
|
|
|
242
248
|
const valueAttr = data.val()
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
249
|
+
const entry = {
|
|
250
|
+
entry: 'contractData',
|
|
251
|
+
owner,
|
|
252
|
+
key: data.key().toXDR('base64'),
|
|
253
|
+
value: valueAttr.toXDR('base64'),
|
|
254
|
+
durability: data.durability().name,
|
|
255
|
+
keyHash: generateContractStateEntryHash(data)
|
|
256
|
+
}
|
|
257
|
+
if (data.key().switch()?.name === 'scvLedgerKeyContractInstance' && entry.durability === 'persistent') {
|
|
258
|
+
entry.durability = 'instance'
|
|
259
|
+
const instance = valueAttr.instance()._attributes
|
|
260
|
+
const type = instance.executable._switch.name
|
|
261
|
+
switch (type) {
|
|
262
|
+
case 'contractExecutableStellarAsset':
|
|
263
|
+
entry.kind = 'fromAsset'
|
|
264
|
+
if (instance.storage?.length) { //if not -- the asset has been created "fromAddress" - no metadata in this case
|
|
256
265
|
const metaArgs = instance.storage[0]._attributes
|
|
257
266
|
if (metaArgs.key._value.toString() !== 'METADATA')
|
|
258
267
|
throw new TxMetaEffectParserError('Unexpected asset initialization metadata')
|
|
259
268
|
entry.asset = xdrParseAsset(metaArgs.val._value[1]._attributes.val._value.toString())
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
274
|
-
|
|
269
|
+
}
|
|
270
|
+
break
|
|
271
|
+
case 'contractExecutableWasm':
|
|
272
|
+
entry.kind = 'wasm'
|
|
273
|
+
entry.wasmHash = instance.executable.wasmHash().toString('hex')
|
|
274
|
+
break
|
|
275
|
+
default:
|
|
276
|
+
throw new TxMetaEffectParserError('Unsupported executable type: ' + type)
|
|
277
|
+
}
|
|
278
|
+
if (instance.storage?.length) {
|
|
279
|
+
entry.storage = instance.storage.map(entry => ({
|
|
280
|
+
key: entry.key().toXDR('base64'),
|
|
281
|
+
val: entry.val().toXDR('base64')
|
|
282
|
+
}))
|
|
283
|
+
}
|
|
275
284
|
}
|
|
285
|
+
return entry
|
|
286
|
+
}
|
|
276
287
|
|
|
288
|
+
function parseTtl(data) {
|
|
289
|
+
const attrs = data._value._attributes
|
|
277
290
|
return {
|
|
278
|
-
entry: '
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
value: valueAttr.toXDR('base64'),
|
|
282
|
-
durability: data.durability().name
|
|
291
|
+
entry: 'ttl',
|
|
292
|
+
keyHash: attrs.keyHash.toString('hex'),
|
|
293
|
+
ttl: attrs.liveUntilLedgerSeq
|
|
283
294
|
}
|
|
284
295
|
}
|
|
285
296
|
|
|
@@ -289,13 +300,14 @@ function parseStateOwnerDataAddress(contract) {
|
|
|
289
300
|
return xdrParseAccountAddress(contract.accountId())
|
|
290
301
|
}
|
|
291
302
|
|
|
292
|
-
|
|
303
|
+
function parseContractCode(value) {
|
|
293
304
|
const contract = value.value()
|
|
305
|
+
const hash = contract.hash()
|
|
294
306
|
return {
|
|
295
307
|
entry: 'contractCode',
|
|
296
|
-
hash:
|
|
297
|
-
|
|
308
|
+
hash: hash.toString('hex'),
|
|
309
|
+
keyHash: generateContractCodeEntryHash(hash)
|
|
298
310
|
}
|
|
299
|
-
}
|
|
311
|
+
}
|
|
300
312
|
|
|
301
313
|
module.exports = {parseLedgerEntryChanges}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const {xdr, hash} = require('@stellar/stellar-base')
|
|
2
|
+
|
|
3
|
+
function generateContractStateEntryHash(data) {
|
|
4
|
+
const {contract, durability, key} = data._attributes
|
|
5
|
+
const contractDataKey = new xdr.LedgerKeyContractData({contract, durability, key})
|
|
6
|
+
const ledgerKey = xdr.LedgerKey.contractData(contractDataKey)
|
|
7
|
+
return hash(ledgerKey.toXDR()).toString('hex')
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function generateContractCodeEntryHash(wasmHash) {
|
|
11
|
+
const contractDataKey = new xdr.LedgerKeyContractCode({hash: wasmHash})
|
|
12
|
+
const ledgerKey = xdr.LedgerKey.contractCode(contractDataKey)
|
|
13
|
+
return hash(ledgerKey.toXDR()).toString('hex')
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
module.exports = {
|
|
17
|
+
generateContractStateEntryHash,
|
|
18
|
+
generateContractCodeEntryHash
|
|
19
|
+
}
|
|
@@ -234,7 +234,6 @@ function xdrParseAsset(src) {
|
|
|
234
234
|
return `${src.code}-${src.issuer}-${src.type || (src.code.length > 4 ? 2 : 1)}`
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
|
|
238
237
|
function xdrParseScVal(value, treatBytesAsContractId = false) {
|
|
239
238
|
if (typeof value === 'string') {
|
|
240
239
|
value = xdr.ScVal.fromXDR(value, 'base64')
|