@wtasnorg/node-lib 0.0.9 → 0.0.11
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/changelog.txt +14 -0
- package/dev_checklist.txt +9 -3
- package/docs/README.md +12 -0
- package/docs/docs.json +1523 -233
- package/docs/functions/createFindDirectories.md +1 -1
- package/docs/functions/decode.md +1 -1
- package/docs/functions/decode32.md +49 -0
- package/docs/functions/decode58.md +49 -0
- package/docs/functions/decode85.md +49 -0
- package/docs/functions/encode.md +1 -1
- package/docs/functions/encode32.md +45 -0
- package/docs/functions/encode58.md +45 -0
- package/docs/functions/encode85.md +45 -0
- package/docs/functions/hello.md +35 -3
- package/docs/functions/parseUserAgent.md +1 -1
- package/docs/functions/pojo.md +1 -1
- package/docs/interfaces/FileSystemDependencies.md +3 -3
- package/docs/interfaces/FindDirectoriesOptions.md +5 -5
- package/docs/interfaces/UserAgentInfo.md +6 -6
- package/docs/type-aliases/Base32CharsetType.md +13 -0
- package/docs/type-aliases/Base58CharsetType.md +13 -0
- package/docs/type-aliases/Base64CharsetType.md +1 -1
- package/docs/type-aliases/Base85CharsetType.md +13 -0
- package/docs/variables/Base32Charset.md +16 -0
- package/docs/variables/Base58Charset.md +16 -0
- package/docs/variables/Base64Charset.md +1 -1
- package/docs/variables/Base85Charset.md +16 -0
- package/package.json +44 -3
- package/readme.txt +12 -0
- package/src/base32.d.ts +58 -0
- package/src/base32.js +143 -0
- package/src/base32.test.d.ts +2 -0
- package/src/base32.test.js +121 -0
- package/src/base32.test.ts +144 -0
- package/src/base32.ts +169 -0
- package/src/base58.d.ts +58 -0
- package/src/base58.js +155 -0
- package/src/base58.test.d.ts +2 -0
- package/src/base58.test.js +108 -0
- package/src/base58.test.ts +128 -0
- package/src/base58.ts +177 -0
- package/src/base85.d.ts +58 -0
- package/src/base85.js +173 -0
- package/src/base85.test.d.ts +2 -0
- package/src/base85.test.js +107 -0
- package/src/base85.test.ts +125 -0
- package/src/base85.ts +199 -0
- package/src/hello.d.ts +27 -2
- package/src/hello.js +29 -4
- package/src/hello.test.js +11 -0
- package/src/hello.test.ts +13 -0
- package/src/hello.ts +29 -4
- package/src/index.d.ts +8 -2
- package/src/index.js +4 -1
- package/src/index.ts +20 -2
package/src/base32.ts
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base32 encoding/decoding with multiple charset variants.
|
|
3
|
+
* Base32 is case-insensitive and useful for human-readable encoding (TOTP codes).
|
|
4
|
+
* @module base32
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Available Base32 charset variants.
|
|
9
|
+
* - `rfc4648`: Standard RFC 4648 alphabet (A-Z, 2-7)
|
|
10
|
+
* - `hex`: Extended hex alphabet (0-9, A-V)
|
|
11
|
+
* - `crockford`: Douglas Crockford's alphabet (excludes I, L, O, U)
|
|
12
|
+
*/
|
|
13
|
+
const Base32Charset = ["rfc4648", "hex", "crockford"] as const;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Base32 charset type.
|
|
17
|
+
*/
|
|
18
|
+
type Base32CharsetType = (typeof Base32Charset)[number];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Charset alphabets for Base32 variants.
|
|
22
|
+
*/
|
|
23
|
+
const CHARSETS: Record<Base32CharsetType, string> = {
|
|
24
|
+
rfc4648: "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
|
|
25
|
+
hex: "0123456789ABCDEFGHIJKLMNOPQRSTUV",
|
|
26
|
+
crockford: "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Padding character for Base32 encoding.
|
|
31
|
+
*/
|
|
32
|
+
const PAD = "=";
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Build a reverse lookup table for decoding.
|
|
36
|
+
* @param alphabet - The 32-character alphabet string.
|
|
37
|
+
* @param caseInsensitive - Whether to add lowercase mappings.
|
|
38
|
+
* @returns Map of character to index.
|
|
39
|
+
*/
|
|
40
|
+
function buildDecodeTable(alphabet: string, caseInsensitive = true): Map<string, number> {
|
|
41
|
+
const table = new Map<string, number>();
|
|
42
|
+
for (let i = 0; i < alphabet.length; i++) {
|
|
43
|
+
const char = alphabet[i];
|
|
44
|
+
if (char !== undefined) {
|
|
45
|
+
table.set(char, i);
|
|
46
|
+
if (caseInsensitive) {
|
|
47
|
+
table.set(char.toLowerCase(), i);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return table;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Pre-built decode tables for each charset.
|
|
56
|
+
*/
|
|
57
|
+
const DECODE_TABLES: Record<Base32CharsetType, Map<string, number>> = {
|
|
58
|
+
rfc4648: buildDecodeTable(CHARSETS.rfc4648),
|
|
59
|
+
hex: buildDecodeTable(CHARSETS.hex),
|
|
60
|
+
crockford: buildDecodeTable(CHARSETS.crockford)
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Encode a string to Base32.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* import { encode32 } from "./base32.js";
|
|
69
|
+
*
|
|
70
|
+
* encode32("Hello");
|
|
71
|
+
* // => "JBSWY3DP"
|
|
72
|
+
*
|
|
73
|
+
* encode32("test", "hex");
|
|
74
|
+
* // => "EHMP6SS="
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @param input - The string to encode.
|
|
78
|
+
* @param charset - The charset variant to use (default: "rfc4648").
|
|
79
|
+
* @returns The Base32 encoded string.
|
|
80
|
+
*/
|
|
81
|
+
function encode32(input: string, charset: Base32CharsetType = "rfc4648"): string {
|
|
82
|
+
if (input === "") {
|
|
83
|
+
return "";
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const alphabet = CHARSETS[charset];
|
|
87
|
+
const bytes = new TextEncoder().encode(input);
|
|
88
|
+
let result = "";
|
|
89
|
+
let buffer = 0;
|
|
90
|
+
let bitsInBuffer = 0;
|
|
91
|
+
|
|
92
|
+
for (const byte of bytes) {
|
|
93
|
+
buffer = (buffer << 8) | byte;
|
|
94
|
+
bitsInBuffer += 8;
|
|
95
|
+
|
|
96
|
+
while (bitsInBuffer >= 5) {
|
|
97
|
+
bitsInBuffer -= 5;
|
|
98
|
+
const index = (buffer >> bitsInBuffer) & 0x1f;
|
|
99
|
+
result += alphabet[index];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Handle remaining bits
|
|
104
|
+
if (bitsInBuffer > 0) {
|
|
105
|
+
const index = (buffer << (5 - bitsInBuffer)) & 0x1f;
|
|
106
|
+
result += alphabet[index];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Add padding to make length a multiple of 8
|
|
110
|
+
while (result.length % 8 !== 0) {
|
|
111
|
+
result += PAD;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Decode a Base32 string.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```typescript
|
|
122
|
+
* import { decode32 } from "./base32.js";
|
|
123
|
+
*
|
|
124
|
+
* decode32("JBSWY3DP");
|
|
125
|
+
* // => "Hello"
|
|
126
|
+
*
|
|
127
|
+
* decode32("EHMP6SS=", "hex");
|
|
128
|
+
* // => "test"
|
|
129
|
+
* ```
|
|
130
|
+
*
|
|
131
|
+
* @param input - The Base32 encoded string.
|
|
132
|
+
* @param charset - The charset variant to use (default: "rfc4648").
|
|
133
|
+
* @returns The decoded string.
|
|
134
|
+
* @throws Error if the input contains invalid characters.
|
|
135
|
+
*/
|
|
136
|
+
function decode32(input: string, charset: Base32CharsetType = "rfc4648"): string {
|
|
137
|
+
if (input === "") {
|
|
138
|
+
return "";
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const decodeTable = DECODE_TABLES[charset];
|
|
142
|
+
|
|
143
|
+
// Remove padding
|
|
144
|
+
const cleanInput = input.replace(/=+$/, "");
|
|
145
|
+
const bytes: number[] = [];
|
|
146
|
+
|
|
147
|
+
let buffer = 0;
|
|
148
|
+
let bitsInBuffer = 0;
|
|
149
|
+
|
|
150
|
+
for (const char of cleanInput) {
|
|
151
|
+
const value = decodeTable.get(char);
|
|
152
|
+
if (value === undefined) {
|
|
153
|
+
throw new Error(`Invalid Base32 character: ${char}`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
buffer = (buffer << 5) | value;
|
|
157
|
+
bitsInBuffer += 5;
|
|
158
|
+
|
|
159
|
+
if (bitsInBuffer >= 8) {
|
|
160
|
+
bitsInBuffer -= 8;
|
|
161
|
+
bytes.push((buffer >> bitsInBuffer) & 0xff);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return new TextDecoder().decode(new Uint8Array(bytes));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export { encode32, decode32, Base32Charset };
|
|
169
|
+
export type { Base32CharsetType };
|
package/src/base58.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base58 encoding/decoding with multiple charset variants.
|
|
3
|
+
* Base58 excludes visually ambiguous characters (0, O, I, l).
|
|
4
|
+
* @module base58
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Available Base58 charset variants.
|
|
8
|
+
* - `bitcoin`: Bitcoin/IPFS alphabet (default)
|
|
9
|
+
* - `flickr`: Flickr short URLs (swaps case)
|
|
10
|
+
* - `ripple`: Ripple addresses
|
|
11
|
+
*/
|
|
12
|
+
declare const Base58Charset: readonly ["bitcoin", "flickr", "ripple"];
|
|
13
|
+
/**
|
|
14
|
+
* Base58 charset type.
|
|
15
|
+
*/
|
|
16
|
+
type Base58CharsetType = (typeof Base58Charset)[number];
|
|
17
|
+
/**
|
|
18
|
+
* Encode a string to Base58.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* import { encode58 } from "./base58.js";
|
|
23
|
+
*
|
|
24
|
+
* encode58("Hello World");
|
|
25
|
+
* // => "JxF12TrwUP45BMd"
|
|
26
|
+
*
|
|
27
|
+
* encode58("Hello World", "flickr");
|
|
28
|
+
* // => "jXf12sRWto45bmD"
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @param input - The string to encode.
|
|
32
|
+
* @param charset - The charset variant to use (default: "bitcoin").
|
|
33
|
+
* @returns The Base58 encoded string.
|
|
34
|
+
*/
|
|
35
|
+
declare function encode58(input: string, charset?: Base58CharsetType): string;
|
|
36
|
+
/**
|
|
37
|
+
* Decode a Base58 string.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* import { decode58 } from "./base58.js";
|
|
42
|
+
*
|
|
43
|
+
* decode58("JxF12TrwUP45BMd");
|
|
44
|
+
* // => "Hello World"
|
|
45
|
+
*
|
|
46
|
+
* decode58("jXf12sRWto45bmD", "flickr");
|
|
47
|
+
* // => "Hello World"
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @param input - The Base58 encoded string.
|
|
51
|
+
* @param charset - The charset variant to use (default: "bitcoin").
|
|
52
|
+
* @returns The decoded string.
|
|
53
|
+
* @throws Error if the input contains invalid characters.
|
|
54
|
+
*/
|
|
55
|
+
declare function decode58(input: string, charset?: Base58CharsetType): string;
|
|
56
|
+
export { encode58, decode58, Base58Charset };
|
|
57
|
+
export type { Base58CharsetType };
|
|
58
|
+
//# sourceMappingURL=base58.d.ts.map
|
package/src/base58.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base58 encoding/decoding with multiple charset variants.
|
|
3
|
+
* Base58 excludes visually ambiguous characters (0, O, I, l).
|
|
4
|
+
* @module base58
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Available Base58 charset variants.
|
|
8
|
+
* - `bitcoin`: Bitcoin/IPFS alphabet (default)
|
|
9
|
+
* - `flickr`: Flickr short URLs (swaps case)
|
|
10
|
+
* - `ripple`: Ripple addresses
|
|
11
|
+
*/
|
|
12
|
+
const Base58Charset = ["bitcoin", "flickr", "ripple"];
|
|
13
|
+
/**
|
|
14
|
+
* Charset alphabets for Base58 variants.
|
|
15
|
+
*/
|
|
16
|
+
const CHARSETS = {
|
|
17
|
+
bitcoin: "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",
|
|
18
|
+
flickr: "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ",
|
|
19
|
+
ripple: "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Build a reverse lookup table for decoding.
|
|
23
|
+
* @param alphabet - The 58-character alphabet string.
|
|
24
|
+
* @returns Map of character to index.
|
|
25
|
+
*/
|
|
26
|
+
function buildDecodeTable(alphabet) {
|
|
27
|
+
const table = new Map();
|
|
28
|
+
for (let i = 0; i < alphabet.length; i++) {
|
|
29
|
+
const char = alphabet[i];
|
|
30
|
+
if (char !== undefined) {
|
|
31
|
+
table.set(char, i);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return table;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Pre-built decode tables for each charset.
|
|
38
|
+
*/
|
|
39
|
+
const DECODE_TABLES = {
|
|
40
|
+
bitcoin: buildDecodeTable(CHARSETS.bitcoin),
|
|
41
|
+
flickr: buildDecodeTable(CHARSETS.flickr),
|
|
42
|
+
ripple: buildDecodeTable(CHARSETS.ripple)
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Encode a string to Base58.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* import { encode58 } from "./base58.js";
|
|
50
|
+
*
|
|
51
|
+
* encode58("Hello World");
|
|
52
|
+
* // => "JxF12TrwUP45BMd"
|
|
53
|
+
*
|
|
54
|
+
* encode58("Hello World", "flickr");
|
|
55
|
+
* // => "jXf12sRWto45bmD"
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @param input - The string to encode.
|
|
59
|
+
* @param charset - The charset variant to use (default: "bitcoin").
|
|
60
|
+
* @returns The Base58 encoded string.
|
|
61
|
+
*/
|
|
62
|
+
function encode58(input, charset = "bitcoin") {
|
|
63
|
+
if (input === "") {
|
|
64
|
+
return "";
|
|
65
|
+
}
|
|
66
|
+
const alphabet = CHARSETS[charset];
|
|
67
|
+
const bytes = new TextEncoder().encode(input);
|
|
68
|
+
// Count leading zeros
|
|
69
|
+
let leadingZeros = 0;
|
|
70
|
+
for (const byte of bytes) {
|
|
71
|
+
if (byte === 0) {
|
|
72
|
+
leadingZeros++;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Convert bytes to a big integer
|
|
79
|
+
let num = 0n;
|
|
80
|
+
for (const byte of bytes) {
|
|
81
|
+
num = num * 256n + BigInt(byte);
|
|
82
|
+
}
|
|
83
|
+
// Convert to Base58
|
|
84
|
+
let result = "";
|
|
85
|
+
while (num > 0n) {
|
|
86
|
+
const remainder = Number(num % 58n);
|
|
87
|
+
num = num / 58n;
|
|
88
|
+
result = alphabet[remainder] + result;
|
|
89
|
+
}
|
|
90
|
+
// Add leading '1's for leading zero bytes
|
|
91
|
+
const leadChar = alphabet[0];
|
|
92
|
+
for (let i = 0; i < leadingZeros; i++) {
|
|
93
|
+
result = leadChar + result;
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Decode a Base58 string.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* import { decode58 } from "./base58.js";
|
|
103
|
+
*
|
|
104
|
+
* decode58("JxF12TrwUP45BMd");
|
|
105
|
+
* // => "Hello World"
|
|
106
|
+
*
|
|
107
|
+
* decode58("jXf12sRWto45bmD", "flickr");
|
|
108
|
+
* // => "Hello World"
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* @param input - The Base58 encoded string.
|
|
112
|
+
* @param charset - The charset variant to use (default: "bitcoin").
|
|
113
|
+
* @returns The decoded string.
|
|
114
|
+
* @throws Error if the input contains invalid characters.
|
|
115
|
+
*/
|
|
116
|
+
function decode58(input, charset = "bitcoin") {
|
|
117
|
+
if (input === "") {
|
|
118
|
+
return "";
|
|
119
|
+
}
|
|
120
|
+
const alphabet = CHARSETS[charset];
|
|
121
|
+
const decodeTable = DECODE_TABLES[charset];
|
|
122
|
+
const leadChar = alphabet[0];
|
|
123
|
+
// Count leading '1's (or equivalent)
|
|
124
|
+
let leadingOnes = 0;
|
|
125
|
+
for (const char of input) {
|
|
126
|
+
if (char === leadChar) {
|
|
127
|
+
leadingOnes++;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Convert from Base58 to big integer
|
|
134
|
+
let num = 0n;
|
|
135
|
+
for (const char of input) {
|
|
136
|
+
const value = decodeTable.get(char);
|
|
137
|
+
if (value === undefined) {
|
|
138
|
+
throw new Error(`Invalid Base58 character: ${char}`);
|
|
139
|
+
}
|
|
140
|
+
num = num * 58n + BigInt(value);
|
|
141
|
+
}
|
|
142
|
+
// Convert big integer to bytes
|
|
143
|
+
const bytes = [];
|
|
144
|
+
while (num > 0n) {
|
|
145
|
+
bytes.unshift(Number(num % 256n));
|
|
146
|
+
num = num / 256n;
|
|
147
|
+
}
|
|
148
|
+
// Add leading zeros
|
|
149
|
+
for (let i = 0; i < leadingOnes; i++) {
|
|
150
|
+
bytes.unshift(0);
|
|
151
|
+
}
|
|
152
|
+
return new TextDecoder().decode(new Uint8Array(bytes));
|
|
153
|
+
}
|
|
154
|
+
export { encode58, decode58, Base58Charset };
|
|
155
|
+
//# sourceMappingURL=base58.js.map
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { describe, it } from "node:test";
|
|
2
|
+
import { strictEqual, throws } from "node:assert";
|
|
3
|
+
import { encode58, decode58, Base58Charset } from "./base58.js";
|
|
4
|
+
describe("Base58 encode58", () => {
|
|
5
|
+
it("encodes empty string", () => {
|
|
6
|
+
strictEqual(encode58(""), "");
|
|
7
|
+
});
|
|
8
|
+
it("encodes 'Hello World' with bitcoin charset", () => {
|
|
9
|
+
strictEqual(encode58("Hello World"), "JxF12TrwUP45BMd");
|
|
10
|
+
});
|
|
11
|
+
it("encodes single character", () => {
|
|
12
|
+
// Verify round-trip rather than hardcoded value
|
|
13
|
+
const encoded = encode58("A");
|
|
14
|
+
strictEqual(encoded.length > 0, true);
|
|
15
|
+
strictEqual(decode58(encoded), "A");
|
|
16
|
+
});
|
|
17
|
+
it("encodes 'abc'", () => {
|
|
18
|
+
strictEqual(encode58("abc"), "ZiCa");
|
|
19
|
+
});
|
|
20
|
+
it("encodes with flickr charset", () => {
|
|
21
|
+
const bitcoin = encode58("Hello World", "bitcoin");
|
|
22
|
+
const flickr = encode58("Hello World", "flickr");
|
|
23
|
+
// Flickr swaps case
|
|
24
|
+
strictEqual(bitcoin !== flickr, true);
|
|
25
|
+
});
|
|
26
|
+
it("encodes with ripple charset", () => {
|
|
27
|
+
const bitcoin = encode58("Hello World", "bitcoin");
|
|
28
|
+
const ripple = encode58("Hello World", "ripple");
|
|
29
|
+
strictEqual(bitcoin !== ripple, true);
|
|
30
|
+
});
|
|
31
|
+
it("encodes UTF-8 characters", () => {
|
|
32
|
+
const input = "こんにちは";
|
|
33
|
+
const encoded = encode58(input);
|
|
34
|
+
const decoded = decode58(encoded);
|
|
35
|
+
strictEqual(decoded, input);
|
|
36
|
+
});
|
|
37
|
+
it("preserves leading zero bytes", () => {
|
|
38
|
+
const input = "\x00\x00Hello";
|
|
39
|
+
const encoded = encode58(input);
|
|
40
|
+
const decoded = decode58(encoded);
|
|
41
|
+
strictEqual(decoded, input);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
describe("Base58 decode58", () => {
|
|
45
|
+
it("decodes empty string", () => {
|
|
46
|
+
strictEqual(decode58(""), "");
|
|
47
|
+
});
|
|
48
|
+
it("decodes 'JxF12TrwUP45BMd' to 'Hello World'", () => {
|
|
49
|
+
strictEqual(decode58("JxF12TrwUP45BMd"), "Hello World");
|
|
50
|
+
});
|
|
51
|
+
it("decodes single character", () => {
|
|
52
|
+
const encoded = encode58("A");
|
|
53
|
+
strictEqual(decode58(encoded), "A");
|
|
54
|
+
});
|
|
55
|
+
it("decodes 'ZiCa' to 'abc'", () => {
|
|
56
|
+
strictEqual(decode58("ZiCa"), "abc");
|
|
57
|
+
});
|
|
58
|
+
it("throws on invalid character (0)", () => {
|
|
59
|
+
throws(() => decode58("0invalid"), /Invalid Base58 character/);
|
|
60
|
+
});
|
|
61
|
+
it("throws on invalid character (O)", () => {
|
|
62
|
+
throws(() => decode58("OOO"), /Invalid Base58 character/);
|
|
63
|
+
});
|
|
64
|
+
it("throws on invalid character (I)", () => {
|
|
65
|
+
throws(() => decode58("III"), /Invalid Base58 character/);
|
|
66
|
+
});
|
|
67
|
+
it("throws on invalid character (l)", () => {
|
|
68
|
+
throws(() => decode58("lll"), /Invalid Base58 character/);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe("Base58 round-trip", () => {
|
|
72
|
+
const testCases = [
|
|
73
|
+
"",
|
|
74
|
+
"a",
|
|
75
|
+
"ab",
|
|
76
|
+
"abc",
|
|
77
|
+
"abcd",
|
|
78
|
+
"Hello, World!",
|
|
79
|
+
"The quick brown fox jumps over the lazy dog",
|
|
80
|
+
"こんにちは世界",
|
|
81
|
+
"🎉🚀✨",
|
|
82
|
+
"\x00\x00\x00abc"
|
|
83
|
+
];
|
|
84
|
+
for (const charset of Base58Charset) {
|
|
85
|
+
describe(`charset: ${charset}`, () => {
|
|
86
|
+
for (const input of testCases) {
|
|
87
|
+
it(`round-trips: ${JSON.stringify(input)}`, () => {
|
|
88
|
+
const encoded = encode58(input, charset);
|
|
89
|
+
const decoded = decode58(encoded, charset);
|
|
90
|
+
strictEqual(decoded, input);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
describe("Base58Charset", () => {
|
|
97
|
+
it("exports array with three charsets", () => {
|
|
98
|
+
strictEqual(Base58Charset.length, 3);
|
|
99
|
+
strictEqual(Base58Charset[0], "bitcoin");
|
|
100
|
+
strictEqual(Base58Charset[1], "flickr");
|
|
101
|
+
strictEqual(Base58Charset[2], "ripple");
|
|
102
|
+
});
|
|
103
|
+
it("charset type works correctly", () => {
|
|
104
|
+
const cs = "flickr";
|
|
105
|
+
strictEqual(encode58("test", cs), encode58("test", "flickr"));
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
//# sourceMappingURL=base58.test.js.map
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { describe, it } from "node:test";
|
|
2
|
+
import { strictEqual, throws } from "node:assert";
|
|
3
|
+
import { encode58, decode58, Base58Charset } from "./base58.js";
|
|
4
|
+
import type { Base58CharsetType } from "./base58.js";
|
|
5
|
+
|
|
6
|
+
describe("Base58 encode58", () => {
|
|
7
|
+
it("encodes empty string", () => {
|
|
8
|
+
strictEqual(encode58(""), "");
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("encodes 'Hello World' with bitcoin charset", () => {
|
|
12
|
+
strictEqual(encode58("Hello World"), "JxF12TrwUP45BMd");
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("encodes single character", () => {
|
|
16
|
+
// Verify round-trip rather than hardcoded value
|
|
17
|
+
const encoded = encode58("A");
|
|
18
|
+
strictEqual(encoded.length > 0, true);
|
|
19
|
+
strictEqual(decode58(encoded), "A");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("encodes 'abc'", () => {
|
|
23
|
+
strictEqual(encode58("abc"), "ZiCa");
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("encodes with flickr charset", () => {
|
|
27
|
+
const bitcoin = encode58("Hello World", "bitcoin");
|
|
28
|
+
const flickr = encode58("Hello World", "flickr");
|
|
29
|
+
// Flickr swaps case
|
|
30
|
+
strictEqual(bitcoin !== flickr, true);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("encodes with ripple charset", () => {
|
|
34
|
+
const bitcoin = encode58("Hello World", "bitcoin");
|
|
35
|
+
const ripple = encode58("Hello World", "ripple");
|
|
36
|
+
strictEqual(bitcoin !== ripple, true);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("encodes UTF-8 characters", () => {
|
|
40
|
+
const input = "こんにちは";
|
|
41
|
+
const encoded = encode58(input);
|
|
42
|
+
const decoded = decode58(encoded);
|
|
43
|
+
strictEqual(decoded, input);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("preserves leading zero bytes", () => {
|
|
47
|
+
const input = "\x00\x00Hello";
|
|
48
|
+
const encoded = encode58(input);
|
|
49
|
+
const decoded = decode58(encoded);
|
|
50
|
+
strictEqual(decoded, input);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
describe("Base58 decode58", () => {
|
|
55
|
+
it("decodes empty string", () => {
|
|
56
|
+
strictEqual(decode58(""), "");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("decodes 'JxF12TrwUP45BMd' to 'Hello World'", () => {
|
|
60
|
+
strictEqual(decode58("JxF12TrwUP45BMd"), "Hello World");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("decodes single character", () => {
|
|
64
|
+
const encoded = encode58("A");
|
|
65
|
+
strictEqual(decode58(encoded), "A");
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("decodes 'ZiCa' to 'abc'", () => {
|
|
69
|
+
strictEqual(decode58("ZiCa"), "abc");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("throws on invalid character (0)", () => {
|
|
73
|
+
throws(() => decode58("0invalid"), /Invalid Base58 character/);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("throws on invalid character (O)", () => {
|
|
77
|
+
throws(() => decode58("OOO"), /Invalid Base58 character/);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("throws on invalid character (I)", () => {
|
|
81
|
+
throws(() => decode58("III"), /Invalid Base58 character/);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("throws on invalid character (l)", () => {
|
|
85
|
+
throws(() => decode58("lll"), /Invalid Base58 character/);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
describe("Base58 round-trip", () => {
|
|
90
|
+
const testCases = [
|
|
91
|
+
"",
|
|
92
|
+
"a",
|
|
93
|
+
"ab",
|
|
94
|
+
"abc",
|
|
95
|
+
"abcd",
|
|
96
|
+
"Hello, World!",
|
|
97
|
+
"The quick brown fox jumps over the lazy dog",
|
|
98
|
+
"こんにちは世界",
|
|
99
|
+
"🎉🚀✨",
|
|
100
|
+
"\x00\x00\x00abc"
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
for (const charset of Base58Charset) {
|
|
104
|
+
describe(`charset: ${charset}`, () => {
|
|
105
|
+
for (const input of testCases) {
|
|
106
|
+
it(`round-trips: ${JSON.stringify(input)}`, () => {
|
|
107
|
+
const encoded = encode58(input, charset);
|
|
108
|
+
const decoded = decode58(encoded, charset);
|
|
109
|
+
strictEqual(decoded, input);
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe("Base58Charset", () => {
|
|
117
|
+
it("exports array with three charsets", () => {
|
|
118
|
+
strictEqual(Base58Charset.length, 3);
|
|
119
|
+
strictEqual(Base58Charset[0], "bitcoin");
|
|
120
|
+
strictEqual(Base58Charset[1], "flickr");
|
|
121
|
+
strictEqual(Base58Charset[2], "ripple");
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("charset type works correctly", () => {
|
|
125
|
+
const cs: Base58CharsetType = "flickr";
|
|
126
|
+
strictEqual(encode58("test", cs), encode58("test", "flickr"));
|
|
127
|
+
});
|
|
128
|
+
});
|