From 3b9d7124106219c8c7a18c5ef90194ecd91bb037 Mon Sep 17 00:00:00 2001 From: Joshua Rogers Date: Thu, 4 Jun 2026 01:49:22 +0200 Subject: [PATCH] refactor!: migrate to native ESM (0.2.9 -> 0.3.0) Convert @exodus/ripple-binary-codec from CommonJS to native ESM, mirroring the @exodus/ripple-address-codec model (raw src shipped, "type": "module", no babel build step). Motivation: the CVE-2025-27611 (base-x) fix shipped @exodus/ripple-address-codec 4.2.0-alpha0.0 as ESM. ripple-binary-codec (CJS) require()s ripple-address-codec inside ripple-lib's import cycle, so under Node it throws ERR_REQUIRE_CYCLE_MODULE (assets#8196 CI failure). ESM makes that an ESM->ESM import, removing the require-in-cycle and unblocking the security bump across the XRP stack. - 33 src + 13 test files converted; .babelrc and test/mocha.opts removed; babel devDeps and the compile/prepublish scripts dropped (raw src shipped). - src/index.js keeps BOTH a default export (the old module.exports object) and named exports, so default-import consumers (ripple-lib sign paths, hw-ledger) and named-import consumers both keep working. - make-class.js: restore Babel-era constructor behavior for concise methods (no .prototype under native ESM) via an asConstructor wrapper. - CI: drop obsolete compile + babel-eslint lint steps; Node matrix -> 20.x/22.x. Tests: 971 passing / 1 pending, unchanged from baseline; no assertions changed. BREAKING CHANGE: package is now ESM-only; CommonJS consumers must migrate to ESM or use dynamic import(). --- .babelrc | 4 -- .github/workflows/nodejs.yml | 4 +- package.json | 20 +++------ src/binary.js | 16 +++---- src/coretypes.js | 20 ++++----- src/enums/index.js | 12 ++--- src/hash-prefixes.js | 4 +- src/hashes.js | 13 +++--- src/index.js | 22 +++++++-- src/ledger-hashes.js | 18 ++++---- src/quality.js | 11 ++--- src/serdes/binary-parser.js | 11 ++--- src/serdes/binary-serializer.js | 11 ++--- src/shamap.js | 13 +++--- src/types/account-id.js | 10 ++--- src/types/amount.js | 22 ++++----- src/types/blob.js | 8 ++-- src/types/currency.js | 10 ++--- src/types/hash-128.js | 6 +-- src/types/hash-160.js | 6 +-- src/types/hash-256.js | 6 +-- src/types/hash.js | 10 ++--- src/types/index.js | 34 +++++++------- src/types/path-set.js | 10 ++--- src/types/serialized-type.js | 6 +-- src/types/st-array.js | 11 ++--- src/types/st-object.js | 13 +++--- src/types/uint-16.js | 6 +-- src/types/uint-32.js | 6 +-- src/types/uint-64.js | 14 +++--- src/types/uint-8.js | 6 +-- src/types/uint.js | 12 ++--- src/types/vector-256.js | 8 ++-- src/utils/bytes-utils.js | 4 +- src/utils/make-class.js | 33 +++++++++++--- test/amount-test.js | 9 ++-- test/binary-json-test.js | 6 +-- test/binary-parser-test.js | 14 +++--- test/binary-serializer-test.js | 71 +++++++++++++++++++----------- test/bytes-utils-test.js | 4 +- test/hash-test.js | 5 ++- test/ledger-test.js | 6 +-- test/mocha.opts | 1 - test/quality-test.js | 5 ++- test/shamap-test.js | 10 ++--- test/signing-data-encoding-test.js | 8 ++-- test/tx-encode-decode-test.js | 6 +-- test/types-test.js | 8 ++-- test/uint-test.js | 4 +- test/utils.js | 18 +++++--- 50 files changed, 324 insertions(+), 271 deletions(-) delete mode 100644 .babelrc delete mode 100644 test/mocha.opts diff --git a/.babelrc b/.babelrc deleted file mode 100644 index d521395..0000000 --- a/.babelrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "presets" : ["es2015"], - "retainLines": true -} diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index e89a06c..f87a53f 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - node-version: [10.x, 12.x, 13.x, 14.x] + node-version: [20.x, 22.x] steps: - uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2.7.0 @@ -26,5 +26,3 @@ jobs: node-version: ${{ matrix.node-version }} - run: yarn install - run: yarn run test - - run: yarn run lint - - run: yarn run compile diff --git a/package.json b/package.json index 1689a32..8ea8375 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,12 @@ { "name": "@exodus/ripple-binary-codec", - "version": "0.2.9", + "version": "0.3.0", "description": "XRP Ledger binary codec", + "type": "module", "files": [ - "distrib/npm/*" + "src" ], - "main": "distrib/npm/", + "main": "src/index.js", "directories": { "test": "test" }, @@ -18,23 +19,12 @@ "lodash": "^4.17.15" }, "devDependencies": { - "babel-cli": "^6.8.0", - "babel-core": "^6.8.0", - "babel-eslint": "^10.0.2", - "babel-loader": "^6.2.4", - "babel-preset-es2015": "^6.6.0", - "babel-register": "^6.8.0", - "eslint": "^7.0.0", "fs-extra": "^9.0.0", "intercept-stdout": "^0.1.2", - "istanbul": "~0.4.3", "mocha": "~7.1.2" }, "scripts": { - "compile": "babel --optional runtime -d distrib/npm/ src/ && cp src/enums/definitions.json distrib/npm/enums", - "prepublish": "npm test && npm run lint && npm run compile", - "test": "istanbul test _mocha", - "lint": "if ! [ -f eslintrc ]; then curl -o eslintrc 'https://raw.githubusercontent.com/ripple/javascript-style-guide/es6/eslintrc'; echo 'parser: babel-eslint' >> eslintrc; fi; eslint -c eslintrc src/**/*.js test/*.js" + "test": "mocha 'test/*-test.js'" }, "repository": { "type": "git", diff --git a/src/binary.js b/src/binary.js index 03e4494..fd75403 100644 --- a/src/binary.js +++ b/src/binary.js @@ -1,13 +1,13 @@ /* eslint-disable func-style */ -const BN = require('bn.js'); -const types = require('./types'); -const {HashPrefix} = require('./hash-prefixes'); -const {BinaryParser} = require('./serdes/binary-parser'); -const {BinarySerializer, BytesList} = require('./serdes/binary-serializer'); -const {bytesToHex, slice, parseBytes} = require('./utils/bytes-utils'); +import BN from 'bn.js'; +import types from './types/index.js'; +import {HashPrefix} from './hash-prefixes.js'; +import {BinaryParser} from './serdes/binary-parser.js'; +import {BinarySerializer, BytesList} from './serdes/binary-serializer.js'; +import {bytesToHex, slice, parseBytes} from './utils/bytes-utils.js'; -const {sha512Half, transactionID} = require('./hashes'); +import {sha512Half, transactionID} from './hashes.js'; const makeParser = bytes => new BinaryParser(bytes); const readJSON = parser => parser.readType(types.STObject).toJSON(); @@ -50,7 +50,7 @@ function multiSigningData(tx, signingAccount) { return serializeObject(tx, {prefix, suffix, signingFieldsOnly: true}); } -module.exports = { +export { BinaryParser, BinarySerializer, BytesList, diff --git a/src/coretypes.js b/src/coretypes.js index 29b84c0..cb5792f 100644 --- a/src/coretypes.js +++ b/src/coretypes.js @@ -1,16 +1,16 @@ -const _ = require('lodash'); -const enums = require('./enums'); +import _ from 'lodash'; +import enums from './enums/index.js'; +import types from './types/index.js'; +import * as binary from './binary.js'; +import {ShaMap} from './shamap.js'; +import * as ledgerHashes from './ledger-hashes.js'; +import * as hashes from './hashes.js'; +import quality from './quality.js'; +import {HashPrefix} from './hash-prefixes.js'; const {Field} = enums; -const types = require('./types'); -const binary = require('./binary'); -const {ShaMap} = require('./shamap'); -const ledgerHashes = require('./ledger-hashes'); -const hashes = require('./hashes'); -const quality = require('./quality'); -const {HashPrefix} = require('./hash-prefixes'); -module.exports = _.assign({ +export default _.assign({ hashes: _.assign({}, hashes, ledgerHashes), binary, enums, diff --git a/src/enums/index.js b/src/enums/index.js index eeb8172..9c58914 100644 --- a/src/enums/index.js +++ b/src/enums/index.js @@ -1,8 +1,8 @@ -const assert = require('assert'); -const _ = require('lodash'); -const {parseBytes, serializeUIntN} = require('./../utils/bytes-utils'); -const makeClass = require('./../utils/make-class'); -const enums = require('./definitions.json'); +import assert from 'assert'; +import _ from 'lodash'; +import {parseBytes, serializeUIntN} from './../utils/bytes-utils.js'; +import makeClass from './../utils/make-class.js'; +import enums from './definitions.json' with { type: 'json' }; function transformWith(func, obj) { return _.transform(obj, func); @@ -122,4 +122,4 @@ Enums.Field = makeClass({ } }); -module.exports = Enums; +export default Enums; diff --git a/src/hash-prefixes.js b/src/hash-prefixes.js index 707e6b3..b933756 100644 --- a/src/hash-prefixes.js +++ b/src/hash-prefixes.js @@ -1,4 +1,4 @@ -const {serializeUIntN} = require('./utils/bytes-utils'); +import {serializeUIntN} from './utils/bytes-utils.js'; function bytes(uint32) { return serializeUIntN(uint32, 4); @@ -26,6 +26,6 @@ const HashPrefix = { paymentChannelClaim: bytes(0x434C4D00) }; -module.exports = { +export { HashPrefix }; diff --git a/src/hashes.js b/src/hashes.js index 4495946..d49f9a5 100644 --- a/src/hashes.js +++ b/src/hashes.js @@ -1,8 +1,9 @@ -const makeClass = require('./utils/make-class'); -const {HashPrefix} = require('./hash-prefixes'); -const {Hash256} = require('./types'); -const {parseBytes} = require('./utils/bytes-utils'); -const createHash = require('create-hash'); +import makeClass from './utils/make-class.js'; +import {HashPrefix} from './hash-prefixes.js'; +import types from './types/index.js'; +import {parseBytes} from './utils/bytes-utils.js'; +import createHash from 'create-hash'; +const {Hash256} = types; const Sha512Half = makeClass({ Sha512Half() { @@ -36,7 +37,7 @@ function transactionID(serialized) { return new Hash256(sha512Half(HashPrefix.transactionID, serialized)); } -module.exports = { +export { Sha512Half, sha512Half, transactionID diff --git a/src/index.js b/src/index.js index 18cc587..f48543e 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,5 @@ -const assert = require('assert'); -const coreTypes = require('./coretypes'); +import assert from 'assert'; +import coreTypes from './coretypes.js'; const {quality, binary: {bytesToHex, signingData, @@ -61,7 +61,23 @@ function decodeQuality(value) { return quality.decode(value).toString(); } -module.exports = { +export { + decode, + encode, + encodeForSigning, + encodeForSigningClaim, + encodeForMultisigning, + encodeQuality, + decodeQuality, + decodeLedgerData +}; + +// Preserve the CommonJS `module.exports = { ... }` shape as the ESM default +// export, so existing default-import consumers (e.g. `@exodus/ripple-lib`'s +// sign paths and `hw-ledger`, which do `import binaryCodec from +// '@exodus/ripple-binary-codec'` then call `binaryCodec.encode(...)`) keep +// working. Named exports above cover `import { encode } from ...` consumers. +export default { decode, encode, encodeForSigning, diff --git a/src/ledger-hashes.js b/src/ledger-hashes.js index d3234c4..bc44cf0 100644 --- a/src/ledger-hashes.js +++ b/src/ledger-hashes.js @@ -1,12 +1,12 @@ -const _ = require('lodash'); -const BN = require('bn.js'); -const assert = require('assert'); -const types = require('./types'); +import _ from 'lodash'; +import BN from 'bn.js'; +import assert from 'assert'; +import types from './types/index.js'; +import {ShaMap} from './shamap.js'; +import {HashPrefix} from './hash-prefixes.js'; +import {Sha512Half} from './hashes.js'; +import {BinarySerializer, serializeObject} from './binary.js'; const {STObject, Hash256} = types; -const {ShaMap} = require('./shamap'); -const {HashPrefix} = require('./hash-prefixes'); -const {Sha512Half} = require('./hashes'); -const {BinarySerializer, serializeObject} = require('./binary'); function computeHash(itemizer, itemsJson) { const map = new ShaMap(); @@ -65,7 +65,7 @@ function ledgerHash(header) { return hash.finish(); } -module.exports = { +export { accountStateHash, transactionTreeHash, ledgerHash diff --git a/src/quality.js b/src/quality.js index 1f84f2f..7c9dabc 100644 --- a/src/quality.js +++ b/src/quality.js @@ -1,9 +1,10 @@ -const Decimal = require('decimal.js').default; -const {bytesToHex, slice, parseBytes} = require('./utils/bytes-utils'); -const {UInt64} = require('./types'); -const BN = require('bn.js'); +import Decimal from 'decimal.js'; +import {bytesToHex, slice, parseBytes} from './utils/bytes-utils.js'; +import types from './types/index.js'; +import BN from 'bn.js'; +const {UInt64} = types; -module.exports = { +export default { encode(arg) { const quality = arg instanceof Decimal ? arg : new Decimal(arg); const exponent = quality.e - 15; diff --git a/src/serdes/binary-parser.js b/src/serdes/binary-parser.js index c747373..afa2e55 100644 --- a/src/serdes/binary-parser.js +++ b/src/serdes/binary-parser.js @@ -1,7 +1,8 @@ -const assert = require('assert'); -const makeClass = require('../utils/make-class'); -const {Field} = require('../enums'); -const {slice, parseBytes} = require('../utils/bytes-utils'); +import assert from 'assert'; +import makeClass from '../utils/make-class.js'; +import enums from '../enums/index.js'; +import {slice, parseBytes} from '../utils/bytes-utils.js'; +const {Field} = enums; const BinaryParser = makeClass({ BinaryParser(buf) { @@ -94,6 +95,6 @@ const BinaryParser = makeClass({ }); -module.exports = { +export { BinaryParser }; diff --git a/src/serdes/binary-serializer.js b/src/serdes/binary-serializer.js index 620aa3d..903294e 100644 --- a/src/serdes/binary-serializer.js +++ b/src/serdes/binary-serializer.js @@ -1,7 +1,8 @@ -const assert = require('assert'); -const {parseBytes, bytesToHex} = require('../utils/bytes-utils'); -const makeClass = require('../utils/make-class'); -const {Type, Field} = require('../enums'); +import assert from 'assert'; +import {parseBytes, bytesToHex} from '../utils/bytes-utils.js'; +import makeClass from '../utils/make-class.js'; +import enums from '../enums/index.js'; +const {Type, Field} = enums; const BytesSink = { put(/* bytesSequence */) { @@ -101,7 +102,7 @@ const BinarySerializer = makeClass({ } }); -module.exports = { +export { BytesList, BinarySerializer }; diff --git a/src/shamap.js b/src/shamap.js index fd608f3..8c2512f 100644 --- a/src/shamap.js +++ b/src/shamap.js @@ -1,8 +1,9 @@ -const assert = require('assert'); -const makeClass = require('./utils/make-class'); -const {Hash256} = require('./types'); -const {HashPrefix} = require('./hash-prefixes'); -const {Sha512Half: Hasher} = require('./hashes'); +import assert from 'assert'; +import makeClass from './utils/make-class.js'; +import types from './types/index.js'; +import {HashPrefix} from './hash-prefixes.js'; +import {Sha512Half as Hasher} from './hashes.js'; +const {Hash256} = types; const ShaMapNode = makeClass({ virtuals: { @@ -103,6 +104,6 @@ const ShaMap = makeClass({ inherits: ShaMapInner }); -module.exports = { +export { ShaMap }; diff --git a/src/types/account-id.js b/src/types/account-id.js index 564e0fa..77cdc8c 100644 --- a/src/types/account-id.js +++ b/src/types/account-id.js @@ -1,9 +1,9 @@ -const makeClass = require('../utils/make-class'); -const { +import makeClass from '../utils/make-class.js'; +import { decodeAccountID, encodeAccountID -} = require('@exodus/ripple-address-codec'); -const {Hash160} = require('./hash-160'); +} from '@exodus/ripple-address-codec'; +import {Hash160} from './hash-160.js'; const AccountID = makeClass({ AccountID(bytes) { @@ -40,6 +40,6 @@ const AccountID = makeClass({ } }); -module.exports = { +export { AccountID }; diff --git a/src/types/amount.js b/src/types/amount.js index fc03d87..0095166 100644 --- a/src/types/amount.js +++ b/src/types/amount.js @@ -1,13 +1,13 @@ -const _ = require('lodash'); -const assert = require('assert'); -const BN = require('bn.js'); -const Decimal = require('decimal.js').default; -const makeClass = require('../utils/make-class'); -const {SerializedType} = require('./serialized-type'); -const {bytesToHex} = require('../utils/bytes-utils'); -const {Currency} = require('./currency'); -const {AccountID} = require('./account-id'); -const {UInt64} = require('./uint-64'); +import _ from 'lodash'; +import assert from 'assert'; +import BN from 'bn.js'; +import Decimal from 'decimal.js'; +import makeClass from '../utils/make-class.js'; +import {SerializedType} from './serialized-type.js'; +import {bytesToHex} from '../utils/bytes-utils.js'; +import {Currency} from './currency.js'; +import {AccountID} from './account-id.js'; +import {UInt64} from './uint-64.js'; const MIN_IOU_EXPONENT = -96; const MAX_IOU_EXPONENT = 80; @@ -211,6 +211,6 @@ const Amount = makeClass({ } }); -module.exports = { +export { Amount }; diff --git a/src/types/blob.js b/src/types/blob.js index 7d6a3c9..074730f 100644 --- a/src/types/blob.js +++ b/src/types/blob.js @@ -1,6 +1,6 @@ -const makeClass = require('../utils/make-class'); -const {parseBytes} = require('../utils/bytes-utils'); -const {SerializedType} = require('./serialized-type'); +import makeClass from '../utils/make-class.js'; +import {parseBytes} from '../utils/bytes-utils.js'; +import {SerializedType} from './serialized-type.js'; const Blob = makeClass({ mixins: SerializedType, @@ -24,6 +24,6 @@ const Blob = makeClass({ } }); -module.exports = { +export { Blob }; diff --git a/src/types/currency.js b/src/types/currency.js index d96f2d1..f220773 100644 --- a/src/types/currency.js +++ b/src/types/currency.js @@ -1,7 +1,7 @@ -const _ = require('lodash'); -const makeClass = require('../utils/make-class'); -const {slice} = require('../utils/bytes-utils'); -const {Hash160} = require('./hash-160'); +import _ from 'lodash'; +import makeClass from '../utils/make-class.js'; +import {slice} from '../utils/bytes-utils.js'; +import {Hash160} from './hash-160.js'; const ISO_REGEX = /^[A-Z0-9]{3}$/; const HEX_REGEX = /^[A-F0-9]{40}$/; @@ -87,6 +87,6 @@ const Currency = makeClass({ } }); -module.exports = { +export { Currency }; diff --git a/src/types/hash-128.js b/src/types/hash-128.js index bb29417..6c145b1 100644 --- a/src/types/hash-128.js +++ b/src/types/hash-128.js @@ -1,11 +1,11 @@ -const makeClass = require('../utils/make-class'); -const {Hash} = require('./hash'); +import makeClass from '../utils/make-class.js'; +import {Hash} from './hash.js'; const Hash128 = makeClass({ inherits: Hash, statics: {width: 16} }); -module.exports = { +export { Hash128 }; diff --git a/src/types/hash-160.js b/src/types/hash-160.js index 8a96875..98cadda 100644 --- a/src/types/hash-160.js +++ b/src/types/hash-160.js @@ -1,11 +1,11 @@ -const makeClass = require('../utils/make-class'); -const {Hash} = require('./hash'); +import makeClass from '../utils/make-class.js'; +import {Hash} from './hash.js'; const Hash160 = makeClass({ inherits: Hash, statics: {width: 20} }); -module.exports = { +export { Hash160 }; diff --git a/src/types/hash-256.js b/src/types/hash-256.js index 4a4bfb2..271b6d0 100644 --- a/src/types/hash-256.js +++ b/src/types/hash-256.js @@ -1,5 +1,5 @@ -const makeClass = require('../utils/make-class'); -const {Hash} = require('./hash'); +import makeClass from '../utils/make-class.js'; +import {Hash} from './hash.js'; const Hash256 = makeClass({ inherits: Hash, @@ -11,6 +11,6 @@ const Hash256 = makeClass({ } }); -module.exports = { +export { Hash256 }; diff --git a/src/types/hash.js b/src/types/hash.js index e68375c..4f3bd5b 100644 --- a/src/types/hash.js +++ b/src/types/hash.js @@ -1,7 +1,7 @@ -const assert = require('assert'); -const makeClass = require('../utils/make-class'); -const {Comparable, SerializedType} = require('./serialized-type'); -const {compareBytes, parseBytes} = require('../utils/bytes-utils'); +import assert from 'assert'; +import makeClass from '../utils/make-class.js'; +import {Comparable, SerializedType} from './serialized-type.js'; +import {compareBytes, parseBytes} from '../utils/bytes-utils.js'; const Hash = makeClass({ Hash(bytes) { @@ -41,6 +41,6 @@ const Hash = makeClass({ } }); -module.exports = { +export { Hash }; diff --git a/src/types/index.js b/src/types/index.js index 7df5c8b..afbd3f7 100644 --- a/src/types/index.js +++ b/src/types/index.js @@ -1,20 +1,20 @@ -const enums = require('../enums'); +import enums from '../enums/index.js'; +import {AccountID} from './account-id.js'; +import {Amount} from './amount.js'; +import {Blob} from './blob.js'; +import {Currency} from './currency.js'; +import {Hash128} from './hash-128.js'; +import {Hash160} from './hash-160.js'; +import {Hash256} from './hash-256.js'; +import {PathSet} from './path-set.js'; +import {STArray} from './st-array.js'; +import {STObject} from './st-object.js'; +import {UInt16} from './uint-16.js'; +import {UInt32} from './uint-32.js'; +import {UInt64} from './uint-64.js'; +import {UInt8} from './uint-8.js'; +import {Vector256} from './vector-256.js'; const {Field} = enums; -const {AccountID} = require('./account-id'); -const {Amount} = require('./amount'); -const {Blob} = require('./blob'); -const {Currency} = require('./currency'); -const {Hash128} = require('./hash-128'); -const {Hash160} = require('./hash-160'); -const {Hash256} = require('./hash-256'); -const {PathSet} = require('./path-set'); -const {STArray} = require('./st-array'); -const {STObject} = require('./st-object'); -const {UInt16} = require('./uint-16'); -const {UInt32} = require('./uint-32'); -const {UInt64} = require('./uint-64'); -const {UInt8} = require('./uint-8'); -const {Vector256} = require('./vector-256'); const coreTypes = { AccountID, @@ -42,4 +42,4 @@ Field.TransactionType.associatedType = enums.TransactionType; Field.TransactionResult.associatedType = enums.TransactionResult; Field.LedgerEntryType.associatedType = enums.LedgerEntryType; -module.exports = coreTypes; +export default coreTypes; diff --git a/src/types/path-set.js b/src/types/path-set.js index 5a9517b..6766d59 100644 --- a/src/types/path-set.js +++ b/src/types/path-set.js @@ -1,9 +1,9 @@ /* eslint-disable no-unused-expressions */ -const makeClass = require('../utils/make-class'); -const {SerializedType, ensureArrayLikeIs} = require('./serialized-type'); -const {Currency} = require('./currency'); -const {AccountID} = require('./account-id'); +import makeClass from '../utils/make-class.js'; +import {SerializedType, ensureArrayLikeIs} from './serialized-type.js'; +import {Currency} from './currency.js'; +import {AccountID} from './account-id.js'; const PATHSET_END_BYTE = 0x00; const PATH_SEPARATOR_BYTE = 0xFF; @@ -108,6 +108,6 @@ const PathSet = makeClass({ } }); -module.exports = { +export { PathSet }; diff --git a/src/types/serialized-type.js b/src/types/serialized-type.js index 2bf61da..10febe8 100644 --- a/src/types/serialized-type.js +++ b/src/types/serialized-type.js @@ -1,5 +1,5 @@ -const {bytesToHex, slice} = require('../utils/bytes-utils'); -const {BytesList} = require('../serdes/binary-serializer'); +import {bytesToHex, slice} from '../utils/bytes-utils.js'; +import {BytesList} from '../serdes/binary-serializer.js'; const Comparable = { lt(other) { @@ -57,7 +57,7 @@ function ensureArrayLikeIs(Type, arrayLike) { }; } -module.exports = { +export { ensureArrayLikeIs, SerializedType, Comparable diff --git a/src/types/st-array.js b/src/types/st-array.js index 5e3e6df..28870dc 100644 --- a/src/types/st-array.js +++ b/src/types/st-array.js @@ -1,7 +1,8 @@ -const makeClass = require('../utils/make-class'); -const {ensureArrayLikeIs, SerializedType} = require('./serialized-type'); -const {Field} = require('../enums'); -const {STObject} = require('./st-object'); +import makeClass from '../utils/make-class.js'; +import {ensureArrayLikeIs, SerializedType} from './serialized-type.js'; +import enums from '../enums/index.js'; +import {STObject} from './st-object.js'; +const {Field} = enums; const {ArrayEndMarker} = Field; const STArray = makeClass({ @@ -33,6 +34,6 @@ const STArray = makeClass({ } }); -module.exports = { +export { STArray }; diff --git a/src/types/st-object.js b/src/types/st-object.js index d22dcdb..cac8ab4 100644 --- a/src/types/st-object.js +++ b/src/types/st-object.js @@ -1,9 +1,10 @@ -const _ = require('lodash'); -const makeClass = require('../utils/make-class'); -const {Field} = require('../enums'); -const {BinarySerializer} = require('../serdes/binary-serializer'); +import _ from 'lodash'; +import makeClass from '../utils/make-class.js'; +import enums from '../enums/index.js'; +import {BinarySerializer} from '../serdes/binary-serializer.js'; +import {SerializedType} from './serialized-type.js'; +const {Field} = enums; const {ObjectEndMarker} = Field; -const {SerializedType} = require('./serialized-type'); const STObject = makeClass({ mixins: SerializedType, @@ -61,6 +62,6 @@ const STObject = makeClass({ } }); -module.exports = { +export { STObject }; diff --git a/src/types/uint-16.js b/src/types/uint-16.js index c6547ca..4aa46f5 100644 --- a/src/types/uint-16.js +++ b/src/types/uint-16.js @@ -1,11 +1,11 @@ -const makeClass = require('../utils/make-class'); -const {UInt} = require('./uint'); +import makeClass from '../utils/make-class.js'; +import {UInt} from './uint.js'; const UInt16 = makeClass({ inherits: UInt, statics: {width: 2} }); -module.exports = { +export { UInt16 }; diff --git a/src/types/uint-32.js b/src/types/uint-32.js index 2865608..ce41ac6 100644 --- a/src/types/uint-32.js +++ b/src/types/uint-32.js @@ -1,11 +1,11 @@ -const makeClass = require('../utils/make-class'); -const {UInt} = require('./uint'); +import makeClass from '../utils/make-class.js'; +import {UInt} from './uint.js'; const UInt32 = makeClass({ inherits: UInt, statics: {width: 4} }); -module.exports = { +export { UInt32 }; diff --git a/src/types/uint-64.js b/src/types/uint-64.js index fd731a1..a2800c6 100644 --- a/src/types/uint-64.js +++ b/src/types/uint-64.js @@ -1,9 +1,9 @@ -const assert = require('assert'); -const BN = require('bn.js'); -const makeClass = require('../utils/make-class'); -const {bytesToHex, parseBytes, serializeUIntN} - = require('../utils/bytes-utils'); -const {UInt} = require('./uint'); +import assert from 'assert'; +import BN from 'bn.js'; +import makeClass from '../utils/make-class.js'; +import {bytesToHex, parseBytes, serializeUIntN} + from '../utils/bytes-utils.js'; +import {UInt} from './uint.js'; const HEX_REGEX = /^[A-F0-9]{16}$/; @@ -45,6 +45,6 @@ const UInt64 = makeClass({ } }); -module.exports = { +export { UInt64 }; diff --git a/src/types/uint-8.js b/src/types/uint-8.js index 2f261e1..ad79434 100644 --- a/src/types/uint-8.js +++ b/src/types/uint-8.js @@ -1,11 +1,11 @@ -const makeClass = require('../utils/make-class'); -const {UInt} = require('./uint'); +import makeClass from '../utils/make-class.js'; +import {UInt} from './uint.js'; const UInt8 = makeClass({ inherits: UInt, statics: {width: 1} }); -module.exports = { +export { UInt8 }; diff --git a/src/types/uint.js b/src/types/uint.js index 16c0062..f9d80df 100644 --- a/src/types/uint.js +++ b/src/types/uint.js @@ -1,8 +1,8 @@ -const assert = require('assert'); -const BN = require('bn.js'); -const makeClass = require('../utils/make-class'); -const {Comparable, SerializedType} = require('./serialized-type'); -const {serializeUIntN} = require('../utils/bytes-utils'); +import assert from 'assert'; +import BN from 'bn.js'; +import makeClass from '../utils/make-class.js'; +import {Comparable, SerializedType} from './serialized-type.js'; +import {serializeUIntN} from '../utils/bytes-utils.js'; const MAX_VALUES = [0, 255, 65535, 16777215, 4294967295]; function signum(a, b) { @@ -56,6 +56,6 @@ const UInt = makeClass({ } }); -module.exports = { +export { UInt }; diff --git a/src/types/vector-256.js b/src/types/vector-256.js index fdbcc44..df4715a 100644 --- a/src/types/vector-256.js +++ b/src/types/vector-256.js @@ -1,6 +1,6 @@ -const makeClass = require('../utils/make-class'); -const {Hash256} = require('./hash-256'); -const {ensureArrayLikeIs, SerializedType} = require('./serialized-type'); +import makeClass from '../utils/make-class.js'; +import {Hash256} from './hash-256.js'; +import {ensureArrayLikeIs, SerializedType} from './serialized-type.js'; const Vector256 = makeClass({ mixins: SerializedType, @@ -27,6 +27,6 @@ const Vector256 = makeClass({ } }); -module.exports = { +export { Vector256 }; diff --git a/src/utils/bytes-utils.js b/src/utils/bytes-utils.js index 7daba22..ae3df84 100644 --- a/src/utils/bytes-utils.js +++ b/src/utils/bytes-utils.js @@ -1,4 +1,4 @@ -const assert = require('assert'); +import assert from 'assert'; function signum(a, b) { return a < b ? -1 : a === b ? 0 : 1; @@ -104,7 +104,7 @@ function slice(val, startIx = 0, endIx = val.length, Output = val.constructor) { return res; } -module.exports = { +export { parseBytes, bytesToHex, slice, diff --git a/src/utils/make-class.js b/src/utils/make-class.js index d51b984..db8cf66 100644 --- a/src/utils/make-class.js +++ b/src/utils/make-class.js @@ -1,5 +1,5 @@ -const _ = require('lodash'); -const inherits = require('inherits'); +import _ from 'lodash'; +import inherits from 'inherits'; function forEach(obj, func) { Object.keys(obj || {}).forEach(k => { @@ -11,13 +11,34 @@ function ensureArray(val) { return Array.isArray(val) ? val : [val]; } -module.exports = function makeClass(klass_, definition_) { +function asConstructor(fn) { + // Concise object methods (`Name(args) {}`) are not constructors and have no + // `prototype`. Under the previous Babel (es2015) build these were emitted as + // ordinary function expressions, which makeClass relies on (it reads + // `klass.prototype` and instantiates via `new this(...)`). When the raw + // source runs as native ESM we restore that behaviour by wrapping such a + // method in a plain function that forwards `this`/`arguments`. + if (typeof fn === 'function' && + !Object.prototype.hasOwnProperty.call(fn, 'prototype')) { + return function() { + return fn.apply(this, arguments); + }; + } + return fn; +} + +export default function makeClass(klass_, definition_) { const definition = definition_ || klass_; - let klass = typeof klass_ === 'function' ? klass_ : null; + // Keep a reference to the original constructor function as it appears on the + // definition, so the prototype-method loop below can skip it (asConstructor + // may return a wrapper, which would otherwise no longer compare equal). + let klassDef = typeof klass_ === 'function' ? klass_ : null; + let klass = asConstructor(klassDef); if (klass === null) { for (const k in definition) { if (k[0].match(/[A-Z]/)) { - klass = definition[k]; + klassDef = definition[k]; + klass = asConstructor(klassDef); break; } } @@ -52,7 +73,7 @@ module.exports = function makeClass(klass_, definition_) { }); forEach(definition.methods, addFunc); forEach(definition, (f, n) => { - if (_.isFunction(f) && f !== klass) { + if (_.isFunction(f) && f !== klass && f !== klassDef) { addFunc(f, n); } }); diff --git a/test/amount-test.js b/test/amount-test.js index 5accf71..9813f3c 100644 --- a/test/amount-test.js +++ b/test/amount-test.js @@ -1,7 +1,8 @@ -const _ = require('lodash'); -const assert = require('assert'); -const utils = require('./utils'); -const {Amount} = require('../src/coretypes'); +import _ from 'lodash'; +import assert from 'assert'; +import * as utils from './utils.js'; +import coreTypes from '../src/coretypes.js'; +const {Amount} = coreTypes; const {loadFixture} = utils; const fixtures = loadFixture('data-driven-tests.json'); diff --git a/test/binary-json-test.js b/test/binary-json-test.js index 1daf40e..e26ec19 100644 --- a/test/binary-json-test.js +++ b/test/binary-json-test.js @@ -1,6 +1,6 @@ -const assert = require('assert'); -const fixtures = require('./fixtures/codec-fixtures.json'); -const {decode, encode, decodeLedgerData} = require('../src'); +import assert from 'assert'; +import fixtures from './fixtures/codec-fixtures.json' with { type: 'json' }; +import {decode, encode, decodeLedgerData} from '../src/index.js'; function json(object) { return JSON.stringify(object); diff --git a/test/binary-parser-test.js b/test/binary-parser-test.js index 894e73d..2bc85e4 100644 --- a/test/binary-parser-test.js +++ b/test/binary-parser-test.js @@ -1,17 +1,17 @@ /* eslint-disable func-style */ -const coreTypes = require('../src/coretypes'); +import coreTypes from '../src/coretypes.js'; -const _ = require('lodash'); -const assert = require('assert'); -const {encodeAccountID} = require('@exodus/ripple-address-codec'); +import _ from 'lodash'; +import assert from 'assert'; +import {encodeAccountID} from '@exodus/ripple-address-codec'; +import * as utils from './utils.js'; +import {bytesToHex} from '../src/utils/bytes-utils.js'; +import {BytesList} from '../src/serdes/binary-serializer.js'; const {binary: {makeParser, readJSON}, Field, Amount, Hash160} = coreTypes; const {enums: {TransactionType}} = coreTypes; -const utils = require('./utils'); const {parseHexOnly, assertEqualAmountJSON, hexOnly, loadFixture} = utils; -const {bytesToHex} = require('../src/utils/bytes-utils'); const fixtures = loadFixture('data-driven-tests.json'); -const {BytesList} = require('../src/serdes/binary-serializer'); const __ = hexOnly; function unused() {} diff --git a/test/binary-serializer-test.js b/test/binary-serializer-test.js index 37b1e01..e6af19b 100644 --- a/test/binary-serializer-test.js +++ b/test/binary-serializer-test.js @@ -1,52 +1,71 @@ /* eslint-disable func-style */ -const BN = require('bn.js'); -const assert = require('assert'); -const lib = require('../src/coretypes'); -const encode = require('../src').encode; +import BN from 'bn.js'; +import assert from 'assert'; +import lib from '../src/coretypes.js'; +import {encode} from '../src/index.js'; +import {loadFixture} from './utils.js'; +import deliverMinTx from './fixtures/delivermin-tx.json' with { type: 'json' }; +import deliverMinTxBinary from './fixtures/delivermin-tx-binary.json' with { type: 'json' }; +import signerListSetTx from './fixtures/signerlistset-tx.json' with { type: 'json' }; +import signerListSetBinary from './fixtures/signerlistset-tx-binary.json' with { type: 'json' }; +import signerListSetMeta from './fixtures/signerlistset-tx-meta-binary.json' with { type: 'json' }; +import depositPreauthTx from './fixtures/deposit-preauth-tx.json' with { type: 'json' }; +import depositPreauthBinary from './fixtures/deposit-preauth-tx-binary.json' with { type: 'json' }; +import depositPreauthMeta from './fixtures/deposit-preauth-tx-meta-binary.json' with { type: 'json' }; +import escrowCreateTx from './fixtures/escrow-create-tx.json' with { type: 'json' }; +import escrowCreateBinary from './fixtures/escrow-create-binary.json' with { type: 'json' }; +import escrowFinishTx from './fixtures/escrow-finish-tx.json' with { type: 'json' }; +import escrowFinishBinary from './fixtures/escrow-finish-binary.json' with { type: 'json' }; +import escrowFinishMeta from './fixtures/escrow-finish-meta-binary.json' with { type: 'json' }; +import escrowCancelTx from './fixtures/escrow-cancel-tx.json' with { type: 'json' }; +import escrowCancelBinary from './fixtures/escrow-cancel-binary.json' with { type: 'json' }; +import paymentChannelCreateTx from './fixtures/payment-channel-create-tx.json' with { type: 'json' }; +import paymentChannelCreateBinary from './fixtures/payment-channel-create-binary.json' with { type: 'json' }; +import paymentChannelFundTx from './fixtures/payment-channel-fund-tx.json' with { type: 'json' }; +import paymentChannelFundBinary from './fixtures/payment-channel-fund-binary.json' with { type: 'json' }; +import paymentChannelClaimTx from './fixtures/payment-channel-claim-tx.json' with { type: 'json' }; +import paymentChannelClaimBinary from './fixtures/payment-channel-claim-binary.json' with { type: 'json' }; const {binary: {makeParser, BytesList, BinarySerializer}} = lib; const {UInt8, UInt16, UInt32, UInt64, STObject} = lib; -const {loadFixture} = require('./utils'); const fixtures = loadFixture('data-driven-tests.json'); -const deliverMinTx = require('./fixtures/delivermin-tx.json'); -const deliverMinTxBinary = require('./fixtures/delivermin-tx-binary.json'); const SignerListSet = { - tx: require('./fixtures/signerlistset-tx.json'), - binary: require('./fixtures/signerlistset-tx-binary.json'), - meta: require('./fixtures/signerlistset-tx-meta-binary.json') + tx: signerListSetTx, + binary: signerListSetBinary, + meta: signerListSetMeta }; const DepositPreauth = { - tx: require('./fixtures/deposit-preauth-tx.json'), - binary: require('./fixtures/deposit-preauth-tx-binary.json'), - meta: require('./fixtures/deposit-preauth-tx-meta-binary.json') + tx: depositPreauthTx, + binary: depositPreauthBinary, + meta: depositPreauthMeta }; const Escrow = { create: { - tx: require('./fixtures/escrow-create-tx.json'), - binary: require('./fixtures/escrow-create-binary.json') + tx: escrowCreateTx, + binary: escrowCreateBinary }, finish: { - tx: require('./fixtures/escrow-finish-tx.json'), - binary: require('./fixtures/escrow-finish-binary.json'), - meta: require('./fixtures/escrow-finish-meta-binary.json') + tx: escrowFinishTx, + binary: escrowFinishBinary, + meta: escrowFinishMeta }, cancel: { - tx: require('./fixtures/escrow-cancel-tx.json'), - binary: require('./fixtures/escrow-cancel-binary.json') + tx: escrowCancelTx, + binary: escrowCancelBinary } } const PaymentChannel = { create: { - tx: require('./fixtures/payment-channel-create-tx.json'), - binary: require('./fixtures/payment-channel-create-binary.json') + tx: paymentChannelCreateTx, + binary: paymentChannelCreateBinary }, fund: { - tx: require('./fixtures/payment-channel-fund-tx.json'), - binary: require('./fixtures/payment-channel-fund-binary.json') + tx: paymentChannelFundTx, + binary: paymentChannelFundBinary }, claim: { - tx: require('./fixtures/payment-channel-claim-tx.json'), - binary: require('./fixtures/payment-channel-claim-binary.json') + tx: paymentChannelClaimTx, + binary: paymentChannelClaimBinary } } diff --git a/test/bytes-utils-test.js b/test/bytes-utils-test.js index 5d461e0..d0c4820 100644 --- a/test/bytes-utils-test.js +++ b/test/bytes-utils-test.js @@ -1,5 +1,5 @@ -const assert = require('assert'); -const bytesUtils = require('../src/utils/bytes-utils'); +import assert from 'assert'; +import * as bytesUtils from '../src/utils/bytes-utils.js'; const {slice, compareBytes, parseBytes, bytesToHex} = bytesUtils; describe('bytes-utils', function() { diff --git a/test/hash-test.js b/test/hash-test.js index c39a5ca..e64d385 100644 --- a/test/hash-test.js +++ b/test/hash-test.js @@ -1,5 +1,6 @@ -const assert = require('assert'); -const {Hash160, Hash256, Currency, AccountID} = require('../src/coretypes'); +import assert from 'assert'; +import coreTypes from '../src/coretypes.js'; +const {Hash160, Hash256, Currency, AccountID} = coreTypes; describe('Hash160', function() { it('has a static width membmer', function() { diff --git a/test/ledger-test.js b/test/ledger-test.js index f06b6c4..b879037 100644 --- a/test/ledger-test.js +++ b/test/ledger-test.js @@ -1,6 +1,6 @@ -const assert = require('assert'); -const {loadFixture} = require('./utils'); -const ledgerHashes = require('../src/ledger-hashes'); +import assert from 'assert'; +import {loadFixture} from './utils.js'; +import * as ledgerHashes from '../src/ledger-hashes.js'; const {transactionTreeHash, ledgerHash, accountStateHash} = ledgerHashes; describe('Ledger Hashes', function() { diff --git a/test/mocha.opts b/test/mocha.opts deleted file mode 100644 index fc53e34..0000000 --- a/test/mocha.opts +++ /dev/null @@ -1 +0,0 @@ ---reporter spec --slow 500 --require babel-core/register diff --git a/test/quality-test.js b/test/quality-test.js index a39d854..8de177d 100644 --- a/test/quality-test.js +++ b/test/quality-test.js @@ -1,5 +1,6 @@ -const assert = require('assert'); -const {quality, binary: {bytesToHex}} = require('../src/coretypes'); +import assert from 'assert'; +import coreTypes from '../src/coretypes.js'; +const {quality, binary: {bytesToHex}} = coreTypes; describe('Quality encode/decode', function() { const bookDirectory = diff --git a/test/shamap-test.js b/test/shamap-test.js index 5a3763f..0566d42 100644 --- a/test/shamap-test.js +++ b/test/shamap-test.js @@ -1,8 +1,8 @@ -const assert = require('assert'); -const {ShaMap} = require('../src/shamap.js'); -const {binary: {serializeObject}, Hash256, HashPrefix} - = require('../src/coretypes'); -const {loadFixture} = require('./utils'); +import assert from 'assert'; +import {ShaMap} from '../src/shamap.js'; +import coreTypes from '../src/coretypes.js'; +import {loadFixture} from './utils.js'; +const {binary: {serializeObject}, Hash256, HashPrefix} = coreTypes; function now() { return (Number(Date.now())) / 1000; diff --git a/test/signing-data-encoding-test.js b/test/signing-data-encoding-test.js index a501bec..8b49ca1 100644 --- a/test/signing-data-encoding-test.js +++ b/test/signing-data-encoding-test.js @@ -1,7 +1,7 @@ -const _ = require('lodash'); -const assert = require('assert'); -const {encodeForSigning, encodeForSigningClaim, encodeForMultisigning} = - require('../src'); +import _ from 'lodash'; +import assert from 'assert'; +import {encodeForSigning, encodeForSigningClaim, encodeForMultisigning} + from '../src/index.js'; const tx_json = { Account: 'r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ', diff --git a/test/tx-encode-decode-test.js b/test/tx-encode-decode-test.js index c1c6c2f..5a733d1 100644 --- a/test/tx-encode-decode-test.js +++ b/test/tx-encode-decode-test.js @@ -1,8 +1,8 @@ -const assert = require('assert'); -const { +import assert from 'assert'; +import { encode, decode -} = require('../src') +} from '../src/index.js' // Notice: no Amount or Fee const tx_json = { diff --git a/test/types-test.js b/test/types-test.js index eb89d2c..a63508e 100644 --- a/test/types-test.js +++ b/test/types-test.js @@ -1,7 +1,7 @@ -const _ = require('lodash'); -const assert = require('assert'); -const coreTypes = require('../src/types'); -const {SerializedType} = require('../src/types/serialized-type'); +import _ from 'lodash'; +import assert from 'assert'; +import coreTypes from '../src/types/index.js'; +import {SerializedType} from '../src/types/serialized-type.js'; describe('SerializedType interfaces', () => { _.forOwn(coreTypes, (Value, name) => { diff --git a/test/uint-test.js b/test/uint-test.js index a01fb65..8fef9e7 100644 --- a/test/uint-test.js +++ b/test/uint-test.js @@ -1,5 +1,5 @@ -const assert = require('assert'); -const coreTypes = require('../src/coretypes'); +import assert from 'assert'; +import coreTypes from '../src/coretypes.js'; /* eslint-disable no-unused-vars */ const {UInt8, UInt16, UInt32, UInt64} = coreTypes; /* eslint-enable no-unused-vars */ diff --git a/test/utils.js b/test/utils.js index 3a0a088..523ac61 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,9 +1,13 @@ -const intercept = require('intercept-stdout'); -const fs = require('fs'); -const fsExtra = require('fs-extra'); -const assert = require('assert'); -const Decimal = require('decimal.js'); -const {parseBytes} = require('../src/utils/bytes-utils'); +import intercept from 'intercept-stdout'; +import fs from 'fs'; +import fsExtra from 'fs-extra'; +import assert from 'assert'; +import Decimal from 'decimal.js'; +import {createRequire} from 'module'; +import {parseBytes} from '../src/utils/bytes-utils.js'; + +const require = createRequire(import.meta.url); +const __dirname = import.meta.dirname; function hexOnly(hex) { return hex.replace(/[^a-fA-F0-9]/g, ''); @@ -80,7 +84,7 @@ function assertEqualAmountJSON(actual, expected) { new Decimal(expected.value))); } -module.exports = { +export { hexOnly, parseHexOnly, loadFixture,