ripple-binary-codec 2.7.0 → 2.8.0-smartcontract.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.
Files changed (196) hide show
  1. package/dist/enums/definitions.json +238 -260
  2. package/dist/enums/src/enums/definitions.json +238 -260
  3. package/dist/quality.js +15 -3
  4. package/dist/quality.js.map +1 -1
  5. package/dist/serdes/binary-parser.js +8 -2
  6. package/dist/serdes/binary-parser.js.map +1 -1
  7. package/dist/serdes/binary-serializer.d.ts +1 -1
  8. package/dist/serdes/binary-serializer.js +2 -2
  9. package/dist/serdes/binary-serializer.js.map +1 -1
  10. package/dist/src/enums/definitions.json +238 -260
  11. package/dist/src/quality.js +15 -3
  12. package/dist/src/quality.js.map +1 -1
  13. package/dist/src/serdes/binary-parser.js +8 -2
  14. package/dist/src/serdes/binary-parser.js.map +1 -1
  15. package/dist/src/serdes/binary-serializer.d.ts +1 -1
  16. package/dist/src/serdes/binary-serializer.js +2 -2
  17. package/dist/src/serdes/binary-serializer.js.map +1 -1
  18. package/dist/src/types/account-id.d.ts +2 -0
  19. package/dist/src/types/account-id.js +4 -0
  20. package/dist/src/types/account-id.js.map +1 -1
  21. package/dist/src/types/amount.d.ts +2 -1
  22. package/dist/src/types/amount.js +25 -4
  23. package/dist/src/types/amount.js.map +1 -1
  24. package/dist/src/types/blob.d.ts +2 -1
  25. package/dist/src/types/blob.js +3 -0
  26. package/dist/src/types/blob.js.map +1 -1
  27. package/dist/src/types/currency.d.ts +2 -0
  28. package/dist/src/types/currency.js +4 -0
  29. package/dist/src/types/currency.js.map +1 -1
  30. package/dist/src/types/data.d.ts +86 -0
  31. package/dist/src/types/data.js +252 -0
  32. package/dist/src/types/data.js.map +1 -0
  33. package/dist/src/types/dataType.d.ts +94 -0
  34. package/dist/src/types/dataType.js +145 -0
  35. package/dist/src/types/dataType.js.map +1 -0
  36. package/dist/src/types/hash-128.d.ts +2 -0
  37. package/dist/src/types/hash-128.js +4 -0
  38. package/dist/src/types/hash-128.js.map +1 -1
  39. package/dist/src/types/hash-160.d.ts +2 -0
  40. package/dist/src/types/hash-160.js +4 -0
  41. package/dist/src/types/hash-160.js.map +1 -1
  42. package/dist/src/types/hash-192.d.ts +2 -0
  43. package/dist/src/types/hash-192.js +4 -0
  44. package/dist/src/types/hash-192.js.map +1 -1
  45. package/dist/src/types/hash-256.d.ts +2 -0
  46. package/dist/src/types/hash-256.js +4 -0
  47. package/dist/src/types/hash-256.js.map +1 -1
  48. package/dist/src/types/index.d.ts +3 -1
  49. package/dist/src/types/index.js +7 -1
  50. package/dist/src/types/index.js.map +1 -1
  51. package/dist/src/types/issue.d.ts +2 -1
  52. package/dist/src/types/issue.js +3 -0
  53. package/dist/src/types/issue.js.map +1 -1
  54. package/dist/src/types/json.d.ts +173 -0
  55. package/dist/src/types/json.js +531 -0
  56. package/dist/src/types/json.js.map +1 -0
  57. package/dist/src/types/path-set.d.ts +2 -1
  58. package/dist/src/types/path-set.js +3 -0
  59. package/dist/src/types/path-set.js.map +1 -1
  60. package/dist/src/types/serialized-type.d.ts +43 -0
  61. package/dist/src/types/serialized-type.js +63 -1
  62. package/dist/src/types/serialized-type.js.map +1 -1
  63. package/dist/src/types/st-array.d.ts +2 -1
  64. package/dist/src/types/st-array.js +3 -0
  65. package/dist/src/types/st-array.js.map +1 -1
  66. package/dist/src/types/st-number.d.ts +2 -1
  67. package/dist/src/types/st-number.js +3 -0
  68. package/dist/src/types/st-number.js.map +1 -1
  69. package/dist/src/types/st-object.d.ts +2 -1
  70. package/dist/src/types/st-object.js +9 -1
  71. package/dist/src/types/st-object.js.map +1 -1
  72. package/dist/src/types/uint-16.d.ts +2 -0
  73. package/dist/src/types/uint-16.js +4 -0
  74. package/dist/src/types/uint-16.js.map +1 -1
  75. package/dist/src/types/uint-32.d.ts +2 -0
  76. package/dist/src/types/uint-32.js +4 -0
  77. package/dist/src/types/uint-32.js.map +1 -1
  78. package/dist/src/types/uint-64.d.ts +2 -0
  79. package/dist/src/types/uint-64.js +4 -0
  80. package/dist/src/types/uint-64.js.map +1 -1
  81. package/dist/src/types/uint-8.d.ts +2 -0
  82. package/dist/src/types/uint-8.js +4 -0
  83. package/dist/src/types/uint-8.js.map +1 -1
  84. package/dist/src/types/vector-256.d.ts +2 -1
  85. package/dist/src/types/vector-256.js +3 -0
  86. package/dist/src/types/vector-256.js.map +1 -1
  87. package/dist/src/types/xchain-bridge.d.ts +2 -1
  88. package/dist/src/types/xchain-bridge.js +3 -0
  89. package/dist/src/types/xchain-bridge.js.map +1 -1
  90. package/dist/src/utils.js +1 -1
  91. package/dist/src/utils.js.map +1 -1
  92. package/dist/tsconfig.tsbuildinfo +1 -1
  93. package/dist/types/account-id.d.ts +2 -0
  94. package/dist/types/account-id.js +4 -0
  95. package/dist/types/account-id.js.map +1 -1
  96. package/dist/types/amount.d.ts +2 -1
  97. package/dist/types/amount.js +25 -4
  98. package/dist/types/amount.js.map +1 -1
  99. package/dist/types/blob.d.ts +2 -1
  100. package/dist/types/blob.js +3 -0
  101. package/dist/types/blob.js.map +1 -1
  102. package/dist/types/currency.d.ts +2 -0
  103. package/dist/types/currency.js +4 -0
  104. package/dist/types/currency.js.map +1 -1
  105. package/dist/types/data.d.ts +86 -0
  106. package/dist/types/data.js +252 -0
  107. package/dist/types/data.js.map +1 -0
  108. package/dist/types/dataType.d.ts +94 -0
  109. package/dist/types/dataType.js +145 -0
  110. package/dist/types/dataType.js.map +1 -0
  111. package/dist/types/hash-128.d.ts +2 -0
  112. package/dist/types/hash-128.js +4 -0
  113. package/dist/types/hash-128.js.map +1 -1
  114. package/dist/types/hash-160.d.ts +2 -0
  115. package/dist/types/hash-160.js +4 -0
  116. package/dist/types/hash-160.js.map +1 -1
  117. package/dist/types/hash-192.d.ts +2 -0
  118. package/dist/types/hash-192.js +4 -0
  119. package/dist/types/hash-192.js.map +1 -1
  120. package/dist/types/hash-256.d.ts +2 -0
  121. package/dist/types/hash-256.js +4 -0
  122. package/dist/types/hash-256.js.map +1 -1
  123. package/dist/types/index.d.ts +3 -1
  124. package/dist/types/index.js +7 -1
  125. package/dist/types/index.js.map +1 -1
  126. package/dist/types/issue.d.ts +2 -1
  127. package/dist/types/issue.js +3 -0
  128. package/dist/types/issue.js.map +1 -1
  129. package/dist/types/json.d.ts +173 -0
  130. package/dist/types/json.js +531 -0
  131. package/dist/types/json.js.map +1 -0
  132. package/dist/types/path-set.d.ts +2 -1
  133. package/dist/types/path-set.js +3 -0
  134. package/dist/types/path-set.js.map +1 -1
  135. package/dist/types/serialized-type.d.ts +43 -0
  136. package/dist/types/serialized-type.js +63 -1
  137. package/dist/types/serialized-type.js.map +1 -1
  138. package/dist/types/st-array.d.ts +2 -1
  139. package/dist/types/st-array.js +3 -0
  140. package/dist/types/st-array.js.map +1 -1
  141. package/dist/types/st-number.d.ts +2 -1
  142. package/dist/types/st-number.js +3 -0
  143. package/dist/types/st-number.js.map +1 -1
  144. package/dist/types/st-object.d.ts +2 -1
  145. package/dist/types/st-object.js +9 -1
  146. package/dist/types/st-object.js.map +1 -1
  147. package/dist/types/uint-16.d.ts +2 -0
  148. package/dist/types/uint-16.js +4 -0
  149. package/dist/types/uint-16.js.map +1 -1
  150. package/dist/types/uint-32.d.ts +2 -0
  151. package/dist/types/uint-32.js +4 -0
  152. package/dist/types/uint-32.js.map +1 -1
  153. package/dist/types/uint-64.d.ts +2 -0
  154. package/dist/types/uint-64.js +4 -0
  155. package/dist/types/uint-64.js.map +1 -1
  156. package/dist/types/uint-8.d.ts +2 -0
  157. package/dist/types/uint-8.js +4 -0
  158. package/dist/types/uint-8.js.map +1 -1
  159. package/dist/types/vector-256.d.ts +2 -1
  160. package/dist/types/vector-256.js +3 -0
  161. package/dist/types/vector-256.js.map +1 -1
  162. package/dist/types/xchain-bridge.d.ts +2 -1
  163. package/dist/types/xchain-bridge.js +3 -0
  164. package/dist/types/xchain-bridge.js.map +1 -1
  165. package/dist/utils.js +1 -1
  166. package/dist/utils.js.map +1 -1
  167. package/package.json +2 -2
  168. package/src/enums/definitions.json +238 -260
  169. package/src/quality.ts +13 -3
  170. package/src/serdes/binary-parser.ts +12 -2
  171. package/src/serdes/binary-serializer.ts +2 -2
  172. package/src/types/account-id.ts +5 -0
  173. package/src/types/amount.ts +25 -6
  174. package/src/types/blob.ts +5 -1
  175. package/src/types/currency.ts +5 -0
  176. package/src/types/data.ts +294 -0
  177. package/src/types/dataType.ts +178 -0
  178. package/src/types/hash-128.ts +5 -0
  179. package/src/types/hash-160.ts +5 -0
  180. package/src/types/hash-192.ts +5 -0
  181. package/src/types/hash-256.ts +5 -0
  182. package/src/types/index.ts +6 -0
  183. package/src/types/issue.ts +5 -1
  184. package/src/types/json.ts +650 -0
  185. package/src/types/path-set.ts +5 -1
  186. package/src/types/serialized-type.ts +67 -0
  187. package/src/types/st-array.ts +5 -1
  188. package/src/types/st-number.ts +5 -1
  189. package/src/types/st-object.ts +12 -2
  190. package/src/types/uint-16.ts +5 -0
  191. package/src/types/uint-32.ts +5 -0
  192. package/src/types/uint-64.ts +6 -1
  193. package/src/types/uint-8.ts +5 -0
  194. package/src/types/vector-256.ts +5 -1
  195. package/src/types/xchain-bridge.ts +5 -1
  196. package/src/utils.ts +1 -1
@@ -0,0 +1,650 @@
1
+ /* eslint-disable max-lines */
2
+ import { BinaryParser } from '../serdes/binary-parser'
3
+ import { JsonObject, SerializedType, SerializedTypeID } from './serialized-type'
4
+ import { bytesToHex } from '@xrplf/isomorphic/utils'
5
+ import { BinarySerializer, BytesList } from '../serdes/binary-serializer'
6
+
7
+ /**
8
+ * STJson: Serialized Type for JSON-like structures (objects or arrays).
9
+ *
10
+ * Supports two modes:
11
+ * - Object: Key-value pairs where keys are VL-encoded strings
12
+ * - Array: Ordered list of values
13
+ *
14
+ * Values are [SType marker][VL-encoded SType serialization].
15
+ * Values can be any SType, including nested STJson.
16
+ *
17
+ * Serialization format: [type_byte][VL_length][data...]
18
+ * - type_byte: 0x00 = Object, 0x01 = Array
19
+ *
20
+ * Depth constraint: Maximum nesting depth of 1 level
21
+ */
22
+ class STJson extends SerializedType {
23
+ private static readonly JsonType = {
24
+ Object: 0x00,
25
+ Array: 0x01,
26
+ }
27
+
28
+ private data: Map<string, SerializedType | null> | (SerializedType | null)[]
29
+ private jsonType: number
30
+ private default_ = false
31
+
32
+ /**
33
+ * Construct STJson from bytes
34
+ * @param bytes - Uint8Array containing serialized JSON
35
+ */
36
+ constructor(bytes: Uint8Array) {
37
+ super(bytes)
38
+ this.data = new Map()
39
+ this.jsonType = STJson.JsonType.Object
40
+ }
41
+
42
+ /**
43
+ * Create an empty STJson with the given type
44
+ */
45
+ private static createEmpty(
46
+ type: number,
47
+ initialData?:
48
+ | Map<string, SerializedType | null>
49
+ | (SerializedType | null)[],
50
+ ): STJson {
51
+ const json = new STJson(new Uint8Array())
52
+ json.data = initialData ?? (type === STJson.JsonType.Array ? [] : new Map())
53
+ json.jsonType = type
54
+ return json
55
+ }
56
+
57
+ /**
58
+ * Parse STJson from BinaryParser
59
+ *
60
+ * @param parser - BinaryParser positioned at the start of STJson
61
+ * @returns STJson instance
62
+ */
63
+ static fromParser(parser: BinaryParser): STJson {
64
+ const dataLength = parser.readVariableLengthLength()
65
+
66
+ if (dataLength < 0) {
67
+ throw new Error('Invalid STJson length')
68
+ }
69
+
70
+ if (dataLength === 0) {
71
+ const json = new STJson(new Uint8Array())
72
+ json.data = new Map()
73
+ return json
74
+ }
75
+
76
+ // Read type byte
77
+ const typeByte = parser.read(1)[0]
78
+ const type = typeByte
79
+ const initialBytesLeft = parser.size()
80
+
81
+ if (type === STJson.JsonType.Array) {
82
+ const array: (SerializedType | null)[] = []
83
+ while (
84
+ parser.size() > 0 &&
85
+ initialBytesLeft - parser.size() < dataLength
86
+ ) {
87
+ const valueVL = parser.readVariableLength()
88
+ if (valueVL.length > 0) {
89
+ const valueSit = new BinaryParser(bytesToHex(valueVL))
90
+ const value = STJson.makeValueFromVLWithType(valueSit)
91
+ array.push(value)
92
+ } else {
93
+ array.push(null)
94
+ }
95
+ }
96
+
97
+ const json = new STJson(new Uint8Array())
98
+ json.data = array
99
+ json.jsonType = STJson.JsonType.Array
100
+ return json
101
+ } else {
102
+ // JsonType.Object
103
+ const map = new Map<string, SerializedType | null>()
104
+ while (
105
+ parser.size() > 0 &&
106
+ initialBytesLeft - parser.size() < dataLength
107
+ ) {
108
+ const [key, value] = STJson.parsePair(parser)
109
+ map.set(key, value)
110
+ }
111
+
112
+ const json = new STJson(new Uint8Array())
113
+ json.data = map
114
+ json.jsonType = STJson.JsonType.Object
115
+ return json
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Parse a single key-value pair from the parser
121
+ */
122
+ private static parsePair(
123
+ parser: BinaryParser,
124
+ ): [string, SerializedType | null] {
125
+ const keyVL = parser.readVariableLength()
126
+ const key = new TextDecoder().decode(keyVL)
127
+
128
+ const valueVL = parser.readVariableLength()
129
+ let value: SerializedType | null = null
130
+
131
+ if (valueVL.length > 0) {
132
+ const valueSit = new BinaryParser(bytesToHex(valueVL))
133
+ value = STJson.makeValueFromVLWithType(valueSit)
134
+ }
135
+
136
+ return [key, value]
137
+ }
138
+
139
+ /**
140
+ * Factory for SType value from VL blob (with SType marker)
141
+ */
142
+ private static makeValueFromVLWithType(parser: BinaryParser): SerializedType {
143
+ if (parser.size() === 0) {
144
+ throw new Error('Empty data when parsing STJson value')
145
+ }
146
+
147
+ const typeId = parser.read(1)[0]
148
+
149
+ // Delegate to appropriate type's fromParser
150
+ // This is a placeholder - actual implementation would dispatch to concrete types
151
+ // For now, we create an STJson if type is Object or Array
152
+ if (typeId === STJson.JsonType.Object || typeId === STJson.JsonType.Array) {
153
+ return STJson.fromParser(parser)
154
+ }
155
+
156
+ throw new Error(`Unsupported type ID in STJson: ${typeId}`)
157
+ }
158
+
159
+ /**
160
+ * Check if this is an array type
161
+ */
162
+ isArray(): boolean {
163
+ return this.jsonType === STJson.JsonType.Array
164
+ }
165
+
166
+ /**
167
+ * Check if this is an object type
168
+ */
169
+ isObject(): boolean {
170
+ return this.jsonType === STJson.JsonType.Object
171
+ }
172
+
173
+ /**
174
+ * Get the JSON type
175
+ */
176
+ getType(): number {
177
+ return this.jsonType
178
+ }
179
+
180
+ /**
181
+ * Get nesting depth (0 = no nesting, 1 = one level of nesting)
182
+ */
183
+ getDepth(): number {
184
+ if (this.isArray()) {
185
+ const array = this.data as (SerializedType | null)[]
186
+ for (const value of array) {
187
+ if (value && value instanceof STJson) {
188
+ return 1 + value.getDepth()
189
+ }
190
+ }
191
+ return 0
192
+ } else {
193
+ // isObject()
194
+ const map = this.data as Map<string, SerializedType | null>
195
+ for (const value of map.values()) {
196
+ if (value && value instanceof STJson) {
197
+ return 1 + value.getDepth()
198
+ }
199
+ }
200
+ return 0
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Validate nesting depth (max 1 level)
206
+ */
207
+ private validateDepth(
208
+ value: SerializedType | null,
209
+ currentDepth: number,
210
+ ): void {
211
+ if (!value) {
212
+ return
213
+ }
214
+
215
+ if (!(value instanceof STJson)) {
216
+ return
217
+ }
218
+
219
+ const valueDepth = value.getDepth()
220
+ if (currentDepth + valueDepth > 1) {
221
+ throw new Error('STJson nesting depth exceeds maximum of 1')
222
+ }
223
+ }
224
+
225
+ /**
226
+ * Set a field in an object
227
+ */
228
+ setObjectField(key: string, value: SerializedType | null): void {
229
+ if (!this.isObject()) {
230
+ throw new Error('STJson::setObjectField called on non-object')
231
+ }
232
+ this.validateDepth(value, 0)
233
+ ;(this.data as Map<string, SerializedType | null>).set(key, value)
234
+ }
235
+
236
+ /**
237
+ * Get a field from an object
238
+ */
239
+ getObjectField(key: string): SerializedType | null | undefined {
240
+ if (!this.isObject()) {
241
+ return undefined
242
+ }
243
+ return (this.data as Map<string, SerializedType | null>).get(key)
244
+ }
245
+
246
+ /**
247
+ * Set a nested object field (one level deep)
248
+ */
249
+ setNestedObjectField(
250
+ key: string,
251
+ nestedKey: string,
252
+ value: SerializedType | null,
253
+ ): void {
254
+ if (!this.isObject()) {
255
+ throw new Error('STJson::setNestedObjectField called on non-object')
256
+ }
257
+
258
+ const map = this.data as Map<string, SerializedType | null>
259
+ let nestedObj = map.get(key)
260
+
261
+ if (!nestedObj || !(nestedObj instanceof STJson) || !nestedObj.isObject()) {
262
+ const newNested = STJson.createEmpty(STJson.JsonType.Object)
263
+ map.set(key, newNested as SerializedType)
264
+ nestedObj = newNested
265
+ }
266
+
267
+ if (nestedObj instanceof STJson) {
268
+ nestedObj.setObjectField(nestedKey, value)
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Get a nested object field
274
+ */
275
+ getNestedObjectField(
276
+ key: string,
277
+ nestedKey: string,
278
+ ): SerializedType | null | undefined {
279
+ if (!this.isObject()) {
280
+ return undefined
281
+ }
282
+
283
+ const nestedObj = (this.data as Map<string, SerializedType | null>).get(key)
284
+ if (nestedObj instanceof STJson && nestedObj.isObject()) {
285
+ return nestedObj.getObjectField(nestedKey)
286
+ }
287
+ return undefined
288
+ }
289
+
290
+ /**
291
+ * Get the inner data as a Map (for objects)
292
+ */
293
+ getMap(): Map<string, SerializedType | null> {
294
+ if (!this.isObject()) {
295
+ throw new Error('STJson is not an object type')
296
+ }
297
+ return this.data as Map<string, SerializedType | null>
298
+ }
299
+
300
+ /**
301
+ * Get the inner data as an array
302
+ */
303
+ getArray(): (SerializedType | null)[] {
304
+ if (!this.isArray()) {
305
+ throw new Error('STJson is not an array type')
306
+ }
307
+ return this.data as (SerializedType | null)[]
308
+ }
309
+
310
+ /**
311
+ * Push an element to an array
312
+ */
313
+ pushArrayElement(value: SerializedType | null): void {
314
+ if (!this.isArray()) {
315
+ throw new Error('STJson::pushArrayElement called on non-array')
316
+ }
317
+ this.validateDepth(value, 0)
318
+ ;(this.data as (SerializedType | null)[]).push(value)
319
+ }
320
+
321
+ /**
322
+ * Get an array element by index
323
+ */
324
+ getArrayElement(index: number): SerializedType | null | undefined {
325
+ if (!this.isArray()) {
326
+ return undefined
327
+ }
328
+ const array = this.data as (SerializedType | null)[]
329
+ return array[index]
330
+ }
331
+
332
+ /**
333
+ * Set an array element by index
334
+ */
335
+ setArrayElement(index: number, value: SerializedType | null): void {
336
+ if (!this.isArray()) {
337
+ throw new Error('STJson::setArrayElement called on non-array')
338
+ }
339
+ this.validateDepth(value, 0)
340
+
341
+ const array = this.data as (SerializedType | null)[]
342
+ // Auto-resize with nulls if needed
343
+ if (index >= array.length) {
344
+ array.length = index + 1
345
+ array.fill(null)
346
+ }
347
+ array[index] = value
348
+ }
349
+
350
+ /**
351
+ * Set a field within an array element (element must be an object)
352
+ */
353
+ setArrayElementField(
354
+ index: number,
355
+ key: string,
356
+ value: SerializedType | null,
357
+ ): void {
358
+ if (!this.isArray()) {
359
+ throw new Error('STJson::setArrayElementField called on non-array')
360
+ }
361
+
362
+ this.validateDepth(value, 1)
363
+
364
+ const array = this.data as (SerializedType | null)[]
365
+ // Auto-resize with nulls if needed
366
+ if (index >= array.length) {
367
+ array.length = index + 1
368
+ array.fill(null)
369
+ }
370
+
371
+ let element = array[index]
372
+ if (!element || !(element instanceof STJson) || !element.isObject()) {
373
+ const newElement = STJson.createEmpty(STJson.JsonType.Object)
374
+ array[index] = newElement as SerializedType
375
+ element = newElement
376
+ }
377
+
378
+ if (element instanceof STJson) {
379
+ element.setObjectField(key, value)
380
+ }
381
+ }
382
+
383
+ /**
384
+ * Get a field within an array element
385
+ */
386
+ getArrayElementField(
387
+ index: number,
388
+ key: string,
389
+ ): SerializedType | null | undefined {
390
+ if (!this.isArray()) {
391
+ return undefined
392
+ }
393
+
394
+ const array = this.data as (SerializedType | null)[]
395
+ if (index >= array.length) {
396
+ return undefined
397
+ }
398
+
399
+ const element = array[index]
400
+ if (element instanceof STJson && element.isObject()) {
401
+ return element.getObjectField(key)
402
+ }
403
+ return undefined
404
+ }
405
+
406
+ /**
407
+ * Get the size of the array
408
+ */
409
+ arraySize(): number {
410
+ if (!this.isArray()) {
411
+ return 0
412
+ }
413
+ return (this.data as (SerializedType | null)[]).length
414
+ }
415
+
416
+ /**
417
+ * Set a nested array element (array stored in object field)
418
+ */
419
+ setNestedArrayElement(
420
+ key: string,
421
+ index: number,
422
+ value: SerializedType | null,
423
+ ): void {
424
+ if (!this.isObject()) {
425
+ throw new Error('STJson::setNestedArrayElement called on non-object')
426
+ }
427
+
428
+ this.validateDepth(value, 1)
429
+
430
+ const map = this.data as Map<string, SerializedType | null>
431
+ let arrayJson = map.get(key)
432
+
433
+ if (!arrayJson || !(arrayJson instanceof STJson) || !arrayJson.isArray()) {
434
+ const newArray = STJson.createEmpty(STJson.JsonType.Array)
435
+ map.set(key, newArray as SerializedType)
436
+ arrayJson = newArray
437
+ }
438
+
439
+ if (arrayJson instanceof STJson) {
440
+ arrayJson.setArrayElement(index, value)
441
+ }
442
+ }
443
+
444
+ /**
445
+ * Set a field within a nested array element
446
+ */
447
+ // eslint-disable-next-line max-params -- all 4 params are needed to address a nested array element field
448
+ setNestedArrayElementField(
449
+ key: string,
450
+ index: number,
451
+ nestedKey: string,
452
+ value: SerializedType | null,
453
+ ): void {
454
+ if (!this.isObject()) {
455
+ throw new Error('STJson::setNestedArrayElementField called on non-object')
456
+ }
457
+
458
+ this.validateDepth(value, 1)
459
+
460
+ const map = this.data as Map<string, SerializedType | null>
461
+ let arrayJson = map.get(key)
462
+
463
+ if (!arrayJson || !(arrayJson instanceof STJson) || !arrayJson.isArray()) {
464
+ const newArray = STJson.createEmpty(STJson.JsonType.Array)
465
+ map.set(key, newArray as SerializedType)
466
+ arrayJson = newArray
467
+ }
468
+
469
+ if (arrayJson instanceof STJson) {
470
+ arrayJson.setArrayElementField(index, nestedKey, value)
471
+ }
472
+ }
473
+
474
+ /**
475
+ * Get a nested array element
476
+ */
477
+ getNestedArrayElement(
478
+ key: string,
479
+ index: number,
480
+ ): SerializedType | null | undefined {
481
+ if (!this.isObject()) {
482
+ return undefined
483
+ }
484
+
485
+ const arrayJson = (this.data as Map<string, SerializedType | null>).get(key)
486
+ if (arrayJson instanceof STJson && arrayJson.isArray()) {
487
+ return arrayJson.getArrayElement(index)
488
+ }
489
+ return undefined
490
+ }
491
+
492
+ /**
493
+ * Get a field within a nested array element
494
+ */
495
+ getNestedArrayElementField(
496
+ key: string,
497
+ index: number,
498
+ nestedKey: string,
499
+ ): SerializedType | null | undefined {
500
+ if (!this.isObject()) {
501
+ return undefined
502
+ }
503
+
504
+ const arrayJson = (this.data as Map<string, SerializedType | null>).get(key)
505
+ if (arrayJson instanceof STJson && arrayJson.isArray()) {
506
+ return arrayJson.getArrayElementField(index, nestedKey)
507
+ }
508
+ return undefined
509
+ }
510
+
511
+ /**
512
+ * Serialize to binary
513
+ */
514
+ add(s: BinarySerializer): void {
515
+ const bytesList = new BytesList()
516
+ const tmp = new BinarySerializer(bytesList)
517
+
518
+ // Add type byte
519
+ tmp.put(new Uint8Array([this.jsonType]))
520
+
521
+ if (this.isArray()) {
522
+ const array = this.data as (SerializedType | null)[]
523
+ for (const value of array) {
524
+ STJson.addVLValue(tmp, value)
525
+ }
526
+ } else {
527
+ // isObject()
528
+ const map = this.data as Map<string, SerializedType | null>
529
+ for (const [key, value] of map.entries()) {
530
+ STJson.addVLKey(tmp, key)
531
+ STJson.addVLValue(tmp, value)
532
+ }
533
+ }
534
+
535
+ const innerBytes = bytesList.toBytes()
536
+ const lengthBytes = BinarySerializer.encodeVariableLength(innerBytes.length)
537
+ s.put(lengthBytes)
538
+ s.put(innerBytes)
539
+ }
540
+
541
+ /**
542
+ * Encode a key as VL
543
+ */
544
+ private static addVLKey(s: BinarySerializer, str: string): void {
545
+ const keyBytes = new TextEncoder().encode(str)
546
+ const lengthBytes = BinarySerializer.encodeVariableLength(keyBytes.length)
547
+ s.put(lengthBytes)
548
+ s.put(keyBytes)
549
+ }
550
+
551
+ /**
552
+ * Encode a value as [SType marker][VL]
553
+ */
554
+ private static addVLValue(
555
+ s: BinarySerializer,
556
+ value: SerializedType | null,
557
+ ): void {
558
+ if (!value) {
559
+ s.put(BinarySerializer.encodeVariableLength(0))
560
+ return
561
+ }
562
+
563
+ const bytesList = new BytesList()
564
+ const tmp = new BinarySerializer(bytesList)
565
+ tmp.put(new Uint8Array([value.getSType()]))
566
+ value.toBytesSink(bytesList)
567
+
568
+ const innerBytes = bytesList.toBytes()
569
+ const lengthBytes = BinarySerializer.encodeVariableLength(innerBytes.length)
570
+ s.put(lengthBytes)
571
+ s.put(innerBytes)
572
+ }
573
+
574
+ /**
575
+ * Convert to JSON representation
576
+ */
577
+ toJSON(): JsonObject | JsonObject[] {
578
+ if (this.isArray()) {
579
+ const array = this.data as (SerializedType | null)[]
580
+ return array.map((item) => {
581
+ return item ? item.toJSON() : null
582
+ }) as JsonObject[]
583
+ } else {
584
+ // isObject()
585
+ const map = this.data as Map<string, SerializedType | null>
586
+ const result: JsonObject = {}
587
+ for (const [key, value] of map.entries()) {
588
+ result[key] = value ? value.toJSON() : null
589
+ }
590
+ return result
591
+ }
592
+ }
593
+
594
+ /**
595
+ * Compare with another STJson for equivalence
596
+ */
597
+ isEquivalent(t: SerializedType): boolean {
598
+ if (!(t instanceof STJson)) {
599
+ return false
600
+ }
601
+ return bytesToHex(this.bytes) === bytesToHex(t.bytes)
602
+ }
603
+
604
+ /**
605
+ * Check if this is the default value
606
+ */
607
+ isDefault(): boolean {
608
+ return this.default_
609
+ }
610
+
611
+ /**
612
+ * Get blob representation
613
+ */
614
+ toBlob(): Uint8Array {
615
+ const bytesList = new BytesList()
616
+ const s = new BinarySerializer(bytesList)
617
+ this.add(s)
618
+ return bytesList.toBytes()
619
+ }
620
+
621
+ /**
622
+ * Get the size (number of bytes in serialized form)
623
+ */
624
+ size(): number {
625
+ const bytesList = new BytesList()
626
+ const s = new BinarySerializer(bytesList)
627
+ this.add(s)
628
+ return bytesList.getLength()
629
+ }
630
+
631
+ /**
632
+ * Set the value from another STJson
633
+ */
634
+ setValue(v: STJson): void {
635
+ if (!(v instanceof STJson)) {
636
+ throw new Error('setValue: value must be STJson')
637
+ }
638
+ this.data = v.data
639
+ this.jsonType = v.jsonType
640
+ }
641
+
642
+ /**
643
+ * Get serialized type ID
644
+ */
645
+ getSType(): SerializedTypeID {
646
+ return SerializedTypeID.STI_JSON
647
+ }
648
+ }
649
+
650
+ export { STJson }
@@ -1,7 +1,7 @@
1
1
  import { AccountID } from './account-id'
2
2
  import { Currency } from './currency'
3
3
  import { BinaryParser } from '../serdes/binary-parser'
4
- import { SerializedType, JsonObject } from './serialized-type'
4
+ import { SerializedType, JsonObject, SerializedTypeID } from './serialized-type'
5
5
  import { bytesToHex, concat } from '@xrplf/isomorphic/utils'
6
6
 
7
7
  /**
@@ -285,6 +285,10 @@ class PathSet extends SerializedType {
285
285
 
286
286
  return json
287
287
  }
288
+
289
+ getSType(): SerializedTypeID {
290
+ return SerializedTypeID.STI_PATHSET
291
+ }
288
292
  }
289
293
 
290
294
  export { PathSet }