123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- "use strict";
- /**
- * Codec class
- */
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.isValidClassicAddress = exports.decodeAccountPublic = exports.encodeAccountPublic = exports.encodeNodePublic = exports.decodeNodePublic = exports.decodeAddress = exports.decodeAccountID = exports.encodeAddress = exports.encodeAccountID = exports.decodeSeed = exports.encodeSeed = exports.codec = void 0;
- const baseCodec = require("base-x");
- const createHash = require("create-hash");
- const utils_1 = require("./utils");
- class Codec {
- constructor(options) {
- 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, opts) {
- const versions = opts.versions;
- return this.encodeVersioned(bytes, versions, opts.expectedLength);
- }
- encodeVersioned(bytes, versions, expectedLength) {
- if (expectedLength && bytes.length !== expectedLength) {
- throw new Error('unexpected_payload_length: bytes.length does not match expectedLength.' +
- ' Ensure that the bytes are a Buffer.');
- }
- return this.encodeChecked(Buffer.from((0, utils_1.concatArgs)(versions, bytes)));
- }
- encodeChecked(buffer) {
- const check = this.sha256(this.sha256(buffer)).slice(0, 4);
- return this.encodeRaw(Buffer.from((0, utils_1.concatArgs)(buffer, check)));
- }
- encodeRaw(bytes) {
- 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.
- */
- /* eslint-disable max-lines-per-function --
- * TODO refactor */
- decode(base58string, opts) {
- const versions = opts.versions;
- const types = opts.versionTypes;
- 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].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 = Array.isArray(versions[i])
- ? versions[i]
- : [versions[i]];
- if ((0, utils_1.seqEqual)(versionBytes, version)) {
- return {
- version,
- bytes: payload,
- type: types ? types[i] : null,
- };
- }
- }
- throw new Error('version_invalid: version bytes do not match any of the provided version(s)');
- }
- /* eslint-enable max-lines-per-function */
- decodeChecked(base58string) {
- 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) {
- return this.codec.decode(base58string);
- }
- verifyCheckSum(bytes) {
- const computed = this.sha256(this.sha256(bytes.slice(0, -4))).slice(0, 4);
- const checksum = bytes.slice(-4);
- return (0, utils_1.seqEqual)(computed, checksum);
- }
- }
- /**
- * XRP codec
- */
- // base58 encodings: https://xrpl.org/base58-encodings.html
- // Account address (20 bytes)
- const ACCOUNT_ID = 0;
- // Account public key (33 bytes)
- const ACCOUNT_PUBLIC_KEY = 0x23;
- // 33; Seed value (for secret keys) (16 bytes)
- const FAMILY_SEED = 0x21;
- // 28; Validation public key (33 bytes)
- const NODE_PUBLIC = 0x1c;
- // [1, 225, 75]
- const ED25519_SEED = [0x01, 0xe1, 0x4b];
- const codecOptions = {
- sha256(bytes) {
- return createHash('sha256').update(Buffer.from(bytes)).digest();
- },
- alphabet: 'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz',
- };
- const codecWithXrpAlphabet = new Codec(codecOptions);
- exports.codec = codecWithXrpAlphabet;
- // entropy is a Buffer of size 16
- // type is 'ed25519' or 'secp256k1'
- function encodeSeed(entropy, type) {
- if (entropy.length !== 16) {
- throw new Error('entropy must have length 16');
- }
- 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);
- }
- exports.encodeSeed = encodeSeed;
- function decodeSeed(seed, opts = {
- versionTypes: ['ed25519', 'secp256k1'],
- versions: [ED25519_SEED, FAMILY_SEED],
- expectedLength: 16,
- }) {
- return codecWithXrpAlphabet.decode(seed, opts);
- }
- exports.decodeSeed = decodeSeed;
- function encodeAccountID(bytes) {
- const opts = { versions: [ACCOUNT_ID], expectedLength: 20 };
- return codecWithXrpAlphabet.encode(bytes, opts);
- }
- exports.encodeAccountID = encodeAccountID;
- /* eslint-disable import/no-unused-modules ---
- * unclear why this is aliased but we should keep it in case someone else is
- * importing it with the aliased name */
- exports.encodeAddress = encodeAccountID;
- /* eslint-enable import/no-unused-modules */
- function decodeAccountID(accountId) {
- const opts = { versions: [ACCOUNT_ID], expectedLength: 20 };
- return codecWithXrpAlphabet.decode(accountId, opts).bytes;
- }
- exports.decodeAccountID = decodeAccountID;
- /* eslint-disable import/no-unused-modules ---
- * unclear why this is aliased but we should keep it in case someone else is
- * importing it with the aliased name */
- exports.decodeAddress = decodeAccountID;
- /* eslint-enable import/no-unused-modules */
- function decodeNodePublic(base58string) {
- const opts = { versions: [NODE_PUBLIC], expectedLength: 33 };
- return codecWithXrpAlphabet.decode(base58string, opts).bytes;
- }
- exports.decodeNodePublic = decodeNodePublic;
- function encodeNodePublic(bytes) {
- const opts = { versions: [NODE_PUBLIC], expectedLength: 33 };
- return codecWithXrpAlphabet.encode(bytes, opts);
- }
- exports.encodeNodePublic = encodeNodePublic;
- function encodeAccountPublic(bytes) {
- const opts = { versions: [ACCOUNT_PUBLIC_KEY], expectedLength: 33 };
- return codecWithXrpAlphabet.encode(bytes, opts);
- }
- exports.encodeAccountPublic = encodeAccountPublic;
- function decodeAccountPublic(base58string) {
- const opts = { versions: [ACCOUNT_PUBLIC_KEY], expectedLength: 33 };
- return codecWithXrpAlphabet.decode(base58string, opts).bytes;
- }
- exports.decodeAccountPublic = decodeAccountPublic;
- function isValidClassicAddress(address) {
- try {
- decodeAccountID(address);
- }
- catch (_error) {
- return false;
- }
- return true;
- }
- exports.isValidClassicAddress = isValidClassicAddress;
- //# sourceMappingURL=xrp-codec.js.map
|