diff --git a/README.md b/README.md index 0f0ab32..ffcba24 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,13 @@ path = "M/44'/0'/0'" xpub = BlockKeys.CKD.derive(root_key, path) ``` +### Litecoin + +``` +path = "M/44'/2'/0'" +xpub = BlockKeys.CKD.derive(root_key, path) +``` + ### Ethereum ``` @@ -120,6 +127,13 @@ path = "M/0/0" address = BlockKeys.Bitcoin.address(xpub, path) ``` +### Litecoin + +``` +path = "M/0/0" +address = BlockKeys.Litecoin.address(xpub, path) +``` + ### Ethereum ``` diff --git a/lib/block_keys/litecoin/address.ex b/lib/block_keys/litecoin/address.ex new file mode 100644 index 0000000..08468f2 --- /dev/null +++ b/lib/block_keys/litecoin/address.ex @@ -0,0 +1,22 @@ +defmodule BlockKeys.Litecoin.Address do + @moduledoc """ + Converts a public extended key into a Litecoin Address + """ + + alias BlockKeys.{Crypto, Encoding} + + def from_xpub(xpub) do + xpub + |> maybe_decode() + |> Crypto.hash160() + |> Encoding.base58_encode(<<48>>) + end + + defp maybe_decode(<<"xpub", _rest::binary>> = encoded_key) do + encoded_key + |> Encoding.decode_extended_key() + |> Map.fetch!(:key) + end + + defp maybe_decode(key), do: key +end diff --git a/lib/block_keys/litecoin/litecoin.ex b/lib/block_keys/litecoin/litecoin.ex new file mode 100644 index 0000000..7c4f369 --- /dev/null +++ b/lib/block_keys/litecoin/litecoin.ex @@ -0,0 +1,13 @@ +defmodule BlockKeys.Litecoin do + @moduledoc """ + Helper module to derive and convert to a Litecoin Address + """ + + alias BlockKeys.Litecoin.Address + alias BlockKeys.CKD + + def address(key, path) do + CKD.derive(key, path) + |> Address.from_xpub() + end +end diff --git a/test/block_keys/litecoin/address_test.exs b/test/block_keys/litecoin/address_test.exs new file mode 100644 index 0000000..46986dd --- /dev/null +++ b/test/block_keys/litecoin/address_test.exs @@ -0,0 +1,24 @@ +defmodule LitecoinAddressTest do + use ExUnit.Case, async: true + + alias BlockKeys.Litecoin.Address + alias BlockKeys.CKD + + test "generate address from public key" do + xpub = + "xpub6C35qtG2zHpXwVKjpEmTjam5igvoQh2bYkPNdYrCekv44W3ioNi8DJ7zAXTuWgYCbm57ZZRhgiwC56dCYvzfur7pxwKQhcgqga7fafdeH4q" + + assert Address.from_xpub(xpub) == "LaFTXS4cTPZGRf2ie6wDsG7S6RVuXYSW9A" + end + + test "generates the first address for BIP44 path" do + path = "M/44'/2'/0'/0/0" + + xprv = + "xprv9s21ZrQH143K4RdNK1f51Rdeu4XRG8q2cgzeh7ejtzgYpdZcHpNb1MJ2DdBa4iX6NVoZZajsC4gr26mLFaHGBrrtvGkxwhGh6ng8HVZRSeV" + + xpub = CKD.derive(xprv, path) + + assert Address.from_xpub(xpub) == "LdWaYyadtKgZmfg5tf1fPj9m5FQq3Hdc1K" + end +end