From a9f0e8e7e789e7d47346a0af8026908c9ee6e4ba Mon Sep 17 00:00:00 2001 From: tenmoves Date: Mon, 23 Jan 2023 19:27:05 +0100 Subject: [PATCH 1/4] added get_token_id function in smart contract library --- .../contracts/interpreter/condition.ex | 8 +++ .../contracts/interpreter/library.ex | 35 +++++++++++ lib/archethic/contracts/interpreter/utils.ex | 9 +++ lib/archethic/utils.ex | 47 ++++++++++++++ lib/archethic_web/graphql_schema/resolver.ex | 35 ++--------- .../contracts/interpreter/library_test.exs | 61 +++++++++++++++++-- 6 files changed, 160 insertions(+), 35 deletions(-) diff --git a/lib/archethic/contracts/interpreter/condition.ex b/lib/archethic/contracts/interpreter/condition.ex index 54f9b5ebd..1e885a5e3 100644 --- a/lib/archethic/contracts/interpreter/condition.ex +++ b/lib/archethic/contracts/interpreter/condition.ex @@ -235,6 +235,14 @@ defmodule Archethic.Contracts.ConditionInterpreter do {node, acc} end + # Whitelist the get_token_id/1 function in the condition + defp prewalk( + node = {{:atom, "get_token_id"}, _, [_search]}, + acc = {:ok, %{scope: {:condition, _, _}}} + ) do + {node, acc} + end + # Whitelist the hash/0 function in the condition defp prewalk( node = {{:atom, "hash"}, _, []}, diff --git a/lib/archethic/contracts/interpreter/library.ex b/lib/archethic/contracts/interpreter/library.ex index a5795636a..3859d6083 100644 --- a/lib/archethic/contracts/interpreter/library.ex +++ b/lib/archethic/contracts/interpreter/library.ex @@ -12,6 +12,10 @@ defmodule Archethic.Contracts.Interpreter.Library do Contracts.Interpreter.Utils } + alias Archethic.Utils + + require Logger + @doc """ Match a regex expression @@ -228,6 +232,37 @@ defmodule Archethic.Contracts.Interpreter.Library do @spec timestamp() :: non_neg_integer() def timestamp, do: DateTime.utc_now() |> DateTime.to_unix() + @doc """ + Provide a token id which uniquely identify the token base on it's properties and genesis address. + """ + @spec get_token_id(binary()) :: {:error, binary()} | {:ok, binary()} + def get_token_id(address) do + t1 = Task.async(fn -> Archethic.fetch_genesis_address_remotely(address) end) + t2 = Task.async(fn -> Utils.get_transaction_content(address) end) + + with {:ok, {:ok, genesis_address}} <- Task.yield(t1), + {:ok, {:ok, definition}} <- Task.yield(t2) do + Utils.get_token_id(genesis_address, definition) + else + {:ok, {:error, :network_issue}} -> + {:error, "Network issue"} + + {:ok, {:error, :decode_error}} -> + {:error, "Error in decoding transaction"} + + {:ok, {:error, :not_a_token_transaction}} -> + {:error, "Transaction is not of type token"} + + {:exit, reason} -> + Logger.debug("Task exited with reason") + Logger.debug(reason) + {:error, "Task Exited!"} + + nil -> + {:error, "Task didn't responded within timeout!"} + end + end + @doc """ Get the genesis address of the chain """ diff --git a/lib/archethic/contracts/interpreter/utils.ex b/lib/archethic/contracts/interpreter/utils.ex index 856cbbb93..8e31e364f 100644 --- a/lib/archethic/contracts/interpreter/utils.ex +++ b/lib/archethic/contracts/interpreter/utils.ex @@ -287,6 +287,15 @@ defmodule Archethic.Contracts.Interpreter.Utils do {node, acc} end + # Whitelist the get_token_id/0 function + def prewalk( + node = {{:atom, "get_token_id"}, _, [_address]}, + acc = {:ok, %{scope: scope}} + ) + when scope != :root do + {node, acc} + end + # Whitelist the timestamp/0 function in condition def prewalk(node = {{:atom, "timestamp"}, _, _}, acc = {:ok, %{scope: scope}}) when scope != :root do diff --git a/lib/archethic/utils.ex b/lib/archethic/utils.ex index 023a79252..7e1ed0c64 100644 --- a/lib/archethic/utils.ex +++ b/lib/archethic/utils.ex @@ -12,6 +12,9 @@ defmodule Archethic.Utils do alias Archethic.P2P.Node + alias Archethic.TransactionChain.Transaction + alias Archethic.TransactionChain.TransactionData + alias Archethic.Reward.Scheduler, as: RewardScheduler import Bitwise @@ -913,4 +916,48 @@ defmodule Archethic.Utils do |> Stream.take_while(&(NaiveDateTime.compare(&1, end_of_month_datetime) in [:lt])) |> Enum.count() end + + @doc """ + computes token id based on the genesis address and transaction content + """ + @spec get_token_id(binary(), map()) :: binary() + def get_token_id(genesis_address, transaction_content) do + properties = Map.get(transaction_content, "properties", %{}) + decimals = Map.get(transaction_content, "decimals", 8) + name = Map.get(transaction_content, "name", "") + symbol = Map.get(transaction_content, "symbol", "") + + data_to_digest = %{ + genesis_address: Base.encode16(genesis_address), + name: name, + symbol: symbol, + properties: properties, + decimals: decimals + } + + :crypto.hash(:sha256, Jason.encode!(data_to_digest)) + |> Base.encode16() + end + + @doc """ + get transaction content based on the address of the transaction + """ + @spec get_transaction_content(binary()) :: {:ok, map()} | {:error, atom()} + def get_transaction_content(address) do + case Archethic.search_transaction(address) do + {:ok, + %Transaction{data: %TransactionData{content: content, ownerships: ownerships}, type: type}} + when type in [:token, :mint_rewards] -> + case Jason.decode(content) do + {:ok, map} -> + {:ok, map |> Map.put("ownerships", ownerships)} + + _ -> + {:error, :decode_error} + end + + _ -> + {:error, :not_a_token_transaction} + end + end end diff --git a/lib/archethic_web/graphql_schema/resolver.ex b/lib/archethic_web/graphql_schema/resolver.ex index 2e376eb22..c89e3cc19 100644 --- a/lib/archethic_web/graphql_schema/resolver.ex +++ b/lib/archethic_web/graphql_schema/resolver.ex @@ -13,11 +13,12 @@ defmodule ArchethicWeb.GraphQLSchema.Resolver do alias Archethic.TransactionChain alias Archethic.TransactionChain.Transaction - alias Archethic.TransactionChain.TransactionData alias Archethic.TransactionChain.TransactionInput alias Archethic.Mining + alias Archethic.Utils + require Logger @limit_page 10 @@ -54,7 +55,7 @@ defmodule ArchethicWeb.GraphQLSchema.Resolver do def get_token(address) do t1 = Task.async(fn -> Archethic.fetch_genesis_address_remotely(address) end) - t2 = Task.async(fn -> get_transaction_content(address) end) + t2 = Task.async(fn -> Utils.get_transaction_content(address) end) with {:ok, {:ok, genesis_address}} <- Task.yield(t1), {:ok, @@ -70,15 +71,7 @@ defmodule ArchethicWeb.GraphQLSchema.Resolver do name = Map.get(definition, "name", "") symbol = Map.get(definition, "symbol", "") - data_to_digest = %{ - genesis_address: Base.encode16(genesis_address), - name: name, - symbol: symbol, - properties: properties, - decimals: decimals - } - - token_id = :crypto.hash(:sha256, Jason.encode!(data_to_digest)) |> Base.encode16() + token_id = Utils.get_token_id(genesis_address, definition) {:ok, %{ @@ -101,7 +94,7 @@ defmodule ArchethicWeb.GraphQLSchema.Resolver do {:error, "Error in decoding transaction"} {:ok, {:error, :transaction_not_found}} -> - {:error, "Transaction does not exist!"} + {:error, "Transaction is not of type token"} {:exit, reason} -> Logger.debug("Task exited with reason") @@ -113,24 +106,6 @@ defmodule ArchethicWeb.GraphQLSchema.Resolver do end end - defp get_transaction_content(address) do - case Archethic.search_transaction(address) do - {:ok, - %Transaction{data: %TransactionData{content: content, ownerships: ownerships}, type: type}} - when type in [:token, :mint_rewards] -> - case Jason.decode(content) do - {:ok, map} -> - {:ok, map |> Map.put("ownerships", ownerships)} - - _ -> - {:error, :decode_error} - end - - _ -> - {:error, :transaction_not_found} - end - end - def get_inputs(address, paging_offset \\ 0, limit \\ 0) do inputs = address diff --git a/test/archethic/contracts/interpreter/library_test.exs b/test/archethic/contracts/interpreter/library_test.exs index 072b876f5..214745d8b 100644 --- a/test/archethic/contracts/interpreter/library_test.exs +++ b/test/archethic/contracts/interpreter/library_test.exs @@ -1,17 +1,68 @@ defmodule Archethic.Contracts.Interpreter.LibraryTest do use ArchethicCase - alias Archethic.{Contracts.Interpreter.Library, P2P, P2P.Node} + alias Archethic.Contracts.Interpreter.Library - alias P2P.Message.{ - GetFirstTransactionAddress, - FirstTransactionAddress - } + alias P2P.Message.GetFirstTransactionAddress + alias P2P.Message.FirstTransactionAddress + + alias Archethic.TransactionChain.Transaction + alias Archethic.TransactionChain.TransactionData + + alias Archethic.Utils + + alias Archethic.P2P + alias Archethic.P2P.Node doctest Library import Mox + describe "get_token_id\1" do + test "should return token_id given the address of the transaction" do + tx_seed = :crypto.strong_rand_bytes(32) + + tx = + Transaction.new( + :token, + %TransactionData{ + content: + Jason.encode!(%{ + supply: 300_000_000, + name: "MyToken", + type: "non-fungible", + symbol: "MTK", + properties: %{ + global: "property" + }, + collection: [ + %{image: "link", value: "link"}, + %{image: "link", value: "link"}, + %{image: "link", value: "link"} + ] + }) + }, + tx_seed, + 0 + ) + + genesis_address = "@Alice1" + + transaction_content = + tx.data.content + |> Jason.decode!() + + MockDB + |> stub(:get_transaction, fn _, _ -> {:ok, tx} end) + |> stub(:get_genesis_address, fn _ -> genesis_address end) + + assert Utils.get_token_id(genesis_address, transaction_content) == + Library.get_token_id(tx.address) + end + end + + import Mox + test "get_first_transaction_address/1" do P2P.add_and_connect_node(%Node{ ip: {127, 0, 0, 1}, From a8ae0ee8756dbca8353a9f7f027ee991d0c43288 Mon Sep 17 00:00:00 2001 From: tenmoves Date: Tue, 24 Jan 2023 11:24:44 +0100 Subject: [PATCH 2/4] review feedbacks --- lib/archethic/contracts/interpreter/condition.ex | 8 -------- lib/archethic/contracts/interpreter/library.ex | 7 +++---- lib/archethic/contracts/interpreter/utils.ex | 2 +- test/archethic/contracts/interpreter/library_test.exs | 6 +++--- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/lib/archethic/contracts/interpreter/condition.ex b/lib/archethic/contracts/interpreter/condition.ex index 1e885a5e3..54f9b5ebd 100644 --- a/lib/archethic/contracts/interpreter/condition.ex +++ b/lib/archethic/contracts/interpreter/condition.ex @@ -235,14 +235,6 @@ defmodule Archethic.Contracts.ConditionInterpreter do {node, acc} end - # Whitelist the get_token_id/1 function in the condition - defp prewalk( - node = {{:atom, "get_token_id"}, _, [_search]}, - acc = {:ok, %{scope: {:condition, _, _}}} - ) do - {node, acc} - end - # Whitelist the hash/0 function in the condition defp prewalk( node = {{:atom, "hash"}, _, []}, diff --git a/lib/archethic/contracts/interpreter/library.ex b/lib/archethic/contracts/interpreter/library.ex index 3859d6083..23c1a9342 100644 --- a/lib/archethic/contracts/interpreter/library.ex +++ b/lib/archethic/contracts/interpreter/library.ex @@ -12,8 +12,6 @@ defmodule Archethic.Contracts.Interpreter.Library do Contracts.Interpreter.Utils } - alias Archethic.Utils - require Logger @doc """ @@ -237,12 +235,13 @@ defmodule Archethic.Contracts.Interpreter.Library do """ @spec get_token_id(binary()) :: {:error, binary()} | {:ok, binary()} def get_token_id(address) do + address = Utils.maybe_decode_hex(address) t1 = Task.async(fn -> Archethic.fetch_genesis_address_remotely(address) end) - t2 = Task.async(fn -> Utils.get_transaction_content(address) end) + t2 = Task.async(fn -> Archethic.Utils.get_transaction_content(address) end) with {:ok, {:ok, genesis_address}} <- Task.yield(t1), {:ok, {:ok, definition}} <- Task.yield(t2) do - Utils.get_token_id(genesis_address, definition) + Archethic.Utils.get_token_id(genesis_address, definition) else {:ok, {:error, :network_issue}} -> {:error, "Network issue"} diff --git a/lib/archethic/contracts/interpreter/utils.ex b/lib/archethic/contracts/interpreter/utils.ex index 8e31e364f..0b9a7c644 100644 --- a/lib/archethic/contracts/interpreter/utils.ex +++ b/lib/archethic/contracts/interpreter/utils.ex @@ -287,7 +287,7 @@ defmodule Archethic.Contracts.Interpreter.Utils do {node, acc} end - # Whitelist the get_token_id/0 function + # Whitelist the get_token_id/1 function def prewalk( node = {{:atom, "get_token_id"}, _, [_address]}, acc = {:ok, %{scope: scope}} diff --git a/test/archethic/contracts/interpreter/library_test.exs b/test/archethic/contracts/interpreter/library_test.exs index 214745d8b..a2f28b795 100644 --- a/test/archethic/contracts/interpreter/library_test.exs +++ b/test/archethic/contracts/interpreter/library_test.exs @@ -3,8 +3,8 @@ defmodule Archethic.Contracts.Interpreter.LibraryTest do alias Archethic.Contracts.Interpreter.Library - alias P2P.Message.GetFirstTransactionAddress - alias P2P.Message.FirstTransactionAddress + alias Archethic.P2P.Message.GetFirstTransactionAddress + alias Archethic.P2P.Message.FirstTransactionAddress alias Archethic.TransactionChain.Transaction alias Archethic.TransactionChain.TransactionData @@ -53,7 +53,7 @@ defmodule Archethic.Contracts.Interpreter.LibraryTest do |> Jason.decode!() MockDB - |> stub(:get_transaction, fn _, _ -> {:ok, tx} end) + |> stub(:get_transaction, fn _, _, _ -> {:ok, tx} end) |> stub(:get_genesis_address, fn _ -> genesis_address end) assert Utils.get_token_id(genesis_address, transaction_content) == From 67d802ff11f59b4ac7ebaa85ac5f8253a8ddcb75 Mon Sep 17 00:00:00 2001 From: tenmoves Date: Mon, 30 Jan 2023 18:48:58 +0100 Subject: [PATCH 3/4] handled review feedbacks --- .../contracts/interpreter/library.ex | 38 ++++---- lib/archethic/utils.ex | 86 +++++++++++-------- lib/archethic_web/graphql_schema/resolver.ex | 46 +++------- .../contracts/interpreter/library_test.exs | 8 +- 4 files changed, 89 insertions(+), 89 deletions(-) diff --git a/lib/archethic/contracts/interpreter/library.ex b/lib/archethic/contracts/interpreter/library.ex index 23c1a9342..02491f47b 100644 --- a/lib/archethic/contracts/interpreter/library.ex +++ b/lib/archethic/contracts/interpreter/library.ex @@ -9,9 +9,11 @@ defmodule Archethic.Contracts.Interpreter.Library do TransactionChain, Contracts.ContractConstants, Contracts.TransactionLookup, - Contracts.Interpreter.Utils + Utils } + alias Archethic.Contracts.Interpreter.Utils, as: SCUtils + require Logger @doc """ @@ -143,7 +145,7 @@ defmodule Archethic.Contracts.Interpreter.Library do :blake2b end - :crypto.hash(algo, Utils.maybe_decode_hex(content)) + :crypto.hash(algo, SCUtils.maybe_decode_hex(content)) |> Base.encode16() end @@ -182,7 +184,7 @@ defmodule Archethic.Contracts.Interpreter.Library do 2 """ @spec size(binary() | list()) :: non_neg_integer() - def size(binary) when is_binary(binary), do: binary |> Utils.maybe_decode_hex() |> byte_size() + def size(binary) when is_binary(binary), do: binary |> SCUtils.maybe_decode_hex() |> byte_size() def size(list) when is_list(list), do: length(list) def size(map) when is_map(map), do: map_size(map) @@ -194,7 +196,7 @@ defmodule Archethic.Contracts.Interpreter.Library do @spec get_calls(binary()) :: list(map()) def get_calls(contract_address) do contract_address - |> Utils.maybe_decode_hex() + |> SCUtils.maybe_decode_hex() |> TransactionLookup.list_contract_transactions() |> Enum.map(fn {address, _, _} -> # TODO: parallelize @@ -208,7 +210,7 @@ defmodule Archethic.Contracts.Interpreter.Library do """ @spec get_genesis_public_key(binary()) :: binary() def get_genesis_public_key(address) do - bin_address = Utils.maybe_decode_hex(address) + bin_address = SCUtils.maybe_decode_hex(address) nodes = Election.chain_storage_nodes(bin_address, P2P.authorized_and_available_nodes()) {:ok, key} = download_first_public_key(nodes, bin_address) Base.encode16(key) @@ -235,26 +237,32 @@ defmodule Archethic.Contracts.Interpreter.Library do """ @spec get_token_id(binary()) :: {:error, binary()} | {:ok, binary()} def get_token_id(address) do - address = Utils.maybe_decode_hex(address) + address = SCUtils.get_address(address, :get_token_id) t1 = Task.async(fn -> Archethic.fetch_genesis_address_remotely(address) end) - t2 = Task.async(fn -> Archethic.Utils.get_transaction_content(address) end) + t2 = Task.async(fn -> Archethic.search_transaction(address) end) with {:ok, {:ok, genesis_address}} <- Task.yield(t1), - {:ok, {:ok, definition}} <- Task.yield(t2) do - Archethic.Utils.get_token_id(genesis_address, definition) + {:ok, {:ok, tx}} <- Task.yield(t2), + {:ok, %{id: id}} <- Utils.get_token_properties(genesis_address, tx) do + id else {:ok, {:error, :network_issue}} -> {:error, "Network issue"} - {:ok, {:error, :decode_error}} -> + {:ok, {:error, :transaction_not_exists}} -> + {:error, "Transaction not exists"} + + {:ok, {:error, :transaction_invalid}} -> + {:error, "Transaction invalid"} + + {:error, :decode_error} -> {:error, "Error in decoding transaction"} - {:ok, {:error, :not_a_token_transaction}} -> + {:error, :not_a_token_transaction} -> {:error, "Transaction is not of type token"} {:exit, reason} -> - Logger.debug("Task exited with reason") - Logger.debug(reason) + Logger.debug("Task exited with reason #{inspect(reason)}") {:error, "Task Exited!"} nil -> @@ -268,7 +276,7 @@ defmodule Archethic.Contracts.Interpreter.Library do @spec get_genesis_address(binary()) :: binary() def get_genesis_address(address) do - addr_bin = Utils.maybe_decode_hex(address) + addr_bin = SCUtils.maybe_decode_hex(address) nodes = Election.chain_storage_nodes(address, P2P.authorized_and_available_nodes()) case TransactionChain.fetch_genesis_address_remotely(addr_bin, nodes) do @@ -283,7 +291,7 @@ defmodule Archethic.Contracts.Interpreter.Library do @spec get_first_transaction_address(address :: binary()) :: binary() def get_first_transaction_address(address) do - addr_bin = Utils.maybe_decode_hex(address) + addr_bin = SCUtils.maybe_decode_hex(address) nodes = Election.chain_storage_nodes(address, P2P.authorized_and_available_nodes()) case TransactionChain.fetch_first_transaction_address_remotely(addr_bin, nodes) do diff --git a/lib/archethic/utils.ex b/lib/archethic/utils.ex index 7e1ed0c64..7e51bf4c7 100644 --- a/lib/archethic/utils.ex +++ b/lib/archethic/utils.ex @@ -918,46 +918,60 @@ defmodule Archethic.Utils do end @doc """ - computes token id based on the genesis address and transaction content + get token properties based on the genesis address and the transaction """ - @spec get_token_id(binary(), map()) :: binary() - def get_token_id(genesis_address, transaction_content) do - properties = Map.get(transaction_content, "properties", %{}) - decimals = Map.get(transaction_content, "decimals", 8) - name = Map.get(transaction_content, "name", "") - symbol = Map.get(transaction_content, "symbol", "") - - data_to_digest = %{ - genesis_address: Base.encode16(genesis_address), - name: name, - symbol: symbol, - properties: properties, - decimals: decimals - } - - :crypto.hash(:sha256, Jason.encode!(data_to_digest)) - |> Base.encode16() - end + @spec get_token_properties(binary(), Transaction.t()) :: {:ok, map()} | {:error, atom()} + def get_token_properties(genesis_address, %Transaction{ + data: %TransactionData{ + content: content, + ownerships: ownerships + }, + type: type + }) + when type in [:token, :mint_rewards] do + case Jason.decode(content) do + {:ok, map} -> + result = %{ + genesis: genesis_address, + name: Map.get(map, "name", ""), + supply: Map.get(map, "supply"), + symbol: Map.get(map, "symbol", ""), + type: type, + decimals: Map.get(map, "decimals", 8), + properties: Map.get(map, "properties", %{}), + collection: Map.get(map, "collection", []), + ownerships: ownerships + } - @doc """ - get transaction content based on the address of the transaction - """ - @spec get_transaction_content(binary()) :: {:ok, map()} | {:error, atom()} - def get_transaction_content(address) do - case Archethic.search_transaction(address) do - {:ok, - %Transaction{data: %TransactionData{content: content, ownerships: ownerships}, type: type}} - when type in [:token, :mint_rewards] -> - case Jason.decode(content) do - {:ok, map} -> - {:ok, map |> Map.put("ownerships", ownerships)} - - _ -> - {:error, :decode_error} - end + token_id = get_token_id(genesis_address, result) + + {:ok, Map.put(result, :id, token_id)} _ -> - {:error, :not_a_token_transaction} + {:error, :decode_error} end end + + def get_token_properties(_, _), do: {:error, :not_a_token_transaction} + + defp get_token_id(genesis_address, %{ + genesis: genesis_address, + name: name, + symbol: symbol, + decimals: decimals, + properties: properties + }) do + data_to_digest = + %{ + genesis_address: Base.encode16(genesis_address), + name: name, + symbol: symbol, + properties: properties, + decimals: decimals + } + |> Jason.encode!() + + :crypto.hash(:sha256, data_to_digest) + |> Base.encode16() + end end diff --git a/lib/archethic_web/graphql_schema/resolver.ex b/lib/archethic_web/graphql_schema/resolver.ex index c89e3cc19..a968382d9 100644 --- a/lib/archethic_web/graphql_schema/resolver.ex +++ b/lib/archethic_web/graphql_schema/resolver.ex @@ -55,50 +55,30 @@ defmodule ArchethicWeb.GraphQLSchema.Resolver do def get_token(address) do t1 = Task.async(fn -> Archethic.fetch_genesis_address_remotely(address) end) - t2 = Task.async(fn -> Utils.get_transaction_content(address) end) + t2 = Task.async(fn -> Archethic.search_transaction(address) end) with {:ok, {:ok, genesis_address}} <- Task.yield(t1), - {:ok, - {:ok, - definition = %{ - "ownerships" => ownerships, - "supply" => supply, - "type" => type - }}} <- Task.yield(t2) do - properties = Map.get(definition, "properties", %{}) - collection = Map.get(definition, "collection", []) - decimals = Map.get(definition, "decimals", 8) - name = Map.get(definition, "name", "") - symbol = Map.get(definition, "symbol", "") - - token_id = Utils.get_token_id(genesis_address, definition) - - {:ok, - %{ - genesis: genesis_address, - name: name, - supply: supply, - symbol: symbol, - type: type, - decimals: decimals, - properties: properties, - collection: collection, - ownerships: ownerships, - id: token_id - }} + {:ok, {:ok, tx}} <- Task.yield(t2), + res = {:ok, _get_token_properties} <- Utils.get_token_properties(genesis_address, tx) do + res else {:ok, {:error, :network_issue}} -> {:error, "Network issue"} - {:ok, {:error, :decode_error}} -> + {:ok, {:error, :transaction_not_exists}} -> + {:error, "Transaction not exists"} + + {:ok, {:error, :transaction_invalid}} -> + {:error, "Transaction invalid"} + + {:error, :decode_error} -> {:error, "Error in decoding transaction"} - {:ok, {:error, :transaction_not_found}} -> + {:error, :not_a_token_transaction} -> {:error, "Transaction is not of type token"} {:exit, reason} -> - Logger.debug("Task exited with reason") - Logger.debug(reason) + Logger.debug("Task exited with reason #{inspect(reason)}") {:error, "Task Exited!"} nil -> diff --git a/test/archethic/contracts/interpreter/library_test.exs b/test/archethic/contracts/interpreter/library_test.exs index a2f28b795..00ad42016 100644 --- a/test/archethic/contracts/interpreter/library_test.exs +++ b/test/archethic/contracts/interpreter/library_test.exs @@ -48,15 +48,13 @@ defmodule Archethic.Contracts.Interpreter.LibraryTest do genesis_address = "@Alice1" - transaction_content = - tx.data.content - |> Jason.decode!() - MockDB |> stub(:get_transaction, fn _, _, _ -> {:ok, tx} end) |> stub(:get_genesis_address, fn _ -> genesis_address end) - assert Utils.get_token_id(genesis_address, transaction_content) == + {:ok, %{id: token_id}} = Utils.get_token_properties(genesis_address, tx) + + assert token_id == Library.get_token_id(tx.address) end end From 32eae93df9a444e48e0d428b8007858959656e7a Mon Sep 17 00:00:00 2001 From: tenmoves Date: Tue, 31 Jan 2023 15:13:58 +0100 Subject: [PATCH 4/4] review feedbacks --- lib/archethic/utils.ex | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/archethic/utils.ex b/lib/archethic/utils.ex index 7e51bf4c7..44088045b 100644 --- a/lib/archethic/utils.ex +++ b/lib/archethic/utils.ex @@ -920,15 +920,16 @@ defmodule Archethic.Utils do @doc """ get token properties based on the genesis address and the transaction """ - @spec get_token_properties(binary(), Transaction.t()) :: {:ok, map()} | {:error, atom()} + @spec get_token_properties(binary(), Transaction.t()) :: + {:ok, map()} | {:error, :decode_error} | {:error, :not_a_token_transaction} def get_token_properties(genesis_address, %Transaction{ data: %TransactionData{ content: content, ownerships: ownerships }, - type: type + type: tx_type }) - when type in [:token, :mint_rewards] do + when tx_type in [:token, :mint_rewards] do case Jason.decode(content) do {:ok, map} -> result = %{ @@ -936,7 +937,7 @@ defmodule Archethic.Utils do name: Map.get(map, "name", ""), supply: Map.get(map, "supply"), symbol: Map.get(map, "symbol", ""), - type: type, + type: Map.get(map, "type"), decimals: Map.get(map, "decimals", 8), properties: Map.get(map, "properties", %{}), collection: Map.get(map, "collection", []),