mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-19 19:55:51 +00:00
Refactor and simplify code (#8)
* Remove dependency on x-address-codec * Version 3.0.0
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- '0.12'
|
||||
- 6
|
||||
- 8
|
||||
- 9
|
||||
script:
|
||||
- npm test --coverage
|
||||
- npm run codecov
|
||||
- npm run lint
|
||||
- yarn compile
|
||||
- yarn test
|
||||
- yarn lint
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# ripple-address-codec [](https://npmjs.org/package/ripple-address-codec) [](https://travis-ci.org/ripple/ripple-address-codec) [](http://codecov.io/github/ripple/ripple-address-codec?branch=master)
|
||||
# ripple-address-codec [](https://npmjs.org/package/ripple-address-codec)
|
||||
|
||||
## API
|
||||
|
||||
@@ -34,66 +34,3 @@
|
||||
112,
|
||||
114 ]
|
||||
```
|
||||
|
||||
## And ?? There's more to the wonderful world than ripple
|
||||
|
||||
We give you the kitchen sink.
|
||||
|
||||
```js
|
||||
> console.log(api)
|
||||
{ Codec: [Function: AddressCodec],
|
||||
codecs:
|
||||
{ bitcoin:
|
||||
{ alphabet: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz',
|
||||
codec: [Object],
|
||||
base: 58 },
|
||||
ripple:
|
||||
{ alphabet: 'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz',
|
||||
codec: [Object],
|
||||
base: 58 },
|
||||
tipple:
|
||||
{ alphabet: 'RPShNAF39wBUDnEGHJKLM4pQrsT7VWXYZ2bcdeCg65jkm8ofqi1tuvaxyz',
|
||||
codec: [Object],
|
||||
base: 58 },
|
||||
stellar:
|
||||
{ alphabet: 'gsphnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCr65jkm8oFqi1tuvAxyz',
|
||||
codec: [Object],
|
||||
base: 58 } },
|
||||
decode: [Function: decode],
|
||||
encode: [Function: encode],
|
||||
decodeEdSeed: [Function],
|
||||
encodeEdSeed: [Function],
|
||||
isValidEdSeed: [Function],
|
||||
decodeSeed: [Function],
|
||||
encodeSeed: [Function],
|
||||
isValidSeed: [Function],
|
||||
decodeAccountID: [Function],
|
||||
encodeAccountID: [Function],
|
||||
isValidAccountID: [Function],
|
||||
decodeAddress: [Function],
|
||||
encodeAddress: [Function],
|
||||
isValidAddress: [Function],
|
||||
decodeNodePublic: [Function],
|
||||
encodeNodePublic: [Function],
|
||||
isValidNodePublic: [Function],
|
||||
decodeNodePrivate: [Function],
|
||||
encodeNodePrivate: [Function],
|
||||
isValidNodePrivate: [Function],
|
||||
decodeK256Seed: [Function],
|
||||
encodeK256Seed: [Function],
|
||||
isValidK256Seed: [Function] }
|
||||
```
|
||||
|
||||
# Decode a bip32 bitcoin public key
|
||||
|
||||
```js
|
||||
var pubVersion = [0x04, 0x88, 0xB2, 0x1E];
|
||||
var options = {version: pubVersion, alphabet: 'bitcoin'};
|
||||
var key = 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6LBpB85b3D2yc8sfvZU521AAwdZafEz7mnzBBsz4wKY5e4cp9LB';
|
||||
var decoded = api.decode(key, options);
|
||||
var reencoded = api.encode(decoded, options);
|
||||
console.log(key);
|
||||
// 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6LBpB85b3D2yc8sfvZU521AAwdZafEz7mnzBBsz4wKY5e4cp9LB'
|
||||
console.log(reencoded);
|
||||
// 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6LBpB85b3D2yc8sfvZU521AAwdZafEz7mnzBBsz4wKY5e4cp9LB'
|
||||
```
|
||||
|
||||
@@ -1,33 +1,32 @@
|
||||
{
|
||||
"name": "ripple-address-codec",
|
||||
"version": "2.0.2",
|
||||
"version": "3.0.0",
|
||||
"description": "encodes/decodes base58 encoded ripple identifiers",
|
||||
"main": "src/index.js",
|
||||
"main": "dist/index.js",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"create-hash": "^1.1.2",
|
||||
"x-address-codec": "^0.7.2"
|
||||
"base-x": "3.0.4",
|
||||
"create-hash": "^1.1.2"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/ripple/ripple-address-codec.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "istanbul test _mocha",
|
||||
"prepublish": "npm test && npm run lint",
|
||||
"codecov": "cat ./coverage/coverage.json | ./node_modules/codecov.io/bin/codecov.io.js",
|
||||
"lint": "if ! [ -f eslintrc ]; then curl -o eslintrc 'https://raw.githubusercontent.com/ripple/javascript-style-guide/master/eslintrc'; fi; eslint -c eslintrc src/*.js test/*.js"
|
||||
"compile": "tsc",
|
||||
"test": "tsc && istanbul test _mocha",
|
||||
"lint": "tslint -p ./"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^10.12.0",
|
||||
"codecov.io": "^0.1.6",
|
||||
"coveralls": "~2.11.4",
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-plugin-no-unused-expressions": "^0.1.0",
|
||||
"istanbul": "~0.3.21",
|
||||
"mocha": "^5.0.5"
|
||||
},
|
||||
"readmeFilename": "README.md",
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
"mocha": "^5.0.5",
|
||||
"tslint": "^5.11.0",
|
||||
"tslint-eslint-rules": "^5.4.0",
|
||||
"typescript": "^3.1.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const createHash = require('create-hash')
|
||||
const apiFactory = require('x-address-codec')
|
||||
|
||||
const NODE_PUBLIC = 28
|
||||
const NODE_PRIVATE = 32
|
||||
const ACCOUNT_ID = 0
|
||||
const FAMILY_SEED = 33
|
||||
const ED25519_SEED = [0x01, 0xE1, 0x4B]
|
||||
|
||||
module.exports = apiFactory({
|
||||
sha256: function(bytes) {
|
||||
return createHash('sha256').update(new Buffer(bytes)).digest()
|
||||
},
|
||||
defaultAlphabet: 'ripple',
|
||||
codecMethods: {
|
||||
EdSeed: {
|
||||
expectedLength: 16,
|
||||
version: ED25519_SEED
|
||||
},
|
||||
Seed: {
|
||||
// TODO: Use a map, not a parallel array
|
||||
versionTypes: ['ed25519', 'secp256k1'],
|
||||
versions: [ED25519_SEED, FAMILY_SEED],
|
||||
expectedLength: 16
|
||||
},
|
||||
AccountID: {version: ACCOUNT_ID, expectedLength: 20},
|
||||
Address: {version: ACCOUNT_ID, expectedLength: 20},
|
||||
NodePublic: {version: NODE_PUBLIC, expectedLength: 33},
|
||||
NodePrivate: {version: NODE_PRIVATE, expectedLength: 32},
|
||||
K256Seed: {version: FAMILY_SEED, expectedLength: 16}}
|
||||
})
|
||||
1
packages/ripple-address-codec/src/index.ts
Normal file
1
packages/ripple-address-codec/src/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './xrp-codec'
|
||||
59
packages/ripple-address-codec/src/utils.ts
Normal file
59
packages/ripple-address-codec/src/utils.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
'use strict'
|
||||
|
||||
function seqEqual(arr1, arr2) {
|
||||
if (arr1.length !== arr2.length) {
|
||||
return false
|
||||
}
|
||||
|
||||
for (let i = 0; i < arr1.length; i++) {
|
||||
if (arr1[i] !== arr2[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
function isSequence(val) {
|
||||
return val.length !== undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates 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], new Buffer([4,5]), new Uint8Array([6, 7]));
|
||||
* [1,2,3,4,5,6,7]
|
||||
*
|
||||
* @return {Array} - 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]
|
||||
}
|
||||
|
||||
args.forEach(function (arg) {
|
||||
if (isSequence(arg)) {
|
||||
for (let j = 0; j < arg.length; j++) {
|
||||
ret.push(arg[j])
|
||||
}
|
||||
} else {
|
||||
ret.push(arg)
|
||||
}
|
||||
})
|
||||
return ret
|
||||
}
|
||||
|
||||
function isSet(o) {
|
||||
return o !== null && o !== undefined
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
seqEqual: seqEqual,
|
||||
concatArgs: concatArgs,
|
||||
isSet: isSet
|
||||
}
|
||||
219
packages/ripple-address-codec/src/xrp-codec.ts
Normal file
219
packages/ripple-address-codec/src/xrp-codec.ts
Normal file
@@ -0,0 +1,219 @@
|
||||
/**
|
||||
* Codec class
|
||||
*/
|
||||
|
||||
const baseCodec = require('base-x')
|
||||
const {seqEqual, concatArgs} = require('.//utils')
|
||||
|
||||
class Codec {
|
||||
sha256: (bytes: Uint8Array) => Buffer
|
||||
alphabet: string
|
||||
codec: any
|
||||
base: number
|
||||
|
||||
constructor(options: {
|
||||
sha256: (bytes: Uint8Array) => Buffer,
|
||||
alphabet: string
|
||||
}) {
|
||||
this.sha256 = options.sha256
|
||||
this.alphabet = options.alphabet
|
||||
this.codec = baseCodec(this.alphabet)
|
||||
this.base = this.alphabet.length
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoder.
|
||||
*
|
||||
* @param bytes Buffer of data to encode.
|
||||
* @param opts Options object including the version bytes and the expected length of the data to encode.
|
||||
*/
|
||||
encode(bytes: Buffer, opts: {
|
||||
versions: number[],
|
||||
expectedLength: number
|
||||
}) {
|
||||
const versions = opts.versions
|
||||
return this.encodeVersioned(bytes, versions, opts.expectedLength)
|
||||
}
|
||||
|
||||
encodeVersioned(bytes: Buffer, versions: number[], expectedLength: number) {
|
||||
if (expectedLength && bytes.length !== expectedLength) {
|
||||
throw new Error('unexpected_payload_length: bytes.length does not match expectedLength')
|
||||
}
|
||||
return this.encodeChecked(concatArgs(versions, bytes))
|
||||
}
|
||||
|
||||
encodeChecked(buffer: Buffer) {
|
||||
const check = this.sha256(this.sha256(buffer)).slice(0, 4)
|
||||
return this.encodeRaw(concatArgs(buffer, check))
|
||||
}
|
||||
|
||||
encodeRaw(bytes: Buffer) {
|
||||
return this.codec.encode(bytes)
|
||||
}
|
||||
|
||||
/**
|
||||
* Decoder.
|
||||
*
|
||||
* @param base58string Base58Check-encoded string to decode.
|
||||
* @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[])[],
|
||||
expectedLength?: number,
|
||||
versionTypes?: ['ed25519', 'secp256k1']
|
||||
} = {}) {
|
||||
const versions = Array.isArray(opts.versions) ? opts.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
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
decodeChecked(base58string: string) {
|
||||
const buffer = this.decodeRaw(base58string)
|
||||
if (buffer.length < 5) {
|
||||
throw new Error('invalid_input_size: decoded data must have length >= 5')
|
||||
}
|
||||
if (!this.verifyCheckSum(buffer)) {
|
||||
throw new Error('checksum_invalid')
|
||||
}
|
||||
return buffer.slice(0, -4)
|
||||
}
|
||||
|
||||
decodeRaw(base58string: string) {
|
||||
return this.codec.decode(base58string)
|
||||
}
|
||||
|
||||
verifyCheckSum(bytes: Buffer) {
|
||||
const computed = this.sha256(this.sha256(bytes.slice(0, -4))).slice(0, 4)
|
||||
const checksum = bytes.slice(-4)
|
||||
return seqEqual(computed, checksum)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* XRP codec
|
||||
*/
|
||||
|
||||
const createHash = require('create-hash')
|
||||
|
||||
const NODE_PUBLIC = 28
|
||||
const ACCOUNT_ID = 0
|
||||
const FAMILY_SEED = 0x21 // 33
|
||||
const ED25519_SEED = [0x01, 0xE1, 0x4B] // [1, 225, 75]
|
||||
|
||||
const codecOptions = {
|
||||
sha256: function(bytes: Uint8Array) {
|
||||
return createHash('sha256').update(Buffer.from(bytes)).digest()
|
||||
},
|
||||
alphabet: 'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz'
|
||||
}
|
||||
|
||||
const codecWithXrpAlphabet = new Codec(codecOptions)
|
||||
|
||||
// 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,
|
||||
|
||||
// for secp256k1, use `FAMILY_SEED`
|
||||
versions: type === 'ed25519' ? ED25519_SEED : [FAMILY_SEED]
|
||||
}
|
||||
|
||||
// prefixes entropy with version bytes
|
||||
return codecWithXrpAlphabet.encode(entropy, opts)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
return codecWithXrpAlphabet.decode(seed, opts)
|
||||
}
|
||||
|
||||
export function encodeAccountID(bytes: Buffer): string {
|
||||
const opts = {versions: [ACCOUNT_ID], expectedLength: 20}
|
||||
return codecWithXrpAlphabet.encode(bytes, opts)
|
||||
}
|
||||
|
||||
export function decodeAccountID(accountId: string): Buffer {
|
||||
const opts = {versions: [ACCOUNT_ID], expectedLength: 20}
|
||||
return codecWithXrpAlphabet.decode(accountId, opts).bytes
|
||||
}
|
||||
|
||||
export function decodeNodePublic(base58string: string): Buffer {
|
||||
const opts = {versions: [NODE_PUBLIC], expectedLength: 33}
|
||||
return codecWithXrpAlphabet.decode(base58string, opts).bytes
|
||||
}
|
||||
|
||||
export function encodeNodePublic(bytes: Buffer): string {
|
||||
const opts = {versions: [NODE_PUBLIC], expectedLength: 33}
|
||||
return codecWithXrpAlphabet.encode(bytes, opts)
|
||||
}
|
||||
|
||||
// Address === AccountID
|
||||
export function isValidAddress(address: string): boolean {
|
||||
try {
|
||||
this.decodeAccountID(address)
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
'use strict'
|
||||
|
||||
const assert = require('assert')
|
||||
const api = require('../')
|
||||
const api = require('../dist')
|
||||
|
||||
function toHex(bytes) {
|
||||
return new Buffer(bytes).toString('hex').toUpperCase()
|
||||
@@ -15,11 +15,11 @@ function toBytes(hex) {
|
||||
|
||||
describe('ripple-address-codec', function() {
|
||||
function makeTest(type, base58, hex) {
|
||||
it('can translate between ' + hex + ' and ' + base58, function() {
|
||||
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, function() {
|
||||
it(`can translate between ${base58} and ${hex} (decode ${type})`, function() {
|
||||
const buf = api['decode' + type](base58)
|
||||
assert.equal(toHex(buf), hex)
|
||||
})
|
||||
@@ -33,13 +33,7 @@ describe('ripple-address-codec', function() {
|
||||
'n9MXXueo837zYH36DvMc13BwHcqtfAWNJY5czWVbp7uYTj7x17TH',
|
||||
'0388E5BA87A000CB807240DF8C848EB0B5FFA5C8E5A521BC8E105C0F0A44217828')
|
||||
|
||||
makeTest('K256Seed', 'sn259rEFXrQrWyx3Q7XneWcwV6dfL',
|
||||
'CF2DE378FBDD7E2EE87D486DFB5A7BFF')
|
||||
|
||||
makeTest('EdSeed', 'sEdTM1uX8pu2do5XvTnutH6HsouMaM2',
|
||||
'4C3A1D213FBDFB14C7C28D609469B341')
|
||||
|
||||
it('can decode arbitray seeds', function() {
|
||||
it('can decode arbitrary seeds', function() {
|
||||
const decoded = api.decodeSeed('sEdTM1uX8pu2do5XvTnutH6HsouMaM2')
|
||||
assert.equal(toHex(decoded.bytes), '4C3A1D213FBDFB14C7C28D609469B341')
|
||||
assert.equal(decoded.type, 'ed25519')
|
||||
|
||||
81
packages/ripple-address-codec/test/xrp-codec-test.js
Normal file
81
packages/ripple-address-codec/test/xrp-codec-test.js
Normal file
@@ -0,0 +1,81 @@
|
||||
/* eslint-disable no-unused-expressions/no-unused-expressions */
|
||||
|
||||
'use strict'
|
||||
|
||||
const assert = require('assert')
|
||||
const api = require('../dist/xrp-codec')
|
||||
|
||||
function toHex(bytes) {
|
||||
return new Buffer(bytes).toString('hex').toUpperCase()
|
||||
}
|
||||
|
||||
function toBytes(hex) {
|
||||
return new Buffer(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')
|
||||
})
|
||||
})
|
||||
})
|
||||
25
packages/ripple-address-codec/tsconfig.json
Normal file
25
packages/ripple-address-codec/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"lib": [
|
||||
"es2017"
|
||||
],
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"strictNullChecks": false,
|
||||
"noImplicitAny": false,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"removeComments": false,
|
||||
"preserveConstEnums": false,
|
||||
"suppressImplicitAnyIndexErrors": false,
|
||||
"sourceMap": true,
|
||||
"skipLibCheck": true,
|
||||
"allowJs": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
]
|
||||
}
|
||||
74
packages/ripple-address-codec/tslint.json
Normal file
74
packages/ripple-address-codec/tslint.json
Normal file
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"extends": [
|
||||
"tslint-eslint-rules"
|
||||
],
|
||||
"rules": {
|
||||
"ban": [true, ["alert"]],
|
||||
"no-arg": true,
|
||||
"no-conditional-assignment": true,
|
||||
"no-console": false,
|
||||
"no-constant-condition": true,
|
||||
"no-control-regex": true,
|
||||
"no-debugger": true,
|
||||
"no-duplicate-case": true,
|
||||
"no-empty": true,
|
||||
"no-empty-character-class": true,
|
||||
"no-eval": true,
|
||||
"no-ex-assign": true,
|
||||
"no-extra-boolean-cast": true,
|
||||
"no-extra-semi": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-inner-declarations": [true, "functions"],
|
||||
"no-invalid-regexp": true,
|
||||
"no-invalid-this": false,
|
||||
"no-irregular-whitespace": true,
|
||||
"ter-no-irregular-whitespace": true,
|
||||
"label-position": true,
|
||||
"indent": [true, "spaces", 2],
|
||||
"linebreak-style": [true, "unix"],
|
||||
"no-multi-spaces": true,
|
||||
"no-consecutive-blank-lines": [true, 2],
|
||||
"no-unused-expression": true,
|
||||
"no-construct": true,
|
||||
"no-duplicate-variable": true,
|
||||
"no-regex-spaces": true,
|
||||
"no-shadowed-variable": true,
|
||||
"ter-no-sparse-arrays": true,
|
||||
"no-trailing-whitespace": true,
|
||||
"no-string-throw": true,
|
||||
"no-unexpected-multiline": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-var-keyword": true,
|
||||
"no-magic-numbers": false,
|
||||
"array-bracket-spacing": [true, "never"],
|
||||
"ter-arrow-body-style": false,
|
||||
"ter-arrow-parens": [true, "as-needed"],
|
||||
"ter-arrow-spacing": true,
|
||||
"block-spacing": true,
|
||||
"brace-style": [true, "1tbs", {"allowSingleLine": true}],
|
||||
"variable-name": false,
|
||||
"trailing-comma": [true, {"multiline": "never", "singleline": "never"}],
|
||||
"cyclomatic-complexity": [false, 11],
|
||||
"curly": [true, "all"],
|
||||
"switch-default": false,
|
||||
"eofline": true,
|
||||
"triple-equals": true,
|
||||
"forin": false,
|
||||
"handle-callback-err": true,
|
||||
"ter-max-len": [true, 120],
|
||||
"new-parens": true,
|
||||
"object-curly-spacing": [true, "never"],
|
||||
"object-literal-shorthand": false,
|
||||
"one-variable-per-declaration": [true, "ignore-for-loop"],
|
||||
"ter-prefer-arrow-callback": false,
|
||||
"prefer-const": true,
|
||||
"object-literal-key-quotes": false,
|
||||
"quotemark": [true, "single"],
|
||||
"radix": true,
|
||||
"semicolon": [true, "never"],
|
||||
"space-in-parens": [true, "never"],
|
||||
"comment-format": [true, "check-space"],
|
||||
"use-isnan": true,
|
||||
"valid-typeof": true
|
||||
}
|
||||
}
|
||||
2085
packages/ripple-address-codec/yarn.lock
Normal file
2085
packages/ripple-address-codec/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user