Skip to content

Commit d626069

Browse files
Merge pull request #27 from sovereignbase/feat/issue-25-base58
Base58 and Base58BTC support.
2 parents 49de3a8 + 49438d5 commit d626069

File tree

17 files changed

+752
-78
lines changed

17 files changed

+752
-78
lines changed

README.md

Lines changed: 63 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
# bytecodec
77

8-
Typed JavaScript and TypeScript byte utilities for base64, base64url, hex, Z85, UTF-8 strings, unsigned BigInt conversion, JSON, gzip, concatenation, comparison, and byte-source normalization. The package ships tree-shakeable ESM plus CommonJS entry points and keeps the same API across Node, Bun, Deno, browsers, and edge runtimes.
8+
Typed JavaScript and TypeScript byte utilities for base58, base58btc, base64, base64url, hex, Z85, UTF-8 strings, unsigned BigInt conversion, JSON, gzip, concatenation, comparison, and byte-source normalization. The package ships tree-shakeable ESM plus CommonJS entry points and keeps the same API across Node, Bun, Deno, browsers, and edge runtimes.
99

1010
## Compatibility
1111

@@ -17,7 +17,7 @@ Typed JavaScript and TypeScript byte utilities for base64, base64url, hex, Z85,
1717

1818
## Goals
1919

20-
- Developer-friendly API for base64, base64url, hex, Z85, UTF-8, unsigned BigInt conversion, JSON, gzip, concat, equality, and byte normalization.
20+
- Developer-friendly API for base58, base58btc, base64, base64url, hex, Z85, UTF-8, unsigned BigInt conversion, JSON, gzip, concat, equality, and byte normalization.
2121
- No runtime dependencies or bundler shims.
2222
- Tree-shakeable ESM by default with CommonJS compatibility and no side effects.
2323
- Returns copies for safety when normalizing inputs.
@@ -60,6 +60,28 @@ const encoded = toBase64String(bytes) // string of base64 chars
6060
const decoded = fromBase64String(encoded) // Uint8Array
6161
```
6262

63+
### Base58
64+
65+
```js
66+
import { toBase58String, fromBase58String } from '@sovereignbase/bytecodec'
67+
68+
const bytes = new Uint8Array([104, 101, 108, 108, 111])
69+
const encoded = toBase58String(bytes) // "Cn8eVZg"
70+
const decoded = fromBase58String(encoded) // Uint8Array
71+
```
72+
73+
### Base58btc
74+
75+
```js
76+
import { toBase58BtcString, fromBase58BtcString } from '@sovereignbase/bytecodec'
77+
78+
const bytes = new Uint8Array([104, 101, 108, 108, 111])
79+
const encoded = toBase58BtcString(bytes) // "zCn8eVZg"
80+
const decoded = fromBase58BtcString(encoded) // Uint8Array
81+
```
82+
83+
`base58btc` uses the Bitcoin base58 alphabet and adds the multibase `z` prefix.
84+
6385
### CommonJS
6486

6587
```js
@@ -184,7 +206,7 @@ const joined = concat([new Uint8Array([1, 2]), new Uint8Array([3, 4]), [5, 6]])
184206

185207
### Node
186208

187-
Uses `Buffer.from` for base64 helpers, `TextEncoder` and `TextDecoder` when available with `Buffer` fallback for UTF-8, and `node:zlib` for gzip.
209+
Uses pure JavaScript for base58/base58btc, `Buffer.from` for base64 helpers, `TextEncoder` and `TextDecoder` when available with `Buffer` fallback for UTF-8, and `node:zlib` for gzip.
188210

189211
### Bun
190212

@@ -196,7 +218,7 @@ Uses `TextEncoder`, `TextDecoder`, `btoa`, and `atob`. Gzip uses `CompressionStr
196218

197219
### Validation & errors
198220

199-
Validation failures throw `BytecodecError` instances with a `code` string, for example `BASE64URL_INVALID_LENGTH`, `BIGINT_UNSIGNED_EXPECTED`, `HEX_INVALID_CHARACTER`, `Z85_INVALID_BLOCK`, `BASE64_DECODER_UNAVAILABLE`, `UTF8_DECODER_UNAVAILABLE`, and `GZIP_COMPRESSION_UNAVAILABLE`. Messages are prefixed with `{@sovereignbase/bytecodec}`.
221+
Validation failures throw `BytecodecError` instances with a `code` string, for example `BASE58_INVALID_CHARACTER`, `BASE58BTC_INVALID_PREFIX`, `BASE64URL_INVALID_LENGTH`, `BIGINT_UNSIGNED_EXPECTED`, `HEX_INVALID_CHARACTER`, `Z85_INVALID_BLOCK`, `BASE64_DECODER_UNAVAILABLE`, `UTF8_DECODER_UNAVAILABLE`, and `GZIP_COMPRESSION_UNAVAILABLE`. Messages are prefixed with `{@sovereignbase/bytecodec}`.
200222

201223
### Safety / copying semantics
202224

@@ -206,44 +228,48 @@ Validation failures throw `BytecodecError` instances with a `code` string, for e
206228

207229
`npm test` covers:
208230

209-
- 75 unit tests
210-
- 7 integration tests
211-
- Node E2E: 23/23 passed in ESM and 23/23 passed in CommonJS
212-
- Bun E2E: 23/23 passed in ESM and 23/23 passed in CommonJS
213-
- Deno E2E: 23/23 passed in ESM
214-
- Cloudflare Workers E2E: 23/23 passed in ESM
215-
- Edge Runtime E2E: 23/23 passed in ESM
231+
- 85 unit tests
232+
- 9 integration tests
233+
- Node E2E: 27/27 passed in ESM and 27/27 passed in CommonJS
234+
- Bun E2E: 27/27 passed in ESM and 27/27 passed in CommonJS
235+
- Deno E2E: 27/27 passed in ESM
236+
- Cloudflare Workers E2E: 27/27 passed in ESM
237+
- Edge Runtime E2E: 27/27 passed in ESM
216238
- Browser E2E: 5/5 passed in Chromium, Firefox, WebKit, mobile-chrome, and mobile-safari
217239
- Coverage gate: 100% statements, branches, functions, and lines
218240

219241
## Benchmarks
220242

221-
Latest local `npm run bench` run on 2026-03-27 with Node `v22.14.0 (win32 x64)`:
222-
223-
| Benchmark | Result |
224-
| ---------------- | ------------------------- |
225-
| base64 encode | 979,522 ops/s (51.0 ms) |
226-
| base64 decode | 1,825,737 ops/s (27.4 ms) |
227-
| base64url encode | 407,973 ops/s (122.6 ms) |
228-
| base64url decode | 560,991 ops/s (89.1 ms) |
229-
| hex encode | 781,944 ops/s (63.9 ms) |
230-
| hex decode | 806,002 ops/s (62.0 ms) |
231-
| z85 encode | 170,125 ops/s (293.9 ms) |
232-
| z85 decode | 1,141,472 ops/s (43.8 ms) |
233-
| utf8 encode | 1,241,977 ops/s (40.3 ms) |
234-
| utf8 decode | 2,610,407 ops/s (19.2 ms) |
235-
| bigint encode | 490,692 ops/s (101.9 ms) |
236-
| bigint decode | 428,938 ops/s (116.6 ms) |
237-
| json encode | 588,066 ops/s (34.0 ms) |
238-
| json decode | 603,058 ops/s (33.2 ms) |
239-
| concat 3 buffers | 560,639 ops/s (89.2 ms) |
240-
| toUint8Array | 6,292,910 ops/s (31.8 ms) |
241-
| toArrayBuffer | 677,822 ops/s (295.1 ms) |
242-
| toBufferSource | 7,465,472 ops/s (26.8 ms) |
243-
| equals same | 2,217,064 ops/s (90.2 ms) |
244-
| equals diff | 2,302,002 ops/s (86.9 ms) |
245-
| gzip compress | 3,473 ops/s (115.2 ms) |
246-
| gzip decompress | 4,753 ops/s (84.2 ms) |
243+
Latest local `npm run bench` run on 2026-04-17 with Node `v22.14.0 (win32 x64)`. Each benchmark uses the same `5,000` operations:
244+
245+
| Benchmark | Ops | Ms | Ms/Op | Ops/Sec |
246+
| ---------------- | ----- | -------- | -------- | --------- |
247+
| base58 encode | 5,000 | 378.548 | 0.075710 | 13,208 |
248+
| base58 decode | 5,000 | 64.313 | 0.012863 | 77,745 |
249+
| base58btc encode | 5,000 | 318.044 | 0.063609 | 15,721 |
250+
| base58btc decode | 5,000 | 56.138 | 0.011228 | 89,066 |
251+
| base64 encode | 5,000 | 16.971 | 0.003394 | 294,629 |
252+
| base64 decode | 5,000 | 13.244 | 0.002649 | 377,541 |
253+
| base64url encode | 5,000 | 23.162 | 0.004632 | 215,867 |
254+
| base64url decode | 5,000 | 22.993 | 0.004599 | 217,454 |
255+
| hex encode | 5,000 | 18.494 | 0.003699 | 270,361 |
256+
| hex decode | 5,000 | 10.099 | 0.002020 | 495,084 |
257+
| z85 encode | 5,000 | 65.417 | 0.013083 | 76,433 |
258+
| z85 decode | 5,000 | 11.928 | 0.002386 | 419,171 |
259+
| utf8 encode | 5,000 | 9.949 | 0.001990 | 502,583 |
260+
| utf8 decode | 5,000 | 4.835 | 0.000967 | 1,034,105 |
261+
| bigint encode | 5,000 | 17.098 | 0.003420 | 292,435 |
262+
| bigint decode | 5,000 | 21.104 | 0.004221 | 236,922 |
263+
| json encode | 5,000 | 10.640 | 0.002128 | 469,912 |
264+
| json decode | 5,000 | 11.192 | 0.002238 | 446,740 |
265+
| concat 3 buffers | 5,000 | 28.862 | 0.005772 | 173,240 |
266+
| toUint8Array | 5,000 | 4.866 | 0.000973 | 1,027,475 |
267+
| toArrayBuffer | 5,000 | 13.325 | 0.002665 | 375,229 |
268+
| toBufferSource | 5,000 | 3.412 | 0.000682 | 1,465,373 |
269+
| equals same | 5,000 | 9.302 | 0.001860 | 537,536 |
270+
| equals diff | 5,000 | 5.908 | 0.001182 | 846,267 |
271+
| gzip compress | 5,000 | 1370.000 | 0.274000 | 3,650 |
272+
| gzip decompress | 5,000 | 1493.242 | 0.298648 | 3,348 |
247273

248274
Results vary by machine and Node version.
249275

0 commit comments

Comments
 (0)