@vandeurenglenn/base-x 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 base-x contributors
4
+ Copyright (c) 2014-2018 The Bitcoin Core developers (base58.cpp)
5
+ Copyright (c) 2026 Vandeuren Glenn
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
package/README.md CHANGED
@@ -1,28 +1,75 @@
1
- # base-x
2
- > module compatible base-x
3
-
4
- ## install
5
- ```sh
6
- npm i -S @vandeurenglenn/base-x
7
- ```
8
-
9
- ## usage
10
-
11
- ```js
12
- const base = require('@vandeurenglenn/base-x')
13
- // or
14
- import base from '@vandeurenglenn/base-x'
15
-
16
- const base32 = base('abcdefghijklmnopqrstuvwxyz234567') // base32 Alphabet
17
-
18
- // encode
19
- const uint8Array = new TextEncoder().encode('hi');
20
- const bs32 = base32.encode(uint8Array)
21
- console.log(bs32); // '2dj'
22
-
23
- // decode
24
- const hi = base32.decode(bs32)
25
- const string = new TextDecoder().decode(hi);
26
- console.log(string) // 'hi'
27
-
28
- ```
1
+ # @vandeurenglenn/base-x
2
+
3
+ > Fast, optimized, and compatible `base-x` encoding/decoding library.
4
+
5
+ This library is a high-performance drop-in replacement for the standard [base-x](https://github.com/cryptocoinjs/base-x) library. It includes transparent optimizations for power-of-2 bases (Base16, Base32, Base64), achieving **5x-7x faster** performance while maintaining full backward compatibility.
6
+
7
+ It also introduces optional **RFC 4648** compliance for standard Hex, Base32, and Base64 implementations.
8
+
9
+ ## Install
10
+
11
+ ```sh
12
+ npm i -S @vandeurenglenn/base-x
13
+ ```
14
+
15
+ ## Features
16
+
17
+ - **High Performance**: Automatically switches to a customized bitwise algorithm for bases that are powers of 2 (16, 32, 64), offering significant speedups over generic integer arithmetic.
18
+ - **Backwards Compatible**: By default, it mimics the behavior of the original `base-x` library (integer-based encoding, preserving leading zero characters), making it safe for use in cryptocurrency applications (e.g., Bitcoin Base58).
19
+ - **RFC 4648 Support**: Optional mode to strictly follow RFC standards (padding, 8-bit block alignment) for standard web/network use cases.
20
+ - **TypeScript**: First-class TypeScript support with included type definitions.
21
+
22
+ ## Usage
23
+
24
+ ### Standard Mode (Drop-in Replacement)
25
+ Behaves exactly like `base-x`. Note: This mode follows the "Bitcoin-style" integer encoding (leading zero preservation, no padding).
26
+
27
+ ```js
28
+ import base from '@vandeurenglenn/base-x'
29
+
30
+ const BASE58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
31
+ const bs58 = base(BASE58)
32
+
33
+ const data = new Uint8Array([0, 255])
34
+ const encoded = bs58.encode(data)
35
+ console.log(encoded) // "1LU" (1 preserves the leading zero byte)
36
+
37
+ const decoded = bs58.decode(encoded)
38
+ console.log(decoded) // Uint8Array [0, 255]
39
+ ```
40
+
41
+ ### RFC 4648 Mode (Standard Base64/Hex/Base32)
42
+ Enable this mode if you need standard padding (`=`) and strict behavior matching built-in browser/Node.js methods.
43
+
44
+ ```js
45
+ import base from '@vandeurenglenn/base-x'
46
+
47
+ const BASE64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
48
+ // Enable RFC 4648 compliance
49
+ const b64 = base(BASE64, { rfc4648: true })
50
+
51
+ const data = new TextEncoder().encode('Hello World')
52
+
53
+ // Encodes with padding
54
+ const encoded = b64.encode(data)
55
+ console.log(encoded) // "SGVsbG8gV29ybGQ="
56
+
57
+ // Decodes standard Base64 string
58
+ const decoded = b64.decode(encoded)
59
+ console.log(new TextDecoder().decode(decoded)) // "Hello World"
60
+ ```
61
+
62
+ ## Performance
63
+
64
+ Benchmarks run on Node.js v25:
65
+
66
+ | Algorithm | @vandeurenglenn/base-x | standard base-x | Speedup |
67
+ |-----------|------------------------|-----------------|---------|
68
+ | **Base16**| ~3,400,000 ops/sec | ~516,000 ops/sec| **~6.5x**|
69
+ | **Base32**| ~4,100,000 ops/sec | ~680,000 ops/sec| **~6.0x**|
70
+ | **Base64**| ~4,900,000 ops/sec | ~878,000 ops/sec| **~5.5x**|
71
+ | **Base58**| ~600,000 ops/sec | ~594,000 ops/sec| ~1.0x |
72
+
73
+ ## License
74
+
75
+ MIT © [base-x contributors](https://github.com/cryptocoinjs/base-x) & Vandeuren Glenn
package/package.json CHANGED
@@ -1,27 +1,44 @@
1
1
  {
2
2
  "name": "@vandeurenglenn/base-x",
3
- "version": "1.1.2",
4
- "description": "",
3
+ "version": "1.2.0",
4
+ "description": "Fast, optimized, and compatible base-x encoding/decoding library.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/VandeurenGlenn/base-x.git"
8
+ },
9
+ "files": [
10
+ "index.js",
11
+ "index.d.ts"
12
+ ],
5
13
  "exports": {
6
- ".": "./index.js"
14
+ ".": {
15
+ "import": "./index.js",
16
+ "types": "./index.d.ts"
17
+ }
7
18
  },
8
19
  "type": "module",
9
- "types": "./index.d.ts",
10
20
  "scripts": {
21
+ "bench": "node bench.js",
11
22
  "build": "rollup -c",
12
23
  "test": "echo \"Error: no test specified\" && exit 1"
13
24
  },
14
25
  "keywords": [
15
- "base",
16
- "x",
17
26
  "base-x",
18
- "es"
27
+ "base58",
28
+ "base64",
29
+ "base32",
30
+ "base16",
31
+ "encoder",
32
+ "decoder",
33
+ "codec",
34
+ "crypto",
35
+ "base"
19
36
  ],
20
- "author": "",
37
+ "author": "Vandeuren Glenn <vandeurenglenn@gmail.com>",
21
38
  "license": "MIT",
22
39
  "devDependencies": {
23
- "@rollup/plugin-typescript": "^10.0.1",
24
- "rollup": "^2.70.2",
25
- "tslib": "^2.4.1"
40
+ "@rollup/plugin-typescript": "^12.3.0",
41
+ "rollup": "^4.57.1",
42
+ "tslib": "^2.8.1"
26
43
  }
27
44
  }
package/.gitattributes DELETED
@@ -1,2 +0,0 @@
1
- # Auto detect text files and perform LF normalization
2
- * text=auto
package/index.d.ts DELETED
@@ -1,11 +0,0 @@
1
- /**
2
- * string containging only given ALPHABET letters/numbers
3
- */
4
- type baseString = string;
5
- type baseX = {
6
- encode: (uint8Array: Uint8Array) => baseString;
7
- decode: (string: baseString) => Uint8Array;
8
- decodeUnsafe: (string: baseString) => Uint8Array;
9
- };
10
- declare const base: (ALPHABET: string) => baseX;
11
- export { base as default };
package/index.js DELETED
@@ -1,144 +0,0 @@
1
- // base-x encoding / decoding
2
- // Copyright (c) 2018 base-x contributors
3
- // Copyright (c) 2014-2018 The Bitcoin Core developers (base58.cpp)
4
- // Distributed under the MIT software license, see the accompanying
5
- // file LICENSE or http://www.opensource.org/licenses/mit-license.php.
6
- const base = (ALPHABET) => {
7
- if (ALPHABET.length >= 255) {
8
- throw new TypeError('Alphabet too long');
9
- }
10
- const BASE_MAP = new Uint8Array(256);
11
- for (let j = 0; j < BASE_MAP.length; j++) {
12
- BASE_MAP[j] = 255;
13
- }
14
- for (let i = 0; i < ALPHABET.length; i++) {
15
- const x = ALPHABET.charAt(i);
16
- const xc = x.charCodeAt(0);
17
- if (BASE_MAP[xc] !== 255) {
18
- throw new TypeError(x + ' is ambiguous');
19
- }
20
- BASE_MAP[xc] = i;
21
- }
22
- const BASE = ALPHABET.length;
23
- const LEADER = ALPHABET.charAt(0);
24
- const FACTOR = Math.log(BASE) / Math.log(256); // log(BASE) / log(256), rounded up
25
- const iFACTOR = Math.log(256) / Math.log(BASE); // log(256) / log(BASE), rounded up
26
- const encode = (source) => {
27
- if (source instanceof Uint8Array) ;
28
- else if (ArrayBuffer.isView(source)) {
29
- source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
30
- }
31
- else if (Array.isArray(source)) {
32
- source = Uint8Array.from(source);
33
- }
34
- if (!(source instanceof Uint8Array)) {
35
- throw new TypeError('Expected Uint8Array');
36
- }
37
- if (source.length === 0) {
38
- return '';
39
- }
40
- // Skip & count leading zeroes.
41
- let zeroes = 0;
42
- let length = 0;
43
- let pbegin = 0;
44
- const pend = source.length;
45
- while (pbegin !== pend && source[pbegin] === 0) {
46
- pbegin++;
47
- zeroes++;
48
- }
49
- // Allocate enough space in big-endian base58 representation.
50
- const size = ((pend - pbegin) * iFACTOR + 1) >>> 0;
51
- const b58 = new Uint8Array(size);
52
- // Process the bytes.
53
- while (pbegin !== pend) {
54
- let carry = source[pbegin];
55
- // Apply "b58 = b58 * 256 + ch".
56
- let i = 0;
57
- for (let it1 = size - 1; (carry !== 0 || i < length) && (it1 !== -1); it1--, i++) {
58
- carry += (256 * b58[it1]) >>> 0;
59
- b58[it1] = (carry % BASE) >>> 0;
60
- carry = (carry / BASE) >>> 0;
61
- }
62
- if (carry !== 0) {
63
- throw new Error('Non-zero carry');
64
- }
65
- length = i;
66
- pbegin++;
67
- }
68
- // Skip leading zeroes in base58 result.
69
- let it2 = size - length;
70
- while (it2 !== size && b58[it2] === 0) {
71
- it2++;
72
- }
73
- // Translate the result into a string.
74
- let str = LEADER.repeat(zeroes);
75
- for (; it2 < size; ++it2) {
76
- str += ALPHABET.charAt(b58[it2]);
77
- }
78
- return str;
79
- };
80
- const decodeUnsafe = (source) => {
81
- if (typeof source !== 'string') {
82
- throw new TypeError('Expected String');
83
- }
84
- if (source.length === 0) {
85
- return new Uint8Array();
86
- }
87
- let psz = 0;
88
- // Skip and count leading '1's.
89
- let zeroes = 0;
90
- let length = 0;
91
- while (source[psz] === LEADER) {
92
- zeroes++;
93
- psz++;
94
- }
95
- // Allocate enough space in big-endian base256 representation.
96
- const size = (((source.length - psz) * FACTOR) + 1) >>> 0; // log(58) / log(256), rounded up.
97
- let b256 = new Uint8Array(size);
98
- // Process the characters.
99
- while (source[psz]) {
100
- // Decode character
101
- let carry = BASE_MAP[source.charCodeAt(psz)];
102
- // Invalid character
103
- if (carry === 255) {
104
- return;
105
- }
106
- let i = 0;
107
- for (let it3 = size - 1; (carry !== 0 || i < length) && (it3 !== -1); it3--, i++) {
108
- carry += (BASE * b256[it3]) >>> 0;
109
- b256[it3] = (carry % 256) >>> 0;
110
- carry = (carry / 256) >>> 0;
111
- }
112
- if (carry !== 0) {
113
- throw new Error('Non-zero carry');
114
- }
115
- length = i;
116
- psz++;
117
- }
118
- // Skip leading zeroes in b256.
119
- let it4 = size - length;
120
- while (it4 !== size && b256[it4] === 0) {
121
- it4++;
122
- }
123
- let vch = new Uint8Array(zeroes + (size - it4));
124
- let j = zeroes;
125
- while (it4 !== size) {
126
- vch[j++] = b256[it4++];
127
- }
128
- return vch;
129
- };
130
- const decode = (string) => {
131
- const buffer = decodeUnsafe(string);
132
- if (buffer) {
133
- return buffer;
134
- }
135
- throw new Error('Non-base' + BASE + ' character');
136
- };
137
- return {
138
- encode,
139
- decodeUnsafe,
140
- decode
141
- };
142
- };
143
-
144
- export { base as default };
package/src/index.ts DELETED
@@ -1,136 +0,0 @@
1
- /**
2
- * string containing only given ALPHABET letters/numbers
3
- */
4
- type baseString = string
5
-
6
- type baseX = {
7
- encode: (uint8Array: Uint8Array) => baseString,
8
- decode: (string: baseString) => Uint8Array,
9
- decodeUnsafe: (string: baseString) => Uint8Array,
10
- }
11
-
12
- // base-x encoding / decoding
13
- // Copyright (c) 2018 base-x contributors
14
- // Copyright (c) 2014-2018 The Bitcoin Core developers (base58.cpp)
15
- // Distributed under the MIT software license, see the accompanying
16
- // file LICENSE or http://www.opensource.org/licenses/mit-license.php.
17
- const base = (ALPHABET: string):baseX => {
18
- if (ALPHABET.length >= 255) { throw new TypeError('Alphabet too long') }
19
- const BASE_MAP = new Uint8Array(256)
20
- for (let j = 0; j < BASE_MAP.length; j++) {
21
- BASE_MAP[j] = 255
22
- }
23
- for (let i = 0; i < ALPHABET.length; i++) {
24
- const x = ALPHABET.charAt(i)
25
- const xc = x.charCodeAt(0)
26
- if (BASE_MAP[xc] !== 255) { throw new TypeError(x + ' is ambiguous') }
27
- BASE_MAP[xc] = i
28
- }
29
- const BASE = ALPHABET.length
30
- const LEADER = ALPHABET.charAt(0)
31
- const FACTOR = Math.log(BASE) / Math.log(256) // log(BASE) / log(256), rounded up
32
- const iFACTOR = Math.log(256) / Math.log(BASE) // log(256) / log(BASE), rounded up
33
-
34
- const encode = (source: Uint8Array | ArrayBuffer): string => {
35
- if (source instanceof Uint8Array) {
36
- } else if (ArrayBuffer.isView(source)) {
37
- source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength)
38
- } else if (Array.isArray(source)) {
39
- source = Uint8Array.from(source)
40
- }
41
- if (!(source instanceof Uint8Array)) { throw new TypeError('Expected Uint8Array') }
42
- if (source.length === 0) { return '' }
43
- // Skip & count leading zeroes.
44
- let zeroes = 0
45
- let length = 0
46
- let pbegin = 0
47
- const pend = source.length
48
- while (pbegin !== pend && source[pbegin] === 0) {
49
- pbegin++
50
- zeroes++
51
- }
52
- // Allocate enough space in big-endian base58 representation.
53
- const size = ((pend - pbegin) * iFACTOR + 1) >>> 0
54
- const b58 = new Uint8Array(size)
55
- // Process the bytes.
56
- while (pbegin !== pend) {
57
- let carry = source[pbegin]
58
- // Apply "b58 = b58 * 256 + ch".
59
- let i = 0
60
- for (let it1 = size - 1; (carry !== 0 || i < length) && (it1 !== -1); it1--, i++) {
61
- carry += (256 * b58[it1]) >>> 0
62
- b58[it1] = (carry % BASE) >>> 0
63
- carry = (carry / BASE) >>> 0
64
- }
65
- if (carry !== 0) { throw new Error('Non-zero carry') }
66
- length = i
67
- pbegin++
68
- }
69
- // Skip leading zeroes in base58 result.
70
- let it2 = size - length
71
- while (it2 !== size && b58[it2] === 0) {
72
- it2++
73
- }
74
- // Translate the result into a string.
75
- let str = LEADER.repeat(zeroes)
76
- for (; it2 < size; ++it2) { str += ALPHABET.charAt(b58[it2]) }
77
- return str
78
- }
79
-
80
- const decodeUnsafe = (source: string):Uint8Array | undefined => {
81
- if (typeof source !== 'string') { throw new TypeError('Expected String') }
82
- if (source.length === 0) { return new Uint8Array() }
83
- let psz = 0
84
- // Skip and count leading '1's.
85
- let zeroes = 0
86
- let length = 0
87
- while (source[psz] === LEADER) {
88
- zeroes++
89
- psz++
90
- }
91
- // Allocate enough space in big-endian base256 representation.
92
- const size = (((source.length - psz) * FACTOR) + 1) >>> 0 // log(58) / log(256), rounded up.
93
- let b256 = new Uint8Array(size)
94
- // Process the characters.
95
- while (source[psz]) {
96
- // Decode character
97
- let carry = BASE_MAP[source.charCodeAt(psz)]
98
- // Invalid character
99
- if (carry === 255) { return }
100
- let i = 0
101
- for (let it3 = size - 1; (carry !== 0 || i < length) && (it3 !== -1); it3--, i++) {
102
- carry += (BASE * b256[it3]) >>> 0
103
- b256[it3] = (carry % 256) >>> 0
104
- carry = (carry / 256) >>> 0
105
- }
106
- if (carry !== 0) { throw new Error('Non-zero carry') }
107
- length = i
108
- psz++
109
- }
110
- // Skip leading zeroes in b256.
111
- let it4 = size - length
112
- while (it4 !== size && b256[it4] === 0) {
113
- it4++
114
- }
115
- let vch = new Uint8Array(zeroes + (size - it4))
116
- let j = zeroes
117
- while (it4 !== size) {
118
- vch[j++] = b256[it4++]
119
- }
120
- return vch
121
- }
122
-
123
- const decode = (string: string):Uint8Array => {
124
- const buffer = decodeUnsafe(string)
125
- if (buffer) { return buffer }
126
- throw new Error('Non-base' + BASE + ' character')
127
- }
128
-
129
- return {
130
- encode,
131
- decodeUnsafe,
132
- decode
133
- }
134
- }
135
-
136
- export { base as default }
package/test.js DELETED
@@ -1,18 +0,0 @@
1
- import base from './index.js'
2
- const base32 = base('a1')
3
-
4
- // const uint8Array = new Uint8Array(2)
5
- // uint8Array[0] = Buffer.from('h').toString('hex')
6
- // uint8Array[1] = Buffer.from('i').toString('hex')
7
- const uint8Array = new TextEncoder().encode('hi hello, hi');
8
- const bs32 = base32.encode(uint8Array)
9
- console.log(bs32);
10
- const hi = base32.decode(bs32)
11
- const string = new TextDecoder().decode(hi);
12
- // let str = ''
13
- // hi.forEach((item, i) => {
14
- // str+= Buffer.from(item.toString(), 'hex').toString()
15
- // });
16
- // console.log(hi);
17
-
18
- console.log(string === 'hi hello, hi');
package/tsconfig.json DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "moduleResolution":"NodeNext",
4
- "outDir": "./",
5
- "allowJs": true,
6
- "target": "es2022",
7
- "declaration": true
8
- },
9
- "include": [
10
- "./src/**/*"
11
- ],
12
- "exclude": ["./tsconfig.json"]
13
- }