mirror of
https://github.com/dergigi/boris.git
synced 2025-12-18 15:14:20 +01:00
feat: initialize markr nostr bookmark client
- Add project structure with TypeScript, React, and Vite - Implement nostr authentication using browser extension (NIP-07) - Add NIP-51 compliant bookmark fetching and display - Create minimal UI with login and bookmark components - Integrate applesauce-core and applesauce-react libraries - Add responsive styling with dark/light mode support - Include comprehensive README with setup instructions This is a minimal MVP for a nostr bookmark client that allows users to view their bookmarks according to NIP-51 specification.
This commit is contained in:
21
node_modules/@scure/base/LICENSE
generated
vendored
Normal file
21
node_modules/@scure/base/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2022 Paul Miller (https://paulmillr.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the “Software”), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
228
node_modules/@scure/base/README.md
generated
vendored
Normal file
228
node_modules/@scure/base/README.md
generated
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
# scure-base
|
||||
|
||||
Audited & minimal implementation of bech32, base64, base58, base32 & base16.
|
||||
|
||||
- 🔒 [Audited](#security) by an independent security firm
|
||||
- 🔻 Tree-shakeable: unused code is excluded from your builds
|
||||
- 📦 ESM and common.js
|
||||
- ✍️ Written in [functional style](#design-rationale), easily composable
|
||||
- 💼 Matches specs
|
||||
- [BIP173](https://en.bitcoin.it/wiki/BIP_0173), [BIP350](https://en.bitcoin.it/wiki/BIP_0350) for bech32 / bech32m
|
||||
- [RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648) (aka RFC 3548) for Base16, Base32, Base32Hex, Base64, Base64Url
|
||||
- [Base58](https://www.ietf.org/archive/id/draft-msporny-base58-03.txt),
|
||||
[Base58check](https://en.bitcoin.it/wiki/Base58Check_encoding),
|
||||
[Base32 Crockford](https://www.crockford.com/base32.html)
|
||||
- 🪶 4KB gzipped
|
||||
|
||||
Check out [Projects using scure-base](#projects-using-scure-base).
|
||||
|
||||
### This library belongs to _scure_
|
||||
|
||||
> **scure** — audited micro-libraries.
|
||||
|
||||
- Zero or minimal dependencies
|
||||
- Highly readable TypeScript / JS code
|
||||
- PGP-signed releases and transparent NPM builds
|
||||
- Check out [homepage](https://paulmillr.com/noble/#scure) & all libraries:
|
||||
[base](https://github.com/paulmillr/scure-base),
|
||||
[bip32](https://github.com/paulmillr/scure-bip32),
|
||||
[bip39](https://github.com/paulmillr/scure-bip39),
|
||||
[btc-signer](https://github.com/paulmillr/scure-btc-signer),
|
||||
[starknet](https://github.com/paulmillr/scure-starknet)
|
||||
|
||||
## Usage
|
||||
|
||||
> `npm install @scure/base`
|
||||
|
||||
> `deno add jsr:@scure/base`
|
||||
|
||||
> `deno doc jsr:@scure/base` # command-line documentation
|
||||
|
||||
We support all major platforms and runtimes. The library is hybrid ESM / Common.js package.
|
||||
|
||||
```js
|
||||
import { base16, base32, base64, base58 } from '@scure/base';
|
||||
// Flavors
|
||||
import {
|
||||
base58xmr,
|
||||
base58xrp,
|
||||
base32nopad,
|
||||
base32hex,
|
||||
base32hexnopad,
|
||||
base32crockford,
|
||||
base64nopad,
|
||||
base64url,
|
||||
base64urlnopad,
|
||||
} from '@scure/base';
|
||||
|
||||
const data = Uint8Array.from([1, 2, 3]);
|
||||
base64.decode(base64.encode(data));
|
||||
|
||||
// Convert utf8 string to Uint8Array
|
||||
const data2 = new TextEncoder().encode('hello');
|
||||
base58.encode(data2);
|
||||
|
||||
// Everything has the same API except for bech32 and base58check
|
||||
base32.encode(data);
|
||||
base16.encode(data);
|
||||
base32hex.encode(data);
|
||||
```
|
||||
|
||||
base58check is a special case: you need to pass `sha256()` function:
|
||||
|
||||
```js
|
||||
import { createBase58check } from '@scure/base';
|
||||
createBase58check(sha256).encode(data);
|
||||
```
|
||||
|
||||
## Bech32, Bech32m and Bitcoin
|
||||
|
||||
We provide low-level bech32 operations.
|
||||
If you need high-level methods for BTC (addresses, and others), use
|
||||
[scure-btc-signer](https://github.com/paulmillr/scure-btc-signer) instead.
|
||||
|
||||
Bitcoin addresses use both 5-bit words and bytes representations.
|
||||
They can't be parsed using `bech32.decodeToBytes`.
|
||||
|
||||
Same applies to Lightning Invoice Protocol
|
||||
[BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md).
|
||||
We have many tests in `./test/bip173.test.js` that serve as minimal examples of
|
||||
Bitcoin address and Lightning Invoice Protocol parsers.
|
||||
Keep in mind that you'll need to verify the examples before using them in your code.
|
||||
|
||||
Do something like this:
|
||||
|
||||
```ts
|
||||
const decoded = bech32.decode(address);
|
||||
// NOTE: words in bitcoin addresses contain version as first element,
|
||||
// with actual witness program words in rest
|
||||
// BIP-141: The value of the first push is called the "version byte".
|
||||
// The following byte vector pushed is called the "witness program".
|
||||
const [version, ...dataW] = decoded.words;
|
||||
const program = bech32.fromWords(dataW); // actual witness program
|
||||
```
|
||||
|
||||
## Design rationale
|
||||
|
||||
The code may feel unnecessarily complicated; but actually it's much easier to reason about.
|
||||
Any encoding library consists of two functions:
|
||||
|
||||
```
|
||||
encode(A) -> B
|
||||
decode(B) -> A
|
||||
where X = decode(encode(X))
|
||||
# encode(decode(X)) can be !== X!
|
||||
# because decoding can normalize input
|
||||
|
||||
e.g.
|
||||
base58checksum = {
|
||||
encode(): {
|
||||
// checksum
|
||||
// radix conversion
|
||||
// alphabet
|
||||
},
|
||||
decode(): {
|
||||
// alphabet
|
||||
// radix conversion
|
||||
// checksum
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
But instead of creating two big functions for each specific case,
|
||||
we create them from tiny composable building blocks:
|
||||
|
||||
```
|
||||
base58checksum = chain(checksum(), radix(), alphabet())
|
||||
```
|
||||
|
||||
Which is the same as chain/pipe/sequence function in Functional Programming,
|
||||
but significantly more useful since it enforces same order of execution of encode/decode.
|
||||
Basically you only define encode (in declarative way) and get correct decode for free.
|
||||
So, instead of reasoning about two big functions you need only reason about primitives and encode chain.
|
||||
The design revealed obvious bug in older version of the lib,
|
||||
where xmr version of base58 had errors in decode's block processing.
|
||||
|
||||
Besides base-encodings, we can reuse the same approach with any encode/decode function
|
||||
(`bytes2number`, `bytes2u32`, etc).
|
||||
For example, you can easily encode entropy to mnemonic (BIP-39):
|
||||
|
||||
```ts
|
||||
export function getCoder(wordlist: string[]) {
|
||||
if (!Array.isArray(wordlist) || wordlist.length !== 2 ** 11 || typeof wordlist[0] !== 'string') {
|
||||
throw new Error('Wordlist: expected array of 2048 strings');
|
||||
}
|
||||
return mbc.chain(mbu.checksum(1, checksum), mbu.radix2(11, true), mbu.alphabet(wordlist));
|
||||
}
|
||||
```
|
||||
|
||||
### base58 is O(n^2) and radixes
|
||||
|
||||
`Uint8Array` is represented as big-endian number:
|
||||
|
||||
```
|
||||
[1, 2, 3, 4, 5] -> 1*(256**4) + 2*(256**3) 3*(256**2) + 4*(256**1) + 5*(256**0)
|
||||
where 256 = 2**8 (8 bits per byte)
|
||||
```
|
||||
|
||||
which is then converted to a number in another radix/base (16/32/58/64, etc).
|
||||
|
||||
However, generic conversion between bases has [quadratic O(n^2) time complexity](https://cs.stackexchange.com/q/21799).
|
||||
|
||||
Which means base58 has quadratic time complexity too. Use base58 only when you have small
|
||||
constant sized input, because variable length sized input from user can cause DoS.
|
||||
|
||||
On the other hand, if both bases are power of same number (like `2**8 <-> 2**64`),
|
||||
there is linear algorithm. For now we have implementation for power-of-two bases only (radix2).
|
||||
|
||||
## Security
|
||||
|
||||
The library has been independently audited:
|
||||
|
||||
- at version 1.0.0, in Jan 2022, by [cure53](https://cure53.de)
|
||||
- PDFs: [online](https://cure53.de/pentest-report_hashing-libs.pdf), [offline](./audit/2022-01-05-cure53-audit-nbl2.pdf)
|
||||
- [Changes since audit](https://github.com/paulmillr/scure-base/compare/1.0.0..main).
|
||||
- The audit has been funded by [Ethereum Foundation](https://ethereum.org/en/) with help of [Nomic Labs](https://nomiclabs.io)
|
||||
|
||||
The library was initially developed for [js-ethereum-cryptography](https://github.com/ethereum/js-ethereum-cryptography).
|
||||
At commit [ae00e6d7](https://github.com/ethereum/js-ethereum-cryptography/commit/ae00e6d7d24fb3c76a1c7fe10039f6ecd120b77e),
|
||||
it was extracted to a separate package called `micro-base`.
|
||||
After the audit we've decided to use `@scure` NPM namespace for security.
|
||||
|
||||
### Supply chain security
|
||||
|
||||
- **Commits** are signed with PGP keys, to prevent forgery. Make sure to verify commit signatures
|
||||
- **Releases** are transparent and built on GitHub CI. Make sure to verify [provenance](https://docs.npmjs.com/generating-provenance-statements) logs
|
||||
- Use GitHub CLI to verify single-file builds:
|
||||
`gh attestation verify --owner paulmillr scure-base.js`
|
||||
- **Rare releasing** is followed to ensure less re-audit need for end-users
|
||||
- **Dependencies** are minimized and locked-down: any dependency could get hacked and users will be downloading malware with every install.
|
||||
- We make sure to use as few dependencies as possible
|
||||
- Automatic dep updates are prevented by locking-down version ranges; diffs are checked with `npm-diff`
|
||||
- **Dev Dependencies** are disabled for end-users; they are only used to develop / build the source code
|
||||
|
||||
For this package, there are 0 dependencies; and a few dev dependencies:
|
||||
|
||||
- micro-bmark, micro-should and jsbt are used for benchmarking / testing / build tooling and developed by the same author
|
||||
- prettier, fast-check and typescript are used for code quality / test generation / ts compilation. It's hard to audit their source code thoroughly and fully because of their size
|
||||
|
||||
## Contributing & testing
|
||||
|
||||
- `npm install && npm run build && npm test` will build the code and run tests.
|
||||
- `npm run lint` / `npm run format` will run linter / fix linter issues.
|
||||
- `npm run build:release` will build single file
|
||||
|
||||
### Projects using scure-base
|
||||
|
||||
- [scure-btc-signer](https://github.com/paulmillr/scure-btc-signer)
|
||||
- [prefixed-api-key](https://github.com/truestamp/prefixed-api-key)
|
||||
- [coinspace](https://github.com/CoinSpace/CoinSpace) wallet and its modules:
|
||||
[ada](https://github.com/CoinSpace/cs-cardano-wallet),
|
||||
[btc](https://github.com/CoinSpace/cs-bitcoin-wallet)
|
||||
[eos](https://github.com/CoinSpace/cs-eos-wallet),
|
||||
[sol](https://github.com/CoinSpace/cs-solana-wallet),
|
||||
[xmr](https://github.com/CoinSpace/cs-monero-wallet)
|
||||
|
||||
## License
|
||||
|
||||
MIT (c) Paul Miller [(https://paulmillr.com)](https://paulmillr.com), see LICENSE file.
|
||||
861
node_modules/@scure/base/index.ts
generated
vendored
Normal file
861
node_modules/@scure/base/index.ts
generated
vendored
Normal file
@@ -0,0 +1,861 @@
|
||||
/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
|
||||
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 || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
|
||||
}
|
||||
/** Asserts something is Uint8Array. */
|
||||
function abytes(b: Uint8Array | undefined, ...lengths: number[]): void {
|
||||
if (!isBytes(b)) throw new Error('Uint8Array expected');
|
||||
if (lengths.length > 0 && !lengths.includes(b.length))
|
||||
throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length);
|
||||
}
|
||||
|
||||
function isArrayOf(isString: boolean, arr: any[]) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
// no abytes: seems to have 10% slowdown. Why?!
|
||||
|
||||
function afn(input: Function): input is Function {
|
||||
if (typeof input !== 'function') throw new Error('function expected');
|
||||
return true;
|
||||
}
|
||||
|
||||
function astr(label: string, input: unknown): input is string {
|
||||
if (typeof input !== 'string') throw new Error(`${label}: string expected`);
|
||||
return true;
|
||||
}
|
||||
|
||||
function anumber(n: number): void {
|
||||
if (!Number.isSafeInteger(n)) throw new Error(`invalid integer: ${n}`);
|
||||
}
|
||||
|
||||
function aArr(input: any[]) {
|
||||
if (!Array.isArray(input)) throw new Error('array expected');
|
||||
}
|
||||
function astrArr(label: string, input: string[]) {
|
||||
if (!isArrayOf(true, input)) throw new Error(`${label}: array of strings expected`);
|
||||
}
|
||||
function anumArr(label: string, input: number[]) {
|
||||
if (!isArrayOf(false, input)) throw new Error(`${label}: array of numbers expected`);
|
||||
}
|
||||
|
||||
// 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 type
|
||||
type Input<F> = F extends Coder<infer T, any> ? T : never;
|
||||
type Output<F> = F extends Coder<any, infer T> ? T : never;
|
||||
// Generic function for arrays
|
||||
type 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 };
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes integer radix representation to array of strings using alphabet and back.
|
||||
* Could also be array of strings.
|
||||
* @__NO_SIDE_EFFECTS__
|
||||
*/
|
||||
function alphabet(letters: string | string[]): Coder<number[], string[]> {
|
||||
// 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: number[]) => {
|
||||
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: string[]): number[] => {
|
||||
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 = ''): Coder<string[], string> {
|
||||
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: number, chr = '='): Coder<string[], string[]> {
|
||||
anumber(bits);
|
||||
astr('padding', chr);
|
||||
return {
|
||||
encode(data: string[]): string[] {
|
||||
astrArr('padding.encode', data);
|
||||
while ((data.length * bits) % 8) data.push(chr);
|
||||
return data;
|
||||
},
|
||||
decode(input: string[]): string[] {
|
||||
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<T>(fn: (val: T) => T): Coder<T, T> {
|
||||
afn(fn);
|
||||
return { encode: (from: T) => from, decode: (to: T) => fn(to) };
|
||||
}
|
||||
|
||||
/**
|
||||
* Slow: O(n^2) time complexity
|
||||
*/
|
||||
function convertRadix(data: number[], from: number, to: number): number[] {
|
||||
// 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: number, b: number): number => (b === 0 ? a : gcd(b, a % b));
|
||||
const radix2carry = /* @__NO_SIDE_EFFECTS__ */ (from: number, to: number) =>
|
||||
from + (to - gcd(from, to));
|
||||
const powers: number[] = /* @__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: number[], from: number, to: number, padding: boolean): number[] {
|
||||
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: number[] = [];
|
||||
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: number): Coder<Uint8Array, number[]> {
|
||||
anumber(num);
|
||||
const _256 = 2 ** 8;
|
||||
return {
|
||||
encode: (bytes: Uint8Array) => {
|
||||
if (!isBytes(bytes)) throw new Error('radix.encode input should be Uint8Array');
|
||||
return convertRadix(Array.from(bytes), _256, num);
|
||||
},
|
||||
decode: (digits: number[]) => {
|
||||
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: number, revPadding = false): Coder<Uint8Array, number[]> {
|
||||
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: Uint8Array) => {
|
||||
if (!isBytes(bytes)) throw new Error('radix2.encode input should be Uint8Array');
|
||||
return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
|
||||
},
|
||||
decode: (digits: number[]) => {
|
||||
anumArr('radix2.decode', digits);
|
||||
return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
type ArgumentTypes<F extends Function> = F extends (...args: infer A) => any ? A : never;
|
||||
function unsafeWrapper<T extends (...args: any) => any>(fn: T) {
|
||||
afn(fn);
|
||||
return function (...args: ArgumentTypes<T>): ReturnType<T> | void {
|
||||
try {
|
||||
return fn.apply(null, args);
|
||||
} catch (e) {}
|
||||
};
|
||||
}
|
||||
|
||||
function checksum(
|
||||
len: number,
|
||||
fn: (data: Uint8Array) => Uint8Array
|
||||
): Coder<Uint8Array, Uint8Array> {
|
||||
anumber(len);
|
||||
afn(fn);
|
||||
return {
|
||||
encode(data: Uint8Array) {
|
||||
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: Uint8Array) {
|
||||
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: typeof alphabet; chain: typeof chain; checksum: typeof checksum; convertRadix: typeof convertRadix; convertRadix2: typeof convertRadix2; radix: typeof radix; radix2: typeof radix2; join: typeof join; padding: typeof padding; } = {
|
||||
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: BytesCoder = 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: BytesCoder = 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: BytesCoder = 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: BytesCoder = 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: BytesCoder = 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: BytesCoder = chain(
|
||||
radix2(5),
|
||||
alphabet('0123456789ABCDEFGHJKMNPQRSTVWXYZ'),
|
||||
join(''),
|
||||
normalize((s: string) => 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: boolean = /* @__PURE__ */ (() =>
|
||||
typeof (Uint8Array as any).from([]).toBase64 === 'function' &&
|
||||
typeof (Uint8Array as any).fromBase64 === 'function')();
|
||||
|
||||
const decodeBase64Builtin = (s: string, isUrl: boolean) => {
|
||||
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 as any).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: BytesCoder = hasBase64Builtin ? {
|
||||
encode(b) { abytes(b); return (b as any).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: BytesCoder = 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: BytesCoder = hasBase64Builtin ? {
|
||||
encode(b) { abytes(b); return (b as any).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: BytesCoder = chain(
|
||||
radix2(6),
|
||||
alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'),
|
||||
join('')
|
||||
);
|
||||
|
||||
// base58 code
|
||||
// -----------
|
||||
const genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc: string) =>
|
||||
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: BytesCoder = genBase58(
|
||||
'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
||||
);
|
||||
/**
|
||||
* base58: flickr version. Check out `base58`.
|
||||
*/
|
||||
export const base58flickr: BytesCoder = genBase58(
|
||||
'123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
|
||||
);
|
||||
/**
|
||||
* base58: XRP version. Check out `base58`.
|
||||
*/
|
||||
export const base58xrp: BytesCoder = 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: 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);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Method, which creates base58check encoder.
|
||||
* Requires function, calculating sha256.
|
||||
*/
|
||||
export const createBase58check = (sha256: (data: Uint8Array) => Uint8Array): BytesCoder =>
|
||||
chain(
|
||||
checksum(4, (data) => sha256(sha256(data))),
|
||||
base58
|
||||
);
|
||||
|
||||
/**
|
||||
* Use `createBase58check` instead.
|
||||
* @deprecated
|
||||
*/
|
||||
export const base58check: (sha256: (data: Uint8Array) => Uint8Array) => BytesCoder =
|
||||
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> = chain(
|
||||
alphabet('qpzry9x8gf2tvdw0s3jn54khce6mua7l'),
|
||||
join('')
|
||||
);
|
||||
|
||||
const POLYMOD_GENERATORS = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
|
||||
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;
|
||||
}
|
||||
|
||||
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 % powers[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}` {
|
||||
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}` 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 {
|
||||
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: 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,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 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: 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: Bech32 = genBech32('bech32m');
|
||||
|
||||
declare const TextEncoder: any;
|
||||
declare const TextDecoder: any;
|
||||
|
||||
/**
|
||||
* 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: BytesCoder = {
|
||||
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: boolean = /* @__PURE__ */ (() =>
|
||||
typeof (Uint8Array as any).from([]).toHex === 'function' &&
|
||||
typeof (Uint8Array as any).fromHex === 'function')();
|
||||
// prettier-ignore
|
||||
const hexBuiltin: BytesCoder = {
|
||||
encode(data) { abytes(data); return (data as any).toHex(); },
|
||||
decode(s) { astr('hex', s); return (Uint8Array as any).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: BytesCoder = hasHexBuiltin
|
||||
? hexBuiltin
|
||||
: chain(
|
||||
radix2(4),
|
||||
alphabet('0123456789abcdef'),
|
||||
join(''),
|
||||
normalize((s: string) => {
|
||||
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();
|
||||
})
|
||||
);
|
||||
|
||||
export type SomeCoders = {
|
||||
utf8: BytesCoder;
|
||||
hex: BytesCoder;
|
||||
base16: BytesCoder;
|
||||
base32: BytesCoder;
|
||||
base64: BytesCoder;
|
||||
base64url: BytesCoder;
|
||||
base58: BytesCoder;
|
||||
base58xmr: BytesCoder;
|
||||
};
|
||||
// prettier-ignore
|
||||
const CODERS: SomeCoders = {
|
||||
utf8, hex, base16, base32, base64, base64url, base58, base58xmr
|
||||
};
|
||||
type CoderType = keyof SomeCoders;
|
||||
const coderTypeError =
|
||||
'Invalid encoding type. Available types: utf8, hex, base16, base32, base64, base64url, base58, base58xmr';
|
||||
|
||||
/** @deprecated */
|
||||
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);
|
||||
};
|
||||
|
||||
/** @deprecated */
|
||||
export const str: (type: CoderType, bytes: Uint8Array) => string = bytesToString; // as in python, but for bytes only
|
||||
|
||||
/** @deprecated */
|
||||
export 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);
|
||||
};
|
||||
/** @deprecated */
|
||||
export const bytes: (type: CoderType, str: string) => Uint8Array = stringToBytes;
|
||||
294
node_modules/@scure/base/lib/esm/index.d.ts
generated
vendored
Normal file
294
node_modules/@scure/base/lib/esm/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,294 @@
|
||||
/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
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;
|
||||
}
|
||||
type Chain = [Coder<any, any>, ...Coder<any, any>[]];
|
||||
type Input<F> = F extends Coder<infer T, any> ? T : never;
|
||||
type Output<F> = F extends Coder<any, infer T> ? T : never;
|
||||
type 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>> = {
|
||||
[K in keyof C]: Coder<Input<C[K]>, Input<K extends keyof Rest ? Rest[K] : any>>;
|
||||
};
|
||||
/**
|
||||
* @__NO_SIDE_EFFECTS__
|
||||
*/
|
||||
declare function chain<T extends Chain & AsChain<T>>(...args: T): Coder<Input<First<T>>, Output<Last<T>>>;
|
||||
/**
|
||||
* Encodes integer radix representation to array of strings using alphabet and back.
|
||||
* Could also be array of strings.
|
||||
* @__NO_SIDE_EFFECTS__
|
||||
*/
|
||||
declare function alphabet(letters: string | string[]): Coder<number[], string[]>;
|
||||
/**
|
||||
* @__NO_SIDE_EFFECTS__
|
||||
*/
|
||||
declare function join(separator?: string): Coder<string[], string>;
|
||||
/**
|
||||
* Pad strings array so it has integer number of bits
|
||||
* @__NO_SIDE_EFFECTS__
|
||||
*/
|
||||
declare function padding(bits: number, chr?: string): Coder<string[], string[]>;
|
||||
/**
|
||||
* Slow: O(n^2) time complexity
|
||||
*/
|
||||
declare function convertRadix(data: number[], from: number, to: number): number[];
|
||||
/**
|
||||
* Implemented with numbers, because BigInt is 5x slower
|
||||
*/
|
||||
declare function convertRadix2(data: number[], from: number, to: number, padding: boolean): number[];
|
||||
/**
|
||||
* @__NO_SIDE_EFFECTS__
|
||||
*/
|
||||
declare function radix(num: number): Coder<Uint8Array, number[]>;
|
||||
/**
|
||||
* 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__
|
||||
*/
|
||||
declare function radix2(bits: number, revPadding?: boolean): Coder<Uint8Array, number[]>;
|
||||
declare function checksum(len: number, fn: (data: Uint8Array) => Uint8Array): Coder<Uint8Array, Uint8Array>;
|
||||
export declare const utils: {
|
||||
alphabet: typeof alphabet;
|
||||
chain: typeof chain;
|
||||
checksum: typeof checksum;
|
||||
convertRadix: typeof convertRadix;
|
||||
convertRadix2: typeof convertRadix2;
|
||||
radix: typeof radix;
|
||||
radix2: typeof radix2;
|
||||
join: typeof join;
|
||||
padding: typeof padding;
|
||||
};
|
||||
/**
|
||||
* base16 encoding from RFC 4648.
|
||||
* @example
|
||||
* ```js
|
||||
* base16.encode(Uint8Array.from([0x12, 0xab]));
|
||||
* // => '12AB'
|
||||
* ```
|
||||
*/
|
||||
export declare const base16: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base32: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base32nopad: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base32hex: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base32hexnopad: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base32crockford: BytesCoder;
|
||||
/**
|
||||
* 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])
|
||||
* ```
|
||||
*/
|
||||
export declare const base64: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base64nopad: BytesCoder;
|
||||
/**
|
||||
* 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])
|
||||
* ```
|
||||
*/
|
||||
export declare const base64url: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base64urlnopad: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base58: BytesCoder;
|
||||
/**
|
||||
* base58: flickr version. Check out `base58`.
|
||||
*/
|
||||
export declare const base58flickr: BytesCoder;
|
||||
/**
|
||||
* base58: XRP version. Check out `base58`.
|
||||
*/
|
||||
export declare const base58xrp: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base58xmr: BytesCoder;
|
||||
/**
|
||||
* Method, which creates base58check encoder.
|
||||
* Requires function, calculating sha256.
|
||||
*/
|
||||
export declare const createBase58check: (sha256: (data: Uint8Array) => Uint8Array) => BytesCoder;
|
||||
/**
|
||||
* Use `createBase58check` instead.
|
||||
* @deprecated
|
||||
*/
|
||||
export declare const base58check: (sha256: (data: Uint8Array) => Uint8Array) => BytesCoder;
|
||||
export interface Bech32Decoded<Prefix extends string = string> {
|
||||
prefix: Prefix;
|
||||
words: number[];
|
||||
}
|
||||
export interface Bech32DecodedWithArray<Prefix extends string = string> {
|
||||
prefix: Prefix;
|
||||
words: number[];
|
||||
bytes: Uint8Array;
|
||||
}
|
||||
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[];
|
||||
}
|
||||
/**
|
||||
* bech32 from BIP 173. Operates on words.
|
||||
* For high-level, check out scure-btc-signer:
|
||||
* https://github.com/paulmillr/scure-btc-signer.
|
||||
*/
|
||||
export declare const bech32: 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 declare const bech32m: Bech32;
|
||||
/**
|
||||
* 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 declare const utf8: BytesCoder;
|
||||
/**
|
||||
* 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 declare const hex: BytesCoder;
|
||||
export type SomeCoders = {
|
||||
utf8: BytesCoder;
|
||||
hex: BytesCoder;
|
||||
base16: BytesCoder;
|
||||
base32: BytesCoder;
|
||||
base64: BytesCoder;
|
||||
base64url: BytesCoder;
|
||||
base58: BytesCoder;
|
||||
base58xmr: BytesCoder;
|
||||
};
|
||||
type CoderType = keyof SomeCoders;
|
||||
/** @deprecated */
|
||||
export declare const bytesToString: (type: CoderType, bytes: Uint8Array) => string;
|
||||
/** @deprecated */
|
||||
export declare const str: (type: CoderType, bytes: Uint8Array) => string;
|
||||
/** @deprecated */
|
||||
export declare const stringToBytes: (type: CoderType, str: string) => Uint8Array;
|
||||
/** @deprecated */
|
||||
export declare const bytes: (type: CoderType, str: string) => Uint8Array;
|
||||
export {};
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
1
node_modules/@scure/base/lib/esm/index.d.ts.map
generated
vendored
Normal file
1
node_modules/@scure/base/lib/esm/index.d.ts.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
707
node_modules/@scure/base/lib/esm/index.js
generated
vendored
Normal file
707
node_modules/@scure/base/lib/esm/index.js
generated
vendored
Normal file
@@ -0,0 +1,707 @@
|
||||
/*! 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, ...lengths) {
|
||||
if (!isBytes(b))
|
||||
throw new Error('Uint8Array expected');
|
||||
if (lengths.length > 0 && !lengths.includes(b.length))
|
||||
throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length);
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
// no abytes: seems to have 10% slowdown. Why?!
|
||||
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
|
||||
1
node_modules/@scure/base/lib/esm/index.js.map
generated
vendored
Normal file
1
node_modules/@scure/base/lib/esm/index.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
node_modules/@scure/base/lib/esm/package.json
generated
vendored
Normal file
1
node_modules/@scure/base/lib/esm/package.json
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{ "type": "module", "sideEffects": false }
|
||||
294
node_modules/@scure/base/lib/index.d.ts
generated
vendored
Normal file
294
node_modules/@scure/base/lib/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,294 @@
|
||||
/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
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;
|
||||
}
|
||||
type Chain = [Coder<any, any>, ...Coder<any, any>[]];
|
||||
type Input<F> = F extends Coder<infer T, any> ? T : never;
|
||||
type Output<F> = F extends Coder<any, infer T> ? T : never;
|
||||
type 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>> = {
|
||||
[K in keyof C]: Coder<Input<C[K]>, Input<K extends keyof Rest ? Rest[K] : any>>;
|
||||
};
|
||||
/**
|
||||
* @__NO_SIDE_EFFECTS__
|
||||
*/
|
||||
declare function chain<T extends Chain & AsChain<T>>(...args: T): Coder<Input<First<T>>, Output<Last<T>>>;
|
||||
/**
|
||||
* Encodes integer radix representation to array of strings using alphabet and back.
|
||||
* Could also be array of strings.
|
||||
* @__NO_SIDE_EFFECTS__
|
||||
*/
|
||||
declare function alphabet(letters: string | string[]): Coder<number[], string[]>;
|
||||
/**
|
||||
* @__NO_SIDE_EFFECTS__
|
||||
*/
|
||||
declare function join(separator?: string): Coder<string[], string>;
|
||||
/**
|
||||
* Pad strings array so it has integer number of bits
|
||||
* @__NO_SIDE_EFFECTS__
|
||||
*/
|
||||
declare function padding(bits: number, chr?: string): Coder<string[], string[]>;
|
||||
/**
|
||||
* Slow: O(n^2) time complexity
|
||||
*/
|
||||
declare function convertRadix(data: number[], from: number, to: number): number[];
|
||||
/**
|
||||
* Implemented with numbers, because BigInt is 5x slower
|
||||
*/
|
||||
declare function convertRadix2(data: number[], from: number, to: number, padding: boolean): number[];
|
||||
/**
|
||||
* @__NO_SIDE_EFFECTS__
|
||||
*/
|
||||
declare function radix(num: number): Coder<Uint8Array, number[]>;
|
||||
/**
|
||||
* 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__
|
||||
*/
|
||||
declare function radix2(bits: number, revPadding?: boolean): Coder<Uint8Array, number[]>;
|
||||
declare function checksum(len: number, fn: (data: Uint8Array) => Uint8Array): Coder<Uint8Array, Uint8Array>;
|
||||
export declare const utils: {
|
||||
alphabet: typeof alphabet;
|
||||
chain: typeof chain;
|
||||
checksum: typeof checksum;
|
||||
convertRadix: typeof convertRadix;
|
||||
convertRadix2: typeof convertRadix2;
|
||||
radix: typeof radix;
|
||||
radix2: typeof radix2;
|
||||
join: typeof join;
|
||||
padding: typeof padding;
|
||||
};
|
||||
/**
|
||||
* base16 encoding from RFC 4648.
|
||||
* @example
|
||||
* ```js
|
||||
* base16.encode(Uint8Array.from([0x12, 0xab]));
|
||||
* // => '12AB'
|
||||
* ```
|
||||
*/
|
||||
export declare const base16: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base32: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base32nopad: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base32hex: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base32hexnopad: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base32crockford: BytesCoder;
|
||||
/**
|
||||
* 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])
|
||||
* ```
|
||||
*/
|
||||
export declare const base64: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base64nopad: BytesCoder;
|
||||
/**
|
||||
* 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])
|
||||
* ```
|
||||
*/
|
||||
export declare const base64url: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base64urlnopad: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base58: BytesCoder;
|
||||
/**
|
||||
* base58: flickr version. Check out `base58`.
|
||||
*/
|
||||
export declare const base58flickr: BytesCoder;
|
||||
/**
|
||||
* base58: XRP version. Check out `base58`.
|
||||
*/
|
||||
export declare const base58xrp: BytesCoder;
|
||||
/**
|
||||
* 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 declare const base58xmr: BytesCoder;
|
||||
/**
|
||||
* Method, which creates base58check encoder.
|
||||
* Requires function, calculating sha256.
|
||||
*/
|
||||
export declare const createBase58check: (sha256: (data: Uint8Array) => Uint8Array) => BytesCoder;
|
||||
/**
|
||||
* Use `createBase58check` instead.
|
||||
* @deprecated
|
||||
*/
|
||||
export declare const base58check: (sha256: (data: Uint8Array) => Uint8Array) => BytesCoder;
|
||||
export interface Bech32Decoded<Prefix extends string = string> {
|
||||
prefix: Prefix;
|
||||
words: number[];
|
||||
}
|
||||
export interface Bech32DecodedWithArray<Prefix extends string = string> {
|
||||
prefix: Prefix;
|
||||
words: number[];
|
||||
bytes: Uint8Array;
|
||||
}
|
||||
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[];
|
||||
}
|
||||
/**
|
||||
* bech32 from BIP 173. Operates on words.
|
||||
* For high-level, check out scure-btc-signer:
|
||||
* https://github.com/paulmillr/scure-btc-signer.
|
||||
*/
|
||||
export declare const bech32: 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 declare const bech32m: Bech32;
|
||||
/**
|
||||
* 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 declare const utf8: BytesCoder;
|
||||
/**
|
||||
* 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 declare const hex: BytesCoder;
|
||||
export type SomeCoders = {
|
||||
utf8: BytesCoder;
|
||||
hex: BytesCoder;
|
||||
base16: BytesCoder;
|
||||
base32: BytesCoder;
|
||||
base64: BytesCoder;
|
||||
base64url: BytesCoder;
|
||||
base58: BytesCoder;
|
||||
base58xmr: BytesCoder;
|
||||
};
|
||||
type CoderType = keyof SomeCoders;
|
||||
/** @deprecated */
|
||||
export declare const bytesToString: (type: CoderType, bytes: Uint8Array) => string;
|
||||
/** @deprecated */
|
||||
export declare const str: (type: CoderType, bytes: Uint8Array) => string;
|
||||
/** @deprecated */
|
||||
export declare const stringToBytes: (type: CoderType, str: string) => Uint8Array;
|
||||
/** @deprecated */
|
||||
export declare const bytes: (type: CoderType, str: string) => Uint8Array;
|
||||
export {};
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
1
node_modules/@scure/base/lib/index.d.ts.map
generated
vendored
Normal file
1
node_modules/@scure/base/lib/index.d.ts.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
713
node_modules/@scure/base/lib/index.js
generated
vendored
Normal file
713
node_modules/@scure/base/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,713 @@
|
||||
"use strict";
|
||||
/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
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;
|
||||
function isBytes(a) {
|
||||
return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
|
||||
}
|
||||
/** Asserts something is Uint8Array. */
|
||||
function abytes(b, ...lengths) {
|
||||
if (!isBytes(b))
|
||||
throw new Error('Uint8Array expected');
|
||||
if (lengths.length > 0 && !lengths.includes(b.length))
|
||||
throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length);
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
// no abytes: seems to have 10% slowdown. Why?!
|
||||
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
|
||||
exports.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'
|
||||
* ```
|
||||
*/
|
||||
exports.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])
|
||||
* ```
|
||||
*/
|
||||
exports.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])
|
||||
* ```
|
||||
*/
|
||||
exports.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])
|
||||
* ```
|
||||
*/
|
||||
exports.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])
|
||||
* ```
|
||||
*/
|
||||
exports.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])
|
||||
* ```
|
||||
*/
|
||||
exports.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
|
||||
exports.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])
|
||||
* ```
|
||||
*/
|
||||
exports.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
|
||||
exports.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])
|
||||
* ```
|
||||
*/
|
||||
exports.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'
|
||||
* ```
|
||||
*/
|
||||
exports.base58 = genBase58('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');
|
||||
/**
|
||||
* base58: flickr version. Check out `base58`.
|
||||
*/
|
||||
exports.base58flickr = genBase58('123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ');
|
||||
/**
|
||||
* base58: XRP version. Check out `base58`.
|
||||
*/
|
||||
exports.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.
|
||||
*/
|
||||
exports.base58xmr = {
|
||||
encode(data) {
|
||||
let res = '';
|
||||
for (let i = 0; i < data.length; i += 8) {
|
||||
const block = data.subarray(i, i + 8);
|
||||
res += exports.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 = exports.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.
|
||||
*/
|
||||
const createBase58check = (sha256) => chain(checksum(4, (data) => sha256(sha256(data))), exports.base58);
|
||||
exports.createBase58check = createBase58check;
|
||||
/**
|
||||
* Use `createBase58check` instead.
|
||||
* @deprecated
|
||||
*/
|
||||
exports.base58check = exports.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.
|
||||
*/
|
||||
exports.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.
|
||||
*/
|
||||
exports.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"
|
||||
* ```
|
||||
*/
|
||||
exports.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"
|
||||
* ```
|
||||
*/
|
||||
exports.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: exports.utf8, hex: exports.hex, base16: exports.base16, base32: exports.base32, base64: exports.base64, base64url: exports.base64url, base58: exports.base58, base58xmr: exports.base58xmr
|
||||
};
|
||||
const coderTypeError = 'Invalid encoding type. Available types: utf8, hex, base16, base32, base64, base64url, base58, base58xmr';
|
||||
/** @deprecated */
|
||||
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);
|
||||
};
|
||||
exports.bytesToString = bytesToString;
|
||||
/** @deprecated */
|
||||
exports.str = exports.bytesToString; // as in python, but for bytes only
|
||||
/** @deprecated */
|
||||
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);
|
||||
};
|
||||
exports.stringToBytes = stringToBytes;
|
||||
/** @deprecated */
|
||||
exports.bytes = exports.stringToBytes;
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
node_modules/@scure/base/lib/index.js.map
generated
vendored
Normal file
1
node_modules/@scure/base/lib/index.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
70
node_modules/@scure/base/package.json
generated
vendored
Normal file
70
node_modules/@scure/base/package.json
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"name": "@scure/base",
|
||||
"version": "1.2.6",
|
||||
"description": "Secure, audited & 0-dep implementation of base64, bech32, base58, base32 & base16",
|
||||
"files": [
|
||||
"lib/index.js",
|
||||
"lib/index.js.map",
|
||||
"lib/index.d.ts",
|
||||
"lib/index.d.ts.map",
|
||||
"lib/esm/index.js",
|
||||
"lib/esm/index.js.map",
|
||||
"lib/esm/index.d.ts",
|
||||
"lib/esm/index.d.ts.map",
|
||||
"lib/esm/package.json",
|
||||
"index.ts"
|
||||
],
|
||||
"main": "./lib/index.js",
|
||||
"module": "./lib/esm/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./lib/esm/index.js",
|
||||
"require": "./lib/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"bench": "node test/benchmark/index.js",
|
||||
"build": "tsc && tsc -p tsconfig.cjs.json",
|
||||
"build:release": "npx jsbt esbuild test/build",
|
||||
"lint": "prettier --check index.ts",
|
||||
"format": "prettier --write index.ts",
|
||||
"test": "node test/index.js",
|
||||
"test:bun": "bun test/index.js",
|
||||
"test:deno": "deno --allow-env --allow-read test/index.js && deno test/deno.ts"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"author": "Paul Miller (https://paulmillr.com)",
|
||||
"license": "MIT",
|
||||
"homepage": "https://paulmillr.com/noble/#scure",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/paulmillr/scure-base.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@noble/hashes": "1.8.0",
|
||||
"@paulmillr/jsbt": "0.3.3",
|
||||
"@types/node": "22.15.23",
|
||||
"fast-check": "4.1.1",
|
||||
"micro-bmark": "0.4.2",
|
||||
"micro-should": "0.5.3",
|
||||
"prettier": "3.5.3",
|
||||
"typescript": "5.8.3"
|
||||
},
|
||||
"keywords": [
|
||||
"bech32",
|
||||
"bech32m",
|
||||
"base64",
|
||||
"base58",
|
||||
"base32",
|
||||
"base16",
|
||||
"rfc4648",
|
||||
"rfc3548",
|
||||
"crockford",
|
||||
"encode",
|
||||
"encoder",
|
||||
"base-x",
|
||||
"base"
|
||||
],
|
||||
"funding": "https://paulmillr.com/funding/"
|
||||
}
|
||||
Reference in New Issue
Block a user