diff --git a/lib/twetch/transaction.ex b/lib/twetch/transaction.ex index d076a73..ab53b32 100644 --- a/lib/twetch/transaction.ex +++ b/lib/twetch/transaction.ex @@ -2,7 +2,7 @@ defmodule Twetch.Transaction do @moduledoc """ A module for building valid Twetch transactions. """ - alias BSV.Script + alias BSV.{UTXO, Script} alias Twetch.{BProtocol, MAPProtocol, AIPProtocol} def build_op_return_args(content) do @@ -17,6 +17,10 @@ defmodule Twetch.Transaction do script.chunks end + # def build(content, utxo_params, outputs) do + # UTXO.from_params!() |> IO.inspect() + # end + def build_op_return(content, privkey, address) do %Script{} |> Script.push(:OP_FALSE) diff --git a/lib/twetch/utxo.ex b/lib/twetch/utxo.ex index a7309d8..47372b7 100644 --- a/lib/twetch/utxo.ex +++ b/lib/twetch/utxo.ex @@ -2,13 +2,14 @@ defmodule Twetch.UTXO do @moduledoc """ A module for getting your Twetch UTXOs. """ - alias BSV.{ExtKey, PubKey} + alias BSV.{Address, Contract, ExtKey, PubKey, Script, UTXO} @twetch_utxo_url "https://metasync.twetch.app/wallet/utxo" @doc """ Get Twetch account UTXOs. """ + @spec fetch() :: {:ok, list(UTXO.t())} | {:error, any()} def fetch() do with {:ok, pubkey} <- get_pubkey(), {:ok, utxos} <- get_utxos(pubkey) do @@ -26,7 +27,7 @@ defmodule Twetch.UTXO do {:ok, key} -> %{pubkey: pubkey} = ExtKey.derive(key, "m/0/0") - {:ok, PubKey.to_binary(pubkey, encoding: :hex)} + {:ok, pubkey} {:error, _error} -> {:error, "Unable to decode seed; Expecting base64 format"} @@ -36,21 +37,37 @@ defmodule Twetch.UTXO do defp get_utxos(pubkey) do headers = [{"content-type", "application/json"}] - body = JSON.encode!(%{pubkey: pubkey, amount: 1}) + body = JSON.encode!(%{pubkey: PubKey.to_binary(pubkey, encoding: :hex), amount: 1}) case HTTPoison.post(@twetch_utxo_url, body, headers) do {:ok, response} -> + address = Address.from_pubkey(pubkey) + response.body |> JSON.decode() - |> parse_utxos() + |> parse_utxos(address) {:error, error} -> {:error, error} end end - defp parse_utxos({:ok, %{"utxos" => []}}), do: {:error, "No UTXOs found"} - defp parse_utxos({:ok, %{"utxos" => utxos}}), do: {:ok, utxos} - defp parse_utxos({:ok, %{"error" => error}}), do: {:error, error} - defp parse_utxos(_), do: {:error, "Unable to parse Twetch utxos response"} + defp parse_utxos({:ok, %{"utxos" => []}}, _address), do: {:error, "No UTXOs found"} + + defp parse_utxos({:ok, %{"utxos" => utxos}}, address) do + {:ok, Enum.map(utxos, &to_utxo(&1, address))} + end + + defp parse_utxos({:ok, %{"error" => error}}, _address), do: {:error, error} + defp parse_utxos(_garbage, _address), do: {:error, "Unable to parse Twetch utxos response"} + + defp to_utxo(%{"txid" => txid, "vout" => vout, "satoshis" => sats}, address) do + script = + sats + |> Contract.P2PKH.lock(%{address: address}) + |> Contract.to_script() + |> Script.to_binary(encoding: :hex) + + UTXO.from_params!(%{"txid" => txid, "vout" => vout, "satoshis" => sats, "script" => script}) + end end diff --git a/test/twetch/utxo_test.exs b/test/twetch/utxo_test.exs index ce6d503..9f4f513 100644 --- a/test/twetch/utxo_test.exs +++ b/test/twetch/utxo_test.exs @@ -12,22 +12,27 @@ defmodule Twetch.UTXOTest do end test "successfully gets utxos" do - utxos = [ - %{ - "path" => "1", - "satoshis" => "1830713", - "txid" => "1621958979c3f2bd1c51648f9f5ca2527450bd7fc083b36aba7d5f81ffc9f516", - "vout" => 4 - } - ] - - utxo_body = JSON.encode!(%{"utxos" => utxos}) + sats = "1830713" + vout = 4 + + utxo_body = + JSON.encode!(%{ + "utxos" => [ + %{ + "path" => "1", + "satoshis" => sats, + "txid" => "1621958979c3f2bd1c51648f9f5ca2527450bd7fc083b36aba7d5f81ffc9f516", + "vout" => vout + } + ] + }) Mimic.expect(HTTPoison, :post, fn _url, _body, _headers -> {:ok, %HTTPoison.Response{body: utxo_body}} end) - assert {:ok, ^utxos} = UTXO.fetch() + assert {:ok, [utxo]} = UTXO.fetch() + assert %BSV.UTXO{outpoint: %{vout: ^vout}, txout: %{satoshis: ^sats}} = utxo end test "handles no utxos result" do