Skip to content
markpaper

src/address/base58.ts

v0.1.0 · 1.7 KB

Download file
// Canonical base58 addresses are case-sensitive.
const ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; // privacy-allow: public canonical base58 alphabet
const INDEX = new Map<string, number>([...ALPHABET].map((c, i) => [c, i]));
export function base58Decode(s: string): Uint8Array | null {
  if (typeof s !== 'string' || s.length === 0 || s.length > 128) return null;
  const bytes: number[] = [];
  for (const ch of s) {
    const v = INDEX.get(ch);
    if (v === undefined) return null;
    let carry = v;
    for (let i = 0; i < bytes.length; i++) {
      carry += bytes[i]! * 58;
      bytes[i] = carry & 0xff;
      carry >>= 8;
    }
    while (carry > 0) {
      bytes.push(carry & 0xff);
      carry >>= 8;
    }
  }
  for (let i = 0; i < s.length && s[i] === '1'; i++) bytes.push(0);
  return Uint8Array.from(bytes.reverse());
}
export function base58Encode(data: Uint8Array): string {
  const digits: number[] = [];
  for (const byte of data) {
    let carry = byte;
    for (let i = 0; i < digits.length; i++) {
      carry += digits[i]! << 8;
      digits[i] = carry % 58;
      carry = Math.floor(carry / 58);
    }
    while (carry > 0) {
      digits.push(carry % 58);
      carry = Math.floor(carry / 58);
    }
  }
  let out = '';
  for (let i = 0; i < data.length && data[i] === 0; i++) out += '1';
  for (let i = digits.length - 1; i >= 0; i--) out += ALPHABET[digits[i]!];
  return out;
}
export function isBase58Pubkey(s: string): boolean {
  const b = base58Decode(s);
  return b !== null && b.length === 32 && base58Encode(b) === s;
}

export function isSignatureString(s: string): boolean {
  const b = base58Decode(s);
  return b !== null && b.length === 64 && base58Encode(b) === s;
}
All files