mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-13 09:05:49 +00:00
Migrate unit tests to TypeScript (#12)
* Add type information for utils * Enable "strictNullChecks" and "noImplicitAny" * Replace mocha with jest * Fix #11 * Refactor and add tests for 100% code coverage * Mention --coverage option in README * Travis: remove node v9 and add node v10 and v12 * Improvements per review by @keefertaylor Node.js v6 throws "Invalid hex string" if the hex string has an odd number of characters (two hex characters per byte means the string should have an even length). This changed in later versions of Node.js.
This commit is contained in:
@@ -2,7 +2,8 @@ language: node_js
|
||||
node_js:
|
||||
- 6
|
||||
- 8
|
||||
- 9
|
||||
- 10
|
||||
- 12
|
||||
script:
|
||||
- yarn compile
|
||||
- yarn test
|
||||
|
||||
5
packages/ripple-address-codec/.vscode/settings.json
vendored
Normal file
5
packages/ripple-address-codec/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"secp256k1"
|
||||
]
|
||||
}
|
||||
@@ -34,3 +34,19 @@
|
||||
112,
|
||||
114 ]
|
||||
```
|
||||
|
||||
## Tests
|
||||
|
||||
Run unit tests with:
|
||||
|
||||
yarn test
|
||||
|
||||
Use `--watch` to run in watch mode, so that when you modify the tests, they are automatically re-run:
|
||||
|
||||
yarn test --watch
|
||||
|
||||
Use `--coverage` to generate and display code coverage information:
|
||||
|
||||
yarn test --coverage
|
||||
|
||||
This tells jest to output code coverage info in the `./coverage` directory, in addition to showing it on the command line.
|
||||
|
||||
8
packages/ripple-address-codec/jest.config.js
Normal file
8
packages/ripple-address-codec/jest.config.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
"roots": [
|
||||
"<rootDir>/src"
|
||||
],
|
||||
"transform": {
|
||||
"^.+\\.tsx?$": "ts-jest"
|
||||
},
|
||||
}
|
||||
491
packages/ripple-address-codec/package-lock.json
generated
491
packages/ripple-address-codec/package-lock.json
generated
@@ -1,491 +0,0 @@
|
||||
{
|
||||
"name": "ripple-address-codec",
|
||||
"version": "3.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": {
|
||||
"version": "7.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz",
|
||||
"integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/highlight": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@babel/highlight": {
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz",
|
||||
"integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.0.0",
|
||||
"esutils": "^2.0.2",
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "10.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.0.tgz",
|
||||
"integrity": "sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ==",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"argparse": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||
"dev": true
|
||||
},
|
||||
"base-x": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.4.tgz",
|
||||
"integrity": "sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA==",
|
||||
"requires": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"browser-stdout": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
|
||||
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
|
||||
"dev": true
|
||||
},
|
||||
"builtin-modules": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
|
||||
"integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.15.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
|
||||
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"dev": true
|
||||
},
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"diff": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
|
||||
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
|
||||
"dev": true
|
||||
},
|
||||
"doctrine": {
|
||||
"version": "0.7.2",
|
||||
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz",
|
||||
"integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esutils": "^1.1.6",
|
||||
"isarray": "0.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"esutils": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz",
|
||||
"integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true
|
||||
},
|
||||
"esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||
"dev": true
|
||||
},
|
||||
"esutils": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
||||
"dev": true
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||
"dev": true
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
||||
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"growl": {
|
||||
"version": "1.10.5",
|
||||
"resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
|
||||
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
|
||||
"dev": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||
"dev": true
|
||||
},
|
||||
"hash-base": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
|
||||
"integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
|
||||
"requires": {
|
||||
"inherits": "^2.0.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"he": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
|
||||
"integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
|
||||
"dev": true
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"isarray": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
|
||||
"dev": true
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.13.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
||||
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
||||
"dev": true
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
},
|
||||
"mocha": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz",
|
||||
"integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"browser-stdout": "1.3.1",
|
||||
"commander": "2.15.1",
|
||||
"debug": "3.1.0",
|
||||
"diff": "3.5.0",
|
||||
"escape-string-regexp": "1.0.5",
|
||||
"glob": "7.1.2",
|
||||
"growl": "1.10.5",
|
||||
"he": "1.1.1",
|
||||
"minimatch": "3.0.4",
|
||||
"mkdirp": "0.5.1",
|
||||
"supports-color": "5.4.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
||||
"dev": true
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||
"dev": true
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
|
||||
"dev": true
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
|
||||
"integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-parse": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"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.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
|
||||
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||
"dev": true
|
||||
},
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
|
||||
"integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
|
||||
"integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==",
|
||||
"dev": true
|
||||
},
|
||||
"tslint": {
|
||||
"version": "5.19.0",
|
||||
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.19.0.tgz",
|
||||
"integrity": "sha512-1LwwtBxfRJZnUvoS9c0uj8XQtAnyhWr9KlNvDIdB+oXyT+VpsOAaEhEgKi1HrZ8rq0ki/AAnbGSv4KM6/AfVZw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"builtin-modules": "^1.1.1",
|
||||
"chalk": "^2.3.0",
|
||||
"commander": "^2.12.1",
|
||||
"diff": "^3.2.0",
|
||||
"glob": "^7.1.1",
|
||||
"js-yaml": "^3.13.1",
|
||||
"minimatch": "^3.0.4",
|
||||
"mkdirp": "^0.5.1",
|
||||
"resolve": "^1.3.2",
|
||||
"semver": "^5.3.0",
|
||||
"tslib": "^1.8.0",
|
||||
"tsutils": "^2.29.0"
|
||||
}
|
||||
},
|
||||
"tslint-eslint-rules": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tslint-eslint-rules/-/tslint-eslint-rules-5.4.0.tgz",
|
||||
"integrity": "sha512-WlSXE+J2vY/VPgIcqQuijMQiel+UtmXS+4nvK4ZzlDiqBfXse8FAvkNnTcYhnQyOTW5KFM+uRRGXxYhFpuBc6w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"doctrine": "0.7.2",
|
||||
"tslib": "1.9.0",
|
||||
"tsutils": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz",
|
||||
"integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==",
|
||||
"dev": true
|
||||
},
|
||||
"tsutils": {
|
||||
"version": "3.17.1",
|
||||
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz",
|
||||
"integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^1.8.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tsutils": {
|
||||
"version": "2.29.0",
|
||||
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
|
||||
"integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^1.8.1"
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.3.tgz",
|
||||
"integrity": "sha512-+81MUSyX+BaSo+u2RbozuQk/UWx6hfG0a5gHu4ANEM4sU96XbuIyAB+rWBW1u70c6a5QuZfuYICn3s2UjuHUpA==",
|
||||
"dev": true
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
"types": "dist/index.d.ts",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@types/base-x": "^3.0.0",
|
||||
"base-x": "3.0.4",
|
||||
"create-hash": "^1.1.2"
|
||||
},
|
||||
@@ -20,12 +21,14 @@
|
||||
"prepublish": "tsc",
|
||||
"scripts": {
|
||||
"compile": "tsc",
|
||||
"test": "tsc && tslint -p ./ && mocha",
|
||||
"test": "jest",
|
||||
"lint": "tslint -p ./"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^24.0.18",
|
||||
"@types/node": "^10.12.0",
|
||||
"mocha": "^5.0.5",
|
||||
"jest": "^24.9.0",
|
||||
"ts-jest": "^24.1.0",
|
||||
"tslint": "^5.19.0",
|
||||
"tslint-eslint-rules": "^5.4.0",
|
||||
"typescript": "^3.1.3"
|
||||
|
||||
40
packages/ripple-address-codec/src/utils.test.ts
Normal file
40
packages/ripple-address-codec/src/utils.test.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import {seqEqual, concatArgs} from './utils'
|
||||
|
||||
test('two sequences are equal', () => {
|
||||
expect(seqEqual([1, 2, 3], [1, 2, 3])).toBe(true)
|
||||
})
|
||||
|
||||
test('elements must be in the same order', () => {
|
||||
expect(seqEqual([3, 2, 1], [1, 2, 3])).toBe(false)
|
||||
})
|
||||
|
||||
test('sequences do not need to be the same type', () => {
|
||||
expect(seqEqual(Buffer.from([1, 2, 3]), [1, 2, 3])).toBe(true)
|
||||
expect(seqEqual(Buffer.from([1, 2, 3]), new Uint8Array([1, 2, 3]))).toBe(true)
|
||||
})
|
||||
|
||||
test('sequences with a single element', () => {
|
||||
expect(seqEqual(Buffer.from([1]), [1])).toBe(true)
|
||||
expect(seqEqual(Buffer.from([1]), new Uint8Array([1]))).toBe(true)
|
||||
})
|
||||
|
||||
test('empty sequences', () => {
|
||||
expect(seqEqual(Buffer.from([]), [])).toBe(true)
|
||||
expect(seqEqual(Buffer.from([]), new Uint8Array([]))).toBe(true)
|
||||
})
|
||||
|
||||
test('plain numbers are concatenated', () => {
|
||||
expect(concatArgs(10, 20, 30, 40)).toStrictEqual([10, 20, 30, 40])
|
||||
})
|
||||
|
||||
test('a variety of values are concatenated', () => {
|
||||
expect(concatArgs(1, [2, 3], Buffer.from([4,5]), new Uint8Array([6, 7]))).toStrictEqual([1,2,3,4,5,6,7])
|
||||
})
|
||||
|
||||
test('a single value is returned as an array', () => {
|
||||
expect(concatArgs(Buffer.from([7]))).toStrictEqual([7])
|
||||
})
|
||||
|
||||
test('no arguments returns an empty array', () => {
|
||||
expect(concatArgs()).toStrictEqual([])
|
||||
})
|
||||
@@ -1,6 +1,12 @@
|
||||
'use strict'
|
||||
type Sequence = number[] | Buffer | Uint8Array
|
||||
|
||||
function seqEqual(arr1, arr2) {
|
||||
/**
|
||||
* Check whether two sequences (e.g. arrays of numbers) are equal.
|
||||
*
|
||||
* @param arr1 One of the arrays to compare.
|
||||
* @param arr2 The other array to compare.
|
||||
*/
|
||||
export function seqEqual(arr1: Sequence, arr2: Sequence): boolean {
|
||||
if (arr1.length !== arr2.length) {
|
||||
return false
|
||||
}
|
||||
@@ -13,28 +19,27 @@ function seqEqual(arr1, arr2) {
|
||||
return true
|
||||
}
|
||||
|
||||
function isSequence(val) {
|
||||
return val.length !== undefined
|
||||
/**
|
||||
* Check whether a value is a sequence (e.g. array of numbers).
|
||||
*
|
||||
* @param val The value to check.
|
||||
*/
|
||||
function isSequence(val: Sequence | number): val is Sequence {
|
||||
return (val as Sequence).length !== undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates all `arguments` into a single array. Each argument can be either
|
||||
* Concatenate all `arguments` into a single array. Each argument can be either
|
||||
* a single element or a sequence, which has a `length` property and supports
|
||||
* element retrieval via sequence[ix].
|
||||
*
|
||||
* > concatArgs(1, [2, 3], Buffer.from([4,5]), new Uint8Array([6, 7]));
|
||||
* [1,2,3,4,5,6,7]
|
||||
*
|
||||
* @return {Array} - concatenated arguments
|
||||
* @returns {number[]} Array of concatenated arguments
|
||||
*/
|
||||
function concatArgs() {
|
||||
const ret = []
|
||||
const _len = arguments.length
|
||||
const args = Array(_len)
|
||||
|
||||
for (let _key = 0; _key < _len; _key++) {
|
||||
args[_key] = arguments[_key]
|
||||
}
|
||||
export function concatArgs(...args: (number | Sequence)[]): number[] {
|
||||
const ret: number[] = []
|
||||
|
||||
args.forEach(function (arg) {
|
||||
if (isSequence(arg)) {
|
||||
@@ -47,13 +52,3 @@ function concatArgs() {
|
||||
})
|
||||
return ret
|
||||
}
|
||||
|
||||
function isSet(o) {
|
||||
return o !== null && o !== undefined
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
seqEqual: seqEqual,
|
||||
concatArgs: concatArgs,
|
||||
isSet: isSet
|
||||
}
|
||||
|
||||
242
packages/ripple-address-codec/src/xrp-codec.test.ts
Normal file
242
packages/ripple-address-codec/src/xrp-codec.test.ts
Normal file
@@ -0,0 +1,242 @@
|
||||
import * as api from './xrp-codec'
|
||||
|
||||
function toHex(bytes: Buffer) {
|
||||
return Buffer.from(bytes).toString('hex').toUpperCase()
|
||||
}
|
||||
|
||||
function toBytes(hex: string) {
|
||||
return Buffer.from(hex, 'hex').toJSON().data
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a test case for encoding data and a test case for decoding data.
|
||||
*
|
||||
* @param encoder Encoder function to test
|
||||
* @param decoder Decoder function to test
|
||||
* @param base58 Base58-encoded string to decode
|
||||
* @param hex Hexadecimal representation of expected decoded data
|
||||
*/
|
||||
function makeEncodeDecodeTest(encoder: Function, decoder: Function, base58: string, hex: string) {
|
||||
test(`can translate between ${hex} and ${base58}`, function() {
|
||||
const actual = encoder(toBytes(hex))
|
||||
expect(actual).toBe(base58)
|
||||
})
|
||||
test(`can translate between ${base58} and ${hex})`, function() {
|
||||
const buf = decoder(base58)
|
||||
expect(toHex(buf)).toBe(hex)
|
||||
})
|
||||
}
|
||||
|
||||
makeEncodeDecodeTest(api.encodeAccountID, api.decodeAccountID, 'rJrRMgiRgrU6hDF4pgu5DXQdWyPbY35ErN',
|
||||
'BA8E78626EE42C41B46D46C3048DF3A1C3C87072')
|
||||
|
||||
makeEncodeDecodeTest(api.encodeNodePublic, api.decodeNodePublic,
|
||||
'n9MXXueo837zYH36DvMc13BwHcqtfAWNJY5czWVbp7uYTj7x17TH',
|
||||
'0388E5BA87A000CB807240DF8C848EB0B5FFA5C8E5A521BC8E105C0F0A44217828')
|
||||
|
||||
test('can decode arbitrary seeds', function() {
|
||||
const decoded = api.decodeSeed('sEdTM1uX8pu2do5XvTnutH6HsouMaM2')
|
||||
expect(toHex(decoded.bytes)).toBe('4C3A1D213FBDFB14C7C28D609469B341')
|
||||
expect(decoded.type).toBe('ed25519')
|
||||
|
||||
const decoded2 = api.decodeSeed('sn259rEFXrQrWyx3Q7XneWcwV6dfL')
|
||||
expect(toHex(decoded2.bytes)).toBe('CF2DE378FBDD7E2EE87D486DFB5A7BFF')
|
||||
expect(decoded2.type).toBe('secp256k1')
|
||||
})
|
||||
|
||||
test('can pass a type as second arg to encodeSeed', function() {
|
||||
const edSeed = 'sEdTM1uX8pu2do5XvTnutH6HsouMaM2'
|
||||
const decoded = api.decodeSeed(edSeed)
|
||||
const type = 'ed25519'
|
||||
expect(toHex(decoded.bytes)).toBe('4C3A1D213FBDFB14C7C28D609469B341')
|
||||
expect(decoded.type).toBe(type)
|
||||
expect(api.encodeSeed(decoded.bytes, type)).toBe(edSeed)
|
||||
})
|
||||
|
||||
test('isValidAddress - secp256k1 address valid', function() {
|
||||
expect(api.isValidAddress('rU6K7V3Po4snVhBBaU29sesqs2qTQJWDw1')).toBe(true)
|
||||
})
|
||||
|
||||
test('isValidAddress - ed25519 address valid', function() {
|
||||
expect(api.isValidAddress('rLUEXYuLiQptky37CqLcm9USQpPiz5rkpD')).toBe(true)
|
||||
})
|
||||
|
||||
test('isValidAddress - invalid', function() {
|
||||
expect(api.isValidAddress('rU6K7V3Po4snVhBBaU29sesqs2qTQJWDw2')).toBe(false)
|
||||
})
|
||||
|
||||
test('isValidAddress - empty', function() {
|
||||
expect(api.isValidAddress('')).toBe(false)
|
||||
})
|
||||
|
||||
describe('encodeSeed', function() {
|
||||
|
||||
it('encodes a secp256k1 seed', function() {
|
||||
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')
|
||||
expect(result).toBe('sp6JS7f14BuwFY8Mw6bTtLKWauoUs')
|
||||
})
|
||||
|
||||
it('encodes high secp256k1 seed', function() {
|
||||
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')
|
||||
expect(result).toBe('sEdTM1uX8pu2do5XvTnutH6HsouMaM2')
|
||||
})
|
||||
|
||||
it('encodes low ed25519 seed', function() {
|
||||
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')
|
||||
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')
|
||||
}).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')
|
||||
}).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')
|
||||
expect(decoded.type).toBe('ed25519')
|
||||
})
|
||||
|
||||
it('can decode a secp256k1 seed', function() {
|
||||
const decoded = api.decodeSeed('sn259rEFXrQrWyx3Q7XneWcwV6dfL')
|
||||
expect(toHex(decoded.bytes)).toBe('CF2DE378FBDD7E2EE87D486DFB5A7BFF')
|
||||
expect(decoded.type).toBe('secp256k1')
|
||||
})
|
||||
})
|
||||
|
||||
describe('encodeAccountID', function() {
|
||||
|
||||
it('can encode an AccountID', function() {
|
||||
const encoded = api.encodeAccountID(Buffer.from('BA8E78626EE42C41B46D46C3048DF3A1C3C87072', 'hex'))
|
||||
expect(encoded).toBe('rJrRMgiRgrU6hDF4pgu5DXQdWyPbY35ErN')
|
||||
})
|
||||
|
||||
test('unexpected length should throw', function() {
|
||||
expect(() => {
|
||||
api.encodeAccountID(Buffer.from('ABCDEF', 'hex'))
|
||||
}).toThrow(
|
||||
'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')
|
||||
})
|
||||
})
|
||||
|
||||
test('encodes 123456789 with version byte of 0', () => {
|
||||
expect(api.codec.encode(Buffer.from('123456789'), {
|
||||
versions: [0],
|
||||
expectedLength: 9
|
||||
})).toBe('rnaC7gW34M77Kneb78s')
|
||||
})
|
||||
|
||||
test('multiple versions with no expected length should throw', () => {
|
||||
expect(() => {
|
||||
api.codec.decode('rnaC7gW34M77Kneb78s', {
|
||||
versions: [0, 1]
|
||||
})
|
||||
}).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]
|
||||
})
|
||||
}).toThrow('invalid_input_size: decoded data must have length >= 5')
|
||||
})
|
||||
|
||||
test('attempting to decode data with unexpected version should throw', () => {
|
||||
expect(() => {
|
||||
api.codec.decode('rnaC7gW34M77Kneb78s', {
|
||||
versions: [2]
|
||||
})
|
||||
}).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]
|
||||
})
|
||||
}).toThrow('checksum_invalid')
|
||||
})
|
||||
|
||||
test('empty payload should throw', () => {
|
||||
expect(() => {
|
||||
api.codec.decode('', {
|
||||
versions: [0, 1]
|
||||
})
|
||||
}).toThrow('invalid_input_size: decoded data must have length >= 5')
|
||||
})
|
||||
|
||||
test('decode data', () => {
|
||||
expect(api.codec.decode('rnaC7gW34M77Kneb78s', {
|
||||
versions: [0]
|
||||
})).toStrictEqual({
|
||||
version: [0],
|
||||
bytes: Buffer.from('123456789'),
|
||||
type: null
|
||||
})
|
||||
})
|
||||
|
||||
test('decode data with expected length', function() {
|
||||
expect(api.codec.decode('rnaC7gW34M77Kneb78s', {
|
||||
versions: [0],
|
||||
expectedLength: 9
|
||||
})
|
||||
).toStrictEqual({
|
||||
version: [0],
|
||||
bytes: Buffer.from('123456789'),
|
||||
type: null
|
||||
})
|
||||
})
|
||||
|
||||
test('decode data with wrong expected length should throw', function() {
|
||||
expect(() => {
|
||||
api.codec.decode('rnaC7gW34M77Kneb78s', {
|
||||
versions: [0],
|
||||
expectedLength: 8
|
||||
})
|
||||
}).toThrow(
|
||||
'version_invalid: version bytes do not match any of the provided version(s)'
|
||||
)
|
||||
expect(() => {
|
||||
api.codec.decode('rnaC7gW34M77Kneb78s', {
|
||||
versions: [0],
|
||||
expectedLength: 10
|
||||
})
|
||||
}).toThrow(
|
||||
'version_invalid: version bytes do not match any of the provided version(s)'
|
||||
)
|
||||
})
|
||||
@@ -2,8 +2,8 @@
|
||||
* Codec class
|
||||
*/
|
||||
|
||||
const baseCodec = require('base-x')
|
||||
const {seqEqual, concatArgs} = require('./utils')
|
||||
import * as baseCodec from 'base-x'
|
||||
import {seqEqual, concatArgs} from './utils'
|
||||
|
||||
class Codec {
|
||||
sha256: (bytes: Uint8Array) => Buffer
|
||||
@@ -39,12 +39,12 @@ class Codec {
|
||||
if (expectedLength && bytes.length !== expectedLength) {
|
||||
throw new Error('unexpected_payload_length: bytes.length does not match expectedLength')
|
||||
}
|
||||
return this.encodeChecked(concatArgs(versions, bytes))
|
||||
return this.encodeChecked(Buffer.from(concatArgs(versions, bytes)))
|
||||
}
|
||||
|
||||
encodeChecked(buffer: Buffer) {
|
||||
const check = this.sha256(this.sha256(buffer)).slice(0, 4)
|
||||
return this.encodeRaw(concatArgs(buffer, check))
|
||||
return this.encodeRaw(Buffer.from(concatArgs(buffer, check)))
|
||||
}
|
||||
|
||||
encodeRaw(bytes: Buffer) {
|
||||
@@ -58,57 +58,39 @@ class Codec {
|
||||
* @param opts Options object including the version byte(s) and the expected length of the data after decoding.
|
||||
*/
|
||||
decode(base58string: string, opts: {
|
||||
versions?: (number | number[])[],
|
||||
versions: (number | number[])[],
|
||||
expectedLength?: number,
|
||||
versionTypes?: ['ed25519', 'secp256k1']
|
||||
} = {}) {
|
||||
const versions = Array.isArray(opts.versions) ? opts.versions : [opts.versions]
|
||||
}): {
|
||||
version: number[],
|
||||
bytes: Buffer,
|
||||
type: string | null
|
||||
} {
|
||||
const versions = opts.versions
|
||||
const types = opts.versionTypes
|
||||
if (versions) {
|
||||
const withoutSum = this.decodeChecked(base58string)
|
||||
const ret: {
|
||||
version: number[] | null,
|
||||
bytes: Buffer | null,
|
||||
type: string | null // for seeds, 'ed25519' | 'secp256k1'
|
||||
} = {
|
||||
version: null,
|
||||
bytes: null,
|
||||
type: null
|
||||
}
|
||||
if (versions.length > 1 && !opts.expectedLength) {
|
||||
throw new Error('expectedLength is required because there are >= 2 possible versions')
|
||||
}
|
||||
const versionLengthGuess = typeof versions[0] === 'number' ? 1 : (versions[0] as number[]).length
|
||||
const payloadLength = opts.expectedLength || withoutSum.length - versionLengthGuess
|
||||
const versionBytes = withoutSum.slice(0, -payloadLength)
|
||||
const payload = withoutSum.slice(-payloadLength)
|
||||
|
||||
let foundVersion = false
|
||||
for (let i = 0; i < versions.length; i++) {
|
||||
const version: number[] = Array.isArray(versions[i]) ? versions[i] as number[] : [versions[i] as number]
|
||||
if (seqEqual(versionBytes, version)) {
|
||||
ret.version = version
|
||||
ret.bytes = payload
|
||||
if (types) {
|
||||
ret.type = types[i]
|
||||
}
|
||||
foundVersion = true
|
||||
const withoutSum = this.decodeChecked(base58string)
|
||||
|
||||
if (versions.length > 1 && !opts.expectedLength) {
|
||||
throw new Error('expectedLength is required because there are >= 2 possible versions')
|
||||
}
|
||||
const versionLengthGuess = typeof versions[0] === 'number' ? 1 : (versions[0] as number[]).length
|
||||
const payloadLength = opts.expectedLength || withoutSum.length - versionLengthGuess
|
||||
const versionBytes = withoutSum.slice(0, -payloadLength)
|
||||
const payload = withoutSum.slice(-payloadLength)
|
||||
|
||||
for (let i = 0; i < versions.length; i++) {
|
||||
const version: number[] = Array.isArray(versions[i]) ? versions[i] as number[] : [versions[i] as number]
|
||||
if (seqEqual(versionBytes, version)) {
|
||||
return {
|
||||
version,
|
||||
bytes: payload,
|
||||
type: types ? types[i] : null
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundVersion) {
|
||||
throw new Error('version_invalid: version bytes do not match any of the provided version(s)')
|
||||
}
|
||||
|
||||
if (opts.expectedLength && ret.bytes.length !== opts.expectedLength) {
|
||||
throw new Error('unexpected_payload_length: payload length does not match expectedLength')
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// Assume that base58string is 'checked'
|
||||
return this.decodeChecked(base58string)
|
||||
throw new Error('version_invalid: version bytes do not match any of the provided version(s)')
|
||||
}
|
||||
|
||||
decodeChecked(base58string: string) {
|
||||
@@ -153,15 +135,14 @@ const codecOptions = {
|
||||
|
||||
const codecWithXrpAlphabet = new Codec(codecOptions)
|
||||
|
||||
export const codec = codecWithXrpAlphabet
|
||||
|
||||
// entropy is a Buffer of size 16
|
||||
// type is 'ed25519' or 'secp256k1'
|
||||
export function encodeSeed(entropy: Buffer, type: 'ed25519' | 'secp256k1'): string {
|
||||
if (entropy.length !== 16) {
|
||||
throw new Error('entropy must have length 16')
|
||||
}
|
||||
if (type !== 'ed25519' && type !== 'secp256k1') {
|
||||
throw new Error('type must be ed25519 or secp256k1')
|
||||
}
|
||||
const opts = {
|
||||
expectedLength: 16,
|
||||
|
||||
@@ -174,17 +155,14 @@ export function encodeSeed(entropy: Buffer, type: 'ed25519' | 'secp256k1'): stri
|
||||
}
|
||||
|
||||
export function decodeSeed(seed: string, opts: {
|
||||
versionTypes?: ['ed25519', 'secp256k1'],
|
||||
versions?: (number | number[])[]
|
||||
expectedLength?: number
|
||||
} = {}) {
|
||||
if (!opts.versionTypes || !opts.versions) {
|
||||
opts.versionTypes = ['ed25519', 'secp256k1']
|
||||
opts.versions = [ED25519_SEED, FAMILY_SEED]
|
||||
}
|
||||
if (!opts.expectedLength) {
|
||||
opts.expectedLength = 16
|
||||
}
|
||||
versionTypes: ['ed25519', 'secp256k1'],
|
||||
versions: (number | number[])[]
|
||||
expectedLength: number
|
||||
} = {
|
||||
versionTypes: ['ed25519', 'secp256k1'],
|
||||
versions: [ED25519_SEED, FAMILY_SEED],
|
||||
expectedLength: 16
|
||||
}) {
|
||||
return codecWithXrpAlphabet.decode(seed, opts)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
const assert = require('assert')
|
||||
const api = require('../dist')
|
||||
|
||||
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() {
|
||||
function makeTest(type, base58, hex) {
|
||||
it(`can translate between ${hex} and ${base58} (encode ${type})`, function() {
|
||||
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)
|
||||
assert.equal(toHex(buf), hex)
|
||||
})
|
||||
}
|
||||
|
||||
makeTest('AccountID', 'rJrRMgiRgrU6hDF4pgu5DXQdWyPbY35ErN',
|
||||
'BA8E78626EE42C41B46D46C3048DF3A1C3C87072')
|
||||
|
||||
makeTest(
|
||||
'NodePublic',
|
||||
'n9MXXueo837zYH36DvMc13BwHcqtfAWNJY5czWVbp7uYTj7x17TH',
|
||||
'0388E5BA87A000CB807240DF8C848EB0B5FFA5C8E5A521BC8E105C0F0A44217828')
|
||||
|
||||
it('can decode arbitrary seeds', function() {
|
||||
const decoded = api.decodeSeed('sEdTM1uX8pu2do5XvTnutH6HsouMaM2')
|
||||
assert.equal(toHex(decoded.bytes), '4C3A1D213FBDFB14C7C28D609469B341')
|
||||
assert.equal(decoded.type, 'ed25519')
|
||||
|
||||
const decoded2 = api.decodeSeed('sn259rEFXrQrWyx3Q7XneWcwV6dfL')
|
||||
assert.equal(toHex(decoded2.bytes), 'CF2DE378FBDD7E2EE87D486DFB5A7BFF')
|
||||
assert.equal(decoded2.type, 'secp256k1')
|
||||
})
|
||||
|
||||
it('can pass a type as second arg to encodeSeed', function() {
|
||||
const edSeed = 'sEdTM1uX8pu2do5XvTnutH6HsouMaM2'
|
||||
const decoded = api.decodeSeed(edSeed)
|
||||
assert.equal(toHex(decoded.bytes), '4C3A1D213FBDFB14C7C28D609469B341')
|
||||
assert.equal(decoded.type, 'ed25519')
|
||||
assert.equal(api.encodeSeed(decoded.bytes, decoded.type), edSeed)
|
||||
})
|
||||
|
||||
it('isValidAddress - secp256k1 address valid', function() {
|
||||
assert(api.isValidAddress('rU6K7V3Po4snVhBBaU29sesqs2qTQJWDw1'))
|
||||
})
|
||||
it('isValidAddress - ed25519 address valid', function() {
|
||||
assert(api.isValidAddress('rLUEXYuLiQptky37CqLcm9USQpPiz5rkpD'))
|
||||
})
|
||||
it('isValidAddress - invalid', function() {
|
||||
assert(!api.isValidAddress('rU6K7V3Po4snVhBBaU29sesqs2qTQJWDw2'))
|
||||
})
|
||||
it('isValidAddress - empty', function() {
|
||||
assert(!api.isValidAddress(''))
|
||||
})
|
||||
|
||||
})
|
||||
@@ -1,77 +0,0 @@
|
||||
const assert = require('assert')
|
||||
const api = require('../dist/xrp-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')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -8,8 +8,6 @@
|
||||
"rootDir": "src",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"strictNullChecks": false,
|
||||
"noImplicitAny": false,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"removeComments": false,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user