@stellar-expert/contract-wasm-interface-parser 2.0.1 → 3.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/README.md CHANGED
@@ -20,97 +20,242 @@ Example output:
20
20
 
21
21
  ```json
22
22
  {
23
- "unions": [
24
- {
25
- "name": "Asset",
26
- "cases": {
27
- "Stellar": [
28
- "address"
29
- ],
30
- "Other": [
31
- "symbol"
32
- ]
23
+ "enums": {
24
+ "SubscriptionStatus": {
25
+ "Active": {
26
+ "value": 0
27
+ },
28
+ "Cancelled": {
29
+ "value": 2
30
+ },
31
+ "Suspended": {
32
+ "value": 1
33
33
  }
34
34
  }
35
- ],
36
- "structs": [
37
- {
38
- "name": "TickerAsset",
39
- "fields": [
40
- {
41
- "name": "asset",
42
- "type": "Asset",
43
- "doc": "Short ticker name of the asset"
35
+ },
36
+ "errors": {
37
+ "AlreadyInitialized": {
38
+ "value": 0
39
+ },
40
+ "InvalidAmount": {
41
+ "value": 4
42
+ },
43
+ "InvalidHeartbeat": {
44
+ "value": 5
45
+ },
46
+ "InvalidSubscriptionStatusError": {
47
+ "value": 8
48
+ },
49
+ "InvalidThreshold": {
50
+ "value": 6
51
+ },
52
+ "NotInitialized": {
53
+ "value": 3
54
+ },
55
+ "SubscriptionNotFound": {
56
+ "value": 2
57
+ },
58
+ "Unauthorized": {
59
+ "value": 1
60
+ },
61
+ "WebhookTooLong": {
62
+ "value": 7
63
+ }
64
+ },
65
+ "functions": {
66
+ "admin": {
67
+ "inputs": {},
68
+ "outputs": [
69
+ "option<address>"
70
+ ]
71
+ },
72
+ "cancel": {
73
+ "inputs": {
74
+ "subscription_id": {
75
+ "type": "u64"
76
+ }
77
+ },
78
+ "outputs": []
79
+ },
80
+ "charge": {
81
+ "inputs": {
82
+ "subscription_ids": {
83
+ "type": "vec<u64>"
84
+ }
85
+ },
86
+ "outputs": []
87
+ },
88
+ "config": {
89
+ "inputs": {
90
+ "config": {
91
+ "type": "ConfigData"
92
+ }
93
+ },
94
+ "outputs": []
95
+ },
96
+ "create_subscription": {
97
+ "inputs": {
98
+ "amount": {
99
+ "type": "u64"
44
100
  },
45
- {
46
- "name": "source",
47
- "type": "string",
48
- "doc": "Data provider ID"
101
+ "new_subscription": {
102
+ "type": "CreateSubscription"
49
103
  }
104
+ },
105
+ "outputs": [
106
+ "tuple<u64,Subscription>"
50
107
  ]
51
- }
52
- ],
53
- "errors": [
54
- {
55
- "name": "Error",
56
- "cases": [
57
- {
58
- "name": "AlreadyInitialized",
59
- "value": 0
108
+ },
109
+ "deposit": {
110
+ "inputs": {
111
+ "amount": {
112
+ "type": "u64"
60
113
  },
61
- {
62
- "name": "Unauthorized",
63
- "value": 1
114
+ "from": {
115
+ "type": "address"
116
+ },
117
+ "subscription_id": {
118
+ "type": "u64"
64
119
  }
120
+ },
121
+ "outputs": []
122
+ },
123
+ "fee": {
124
+ "inputs": {},
125
+ "outputs": [
126
+ "u64"
65
127
  ]
66
- }
67
- ],
68
- "enums": [
69
- {
70
- "name": "SubscriptionStatus",
71
- "cases": {
72
- "Active": 0,
73
- "Suspended": 1,
74
- "Cancelled": 2
75
- }
76
- }
77
- ],
78
- "functions": [
79
- {
80
- "name": "config",
81
- "inputs": [
82
- {
83
- "name": "config",
84
- "type": "ConfigData"
85
- "doc": "New configuration data"
128
+ },
129
+ "get_subscription": {
130
+ "inputs": {
131
+ "subscription_id": {
132
+ "type": "u64"
86
133
  }
87
- ],
88
- "outputs": [],
89
- "doc": "Update contract confirguration"
90
- },
91
- {
92
- "name": "set_fee",
93
- "inputs": [
94
- {
95
- "name": "fee",
134
+ },
135
+ "outputs": [
136
+ "Subscription"
137
+ ]
138
+ },
139
+ "set_fee": {
140
+ "inputs": {
141
+ "fee": {
96
142
  "type": "u64"
97
143
  }
98
- ],
144
+ },
99
145
  "outputs": []
100
146
  },
101
- {
102
- "name": "get_subscription",
103
- "inputs": [
104
- {
105
- "name": "subscription_id",
147
+ "token": {
148
+ "inputs": {},
149
+ "outputs": [
150
+ "address"
151
+ ]
152
+ },
153
+ "trigger": {
154
+ "inputs": {
155
+ "timestamp": {
106
156
  "type": "u64"
157
+ },
158
+ "trigger_hash": {
159
+ "type": "bytesn<32>"
107
160
  }
108
- ],
161
+ },
162
+ "outputs": []
163
+ },
164
+ "update_contract": {
165
+ "inputs": {
166
+ "wasm_hash": {
167
+ "type": "bytesn<32>"
168
+ }
169
+ },
170
+ "outputs": []
171
+ },
172
+ "version": {
173
+ "inputs": {},
109
174
  "outputs": [
110
- "Subscription"
175
+ "u32"
176
+ ]
177
+ }
178
+ },
179
+ "structs": {
180
+ "ConfigData": {
181
+ "admin": {
182
+ "type": "address"
183
+ },
184
+ "fee": {
185
+ "type": "u64"
186
+ },
187
+ "token": {
188
+ "type": "address"
189
+ }
190
+ },
191
+ "CreateSubscription": {
192
+ "asset1": {
193
+ "type": "TickerAsset"
194
+ },
195
+ "asset2": {
196
+ "type": "TickerAsset"
197
+ },
198
+ "heartbeat": {
199
+ "type": "u32"
200
+ },
201
+ "owner": {
202
+ "type": "address"
203
+ },
204
+ "threshold": {
205
+ "type": "u32"
206
+ },
207
+ "webhook": {
208
+ "type": "bytes"
209
+ }
210
+ },
211
+ "Subscription": {
212
+ "asset1": {
213
+ "type": "TickerAsset"
214
+ },
215
+ "asset2": {
216
+ "type": "TickerAsset"
217
+ },
218
+ "balance": {
219
+ "type": "u64"
220
+ },
221
+ "heartbeat": {
222
+ "type": "u32"
223
+ },
224
+ "last_charge": {
225
+ "type": "u64"
226
+ },
227
+ "owner": {
228
+ "type": "address"
229
+ },
230
+ "status": {
231
+ "type": "SubscriptionStatus"
232
+ },
233
+ "threshold": {
234
+ "type": "u32"
235
+ },
236
+ "webhook": {
237
+ "type": "bytes"
238
+ }
239
+ },
240
+ "TickerAsset": {
241
+ "asset": {
242
+ "type": "Asset"
243
+ },
244
+ "source": {
245
+ "type": "string"
246
+ }
247
+ }
248
+ },
249
+ "unions": {
250
+ "Asset": {
251
+ "Other": [
252
+ "symbol"
253
+ ],
254
+ "Stellar": [
255
+ "address"
111
256
  ]
112
257
  }
113
- ],
258
+ },
114
259
  "interfaceVersion": "85899345920",
115
260
  "rustVersion": "1.74.0",
116
261
  "sdkVersion": "20.5.0#9e2c3022b4355b224a7a814e13ba51761eeb14bb"
package/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import {xdr} from '@stellar/stellar-base'
2
- import {XdrReader} from './src/xdr-reader'
2
+ import {parseSectionEntriesXdr} from './src/xdr-reader'
3
3
  import {WasmSectionReader} from './src/wasm-section-reader'
4
4
  import {parseContractMeta, parseSpec} from './src/xdr-spec-parser'
5
5
 
6
6
  /**
7
7
  * Parse contract metadata from WASM sections
8
8
  * @param {Buffer} rawWasm
9
- * @return {{}}
9
+ * @return {ParsedWasmMeta}
10
10
  */
11
11
  export function parseContractMetadata(rawWasm) {
12
12
  const wasmSectionReader = new WasmSectionReader(rawWasm)
@@ -18,21 +18,24 @@ export function parseContractMetadata(rawWasm) {
18
18
  res.interfaceVersion = xdr.ScEnvMetaEntry.fromXDR(section.contents).value().toString()
19
19
  break
20
20
  case 'contractmetav0':
21
- Object.assign(res, parseContractMeta(parseEntries(section.contents, xdr.ScMetaEntry)))
21
+ Object.assign(res, parseContractMeta(parseSectionEntriesXdr(section.contents, xdr.ScMetaEntry)))
22
22
  break
23
23
  case 'contractspecv0':
24
- Object.assign(res, parseSpec(parseEntries(section.contents, xdr.ScSpecEntry)))
24
+ Object.assign(res, parseSpec(parseSectionEntriesXdr(section.contents, xdr.ScSpecEntry)))
25
25
  break
26
26
  }
27
27
  }
28
28
  return res
29
29
  }
30
30
 
31
- function parseEntries(buffer, xdrContract) {
32
- const reader = new XdrReader(buffer)
33
- const entries = []
34
- while (!reader.eof) {
35
- entries.push(xdrContract.read(reader))
36
- }
37
- return entries
38
- }
31
+ /**
32
+ * @typedef {{}} ParsedWasmMeta
33
+ * @property {{}} functions
34
+ * @property {{}} [errors]
35
+ * @property {{}} [enums]
36
+ * @property {{}} [structs]
37
+ * @property {{}} [unions]
38
+ * @property {string} rustVersion
39
+ * @property {string} sdkVersion
40
+ * @property {string} interfaceVersion
41
+ */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stellar-expert/contract-wasm-interface-parser",
3
- "version": "2.0.1",
3
+ "version": "3.0.0",
4
4
  "description": "Contract interface metadata parser for binary WASM",
5
5
  "main": "index.js",
6
6
  "module": "./index.js",
@@ -8,6 +8,9 @@
8
8
  "type": "git",
9
9
  "url": "git+https://github.com/stellar-expert/contract-wasm-interface-parser.git"
10
10
  },
11
+ "scripts": {
12
+ "test": "jest"
13
+ },
11
14
  "author": "orbitlens <orbit@stellar.expert>",
12
15
  "license": "MIT",
13
16
  "peerDependencies": {
package/src/xdr-reader.js CHANGED
@@ -1,4 +1,19 @@
1
- export class XdrReader {
1
+ /**
2
+ *
3
+ * @param {Buffer} buffer
4
+ * @param {{read: function}} xdrContract
5
+ * @return {{}[]}
6
+ */
7
+ export function parseSectionEntriesXdr(buffer, xdrContract) {
8
+ const reader = new XdrReader(buffer)
9
+ const entries = []
10
+ while (!reader.eof) {
11
+ entries.push(xdrContract.read(reader))
12
+ }
13
+ return entries
14
+ }
15
+
16
+ class XdrReader {
2
17
  /**
3
18
  * @constructor
4
19
  * @param {Buffer} source - Buffer containing serialized data
@@ -30,12 +30,13 @@ class SpecParser {
30
30
  */
31
31
  res
32
32
 
33
- addSpec(key, descriptor, doc) {
33
+ addSpec(key, attr, parser) {
34
+ //this.parseFunction(attr), attr.doc
34
35
  let spec = this.res[key]
35
36
  if (spec === undefined) {
36
- spec = this.res[key] = []
37
+ spec = this.res[key] = {}
37
38
  }
38
- spec.push(this.withDocs(descriptor, doc))
39
+ parser.call(this, attr, spec)
39
40
  }
40
41
 
41
42
  parse(entries) {
@@ -44,19 +45,19 @@ class SpecParser {
44
45
  const {_attributes: attr} = value
45
46
  switch (spec._arm) {
46
47
  case 'functionV0':
47
- this.addSpec('functions', this.parseFunction(attr), attr.doc)
48
+ this.addSpec('functions', attr, this.parseFunction)
48
49
  break
49
50
  case 'udtStructV0':
50
- this.addSpec('structs', this.parseStruct(attr), attr.doc)
51
+ this.addSpec('structs', attr, this.parseStruct)
51
52
  break
52
53
  case 'udtUnionV0':
53
- this.addSpec('unions', this.parseUnion(attr), attr.doc)
54
+ this.addSpec('unions', attr, this.parseUnion)
54
55
  break
55
56
  case 'udtEnumV0':
56
- this.addSpec('enums', this.parseEnum(attr), attr.doc)
57
+ this.addSpec('enums', attr, this.parseEnum)
57
58
  break
58
59
  case 'udtErrorEnumV0':
59
- this.addSpec('errors', this.parseError(attr), attr.doc)
60
+ this.addSpec('errors', attr, this.parseError)
60
61
  break
61
62
  default:
62
63
  console.log('Unknown spec type: ' + spec._arm)
@@ -66,57 +67,47 @@ class SpecParser {
66
67
  return this.res
67
68
  }
68
69
 
69
- parseFunction(attr) {
70
- return {
71
- name: attr.name.toString(),
72
- inputs: attr.inputs.map(i => this.parseParameter(i)),
70
+ parseFunction(attr, into) {
71
+ const inputs = {}
72
+ attr.inputs.forEach(i => this.parseParameter(i, inputs))
73
+ into[attr.name.toString()] = this.withDocs({
74
+ inputs,
73
75
  outputs: attr.outputs.map(o => this.parseParameterType(o))
74
- }
76
+ }, attr.doc)
75
77
  }
76
78
 
77
- parseStruct(attr) {
78
- return {
79
- name: this.parseStructName(attr),
80
- fields: attr.fields.map(f => this.parseParameter(f))
81
- }
79
+ parseStruct(attr, into) {
80
+ const fields = {}
81
+ attr.fields.forEach(f => this.parseParameter(f, fields))
82
+ into[this.parseStructName(attr)] = this.withDocs(fields, attr.doc)
82
83
  }
83
84
 
84
- parseUnion(attr) {
85
- return {
86
- name: this.parseStructName(attr),
87
- cases: attr.cases.reduce((agg, c) => {
88
- const value = c.value()
89
- agg[value.name().toString()] = value.type ?
90
- value.type().map(t => this.parseParameterType(t)) :
91
- []
92
- return agg
93
- }, {})
94
- }
85
+ parseUnion(attr, into) {
86
+ const cases = {}
87
+ attr.cases.forEach(c => {
88
+ const value = c.value()
89
+ cases[value.name().toString()] = value.type ?
90
+ value.type().map(t => this.parseParameterType(t)) :
91
+ []
92
+ })
93
+ into[this.parseStructName(attr)] = this.withDocs(cases, attr.doc)
95
94
  }
96
95
 
97
- parseEnum(attr) {
98
- return {
99
- name: this.parseStructName(attr),
100
- cases: attr.cases.reduce((agg, c) => {
101
- const value = c.value()
102
- if (value.name) {
103
- agg[value.name().toString()] = value.value()
104
- } else {
105
- agg[c._attributes.name] = value
106
- }
107
- return agg
108
- }, {})
109
- }
96
+ parseEnum(attr, into) {
97
+ const cases = {}
98
+ attr.cases.forEach(c => {
99
+ const value = c.value()
100
+ if (value.name) {
101
+ cases[value.name().toString()] = value.value()
102
+ } else {
103
+ cases[c._attributes.name.toString()] = this.withDocs({value}, c.doc())
104
+ }
105
+ })
106
+ into[this.parseStructName(attr)] = this.withDocs(cases, attr.doc)
110
107
  }
111
108
 
112
- parseError(attr) {
113
- return {
114
- name: this.parseStructName(attr),
115
- cases: attr.cases.map(c => ({
116
- name: c.name().toString(),
117
- value: c.value()
118
- }))
119
- }
109
+ parseError(attr, into) {
110
+ attr.cases.forEach(c => into[c.name().toString()] = this.withDocs({value: c.value()}, c.doc()))
120
111
  }
121
112
 
122
113
  parseParameterType(type) {
@@ -149,13 +140,9 @@ class SpecParser {
149
140
  return structName
150
141
  }
151
142
 
152
- parseParameter(param) {
143
+ parseParameter(param, into) {
153
144
  const {_attributes: attr} = param
154
- const res = {
155
- name: attr.name.toString(),
156
- type: this.parseParameterType(attr.type)
157
- }
158
- return this.withDocs(res, attr.doc)
145
+ into[attr.name.toString()] = this.withDocs({type: this.parseParameterType(attr.type)}, attr.doc)
159
146
  }
160
147
 
161
148
  withDocs(descriptor, doc) {