I'm trying to encode hex to base58. It works with js library base-x
with hex = 1777c7ba65e23151ec09125011dd25c28998c70230e7b89ca6
Expected
base58 = AShDKgLSuCjGZr8Fs5SRLSYvmcSV7S4zwX
Got
base58 = cAvfov2bvPACeGktuSEtz6G526UBfCwpia1354fp5bYJwP2rhhnxqYkRcwRoDrmgqZaG
defmodule Base58 do
@alphabet '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
def encode(data, hash \\ "")
def encode(data, hash) when is_binary(data) do
encode_zeros(data) <> encode(:binary.decode_unsigned(data), hash)
end
def encode(0, hash), do: hash
def encode(data, hash) do
character = <<Enum.at(@alphabet, rem(data, 58))>>
encode(div(data, 58), character <> hash)
end
defp encode_zeros(data) do
<<Enum.at(@alphabet, 0)>>
|> String.duplicate(leading_zeros(data))
end
defp leading_zeros(data) do
:binary.bin_to_list(data)
|> Enum.find_index(&(&1 != 0))
end
end
What's happening is that the input is supposed to be the chunk of binary data represented by those hexadecimal digits, but you passed the string containing the hexadecimal digits to Base58.encode
instead. You get the expected result if you pass the input as an integer (using the 0x
prefix to mark it as a hexadecimal literal integer):
iex(2)> Base58.encode("1777c7ba65e23151ec09125011dd25c28998c70230e7b89ca6")
"cAvfov2bvPACeGktuSEtz6G526UBfCwpia1354fp5bYJwP2rhhnxqYkRcvTMFJ2ouddX"
iex(3)> Base58.encode(0x1777c7ba65e23151ec09125011dd25c28998c70230e7b89ca6)
"AShDKgLSuCjGZr8Fs5SRLSYvmcSV7S4zwX"
If you already have this data in a string, you can use Integer.parse/2
to convert it to an integer:
iex(5)> with {integer, _} <- Integer.parse("1777c7ba65e23151ec09125011dd25c28998c70230e7b89ca6", 16) do
...(5)> Base58.encode(integer)
...(5)> end
"AShDKgLSuCjGZr8Fs5SRLSYvmcSV7S4zwX"