Linter config lints test directory (#99)

Modify eslint config to lint ./test/
This commit is contained in:
Nathan Nichols
2020-08-21 17:04:14 -05:00
parent 7438640753
commit b14f055c6c
20 changed files with 1129 additions and 1066 deletions

View File

@@ -26,6 +26,7 @@ module.exports = {
'@typescript-eslint', // Add some TypeScript specific rules, and disable rules covered by the typechecker '@typescript-eslint', // Add some TypeScript specific rules, and disable rules covered by the typechecker
'import', // Add rules that help validate proper imports 'import', // Add rules that help validate proper imports
'prettier', // Allows running prettier as an ESLint rule, and reporting differences as individual linting issues 'prettier', // Allows running prettier as an ESLint rule, and reporting differences as individual linting issues
'jest'
], ],
extends: [ extends: [
@@ -58,16 +59,24 @@ module.exports = {
overrides: [ overrides: [
// Overrides for all test files // Overrides for all test files
{ {
files: 'test/**/*.ts', files: 'test/**/*.test.js',
extends: ["plugin:jest/recommended"],
rules: { rules: {
// For our Mocha test files, the pattern has been to have unnamed functions // For our Mocha test files, the pattern has been to have unnamed functions
'func-names': 'off', 'func-names': 'off',
// Using non-null assertions (obj!.property) cancels the benefits of the strict null-checking mode, but these are test files, so we don't care.
'@typescript-eslint/no-non-null-assertion': 'off',
// For some test files, we shadow testing constants with function parameter names // For some test files, we shadow testing constants with function parameter names
'no-shadow': 'off', 'no-shadow': 'off',
// Some of our test files declare helper classes with errors // Some of our test files declare helper classes with errors
'max-classes-per-file': 'off', 'max-classes-per-file': 'off',
// Test files are in javascript, turn off TypeScript linting.
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/restrict-template-expressions': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/restrict-template-expressions': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/unbound-method': 'off'
}, },
}, },
{ {
@@ -79,6 +88,8 @@ module.exports = {
{ argsIgnorePattern: '^_' }, { argsIgnorePattern: '^_' },
], ],
'@typescript-eslint/ban-types': 'off',
// These rules are deprecated, but we have an old config that enables it // These rules are deprecated, but we have an old config that enables it
'@typescript-eslint/camelcase': 'off', '@typescript-eslint/camelcase': 'off',
'@typescript-eslint/ban-ts-ignore': 'off', '@typescript-eslint/ban-ts-ignore': 'off',
@@ -87,7 +98,6 @@ module.exports = {
'@typescript-eslint/no-unsafe-call': 'off', '@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off', '@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off', '@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/ban-types': 'off',
"spaced-comment": ["error", "always"], "spaced-comment": ["error", "always"],
}, },
}, },

View File

@@ -22,20 +22,21 @@
"@types/node": "^14.0.10", "@types/node": "^14.0.10",
"@typescript-eslint/eslint-plugin": "^3.2.0", "@typescript-eslint/eslint-plugin": "^3.2.0",
"@typescript-eslint/parser": "^3.2.0", "@typescript-eslint/parser": "^3.2.0",
"eslint": "^7.2.0", "eslint": "^7.7.0",
"eslint-config-prettier": "^6.11.0", "eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.21.1", "eslint-plugin-import": "^2.21.1",
"eslint-plugin-jest": "^23.20.0",
"eslint-plugin-mocha": "^7.0.1", "eslint-plugin-mocha": "^7.0.1",
"eslint-plugin-prettier": "^3.1.3", "eslint-plugin-prettier": "^3.1.3",
"prettier": "^2.0.4",
"jest": "^26.0.1", "jest": "^26.0.1",
"prettier": "^2.0.4",
"typescript": "^3.9.5" "typescript": "^3.9.5"
}, },
"scripts": { "scripts": {
"compile": "tsc && cp ./src/enums/definitions.json ./dist/enums", "compile": "tsc && cp ./src/enums/definitions.json ./dist/enums",
"prepare": "npm run compile && npm test", "prepare": "npm run compile && npm test",
"test": "jest", "test": "jest",
"lint": "eslint . --ext .ts --fix" "lint": "eslint . --ext .ts --ext .test.js"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@@ -1,42 +1,43 @@
const _ = require('lodash') const { loadFixture } = require("./utils");
const { loadFixture } = require('./utils') const { coreTypes } = require("../dist/types");
const { coreTypes } = require('../dist/types') const { Amount } = coreTypes;
const { Amount } = coreTypes const fixtures = loadFixture("data-driven-tests.json");
const fixtures = loadFixture('data-driven-tests.json')
function amountErrorTests () { function amountErrorTests() {
fixtures.values_tests.filter(obj => obj.type === 'Amount').forEach(f => { fixtures.values_tests
.filter((obj) => obj.type === "Amount")
.forEach((f) => {
// We only want these with errors // We only want these with errors
if (!f.error) { if (!f.error) {
return return;
} }
const testName = `${JSON.stringify(f.test_json)}\n\tis invalid ` + const testName =
`because: ${f.error}` `${JSON.stringify(f.test_json)}\n\tis invalid ` + `because: ${f.error}`;
it(testName, () => { it(testName, () => {
expect(() => { expect(() => {
Amount.from(f.test_json) Amount.from(f.test_json);
JSON.stringify(f.test_json) JSON.stringify(f.test_json);
}).toThrow() }).toThrow();
}) });
}) });
} }
describe('Amount', function () { describe("Amount", function () {
it('can be parsed from', function () { it("can be parsed from", function () {
expect(Amount.from('1000000') instanceof Amount).toBe(true) expect(Amount.from("1000000") instanceof Amount).toBe(true);
expect(Amount.from('1000000').toJSON()).toEqual('1000000') expect(Amount.from("1000000").toJSON()).toEqual("1000000");
const fixture = { const fixture = {
value: '1', value: "1",
issuer: '0000000000000000000000000000000000000000', issuer: "0000000000000000000000000000000000000000",
currency: 'USD' currency: "USD",
} };
const amt = Amount.from(fixture) const amt = Amount.from(fixture);
const rewritten = { const rewritten = {
value: '1', value: "1",
issuer: 'rrrrrrrrrrrrrrrrrrrrrhoLvTp', issuer: "rrrrrrrrrrrrrrrrrrrrrhoLvTp",
currency: 'USD' currency: "USD",
} };
expect(amt.toJSON()).toEqual(rewritten) expect(amt.toJSON()).toEqual(rewritten);
}) });
amountErrorTests() amountErrorTests();
}) });

View File

@@ -1,44 +1,47 @@
const fixtures = require('./fixtures/codec-fixtures.json') const fixtures = require("./fixtures/codec-fixtures.json");
const { decode, encode, decodeLedgerData } = require('../dist') const { decode, encode, decodeLedgerData } = require("../dist");
function json (object) { function json(object) {
return JSON.stringify(object) return JSON.stringify(object);
} }
function truncateForDisplay (longStr) { function truncateForDisplay(longStr) {
return longStr.slice(0, 10) + '...' + longStr.slice(-10) return `${longStr.slice(0, 10)} ... ${longStr.slice(-10)}`;
} }
describe('ripple-binary-codec', function () { describe("ripple-binary-codec", function () {
function makeSuite (name, entries) { function makeSuite(name, entries) {
describe(name, function () { describe(name, function () {
entries.forEach((t, testN) => { entries.forEach((t, testN) => {
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
test(`${name}[${testN}] can encode ${truncateForDisplay(json(t.json))} to ${truncateForDisplay(t.binary)}`, test(`${name}[${testN}] can encode ${truncateForDisplay(
() => { json(t.json)
expect(encode(t.json)).toEqual(t.binary) )} to ${truncateForDisplay(t.binary)}`, () => {
}) expect(encode(t.json)).toEqual(t.binary);
});
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
test(`${name}[${testN}] can decode ${truncateForDisplay(t.binary)} to ${truncateForDisplay(json(t.json))}`, test(`${name}[${testN}] can decode ${truncateForDisplay(
() => { t.binary
const decoded = decode(t.binary) )} to ${truncateForDisplay(json(t.json))}`, () => {
expect(decoded).toEqual(t.json) const decoded = decode(t.binary);
}) expect(decoded).toEqual(t.json);
}) });
}) });
});
} }
makeSuite('transactions', fixtures.transactions) makeSuite("transactions", fixtures.transactions);
makeSuite('accountState', fixtures.accountState) makeSuite("accountState", fixtures.accountState);
describe('ledgerData', function () { describe("ledgerData", function () {
if (fixtures.ledgerData) { if (fixtures.ledgerData) {
fixtures.ledgerData.forEach((t, testN) => { fixtures.ledgerData.forEach((t, testN) => {
test(`ledgerData[${testN}] can decode ${t.binary} to ${json(t.json)}`, test(`ledgerData[${testN}] can decode ${t.binary} to ${json(
() => { t.json
const decoded = decodeLedgerData(t.binary) )}`, () => {
expect(t.json).toEqual(decoded) const decoded = decodeLedgerData(t.binary);
}) expect(t.json).toEqual(decoded);
}) });
});
} }
}) });
}) });

View File

@@ -1,75 +1,74 @@
/* eslint-disable func-style */ /* eslint-disable func-style */
const { coreTypes } = require('../dist/types') const { coreTypes } = require("../dist/types");
const Decimal = require('decimal.js') const Decimal = require("decimal.js");
const _ = require('lodash') const { encodeAccountID } = require("ripple-address-codec");
const { encodeAccountID } = require('ripple-address-codec') const { binary } = require("../dist/coretypes");
const { binary } = require('../dist/coretypes') const { Amount, Hash160 } = coreTypes;
const { Amount, Hash160 } = coreTypes const { makeParser, readJSON } = binary;
const { makeParser, readJSON } = binary const { Field, TransactionType } = require("./../dist/enums");
const { Field, TransactionType } = require('./../dist/enums') const { parseHexOnly, hexOnly, loadFixture } = require("./utils");
const { parseHexOnly, hexOnly, loadFixture } = require('./utils') const fixtures = loadFixture("data-driven-tests.json");
const fixtures = loadFixture('data-driven-tests.json') const { BytesList } = require("../dist/serdes/binary-serializer");
const { BytesList } = require('../dist/serdes/binary-serializer')
const __ = hexOnly const __ = hexOnly;
function unused () {} function toJSON(v) {
function toJSON (v) { return v.toJSON ? v.toJSON() : v;
return v.toJSON ? v.toJSON() : v
} }
function assertEqualAmountJSON (actual, expected) { function assertEqualAmountJSON(actual, expected) {
expect((typeof actual) === (typeof expected)).toBe(true) expect(typeof actual === typeof expected).toBe(true);
if ((typeof actual) === 'string') { if (typeof actual === "string") {
expect(actual).toEqual(expected) expect(actual).toEqual(expected);
return return;
} }
expect(actual.currency).toEqual(expected.currency) expect(actual.currency).toEqual(expected.currency);
expect(actual.issuer).toEqual(expected.issuer) expect(actual.issuer).toEqual(expected.issuer);
expect(actual.value === expected.value || expect(
new Decimal(actual.value).equals( actual.value === expected.value ||
new Decimal(expected.value))).toBe(true) new Decimal(actual.value).equals(new Decimal(expected.value))
).toBe(true);
} }
function basicApiTests () { function basicApiTests() {
const bytes = parseHexOnly('00,01020304,0506', Uint8Array) const bytes = parseHexOnly("00,01020304,0506", Uint8Array);
test('can read slices of bytes', () => { test("can read slices of bytes", () => {
const parser = makeParser(bytes) const parser = makeParser(bytes);
expect(parser.bytes instanceof Buffer).toBe(true) expect(parser.bytes instanceof Buffer).toBe(true);
const read1 = parser.read(1) const read1 = parser.read(1);
expect(read1 instanceof Buffer).toBe(true) expect(read1 instanceof Buffer).toBe(true);
expect(read1).toEqual(Buffer.from([0])) expect(read1).toEqual(Buffer.from([0]));
expect(parser.read(4)).toEqual(Buffer.from([1, 2, 3, 4])) expect(parser.read(4)).toEqual(Buffer.from([1, 2, 3, 4]));
expect(parser.read(2)).toEqual(Buffer.from([5, 6])) expect(parser.read(2)).toEqual(Buffer.from([5, 6]));
expect(() => parser.read(1)).toThrow() expect(() => parser.read(1)).toThrow();
}) });
test('can read a Uint32 at full', () => { test("can read a Uint32 at full", () => {
const parser = makeParser('FFFFFFFF') const parser = makeParser("FFFFFFFF");
expect(parser.readUInt32()).toEqual(0xFFFFFFFF) expect(parser.readUInt32()).toEqual(0xffffffff);
}) });
} }
function transactionParsingTests () { function transactionParsingTests() {
const transaction = { const transaction = {
json: { json: {
Account: 'raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3', Account: "raD5qJMAShLeHZXf9wjUmo6vRK4arj9cF3",
Fee: '10', Fee: "10",
Flags: 0, Flags: 0,
Sequence: 103929, Sequence: 103929,
SigningPubKey: SigningPubKey:
'028472865AF4CB32AA285834B57576B7290AA8C31B459047DB27E16F418D6A7166', "028472865AF4CB32AA285834B57576B7290AA8C31B459047DB27E16F418D6A7166",
TakerGets: { TakerGets: {
currency: 'ILS', currency: "ILS",
issuer: 'rNPRNzBB92BVpAhhZr4iXDTveCgV5Pofm9', issuer: "rNPRNzBB92BVpAhhZr4iXDTveCgV5Pofm9",
value: '1694.768' value: "1694.768",
}, },
TakerPays: '98957503520', TakerPays: "98957503520",
TransactionType: 'OfferCreate', TransactionType: "OfferCreate",
TxnSignature: __(` TxnSignature: __(`
304502202ABE08D5E78D1E74A4C18F2714F64E87B8BD57444AF 304502202ABE08D5E78D1E74A4C18F2714F64E87B8BD57444AF
A5733109EB3C077077520022100DB335EE97386E4C0591CAC02 A5733109EB3C077077520022100DB335EE97386E4C0591CAC02
4D50E9230D8F171EEB901B5E5E4BD6D1E0AEF98C`) 4D50E9230D8F171EEB901B5E5E4BD6D1E0AEF98C`),
}, },
binary: __(` binary: __(`
120007220000000024000195F964400000170A53AC2065D5460561E 120007220000000024000195F964400000170A53AC2065D5460561E
@@ -79,207 +78,212 @@ function transactionParsingTests () {
418D6A71667447304502202ABE08D5E78D1E74A4C18F2714F64E87B 418D6A71667447304502202ABE08D5E78D1E74A4C18F2714F64E87B
8BD57444AFA5733109EB3C077077520022100DB335EE97386E4C059 8BD57444AFA5733109EB3C077077520022100DB335EE97386E4C059
1CAC024D50E9230D8F171EEB901B5E5E4BD6D1E0AEF98C811439408 1CAC024D50E9230D8F171EEB901B5E5E4BD6D1E0AEF98C811439408
A69F0895E62149CFCC006FB89FA7D1E6E5D`) A69F0895E62149CFCC006FB89FA7D1E6E5D`),
} };
const tx_json = transaction.json const tx_json = transaction.json;
// These tests are basically development logs // These tests are basically development logs
test('can be done with low level apis', () => { test("can be done with low level apis", () => {
const parser = makeParser(transaction.binary) const parser = makeParser(transaction.binary);
expect(parser.readField()).toEqual(Field.TransactionType) expect(parser.readField()).toEqual(Field.TransactionType);
expect(parser.readUInt16()).toEqual(7) expect(parser.readUInt16()).toEqual(7);
expect(parser.readField()).toEqual(Field.Flags) expect(parser.readField()).toEqual(Field.Flags);
expect(parser.readUInt32()).toEqual(0) expect(parser.readUInt32()).toEqual(0);
expect(parser.readField()).toEqual(Field.Sequence) expect(parser.readField()).toEqual(Field.Sequence);
expect(parser.readUInt32()).toEqual(103929) expect(parser.readUInt32()).toEqual(103929);
expect(parser.readField()).toEqual(Field.TakerPays) expect(parser.readField()).toEqual(Field.TakerPays);
parser.read(8) parser.read(8);
expect(parser.readField()).toEqual(Field.TakerGets) expect(parser.readField()).toEqual(Field.TakerGets);
// amount value // amount value
expect(parser.read(8)).not.toBe([]) expect(parser.read(8)).not.toBe([]);
// amount currency // amount currency
expect(Hash160.fromParser(parser)).not.toBe([]) expect(Hash160.fromParser(parser)).not.toBe([]);
expect(encodeAccountID(parser.read(20))).toEqual(tx_json.TakerGets.issuer) expect(encodeAccountID(parser.read(20))).toEqual(tx_json.TakerGets.issuer);
expect(parser.readField()).toEqual(Field.Fee) expect(parser.readField()).toEqual(Field.Fee);
expect(parser.read(8)).not.toEqual([]) expect(parser.read(8)).not.toEqual([]);
expect(parser.readField()).toEqual(Field.SigningPubKey) expect(parser.readField()).toEqual(Field.SigningPubKey);
expect(parser.readVariableLengthLength()).toBe(33) expect(parser.readVariableLengthLength()).toBe(33);
expect(parser.read(33).toString('hex').toUpperCase()).toEqual(tx_json.SigningPubKey) expect(parser.read(33).toString("hex").toUpperCase()).toEqual(
expect(parser.readField()).toEqual(Field.TxnSignature) tx_json.SigningPubKey
expect(parser.readVariableLength().toString('hex').toUpperCase()).toEqual(tx_json.TxnSignature) );
expect(parser.readField()).toEqual(Field.Account) expect(parser.readField()).toEqual(Field.TxnSignature);
expect(encodeAccountID(parser.readVariableLength())).toEqual(tx_json.Account) expect(parser.readVariableLength().toString("hex").toUpperCase()).toEqual(
expect(parser.end()).toBe(true) tx_json.TxnSignature
}) );
expect(parser.readField()).toEqual(Field.Account);
expect(encodeAccountID(parser.readVariableLength())).toEqual(
tx_json.Account
);
expect(parser.end()).toBe(true);
});
test('can be done with high level apis', () => { test("can be done with high level apis", () => {
const parser = makeParser(transaction.binary) const parser = makeParser(transaction.binary);
function readField () { function readField() {
return parser.readFieldAndValue() return parser.readFieldAndValue();
} }
{ {
const [field, value] = readField() const [field, value] = readField();
expect(field).toEqual(Field.TransactionType) expect(field).toEqual(Field.TransactionType);
expect(value).toEqual(TransactionType.OfferCreate) expect(value).toEqual(TransactionType.OfferCreate);
} }
{ {
const [field, value] = readField() const [field, value] = readField();
expect(field).toEqual(Field.Flags) expect(field).toEqual(Field.Flags);
expect(value.valueOf()).toEqual(0) expect(value.valueOf()).toEqual(0);
} }
{ {
const [field, value] = readField() const [field, value] = readField();
expect(field).toEqual(Field.Sequence) expect(field).toEqual(Field.Sequence);
expect(value.valueOf()).toEqual(103929) expect(value.valueOf()).toEqual(103929);
} }
{ {
const [field, value] = readField() const [field, value] = readField();
expect(field).toEqual(Field.TakerPays) expect(field).toEqual(Field.TakerPays);
expect(value.isNative()).toEqual(true) expect(value.isNative()).toEqual(true);
expect(value.toJSON()).toEqual('98957503520') expect(value.toJSON()).toEqual("98957503520");
} }
{ {
const [field, value] = readField() const [field, value] = readField();
expect(field).toEqual(Field.TakerGets) expect(field).toEqual(Field.TakerGets);
expect(value.isNative()).toEqual(false) expect(value.isNative()).toEqual(false);
expect(value.toJSON().issuer).toEqual(tx_json.TakerGets.issuer) expect(value.toJSON().issuer).toEqual(tx_json.TakerGets.issuer);
} }
{ {
const [field, value] = readField() const [field, value] = readField();
expect(field).toEqual(Field.Fee) expect(field).toEqual(Field.Fee);
expect(value.isNative()).toEqual(true) expect(value.isNative()).toEqual(true);
} }
{ {
const [field, value] = readField() const [field, value] = readField();
expect(field).toEqual(Field.SigningPubKey) expect(field).toEqual(Field.SigningPubKey);
expect(value.toJSON()).toEqual(tx_json.SigningPubKey) expect(value.toJSON()).toEqual(tx_json.SigningPubKey);
} }
{ {
const [field, value] = readField() const [field, value] = readField();
expect(field).toEqual(Field.TxnSignature) expect(field).toEqual(Field.TxnSignature);
expect(value.toJSON()).toEqual(tx_json.TxnSignature) expect(value.toJSON()).toEqual(tx_json.TxnSignature);
} }
{ {
const [field, value] = readField() const [field, value] = readField();
expect(field).toEqual(Field.Account) expect(field).toEqual(Field.Account);
expect(value.toJSON()).toEqual(tx_json.Account) expect(value.toJSON()).toEqual(tx_json.Account);
} }
expect(parser.end()).toBe(true) expect(parser.end()).toBe(true);
}) });
test('can be done with higher level apis', () => { test("can be done with higher level apis", () => {
const parser = makeParser(transaction.binary) const parser = makeParser(transaction.binary);
const jsonFromBinary = readJSON(parser) const jsonFromBinary = readJSON(parser);
expect(jsonFromBinary).toEqual(tx_json) expect(jsonFromBinary).toEqual(tx_json);
}) });
test('readJSON (binary.decode) does not return STObject ', () => { test("readJSON (binary.decode) does not return STObject ", () => {
const parser = makeParser(transaction.binary) const parser = makeParser(transaction.binary);
const jsonFromBinary = readJSON(parser) const jsonFromBinary = readJSON(parser);
expect(jsonFromBinary instanceof coreTypes.STObject).toBe(false) expect(jsonFromBinary instanceof coreTypes.STObject).toBe(false);
expect(jsonFromBinary instanceof Object).toBe(true); expect(jsonFromBinary instanceof Object).toBe(true);
expect(jsonFromBinary.prototype).toBe(undefined) expect(jsonFromBinary.prototype).toBe(undefined);
}) });
} }
function amountParsingTests () { function amountParsingTests() {
fixtures.values_tests.filter(obj => obj.type === 'Amount').forEach((f, i) => { fixtures.values_tests
.filter((obj) => obj.type === "Amount")
.forEach((f, i) => {
if (f.error) { if (f.error) {
return return;
} }
const parser = makeParser(f.expected_hex) const parser = makeParser(f.expected_hex);
const testName = const testName = `values_tests[${i}] parses ${f.expected_hex.slice(
`values_tests[${i}] parses ${f.expected_hex.slice(0, 16)}... 0,
as ${JSON.stringify(f.test_json)}` 16
)}...
as ${JSON.stringify(f.test_json)}`;
test(testName, () => { test(testName, () => {
const value = parser.readType(Amount) const value = parser.readType(Amount);
// May not actually be in canonical form. The fixtures are to be used // May not actually be in canonical form. The fixtures are to be used
// also for json -> binary; // also for json -> binary;
const json = toJSON(value) const json = toJSON(value);
assertEqualAmountJSON(json, (f.test_json)) assertEqualAmountJSON(json, f.test_json);
if (f.exponent) { if (f.exponent) {
const exponent = new Decimal(json.value); const exponent = new Decimal(json.value);
expect(exponent.e-15).toEqual(f.exponent) expect(exponent.e - 15).toEqual(f.exponent);
} }
}) });
}) });
} }
function fieldParsingTests () { function fieldParsingTests() {
fixtures.fields_tests.forEach((f, i) => { fixtures.fields_tests.forEach((f, i) => {
const parser = makeParser(f.expected_hex) const parser = makeParser(f.expected_hex);
test(`fields[${i}]: parses ${f.expected_hex} as ${f.name}`, () => { test(`fields[${i}]: parses ${f.expected_hex} as ${f.name}`, () => {
const field = parser.readField() const field = parser.readField();
expect(field.name).toEqual(f.name) expect(field.name).toEqual(f.name);
expect(field.type.name).toEqual(f.type_name) expect(field.type.name).toEqual(f.type_name);
}) });
}) });
test("Field throws when type code out of range", () => { test("Field throws when type code out of range", () => {
const parser = makeParser("0101"); const parser = makeParser("0101");
expect(() => parser.readField()).toThrow(new Error("Cannot read FieldOrdinal, type_code out of range")); expect(() => parser.readField()).toThrow(
}) new Error("Cannot read FieldOrdinal, type_code out of range")
);
});
test("Field throws when field code out of range", () => { test("Field throws when field code out of range", () => {
const parser = makeParser("1001"); const parser = makeParser("1001");
expect(() => parser.readFieldOrdinal()).toThrowError(new Error("Cannot read FieldOrdinal, field_code out of range")) expect(() => parser.readFieldOrdinal()).toThrowError(
}) new Error("Cannot read FieldOrdinal, field_code out of range")
);
});
test("Field throws when both type and field code out of range", () => { test("Field throws when both type and field code out of range", () => {
const parser = makeParser("000101"); const parser = makeParser("000101");
expect(() => parser.readFieldOrdinal()).toThrowError(new Error("Cannot read FieldOrdinal, type_code out of range")) expect(() => parser.readFieldOrdinal()).toThrowError(
}) new Error("Cannot read FieldOrdinal, type_code out of range")
);
});
} }
function assertRecyclable(json, forField) {
function assertRecyclable (json, forField) { const Type = forField.associatedType;
const Type = forField.associatedType const recycled = Type.from(json).toJSON();
const recycled = Type.from(json).toJSON() expect(recycled).toEqual(json);
expect(recycled).toEqual(json) const sink = new BytesList();
const sink = new BytesList() Type.from(recycled).toBytesSink(sink);
Type.from(recycled).toBytesSink(sink) const recycledAgain = makeParser(sink.toHex()).readType(Type).toJSON();
const recycledAgain = makeParser(sink.toHex()) expect(recycledAgain).toEqual(json);
.readType(Type)
.toJSON()
expect(recycledAgain).toEqual(json)
} }
function nestedObjectTests () { function nestedObjectTests() {
function disabled (i) {
unused(i)
return false
}
fixtures.whole_objects.forEach((f, i) => { fixtures.whole_objects.forEach((f, i) => {
if (disabled(i)) {
return
}
test(`whole_objects[${i}]: can parse blob into test(`whole_objects[${i}]: can parse blob into
${JSON.stringify(f.tx_json)}`, ${JSON.stringify(
/* */ () => { f.tx_json
const parser = makeParser(f.blob_with_no_signing) )}`, /* */ () => {
let ix = 0 const parser = makeParser(f.blob_with_no_signing);
let ix = 0;
while (!parser.end()) { while (!parser.end()) {
const [field, value] = parser.readFieldAndValue() const [field, value] = parser.readFieldAndValue();
const expected = f.fields[ix] const expected = f.fields[ix];
const expectedJSON = expected[1].json const expectedJSON = expected[1].json;
const expectedField = expected[0] const expectedField = expected[0];
const actual = toJSON(value) const actual = toJSON(value);
try { try {
expect(actual).toEqual(expectedJSON) expect(actual).toEqual(expectedJSON);
} catch (e) { } catch (e) {
throw new Error(`${e} ${field} a: ${actual} e: ${expectedJSON}`) throw new Error(`${e} ${field} a: ${actual} e: ${expectedJSON}`);
} }
expect(field.name).toEqual(expectedField) expect(field.name).toEqual(expectedField);
assertRecyclable(actual, field) assertRecyclable(actual, field);
ix++ ix++;
} }
}) });
}) });
} }
function pathSetBinaryTests () { function pathSetBinaryTests() {
const bytes = __( const bytes = __(
`1200002200000000240000002E2E00004BF161D4C71AFD498D00000000000000 `1200002200000000240000002E2E00004BF161D4C71AFD498D00000000000000
0000000000000055534400000000000A20B3C85F482532A9578DBB3950B85CA0 0000000000000055534400000000000A20B3C85F482532A9578DBB3950B85CA0
@@ -309,80 +313,85 @@ function pathSetBinaryTests () {
69E6DCC940CA48D82337AD000000000000000000000000425443000000000057 69E6DCC940CA48D82337AD000000000000000000000000425443000000000057
180C769B66D942EE69E6DCC940CA48D82337AD10000000000000000000000000 180C769B66D942EE69E6DCC940CA48D82337AD10000000000000000000000000
58525000000000003000000000000000000000000055534400000000000A20B3 58525000000000003000000000000000000000000055534400000000000A20B3
C85F482532A9578DBB3950B85CA06594D100`) C85F482532A9578DBB3950B85CA06594D100`
);
const expectedJSON = const expectedJSON = [
[[{ [
account: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K', {
currency: 'BTC', account: "r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K",
issuer: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K' currency: "BTC",
issuer: "r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K",
}, },
{ {
account: 'rM1oqKtfh1zgjdAgbFmaRm3btfGBX25xVo', account: "rM1oqKtfh1zgjdAgbFmaRm3btfGBX25xVo",
currency: 'BTC', currency: "BTC",
issuer: 'rM1oqKtfh1zgjdAgbFmaRm3btfGBX25xVo' issuer: "rM1oqKtfh1zgjdAgbFmaRm3btfGBX25xVo",
}, },
{ {
account: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B', account: "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
currency: 'BTC', currency: "BTC",
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' issuer: "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
}, },
{ {
currency: 'USD', currency: "USD",
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' issuer: "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
}], },
[{ ],
account: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K', [
currency: 'BTC', {
issuer: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K' account: "r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K",
currency: "BTC",
issuer: "r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K",
}, },
{ {
account: 'rM1oqKtfh1zgjdAgbFmaRm3btfGBX25xVo', account: "rM1oqKtfh1zgjdAgbFmaRm3btfGBX25xVo",
currency: 'BTC', currency: "BTC",
issuer: 'rM1oqKtfh1zgjdAgbFmaRm3btfGBX25xVo' issuer: "rM1oqKtfh1zgjdAgbFmaRm3btfGBX25xVo",
}, },
{ {
account: 'rpvfJ4mR6QQAeogpXEKnuyGBx8mYCSnYZi', account: "rpvfJ4mR6QQAeogpXEKnuyGBx8mYCSnYZi",
currency: 'BTC', currency: "BTC",
issuer: 'rpvfJ4mR6QQAeogpXEKnuyGBx8mYCSnYZi' issuer: "rpvfJ4mR6QQAeogpXEKnuyGBx8mYCSnYZi",
}, },
{ {
currency: 'USD', currency: "USD",
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' issuer: "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
}], },
[{ ],
account: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K', [
currency: 'BTC', {
issuer: 'r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K' account: "r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K",
currency: "BTC",
issuer: "r9hEDb4xBGRfBCcX3E4FirDWQBAYtpxC8K",
}, },
{ {
account: 'r3AWbdp2jQLXLywJypdoNwVSvr81xs3uhn', account: "r3AWbdp2jQLXLywJypdoNwVSvr81xs3uhn",
currency: 'BTC', currency: "BTC",
issuer: 'r3AWbdp2jQLXLywJypdoNwVSvr81xs3uhn' issuer: "r3AWbdp2jQLXLywJypdoNwVSvr81xs3uhn",
}, },
{ currency: '0000000000000000000000005852500000000000' }, { currency: "0000000000000000000000005852500000000000" },
{ {
currency: 'USD', currency: "USD",
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' issuer: "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
}]] },
],
];
test('works with long paths', () => { test("works with long paths", () => {
const parser = makeParser(bytes) const parser = makeParser(bytes);
const txn = readJSON(parser) const txn = readJSON(parser);
expect(txn.Paths).toEqual(expectedJSON) expect(txn.Paths).toEqual(expectedJSON);
// TODO: this should go elsewhere // TODO: this should go elsewhere
expect( expect(coreTypes.PathSet.from(txn.Paths).toJSON()).toEqual(expectedJSON);
coreTypes.PathSet.from(txn.Paths).toJSON()).toEqual( });
expectedJSON
)
})
} }
describe('Binary Parser', function() { describe("Binary Parser", function () {
describe('pathSetBinaryTests', pathSetBinaryTests); describe("pathSetBinaryTests", () => pathSetBinaryTests());
describe('nestedObjectTests', nestedObjectTests); describe("nestedObjectTests", () => nestedObjectTests());
describe('fieldParsingTests', fieldParsingTests); describe("fieldParsingTests", () => fieldParsingTests());
describe('amountParsingTests', amountParsingTests); describe("amountParsingTests", () => amountParsingTests());
describe('transactionParsingTests', transactionParsingTests); describe("transactionParsingTests", () => transactionParsingTests());
describe('basicApiTests', basicApiTests); describe("basicApiTests", () => basicApiTests());
}); });

View File

@@ -1,194 +1,191 @@
/* eslint-disable func-style */ /* eslint-disable func-style */
const { binary } = require('../dist/coretypes') const { binary } = require("../dist/coretypes");
const { encode, decode } = require('../dist') const { encode, decode } = require("../dist");
const { makeParser, BytesList, BinarySerializer } = binary const { makeParser, BytesList, BinarySerializer } = binary;
const { coreTypes } = require('../dist/types') const { coreTypes } = require("../dist/types");
const { UInt8, UInt16, UInt32, UInt64, STObject } = coreTypes const { UInt8, UInt16, UInt32, UInt64, STObject } = coreTypes;
const { loadFixture } = require('./utils') const { loadFixture } = require("./utils");
const fixtures = loadFixture('data-driven-tests.json') const fixtures = loadFixture("data-driven-tests.json");
const deliverMinTx = require('./fixtures/delivermin-tx.json') const deliverMinTx = require("./fixtures/delivermin-tx.json");
const deliverMinTxBinary = require('./fixtures/delivermin-tx-binary.json') const deliverMinTxBinary = require("./fixtures/delivermin-tx-binary.json");
const SignerListSet = { const SignerListSet = {
tx: require('./fixtures/signerlistset-tx.json'), tx: require("./fixtures/signerlistset-tx.json"),
binary: require('./fixtures/signerlistset-tx-binary.json'), binary: require("./fixtures/signerlistset-tx-binary.json"),
meta: require('./fixtures/signerlistset-tx-meta-binary.json') meta: require("./fixtures/signerlistset-tx-meta-binary.json"),
} };
const DepositPreauth = { const DepositPreauth = {
tx: require('./fixtures/deposit-preauth-tx.json'), tx: require("./fixtures/deposit-preauth-tx.json"),
binary: require('./fixtures/deposit-preauth-tx-binary.json'), binary: require("./fixtures/deposit-preauth-tx-binary.json"),
meta: require('./fixtures/deposit-preauth-tx-meta-binary.json') meta: require("./fixtures/deposit-preauth-tx-meta-binary.json"),
} };
const Escrow = { const Escrow = {
create: { create: {
tx: require('./fixtures/escrow-create-tx.json'), tx: require("./fixtures/escrow-create-tx.json"),
binary: require('./fixtures/escrow-create-binary.json') binary: require("./fixtures/escrow-create-binary.json"),
}, },
finish: { finish: {
tx: require('./fixtures/escrow-finish-tx.json'), tx: require("./fixtures/escrow-finish-tx.json"),
binary: require('./fixtures/escrow-finish-binary.json'), binary: require("./fixtures/escrow-finish-binary.json"),
meta: require('./fixtures/escrow-finish-meta-binary.json') meta: require("./fixtures/escrow-finish-meta-binary.json"),
}, },
cancel: { cancel: {
tx: require('./fixtures/escrow-cancel-tx.json'), tx: require("./fixtures/escrow-cancel-tx.json"),
binary: require('./fixtures/escrow-cancel-binary.json') binary: require("./fixtures/escrow-cancel-binary.json"),
} },
} };
const PaymentChannel = { const PaymentChannel = {
create: { create: {
tx: require('./fixtures/payment-channel-create-tx.json'), tx: require("./fixtures/payment-channel-create-tx.json"),
binary: require('./fixtures/payment-channel-create-binary.json') binary: require("./fixtures/payment-channel-create-binary.json"),
}, },
fund: { fund: {
tx: require('./fixtures/payment-channel-fund-tx.json'), tx: require("./fixtures/payment-channel-fund-tx.json"),
binary: require('./fixtures/payment-channel-fund-binary.json') binary: require("./fixtures/payment-channel-fund-binary.json"),
}, },
claim: { claim: {
tx: require('./fixtures/payment-channel-claim-tx.json'), tx: require("./fixtures/payment-channel-claim-tx.json"),
binary: require('./fixtures/payment-channel-claim-binary.json') binary: require("./fixtures/payment-channel-claim-binary.json"),
} },
};
const NegativeUNL = require("./fixtures/negative-unl.json");
function bytesListTest() {
const list = new BytesList()
.put(Buffer.from([0]))
.put(Buffer.from([2, 3]))
.put(Buffer.from([4, 5]));
test("is an Array<Buffer>", function () {
expect(Array.isArray(list.bytesArray)).toBe(true);
expect(list.bytesArray[0] instanceof Buffer).toBe(true);
});
test("keeps track of the length itself", function () {
expect(list.getLength()).toBe(5);
});
test("can join all arrays into one via toBytes", function () {
const joined = list.toBytes();
expect(joined).toHaveLength(5);
expect(joined).toEqual(Buffer.from([0, 2, 3, 4, 5]));
});
} }
const NegativeUNL = require('./fixtures/negative-unl.json'); function assertRecycles(blob) {
const parser = makeParser(blob);
function bytesListTest () { const so = parser.readType(STObject);
const list = new BytesList().put(Buffer.from([0])).put(Buffer.from([2, 3])).put(Buffer.from([4, 5])) const out = new BytesList();
test('is an Array<Buffer>', function () { so.toBytesSink(out);
expect(Array.isArray(list.bytesArray)).toBe(true) const hex = out.toHex();
expect(list.bytesArray[0] instanceof Buffer).toBe(true) expect(hex).toEqual(blob);
}) expect(hex + ":").not.toEqual(blob);
test('keeps track of the length itself', function () {
expect(list.getLength()).toBe(5)
})
test('can join all arrays into one via toBytes', function () {
const joined = list.toBytes()
expect(joined).toHaveLength(5)
expect(joined).toEqual(Buffer.from([0, 2, 3, 4, 5]))
})
} }
function assertRecycles (blob) { function nestedObjectTests() {
const parser = makeParser(blob)
const so = parser.readType(STObject)
const out = new BytesList()
so.toBytesSink(out)
const hex = out.toHex()
expect(hex).toEqual(blob)
expect(hex + ':').not.toEqual(blob)
}
function nestedObjectTests () {
fixtures.whole_objects.forEach((f, i) => { fixtures.whole_objects.forEach((f, i) => {
test(`whole_objects[${i}]: can parse blob and dump out same blob`, /*eslint-disable jest/expect-expect*/
/* */ () => { test(`whole_objects[${i}]: can parse blob and dump out same blob`, () => {
assertRecycles(f.blob_with_no_signing) assertRecycles(f.blob_with_no_signing);
}) });
}) /*eslint-enable jest/expect-expect*/
});
} }
function check (type, n, expected) { function check(type, n, expected) {
test(`Uint${type.width * 8} serializes ${n} as ${expected}`, function () { test(`Uint${type.width * 8} serializes ${n} as ${expected}`, function () {
const bl = new BytesList() const bl = new BytesList();
const serializer = new BinarySerializer(bl) const serializer = new BinarySerializer(bl);
if (expected === 'throws') { if (expected === "throws") {
expect(() => serializer.writeType(type, n)).toThrow() expect(() => serializer.writeType(type, n)).toThrow();
return return;
} }
serializer.writeType(type, n) serializer.writeType(type, n);
expect(bl.toBytes()).toEqual(Buffer.from(expected)) expect(bl.toBytes()).toEqual(Buffer.from(expected));
}) });
} }
check(UInt8, 5, [5]) check(UInt8, 5, [5]);
check(UInt16, 5, [0, 5]) check(UInt16, 5, [0, 5]);
check(UInt32, 5, [0, 0, 0, 5]) check(UInt32, 5, [0, 0, 0, 5]);
check(UInt32, 0xFFFFFFFF, [255, 255, 255, 255]) check(UInt32, 0xffffffff, [255, 255, 255, 255]);
check(UInt8, 0xFEFFFFFF, 'throws') check(UInt8, 0xfeffffff, "throws");
check(UInt16, 0xFEFFFFFF, 'throws') check(UInt16, 0xfeffffff, "throws");
check(UInt16, 0xFEFFFFFF, 'throws') check(UInt16, 0xfeffffff, "throws");
check(UInt64, 0xFEFFFFFF, [0, 0, 0, 0, 254, 255, 255, 255]) check(UInt64, 0xfeffffff, [0, 0, 0, 0, 254, 255, 255, 255]);
check(UInt64, -1, 'throws') check(UInt64, -1, "throws");
check(UInt64, 0, [0, 0, 0, 0, 0, 0, 0, 0]) check(UInt64, 0, [0, 0, 0, 0, 0, 0, 0, 0]);
check(UInt64, 1, [0, 0, 0, 0, 0, 0, 0, 1]) check(UInt64, 1, [0, 0, 0, 0, 0, 0, 0, 1]);
check(UInt64, BigInt(1), [0, 0, 0, 0, 0, 0, 0, 1]) check(UInt64, BigInt(1), [0, 0, 0, 0, 0, 0, 0, 1]);
// function parseLedger4320278() { function deliverMinTest() {
// test('can parse object', done => { test("can serialize DeliverMin", () => {
// const json = loadFixture('as-ledger-4320278.json'); expect(encode(deliverMinTx)).toEqual(deliverMinTxBinary);
// json.forEach(e => { });
// assertRecycles(e.binary);
// });
// done();
// });
// }
// parseLedger4320278();
function deliverMinTest () {
test('can serialize DeliverMin', () => {
expect(encode(deliverMinTx)).toEqual(deliverMinTxBinary)
})
} }
function SignerListSetTest () { function SignerListSetTest() {
test('can serialize SignerListSet', () => { test("can serialize SignerListSet", () => {
expect(encode(SignerListSet.tx)).toEqual(SignerListSet.binary) expect(encode(SignerListSet.tx)).toEqual(SignerListSet.binary);
}) });
test('can serialize SignerListSet metadata', () => { test("can serialize SignerListSet metadata", () => {
expect(encode(SignerListSet.tx.meta)).toEqual(SignerListSet.meta) expect(encode(SignerListSet.tx.meta)).toEqual(SignerListSet.meta);
}) });
} }
function DepositPreauthTest () { function DepositPreauthTest() {
test('can serialize DepositPreauth', () => { test("can serialize DepositPreauth", () => {
expect(encode(DepositPreauth.tx)).toEqual(DepositPreauth.binary) expect(encode(DepositPreauth.tx)).toEqual(DepositPreauth.binary);
}) });
test('can serialize DepositPreauth metadata', () => { test("can serialize DepositPreauth metadata", () => {
expect(encode(DepositPreauth.tx.meta)).toEqual(DepositPreauth.meta) expect(encode(DepositPreauth.tx.meta)).toEqual(DepositPreauth.meta);
}) });
} }
function EscrowTest () { function EscrowTest() {
test('can serialize EscrowCreate', () => { test("can serialize EscrowCreate", () => {
expect(encode(Escrow.create.tx)).toEqual(Escrow.create.binary) expect(encode(Escrow.create.tx)).toEqual(Escrow.create.binary);
}) });
test('can serialize EscrowFinish', () => { test("can serialize EscrowFinish", () => {
expect(encode(Escrow.finish.tx)).toEqual(Escrow.finish.binary) expect(encode(Escrow.finish.tx)).toEqual(Escrow.finish.binary);
expect(encode(Escrow.finish.tx.meta)).toEqual(Escrow.finish.meta) expect(encode(Escrow.finish.tx.meta)).toEqual(Escrow.finish.meta);
}) });
test('can serialize EscrowCancel', () => { test("can serialize EscrowCancel", () => {
expect(encode(Escrow.cancel.tx)).toEqual(Escrow.cancel.binary) expect(encode(Escrow.cancel.tx)).toEqual(Escrow.cancel.binary);
}) });
} }
function PaymentChannelTest () { function PaymentChannelTest() {
test('can serialize PaymentChannelCreate', () => { test("can serialize PaymentChannelCreate", () => {
expect(encode(PaymentChannel.create.tx)).toEqual(PaymentChannel.create.binary) expect(encode(PaymentChannel.create.tx)).toEqual(
}) PaymentChannel.create.binary
test('can serialize PaymentChannelFund', () => { );
expect(encode(PaymentChannel.fund.tx)).toEqual(PaymentChannel.fund.binary) });
}) test("can serialize PaymentChannelFund", () => {
test('can serialize PaymentChannelClaim', () => { expect(encode(PaymentChannel.fund.tx)).toEqual(PaymentChannel.fund.binary);
expect(encode(PaymentChannel.claim.tx)).toEqual(PaymentChannel.claim.binary) });
}) test("can serialize PaymentChannelClaim", () => {
expect(encode(PaymentChannel.claim.tx)).toEqual(
PaymentChannel.claim.binary
);
});
} }
function NegativeUNLTest () { function NegativeUNLTest() {
test('can serialize NegativeUNL', () => { test("can serialize NegativeUNL", () => {
expect(encode(NegativeUNL.tx)).toEqual(NegativeUNL.binary); expect(encode(NegativeUNL.tx)).toEqual(NegativeUNL.binary);
}) });
test('can deserialize NegativeUNL', () => { test("can deserialize NegativeUNL", () => {
expect(decode(NegativeUNL.binary)).toEqual(NegativeUNL.tx); expect(decode(NegativeUNL.binary)).toEqual(NegativeUNL.tx);
}) });
} }
describe('Binary Serialization', function() { describe("Binary Serialization", function () {
describe('nestedObjectTests', nestedObjectTests); describe("nestedObjectTests", () => nestedObjectTests());
describe('BytesList', bytesListTest); describe("BytesList", () => bytesListTest());
describe('DeliverMin', deliverMinTest); describe("DeliverMin", () => deliverMinTest());
describe('DepositPreauth', DepositPreauthTest); describe("DepositPreauth", () => DepositPreauthTest());
describe('SignerListSet', SignerListSetTest); describe("SignerListSet", () => SignerListSetTest());
describe('Escrow', EscrowTest); describe("Escrow", () => EscrowTest());
describe('PaymentChannel', PaymentChannelTest); describe("PaymentChannel", () => PaymentChannelTest());
describe('NegativeUNLTest', NegativeUNLTest); describe("NegativeUNLTest", () => NegativeUNLTest());
}) });

View File

@@ -1,60 +1,68 @@
const { coreTypes } = require('../dist/types') const { coreTypes } = require("../dist/types");
const { Hash160, Hash256, AccountID, Currency } = coreTypes const { Hash160, Hash256, AccountID, Currency } = coreTypes;
describe('Hash160', function () { describe("Hash160", function () {
test('has a static width member', function () { test("has a static width member", function () {
expect(Hash160.width).toBe(20) expect(Hash160.width).toBe(20);
}) });
test('inherited by subclasses', function () { test("inherited by subclasses", function () {
expect(AccountID.width).toBe(20) expect(AccountID.width).toBe(20);
expect(Currency.width).toBe(20) expect(Currency.width).toBe(20);
}) });
test('can be compared against another', function () { test("can be compared against another", function () {
const h1 = Hash160.from('1000000000000000000000000000000000000000') const h1 = Hash160.from("1000000000000000000000000000000000000000");
const h2 = Hash160.from('2000000000000000000000000000000000000000') const h2 = Hash160.from("2000000000000000000000000000000000000000");
const h3 = Hash160.from('0000000000000000000000000000000000000003') const h3 = Hash160.from("0000000000000000000000000000000000000003");
expect(h1.lt(h2)).toBe(true) expect(h1.lt(h2)).toBe(true);
expect(h3.lt(h2)).toBe(true) expect(h3.lt(h2)).toBe(true);
}) });
test('throws when constructed from invalid hash length', () => { test("throws when constructed from invalid hash length", () => {
expect(() => Hash160.from('10000000000000000000000000000000000000')).toThrow('Invalid Hash length 19') expect(() =>
expect(() => Hash160.from('100000000000000000000000000000000000000000')).toThrow('Invalid Hash length 21') Hash160.from("10000000000000000000000000000000000000")
}) ).toThrow("Invalid Hash length 19");
}) expect(() =>
Hash160.from("100000000000000000000000000000000000000000")
).toThrow("Invalid Hash length 21");
});
});
describe('Hash256', function () { describe("Hash256", function () {
test('has a static width member', function () { test("has a static width member", function () {
expect(Hash256.width).toBe(32) expect(Hash256.width).toBe(32);
}) });
test('has a ZERO_256 member', function () { test("has a ZERO_256 member", function () {
expect(Hash256.ZERO_256.toJSON()).toBe('0000000000000000000000000000000000000000000000000000000000000000') expect(Hash256.ZERO_256.toJSON()).toBe(
}) "0000000000000000000000000000000000000000000000000000000000000000"
test('supports getting the nibblet values at given positions', function () { );
});
test("supports getting the nibblet values at given positions", function () {
const h = Hash256.from( const h = Hash256.from(
'1359BD0000000000000000000000000000000000000000000000000000000000') "1359BD0000000000000000000000000000000000000000000000000000000000"
expect(h.nibblet(0)).toBe(0x1) );
expect(h.nibblet(1)).toBe(0x3) expect(h.nibblet(0)).toBe(0x1);
expect(h.nibblet(2)).toBe(0x5) expect(h.nibblet(1)).toBe(0x3);
expect(h.nibblet(3)).toBe(0x9) expect(h.nibblet(2)).toBe(0x5);
expect(h.nibblet(4)).toBe(0x0b) expect(h.nibblet(3)).toBe(0x9);
expect(h.nibblet(5)).toBe(0xd) expect(h.nibblet(4)).toBe(0x0b);
}) expect(h.nibblet(5)).toBe(0xd);
}) });
});
describe('Currency', function () { describe("Currency", function () {
test('Will have a null iso() for dodgy XRP ', function () { test("Will have a null iso() for dodgy XRP ", function () {
const bad = Currency.from('0000000000000000000000005852500000000000',) const bad = Currency.from("0000000000000000000000005852500000000000");
expect(bad.iso()).toBeUndefined() expect(bad.iso()).toBeUndefined();
expect(bad.isNative()).toBe(false) expect(bad.isNative()).toBe(false);
}) });
test('can be constructed from a Buffer', function () { test("can be constructed from a Buffer", function () {
const xrp = new Currency(Buffer.alloc(20)) const xrp = new Currency(Buffer.alloc(20));
expect(xrp.iso()).toBe('XRP') expect(xrp.iso()).toBe("XRP");
}) });
test('throws on invalid reprs', function () { test("throws on invalid reprs", function () {
expect(() => Currency.from(Buffer.alloc(19))).toThrow() expect(() => Currency.from(Buffer.alloc(19))).toThrow();
expect(() => Currency.from(1)).toThrow() expect(() => Currency.from(1)).toThrow();
expect(() => Currency.from( expect(() =>
'00000000000000000000000000000000000000m')).toThrow() Currency.from("00000000000000000000000000000000000000m")
}) ).toThrow();
}) });
});

View File

@@ -1,21 +1,29 @@
const { loadFixture } = require('./utils') const { loadFixture } = require("./utils");
const { transactionTreeHash, ledgerHash, accountStateHash } = require('../dist/ledger-hashes') const {
transactionTreeHash,
ledgerHash,
accountStateHash,
} = require("../dist/ledger-hashes");
describe('Ledger Hashes', function () { describe("Ledger Hashes", function () {
function testFactory (ledgerFixture) { function testFactory(ledgerFixture) {
describe(`can calculate hashes for ${ledgerFixture}`, function () { describe(`can calculate hashes for ${ledgerFixture}`, function () {
const ledger = loadFixture(ledgerFixture) const ledger = loadFixture(ledgerFixture);
test('computes correct account state hash', function () { test("computes correct account state hash", function () {
expect(accountStateHash(ledger.accountState).toHex()).toBe(ledger.account_hash) expect(accountStateHash(ledger.accountState).toHex()).toBe(
}) ledger.account_hash
test('computes correct transaction tree hash', function () { );
expect(transactionTreeHash(ledger.transactions).toHex()).toBe(ledger.transaction_hash) });
}) test("computes correct transaction tree hash", function () {
test('computes correct ledger header hash', function () { expect(transactionTreeHash(ledger.transactions).toHex()).toBe(
expect(ledgerHash(ledger).toHex()).toBe(ledger.hash) ledger.transaction_hash
}) );
}) });
test("computes correct ledger header hash", function () {
expect(ledgerHash(ledger).toHex()).toBe(ledger.hash);
});
});
} }
testFactory('ledger-full-40000.json') testFactory("ledger-full-40000.json");
testFactory('ledger-full-38129.json') testFactory("ledger-full-38129.json");
}) });

View File

@@ -1,42 +1,45 @@
const { encode, decode } = require('../dist') const { encode, decode } = require("../dist");
let str = "1100612200000000240000000125000068652D0000000055B6632D6376A2D9319F20A1C6DCCB486432D1E4A79951229D4C3DE2946F51D56662400009184E72A00081140DD319918CD5AE792BF7EC80D63B0F01B4573BBC" let str =
"1100612200000000240000000125000068652D0000000055B6632D6376A2D9319F20A1C6DCCB486432D1E4A79951229D4C3DE2946F51D56662400009184E72A00081140DD319918CD5AE792BF7EC80D63B0F01B4573BBC";
let lower = str.toLowerCase(); let lower = str.toLowerCase();
let bin = "1100612200000000240000000125000000082D00000000550735A0B32B2A3F4C938B76D6933003E29447DB8C7CE382BBE089402FF12A03E56240000002540BE400811479927BAFFD3D04A26096C0C97B1B0D45B01AD3C0" let bin =
"1100612200000000240000000125000000082D00000000550735A0B32B2A3F4C938B76D6933003E29447DB8C7CE382BBE089402FF12A03E56240000002540BE400811479927BAFFD3D04A26096C0C97B1B0D45B01AD3C0";
let json = { let json = {
"OwnerCount": 0, OwnerCount: 0,
"Account": "rUnFEsHjxqTswbivzL2DNHBb34rhAgZZZK", Account: "rUnFEsHjxqTswbivzL2DNHBb34rhAgZZZK",
"PreviousTxnLgrSeq": 8, PreviousTxnLgrSeq: 8,
"LedgerEntryType": "AccountRoot", LedgerEntryType: "AccountRoot",
"PreviousTxnID": "0735A0B32B2A3F4C938B76D6933003E29447DB8C7CE382BBE089402FF12A03E5".toLowerCase(), PreviousTxnID: "0735A0B32B2A3F4C938B76D6933003E29447DB8C7CE382BBE089402FF12A03E5".toLowerCase(),
"Flags": 0, Flags: 0,
"Sequence": 1, Sequence: 1,
"Balance": "10000000000" Balance: "10000000000",
} };
let jsonUpper = { let jsonUpper = {
"OwnerCount": 0, OwnerCount: 0,
"Account": "rUnFEsHjxqTswbivzL2DNHBb34rhAgZZZK", Account: "rUnFEsHjxqTswbivzL2DNHBb34rhAgZZZK",
"PreviousTxnLgrSeq": 8, PreviousTxnLgrSeq: 8,
"LedgerEntryType": "AccountRoot", LedgerEntryType: "AccountRoot",
"PreviousTxnID": "0735A0B32B2A3F4C938B76D6933003E29447DB8C7CE382BBE089402FF12A03E5", PreviousTxnID:
"Flags": 0, "0735A0B32B2A3F4C938B76D6933003E29447DB8C7CE382BBE089402FF12A03E5",
"Sequence": 1, Flags: 0,
"Balance": "10000000000" Sequence: 1,
} Balance: "10000000000",
};
describe("Lowercase hex test", () => { describe("Lowercase hex test", () => {
test("Correctly decodes", () => { test("Correctly decodes", () => {
expect(decode(lower)).toEqual(decode(str)) expect(decode(lower)).toEqual(decode(str));
}) });
test("Re-encodes to uppercase hex", () => { test("Re-encodes to uppercase hex", () => {
expect(encode(decode(lower))).toEqual(str) expect(encode(decode(lower))).toEqual(str);
}) });
test("Encode when hex field lowercase", () => { test("Encode when hex field lowercase", () => {
expect(encode(json)).toBe(bin) expect(encode(json)).toBe(bin);
}) });
test("Re-decodes to uppercase hex", () => { test("Re-decodes to uppercase hex", () => {
expect(decode(encode(json))).toEqual(jsonUpper) expect(decode(encode(json))).toEqual(jsonUpper);
}) });
}) });

View File

@@ -1,37 +1,38 @@
const { encode, decode } = require('../dist') const { encode, decode } = require("../dist");
let json = { let json = {
"Account": "rrrrrrrrrrrrrrrrrrrrrhoLvTp", Account: "rrrrrrrrrrrrrrrrrrrrrhoLvTp",
"Sequence": 0, Sequence: 0,
"Fee": "0", Fee: "0",
"SigningPubKey": "", SigningPubKey: "",
"Signature": "" Signature: "",
} };
let json_blank_acct = { let json_blank_acct = {
"Account": "", Account: "",
"Sequence": 0, Sequence: 0,
"Fee": "0", Fee: "0",
"SigningPubKey": "", SigningPubKey: "",
"Signature": "" Signature: "",
} };
let binary = "24000000006840000000000000007300760081140000000000000000000000000000000000000000" let binary =
"24000000006840000000000000007300760081140000000000000000000000000000000000000000";
describe("Can encode Pseudo Transactions", () => { describe("Can encode Pseudo Transactions", () => {
test("Correctly encodes Pseudo Transaciton", () => { test("Correctly encodes Pseudo Transaciton", () => {
expect(encode(json)).toEqual(binary); expect(encode(json)).toEqual(binary);
}) });
test("Can decode account objects", () => { test("Can decode account objects", () => {
expect(decode(encode(json))).toEqual(json); expect(decode(encode(json))).toEqual(json);
}) });
test("Blank AccountID is ACCOUNT_ZERO", () => { test("Blank AccountID is ACCOUNT_ZERO", () => {
expect(encode(json_blank_acct)).toEqual(binary) expect(encode(json_blank_acct)).toEqual(binary);
}) });
test("Decodes Blank AccountID", () => { test("Decodes Blank AccountID", () => {
expect(decode(encode(json_blank_acct))).toEqual(json); expect(decode(encode(json_blank_acct))).toEqual(json);
}) });
}) });

View File

@@ -1,15 +1,15 @@
const { quality } = require('../dist/coretypes') const { quality } = require("../dist/coretypes");
describe('Quality encode/decode', function () { describe("Quality encode/decode", function () {
const bookDirectory = const bookDirectory =
'4627DFFCFF8B5A265EDBD8AE8C14A52325DBFEDAF4F5C32E5D06F4C3362FE1D0' "4627DFFCFF8B5A265EDBD8AE8C14A52325DBFEDAF4F5C32E5D06F4C3362FE1D0";
const expectedQuality = '195796912.5171664' const expectedQuality = "195796912.5171664";
test('can decode', function () { test("can decode", function () {
const decimal = quality.decode(bookDirectory) const decimal = quality.decode(bookDirectory);
expect(decimal.toString()).toBe(expectedQuality) expect(decimal.toString()).toBe(expectedQuality);
}) });
test('can encode', function () { test("can encode", function () {
const bytes = quality.encode(expectedQuality) const bytes = quality.encode(expectedQuality);
expect(bytes.toString('hex').toUpperCase()).toBe(bookDirectory.slice(-16)) expect(bytes.toString("hex").toUpperCase()).toBe(bookDirectory.slice(-16));
}) });
}) });

View File

@@ -1,87 +1,88 @@
const { ShaMap } = require('../dist/shamap.js') const { ShaMap } = require("../dist/shamap.js");
const { binary, HashPrefix } = require('../dist/coretypes') const { binary, HashPrefix } = require("../dist/coretypes");
const { coreTypes } = require('../dist/types') const { coreTypes } = require("../dist/types");
const { loadFixture } = require('./utils') const { loadFixture } = require("./utils");
function now () { function now() {
return (Number(Date.now())) / 1000 return Number(Date.now()) / 1000;
} }
const ZERO = const ZERO = "0000000000000000000000000000000000000000000000000000000000000000";
'0000000000000000000000000000000000000000000000000000000000000000'
function makeItem (indexArg) { function makeItem(indexArg) {
let str = indexArg let str = indexArg;
while (str.length < 64) { while (str.length < 64) {
str += '0' str += "0";
} }
const index = coreTypes.Hash256.from(str) const index = coreTypes.Hash256.from(str);
const item = { const item = {
toBytesSink (sink) { toBytesSink(sink) {
index.toBytesSink(sink) index.toBytesSink(sink);
}, },
hashPrefix () { hashPrefix() {
return Buffer.from([1, 3, 3, 7]) return Buffer.from([1, 3, 3, 7]);
} },
} };
return [index, item] return [index, item];
} }
describe('ShaMap', () => { describe("ShaMap", () => {
now() now();
test('hashes to zero when empty', () => { test("hashes to zero when empty", () => {
const map = new ShaMap() const map = new ShaMap();
expect(map.hash().toHex()).toBe(ZERO) expect(map.hash().toHex()).toBe(ZERO);
}) });
test('creates the same hash no matter which order items are added', () => { test("creates the same hash no matter which order items are added", () => {
let map = new ShaMap() let map = new ShaMap();
const items = [ const items = [
'0', "0",
'1', "1",
'11', "11",
'7000DE445E22CB9BB7E1717589FA858736BAA5FD192310E20000000000000000', "7000DE445E22CB9BB7E1717589FA858736BAA5FD192310E20000000000000000",
'7000DE445E22CB9BB7E1717589FA858736BAA5FD192310E21000000000000000', "7000DE445E22CB9BB7E1717589FA858736BAA5FD192310E21000000000000000",
'7000DE445E22CB9BB7E1717589FA858736BAA5FD192310E22000000000000000', "7000DE445E22CB9BB7E1717589FA858736BAA5FD192310E22000000000000000",
'7000DE445E22CB9BB7E1717589FA858736BAA5FD192310E23000000000000000', "7000DE445E22CB9BB7E1717589FA858736BAA5FD192310E23000000000000000",
'12', "12",
'122' "122",
] ];
items.forEach(i => map.addItem(...makeItem(i))) items.forEach((i) => map.addItem(...makeItem(i)));
const h1 = map.hash() const h1 = map.hash();
expect(h1.eq(h1)).toBe(true) expect(h1.eq(h1)).toBe(true);
map = new ShaMap() map = new ShaMap();
items.reverse().forEach(i => map.addItem(...makeItem(i))) items.reverse().forEach((i) => map.addItem(...makeItem(i)));
expect(map.hash()).toStrictEqual(h1) expect(map.hash()).toStrictEqual(h1);
}) });
function factory (fixture) { function factory(fixture) {
test(`recreate account state hash from ${fixture}`, () => { test(`recreate account state hash from ${fixture}`, () => {
const map = new ShaMap() const map = new ShaMap();
const ledger = loadFixture(fixture) const ledger = loadFixture(fixture);
// const t = now(); // const t = now();
const leafNodePrefix = HashPrefix.accountStateEntry const leafNodePrefix = HashPrefix.accountStateEntry;
ledger.accountState.map((e, i) => { ledger.accountState
if (i > 1000 & (i % 1000) === 0) { .map((e, i) => {
console.log(e.index) if ((i > 1000) & (i % 1000 === 0)) {
console.log(i) console.log(e.index);
console.log(i);
} }
const bytes = binary.serializeObject(e) const bytes = binary.serializeObject(e);
return { return {
index: coreTypes.Hash256.from(e.index), index: coreTypes.Hash256.from(e.index),
hashPrefix () { hashPrefix() {
return leafNodePrefix return leafNodePrefix;
}, },
toBytesSink (sink) { toBytesSink(sink) {
sink.put(bytes) sink.put(bytes);
} },
} };
}).forEach(so => map.addItem(so.index, so))
expect(map.hash().toHex()).toBe(ledger.account_hash)
// console.log('took seconds: ', (now() - t));
}) })
.forEach((so) => map.addItem(so.index, so));
expect(map.hash().toHex()).toBe(ledger.account_hash);
// console.log('took seconds: ', (now() - t));
});
} }
factory('ledger-full-38129.json') factory("ledger-full-38129.json");
factory('ledger-full-40000.json') factory("ledger-full-40000.json");
// factory('ledger-4320277.json'); // factory('ledger-4320277.json');
// factory('14280680.json'); // factory('14280680.json');
}) });

View File

@@ -1,118 +1,129 @@
const _ = require('lodash') const {
const { encodeForSigning, encodeForSigningClaim, encodeForMultisigning } = require('../dist') encodeForSigning,
encodeForSigningClaim,
encodeForMultisigning,
} = require("../dist");
const tx_json = { const tx_json = {
Account: 'r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ', Account: "r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ",
Amount: '1000', Amount: "1000",
Destination: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Destination: "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
Fee: '10', Fee: "10",
Flags: 2147483648, Flags: 2147483648,
Sequence: 1, Sequence: 1,
TransactionType: 'Payment', TransactionType: "Payment",
TxnSignature: '30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1' + TxnSignature:
'E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80' + "30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1" +
'ECA3CD7B9B', "E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80" +
Signature: '30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E72' + "ECA3CD7B9B",
'1B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA' + Signature:
'3CD7B9B', "30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E72" +
"1B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA" +
"3CD7B9B",
SigningPubKey: SigningPubKey:
'ED5F5AC8B98974A3CA843326D9B88CEBD0560177B973EE0B149F782CFAA06DC66A' "ED5F5AC8B98974A3CA843326D9B88CEBD0560177B973EE0B149F782CFAA06DC66A",
} };
describe('Signing data', function () { describe("Signing data", function () {
test('can create single signing blobs', function () { test("can create single signing blobs", function () {
const actual = encodeForSigning(tx_json) const actual = encodeForSigning(tx_json);
expect(actual).toBe( expect(actual).toBe(
['53545800', // signingPrefix [
"53545800", // signingPrefix
// TransactionType // TransactionType
'12', "12",
'0000', "0000",
// Flags // Flags
'22', "22",
'80000000', "80000000",
// Sequence // Sequence
'24', "24",
'00000001', "00000001",
// Amount // Amount
'61', "61",
// native amount // native amount
'40000000000003E8', "40000000000003E8",
// Fee // Fee
'68', "68",
// native amount // native amount
'400000000000000A', "400000000000000A",
// SigningPubKey // SigningPubKey
'73', "73",
// VLLength // VLLength
'21', "21",
'ED5F5AC8B98974A3CA843326D9B88CEBD0560177B973EE0B149F782CFAA06DC66A', "ED5F5AC8B98974A3CA843326D9B88CEBD0560177B973EE0B149F782CFAA06DC66A",
// Account // Account
'81', "81",
// VLLength // VLLength
'14', "14",
'5B812C9D57731E27A2DA8B1830195F88EF32A3B6', "5B812C9D57731E27A2DA8B1830195F88EF32A3B6",
// Destination // Destination
'83', "83",
// VLLength // VLLength
'14', "14",
'B5F762798A53D543A014CAF8B297CFF8F2F937E8'].join('') "B5F762798A53D543A014CAF8B297CFF8F2F937E8",
) ].join("")
}) );
test('can create multi signing blobs', function () { });
const signingAccount = 'rJZdUusLDtY9NEsGea7ijqhVrXv98rYBYN' test("can create multi signing blobs", function () {
const signingJson = Object.assign({}, tx_json, { SigningPubKey: '' }) const signingAccount = "rJZdUusLDtY9NEsGea7ijqhVrXv98rYBYN";
const actual = encodeForMultisigning(signingJson, signingAccount) const signingJson = Object.assign({}, tx_json, { SigningPubKey: "" });
const actual = encodeForMultisigning(signingJson, signingAccount);
expect(actual).toBe( expect(actual).toBe(
['534D5400', // signingPrefix [
"534D5400", // signingPrefix
// TransactionType // TransactionType
'12', "12",
'0000', "0000",
// Flags // Flags
'22', "22",
'80000000', "80000000",
// Sequence // Sequence
'24', "24",
'00000001', "00000001",
// Amount // Amount
'61', "61",
// native amount // native amount
'40000000000003E8', "40000000000003E8",
// Fee // Fee
'68', "68",
// native amount // native amount
'400000000000000A', "400000000000000A",
// SigningPubKey // SigningPubKey
'73', "73",
// VLLength // VLLength
'00', "00",
// '', // '',
// Account // Account
'81', "81",
// VLLength // VLLength
'14', "14",
'5B812C9D57731E27A2DA8B1830195F88EF32A3B6', "5B812C9D57731E27A2DA8B1830195F88EF32A3B6",
// Destination // Destination
'83', "83",
// VLLength // VLLength
'14', "14",
'B5F762798A53D543A014CAF8B297CFF8F2F937E8', "B5F762798A53D543A014CAF8B297CFF8F2F937E8",
// signingAccount suffix // signingAccount suffix
'C0A5ABEF242802EFED4B041E8F2D4A8CC86AE3D1'].join('') "C0A5ABEF242802EFED4B041E8F2D4A8CC86AE3D1",
) ].join("")
}) );
test('can create claim blob', function () { });
test("can create claim blob", function () {
const channel = const channel =
'43904CBFCDCEC530B4037871F86EE90BF799DF8D2E0EA564BC8A3F332E4F5FB1' "43904CBFCDCEC530B4037871F86EE90BF799DF8D2E0EA564BC8A3F332E4F5FB1";
const amount = '1000' const amount = "1000";
const json = { channel, amount } const json = { channel, amount };
const actual = encodeForSigningClaim(json) const actual = encodeForSigningClaim(json);
expect(actual).toBe([ expect(actual).toBe(
[
// hash prefix // hash prefix
'434C4D00', "434C4D00",
// channel ID // channel ID
'43904CBFCDCEC530B4037871F86EE90BF799DF8D2E0EA564BC8A3F332E4F5FB1', "43904CBFCDCEC530B4037871F86EE90BF799DF8D2E0EA564BC8A3F332E4F5FB1",
// amount as a uint64 // amount as a uint64
'00000000000003E8' "00000000000003E8",
].join('')) ].join("")
}) );
}) });
});

View File

@@ -1,107 +1,80 @@
const { const { encode, decode } = require("../dist");
encode,
decode
} = require('../dist')
// Notice: no Amount or Fee // Notice: no Amount or Fee
const tx_json = { const tx_json = {
Account: 'r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ', Account: "r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ",
// Amount: '1000', // Amount: '1000',
Destination: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh', Destination: "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
// Fee: '10', // Fee: '10',
// JavaScript converts operands to 32-bit signed ints after doing bitwise // JavaScript converts operands to 32-bit signed ints after doing bitwise
// operations. We need to convert it back to an unsigned int with >>> 0. // operations. We need to convert it back to an unsigned int with >>> 0.
Flags: ((1 << 31) >>> 0), // tfFullyCanonicalSig Flags: (1 << 31) >>> 0, // tfFullyCanonicalSig
Sequence: 1, Sequence: 1,
TransactionType: 'Payment' TransactionType: "Payment",
// TxnSignature, // TxnSignature,
// Signature, // Signature,
// SigningPubKey // SigningPubKey
} };
const amount_parameters_message = input => { describe("encoding and decoding tx_json", function () {
// disables the ESLint rule on the whole rest of the file test("can encode tx_json without Amount or Fee", function () {
/* eslint-disable max-len */ const encoded = encode(tx_json);
return `${input} is an illegal amount const decoded = decode(encoded);
expect(tx_json).toEqual(decoded);
Native values must be described in drops, a million of which equal one XRP. });
This must be an integer number, with the absolute value not exceeding 100000000000000000 test("can encode tx_json with Amount and Fee", function () {
IOU values must have a maximum precision of 16 significant digits. They are serialized as
a canonicalised mantissa and exponent.
The valid range for a mantissa is between 1000000000000000 and 9999999999999999
The exponent must be >= -96 and <= 80
Thus the largest serializable IOU value is:
999999999999999900000000000000000000000000000000000000000000000000000000000000000000000000000000
And the smallest:
0.000000000000000000000000000000000000000000000000000000000000000000000000000000001
`
}
describe('encoding and decoding tx_json', function () {
test('can encode tx_json without Amount or Fee', function () {
const encoded = encode(tx_json)
const decoded = decode(encoded)
expect(tx_json).toEqual(decoded)
})
test('can encode tx_json with Amount and Fee', function () {
const my_tx = Object.assign({}, tx_json, { const my_tx = Object.assign({}, tx_json, {
Amount: '1000', Amount: "1000",
Fee: '10' Fee: "10",
}) });
const encoded = encode(my_tx) const encoded = encode(my_tx);
const decoded = decode(encoded) const decoded = decode(encoded);
expect(my_tx).toEqual(decoded) expect(my_tx).toEqual(decoded);
}) });
test('throws when Amount is invalid', function () { test("throws when Amount is invalid", function () {
const my_tx = Object.assign({}, tx_json, { const my_tx = Object.assign({}, tx_json, {
Amount: '1000.001', Amount: "1000.001",
Fee: '10' Fee: "10",
}) });
expect(() => { expect(() => {
encode(my_tx) encode(my_tx);
}).toThrow() }).toThrow();
}) });
test('throws when Fee is invalid', function () { test("throws when Fee is invalid", function () {
const my_tx = Object.assign({}, tx_json, { const my_tx = Object.assign({}, tx_json, {
Amount: '1000', Amount: "1000",
Fee: '10.123' Fee: "10.123",
}) });
expect(() => { expect(() => {
encode(my_tx) encode(my_tx);
}).toThrow() }).toThrow();
}) });
test('throws when Amount and Fee are invalid', function () { test("throws when Amount and Fee are invalid", function () {
const my_tx = Object.assign({}, tx_json, { const my_tx = Object.assign({}, tx_json, {
Amount: '1000.789', Amount: "1000.789",
Fee: '10.123' Fee: "10.123",
}) });
expect(() => { expect(() => {
encode(my_tx) encode(my_tx);
}).toThrow() }).toThrow();
}) });
test('throws when Amount is a number instead of a string-encoded integer', test("throws when Amount is a number instead of a string-encoded integer", function () {
function () {
const my_tx = Object.assign({}, tx_json, { const my_tx = Object.assign({}, tx_json, {
Amount: 1000.789 Amount: 1000.789,
}) });
expect(() => { expect(() => {
encode(my_tx) encode(my_tx);
}).toThrow() }).toThrow();
}) });
test('throws when Fee is a number instead of a string-encoded integer', test("throws when Fee is a number instead of a string-encoded integer", function () {
function () {
const my_tx = Object.assign({}, tx_json, { const my_tx = Object.assign({}, tx_json, {
Amount: 1234.56 Amount: 1234.56,
}) });
expect(() => { expect(() => {
encode(my_tx) encode(my_tx);
}).toThrow() }).toThrow();
}) });
}) });

View File

@@ -1,37 +1,34 @@
const _ = require('lodash') const { coreTypes } = require("../dist/types");
const { coreTypes } = require('../dist/types') const { SerializedType } = require("../dist/types/serialized-type");
const { SerializedType } = require('../dist/types/serialized-type')
describe('SerializedType interfaces', () => { describe("SerializedType interfaces", () => {
Object.entries(coreTypes).forEach(([name, Value]) => { Object.entries(coreTypes).forEach(([name, Value]) => {
test(`${name} has a \`from\` static constructor`, () => { test(`${name} has a \`from\` static constructor`, () => {
expect(Value.from && Value.from !== Array.from).toBe(true) expect(Value.from && Value.from !== Array.from).toBe(true);
}) });
test(`${name} has a default constructor`, () => { test(`${name} has a default constructor`, () => {
/* eslint-disable no-new */ expect(new Value()).not.toBe(undefined);
new Value() });
/* eslint-enable no-new */
})
test(`${name}.from will return the same object`, () => { test(`${name}.from will return the same object`, () => {
const instance = new Value() const instance = new Value();
expect(Value.from(instance) === instance).toBe(true) expect(Value.from(instance) === instance).toBe(true);
}) });
test(`${name} instances have toBytesSink`, () => { test(`${name} instances have toBytesSink`, () => {
expect(new Value().toBytesSink).not.toBe(undefined) expect(new Value().toBytesSink).not.toBe(undefined);
}) });
test(`${name} instances have toJSON`, () => { test(`${name} instances have toJSON`, () => {
expect(new Value().toJSON).not.toBe(undefined) expect(new Value().toJSON).not.toBe(undefined);
}) });
test(`${name}.from(json).toJSON() == json`, () => { test(`${name}.from(json).toJSON() == json`, () => {
const newJSON = new Value().toJSON() const newJSON = new Value().toJSON();
expect(Value.from(newJSON).toJSON()).toEqual(newJSON) expect(Value.from(newJSON).toJSON()).toEqual(newJSON);
}) });
describe(`${name} supports all methods of the SerializedType mixin`, () => { describe(`${name} supports all methods of the SerializedType mixin`, () => {
Object.keys(SerializedType.prototype).forEach(k => { Object.keys(SerializedType.prototype).forEach((k) => {
test(`new ${name}.prototype.${k} !== undefined`, () => { test(`new ${name}.prototype.${k} !== undefined`, () => {
expect(Value.prototype[k]).not.toBe(undefined) expect(Value.prototype[k]).not.toBe(undefined);
}) });
}) });
}) });
}) });
}) });

View File

@@ -1,40 +1,40 @@
const { coreTypes } = require('../dist/types') const { coreTypes } = require("../dist/types");
const { UInt8, UInt64 } = coreTypes const { UInt8, UInt64 } = coreTypes;
test('compareToTests', () => { test("compareToTests[0]", () => {
expect(UInt8.from(124).compareTo(UInt64.from(124))).toBe(0) expect(UInt8.from(124).compareTo(UInt64.from(124))).toBe(0);
}) });
test('compareToTest', () => { test("compareToTest[1]", () => {
expect(UInt64.from(124).compareTo(UInt8.from(124))).toBe(0) expect(UInt64.from(124).compareTo(UInt8.from(124))).toBe(0);
}) });
test('compareToTest', () => { test("compareToTest[2]", () => {
expect(UInt64.from(124).compareTo(UInt8.from(123))).toBe(1) expect(UInt64.from(124).compareTo(UInt8.from(123))).toBe(1);
}) });
test('compareToTest', () => { test("compareToTest[3]", () => {
expect(UInt8.from(124).compareTo(UInt8.from(13))).toBe(1) expect(UInt8.from(124).compareTo(UInt8.from(13))).toBe(1);
}) });
test('compareToTest', () => { test("compareToTest[4]", () => {
expect(UInt8.from(124).compareTo(124)).toBe(0) expect(UInt8.from(124).compareTo(124)).toBe(0);
}) });
test('compareToTest', () => { test("compareToTest[5]", () => {
expect(UInt64.from(124).compareTo(124)).toBe(0) expect(UInt64.from(124).compareTo(124)).toBe(0);
}) });
test('compareToTest', () => { test("compareToTest[6]", () => {
expect(UInt64.from(124).compareTo(123)).toBe(1) expect(UInt64.from(124).compareTo(123)).toBe(1);
}) });
test('compareToTest', () => { test("compareToTest[7]", () => {
expect(UInt8.from(124).compareTo(13)).toBe(1) expect(UInt8.from(124).compareTo(13)).toBe(1);
}) });
test('valueOfTests', () => { test("valueOfTests", () => {
let val = UInt8.from(1) let val = UInt8.from(1);
val |= 0x2 val |= 0x2;
expect(val).toBe(3) expect(val).toBe(3);
}) });

View File

@@ -1,23 +1,23 @@
const fs = require('fs') const fs = require("fs");
function hexOnly (hex) { function hexOnly(hex) {
return hex.replace(/[^a-fA-F0-9]/g, '') return hex.replace(/[^a-fA-F0-9]/g, "");
} }
function unused () {} function unused() {}
function parseHexOnly (hex) { function parseHexOnly(hex) {
return Buffer.from(hexOnly(hex), 'hex'); return Buffer.from(hexOnly(hex), "hex");
} }
function loadFixture (relativePath) { function loadFixture(relativePath) {
const fn = __dirname + '/fixtures/' + relativePath const fn = __dirname + "/fixtures/" + relativePath;
return require(fn) return require(fn);
} }
function loadFixtureText (relativePath) { function loadFixtureText(relativePath) {
const fn = __dirname + '/fixtures/' + relativePath const fn = __dirname + "/fixtures/" + relativePath;
return fs.readFileSync(fn).toString('utf8') return fs.readFileSync(fn).toString("utf8");
} }
module.exports = { module.exports = {
@@ -25,5 +25,5 @@ module.exports = {
parseHexOnly, parseHexOnly,
loadFixture, loadFixture,
loadFixtureText, loadFixtureText,
unused unused,
} };

View File

@@ -1,137 +1,147 @@
const { encode, decode } = require("./../dist/index"); const { encode, decode } = require("./../dist/index");
const fixtures = require('./fixtures/x-codec-fixtures.json') const fixtures = require("./fixtures/x-codec-fixtures.json");
let json_x1 = { let json_x1 = {
OwnerCount: 0, OwnerCount: 0,
Account: "XVXdn5wEVm5G4UhEHWDPqjvdeH361P7BsapL4m2D2XnPSwT", Account: "XVXdn5wEVm5G4UhEHWDPqjvdeH361P7BsapL4m2D2XnPSwT",
PreviousTxnLgrSeq: 7, PreviousTxnLgrSeq: 7,
LedgerEntryType: "AccountRoot", LedgerEntryType: "AccountRoot",
PreviousTxnID: "DF530FB14C5304852F20080B0A8EEF3A6BDD044F41F4EBBD68B8B321145FE4FF", PreviousTxnID:
"DF530FB14C5304852F20080B0A8EEF3A6BDD044F41F4EBBD68B8B321145FE4FF",
Flags: 0, Flags: 0,
Sequence: 1, Sequence: 1,
Balance: "10000000000" Balance: "10000000000",
} };
let json_r1 = { let json_r1 = {
OwnerCount: 0, OwnerCount: 0,
Account: 'rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv', Account: "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv",
PreviousTxnLgrSeq: 7, PreviousTxnLgrSeq: 7,
LedgerEntryType: 'AccountRoot', LedgerEntryType: "AccountRoot",
PreviousTxnID: 'DF530FB14C5304852F20080B0A8EEF3A6BDD044F41F4EBBD68B8B321145FE4FF', PreviousTxnID:
"DF530FB14C5304852F20080B0A8EEF3A6BDD044F41F4EBBD68B8B321145FE4FF",
Flags: 0, Flags: 0,
Sequence: 1, Sequence: 1,
Balance: '10000000000', Balance: "10000000000",
SourceTag: 12345, SourceTag: 12345,
} };
let json_null_x = { let json_null_x = {
"OwnerCount": 0, OwnerCount: 0,
"Account": "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv", Account: "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv",
"Destination": "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv", Destination: "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv",
"Issuer": "XVXdn5wEVm5G4UhEHWDPqjvdeH361P4GETfNyyXGaoqBj71", Issuer: "XVXdn5wEVm5G4UhEHWDPqjvdeH361P4GETfNyyXGaoqBj71",
"PreviousTxnLgrSeq": 7, PreviousTxnLgrSeq: 7,
"LedgerEntryType": "AccountRoot", LedgerEntryType: "AccountRoot",
"PreviousTxnID": "DF530FB14C5304852F20080B0A8EEF3A6BDD044F41F4EBBD68B8B321145FE4FF", PreviousTxnID:
"Flags": 0, "DF530FB14C5304852F20080B0A8EEF3A6BDD044F41F4EBBD68B8B321145FE4FF",
"Sequence": 1, Flags: 0,
"Balance": "10000000000" Sequence: 1,
} Balance: "10000000000",
};
let json_invalid_x = { let json_invalid_x = {
"OwnerCount": 0, OwnerCount: 0,
"Account": "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv", Account: "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv",
"Destination": "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv", Destination: "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv",
"Issuer": "XVXdn5wEVm5g4UhEHWDPqjvdeH361P4GETfNyyXGaoqBj71", Issuer: "XVXdn5wEVm5g4UhEHWDPqjvdeH361P4GETfNyyXGaoqBj71",
"PreviousTxnLgrSeq": 7, PreviousTxnLgrSeq: 7,
"LedgerEntryType": "AccountRoot", LedgerEntryType: "AccountRoot",
"PreviousTxnID": "DF530FB14C5304852F20080B0A8EEF3A6BDD044F41F4EBBD68B8B321145FE4FF", PreviousTxnID:
"Flags": 0, "DF530FB14C5304852F20080B0A8EEF3A6BDD044F41F4EBBD68B8B321145FE4FF",
"Sequence": 1, Flags: 0,
"Balance": "10000000000" Sequence: 1,
} Balance: "10000000000",
};
let json_null_r = { let json_null_r = {
"OwnerCount": 0, OwnerCount: 0,
"Account": "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv", Account: "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv",
"Destination": "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv", Destination: "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv",
"Issuer": "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv", Issuer: "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv",
"PreviousTxnLgrSeq": 7, PreviousTxnLgrSeq: 7,
"LedgerEntryType": "AccountRoot", LedgerEntryType: "AccountRoot",
"PreviousTxnID": "DF530FB14C5304852F20080B0A8EEF3A6BDD044F41F4EBBD68B8B321145FE4FF", PreviousTxnID:
"Flags": 0, "DF530FB14C5304852F20080B0A8EEF3A6BDD044F41F4EBBD68B8B321145FE4FF",
"Sequence": 1, Flags: 0,
"Balance": "10000000000" Sequence: 1,
} Balance: "10000000000",
};
let invalid_json_issuer_tagged = { let invalid_json_issuer_tagged = {
"OwnerCount": 0, OwnerCount: 0,
"Account": "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv", Account: "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv",
"Destination": "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv", Destination: "rLs1MzkFWCxTbuAHgjeTZK4fcCDDnf2KRv",
"Issuer": "XVXdn5wEVm5G4UhEHWDPqjvdeH361P7BsapL4m2D2XnPSwT", Issuer: "XVXdn5wEVm5G4UhEHWDPqjvdeH361P7BsapL4m2D2XnPSwT",
"PreviousTxnLgrSeq": 7, PreviousTxnLgrSeq: 7,
"LedgerEntryType": "AccountRoot", LedgerEntryType: "AccountRoot",
"PreviousTxnID": "DF530FB14C5304852F20080B0A8EEF3A6BDD044F41F4EBBD68B8B321145FE4FF", PreviousTxnID:
"Flags": 0, "DF530FB14C5304852F20080B0A8EEF3A6BDD044F41F4EBBD68B8B321145FE4FF",
"Sequence": 1, Flags: 0,
"Balance": "10000000000" Sequence: 1,
} Balance: "10000000000",
};
let invalid_json_x_and_tagged = { let invalid_json_x_and_tagged = {
OwnerCount: 0, OwnerCount: 0,
Account: 'XVXdn5wEVm5G4UhEHWDPqjvdeH361P7BsapL4m2D2XnPSwT', Account: "XVXdn5wEVm5G4UhEHWDPqjvdeH361P7BsapL4m2D2XnPSwT",
PreviousTxnLgrSeq: 7, PreviousTxnLgrSeq: 7,
LedgerEntryType: 'AccountRoot', LedgerEntryType: "AccountRoot",
PreviousTxnID: 'DF530FB14C5304852F20080B0A8EEF3A6BDD044F41F4EBBD68B8B321145FE4FF', PreviousTxnID:
"DF530FB14C5304852F20080B0A8EEF3A6BDD044F41F4EBBD68B8B321145FE4FF",
Flags: 0, Flags: 0,
Sequence: 1, Sequence: 1,
Balance: '10000000000', Balance: "10000000000",
SourceTag: 12345, SourceTag: 12345,
} };
describe("X-Address Account is equivalent to a classic address w/ SourceTag", () => { describe("X-Address Account is equivalent to a classic address w/ SourceTag", () => {
let encoded_x = encode(json_x1); let encoded_x = encode(json_x1);
let encoded_r = encode(json_r1); let encoded_r = encode(json_r1);
test("Can encode with x-Address", () => { test("Can encode with x-Address", () => {
expect(encoded_x).toEqual(encoded_r); expect(encoded_x).toEqual(encoded_r);
}) });
test("decoded X-address is object w/ source and tag", () => { test("decoded X-address is object w/ source and tag", () => {
let decoded_x = decode(encoded_x); let decoded_x = decode(encoded_x);
expect(decoded_x).toEqual(json_r1); expect(decoded_x).toEqual(json_r1);
}) });
test("Encoding issuer X-Address w/ undefined destination tag", () => { test("Encoding issuer X-Address w/ undefined destination tag", () => {
expect(encode(json_null_x)).toEqual(encode(json_null_r)); expect(encode(json_null_x)).toEqual(encode(json_null_r));
}) });
test("Throws when X-Address is invalid", () => { test("Throws when X-Address is invalid", () => {
expect(() => encode(json_invalid_x)).toThrow("checksum_invalid"); expect(() => encode(json_invalid_x)).toThrow("checksum_invalid");
}) });
}) });
describe("Invalid X-Address behavior", () => { describe("Invalid X-Address behavior", () => {
test("X-Address with tag throws value for invalid field",() => { test("X-Address with tag throws value for invalid field", () => {
expect(() => encode(invalid_json_issuer_tagged)).toThrow(new Error("Issuer cannot have an associated tag")) expect(() => encode(invalid_json_issuer_tagged)).toThrow(
}) new Error("Issuer cannot have an associated tag")
);
});
test("Throws when Account has both X-Addr and Destination Tag", () => { test("Throws when Account has both X-Addr and Destination Tag", () => {
expect(() => encode(invalid_json_x_and_tagged)).toThrow(new Error("Cannot have Account X-Address and SourceTag")); expect(() => encode(invalid_json_x_and_tagged)).toThrow(
new Error("Cannot have Account X-Address and SourceTag")
);
}); });
}) });
describe('ripple-binary-codec x-address test', function () { describe("ripple-binary-codec x-address test", function () {
function makeSuite (name, entries) { function makeSuite(name, entries) {
describe(name, function () { describe(name, function () {
entries.forEach((t, testN) => { entries.forEach((t, testN) => {
test(`${name}[${testN}] encodes X-address json equivalent to classic address json`, test(`${name}[${testN}] encodes X-address json equivalent to classic address json`, () => {
() => { expect(encode(t.rjson)).toEqual(encode(t.xjson));
expect(encode(t.rjson)).toEqual(encode(t.xjson)) });
})
test(`${name}[${testN}] decodes X-address json equivalent to classic address json`, () => { test(`${name}[${testN}] decodes X-address json equivalent to classic address json`, () => {
expect(decode(encode(t.xjson))).toEqual(t.rjson); expect(decode(encode(t.xjson))).toEqual(t.rjson);
}) });
}) });
}) });
} }
makeSuite('transactions', fixtures.transactions) makeSuite("transactions", fixtures.transactions);
}) });

View File

@@ -3,5 +3,5 @@
{ {
// extend your base config so you don't have to redefine your compilerOptions // extend your base config so you don't have to redefine your compilerOptions
"extends": "./tsconfig.json", "extends": "./tsconfig.json",
"include": ["src/**/*.ts"] "include": ["src/**/*.ts", "test/**/*.js"]
} }

View File

@@ -625,6 +625,16 @@
eslint-scope "^5.0.0" eslint-scope "^5.0.0"
eslint-utils "^2.0.0" eslint-utils "^2.0.0"
"@typescript-eslint/experimental-utils@^2.5.0":
version "2.34.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz#d3524b644cdb40eebceca67f8cf3e4cc9c8f980f"
integrity sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA==
dependencies:
"@types/json-schema" "^7.0.3"
"@typescript-eslint/typescript-estree" "2.34.0"
eslint-scope "^5.0.0"
eslint-utils "^2.0.0"
"@typescript-eslint/parser@^3.2.0": "@typescript-eslint/parser@^3.2.0":
version "3.7.1" version "3.7.1"
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.7.1.tgz#5d9ccecb116d12d9c6073e9861c57c9b1aa88128" resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.7.1.tgz#5d9ccecb116d12d9c6073e9861c57c9b1aa88128"
@@ -641,6 +651,19 @@
resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.7.1.tgz#90375606b2fd73c1224fe9e397ee151e28fa1e0c" resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.7.1.tgz#90375606b2fd73c1224fe9e397ee151e28fa1e0c"
integrity sha512-PZe8twm5Z4b61jt7GAQDor6KiMhgPgf4XmUb9zdrwTbgtC/Sj29gXP1dws9yEn4+aJeyXrjsD9XN7AWFhmnUfg== integrity sha512-PZe8twm5Z4b61jt7GAQDor6KiMhgPgf4XmUb9zdrwTbgtC/Sj29gXP1dws9yEn4+aJeyXrjsD9XN7AWFhmnUfg==
"@typescript-eslint/typescript-estree@2.34.0":
version "2.34.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz#14aeb6353b39ef0732cc7f1b8285294937cf37d5"
integrity sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==
dependencies:
debug "^4.1.1"
eslint-visitor-keys "^1.1.0"
glob "^7.1.6"
is-glob "^4.0.1"
lodash "^4.17.15"
semver "^7.3.2"
tsutils "^3.17.1"
"@typescript-eslint/typescript-estree@3.7.1": "@typescript-eslint/typescript-estree@3.7.1":
version "3.7.1" version "3.7.1"
resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.7.1.tgz#ce1ffbd0fa53f34d4ce851a7a364e392432f6eb3" resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.7.1.tgz#ce1ffbd0fa53f34d4ce851a7a364e392432f6eb3"
@@ -1467,6 +1490,13 @@ eslint-plugin-import@^2.21.1:
resolve "^1.17.0" resolve "^1.17.0"
tsconfig-paths "^3.9.0" tsconfig-paths "^3.9.0"
eslint-plugin-jest@^23.20.0:
version "23.20.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.20.0.tgz#e1d69c75f639e99d836642453c4e75ed22da4099"
integrity sha512-+6BGQt85OREevBDWCvhqj1yYA4+BFK4XnRZSGJionuEYmcglMZYLNNBBemwzbqUAckURaHdJSBcjHPyrtypZOw==
dependencies:
"@typescript-eslint/experimental-utils" "^2.5.0"
eslint-plugin-mocha@^7.0.1: eslint-plugin-mocha@^7.0.1:
version "7.0.1" version "7.0.1"
resolved "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-7.0.1.tgz#b2e9e8ebef7836f999a83f8bab25d0e0c05f0d28" resolved "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-7.0.1.tgz#b2e9e8ebef7836f999a83f8bab25d0e0c05f0d28"
@@ -1502,10 +1532,10 @@ eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
eslint@^7.2.0: eslint@^7.7.0:
version "7.5.0" version "7.7.0"
resolved "https://registry.npmjs.org/eslint/-/eslint-7.5.0.tgz#9ecbfad62216d223b82ac9ffea7ef3444671d135" resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.7.0.tgz#18beba51411927c4b64da0a8ceadefe4030d6073"
integrity sha512-vlUP10xse9sWt9SGRtcr1LAC67BENcQMFeV+w5EvLEoFe3xJ8cF1Skd0msziRx/VMC+72B4DxreCE+OR12OA6Q== integrity sha512-1KUxLzos0ZVsyL81PnRN335nDtQ8/vZUD6uMtWbF+5zDtjKcsklIi78XoE0MVL93QvWTu+E5y44VyyCsOMBrIg==
dependencies: dependencies:
"@babel/code-frame" "^7.0.0" "@babel/code-frame" "^7.0.0"
ajv "^6.10.0" ajv "^6.10.0"