from __future__ import annotations try: # Prefer external package if available from base58 import b58encode, b58decode # type: ignore except Exception: # Minimal fallback (compatible subset) ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" ALPHABET_INDEX = {c: i for i, c in enumerate(ALPHABET)} def _to_bytes(value: bytes | bytearray | str) -> bytes: if isinstance(value, (bytes, bytearray)): return bytes(value) if isinstance(value, str): return value.encode() raise TypeError("value must be bytes or str") def b58encode(data: bytes | bytearray | str) -> bytes: data = _to_bytes(data) if not data: return b"" n = int.from_bytes(data, "big") out = [] while n > 0: n, rem = divmod(n, 58) out.append(ALPHABET[rem]) enc = "".join(reversed(out)) leading = 0 for b in data: if b == 0: leading += 1 else: break return ("1" * leading + enc).encode() def b58decode(data: bytes | bytearray | str) -> bytes: data_b = _to_bytes(data) if not data_b: return b"" num = 0 for ch in data_b.decode(): num = num * 58 + ALPHABET_INDEX[ch] full = num.to_bytes((num.bit_length() + 7) // 8, "big") leading = 0 for ch in data_b: if ch == ord('1'): leading += 1 else: break return b"\x00" * leading + full