Skip to content

Commit

Permalink
refactor(rpc): simplify send_operation
Browse files Browse the repository at this point in the history
  • Loading branch information
Awea committed May 8, 2024
1 parent 0237c08 commit 9594217
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 251 deletions.
34 changes: 13 additions & 21 deletions lib/forge_operation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -59,28 +59,20 @@ defmodule Tezex.ForgeOperation do

@spec operation(map()) :: nonempty_binary()
def operation(content) do
encoders = %{
"failing_noop" => &failing_noop/1,
"activate_account" => &activate_account/1,
"reveal" => &reveal/1,
"transaction" => &transaction/1,
"origination" => &origination/1,
"delegation" => &delegation/1,
"endorsement" => &endorsement/1,
"endorsement_with_slot" => &endorsement_with_slot/1,
"register_global_constant" => &register_global_constant/1,
"transfer_ticket" => &transfer_ticket/1,
"smart_rollup_add_messages" => &smart_rollup_add_messages/1,
"smart_rollup_execute_outbox_message" => &smart_rollup_execute_outbox_message/1
}

encoder = encoders[content["kind"]]

if is_nil(encoder) do
raise "No encoder for #{content["kind"]}"
case content["kind"] do
"failing_noop" -> failing_noop(content)
"activate_account" -> activate_account(content)
"reveal" -> reveal(content)
"transaction" -> transaction(content)
"origination" -> origination(content)
"delegation" -> delegation(content)
"endorsement" -> endorsement(content)
"endorsement_with_slot" -> endorsement_with_slot(content)
"register_global_constant" -> register_global_constant(content)
"transfer_ticket" -> transfer_ticket(content)
"smart_rollup_add_messages" -> smart_rollup_add_messages(content)
"smart_rollup_execute_outbox_message" -> smart_rollup_execute_outbox_message(content)
end

encoder.(content)
end

@spec operation_group(map()) :: nonempty_binary()
Expand Down
78 changes: 24 additions & 54 deletions lib/rpc.ex
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
defmodule Tezex.Rpc do
# alias Tezex.Crypto
# alias Tezex.Crypto.Base58Check
# alias Tezex.ForgeOperation
alias Tezex.Crypto
alias Tezex.ForgeOperation
alias Tezex.Rpc
alias Tezex.Transaction

@type t() :: %__MODULE__{
endpoint: binary(),
Expand Down Expand Up @@ -69,61 +67,33 @@ defmodule Tezex.Rpc do

# @genesis_block_time ~U[2018-06-30 10:07:32.000Z]

def build_contract_operation(
%Rpc{} = _rpc,
public_key_hash,
counter,
contract,
amount,
fee,
storage_limit,
gas_limit,
entrypoint,
parameters,
_encoded_private_key
) do
parameters =
cond do
not is_nil(parameters) -> %{entrypoint: entrypoint || "default", value: parameters}
not is_nil(entrypoint) -> %{entrypoint: entrypoint, value: []}
true -> nil
end

%Transaction{
source: public_key_hash,
destination: contract,
amount: Integer.to_string(amount),
storage_limit: Integer.to_string(storage_limit),
gas_limit: Integer.to_string(gas_limit),
counter: Integer.to_string(counter),
fee: Integer.to_string(fee),
kind: "transaction",
parameters: parameters
}
end
def send_operation(%Rpc{} = rpc, contents, wallet_address, encoded_private_key, offset \\ 0) do
{:ok, block_head} = get_block_at_offset(rpc, offset)
branch = binary_part(block_head["hash"], 0, 51)

# def send_operation(%Rpc{} = rpc, operations, encoded_private_key, offset) do
# {:ok, block_head} = get_block_at_offset(rpc, offset)
# block_hash = binary_part(block_head["hash"], 0, 51)
counter = get_next_counter_for_account(rpc, wallet_address)

# forged_operation_group =
# ForgeOperation.operation_group(%{"branch" => block_hash, "contents" => operations})
contents =
contents
|> Enum.with_index()
|> Enum.map(fn {c, i} ->
Map.merge(c, %{"counter" => Integer.to_string(counter + i), "source" => wallet_address})
end)

# op_signature =
# Crypto.sign_message(
# encoded_private_key,
# @operation_group_watermark <> forged_operation_group
# )
operation = %{
"branch" => branch,
"contents" => contents
}

# signed_op_group = forged_operation_group <> op_signature
forged_operation = ForgeOperation.operation_group(operation)

# op_pair = %{bytes: signed_op_group, signature: op_signature}
signature = Crypto.sign_operation(encoded_private_key, forged_operation)
{:ok, decoded_signature} = Crypto.decode_signature(signature)

# # applied = preapply_operation(rpc, block_hash, block_head["protocol"], operations, op_pair)
# # injected_op = inject_operation(rpc, op_pair)
decoded_signature = Base.encode16(decoded_signature, case: :lower)

# # %{results: applied[0], operation_group_id: injected_op = inject_operation(rpc, op_pair)}
# end
inject_operation(rpc, forged_operation, decoded_signature)
end

def get_counter_for_account(%Rpc{} = rpc, address) do
with {:ok, n} <- get(rpc, "/blocks/head/context/contracts/#{address}/counter"),
Expand Down Expand Up @@ -153,7 +123,7 @@ defmodule Tezex.Rpc do
post(rpc, "/injection/operation", forged_operation <> signature)
end

def get(%Rpc{} = rpc, path) do
defp get(%Rpc{} = rpc, path) do
url =
URI.parse(rpc.endpoint)
|> URI.append_path("/chains/#{rpc.chain_id}")
Expand All @@ -168,7 +138,7 @@ defmodule Tezex.Rpc do
end
end

def post(%Rpc{} = rpc, path, body) do
defp post(%Rpc{} = rpc, path, body) do
url =
URI.parse(rpc.endpoint)
# 🚧 Try to reproduce the same API as the rest of this file but it doesn't make sense for the injection endpoint since it doesn't include the /chains/id
Expand Down
52 changes: 0 additions & 52 deletions lib/transaction.ex

This file was deleted.

173 changes: 98 additions & 75 deletions test/rpc_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ defmodule Tezex.RpcTest do
doctest Tezex.Rpc

@endpoint "https://ghostnet.tezos.marigold.dev/"
@ghostnet_1_address "tz1ZW1ZSN4ruXYc3nCon8EaTXp1t3tKWb9Ew"
@ghostnet_1_pkey "edsk33h91RysSBUiYyEWbeRwo41YeZrtMPTNsuZ9nzsYWwiV8CFyKi"
@ghostnet_2_address "tz1cMcDFLgFe2picQbo4DY1i6mZJiVhPCu5B"

test "get_counter_for_account" do
counter =
Expand All @@ -16,84 +19,104 @@ defmodule Tezex.RpcTest do
assert is_integer(counter)
end

test "build_contract_operation" do
rpc = %Rpc{endpoint: @endpoint}
public_key_hash = "tz1b9kV41KV9N3sp69ycLdSoZ2Ak8jXwtNPv"
encoded_private_key = "edsk4TjJWEszkHKono7XMnepVqwi37FrpbVt1KCsifJeAGimxheShG"
counter = Rpc.get_next_counter_for_account(rpc, public_key_hash)
# test "build_contract_operation" do
# rpc = %Rpc{endpoint: @endpoint}
# public_key_hash = "tz1b9kV41KV9N3sp69ycLdSoZ2Ak8jXwtNPv"
# encoded_private_key = "edsk4TjJWEszkHKono7XMnepVqwi37FrpbVt1KCsifJeAGimxheShG"
# counter = Rpc.get_next_counter_for_account(rpc, public_key_hash)

contract = "KT1MFWsAXGUZ4gFkQnjByWjrrVtuQi4Tya8G"
entrypoint = "offer"
gas_limit = 1000
storage_limit = 1000
fee = 1000
amount = 1
# contract = "KT1MFWsAXGUZ4gFkQnjByWjrrVtuQi4Tya8G"
# entrypoint = "offer"
# gas_limit = 1000
# storage_limit = 1000
# fee = 1000
# amount = 1

price = 100
fa_contract = "KT1JzqDsR2eMqhu76uRqAUEuTWj7bbwqa9wY"
token_id = "5"
royalty_address = public_key_hash
royalty_share = 1000
# price = 100
# fa_contract = "KT1JzqDsR2eMqhu76uRqAUEuTWj7bbwqa9wY"
# token_id = "5"
# royalty_address = public_key_hash
# royalty_share = 1000

parameters = %{
prim: "Pair",
args: [
%{
prim: "Pair",
args: [%{string: fa_contract}, %{prim: "Some", args: [%{int: token_id}]}]
},
%{
prim: "Pair",
args: [
%{prim: "Right", args: [%{prim: "Right", args: [%{prim: "Unit"}]}]},
%{
prim: "Pair",
args: [
%{int: Integer.to_string(price)},
%{
prim: "Pair",
args: [
[
%{
prim: "Elt",
args: [
%{string: royalty_address},
%{int: Integer.to_string(royalty_share)}
]
}
],
%{
prim: "Pair",
args: [
%{prim: "None"},
%{
prim: "Pair",
args: [[], %{prim: "Pair", args: [%{prim: "None"}, %{prim: "None"}]}]
}
]
}
]
}
]
}
]
}
]
}
# parameters = %{
# prim: "Pair",
# args: [
# %{
# prim: "Pair",
# args: [%{string: fa_contract}, %{prim: "Some", args: [%{int: token_id}]}]
# },
# %{
# prim: "Pair",
# args: [
# %{prim: "Right", args: [%{prim: "Right", args: [%{prim: "Unit"}]}]},
# %{
# prim: "Pair",
# args: [
# %{int: Integer.to_string(price)},
# %{
# prim: "Pair",
# args: [
# [
# %{
# prim: "Elt",
# args: [
# %{string: royalty_address},
# %{int: Integer.to_string(royalty_share)}
# ]
# }
# ],
# %{
# prim: "Pair",
# args: [
# %{prim: "None"},
# %{
# prim: "Pair",
# args: [[], %{prim: "Pair", args: [%{prim: "None"}, %{prim: "None"}]}]
# }
# ]
# }
# ]
# }
# ]
# }
# ]
# }
# ]
# }

tx =
Rpc.build_contract_operation(
rpc,
public_key_hash,
counter,
contract,
amount,
fee,
storage_limit,
gas_limit,
entrypoint,
parameters,
encoded_private_key
)
# Rpc.build_contract_operation(
# rpc,
# public_key_hash,
# counter,
# contract,
# amount,
# fee,
# storage_limit,
# gas_limit,
# entrypoint,
# parameters,
# encoded_private_key
# )
# end

@tag :tezos
test "inject an operation" do
rpc = %Rpc{endpoint: @endpoint}

contents = [
%{
"amount" => "100",
"destination" => @ghostnet_2_address,
"fee" => "349",
"gas_limit" => "186",
"kind" => "transaction",
"storage_limit" => "0"
}
]

assert {:ok, operation_id} =
Rpc.send_operation(rpc, contents, @ghostnet_1_address, @ghostnet_1_pkey)

assert is_binary(operation_id)
end
end
Loading

0 comments on commit 9594217

Please sign in to comment.