mirror of
				https://github.com/Xahau/xahau.js.git
				synced 2025-11-04 04:55:48 +00:00 
			
		
		
		
	feat: Jest Test Runner (#2170)
This commit is contained in:
		
							
								
								
									
										4
									
								
								.github/workflows/nodejs.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/nodejs.yml
									
									
									
									
										vendored
									
									
								
							@@ -57,7 +57,7 @@ jobs:
 | 
			
		||||
 | 
			
		||||
    strategy:
 | 
			
		||||
      matrix:
 | 
			
		||||
        node-version: [12.x, 14.x, 16.x, 18.x]
 | 
			
		||||
        node-version: [14.x, 16.x, 18.x]
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v3
 | 
			
		||||
@@ -98,7 +98,7 @@ jobs:
 | 
			
		||||
 | 
			
		||||
    strategy:
 | 
			
		||||
      matrix:
 | 
			
		||||
        node-version: [12.x, 14.x, 16.x, 18.x]
 | 
			
		||||
        node-version: [14.x, 16.x, 18.x]
 | 
			
		||||
 | 
			
		||||
    services:
 | 
			
		||||
      rippled:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								.ncurc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.ncurc.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
{
 | 
			
		||||
  "reject": [
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							@@ -39,4 +39,12 @@
 | 
			
		||||
        "**/.git/subtree-cache/**": true,
 | 
			
		||||
        "**/.hg/store/**": true
 | 
			
		||||
    },
 | 
			
		||||
    "search.exclude": {
 | 
			
		||||
        "**/.git": true,
 | 
			
		||||
        "**/node_modules": true,
 | 
			
		||||
        "**/tmp": true,
 | 
			
		||||
        "**/docs/**/*.html": true,
 | 
			
		||||
        "**/fixtures/**/*.json": true,
 | 
			
		||||
        "**/docs/assets": true
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -122,8 +122,6 @@ If your code connects to the ledger (ex. Adding a new transaction type) it's han
 | 
			
		||||
 | 
			
		||||
All integration tests should be written in the `test/integration` folder, with new `Requests` and `Transactions` tests being in their respective folders.
 | 
			
		||||
 | 
			
		||||
One last note for integration tests is that all imports from `xrpl.js` should be from `xrpl-local` instead of `../../src`. This is required for the integraiton tests to run in the browser.
 | 
			
		||||
 | 
			
		||||
For an example of how to write an integration test for `xrpl.js`, you can look at the [Payment integration test](./packages/xrpl/test/integration/transactions/payment.ts).
 | 
			
		||||
 | 
			
		||||
## Generate reference docs
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ All of which works in Node.js (tested for v14+) & web browsers (tested for Chrom
 | 
			
		||||
 | 
			
		||||
### Requirements
 | 
			
		||||
 | 
			
		||||
- **[Node.js v14](https://nodejs.org/)** is recommended. We also support v12 and v16. Other versions may work but are not frequently tested.
 | 
			
		||||
+ **[Node.js v14](https://nodejs.org/)** is recommended. We also support v16 and v18. Other versions may work but are not frequently tested.
 | 
			
		||||
 | 
			
		||||
### Installing xrpl.js
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								jest.config.base.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								jest.config.base.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
const { TextDecoder, TextEncoder } = require("util");
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  roots: ["<rootDir>/src"],
 | 
			
		||||
  transform: {
 | 
			
		||||
    "^.+\\.ts$": "ts-jest",
 | 
			
		||||
  },
 | 
			
		||||
  moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
 | 
			
		||||
  collectCoverage: true,
 | 
			
		||||
  verbose: true,
 | 
			
		||||
  testEnvironment: "node",
 | 
			
		||||
  globals: {
 | 
			
		||||
    TextDecoder: TextDecoder,
 | 
			
		||||
    TextEncoder: TextEncoder,
 | 
			
		||||
    error: console.error,
 | 
			
		||||
    warn: console.warn,
 | 
			
		||||
    info: console.info,
 | 
			
		||||
    debug: console.debug,
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										8
									
								
								jest.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								jest.config.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
const path = require("path");
 | 
			
		||||
const base = require("./jest.config.base.js");
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  ...base,
 | 
			
		||||
  projects: ["<rootDir>/packages/**/jest.config.js"],
 | 
			
		||||
  coverageDirectory: "<rootDir>/coverage/",
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										17063
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										17063
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										19
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								package.json
									
									
									
									
									
								
							@@ -8,7 +8,9 @@
 | 
			
		||||
    "lint": "lerna run lint --stream",
 | 
			
		||||
    "clean": "lerna run clean --stream",
 | 
			
		||||
    "build": "lerna run build --stream",
 | 
			
		||||
    "docgen": "lerna run docgen --stream"
 | 
			
		||||
    "docgen": "lerna run docgen --stream",
 | 
			
		||||
    "update:check": "npx npm-check-updates --configFileName .ncurc.json",
 | 
			
		||||
    "update:confirm": "npx npm-check-updates --configFileName .ncurc.json -u"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "ripple-address-codec": "file:packages/ripple-address-codec",
 | 
			
		||||
@@ -17,11 +19,12 @@
 | 
			
		||||
    "xrpl": "file:packages/xrpl"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@types/brorand": "^1.0.30",
 | 
			
		||||
    "@types/chai": "^4.2.21",
 | 
			
		||||
    "@types/create-hash": "^1.2.2",
 | 
			
		||||
    "@types/jest": "^29.2.2",
 | 
			
		||||
    "@types/lodash": "^4.14.136",
 | 
			
		||||
    "@types/mocha": "^9.0.0",
 | 
			
		||||
    "@types/node": "^17.0.14",
 | 
			
		||||
    "@types/node": "^14.18.35",
 | 
			
		||||
    "@types/puppeteer": "5.4.6",
 | 
			
		||||
    "@types/ws": "^8.2.0",
 | 
			
		||||
    "@typescript-eslint/eslint-plugin": "^4.30.0",
 | 
			
		||||
@@ -40,15 +43,15 @@
 | 
			
		||||
    "eslint-plugin-eslint-comments": "^3.2.0",
 | 
			
		||||
    "eslint-plugin-import": "^2.24.1",
 | 
			
		||||
    "eslint-plugin-jsdoc": "^37.1.0",
 | 
			
		||||
    "eslint-plugin-mocha": "^10.0.3",
 | 
			
		||||
    "eslint-plugin-node": "^11.1.0",
 | 
			
		||||
    "eslint-plugin-prettier": "^4.0.0",
 | 
			
		||||
    "eslint-plugin-tsdoc": "^0.2.14",
 | 
			
		||||
    "eventemitter2": "^6.0.0",
 | 
			
		||||
    "expect": "^29.3.1",
 | 
			
		||||
    "https-browserify": "^1.0.0",
 | 
			
		||||
    "jest": "^26.0.1",
 | 
			
		||||
    "jest": "^29.3.1",
 | 
			
		||||
    "jest-mock": "^29.3.1",
 | 
			
		||||
    "lerna": "^4.0.0",
 | 
			
		||||
    "mocha": "^10",
 | 
			
		||||
    "npm-run-all": "^4.1.5",
 | 
			
		||||
    "nyc": "^15",
 | 
			
		||||
    "path-browserify": "1.0.1",
 | 
			
		||||
@@ -59,7 +62,7 @@
 | 
			
		||||
    "source-map-support": "^0.5.16",
 | 
			
		||||
    "stream-browserify": "^3.0.0",
 | 
			
		||||
    "stream-http": "3.2.0",
 | 
			
		||||
    "ts-jest": "^26.4.4",
 | 
			
		||||
    "ts-jest": "^29.0.3",
 | 
			
		||||
    "ts-loader": "^9.2.5",
 | 
			
		||||
    "ts-node": "^10.2.1",
 | 
			
		||||
    "typescript": "^4.4.2",
 | 
			
		||||
@@ -69,7 +72,7 @@
 | 
			
		||||
    "webpack-cli": "^4.2.0"
 | 
			
		||||
  },
 | 
			
		||||
  "workspaces": [
 | 
			
		||||
    "packages/*"
 | 
			
		||||
    "./packages/*"
 | 
			
		||||
  ],
 | 
			
		||||
  "engines": {
 | 
			
		||||
    "node": ">=12.0.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -40,5 +40,6 @@ module.exports = {
 | 
			
		||||
    'jsdoc/require-jsdoc': 'off',
 | 
			
		||||
    'jsdoc/require-param': 'off',
 | 
			
		||||
    'tsdoc/syntax': 'off',
 | 
			
		||||
    '@typescript-eslint/no-require-imports': 'off',
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
# ripple-address-codec
 | 
			
		||||
 | 
			
		||||
## Unreleased
 | 
			
		||||
### Changed
 | 
			
		||||
- All tests now use the Jest test runner and have been refactored for consistency across all packages
 | 
			
		||||
 | 
			
		||||
## 4.2.4 (2022-04-21)
 | 
			
		||||
### Fixed
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,7 @@
 | 
			
		||||
// Jest configuration for api
 | 
			
		||||
const base = require('../../jest.config.base.js')
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  "roots": [
 | 
			
		||||
    "<rootDir>/src"
 | 
			
		||||
  ],
 | 
			
		||||
  "transform": {
 | 
			
		||||
    "^.+\\.tsx?$": "ts-jest"
 | 
			
		||||
  },
 | 
			
		||||
  ...base,
 | 
			
		||||
  displayName: 'ripple-address-codec',
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										245
									
								
								packages/ripple-address-codec/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								packages/ripple-address-codec/package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,245 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "ripple-address-codec",
 | 
			
		||||
  "version": "4.2.4",
 | 
			
		||||
  "lockfileVersion": 2,
 | 
			
		||||
  "requires": true,
 | 
			
		||||
  "packages": {
 | 
			
		||||
    "": {
 | 
			
		||||
      "name": "ripple-address-codec",
 | 
			
		||||
      "version": "4.2.4",
 | 
			
		||||
      "license": "ISC",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "base-x": "^3.0.9",
 | 
			
		||||
        "create-hash": "^1.1.2"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">= 10"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/base-x": {
 | 
			
		||||
      "version": "3.0.9",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz",
 | 
			
		||||
      "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "safe-buffer": "^5.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/cipher-base": {
 | 
			
		||||
      "version": "1.0.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
 | 
			
		||||
      "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "inherits": "^2.0.1",
 | 
			
		||||
        "safe-buffer": "^5.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/create-hash": {
 | 
			
		||||
      "version": "1.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
 | 
			
		||||
      "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "cipher-base": "^1.0.1",
 | 
			
		||||
        "inherits": "^2.0.1",
 | 
			
		||||
        "md5.js": "^1.3.4",
 | 
			
		||||
        "ripemd160": "^2.0.1",
 | 
			
		||||
        "sha.js": "^2.4.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/hash-base": {
 | 
			
		||||
      "version": "3.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
 | 
			
		||||
      "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "inherits": "^2.0.4",
 | 
			
		||||
        "readable-stream": "^3.6.0",
 | 
			
		||||
        "safe-buffer": "^5.2.0"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=4"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/inherits": {
 | 
			
		||||
      "version": "2.0.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
 | 
			
		||||
      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/md5.js": {
 | 
			
		||||
      "version": "1.3.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
 | 
			
		||||
      "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "hash-base": "^3.0.0",
 | 
			
		||||
        "inherits": "^2.0.1",
 | 
			
		||||
        "safe-buffer": "^5.1.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/readable-stream": {
 | 
			
		||||
      "version": "3.6.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
 | 
			
		||||
      "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "inherits": "^2.0.3",
 | 
			
		||||
        "string_decoder": "^1.1.1",
 | 
			
		||||
        "util-deprecate": "^1.0.1"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">= 6"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/ripemd160": {
 | 
			
		||||
      "version": "2.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
 | 
			
		||||
      "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "hash-base": "^3.0.0",
 | 
			
		||||
        "inherits": "^2.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/safe-buffer": {
 | 
			
		||||
      "version": "5.2.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
 | 
			
		||||
      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
 | 
			
		||||
      "funding": [
 | 
			
		||||
        {
 | 
			
		||||
          "type": "github",
 | 
			
		||||
          "url": "https://github.com/sponsors/feross"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "type": "patreon",
 | 
			
		||||
          "url": "https://www.patreon.com/feross"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "type": "consulting",
 | 
			
		||||
          "url": "https://feross.org/support"
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/sha.js": {
 | 
			
		||||
      "version": "2.4.11",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
 | 
			
		||||
      "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "inherits": "^2.0.1",
 | 
			
		||||
        "safe-buffer": "^5.0.1"
 | 
			
		||||
      },
 | 
			
		||||
      "bin": {
 | 
			
		||||
        "sha.js": "bin.js"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/string_decoder": {
 | 
			
		||||
      "version": "1.3.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
 | 
			
		||||
      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "safe-buffer": "~5.2.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/util-deprecate": {
 | 
			
		||||
      "version": "1.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
 | 
			
		||||
      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "base-x": {
 | 
			
		||||
      "version": "3.0.9",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz",
 | 
			
		||||
      "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "safe-buffer": "^5.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "cipher-base": {
 | 
			
		||||
      "version": "1.0.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
 | 
			
		||||
      "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "inherits": "^2.0.1",
 | 
			
		||||
        "safe-buffer": "^5.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "create-hash": {
 | 
			
		||||
      "version": "1.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
 | 
			
		||||
      "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "cipher-base": "^1.0.1",
 | 
			
		||||
        "inherits": "^2.0.1",
 | 
			
		||||
        "md5.js": "^1.3.4",
 | 
			
		||||
        "ripemd160": "^2.0.1",
 | 
			
		||||
        "sha.js": "^2.4.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "hash-base": {
 | 
			
		||||
      "version": "3.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
 | 
			
		||||
      "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "inherits": "^2.0.4",
 | 
			
		||||
        "readable-stream": "^3.6.0",
 | 
			
		||||
        "safe-buffer": "^5.2.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "inherits": {
 | 
			
		||||
      "version": "2.0.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
 | 
			
		||||
      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
 | 
			
		||||
    },
 | 
			
		||||
    "md5.js": {
 | 
			
		||||
      "version": "1.3.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
 | 
			
		||||
      "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "hash-base": "^3.0.0",
 | 
			
		||||
        "inherits": "^2.0.1",
 | 
			
		||||
        "safe-buffer": "^5.1.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "readable-stream": {
 | 
			
		||||
      "version": "3.6.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
 | 
			
		||||
      "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "inherits": "^2.0.3",
 | 
			
		||||
        "string_decoder": "^1.1.1",
 | 
			
		||||
        "util-deprecate": "^1.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "ripemd160": {
 | 
			
		||||
      "version": "2.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
 | 
			
		||||
      "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "hash-base": "^3.0.0",
 | 
			
		||||
        "inherits": "^2.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "safe-buffer": {
 | 
			
		||||
      "version": "5.2.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
 | 
			
		||||
      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
 | 
			
		||||
    },
 | 
			
		||||
    "sha.js": {
 | 
			
		||||
      "version": "2.4.11",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
 | 
			
		||||
      "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "inherits": "^2.0.1",
 | 
			
		||||
        "safe-buffer": "^5.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "string_decoder": {
 | 
			
		||||
      "version": "1.3.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
 | 
			
		||||
      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "safe-buffer": "~5.2.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "util-deprecate": {
 | 
			
		||||
      "version": "1.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
 | 
			
		||||
      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
  "types": "dist/index.d.ts",
 | 
			
		||||
  "license": "ISC",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "base-x": "3.0.9",
 | 
			
		||||
    "base-x": "^3.0.9",
 | 
			
		||||
    "create-hash": "^1.1.2"
 | 
			
		||||
  },
 | 
			
		||||
  "repository": {
 | 
			
		||||
@@ -21,7 +21,7 @@
 | 
			
		||||
  "prepublishOnly": "tslint -b ./ && jest",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "build": "tsc -b",
 | 
			
		||||
    "test": "jest",
 | 
			
		||||
    "test": "jest --verbose false --silent=false ./src/*.test.js",
 | 
			
		||||
    "lint": "eslint . --ext .ts",
 | 
			
		||||
    "clean": "rm -rf ./dist && rm -rf tsconfig.tsbuildinfo"
 | 
			
		||||
  },
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@ const {
 | 
			
		||||
  classicAddressToXAddress,
 | 
			
		||||
  xAddressToClassicAddress,
 | 
			
		||||
  isValidXAddress,
 | 
			
		||||
  encodeXAddress
 | 
			
		||||
  encodeXAddress,
 | 
			
		||||
} = require('./index')
 | 
			
		||||
 | 
			
		||||
const testCases = [
 | 
			
		||||
@@ -10,137 +10,137 @@ const testCases = [
 | 
			
		||||
    'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59',
 | 
			
		||||
    false,
 | 
			
		||||
    'X7AcgcsBL6XDcUb289X4mJ8djcdyKaB5hJDWMArnXr61cqZ',
 | 
			
		||||
    'T719a5UwUCnEs54UsxG9CJYYDhwmFCqkr7wxCcNcfZ6p5GZ'
 | 
			
		||||
    'T719a5UwUCnEs54UsxG9CJYYDhwmFCqkr7wxCcNcfZ6p5GZ',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59',
 | 
			
		||||
    1,
 | 
			
		||||
    'X7AcgcsBL6XDcUb289X4mJ8djcdyKaGZMhc9YTE92ehJ2Fu',
 | 
			
		||||
    'T719a5UwUCnEs54UsxG9CJYYDhwmFCvbJNZbi37gBGkRkbE'
 | 
			
		||||
    'T719a5UwUCnEs54UsxG9CJYYDhwmFCvbJNZbi37gBGkRkbE',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59',
 | 
			
		||||
    14,
 | 
			
		||||
    'X7AcgcsBL6XDcUb289X4mJ8djcdyKaGo2K5VpXpmCqbV2gS',
 | 
			
		||||
    'T719a5UwUCnEs54UsxG9CJYYDhwmFCvqXVCALUGJGSbNV3x'
 | 
			
		||||
    'T719a5UwUCnEs54UsxG9CJYYDhwmFCvqXVCALUGJGSbNV3x',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59',
 | 
			
		||||
    11747,
 | 
			
		||||
    'X7AcgcsBL6XDcUb289X4mJ8djcdyKaLFuhLRuNXPrDeJd9A',
 | 
			
		||||
    'T719a5UwUCnEs54UsxG9CJYYDhwmFCziiNHtUukubF2Mg6t'
 | 
			
		||||
    'T719a5UwUCnEs54UsxG9CJYYDhwmFCziiNHtUukubF2Mg6t',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rLczgQHxPhWtjkaQqn3Q6UM8AbRbbRvs5K',
 | 
			
		||||
    false,
 | 
			
		||||
    'XVZVpQj8YSVpNyiwXYSqvQoQqgBttTxAZwMcuJd4xteQHyt',
 | 
			
		||||
    'TVVrSWtmQQssgVcmoMBcFQZKKf56QscyWLKnUyiuZW8ALU4'
 | 
			
		||||
    'TVVrSWtmQQssgVcmoMBcFQZKKf56QscyWLKnUyiuZW8ALU4',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo',
 | 
			
		||||
    false,
 | 
			
		||||
    'X7YenJqxv3L66CwhBSfd3N8RzGXxYqPopMGMsCcpho79rex',
 | 
			
		||||
    'T77wVQzA8ntj9wvCTNiQpNYLT5hmhRsFyXDoMLqYC4BzQtV'
 | 
			
		||||
    'T77wVQzA8ntj9wvCTNiQpNYLT5hmhRsFyXDoMLqYC4BzQtV',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rpZc4mVfWUif9CRoHRKKcmhu1nx2xktxBo',
 | 
			
		||||
    58,
 | 
			
		||||
    'X7YenJqxv3L66CwhBSfd3N8RzGXxYqV56ZkTCa9UCzgaao1',
 | 
			
		||||
    'T77wVQzA8ntj9wvCTNiQpNYLT5hmhR9kej6uxm4jGcQD7rZ'
 | 
			
		||||
    'T77wVQzA8ntj9wvCTNiQpNYLT5hmhR9kej6uxm4jGcQD7rZ',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW',
 | 
			
		||||
    23480,
 | 
			
		||||
    'X7d3eHCXzwBeWrZec1yT24iZerQjYL8m8zCJ16ACxu1BrBY',
 | 
			
		||||
    'T7YChPFWifjCAXLEtg5N74c7fSAYsvSokwcmBPBUZWhxH5P'
 | 
			
		||||
    'T7YChPFWifjCAXLEtg5N74c7fSAYsvSokwcmBPBUZWhxH5P',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW',
 | 
			
		||||
    11747,
 | 
			
		||||
    'X7d3eHCXzwBeWrZec1yT24iZerQjYLo2CJf8oVC5CMWey5m',
 | 
			
		||||
    'T7YChPFWifjCAXLEtg5N74c7fSAYsvTcc7nEfwuEEvn5Q4w'
 | 
			
		||||
    'T7YChPFWifjCAXLEtg5N74c7fSAYsvTcc7nEfwuEEvn5Q4w',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf',
 | 
			
		||||
    false,
 | 
			
		||||
    'XVLhHMPHU98es4dbozjVtdWzVrDjtV5fdx1mHp98tDMoQXb',
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQn49b3qD26PK7FcGSKE'
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQn49b3qD26PK7FcGSKE',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf',
 | 
			
		||||
    0,
 | 
			
		||||
    'XVLhHMPHU98es4dbozjVtdWzVrDjtV8AqEL4xcZj5whKbmc',
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQnSy8RHqGHoGJ59spi2'
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQnSy8RHqGHoGJ59spi2',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf',
 | 
			
		||||
    1,
 | 
			
		||||
    'XVLhHMPHU98es4dbozjVtdWzVrDjtV8xvjGQTYPiAx6gwDC',
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQnSz1uDimDdPYXzSpyw'
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQnSz1uDimDdPYXzSpyw',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf',
 | 
			
		||||
    2,
 | 
			
		||||
    'XVLhHMPHU98es4dbozjVtdWzVrDjtV8zpDURx7DzBCkrQE7',
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQnTryP9tG9TW8GeMBmd'
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQnTryP9tG9TW8GeMBmd',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf',
 | 
			
		||||
    32,
 | 
			
		||||
    'XVLhHMPHU98es4dbozjVtdWzVrDjtVoYiC9UvKfjKar4LJe',
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQnT2oqaCDzMEuCDAj1j'
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQnT2oqaCDzMEuCDAj1j',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf',
 | 
			
		||||
    276,
 | 
			
		||||
    'XVLhHMPHU98es4dbozjVtdWzVrDjtVoKj3MnFGMXEFMnvJV',
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQnTMgJJYfAbsiPsc6Zg'
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQnTMgJJYfAbsiPsc6Zg',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf',
 | 
			
		||||
    65591,
 | 
			
		||||
    'XVLhHMPHU98es4dbozjVtdWzVrDjtVozpjdhPQVdt3ghaWw',
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQn7ryu2W6njw7mT1jmS'
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQn7ryu2W6njw7mT1jmS',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf',
 | 
			
		||||
    16781933,
 | 
			
		||||
    'XVLhHMPHU98es4dbozjVtdWzVrDjtVqrDUk2vDpkTjPsY73',
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQnVsw45sDtGHhLi27Qa'
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQnVsw45sDtGHhLi27Qa',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf',
 | 
			
		||||
    4294967294,
 | 
			
		||||
    'XVLhHMPHU98es4dbozjVtdWzVrDjtV1kAsixQTdMjbWi39u',
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQnX8tDFQ53itLNqs6vU'
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQnX8tDFQ53itLNqs6vU',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf',
 | 
			
		||||
    4294967295,
 | 
			
		||||
    'XVLhHMPHU98es4dbozjVtdWzVrDjtV18pX8yuPT7y4xaEHi',
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQnXoy6kSDh6rZzApc69'
 | 
			
		||||
    'TVE26TYGhfLC7tQDno7G8dGtxSkYQnXoy6kSDh6rZzApc69',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rPEPPER7kfTD9w2To4CQk6UCfuHM9c6GDY',
 | 
			
		||||
    false,
 | 
			
		||||
    'XV5sbjUmgPpvXv4ixFWZ5ptAYZ6PD2gYsjNFQLKYW33DzBm',
 | 
			
		||||
    'TVd2rqMkYL2AyS97NdELcpeiprNBjwLZzuUG5rZnaewsahi'
 | 
			
		||||
    'TVd2rqMkYL2AyS97NdELcpeiprNBjwLZzuUG5rZnaewsahi',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rPEPPER7kfTD9w2To4CQk6UCfuHM9c6GDY',
 | 
			
		||||
    0,
 | 
			
		||||
    'XV5sbjUmgPpvXv4ixFWZ5ptAYZ6PD2m4Er6SnvjVLpMWPjR',
 | 
			
		||||
    'TVd2rqMkYL2AyS97NdELcpeiprNBjwRQUBetPbyrvXSTuxU'
 | 
			
		||||
    'TVd2rqMkYL2AyS97NdELcpeiprNBjwRQUBetPbyrvXSTuxU',
 | 
			
		||||
  ],
 | 
			
		||||
  [
 | 
			
		||||
    'rPEPPER7kfTD9w2To4CQk6UCfuHM9c6GDY',
 | 
			
		||||
    13371337,
 | 
			
		||||
    'XV5sbjUmgPpvXv4ixFWZ5ptAYZ6PD2qwGkhgc48zzcx6Gkr',
 | 
			
		||||
    'TVd2rqMkYL2AyS97NdELcpeiprNBjwVUDvp3vhpXbNhLwJi'
 | 
			
		||||
  ]
 | 
			
		||||
    'TVd2rqMkYL2AyS97NdELcpeiprNBjwVUDvp3vhpXbNhLwJi',
 | 
			
		||||
  ],
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
;[false, true].forEach(isTestAddress => {
 | 
			
		||||
;[false, true].forEach((isTestAddress) => {
 | 
			
		||||
  const MAX_32_BIT_UNSIGNED_INT = 4294967295
 | 
			
		||||
  const network = isTestAddress ? ' (test)' : ' (main)'
 | 
			
		||||
 | 
			
		||||
@@ -149,13 +149,17 @@ const testCases = [
 | 
			
		||||
    const classicAddress = testCase[0]
 | 
			
		||||
    const tag = testCase[1] !== false ? testCase[1] : false
 | 
			
		||||
    const xAddress = isTestAddress ? testCase[3] : testCase[2]
 | 
			
		||||
    test(`Converts ${classicAddress}${tag ? ':' + tag : ''} to ${xAddress}${network}`, () => {
 | 
			
		||||
      expect(classicAddressToXAddress(classicAddress, tag, isTestAddress)).toBe(xAddress)
 | 
			
		||||
    test(`Converts ${classicAddress}${
 | 
			
		||||
      tag ? `:${tag}` : ''
 | 
			
		||||
    } to ${xAddress}${network}`, () => {
 | 
			
		||||
      expect(classicAddressToXAddress(classicAddress, tag, isTestAddress)).toBe(
 | 
			
		||||
        xAddress,
 | 
			
		||||
      )
 | 
			
		||||
      const myClassicAddress = xAddressToClassicAddress(xAddress)
 | 
			
		||||
      expect(myClassicAddress).toEqual({
 | 
			
		||||
        classicAddress,
 | 
			
		||||
        tag,
 | 
			
		||||
        test: isTestAddress
 | 
			
		||||
        test: isTestAddress,
 | 
			
		||||
      })
 | 
			
		||||
      expect(isValidXAddress(xAddress)).toBe(true)
 | 
			
		||||
    })
 | 
			
		||||
@@ -177,23 +181,28 @@ const testCases = [
 | 
			
		||||
    test(`Invalid classic address: Converting ${classicAddress}${network} throws`, () => {
 | 
			
		||||
      expect(() => {
 | 
			
		||||
        classicAddressToXAddress(classicAddress, false, isTestAddress)
 | 
			
		||||
      }).toThrowError(new Error('invalid_input_size: decoded data must have length >= 5'))
 | 
			
		||||
      }).toThrowError(
 | 
			
		||||
        new Error('invalid_input_size: decoded data must have length >= 5'),
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    const highAndLowAccounts = [
 | 
			
		||||
      Buffer.from('00'.repeat(20), 'hex'),
 | 
			
		||||
      Buffer.from('00'.repeat(19) + '01', 'hex'),
 | 
			
		||||
      Buffer.from(`${'00'.repeat(19)}01`, 'hex'),
 | 
			
		||||
      Buffer.from('01'.repeat(20), 'hex'),
 | 
			
		||||
      Buffer.from('FF'.repeat(20), 'hex')
 | 
			
		||||
      Buffer.from('FF'.repeat(20), 'hex'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    highAndLowAccounts.forEach(accountId => {
 | 
			
		||||
      [false, 0, 1, MAX_32_BIT_UNSIGNED_INT].forEach(t => {
 | 
			
		||||
        const tag = (t | false)
 | 
			
		||||
    highAndLowAccounts.forEach((accountId) => {
 | 
			
		||||
      const testCases = [false, 0, 1, MAX_32_BIT_UNSIGNED_INT]
 | 
			
		||||
      testCases.forEach((t) => {
 | 
			
		||||
        const tag = t | false
 | 
			
		||||
        const xAddress = encodeXAddress(accountId, tag, isTestAddress)
 | 
			
		||||
        test(`Encoding ${accountId.toString('hex')}${tag ? ':' + tag : ''} to ${xAddress} has expected length`, () => {
 | 
			
		||||
        test(`Encoding ${accountId.toString('hex')}${
 | 
			
		||||
          tag ? `:${tag}` : ''
 | 
			
		||||
        } to ${xAddress} has expected length`, () => {
 | 
			
		||||
          expect(xAddress.length).toBe(47)
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
@@ -237,7 +246,9 @@ test(`Invalid Account ID throws`, () => {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test(`isValidXAddress returns false for invalid X-address`, () => {
 | 
			
		||||
  expect(isValidXAddress('XVLhHMPHU98es4dbozjVtdWzVrDjtV18pX8zeUygYrCgrPh')).toBe(false)
 | 
			
		||||
  expect(
 | 
			
		||||
    isValidXAddress('XVLhHMPHU98es4dbozjVtdWzVrDjtV18pX8zeUygYrCgrPh'),
 | 
			
		||||
  ).toBe(false)
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test(`Converts X7AcgcsBL6XDcUb... to r9cZA1mLK5R5A... and tag: false`, () => {
 | 
			
		||||
@@ -245,12 +256,14 @@ test(`Converts X7AcgcsBL6XDcUb... to r9cZA1mLK5R5A... and tag: false`, () => {
 | 
			
		||||
  const tag = false
 | 
			
		||||
  const xAddress = 'X7AcgcsBL6XDcUb289X4mJ8djcdyKaB5hJDWMArnXr61cqZ'
 | 
			
		||||
  const isTestAddress = false
 | 
			
		||||
  expect(classicAddressToXAddress(classicAddress, tag, isTestAddress)).toBe(xAddress)
 | 
			
		||||
  expect(classicAddressToXAddress(classicAddress, tag, isTestAddress)).toBe(
 | 
			
		||||
    xAddress,
 | 
			
		||||
  )
 | 
			
		||||
  const myClassicAddress = xAddressToClassicAddress(xAddress)
 | 
			
		||||
  expect(myClassicAddress).toEqual({
 | 
			
		||||
    classicAddress,
 | 
			
		||||
    tag,
 | 
			
		||||
    test: isTestAddress
 | 
			
		||||
    test: isTestAddress,
 | 
			
		||||
  })
 | 
			
		||||
  expect(isValidXAddress(xAddress)).toBe(true)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -119,6 +119,7 @@ function isBufferForTestAddress(buf: Buffer): boolean {
 | 
			
		||||
  if (PREFIX_BYTES.test.equals(decodedPrefix)) {
 | 
			
		||||
    return true
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  throw new Error('Invalid X-address: bad prefix')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -27,16 +27,26 @@ function makeEncodeDecodeTest(encoder, decoder, base58, hex) {
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
makeEncodeDecodeTest(api.encodeAccountID, api.decodeAccountID, 'rJrRMgiRgrU6hDF4pgu5DXQdWyPbY35ErN',
 | 
			
		||||
  'BA8E78626EE42C41B46D46C3048DF3A1C3C87072')
 | 
			
		||||
makeEncodeDecodeTest(
 | 
			
		||||
  api.encodeAccountID,
 | 
			
		||||
  api.decodeAccountID,
 | 
			
		||||
  'rJrRMgiRgrU6hDF4pgu5DXQdWyPbY35ErN',
 | 
			
		||||
  'BA8E78626EE42C41B46D46C3048DF3A1C3C87072',
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
makeEncodeDecodeTest(api.encodeNodePublic, api.decodeNodePublic,
 | 
			
		||||
makeEncodeDecodeTest(
 | 
			
		||||
  api.encodeNodePublic,
 | 
			
		||||
  api.decodeNodePublic,
 | 
			
		||||
  'n9MXXueo837zYH36DvMc13BwHcqtfAWNJY5czWVbp7uYTj7x17TH',
 | 
			
		||||
  '0388E5BA87A000CB807240DF8C848EB0B5FFA5C8E5A521BC8E105C0F0A44217828')
 | 
			
		||||
  '0388E5BA87A000CB807240DF8C848EB0B5FFA5C8E5A521BC8E105C0F0A44217828',
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
  makeEncodeDecodeTest(api.encodeAccountPublic, api.decodeAccountPublic,
 | 
			
		||||
makeEncodeDecodeTest(
 | 
			
		||||
  api.encodeAccountPublic,
 | 
			
		||||
  api.decodeAccountPublic,
 | 
			
		||||
  'aB44YfzW24VDEJQ2UuLPV2PvqcPCSoLnL7y5M1EzhdW4LnK5xMS3',
 | 
			
		||||
    '023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6')
 | 
			
		||||
  '023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6',
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
test('can decode arbitrary seeds', function () {
 | 
			
		||||
  const decoded = api.decodeSeed('sEdTM1uX8pu2do5XvTnutH6HsouMaM2')
 | 
			
		||||
@@ -58,15 +68,21 @@ test('can pass a type as second arg to encodeSeed', function() {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('isValidClassicAddress - secp256k1 address valid', function () {
 | 
			
		||||
  expect(api.isValidClassicAddress('rU6K7V3Po4snVhBBaU29sesqs2qTQJWDw1')).toBe(true)
 | 
			
		||||
  expect(api.isValidClassicAddress('rU6K7V3Po4snVhBBaU29sesqs2qTQJWDw1')).toBe(
 | 
			
		||||
    true,
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('isValidClassicAddress - ed25519 address valid', function () {
 | 
			
		||||
  expect(api.isValidClassicAddress('rLUEXYuLiQptky37CqLcm9USQpPiz5rkpD')).toBe(true)
 | 
			
		||||
  expect(api.isValidClassicAddress('rLUEXYuLiQptky37CqLcm9USQpPiz5rkpD')).toBe(
 | 
			
		||||
    true,
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('isValidClassicAddress - invalid', function () {
 | 
			
		||||
  expect(api.isValidClassicAddress('rU6K7V3Po4snVhBBaU29sesqs2qTQJWDw2')).toBe(false)
 | 
			
		||||
  expect(api.isValidClassicAddress('rU6K7V3Po4snVhBBaU29sesqs2qTQJWDw2')).toBe(
 | 
			
		||||
    false,
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('isValidClassicAddress - empty', function () {
 | 
			
		||||
@@ -74,52 +90,74 @@ test('isValidClassicAddress - empty', function() {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
describe('encodeSeed', function () {
 | 
			
		||||
 | 
			
		||||
  it('encodes a secp256k1 seed', function () {
 | 
			
		||||
    const result = api.encodeSeed(Buffer.from('CF2DE378FBDD7E2EE87D486DFB5A7BFF', 'hex'), 'secp256k1')
 | 
			
		||||
    const result = api.encodeSeed(
 | 
			
		||||
      Buffer.from('CF2DE378FBDD7E2EE87D486DFB5A7BFF', 'hex'),
 | 
			
		||||
      'secp256k1',
 | 
			
		||||
    )
 | 
			
		||||
    expect(result).toBe('sn259rEFXrQrWyx3Q7XneWcwV6dfL')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('encodes low secp256k1 seed', function () {
 | 
			
		||||
    const result = api.encodeSeed(Buffer.from('00000000000000000000000000000000', 'hex'), 'secp256k1')
 | 
			
		||||
    const result = api.encodeSeed(
 | 
			
		||||
      Buffer.from('00000000000000000000000000000000', 'hex'),
 | 
			
		||||
      'secp256k1',
 | 
			
		||||
    )
 | 
			
		||||
    expect(result).toBe('sp6JS7f14BuwFY8Mw6bTtLKWauoUs')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('encodes high secp256k1 seed', function () {
 | 
			
		||||
    const result = api.encodeSeed(Buffer.from('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 'hex'), 'secp256k1')
 | 
			
		||||
    const result = api.encodeSeed(
 | 
			
		||||
      Buffer.from('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 'hex'),
 | 
			
		||||
      'secp256k1',
 | 
			
		||||
    )
 | 
			
		||||
    expect(result).toBe('saGwBRReqUNKuWNLpUAq8i8NkXEPN')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('encodes an ed25519 seed', function () {
 | 
			
		||||
    const result = api.encodeSeed(Buffer.from('4C3A1D213FBDFB14C7C28D609469B341', 'hex'), 'ed25519')
 | 
			
		||||
    const result = api.encodeSeed(
 | 
			
		||||
      Buffer.from('4C3A1D213FBDFB14C7C28D609469B341', 'hex'),
 | 
			
		||||
      'ed25519',
 | 
			
		||||
    )
 | 
			
		||||
    expect(result).toBe('sEdTM1uX8pu2do5XvTnutH6HsouMaM2')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('encodes low ed25519 seed', function () {
 | 
			
		||||
    const result = api.encodeSeed(Buffer.from('00000000000000000000000000000000', 'hex'), 'ed25519')
 | 
			
		||||
    const result = api.encodeSeed(
 | 
			
		||||
      Buffer.from('00000000000000000000000000000000', 'hex'),
 | 
			
		||||
      'ed25519',
 | 
			
		||||
    )
 | 
			
		||||
    expect(result).toBe('sEdSJHS4oiAdz7w2X2ni1gFiqtbJHqE')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('encodes high ed25519 seed', function () {
 | 
			
		||||
    const result = api.encodeSeed(Buffer.from('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 'hex'), 'ed25519')
 | 
			
		||||
    const result = api.encodeSeed(
 | 
			
		||||
      Buffer.from('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 'hex'),
 | 
			
		||||
      'ed25519',
 | 
			
		||||
    )
 | 
			
		||||
    expect(result).toBe('sEdV19BLfeQeKdEXyYA4NhjPJe6XBfG')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test('attempting to encode a seed with less than 16 bytes of entropy throws', function () {
 | 
			
		||||
    expect(() => {
 | 
			
		||||
      api.encodeSeed(Buffer.from('CF2DE378FBDD7E2EE87D486DFB5A7B', 'hex'), 'secp256k1')
 | 
			
		||||
      api.encodeSeed(
 | 
			
		||||
        Buffer.from('CF2DE378FBDD7E2EE87D486DFB5A7B', 'hex'),
 | 
			
		||||
        'secp256k1',
 | 
			
		||||
      )
 | 
			
		||||
    }).toThrow('entropy must have length 16')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  test('attempting to encode a seed with more than 16 bytes of entropy throws', function () {
 | 
			
		||||
    expect(() => {
 | 
			
		||||
      api.encodeSeed(Buffer.from('CF2DE378FBDD7E2EE87D486DFB5A7BFFFF', 'hex'), 'secp256k1')
 | 
			
		||||
      api.encodeSeed(
 | 
			
		||||
        Buffer.from('CF2DE378FBDD7E2EE87D486DFB5A7BFFFF', 'hex'),
 | 
			
		||||
        'secp256k1',
 | 
			
		||||
      )
 | 
			
		||||
    }).toThrow('entropy must have length 16')
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
describe('decodeSeed', function () {
 | 
			
		||||
 | 
			
		||||
  it('can decode an Ed25519 seed', function () {
 | 
			
		||||
    const decoded = api.decodeSeed('sEdTM1uX8pu2do5XvTnutH6HsouMaM2')
 | 
			
		||||
    expect(toHex(decoded.bytes)).toBe('4C3A1D213FBDFB14C7C28D609469B341')
 | 
			
		||||
@@ -134,9 +172,10 @@ describe('decodeSeed', function() {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
describe('encodeAccountID', function () {
 | 
			
		||||
 | 
			
		||||
  it('can encode an AccountID', function () {
 | 
			
		||||
    const encoded = api.encodeAccountID(Buffer.from('BA8E78626EE42C41B46D46C3048DF3A1C3C87072', 'hex'))
 | 
			
		||||
    const encoded = api.encodeAccountID(
 | 
			
		||||
      Buffer.from('BA8E78626EE42C41B46D46C3048DF3A1C3C87072', 'hex'),
 | 
			
		||||
    )
 | 
			
		||||
    expect(encoded).toBe('rJrRMgiRgrU6hDF4pgu5DXQdWyPbY35ErN')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
@@ -144,38 +183,45 @@ describe('encodeAccountID', function() {
 | 
			
		||||
    expect(() => {
 | 
			
		||||
      api.encodeAccountID(Buffer.from('ABCDEF', 'hex'))
 | 
			
		||||
    }).toThrow(
 | 
			
		||||
      'unexpected_payload_length: bytes.length does not match expectedLength'
 | 
			
		||||
      'unexpected_payload_length: bytes.length does not match expectedLength',
 | 
			
		||||
    )
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
describe('decodeNodePublic', function () {
 | 
			
		||||
 | 
			
		||||
  it('can decode a NodePublic', function () {
 | 
			
		||||
    const decoded = api.decodeNodePublic('n9MXXueo837zYH36DvMc13BwHcqtfAWNJY5czWVbp7uYTj7x17TH')
 | 
			
		||||
    expect(toHex(decoded)).toBe('0388E5BA87A000CB807240DF8C848EB0B5FFA5C8E5A521BC8E105C0F0A44217828')
 | 
			
		||||
    const decoded = api.decodeNodePublic(
 | 
			
		||||
      'n9MXXueo837zYH36DvMc13BwHcqtfAWNJY5czWVbp7uYTj7x17TH',
 | 
			
		||||
    )
 | 
			
		||||
    expect(toHex(decoded)).toBe(
 | 
			
		||||
      '0388E5BA87A000CB807240DF8C848EB0B5FFA5C8E5A521BC8E105C0F0A44217828',
 | 
			
		||||
    )
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('encodes 123456789 with version byte of 0', () => {
 | 
			
		||||
  expect(api.codec.encode(Buffer.from('123456789'), {
 | 
			
		||||
  expect(
 | 
			
		||||
    api.codec.encode(Buffer.from('123456789'), {
 | 
			
		||||
      versions: [0],
 | 
			
		||||
    expectedLength: 9
 | 
			
		||||
  })).toBe('rnaC7gW34M77Kneb78s')
 | 
			
		||||
      expectedLength: 9,
 | 
			
		||||
    }),
 | 
			
		||||
  ).toBe('rnaC7gW34M77Kneb78s')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('multiple versions with no expected length should throw', () => {
 | 
			
		||||
  expect(() => {
 | 
			
		||||
    api.codec.decode('rnaC7gW34M77Kneb78s', {
 | 
			
		||||
      versions: [0, 1]
 | 
			
		||||
      versions: [0, 1],
 | 
			
		||||
    })
 | 
			
		||||
  }).toThrow('expectedLength is required because there are >= 2 possible versions')
 | 
			
		||||
  }).toThrow(
 | 
			
		||||
    'expectedLength is required because there are >= 2 possible versions',
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('attempting to decode data with length < 5 should throw', () => {
 | 
			
		||||
  expect(() => {
 | 
			
		||||
    api.codec.decode('1234', {
 | 
			
		||||
      versions: [0]
 | 
			
		||||
      versions: [0],
 | 
			
		||||
    })
 | 
			
		||||
  }).toThrow('invalid_input_size: decoded data must have length >= 5')
 | 
			
		||||
})
 | 
			
		||||
@@ -183,15 +229,17 @@ test('attempting to decode data with length < 5 should throw', () => {
 | 
			
		||||
test('attempting to decode data with unexpected version should throw', () => {
 | 
			
		||||
  expect(() => {
 | 
			
		||||
    api.codec.decode('rnaC7gW34M77Kneb78s', {
 | 
			
		||||
      versions: [2]
 | 
			
		||||
      versions: [2],
 | 
			
		||||
    })
 | 
			
		||||
  }).toThrow('version_invalid: version bytes do not match any of the provided version(s)')
 | 
			
		||||
  }).toThrow(
 | 
			
		||||
    'version_invalid: version bytes do not match any of the provided version(s)',
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('invalid checksum should throw', () => {
 | 
			
		||||
  expect(() => {
 | 
			
		||||
    api.codec.decode('123456789', {
 | 
			
		||||
      versions: [0, 1]
 | 
			
		||||
      versions: [0, 1],
 | 
			
		||||
    })
 | 
			
		||||
  }).toThrow('checksum_invalid')
 | 
			
		||||
})
 | 
			
		||||
@@ -199,30 +247,33 @@ test('invalid checksum should throw', () => {
 | 
			
		||||
test('empty payload should throw', () => {
 | 
			
		||||
  expect(() => {
 | 
			
		||||
    api.codec.decode('', {
 | 
			
		||||
      versions: [0, 1]
 | 
			
		||||
      versions: [0, 1],
 | 
			
		||||
    })
 | 
			
		||||
  }).toThrow('invalid_input_size: decoded data must have length >= 5')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('decode data', () => {
 | 
			
		||||
  expect(api.codec.decode('rnaC7gW34M77Kneb78s', {
 | 
			
		||||
    versions: [0]
 | 
			
		||||
  })).toStrictEqual({
 | 
			
		||||
  expect(
 | 
			
		||||
    api.codec.decode('rnaC7gW34M77Kneb78s', {
 | 
			
		||||
      versions: [0],
 | 
			
		||||
    }),
 | 
			
		||||
  ).toStrictEqual({
 | 
			
		||||
    version: [0],
 | 
			
		||||
    bytes: Buffer.from('123456789'),
 | 
			
		||||
    type: null
 | 
			
		||||
    type: null,
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('decode data with expected length', function () {
 | 
			
		||||
  expect(api.codec.decode('rnaC7gW34M77Kneb78s', {
 | 
			
		||||
  expect(
 | 
			
		||||
    api.codec.decode('rnaC7gW34M77Kneb78s', {
 | 
			
		||||
      versions: [0],
 | 
			
		||||
      expectedLength: 9
 | 
			
		||||
    })
 | 
			
		||||
      expectedLength: 9,
 | 
			
		||||
    }),
 | 
			
		||||
  ).toStrictEqual({
 | 
			
		||||
    version: [0],
 | 
			
		||||
    bytes: Buffer.from('123456789'),
 | 
			
		||||
      type: null
 | 
			
		||||
    type: null,
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@@ -230,17 +281,17 @@ test('decode data with wrong expected length should throw', function() {
 | 
			
		||||
  expect(() => {
 | 
			
		||||
    api.codec.decode('rnaC7gW34M77Kneb78s', {
 | 
			
		||||
      versions: [0],
 | 
			
		||||
      expectedLength: 8
 | 
			
		||||
      expectedLength: 8,
 | 
			
		||||
    })
 | 
			
		||||
  }).toThrow(
 | 
			
		||||
    'version_invalid: version bytes do not match any of the provided version(s)'
 | 
			
		||||
    'version_invalid: version bytes do not match any of the provided version(s)',
 | 
			
		||||
  )
 | 
			
		||||
  expect(() => {
 | 
			
		||||
    api.codec.decode('rnaC7gW34M77Kneb78s', {
 | 
			
		||||
      versions: [0],
 | 
			
		||||
      expectedLength: 10
 | 
			
		||||
      expectedLength: 10,
 | 
			
		||||
    })
 | 
			
		||||
  }).toThrow(
 | 
			
		||||
    'version_invalid: version bytes do not match any of the provided version(s)'
 | 
			
		||||
    'version_invalid: version bytes do not match any of the provided version(s)',
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
 
 | 
			
		||||
@@ -2,15 +2,16 @@
 | 
			
		||||
 * Codec class
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import * as baseCodec from 'base-x'
 | 
			
		||||
import * as createHash from 'create-hash'
 | 
			
		||||
import baseCodec = require('base-x')
 | 
			
		||||
import type { BaseConverter } from 'base-x'
 | 
			
		||||
import createHash = require('create-hash')
 | 
			
		||||
 | 
			
		||||
import { seqEqual, concatArgs } from './utils'
 | 
			
		||||
 | 
			
		||||
class Codec {
 | 
			
		||||
  private readonly _sha256: (bytes: Uint8Array) => Buffer
 | 
			
		||||
  private readonly _alphabet: string
 | 
			
		||||
  private readonly _codec: baseCodec.BaseConverter
 | 
			
		||||
  private readonly _codec: BaseConverter
 | 
			
		||||
 | 
			
		||||
  public constructor(options: {
 | 
			
		||||
    sha256: (bytes: Uint8Array) => Buffer
 | 
			
		||||
@@ -56,7 +57,7 @@ class Codec {
 | 
			
		||||
  ): {
 | 
			
		||||
    version: number[]
 | 
			
		||||
    bytes: Buffer
 | 
			
		||||
    type: string | null
 | 
			
		||||
    type: 'ed25519' | 'secp256k1' | null
 | 
			
		||||
  } {
 | 
			
		||||
    const versions = opts.versions
 | 
			
		||||
    const types = opts.versionTypes
 | 
			
		||||
@@ -204,7 +205,7 @@ export function decodeSeed(
 | 
			
		||||
): {
 | 
			
		||||
  version: number[]
 | 
			
		||||
  bytes: Buffer
 | 
			
		||||
  type: string | null
 | 
			
		||||
  type: 'ed25519' | 'secp256k1' | null
 | 
			
		||||
} {
 | 
			
		||||
  return codecWithXrpAlphabet.decode(seed, opts)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								packages/ripple-address-codec/tsconfig.eslint.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								packages/ripple-address-codec/tsconfig.eslint.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": "./tsconfig.json",
 | 
			
		||||
  "include": ["src/**/*.ts", "src/*.test.ts"]
 | 
			
		||||
}
 | 
			
		||||
@@ -13,7 +13,8 @@
 | 
			
		||||
    "preserveConstEnums": false,
 | 
			
		||||
    "suppressImplicitAnyIndexErrors": false,
 | 
			
		||||
    "skipLibCheck": true,
 | 
			
		||||
    "declaration": true
 | 
			
		||||
    "declaration": true,
 | 
			
		||||
    "strictNullChecks": true
 | 
			
		||||
  },
 | 
			
		||||
  "include": ["src/**/*.ts"]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,8 @@ module.exports = {
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  ignorePatterns: ['jest.config.js', '.eslintrc.js'],
 | 
			
		||||
 | 
			
		||||
  // Specify global variables that are predefined
 | 
			
		||||
  env: {
 | 
			
		||||
    browser: true, // Enable browser global variables
 | 
			
		||||
@@ -103,19 +105,19 @@ module.exports = {
 | 
			
		||||
    'max-lines-per-function': 'off',
 | 
			
		||||
    'require-unicode-regexp': 'off',
 | 
			
		||||
    'no-undef-init': 'off',
 | 
			
		||||
    'curly': 'off',
 | 
			
		||||
    'eqeqeq': 'off',
 | 
			
		||||
    curly: 'off',
 | 
			
		||||
    eqeqeq: 'off',
 | 
			
		||||
    'no-console': 'off',
 | 
			
		||||
    'max-classes-per-file': 'off',
 | 
			
		||||
    'operator-assignment': 'off',
 | 
			
		||||
    'class-methods-use-this': 'off',
 | 
			
		||||
    'no-else-return': 'off',
 | 
			
		||||
    'yoda': 'off',
 | 
			
		||||
    yoda: 'off',
 | 
			
		||||
    'max-depth': 'off',
 | 
			
		||||
    'multiline-comment-style': 'off',
 | 
			
		||||
    'one-var': 'off',
 | 
			
		||||
    'no-negated-condition': 'off',
 | 
			
		||||
    'radix': 'off',
 | 
			
		||||
    radix: 'off',
 | 
			
		||||
    'no-nested-ternary': 'off',
 | 
			
		||||
    'no-useless-concat': 'off',
 | 
			
		||||
    'object-shorthand': 'off',
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
10.22.0
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
# ripple-binary-codec Release History
 | 
			
		||||
 | 
			
		||||
## Unreleased
 | 
			
		||||
### Changed
 | 
			
		||||
- All tests now use the Jest test runner and have been refactored for consistency across all packages
 | 
			
		||||
 | 
			
		||||
## 1.4.2 (2022-06-27)
 | 
			
		||||
- Fixed standard currency codes with lowercase and allowed symbols not decoding into standard codes.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								packages/ripple-binary-codec/jest.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								packages/ripple-binary-codec/jest.config.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
// Jest configuration for api
 | 
			
		||||
const base = require('../../jest.config.base.js')
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  ...base,
 | 
			
		||||
  roots: [...base.roots, '<rootDir>/test'],
 | 
			
		||||
  displayName: 'ripple-binary-codec',
 | 
			
		||||
}
 | 
			
		||||
@@ -23,7 +23,7 @@
 | 
			
		||||
    "build": "tsc -b && copyfiles ./src/enums/definitions.json ./dist/enums/",
 | 
			
		||||
    "clean": "rm -rf ./dist && rm -rf tsconfig.tsbuildinfo",
 | 
			
		||||
    "prepare": "npm run build && npm test",
 | 
			
		||||
    "test": "jest",
 | 
			
		||||
    "test": "jest --verbose false --silent=false ./test/*.test.js",
 | 
			
		||||
    "lint": "eslint . --ext .ts --ext .test.js"
 | 
			
		||||
  },
 | 
			
		||||
  "repository": {
 | 
			
		||||
@@ -38,6 +38,6 @@
 | 
			
		||||
  "readmeFilename": "README.md",
 | 
			
		||||
  "prettier": "@xrplf/prettier-config",
 | 
			
		||||
  "engines": {
 | 
			
		||||
    "node": ">=10.22.0"
 | 
			
		||||
    "node": ">= 10"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ import { FieldInstance } from './enums'
 | 
			
		||||
import { STObject } from './types/st-object'
 | 
			
		||||
import { JsonObject } from './types/serialized-type'
 | 
			
		||||
import { Buffer } from 'buffer/'
 | 
			
		||||
import * as bigInt from 'big-integer'
 | 
			
		||||
import bigInt = require('big-integer')
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Construct a BinaryParser
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
import { HashPrefix } from './hash-prefixes'
 | 
			
		||||
import * as createHash from 'create-hash'
 | 
			
		||||
import createHash = require('create-hash')
 | 
			
		||||
import { Hash256 } from './types/hash-256'
 | 
			
		||||
import { BytesList } from './serdes/binary-serializer'
 | 
			
		||||
import { Buffer } from 'buffer/'
 | 
			
		||||
 
 | 
			
		||||
@@ -102,7 +102,7 @@ function decodeQuality(value: string): string {
 | 
			
		||||
  return quality.decode(value).toString()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export = {
 | 
			
		||||
export {
 | 
			
		||||
  decode,
 | 
			
		||||
  encode,
 | 
			
		||||
  encodeForSigning,
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ import { UInt32 } from './types/uint-32'
 | 
			
		||||
import { UInt8 } from './types/uint-8'
 | 
			
		||||
import { BinaryParser } from './serdes/binary-parser'
 | 
			
		||||
import { JsonObject } from './types/serialized-type'
 | 
			
		||||
import * as bigInt from 'big-integer'
 | 
			
		||||
import bigInt = require('big-integer')
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Computes the hash of a list of objects
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
import { coreTypes } from './types'
 | 
			
		||||
import { Decimal } from 'decimal.js'
 | 
			
		||||
import * as bigInt from 'big-integer'
 | 
			
		||||
import bigInt = require('big-integer')
 | 
			
		||||
import { Buffer } from 'buffer/'
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@ import { BinaryParser } from '../serdes/binary-parser'
 | 
			
		||||
import { AccountID } from './account-id'
 | 
			
		||||
import { Currency } from './currency'
 | 
			
		||||
import { JsonObject, SerializedType } from './serialized-type'
 | 
			
		||||
import * as bigInt from 'big-integer'
 | 
			
		||||
import bigInt = require('big-integer')
 | 
			
		||||
import { Buffer } from 'buffer/'
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
import { BytesList } from '../serdes/binary-serializer'
 | 
			
		||||
import { BinaryParser } from '../serdes/binary-parser'
 | 
			
		||||
import * as bigInt from 'big-integer'
 | 
			
		||||
import bigInt = require('big-integer')
 | 
			
		||||
import { Buffer } from 'buffer/'
 | 
			
		||||
 | 
			
		||||
type JSON = string | number | boolean | null | undefined | JSON[] | JsonObject
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
import { UInt } from './uint'
 | 
			
		||||
import { BinaryParser } from '../serdes/binary-parser'
 | 
			
		||||
import * as bigInt from 'big-integer'
 | 
			
		||||
import bigInt = require('big-integer')
 | 
			
		||||
import { isInstance } from 'big-integer'
 | 
			
		||||
import { Buffer } from 'buffer/'
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import * as bigInt from 'big-integer'
 | 
			
		||||
import bigInt = require('big-integer')
 | 
			
		||||
import { Comparable } from './serialized-type'
 | 
			
		||||
import { Buffer } from 'buffer/'
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
const { loadFixture } = require('./utils')
 | 
			
		||||
const { coreTypes } = require('../dist/types')
 | 
			
		||||
const { coreTypes } = require('../src/types')
 | 
			
		||||
const { Amount } = coreTypes
 | 
			
		||||
const fixtures = loadFixture('data-driven-tests.json')
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
const fixtures = require('./fixtures/codec-fixtures.json')
 | 
			
		||||
const { decode, encode, decodeLedgerData } = require('../dist')
 | 
			
		||||
const { decode, encode, decodeLedgerData } = require('../src')
 | 
			
		||||
 | 
			
		||||
function json(object) {
 | 
			
		||||
  return JSON.stringify(object)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
const { coreTypes } = require('../dist/types')
 | 
			
		||||
const { coreTypes } = require('../src/types')
 | 
			
		||||
const Decimal = require('decimal.js')
 | 
			
		||||
 | 
			
		||||
const { encodeAccountID } = require('ripple-address-codec')
 | 
			
		||||
const { binary } = require('../dist/coretypes')
 | 
			
		||||
const { binary } = require('../src/coretypes')
 | 
			
		||||
const { Amount, Hash160 } = coreTypes
 | 
			
		||||
const { makeParser, readJSON } = binary
 | 
			
		||||
const { Field, TransactionType } = require('./../dist/enums')
 | 
			
		||||
const { Field, TransactionType } = require('./../src/enums')
 | 
			
		||||
const { parseHexOnly, hexOnly, loadFixture } = require('./utils')
 | 
			
		||||
const fixtures = loadFixture('data-driven-tests.json')
 | 
			
		||||
const { BytesList } = require('../dist/serdes/binary-serializer')
 | 
			
		||||
const { BytesList } = require('../src/serdes/binary-serializer')
 | 
			
		||||
const { Buffer } = require('buffer/')
 | 
			
		||||
 | 
			
		||||
const __ = hexOnly
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
const { binary } = require('../dist/coretypes')
 | 
			
		||||
const { encode, decode } = require('../dist')
 | 
			
		||||
const { binary } = require('../src/coretypes')
 | 
			
		||||
const { encode, decode } = require('../src')
 | 
			
		||||
const { makeParser, BytesList, BinarySerializer } = binary
 | 
			
		||||
const { coreTypes } = require('../dist/types')
 | 
			
		||||
const { coreTypes } = require('../src/types')
 | 
			
		||||
const { UInt8, UInt16, UInt32, UInt64, STObject } = coreTypes
 | 
			
		||||
const bigInt = require('big-integer')
 | 
			
		||||
const { Buffer } = require('buffer/')
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
const { coreTypes } = require('../dist/types')
 | 
			
		||||
const { coreTypes } = require('../src/types')
 | 
			
		||||
const { Hash128, Hash160, Hash256, AccountID, Currency } = coreTypes
 | 
			
		||||
const { Buffer } = require('buffer/')
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ const {
 | 
			
		||||
  transactionTreeHash,
 | 
			
		||||
  ledgerHash,
 | 
			
		||||
  accountStateHash,
 | 
			
		||||
} = require('../dist/ledger-hashes')
 | 
			
		||||
} = require('../src/ledger-hashes')
 | 
			
		||||
 | 
			
		||||
describe('Ledger Hashes', function () {
 | 
			
		||||
  function testFactory(ledgerFixture) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
const { encode, decode } = require('../dist')
 | 
			
		||||
const { encode, decode } = require('../src')
 | 
			
		||||
 | 
			
		||||
let str =
 | 
			
		||||
  '1100612200000000240000000125000068652D0000000055B6632D6376A2D9319F20A1C6DCCB486432D1E4A79951229D4C3DE2946F51D56662400009184E72A00081140DD319918CD5AE792BF7EC80D63B0F01B4573BBC'
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
const { encode, decode } = require('../dist')
 | 
			
		||||
const { encode, decode } = require('../src')
 | 
			
		||||
 | 
			
		||||
let json = {
 | 
			
		||||
  Account: 'rrrrrrrrrrrrrrrrrrrrrhoLvTp',
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
const { quality } = require('../dist/coretypes')
 | 
			
		||||
const { quality } = require('../src/coretypes')
 | 
			
		||||
 | 
			
		||||
describe('Quality encode/decode', function () {
 | 
			
		||||
  const bookDirectory =
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
const { ShaMap } = require('../dist/shamap.js')
 | 
			
		||||
const { binary, HashPrefix } = require('../dist/coretypes')
 | 
			
		||||
const { coreTypes } = require('../dist/types')
 | 
			
		||||
const { ShaMap } = require('../src/shamap')
 | 
			
		||||
const { binary, HashPrefix } = require('../src/coretypes')
 | 
			
		||||
const { coreTypes } = require('../src/types')
 | 
			
		||||
const { loadFixture } = require('./utils')
 | 
			
		||||
const { Buffer } = require('buffer/')
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ const {
 | 
			
		||||
  encodeForSigning,
 | 
			
		||||
  encodeForSigningClaim,
 | 
			
		||||
  encodeForMultisigning,
 | 
			
		||||
} = require('../dist')
 | 
			
		||||
} = require('../src')
 | 
			
		||||
 | 
			
		||||
const tx_json = {
 | 
			
		||||
  Account: 'r9LqNeG6qHxjeUocjvVki2XR35weJ9mZgQ',
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
const { encode, decode } = require('../dist')
 | 
			
		||||
const { encode, decode } = require('../src')
 | 
			
		||||
 | 
			
		||||
// Notice: no Amount or Fee
 | 
			
		||||
const tx_json = {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
const { coreTypes } = require('../dist/types')
 | 
			
		||||
const { SerializedType } = require('../dist/types/serialized-type')
 | 
			
		||||
const { coreTypes } = require('../src/types')
 | 
			
		||||
const { SerializedType } = require('../src/types/serialized-type')
 | 
			
		||||
 | 
			
		||||
describe('SerializedType interfaces', () => {
 | 
			
		||||
  Object.entries(coreTypes).forEach(([name, Value]) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
const { coreTypes } = require('../dist/types')
 | 
			
		||||
const { coreTypes } = require('../src/types')
 | 
			
		||||
const { UInt8, UInt64 } = coreTypes
 | 
			
		||||
 | 
			
		||||
const { encode } = require('../dist')
 | 
			
		||||
const { encode } = require('../src')
 | 
			
		||||
 | 
			
		||||
const binary =
 | 
			
		||||
  '11007222000300003700000000000000003800000000000000006280000000000000000000000000000000000000005553440000000000000000000000000000000000000000000000000166D5438D7EA4C680000000000000000000000000005553440000000000AE123A8556F3CF91154711376AFB0F894F832B3D67D5438D7EA4C680000000000000000000000000005553440000000000F51DFC2A09D62CBBA1DFBDD4691DAC96AD98B90F'
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
const { encode, decode } = require('./../dist/index')
 | 
			
		||||
const { encode, decode } = require('./../src/index')
 | 
			
		||||
const fixtures = require('./fixtures/x-codec-fixtures.json')
 | 
			
		||||
 | 
			
		||||
let json_x1 = {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": "../../tsconfig.json",
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "target": "es5",
 | 
			
		||||
    "target": "es6",
 | 
			
		||||
    "lib": [
 | 
			
		||||
      "es2017"
 | 
			
		||||
    ],
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@ module.exports = {
 | 
			
		||||
  parserOptions: {
 | 
			
		||||
    // Enable linting rules with type information from our tsconfig
 | 
			
		||||
    tsconfigRootDir: __dirname,
 | 
			
		||||
    project: ['./tsconfig.json'],
 | 
			
		||||
    project: ['./tsconfig.json', './tsconfig.eslint.json'],
 | 
			
		||||
 | 
			
		||||
    sourceType: 'module', // Allow the use of imports / ES modules
 | 
			
		||||
 | 
			
		||||
@@ -19,11 +19,11 @@ module.exports = {
 | 
			
		||||
    browser: true, // Enable browser global variables
 | 
			
		||||
    node: true, // Enable node global variables & Node.js scoping
 | 
			
		||||
    es2020: true, // Add all ECMAScript 2020 globals and automatically set the ecmaVersion parser option to ES2020
 | 
			
		||||
    mocha: true, // Add Mocha testing global variables
 | 
			
		||||
    jest: true, // Add Jest testing global variables
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  plugins: [],
 | 
			
		||||
  extends: ['@xrplf/eslint-config/base', 'plugin:mocha/recommended'],
 | 
			
		||||
  extends: ['@xrplf/eslint-config/base'],
 | 
			
		||||
 | 
			
		||||
  rules: {
 | 
			
		||||
    // ** TODO **
 | 
			
		||||
@@ -56,5 +56,6 @@ module.exports = {
 | 
			
		||||
    'eslint-comments/require-description': 'off',
 | 
			
		||||
    'no-shadow': 'off',
 | 
			
		||||
    'multiline-comment-style': 'off',
 | 
			
		||||
    '@typescript-eslint/no-require-imports': 'off',
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
# ripple-keypairs Release History
 | 
			
		||||
 | 
			
		||||
## Unreleased
 | 
			
		||||
### Changed
 | 
			
		||||
- All tests now use the Jest test runner and have been refactored for consistency across all packages
 | 
			
		||||
 | 
			
		||||
## 1.1.4 (2022-05-02)
 | 
			
		||||
- `hexToBytes` now produces empty output for empty input, rather than `[0]`.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								packages/ripple-keypairs/jest.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								packages/ripple-keypairs/jest.config.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
// Jest configuration for api
 | 
			
		||||
const base = require('../../jest.config.base.js')
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  ...base,
 | 
			
		||||
  roots: [...base.roots, '<rootDir>/test'],
 | 
			
		||||
  displayName: 'ripple-keypairs',
 | 
			
		||||
}
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
  "description": "Cryptographic key pairs for the XRP Ledger",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "build": "tsc -b",
 | 
			
		||||
    "test": "tsc -b && nyc mocha",
 | 
			
		||||
    "test": "jest --verbose false --silent=false ./test/*.test.ts",
 | 
			
		||||
    "clean": "rm -rf ./dist && rm -rf tsconfig.tsbuildinfo",
 | 
			
		||||
    "lint": "eslint . --ext .ts",
 | 
			
		||||
    "prepublish": "npm run lint && npm test"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
/* eslint-disable no-bitwise --
 | 
			
		||||
 * lots of bitwise operators necessary for this */
 | 
			
		||||
import * as hashjs from 'hash.js'
 | 
			
		||||
import * as BigNum from 'bn.js'
 | 
			
		||||
import BigNum = require('bn.js')
 | 
			
		||||
 | 
			
		||||
export default class Sha512 {
 | 
			
		||||
  // TODO: type of `hash`?
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
import * as assert from 'assert'
 | 
			
		||||
import * as brorand from 'brorand'
 | 
			
		||||
import brorand = require('brorand')
 | 
			
		||||
import * as hashjs from 'hash.js'
 | 
			
		||||
import * as elliptic from 'elliptic'
 | 
			
		||||
 | 
			
		||||
@@ -157,7 +157,7 @@ function deriveNodeAddress(publicKey): string {
 | 
			
		||||
 | 
			
		||||
const { decodeSeed } = addressCodec
 | 
			
		||||
 | 
			
		||||
export = {
 | 
			
		||||
export {
 | 
			
		||||
  generateSeed,
 | 
			
		||||
  deriveKeypair,
 | 
			
		||||
  sign,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
import * as assert from 'assert'
 | 
			
		||||
import * as hashjs from 'hash.js'
 | 
			
		||||
import * as BN from 'bn.js'
 | 
			
		||||
import BN = require('bn.js')
 | 
			
		||||
 | 
			
		||||
function bytesToHex(a: Iterable<number> | ArrayLike<number>): string {
 | 
			
		||||
  return Array.from(a, (byteValue) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,11 @@
 | 
			
		||||
'use strict' // eslint-disable-line strict
 | 
			
		||||
import assert from 'assert'
 | 
			
		||||
import fixtures from './fixtures/api.json'
 | 
			
		||||
import * as api from '../src'
 | 
			
		||||
 | 
			
		||||
const assert = require('assert')
 | 
			
		||||
const fixtures = require('./fixtures/api.json')
 | 
			
		||||
const api = require('../dist')
 | 
			
		||||
const decodeSeed = api.decodeSeed
 | 
			
		||||
const entropy = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
 | 
			
		||||
const entropy = new Uint8Array([
 | 
			
		||||
  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
describe('api', () => {
 | 
			
		||||
  it('generateSeed - secp256k1', () => {
 | 
			
		||||
@@ -13,20 +14,22 @@ describe('api', () => {
 | 
			
		||||
 | 
			
		||||
  it('generateSeed - secp256k1, random', () => {
 | 
			
		||||
    const seed = api.generateSeed()
 | 
			
		||||
    assert(seed.charAt(0) === 's')
 | 
			
		||||
    assert(seed.startsWith('s'))
 | 
			
		||||
    const { type, bytes } = decodeSeed(seed)
 | 
			
		||||
    assert(type === 'secp256k1')
 | 
			
		||||
    assert(bytes.length === 16)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('generateSeed - ed25519', () => {
 | 
			
		||||
    assert.strictEqual(api.generateSeed({entropy, algorithm: 'ed25519'}),
 | 
			
		||||
      fixtures.ed25519.seed)
 | 
			
		||||
    assert.strictEqual(
 | 
			
		||||
      api.generateSeed({ entropy, algorithm: 'ed25519' }),
 | 
			
		||||
      fixtures.ed25519.seed,
 | 
			
		||||
    )
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('generateSeed - ed25519, random', () => {
 | 
			
		||||
    const seed = api.generateSeed({ algorithm: 'ed25519' })
 | 
			
		||||
    assert(seed.slice(0, 3) === 'sEd')
 | 
			
		||||
    assert(seed.startsWith('sEd'))
 | 
			
		||||
    const { type, bytes } = decodeSeed(seed)
 | 
			
		||||
    assert(type === 'ed25519')
 | 
			
		||||
    assert(bytes.length === 16)
 | 
			
		||||
@@ -43,12 +46,16 @@ describe('api', () => {
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('deriveKeypair - secp256k1 - validator', () => {
 | 
			
		||||
    const keypair = api.deriveKeypair(fixtures.secp256k1.seed, {validator: true})
 | 
			
		||||
    const keypair = api.deriveKeypair(fixtures.secp256k1.seed, {
 | 
			
		||||
      validator: true,
 | 
			
		||||
    })
 | 
			
		||||
    assert.deepEqual(keypair, fixtures.secp256k1.validatorKeypair)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('deriveKeypair - ed25519 - validator', () => {
 | 
			
		||||
    const keypair = api.deriveKeypair(fixtures.ed25519.seed, {validator: true})
 | 
			
		||||
    const keypair = api.deriveKeypair(fixtures.ed25519.seed, {
 | 
			
		||||
      validator: true,
 | 
			
		||||
    })
 | 
			
		||||
    assert.deepEqual(keypair, fixtures.ed25519.validatorKeypair)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
@@ -65,7 +72,7 @@ describe('api', () => {
 | 
			
		||||
  it('sign - secp256k1', () => {
 | 
			
		||||
    const privateKey = fixtures.secp256k1.keypair.privateKey
 | 
			
		||||
    const message = fixtures.secp256k1.message
 | 
			
		||||
    const messageHex = (Buffer.from(message, 'utf8')).toString('hex')
 | 
			
		||||
    const messageHex = Buffer.from(message, 'utf8').toString('hex')
 | 
			
		||||
    const signature = api.sign(messageHex, privateKey)
 | 
			
		||||
    assert.strictEqual(signature, fixtures.secp256k1.signature)
 | 
			
		||||
  })
 | 
			
		||||
@@ -74,14 +81,14 @@ describe('api', () => {
 | 
			
		||||
    const signature = fixtures.secp256k1.signature
 | 
			
		||||
    const publicKey = fixtures.secp256k1.keypair.publicKey
 | 
			
		||||
    const message = fixtures.secp256k1.message
 | 
			
		||||
    const messageHex = (Buffer.from(message, 'utf8')).toString('hex')
 | 
			
		||||
    const messageHex = Buffer.from(message, 'utf8').toString('hex')
 | 
			
		||||
    assert(api.verify(messageHex, signature, publicKey))
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('sign - ed25519', () => {
 | 
			
		||||
    const privateKey = fixtures.ed25519.keypair.privateKey
 | 
			
		||||
    const message = fixtures.ed25519.message
 | 
			
		||||
    const messageHex = (Buffer.from(message, 'utf8')).toString('hex')
 | 
			
		||||
    const messageHex = Buffer.from(message, 'utf8').toString('hex')
 | 
			
		||||
    const signature = api.sign(messageHex, privateKey)
 | 
			
		||||
    assert.strictEqual(signature, fixtures.ed25519.signature)
 | 
			
		||||
  })
 | 
			
		||||
@@ -90,20 +97,20 @@ describe('api', () => {
 | 
			
		||||
    const signature = fixtures.ed25519.signature
 | 
			
		||||
    const publicKey = fixtures.ed25519.keypair.publicKey
 | 
			
		||||
    const message = fixtures.ed25519.message
 | 
			
		||||
    const messageHex = (Buffer.from(message, 'utf8')).toString('hex')
 | 
			
		||||
    const messageHex = Buffer.from(message, 'utf8').toString('hex')
 | 
			
		||||
    assert(api.verify(messageHex, signature, publicKey))
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('deriveNodeAddress', () => {
 | 
			
		||||
    const x = 'n9KHn8NfbBsZV5q8bLfS72XyGqwFt5mgoPbcTV4c6qKiuPTAtXYk'
 | 
			
		||||
    const y = 'rU7bM9ENDkybaxNrefAVjdLTyNLuue1KaJ'
 | 
			
		||||
    assert.strictEqual(api.deriveNodeAddress(x), y)
 | 
			
		||||
    const addrX = 'n9KHn8NfbBsZV5q8bLfS72XyGqwFt5mgoPbcTV4c6qKiuPTAtXYk'
 | 
			
		||||
    const addrY = 'rU7bM9ENDkybaxNrefAVjdLTyNLuue1KaJ'
 | 
			
		||||
    assert.strictEqual(api.deriveNodeAddress(addrX), addrY)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('Random Address', () => {
 | 
			
		||||
    const seed = api.generateSeed()
 | 
			
		||||
    const keypair = api.deriveKeypair(seed)
 | 
			
		||||
    const address = api.deriveAddress(keypair.publicKey)
 | 
			
		||||
    assert(address[0] === 'r')
 | 
			
		||||
    assert(address.startsWith('r'))
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
@@ -1,9 +1,5 @@
 | 
			
		||||
/* eslint-disable no-unused-expressions/no-unused-expressions */
 | 
			
		||||
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
const assert = require('assert')
 | 
			
		||||
const api = require('ripple-address-codec')
 | 
			
		||||
import assert from 'assert'
 | 
			
		||||
import * as api from 'ripple-address-codec'
 | 
			
		||||
 | 
			
		||||
function toHex(bytes) {
 | 
			
		||||
  return Buffer.from(bytes).toString('hex').toUpperCase()
 | 
			
		||||
@@ -15,25 +11,29 @@ function toBytes(hex) {
 | 
			
		||||
 | 
			
		||||
describe('ripple-address-codec', function () {
 | 
			
		||||
  function makeTest(type, base58, hex) {
 | 
			
		||||
    it('can translate between ' + hex + ' and ' + base58 + ' (encode ' + type + ')', function() {
 | 
			
		||||
      const actual = api['encode' + type](toBytes(hex))
 | 
			
		||||
    it(`can translate between ${hex} and ${base58} (encode ${type})`, () => {
 | 
			
		||||
      const actual = api[`encode${type}`](toBytes(hex))
 | 
			
		||||
      assert.equal(actual, base58)
 | 
			
		||||
    })
 | 
			
		||||
    it('can translate between ' + base58 + ' and ' + hex + ' (decode ' + type + ')', function() {
 | 
			
		||||
      const buf = api['decode' + type](base58)
 | 
			
		||||
    it(`can translate between ${base58} and ${hex} (decode ${type})`, () => {
 | 
			
		||||
      const buf = api[`decode${type}`](base58)
 | 
			
		||||
      assert.equal(toHex(buf), hex)
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  makeTest('AccountID', 'rJrRMgiRgrU6hDF4pgu5DXQdWyPbY35ErN',
 | 
			
		||||
    'BA8E78626EE42C41B46D46C3048DF3A1C3C87072')
 | 
			
		||||
  makeTest(
 | 
			
		||||
    'AccountID',
 | 
			
		||||
    'rJrRMgiRgrU6hDF4pgu5DXQdWyPbY35ErN',
 | 
			
		||||
    'BA8E78626EE42C41B46D46C3048DF3A1C3C87072',
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  makeTest(
 | 
			
		||||
    'NodePublic',
 | 
			
		||||
    'n9MXXueo837zYH36DvMc13BwHcqtfAWNJY5czWVbp7uYTj7x17TH',
 | 
			
		||||
    '0388E5BA87A000CB807240DF8C848EB0B5FFA5C8E5A521BC8E105C0F0A44217828')
 | 
			
		||||
    '0388E5BA87A000CB807240DF8C848EB0B5FFA5C8E5A521BC8E105C0F0A44217828',
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  it('can decode arbitrary seeds', function() {
 | 
			
		||||
  it('can decode arbitrary seeds', () => {
 | 
			
		||||
    const decoded = api.decodeSeed('sEdTM1uX8pu2do5XvTnutH6HsouMaM2')
 | 
			
		||||
    assert.equal(toHex(decoded.bytes), '4C3A1D213FBDFB14C7C28D609469B341')
 | 
			
		||||
    assert.equal(decoded.type, 'ed25519')
 | 
			
		||||
@@ -43,11 +43,16 @@ describe('ripple-address-codec', function() {
 | 
			
		||||
    assert.equal(decoded2.type, 'secp256k1')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('can pass a type as second arg to encodeSeed', function() {
 | 
			
		||||
  it('can pass a type as second arg to encodeSeed', () => {
 | 
			
		||||
    const edSeed = 'sEdTM1uX8pu2do5XvTnutH6HsouMaM2'
 | 
			
		||||
    const decoded = api.decodeSeed(edSeed)
 | 
			
		||||
    assert.equal(toHex(decoded.bytes), '4C3A1D213FBDFB14C7C28D609469B341')
 | 
			
		||||
    assert.equal(decoded.type, 'ed25519')
 | 
			
		||||
    if (decoded.type === null) {
 | 
			
		||||
      assert.fail('decoded.type should not be null')
 | 
			
		||||
    }
 | 
			
		||||
    assert.equal(api.encodeSeed(decoded.bytes, decoded.type), edSeed)
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export {}
 | 
			
		||||
@@ -1,9 +1,7 @@
 | 
			
		||||
'use strict' // eslint-disable-line strict
 | 
			
		||||
import assert from 'assert'
 | 
			
		||||
import * as utils from '../src/utils'
 | 
			
		||||
 | 
			
		||||
const assert = require('assert')
 | 
			
		||||
const utils = require('../dist/utils')
 | 
			
		||||
 | 
			
		||||
describe('utils', () => {
 | 
			
		||||
describe('utils', function () {
 | 
			
		||||
  it('hexToBytes - empty', () => {
 | 
			
		||||
    assert.deepEqual(utils.hexToBytes(''), [])
 | 
			
		||||
  })
 | 
			
		||||
@@ -18,9 +16,14 @@ describe('utils', () => {
 | 
			
		||||
 | 
			
		||||
  it('bytesToHex - DEADBEEF', () => {
 | 
			
		||||
    assert.deepEqual(utils.bytesToHex([222, 173, 190, 239]), 'DEADBEEF')
 | 
			
		||||
  });
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('bytesToHex - DEADBEEF (Uint8Array)', () => {
 | 
			
		||||
    assert.deepEqual(utils.bytesToHex(new Uint8Array([222, 173, 190, 239])), 'DEADBEEF')
 | 
			
		||||
  });
 | 
			
		||||
    assert.deepEqual(
 | 
			
		||||
      utils.bytesToHex(new Uint8Array([222, 173, 190, 239])),
 | 
			
		||||
      'DEADBEEF',
 | 
			
		||||
    )
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export {}
 | 
			
		||||
@@ -1,81 +0,0 @@
 | 
			
		||||
/* eslint-disable no-unused-expressions/no-unused-expressions */
 | 
			
		||||
 | 
			
		||||
'use strict'
 | 
			
		||||
 | 
			
		||||
const assert = require('assert')
 | 
			
		||||
const api = require('ripple-address-codec')
 | 
			
		||||
 | 
			
		||||
function toHex(bytes) {
 | 
			
		||||
  return Buffer.from(bytes).toString('hex').toUpperCase()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function toBytes(hex) {
 | 
			
		||||
  return Buffer.from(hex, 'hex').toJSON().data
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
describe('ripple-address-codec', function() {
 | 
			
		||||
 | 
			
		||||
  describe('encodeSeed', function() {
 | 
			
		||||
 | 
			
		||||
    it('encodes a secp256k1 seed', function() {
 | 
			
		||||
      const result = api.encodeSeed(toBytes('CF2DE378FBDD7E2EE87D486DFB5A7BFF'), 'secp256k1')
 | 
			
		||||
      assert.equal(result, 'sn259rEFXrQrWyx3Q7XneWcwV6dfL')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('encodes low secp256k1 seed', function() {
 | 
			
		||||
      const result = api.encodeSeed(toBytes('00000000000000000000000000000000'), 'secp256k1')
 | 
			
		||||
      assert.equal(result, 'sp6JS7f14BuwFY8Mw6bTtLKWauoUs')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('encodes high secp256k1 seed', function() {
 | 
			
		||||
      const result = api.encodeSeed(toBytes('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'), 'secp256k1')
 | 
			
		||||
      assert.equal(result, 'saGwBRReqUNKuWNLpUAq8i8NkXEPN')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('encodes an ed25519 seed', function() {
 | 
			
		||||
      const result = api.encodeSeed(toBytes('4C3A1D213FBDFB14C7C28D609469B341'), 'ed25519')
 | 
			
		||||
      assert.equal(result, 'sEdTM1uX8pu2do5XvTnutH6HsouMaM2')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('encodes low ed25519 seed', function() {
 | 
			
		||||
      const result = api.encodeSeed(toBytes('00000000000000000000000000000000'), 'ed25519')
 | 
			
		||||
      assert.equal(result, 'sEdSJHS4oiAdz7w2X2ni1gFiqtbJHqE')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('encodes high ed25519 seed', function() {
 | 
			
		||||
      const result = api.encodeSeed(toBytes('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'), 'ed25519')
 | 
			
		||||
      assert.equal(result, 'sEdV19BLfeQeKdEXyYA4NhjPJe6XBfG')
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  describe('decodeSeed', function() {
 | 
			
		||||
 | 
			
		||||
    it('can decode an Ed25519 seed', function() {
 | 
			
		||||
      const decoded = api.decodeSeed('sEdTM1uX8pu2do5XvTnutH6HsouMaM2')
 | 
			
		||||
      assert.equal(toHex(decoded.bytes), '4C3A1D213FBDFB14C7C28D609469B341')
 | 
			
		||||
      assert.equal(decoded.type, 'ed25519')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('can decode a secp256k1 seed', function() {
 | 
			
		||||
      const decoded = api.decodeSeed('sn259rEFXrQrWyx3Q7XneWcwV6dfL')
 | 
			
		||||
      assert.equal(toHex(decoded.bytes), 'CF2DE378FBDD7E2EE87D486DFB5A7BFF')
 | 
			
		||||
      assert.equal(decoded.type, 'secp256k1')
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  describe('encodeAccountID', function() {
 | 
			
		||||
 | 
			
		||||
    it('can encode an AccountID', function() {
 | 
			
		||||
      const encoded = api.encodeAccountID(toBytes('BA8E78626EE42C41B46D46C3048DF3A1C3C87072'))
 | 
			
		||||
      assert.equal(encoded, 'rJrRMgiRgrU6hDF4pgu5DXQdWyPbY35ErN')
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  describe('decodeNodePublic', function() {
 | 
			
		||||
 | 
			
		||||
    it('can decode a NodePublic', function() {
 | 
			
		||||
      const decoded = api.decodeNodePublic('n9MXXueo837zYH36DvMc13BwHcqtfAWNJY5czWVbp7uYTj7x17TH')
 | 
			
		||||
      assert.equal(toHex(decoded), '0388E5BA87A000CB807240DF8C848EB0B5FFA5C8E5A521BC8E105C0F0A44217828')
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										99
									
								
								packages/ripple-keypairs/test/xrp-codec.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								packages/ripple-keypairs/test/xrp-codec.test.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
			
		||||
import assert from 'assert'
 | 
			
		||||
import * as api from 'ripple-address-codec'
 | 
			
		||||
 | 
			
		||||
function toHex(bytes: Buffer) {
 | 
			
		||||
  return Buffer.from(bytes).toString('hex').toUpperCase()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function toBytes(hex: string) {
 | 
			
		||||
  return Buffer.from(hex, 'hex').toJSON().data
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
describe('ripple-address-codec', function () {
 | 
			
		||||
  describe('encodeSeed', function () {
 | 
			
		||||
    it('encodes a secp256k1 seed', () => {
 | 
			
		||||
      const result = api.encodeSeed(
 | 
			
		||||
        Buffer.from(toBytes('CF2DE378FBDD7E2EE87D486DFB5A7BFF')),
 | 
			
		||||
        'secp256k1',
 | 
			
		||||
      )
 | 
			
		||||
      assert.equal(result, 'sn259rEFXrQrWyx3Q7XneWcwV6dfL')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('encodes low secp256k1 seed', () => {
 | 
			
		||||
      const result = api.encodeSeed(
 | 
			
		||||
        Buffer.from(toBytes('00000000000000000000000000000000')),
 | 
			
		||||
        'secp256k1',
 | 
			
		||||
      )
 | 
			
		||||
      assert.equal(result, 'sp6JS7f14BuwFY8Mw6bTtLKWauoUs')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('encodes high secp256k1 seed', () => {
 | 
			
		||||
      const result = api.encodeSeed(
 | 
			
		||||
        Buffer.from(toBytes('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF')),
 | 
			
		||||
        'secp256k1',
 | 
			
		||||
      )
 | 
			
		||||
      assert.equal(result, 'saGwBRReqUNKuWNLpUAq8i8NkXEPN')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('encodes an ed25519 seed', () => {
 | 
			
		||||
      const result = api.encodeSeed(
 | 
			
		||||
        Buffer.from(toBytes('4C3A1D213FBDFB14C7C28D609469B341')),
 | 
			
		||||
        'ed25519',
 | 
			
		||||
      )
 | 
			
		||||
      assert.equal(result, 'sEdTM1uX8pu2do5XvTnutH6HsouMaM2')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('encodes low ed25519 seed', () => {
 | 
			
		||||
      const result = api.encodeSeed(
 | 
			
		||||
        Buffer.from(toBytes('00000000000000000000000000000000')),
 | 
			
		||||
        'ed25519',
 | 
			
		||||
      )
 | 
			
		||||
      assert.equal(result, 'sEdSJHS4oiAdz7w2X2ni1gFiqtbJHqE')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('encodes high ed25519 seed', () => {
 | 
			
		||||
      const result = api.encodeSeed(
 | 
			
		||||
        Buffer.from(toBytes('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF')),
 | 
			
		||||
        'ed25519',
 | 
			
		||||
      )
 | 
			
		||||
      assert.equal(result, 'sEdV19BLfeQeKdEXyYA4NhjPJe6XBfG')
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  describe('decodeSeed', function () {
 | 
			
		||||
    it('can decode an Ed25519 seed', () => {
 | 
			
		||||
      const decoded = api.decodeSeed('sEdTM1uX8pu2do5XvTnutH6HsouMaM2')
 | 
			
		||||
      assert.equal(toHex(decoded.bytes), '4C3A1D213FBDFB14C7C28D609469B341')
 | 
			
		||||
      assert.equal(decoded.type, 'ed25519')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    it('can decode a secp256k1 seed', () => {
 | 
			
		||||
      const decoded = api.decodeSeed('sn259rEFXrQrWyx3Q7XneWcwV6dfL')
 | 
			
		||||
      assert.equal(toHex(decoded.bytes), 'CF2DE378FBDD7E2EE87D486DFB5A7BFF')
 | 
			
		||||
      assert.equal(decoded.type, 'secp256k1')
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  describe('encodeAccountID', function () {
 | 
			
		||||
    it('can encode an AccountID', () => {
 | 
			
		||||
      const encoded = api.encodeAccountID(
 | 
			
		||||
        Buffer.from(toBytes('BA8E78626EE42C41B46D46C3048DF3A1C3C87072')),
 | 
			
		||||
      )
 | 
			
		||||
      assert.equal(encoded, 'rJrRMgiRgrU6hDF4pgu5DXQdWyPbY35ErN')
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  describe('decodeNodePublic', function () {
 | 
			
		||||
    it('can decode a NodePublic', () => {
 | 
			
		||||
      const decoded = api.decodeNodePublic(
 | 
			
		||||
        'n9MXXueo837zYH36DvMc13BwHcqtfAWNJY5czWVbp7uYTj7x17TH',
 | 
			
		||||
      )
 | 
			
		||||
      assert.equal(
 | 
			
		||||
        toHex(decoded),
 | 
			
		||||
        '0388E5BA87A000CB807240DF8C848EB0B5FFA5C8E5A521BC8E105C0F0A44217828',
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export {}
 | 
			
		||||
							
								
								
									
										4
									
								
								packages/ripple-keypairs/tsconfig.eslint.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								packages/ripple-keypairs/tsconfig.eslint.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": "./tsconfig.json",
 | 
			
		||||
  "include": ["src/**/*.ts", "test/**/*.ts"]
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": "../../tsconfig.json",
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "target": "ES2017",
 | 
			
		||||
    "target": "es6",
 | 
			
		||||
    "declaration": true,
 | 
			
		||||
    "declarationMap": true,
 | 
			
		||||
    "outDir": "./dist",
 | 
			
		||||
@@ -11,7 +11,9 @@
 | 
			
		||||
    "noUnusedParameters": true,
 | 
			
		||||
    "noImplicitReturns": true,
 | 
			
		||||
    "noFallthroughCasesInSwitch": true,
 | 
			
		||||
    "forceConsistentCasingInFileNames": true
 | 
			
		||||
    "forceConsistentCasingInFileNames": true,
 | 
			
		||||
    "strictNullChecks": true,
 | 
			
		||||
    "resolveJsonModule": true
 | 
			
		||||
  },
 | 
			
		||||
  "references": [{
 | 
			
		||||
    "path": "../ripple-address-codec/tsconfig.json"
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,12 @@ module.exports = {
 | 
			
		||||
  parserOptions: {
 | 
			
		||||
    // Enable linting rules with type information from our tsconfig
 | 
			
		||||
    tsconfigRootDir: __dirname,
 | 
			
		||||
    project: ['./tsconfig.eslint.json'],
 | 
			
		||||
    project: [
 | 
			
		||||
      './tsconfig.eslint.json',
 | 
			
		||||
      '../ripple-binary-codec/tsconfig.eslint.json',
 | 
			
		||||
      '../ripple-address-codec/tsconfig.eslint.json',
 | 
			
		||||
      '../ripple-keypairs/tsconfig.eslint.json',
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
    // Allow the use of imports / ES modules
 | 
			
		||||
    sourceType: 'module',
 | 
			
		||||
@@ -23,11 +28,13 @@ module.exports = {
 | 
			
		||||
    node: true,
 | 
			
		||||
    // Add all ECMAScript 2020 globals and automatically set the ecmaVersion parser option to ES2020
 | 
			
		||||
    es2020: true,
 | 
			
		||||
    jest: true,
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  plugins: [],
 | 
			
		||||
  extends: ['@xrplf/eslint-config/base', 'plugin:mocha/recommended'],
 | 
			
		||||
  extends: ['@xrplf/eslint-config/base'],
 | 
			
		||||
  rules: {
 | 
			
		||||
    'multiline-comment-style': 'off',
 | 
			
		||||
    // Disabled until https://github.com/import-js/eslint-plugin-import/pull/2305 is resolved to
 | 
			
		||||
    // accomodate this change https://github.com/XRPLF/xrpl.js/pull/2133
 | 
			
		||||
    'import/no-unused-modules': 'off',
 | 
			
		||||
@@ -51,7 +58,6 @@ module.exports = {
 | 
			
		||||
    // no-shadow has false-positives for enum, @typescript-eslint version fixes that
 | 
			
		||||
    'no-shadow': 'off',
 | 
			
		||||
    '@typescript-eslint/no-shadow': ['error'],
 | 
			
		||||
    'multiline-comment-style': ['error', 'starred-block'],
 | 
			
		||||
    'jsdoc/check-examples': 'off',
 | 
			
		||||
 | 
			
		||||
    'tsdoc/syntax': 'off',
 | 
			
		||||
@@ -74,13 +80,16 @@ module.exports = {
 | 
			
		||||
        'max-statements': 'off',
 | 
			
		||||
        // Snippets have logs on console to better understand the working.
 | 
			
		||||
        'no-console': 'off',
 | 
			
		||||
        'import/no-extraneous-dependencies': 'off',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      files: ['test/**/*.ts'],
 | 
			
		||||
      rules: {
 | 
			
		||||
        // Because this project is managed by lerna, dev dependencies are
 | 
			
		||||
        // hoisted and do not appear in the package.json.
 | 
			
		||||
        /*
 | 
			
		||||
         * Because this project is managed by lerna, dev dependencies are
 | 
			
		||||
         * hoisted and do not appear in the package.json.
 | 
			
		||||
         */
 | 
			
		||||
        'import/no-extraneous-dependencies': 'off',
 | 
			
		||||
        'node/no-extraneous-import': 'off',
 | 
			
		||||
 | 
			
		||||
@@ -102,19 +111,12 @@ module.exports = {
 | 
			
		||||
        // Tests are already in 2 callbacks, so max 3 is pretty restrictive
 | 
			
		||||
        'max-nested-callbacks': 'off',
 | 
			
		||||
 | 
			
		||||
        // setup/teardown client is easier to do in before/after, even if there is only one testcase
 | 
			
		||||
        'mocha/no-hooks-for-single-case': 'off',
 | 
			
		||||
 | 
			
		||||
        // messes with fixtures
 | 
			
		||||
        'consistent-default-export-name/default-import-match-filename': 'off',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      files: ['test/client/*.ts'],
 | 
			
		||||
      rules: {
 | 
			
		||||
        // Rule does not work with dynamically generated tests.
 | 
			
		||||
        'mocha/no-setup-in-describe': 'off',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      files: ['test/models/*.ts'],
 | 
			
		||||
 
 | 
			
		||||
@@ -4,11 +4,16 @@ Subscribe to [the **xrpl-announce** mailing list](https://groups.google.com/g/xr
 | 
			
		||||
## Unreleased
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
* Code splitting improvements for lodash
 | 
			
		||||
* Fixed missing reason code in websocket implemntation on websocket disconnect
 | 
			
		||||
* Fix timeout error in request manager
 | 
			
		||||
* Improved typescript typing
 | 
			
		||||
 | 
			
		||||
### Added
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
* All tests now use the Jest test runner and have been refactored for consistency across all packages
 | 
			
		||||
 | 
			
		||||
### Deprecated
 | 
			
		||||
Wallet.fromMmnemonic()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								packages/xrpl/jest.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								packages/xrpl/jest.config.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
// Jest configuration for api
 | 
			
		||||
const base = require('../../jest.config.base.js')
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  ...base,
 | 
			
		||||
  roots: [...base.roots, '<rootDir>/test'],
 | 
			
		||||
  displayName: 'xrpl.js',
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								packages/xrpl/karma-setup.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								packages/xrpl/karma-setup.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
// the jest.fn() API
 | 
			
		||||
import * as jest from 'jest-mock'
 | 
			
		||||
// The matchers API
 | 
			
		||||
import expect from 'expect'
 | 
			
		||||
 | 
			
		||||
// Add missing Jest functions
 | 
			
		||||
window.test = window.it
 | 
			
		||||
window.test.each = (inputs) => (testName, test) =>
 | 
			
		||||
  inputs.forEach((args) => window.it(testName, () => test(...args)))
 | 
			
		||||
window.test.todo = function () {
 | 
			
		||||
  return undefined
 | 
			
		||||
}
 | 
			
		||||
window.jest = jest
 | 
			
		||||
window.expect = expect
 | 
			
		||||
							
								
								
									
										34
									
								
								packages/xrpl/karma.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								packages/xrpl/karma.config.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
const webpackConfig = require('./test/webpack.config')[0]()
 | 
			
		||||
delete webpackConfig.entry
 | 
			
		||||
 | 
			
		||||
module.exports = function (config) {
 | 
			
		||||
  config.set({
 | 
			
		||||
    plugins: ['karma-webpack', 'karma-jasmine', 'karma-chrome-launcher'],
 | 
			
		||||
 | 
			
		||||
    // base path that will be used to resolve all patterns (eg. files, exclude)
 | 
			
		||||
    basePath: '',
 | 
			
		||||
 | 
			
		||||
    webpack: webpackConfig,
 | 
			
		||||
 | 
			
		||||
    // frameworks to use
 | 
			
		||||
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
 | 
			
		||||
    frameworks: ['jasmine'],
 | 
			
		||||
 | 
			
		||||
    // list of files / patterns to load in the browser
 | 
			
		||||
    files: [
 | 
			
		||||
      'build/xrpl-latest.js',
 | 
			
		||||
      'test/integration/index.ts',
 | 
			
		||||
      'karma-setup.js',
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
    // preprocess matching files before serving them to the browser
 | 
			
		||||
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
 | 
			
		||||
    preprocessors: {
 | 
			
		||||
      'karma-setup.js': ['webpack'],
 | 
			
		||||
      // Use webpack to bundle our test files
 | 
			
		||||
      'test/integration/index.ts': ['webpack'],
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    browsers: ['ChromeHeadless'],
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2214
									
								
								packages/xrpl/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2214
									
								
								packages/xrpl/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -33,9 +33,19 @@
 | 
			
		||||
    "ws": "^8.2.2"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@geut/browser-node-core": "^2.0.13",
 | 
			
		||||
    "@types/node": "^14.18.36",
 | 
			
		||||
    "assert-browserify": "^2.0.0",
 | 
			
		||||
    "browserify-fs": "^1.0.0",
 | 
			
		||||
    "constants-browserify": "^1.0.0",
 | 
			
		||||
    "https-browserify": "^1.0.0",
 | 
			
		||||
    "karma": "^6.4.1",
 | 
			
		||||
    "karma-chrome-launcher": "^3.1.1",
 | 
			
		||||
    "karma-jasmine": "^5.1.0",
 | 
			
		||||
    "karma-webpack": "^5.0.0",
 | 
			
		||||
    "node-polyfill-webpack-plugin": "^2.0.1",
 | 
			
		||||
    "react": "^18.2.0",
 | 
			
		||||
    "typedoc": "^0.23.24",
 | 
			
		||||
    "xrpl-local": "file:./src"
 | 
			
		||||
    "typedoc": "^0.23.24"
 | 
			
		||||
  },
 | 
			
		||||
  "resolutions": {
 | 
			
		||||
    "elliptic": "^6.5.4"
 | 
			
		||||
@@ -48,13 +58,13 @@
 | 
			
		||||
    "build:browserTests": "webpack --config ./test/webpack.config.js",
 | 
			
		||||
    "analyze": "run-s build:web --analyze",
 | 
			
		||||
    "watch": "run-s build:lib --watch",
 | 
			
		||||
    "clean": "rm -rf dist",
 | 
			
		||||
    "clean": "rm -rf dist build coverage",
 | 
			
		||||
    "docgen": "tsc --build tsconfig.docs.json && typedoc && echo js.xrpl.org >> ../../docs/CNAME",
 | 
			
		||||
    "prepublish": "run-s clean build",
 | 
			
		||||
    "test": "nyc mocha --config=test/.mocharc.json --exit",
 | 
			
		||||
    "test:integration": "TS_NODE_PROJECT=tsconfig.build.json nyc mocha ./test/integration/**/*.test.ts ./test/integration/*.test.ts",
 | 
			
		||||
    "test:browser": "npm run build:browserTests && TS_NODE_PROJECT=tsconfig.build.json nyc mocha ./test/browser/*.ts",
 | 
			
		||||
    "test:watch": "TS_NODE_PROJECT=src/tsconfig.json mocha --config=test/.mocharc.json --watch --reporter dot",
 | 
			
		||||
    "test": "jest --verbose false --silent=false ./test/**/*.test.ts --testPathIgnorePatterns=./test/integration --testPathIgnorePatterns=./test/fixtures",
 | 
			
		||||
    "test:integration": "TS_NODE_PROJECT=tsconfig.build.json jest --verbose false --silent=false --runInBand ./test/integration/**/*.test.ts",
 | 
			
		||||
    "test:browser": "npm run build && npm run build:browserTests && karma start ./karma.config.js --single-run",
 | 
			
		||||
    "test:watch": "jest --watch --verbose false --silent=false --runInBand ./test/**/*.test.ts --testPathIgnorePatterns=./test/integration --testPathIgnorePatterns=./test/fixtures",
 | 
			
		||||
    "format": "prettier --write '{src,test}/**/*.ts'",
 | 
			
		||||
    "lint": "eslint . --ext .ts --max-warnings 0",
 | 
			
		||||
    "perf": "./scripts/perf_test.sh",
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ import {
 | 
			
		||||
  PaymentChannelCreate,
 | 
			
		||||
  PaymentChannelClaim,
 | 
			
		||||
  hashes,
 | 
			
		||||
} from '../../dist/npm'
 | 
			
		||||
} from '../../src'
 | 
			
		||||
 | 
			
		||||
const client = new Client('wss://s.altnet.rippletest.net:51233')
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import { Client, LedgerResponse, TxResponse } from '../../dist/npm'
 | 
			
		||||
import { Client, LedgerResponse, TxResponse } from '../../src'
 | 
			
		||||
 | 
			
		||||
const client = new Client('wss://s.altnet.rippletest.net:51233')
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ import {
 | 
			
		||||
  AccountSet,
 | 
			
		||||
  convertStringToHex,
 | 
			
		||||
  SignerListSet,
 | 
			
		||||
} from '../../dist/npm'
 | 
			
		||||
} from '../../src'
 | 
			
		||||
 | 
			
		||||
const client = new Client('wss://s.altnet.rippletest.net:51233')
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import { Client, Payment, PaymentFlags, TrustSet } from '../../dist/npm'
 | 
			
		||||
import { Client, Payment, PaymentFlags, TrustSet } from '../../src'
 | 
			
		||||
 | 
			
		||||
const client = new Client('wss://s.altnet.rippletest.net:51233')
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import { Client, Payment, RipplePathFindResponse } from '../../dist/npm'
 | 
			
		||||
import { Client, Payment, RipplePathFindResponse } from '../../src'
 | 
			
		||||
 | 
			
		||||
const client = new Client('wss://s.altnet.rippletest.net:51233')
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import { Client, Payment } from '../../dist/npm'
 | 
			
		||||
import { Client, Payment } from '../../src'
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * When implementing Reliable Transaction Submission, there are many potential solutions, each with different trade-offs.
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ import {
 | 
			
		||||
  EscrowCreate,
 | 
			
		||||
  EscrowFinish,
 | 
			
		||||
  isoTimeToRippleTime,
 | 
			
		||||
} from '../../dist/npm'
 | 
			
		||||
} from '../../src'
 | 
			
		||||
 | 
			
		||||
const client = new Client('wss://s.altnet.rippletest.net:51233')
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import { Client, Payment, SetRegularKey } from '../../dist/npm'
 | 
			
		||||
import { Client, Payment, SetRegularKey } from '../../src'
 | 
			
		||||
 | 
			
		||||
const client = new Client('wss://s.altnet.rippletest.net:51233')
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": "../tsconfig.json",
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "rootDir": "./src"
 | 
			
		||||
    "rootDir": "../../xrpl"
 | 
			
		||||
  },
 | 
			
		||||
  "include": ["./src/**/*.ts"]
 | 
			
		||||
  "include": ["./src/**/*.ts", "../src/**/*.ts", "../src/**/*.json"]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import type { Client } from '..'
 | 
			
		||||
import type { Client } from '../client'
 | 
			
		||||
import { XRPLFaucetError } from '../errors'
 | 
			
		||||
 | 
			
		||||
export interface FaucetWallet {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ import { request as httpsRequest, RequestOptions } from 'https'
 | 
			
		||||
 | 
			
		||||
import { isValidClassicAddress } from 'ripple-address-codec'
 | 
			
		||||
 | 
			
		||||
import type { Client } from '..'
 | 
			
		||||
import type { Client } from '../client'
 | 
			
		||||
import { RippledError, XRPLFaucetError } from '../errors'
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
import BigNumber from 'bignumber.js'
 | 
			
		||||
import { fromSeed } from 'bip32'
 | 
			
		||||
import { mnemonicToSeedSync, validateMnemonic } from 'bip39'
 | 
			
		||||
import _ from 'lodash'
 | 
			
		||||
import isEqual from 'lodash/isEqual'
 | 
			
		||||
import {
 | 
			
		||||
  classicAddressToXAddress,
 | 
			
		||||
  isValidXAddress,
 | 
			
		||||
@@ -498,7 +498,7 @@ class Wallet {
 | 
			
		||||
    })
 | 
			
		||||
    /* eslint-enable @typescript-eslint/consistent-type-assertions -- Done with dynamic checking */
 | 
			
		||||
 | 
			
		||||
    if (!_.isEqual(decoded, txCopy)) {
 | 
			
		||||
    if (!isEqual(decoded, txCopy)) {
 | 
			
		||||
      const data = {
 | 
			
		||||
        decoded,
 | 
			
		||||
        tx,
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ export default class RequestManager {
 | 
			
		||||
    {
 | 
			
		||||
      resolve: (value: Response | PromiseLike<Response>) => void
 | 
			
		||||
      reject: (value: Error) => void
 | 
			
		||||
      timer: NodeJS.Timeout
 | 
			
		||||
      timer: ReturnType<typeof setTimeout>
 | 
			
		||||
    }
 | 
			
		||||
  >()
 | 
			
		||||
 | 
			
		||||
@@ -34,7 +34,10 @@ export default class RequestManager {
 | 
			
		||||
  public resolve(id: string | number, response: Response): void {
 | 
			
		||||
    const promise = this.promisesAwaitingResponse.get(id)
 | 
			
		||||
    if (promise == null) {
 | 
			
		||||
      throw new XrplError(`No existing promise with id ${id}`)
 | 
			
		||||
      throw new XrplError(`No existing promise with id ${id}`, {
 | 
			
		||||
        type: 'resolve',
 | 
			
		||||
        response,
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
    clearTimeout(promise.timer)
 | 
			
		||||
    promise.resolve(response)
 | 
			
		||||
@@ -51,7 +54,10 @@ export default class RequestManager {
 | 
			
		||||
  public reject(id: string | number, error: Error): void {
 | 
			
		||||
    const promise = this.promisesAwaitingResponse.get(id)
 | 
			
		||||
    if (promise == null) {
 | 
			
		||||
      throw new XrplError(`No existing promise with id ${id}`)
 | 
			
		||||
      throw new XrplError(`No existing promise with id ${id}`, {
 | 
			
		||||
        type: 'reject',
 | 
			
		||||
        error,
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
    clearTimeout(promise.timer)
 | 
			
		||||
    // TODO: figure out how to have a better stack trace for an error
 | 
			
		||||
@@ -93,20 +99,35 @@ export default class RequestManager {
 | 
			
		||||
      newId = request.id
 | 
			
		||||
    }
 | 
			
		||||
    const newRequest = JSON.stringify({ ...request, id: newId })
 | 
			
		||||
    const timer = setTimeout(
 | 
			
		||||
      () => this.reject(newId, new TimeoutError()),
 | 
			
		||||
      timeout,
 | 
			
		||||
    // Typing required for Jest running in browser
 | 
			
		||||
    const timer: ReturnType<typeof setTimeout> = setTimeout(() => {
 | 
			
		||||
      this.reject(
 | 
			
		||||
        newId,
 | 
			
		||||
        new TimeoutError(
 | 
			
		||||
          `Timeout for request: ${JSON.stringify(request)} with id ${newId}`,
 | 
			
		||||
          request,
 | 
			
		||||
        ),
 | 
			
		||||
      )
 | 
			
		||||
    }, timeout)
 | 
			
		||||
    /*
 | 
			
		||||
     * Node.js won't exit if a timer is still running, so we tell Node to ignore.
 | 
			
		||||
     * (Node will still wait for the request to complete).
 | 
			
		||||
     */
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Reason above.
 | 
			
		||||
    if (timer.unref) {
 | 
			
		||||
      timer.unref()
 | 
			
		||||
    // The following type assertions are required to get this code to pass in browser environments
 | 
			
		||||
    // where setTimeout has a different type
 | 
			
		||||
    // eslint-disable-next-line max-len -- Necessary to disable both rules.
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access -- Reason above.
 | 
			
		||||
    if ((timer as unknown as any).unref) {
 | 
			
		||||
      // eslint-disable-next-line max-len -- Necessary to disable both rules.
 | 
			
		||||
      // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call -- Reason above.
 | 
			
		||||
      ;(timer as unknown as any).unref()
 | 
			
		||||
    }
 | 
			
		||||
    if (this.promisesAwaitingResponse.has(newId)) {
 | 
			
		||||
      throw new XrplError(`Response with id '${newId}' is already pending`)
 | 
			
		||||
      clearTimeout(timer)
 | 
			
		||||
      throw new XrplError(
 | 
			
		||||
        `Response with id '${newId}' is already pending`,
 | 
			
		||||
        request,
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
    const newPromise = new Promise<Response>(
 | 
			
		||||
      (resolve: (value: Response | PromiseLike<Response>) => void, reject) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,13 +3,13 @@ import { EventEmitter } from 'events'
 | 
			
		||||
 | 
			
		||||
// Define the global WebSocket class found on the native browser
 | 
			
		||||
declare class WebSocket {
 | 
			
		||||
  public onclose?: () => void
 | 
			
		||||
  public onopen?: () => void
 | 
			
		||||
  public onclose?: (closeEvent: CloseEvent) => void
 | 
			
		||||
  public onopen?: (openEvent: Event) => void
 | 
			
		||||
  public onerror?: (error: Error) => void
 | 
			
		||||
  public onmessage?: (message: MessageEvent) => void
 | 
			
		||||
  public readyState: number
 | 
			
		||||
  public constructor(url: string)
 | 
			
		||||
  public close(code?: number): void
 | 
			
		||||
  public close(code?: number, reason?: Buffer): void
 | 
			
		||||
  public send(message: string): void
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -52,8 +52,13 @@ export default class WSWrapper extends EventEmitter {
 | 
			
		||||
 | 
			
		||||
    this.ws = new WebSocket(url)
 | 
			
		||||
 | 
			
		||||
    this.ws.onclose = (): void => {
 | 
			
		||||
      this.emit('close')
 | 
			
		||||
    this.ws.onclose = (closeEvent: CloseEvent): void => {
 | 
			
		||||
      let reason: Uint8Array | undefined
 | 
			
		||||
      if (closeEvent.reason) {
 | 
			
		||||
        const enc = new TextEncoder()
 | 
			
		||||
        reason = enc.encode(closeEvent.reason)
 | 
			
		||||
      }
 | 
			
		||||
      this.emit('close', closeEvent.code, reason)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.ws.onopen = (): void => {
 | 
			
		||||
@@ -71,10 +76,13 @@ export default class WSWrapper extends EventEmitter {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Closes the websocket.
 | 
			
		||||
   *
 | 
			
		||||
   * @param code - Close code.
 | 
			
		||||
   * @param reason - Close reason.
 | 
			
		||||
   */
 | 
			
		||||
  public close(): void {
 | 
			
		||||
  public close(code?: number, reason?: Buffer): void {
 | 
			
		||||
    if (this.readyState === 1) {
 | 
			
		||||
      this.ws.close()
 | 
			
		||||
      this.ws.close(code, reason)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,9 @@
 | 
			
		||||
/* eslint-disable max-lines -- Connection is a large file w/ lots of imports/exports */
 | 
			
		||||
 | 
			
		||||
import { EventEmitter } from 'events'
 | 
			
		||||
import { Agent } from 'http'
 | 
			
		||||
 | 
			
		||||
import _ from 'lodash'
 | 
			
		||||
import omitBy from 'lodash/omitBy'
 | 
			
		||||
import WebSocket from 'ws'
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
@@ -63,7 +64,7 @@ function getAgent(url: string, config: ConnectionOptions): Agent | undefined {
 | 
			
		||||
  const parsedURL = new URL(url)
 | 
			
		||||
  const parsedProxyURL = new URL(config.proxy)
 | 
			
		||||
 | 
			
		||||
  const proxyOptions = _.omitBy(
 | 
			
		||||
  const proxyOptions = omitBy(
 | 
			
		||||
    {
 | 
			
		||||
      secureEndpoint: parsedURL.protocol === 'wss:',
 | 
			
		||||
      secureProxy: parsedProxyURL.protocol === 'https:',
 | 
			
		||||
@@ -125,7 +126,7 @@ function createWebSocket(
 | 
			
		||||
      Authorization: `Basic ${base64}`,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  const optionsOverrides = _.omitBy(
 | 
			
		||||
  const optionsOverrides = omitBy(
 | 
			
		||||
    {
 | 
			
		||||
      ca: config.trustedCertificates,
 | 
			
		||||
      key: config.key,
 | 
			
		||||
@@ -175,8 +176,10 @@ async function websocketSendAsync(
 | 
			
		||||
export class Connection extends EventEmitter {
 | 
			
		||||
  private readonly url: string | undefined
 | 
			
		||||
  private ws: WebSocket | null = null
 | 
			
		||||
  private reconnectTimeoutID: null | NodeJS.Timeout = null
 | 
			
		||||
  private heartbeatIntervalID: null | NodeJS.Timeout = null
 | 
			
		||||
  // Typing necessary for Jest tests running in browser
 | 
			
		||||
  private reconnectTimeoutID: null | ReturnType<typeof setTimeout> = null
 | 
			
		||||
  // Typing necessary for Jest tetsts running in browser
 | 
			
		||||
  private heartbeatIntervalID: null | ReturnType<typeof setTimeout> = null
 | 
			
		||||
  private readonly retryConnectionBackoff = new ExponentialBackoff({
 | 
			
		||||
    min: 100,
 | 
			
		||||
    max: SECONDS_PER_MINUTE * 1000,
 | 
			
		||||
@@ -224,6 +227,7 @@ export class Connection extends EventEmitter {
 | 
			
		||||
   * @returns When the websocket is connected.
 | 
			
		||||
   * @throws ConnectionError if there is a connection error, RippleError if there is already a WebSocket in existence.
 | 
			
		||||
   */
 | 
			
		||||
  // eslint-disable-next-line max-lines-per-function -- Necessary
 | 
			
		||||
  public async connect(): Promise<void> {
 | 
			
		||||
    if (this.isConnected()) {
 | 
			
		||||
      return Promise.resolve()
 | 
			
		||||
@@ -245,14 +249,17 @@ export class Connection extends EventEmitter {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Create the connection timeout, in case the connection hangs longer than expected.
 | 
			
		||||
    const connectionTimeoutID = setTimeout(() => {
 | 
			
		||||
    const connectionTimeoutID: ReturnType<typeof setTimeout> = setTimeout(
 | 
			
		||||
      () => {
 | 
			
		||||
        this.onConnectionFailed(
 | 
			
		||||
          new ConnectionError(
 | 
			
		||||
            `Error: connect() timed out after ${this.config.connectionTimeout} ms. If your internet connection is working, the ` +
 | 
			
		||||
              `rippled server may be blocked or inaccessible. You can also try setting the 'connectionTimeout' option in the Client constructor.`,
 | 
			
		||||
          ),
 | 
			
		||||
        )
 | 
			
		||||
    }, this.config.connectionTimeout)
 | 
			
		||||
      },
 | 
			
		||||
      this.config.connectionTimeout,
 | 
			
		||||
    )
 | 
			
		||||
    // Connection listeners: these stay attached only until a connection is done/open.
 | 
			
		||||
    this.ws = createWebSocket(this.url, this.config)
 | 
			
		||||
 | 
			
		||||
@@ -337,7 +344,7 @@ export class Connection extends EventEmitter {
 | 
			
		||||
    timeout?: number,
 | 
			
		||||
  ): Promise<unknown> {
 | 
			
		||||
    if (!this.shouldBeConnected || this.ws == null) {
 | 
			
		||||
      throw new NotConnectedError()
 | 
			
		||||
      throw new NotConnectedError(JSON.stringify(request), request)
 | 
			
		||||
    }
 | 
			
		||||
    const [id, message, responsePromise] = this.requestManager.createRequest(
 | 
			
		||||
      request,
 | 
			
		||||
@@ -429,7 +436,9 @@ export class Connection extends EventEmitter {
 | 
			
		||||
   * @throws Error if the websocket initialized is somehow null.
 | 
			
		||||
   */
 | 
			
		||||
  // eslint-disable-next-line max-lines-per-function -- Many error code conditionals to check.
 | 
			
		||||
  private async onceOpen(connectionTimeoutID: NodeJS.Timeout): Promise<void> {
 | 
			
		||||
  private async onceOpen(
 | 
			
		||||
    connectionTimeoutID: ReturnType<typeof setTimeout>,
 | 
			
		||||
  ): Promise<void> {
 | 
			
		||||
    if (this.ws == null) {
 | 
			
		||||
      throw new XrplError('onceOpen: ws is null')
 | 
			
		||||
    }
 | 
			
		||||
@@ -458,13 +467,14 @@ export class Connection extends EventEmitter {
 | 
			
		||||
      this.ws = null
 | 
			
		||||
 | 
			
		||||
      if (code === undefined) {
 | 
			
		||||
        const reasonText = reason ? reason.toString() : 'undefined'
 | 
			
		||||
        // eslint-disable-next-line no-console -- The error is helpful for debugging.
 | 
			
		||||
        console.error(
 | 
			
		||||
          `Disconnected but the disconnect code was undefined (The given reason was ${reasonText}).` +
 | 
			
		||||
            `This could be caused by an exception being thrown during a 'connect' callback. ` +
 | 
			
		||||
            `Disconnecting with code 1011 to indicate an internal error has occurred.`,
 | 
			
		||||
        )
 | 
			
		||||
        // Useful to keep this code for debugging purposes.
 | 
			
		||||
        // const reasonText = reason ? reason.toString() : 'undefined'
 | 
			
		||||
        // // eslint-disable-next-line no-console -- The error is helpful for debugging.
 | 
			
		||||
        // console.error(
 | 
			
		||||
        //   `Disconnected but the disconnect code was undefined (The given reason was ${reasonText}).` +
 | 
			
		||||
        //     `This could be caused by an exception being thrown during a 'connect' callback. ` +
 | 
			
		||||
        //     `Disconnecting with code 1011 to indicate an internal error has occurred.`,
 | 
			
		||||
        // )
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Error code 1011 represents an Internal Error according to
 | 
			
		||||
 
 | 
			
		||||
@@ -454,6 +454,10 @@ class Client extends EventEmitter {
 | 
			
		||||
    event: 'consensusPhase',
 | 
			
		||||
    listener: (phase: ConsensusStream) => void,
 | 
			
		||||
  ): this
 | 
			
		||||
  public on(
 | 
			
		||||
    event: 'manifestReceived',
 | 
			
		||||
    listener: (manifest: ManifestResponse) => void,
 | 
			
		||||
  ): this
 | 
			
		||||
  public on(event: 'path_find', listener: (path: PathFindStream) => void): this
 | 
			
		||||
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- needs to be any for overload
 | 
			
		||||
  public on(event: 'error', listener: (...err: any[]) => void): this
 | 
			
		||||
 
 | 
			
		||||
@@ -108,6 +108,10 @@ export interface ResponseOnlyTxInfo {
 | 
			
		||||
   * The sequence number of the ledger that included this transaction.
 | 
			
		||||
   */
 | 
			
		||||
  ledger_index?: number
 | 
			
		||||
  /**
 | 
			
		||||
   * @deprecated Alias for ledger_index.
 | 
			
		||||
   */
 | 
			
		||||
  inLedger?: number
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@ export interface LedgerDataRequest extends BaseRequest {
 | 
			
		||||
 | 
			
		||||
type LabeledLedgerEntry = { ledgerEntryType: string } & LedgerEntry
 | 
			
		||||
 | 
			
		||||
interface BinaryLedgerEntry {
 | 
			
		||||
export interface BinaryLedgerEntry {
 | 
			
		||||
  data: string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,14 @@ export interface JobType {
 | 
			
		||||
  in_progress?: number
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// The states for validating and proposing do not exist in the field state_accounting
 | 
			
		||||
// See https://github.com/XRPLF/rippled/blob/develop/src/ripple/app/misc/NetworkOPs.cpp#L4545
 | 
			
		||||
// https://github.com/XRPLF/rippled/blob/develop/src/ripple/app/misc/NetworkOPs.h#L66
 | 
			
		||||
export type StateAccountingFinal = Record<
 | 
			
		||||
  Exclude<ServerState, 'validating' | 'proposing'>,
 | 
			
		||||
  StateAccounting
 | 
			
		||||
>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Response expected from a {@link ServerInfoRequest}.
 | 
			
		||||
 *
 | 
			
		||||
@@ -158,6 +166,14 @@ export interface ServerInfoResponse extends BaseResponse {
 | 
			
		||||
       * cost.
 | 
			
		||||
       */
 | 
			
		||||
      load_factor_server?: number
 | 
			
		||||
      /**
 | 
			
		||||
       * The number of peer connections which were severed.
 | 
			
		||||
       */
 | 
			
		||||
      peer_disconnects?: string
 | 
			
		||||
      /**
 | 
			
		||||
       * The number of peer connections which were severed due to excess resource consumption.
 | 
			
		||||
       */
 | 
			
		||||
      peer_disconnects_resources?: string
 | 
			
		||||
      network_ledger?: 'waiting'
 | 
			
		||||
      /** How many other rippled servers this one is currently connected to. */
 | 
			
		||||
      peers: number
 | 
			
		||||
@@ -179,13 +195,13 @@ export interface ServerInfoResponse extends BaseResponse {
 | 
			
		||||
       * The number of consecutive microseconds the server has been in the
 | 
			
		||||
       * current state.
 | 
			
		||||
       */
 | 
			
		||||
      server_state_duration_us: number
 | 
			
		||||
      server_state_duration_us: string
 | 
			
		||||
      /**
 | 
			
		||||
       * A map of various server states with information about the time the
 | 
			
		||||
       * server spends in each. This can be useful for tracking the long-term
 | 
			
		||||
       * health of your server's connectivity to the network.
 | 
			
		||||
       */
 | 
			
		||||
      state_accounting: Record<ServerState, StateAccounting>
 | 
			
		||||
      state_accounting: StateAccountingFinal
 | 
			
		||||
      /** The current time in UTC, according to the server's clock. */
 | 
			
		||||
      time: string
 | 
			
		||||
      /** Number of consecutive seconds that the server has been operational. */
 | 
			
		||||
@@ -227,6 +243,11 @@ export interface ServerInfoResponse extends BaseResponse {
 | 
			
		||||
       * static validator list.
 | 
			
		||||
       */
 | 
			
		||||
      validator_list_expires?: string
 | 
			
		||||
      validator_list?: {
 | 
			
		||||
        count: number
 | 
			
		||||
        expiration: 'never' | 'unknown' | string
 | 
			
		||||
        status: 'active' | 'expired' | 'unknown'
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
import { BaseRequest, BaseResponse } from './baseMethod'
 | 
			
		||||
import { JobType, ServerState, StateAccounting } from './serverInfo'
 | 
			
		||||
import { JobType, ServerState, StateAccountingFinal } from './serverInfo'
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The `server_state` command asks the server for various machine-readable
 | 
			
		||||
@@ -35,7 +35,10 @@ export interface ServerStateResponse extends BaseResponse {
 | 
			
		||||
      io_latency_ms: number
 | 
			
		||||
      jq_trans_overflow: string
 | 
			
		||||
      last_close: {
 | 
			
		||||
        converge_time_s: number
 | 
			
		||||
        // coverage_time_s only exists for `server_info` requests. `server_state` is a "non human" api request,
 | 
			
		||||
        // therefore the type is coverage_time
 | 
			
		||||
        // See https://github.com/XRPLF/rippled/blob/83faf43140e27e5d6d6779eaa0ffb75c33d98029/src/ripple/app/misc/NetworkOPs.cpp#L2458
 | 
			
		||||
        converge_time: number
 | 
			
		||||
        proposers: number
 | 
			
		||||
      }
 | 
			
		||||
      load?: {
 | 
			
		||||
@@ -48,24 +51,27 @@ export interface ServerStateResponse extends BaseResponse {
 | 
			
		||||
      load_factor_fee_queue?: number
 | 
			
		||||
      load_factor_fee_reference?: number
 | 
			
		||||
      load_factor_server?: number
 | 
			
		||||
      peer_disconnects?: string
 | 
			
		||||
      peer_disconnects_resources?: string
 | 
			
		||||
      peers: number
 | 
			
		||||
      pubkey_node: string
 | 
			
		||||
      pubkey_validator?: string
 | 
			
		||||
      server_state: ServerState
 | 
			
		||||
      server_state_duration_us: number
 | 
			
		||||
      state_accounting: Record<ServerState, StateAccounting>
 | 
			
		||||
      server_state_duration_us: string
 | 
			
		||||
      state_accounting: StateAccountingFinal
 | 
			
		||||
      time: string
 | 
			
		||||
      uptime: number
 | 
			
		||||
      validated_ledger?: {
 | 
			
		||||
        age: number
 | 
			
		||||
        age?: number
 | 
			
		||||
        base_fee: number
 | 
			
		||||
        close_time: number
 | 
			
		||||
        hash: string
 | 
			
		||||
        reserve_base: number
 | 
			
		||||
        reserve_inc: number
 | 
			
		||||
        seq: number
 | 
			
		||||
      }
 | 
			
		||||
      validation_quorum: number
 | 
			
		||||
      validator_list_expires?: string
 | 
			
		||||
      validator_list_expires?: number
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -53,12 +53,14 @@ export function validateCheckCash(tx: Record<string, unknown>): void {
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Necessary check
 | 
			
		||||
  if (tx.Amount != null && tx.Amount !== undefined && !isAmount(tx.Amount)) {
 | 
			
		||||
    throw new ValidationError('CheckCash: invalid Amount')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (
 | 
			
		||||
    tx.DeliverMin != null &&
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Necessary check
 | 
			
		||||
    tx.DeliverMin !== undefined &&
 | 
			
		||||
    !isAmount(tx.DeliverMin)
 | 
			
		||||
  ) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
/* eslint-disable complexity -- verifies 19 tx types hence a lot of checks needed */
 | 
			
		||||
/* eslint-disable max-lines-per-function -- need to work with a lot of Tx verifications */
 | 
			
		||||
 | 
			
		||||
import _ from 'lodash'
 | 
			
		||||
import isEqual from 'lodash/isEqual'
 | 
			
		||||
import omitBy from 'lodash/omitBy'
 | 
			
		||||
import { encode, decode } from 'ripple-binary-codec'
 | 
			
		||||
 | 
			
		||||
import { ValidationError } from '../../errors'
 | 
			
		||||
@@ -210,9 +211,9 @@ export function validate(transaction: Record<string, unknown>): void {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (
 | 
			
		||||
    !_.isEqual(
 | 
			
		||||
    !isEqual(
 | 
			
		||||
      decode(encode(tx)),
 | 
			
		||||
      _.omitBy(tx, (value) => value == null),
 | 
			
		||||
      omitBy(tx, (value) => value == null),
 | 
			
		||||
    )
 | 
			
		||||
  ) {
 | 
			
		||||
    throw new ValidationError(`Invalid Transaction: ${tx.TransactionType}`)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import _ from 'lodash'
 | 
			
		||||
import flatMap from 'lodash/flatMap'
 | 
			
		||||
 | 
			
		||||
import type { Client } from '..'
 | 
			
		||||
import { LedgerIndex } from '../models/common'
 | 
			
		||||
@@ -111,7 +111,7 @@ async function getBalances(
 | 
			
		||||
  // combine results
 | 
			
		||||
  await Promise.all([xrpPromise, linesPromise]).then(
 | 
			
		||||
    ([xrpBalance, linesResponses]) => {
 | 
			
		||||
      const accountLinesBalance = _.flatMap(linesResponses, (response) =>
 | 
			
		||||
      const accountLinesBalance = flatMap(linesResponses, (response) =>
 | 
			
		||||
        formatBalances(response.result.lines),
 | 
			
		||||
      )
 | 
			
		||||
      if (xrpBalance !== '') {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,9 @@
 | 
			
		||||
/* eslint-disable max-lines-per-function -- Needs to process orderbooks. */
 | 
			
		||||
import BigNumber from 'bignumber.js'
 | 
			
		||||
import _ from 'lodash'
 | 
			
		||||
import flatMap from 'lodash/flatMap'
 | 
			
		||||
 | 
			
		||||
import type { Client } from '../client'
 | 
			
		||||
import { ValidationError } from '../errors'
 | 
			
		||||
import { LedgerIndex } from '../models/common'
 | 
			
		||||
import { OfferFlags } from '../models/ledger/Offer'
 | 
			
		||||
import {
 | 
			
		||||
@@ -22,6 +23,13 @@ function sortOffers(offers: BookOffer[]): BookOffer[] {
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const getOrderbookOptionsSet = new Set([
 | 
			
		||||
  'limit',
 | 
			
		||||
  'ledger_index',
 | 
			
		||||
  'ledger_hash',
 | 
			
		||||
  'taker',
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Fetch orderbook (buy/sell orders) between two accounts.
 | 
			
		||||
 *
 | 
			
		||||
@@ -40,7 +48,7 @@ function sortOffers(offers: BookOffer[]): BookOffer[] {
 | 
			
		||||
 * the order book. Defaults to 20.
 | 
			
		||||
 * @returns An object containing buy and sell objects.
 | 
			
		||||
 */
 | 
			
		||||
// eslint-disable-next-line max-params -- Once bound to Client, getOrderbook only has 3 parameters.
 | 
			
		||||
// eslint-disable-next-line max-params, complexity -- Once bound to Client, getOrderbook only has 3 parameters.
 | 
			
		||||
async function getOrderbook(
 | 
			
		||||
  this: Client,
 | 
			
		||||
  takerPays: TakerAmount,
 | 
			
		||||
@@ -48,21 +56,60 @@ async function getOrderbook(
 | 
			
		||||
  options: {
 | 
			
		||||
    limit?: number
 | 
			
		||||
    ledger_index?: LedgerIndex
 | 
			
		||||
    ledger_hash?: string
 | 
			
		||||
    taker?: string
 | 
			
		||||
    ledger_hash?: string | null
 | 
			
		||||
    taker?: string | null
 | 
			
		||||
  } = {},
 | 
			
		||||
): Promise<{
 | 
			
		||||
  buy: BookOffer[]
 | 
			
		||||
  sell: BookOffer[]
 | 
			
		||||
}> {
 | 
			
		||||
  Object.keys(options).forEach((key) => {
 | 
			
		||||
    if (!getOrderbookOptionsSet.has(key)) {
 | 
			
		||||
      throw new ValidationError(`Unexpected option: ${key}`, options)
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  if (options.limit && typeof options.limit !== 'number') {
 | 
			
		||||
    throw new ValidationError('limit must be a number', options.limit)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (
 | 
			
		||||
    options.ledger_index &&
 | 
			
		||||
    !(
 | 
			
		||||
      typeof options.ledger_index === 'number' ||
 | 
			
		||||
      (typeof options.ledger_index === 'string' &&
 | 
			
		||||
        ['validated', 'closed', 'current'].includes(options.ledger_index))
 | 
			
		||||
    )
 | 
			
		||||
  ) {
 | 
			
		||||
    throw new ValidationError(
 | 
			
		||||
      'ledger_index must be a number or a string of "validated", "closed", or "current"',
 | 
			
		||||
      options.ledger_index,
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (
 | 
			
		||||
    options.ledger_hash !== undefined &&
 | 
			
		||||
    options.ledger_hash !== null &&
 | 
			
		||||
    typeof options.ledger_hash !== 'string'
 | 
			
		||||
  ) {
 | 
			
		||||
    throw new ValidationError(
 | 
			
		||||
      'ledger_hash must be a string',
 | 
			
		||||
      options.ledger_hash,
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (options.taker !== undefined && typeof options.taker !== 'string') {
 | 
			
		||||
    throw new ValidationError('taker must be a string', options.taker)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const request: BookOffersRequest = {
 | 
			
		||||
    command: 'book_offers',
 | 
			
		||||
    taker_pays: takerPays,
 | 
			
		||||
    taker_gets: takerGets,
 | 
			
		||||
    ledger_index: options.ledger_index ?? 'validated',
 | 
			
		||||
    ledger_hash: options.ledger_hash,
 | 
			
		||||
    ledger_hash: options.ledger_hash === null ? undefined : options.ledger_hash,
 | 
			
		||||
    limit: options.limit ?? DEFAULT_LIMIT,
 | 
			
		||||
    taker: options.taker,
 | 
			
		||||
    taker: options.taker ? options.taker : undefined,
 | 
			
		||||
  }
 | 
			
		||||
  // 2. Make Request
 | 
			
		||||
  const directOfferResults = await this.requestAll(request)
 | 
			
		||||
@@ -70,11 +117,11 @@ async function getOrderbook(
 | 
			
		||||
  request.taker_pays = takerGets
 | 
			
		||||
  const reverseOfferResults = await this.requestAll(request)
 | 
			
		||||
  // 3. Return Formatted Response
 | 
			
		||||
  const directOffers = _.flatMap(
 | 
			
		||||
  const directOffers = flatMap(
 | 
			
		||||
    directOfferResults,
 | 
			
		||||
    (directOfferResult) => directOfferResult.result.offers,
 | 
			
		||||
  )
 | 
			
		||||
  const reverseOffers = _.flatMap(
 | 
			
		||||
  const reverseOffers = flatMap(
 | 
			
		||||
    reverseOfferResults,
 | 
			
		||||
    (reverseOfferResult) => reverseOfferResult.result.offers,
 | 
			
		||||
  )
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
import BigNumber from 'bignumber.js'
 | 
			
		||||
import _ from 'lodash'
 | 
			
		||||
import flatten from 'lodash/flatten'
 | 
			
		||||
import groupBy from 'lodash/groupBy'
 | 
			
		||||
 | 
			
		||||
import { Amount, IssuedCurrencyAmount } from '../models/common'
 | 
			
		||||
import { TransactionMetadata, Node } from '../models/transactions/metadata'
 | 
			
		||||
@@ -63,7 +64,7 @@ function groupByAccount(balanceChanges: BalanceChange[]): Array<{
 | 
			
		||||
  account: string
 | 
			
		||||
  balances: Balance[]
 | 
			
		||||
}> {
 | 
			
		||||
  const grouped = _.groupBy(balanceChanges, (node) => node.account)
 | 
			
		||||
  const grouped = groupBy(balanceChanges, (node) => node.account)
 | 
			
		||||
  return Object.entries(grouped).map(([account, items]) => {
 | 
			
		||||
    return { account, balances: items.map((item) => item.balance) }
 | 
			
		||||
  })
 | 
			
		||||
@@ -186,5 +187,5 @@ export default function getBalanceChanges(
 | 
			
		||||
    }
 | 
			
		||||
    return []
 | 
			
		||||
  })
 | 
			
		||||
  return groupByAccount(_.flatten(quantities))
 | 
			
		||||
  return groupByAccount(flatten(quantities))
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
import binary from 'ripple-binary-codec'
 | 
			
		||||
import keypairs from 'ripple-keypairs'
 | 
			
		||||
import { encodeForSigningClaim } from 'ripple-binary-codec'
 | 
			
		||||
import { sign } from 'ripple-keypairs'
 | 
			
		||||
 | 
			
		||||
import { xrpToDrops } from './xrpConversion'
 | 
			
		||||
 | 
			
		||||
@@ -17,11 +17,11 @@ function signPaymentChannelClaim(
 | 
			
		||||
  amount: string,
 | 
			
		||||
  privateKey: string,
 | 
			
		||||
): string {
 | 
			
		||||
  const signingData = binary.encodeForSigningClaim({
 | 
			
		||||
  const signingData = encodeForSigningClaim({
 | 
			
		||||
    channel,
 | 
			
		||||
    amount: xrpToDrops(amount),
 | 
			
		||||
  })
 | 
			
		||||
  return keypairs.sign(signingData, privateKey)
 | 
			
		||||
  return sign(signingData, privateKey)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default signPaymentChannelClaim
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
import binary from 'ripple-binary-codec'
 | 
			
		||||
import keypairs from 'ripple-keypairs'
 | 
			
		||||
import { encodeForSigningClaim } from 'ripple-binary-codec'
 | 
			
		||||
import { verify } from 'ripple-keypairs'
 | 
			
		||||
 | 
			
		||||
import { xrpToDrops } from './xrpConversion'
 | 
			
		||||
 | 
			
		||||
@@ -20,11 +20,11 @@ function verifyPaymentChannelClaim(
 | 
			
		||||
  signature: string,
 | 
			
		||||
  publicKey: string,
 | 
			
		||||
): boolean {
 | 
			
		||||
  const signingData = binary.encodeForSigningClaim({
 | 
			
		||||
  const signingData = encodeForSigningClaim({
 | 
			
		||||
    channel,
 | 
			
		||||
    amount: xrpToDrops(amount),
 | 
			
		||||
  })
 | 
			
		||||
  return keypairs.verify(signingData, signature, publicKey)
 | 
			
		||||
  return verify(signingData, signature, publicKey)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default verifyPaymentChannelClaim
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
import { assert } from 'chai'
 | 
			
		||||
import ExponentialBackoff from 'xrpl-local/client/ExponentialBackoff'
 | 
			
		||||
 | 
			
		||||
import ExponentialBackoff from '../src/client/ExponentialBackoff'
 | 
			
		||||
 | 
			
		||||
describe('ExponentialBackoff', function () {
 | 
			
		||||
  it('duration() return value starts with the min value', function () {
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user