Skip to content
This repository has been archived by the owner on May 14, 2024. It is now read-only.

support getFeeForMessage #2

Merged
merged 6 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,17 @@ jobs:
- name: Run security check
run: |
mix sobelow --config


# Install Solana CLI --------------------------------------------------
- name: Install Solana CLI
run: |
sh -c "$(curl -sSfL https://release.solana.com/stable/install)"

# Set Solana to Path --------------------------------------------------
- name: Set Solana to Path
run: |
echo "/home/runner/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH

# Run the unit tests ----------------------------------------------------
- name: Run unit tests
run: |
Expand Down
11 changes: 11 additions & 0 deletions lib/solana/rpc/request.ex
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,17 @@ defmodule Solana.RPC.Request do
{"getBlock", [start_slot, encode_opts(opts)]}
end

@doc """
Get the fee the network will charge for a transaction
For more information, see [the Solana
docs](https://solana.com/docs/rpc/http/getfeeformessage).
"""
@spec get_fee_for_message(transaction :: Solana.Transaction.t(), opts :: keyword) :: t
def get_fee_for_message(tx = %Solana.Transaction{}, opts \\ []) do
{:ok, message_bin} = Solana.Transaction.to_binary_message(tx)
{"getFeeForMessage", [Base.encode64(message_bin), encode_opts(opts)]}
end

@doc """
Returns a recent block hash from the ledger, and a fee schedule that can be
used to compute the cost of submitting a transaction using it.
Expand Down
17 changes: 17 additions & 0 deletions lib/solana/tx.ex
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,23 @@ defmodule Solana.Transaction do
end
end

def to_binary_message(tx = %__MODULE__{instructions: ixs}) do
wchenNL marked this conversation as resolved.
Show resolved Hide resolved
with {:ok, ixs} <- check_instructions(List.flatten(ixs)) do
accounts = compile_accounts(ixs, tx.payer)
message = encode_message(accounts, tx.blockhash, ixs)

{:ok, :erlang.list_to_binary([message])}
else
{:error, :no_program, idx} ->
Logger.error("Missing program id on instruction at index #{idx}")
{:error, :no_program}

{:error, message, idx} ->
Logger.error("error compiling instruction at index #{idx}: #{inspect(message)}")
{:error, message}
end
end

defp check_instructions(ixs) do
ixs
|> Enum.with_index()
Expand Down
45 changes: 45 additions & 0 deletions test/solana/tx_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,51 @@ defmodule Solana.TransactionTest do
end
end

describe "to_binary_message/1" do
test "succeeds" do
payer = Solana.keypair()
read_only = Solana.keypair()
program = Solana.keypair() |> pubkey!()
blockhash = Solana.keypair() |> pubkey!()

ix = %Instruction{
program: program,
accounts: [%Account{key: pubkey!(payer)}, %Account{key: pubkey!(read_only)}]
}

tx = %Transaction{
payer: pubkey!(payer),
instructions: [ix],
blockhash: blockhash
}

{:ok, message_bin} = Transaction.to_binary_message(tx)

blockhash_set = MapSet.new(:erlang.binary_to_list(blockhash))
message_set = MapSet.new(:erlang.binary_to_list(message_bin))

assert MapSet.subset?(blockhash_set, message_set) == true
end

test "fail because program does not exist" do
payer = Solana.keypair()
read_only = Solana.keypair()
blockhash = Solana.keypair() |> pubkey!()

ix = %Instruction{
accounts: [%Account{key: pubkey!(payer)}, %Account{key: pubkey!(read_only)}]
}

tx = %Transaction{
payer: pubkey!(payer),
instructions: [ix],
blockhash: blockhash
}

assert {:error, :no_program} = Transaction.to_binary_message(tx)
end
end

describe "parse/1" do
test "cannot parse an empty string" do
assert :error = Transaction.parse("")
Expand Down