ripple-binary-codec 1.7.1 → 1.9.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 (99) hide show
  1. package/dist/enums/definitions.json +250 -1
  2. package/dist/enums/src/enums/definitions.json +250 -1
  3. package/dist/types/index.js +2 -0
  4. package/dist/types/index.js.map +1 -1
  5. package/dist/types/issue.d.ts +39 -0
  6. package/dist/types/issue.js +81 -0
  7. package/dist/types/issue.js.map +1 -0
  8. package/dist/types/xchain-bridge.d.ts +45 -0
  9. package/dist/types/xchain-bridge.js +102 -0
  10. package/dist/types/xchain-bridge.js.map +1 -0
  11. package/package.json +3 -4
  12. package/src/README.md +3 -0
  13. package/src/binary.ts +188 -0
  14. package/src/coretypes.ts +31 -0
  15. package/src/enums/README.md +144 -0
  16. package/src/enums/bytes.ts +75 -0
  17. package/src/enums/constants.ts +4 -0
  18. package/src/enums/definitions.json +2599 -0
  19. package/src/enums/field.ts +85 -0
  20. package/src/enums/index.ts +34 -0
  21. package/src/enums/utils-renumber.ts +134 -0
  22. package/src/enums/xrpl-definitions-base.ts +111 -0
  23. package/src/enums/xrpl-definitions.ts +32 -0
  24. package/src/hash-prefixes.ts +40 -0
  25. package/src/hashes.ts +76 -0
  26. package/src/index.ts +141 -0
  27. package/src/ledger-hashes.ts +187 -0
  28. package/src/quality.ts +39 -0
  29. package/src/serdes/binary-parser.ts +217 -0
  30. package/src/serdes/binary-serializer.ts +166 -0
  31. package/src/shamap.ts +186 -0
  32. package/src/types/account-id.ts +86 -0
  33. package/src/types/amount.ts +256 -0
  34. package/src/types/blob.ts +43 -0
  35. package/src/types/currency.ts +140 -0
  36. package/src/types/hash-128.ts +33 -0
  37. package/src/types/hash-160.ts +20 -0
  38. package/src/types/hash-256.ts +16 -0
  39. package/src/types/hash.ts +81 -0
  40. package/src/types/index.ts +61 -0
  41. package/src/types/issue.ts +96 -0
  42. package/src/types/path-set.ts +290 -0
  43. package/src/types/serialized-type.ts +120 -0
  44. package/src/types/st-array.ts +107 -0
  45. package/src/types/st-object.ts +192 -0
  46. package/src/types/uint-16.ts +49 -0
  47. package/src/types/uint-32.ts +56 -0
  48. package/src/types/uint-64.ts +105 -0
  49. package/src/types/uint-8.ts +49 -0
  50. package/src/types/uint.ts +57 -0
  51. package/src/types/vector-256.ts +84 -0
  52. package/test/amount.test.js +0 -43
  53. package/test/binary-json.test.js +0 -45
  54. package/test/binary-parser.test.js +0 -396
  55. package/test/binary-serializer.test.js +0 -289
  56. package/test/definitions.test.js +0 -160
  57. package/test/fixtures/account-tx-transactions.db +0 -0
  58. package/test/fixtures/codec-fixtures.json +0 -4466
  59. package/test/fixtures/data-driven-tests.json +0 -2919
  60. package/test/fixtures/delivermin-tx-binary.json +0 -1
  61. package/test/fixtures/delivermin-tx.json +0 -98
  62. package/test/fixtures/deposit-preauth-tx-binary.json +0 -1
  63. package/test/fixtures/deposit-preauth-tx-meta-binary.json +0 -1
  64. package/test/fixtures/deposit-preauth-tx.json +0 -58
  65. package/test/fixtures/escrow-cancel-binary.json +0 -1
  66. package/test/fixtures/escrow-cancel-tx.json +0 -6
  67. package/test/fixtures/escrow-create-binary.json +0 -1
  68. package/test/fixtures/escrow-create-tx.json +0 -10
  69. package/test/fixtures/escrow-finish-binary.json +0 -1
  70. package/test/fixtures/escrow-finish-meta-binary.json +0 -1
  71. package/test/fixtures/escrow-finish-tx.json +0 -95
  72. package/test/fixtures/ledger-full-38129.json +0 -1
  73. package/test/fixtures/ledger-full-40000.json +0 -1
  74. package/test/fixtures/negative-unl.json +0 -12
  75. package/test/fixtures/nf-token.json +0 -547
  76. package/test/fixtures/payment-channel-claim-binary.json +0 -1
  77. package/test/fixtures/payment-channel-claim-tx.json +0 -8
  78. package/test/fixtures/payment-channel-create-binary.json +0 -1
  79. package/test/fixtures/payment-channel-create-tx.json +0 -11
  80. package/test/fixtures/payment-channel-fund-binary.json +0 -1
  81. package/test/fixtures/payment-channel-fund-tx.json +0 -7
  82. package/test/fixtures/signerlistset-tx-binary.json +0 -1
  83. package/test/fixtures/signerlistset-tx-meta-binary.json +0 -1
  84. package/test/fixtures/signerlistset-tx.json +0 -94
  85. package/test/fixtures/ticket-create-binary.json +0 -1
  86. package/test/fixtures/ticket-create-tx.json +0 -7
  87. package/test/fixtures/x-codec-fixtures.json +0 -188
  88. package/test/hash.test.js +0 -135
  89. package/test/ledger.test.js +0 -29
  90. package/test/lower-case-hex.test.js +0 -46
  91. package/test/pseudo-transaction.test.js +0 -38
  92. package/test/quality.test.js +0 -15
  93. package/test/shamap.test.js +0 -89
  94. package/test/signing-data-encoding.test.js +0 -242
  95. package/test/tx-encode-decode.test.js +0 -119
  96. package/test/types.test.js +0 -34
  97. package/test/uint.test.js +0 -148
  98. package/test/utils.js +0 -30
  99. package/test/x-address.test.js +0 -181
@@ -0,0 +1,120 @@
1
+ import { BytesList } from '../serdes/binary-serializer'
2
+ import { BinaryParser } from '../serdes/binary-parser'
3
+ import bigInt = require('big-integer')
4
+ import { Buffer } from 'buffer/'
5
+ import { XrplDefinitionsBase } from '../enums'
6
+
7
+ type JSON = string | number | boolean | null | undefined | JSON[] | JsonObject
8
+
9
+ type JsonObject = { [key: string]: JSON }
10
+
11
+ /**
12
+ * The base class for all binary-codec types
13
+ */
14
+ class SerializedType {
15
+ protected readonly bytes: Buffer = Buffer.alloc(0)
16
+
17
+ constructor(bytes: Buffer) {
18
+ this.bytes = bytes ?? Buffer.alloc(0)
19
+ }
20
+
21
+ static fromParser(parser: BinaryParser, hint?: number): SerializedType {
22
+ throw new Error('fromParser not implemented')
23
+ return this.fromParser(parser, hint)
24
+ }
25
+
26
+ static from(
27
+ value: SerializedType | JSON | bigInt.BigInteger,
28
+ ): SerializedType {
29
+ throw new Error('from not implemented')
30
+ return this.from(value)
31
+ }
32
+
33
+ /**
34
+ * Write the bytes representation of a SerializedType to a BytesList
35
+ *
36
+ * @param list The BytesList to write SerializedType bytes to
37
+ */
38
+ toBytesSink(list: BytesList): void {
39
+ list.put(this.bytes)
40
+ }
41
+
42
+ /**
43
+ * Get the hex representation of a SerializedType's bytes
44
+ *
45
+ * @returns hex String of this.bytes
46
+ */
47
+ toHex(): string {
48
+ return this.toBytes().toString('hex').toUpperCase()
49
+ }
50
+
51
+ /**
52
+ * Get the bytes representation of a SerializedType
53
+ *
54
+ * @returns A buffer of the bytes
55
+ */
56
+ toBytes(): Buffer {
57
+ if (this.bytes) {
58
+ return this.bytes
59
+ }
60
+ const bytes = new BytesList()
61
+ this.toBytesSink(bytes)
62
+ return bytes.toBytes()
63
+ }
64
+
65
+ /**
66
+ * Return the JSON representation of a SerializedType
67
+ *
68
+ * @param _definitions rippled definitions used to parse the values of transaction types and such.
69
+ * Unused in default, but used in STObject, STArray
70
+ * Can be customized for sidechains and amendments.
71
+ * @returns any type, if not overloaded returns hexString representation of bytes
72
+ */
73
+ toJSON(_definitions?: XrplDefinitionsBase): JSON {
74
+ return this.toHex()
75
+ }
76
+
77
+ /**
78
+ * @returns hexString representation of this.bytes
79
+ */
80
+ toString(): string {
81
+ return this.toHex()
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Base class for SerializedTypes that are comparable
87
+ */
88
+ class Comparable extends SerializedType {
89
+ lt(other: Comparable): boolean {
90
+ return this.compareTo(other) < 0
91
+ }
92
+
93
+ eq(other: Comparable): boolean {
94
+ return this.compareTo(other) === 0
95
+ }
96
+
97
+ gt(other: Comparable): boolean {
98
+ return this.compareTo(other) > 0
99
+ }
100
+
101
+ gte(other: Comparable): boolean {
102
+ return this.compareTo(other) > -1
103
+ }
104
+
105
+ lte(other: Comparable): boolean {
106
+ return this.compareTo(other) < 1
107
+ }
108
+
109
+ /**
110
+ * Overload this method to define how two Comparable SerializedTypes are compared
111
+ *
112
+ * @param other The comparable object to compare this to
113
+ * @returns A number denoting the relationship of this and other
114
+ */
115
+ compareTo(other: Comparable): number {
116
+ throw new Error(`cannot compare ${this.toString()} and ${other.toString()}`)
117
+ }
118
+ }
119
+
120
+ export { SerializedType, Comparable, JSON, JsonObject }
@@ -0,0 +1,107 @@
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 { Buffer } from 'buffer/'
6
+
7
+ const ARRAY_END_MARKER = Buffer.from([0xf1])
8
+ const ARRAY_END_MARKER_NAME = 'ArrayEndMarker'
9
+
10
+ const OBJECT_END_MARKER = Buffer.from([0xe1])
11
+
12
+ /**
13
+ * TypeGuard for Array<JsonObject>
14
+ */
15
+ function isObjects(args): args is Array<JsonObject> {
16
+ return (
17
+ Array.isArray(args) && (args.length === 0 || typeof args[0] === 'object')
18
+ )
19
+ }
20
+
21
+ /**
22
+ * Class for serializing and deserializing Arrays of Objects
23
+ */
24
+ class STArray extends SerializedType {
25
+ /**
26
+ * Construct an STArray from a BinaryParser
27
+ *
28
+ * @param parser BinaryParser to parse an STArray from
29
+ * @returns An STArray Object
30
+ */
31
+ static fromParser(parser: BinaryParser): STArray {
32
+ const bytes: Array<Buffer> = []
33
+
34
+ while (!parser.end()) {
35
+ const field = parser.readField()
36
+ if (field.name === ARRAY_END_MARKER_NAME) {
37
+ break
38
+ }
39
+
40
+ bytes.push(
41
+ field.header,
42
+ parser.readFieldValue(field).toBytes(),
43
+ OBJECT_END_MARKER,
44
+ )
45
+ }
46
+
47
+ bytes.push(ARRAY_END_MARKER)
48
+ return new STArray(Buffer.concat(bytes))
49
+ }
50
+
51
+ /**
52
+ * Construct an STArray from an Array of JSON Objects
53
+ *
54
+ * @param value STArray or Array of Objects to parse into an STArray
55
+ * @param definitions optional, types and values to use to encode/decode a transaction
56
+ * @returns An STArray object
57
+ */
58
+ static from<T extends STArray | Array<JsonObject>>(
59
+ value: T,
60
+ definitions: XrplDefinitionsBase = DEFAULT_DEFINITIONS,
61
+ ): STArray {
62
+ if (value instanceof STArray) {
63
+ return value
64
+ }
65
+
66
+ if (isObjects(value)) {
67
+ const bytes: Array<Buffer> = []
68
+ value.forEach((obj) => {
69
+ bytes.push(STObject.from(obj, undefined, definitions).toBytes())
70
+ })
71
+
72
+ bytes.push(ARRAY_END_MARKER)
73
+ return new STArray(Buffer.concat(bytes))
74
+ }
75
+
76
+ throw new Error('Cannot construct STArray from value given')
77
+ }
78
+
79
+ /**
80
+ * Return the JSON representation of this.bytes
81
+ *
82
+ * @param definitions optional, types and values to use to encode/decode a transaction
83
+ * @returns An Array of JSON objects
84
+ */
85
+ toJSON(
86
+ definitions: XrplDefinitionsBase = DEFAULT_DEFINITIONS,
87
+ ): Array<JsonObject> {
88
+ const result: Array<JsonObject> = []
89
+
90
+ const arrayParser = new BinaryParser(this.toString(), definitions)
91
+
92
+ while (!arrayParser.end()) {
93
+ const field = arrayParser.readField()
94
+ if (field.name === ARRAY_END_MARKER_NAME) {
95
+ break
96
+ }
97
+
98
+ const outer = {}
99
+ outer[field.name] = STObject.fromParser(arrayParser).toJSON(definitions)
100
+ result.push(outer)
101
+ }
102
+
103
+ return result
104
+ }
105
+ }
106
+
107
+ export { STArray }
@@ -0,0 +1,192 @@
1
+ import {
2
+ DEFAULT_DEFINITIONS,
3
+ FieldInstance,
4
+ Bytes,
5
+ XrplDefinitionsBase,
6
+ } from '../enums'
7
+ import { SerializedType, JsonObject } from './serialized-type'
8
+ import { xAddressToClassicAddress, isValidXAddress } from 'ripple-address-codec'
9
+ import { BinaryParser } from '../serdes/binary-parser'
10
+ import { BinarySerializer, BytesList } from '../serdes/binary-serializer'
11
+ import { Buffer } from 'buffer/'
12
+ import { STArray } from './st-array'
13
+
14
+ const OBJECT_END_MARKER_BYTE = Buffer.from([0xe1])
15
+ const OBJECT_END_MARKER = 'ObjectEndMarker'
16
+ const ST_OBJECT = 'STObject'
17
+ const DESTINATION = 'Destination'
18
+ const ACCOUNT = 'Account'
19
+ const SOURCE_TAG = 'SourceTag'
20
+ const DEST_TAG = 'DestinationTag'
21
+
22
+ /**
23
+ * Break down an X-Address into an account and a tag
24
+ *
25
+ * @param field Name of field
26
+ * @param xAddress X-Address corresponding to the field
27
+ */
28
+ function handleXAddress(field: string, xAddress: string): JsonObject {
29
+ const decoded = xAddressToClassicAddress(xAddress)
30
+
31
+ let tagName
32
+ if (field === DESTINATION) tagName = DEST_TAG
33
+ else if (field === ACCOUNT) tagName = SOURCE_TAG
34
+ else if (decoded.tag !== false)
35
+ throw new Error(`${field} cannot have an associated tag`)
36
+
37
+ return decoded.tag !== false
38
+ ? { [field]: decoded.classicAddress, [tagName]: decoded.tag }
39
+ : { [field]: decoded.classicAddress }
40
+ }
41
+
42
+ /**
43
+ * Validate that two objects don't both have the same tag fields
44
+ *
45
+ * @param obj1 First object to check for tags
46
+ * @param obj2 Second object to check for tags
47
+ * @throws When both objects have SourceTag or DestinationTag
48
+ */
49
+ function checkForDuplicateTags(obj1: JsonObject, obj2: JsonObject): void {
50
+ if (!(obj1[SOURCE_TAG] === undefined || obj2[SOURCE_TAG] === undefined))
51
+ throw new Error('Cannot have Account X-Address and SourceTag')
52
+ if (!(obj1[DEST_TAG] === undefined || obj2[DEST_TAG] === undefined))
53
+ throw new Error('Cannot have Destination X-Address and DestinationTag')
54
+ }
55
+
56
+ /**
57
+ * Class for Serializing/Deserializing objects
58
+ */
59
+ class STObject extends SerializedType {
60
+ /**
61
+ * Construct a STObject from a BinaryParser
62
+ *
63
+ * @param parser BinaryParser to read STObject from
64
+ * @returns A STObject object
65
+ */
66
+ static fromParser(parser: BinaryParser): STObject {
67
+ const list: BytesList = new BytesList()
68
+ const bytes: BinarySerializer = new BinarySerializer(list)
69
+
70
+ while (!parser.end()) {
71
+ const field = parser.readField()
72
+ if (field.name === OBJECT_END_MARKER) {
73
+ break
74
+ }
75
+
76
+ const associatedValue = parser.readFieldValue(field)
77
+
78
+ bytes.writeFieldAndValue(field, associatedValue)
79
+ if (field.type.name === ST_OBJECT) {
80
+ bytes.put(OBJECT_END_MARKER_BYTE)
81
+ }
82
+ }
83
+
84
+ return new STObject(list.toBytes())
85
+ }
86
+
87
+ /**
88
+ * Construct a STObject from a JSON object
89
+ *
90
+ * @param value An object to include
91
+ * @param filter optional, denote which field to include in serialized object
92
+ * @param definitions optional, types and values to use to encode/decode a transaction
93
+ * @returns a STObject object
94
+ */
95
+ static from<T extends STObject | JsonObject>(
96
+ value: T,
97
+ filter?: (...any) => boolean,
98
+ definitions: XrplDefinitionsBase = DEFAULT_DEFINITIONS,
99
+ ): STObject {
100
+ if (value instanceof STObject) {
101
+ return value
102
+ }
103
+
104
+ const list: BytesList = new BytesList()
105
+ const bytes: BinarySerializer = new BinarySerializer(list)
106
+
107
+ let isUnlModify = false
108
+
109
+ const xAddressDecoded = Object.entries(value).reduce((acc, [key, val]) => {
110
+ let handled: JsonObject | undefined = undefined
111
+ if (val && isValidXAddress(val.toString())) {
112
+ handled = handleXAddress(key, val.toString())
113
+ checkForDuplicateTags(handled, value)
114
+ }
115
+ return Object.assign(acc, handled ?? { [key]: val })
116
+ }, {})
117
+
118
+ let sorted = Object.keys(xAddressDecoded)
119
+ .map((f: string): FieldInstance => definitions.field[f] as FieldInstance)
120
+ .filter(
121
+ (f: FieldInstance): boolean =>
122
+ f !== undefined &&
123
+ xAddressDecoded[f.name] !== undefined &&
124
+ f.isSerialized,
125
+ )
126
+ .sort((a, b) => {
127
+ return a.ordinal - b.ordinal
128
+ })
129
+
130
+ if (filter !== undefined) {
131
+ sorted = sorted.filter(filter)
132
+ }
133
+
134
+ sorted.forEach((field) => {
135
+ const associatedValue =
136
+ field.type.name === ST_OBJECT
137
+ ? this.from(xAddressDecoded[field.name], undefined, definitions)
138
+ : field.type.name === 'STArray'
139
+ ? STArray.from(xAddressDecoded[field.name], definitions)
140
+ : field.associatedType.from(xAddressDecoded[field.name])
141
+
142
+ if (associatedValue == undefined) {
143
+ throw new TypeError(
144
+ `Unable to interpret "${field.name}: ${
145
+ xAddressDecoded[field.name]
146
+ }".`,
147
+ )
148
+ }
149
+
150
+ if ((associatedValue as unknown as Bytes).name === 'UNLModify') {
151
+ // triggered when the TransactionType field has a value of 'UNLModify'
152
+ isUnlModify = true
153
+ }
154
+ // true when in the UNLModify pseudotransaction (after the transaction type has been processed) and working with the
155
+ // Account field
156
+ // The Account field must not be a part of the UNLModify pseudotransaction encoding, due to a bug in rippled
157
+ const isUnlModifyWorkaround = field.name == 'Account' && isUnlModify
158
+ bytes.writeFieldAndValue(field, associatedValue, isUnlModifyWorkaround)
159
+ if (field.type.name === ST_OBJECT) {
160
+ bytes.put(OBJECT_END_MARKER_BYTE)
161
+ }
162
+ })
163
+
164
+ return new STObject(list.toBytes())
165
+ }
166
+
167
+ /**
168
+ * Get the JSON interpretation of this.bytes
169
+ * @param definitions rippled definitions used to parse the values of transaction types and such.
170
+ * Can be customized for sidechains and amendments.
171
+ * @returns a JSON object
172
+ */
173
+ toJSON(definitions?: XrplDefinitionsBase): JsonObject {
174
+ const objectParser = new BinaryParser(this.toString(), definitions)
175
+ const accumulator = {}
176
+
177
+ while (!objectParser.end()) {
178
+ const field = objectParser.readField()
179
+ if (field.name === OBJECT_END_MARKER) {
180
+ break
181
+ }
182
+
183
+ accumulator[field.name] = objectParser
184
+ .readFieldValue(field)
185
+ .toJSON(definitions)
186
+ }
187
+
188
+ return accumulator
189
+ }
190
+ }
191
+
192
+ export { STObject }
@@ -0,0 +1,49 @@
1
+ import { UInt } from './uint'
2
+ import { BinaryParser } from '../serdes/binary-parser'
3
+ import { Buffer } from 'buffer/'
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(Buffer.alloc(UInt16.width))
11
+
12
+ constructor(bytes: Buffer) {
13
+ super(bytes ?? UInt16.defaultUInt16.bytes)
14
+ }
15
+
16
+ static fromParser(parser: BinaryParser): UInt {
17
+ return new UInt16(parser.read(UInt16.width))
18
+ }
19
+
20
+ /**
21
+ * Construct a UInt16 object from a number
22
+ *
23
+ * @param val UInt16 object or number
24
+ */
25
+ static from<T extends UInt16 | number>(val: T): UInt16 {
26
+ if (val instanceof UInt16) {
27
+ return val
28
+ }
29
+
30
+ if (typeof val === 'number') {
31
+ const buf = Buffer.alloc(UInt16.width)
32
+ buf.writeUInt16BE(val, 0)
33
+ return new UInt16(buf)
34
+ }
35
+
36
+ throw new Error('Can not construct UInt16 with given value')
37
+ }
38
+
39
+ /**
40
+ * get the value of a UInt16 object
41
+ *
42
+ * @returns the number represented by this.bytes
43
+ */
44
+ valueOf(): number {
45
+ return this.bytes.readUInt16BE(0)
46
+ }
47
+ }
48
+
49
+ export { UInt16 }
@@ -0,0 +1,56 @@
1
+ import { UInt } from './uint'
2
+ import { BinaryParser } from '../serdes/binary-parser'
3
+ import { Buffer } from 'buffer/'
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(Buffer.alloc(UInt32.width))
11
+
12
+ constructor(bytes: Buffer) {
13
+ super(bytes ?? UInt32.defaultUInt32.bytes)
14
+ }
15
+
16
+ static fromParser(parser: BinaryParser): UInt {
17
+ return new UInt32(parser.read(UInt32.width))
18
+ }
19
+
20
+ /**
21
+ * Construct a UInt32 object from a number
22
+ *
23
+ * @param val UInt32 object or number
24
+ */
25
+ static from<T extends UInt32 | number | string>(val: T): UInt32 {
26
+ if (val instanceof UInt32) {
27
+ return val
28
+ }
29
+
30
+ const buf = Buffer.alloc(UInt32.width)
31
+
32
+ if (typeof val === 'string') {
33
+ const num = Number.parseInt(val)
34
+ buf.writeUInt32BE(num, 0)
35
+ return new UInt32(buf)
36
+ }
37
+
38
+ if (typeof val === 'number') {
39
+ buf.writeUInt32BE(val, 0)
40
+ return new UInt32(buf)
41
+ }
42
+
43
+ throw new Error('Cannot construct UInt32 from given value')
44
+ }
45
+
46
+ /**
47
+ * get the value of a UInt32 object
48
+ *
49
+ * @returns the number represented by this.bytes
50
+ */
51
+ valueOf(): number {
52
+ return this.bytes.readUInt32BE(0)
53
+ }
54
+ }
55
+
56
+ export { UInt32 }
@@ -0,0 +1,105 @@
1
+ import { UInt } from './uint'
2
+ import { BinaryParser } from '../serdes/binary-parser'
3
+ import bigInt = require('big-integer')
4
+ import { isInstance } from 'big-integer'
5
+ import { Buffer } from 'buffer/'
6
+
7
+ const HEX_REGEX = /^[a-fA-F0-9]{1,16}$/
8
+ const mask = bigInt(0x00000000ffffffff)
9
+
10
+ /**
11
+ * Derived UInt class for serializing/deserializing 64 bit UInt
12
+ */
13
+ class UInt64 extends UInt {
14
+ protected static readonly width: number = 64 / 8 // 8
15
+ static readonly defaultUInt64: UInt64 = new UInt64(Buffer.alloc(UInt64.width))
16
+
17
+ constructor(bytes: Buffer) {
18
+ super(bytes ?? UInt64.defaultUInt64.bytes)
19
+ }
20
+
21
+ static fromParser(parser: BinaryParser): UInt {
22
+ return new UInt64(parser.read(UInt64.width))
23
+ }
24
+
25
+ /**
26
+ * Construct a UInt64 object
27
+ *
28
+ * @param val A UInt64, hex-string, bigInt, or number
29
+ * @returns A UInt64 object
30
+ */
31
+ static from<T extends UInt64 | string | bigInt.BigInteger | number>(
32
+ val: T,
33
+ ): UInt64 {
34
+ if (val instanceof UInt64) {
35
+ return val
36
+ }
37
+
38
+ let buf = Buffer.alloc(UInt64.width)
39
+
40
+ if (typeof val === 'number') {
41
+ if (val < 0) {
42
+ throw new Error('value must be an unsigned integer')
43
+ }
44
+
45
+ const number = bigInt(val)
46
+
47
+ const intBuf = [Buffer.alloc(4), Buffer.alloc(4)]
48
+ intBuf[0].writeUInt32BE(Number(number.shiftRight(32)), 0)
49
+ intBuf[1].writeUInt32BE(Number(number.and(mask)), 0)
50
+
51
+ return new UInt64(Buffer.concat(intBuf))
52
+ }
53
+
54
+ if (typeof val === 'string') {
55
+ if (!HEX_REGEX.test(val)) {
56
+ throw new Error(`${val} is not a valid hex-string`)
57
+ }
58
+
59
+ const strBuf = val.padStart(16, '0')
60
+ buf = Buffer.from(strBuf, 'hex')
61
+ return new UInt64(buf)
62
+ }
63
+
64
+ if (isInstance(val)) {
65
+ const intBuf = [Buffer.alloc(4), Buffer.alloc(4)]
66
+ intBuf[0].writeUInt32BE(Number(val.shiftRight(bigInt(32))), 0)
67
+ intBuf[1].writeUInt32BE(Number(val.and(mask)), 0)
68
+
69
+ return new UInt64(Buffer.concat(intBuf))
70
+ }
71
+
72
+ throw new Error('Cannot construct UInt64 from given value')
73
+ }
74
+
75
+ /**
76
+ * The JSON representation of a UInt64 object
77
+ *
78
+ * @returns a hex-string
79
+ */
80
+ toJSON(): string {
81
+ return this.bytes.toString('hex').toUpperCase()
82
+ }
83
+
84
+ /**
85
+ * Get the value of the UInt64
86
+ *
87
+ * @returns the number represented buy this.bytes
88
+ */
89
+ valueOf(): bigInt.BigInteger {
90
+ const msb = bigInt(this.bytes.slice(0, 4).readUInt32BE(0))
91
+ const lsb = bigInt(this.bytes.slice(4).readUInt32BE(0))
92
+ return msb.shiftLeft(bigInt(32)).or(lsb)
93
+ }
94
+
95
+ /**
96
+ * Get the bytes representation of the UInt64 object
97
+ *
98
+ * @returns 8 bytes representing the UInt64
99
+ */
100
+ toBytes(): Buffer {
101
+ return this.bytes
102
+ }
103
+ }
104
+
105
+ export { UInt64 }
@@ -0,0 +1,49 @@
1
+ import { UInt } from './uint'
2
+ import { BinaryParser } from '../serdes/binary-parser'
3
+ import { Buffer } from 'buffer/'
4
+
5
+ /**
6
+ * Derived UInt class for serializing/deserializing 8 bit UInt
7
+ */
8
+ class UInt8 extends UInt {
9
+ protected static readonly width: number = 8 / 8 // 1
10
+ static readonly defaultUInt8: UInt8 = new UInt8(Buffer.alloc(UInt8.width))
11
+
12
+ constructor(bytes: Buffer) {
13
+ super(bytes ?? UInt8.defaultUInt8.bytes)
14
+ }
15
+
16
+ static fromParser(parser: BinaryParser): UInt {
17
+ return new UInt8(parser.read(UInt8.width))
18
+ }
19
+
20
+ /**
21
+ * Construct a UInt8 object from a number
22
+ *
23
+ * @param val UInt8 object or number
24
+ */
25
+ static from<T extends UInt8 | number>(val: T): UInt8 {
26
+ if (val instanceof UInt8) {
27
+ return val
28
+ }
29
+
30
+ if (typeof val === 'number') {
31
+ const buf = Buffer.alloc(UInt8.width)
32
+ buf.writeUInt8(val, 0)
33
+ return new UInt8(buf)
34
+ }
35
+
36
+ throw new Error('Cannot construct UInt8 from given value')
37
+ }
38
+
39
+ /**
40
+ * get the value of a UInt8 object
41
+ *
42
+ * @returns the number represented by this.bytes
43
+ */
44
+ valueOf(): number {
45
+ return this.bytes.readUInt8(0)
46
+ }
47
+ }
48
+
49
+ export { UInt8 }