lib/solana/ix.ex

defmodule Solana.Instruction do
  @moduledoc """
  Functions, types, and structures related to Solana
  [instructions](https://docs.solana.com/developing/programming-model/transactions#instructions).
  """
  alias Solana.Account

  @typedoc """
  All the details needed to encode an instruction.
  """
  @type t :: %__MODULE__{
          program: Solana.key() | nil,
          accounts: [Account.t()],
          data: binary | nil
        }

  defstruct [
    :data,
    :program,
    accounts: []
  ]

  @doc false
  def encode_data(data) do
    Enum.into(data, <<>>, &encode_value/1)
  end

  # encodes a string in Rust's expected format
  defp encode_value({value, "str"}) when is_binary(value) do
    <<byte_size(value)::little-size(32), 0::32, value::binary>>
  end

  defp encode_value({value, size}), do: encode_value({value, size, :little})
  defp encode_value({value, size, :big}), do: <<value::size(size)-big>>
  defp encode_value({value, size, :little}), do: <<value::size(size)-little>>
  defp encode_value(value) when is_binary(value), do: value
  defp encode_value(value) when is_integer(value), do: <<value>>
end