@transia/ripple-binary-codec 1.4.6-alpha.9 → 2.5.1-quantum.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 (340) hide show
  1. package/dist/binary.d.ts +30 -16
  2. package/dist/binary.js +36 -16
  3. package/dist/binary.js.map +1 -1
  4. package/dist/enums/bytes.d.ts +1 -2
  5. package/dist/enums/bytes.js +1 -2
  6. package/dist/enums/bytes.js.map +1 -1
  7. package/dist/enums/constants.d.ts +1 -0
  8. package/dist/enums/constants.js +6 -5
  9. package/dist/enums/constants.js.map +1 -1
  10. package/dist/enums/definitions.json +1535 -919
  11. package/dist/enums/field.d.ts +1 -2
  12. package/dist/enums/field.js +1 -2
  13. package/dist/enums/field.js.map +1 -1
  14. package/dist/enums/index.d.ts +1 -2
  15. package/dist/enums/index.js +5 -27
  16. package/dist/enums/index.js.map +1 -1
  17. package/dist/enums/src/enums/definitions.json +1537 -921
  18. package/dist/enums/xrpl-definitions-base.d.ts +5 -3
  19. package/dist/enums/xrpl-definitions-base.js +26 -6
  20. package/dist/enums/xrpl-definitions-base.js.map +1 -1
  21. package/dist/enums/xrpl-definitions.d.ts +2 -1
  22. package/dist/enums/xrpl-definitions.js +2 -1
  23. package/dist/enums/xrpl-definitions.js.map +1 -1
  24. package/dist/hash-prefixes.d.ts +1 -2
  25. package/dist/hash-prefixes.js +8 -6
  26. package/dist/hash-prefixes.js.map +1 -1
  27. package/dist/hashes.d.ts +6 -7
  28. package/dist/hashes.js +6 -7
  29. package/dist/hashes.js.map +1 -1
  30. package/dist/index.d.ts +16 -11
  31. package/dist/index.js +53 -58
  32. package/dist/index.js.map +1 -1
  33. package/dist/ledger-hashes.d.ts +1 -2
  34. package/dist/ledger-hashes.js +11 -30
  35. package/dist/ledger-hashes.js.map +1 -1
  36. package/dist/quality.d.ts +3 -4
  37. package/dist/quality.js +10 -8
  38. package/dist/quality.js.map +1 -1
  39. package/dist/serdes/binary-parser.d.ts +2 -3
  40. package/dist/serdes/binary-parser.js +16 -32
  41. package/dist/serdes/binary-parser.js.map +1 -1
  42. package/dist/serdes/binary-serializer.d.ts +6 -7
  43. package/dist/serdes/binary-serializer.js +12 -35
  44. package/dist/serdes/binary-serializer.js.map +1 -1
  45. package/dist/shamap.d.ts +4 -5
  46. package/dist/shamap.js +5 -5
  47. package/dist/shamap.js.map +1 -1
  48. package/dist/src/binary.d.ts +106 -0
  49. package/dist/src/binary.js +154 -0
  50. package/dist/src/binary.js.map +1 -0
  51. package/dist/src/coretypes.d.ts +9 -0
  52. package/dist/src/coretypes.js +48 -0
  53. package/dist/src/coretypes.js.map +1 -0
  54. package/dist/src/enums/bytes.d.ts +25 -0
  55. package/dist/src/enums/bytes.js +63 -0
  56. package/dist/src/enums/bytes.js.map +1 -0
  57. package/dist/src/enums/constants.d.ts +5 -0
  58. package/dist/src/enums/constants.js +9 -0
  59. package/dist/src/enums/constants.js.map +1 -0
  60. package/dist/src/enums/definitions.json +3385 -0
  61. package/dist/src/enums/field.d.ts +28 -0
  62. package/dist/src/enums/field.js +58 -0
  63. package/dist/src/enums/field.js.map +1 -0
  64. package/dist/src/enums/index.d.ts +12 -0
  65. package/dist/src/enums/index.js +31 -0
  66. package/dist/src/enums/index.js.map +1 -0
  67. package/dist/src/enums/utils-renumber.d.ts +101 -0
  68. package/dist/src/enums/utils-renumber.js +127 -0
  69. package/dist/src/enums/utils-renumber.js.map +1 -0
  70. package/dist/src/enums/xrpl-definitions-base.d.ts +47 -0
  71. package/dist/src/enums/xrpl-definitions-base.js +83 -0
  72. package/dist/src/enums/xrpl-definitions-base.js.map +1 -0
  73. package/dist/src/enums/xrpl-definitions.d.ts +22 -0
  74. package/dist/src/enums/xrpl-definitions.js +30 -0
  75. package/dist/src/enums/xrpl-definitions.js.map +1 -0
  76. package/dist/src/hash-prefixes.d.ts +5 -0
  77. package/dist/src/hash-prefixes.js +43 -0
  78. package/dist/src/hash-prefixes.js.map +1 -0
  79. package/dist/src/hashes.d.ts +50 -0
  80. package/dist/src/hashes.js +76 -0
  81. package/dist/src/hashes.js.map +1 -0
  82. package/dist/src/index.d.ts +69 -0
  83. package/dist/src/index.js +134 -0
  84. package/dist/src/index.js.map +1 -0
  85. package/dist/src/ledger-hashes.d.ts +48 -0
  86. package/dist/src/ledger-hashes.js +141 -0
  87. package/dist/src/ledger-hashes.js.map +1 -0
  88. package/dist/src/quality.d.ts +21 -0
  89. package/dist/src/quality.js +42 -0
  90. package/dist/src/quality.js.map +1 -0
  91. package/dist/src/serdes/binary-parser.d.ts +100 -0
  92. package/dist/src/serdes/binary-parser.js +194 -0
  93. package/dist/src/serdes/binary-parser.js.map +1 -0
  94. package/dist/src/serdes/binary-serializer.d.ts +81 -0
  95. package/dist/src/serdes/binary-serializer.js +149 -0
  96. package/dist/src/serdes/binary-serializer.js.map +1 -0
  97. package/dist/src/shamap.d.ts +102 -0
  98. package/dist/src/shamap.js +172 -0
  99. package/dist/src/shamap.js.map +1 -0
  100. package/dist/src/types/account-id.d.ts +35 -0
  101. package/dist/src/types/account-id.js +69 -0
  102. package/dist/src/types/account-id.js.map +1 -0
  103. package/dist/src/types/amount.d.ts +91 -0
  104. package/dist/src/types/amount.js +289 -0
  105. package/dist/src/types/amount.js.map +1 -0
  106. package/dist/src/types/blob.d.ts +24 -0
  107. package/dist/src/types/blob.js +43 -0
  108. package/dist/src/types/blob.js.map +1 -0
  109. package/dist/src/types/currency.d.ts +28 -0
  110. package/dist/src/types/currency.js +127 -0
  111. package/dist/src/types/currency.js.map +1 -0
  112. package/dist/src/types/hash-128.d.ts +16 -0
  113. package/dist/src/types/hash-128.js +32 -0
  114. package/dist/src/types/hash-128.js.map +1 -0
  115. package/dist/src/types/hash-160.d.ts +10 -0
  116. package/dist/src/types/hash-160.js +19 -0
  117. package/dist/src/types/hash-160.js.map +1 -0
  118. package/dist/src/types/hash-192.d.ts +10 -0
  119. package/dist/src/types/hash-192.js +19 -0
  120. package/dist/src/types/hash-192.js.map +1 -0
  121. package/dist/src/types/hash-256.d.ts +10 -0
  122. package/dist/src/types/hash-256.js +16 -0
  123. package/dist/src/types/hash-256.js.map +1 -0
  124. package/dist/src/types/hash.d.ts +40 -0
  125. package/dist/src/types/hash.js +76 -0
  126. package/dist/src/types/hash.js.map +1 -0
  127. package/dist/src/types/index.d.ts +19 -0
  128. package/dist/src/types/index.js +66 -0
  129. package/dist/src/types/index.js.map +1 -0
  130. package/dist/src/types/issue.d.ts +48 -0
  131. package/dist/src/types/issue.js +104 -0
  132. package/dist/src/types/issue.js.map +1 -0
  133. package/dist/src/types/path-set.d.ts +36 -0
  134. package/dist/src/types/path-set.js +233 -0
  135. package/dist/src/types/path-set.js.map +1 -0
  136. package/dist/src/types/serialized-type.d.ts +70 -0
  137. package/dist/src/types/serialized-type.js +105 -0
  138. package/dist/src/types/serialized-type.js.map +1 -0
  139. package/dist/src/types/st-array.d.ts +31 -0
  140. package/dist/src/types/st-array.js +86 -0
  141. package/dist/src/types/st-array.js.map +1 -0
  142. package/dist/src/types/st-number.d.ts +54 -0
  143. package/dist/src/types/st-number.js +208 -0
  144. package/dist/src/types/st-number.js.map +1 -0
  145. package/dist/src/types/st-object.d.ts +32 -0
  146. package/dist/src/types/st-object.js +173 -0
  147. package/dist/src/types/st-object.js.map +1 -0
  148. package/dist/src/types/uint-16.d.ts +24 -0
  149. package/dist/src/types/uint-16.js +45 -0
  150. package/dist/src/types/uint-16.js.map +1 -0
  151. package/dist/src/types/uint-32.d.ts +24 -0
  152. package/dist/src/types/uint-32.js +50 -0
  153. package/dist/src/types/uint-32.js.map +1 -0
  154. package/dist/src/types/uint-64.d.ts +38 -0
  155. package/dist/src/types/uint-64.js +107 -0
  156. package/dist/src/types/uint-64.js.map +1 -0
  157. package/dist/src/types/uint-8.d.ts +24 -0
  158. package/dist/src/types/uint-8.js +46 -0
  159. package/dist/src/types/uint-8.js.map +1 -0
  160. package/dist/src/types/uint.d.ts +29 -0
  161. package/dist/src/types/uint.js +47 -0
  162. package/dist/src/types/uint.js.map +1 -0
  163. package/dist/src/types/vector-256.d.ts +30 -0
  164. package/dist/src/types/vector-256.js +73 -0
  165. package/dist/src/types/vector-256.js.map +1 -0
  166. package/dist/src/types/xchain-bridge.d.ts +44 -0
  167. package/dist/src/types/xchain-bridge.js +102 -0
  168. package/dist/src/types/xchain-bridge.js.map +1 -0
  169. package/dist/src/utils.d.ts +79 -0
  170. package/dist/src/utils.js +181 -0
  171. package/dist/src/utils.js.map +1 -0
  172. package/dist/tsconfig.tsbuildinfo +1 -0
  173. package/dist/types/account-id.d.ts +1 -2
  174. package/dist/types/account-id.js +4 -6
  175. package/dist/types/account-id.js.map +1 -1
  176. package/dist/types/amount.d.ts +31 -8
  177. package/dist/types/amount.js +125 -43
  178. package/dist/types/amount.js.map +1 -1
  179. package/dist/types/blob.d.ts +1 -2
  180. package/dist/types/blob.js +5 -2
  181. package/dist/types/blob.js.map +1 -1
  182. package/dist/types/currency.d.ts +1 -2
  183. package/dist/types/currency.js +13 -13
  184. package/dist/types/currency.js.map +1 -1
  185. package/dist/types/hash-128.d.ts +1 -2
  186. package/dist/types/hash-128.js +3 -3
  187. package/dist/types/hash-128.js.map +1 -1
  188. package/dist/types/hash-160.d.ts +1 -2
  189. package/dist/types/hash-160.js +1 -2
  190. package/dist/types/hash-160.js.map +1 -1
  191. package/dist/types/hash-192.d.ts +10 -0
  192. package/dist/types/hash-192.js +19 -0
  193. package/dist/types/hash-192.js.map +1 -0
  194. package/dist/types/hash-256.d.ts +1 -2
  195. package/dist/types/hash-256.js +1 -2
  196. package/dist/types/hash-256.js.map +1 -1
  197. package/dist/types/hash.d.ts +2 -3
  198. package/dist/types/hash.js +8 -4
  199. package/dist/types/hash.js.map +1 -1
  200. package/dist/types/index.d.ts +2 -1
  201. package/dist/types/index.js +11 -2
  202. package/dist/types/index.js.map +1 -1
  203. package/dist/types/issue.d.ts +48 -0
  204. package/dist/types/issue.js +104 -0
  205. package/dist/types/issue.js.map +1 -0
  206. package/dist/types/path-set.js +12 -12
  207. package/dist/types/path-set.js.map +1 -1
  208. package/dist/types/serialized-type.d.ts +23 -16
  209. package/dist/types/serialized-type.js +15 -7
  210. package/dist/types/serialized-type.js.map +1 -1
  211. package/dist/types/st-array.d.ts +5 -2
  212. package/dist/types/st-array.js +17 -11
  213. package/dist/types/st-array.js.map +1 -1
  214. package/dist/types/st-number.d.ts +54 -0
  215. package/dist/types/st-number.js +208 -0
  216. package/dist/types/st-number.js.map +1 -0
  217. package/dist/types/st-object.js +32 -8
  218. package/dist/types/st-object.js.map +1 -1
  219. package/dist/types/uint-16.d.ts +1 -2
  220. package/dist/types/uint-16.js +6 -5
  221. package/dist/types/uint-16.js.map +1 -1
  222. package/dist/types/uint-32.d.ts +1 -2
  223. package/dist/types/uint-32.js +7 -6
  224. package/dist/types/uint-32.js.map +1 -1
  225. package/dist/types/uint-64.d.ts +6 -7
  226. package/dist/types/uint-64.js +44 -24
  227. package/dist/types/uint-64.js.map +1 -1
  228. package/dist/types/uint-8.d.ts +1 -2
  229. package/dist/types/uint-8.js +7 -5
  230. package/dist/types/uint-8.js.map +1 -1
  231. package/dist/types/uint.d.ts +5 -6
  232. package/dist/types/uint.js +5 -0
  233. package/dist/types/uint.js.map +1 -1
  234. package/dist/types/vector-256.d.ts +1 -2
  235. package/dist/types/vector-256.js +2 -4
  236. package/dist/types/vector-256.js.map +1 -1
  237. package/dist/types/xchain-bridge.d.ts +44 -0
  238. package/dist/types/xchain-bridge.js +102 -0
  239. package/dist/types/xchain-bridge.js.map +1 -0
  240. package/dist/utils.d.ts +79 -0
  241. package/dist/utils.js +181 -0
  242. package/dist/utils.js.map +1 -0
  243. package/package.json +21 -17
  244. package/src/README.md +5 -0
  245. package/src/binary.ts +235 -0
  246. package/src/coretypes.ts +31 -0
  247. package/src/enums/README.md +144 -0
  248. package/src/enums/bytes.ts +74 -0
  249. package/src/enums/constants.ts +5 -0
  250. package/src/enums/definitions.json +3390 -0
  251. package/src/enums/field.ts +84 -0
  252. package/src/enums/index.ts +34 -0
  253. package/src/enums/utils-renumber.ts +134 -0
  254. package/src/enums/xrpl-definitions-base.ts +150 -0
  255. package/src/enums/xrpl-definitions.ts +33 -0
  256. package/src/hash-prefixes.ts +42 -0
  257. package/src/hashes.ts +75 -0
  258. package/src/index.ts +166 -0
  259. package/src/ledger-hashes.ts +191 -0
  260. package/src/quality.ts +38 -0
  261. package/src/serdes/binary-parser.ts +228 -0
  262. package/src/serdes/binary-serializer.ts +166 -0
  263. package/src/shamap.ts +186 -0
  264. package/src/types/account-id.ts +86 -0
  265. package/src/types/amount.ts +362 -0
  266. package/src/types/blob.ts +46 -0
  267. package/src/types/currency.ts +140 -0
  268. package/src/types/hash-128.ts +33 -0
  269. package/src/types/hash-160.ts +19 -0
  270. package/src/types/hash-192.ts +19 -0
  271. package/src/types/hash-256.ts +15 -0
  272. package/src/types/hash.ts +86 -0
  273. package/src/types/index.ts +68 -0
  274. package/src/types/issue.ts +136 -0
  275. package/src/types/path-set.ts +290 -0
  276. package/src/types/serialized-type.ts +122 -0
  277. package/src/types/st-array.ts +113 -0
  278. package/src/types/st-number.ts +233 -0
  279. package/src/types/st-object.ts +215 -0
  280. package/src/types/uint-16.ts +53 -0
  281. package/src/types/uint-32.ts +59 -0
  282. package/src/types/uint-64.ts +135 -0
  283. package/src/types/uint-8.ts +52 -0
  284. package/src/types/uint.ts +60 -0
  285. package/src/types/vector-256.ts +79 -0
  286. package/src/types/xchain-bridge.ts +128 -0
  287. package/src/utils.ts +220 -0
  288. package/test/amount.test.js +0 -43
  289. package/test/binary-json.test.js +0 -45
  290. package/test/binary-parser.test.js +0 -396
  291. package/test/binary-serializer.test.js +0 -319
  292. package/test/definitions.test.js +0 -100
  293. package/test/fixtures/account-tx-transactions.db +0 -0
  294. package/test/fixtures/codec-fixtures.json +0 -4466
  295. package/test/fixtures/data-driven-tests.json +0 -2919
  296. package/test/fixtures/delivermin-tx-binary.json +0 -1
  297. package/test/fixtures/delivermin-tx.json +0 -98
  298. package/test/fixtures/deposit-preauth-tx-binary.json +0 -1
  299. package/test/fixtures/deposit-preauth-tx-meta-binary.json +0 -1
  300. package/test/fixtures/deposit-preauth-tx.json +0 -58
  301. package/test/fixtures/escrow-cancel-binary.json +0 -1
  302. package/test/fixtures/escrow-cancel-tx.json +0 -6
  303. package/test/fixtures/escrow-create-binary.json +0 -1
  304. package/test/fixtures/escrow-create-tx.json +0 -10
  305. package/test/fixtures/escrow-finish-binary.json +0 -1
  306. package/test/fixtures/escrow-finish-meta-binary.json +0 -1
  307. package/test/fixtures/escrow-finish-tx.json +0 -95
  308. package/test/fixtures/ledger-full-38129.json +0 -1
  309. package/test/fixtures/ledger-full-40000.json +0 -1
  310. package/test/fixtures/negative-unl.json +0 -12
  311. package/test/fixtures/nf-token.json +0 -547
  312. package/test/fixtures/payment-channel-claim-binary.json +0 -1
  313. package/test/fixtures/payment-channel-claim-tx.json +0 -8
  314. package/test/fixtures/payment-channel-create-binary.json +0 -1
  315. package/test/fixtures/payment-channel-create-tx.json +0 -11
  316. package/test/fixtures/payment-channel-fund-binary.json +0 -1
  317. package/test/fixtures/payment-channel-fund-tx.json +0 -7
  318. package/test/fixtures/remit-binary.json +0 -1
  319. package/test/fixtures/remit-tx.json +0 -39
  320. package/test/fixtures/signerlistset-tx-binary.json +0 -1
  321. package/test/fixtures/signerlistset-tx-meta-binary.json +0 -1
  322. package/test/fixtures/signerlistset-tx.json +0 -94
  323. package/test/fixtures/ticket-create-binary.json +0 -1
  324. package/test/fixtures/ticket-create-tx.json +0 -7
  325. package/test/fixtures/unl-report-binary.json +0 -1
  326. package/test/fixtures/unl-report-meta-binary.json +0 -1
  327. package/test/fixtures/unl-report.json +0 -89
  328. package/test/fixtures/x-codec-fixtures.json +0 -188
  329. package/test/hash.test.js +0 -135
  330. package/test/ledger.test.js +0 -29
  331. package/test/lower-case-hex.test.js +0 -46
  332. package/test/pseudo-transaction.test.js +0 -38
  333. package/test/quality.test.js +0 -15
  334. package/test/shamap.test.js +0 -89
  335. package/test/signing-data-encoding.test.js +0 -213
  336. package/test/tx-encode-decode.test.js +0 -119
  337. package/test/types.test.js +0 -34
  338. package/test/uint.test.js +0 -148
  339. package/test/utils.js +0 -30
  340. package/test/x-address.test.js +0 -181
@@ -0,0 +1,113 @@
1
+ import { DEFAULT_DEFINITIONS, XrplDefinitionsBase } from '../enums'
2
+ import { SerializedType, JsonObject } from './serialized-type'
3
+ import { STObject } from './st-object'
4
+ import { BinaryParser } from '../serdes/binary-parser'
5
+ import { concat } from '@transia/isomorphic/utils'
6
+
7
+ const ARRAY_END_MARKER = Uint8Array.from([0xf1])
8
+ const ARRAY_END_MARKER_NAME = 'ArrayEndMarker'
9
+
10
+ const OBJECT_END_MARKER = Uint8Array.from([0xe1])
11
+
12
+ /**
13
+ * TypeGuard for Array<JsonObject>
14
+ */
15
+ function isObjects(args): args is Array<JsonObject> {
16
+ return (
17
+ Array.isArray(args) &&
18
+ args.every(
19
+ (arg) =>
20
+ typeof arg === 'object' &&
21
+ Object.keys(arg).length === 1 &&
22
+ typeof Object.values(arg)[0] === 'object',
23
+ )
24
+ )
25
+ }
26
+
27
+ /**
28
+ * Class for serializing and deserializing Arrays of Objects
29
+ */
30
+ class STArray extends SerializedType {
31
+ /**
32
+ * Construct an STArray from a BinaryParser
33
+ *
34
+ * @param parser BinaryParser to parse an STArray from
35
+ * @returns An STArray Object
36
+ */
37
+ static fromParser(parser: BinaryParser): STArray {
38
+ const bytes: Array<Uint8Array> = []
39
+
40
+ while (!parser.end()) {
41
+ const field = parser.readField()
42
+ if (field.name === ARRAY_END_MARKER_NAME) {
43
+ break
44
+ }
45
+
46
+ bytes.push(
47
+ field.header,
48
+ parser.readFieldValue(field).toBytes(),
49
+ OBJECT_END_MARKER,
50
+ )
51
+ }
52
+
53
+ bytes.push(ARRAY_END_MARKER)
54
+ return new STArray(concat(bytes))
55
+ }
56
+
57
+ /**
58
+ * Construct an STArray from an Array of JSON Objects
59
+ *
60
+ * @param value STArray or Array of Objects to parse into an STArray
61
+ * @param definitions optional, types and values to use to encode/decode a transaction
62
+ * @returns An STArray object
63
+ */
64
+ static from<T extends STArray | Array<JsonObject>>(
65
+ value: T,
66
+ definitions: XrplDefinitionsBase = DEFAULT_DEFINITIONS,
67
+ ): STArray {
68
+ if (value instanceof STArray) {
69
+ return value
70
+ }
71
+
72
+ if (isObjects(value)) {
73
+ const bytes: Array<Uint8Array> = []
74
+ value.forEach((obj) => {
75
+ bytes.push(STObject.from(obj, undefined, definitions).toBytes())
76
+ })
77
+
78
+ bytes.push(ARRAY_END_MARKER)
79
+ return new STArray(concat(bytes))
80
+ }
81
+
82
+ throw new Error('Cannot construct STArray from value given')
83
+ }
84
+
85
+ /**
86
+ * Return the JSON representation of this.bytes
87
+ *
88
+ * @param definitions optional, types and values to use to encode/decode a transaction
89
+ * @returns An Array of JSON objects
90
+ */
91
+ toJSON(
92
+ definitions: XrplDefinitionsBase = DEFAULT_DEFINITIONS,
93
+ ): Array<JsonObject> {
94
+ const result: Array<JsonObject> = []
95
+
96
+ const arrayParser = new BinaryParser(this.toString(), definitions)
97
+
98
+ while (!arrayParser.end()) {
99
+ const field = arrayParser.readField()
100
+ if (field.name === ARRAY_END_MARKER_NAME) {
101
+ break
102
+ }
103
+
104
+ const outer = {}
105
+ outer[field.name] = STObject.fromParser(arrayParser).toJSON(definitions)
106
+ result.push(outer)
107
+ }
108
+
109
+ return result
110
+ }
111
+ }
112
+
113
+ export { STArray }
@@ -0,0 +1,233 @@
1
+ import { BinaryParser } from '../serdes/binary-parser'
2
+ import { SerializedType } from './serialized-type'
3
+ import { writeInt32BE, writeInt64BE, readInt32BE, readInt64BE } from '../utils'
4
+
5
+ /**
6
+ * Constants for mantissa and exponent normalization per XRPL Number spec.
7
+ * These define allowed magnitude for mantissa and exponent after normalization.
8
+ */
9
+ const MIN_MANTISSA = BigInt('1000000000000000')
10
+ const MAX_MANTISSA = BigInt('9999999999999999')
11
+ const MIN_EXPONENT = -32768
12
+ const MAX_EXPONENT = 32768
13
+ const DEFAULT_VALUE_EXPONENT = -2147483648
14
+
15
+ /**
16
+ * Extract mantissa, exponent, and sign from a number string.
17
+ *
18
+ * @param val - The string representing the number (may be integer, decimal, or scientific notation).
19
+ * @returns Object containing mantissa (BigInt), exponent (number), and isNegative (boolean).
20
+ * @throws Error if the string cannot be parsed as a valid number.
21
+ *
22
+ * Examples:
23
+ * '123' -> { mantissa: 123n, exponent: 0, isNegative: false }
24
+ * '-00123.45' -> { mantissa: -12345n, exponent: -2, isNegative: true }
25
+ * '+7.1e2' -> { mantissa: 71n, exponent: -1 + 2 = 1, isNegative: false }
26
+ */
27
+ function extractNumberPartsFromString(val: string): {
28
+ mantissa: bigint
29
+ exponent: number
30
+ isNegative: boolean
31
+ } {
32
+ /**
33
+ * Regex for parsing decimal/float/scientific number strings with optional sign, integer, decimal, and exponent parts.
34
+ *
35
+ * Pattern: /^([-+]?)([0-9]+)(?:\.([0-9]+))?(?:[eE]([+-]?[0-9]+))?$/
36
+ *
37
+ * Breakdown:
38
+ * 1. ([-+]?) - Optional '+' or '-' sign at the start.
39
+ * 2. ([0-9]+) - Integer part: one or more digits (leading zeros allowed).
40
+ * 3. (?:\.([0-9]+))? - Optional decimal point followed by one or more digits.
41
+ * 4. (?:[eE]([+-]?[0-9]+))? - Optional exponent, starting with 'e' or 'E', optional sign, and digits.
42
+ *
43
+ * Notes:
44
+ * - Leading zeros are accepted and normalized by code after parsing.
45
+ * - Empty decimal ('123.') and missing integer ('.456') are NOT matched—must be fully specified.
46
+ */
47
+ const regex = /^([-+]?)([0-9]+)(?:\.([0-9]+))?(?:[eE]([+-]?[0-9]+))?$/
48
+ const match = regex.exec(val)
49
+ if (!match) throw new Error(`Unable to parse number from string: ${val}`)
50
+
51
+ const [, sign, intPart, fracPart, expPart] = match
52
+ // Remove leading zeros (unless the entire intPart is zeros)
53
+ const cleanIntPart = intPart.replace(/^0+(?=\d)/, '') || '0'
54
+
55
+ let mantissaStr = cleanIntPart
56
+ let exponent = 0
57
+
58
+ if (fracPart) {
59
+ mantissaStr += fracPart
60
+ exponent -= fracPart.length
61
+ }
62
+ if (expPart) exponent += parseInt(expPart, 10)
63
+
64
+ let mantissa = BigInt(mantissaStr)
65
+ if (sign === '-') mantissa = -mantissa
66
+ const isNegative = mantissa < BigInt(0)
67
+
68
+ return { mantissa, exponent, isNegative }
69
+ }
70
+
71
+ /**
72
+ * Normalize the mantissa and exponent to XRPL constraints.
73
+ *
74
+ * Ensures that after normalization, the mantissa is between MIN_MANTISSA and MAX_MANTISSA (unless zero).
75
+ * Adjusts the exponent as needed by shifting the mantissa left/right (multiplying/dividing by 10).
76
+ *
77
+ * @param mantissa - The unnormalized mantissa (BigInt).
78
+ * @param exponent - The unnormalized exponent (number).
79
+ * @returns An object with normalized mantissa and exponent.
80
+ * @throws Error if the number cannot be normalized within allowed exponent range.
81
+ */
82
+ function normalize(
83
+ mantissa: bigint,
84
+ exponent: number,
85
+ ): { mantissa: bigint; exponent: number } {
86
+ let m = mantissa < BigInt(0) ? -mantissa : mantissa
87
+ const isNegative = mantissa < BigInt(0)
88
+
89
+ while (m !== BigInt(0) && m < MIN_MANTISSA && exponent > MIN_EXPONENT) {
90
+ exponent -= 1
91
+ m *= BigInt(10)
92
+ }
93
+ while (m > MAX_MANTISSA) {
94
+ if (exponent >= MAX_EXPONENT)
95
+ throw new Error('Mantissa and exponent are too large')
96
+ exponent += 1
97
+ m /= BigInt(10)
98
+ }
99
+ if (isNegative) m = -m
100
+ return { mantissa: m, exponent }
101
+ }
102
+
103
+ /**
104
+ * STNumber: Encodes XRPL's "Number" type.
105
+ *
106
+ * - Always encoded as 12 bytes: 8-byte signed mantissa, 4-byte signed exponent, both big-endian.
107
+ * - Can only be constructed from a valid number string or another STNumber instance.
108
+ *
109
+ * Usage:
110
+ * STNumber.from("1.2345e5")
111
+ * STNumber.from("-123")
112
+ * STNumber.fromParser(parser)
113
+ */
114
+ export class STNumber extends SerializedType {
115
+ /** 12 zero bytes, represents canonical zero. */
116
+ static defaultBytes = new Uint8Array(12)
117
+
118
+ /**
119
+ * Construct a STNumber from 12 bytes (8 for mantissa, 4 for exponent).
120
+ * @param bytes - 12-byte Uint8Array
121
+ * @throws Error if input is not a Uint8Array of length 12.
122
+ */
123
+ constructor(bytes?: Uint8Array) {
124
+ const used = bytes ?? STNumber.defaultBytes
125
+ if (!(used instanceof Uint8Array) || used.length !== 12) {
126
+ throw new Error(
127
+ `STNumber must be constructed from a 12-byte Uint8Array, got ${used?.length}`,
128
+ )
129
+ }
130
+ super(used)
131
+ }
132
+
133
+ /**
134
+ * Construct from a number string (or another STNumber).
135
+ *
136
+ * @param value - A string, or STNumber instance.
137
+ * @returns STNumber instance.
138
+ * @throws Error if not a string or STNumber.
139
+ */
140
+ static from(value: unknown): STNumber {
141
+ if (value instanceof STNumber) {
142
+ return value
143
+ }
144
+ if (typeof value === 'string') {
145
+ return STNumber.fromValue(value)
146
+ }
147
+ throw new Error(
148
+ 'STNumber.from: Only string or STNumber instance is supported',
149
+ )
150
+ }
151
+
152
+ /**
153
+ * Construct from a number string (integer, decimal, or scientific notation).
154
+ * Handles normalization to XRPL Number constraints.
155
+ *
156
+ * @param val - The number as a string (e.g. '1.23', '-123e5').
157
+ * @returns STNumber instance
158
+ * @throws Error if val is not a valid number string.
159
+ */
160
+ static fromValue(val: string): STNumber {
161
+ const { mantissa, exponent, isNegative } = extractNumberPartsFromString(val)
162
+ let normalizedMantissa: bigint
163
+ let normalizedExponent: number
164
+
165
+ if (mantissa === BigInt(0) && exponent === 0 && !isNegative) {
166
+ normalizedMantissa = BigInt(0)
167
+ normalizedExponent = DEFAULT_VALUE_EXPONENT
168
+ } else {
169
+ ;({ mantissa: normalizedMantissa, exponent: normalizedExponent } =
170
+ normalize(mantissa, exponent))
171
+ }
172
+
173
+ const bytes = new Uint8Array(12)
174
+ writeInt64BE(bytes, normalizedMantissa, 0)
175
+ writeInt32BE(bytes, normalizedExponent, 8)
176
+ return new STNumber(bytes)
177
+ }
178
+
179
+ /**
180
+ * Read a STNumber from a BinaryParser stream (12 bytes).
181
+ * @param parser - BinaryParser positioned at the start of a number
182
+ * @returns STNumber instance
183
+ */
184
+ static fromParser(parser: BinaryParser): STNumber {
185
+ return new STNumber(parser.read(12))
186
+ }
187
+
188
+ /**
189
+ * Convert this STNumber to a normalized string representation.
190
+ * The output is decimal or scientific notation, depending on exponent range.
191
+ * Follows XRPL convention: zero is "0", other values are normalized to a canonical string.
192
+ *
193
+ * @returns String representation of the value
194
+ */
195
+ // eslint-disable-next-line complexity -- required
196
+ toJSON(): string {
197
+ const b = this.bytes
198
+ if (!b || b.length !== 12)
199
+ throw new Error('STNumber internal bytes not set or wrong length')
200
+
201
+ // Signed 64-bit mantissa
202
+ const mantissa = readInt64BE(b, 0)
203
+ // Signed 32-bit exponent
204
+ const exponent = readInt32BE(b, 8)
205
+
206
+ // Special zero: XRPL encodes canonical zero as mantissa=0, exponent=DEFAULT_VALUE_EXPONENT.
207
+ if (mantissa === BigInt(0) && exponent === DEFAULT_VALUE_EXPONENT) {
208
+ return '0'
209
+ }
210
+ if (exponent === 0) return mantissa.toString()
211
+
212
+ // Use scientific notation for small/large exponents, decimal otherwise
213
+ if (exponent < -25 || exponent > -5) {
214
+ return `${mantissa}e${exponent}`
215
+ }
216
+
217
+ // Decimal rendering for -25 <= exp <= -5
218
+ const isNegative = mantissa < BigInt(0)
219
+ const mantissaAbs = mantissa < BigInt(0) ? -mantissa : mantissa
220
+
221
+ const padPrefix = 27
222
+ const padSuffix = 23
223
+ const mantissaStr = mantissaAbs.toString()
224
+ const rawValue = '0'.repeat(padPrefix) + mantissaStr + '0'.repeat(padSuffix)
225
+ const OFFSET = exponent + 43
226
+ const integerPart = rawValue.slice(0, OFFSET).replace(/^0+/, '') || '0'
227
+ const fractionPart = rawValue.slice(OFFSET).replace(/0+$/, '')
228
+
229
+ return `${isNegative ? '-' : ''}${integerPart}${
230
+ fractionPart ? '.' + fractionPart : ''
231
+ }`
232
+ }
233
+ }
@@ -0,0 +1,215 @@
1
+ import {
2
+ DEFAULT_DEFINITIONS,
3
+ FieldInstance,
4
+ Bytes,
5
+ XrplDefinitionsBase,
6
+ } from '../enums'
7
+ import { SerializedType, JsonObject } from './serialized-type'
8
+ import {
9
+ xAddressToClassicAddress,
10
+ isValidXAddress,
11
+ } from '@transia/ripple-address-codec'
12
+ import { BinaryParser } from '../serdes/binary-parser'
13
+ import { BinarySerializer, BytesList } from '../serdes/binary-serializer'
14
+
15
+ import { STArray } from './st-array'
16
+ import { UInt64 } from './uint-64'
17
+
18
+ const OBJECT_END_MARKER_BYTE = Uint8Array.from([0xe1])
19
+ const OBJECT_END_MARKER = 'ObjectEndMarker'
20
+ const ST_OBJECT = 'STObject'
21
+ const DESTINATION = 'Destination'
22
+ const ACCOUNT = 'Account'
23
+ const SOURCE_TAG = 'SourceTag'
24
+ const DEST_TAG = 'DestinationTag'
25
+
26
+ /**
27
+ * Break down an X-Address into an account and a tag
28
+ *
29
+ * @param field Name of field
30
+ * @param xAddress X-Address corresponding to the field
31
+ */
32
+ function handleXAddress(field: string, xAddress: string): JsonObject {
33
+ const decoded = xAddressToClassicAddress(xAddress)
34
+
35
+ let tagName
36
+ if (field === DESTINATION) tagName = DEST_TAG
37
+ else if (field === ACCOUNT) tagName = SOURCE_TAG
38
+ else if (decoded.tag !== false)
39
+ throw new Error(`${field} cannot have an associated tag`)
40
+
41
+ return decoded.tag !== false
42
+ ? { [field]: decoded.classicAddress, [tagName]: decoded.tag }
43
+ : { [field]: decoded.classicAddress }
44
+ }
45
+
46
+ /**
47
+ * Validate that two objects don't both have the same tag fields
48
+ *
49
+ * @param obj1 First object to check for tags
50
+ * @param obj2 Second object to check for tags
51
+ * @throws When both objects have SourceTag or DestinationTag
52
+ */
53
+ function checkForDuplicateTags(obj1: JsonObject, obj2: JsonObject): void {
54
+ if (!(obj1[SOURCE_TAG] === undefined || obj2[SOURCE_TAG] === undefined))
55
+ throw new Error('Cannot have Account X-Address and SourceTag')
56
+ if (!(obj1[DEST_TAG] === undefined || obj2[DEST_TAG] === undefined))
57
+ throw new Error('Cannot have Destination X-Address and DestinationTag')
58
+ }
59
+
60
+ /**
61
+ * Class for Serializing/Deserializing objects
62
+ */
63
+ class STObject extends SerializedType {
64
+ /**
65
+ * Construct a STObject from a BinaryParser
66
+ *
67
+ * @param parser BinaryParser to read STObject from
68
+ * @returns A STObject object
69
+ */
70
+ static fromParser(parser: BinaryParser): STObject {
71
+ const list: BytesList = new BytesList()
72
+ const bytes: BinarySerializer = new BinarySerializer(list)
73
+
74
+ while (!parser.end()) {
75
+ const field = parser.readField()
76
+ if (field.name === OBJECT_END_MARKER) {
77
+ break
78
+ }
79
+
80
+ const associatedValue = parser.readFieldValue(field)
81
+
82
+ bytes.writeFieldAndValue(field, associatedValue)
83
+ if (field.type.name === ST_OBJECT) {
84
+ bytes.put(OBJECT_END_MARKER_BYTE)
85
+ }
86
+ }
87
+
88
+ return new STObject(list.toBytes())
89
+ }
90
+
91
+ /**
92
+ * Construct a STObject from a JSON object
93
+ *
94
+ * @param value An object to include
95
+ * @param filter optional, denote which field to include in serialized object
96
+ * @param definitions optional, types and values to use to encode/decode a transaction
97
+ * @returns a STObject object
98
+ */
99
+ static from<T extends STObject | JsonObject>(
100
+ value: T,
101
+ filter?: (...any) => boolean,
102
+ definitions: XrplDefinitionsBase = DEFAULT_DEFINITIONS,
103
+ ): STObject {
104
+ if (value instanceof STObject) {
105
+ return value
106
+ }
107
+
108
+ const list: BytesList = new BytesList()
109
+ const bytes: BinarySerializer = new BinarySerializer(list)
110
+
111
+ let isUnlModify = false
112
+
113
+ const xAddressDecoded = Object.entries(value).reduce((acc, [key, val]) => {
114
+ let handled: JsonObject | undefined = undefined
115
+ if (val && isValidXAddress(val.toString())) {
116
+ handled = handleXAddress(key, val.toString())
117
+ checkForDuplicateTags(handled, value)
118
+ }
119
+ return Object.assign(acc, handled ?? { [key]: val })
120
+ }, {})
121
+
122
+ function isValidFieldInstance(
123
+ f: FieldInstance | undefined,
124
+ ): f is FieldInstance {
125
+ return (
126
+ f !== undefined &&
127
+ xAddressDecoded[f.name] !== undefined &&
128
+ f.isSerialized
129
+ )
130
+ }
131
+
132
+ let sorted = Object.keys(xAddressDecoded)
133
+ .map((f: string): FieldInstance | undefined => {
134
+ if (!(f in definitions.field)) {
135
+ if (f[0] === f[0].toLowerCase()) return undefined
136
+ throw new Error(`Field ${f} is not defined in the definitions`)
137
+ }
138
+ return definitions.field[f] as FieldInstance
139
+ })
140
+ .filter(isValidFieldInstance)
141
+ .sort((a, b) => {
142
+ return a.ordinal - b.ordinal
143
+ })
144
+
145
+ if (filter !== undefined) {
146
+ sorted = sorted.filter(filter)
147
+ }
148
+
149
+ sorted.forEach((field) => {
150
+ const associatedValue =
151
+ field.type.name === ST_OBJECT
152
+ ? this.from(xAddressDecoded[field.name], undefined, definitions)
153
+ : field.type.name === 'STArray'
154
+ ? STArray.from(xAddressDecoded[field.name], definitions)
155
+ : field.type.name === 'UInt64'
156
+ ? UInt64.from(xAddressDecoded[field.name], field.name)
157
+ : field.associatedType?.from
158
+ ? field.associatedType.from(xAddressDecoded[field.name])
159
+ : (() => {
160
+ throw new Error(
161
+ `Type ${field.type.name} for field ${field.name} is missing associatedType.from`,
162
+ )
163
+ })()
164
+
165
+ if (associatedValue == undefined) {
166
+ throw new TypeError(
167
+ `Unable to interpret "${field.name}: ${
168
+ xAddressDecoded[field.name]
169
+ }".`,
170
+ )
171
+ }
172
+
173
+ if ((associatedValue as unknown as Bytes).name === 'UNLModify') {
174
+ // triggered when the TransactionType field has a value of 'UNLModify'
175
+ isUnlModify = true
176
+ }
177
+ // true when in the UNLModify pseudotransaction (after the transaction type has been processed) and working with the
178
+ // Account field
179
+ // The Account field must not be a part of the UNLModify pseudotransaction encoding, due to a bug in rippled
180
+ const isUnlModifyWorkaround = field.name == 'Account' && isUnlModify
181
+ bytes.writeFieldAndValue(field, associatedValue, isUnlModifyWorkaround)
182
+ if (field.type.name === ST_OBJECT) {
183
+ bytes.put(OBJECT_END_MARKER_BYTE)
184
+ }
185
+ })
186
+
187
+ return new STObject(list.toBytes())
188
+ }
189
+
190
+ /**
191
+ * Get the JSON interpretation of this.bytes
192
+ * @param definitions rippled definitions used to parse the values of transaction types and such.
193
+ * Can be customized for sidechains and amendments.
194
+ * @returns a JSON object
195
+ */
196
+ toJSON(definitions?: XrplDefinitionsBase): JsonObject {
197
+ const objectParser = new BinaryParser(this.toString(), definitions)
198
+ const accumulator = {}
199
+
200
+ while (!objectParser.end()) {
201
+ const field = objectParser.readField()
202
+ if (field.name === OBJECT_END_MARKER) {
203
+ break
204
+ }
205
+
206
+ accumulator[field.name] = objectParser
207
+ .readFieldValue(field)
208
+ .toJSON(definitions, field.name)
209
+ }
210
+
211
+ return accumulator
212
+ }
213
+ }
214
+
215
+ export { STObject }
@@ -0,0 +1,53 @@
1
+ import { UInt } from './uint'
2
+ import { BinaryParser } from '../serdes/binary-parser'
3
+ import { readUInt16BE, writeUInt16BE } from '../utils'
4
+
5
+ /**
6
+ * Derived UInt class for serializing/deserializing 16 bit UInt
7
+ */
8
+ class UInt16 extends UInt {
9
+ protected static readonly width: number = 16 / 8 // 2
10
+ static readonly defaultUInt16: UInt16 = new UInt16(
11
+ new Uint8Array(UInt16.width),
12
+ )
13
+
14
+ constructor(bytes: Uint8Array) {
15
+ super(bytes ?? UInt16.defaultUInt16.bytes)
16
+ }
17
+
18
+ static fromParser(parser: BinaryParser): UInt {
19
+ return new UInt16(parser.read(UInt16.width))
20
+ }
21
+
22
+ /**
23
+ * Construct a UInt16 object from a number
24
+ *
25
+ * @param val UInt16 object or number
26
+ */
27
+ static from<T extends UInt16 | number>(val: T): UInt16 {
28
+ if (val instanceof UInt16) {
29
+ return val
30
+ }
31
+
32
+ if (typeof val === 'number') {
33
+ UInt16.checkUintRange(val, 0, 0xffff)
34
+
35
+ const buf = new Uint8Array(UInt16.width)
36
+ writeUInt16BE(buf, val, 0)
37
+ return new UInt16(buf)
38
+ }
39
+
40
+ throw new Error('Can not construct UInt16 with given value')
41
+ }
42
+
43
+ /**
44
+ * get the value of a UInt16 object
45
+ *
46
+ * @returns the number represented by this.bytes
47
+ */
48
+ valueOf(): number {
49
+ return parseInt(readUInt16BE(this.bytes, 0))
50
+ }
51
+ }
52
+
53
+ export { UInt16 }
@@ -0,0 +1,59 @@
1
+ import { UInt } from './uint'
2
+ import { BinaryParser } from '../serdes/binary-parser'
3
+ import { readUInt32BE, writeUInt32BE } from '../utils'
4
+
5
+ /**
6
+ * Derived UInt class for serializing/deserializing 32 bit UInt
7
+ */
8
+ class UInt32 extends UInt {
9
+ protected static readonly width: number = 32 / 8 // 4
10
+ static readonly defaultUInt32: UInt32 = new UInt32(
11
+ new Uint8Array(UInt32.width),
12
+ )
13
+
14
+ constructor(bytes: Uint8Array) {
15
+ super(bytes ?? UInt32.defaultUInt32.bytes)
16
+ }
17
+
18
+ static fromParser(parser: BinaryParser): UInt {
19
+ return new UInt32(parser.read(UInt32.width))
20
+ }
21
+
22
+ /**
23
+ * Construct a UInt32 object from a number
24
+ *
25
+ * @param val UInt32 object or number
26
+ */
27
+ static from<T extends UInt32 | number | string>(val: T): UInt32 {
28
+ if (val instanceof UInt32) {
29
+ return val
30
+ }
31
+
32
+ const buf = new Uint8Array(UInt32.width)
33
+
34
+ if (typeof val === 'string') {
35
+ const num = Number.parseInt(val)
36
+ writeUInt32BE(buf, num, 0)
37
+ return new UInt32(buf)
38
+ }
39
+
40
+ if (typeof val === 'number') {
41
+ UInt32.checkUintRange(val, 0, 0xffffffff)
42
+ writeUInt32BE(buf, val, 0)
43
+ return new UInt32(buf)
44
+ }
45
+
46
+ throw new Error('Cannot construct UInt32 from given value')
47
+ }
48
+
49
+ /**
50
+ * get the value of a UInt32 object
51
+ *
52
+ * @returns the number represented by this.bytes
53
+ */
54
+ valueOf(): number {
55
+ return parseInt(readUInt32BE(this.bytes, 0), 10)
56
+ }
57
+ }
58
+
59
+ export { UInt32 }