Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add evaluate tx #22

Merged
merged 3 commits into from
Feb 24, 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

- Support for Tx Submission
- Support for Tx Evaluation

## [v0.1.0](https://github.com/wowica/xogmios/releases/tag/v0.1.0) (2024-02-13)

Expand Down
33 changes: 26 additions & 7 deletions lib/xogmios/tx_submission.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ defmodule Xogmios.TxSubmission do
alias Xogmios.TxSubmission.Response
alias Xogmios.TxSubmission.Server

@tx_submit_timeout 2_000
@request_timeout 2_000

@doc """
Starts a new Tx Submission process linked to the current process.
Expand All @@ -29,18 +29,37 @@ defmodule Xogmios.TxSubmission do
"""
@spec submit_tx(pid() | atom(), String.t()) :: {:ok, any()} | {:error, any()}
def submit_tx(client \\ __MODULE__, cbor) do
with {:ok, message} <- build_message(cbor),
{:ok, %Response{} = response} <- call_tx_submission(client, message) do
with {:ok, message} <- build_submit_message(cbor),
{:ok, %Response{} = response} <- call(client, message) do
{:ok, response.result}
end
end

defp build_message(cbor),
@doc """
Evaluates the execution units of scripts present in a given transaction.

This function is synchronous and takes two arguments:

1. (Optional) A process reference. If none given, it defaults to the linked process `__MODULE__`.
2. The CBOR of a transaction. Unlike `submit_tx/1`, this function does not expect the transaction to be signed. Please refer to the [official Ogmios docs](https://ogmios.dev/mini-protocols/local-tx-submission/#evaluating-transactions) for more details on the type of transaction that is accepted.
"""
@spec evaluate_tx(pid() | atom(), String.t()) :: {:ok, any()} | {:error, any()}
def evaluate_tx(client \\ __MODULE__, cbor) do
with {:ok, message} <- build_evaluate_message(cbor),
{:ok, %Response{} = response} <- call(client, message) do
{:ok, response.result}
end
end

defp build_submit_message(cbor),
do: {:ok, Messages.submit_tx(cbor)}

defp call_tx_submission(client, message) do
defp build_evaluate_message(cbor),
do: {:ok, Messages.evaluate_tx(cbor)}

defp call(client, message) do
try do
case GenServer.call(client, {:submit_tx, message}, @tx_submit_timeout) do
case GenServer.call(client, {:send, message}, @request_timeout) do
{:ok, response} -> {:ok, response}
{:error, reason} -> {:error, reason}
end
Expand Down Expand Up @@ -69,7 +88,7 @@ defmodule Xogmios.TxSubmission do
end

@impl true
def handle_call({:submit_tx, message}, from, state) do
def handle_call({:send, message}, from, state) do
{:store_caller, _from} = send(state.ws_pid, {:store_caller, from})
:ok = :websocket_client.send(state.ws_pid, {:text, message})
{:noreply, state}
Expand Down
17 changes: 17 additions & 0 deletions lib/xogmios/tx_submission/messages.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,23 @@ defmodule Xogmios.TxSubmission.Messages do
json
end

def evaluate_tx(cbor) do
json = ~s"""
{
"jsonrpc": "2.0",
"method": "evaluateTransaction",
"params": {
"transaction": {
"cbor": "#{cbor}"
}
}
}
"""

validate_json!(json)
json
end

defp validate_json!(json) do
case Jason.decode(json) do
{:ok, _decoded} -> :ok
Expand Down
41 changes: 31 additions & 10 deletions test/support/tx_submission/test_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,26 @@ defmodule TxSubmission.TestHandler do
{:ok, state}
end

@valid_cbor_value %{
"method" => "submitTransaction",
"params" => %{"transaction" => %{"cbor" => "valid-cbor-value"}}
}

@invalid_cbor_value %{
"method" => "submitTransaction",
"params" => %{"transaction" => %{"cbor" => "invalid-cbor-value"}}
}

@valid_tx_evaluation_cbor %{
"method" => "evaluateTransaction",
"params" => %{"transaction" => %{"cbor" => "valid-cbor-value"}}
}

@impl true
# Sends response back to client
def websocket_handle({:text, payload}, state) do
case Jason.decode(payload) do
{:ok,
%{
"method" => "submitTransaction",
"params" => %{"transaction" => %{"cbor" => "valid-cbor-value"}}
}} ->
{:ok, @valid_cbor_value} ->
payload =
Jason.encode!(%{
"method" => "submitTransaction",
Expand All @@ -36,11 +47,7 @@ defmodule TxSubmission.TestHandler do

{:reply, {:text, payload}, state}

{:ok,
%{
"method" => "submitTransaction",
"params" => %{"transaction" => %{"cbor" => "invalid-cbor-value"}}
}} ->
{:ok, @invalid_cbor_value} ->
# Actual error returned from a malformed CBOR
payload =
Jason.encode!(%{
Expand Down Expand Up @@ -70,6 +77,20 @@ defmodule TxSubmission.TestHandler do

{:reply, {:text, payload}, state}

{:ok, @valid_tx_evaluation_cbor} ->
payload =
Jason.encode!(%{
"method" => "evaluateTransaction",
"result" => [
%{
"budget" => %{"cpu" => 18_563_120, "memory" => 54_404},
"validator" => %{"index" => 0, "purpose" => "spend"}
}
]
})

{:reply, {:text, payload}, state}

result ->
Logger.error("Did not match #{inspect(result)}")
{:reply, {:text, payload}, state}
Expand Down
13 changes: 13 additions & 0 deletions test/tx_submission_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ defmodule Xogmios.TxSubmissionTest do
def submit_tx(pid \\ __MODULE__, cbor) do
TxSubmission.submit_tx(pid, cbor)
end

def evaluate_tx(pid \\ __MODULE__, cbor) do
TxSubmission.evaluate_tx(pid, cbor)
end
end

test "transaction submission" do
Expand All @@ -39,4 +43,13 @@ defmodule Xogmios.TxSubmissionTest do

assert reason =~ "Invalid transaction"
end

test "transaction evaluation" do
pid = start_supervised!({DummyClient, url: @ws_url})
assert is_pid(pid)
Process.sleep(1_000)

assert {:ok, [%{"budget" => _budget, "validator" => _validator}]} =
DummyClient.evaluate_tx(_cbor = "valid-cbor-value")
end
end
Loading