Current section
Files
Jump to
Current section
Files
lib/sutra/coin_selection.ex
defmodule Sutra.CoinSelection do
@moduledoc """
asd
"""
alias Sutra.Cardano.Asset
alias Sutra.Cardano.Transaction
alias Sutra.Cardano.Transaction.Input
defstruct [:selected_inputs, :change]
@type t() :: %__MODULE__{
selected_inputs: [%Input{}],
change: Asset.t()
}
@spec select_utxos_for_lovelace([Transaction.input()], pos_integer(), Asset.t()) ::
{:ok, __MODULE__.t()} | {:error, String.t()}
def select_utxos_for_lovelace(inputs, to_fill_amount, inital_change \\ %{}) do
to_fill_amount = if to_fill_amount < 0, do: to_fill_amount, else: -to_fill_amount
{new_used_inputs, change, remaining_fill} =
sort_by_lovelace(inputs)
|> Enum.reduce_while({[], inital_change, to_fill_amount}, fn i, {used_inputs, c, r} ->
current_lovelace = Asset.lovelace_of(i.output.value)
curr_change = Asset.add(i.output.value, "lovelace", r)
if current_lovelace + r >= 0,
do: {:halt, {[i | used_inputs], Asset.merge(c, curr_change), 0}},
else: {:cont, {[i | used_inputs], c, r + current_lovelace}}
end)
if remaining_fill < 0 do
{:error, "Not enough inputs to fullfill #{remaining_fill} lovelace"}
else
{:ok,
%__MODULE__{
selected_inputs: new_used_inputs,
change: Asset.only_positive(change)
}}
end
end
def sort_by_lovelace(inputs, order \\ :desc),
do: Enum.sort_by(inputs, fn i -> Asset.lovelace_of(i.output.value) end, order)
end