init
This commit is contained in:
+16
@@ -0,0 +1,16 @@
|
||||
/// <reference types="node" />
|
||||
import { codec, encodeSeed, decodeSeed, encodeAccountID, decodeAccountID, encodeNodePublic, decodeNodePublic, encodeAccountPublic, decodeAccountPublic, isValidClassicAddress } from './xrp-codec';
|
||||
declare function classicAddressToXAddress(classicAddress: string, tag: number | false, test: boolean): string;
|
||||
declare function encodeXAddress(accountId: Buffer, tag: number | false, test: boolean): string;
|
||||
declare function xAddressToClassicAddress(xAddress: string): {
|
||||
classicAddress: string;
|
||||
tag: number | false;
|
||||
test: boolean;
|
||||
};
|
||||
declare function decodeXAddress(xAddress: string): {
|
||||
accountId: Buffer;
|
||||
tag: number | false;
|
||||
test: boolean;
|
||||
};
|
||||
declare function isValidXAddress(xAddress: string): boolean;
|
||||
export { codec, encodeSeed, decodeSeed, encodeAccountID, decodeAccountID, encodeNodePublic, decodeNodePublic, encodeAccountPublic, decodeAccountPublic, isValidClassicAddress, classicAddressToXAddress, encodeXAddress, xAddressToClassicAddress, decodeXAddress, isValidXAddress, };
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isValidXAddress = exports.decodeXAddress = exports.xAddressToClassicAddress = exports.encodeXAddress = exports.classicAddressToXAddress = exports.isValidClassicAddress = exports.decodeAccountPublic = exports.encodeAccountPublic = exports.decodeNodePublic = exports.encodeNodePublic = exports.decodeAccountID = exports.encodeAccountID = exports.decodeSeed = exports.encodeSeed = exports.codec = void 0;
|
||||
const assert = __importStar(require("assert"));
|
||||
const xrp_codec_1 = require("./xrp-codec");
|
||||
Object.defineProperty(exports, "codec", { enumerable: true, get: function () { return xrp_codec_1.codec; } });
|
||||
Object.defineProperty(exports, "encodeSeed", { enumerable: true, get: function () { return xrp_codec_1.encodeSeed; } });
|
||||
Object.defineProperty(exports, "decodeSeed", { enumerable: true, get: function () { return xrp_codec_1.decodeSeed; } });
|
||||
Object.defineProperty(exports, "encodeAccountID", { enumerable: true, get: function () { return xrp_codec_1.encodeAccountID; } });
|
||||
Object.defineProperty(exports, "decodeAccountID", { enumerable: true, get: function () { return xrp_codec_1.decodeAccountID; } });
|
||||
Object.defineProperty(exports, "encodeNodePublic", { enumerable: true, get: function () { return xrp_codec_1.encodeNodePublic; } });
|
||||
Object.defineProperty(exports, "decodeNodePublic", { enumerable: true, get: function () { return xrp_codec_1.decodeNodePublic; } });
|
||||
Object.defineProperty(exports, "encodeAccountPublic", { enumerable: true, get: function () { return xrp_codec_1.encodeAccountPublic; } });
|
||||
Object.defineProperty(exports, "decodeAccountPublic", { enumerable: true, get: function () { return xrp_codec_1.decodeAccountPublic; } });
|
||||
Object.defineProperty(exports, "isValidClassicAddress", { enumerable: true, get: function () { return xrp_codec_1.isValidClassicAddress; } });
|
||||
const PREFIX_BYTES = {
|
||||
// 5, 68
|
||||
main: Buffer.from([0x05, 0x44]),
|
||||
// 4, 147
|
||||
test: Buffer.from([0x04, 0x93]),
|
||||
};
|
||||
const MAX_32_BIT_UNSIGNED_INT = 4294967295;
|
||||
function classicAddressToXAddress(classicAddress, tag, test) {
|
||||
const accountId = (0, xrp_codec_1.decodeAccountID)(classicAddress);
|
||||
return encodeXAddress(accountId, tag, test);
|
||||
}
|
||||
exports.classicAddressToXAddress = classicAddressToXAddress;
|
||||
function encodeXAddress(accountId, tag, test) {
|
||||
if (accountId.length !== 20) {
|
||||
// RIPEMD160 is 160 bits = 20 bytes
|
||||
throw new Error('Account ID must be 20 bytes');
|
||||
}
|
||||
if (tag > MAX_32_BIT_UNSIGNED_INT) {
|
||||
throw new Error('Invalid tag');
|
||||
}
|
||||
const theTag = tag || 0;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Passing null is a common js mistake
|
||||
const flag = tag === false || tag == null ? 0 : 1;
|
||||
/* eslint-disable no-bitwise ---
|
||||
* need to use bitwise operations here */
|
||||
const bytes = Buffer.concat([
|
||||
test ? PREFIX_BYTES.test : PREFIX_BYTES.main,
|
||||
accountId,
|
||||
Buffer.from([
|
||||
// 0x00 if no tag, 0x01 if 32-bit tag
|
||||
flag,
|
||||
// first byte
|
||||
theTag & 0xff,
|
||||
// second byte
|
||||
(theTag >> 8) & 0xff,
|
||||
// third byte
|
||||
(theTag >> 16) & 0xff,
|
||||
// fourth byte
|
||||
(theTag >> 24) & 0xff,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
// four zero bytes (reserved for 64-bit tags)
|
||||
0,
|
||||
]),
|
||||
]);
|
||||
/* eslint-enable no-bitwise */
|
||||
return xrp_codec_1.codec.encodeChecked(bytes);
|
||||
}
|
||||
exports.encodeXAddress = encodeXAddress;
|
||||
function xAddressToClassicAddress(xAddress) {
|
||||
/* eslint-disable @typescript-eslint/naming-convention --
|
||||
* TODO 'test' should be something like 'isTest', do this later
|
||||
*/
|
||||
const { accountId, tag, test } = decodeXAddress(xAddress);
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
const classicAddress = (0, xrp_codec_1.encodeAccountID)(accountId);
|
||||
return {
|
||||
classicAddress,
|
||||
tag,
|
||||
test,
|
||||
};
|
||||
}
|
||||
exports.xAddressToClassicAddress = xAddressToClassicAddress;
|
||||
function decodeXAddress(xAddress) {
|
||||
const decoded = xrp_codec_1.codec.decodeChecked(xAddress);
|
||||
/* eslint-disable @typescript-eslint/naming-convention --
|
||||
* TODO 'test' should be something like 'isTest', do this later
|
||||
*/
|
||||
const test = isBufferForTestAddress(decoded);
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
const accountId = decoded.slice(2, 22);
|
||||
const tag = tagFromBuffer(decoded);
|
||||
return {
|
||||
accountId,
|
||||
tag,
|
||||
test,
|
||||
};
|
||||
}
|
||||
exports.decodeXAddress = decodeXAddress;
|
||||
function isBufferForTestAddress(buf) {
|
||||
const decodedPrefix = buf.slice(0, 2);
|
||||
if (PREFIX_BYTES.main.equals(decodedPrefix)) {
|
||||
return false;
|
||||
}
|
||||
if (PREFIX_BYTES.test.equals(decodedPrefix)) {
|
||||
return true;
|
||||
}
|
||||
throw new Error('Invalid X-address: bad prefix');
|
||||
}
|
||||
function tagFromBuffer(buf) {
|
||||
const flag = buf[22];
|
||||
if (flag >= 2) {
|
||||
// No support for 64-bit tags at this time
|
||||
throw new Error('Unsupported X-address');
|
||||
}
|
||||
if (flag === 1) {
|
||||
// Little-endian to big-endian
|
||||
return buf[23] + buf[24] * 0x100 + buf[25] * 0x10000 + buf[26] * 0x1000000;
|
||||
}
|
||||
assert.strictEqual(flag, 0, 'flag must be zero to indicate no tag');
|
||||
assert.ok(Buffer.from('0000000000000000', 'hex').equals(buf.slice(23, 23 + 8)), 'remaining bytes must be zero');
|
||||
return false;
|
||||
}
|
||||
function isValidXAddress(xAddress) {
|
||||
try {
|
||||
decodeXAddress(xAddress);
|
||||
}
|
||||
catch (_error) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
exports.isValidXAddress = isValidXAddress;
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/// <reference types="node" />
|
||||
type Sequence = number[] | Buffer | Uint8Array;
|
||||
/**
|
||||
* 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 declare function seqEqual(arr1: Sequence, arr2: Sequence): boolean;
|
||||
/**
|
||||
* 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]
|
||||
*
|
||||
* @param args - Concatenate of these args into a single array.
|
||||
* @returns Array of concatenated arguments
|
||||
*/
|
||||
export declare function concatArgs(...args: Array<number | Sequence>): number[];
|
||||
export {};
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.concatArgs = exports.seqEqual = void 0;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
exports.seqEqual = seqEqual;
|
||||
/**
|
||||
* Check whether a value is a sequence (e.g. Array of numbers).
|
||||
*
|
||||
* @param val - The value to check.
|
||||
*/
|
||||
function isSequence(val) {
|
||||
return typeof val !== 'number';
|
||||
}
|
||||
/**
|
||||
* 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]
|
||||
*
|
||||
* @param args - Concatenate of these args into a single array.
|
||||
* @returns Array of concatenated arguments
|
||||
*/
|
||||
function concatArgs(...args) {
|
||||
const ret = [];
|
||||
args.forEach((arg) => {
|
||||
if (isSequence(arg)) {
|
||||
for (const j of arg) {
|
||||
ret.push(j);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret.push(arg);
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
exports.concatArgs = concatArgs;
|
||||
//# sourceMappingURL=utils.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;AAEA;;;;;GAKG;AACH,SAAgB,QAAQ,CAAC,IAAc,EAAE,IAAc;IACrD,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE;QAC/B,OAAO,KAAK,CAAA;KACb;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACpC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE;YACvB,OAAO,KAAK,CAAA;SACb;KACF;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAXD,4BAWC;AAED;;;;GAIG;AACH,SAAS,UAAU,CAAC,GAAsB;IACxC,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAA;AAChC,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,UAAU,CAAC,GAAG,IAA8B;IAC1D,MAAM,GAAG,GAAa,EAAE,CAAA;IAExB,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QACnB,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE;YACnB,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE;gBACnB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;aACZ;SACF;aAAM;YACL,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;SACd;IACH,CAAC,CAAC,CAAA;IACF,OAAO,GAAG,CAAA;AACZ,CAAC;AAbD,gCAaC"}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Codec class
|
||||
*/
|
||||
/// <reference types="node" />
|
||||
declare class Codec {
|
||||
private readonly _sha256;
|
||||
private readonly _alphabet;
|
||||
private readonly _codec;
|
||||
constructor(options: {
|
||||
sha256: (bytes: Uint8Array) => Buffer;
|
||||
alphabet: string;
|
||||
});
|
||||
/**
|
||||
* 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;
|
||||
}): string;
|
||||
/**
|
||||
* 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: Array<number | number[]>;
|
||||
expectedLength?: number;
|
||||
versionTypes?: ['ed25519', 'secp256k1'];
|
||||
}): {
|
||||
version: number[];
|
||||
bytes: Buffer;
|
||||
type: 'ed25519' | 'secp256k1' | null;
|
||||
};
|
||||
encodeChecked(buffer: Buffer): string;
|
||||
decodeChecked(base58string: string): Buffer;
|
||||
private _encodeVersioned;
|
||||
private _encodeRaw;
|
||||
private _decodeRaw;
|
||||
private _verifyCheckSum;
|
||||
}
|
||||
export declare const codec: Codec;
|
||||
export declare function encodeSeed(entropy: Buffer, type: 'ed25519' | 'secp256k1'): string;
|
||||
export declare function decodeSeed(seed: string, opts?: {
|
||||
versionTypes: ['ed25519', 'secp256k1'];
|
||||
versions: Array<number | number[]>;
|
||||
expectedLength: number;
|
||||
}): {
|
||||
version: number[];
|
||||
bytes: Buffer;
|
||||
type: 'ed25519' | 'secp256k1' | null;
|
||||
};
|
||||
export declare function encodeAccountID(bytes: Buffer): string;
|
||||
export declare const encodeAddress: typeof encodeAccountID;
|
||||
export declare function decodeAccountID(accountId: string): Buffer;
|
||||
export declare const decodeAddress: typeof decodeAccountID;
|
||||
export declare function decodeNodePublic(base58string: string): Buffer;
|
||||
export declare function encodeNodePublic(bytes: Buffer): string;
|
||||
export declare function encodeAccountPublic(bytes: Buffer): string;
|
||||
export declare function decodeAccountPublic(base58string: string): Buffer;
|
||||
export declare function isValidClassicAddress(address: string): boolean;
|
||||
export {};
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
"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);
|
||||
}
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
/**
|
||||
* 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) {
|
||||
var _a;
|
||||
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 = (_a = opts.expectedLength) !== null && _a !== void 0 ? _a : withoutSum.length - versionLengthGuess;
|
||||
const versionBytes = withoutSum.slice(0, -payloadLength);
|
||||
const payload = withoutSum.slice(-payloadLength);
|
||||
for (let i = 0; i < versions.length; i++) {
|
||||
/* eslint-disable @typescript-eslint/consistent-type-assertions --
|
||||
* TODO refactor */
|
||||
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,
|
||||
};
|
||||
}
|
||||
/* eslint-enable @typescript-eslint/consistent-type-assertions */
|
||||
}
|
||||
throw new Error('version_invalid: version bytes do not match any of the provided version(s)');
|
||||
}
|
||||
encodeChecked(buffer) {
|
||||
const check = this._sha256(this._sha256(buffer)).slice(0, 4);
|
||||
return this._encodeRaw(Buffer.from((0, utils_1.concatArgs)(buffer, check)));
|
||||
}
|
||||
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);
|
||||
}
|
||||
_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)));
|
||||
}
|
||||
_encodeRaw(bytes) {
|
||||
return this._codec.encode(bytes);
|
||||
}
|
||||
/* eslint-enable max-lines-per-function */
|
||||
_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
|
||||
+1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user