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.
- package/dist/enums/definitions.json +250 -1
- package/dist/enums/src/enums/definitions.json +250 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/issue.d.ts +39 -0
- package/dist/types/issue.js +81 -0
- package/dist/types/issue.js.map +1 -0
- package/dist/types/xchain-bridge.d.ts +45 -0
- package/dist/types/xchain-bridge.js +102 -0
- package/dist/types/xchain-bridge.js.map +1 -0
- package/package.json +3 -4
- package/src/README.md +3 -0
- package/src/binary.ts +188 -0
- package/src/coretypes.ts +31 -0
- package/src/enums/README.md +144 -0
- package/src/enums/bytes.ts +75 -0
- package/src/enums/constants.ts +4 -0
- package/src/enums/definitions.json +2599 -0
- package/src/enums/field.ts +85 -0
- package/src/enums/index.ts +34 -0
- package/src/enums/utils-renumber.ts +134 -0
- package/src/enums/xrpl-definitions-base.ts +111 -0
- package/src/enums/xrpl-definitions.ts +32 -0
- package/src/hash-prefixes.ts +40 -0
- package/src/hashes.ts +76 -0
- package/src/index.ts +141 -0
- package/src/ledger-hashes.ts +187 -0
- package/src/quality.ts +39 -0
- package/src/serdes/binary-parser.ts +217 -0
- package/src/serdes/binary-serializer.ts +166 -0
- package/src/shamap.ts +186 -0
- package/src/types/account-id.ts +86 -0
- package/src/types/amount.ts +256 -0
- package/src/types/blob.ts +43 -0
- package/src/types/currency.ts +140 -0
- package/src/types/hash-128.ts +33 -0
- package/src/types/hash-160.ts +20 -0
- package/src/types/hash-256.ts +16 -0
- package/src/types/hash.ts +81 -0
- package/src/types/index.ts +61 -0
- package/src/types/issue.ts +96 -0
- package/src/types/path-set.ts +290 -0
- package/src/types/serialized-type.ts +120 -0
- package/src/types/st-array.ts +107 -0
- package/src/types/st-object.ts +192 -0
- package/src/types/uint-16.ts +49 -0
- package/src/types/uint-32.ts +56 -0
- package/src/types/uint-64.ts +105 -0
- package/src/types/uint-8.ts +49 -0
- package/src/types/uint.ts +57 -0
- package/src/types/vector-256.ts +84 -0
- package/test/amount.test.js +0 -43
- package/test/binary-json.test.js +0 -45
- package/test/binary-parser.test.js +0 -396
- package/test/binary-serializer.test.js +0 -289
- package/test/definitions.test.js +0 -160
- package/test/fixtures/account-tx-transactions.db +0 -0
- package/test/fixtures/codec-fixtures.json +0 -4466
- package/test/fixtures/data-driven-tests.json +0 -2919
- package/test/fixtures/delivermin-tx-binary.json +0 -1
- package/test/fixtures/delivermin-tx.json +0 -98
- package/test/fixtures/deposit-preauth-tx-binary.json +0 -1
- package/test/fixtures/deposit-preauth-tx-meta-binary.json +0 -1
- package/test/fixtures/deposit-preauth-tx.json +0 -58
- package/test/fixtures/escrow-cancel-binary.json +0 -1
- package/test/fixtures/escrow-cancel-tx.json +0 -6
- package/test/fixtures/escrow-create-binary.json +0 -1
- package/test/fixtures/escrow-create-tx.json +0 -10
- package/test/fixtures/escrow-finish-binary.json +0 -1
- package/test/fixtures/escrow-finish-meta-binary.json +0 -1
- package/test/fixtures/escrow-finish-tx.json +0 -95
- package/test/fixtures/ledger-full-38129.json +0 -1
- package/test/fixtures/ledger-full-40000.json +0 -1
- package/test/fixtures/negative-unl.json +0 -12
- package/test/fixtures/nf-token.json +0 -547
- package/test/fixtures/payment-channel-claim-binary.json +0 -1
- package/test/fixtures/payment-channel-claim-tx.json +0 -8
- package/test/fixtures/payment-channel-create-binary.json +0 -1
- package/test/fixtures/payment-channel-create-tx.json +0 -11
- package/test/fixtures/payment-channel-fund-binary.json +0 -1
- package/test/fixtures/payment-channel-fund-tx.json +0 -7
- package/test/fixtures/signerlistset-tx-binary.json +0 -1
- package/test/fixtures/signerlistset-tx-meta-binary.json +0 -1
- package/test/fixtures/signerlistset-tx.json +0 -94
- package/test/fixtures/ticket-create-binary.json +0 -1
- package/test/fixtures/ticket-create-tx.json +0 -7
- package/test/fixtures/x-codec-fixtures.json +0 -188
- package/test/hash.test.js +0 -135
- package/test/ledger.test.js +0 -29
- package/test/lower-case-hex.test.js +0 -46
- package/test/pseudo-transaction.test.js +0 -38
- package/test/quality.test.js +0 -15
- package/test/shamap.test.js +0 -89
- package/test/signing-data-encoding.test.js +0 -242
- package/test/tx-encode-decode.test.js +0 -119
- package/test/types.test.js +0 -34
- package/test/uint.test.js +0 -148
- package/test/utils.js +0 -30
- 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 }
|