Secure, audited & 0-dep implementation of base encoding algorithms
—
Base58 encodings designed primarily for cryptocurrency applications. Base58 eliminates ambiguous characters (0, O, I, l) and offers various alphabet variants for different systems. Note that base58 has O(n^2) complexity and should only be used with small, constant-sized inputs.
Standard base58 encoding using Bitcoin's alphabet.
/**
* base58: base64 without ambiguous characters +, /, 0, O, I, l
* Uses Bitcoin alphabet: 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
* Quadratic O(n^2) complexity - use only with small inputs
*/
const base58: BytesCoder = {
encode: (data: Uint8Array) => string;
decode: (str: string) => Uint8Array;
};Usage Examples:
import { base58 } from "@scure/base";
const data = new Uint8Array([0x01, 0xab, 0xcd, 0xef]);
const encoded = base58.encode(data); // "3UhJW"
const decoded = base58.decode("3UhJW"); // Uint8Array([0x01, 0xab, 0xcd, 0xef])Flickr variant of base58 with case-swapped alphabet.
/**
* base58: flickr version with different alphabet
* Uses Flickr alphabet: 123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ
* Quadratic O(n^2) complexity - use only with small inputs
*/
const base58flickr: BytesCoder = {
encode: (data: Uint8Array) => string;
decode: (str: string) => Uint8Array;
};XRP (Ripple) variant of base58 with custom alphabet.
/**
* base58: XRP version with custom alphabet
* Uses XRP alphabet: rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz
* Quadratic O(n^2) complexity - use only with small inputs
*/
const base58xrp: BytesCoder = {
encode: (data: Uint8Array) => string;
decode: (str: string) => Uint8Array;
};Monero variant of base58 with optimized block processing to reduce quadratic complexity.
/**
* base58: XMR (Monero) version with block processing optimization
* Processes data in 8-byte blocks (11 chars in decoding)
* Block encoding significantly reduces quadratic complexity
* Last non-full block padded with '1' to appropriate size
*/
const base58xmr: BytesCoder = {
encode: (data: Uint8Array) => string;
decode: (str: string) => Uint8Array;
};Usage Examples:
import { base58xmr } from "@scure/base";
// More efficient for longer data due to block processing
const data = new Uint8Array(32); // 32 bytes of data
const encoded = base58xmr.encode(data);
const decoded = base58xmr.decode(encoded);Base58 with double SHA-256 checksum validation. Requires providing a SHA-256 hash function.
/**
* Creates base58check encoder with SHA-256 checksum validation
* Appends 4-byte double SHA-256 checksum for error detection
* @param sha256 - SHA-256 hash function
* @returns BytesCoder with checksum validation
*/
function createBase58check(
sha256: (data: Uint8Array) => Uint8Array
): BytesCoder;Usage Examples:
import { createBase58check } from "@scure/base";
import { sha256 } from "@noble/hashes/sha2";
const base58check = createBase58check(sha256);
const data = new Uint8Array([0x12, 0x34, 0x56]);
const encoded = base58check.encode(data);
const decoded = base58check.decode(encoded);
// Checksum validation happens automatically during decode
try {
base58check.decode("invalid_checksum"); // Throws error
} catch (error) {
console.log("Invalid checksum detected");
}Advanced Usage with Bitcoin Addresses:
import { createBase58check } from "@scure/base";
import { sha256 } from "@noble/hashes/sha2";
const base58check = createBase58check(sha256);
// Example: Bitcoin address creation (simplified)
function createBitcoinAddress(publicKeyHash: Uint8Array): string {
// Add version byte (0x00 for mainnet)
const payload = new Uint8Array([0x00, ...publicKeyHash]);
return base58check.encode(payload);
}
function decodeBitcoinAddress(address: string): { version: number; hash: Uint8Array } {
const decoded = base58check.decode(address);
return {
version: decoded[0],
hash: decoded.slice(1)
};
}Deprecated alias for createBase58check.
/**
* @deprecated Use createBase58check instead
* Legacy alias for createBase58check function
*/
const base58check: (sha256: (data: Uint8Array) => Uint8Array) => BytesCoder;Base58 encodings have quadratic O(n^2) time complexity due to arbitrary radix conversion. This can cause performance issues or DoS attacks with large variable-length inputs.
Recommendations:
import { base58, base64 } from "@scure/base";
// Good: Small, constant-sized data (32 bytes)
const hash = new Uint8Array(32);
const encoded = base58.encode(hash); // Fast
// Avoid: Large variable-length data
const largeData = new Uint8Array(10000); // This will be slow!
const encoded = base64.encode(largeData); // Use base64 insteadBase58 encoders validate input and provide detailed error messages:
import { base58, createBase58check } from "@scure/base";
import { sha256 } from "@noble/hashes/sha2";
try {
base58.decode("0OIl"); // Contains ambiguous characters
} catch (error) {
console.log(error.message); // "Unknown letter: ..."
}
const base58check = createBase58check(sha256);
try {
base58check.decode("corrupted_data"); // Invalid checksum
} catch (error) {
console.log(error.message); // "Invalid checksum"
}Install with Tessl CLI
npx tessl i tessl/npm-scure--base