Skip to content

Commit

Permalink
fix: include local-idx cursor when paginating tx call activities (#1707)
Browse files Browse the repository at this point in the history
  • Loading branch information
sborrazas committed Mar 21, 2024
1 parent 84a6837 commit e0ba8ae
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 34 deletions.
43 changes: 28 additions & 15 deletions lib/ae_mdw/activities.ex
Expand Up @@ -119,6 +119,8 @@ defmodule AeMdw.Activities do
nil -> {nil, nil, nil}
end

txi_idx_cursor = if txi_cursor, do: {txi_cursor, local_idx_cursor}, else: nil

ownership_only? = Map.get(filters, :ownership_only?, false)
stream_types = Map.get(filters, :stream_types)

Expand Down Expand Up @@ -156,15 +158,15 @@ defmodule AeMdw.Activities do
direction,
account_pk,
txi_scope,
txi_cursor
txi_idx_cursor
),
:ext_calls =>
build_ext_contract_calls_stream(
state,
direction,
account_pk,
txi_scope,
txi_cursor,
txi_idx_cursor,
ownership_only?
),
:aex9 =>
Expand Down Expand Up @@ -462,7 +464,7 @@ defmodule AeMdw.Activities do
_direction,
_account_pk,
_txi_scope,
_txi_cursor,
_txi_idx_cursor,
true = _ownership_only?
),
do: []
Expand All @@ -472,12 +474,13 @@ defmodule AeMdw.Activities do
direction,
account_pk,
txi_scope,
txi_cursor,
txi_idx_cursor,
false = _ownership_only?
),
do: build_ext_contract_calls_stream(state, direction, account_pk, txi_scope, txi_cursor)
do:
build_ext_contract_calls_stream(state, direction, account_pk, txi_scope, txi_idx_cursor)

defp build_ext_contract_calls_stream(state, direction, account_pk, txi_scope, txi_cursor) do
defp build_ext_contract_calls_stream(state, direction, account_pk, txi_scope, txi_idx_cursor) do
0..@max_pos
|> Enum.map(fn pos ->
key_boundary =
Expand All @@ -490,10 +493,15 @@ defmodule AeMdw.Activities do
end

cursor =
case txi_cursor do
nil -> nil
txi_cursor when direction == :forward -> {account_pk, pos, txi_cursor, @min_int}
txi_cursor when direction == :backward -> {account_pk, pos, txi_cursor, @max_int}
case txi_idx_cursor do
nil ->
nil

{txi_cursor, local_idx_cursor} when direction == :forward ->
{account_pk, pos, txi_cursor, local_idx_cursor}

{txi_cursor, local_idx_cursor} when direction == :backward ->
{account_pk, pos, txi_cursor, local_idx_cursor}
end

state
Expand All @@ -506,7 +514,7 @@ defmodule AeMdw.Activities do
|> Stream.dedup_by(fn {txi, {:int_contract_call, local_idx}} -> {txi, local_idx} end)
end

defp build_int_contract_calls_stream(state, direction, account_pk, txi_scope, txi_cursor) do
defp build_int_contract_calls_stream(state, direction, account_pk, txi_scope, txi_idx_cursor) do
case Origin.tx_index(state, {:contract, account_pk}) do
{:ok, create_txi} ->
key_boundary =
Expand All @@ -519,10 +527,15 @@ defmodule AeMdw.Activities do
end

cursor =
case txi_cursor do
nil -> nil
txi_cursor when direction == :forward -> {create_txi, txi_cursor, @min_int}
txi_cursor when direction == :backward -> {create_txi, txi_cursor, @max_int}
case txi_idx_cursor do
nil ->
nil

{txi_cursor, local_idx_cursor} when direction == :forward ->
{create_txi, txi_cursor, local_idx_cursor}

{txi_cursor, local_idx_cursor} when direction == :backward ->
{create_txi, txi_cursor, local_idx_cursor}
end

state
Expand Down
68 changes: 49 additions & 19 deletions test/ae_mdw_web/controllers/activities_controller_test.exs
Expand Up @@ -369,41 +369,63 @@ defmodule AeMdwWeb.ActivitiesControllerTest do
mb_hash = TS.micro_block_hash(0)
enc_mb_hash = Enc.encode(:micro_block_hash, mb_hash)

{:ok, aetx} =
{:ok, aetx1} =
:aec_spend_tx.new(%{
sender_id: account_id,
recipient_id: account_id,
amount: 2,
amount: 111,
fee: 3,
nonce: 4,
payload: ""
})

{:spend_tx, tx} = :aetx.specialize_type(aetx)
{:spend_tx, tx1} = :aetx.specialize_type(aetx1)

{:ok, aetx2} =
:aec_spend_tx.new(%{
sender_id: account_id,
recipient_id: account_id,
amount: 222,
fee: 3,
nonce: 4,
payload: ""
})

{:spend_tx, tx2} = :aetx.specialize_type(aetx2)

{:ok, aetx3} =
:aec_spend_tx.new(%{
sender_id: account_id,
recipient_id: account_id,
amount: 333,
fee: 3,
nonce: 4,
payload: ""
})

store =
empty_store()
|> Store.put(
Model.IdIntContractCall,
Model.id_int_contract_call(index: {contract_pk, 1, 1, 0})
)
|> Store.put(Model.IntContractCall, Model.int_contract_call(index: {1, 0}))
|> Store.put(Model.IntContractCall, Model.int_contract_call(index: {1, 0}, tx: aetx1))
|> Store.put(
Model.IdIntContractCall,
Model.id_int_contract_call(index: {contract_pk, 1, 1, 1})
)
|> Store.put(Model.IntContractCall, Model.int_contract_call(index: {1, 1}))
|> Store.put(Model.IntContractCall, Model.int_contract_call(index: {1, 1}, tx: aetx2))
|> Store.put(Model.Tx, Model.tx(index: 1, block_index: {height, mbi}, id: "hash1"))
|> Store.put(
Model.IdIntContractCall,
Model.id_int_contract_call(index: {contract_pk, 3, 2, 0})
)
|> Store.put(Model.IntContractCall, Model.int_contract_call(index: {2, 0}))
|> Store.put(Model.IntContractCall, Model.int_contract_call(index: {2, 0}, tx: aetx3))
|> Store.put(
Model.IdIntContractCall,
Model.id_int_contract_call(index: {contract_pk, 1, 2, 1})
)
|> Store.put(Model.IntContractCall, Model.int_contract_call(index: {2, 1}))
|> Store.put(Model.IntContractCall, Model.int_contract_call(index: {2, 1}, tx: aetx3))
|> Store.put(Model.Tx, Model.tx(index: 2, block_index: {height, mbi}, id: "hash2"))
|> Store.put(Model.Block, Model.block(index: {height, -1}, hash: kb_hash))
|> Store.put(Model.Block, Model.block(index: {height, mbi}, hash: mb_hash))
Expand All @@ -413,43 +435,51 @@ defmodule AeMdwWeb.ActivitiesControllerTest do
[
get_tx_data: fn
"hash1" ->
{"", :spend_tx, aetx, tx}
{"", :spend_tx, aetx1, tx1}

"hash2" ->
{"", :spend_tx, aetx, tx}
{"", :spend_tx, aetx2, tx2}
end,
get_block_time: fn _block_hash ->
456
end
]},
{:aec_db, [], [get_header: fn _block_hash -> :header end]},
{:aetx_sign, [], [serialize_for_client: fn :header, ^aetx -> %{} end]},
{Format, [], [to_map: fn _state, _record, _tab -> %{} end]}
{:aetx_sign, [:passthrough], [serialize_for_client: fn :header, _aetx -> %{} end]}
] do
assert %{"prev" => nil, "data" => [tx1, tx2], "next" => next_url} =
assert %{"prev" => nil, "data" => [tx1] = data1, "next" => next_url} =
conn
|> with_store(store)
|> get("/v2/accounts/#{contract}/activities", direction: "forward", limit: 2)
|> get("/v2/accounts/#{contract}/activities", direction: "forward", limit: 1)
|> json_response(200)

assert %{
"height" => ^height,
"block_hash" => ^enc_mb_hash,
"block_time" => 456,
"type" => "InternalContractCallEvent"
"type" => "InternalContractCallEvent",
"payload" => %{"internal_tx" => %{"amount" => 111}, "local_idx" => 0}
} = tx1

assert %{"prev" => prev_url, "data" => [tx2], "next" => _next_url} =
conn
|> with_store(store)
|> get(next_url)
|> json_response(200)

assert %{
"height" => ^height,
"block_hash" => ^enc_mb_hash,
"block_time" => 456,
"type" => "InternalContractCallEvent"
"type" => "InternalContractCallEvent",
"payload" => %{"internal_tx" => %{"amount" => 222}, "local_idx" => 1}
} = tx2

assert %URI{query: query} = URI.parse(next_url)

assert %{"cursor" => _cursor, "direction" => "forward", "limit" => "2"} =
URI.decode_query(query)
assert %{"data" => ^data1} =
conn
|> with_store(store)
|> get(prev_url)
|> json_response(200)
end
end

Expand Down

0 comments on commit e0ba8ae

Please sign in to comment.