diff --git a/packages/ripple-address-codec/index.js b/packages/ripple-address-codec/index.js index 36e66a3e..c9b73030 100644 --- a/packages/ripple-address-codec/index.js +++ b/packages/ripple-address-codec/index.js @@ -1,10 +1,22 @@ var hashjs = require('hash.js'); var apiFactory = require('x-address-codec'); -var VER_NODE_PUBLIC = 28; -var VER_NODE_PRIVATE = 32; -var VER_ACCOUNT_ID = 0; -var VER_FAMILY_SEED = 33; +var NODE_PUBLIC = 28; +var NODE_PRIVATE = 32; +var ACCOUNT_ID = 0; +var FAMILY_SEED = 33; +var ED25519_SEED = [0x01, 0xE1, 0x4B]; + +var VERSIONS = { + EdSeed : { + expectedLength: 16, + version: ED25519_SEED + }, + AccountID: {version: ACCOUNT_ID }, + NodePublic: {version: NODE_PUBLIC }, + NodePrivate: {version: NODE_PRIVATE }, + K256Seed : {version: FAMILY_SEED } +}; function sha256(bytes) { return hashjs.sha256().update(bytes).digest(); @@ -12,19 +24,25 @@ function sha256(bytes) { var api = apiFactory({sha256: sha256, defaultAlphabet: 'ripple'}); -function addVersion(name, version) { - function add(operation, func) { +function addVersion(name, args) { + function add(operation) { api[operation + name] = function(string) { - return api[operation](string, {version: version}); + return api[operation](string, args); } } - add('decode'); add('encode'); + add('decode'); } -addVersion('Seed', VER_FAMILY_SEED); -addVersion('AccountID', VER_ACCOUNT_ID); -addVersion('NodePublic', VER_NODE_PUBLIC); -addVersion('NodePrivate', VER_NODE_PRIVATE); +api.decodeSeed = function(seed) { + var args = {versions: [ED25519_SEED, FAMILY_SEED], expectedLength: 16}; + var decoded = api.decode(seed, args); + decoded.type = decoded.versionIx === 0 ? 'EdSeed' : 'K256Seed'; + return decoded; +}; + +for (var k in VERSIONS) { + addVersion(k, VERSIONS[k]); +} module.exports = api; \ No newline at end of file diff --git a/packages/ripple-address-codec/package.json b/packages/ripple-address-codec/package.json index bb1a6b10..c1d4588c 100644 --- a/packages/ripple-address-codec/package.json +++ b/packages/ripple-address-codec/package.json @@ -1,11 +1,17 @@ { "name": "ripple-address-codec", - "version": "1.0.3", + "version": "1.1.0", "description": "encodes/decodes base58 encoded ripple identifiers", "main": "index.js", "license": "ISC", "dependencies": { "hash.js": "^1.0.3", - "x-address-codec" : "^0.1.3" + "x-address-codec": "^0.2.0" + }, + "scripts": { + "test": "mocha test/*-test.js" + }, + "devDependencies": { + "mocha": "^2.2.5" } } diff --git a/packages/ripple-address-codec/test/codec-test.js b/packages/ripple-address-codec/test/codec-test.js new file mode 100644 index 00000000..50e3ba44 --- /dev/null +++ b/packages/ripple-address-codec/test/codec-test.js @@ -0,0 +1,42 @@ +var assert = require('assert'); +var api = require('../'); + +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() { + function makeTest(type, base58, hex, opts) { + opts = opts || {}; + + it('can translate between ' + hex + ' and ' + base58, function() { + var actual = api['encode' + type](toBytes(hex)); + var buf = api['decode' + type](base58); + assert.equal(actual, base58); + assert.equal(toHex(buf), hex); + }); + } + + makeTest('AccountID', 'rJrRMgiRgrU6hDF4pgu5DXQdWyPbY35ErN', + 'BA8E78626EE42C41B46D46C3048DF3A1C3C87072'); + + makeTest('K256Seed', 'sn259rEFXrQrWyx3Q7XneWcwV6dfL', + 'CF2DE378FBDD7E2EE87D486DFB5A7BFF'); + + makeTest('EdSeed', 'sEdTM1uX8pu2do5XvTnutH6HsouMaM2', + '4C3A1D213FBDFB14C7C28D609469B341'); + + it('can decode arbitray seeds', function() { + var decoded = api.decodeSeed('sEdTM1uX8pu2do5XvTnutH6HsouMaM2'); + assert.equal(toHex(decoded.bytes), '4C3A1D213FBDFB14C7C28D609469B341'); + assert.equal(decoded.type, 'EdSeed'); + + var decoded = api.decodeSeed('sn259rEFXrQrWyx3Q7XneWcwV6dfL'); + assert.equal(toHex(decoded.bytes), 'CF2DE378FBDD7E2EE87D486DFB5A7BFF'); + assert.equal(decoded.type, 'K256Seed'); + }); +});