| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616 | /*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */// Utilities/** * @__NO_SIDE_EFFECTS__ */export function assertNumber(n: number) {  if (!Number.isSafeInteger(n)) throw new Error(`Wrong integer: ${n}`);}export interface Coder<F, T> {  encode(from: F): T;  decode(to: T): F;}export interface BytesCoder extends Coder<Uint8Array, string> {  encode: (data: Uint8Array) => string;  decode: (str: string) => Uint8Array;}function isBytes(a: unknown): a is Uint8Array {  return (    a instanceof Uint8Array ||    (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array')  );}// TODO: some recusive type inference so it would check correct order of input/output inside rest?// like <string, number>, <number, bytes>, <bytes, float>type Chain = [Coder<any, any>, ...Coder<any, any>[]];// Extract info from Coder typetype Input<F> = F extends Coder<infer T, any> ? T : never;type Output<F> = F extends Coder<any, infer T> ? T : never;// Generic function for arraystype First<T> = T extends [infer U, ...any[]] ? U : never;type Last<T> = T extends [...any[], infer U] ? U : never;type Tail<T> = T extends [any, ...infer U] ? U : never;type AsChain<C extends Chain, Rest = Tail<C>> = {  // C[K] = Coder<Input<C[K]>, Input<Rest[k]>>  [K in keyof C]: Coder<Input<C[K]>, Input<K extends keyof Rest ? Rest[K] : any>>;};/** * @__NO_SIDE_EFFECTS__ */function chain<T extends Chain & AsChain<T>>(...args: T): Coder<Input<First<T>>, Output<Last<T>>> {  const id = (a: any) => a;  // Wrap call in closure so JIT can inline calls  const wrap = (a: any, b: any) => (c: any) => 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 };}type Alphabet = string[] | string;/** * Encodes integer radix representation to array of strings using alphabet and back * @__NO_SIDE_EFFECTS__ */function alphabet(alphabet: Alphabet): Coder<number[], string[]> {  return {    encode: (digits: number[]) => {      if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))        throw new Error('alphabet.encode input should be an array of numbers');      return digits.map((i) => {        assertNumber(i);        if (i < 0 || i >= alphabet.length)          throw new Error(`Digit index outside alphabet: ${i} (alphabet: ${alphabet.length})`);        return alphabet[i]!;      });    },    decode: (input: string[]) => {      if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))        throw new Error('alphabet.decode input should be array of strings');      return input.map((letter) => {        if (typeof letter !== 'string')          throw new Error(`alphabet.decode: not string element=${letter}`);        const index = alphabet.indexOf(letter);        if (index === -1) throw new Error(`Unknown letter: "${letter}". Allowed: ${alphabet}`);        return index;      });    },  };}/** * @__NO_SIDE_EFFECTS__ */function join(separator = ''): Coder<string[], string> {  if (typeof separator !== 'string') throw new Error('join separator should be string');  return {    encode: (from) => {      if (!Array.isArray(from) || (from.length && typeof from[0] !== 'string'))        throw new Error('join.encode input should be array of strings');      for (let i of from)        if (typeof i !== 'string') throw new Error(`join.encode: non-string input=${i}`);      return from.join(separator);    },    decode: (to) => {      if (typeof to !== 'string') throw new Error('join.decode input should be string');      return to.split(separator);    },  };}/** * Pad strings array so it has integer number of bits * @__NO_SIDE_EFFECTS__ */function padding(bits: number, chr = '='): Coder<string[], string[]> {  assertNumber(bits);  if (typeof chr !== 'string') throw new Error('padding chr should be string');  return {    encode(data: string[]): string[] {      if (!Array.isArray(data) || (data.length && typeof data[0] !== 'string'))        throw new Error('padding.encode input should be array of strings');      for (let i of data)        if (typeof i !== 'string') throw new Error(`padding.encode: non-string input=${i}`);      while ((data.length * bits) % 8) data.push(chr);      return data;    },    decode(input: string[]): string[] {      if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))        throw new Error('padding.encode input should be array of strings');      for (let i of input)        if (typeof i !== 'string') throw new Error(`padding.decode: non-string input=${i}`);      let end = input.length;      if ((end * bits) % 8)        throw new Error('Invalid padding: string should have whole number of bytes');      for (; end > 0 && input[end - 1] === chr; end--) {        if (!(((end - 1) * bits) % 8))          throw new Error('Invalid padding: string has too much padding');      }      return input.slice(0, end);    },  };}/** * @__NO_SIDE_EFFECTS__ */function normalize<T>(fn: (val: T) => T): Coder<T, T> {  if (typeof fn !== 'function') throw new Error('normalize fn should be function');  return { encode: (from: T) => from, decode: (to: T) => fn(to) };}/** * Slow: O(n^2) time complexity * @__NO_SIDE_EFFECTS__ */function convertRadix(data: number[], from: number, to: number): number[] {  // base 1 is impossible  if (from < 2) throw new Error(`convertRadix: wrong from=${from}, base cannot be less than 2`);  if (to < 2) throw new Error(`convertRadix: wrong to=${to}, base cannot be less than 2`);  if (!Array.isArray(data)) throw new Error('convertRadix: data should be array');  if (!data.length) return [];  let pos = 0;  const res = [];  const digits = Array.from(data);  digits.forEach((d) => {    assertNumber(d);    if (d < 0 || d >= from) throw new Error(`Wrong integer: ${d}`);  });  while (true) {    let carry = 0;    let done = true;    for (let i = pos; i < digits.length; i++) {      const digit = digits[i]!;      const digitBase = from * carry + digit;      if (        !Number.isSafeInteger(digitBase) ||        (from * carry) / from !== carry ||        digitBase - digit !== from * carry      ) {        throw new Error('convertRadix: carry overflow');      }      carry = digitBase % to;      const rounded = Math.floor(digitBase / to);      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 = /* @__NO_SIDE_EFFECTS__ */ (a: number, b: number): number => (!b ? a : gcd(b, a % b));const radix2carry = /*@__NO_SIDE_EFFECTS__ */ (from: number, to: number) =>  from + (to - gcd(from, to));/** * Implemented with numbers, because BigInt is 5x slower * @__NO_SIDE_EFFECTS__ */function convertRadix2(data: number[], from: number, to: number, padding: boolean): number[] {  if (!Array.isArray(data)) throw new Error('convertRadix2: data should be array');  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 mask = 2 ** to - 1;  const res: number[] = [];  for (const n of data) {    assertNumber(n);    if (n >= 2 ** from) 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);    carry &= 2 ** pos - 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) throw new Error(`Non-zero padding: ${carry}`);  if (padding && pos > 0) res.push(carry >>> 0);  return res;}/** * @__NO_SIDE_EFFECTS__ */function radix(num: number): Coder<Uint8Array, number[]> {  assertNumber(num);  return {    encode: (bytes: Uint8Array) => {      if (!isBytes(bytes)) throw new Error('radix.encode input should be Uint8Array');      return convertRadix(Array.from(bytes), 2 ** 8, num);    },    decode: (digits: number[]) => {      if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))        throw new Error('radix.decode input should be array of numbers');      return Uint8Array.from(convertRadix(digits, num, 2 ** 8));    },  };}/** * 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: number, revPadding = false): Coder<Uint8Array, number[]> {  assertNumber(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: Uint8Array) => {      if (!isBytes(bytes)) throw new Error('radix2.encode input should be Uint8Array');      return convertRadix2(Array.from(bytes), 8, bits, !revPadding);    },    decode: (digits: number[]) => {      if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))        throw new Error('radix2.decode input should be array of numbers');      return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));    },  };}type ArgumentTypes<F extends Function> = F extends (...args: infer A) => any ? A : never;/** * @__NO_SIDE_EFFECTS__ */function unsafeWrapper<T extends (...args: any) => any>(fn: T) {  if (typeof fn !== 'function') throw new Error('unsafeWrapper fn should be function');  return function (...args: ArgumentTypes<T>): ReturnType<T> | void {    try {      return fn.apply(null, args);    } catch (e) {}  };}/** * @__NO_SIDE_EFFECTS__ */function checksum(  len: number,  fn: (data: Uint8Array) => Uint8Array): Coder<Uint8Array, Uint8Array> {  assertNumber(len);  if (typeof fn !== 'function') throw new Error('checksum fn should be function');  return {    encode(data: Uint8Array) {      if (!isBytes(data)) throw new Error('checksum.encode: input should be Uint8Array');      const checksum = fn(data).slice(0, len);      const res = new Uint8Array(data.length + len);      res.set(data);      res.set(checksum, data.length);      return res;    },    decode(data: Uint8Array) {      if (!isBytes(data)) throw new Error('checksum.decode: input should be Uint8Array');      const payload = data.slice(0, -len);      const newChecksum = fn(payload).slice(0, len);      const oldChecksum = data.slice(-len);      for (let i = 0; i < len; i++)        if (newChecksum[i] !== oldChecksum[i]) throw new Error('Invalid checksum');      return payload;    },  };}// prettier-ignoreexport const utils = {  alphabet, chain, checksum, convertRadix, convertRadix2, radix, radix2, join, padding,};// RFC 4648 aka RFC 3548// ---------------------export const base16: BytesCoder = /* @__PURE__ */ chain(  radix2(4),  alphabet('0123456789ABCDEF'),  join(''));export const base32: BytesCoder = /* @__PURE__ */ chain(  radix2(5),  alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'),  padding(5),  join(''));export const base32nopad: BytesCoder = /* @__PURE__ */ chain(  radix2(5),  alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'),  join(''));export const base32hex: BytesCoder = /* @__PURE__ */ chain(  radix2(5),  alphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV'),  padding(5),  join(''));export const base32hexnopad: BytesCoder = /* @__PURE__ */ chain(  radix2(5),  alphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV'),  join(''));export const base32crockford: BytesCoder = /* @__PURE__ */ chain(  radix2(5),  alphabet('0123456789ABCDEFGHJKMNPQRSTVWXYZ'),  join(''),  normalize((s: string) => s.toUpperCase().replace(/O/g, '0').replace(/[IL]/g, '1')));export const base64: BytesCoder = /* @__PURE__ */ chain(  radix2(6),  alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'),  padding(6),  join(''));export const base64nopad: BytesCoder = /* @__PURE__ */ chain(  radix2(6),  alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'),  join(''));export const base64url: BytesCoder = /* @__PURE__ */ chain(  radix2(6),  alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'),  padding(6),  join(''));export const base64urlnopad: BytesCoder = /* @__PURE__ */ chain(  radix2(6),  alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'),  join(''));// base58 code// -----------const genBase58 = (abc: string) => chain(radix(58), alphabet(abc), join(''));export const base58: BytesCoder = /* @__PURE__ */ genBase58(  '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');export const base58flickr: BytesCoder = /* @__PURE__ */ genBase58(  '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ');export const base58xrp: BytesCoder = /* @__PURE__ */ genBase58(  'rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz');// xmr ver is 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.// Data len (index) -> encoded block lenconst XMR_BLOCK_LEN = [0, 2, 3, 5, 6, 7, 9, 10, 11];export const base58xmr: BytesCoder = {  encode(data: Uint8Array) {    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: string) {    let res: number[] = [];    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);  },};export const createBase58check = (sha256: (data: Uint8Array) => Uint8Array): BytesCoder =>  chain(    checksum(4, (data) => sha256(sha256(data))),    base58  );// legacy export, bad nameexport const base58check = createBase58check;// Bech32 code// -----------export interface Bech32Decoded<Prefix extends string = string> {  prefix: Prefix;  words: number[];}export interface Bech32DecodedWithArray<Prefix extends string = string> {  prefix: Prefix;  words: number[];  bytes: Uint8Array;}const BECH_ALPHABET: Coder<number[], string> = /* @__PURE__ */ chain(  alphabet('qpzry9x8gf2tvdw0s3jn54khce6mua7l'),  join(''));const POLYMOD_GENERATORS = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];/** * @__NO_SIDE_EFFECTS__ */function bech32Polymod(pre: number): number {  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;}/** * @__NO_SIDE_EFFECTS__ */function bechChecksum(prefix: string, words: number[], encodingConst = 1): string {  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 % 2 ** 30], 30, 5, false));}export interface Bech32 {  encode<Prefix extends string>(    prefix: Prefix,    words: number[] | Uint8Array,    limit?: number | false  ): `${Lowercase<Prefix>}1${string}`;  decode<Prefix extends string>(    str: `${Prefix}1${string}`,    limit?: number | false  ): Bech32Decoded<Prefix>;  encodeFromBytes(prefix: string, bytes: Uint8Array): string;  decodeToBytes(str: string): Bech32DecodedWithArray;  decodeUnsafe(str: string, limit?: number | false): void | Bech32Decoded<string>;  fromWords(to: number[]): Uint8Array;  fromWordsUnsafe(to: number[]): void | Uint8Array;  toWords(from: Uint8Array): number[];}/** * @__NO_SIDE_EFFECTS__ */function genBech32(encoding: 'bech32' | 'bech32m'): Bech32 {  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 extends string>(    prefix: Prefix,    words: number[] | Uint8Array,    limit: number | false = 90  ): `${Lowercase<Prefix>}1${string}` {    if (typeof prefix !== 'string')      throw new Error(`bech32.encode prefix should be string, not ${typeof prefix}`);    if (words instanceof Uint8Array) words = Array.from(words);    if (!Array.isArray(words) || (words.length && typeof words[0] !== 'number'))      throw new Error(`bech32.encode words should be array of numbers, not ${typeof words}`);    if (prefix.length === 0) throw new TypeError(`Invalid prefix length ${prefix.length}`);    const actualLength = prefix.length + 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}` as `${Lowercase<Prefix>}1${string}`;  }  function decode<Prefix extends string>(    str: `${Prefix}1${string}`,    limit?: number | false  ): Bech32Decoded<Prefix>;  function decode(str: string, limit?: number | false): Bech32Decoded;  function decode(str: string, limit: number | false = 90): Bech32Decoded {    if (typeof str !== 'string')      throw new Error(`bech32.decode input should be string, not ${typeof str}`);    if (str.length < 8 || (limit !== false && str.length > limit))      throw new TypeError(`Wrong string length: ${str.length} (${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: string): Bech32DecodedWithArray {    const { prefix, words } = decode(str, false);    return { prefix, words, bytes: fromWords(words) };  }  function encodeFromBytes(prefix: string, bytes: Uint8Array) {    return encode(prefix, toWords(bytes));  }  return {    encode,    decode,    encodeFromBytes,    decodeToBytes,    decodeUnsafe,    fromWords,    fromWordsUnsafe,    toWords,  };}export const bech32: Bech32 = /* @__PURE__ */ genBech32('bech32');export const bech32m: Bech32 = /* @__PURE__ */ genBech32('bech32m');declare const TextEncoder: any;declare const TextDecoder: any;export const utf8: BytesCoder = {  encode: (data) => new TextDecoder().decode(data),  decode: (str) => new TextEncoder().encode(str),};export const hex: BytesCoder = /* @__PURE__ */ chain(  radix2(4),  alphabet('0123456789abcdef'),  join(''),  normalize((s: string) => {    if (typeof s !== 'string' || s.length % 2)      throw new TypeError(`hex.decode: expected string, got ${typeof s} with length ${s.length}`);    return s.toLowerCase();  }));// prettier-ignoreconst CODERS = {  utf8, hex, base16, base32, base64, base64url, base58, base58xmr};type CoderType = keyof typeof CODERS;const coderTypeError =  'Invalid encoding type. Available types: utf8, hex, base16, base32, base64, base64url, base58, base58xmr';export const bytesToString = (type: CoderType, bytes: Uint8Array): string => {  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);};export const str = bytesToString; // as in python, but for bytes onlyexport const stringToBytes = (type: CoderType, str: string): Uint8Array => {  if (!CODERS.hasOwnProperty(type)) throw new TypeError(coderTypeError);  if (typeof str !== 'string') throw new TypeError('stringToBytes() expects string');  return CODERS[type].decode(str);};export const bytes = stringToBytes;
 |