Module: Solana::Ruby::Kit::Encoding::Base58

Extended by:
T::Sig
Defined in:
lib/solana/ruby/kit/encoding/base58.rb

Overview

Base58 codec using the Bitcoin/Solana alphabet (no check bytes). This module provides the shared base58 encoding used by both Solana::Ruby::Kit::Addresses and Solana::Ruby::Kit::Keys::Signatures.

Constant Summary collapse

ALPHABET =
T.let(
  '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz',
  String
)

Class Method Summary collapse

Class Method Details

.decode(str) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/solana/ruby/kit/encoding/base58.rb', line 40

def decode(str)
  # Each leading '1' maps to a leading zero byte.
  leading_zeros = 0
  str.each_char { |c| c == '1' ? leading_zeros += 1 : break }

  n = 0
  str.each_char do |c|
    idx = ALPHABET.index(c)
    Kernel.raise ArgumentError, "Invalid base58 character: #{c.inspect}" if idx.nil?

    n = n * 58 + idx
  end

  # Convert integer back to a big-endian byte string.
  hex = n.zero? ? '' : n.to_s(16)
  hex = hex.rjust((hex.length + 1) & ~1, '0')  # guarantee even hex length

  raw = [hex].pack('H*')
  ("\x00" * leading_zeros + raw).b
end

.encode(bytes) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/solana/ruby/kit/encoding/base58.rb', line 20

def encode(bytes)
  # Each leading zero byte maps to a leading '1'.
  leading_ones = 0
  bytes.each_byte { |b| b == 0 ? leading_ones += 1 : break }

  # Convert big-endian byte string to an integer.
  n = bytes.unpack1('H*').to_i(16)

  result = +''
  while n > 0
    result.prepend(T.must(ALPHABET[n % 58]))
    n /= 58
  end

  ('1' * leading_ones) + result
end