mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-20 12:15:51 +00:00
Refactor ./src/types Hash and derived types (#82)
Refactored Hash and derived types.
This commit is contained in:
@@ -1,45 +1,58 @@
|
||||
import { makeClass } from "../utils/make-class";
|
||||
const { decodeAccountID, encodeAccountID } = require("ripple-address-codec");
|
||||
const { Hash160 } = require("./hash-160");
|
||||
import { decodeAccountID, encodeAccountID } from "ripple-address-codec";
|
||||
import { Hash160 } from "./hash-160";
|
||||
|
||||
const AccountID = makeClass(
|
||||
{
|
||||
AccountID(bytes) {
|
||||
Hash160.call(this, bytes);
|
||||
},
|
||||
inherits: Hash160,
|
||||
statics: {
|
||||
from(value) {
|
||||
return value instanceof this
|
||||
? value
|
||||
: /^r/.test(value)
|
||||
? this.fromBase58(value)
|
||||
: new this(value);
|
||||
},
|
||||
cache: {},
|
||||
fromCache(base58) {
|
||||
let cached = this.cache[base58];
|
||||
if (!cached) {
|
||||
cached = this.cache[base58] = this.fromBase58(base58);
|
||||
}
|
||||
return cached;
|
||||
},
|
||||
fromBase58(value) {
|
||||
const acc = new this(decodeAccountID(value));
|
||||
acc._toBase58 = value;
|
||||
return acc;
|
||||
},
|
||||
},
|
||||
toJSON() {
|
||||
return this.toBase58();
|
||||
},
|
||||
cached: {
|
||||
toBase58() {
|
||||
return encodeAccountID(this._bytes);
|
||||
},
|
||||
},
|
||||
},
|
||||
undefined
|
||||
);
|
||||
/**
|
||||
* Class defining how to encode and decode an AccountID
|
||||
*/
|
||||
class AccountID extends Hash160 {
|
||||
static readonly defaultAccountID: AccountID = new AccountID(Buffer.alloc(20));
|
||||
|
||||
constructor(bytes: Buffer) {
|
||||
super(bytes ?? AccountID.defaultAccountID.bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines how to construct an AccountID
|
||||
*
|
||||
* @param value either an existing AccountID, a hex-string, or a base58 r-Address
|
||||
* @returns an AccountID object
|
||||
*/
|
||||
static from(value: AccountID | string): AccountID {
|
||||
if (value instanceof this) {
|
||||
return value;
|
||||
}
|
||||
return /^r/.test(value)
|
||||
? this.fromBase58(value)
|
||||
: new AccountID(Buffer.from(value, "hex"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines how to build an AccountID from a base58 r-Address
|
||||
*
|
||||
* @param value a base58 r-Address
|
||||
* @returns an AccountID object
|
||||
*/
|
||||
static fromBase58(value: string): AccountID {
|
||||
return new AccountID(decodeAccountID(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload of toJSON
|
||||
*
|
||||
* @returns the base58 string for this AccountID
|
||||
*/
|
||||
toJSON(): string {
|
||||
return this.toBase58();
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines how to encode AccountID into a base58 address
|
||||
*
|
||||
* @returns the base58 string defined by this.bytes
|
||||
*/
|
||||
toBase58(): string {
|
||||
return encodeAccountID(this.bytes);
|
||||
}
|
||||
}
|
||||
|
||||
export { AccountID };
|
||||
|
||||
@@ -1,30 +1,34 @@
|
||||
import { makeClass } from "../utils/make-class";
|
||||
import { parseBytes } from "../utils/bytes-utils";
|
||||
import { SerializedType } from "./serialized-type";
|
||||
import { SerializedTypeClass } from "./serialized-type";
|
||||
import { BinaryParser } from "../serdes/binary-parser";
|
||||
|
||||
const Blob = makeClass(
|
||||
{
|
||||
mixins: SerializedType,
|
||||
Blob(bytes) {
|
||||
if (bytes) {
|
||||
this._bytes = parseBytes(bytes, Uint8Array);
|
||||
} else {
|
||||
this._bytes = new Uint8Array(0);
|
||||
}
|
||||
},
|
||||
statics: {
|
||||
fromParser(parser, hint) {
|
||||
return new this(parser.read(hint));
|
||||
},
|
||||
from(value) {
|
||||
if (value instanceof this) {
|
||||
return value;
|
||||
}
|
||||
return new this(value);
|
||||
},
|
||||
},
|
||||
},
|
||||
undefined
|
||||
);
|
||||
/**
|
||||
* Variable length encoded type
|
||||
*/
|
||||
class Blob extends SerializedTypeClass {
|
||||
constructor(bytes: Buffer) {
|
||||
super(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines how to read a Blob from a BinaryParser
|
||||
*
|
||||
* @param parser The binary parser to read the Blob from
|
||||
* @param hint The length of the blob, computed by readVariableLengthLength() and passed in
|
||||
* @returns A Blob object
|
||||
*/
|
||||
static fromParser(parser: BinaryParser, hint: number): Blob {
|
||||
return new Blob(parser.read(hint));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Blob object from a hex-string
|
||||
*
|
||||
* @param value existing Blob object or a hex-string
|
||||
* @returns A Blob object
|
||||
*/
|
||||
static from(value: Blob | string): Blob {
|
||||
return value instanceof Blob ? value : new Blob(Buffer.from(value, "hex"));
|
||||
}
|
||||
}
|
||||
|
||||
export { Blob };
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { makeClass } from "../utils/make-class";
|
||||
const _ = require("lodash");
|
||||
const { slice } = require("../utils/bytes-utils");
|
||||
const { Hash160 } = require("./hash-160");
|
||||
import { Hash160 } from "./hash-160";
|
||||
const ISO_REGEX = /^[A-Z0-9]{3}$/;
|
||||
const HEX_REGEX = /^[A-F0-9]{40}$/;
|
||||
|
||||
function isoToBytes(iso) {
|
||||
const bytes = new Uint8Array(20);
|
||||
/**
|
||||
* Convert an ISO code to a currency bytes representation
|
||||
*/
|
||||
function isoToBytes(iso: string): Buffer {
|
||||
const bytes = Buffer.alloc(20);
|
||||
if (iso !== "XRP") {
|
||||
const isoBytes = iso.split("").map((c) => c.charCodeAt(0));
|
||||
bytes.set(isoBytes, 12);
|
||||
@@ -14,80 +14,123 @@ function isoToBytes(iso) {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function isISOCode(val) {
|
||||
return val.length === 3; // ISO_REGEX.test(val);
|
||||
/**
|
||||
* Tests if ISO is a valid iso code
|
||||
*/
|
||||
function isIsoCode(iso: string): boolean {
|
||||
return ISO_REGEX.test(iso);
|
||||
}
|
||||
|
||||
function isHex(val) {
|
||||
return HEX_REGEX.test(val);
|
||||
/**
|
||||
* Tests if hex is a valid hex-string
|
||||
*/
|
||||
function isHex(hex: string): boolean {
|
||||
return HEX_REGEX.test(hex);
|
||||
}
|
||||
|
||||
function isStringRepr(val) {
|
||||
return _.isString(val) && (isISOCode(val) || isHex(val));
|
||||
/**
|
||||
* Tests if a string is a valid representation of a currency
|
||||
*/
|
||||
function isStringRepresentation(input: string): boolean {
|
||||
return isIsoCode(input) || isHex(input);
|
||||
}
|
||||
|
||||
function isBytesArray(val) {
|
||||
return val.length === 20;
|
||||
/**
|
||||
* Tests if a Buffer is a valid representation of a currency
|
||||
*/
|
||||
function isBytesArray(bytes: Buffer): boolean {
|
||||
return bytes.byteLength === 20;
|
||||
}
|
||||
|
||||
function isValidRepr(val) {
|
||||
return isStringRepr(val) || isBytesArray(val);
|
||||
/**
|
||||
* Ensures that a value is a valid representation of a currency
|
||||
*/
|
||||
function isValidRepresentation(input: Buffer | string): boolean {
|
||||
return input instanceof Buffer
|
||||
? isBytesArray(input)
|
||||
: isStringRepresentation(input);
|
||||
}
|
||||
|
||||
function bytesFromRepr(val) {
|
||||
if (isValidRepr(val)) {
|
||||
// We assume at this point that we have an object with a length, either 3,
|
||||
// 20 or 40.
|
||||
return val.length === 3 ? isoToBytes(val) : val;
|
||||
/**
|
||||
* Generate bytes from a string or buffer representation of a currency
|
||||
*/
|
||||
function bytesFromRepresentation(input: string): Buffer {
|
||||
if (!isValidRepresentation(input)) {
|
||||
throw new Error(`Unsupported Currency representation: ${input}`);
|
||||
}
|
||||
throw new Error(`Unsupported Currency repr: ${val}`);
|
||||
return input.length === 3 ? isoToBytes(input) : Buffer.from(input, "hex");
|
||||
}
|
||||
|
||||
const $uper = Hash160.prototype;
|
||||
const Currency = makeClass(
|
||||
{
|
||||
inherits: Hash160,
|
||||
getters: ["isNative", "iso"],
|
||||
statics: {
|
||||
init() {
|
||||
this.XRP = new this(new Uint8Array(20));
|
||||
},
|
||||
from(val) {
|
||||
return val instanceof this ? val : new this(bytesFromRepr(val));
|
||||
},
|
||||
},
|
||||
Currency(bytes) {
|
||||
Hash160.call(this, bytes);
|
||||
this.classify();
|
||||
},
|
||||
classify() {
|
||||
// We only have a non null iso() property available if the currency can be
|
||||
// losslessly represented by the 3 letter iso code. If none is available a
|
||||
// hex encoding of the full 20 bytes is the canonical representation.
|
||||
let onlyISO = true;
|
||||
/**
|
||||
* Class defining how to encode and decode Currencies
|
||||
*/
|
||||
class Currency extends Hash160 {
|
||||
static readonly XRP = new Currency(Buffer.alloc(20));
|
||||
private readonly _iso?: string;
|
||||
private readonly _isNative: boolean;
|
||||
|
||||
const bytes = this._bytes;
|
||||
const code = slice(this._bytes, 12, 15, Array);
|
||||
const iso = code.map((c) => String.fromCharCode(c)).join("");
|
||||
constructor(byteBuf: Buffer) {
|
||||
super(byteBuf ?? Currency.XRP.bytes);
|
||||
|
||||
for (let i = bytes.length - 1; i >= 0; i--) {
|
||||
if (bytes[i] !== 0 && !(i === 12 || i === 13 || i === 14)) {
|
||||
onlyISO = false;
|
||||
break;
|
||||
}
|
||||
let onlyISO = true;
|
||||
|
||||
const bytes = this.bytes;
|
||||
const code = this.bytes.slice(12, 15);
|
||||
const iso = code.toString();
|
||||
|
||||
for (let i = bytes.length - 1; i >= 0; i--) {
|
||||
if (bytes[i] !== 0 && !(i === 12 || i === 13 || i === 14)) {
|
||||
onlyISO = false;
|
||||
break;
|
||||
}
|
||||
const lossLessISO = onlyISO && iso !== "XRP" && ISO_REGEX.test(iso);
|
||||
this._isNative = onlyISO && _.isEqual(code, [0, 0, 0]);
|
||||
this._iso = this._isNative ? "XRP" : lossLessISO ? iso : null;
|
||||
},
|
||||
toJSON() {
|
||||
if (this.iso()) {
|
||||
return this.iso();
|
||||
}
|
||||
return $uper.toJSON.call(this);
|
||||
},
|
||||
},
|
||||
undefined
|
||||
);
|
||||
}
|
||||
|
||||
const lossLessISO = onlyISO && iso !== "XRP" && ISO_REGEX.test(iso);
|
||||
this._isNative = onlyISO && code.toString("hex") === "000000";
|
||||
this._iso = this._isNative ? "XRP" : lossLessISO ? iso : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if this currency is native
|
||||
*
|
||||
* @returns true if native, false if not
|
||||
*/
|
||||
isNative(): boolean {
|
||||
return this._isNative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ISO code of this currency
|
||||
*
|
||||
* @returns ISO code if it exists, else undefined
|
||||
*/
|
||||
iso(): string | undefined {
|
||||
return this._iso;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a Currency object
|
||||
*
|
||||
* @param val Currency object or a string representation of a currency
|
||||
*/
|
||||
static from(val: Currency | string): Currency {
|
||||
return val instanceof this
|
||||
? val
|
||||
: new Currency(bytesFromRepresentation(val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the JSON representation of a currency
|
||||
*
|
||||
* @returns JSON representation
|
||||
*/
|
||||
toJSON(): string {
|
||||
const iso = this.iso();
|
||||
if (iso !== undefined) {
|
||||
return iso;
|
||||
}
|
||||
return this.bytes.toString("hex").toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
export { Currency };
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { makeClass } from "../utils/make-class";
|
||||
import { Hash } from "./hash";
|
||||
|
||||
const Hash128 = makeClass(
|
||||
{
|
||||
inherits: Hash,
|
||||
statics: { width: 16 },
|
||||
},
|
||||
undefined
|
||||
);
|
||||
/**
|
||||
* Hash with a width of 128 bits
|
||||
*/
|
||||
class Hash128 extends Hash {
|
||||
static readonly width = 16;
|
||||
static readonly ZERO_128: Hash128 = new Hash128(Buffer.alloc(Hash128.width));
|
||||
|
||||
constructor(bytes: Buffer) {
|
||||
super(bytes ?? Hash128.ZERO_128.bytes);
|
||||
}
|
||||
}
|
||||
|
||||
export { Hash128 };
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { makeClass } from "../utils/make-class";
|
||||
const { Hash } = require("./hash");
|
||||
import { Hash } from "./hash";
|
||||
|
||||
const Hash160 = makeClass(
|
||||
{
|
||||
inherits: Hash,
|
||||
statics: { width: 20 },
|
||||
},
|
||||
undefined
|
||||
);
|
||||
/**
|
||||
* Hash with a width of 160 bits
|
||||
*/
|
||||
class Hash160 extends Hash {
|
||||
static readonly width = 20;
|
||||
static readonly ZERO_160: Hash160 = new Hash160(Buffer.alloc(Hash160.width));
|
||||
|
||||
constructor(bytes: Buffer) {
|
||||
super(bytes ?? Hash160.ZERO_160.bytes);
|
||||
}
|
||||
}
|
||||
|
||||
export { Hash160 };
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
import { makeClass } from "../utils/make-class";
|
||||
import { Hash } from "./hash";
|
||||
|
||||
const Hash256 = makeClass(
|
||||
{
|
||||
inherits: Hash,
|
||||
statics: {
|
||||
width: 32,
|
||||
init() {
|
||||
this.ZERO_256 = new this(new Uint8Array(this.width));
|
||||
},
|
||||
},
|
||||
},
|
||||
undefined
|
||||
);
|
||||
/**
|
||||
* Hash with a width of 256 bits
|
||||
*/
|
||||
class Hash256 extends Hash {
|
||||
static readonly width = 32;
|
||||
static readonly ZERO_256 = new Hash256(Buffer.alloc(Hash256.width));
|
||||
|
||||
constructor(bytes: Buffer) {
|
||||
super(bytes ?? Hash256.ZERO_256.bytes);
|
||||
}
|
||||
}
|
||||
|
||||
export { Hash256 };
|
||||
|
||||
@@ -1,48 +1,70 @@
|
||||
import * as assert from "assert";
|
||||
import { makeClass } from "../utils/make-class";
|
||||
import { Comparable, SerializedType } from "./serialized-type";
|
||||
import { compareBytes, parseBytes } from "../utils/bytes-utils";
|
||||
import { ComparableClass } from "./serialized-type";
|
||||
import { BinaryParser } from "../serdes/binary-parser";
|
||||
|
||||
const Hash = makeClass(
|
||||
{
|
||||
Hash(bytes) {
|
||||
const width = this.constructor.width;
|
||||
this._bytes = bytes
|
||||
? parseBytes(bytes, Uint8Array)
|
||||
: new Uint8Array(width);
|
||||
assert.equal(this._bytes.length, width);
|
||||
},
|
||||
mixins: [Comparable, SerializedType],
|
||||
statics: {
|
||||
width: NaN,
|
||||
from(value) {
|
||||
if (value instanceof this) {
|
||||
return value;
|
||||
}
|
||||
return new this(parseBytes(value));
|
||||
},
|
||||
fromParser(parser, hint) {
|
||||
return new this(parser.read(hint || this.width));
|
||||
},
|
||||
},
|
||||
compareTo(other) {
|
||||
return compareBytes(this._bytes, this.constructor.from(other)._bytes);
|
||||
},
|
||||
toString() {
|
||||
return this.toHex();
|
||||
},
|
||||
nibblet(depth) {
|
||||
const byteIx = depth > 0 ? (depth / 2) | 0 : 0;
|
||||
let b = this._bytes[byteIx];
|
||||
if (depth % 2 === 0) {
|
||||
b = (b & 0xf0) >>> 4;
|
||||
} else {
|
||||
b = b & 0x0f;
|
||||
}
|
||||
return b;
|
||||
},
|
||||
},
|
||||
undefined
|
||||
);
|
||||
/**
|
||||
* Base class defining how to encode and decode hashes
|
||||
*/
|
||||
class Hash extends ComparableClass {
|
||||
static readonly width: number;
|
||||
|
||||
constructor(bytes: Buffer) {
|
||||
super(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a Hash object from an existing Hash object or a hex-string
|
||||
*
|
||||
* @param value A hash object or hex-string of a hash
|
||||
*/
|
||||
static from(value: Hash | string): Hash {
|
||||
return value instanceof this ? value : new this(Buffer.from(value, "hex"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a Hash object from a BinaryParser
|
||||
*
|
||||
* @param parser BinaryParser to read the hash from
|
||||
* @param hint length of the bytes to read, optional
|
||||
*/
|
||||
static fromParser(parser: BinaryParser, hint?: number): Hash {
|
||||
return new this(parser.read(hint ?? this.width));
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloaded operator for comparing two hash objects
|
||||
*
|
||||
* @param other The Hash to compare this to
|
||||
*/
|
||||
compareTo(other: Hash): number {
|
||||
return Buffer.compare(
|
||||
this.bytes,
|
||||
(this.constructor as typeof Hash).from(other).bytes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns the hex-string representation of this Hash
|
||||
*/
|
||||
toString(): string {
|
||||
return this.toHex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns four bits at the specified depth within a hash
|
||||
*
|
||||
* @param depth The depth of the four bits
|
||||
* @returns The number represented by the four bits
|
||||
*/
|
||||
nibblet(depth: number): number {
|
||||
const byteIx = depth > 0 ? (depth / 2) | 0 : 0;
|
||||
let b = this.bytes[byteIx];
|
||||
if (depth % 2 === 0) {
|
||||
b = (b & 0xf0) >>> 4;
|
||||
} else {
|
||||
b = b & 0x0f;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
export { Hash };
|
||||
|
||||
@@ -1,6 +1,100 @@
|
||||
import { BytesList } from "../serdes/binary-serializer";
|
||||
const { bytesToHex, slice } = require("../utils/bytes-utils");
|
||||
|
||||
/**
|
||||
* The base class for all binary-codec types
|
||||
*/
|
||||
class SerializedTypeClass {
|
||||
protected readonly bytes: Buffer = Buffer.alloc(0);
|
||||
|
||||
constructor(bytes: Buffer) {
|
||||
this.bytes = bytes ?? Buffer.alloc(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the bytes representation of a SerializedType to a BytesList
|
||||
*
|
||||
* @param list The BytesList to write SerializedType bytes to
|
||||
*/
|
||||
toBytesSink(list: BytesList): void {
|
||||
list.put(this.bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hex representation of a SerializedType's bytes
|
||||
*
|
||||
* @returns hex String of this.bytes
|
||||
*/
|
||||
toHex(): string {
|
||||
return this.toBytes().toString("hex").toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bytes representation of a SerializedType
|
||||
*
|
||||
* @returns A buffer of the bytes
|
||||
*/
|
||||
toBytes(): Buffer {
|
||||
if (this.bytes) {
|
||||
return this.bytes;
|
||||
}
|
||||
const bytes = new BytesList();
|
||||
this.toBytesSink(bytes);
|
||||
return bytes.toBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JSON representation of a SerializedType
|
||||
*
|
||||
* @returns any type, if not overloaded returns hexString representation of bytes
|
||||
*/
|
||||
toJSON(): any {
|
||||
return this.toHex();
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns hexString representation of this.bytes
|
||||
*/
|
||||
toString(): string {
|
||||
return this.toHex();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for SerializedTypes that are comparable
|
||||
*/
|
||||
class ComparableClass extends SerializedTypeClass {
|
||||
lt(other: ComparableClass): boolean {
|
||||
return this.compareTo(other) < 0;
|
||||
}
|
||||
|
||||
eq(other: ComparableClass): boolean {
|
||||
return this.compareTo(other) === 0;
|
||||
}
|
||||
|
||||
gt(other: ComparableClass): boolean {
|
||||
return this.compareTo(other) > 0;
|
||||
}
|
||||
|
||||
gte(other: ComparableClass): boolean {
|
||||
return this.compareTo(other) > -1;
|
||||
}
|
||||
|
||||
lte(other: ComparableClass): boolean {
|
||||
return this.compareTo(other) < 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload this method to define how two Comparable SerializedTypes are compared
|
||||
*
|
||||
* @param other The comparable object to compare this to
|
||||
* @returns A number denoting the relationship of this and other
|
||||
*/
|
||||
compareTo(other: ComparableClass): number {
|
||||
throw new Error("cannot compare " + this + " and " + other);
|
||||
}
|
||||
}
|
||||
|
||||
const Comparable = {
|
||||
lt(other) {
|
||||
return this.compareTo(other) < 0;
|
||||
@@ -57,4 +151,10 @@ function ensureArrayLikeIs(Type, arrayLike) {
|
||||
};
|
||||
}
|
||||
|
||||
export { ensureArrayLikeIs, SerializedType, Comparable };
|
||||
export {
|
||||
ensureArrayLikeIs,
|
||||
SerializedType,
|
||||
SerializedTypeClass,
|
||||
Comparable,
|
||||
ComparableClass,
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const { coreTypes } = require('../dist/types')
|
||||
const { Hash160, Hash256, Currency, AccountID } = coreTypes
|
||||
const { Hash160, Hash256, AccountID, Currency } = coreTypes
|
||||
|
||||
describe('Hash160', function () {
|
||||
test('has a static width membmer', function () {
|
||||
test('has a static width member', function () {
|
||||
expect(Hash160.width).toBe(20)
|
||||
})
|
||||
test('inherited by subclasses', function () {
|
||||
@@ -39,16 +39,16 @@ describe('Hash256', function () {
|
||||
|
||||
describe('Currency', function () {
|
||||
test('Will have a null iso() for dodgy XRP ', function () {
|
||||
const bad = Currency.from('0000000000000000000000005852500000000000')
|
||||
expect(bad.iso()).toBeNull()
|
||||
const bad = Currency.from('0000000000000000000000005852500000000000',)
|
||||
expect(bad.iso()).toBeUndefined()
|
||||
expect(bad.isNative()).toBe(false)
|
||||
})
|
||||
test('can be constructed from an Array', function () {
|
||||
const xrp = Currency.from(new Uint8Array(20))
|
||||
test('can be constructed from a Buffer', function () {
|
||||
const xrp = new Currency(Buffer.alloc(20))
|
||||
expect(xrp.iso()).toBe('XRP')
|
||||
})
|
||||
test('throws on invalid reprs', function () {
|
||||
expect(() => Currency.from(new Uint8Array(19))).toThrow()
|
||||
expect(() => Currency.from(Buffer.alloc(19))).toThrow()
|
||||
expect(() => Currency.from(1)).toThrow()
|
||||
expect(() => Currency.from(
|
||||
'00000000000000000000000000000000000000m')).toThrow()
|
||||
|
||||
Reference in New Issue
Block a user