index.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. "use strict";
  2. /*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */
  3. Object.defineProperty(exports, "__esModule", { value: true });
  4. exports.bytes = exports.stringToBytes = exports.str = exports.bytesToString = exports.hex = exports.utf8 = exports.bech32m = exports.bech32 = exports.base58check = exports.createBase58check = exports.base58xmr = exports.base58xrp = exports.base58flickr = exports.base58 = exports.base64urlnopad = exports.base64url = exports.base64nopad = exports.base64 = exports.base32crockford = exports.base32hexnopad = exports.base32hex = exports.base32nopad = exports.base32 = exports.base16 = exports.utils = void 0;
  5. exports.assertNumber = assertNumber;
  6. // Utilities
  7. /**
  8. * @__NO_SIDE_EFFECTS__
  9. */
  10. function assertNumber(n) {
  11. if (!Number.isSafeInteger(n))
  12. throw new Error(`Wrong integer: ${n}`);
  13. }
  14. function isBytes(a) {
  15. return (a instanceof Uint8Array ||
  16. (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array'));
  17. }
  18. /**
  19. * @__NO_SIDE_EFFECTS__
  20. */
  21. function chain(...args) {
  22. const id = (a) => a;
  23. // Wrap call in closure so JIT can inline calls
  24. const wrap = (a, b) => (c) => a(b(c));
  25. // Construct chain of args[-1].encode(args[-2].encode([...]))
  26. const encode = args.map((x) => x.encode).reduceRight(wrap, id);
  27. // Construct chain of args[0].decode(args[1].decode(...))
  28. const decode = args.map((x) => x.decode).reduce(wrap, id);
  29. return { encode, decode };
  30. }
  31. /**
  32. * Encodes integer radix representation to array of strings using alphabet and back
  33. * @__NO_SIDE_EFFECTS__
  34. */
  35. function alphabet(alphabet) {
  36. return {
  37. encode: (digits) => {
  38. if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))
  39. throw new Error('alphabet.encode input should be an array of numbers');
  40. return digits.map((i) => {
  41. assertNumber(i);
  42. if (i < 0 || i >= alphabet.length)
  43. throw new Error(`Digit index outside alphabet: ${i} (alphabet: ${alphabet.length})`);
  44. return alphabet[i];
  45. });
  46. },
  47. decode: (input) => {
  48. if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))
  49. throw new Error('alphabet.decode input should be array of strings');
  50. return input.map((letter) => {
  51. if (typeof letter !== 'string')
  52. throw new Error(`alphabet.decode: not string element=${letter}`);
  53. const index = alphabet.indexOf(letter);
  54. if (index === -1)
  55. throw new Error(`Unknown letter: "${letter}". Allowed: ${alphabet}`);
  56. return index;
  57. });
  58. },
  59. };
  60. }
  61. /**
  62. * @__NO_SIDE_EFFECTS__
  63. */
  64. function join(separator = '') {
  65. if (typeof separator !== 'string')
  66. throw new Error('join separator should be string');
  67. return {
  68. encode: (from) => {
  69. if (!Array.isArray(from) || (from.length && typeof from[0] !== 'string'))
  70. throw new Error('join.encode input should be array of strings');
  71. for (let i of from)
  72. if (typeof i !== 'string')
  73. throw new Error(`join.encode: non-string input=${i}`);
  74. return from.join(separator);
  75. },
  76. decode: (to) => {
  77. if (typeof to !== 'string')
  78. throw new Error('join.decode input should be string');
  79. return to.split(separator);
  80. },
  81. };
  82. }
  83. /**
  84. * Pad strings array so it has integer number of bits
  85. * @__NO_SIDE_EFFECTS__
  86. */
  87. function padding(bits, chr = '=') {
  88. assertNumber(bits);
  89. if (typeof chr !== 'string')
  90. throw new Error('padding chr should be string');
  91. return {
  92. encode(data) {
  93. if (!Array.isArray(data) || (data.length && typeof data[0] !== 'string'))
  94. throw new Error('padding.encode input should be array of strings');
  95. for (let i of data)
  96. if (typeof i !== 'string')
  97. throw new Error(`padding.encode: non-string input=${i}`);
  98. while ((data.length * bits) % 8)
  99. data.push(chr);
  100. return data;
  101. },
  102. decode(input) {
  103. if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))
  104. throw new Error('padding.encode input should be array of strings');
  105. for (let i of input)
  106. if (typeof i !== 'string')
  107. throw new Error(`padding.decode: non-string input=${i}`);
  108. let end = input.length;
  109. if ((end * bits) % 8)
  110. throw new Error('Invalid padding: string should have whole number of bytes');
  111. for (; end > 0 && input[end - 1] === chr; end--) {
  112. if (!(((end - 1) * bits) % 8))
  113. throw new Error('Invalid padding: string has too much padding');
  114. }
  115. return input.slice(0, end);
  116. },
  117. };
  118. }
  119. /**
  120. * @__NO_SIDE_EFFECTS__
  121. */
  122. function normalize(fn) {
  123. if (typeof fn !== 'function')
  124. throw new Error('normalize fn should be function');
  125. return { encode: (from) => from, decode: (to) => fn(to) };
  126. }
  127. /**
  128. * Slow: O(n^2) time complexity
  129. * @__NO_SIDE_EFFECTS__
  130. */
  131. function convertRadix(data, from, to) {
  132. // base 1 is impossible
  133. if (from < 2)
  134. throw new Error(`convertRadix: wrong from=${from}, base cannot be less than 2`);
  135. if (to < 2)
  136. throw new Error(`convertRadix: wrong to=${to}, base cannot be less than 2`);
  137. if (!Array.isArray(data))
  138. throw new Error('convertRadix: data should be array');
  139. if (!data.length)
  140. return [];
  141. let pos = 0;
  142. const res = [];
  143. const digits = Array.from(data);
  144. digits.forEach((d) => {
  145. assertNumber(d);
  146. if (d < 0 || d >= from)
  147. throw new Error(`Wrong integer: ${d}`);
  148. });
  149. while (true) {
  150. let carry = 0;
  151. let done = true;
  152. for (let i = pos; i < digits.length; i++) {
  153. const digit = digits[i];
  154. const digitBase = from * carry + digit;
  155. if (!Number.isSafeInteger(digitBase) ||
  156. (from * carry) / from !== carry ||
  157. digitBase - digit !== from * carry) {
  158. throw new Error('convertRadix: carry overflow');
  159. }
  160. carry = digitBase % to;
  161. const rounded = Math.floor(digitBase / to);
  162. digits[i] = rounded;
  163. if (!Number.isSafeInteger(rounded) || rounded * to + carry !== digitBase)
  164. throw new Error('convertRadix: carry overflow');
  165. if (!done)
  166. continue;
  167. else if (!rounded)
  168. pos = i;
  169. else
  170. done = false;
  171. }
  172. res.push(carry);
  173. if (done)
  174. break;
  175. }
  176. for (let i = 0; i < data.length - 1 && data[i] === 0; i++)
  177. res.push(0);
  178. return res.reverse();
  179. }
  180. const gcd = /* @__NO_SIDE_EFFECTS__ */ (a, b) => (!b ? a : gcd(b, a % b));
  181. const radix2carry = /*@__NO_SIDE_EFFECTS__ */ (from, to) => from + (to - gcd(from, to));
  182. /**
  183. * Implemented with numbers, because BigInt is 5x slower
  184. * @__NO_SIDE_EFFECTS__
  185. */
  186. function convertRadix2(data, from, to, padding) {
  187. if (!Array.isArray(data))
  188. throw new Error('convertRadix2: data should be array');
  189. if (from <= 0 || from > 32)
  190. throw new Error(`convertRadix2: wrong from=${from}`);
  191. if (to <= 0 || to > 32)
  192. throw new Error(`convertRadix2: wrong to=${to}`);
  193. if (radix2carry(from, to) > 32) {
  194. throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${radix2carry(from, to)}`);
  195. }
  196. let carry = 0;
  197. let pos = 0; // bitwise position in current element
  198. const mask = 2 ** to - 1;
  199. const res = [];
  200. for (const n of data) {
  201. assertNumber(n);
  202. if (n >= 2 ** from)
  203. throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
  204. carry = (carry << from) | n;
  205. if (pos + from > 32)
  206. throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
  207. pos += from;
  208. for (; pos >= to; pos -= to)
  209. res.push(((carry >> (pos - to)) & mask) >>> 0);
  210. carry &= 2 ** pos - 1; // clean carry, otherwise it will cause overflow
  211. }
  212. carry = (carry << (to - pos)) & mask;
  213. if (!padding && pos >= from)
  214. throw new Error('Excess padding');
  215. if (!padding && carry)
  216. throw new Error(`Non-zero padding: ${carry}`);
  217. if (padding && pos > 0)
  218. res.push(carry >>> 0);
  219. return res;
  220. }
  221. /**
  222. * @__NO_SIDE_EFFECTS__
  223. */
  224. function radix(num) {
  225. assertNumber(num);
  226. return {
  227. encode: (bytes) => {
  228. if (!isBytes(bytes))
  229. throw new Error('radix.encode input should be Uint8Array');
  230. return convertRadix(Array.from(bytes), 2 ** 8, num);
  231. },
  232. decode: (digits) => {
  233. if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))
  234. throw new Error('radix.decode input should be array of numbers');
  235. return Uint8Array.from(convertRadix(digits, num, 2 ** 8));
  236. },
  237. };
  238. }
  239. /**
  240. * If both bases are power of same number (like `2**8 <-> 2**64`),
  241. * there is a linear algorithm. For now we have implementation for power-of-two bases only.
  242. * @__NO_SIDE_EFFECTS__
  243. */
  244. function radix2(bits, revPadding = false) {
  245. assertNumber(bits);
  246. if (bits <= 0 || bits > 32)
  247. throw new Error('radix2: bits should be in (0..32]');
  248. if (radix2carry(8, bits) > 32 || radix2carry(bits, 8) > 32)
  249. throw new Error('radix2: carry overflow');
  250. return {
  251. encode: (bytes) => {
  252. if (!isBytes(bytes))
  253. throw new Error('radix2.encode input should be Uint8Array');
  254. return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
  255. },
  256. decode: (digits) => {
  257. if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))
  258. throw new Error('radix2.decode input should be array of numbers');
  259. return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
  260. },
  261. };
  262. }
  263. /**
  264. * @__NO_SIDE_EFFECTS__
  265. */
  266. function unsafeWrapper(fn) {
  267. if (typeof fn !== 'function')
  268. throw new Error('unsafeWrapper fn should be function');
  269. return function (...args) {
  270. try {
  271. return fn.apply(null, args);
  272. }
  273. catch (e) { }
  274. };
  275. }
  276. /**
  277. * @__NO_SIDE_EFFECTS__
  278. */
  279. function checksum(len, fn) {
  280. assertNumber(len);
  281. if (typeof fn !== 'function')
  282. throw new Error('checksum fn should be function');
  283. return {
  284. encode(data) {
  285. if (!isBytes(data))
  286. throw new Error('checksum.encode: input should be Uint8Array');
  287. const checksum = fn(data).slice(0, len);
  288. const res = new Uint8Array(data.length + len);
  289. res.set(data);
  290. res.set(checksum, data.length);
  291. return res;
  292. },
  293. decode(data) {
  294. if (!isBytes(data))
  295. throw new Error('checksum.decode: input should be Uint8Array');
  296. const payload = data.slice(0, -len);
  297. const newChecksum = fn(payload).slice(0, len);
  298. const oldChecksum = data.slice(-len);
  299. for (let i = 0; i < len; i++)
  300. if (newChecksum[i] !== oldChecksum[i])
  301. throw new Error('Invalid checksum');
  302. return payload;
  303. },
  304. };
  305. }
  306. // prettier-ignore
  307. exports.utils = {
  308. alphabet, chain, checksum, convertRadix, convertRadix2, radix, radix2, join, padding,
  309. };
  310. // RFC 4648 aka RFC 3548
  311. // ---------------------
  312. exports.base16 = chain(radix2(4), alphabet('0123456789ABCDEF'), join(''));
  313. exports.base32 = chain(radix2(5), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'), padding(5), join(''));
  314. exports.base32nopad = chain(radix2(5), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'), join(''));
  315. exports.base32hex = chain(radix2(5), alphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV'), padding(5), join(''));
  316. exports.base32hexnopad = chain(radix2(5), alphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV'), join(''));
  317. exports.base32crockford = chain(radix2(5), alphabet('0123456789ABCDEFGHJKMNPQRSTVWXYZ'), join(''), normalize((s) => s.toUpperCase().replace(/O/g, '0').replace(/[IL]/g, '1')));
  318. exports.base64 = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'), padding(6), join(''));
  319. exports.base64nopad = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'), join(''));
  320. exports.base64url = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'), padding(6), join(''));
  321. exports.base64urlnopad = chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'), join(''));
  322. // base58 code
  323. // -----------
  324. const genBase58 = (abc) => chain(radix(58), alphabet(abc), join(''));
  325. exports.base58 = genBase58('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');
  326. exports.base58flickr = genBase58('123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ');
  327. exports.base58xrp = genBase58('rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz');
  328. // 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.
  329. // Block encoding significantly reduces quadratic complexity of base58.
  330. // Data len (index) -> encoded block len
  331. const XMR_BLOCK_LEN = [0, 2, 3, 5, 6, 7, 9, 10, 11];
  332. exports.base58xmr = {
  333. encode(data) {
  334. let res = '';
  335. for (let i = 0; i < data.length; i += 8) {
  336. const block = data.subarray(i, i + 8);
  337. res += exports.base58.encode(block).padStart(XMR_BLOCK_LEN[block.length], '1');
  338. }
  339. return res;
  340. },
  341. decode(str) {
  342. let res = [];
  343. for (let i = 0; i < str.length; i += 11) {
  344. const slice = str.slice(i, i + 11);
  345. const blockLen = XMR_BLOCK_LEN.indexOf(slice.length);
  346. const block = exports.base58.decode(slice);
  347. for (let j = 0; j < block.length - blockLen; j++) {
  348. if (block[j] !== 0)
  349. throw new Error('base58xmr: wrong padding');
  350. }
  351. res = res.concat(Array.from(block.slice(block.length - blockLen)));
  352. }
  353. return Uint8Array.from(res);
  354. },
  355. };
  356. const createBase58check = (sha256) => chain(checksum(4, (data) => sha256(sha256(data))), exports.base58);
  357. exports.createBase58check = createBase58check;
  358. // legacy export, bad name
  359. exports.base58check = exports.createBase58check;
  360. const BECH_ALPHABET = /* @__PURE__ */ chain(alphabet('qpzry9x8gf2tvdw0s3jn54khce6mua7l'), join(''));
  361. const POLYMOD_GENERATORS = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
  362. /**
  363. * @__NO_SIDE_EFFECTS__
  364. */
  365. function bech32Polymod(pre) {
  366. const b = pre >> 25;
  367. let chk = (pre & 0x1ffffff) << 5;
  368. for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {
  369. if (((b >> i) & 1) === 1)
  370. chk ^= POLYMOD_GENERATORS[i];
  371. }
  372. return chk;
  373. }
  374. /**
  375. * @__NO_SIDE_EFFECTS__
  376. */
  377. function bechChecksum(prefix, words, encodingConst = 1) {
  378. const len = prefix.length;
  379. let chk = 1;
  380. for (let i = 0; i < len; i++) {
  381. const c = prefix.charCodeAt(i);
  382. if (c < 33 || c > 126)
  383. throw new Error(`Invalid prefix (${prefix})`);
  384. chk = bech32Polymod(chk) ^ (c >> 5);
  385. }
  386. chk = bech32Polymod(chk);
  387. for (let i = 0; i < len; i++)
  388. chk = bech32Polymod(chk) ^ (prefix.charCodeAt(i) & 0x1f);
  389. for (let v of words)
  390. chk = bech32Polymod(chk) ^ v;
  391. for (let i = 0; i < 6; i++)
  392. chk = bech32Polymod(chk);
  393. chk ^= encodingConst;
  394. return BECH_ALPHABET.encode(convertRadix2([chk % 2 ** 30], 30, 5, false));
  395. }
  396. /**
  397. * @__NO_SIDE_EFFECTS__
  398. */
  399. function genBech32(encoding) {
  400. const ENCODING_CONST = encoding === 'bech32' ? 1 : 0x2bc830a3;
  401. const _words = radix2(5);
  402. const fromWords = _words.decode;
  403. const toWords = _words.encode;
  404. const fromWordsUnsafe = unsafeWrapper(fromWords);
  405. function encode(prefix, words, limit = 90) {
  406. if (typeof prefix !== 'string')
  407. throw new Error(`bech32.encode prefix should be string, not ${typeof prefix}`);
  408. if (words instanceof Uint8Array)
  409. words = Array.from(words);
  410. if (!Array.isArray(words) || (words.length && typeof words[0] !== 'number'))
  411. throw new Error(`bech32.encode words should be array of numbers, not ${typeof words}`);
  412. if (prefix.length === 0)
  413. throw new TypeError(`Invalid prefix length ${prefix.length}`);
  414. const actualLength = prefix.length + 7 + words.length;
  415. if (limit !== false && actualLength > limit)
  416. throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);
  417. const lowered = prefix.toLowerCase();
  418. const sum = bechChecksum(lowered, words, ENCODING_CONST);
  419. return `${lowered}1${BECH_ALPHABET.encode(words)}${sum}`;
  420. }
  421. function decode(str, limit = 90) {
  422. if (typeof str !== 'string')
  423. throw new Error(`bech32.decode input should be string, not ${typeof str}`);
  424. if (str.length < 8 || (limit !== false && str.length > limit))
  425. throw new TypeError(`Wrong string length: ${str.length} (${str}). Expected (8..${limit})`);
  426. // don't allow mixed case
  427. const lowered = str.toLowerCase();
  428. if (str !== lowered && str !== str.toUpperCase())
  429. throw new Error(`String must be lowercase or uppercase`);
  430. const sepIndex = lowered.lastIndexOf('1');
  431. if (sepIndex === 0 || sepIndex === -1)
  432. throw new Error(`Letter "1" must be present between prefix and data only`);
  433. const prefix = lowered.slice(0, sepIndex);
  434. const data = lowered.slice(sepIndex + 1);
  435. if (data.length < 6)
  436. throw new Error('Data must be at least 6 characters long');
  437. const words = BECH_ALPHABET.decode(data).slice(0, -6);
  438. const sum = bechChecksum(prefix, words, ENCODING_CONST);
  439. if (!data.endsWith(sum))
  440. throw new Error(`Invalid checksum in ${str}: expected "${sum}"`);
  441. return { prefix, words };
  442. }
  443. const decodeUnsafe = unsafeWrapper(decode);
  444. function decodeToBytes(str) {
  445. const { prefix, words } = decode(str, false);
  446. return { prefix, words, bytes: fromWords(words) };
  447. }
  448. function encodeFromBytes(prefix, bytes) {
  449. return encode(prefix, toWords(bytes));
  450. }
  451. return {
  452. encode,
  453. decode,
  454. encodeFromBytes,
  455. decodeToBytes,
  456. decodeUnsafe,
  457. fromWords,
  458. fromWordsUnsafe,
  459. toWords,
  460. };
  461. }
  462. exports.bech32 = genBech32('bech32');
  463. exports.bech32m = genBech32('bech32m');
  464. exports.utf8 = {
  465. encode: (data) => new TextDecoder().decode(data),
  466. decode: (str) => new TextEncoder().encode(str),
  467. };
  468. exports.hex = chain(radix2(4), alphabet('0123456789abcdef'), join(''), normalize((s) => {
  469. if (typeof s !== 'string' || s.length % 2)
  470. throw new TypeError(`hex.decode: expected string, got ${typeof s} with length ${s.length}`);
  471. return s.toLowerCase();
  472. }));
  473. // prettier-ignore
  474. const CODERS = {
  475. utf8: exports.utf8, hex: exports.hex, base16: exports.base16, base32: exports.base32, base64: exports.base64, base64url: exports.base64url, base58: exports.base58, base58xmr: exports.base58xmr
  476. };
  477. const coderTypeError = 'Invalid encoding type. Available types: utf8, hex, base16, base32, base64, base64url, base58, base58xmr';
  478. const bytesToString = (type, bytes) => {
  479. if (typeof type !== 'string' || !CODERS.hasOwnProperty(type))
  480. throw new TypeError(coderTypeError);
  481. if (!isBytes(bytes))
  482. throw new TypeError('bytesToString() expects Uint8Array');
  483. return CODERS[type].encode(bytes);
  484. };
  485. exports.bytesToString = bytesToString;
  486. exports.str = exports.bytesToString; // as in python, but for bytes only
  487. const stringToBytes = (type, str) => {
  488. if (!CODERS.hasOwnProperty(type))
  489. throw new TypeError(coderTypeError);
  490. if (typeof str !== 'string')
  491. throw new TypeError('stringToBytes() expects string');
  492. return CODERS[type].decode(str);
  493. };
  494. exports.stringToBytes = stringToBytes;
  495. exports.bytes = exports.stringToBytes;
  496. //# sourceMappingURL=index.js.map