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,33 @@
|
|
|
1
|
+
import { Hash } from './hash'
|
|
2
|
+
import { Buffer } from 'buffer/'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hash with a width of 128 bits
|
|
6
|
+
*/
|
|
7
|
+
class Hash128 extends Hash {
|
|
8
|
+
static readonly width = 16
|
|
9
|
+
static readonly ZERO_128: Hash128 = new Hash128(Buffer.alloc(Hash128.width))
|
|
10
|
+
|
|
11
|
+
constructor(bytes: Buffer) {
|
|
12
|
+
if (bytes && bytes.byteLength === 0) {
|
|
13
|
+
bytes = Hash128.ZERO_128.bytes
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
super(bytes ?? Hash128.ZERO_128.bytes)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Get the hex representation of a hash-128 bytes, allowing unset
|
|
21
|
+
*
|
|
22
|
+
* @returns hex String of this.bytes
|
|
23
|
+
*/
|
|
24
|
+
toHex(): string {
|
|
25
|
+
const hex = this.toBytes().toString('hex').toUpperCase()
|
|
26
|
+
if (/^0+$/.exec(hex)) {
|
|
27
|
+
return ''
|
|
28
|
+
}
|
|
29
|
+
return hex
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { Hash128 }
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Hash } from './hash'
|
|
2
|
+
import { Buffer } from 'buffer/'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hash with a width of 160 bits
|
|
6
|
+
*/
|
|
7
|
+
class Hash160 extends Hash {
|
|
8
|
+
static readonly width = 20
|
|
9
|
+
static readonly ZERO_160: Hash160 = new Hash160(Buffer.alloc(Hash160.width))
|
|
10
|
+
|
|
11
|
+
constructor(bytes?: Buffer) {
|
|
12
|
+
if (bytes && bytes.byteLength === 0) {
|
|
13
|
+
bytes = Hash160.ZERO_160.bytes
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
super(bytes ?? Hash160.ZERO_160.bytes)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { Hash160 }
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Hash } from './hash'
|
|
2
|
+
import { Buffer } from 'buffer/'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hash with a width of 256 bits
|
|
6
|
+
*/
|
|
7
|
+
class Hash256 extends Hash {
|
|
8
|
+
static readonly width = 32
|
|
9
|
+
static readonly ZERO_256 = new Hash256(Buffer.alloc(Hash256.width))
|
|
10
|
+
|
|
11
|
+
constructor(bytes: Buffer) {
|
|
12
|
+
super(bytes ?? Hash256.ZERO_256.bytes)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { Hash256 }
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Comparable } from './serialized-type'
|
|
2
|
+
import { BinaryParser } from '../serdes/binary-parser'
|
|
3
|
+
import { Buffer } from 'buffer/'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Base class defining how to encode and decode hashes
|
|
7
|
+
*/
|
|
8
|
+
class Hash extends Comparable {
|
|
9
|
+
static readonly width: number
|
|
10
|
+
|
|
11
|
+
constructor(bytes: Buffer) {
|
|
12
|
+
super(bytes)
|
|
13
|
+
if (this.bytes.byteLength !== (this.constructor as typeof Hash).width) {
|
|
14
|
+
throw new Error(`Invalid Hash length ${this.bytes.byteLength}`)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Construct a Hash object from an existing Hash object or a hex-string
|
|
20
|
+
*
|
|
21
|
+
* @param value A hash object or hex-string of a hash
|
|
22
|
+
*/
|
|
23
|
+
static from<T extends Hash | string>(value: T): Hash {
|
|
24
|
+
if (value instanceof this) {
|
|
25
|
+
return value
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (typeof value === 'string') {
|
|
29
|
+
return new this(Buffer.from(value, 'hex'))
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
throw new Error('Cannot construct Hash from given value')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Read a Hash object from a BinaryParser
|
|
37
|
+
*
|
|
38
|
+
* @param parser BinaryParser to read the hash from
|
|
39
|
+
* @param hint length of the bytes to read, optional
|
|
40
|
+
*/
|
|
41
|
+
static fromParser(parser: BinaryParser, hint?: number): Hash {
|
|
42
|
+
return new this(parser.read(hint ?? this.width))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Overloaded operator for comparing two hash objects
|
|
47
|
+
*
|
|
48
|
+
* @param other The Hash to compare this to
|
|
49
|
+
*/
|
|
50
|
+
compareTo(other: Hash): number {
|
|
51
|
+
return this.bytes.compare(
|
|
52
|
+
(this.constructor as typeof Hash).from(other).bytes,
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @returns the hex-string representation of this Hash
|
|
58
|
+
*/
|
|
59
|
+
toString(): string {
|
|
60
|
+
return this.toHex()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Returns four bits at the specified depth within a hash
|
|
65
|
+
*
|
|
66
|
+
* @param depth The depth of the four bits
|
|
67
|
+
* @returns The number represented by the four bits
|
|
68
|
+
*/
|
|
69
|
+
nibblet(depth: number): number {
|
|
70
|
+
const byteIx = depth > 0 ? (depth / 2) | 0 : 0
|
|
71
|
+
let b = this.bytes[byteIx]
|
|
72
|
+
if (depth % 2 === 0) {
|
|
73
|
+
b = (b & 0xf0) >>> 4
|
|
74
|
+
} else {
|
|
75
|
+
b = b & 0x0f
|
|
76
|
+
}
|
|
77
|
+
return b
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export { Hash }
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { AccountID } from './account-id'
|
|
2
|
+
import { Amount } from './amount'
|
|
3
|
+
import { Blob } from './blob'
|
|
4
|
+
import { Currency } from './currency'
|
|
5
|
+
import { Hash128 } from './hash-128'
|
|
6
|
+
import { Hash160 } from './hash-160'
|
|
7
|
+
import { Hash256 } from './hash-256'
|
|
8
|
+
import { Issue } from './issue'
|
|
9
|
+
import { PathSet } from './path-set'
|
|
10
|
+
import { STArray } from './st-array'
|
|
11
|
+
import { STObject } from './st-object'
|
|
12
|
+
import { UInt16 } from './uint-16'
|
|
13
|
+
import { UInt32 } from './uint-32'
|
|
14
|
+
import { UInt64 } from './uint-64'
|
|
15
|
+
import { UInt8 } from './uint-8'
|
|
16
|
+
import { Vector256 } from './vector-256'
|
|
17
|
+
import { type SerializedType } from './serialized-type'
|
|
18
|
+
import { DEFAULT_DEFINITIONS } from '../enums'
|
|
19
|
+
|
|
20
|
+
const coreTypes: Record<string, typeof SerializedType> = {
|
|
21
|
+
AccountID,
|
|
22
|
+
Amount,
|
|
23
|
+
Blob,
|
|
24
|
+
Currency,
|
|
25
|
+
Hash128,
|
|
26
|
+
Hash160,
|
|
27
|
+
Hash256,
|
|
28
|
+
Issue,
|
|
29
|
+
PathSet,
|
|
30
|
+
STArray,
|
|
31
|
+
STObject,
|
|
32
|
+
UInt8,
|
|
33
|
+
UInt16,
|
|
34
|
+
UInt32,
|
|
35
|
+
UInt64,
|
|
36
|
+
Vector256,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Ensures that the DEFAULT_DEFINITIONS object connects these types to fields for serializing/deserializing
|
|
40
|
+
// This is done here instead of in enums/index.ts to avoid a circular dependency
|
|
41
|
+
// because some of the above types depend on BinarySerializer which depends on enums/index.ts.
|
|
42
|
+
DEFAULT_DEFINITIONS.associateTypes(coreTypes)
|
|
43
|
+
|
|
44
|
+
export {
|
|
45
|
+
coreTypes,
|
|
46
|
+
AccountID,
|
|
47
|
+
Amount,
|
|
48
|
+
Blob,
|
|
49
|
+
Currency,
|
|
50
|
+
Hash128,
|
|
51
|
+
Hash160,
|
|
52
|
+
Hash256,
|
|
53
|
+
PathSet,
|
|
54
|
+
STArray,
|
|
55
|
+
STObject,
|
|
56
|
+
UInt8,
|
|
57
|
+
UInt16,
|
|
58
|
+
UInt32,
|
|
59
|
+
UInt64,
|
|
60
|
+
Vector256,
|
|
61
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { BinaryParser } from '../serdes/binary-parser'
|
|
2
|
+
|
|
3
|
+
import { AccountID } from './account-id'
|
|
4
|
+
import { Currency } from './currency'
|
|
5
|
+
import { JsonObject, SerializedType } from './serialized-type'
|
|
6
|
+
import { Buffer } from 'buffer/'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Interface for JSON objects that represent amounts
|
|
10
|
+
*/
|
|
11
|
+
interface IssueObject extends JsonObject {
|
|
12
|
+
currency: string
|
|
13
|
+
issuer?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Type guard for AmountObject
|
|
18
|
+
*/
|
|
19
|
+
function isIssueObject(arg): arg is IssueObject {
|
|
20
|
+
const keys = Object.keys(arg).sort()
|
|
21
|
+
if (keys.length === 1) {
|
|
22
|
+
return keys[0] === 'currency'
|
|
23
|
+
}
|
|
24
|
+
return keys.length === 2 && keys[0] === 'currency' && keys[1] === 'issuer'
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Class for serializing/Deserializing Amounts
|
|
29
|
+
*/
|
|
30
|
+
class Issue extends SerializedType {
|
|
31
|
+
static readonly ZERO_ISSUED_CURRENCY: Issue = new Issue(Buffer.alloc(20))
|
|
32
|
+
|
|
33
|
+
constructor(bytes: Buffer) {
|
|
34
|
+
super(bytes ?? Issue.ZERO_ISSUED_CURRENCY.bytes)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Construct an amount from an IOU or string amount
|
|
39
|
+
*
|
|
40
|
+
* @param value An Amount, object representing an IOU, or a string
|
|
41
|
+
* representing an integer amount
|
|
42
|
+
* @returns An Amount object
|
|
43
|
+
*/
|
|
44
|
+
static from<T extends Issue | IssueObject>(value: T): Issue {
|
|
45
|
+
if (value instanceof Issue) {
|
|
46
|
+
return value
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (isIssueObject(value)) {
|
|
50
|
+
const currency = Currency.from(value.currency).toBytes()
|
|
51
|
+
if (value.issuer == null) {
|
|
52
|
+
return new Issue(currency)
|
|
53
|
+
}
|
|
54
|
+
const issuer = AccountID.from(value.issuer).toBytes()
|
|
55
|
+
return new Issue(Buffer.concat([currency, issuer]))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
throw new Error('Invalid type to construct an Amount')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Read an amount from a BinaryParser
|
|
63
|
+
*
|
|
64
|
+
* @param parser BinaryParser to read the Amount from
|
|
65
|
+
* @returns An Amount object
|
|
66
|
+
*/
|
|
67
|
+
static fromParser(parser: BinaryParser): Issue {
|
|
68
|
+
const currency = parser.read(20)
|
|
69
|
+
if (new Currency(currency).toJSON() === 'XRP') {
|
|
70
|
+
return new Issue(currency)
|
|
71
|
+
}
|
|
72
|
+
const currencyAndIssuer = [currency, parser.read(20)]
|
|
73
|
+
return new Issue(Buffer.concat(currencyAndIssuer))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Get the JSON representation of this Amount
|
|
78
|
+
*
|
|
79
|
+
* @returns the JSON interpretation of this.bytes
|
|
80
|
+
*/
|
|
81
|
+
toJSON(): IssueObject {
|
|
82
|
+
const parser = new BinaryParser(this.toString())
|
|
83
|
+
const currency = Currency.fromParser(parser) as Currency
|
|
84
|
+
if (currency.toJSON() === 'XRP') {
|
|
85
|
+
return { currency: currency.toJSON() }
|
|
86
|
+
}
|
|
87
|
+
const issuer = AccountID.fromParser(parser) as AccountID
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
currency: currency.toJSON(),
|
|
91
|
+
issuer: issuer.toJSON(),
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export { Issue, IssueObject }
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { AccountID } from './account-id'
|
|
2
|
+
import { Currency } from './currency'
|
|
3
|
+
import { BinaryParser } from '../serdes/binary-parser'
|
|
4
|
+
import { SerializedType, JsonObject } from './serialized-type'
|
|
5
|
+
import { Buffer } from 'buffer/'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Constants for separating Paths in a PathSet
|
|
9
|
+
*/
|
|
10
|
+
const PATHSET_END_BYTE = 0x00
|
|
11
|
+
const PATH_SEPARATOR_BYTE = 0xff
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Constant for masking types of a Hop
|
|
15
|
+
*/
|
|
16
|
+
const TYPE_ACCOUNT = 0x01
|
|
17
|
+
const TYPE_CURRENCY = 0x10
|
|
18
|
+
const TYPE_ISSUER = 0x20
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The object representation of a Hop, an issuer AccountID, an account AccountID, and a Currency
|
|
22
|
+
*/
|
|
23
|
+
interface HopObject extends JsonObject {
|
|
24
|
+
issuer?: string
|
|
25
|
+
account?: string
|
|
26
|
+
currency?: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* TypeGuard for HopObject
|
|
31
|
+
*/
|
|
32
|
+
function isHopObject(arg): arg is HopObject {
|
|
33
|
+
return (
|
|
34
|
+
arg.issuer !== undefined ||
|
|
35
|
+
arg.account !== undefined ||
|
|
36
|
+
arg.currency !== undefined
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* TypeGuard for PathSet
|
|
42
|
+
*/
|
|
43
|
+
function isPathSet(arg): arg is Array<Array<HopObject>> {
|
|
44
|
+
return (
|
|
45
|
+
(Array.isArray(arg) && arg.length === 0) ||
|
|
46
|
+
(Array.isArray(arg) && Array.isArray(arg[0]) && arg[0].length === 0) ||
|
|
47
|
+
(Array.isArray(arg) && Array.isArray(arg[0]) && isHopObject(arg[0][0]))
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Serialize and Deserialize a Hop
|
|
53
|
+
*/
|
|
54
|
+
class Hop extends SerializedType {
|
|
55
|
+
/**
|
|
56
|
+
* Create a Hop from a HopObject
|
|
57
|
+
*
|
|
58
|
+
* @param value Either a hop or HopObject to create a hop with
|
|
59
|
+
* @returns a Hop
|
|
60
|
+
*/
|
|
61
|
+
static from(value: Hop | HopObject): Hop {
|
|
62
|
+
if (value instanceof Hop) {
|
|
63
|
+
return value
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const bytes: Array<Buffer> = [Buffer.from([0])]
|
|
67
|
+
|
|
68
|
+
if (value.account) {
|
|
69
|
+
bytes.push(AccountID.from(value.account).toBytes())
|
|
70
|
+
bytes[0][0] |= TYPE_ACCOUNT
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (value.currency) {
|
|
74
|
+
bytes.push(Currency.from(value.currency).toBytes())
|
|
75
|
+
bytes[0][0] |= TYPE_CURRENCY
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (value.issuer) {
|
|
79
|
+
bytes.push(AccountID.from(value.issuer).toBytes())
|
|
80
|
+
bytes[0][0] |= TYPE_ISSUER
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return new Hop(Buffer.concat(bytes))
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Construct a Hop from a BinaryParser
|
|
88
|
+
*
|
|
89
|
+
* @param parser BinaryParser to read the Hop from
|
|
90
|
+
* @returns a Hop
|
|
91
|
+
*/
|
|
92
|
+
static fromParser(parser: BinaryParser): Hop {
|
|
93
|
+
const type = parser.readUInt8()
|
|
94
|
+
const bytes: Array<Buffer> = [Buffer.from([type])]
|
|
95
|
+
|
|
96
|
+
if (type & TYPE_ACCOUNT) {
|
|
97
|
+
bytes.push(parser.read(AccountID.width))
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (type & TYPE_CURRENCY) {
|
|
101
|
+
bytes.push(parser.read(Currency.width))
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (type & TYPE_ISSUER) {
|
|
105
|
+
bytes.push(parser.read(AccountID.width))
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return new Hop(Buffer.concat(bytes))
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Get the JSON interpretation of this hop
|
|
113
|
+
*
|
|
114
|
+
* @returns a HopObject, an JS object with optional account, issuer, and currency
|
|
115
|
+
*/
|
|
116
|
+
toJSON(): HopObject {
|
|
117
|
+
const hopParser = new BinaryParser(this.bytes.toString('hex'))
|
|
118
|
+
const type = hopParser.readUInt8()
|
|
119
|
+
|
|
120
|
+
let account, currency, issuer
|
|
121
|
+
if (type & TYPE_ACCOUNT) {
|
|
122
|
+
account = (AccountID.fromParser(hopParser) as AccountID).toJSON()
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (type & TYPE_CURRENCY) {
|
|
126
|
+
currency = (Currency.fromParser(hopParser) as Currency).toJSON()
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (type & TYPE_ISSUER) {
|
|
130
|
+
issuer = (AccountID.fromParser(hopParser) as AccountID).toJSON()
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const result: HopObject = {}
|
|
134
|
+
if (account) {
|
|
135
|
+
result.account = account
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (issuer) {
|
|
139
|
+
result.issuer = issuer
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (currency) {
|
|
143
|
+
result.currency = currency
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return result
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* get a number representing the type of this hop
|
|
151
|
+
*
|
|
152
|
+
* @returns a number to be bitwise and-ed with TYPE_ constants to describe the types in the hop
|
|
153
|
+
*/
|
|
154
|
+
type(): number {
|
|
155
|
+
return this.bytes[0]
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Class for serializing/deserializing Paths
|
|
161
|
+
*/
|
|
162
|
+
class Path extends SerializedType {
|
|
163
|
+
/**
|
|
164
|
+
* construct a Path from an array of Hops
|
|
165
|
+
*
|
|
166
|
+
* @param value Path or array of HopObjects to construct a Path
|
|
167
|
+
* @returns the Path
|
|
168
|
+
*/
|
|
169
|
+
static from(value: Path | Array<HopObject>): Path {
|
|
170
|
+
if (value instanceof Path) {
|
|
171
|
+
return value
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const bytes: Array<Buffer> = []
|
|
175
|
+
value.forEach((hop: HopObject) => {
|
|
176
|
+
bytes.push(Hop.from(hop).toBytes())
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
return new Path(Buffer.concat(bytes))
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Read a Path from a BinaryParser
|
|
184
|
+
*
|
|
185
|
+
* @param parser BinaryParser to read Path from
|
|
186
|
+
* @returns the Path represented by the bytes read from the BinaryParser
|
|
187
|
+
*/
|
|
188
|
+
static fromParser(parser: BinaryParser): Path {
|
|
189
|
+
const bytes: Array<Buffer> = []
|
|
190
|
+
while (!parser.end()) {
|
|
191
|
+
bytes.push(Hop.fromParser(parser).toBytes())
|
|
192
|
+
|
|
193
|
+
if (
|
|
194
|
+
parser.peek() === PATHSET_END_BYTE ||
|
|
195
|
+
parser.peek() === PATH_SEPARATOR_BYTE
|
|
196
|
+
) {
|
|
197
|
+
break
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return new Path(Buffer.concat(bytes))
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get the JSON representation of this Path
|
|
205
|
+
*
|
|
206
|
+
* @returns an Array of HopObject constructed from this.bytes
|
|
207
|
+
*/
|
|
208
|
+
toJSON(): Array<HopObject> {
|
|
209
|
+
const json: Array<HopObject> = []
|
|
210
|
+
const pathParser = new BinaryParser(this.toString())
|
|
211
|
+
|
|
212
|
+
while (!pathParser.end()) {
|
|
213
|
+
json.push(Hop.fromParser(pathParser).toJSON())
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return json
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Deserialize and Serialize the PathSet type
|
|
222
|
+
*/
|
|
223
|
+
class PathSet extends SerializedType {
|
|
224
|
+
/**
|
|
225
|
+
* Construct a PathSet from an Array of Arrays representing paths
|
|
226
|
+
*
|
|
227
|
+
* @param value A PathSet or Array of Array of HopObjects
|
|
228
|
+
* @returns the PathSet constructed from value
|
|
229
|
+
*/
|
|
230
|
+
static from<T extends PathSet | Array<Array<HopObject>>>(value: T): PathSet {
|
|
231
|
+
if (value instanceof PathSet) {
|
|
232
|
+
return value
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (isPathSet(value)) {
|
|
236
|
+
const bytes: Array<Buffer> = []
|
|
237
|
+
|
|
238
|
+
value.forEach((path: Array<HopObject>) => {
|
|
239
|
+
bytes.push(Path.from(path).toBytes())
|
|
240
|
+
bytes.push(Buffer.from([PATH_SEPARATOR_BYTE]))
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
bytes[bytes.length - 1] = Buffer.from([PATHSET_END_BYTE])
|
|
244
|
+
|
|
245
|
+
return new PathSet(Buffer.concat(bytes))
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
throw new Error('Cannot construct PathSet from given value')
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Construct a PathSet from a BinaryParser
|
|
253
|
+
*
|
|
254
|
+
* @param parser A BinaryParser to read PathSet from
|
|
255
|
+
* @returns the PathSet read from parser
|
|
256
|
+
*/
|
|
257
|
+
static fromParser(parser: BinaryParser): PathSet {
|
|
258
|
+
const bytes: Array<Buffer> = []
|
|
259
|
+
|
|
260
|
+
while (!parser.end()) {
|
|
261
|
+
bytes.push(Path.fromParser(parser).toBytes())
|
|
262
|
+
bytes.push(parser.read(1))
|
|
263
|
+
|
|
264
|
+
if (bytes[bytes.length - 1][0] == PATHSET_END_BYTE) {
|
|
265
|
+
break
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return new PathSet(Buffer.concat(bytes))
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Get the JSON representation of this PathSet
|
|
274
|
+
*
|
|
275
|
+
* @returns an Array of Array of HopObjects, representing this PathSet
|
|
276
|
+
*/
|
|
277
|
+
toJSON(): Array<Array<HopObject>> {
|
|
278
|
+
const json: Array<Array<HopObject>> = []
|
|
279
|
+
const pathParser = new BinaryParser(this.toString())
|
|
280
|
+
|
|
281
|
+
while (!pathParser.end()) {
|
|
282
|
+
json.push(Path.fromParser(pathParser).toJSON())
|
|
283
|
+
pathParser.skip(1)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return json
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export { PathSet }
|