@scure/base
Version:
Secure, audited & 0-dep implementation of base64, bech32, base58, base32 & base16
704 lines • 24.4 kB
JavaScript
/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */
function isBytes(a) {
return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
}
/** Asserts something is Uint8Array. */
function abytes(b) {
if (!isBytes(b))
throw new Error('Uint8Array expected');
}
function isArrayOf(isString, arr) {
if (!Array.isArray(arr))
return false;
if (arr.length === 0)
return true;
if (isString) {
return arr.every((item) => typeof item === 'string');
}
else {
return arr.every((item) => Number.isSafeInteger(item));
}
}
function afn(input) {
if (typeof input !== 'function')
throw new Error('function expected');
return true;
}
function astr(label, input) {
if (typeof input !== 'string')
throw new Error(`${label}: string expected`);
return true;
}
function anumber(n) {
if (!Number.isSafeInteger(n))
throw new Error(`invalid integer: ${n}`);
}
function aArr(input) {
if (!Array.isArray(input))
throw new Error('array expected');
}
function astrArr(label, input) {
if (!isArrayOf(true, input))
throw new Error(`${label}: array of strings expected`);
}
function anumArr(label, input) {
if (!isArrayOf(false, input))
throw new Error(`${label}: array of numbers expected`);
}
/**
* @__NO_SIDE_EFFECTS__
*/
function chain(...args) {
const id = (a) => a;
// Wrap call in closure so JIT can inline calls
const wrap = (a, b) => (c) => a(b(c));
// Construct chain of args[-1].encode(args[-2].encode([...]))
const encode = args.map((x) => x.encode).reduceRight(wrap, id);
// Construct chain of args[0].decode(args[1].decode(...))
const decode = args.map((x) => x.decode).reduce(wrap, id);
return { encode, decode };
}
/**
* Encodes integer radix representation to array of strings using alphabet and back.
* Could also be array of strings.
* @__NO_SIDE_EFFECTS__
*/
function alphabet(letters) {
// mapping 1 to "b"
const lettersA = typeof letters === 'string' ? letters.split('') : letters;
const len = lettersA.length;
astrArr('alphabet', lettersA);
// mapping "b" to 1
const indexes = new Map(lettersA.map((l, i) => [l, i]));
return {
encode: (digits) => {
aArr(digits);
return digits.map((i) => {
if (!Number.isSafeInteger(i) || i < 0 || i >= len)
throw new Error(`alphabet.encode: digit index outside alphabet "${i}". Allowed: ${letters}`);
return lettersA[i];
});
},
decode: (input) => {
aArr(input);
return input.map((letter) => {
astr('alphabet.decode', letter);
const i = indexes.get(letter);
if (i === undefined)
throw new Error(`Unknown letter: "${letter}". Allowed: ${letters}`);
return i;
});
},
};
}
/**
* @__NO_SIDE_EFFECTS__
*/
function join(separator = '') {
astr('join', separator);
return {
encode: (from) => {
astrArr('join.decode', from);
return from.join(separator);
},
decode: (to) => {
astr('join.decode', to);
return to.split(separator);
},
};
}
/**
* Pad strings array so it has integer number of bits
* @__NO_SIDE_EFFECTS__
*/
function padding(bits, chr = '=') {
anumber(bits);
astr('padding', chr);
return {
encode(data) {
astrArr('padding.encode', data);
while ((data.length * bits) % 8)
data.push(chr);
return data;
},
decode(input) {
astrArr('padding.decode', input);
let end = input.length;
if ((end * bits) % 8)
throw new Error('padding: invalid, string should have whole number of bytes');
for (; end > 0 && input[end - 1] === chr; end--) {
const last = end - 1;
const byte = last * bits;
if (byte % 8 === 0)
throw new Error('padding: invalid, string has too much padding');
}
return input.slice(0, end);
},
};
}
/**
* @__NO_SIDE_EFFECTS__
*/
function normalize(fn) {
afn(fn);
return { encode: (from) => from, decode: (to) => fn(to) };
}
/**
* Slow: O(n^2) time complexity
*/
function convertRadix(data, from, to) {
// base 1 is impossible
if (from < 2)
throw new Error(`convertRadix: invalid from=${from}, base cannot be less than 2`);
if (to < 2)
throw new Error(`convertRadix: invalid to=${to}, base cannot be less than 2`);
aArr(data);
if (!data.length)
return [];
let pos = 0;
const res = [];
const digits = Array.from(data, (d) => {
anumber(d);
if (d < 0 || d >= from)
throw new Error(`invalid integer: ${d}`);
return d;
});
const dlen = digits.length;
while (true) {
let carry = 0;
let done = true;
for (let i = pos; i < dlen; i++) {
const digit = digits[i];
const fromCarry = from * carry;
const digitBase = fromCarry + digit;
if (!Number.isSafeInteger(digitBase) ||
fromCarry / from !== carry ||
digitBase - digit !== fromCarry) {
throw new Error('convertRadix: carry overflow');
}
const div = digitBase / to;
carry = digitBase % to;
const rounded = Math.floor(div);
digits[i] = rounded;
if (!Number.isSafeInteger(rounded) || rounded * to + carry !== digitBase)
throw new Error('convertRadix: carry overflow');
if (!done)
continue;
else if (!rounded)
pos = i;
else
done = false;
}
res.push(carry);
if (done)
break;
}
for (let i = 0; i < data.length - 1 && data[i] === 0; i++)
res.push(0);
return res.reverse();
}
const gcd = (a, b) => (b === 0 ? a : gcd(b, a % b));
const radix2carry = /* @__NO_SIDE_EFFECTS__ */ (from, to) => from + (to - gcd(from, to));
const powers = /* @__PURE__ */ (() => {
let res = [];
for (let i = 0; i < 40; i++)
res.push(2 ** i);
return res;
})();
/**
* Implemented with numbers, because BigInt is 5x slower
*/
function convertRadix2(data, from, to, padding) {
aArr(data);
if (from <= 0 || from > 32)
throw new Error(`convertRadix2: wrong from=${from}`);
if (to <= 0 || to > 32)
throw new Error(`convertRadix2: wrong to=${to}`);
if (radix2carry(from, to) > 32) {
throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${radix2carry(from, to)}`);
}
let carry = 0;
let pos = 0; // bitwise position in current element
const max = powers[from];
const mask = powers[to] - 1;
const res = [];
for (const n of data) {
anumber(n);
if (n >= max)
throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
carry = (carry << from) | n;
if (pos + from > 32)
throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
pos += from;
for (; pos >= to; pos -= to)
res.push(((carry >> (pos - to)) & mask) >>> 0);
const pow = powers[pos];
if (pow === undefined)
throw new Error('invalid carry');
carry &= pow - 1; // clean carry, otherwise it will cause overflow
}
carry = (carry << (to - pos)) & mask;
if (!padding && pos >= from)
throw new Error('Excess padding');
if (!padding && carry > 0)
throw new Error(`Non-zero padding: ${carry}`);
if (padding && pos > 0)
res.push(carry >>> 0);
return res;
}
/**
* @__NO_SIDE_EFFECTS__
*/
function radix(num) {
anumber(num);
const _256 = 2 ** 8;
return {
encode: (bytes) => {
if (!isBytes(bytes))
throw new Error('radix.encode input should be Uint8Array');
return convertRadix(Array.from(bytes), _256, num);
},
decode: (digits) => {
anumArr('radix.decode', digits);
return Uint8Array.from(convertRadix(digits, num, _256));
},
};
}
/**
* If both bases are power of same number (like `2**8 <-> 2**64`),
* there is a linear algorithm. For now we have implementation for power-of-two bases only.
* @__NO_SIDE_EFFECTS__
*/
function radix2(bits, revPadding = false) {
anumber(bits);
if (bits <= 0 || bits > 32)
throw new Error('radix2: bits should be in (0..32]');
if (radix2carry(8, bits) > 32 || radix2carry(bits, 8) > 32)
throw new Error('radix2: carry overflow');
return {
encode: (bytes) => {
if (!isBytes(bytes))
throw new Error('radix2.encode input should be Uint8Array');
return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
},
decode: (digits) => {
anumArr('radix2.decode', digits);
return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
},
};
}
function unsafeWrapper(fn) {
afn(fn);
return function (...args) {
try {
return fn.apply(null, args);
}
catch (e) { }
};
}
function checksum(len, fn) {
anumber(len);
afn(fn);
return {
encode(data) {
if (!isBytes(data))
throw new Error('checksum.encode: input should be Uint8Array');
const sum = fn(data).slice(0, len);
const res = new Uint8Array(data.length + len);
res.set(data);
res.set(sum, data.length);
return res;
},
decode(data) {
if (!isBytes(data))
throw new Error('checksum.decode: input should be Uint8Array');
const payload = data.slice(0, -len);
const oldChecksum = data.slice(-len);
const newChecksum = fn(payload).slice(0, len);
for (let i = 0; i < len; i++)
if (newChecksum[i] !== oldChecksum[i])
throw new Error('Invalid checksum');
return payload;
},
};
}
// prettier-ignore
export const utils = {
alphabet, chain, checksum, convertRadix, convertRadix2, radix, radix2, join, padding,
};
// RFC 4648 aka RFC 3548
// ---------------------
/**
* base16 encoding from RFC 4648.
* @example
* ```js
* base16.encode(Uint8Array.from([0x12, 0xab]));
* // => '12AB'
* ```
*/
export const base16 = chain(radix2(4), alphabet('0123456789ABCDEF'), join(''));
/**
* base32 encoding from RFC 4648. Has padding.
* Use `base32nopad` for unpadded version.
* Also check out `base32hex`, `base32hexnopad`, `base32crockford`.
* @example
* ```js
* base32.encode(Uint8Array.from([0x12, 0xab]));
* // => 'CKVQ===='
* base32.decode('CKVQ====');
* // => Uint8Array.from([0x12, 0xab])
* ```
*/
export const base32 = chain(radix2(5), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'), padding(5), join(''));
/**
* base32 encoding from RFC 4648. No padding.
* Use `base32` for padded version.
* Also check out `base32hex`, `base32hexnopad`, `base32crockford`.
* @example
* ```js
* base32nopad.encode(Uint8Array.from([0x12, 0xab]));
* // => 'CKVQ'
* base32nopad.decode('CKVQ');
* // => Uint8Array.from([0x12, 0xab])
* ```
*/
export const base32nopad = chain(radix2(5), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'), join(''));
/**
* base32 encoding from RFC 4648. Padded. Compared to ordinary `base32`, slightly different alphabet.
* Use `base32hexnopad` for unpadded version.
* @example
* ```js
* base32hex.encode(Uint8Array.from([0x12, 0xab]));
* // => '2ALG===='
* base32hex.decode('2ALG====');
* // => Uint8Array.from([0x12, 0xab])
* ```
*/
export const base32hex = chain(radix2(5), alphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV'), padding(5), join(''));
/**
* base32 encoding from RFC 4648. No padding. Compared to ordinary `base32`, slightly different alphabet.
* Use `base32hex` for padded version.
* @example
* ```js
* base32hexnopad.encode(Uint8Array.from([0x12, 0xab]));
* // => '2ALG'
* base32hexnopad.decode('2ALG');
* // => Uint8Array.from([0x12, 0xab])
* ```
*/
export const base32hexnopad = chain(radix2(5), alphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV'), join(''));
/**
* base32 encoding from RFC 4648. Doug Crockford's version.
* https://www.crockford.com/base32.html
* @example
* ```js
* base32crockford.encode(Uint8Array.from([0x12, 0xab]));
* // => '2ANG'
* base32crockford.decode('2ANG');
* // => Uint8Array.from([0x12, 0xab])
* ```
*/
export const base32crockford = chain(radix2(5), alphabet('0123456789ABCDEFGHJKMNPQRSTVWXYZ'), join(''), normalize((s) => s.toUpperCase().replace(/O/g, '0').replace(/[IL]/g, '1')));
// Built-in base64 conversion https://caniuse.com/mdn-javascript_builtins_uint8array_frombase64
// prettier-ignore
const hasBase64Builtin = /* @__PURE__ */ (() => typeof Uint8Array.from([]).toBase64 === 'function' &&
typeof Uint8Array.fromBase64 === 'function')();
const decodeBase64Builtin = (s, isUrl) => {
astr('base64', s);
const re = isUrl ? /^[A-Za-z0-9=_-]+$/ : /^[A-Za-z0-9=+/]+$/;
const alphabet = isUrl ? 'base64url' : 'base64';
if (s.length > 0 && !re.test(s))
throw new Error('invalid base64');
return Uint8Array.fromBase64(s, { alphabet, lastChunkHandling: 'strict' });
};
/**
* base64 from RFC 4648. Padded.
* Use `base64nopad` for unpadded version.
* Also check out `base64url`, `base64urlnopad`.
* Falls back to built-in function, when available.
* @example
* ```js
* base64.encode(Uint8Array.from([0x12, 0xab]));
* // => 'Eqs='
* base64.decode('Eqs=');
* // => Uint8Array.from([0x12, 0xab])
* ```
*/
// prettier-ignore
export const base64 = hasBase64Builtin ? {
encode(b) { abytes(b); return b.toBase64(); },
decode(s) { return decodeBase64Builtin(s, false); },
} : chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'), padding(6), join(''));
/**
* base64 from RFC 4648. No padding.
* Use `base64` for padded version.
* @example
* ```js
* base64nopad.encode(Uint8Array.from([0x12, 0xab]));
* // => 'Eqs'
* base64nopad.decode('Eqs');
* // => Uint8Array.from([0x12, 0xab])
* ```
*/
export const base64nopad = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'), join(''));
/**
* base64 from RFC 4648, using URL-safe alphabet. Padded.
* Use `base64urlnopad` for unpadded version.
* Falls back to built-in function, when available.
* @example
* ```js
* base64url.encode(Uint8Array.from([0x12, 0xab]));
* // => 'Eqs='
* base64url.decode('Eqs=');
* // => Uint8Array.from([0x12, 0xab])
* ```
*/
// prettier-ignore
export const base64url = hasBase64Builtin ? {
encode(b) { abytes(b); return b.toBase64({ alphabet: 'base64url' }); },
decode(s) { return decodeBase64Builtin(s, true); },
} : chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'), padding(6), join(''));
/**
* base64 from RFC 4648, using URL-safe alphabet. No padding.
* Use `base64url` for padded version.
* @example
* ```js
* base64urlnopad.encode(Uint8Array.from([0x12, 0xab]));
* // => 'Eqs'
* base64urlnopad.decode('Eqs');
* // => Uint8Array.from([0x12, 0xab])
* ```
*/
export const base64urlnopad = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'), join(''));
// base58 code
// -----------
const genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => chain(radix(58), alphabet(abc), join(''));
/**
* base58: base64 without ambigous characters +, /, 0, O, I, l.
* Quadratic (O(n^2)) - so, can't be used on large inputs.
* @example
* ```js
* base58.decode('01abcdef');
* // => '3UhJW'
* ```
*/
export const base58 = genBase58('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');
/**
* base58: flickr version. Check out `base58`.
*/
export const base58flickr = genBase58('123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ');
/**
* base58: XRP version. Check out `base58`.
*/
export const base58xrp = genBase58('rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz');
// Data len (index) -> encoded block len
const XMR_BLOCK_LEN = [0, 2, 3, 5, 6, 7, 9, 10, 11];
/**
* base58: XMR version. Check out `base58`.
* Done in 8-byte blocks (which equals 11 chars in decoding). Last (non-full) block padded with '1' to size in XMR_BLOCK_LEN.
* Block encoding significantly reduces quadratic complexity of base58.
*/
export const base58xmr = {
encode(data) {
let res = '';
for (let i = 0; i < data.length; i += 8) {
const block = data.subarray(i, i + 8);
res += base58.encode(block).padStart(XMR_BLOCK_LEN[block.length], '1');
}
return res;
},
decode(str) {
let res = [];
for (let i = 0; i < str.length; i += 11) {
const slice = str.slice(i, i + 11);
const blockLen = XMR_BLOCK_LEN.indexOf(slice.length);
const block = base58.decode(slice);
for (let j = 0; j < block.length - blockLen; j++) {
if (block[j] !== 0)
throw new Error('base58xmr: wrong padding');
}
res = res.concat(Array.from(block.slice(block.length - blockLen)));
}
return Uint8Array.from(res);
},
};
/**
* Method, which creates base58check encoder.
* Requires function, calculating sha256.
*/
export const createBase58check = (sha256) => chain(checksum(4, (data) => sha256(sha256(data))), base58);
/**
* Use `createBase58check` instead.
* @deprecated
*/
export const base58check = createBase58check;
const BECH_ALPHABET = chain(alphabet('qpzry9x8gf2tvdw0s3jn54khce6mua7l'), join(''));
const POLYMOD_GENERATORS = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
function bech32Polymod(pre) {
const b = pre >> 25;
let chk = (pre & 0x1ffffff) << 5;
for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {
if (((b >> i) & 1) === 1)
chk ^= POLYMOD_GENERATORS[i];
}
return chk;
}
function bechChecksum(prefix, words, encodingConst = 1) {
const len = prefix.length;
let chk = 1;
for (let i = 0; i < len; i++) {
const c = prefix.charCodeAt(i);
if (c < 33 || c > 126)
throw new Error(`Invalid prefix (${prefix})`);
chk = bech32Polymod(chk) ^ (c >> 5);
}
chk = bech32Polymod(chk);
for (let i = 0; i < len; i++)
chk = bech32Polymod(chk) ^ (prefix.charCodeAt(i) & 0x1f);
for (let v of words)
chk = bech32Polymod(chk) ^ v;
for (let i = 0; i < 6; i++)
chk = bech32Polymod(chk);
chk ^= encodingConst;
return BECH_ALPHABET.encode(convertRadix2([chk % powers[30]], 30, 5, false));
}
/**
* @__NO_SIDE_EFFECTS__
*/
function genBech32(encoding) {
const ENCODING_CONST = encoding === 'bech32' ? 1 : 0x2bc830a3;
const _words = radix2(5);
const fromWords = _words.decode;
const toWords = _words.encode;
const fromWordsUnsafe = unsafeWrapper(fromWords);
function encode(prefix, words, limit = 90) {
astr('bech32.encode prefix', prefix);
if (isBytes(words))
words = Array.from(words);
anumArr('bech32.encode', words);
const plen = prefix.length;
if (plen === 0)
throw new TypeError(`Invalid prefix length ${plen}`);
const actualLength = plen + 7 + words.length;
if (limit !== false && actualLength > limit)
throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);
const lowered = prefix.toLowerCase();
const sum = bechChecksum(lowered, words, ENCODING_CONST);
return `${lowered}1${BECH_ALPHABET.encode(words)}${sum}`;
}
function decode(str, limit = 90) {
astr('bech32.decode input', str);
const slen = str.length;
if (slen < 8 || (limit !== false && slen > limit))
throw new TypeError(`invalid string length: ${slen} (${str}). Expected (8..${limit})`);
// don't allow mixed case
const lowered = str.toLowerCase();
if (str !== lowered && str !== str.toUpperCase())
throw new Error(`String must be lowercase or uppercase`);
const sepIndex = lowered.lastIndexOf('1');
if (sepIndex === 0 || sepIndex === -1)
throw new Error(`Letter "1" must be present between prefix and data only`);
const prefix = lowered.slice(0, sepIndex);
const data = lowered.slice(sepIndex + 1);
if (data.length < 6)
throw new Error('Data must be at least 6 characters long');
const words = BECH_ALPHABET.decode(data).slice(0, -6);
const sum = bechChecksum(prefix, words, ENCODING_CONST);
if (!data.endsWith(sum))
throw new Error(`Invalid checksum in ${str}: expected "${sum}"`);
return { prefix, words };
}
const decodeUnsafe = unsafeWrapper(decode);
function decodeToBytes(str) {
const { prefix, words } = decode(str, false);
return { prefix, words, bytes: fromWords(words) };
}
function encodeFromBytes(prefix, bytes) {
return encode(prefix, toWords(bytes));
}
return {
encode,
decode,
encodeFromBytes,
decodeToBytes,
decodeUnsafe,
fromWords,
fromWordsUnsafe,
toWords,
};
}
/**
* bech32 from BIP 173. Operates on words.
* For high-level, check out scure-btc-signer:
* https://github.com/paulmillr/scure-btc-signer.
*/
export const bech32 = genBech32('bech32');
/**
* bech32m from BIP 350. Operates on words.
* It was to mitigate `bech32` weaknesses.
* For high-level, check out scure-btc-signer:
* https://github.com/paulmillr/scure-btc-signer.
*/
export const bech32m = genBech32('bech32m');
/**
* UTF-8-to-byte decoder. Uses built-in TextDecoder / TextEncoder.
* @example
* ```js
* const b = utf8.decode("hey"); // => new Uint8Array([ 104, 101, 121 ])
* const str = utf8.encode(b); // "hey"
* ```
*/
export const utf8 = {
encode: (data) => new TextDecoder().decode(data),
decode: (str) => new TextEncoder().encode(str),
};
// Built-in hex conversion https://caniuse.com/mdn-javascript_builtins_uint8array_fromhex
// prettier-ignore
const hasHexBuiltin = /* @__PURE__ */ (() => typeof Uint8Array.from([]).toHex === 'function' &&
typeof Uint8Array.fromHex === 'function')();
// prettier-ignore
const hexBuiltin = {
encode(data) { abytes(data); return data.toHex(); },
decode(s) { astr('hex', s); return Uint8Array.fromHex(s); },
};
/**
* hex string decoder. Uses built-in function, when available.
* @example
* ```js
* const b = hex.decode("0102ff"); // => new Uint8Array([ 1, 2, 255 ])
* const str = hex.encode(b); // "0102ff"
* ```
*/
export const hex = hasHexBuiltin
? hexBuiltin
: chain(radix2(4), alphabet('0123456789abcdef'), join(''), normalize((s) => {
if (typeof s !== 'string' || s.length % 2 !== 0)
throw new TypeError(`hex.decode: expected string, got ${typeof s} with length ${s.length}`);
return s.toLowerCase();
}));
// prettier-ignore
const CODERS = {
utf8, hex, base16, base32, base64, base64url, base58, base58xmr
};
const coderTypeError = 'Invalid encoding type. Available types: utf8, hex, base16, base32, base64, base64url, base58, base58xmr';
/** @deprecated */
export const bytesToString = (type, bytes) => {
if (typeof type !== 'string' || !CODERS.hasOwnProperty(type))
throw new TypeError(coderTypeError);
if (!isBytes(bytes))
throw new TypeError('bytesToString() expects Uint8Array');
return CODERS[type].encode(bytes);
};
/** @deprecated */
export const str = bytesToString; // as in python, but for bytes only
/** @deprecated */
export const stringToBytes = (type, str) => {
if (!CODERS.hasOwnProperty(type))
throw new TypeError(coderTypeError);
if (typeof str !== 'string')
throw new TypeError('stringToBytes() expects string');
return CODERS[type].decode(str);
};
/** @deprecated */
export const bytes = stringToBytes;
//# sourceMappingURL=index.js.map