ripple-binary-codec 2.7.0-smartescrow.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 (210) hide show
  1. package/dist/enums/definitions.json +173 -270
  2. package/dist/enums/src/enums/definitions.json +173 -270
  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 +173 -270
  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/int-32.d.ts +17 -8
  52. package/dist/src/types/int-32.js +25 -11
  53. package/dist/src/types/int-32.js.map +1 -1
  54. package/dist/src/types/int.d.ts +38 -0
  55. package/dist/src/types/int.js +57 -0
  56. package/dist/src/types/int.js.map +1 -0
  57. package/dist/src/types/issue.d.ts +2 -1
  58. package/dist/src/types/issue.js +3 -0
  59. package/dist/src/types/issue.js.map +1 -1
  60. package/dist/src/types/json.d.ts +173 -0
  61. package/dist/src/types/json.js +531 -0
  62. package/dist/src/types/json.js.map +1 -0
  63. package/dist/src/types/path-set.d.ts +2 -1
  64. package/dist/src/types/path-set.js +3 -0
  65. package/dist/src/types/path-set.js.map +1 -1
  66. package/dist/src/types/serialized-type.d.ts +43 -0
  67. package/dist/src/types/serialized-type.js +63 -1
  68. package/dist/src/types/serialized-type.js.map +1 -1
  69. package/dist/src/types/st-array.d.ts +2 -1
  70. package/dist/src/types/st-array.js +3 -0
  71. package/dist/src/types/st-array.js.map +1 -1
  72. package/dist/src/types/st-number.d.ts +2 -1
  73. package/dist/src/types/st-number.js +3 -0
  74. package/dist/src/types/st-number.js.map +1 -1
  75. package/dist/src/types/st-object.d.ts +2 -1
  76. package/dist/src/types/st-object.js +9 -1
  77. package/dist/src/types/st-object.js.map +1 -1
  78. package/dist/src/types/uint-16.d.ts +2 -0
  79. package/dist/src/types/uint-16.js +4 -0
  80. package/dist/src/types/uint-16.js.map +1 -1
  81. package/dist/src/types/uint-32.d.ts +2 -0
  82. package/dist/src/types/uint-32.js +4 -0
  83. package/dist/src/types/uint-32.js.map +1 -1
  84. package/dist/src/types/uint-64.d.ts +2 -0
  85. package/dist/src/types/uint-64.js +4 -0
  86. package/dist/src/types/uint-64.js.map +1 -1
  87. package/dist/src/types/uint-8.d.ts +2 -0
  88. package/dist/src/types/uint-8.js +4 -0
  89. package/dist/src/types/uint-8.js.map +1 -1
  90. package/dist/src/types/vector-256.d.ts +2 -1
  91. package/dist/src/types/vector-256.js +3 -0
  92. package/dist/src/types/vector-256.js.map +1 -1
  93. package/dist/src/types/xchain-bridge.d.ts +2 -1
  94. package/dist/src/types/xchain-bridge.js +3 -0
  95. package/dist/src/types/xchain-bridge.js.map +1 -1
  96. package/dist/src/utils.js +1 -1
  97. package/dist/src/utils.js.map +1 -1
  98. package/dist/tsconfig.tsbuildinfo +1 -1
  99. package/dist/types/account-id.d.ts +2 -0
  100. package/dist/types/account-id.js +4 -0
  101. package/dist/types/account-id.js.map +1 -1
  102. package/dist/types/amount.d.ts +2 -1
  103. package/dist/types/amount.js +25 -4
  104. package/dist/types/amount.js.map +1 -1
  105. package/dist/types/blob.d.ts +2 -1
  106. package/dist/types/blob.js +3 -0
  107. package/dist/types/blob.js.map +1 -1
  108. package/dist/types/currency.d.ts +2 -0
  109. package/dist/types/currency.js +4 -0
  110. package/dist/types/currency.js.map +1 -1
  111. package/dist/types/data.d.ts +86 -0
  112. package/dist/types/data.js +252 -0
  113. package/dist/types/data.js.map +1 -0
  114. package/dist/types/dataType.d.ts +94 -0
  115. package/dist/types/dataType.js +145 -0
  116. package/dist/types/dataType.js.map +1 -0
  117. package/dist/types/hash-128.d.ts +2 -0
  118. package/dist/types/hash-128.js +4 -0
  119. package/dist/types/hash-128.js.map +1 -1
  120. package/dist/types/hash-160.d.ts +2 -0
  121. package/dist/types/hash-160.js +4 -0
  122. package/dist/types/hash-160.js.map +1 -1
  123. package/dist/types/hash-192.d.ts +2 -0
  124. package/dist/types/hash-192.js +4 -0
  125. package/dist/types/hash-192.js.map +1 -1
  126. package/dist/types/hash-256.d.ts +2 -0
  127. package/dist/types/hash-256.js +4 -0
  128. package/dist/types/hash-256.js.map +1 -1
  129. package/dist/types/index.d.ts +3 -1
  130. package/dist/types/index.js +7 -1
  131. package/dist/types/index.js.map +1 -1
  132. package/dist/types/int-32.d.ts +17 -8
  133. package/dist/types/int-32.js +25 -11
  134. package/dist/types/int-32.js.map +1 -1
  135. package/dist/types/int.d.ts +38 -0
  136. package/dist/types/int.js +57 -0
  137. package/dist/types/int.js.map +1 -0
  138. package/dist/types/issue.d.ts +2 -1
  139. package/dist/types/issue.js +3 -0
  140. package/dist/types/issue.js.map +1 -1
  141. package/dist/types/json.d.ts +173 -0
  142. package/dist/types/json.js +531 -0
  143. package/dist/types/json.js.map +1 -0
  144. package/dist/types/path-set.d.ts +2 -1
  145. package/dist/types/path-set.js +3 -0
  146. package/dist/types/path-set.js.map +1 -1
  147. package/dist/types/serialized-type.d.ts +43 -0
  148. package/dist/types/serialized-type.js +63 -1
  149. package/dist/types/serialized-type.js.map +1 -1
  150. package/dist/types/st-array.d.ts +2 -1
  151. package/dist/types/st-array.js +3 -0
  152. package/dist/types/st-array.js.map +1 -1
  153. package/dist/types/st-number.d.ts +2 -1
  154. package/dist/types/st-number.js +3 -0
  155. package/dist/types/st-number.js.map +1 -1
  156. package/dist/types/st-object.d.ts +2 -1
  157. package/dist/types/st-object.js +9 -1
  158. package/dist/types/st-object.js.map +1 -1
  159. package/dist/types/uint-16.d.ts +2 -0
  160. package/dist/types/uint-16.js +4 -0
  161. package/dist/types/uint-16.js.map +1 -1
  162. package/dist/types/uint-32.d.ts +2 -0
  163. package/dist/types/uint-32.js +4 -0
  164. package/dist/types/uint-32.js.map +1 -1
  165. package/dist/types/uint-64.d.ts +2 -0
  166. package/dist/types/uint-64.js +4 -0
  167. package/dist/types/uint-64.js.map +1 -1
  168. package/dist/types/uint-8.d.ts +2 -0
  169. package/dist/types/uint-8.js +4 -0
  170. package/dist/types/uint-8.js.map +1 -1
  171. package/dist/types/vector-256.d.ts +2 -1
  172. package/dist/types/vector-256.js +3 -0
  173. package/dist/types/vector-256.js.map +1 -1
  174. package/dist/types/xchain-bridge.d.ts +2 -1
  175. package/dist/types/xchain-bridge.js +3 -0
  176. package/dist/types/xchain-bridge.js.map +1 -1
  177. package/dist/utils.js +1 -1
  178. package/dist/utils.js.map +1 -1
  179. package/package.json +2 -2
  180. package/src/enums/definitions.json +173 -270
  181. package/src/quality.ts +13 -3
  182. package/src/serdes/binary-parser.ts +12 -2
  183. package/src/serdes/binary-serializer.ts +2 -2
  184. package/src/types/account-id.ts +5 -0
  185. package/src/types/amount.ts +25 -6
  186. package/src/types/blob.ts +5 -1
  187. package/src/types/currency.ts +5 -0
  188. package/src/types/data.ts +294 -0
  189. package/src/types/dataType.ts +178 -0
  190. package/src/types/hash-128.ts +5 -0
  191. package/src/types/hash-160.ts +5 -0
  192. package/src/types/hash-192.ts +5 -0
  193. package/src/types/hash-256.ts +5 -0
  194. package/src/types/index.ts +6 -0
  195. package/src/types/int-32.ts +27 -12
  196. package/src/types/int.ts +75 -0
  197. package/src/types/issue.ts +5 -1
  198. package/src/types/json.ts +650 -0
  199. package/src/types/path-set.ts +5 -1
  200. package/src/types/serialized-type.ts +67 -0
  201. package/src/types/st-array.ts +5 -1
  202. package/src/types/st-number.ts +5 -1
  203. package/src/types/st-object.ts +12 -2
  204. package/src/types/uint-16.ts +5 -0
  205. package/src/types/uint-32.ts +5 -0
  206. package/src/types/uint-64.ts +6 -1
  207. package/src/types/uint-8.ts +5 -0
  208. package/src/types/vector-256.ts +5 -1
  209. package/src/types/xchain-bridge.ts +5 -1
  210. package/src/utils.ts +1 -1
package/src/quality.ts CHANGED
@@ -13,8 +13,13 @@ class quality {
13
13
  * @returns Serialized quality
14
14
  */
15
15
  static encode(quality: string): Uint8Array {
16
- const decimal = BigNumber(quality)
17
- const exponent = (decimal?.e || 0) - 15
16
+ let decimal: BigNumber
17
+ try {
18
+ decimal = new BigNumber(quality)
19
+ } catch (_err) {
20
+ throw new Error(`${quality} is not a valid quality`)
21
+ }
22
+ const exponent = (decimal.e || 0) - 15
18
23
  const qualityString = decimal.times(`1e${-exponent}`).abs().toString()
19
24
  const bytes = coreTypes.UInt64.from(BigInt(qualityString)).toBytes()
20
25
  bytes[0] = exponent + 100
@@ -30,7 +35,12 @@ class quality {
30
35
  static decode(quality: string): BigNumber {
31
36
  const bytes = hexToBytes(quality).slice(-8)
32
37
  const exponent = bytes[0] - 100
33
- const mantissa = new BigNumber(`0x${bytesToHex(bytes.slice(1))}`)
38
+ let mantissa: BigNumber
39
+ try {
40
+ mantissa = new BigNumber(`0x${bytesToHex(bytes.slice(1))}`)
41
+ } catch (_err) {
42
+ throw new Error(`${quality} is not a valid quality`)
43
+ }
34
44
  return mantissa.times(`1e${exponent}`)
35
45
  }
36
46
  }
@@ -46,8 +46,13 @@ class BinaryParser {
46
46
  * @param n the number of bytes to skip
47
47
  */
48
48
  skip(n: number): void {
49
+ if (n < 0) {
50
+ throw new Error(`skip: negative length ${n}`)
51
+ }
49
52
  if (n > this.bytes.byteLength) {
50
- throw new Error()
53
+ throw new Error(
54
+ `skip: requested ${n} bytes but only ${this.bytes.byteLength} available`,
55
+ )
51
56
  }
52
57
  this.bytes = this.bytes.slice(n)
53
58
  }
@@ -59,8 +64,13 @@ class BinaryParser {
59
64
  * @return The bytes
60
65
  */
61
66
  read(n: number): Uint8Array {
67
+ if (n < 0) {
68
+ throw new Error(`read: negative length ${n}`)
69
+ }
62
70
  if (n > this.bytes.byteLength) {
63
- throw new Error()
71
+ throw new Error(
72
+ `read: requested ${n} bytes but only ${this.bytes.byteLength} available`,
73
+ )
64
74
  }
65
75
 
66
76
  const slice = this.bytes.slice(0, n)
@@ -99,7 +99,7 @@ class BinarySerializer {
99
99
  *
100
100
  * @param length the length of the bytes
101
101
  */
102
- private encodeVariableLength(length: number): Uint8Array {
102
+ static encodeVariableLength(length: number): Uint8Array {
103
103
  const lenBytes = new Uint8Array(3)
104
104
  if (length <= 192) {
105
105
  lenBytes[0] = length
@@ -158,7 +158,7 @@ class BinarySerializer {
158
158
  // this part doesn't happen for the Account field in a UNLModify transaction
159
159
  value.toBytesSink(bytes)
160
160
  }
161
- this.put(this.encodeVariableLength(bytes.getLength()))
161
+ this.put(BinarySerializer.encodeVariableLength(bytes.getLength()))
162
162
  this.writeBytesList(bytes)
163
163
  }
164
164
  }
@@ -6,6 +6,7 @@ import {
6
6
  } from 'ripple-address-codec'
7
7
  import { Hash160 } from './hash-160'
8
8
  import { hexToBytes } from '@xrplf/isomorphic/utils'
9
+ import { SerializedTypeID } from './serialized-type'
9
10
 
10
11
  const HEX_REGEX = /^[A-F0-9]{40}$/
11
12
 
@@ -81,6 +82,10 @@ class AccountID extends Hash160 {
81
82
  toBase58(): string {
82
83
  return encodeAccountID(this.bytes)
83
84
  }
85
+
86
+ getSType(): SerializedTypeID {
87
+ return SerializedTypeID.STI_ACCOUNT
88
+ }
84
89
  }
85
90
 
86
91
  export { AccountID }
@@ -2,7 +2,7 @@ import { BinaryParser } from '../serdes/binary-parser'
2
2
 
3
3
  import { AccountID } from './account-id'
4
4
  import { Currency } from './currency'
5
- import { JsonObject, SerializedType } from './serialized-type'
5
+ import { JsonObject, SerializedType, SerializedTypeID } from './serialized-type'
6
6
  import BigNumber from 'bignumber.js'
7
7
  import { bytesToHex, concat, hexToBytes } from '@xrplf/isomorphic/utils'
8
8
  import { readUInt32BE, writeUInt32BE } from '../utils'
@@ -92,7 +92,7 @@ class Amount extends SerializedType {
92
92
  return value
93
93
  }
94
94
 
95
- let amount = new Uint8Array(8)
95
+ let amount: Uint8Array = new Uint8Array(8)
96
96
  if (typeof value === 'string') {
97
97
  Amount.assertXrpIsValid(value)
98
98
 
@@ -110,7 +110,12 @@ class Amount extends SerializedType {
110
110
  }
111
111
 
112
112
  if (isAmountObjectIOU(value)) {
113
- const number = new BigNumber(value.value)
113
+ let number: BigNumber
114
+ try {
115
+ number = new BigNumber(value.value)
116
+ } catch (_err) {
117
+ throw new Error(`${value.value} is an illegal amount`)
118
+ }
114
119
  Amount.assertIouIsValid(number)
115
120
 
116
121
  if (number.isZero()) {
@@ -189,7 +194,7 @@ class Amount extends SerializedType {
189
194
  */
190
195
  toJSON(): AmountObject | string {
191
196
  if (this.isNative()) {
192
- const bytes = this.bytes
197
+ const bytes = this.bytes.slice()
193
198
  const isPositive = bytes[0] & 0x40
194
199
  const sign = isPositive ? '' : '-'
195
200
  bytes[0] &= 0x3f
@@ -261,7 +266,12 @@ class Amount extends SerializedType {
261
266
  throw new Error(`${amount.toString()} is an illegal amount`)
262
267
  }
263
268
 
264
- const decimal = new BigNumber(amount)
269
+ let decimal: BigNumber
270
+ try {
271
+ decimal = new BigNumber(amount)
272
+ } catch (_err) {
273
+ throw new Error(`${amount.toString()} is an illegal amount`)
274
+ }
265
275
  if (!decimal.isZero()) {
266
276
  if (decimal.lt(MIN_XRP) || decimal.gt(MAX_DROPS)) {
267
277
  throw new Error(`${amount.toString()} is an illegal amount`)
@@ -301,7 +311,12 @@ class Amount extends SerializedType {
301
311
  throw new Error(`${amount.toString()} is an illegal amount`)
302
312
  }
303
313
 
304
- const decimal = new BigNumber(amount)
314
+ let decimal: BigNumber
315
+ try {
316
+ decimal = new BigNumber(amount)
317
+ } catch (_err) {
318
+ throw new Error(`${amount.toString()} is an illegal amount`)
319
+ }
305
320
  if (!decimal.isZero()) {
306
321
  if (decimal < BigNumber(0)) {
307
322
  throw new Error(`${amount.toString()} is an illegal amount`)
@@ -357,6 +372,10 @@ class Amount extends SerializedType {
357
372
  private isIOU(): boolean {
358
373
  return (this.bytes[0] & 0x80) !== 0
359
374
  }
375
+
376
+ getSType(): SerializedTypeID {
377
+ return SerializedTypeID.STI_AMOUNT
378
+ }
360
379
  }
361
380
 
362
381
  export { Amount, AmountObject }
package/src/types/blob.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SerializedType } from './serialized-type'
1
+ import { SerializedType, SerializedTypeID } from './serialized-type'
2
2
  import { BinaryParser } from '../serdes/binary-parser'
3
3
  import { hexToBytes } from '@xrplf/isomorphic/utils'
4
4
 
@@ -41,6 +41,10 @@ class Blob extends SerializedType {
41
41
 
42
42
  throw new Error('Cannot construct Blob from value given')
43
43
  }
44
+
45
+ getSType(): SerializedTypeID {
46
+ return SerializedTypeID.STI_VL
47
+ }
44
48
  }
45
49
 
46
50
  export { Blob }
@@ -1,5 +1,6 @@
1
1
  import { Hash160 } from './hash-160'
2
2
  import { bytesToHex, hexToBytes, hexToString } from '@xrplf/isomorphic/utils'
3
+ import { SerializedTypeID } from './serialized-type'
3
4
 
4
5
  const XRP_HEX_REGEX = /^0{40}$/
5
6
  const ISO_REGEX = /^[A-Z0-9a-z?!@#$%^&*(){}[\]|]{3}$/
@@ -135,6 +136,10 @@ class Currency extends Hash160 {
135
136
  }
136
137
  return bytesToHex(this.bytes)
137
138
  }
139
+
140
+ getSType(): SerializedTypeID {
141
+ return SerializedTypeID.STI_CURRENCY
142
+ }
138
143
  }
139
144
 
140
145
  export { Currency }
@@ -0,0 +1,294 @@
1
+ import { BinaryParser } from '../serdes/binary-parser'
2
+ import {
3
+ JsonObject,
4
+ SerializedType,
5
+ SerializedTypeID,
6
+ TYPE_ID_TO_STRING,
7
+ TYPE_STRING_TO_ID,
8
+ TYPE_NUMBER_TO_ID,
9
+ } from './serialized-type'
10
+ import { readUInt16BE, writeUInt16BE } from '../utils'
11
+ import { bytesToHex, concat } from '@xrplf/isomorphic/utils'
12
+ import { Hash128 } from './hash-128'
13
+ import { Hash160 } from './hash-160'
14
+ import { Hash192 } from './hash-192'
15
+ import { Hash256 } from './hash-256'
16
+ import { AccountID } from './account-id'
17
+ import { Amount } from './amount'
18
+ import { Blob } from './blob'
19
+ import { Currency } from './currency'
20
+ import { STNumber } from './st-number'
21
+ import { Issue } from './issue'
22
+ import { UInt8 } from './uint-8'
23
+ import { UInt16 } from './uint-16'
24
+ import { UInt32 } from './uint-32'
25
+ import { UInt64 } from './uint-64'
26
+ import { BinarySerializer } from '../binary'
27
+
28
+ /**
29
+ * Interface for Data JSON representation
30
+ */
31
+ interface DataJSON extends JsonObject {
32
+ type: string
33
+ value: string | number | JsonObject
34
+ }
35
+
36
+ /**
37
+ * Map from SerializedTypeID to the corresponding type class.
38
+ * Types listed here use standard from()/fromParser()/toBytes() without
39
+ * any extra framing (unlike VL and Account which need length prefixes).
40
+ */
41
+ const SIMPLE_TYPE_MAP: Partial<
42
+ Record<SerializedTypeID, typeof SerializedType>
43
+ > = {
44
+ [SerializedTypeID.STI_UINT8]: UInt8,
45
+ [SerializedTypeID.STI_UINT16]: UInt16,
46
+ [SerializedTypeID.STI_UINT32]: UInt32,
47
+ [SerializedTypeID.STI_UINT64]: UInt64,
48
+ [SerializedTypeID.STI_UINT128]: Hash128,
49
+ [SerializedTypeID.STI_UINT160]: Hash160,
50
+ [SerializedTypeID.STI_UINT192]: Hash192,
51
+ [SerializedTypeID.STI_UINT256]: Hash256,
52
+ [SerializedTypeID.STI_AMOUNT]: Amount,
53
+ [SerializedTypeID.STI_ISSUE]: Issue,
54
+ [SerializedTypeID.STI_CURRENCY]: Currency,
55
+ [SerializedTypeID.STI_NUMBER]: STNumber,
56
+ }
57
+
58
+ /**
59
+ * Types whose from() method expects a numeric argument.
60
+ * For these, json.value is coerced to a number before calling from().
61
+ */
62
+ const NUMERIC_TYPES = new Set<SerializedTypeID>([
63
+ SerializedTypeID.STI_UINT8,
64
+ SerializedTypeID.STI_UINT16,
65
+ SerializedTypeID.STI_UINT32,
66
+ ])
67
+
68
+ /**
69
+ * STData: Encodes XRPL's "Data" type.
70
+ *
71
+ * This type wraps both a SerializedTypeID and the actual data value.
72
+ * It's encoded as a 2-byte type ID followed by the serialized data.
73
+ *
74
+ * Usage:
75
+ * Data.from({ type: "Amount", value: "1000000" })
76
+ * Data.from({ type: "UInt64", value: "123456789" })
77
+ * Data.fromParser(parser)
78
+ */
79
+ class Data extends SerializedType {
80
+ static readonly ZERO_DATA: Data = new Data(
81
+ concat([
82
+ new Uint8Array([0x00, 0x01]), // Type ID for UINT16 (SerializedTypeID.STI_UINT16 = 1) as uint16
83
+ new Uint8Array([0x00, 0x00]), // Value: two zero bytes for UINT16
84
+ ]),
85
+ )
86
+
87
+ /**
88
+ * Construct Data from bytes
89
+ * @param bytes - Uint8Array containing type ID and data
90
+ */
91
+ constructor(bytes: Uint8Array) {
92
+ super(bytes ?? Data.ZERO_DATA.bytes)
93
+ }
94
+
95
+ /**
96
+ * Create Data from various input types
97
+ *
98
+ * @param value - Can be:
99
+ * - Data instance (returns as-is)
100
+ * - DataJSON object with 'type' and 'value' fields
101
+ * @returns Data instance
102
+ * @throws Error if value type is not supported
103
+ */
104
+ static from(value: unknown): Data {
105
+ if (value instanceof Data) {
106
+ return value
107
+ }
108
+
109
+ if (
110
+ typeof value === 'object' &&
111
+ value !== null &&
112
+ 'type' in value &&
113
+ 'value' in value
114
+ ) {
115
+ const json = value as DataJSON
116
+ return Data.fromJSON(json)
117
+ }
118
+
119
+ throw new Error('Data.from: value must be Data instance or DataJSON object')
120
+ }
121
+
122
+ /**
123
+ * Create Data from JSON representation
124
+ *
125
+ * @param json - Object with 'type' and 'value' fields
126
+ * @returns Data instance
127
+ * @throws Error if type is not supported
128
+ */
129
+ static fromJSON(json: DataJSON): Data {
130
+ const typeId = TYPE_STRING_TO_ID[json.type]
131
+ if (typeId === undefined) {
132
+ throw new Error(`Data: unsupported type string: ${json.type}`)
133
+ }
134
+
135
+ let dataBytes: Uint8Array
136
+
137
+ const TypeClass = SIMPLE_TYPE_MAP[typeId]
138
+ if (TypeClass) {
139
+ // For UInt8/16/32, coerce value to number; all others pass through
140
+ const coercedValue = NUMERIC_TYPES.has(typeId)
141
+ ? typeof json.value === 'string'
142
+ ? parseInt(json.value, 10)
143
+ : Number(json.value)
144
+ : json.value
145
+ dataBytes = TypeClass.from(coercedValue).toBytes()
146
+ } else if (typeId === SerializedTypeID.STI_VL) {
147
+ const val =
148
+ typeof json.value === 'string' ? json.value : json.value.toString()
149
+ dataBytes = Blob.from(val).toBytes()
150
+ dataBytes = concat([
151
+ BinarySerializer.encodeVariableLength(dataBytes.length),
152
+ dataBytes,
153
+ ])
154
+ } else if (typeId === SerializedTypeID.STI_ACCOUNT) {
155
+ const val =
156
+ typeof json.value === 'string' ? json.value : json.value.toString()
157
+ dataBytes = concat([
158
+ new Uint8Array([0x14]),
159
+ AccountID.from(val).toBytes(),
160
+ ])
161
+ } else {
162
+ throw new Error(`Data.fromJSON(): unsupported type ID: ${typeId}`)
163
+ }
164
+
165
+ // Combine type header with data bytes
166
+ const typeBytes = new Uint8Array(2)
167
+ writeUInt16BE(typeBytes, typeId, 0)
168
+ return new Data(concat([typeBytes, dataBytes]))
169
+ }
170
+
171
+ /**
172
+ * Read Data from a BinaryParser stream
173
+ *
174
+ * @param parser - BinaryParser positioned at the start of Data
175
+ * @returns Data instance
176
+ */
177
+ static fromParser(parser: BinaryParser): Data {
178
+ // Read the 2-byte type ID
179
+ const typeBytes = parser.read(2)
180
+ const typeId = TYPE_NUMBER_TO_ID[readUInt16BE(typeBytes, 0)]
181
+
182
+ let dataBytes: Uint8Array
183
+
184
+ const TypeClass = SIMPLE_TYPE_MAP[typeId]
185
+ if (TypeClass) {
186
+ dataBytes = TypeClass.fromParser(parser).toBytes()
187
+ } else if (typeId === SerializedTypeID.STI_VL) {
188
+ const valueVL = parser.readVariableLength()
189
+ dataBytes = concat([
190
+ BinarySerializer.encodeVariableLength(valueVL.length),
191
+ valueVL,
192
+ ])
193
+ } else if (typeId === SerializedTypeID.STI_ACCOUNT) {
194
+ parser.skip(1)
195
+ dataBytes = concat([
196
+ new Uint8Array([0x14]),
197
+ AccountID.fromParser(parser).toBytes(),
198
+ ])
199
+ } else {
200
+ throw new Error(`Data: unsupported type ID when parsing: ${typeId}`)
201
+ }
202
+
203
+ return new Data(concat([typeBytes, dataBytes]))
204
+ }
205
+
206
+ /**
207
+ * Get the inner SerializedTypeID
208
+ *
209
+ * @returns The inner type ID
210
+ */
211
+ getInnerType(): SerializedTypeID {
212
+ return TYPE_NUMBER_TO_ID[readUInt16BE(this.bytes, 0)]
213
+ }
214
+
215
+ /**
216
+ * Get the string representation of the inner type
217
+ *
218
+ * @returns String name of the type
219
+ */
220
+ getInnerTypeString(): string {
221
+ const innerType = this.getInnerType()
222
+ return TYPE_ID_TO_STRING[innerType] || innerType.toString()
223
+ }
224
+
225
+ /**
226
+ * Get the data value
227
+ *
228
+ * @returns The stored data value
229
+ */
230
+ getValue(): SerializedType {
231
+ const innerType = this.getInnerType()
232
+ const parser = new BinaryParser(bytesToHex(this.bytes.slice(2)))
233
+
234
+ const TypeClass = SIMPLE_TYPE_MAP[innerType]
235
+ if (TypeClass) {
236
+ return TypeClass.fromParser(parser)
237
+ }
238
+
239
+ if (innerType === SerializedTypeID.STI_VL) {
240
+ const vlLength = parser.readVariableLengthLength()
241
+ return Blob.fromParser(parser, vlLength)
242
+ }
243
+
244
+ if (innerType === SerializedTypeID.STI_ACCOUNT) {
245
+ parser.skip(1)
246
+ return AccountID.fromParser(parser)
247
+ }
248
+
249
+ throw new Error(`Data.getValue(): unsupported type ID: ${typeof innerType}`)
250
+ }
251
+
252
+ /**
253
+ * Convert to JSON representation
254
+ *
255
+ * @returns JSON object with 'type' and 'value' fields
256
+ */
257
+ toJSON(): DataJSON {
258
+ return {
259
+ type: this.getInnerTypeString(),
260
+ value: this.getValue().toJSON() as string | number | JsonObject,
261
+ }
262
+ }
263
+
264
+ /**
265
+ * Compare with another Data for equality
266
+ *
267
+ * @param other - Another Data to compare with
268
+ * @returns true if both have the same inner type and data
269
+ */
270
+ equals(other: Data): boolean {
271
+ if (!(other instanceof Data)) {
272
+ return false
273
+ }
274
+
275
+ // Compare bytes directly
276
+ if (this.bytes.length !== other.bytes.length) {
277
+ return false
278
+ }
279
+
280
+ for (let i = 0; i < this.bytes.length; i++) {
281
+ if (this.bytes[i] !== other.bytes[i]) {
282
+ return false
283
+ }
284
+ }
285
+
286
+ return true
287
+ }
288
+
289
+ getSType(): SerializedTypeID {
290
+ return SerializedTypeID.STI_DATA
291
+ }
292
+ }
293
+
294
+ export { Data }
@@ -0,0 +1,178 @@
1
+ import { BinaryParser } from '../serdes/binary-parser'
2
+ import {
3
+ JsonObject,
4
+ SerializedType,
5
+ SerializedTypeID,
6
+ TYPE_ID_TO_STRING,
7
+ TYPE_STRING_TO_ID,
8
+ } from './serialized-type'
9
+ import { readUInt16BE, writeUInt16BE } from '../utils'
10
+
11
+ /**
12
+ * Interface for DataType JSON representation
13
+ */
14
+ interface DataTypeJSON extends JsonObject {
15
+ type: string
16
+ }
17
+
18
+ /**
19
+ * STDataType: Encodes XRPL's "DataType" type.
20
+ *
21
+ * This type wraps an inner SerializedTypeID to indicate what type of data
22
+ * a field contains. It's encoded as a 2-byte unsigned integer representing
23
+ * the inner type.
24
+ *
25
+ * Usage:
26
+ * DataType.from({ type: "Amount" })
27
+ * DataType.from("UInt64")
28
+ * DataType.fromParser(parser)
29
+ */
30
+ class DataType extends SerializedType {
31
+ private innerType: SerializedTypeID
32
+
33
+ /**
34
+ * Default bytes for DataType (STI_NOTPRESENT)
35
+ */
36
+ static readonly defaultBytes = new Uint8Array([0x00, 0x01])
37
+
38
+ /**
39
+ * Construct a DataType from bytes
40
+ * @param bytes - 2-byte Uint8Array containing the inner type ID
41
+ * @param innerType - Optional explicit inner type (used when constructing from value)
42
+ * @throws Error if bytes is not a 2-byte Uint8Array
43
+ */
44
+ constructor(bytes?: Uint8Array, innerType?: SerializedTypeID) {
45
+ const used = bytes ?? DataType.defaultBytes
46
+ if (!(used instanceof Uint8Array) || used.length !== 2) {
47
+ throw new Error(
48
+ `DataType must be constructed from a 2-byte Uint8Array, got ${used?.length} bytes`,
49
+ )
50
+ }
51
+ super(used)
52
+
53
+ // If innerType is explicitly provided, use it; otherwise read from bytes
54
+ if (innerType !== undefined) {
55
+ this.innerType = innerType
56
+ } else {
57
+ this.innerType = readUInt16BE(used, 0) as unknown as SerializedTypeID
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Construct from various input types
63
+ *
64
+ * @param value - Can be:
65
+ * - DataType instance (returns as-is)
66
+ * - DataTypeJSON object with 'type' field
67
+ * - String type name (e.g., "Amount", "UInt64")
68
+ * - SerializedTypeID enum value
69
+ * @returns DataType instance
70
+ * @throws Error if value type is not supported or type string is unknown
71
+ */
72
+ static from(value: unknown): DataType {
73
+ if (value instanceof DataType) {
74
+ return value
75
+ }
76
+
77
+ if (typeof value === 'object' && value !== null && 'type' in value) {
78
+ const json = value as DataTypeJSON
79
+ return DataType.fromTypeString(json.type)
80
+ }
81
+
82
+ if (typeof value === 'string') {
83
+ return DataType.fromTypeString(value)
84
+ }
85
+
86
+ if (typeof value === 'number') {
87
+ return DataType.fromTypeId(value as SerializedTypeID)
88
+ }
89
+
90
+ throw new Error(
91
+ 'DataType.from: value must be DataType, DataTypeJSON, string, or SerializedTypeID',
92
+ )
93
+ }
94
+
95
+ /**
96
+ * Construct from a type string
97
+ *
98
+ * @param typeStr - Type string like "Amount", "UInt64", etc.
99
+ * @returns DataType instance
100
+ * @throws Error if type string is not recognized
101
+ */
102
+ static fromTypeString(typeStr: string): DataType {
103
+ const typeId = TYPE_STRING_TO_ID[typeStr]
104
+ if (typeId === undefined) {
105
+ throw new Error(`DataType: unsupported type string: ${typeStr}`)
106
+ }
107
+ return DataType.fromTypeId(typeId)
108
+ }
109
+
110
+ /**
111
+ * Construct from a SerializedTypeID
112
+ *
113
+ * @param typeId - The SerializedTypeID enum value
114
+ * @returns DataType instance
115
+ */
116
+ static fromTypeId(typeId: SerializedTypeID): DataType {
117
+ const bytes = new Uint8Array(2)
118
+ writeUInt16BE(bytes, typeId, 0)
119
+ return new DataType(bytes, typeId)
120
+ }
121
+
122
+ /**
123
+ * Read a DataType from a BinaryParser stream (2 bytes)
124
+ *
125
+ * @param parser - BinaryParser positioned at the start of a DataType
126
+ * @returns DataType instance
127
+ */
128
+ static fromParser(parser: BinaryParser): DataType {
129
+ const bytes = parser.read(2)
130
+ return new DataType(bytes)
131
+ }
132
+
133
+ /**
134
+ * Get the inner SerializedTypeID
135
+ *
136
+ * @returns The inner type ID
137
+ */
138
+ getInnerType(): SerializedTypeID {
139
+ return this.innerType
140
+ }
141
+
142
+ /**
143
+ * Set the inner SerializedTypeID
144
+ *
145
+ * @param typeId - The new inner type ID
146
+ */
147
+ setInnerType(typeId: SerializedTypeID): void {
148
+ this.innerType = typeId
149
+ writeUInt16BE(this.bytes, typeId, 0)
150
+ }
151
+
152
+ /**
153
+ * Get the string representation of the inner type
154
+ *
155
+ * @returns String name of the type, or numeric string if unknown
156
+ */
157
+ getInnerTypeString(): string {
158
+ return TYPE_ID_TO_STRING[this.innerType] || this.innerType.toString()
159
+ }
160
+
161
+ /**
162
+ * Convert to JSON representation
163
+ *
164
+ * @returns JSON object with 'type' field
165
+ */
166
+ toJSON(): DataTypeJSON {
167
+ return {
168
+ type: this.getInnerTypeString(),
169
+ }
170
+ }
171
+
172
+ getSType(): SerializedTypeID {
173
+ return SerializedTypeID.STI_DATATYPE
174
+ }
175
+ }
176
+
177
+ // Export the DataType class for external use
178
+ export { DataType }
@@ -1,5 +1,6 @@
1
1
  import { Hash } from './hash'
2
2
  import { bytesToHex } from '@xrplf/isomorphic/utils'
3
+ import { SerializedTypeID } from './serialized-type'
3
4
 
4
5
  /**
5
6
  * Hash with a width of 128 bits
@@ -28,6 +29,10 @@ class Hash128 extends Hash {
28
29
  }
29
30
  return hex
30
31
  }
32
+
33
+ getSType(): SerializedTypeID {
34
+ return SerializedTypeID.STI_UINT128
35
+ }
31
36
  }
32
37
 
33
38
  export { Hash128 }