From aba07497af672cf94dba7af1426cf102be7ce9b1 Mon Sep 17 00:00:00 2001 From: Valentin Atanasov Date: Fri, 21 Jun 2024 16:25:34 +0300 Subject: [PATCH 1/5] feat: further fields to dex endpoints --- docs/swagger_v3/dex.spec.yaml | 32 +++++++++++++ lib/ae_mdw/dex.ex | 45 ++++++++++++++++--- .../controllers/dex_controller_test.exs | 16 +++++++ 3 files changed, 88 insertions(+), 5 deletions(-) diff --git a/docs/swagger_v3/dex.spec.yaml b/docs/swagger_v3/dex.spec.yaml index 396a6af74..3e91d55fe 100644 --- a/docs/swagger_v3/dex.spec.yaml +++ b/docs/swagger_v3/dex.spec.yaml @@ -36,6 +36,30 @@ schemas: tx_hash: type: string example: "th_2t7TnocFw7oCYSS7g2yGutZMpGEJta6dq2DTX38SmuqmwtN6Ch" + from_contract: + type: string + example: "ct_22NTeTHfqVXLChCMCy3eAAj3hGW2nuNUwHhQ1zRX3k4iZKq8Ru" + to_contract: + type: string + example: "ct_22NTeTHfqVXLChCMCy3eAAj3hGW2nuNUwHhQ1zRX3k4iZKq8Ru" + from_amount: + type: integer + example: 1000050 + to_amount: + type: integer + example: 1000060 + from_decimals: + type: integer + example: 18 + to_decimals: + type: integer + example: 18 + microtime: + type: integer + example: 1629820800000 + height: + type: integer + example: 123456 required: - amounts - caller @@ -44,6 +68,14 @@ schemas: - log_idx - to_account - tx_hash + - from_contract + - to_contract + - from_amount + - to_amount + - from_decimals + - to_decimals + - microtime + - height paths: /dex/swaps: get: diff --git a/lib/ae_mdw/dex.ex b/lib/ae_mdw/dex.ex index 34dbeb191..20f3925af 100644 --- a/lib/ae_mdw/dex.ex +++ b/lib/ae_mdw/dex.ex @@ -3,6 +3,7 @@ defmodule AeMdw.Dex do Search for DEX swaps. """ + alias AeMdw.AexnContracts alias AeMdw.Util.Encoding alias AeMdw.Collection alias AeMdw.Contracts @@ -206,16 +207,44 @@ defmodule AeMdw.Dex do Origin.tx_index!(state, {:contract, contract_pk}) end + Model.tx(id: _tx_hash, block_index: {height, _mbi} = block_index, time: time) = + State.fetch!(state, Model.Tx, create_txi) + + Model.block(hash: hash) = State.fetch!(state, Model.Block, block_index) + contract_pk = Origin.pubkey!(state, {:contract, create_txi}) + %{token1: token1_pk, token2: token2_pk} = DexCache.get_pair(contract_pk) + + {:ok, {_name, _symbol, from_decimals}} = AexnContracts.call_meta_info(:aex9, token1_pk, hash) + {:ok, {_name, _symbol, to_decimals}} = AexnContracts.call_meta_info(:aex9, token2_pk, hash) + %{token1: token1_symbol, token2: token2_symbol} = DexCache.get_pair_symbols(create_txi) + %{token1: token1_pk, token2: token2_pk} = DexCache.get_pair(contract_pk) + + %{ + "amount0_in" => amount0_in, + "amount1_in" => amount1_in, + "amount0_out" => amount0_out, + "amount1_out" => amount1_out + } = rendered_amounts = render_amounts(amounts) + %{ caller: Encoding.encode(:account_pubkey, caller_pk), to_account: Encoding.encode(:account_pubkey, to_pk), + from_contract: Encoding.encode_contract(token1_pk), + to_contract: Encoding.encode_contract(token2_pk), from_token: token1_symbol, to_token: token2_symbol, + from_amount: amount0_in + amount1_in, + to_amount: amount0_out + amount1_out, + from_decimals: from_decimals, + to_decimals: to_decimals, tx_hash: Encoding.encode(:tx_hash, Txs.txi_to_hash(state, txi)), log_idx: log_idx, - amounts: render_amounts(amounts) + amounts: rendered_amounts, + # check this one + microtime: time, + height: height } end @@ -228,12 +257,18 @@ defmodule AeMdw.Dex do defp convert_param(other_param), do: {:error, ErrInput.Query.exception(value: other_param)} + @spec render_amounts(list(integer())) :: %{ + amount0_in: integer(), + amount1_in: integer(), + amount0_out: integer(), + amount1_out: integer() + } defp render_amounts([amount0_in, amount1_in, amount0_out, amount1_out]) do %{ - "amount0_in" => amount0_in, - "amount1_in" => amount1_in, - "amount0_out" => amount0_out, - "amount1_out" => amount1_out + amount0_in: amount0_in, + amount1_in: amount1_in, + amount0_out: amount0_out, + amount1_out: amount1_out } end diff --git a/test/ae_mdw_web/controllers/dex_controller_test.exs b/test/ae_mdw_web/controllers/dex_controller_test.exs index d94f58f6f..24fbb601a 100644 --- a/test/ae_mdw_web/controllers/dex_controller_test.exs +++ b/test/ae_mdw_web/controllers/dex_controller_test.exs @@ -64,6 +64,8 @@ defmodule AeMdwWeb.DexControllerTest do txi = 1_000_000 + i log_idx = rem(txi, 2) + block_index_number = 200_000 + i + block_index = {block_index_number, 0} store |> Store.put( @@ -93,6 +95,20 @@ defmodule AeMdwWeb.DexControllerTest do Model.Tx, Model.tx(index: txi, id: <>, block_index: {100_000 + i, 0}) ) + |> Store.put( + Model.Tx, + Model.tx(index: pair_txi, id: <>, block_index: block_index) + ) + |> Store.put( + Model.Block, + Model.block(index: block_index, hash: <>) + ) + |> Store.put( + Model.RevOrigin, + Model.rev_origin( + index: {block_index_number, :contract_create_tx, <>} + ) + ) end) end) |> then(fn store -> From 8b6c8e1dc140bae69912f55416c064e8a39db280 Mon Sep 17 00:00:00 2001 From: Valentin Atanasov Date: Thu, 4 Jul 2024 12:18:33 +0300 Subject: [PATCH 2/5] fix: tests --- lib/ae_mdw/dex.ex | 12 +- lib/ae_mdw/sync/dex_cache.ex | 8 +- .../controllers/dex_controller_test.exs | 587 +++++++++++------- 3 files changed, 376 insertions(+), 231 deletions(-) diff --git a/lib/ae_mdw/dex.ex b/lib/ae_mdw/dex.ex index 20f3925af..232f5d5b5 100644 --- a/lib/ae_mdw/dex.ex +++ b/lib/ae_mdw/dex.ex @@ -208,7 +208,9 @@ defmodule AeMdw.Dex do end Model.tx(id: _tx_hash, block_index: {height, _mbi} = block_index, time: time) = - State.fetch!(state, Model.Tx, create_txi) + tx = State.fetch!(state, Model.Tx, create_txi) + + IO.inspect(tx) Model.block(hash: hash) = State.fetch!(state, Model.Block, block_index) contract_pk = Origin.pubkey!(state, {:contract, create_txi}) @@ -222,10 +224,10 @@ defmodule AeMdw.Dex do %{token1: token1_pk, token2: token2_pk} = DexCache.get_pair(contract_pk) %{ - "amount0_in" => amount0_in, - "amount1_in" => amount1_in, - "amount0_out" => amount0_out, - "amount1_out" => amount1_out + amount0_in: amount0_in, + amount1_in: amount1_in, + amount0_out: amount0_out, + amount1_out: amount1_out } = rendered_amounts = render_amounts(amounts) %{ diff --git a/lib/ae_mdw/sync/dex_cache.ex b/lib/ae_mdw/sync/dex_cache.ex index f07f08f26..acb3413a4 100644 --- a/lib/ae_mdw/sync/dex_cache.ex +++ b/lib/ae_mdw/sync/dex_cache.ex @@ -59,10 +59,10 @@ defmodule AeMdw.Sync.DexCache do @spec add_pair(State.t(), pubkey(), pubkey(), pubkey()) :: :ok def add_pair(state, contract_pk, token1_pk, token2_pk) do - with {:ok, Model.aexn_contract(meta_info: {_name, symbol1, _dec})} <- - State.get(state, Model.AexnContract, {:aex9, token1_pk}), - {:ok, Model.aexn_contract(meta_info: {_name, symbol2, _dec})} <- - State.get(state, Model.AexnContract, {:aex9, token2_pk}), + with {:first, {:ok, Model.aexn_contract(meta_info: {_name, symbol1, _dec})}} <- + {:first, State.get(state, Model.AexnContract, {:aex9, token1_pk})}, + {:second, {:ok, Model.aexn_contract(meta_info: {_name, symbol2, _dec})}} <- + {:second, State.get(state, Model.AexnContract, {:aex9, token2_pk})}, {:ok, pair_create_txi} <- Origin.tx_index(state, {:contract, contract_pk}) do :ets.insert(@tokens_table, {symbol1, pair_create_txi}) :ets.insert(@pairs_table, {contract_pk, token1_pk, token2_pk}) diff --git a/test/ae_mdw_web/controllers/dex_controller_test.exs b/test/ae_mdw_web/controllers/dex_controller_test.exs index 24fbb601a..57ac71ef8 100644 --- a/test/ae_mdw_web/controllers/dex_controller_test.exs +++ b/test/ae_mdw_web/controllers/dex_controller_test.exs @@ -2,7 +2,10 @@ defmodule AeMdwWeb.DexControllerTest do use AeMdwWeb.ConnCase @moduletag skip_store: true + import Mock + alias AeMdw.Db.Model + alias AeMdw.Db.State alias AeMdw.Db.Store alias AeMdw.Sync.DexCache alias AeMdw.Util.Encoding @@ -46,6 +49,8 @@ defmodule AeMdwWeb.DexControllerTest do Model.field(index: {:contract_create_tx, nil, @pair2_pk, @pair2_txi}) ) |> then(fn store -> + state = State.new(store) + Enum.reduce(1..80, store, fn i, store -> {account_pk, pair_txi} = cond do @@ -66,49 +71,75 @@ defmodule AeMdwWeb.DexControllerTest do log_idx = rem(txi, 2) block_index_number = 200_000 + i block_index = {block_index_number, 0} - - store - |> Store.put( - Model.DexAccountSwapTokens, - Model.dex_account_swap_tokens( - index: {account_pk, pair_txi, txi, log_idx}, - to: account_pk, - amounts: [txi + 10, txi + 20, txi + 30, txi + 40] + token1_pk = :crypto.strong_rand_bytes(32) + token2_pk = :crypto.strong_rand_bytes(32) + + store = + store + |> Store.put( + Model.DexAccountSwapTokens, + Model.dex_account_swap_tokens( + index: {account_pk, pair_txi, txi, log_idx}, + to: account_pk, + amounts: [txi + 10, txi + 20, txi + 30, txi + 40] + ) ) - ) - |> Store.put( - Model.DexContractSwapTokens, - Model.dex_contract_swap_tokens(index: {pair_txi, account_pk, txi, log_idx}) - ) - |> Store.put( - Model.DexSwapTokens, - Model.dex_swap_tokens(index: {pair_txi, txi, log_idx}) - ) - |> Store.put( - Model.ContractLog, - Model.contract_log( - index: {pair_txi, txi, log_idx}, - args: [account_pk, account_pk] + |> Store.put( + Model.DexContractSwapTokens, + Model.dex_contract_swap_tokens(index: {pair_txi, account_pk, txi, log_idx}) ) - ) - |> Store.put( - Model.Tx, - Model.tx(index: txi, id: <>, block_index: {100_000 + i, 0}) - ) - |> Store.put( - Model.Tx, - Model.tx(index: pair_txi, id: <>, block_index: block_index) - ) - |> Store.put( - Model.Block, - Model.block(index: block_index, hash: <>) - ) - |> Store.put( - Model.RevOrigin, - Model.rev_origin( - index: {block_index_number, :contract_create_tx, <>} + |> Store.put( + Model.DexSwapTokens, + Model.dex_swap_tokens(index: {pair_txi, txi, log_idx}) + ) + |> Store.put( + Model.ContractLog, + Model.contract_log( + index: {pair_txi, txi, log_idx}, + args: [account_pk, account_pk] + ) + ) + |> Store.put( + Model.Tx, + Model.tx(index: txi, id: <>, block_index: {100_000 + i, 0}) + ) + |> Store.put( + Model.Tx, + Model.tx(index: pair_txi, id: <>, block_index: block_index) + ) + |> Store.put( + Model.Block, + Model.block(index: block_index, hash: <>) + ) + |> Store.put( + Model.RevOrigin, + Model.rev_origin( + index: {block_index_number, :contract_create_tx, <>} + ) + ) + |> Store.put( + Model.AexnContract, + Model.aexn_contract(index: {:aex9, token1_pk}, meta_info: {"TOKEN1", "TK1", 18}) + ) + |> Store.put( + Model.AexnContract, + Model.aexn_contract(index: {:aex9, token2_pk}, meta_info: {"TOKEN2", "TK2", 18}) ) + |> Store.put( + Model.Field, + Model.field( + index: {:contract_create_tx, nil, <>, block_index_number} + ) + ) + + DexCache.add_pair( + state, + <>, + token1_pk, + token2_pk ) + + store end) end) |> then(fn store -> @@ -134,51 +165,79 @@ defmodule AeMdwWeb.DexControllerTest do end test "gets SwapTokens by desc txi", %{conn: conn} do - caller_id = encode_account(@account2_pk) - - assert %{"data" => swaps, "next" => next} = - conn - |> get("/v3/dex/swaps") - |> json_response(200) - - assert @default_limit = length(swaps) - assert ^swaps = Enum.sort_by(swaps, &Validate.id!(&1["tx_hash"]), :desc) - assert Enum.all?(swaps, &valid_caller_swap?(&1, caller_id, "TK3", "TK4")) - - assert %{"data" => next_swaps, "prev" => prev_swaps} = - conn |> get(next) |> json_response(200) - - assert @default_limit = length(next_swaps) - - assert ^next_swaps = Enum.sort_by(next_swaps, &Validate.id!(&1["tx_hash"]), :desc) - - assert Enum.all?(next_swaps, &valid_caller_swap?(&1, caller_id, "TK3", "TK4")) - - assert %{"data" => ^swaps} = conn |> get(prev_swaps) |> json_response(200) + with_mocks [ + {AeMdw.Node.Db, [:passthrough], + [ + find_block_height: fn _mb_hash -> {:ok, 123} end + ]}, + {AeMdw.DryRun.Runner, [:passthrough], + [ + call_contract: fn _contract_pk, {:micro, _test, _mb_hash}, "meta_info", [] -> + meta_info_tuple = {"name", "SYMBOL", 18} + {:ok, {:tuple, meta_info_tuple}} + end + ]} + ] do + caller_id = encode_account(@account2_pk) + + assert %{"data" => swaps, "next" => next} = + conn + |> get("/v3/dex/swaps") + |> json_response(200) + + assert @default_limit = length(swaps) + assert ^swaps = Enum.sort_by(swaps, &Validate.id!(&1["tx_hash"]), :desc) + assert Enum.all?(swaps, &valid_caller_swap?(&1, caller_id, "TK3", "TK4")) + + assert %{"data" => next_swaps, "prev" => prev_swaps} = + conn |> get(next) |> json_response(200) + + assert @default_limit = length(next_swaps) + + assert ^next_swaps = Enum.sort_by(next_swaps, &Validate.id!(&1["tx_hash"]), :desc) + + assert Enum.all?(next_swaps, &valid_caller_swap?(&1, caller_id, "TK3", "TK4")) + + assert %{"data" => ^swaps} = conn |> get(prev_swaps) |> json_response(200) + end end test "gets SwapTokens by asc txi", %{conn: conn} do - caller_id = encode_account(@account1_pk) - - assert %{"data" => swaps, "next" => next} = - conn - |> get("/v3/dex/swaps", direction: :forward) - |> json_response(200) - - assert @default_limit = length(swaps) - assert ^swaps = Enum.sort_by(swaps, &Validate.id!(&1["tx_hash"])) - assert Enum.all?(swaps, &valid_caller_swap?(&1, caller_id, "TK1", "TK2")) - - assert %{"data" => next_swaps, "prev" => prev_swaps} = - conn |> get(next) |> json_response(200) - - assert @default_limit = length(next_swaps) - - assert ^next_swaps = Enum.sort_by(next_swaps, &Validate.id!(&1["tx_hash"])) - - assert Enum.all?(next_swaps, &valid_caller_swap?(&1, caller_id, "TK1", "TK2")) - - assert %{"data" => ^swaps} = conn |> get(prev_swaps) |> json_response(200) + with_mocks [ + {AeMdw.Node.Db, [:passthrough], + [ + find_block_height: fn _mb_hash -> {:ok, 123} end + ]}, + {AeMdw.DryRun.Runner, [:passthrough], + [ + call_contract: fn _contract_pk, {:micro, _test, _mb_hash}, "meta_info", [] -> + meta_info_tuple = {"name", "SYMBOL", 18} + {:ok, {:tuple, meta_info_tuple}} + end + ]} + ] do + caller_id = encode_account(@account1_pk) + + assert %{"data" => swaps, "next" => next} = + conn + |> get("/v3/dex/swaps", direction: :forward) + |> json_response(200) + + assert @default_limit = length(swaps) + assert ^swaps = Enum.sort_by(swaps, &Validate.id!(&1["tx_hash"])) + assert Enum.all?(swaps, &valid_caller_swap?(&1, caller_id, "TK1", "TK2")) + + assert %{"data" => next_swaps, "prev" => prev_swaps} = + conn |> get(next) |> json_response(200) + + assert @default_limit = length(next_swaps) + + assert ^next_swaps = Enum.sort_by(next_swaps, &Validate.id!(&1["tx_hash"])) + + assert Enum.all?(next_swaps, &valid_caller_swap?(&1, caller_id, "TK1", "TK2")) + + assert %{"data" => ^swaps} = conn |> get(prev_swaps) |> json_response(200) + end end test "gets SwapTokens from both external and parent contracts", %{conn: conn, store: store} do @@ -419,110 +478,166 @@ defmodule AeMdwWeb.DexControllerTest do describe "account_tokens" do test "gets SwapTokens from a caller by desc txi", %{conn: conn, store: store} do - caller_id = encode_account(@account1_pk) - - assert %{"data" => swaps, "next" => next} = - conn - |> with_store(store) - |> get("/v3/accounts/#{caller_id}/dex/swaps") - |> json_response(200) - - assert @default_limit = length(swaps) - assert ^swaps = Enum.sort_by(swaps, &Validate.id!(&1["tx_hash"]), :desc) - assert Enum.all?(swaps, &valid_caller_swap?(&1, caller_id, "TK3", "TK4")) - - assert %{"data" => next_swaps, "prev" => prev_swaps} = - conn |> with_store(store) |> get(next) |> json_response(200) - - assert @default_limit = length(next_swaps) - - assert ^next_swaps = Enum.sort_by(next_swaps, &Validate.id!(&1["tx_hash"]), :desc) - - assert Enum.all?(next_swaps, &valid_caller_swap?(&1, caller_id, "TK3", "TK4")) - - assert %{"data" => ^swaps} = - conn |> with_store(store) |> get(prev_swaps) |> json_response(200) + with_mocks [ + {AeMdw.Node.Db, [:passthrough], + [ + find_block_height: fn _mb_hash -> {:ok, 123} end + ]}, + {AeMdw.DryRun.Runner, [:passthrough], + [ + call_contract: fn _contract_pk, {:micro, _test, _mb_hash}, "meta_info", [] -> + meta_info_tuple = {"name", "SYMBOL", 18} + {:ok, {:tuple, meta_info_tuple}} + end + ]} + ] do + caller_id = encode_account(@account1_pk) + + assert %{"data" => swaps, "next" => next} = + conn + |> with_store(store) + |> get("/v3/accounts/#{caller_id}/dex/swaps") + |> json_response(200) + + assert @default_limit = length(swaps) + assert ^swaps = Enum.sort_by(swaps, &Validate.id!(&1["tx_hash"]), :desc) + assert Enum.all?(swaps, &valid_caller_swap?(&1, caller_id, "TK3", "TK4")) + + assert %{"data" => next_swaps, "prev" => prev_swaps} = + conn |> with_store(store) |> get(next) |> json_response(200) + + assert @default_limit = length(next_swaps) + + assert ^next_swaps = Enum.sort_by(next_swaps, &Validate.id!(&1["tx_hash"]), :desc) + + assert Enum.all?(next_swaps, &valid_caller_swap?(&1, caller_id, "TK3", "TK4")) + + assert %{"data" => ^swaps} = + conn |> with_store(store) |> get(prev_swaps) |> json_response(200) + end end test "gets SwapTokens from a caller by asc txi", %{conn: conn, store: store} do - caller_id = encode_account(@account2_pk) - - assert %{"data" => swaps, "next" => next} = - conn - |> with_store(store) - |> get("/v3/accounts/#{caller_id}/dex/swaps", direction: :forward) - |> json_response(200) - - assert @default_limit = length(swaps) - assert ^swaps = Enum.sort_by(swaps, &Validate.id!(&1["tx_hash"])) - assert Enum.all?(swaps, &valid_caller_swap?(&1, caller_id, "TK1", "TK2")) - - assert %{"data" => next_swaps, "prev" => prev_swaps} = - conn |> with_store(store) |> get(next) |> json_response(200) - - assert @default_limit = length(next_swaps) - - assert ^next_swaps = Enum.sort_by(next_swaps, &Validate.id!(&1["tx_hash"])) - - assert Enum.all?(next_swaps, &valid_caller_swap?(&1, caller_id, "TK1", "TK2")) - - assert %{"data" => ^swaps} = - conn |> with_store(store) |> get(prev_swaps) |> json_response(200) + with_mocks [ + {AeMdw.Node.Db, [:passthrough], + [ + find_block_height: fn _mb_hash -> {:ok, 123} end + ]}, + {AeMdw.DryRun.Runner, [:passthrough], + [ + call_contract: fn _contract_pk, {:micro, _test, _mb_hash}, "meta_info", [] -> + meta_info_tuple = {"name", "SYMBOL", 18} + {:ok, {:tuple, meta_info_tuple}} + end + ]} + ] do + caller_id = encode_account(@account2_pk) + + assert %{"data" => swaps, "next" => next} = + conn + |> with_store(store) + |> get("/v3/accounts/#{caller_id}/dex/swaps", direction: :forward) + |> json_response(200) + + assert @default_limit = length(swaps) + assert ^swaps = Enum.sort_by(swaps, &Validate.id!(&1["tx_hash"])) + assert Enum.all?(swaps, &valid_caller_swap?(&1, caller_id, "TK1", "TK2")) + + assert %{"data" => next_swaps, "prev" => prev_swaps} = + conn |> with_store(store) |> get(next) |> json_response(200) + + assert @default_limit = length(next_swaps) + + assert ^next_swaps = Enum.sort_by(next_swaps, &Validate.id!(&1["tx_hash"])) + + assert Enum.all?(next_swaps, &valid_caller_swap?(&1, caller_id, "TK1", "TK2")) + + assert %{"data" => ^swaps} = + conn |> with_store(store) |> get(prev_swaps) |> json_response(200) + end end test "gets SwapTokens from a caller on a token by desc txi", %{conn: conn, store: store} do - caller_id = encode_account(@account1_pk) - - assert %{"data" => swaps, "next" => next} = - conn - |> with_store(store) - |> get("/v3/accounts/#{caller_id}/dex/swaps", token_symbol: "TK1") - |> json_response(200) - - assert @default_limit = length(swaps) - assert ^swaps = Enum.sort_by(swaps, &Validate.id!(&1["tx_hash"]), :desc) - assert Enum.all?(swaps, &valid_caller_swap?(&1, caller_id, "TK1", "TK2")) - - assert %{"data" => next_swaps, "prev" => prev_swaps} = - conn |> with_store(store) |> get(next) |> json_response(200) - - assert @default_limit = length(next_swaps) - - assert ^next_swaps = Enum.sort_by(next_swaps, &Validate.id!(&1["tx_hash"]), :desc) - - assert Enum.all?(next_swaps, &valid_caller_swap?(&1, caller_id, "TK1", "TK2")) - - assert %{"data" => ^swaps} = - conn |> with_store(store) |> get(prev_swaps) |> json_response(200) + with_mocks [ + {AeMdw.Node.Db, [:passthrough], + [ + find_block_height: fn _mb_hash -> {:ok, 123} end + ]}, + {AeMdw.DryRun.Runner, [:passthrough], + [ + call_contract: fn _contract_pk, {:micro, _test, _mb_hash}, "meta_info", [] -> + meta_info_tuple = {"name", "SYMBOL", 18} + {:ok, {:tuple, meta_info_tuple}} + end + ]} + ] do + caller_id = encode_account(@account1_pk) + + assert %{"data" => swaps, "next" => next} = + conn + |> with_store(store) + |> get("/v3/accounts/#{caller_id}/dex/swaps", token_symbol: "TK1") + |> json_response(200) + + assert @default_limit = length(swaps) + assert ^swaps = Enum.sort_by(swaps, &Validate.id!(&1["tx_hash"]), :desc) + assert Enum.all?(swaps, &valid_caller_swap?(&1, caller_id, "TK1", "TK2")) + + assert %{"data" => next_swaps, "prev" => prev_swaps} = + conn |> with_store(store) |> get(next) |> json_response(200) + + assert @default_limit = length(next_swaps) + + assert ^next_swaps = Enum.sort_by(next_swaps, &Validate.id!(&1["tx_hash"]), :desc) + + assert Enum.all?(next_swaps, &valid_caller_swap?(&1, caller_id, "TK1", "TK2")) + + assert %{"data" => ^swaps} = + conn |> with_store(store) |> get(prev_swaps) |> json_response(200) + end end test "gets SwapTokens from a caller on a token by asc txi", %{conn: conn, store: store} do - caller_id = encode_account(@account2_pk) - - assert %{"data" => swaps, "next" => next} = - conn - |> with_store(store) - |> get("/v3/accounts/#{caller_id}/dex/swaps", - token_symbol: "TK3", - direction: :forward - ) - |> json_response(200) - - assert @default_limit = length(swaps) - assert ^swaps = Enum.sort_by(swaps, &Validate.id!(&1["tx_hash"])) - assert Enum.all?(swaps, &valid_caller_swap?(&1, caller_id, "TK3", "TK4")) - - assert %{"data" => next_swaps, "prev" => prev_swaps} = - conn |> with_store(store) |> get(next) |> json_response(200) - - assert @default_limit = length(next_swaps) - - assert ^next_swaps = Enum.sort_by(next_swaps, &Validate.id!(&1["tx_hash"])) - - assert Enum.all?(next_swaps, &valid_caller_swap?(&1, caller_id, "TK3", "TK4")) - - assert %{"data" => ^swaps} = - conn |> with_store(store) |> get(prev_swaps) |> json_response(200) + with_mocks [ + {AeMdw.Node.Db, [:passthrough], + [ + find_block_height: fn _mb_hash -> {:ok, 123} end + ]}, + {AeMdw.DryRun.Runner, [:passthrough], + [ + call_contract: fn _contract_pk, {:micro, _test, _mb_hash}, "meta_info", [] -> + meta_info_tuple = {"name", "SYMBOL", 18} + {:ok, {:tuple, meta_info_tuple}} + end + ]} + ] do + caller_id = encode_account(@account2_pk) + + assert %{"data" => swaps, "next" => next} = + conn + |> with_store(store) + |> get("/v3/accounts/#{caller_id}/dex/swaps", + token_symbol: "TK3", + direction: :forward + ) + |> json_response(200) + + assert @default_limit = length(swaps) + assert ^swaps = Enum.sort_by(swaps, &Validate.id!(&1["tx_hash"])) + assert Enum.all?(swaps, &valid_caller_swap?(&1, caller_id, "TK3", "TK4")) + + assert %{"data" => next_swaps, "prev" => prev_swaps} = + conn |> with_store(store) |> get(next) |> json_response(200) + + assert @default_limit = length(next_swaps) + + assert ^next_swaps = Enum.sort_by(next_swaps, &Validate.id!(&1["tx_hash"])) + + assert Enum.all?(next_swaps, &valid_caller_swap?(&1, caller_id, "TK3", "TK4")) + + assert %{"data" => ^swaps} = + conn |> with_store(store) |> get(prev_swaps) |> json_response(200) + end end test "returns empty list when no transfer exists", %{conn: conn, store: store} do @@ -548,55 +663,83 @@ defmodule AeMdwWeb.DexControllerTest do describe "contract_swaps" do test "gets SwapTokens from a contract_id by desc txi", %{conn: conn, store: store} do - contract_id = Encoding.encode_contract(@pair1_pk) - - assert %{"data" => swaps, "next" => next} = - conn - |> with_store(store) - |> get("/v3/dex/#{contract_id}/swaps") - |> json_response(200) - - assert @default_limit = length(swaps) - assert ^swaps = Enum.sort_by(swaps, &Validate.id!(&1["tx_hash"]), :desc) - assert Enum.all?(swaps, &valid_token_swap?(&1, "TK1", "TK2")) - - assert %{"data" => next_swaps, "prev" => prev_swaps} = - conn |> with_store(store) |> get(next) |> json_response(200) - - assert @default_limit = length(next_swaps) - - assert ^next_swaps = Enum.sort_by(next_swaps, &Validate.id!(&1["tx_hash"]), :desc) - - assert Enum.all?(next_swaps, &valid_token_swap?(&1, "TK1", "TK2")) - - assert %{"data" => ^swaps} = - conn |> with_store(store) |> get(prev_swaps) |> json_response(200) + with_mocks [ + {AeMdw.Node.Db, [:passthrough], + [ + find_block_height: fn _mb_hash -> {:ok, 123} end + ]}, + {AeMdw.DryRun.Runner, [:passthrough], + [ + call_contract: fn _contract_pk, {:micro, _test, _mb_hash}, "meta_info", [] -> + meta_info_tuple = {"name", "SYMBOL", 18} + {:ok, {:tuple, meta_info_tuple}} + end + ]} + ] do + contract_id = Encoding.encode_contract(@pair1_pk) + + assert %{"data" => swaps, "next" => next} = + conn + |> with_store(store) + |> get("/v3/dex/#{contract_id}/swaps") + |> json_response(200) + + assert @default_limit = length(swaps) + assert ^swaps = Enum.sort_by(swaps, &Validate.id!(&1["tx_hash"]), :desc) + assert Enum.all?(swaps, &valid_token_swap?(&1, "TK1", "TK2")) + + assert %{"data" => next_swaps, "prev" => prev_swaps} = + conn |> with_store(store) |> get(next) |> json_response(200) + + assert @default_limit = length(next_swaps) + + assert ^next_swaps = Enum.sort_by(next_swaps, &Validate.id!(&1["tx_hash"]), :desc) + + assert Enum.all?(next_swaps, &valid_token_swap?(&1, "TK1", "TK2")) + + assert %{"data" => ^swaps} = + conn |> with_store(store) |> get(prev_swaps) |> json_response(200) + end end test "gets SwapTokens from a contract_id by asc txi", %{conn: conn, store: store} do - contract_id = Encoding.encode_contract(@pair2_pk) - - assert %{"data" => swaps, "next" => next} = - conn - |> with_store(store) - |> get("/v3/dex/#{contract_id}/swaps", direction: :forward) - |> json_response(200) - - assert @default_limit = length(swaps) - assert ^swaps = Enum.sort_by(swaps, &Validate.id!(&1["tx_hash"])) - assert Enum.all?(swaps, &valid_token_swap?(&1, "TK3", "TK4")) - - assert %{"data" => next_swaps, "prev" => prev_swaps} = - conn |> with_store(store) |> get(next) |> json_response(200) - - assert @default_limit = length(next_swaps) - - assert ^next_swaps = Enum.sort_by(next_swaps, &Validate.id!(&1["tx_hash"])) - - assert Enum.all?(next_swaps, &valid_token_swap?(&1, "TK3", "TK4")) - - assert %{"data" => ^swaps} = - conn |> with_store(store) |> get(prev_swaps) |> json_response(200) + with_mocks [ + {AeMdw.Node.Db, [:passthrough], + [ + find_block_height: fn _mb_hash -> {:ok, 123} end + ]}, + {AeMdw.DryRun.Runner, [:passthrough], + [ + call_contract: fn _contract_pk, {:micro, _test, _mb_hash}, "meta_info", [] -> + meta_info_tuple = {"name", "SYMBOL", 18} + {:ok, {:tuple, meta_info_tuple}} + end + ]} + ] do + contract_id = Encoding.encode_contract(@pair2_pk) + + assert %{"data" => swaps, "next" => next} = + conn + |> with_store(store) + |> get("/v3/dex/#{contract_id}/swaps", direction: :forward) + |> json_response(200) + + assert @default_limit = length(swaps) + assert ^swaps = Enum.sort_by(swaps, &Validate.id!(&1["tx_hash"])) + assert Enum.all?(swaps, &valid_token_swap?(&1, "TK3", "TK4")) + + assert %{"data" => next_swaps, "prev" => prev_swaps} = + conn |> with_store(store) |> get(next) |> json_response(200) + + assert @default_limit = length(next_swaps) + + assert ^next_swaps = Enum.sort_by(next_swaps, &Validate.id!(&1["tx_hash"])) + + assert Enum.all?(next_swaps, &valid_token_swap?(&1, "TK3", "TK4")) + + assert %{"data" => ^swaps} = + conn |> with_store(store) |> get(prev_swaps) |> json_response(200) + end end test "returns bad request when contract_id is invalid", %{conn: conn} do From a7a032170a392bd8690645e460f8fd3366954a03 Mon Sep 17 00:00:00 2001 From: Valentin Atanasov Date: Fri, 5 Jul 2024 09:59:26 +0300 Subject: [PATCH 3/5] fix: remove unnecessary logging --- lib/ae_mdw/dex.ex | 1 - lib/ae_mdw/sync/dex_cache.ex | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/ae_mdw/dex.ex b/lib/ae_mdw/dex.ex index 232f5d5b5..4d02c28a4 100644 --- a/lib/ae_mdw/dex.ex +++ b/lib/ae_mdw/dex.ex @@ -244,7 +244,6 @@ defmodule AeMdw.Dex do tx_hash: Encoding.encode(:tx_hash, Txs.txi_to_hash(state, txi)), log_idx: log_idx, amounts: rendered_amounts, - # check this one microtime: time, height: height } diff --git a/lib/ae_mdw/sync/dex_cache.ex b/lib/ae_mdw/sync/dex_cache.ex index acb3413a4..f07f08f26 100644 --- a/lib/ae_mdw/sync/dex_cache.ex +++ b/lib/ae_mdw/sync/dex_cache.ex @@ -59,10 +59,10 @@ defmodule AeMdw.Sync.DexCache do @spec add_pair(State.t(), pubkey(), pubkey(), pubkey()) :: :ok def add_pair(state, contract_pk, token1_pk, token2_pk) do - with {:first, {:ok, Model.aexn_contract(meta_info: {_name, symbol1, _dec})}} <- - {:first, State.get(state, Model.AexnContract, {:aex9, token1_pk})}, - {:second, {:ok, Model.aexn_contract(meta_info: {_name, symbol2, _dec})}} <- - {:second, State.get(state, Model.AexnContract, {:aex9, token2_pk})}, + with {:ok, Model.aexn_contract(meta_info: {_name, symbol1, _dec})} <- + State.get(state, Model.AexnContract, {:aex9, token1_pk}), + {:ok, Model.aexn_contract(meta_info: {_name, symbol2, _dec})} <- + State.get(state, Model.AexnContract, {:aex9, token2_pk}), {:ok, pair_create_txi} <- Origin.tx_index(state, {:contract, contract_pk}) do :ets.insert(@tokens_table, {symbol1, pair_create_txi}) :ets.insert(@pairs_table, {contract_pk, token1_pk, token2_pk}) From 9c5c5dc79acdf7f447751fc1185ed7db42b8bf10 Mon Sep 17 00:00:00 2001 From: Valentin Atanasov Date: Mon, 8 Jul 2024 14:19:05 +0300 Subject: [PATCH 4/5] fix: tests --- lib/ae_mdw/dex.ex | 4 +- .../controllers/dex_controller_test.exs | 511 ++++++++++-------- 2 files changed, 295 insertions(+), 220 deletions(-) diff --git a/lib/ae_mdw/dex.ex b/lib/ae_mdw/dex.ex index 4d02c28a4..d9e896a5c 100644 --- a/lib/ae_mdw/dex.ex +++ b/lib/ae_mdw/dex.ex @@ -208,9 +208,7 @@ defmodule AeMdw.Dex do end Model.tx(id: _tx_hash, block_index: {height, _mbi} = block_index, time: time) = - tx = State.fetch!(state, Model.Tx, create_txi) - - IO.inspect(tx) + State.fetch!(state, Model.Tx, create_txi) Model.block(hash: hash) = State.fetch!(state, Model.Block, block_index) contract_pk = Origin.pubkey!(state, {:contract, create_txi}) diff --git a/test/ae_mdw_web/controllers/dex_controller_test.exs b/test/ae_mdw_web/controllers/dex_controller_test.exs index 57ac71ef8..a28af8c73 100644 --- a/test/ae_mdw_web/controllers/dex_controller_test.exs +++ b/test/ae_mdw_web/controllers/dex_controller_test.exs @@ -240,239 +240,259 @@ defmodule AeMdwWeb.DexControllerTest do end end - test "gets SwapTokens from both external and parent contracts", %{conn: conn, store: store} do - caller_id = encode_account(@account1_pk) - pair_pk = <<3::256>> - parent_contract_pk = <<4::256>> - ext_contract_pk = <<5::256>> - parent_contract_pk2 = <<6::256>> - ext_contract_pk2 = <<7::256>> - - pair_txi = 1 - ext_contract_txi = 2 - parent_contract_txi = 3 - parent_contract2_txi = 4 - ext_contract2_txi = 4 - - txi1 = 5 - txi2 = 6 - txi3 = 7 - txi4 = 8 - - log_idx = 0 - - store = - empty_store() - # CASE 1 - |> Store.put( - Model.DexSwapTokens, - Model.dex_swap_tokens(index: {pair_txi, txi1, log_idx}) - ) - |> Store.put( - Model.DexAccountSwapTokens, - Model.dex_account_swap_tokens( - index: {@account1_pk, pair_txi, txi1, log_idx}, - to: @account2_pk, - amounts: [90, 91, 92, 93] + test "gets SwapTokens from both external and parent contracts", %{conn: conn} do + with_mocks [ + {AeMdw.Node.Db, [:passthrough], + [ + find_block_height: fn _mb_hash -> {:ok, 123} end + ]}, + {AeMdw.DryRun.Runner, [:passthrough], + [ + call_contract: fn _contract_pk, {:micro, _test, _mb_hash}, "meta_info", [] -> + meta_info_tuple = {"name", "SYMBOL", 18} + {:ok, {:tuple, meta_info_tuple}} + end + ]} + ] do + caller_id = encode_account(@account1_pk) + pair_pk = <<3::256>> + parent_contract_pk = <<4::256>> + ext_contract_pk = <<5::256>> + parent_contract_pk2 = <<6::256>> + ext_contract_pk2 = <<7::256>> + + pair_txi = 1 + ext_contract_txi = 2 + parent_contract_txi = 3 + parent_contract2_txi = 4 + ext_contract2_txi = 4 + + txi1 = 5 + txi2 = 6 + txi3 = 7 + txi4 = 8 + + log_idx = 0 + + store = + empty_store() + # CASE 1 + |> Store.put( + Model.DexSwapTokens, + Model.dex_swap_tokens(index: {pair_txi, txi1, log_idx}) ) - ) - |> Store.put( - Model.Field, - Model.field(index: {:contract_create_tx, nil, pair_pk, pair_txi}) - ) - |> Store.put( - Model.ContractLog, - Model.contract_log( - index: {pair_txi, txi1, log_idx}, - args: [@account1_pk, @account2_pk] + |> Store.put( + Model.DexAccountSwapTokens, + Model.dex_account_swap_tokens( + index: {@account1_pk, pair_txi, txi1, log_idx}, + to: @account2_pk, + amounts: [90, 91, 92, 93] + ) ) - ) - |> Store.put( - Model.Tx, - Model.tx(index: txi1, id: <>, block_index: {100_001, 0}) - ) - # CASE 2 - |> Store.put( - Model.DexSwapTokens, - Model.dex_swap_tokens(index: {pair_txi, txi2, log_idx}) - ) - |> Store.put( - Model.ContractLog, - Model.contract_log( - index: {pair_txi, txi2, log_idx}, - ext_contract: ext_contract_pk, - args: [@account1_pk, @account2_pk] + |> Store.put( + Model.Field, + Model.field(index: {:contract_create_tx, nil, pair_pk, pair_txi}) ) - ) - |> Store.put( - Model.DexAccountSwapTokens, - Model.dex_account_swap_tokens( - index: {@account1_pk, pair_txi, txi2, log_idx}, - to: @account2_pk, - amounts: [94, 95, 96, 97] + |> Store.put( + Model.ContractLog, + Model.contract_log( + index: {pair_txi, txi1, log_idx}, + args: [@account1_pk, @account2_pk] + ) ) - ) - |> Store.put( - Model.Field, - Model.field(index: {:contract_create_tx, nil, ext_contract_pk, ext_contract_txi}) - ) - |> Store.put( - Model.Tx, - Model.tx(index: txi2, id: <>, block_index: {200_002, 0}) - ) - # CASE 3 - |> Store.put( - Model.DexSwapTokens, - Model.dex_swap_tokens(index: {pair_txi, txi3, log_idx}) - ) - |> Store.put( - Model.ContractLog, - Model.contract_log( - index: {pair_txi, txi3, log_idx}, - ext_contract: {:parent_contract_pk, parent_contract_pk}, - args: [@account1_pk, @account2_pk] + |> Store.put( + Model.Tx, + Model.tx(index: txi1, id: <>, block_index: {100_001, 0}) ) - ) - |> Store.put( - Model.ContractLog, - Model.contract_log( - index: {parent_contract_txi, txi3, log_idx}, - ext_contract: nil + # CASE 2 + |> Store.put( + Model.DexSwapTokens, + Model.dex_swap_tokens(index: {pair_txi, txi2, log_idx}) ) - ) - |> Store.put( - Model.DexAccountSwapTokens, - Model.dex_account_swap_tokens( - index: {@account1_pk, pair_txi, txi3, log_idx}, - to: @account2_pk, - amounts: [98, 99, 100, 101] + |> Store.put( + Model.ContractLog, + Model.contract_log( + index: {pair_txi, txi2, log_idx}, + ext_contract: ext_contract_pk, + args: [@account1_pk, @account2_pk] + ) ) - ) - |> Store.put( - Model.Field, - Model.field(index: {:contract_create_tx, nil, parent_contract_pk, parent_contract_txi}) - ) - |> Store.put( - Model.Tx, - Model.tx(index: txi3, id: <>, block_index: {300_003, 0}) - ) - # CASE 4 - |> Store.put( - Model.DexSwapTokens, - Model.dex_swap_tokens(index: {pair_txi, txi4, log_idx}) - ) - |> Store.put( - Model.ContractLog, - Model.contract_log( - index: {pair_txi, txi4, log_idx}, - ext_contract: {:parent_contract_pk, parent_contract_pk2}, - args: [@account1_pk, @account2_pk] + |> Store.put( + Model.DexAccountSwapTokens, + Model.dex_account_swap_tokens( + index: {@account1_pk, pair_txi, txi2, log_idx}, + to: @account2_pk, + amounts: [94, 95, 96, 97] + ) ) - ) - |> Store.put( - Model.ContractLog, - Model.contract_log( - index: {parent_contract2_txi, txi4, log_idx}, - ext_contract: ext_contract_pk2 + |> Store.put( + Model.Field, + Model.field(index: {:contract_create_tx, nil, ext_contract_pk, ext_contract_txi}) ) - ) - |> Store.put( - Model.DexAccountSwapTokens, - Model.dex_account_swap_tokens( - index: {@account1_pk, pair_txi, txi4, log_idx}, - to: @account2_pk, - amounts: [102, 103, 104, 105] + |> Store.put( + Model.Tx, + Model.tx(index: txi2, id: <>, block_index: {200_002, 0}) ) - ) - |> Store.put( - Model.Field, - Model.field( - index: {:contract_create_tx, nil, parent_contract_pk2, parent_contract2_txi} + # CASE 3 + |> Store.put( + Model.DexSwapTokens, + Model.dex_swap_tokens(index: {pair_txi, txi3, log_idx}) ) - ) - |> Store.put( - Model.Field, - Model.field(index: {:contract_create_tx, nil, ext_contract_pk2, ext_contract2_txi}) - ) - |> Store.put( - Model.Tx, - Model.tx(index: txi4, id: <>, block_index: {400_004, 0}) - ) - - :ets.insert(:dex_pairs_symbols, {pair_txi, "TK1", "TK2"}) - :ets.insert(:dex_pairs_symbols, {ext_contract_txi, "TK3", "TK4"}) - :ets.insert(:dex_pairs_symbols, {parent_contract_txi, "TK5", "TK6"}) - :ets.insert(:dex_pairs_symbols, {ext_contract2_txi, "TK7", "TK8"}) + |> Store.put( + Model.ContractLog, + Model.contract_log( + index: {pair_txi, txi3, log_idx}, + ext_contract: {:parent_contract_pk, parent_contract_pk}, + args: [@account1_pk, @account2_pk] + ) + ) + |> Store.put( + Model.ContractLog, + Model.contract_log( + index: {parent_contract_txi, txi3, log_idx}, + ext_contract: nil + ) + ) + |> Store.put( + Model.DexAccountSwapTokens, + Model.dex_account_swap_tokens( + index: {@account1_pk, pair_txi, txi3, log_idx}, + to: @account2_pk, + amounts: [98, 99, 100, 101] + ) + ) + |> Store.put( + Model.Field, + Model.field( + index: {:contract_create_tx, nil, parent_contract_pk, parent_contract_txi} + ) + ) + |> Store.put( + Model.Tx, + Model.tx(index: txi3, id: <>, block_index: {300_003, 0}) + ) + # CASE 4 + |> Store.put( + Model.DexSwapTokens, + Model.dex_swap_tokens(index: {pair_txi, txi4, log_idx}) + ) + |> Store.put( + Model.ContractLog, + Model.contract_log( + index: {pair_txi, txi4, log_idx}, + ext_contract: {:parent_contract_pk, parent_contract_pk2}, + args: [@account1_pk, @account2_pk] + ) + ) + |> Store.put( + Model.ContractLog, + Model.contract_log( + index: {parent_contract2_txi, txi4, log_idx}, + ext_contract: ext_contract_pk2 + ) + ) + |> Store.put( + Model.DexAccountSwapTokens, + Model.dex_account_swap_tokens( + index: {@account1_pk, pair_txi, txi4, log_idx}, + to: @account2_pk, + amounts: [102, 103, 104, 105] + ) + ) + |> Store.put( + Model.Field, + Model.field( + index: {:contract_create_tx, nil, parent_contract_pk2, parent_contract2_txi} + ) + ) + |> Store.put( + Model.Field, + Model.field(index: {:contract_create_tx, nil, ext_contract_pk2, ext_contract2_txi}) + ) + |> Store.put( + Model.Tx, + Model.tx(index: txi4, id: <>, block_index: {400_004, 0}) + ) + |> add_supporting_dex_data(pair_txi, "TK11", "TK12") + |> add_supporting_dex_data(ext_contract_txi, "TK13", "TK14") + |> add_supporting_dex_data(parent_contract_txi, "TK15", "TK16") + |> add_supporting_dex_data(parent_contract2_txi, "TK17", "TK18") - assert %{"data" => swaps, "next" => next} = - conn - |> with_store(store) - |> get("/v3/dex/swaps", direction: :forward, limit: 2) - |> json_response(200) + :ets.insert(:dex_pairs_symbols, {pair_txi, "TK11", "TK12"}) + :ets.insert(:dex_pairs_symbols, {ext_contract_txi, "TK13", "TK14"}) + :ets.insert(:dex_pairs_symbols, {parent_contract_txi, "TK15", "TK16"}) + :ets.insert(:dex_pairs_symbols, {ext_contract2_txi, "TK17", "TK18"}) - assert 2 = length(swaps) + assert %{"data" => swaps, "next" => next} = + conn + |> with_store(store) + |> get("/v3/dex/swaps", direction: :forward, limit: 2) + |> json_response(200) - assert [ - %{ - "amounts" => %{ - "amount0_in" => 90, - "amount0_out" => 92, - "amount1_in" => 91, - "amount1_out" => 93 - }, - "caller" => ^caller_id, - "from_token" => "TK1", - "log_idx" => 0, - "to_token" => "TK2" - }, - %{ - "amounts" => %{ - "amount0_in" => 94, - "amount0_out" => 96, - "amount1_in" => 95, - "amount1_out" => 97 - }, - "caller" => ^caller_id, - "from_token" => "TK3", - "log_idx" => 0, - "to_token" => "TK4" - } - ] = swaps - - assert %{"data" => next_swaps, "prev" => prev_swaps} = - conn |> with_store(store) |> get(next) |> json_response(200) - - assert 2 = length(next_swaps) - - assert [ - %{ - "amounts" => %{ - "amount0_in" => 98, - "amount0_out" => 100, - "amount1_in" => 99, - "amount1_out" => 101 + assert 2 = length(swaps) + + assert [ + %{ + "amounts" => %{ + "amount0_in" => 90, + "amount0_out" => 92, + "amount1_in" => 91, + "amount1_out" => 93 + }, + "caller" => ^caller_id, + "from_token" => "TK11", + "log_idx" => 0, + "to_token" => "TK12" }, - "caller" => ^caller_id, - "from_token" => "TK5", - "log_idx" => 0, - "to_token" => "TK6" - }, - %{ - "amounts" => %{ - "amount0_in" => 102, - "amount0_out" => 104, - "amount1_in" => 103, - "amount1_out" => 105 + %{ + "amounts" => %{ + "amount0_in" => 94, + "amount0_out" => 96, + "amount1_in" => 95, + "amount1_out" => 97 + }, + "caller" => ^caller_id, + "from_token" => "TK13", + "log_idx" => 0, + "to_token" => "TK14" + } + ] = swaps + + assert %{"data" => next_swaps, "prev" => prev_swaps} = + conn |> with_store(store) |> get(next) |> json_response(200) + + assert 2 = length(next_swaps) + + assert [ + %{ + "amounts" => %{ + "amount0_in" => 98, + "amount0_out" => 100, + "amount1_in" => 99, + "amount1_out" => 101 + }, + "caller" => ^caller_id, + "from_token" => "TK15", + "log_idx" => 0, + "to_token" => "TK16" }, - "caller" => ^caller_id, - "from_token" => "TK7", - "log_idx" => 0, - "to_token" => "TK8" - } - ] = next_swaps - - assert %{"data" => ^swaps} = - conn |> with_store(store) |> get(prev_swaps) |> json_response(200) + %{ + "amounts" => %{ + "amount0_in" => 102, + "amount0_out" => 104, + "amount1_in" => 103, + "amount1_out" => 105 + }, + "caller" => ^caller_id, + "from_token" => "TK17", + "log_idx" => 0, + "to_token" => "TK18" + } + ] = next_swaps + + assert %{"data" => ^swaps} = + conn |> with_store(store) |> get(prev_swaps) |> json_response(200) + end end end @@ -803,4 +823,61 @@ defmodule AeMdwWeb.DexControllerTest do "amount1_out" => txi + 40 } end + + defp add_supporting_dex_data(store, txi, token1_symbol, token2_symbol) do + block_index_number = 900_000 + txi + block_index = {block_index_number, 0} + + token1_pk = :crypto.strong_rand_bytes(32) + token2_pk = :crypto.strong_rand_bytes(32) + + store = + store + |> Store.put( + Model.Tx, + Model.tx( + index: txi, + id: <>, + block_index: block_index + ) + ) + |> Store.put( + Model.Block, + Model.block( + index: block_index, + hash: <> + ) + ) + |> Store.put( + Model.RevOrigin, + Model.rev_origin(index: {txi, :contract_create_tx, <>}) + ) + |> Store.put( + Model.Field, + Model.field( + index: {:contract_create_tx, nil, <>, block_index_number} + ) + ) + |> Store.put( + Model.AexnContract, + Model.aexn_contract(index: {:aex9, token1_pk}, meta_info: {"TOKEN1", token1_symbol, 18}) + ) + |> Store.put( + Model.AexnContract, + Model.aexn_contract(index: {:aex9, token2_pk}, meta_info: {"TOKEN2", token2_symbol, 18}) + ) + + # TODO: TESTS randomly fail + + state = State.new(store) + + DexCache.add_pair( + state, + <>, + token1_pk, + token2_pk + ) + + store + end end From c08db84be954b0b00d1bbc7222f91f3ba0d77140 Mon Sep 17 00:00:00 2001 From: Valentin Atanasov Date: Mon, 8 Jul 2024 14:30:07 +0300 Subject: [PATCH 5/5] fix: remove unnecessary comment --- test/ae_mdw_web/controllers/dex_controller_test.exs | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/ae_mdw_web/controllers/dex_controller_test.exs b/test/ae_mdw_web/controllers/dex_controller_test.exs index a28af8c73..348d6e7e4 100644 --- a/test/ae_mdw_web/controllers/dex_controller_test.exs +++ b/test/ae_mdw_web/controllers/dex_controller_test.exs @@ -867,8 +867,6 @@ defmodule AeMdwWeb.DexControllerTest do Model.aexn_contract(index: {:aex9, token2_pk}, meta_info: {"TOKEN2", token2_symbol, 18}) ) - # TODO: TESTS randomly fail - state = State.new(store) DexCache.add_pair(