Skip to content
This repository has been archived by the owner on Jun 5, 2023. It is now read-only.

Commit

Permalink
Merge pull request #400 from helium/madninja/rewards_block
Browse files Browse the repository at this point in the history
Add /v1/[accounts|hotspots]/:address/rewards/:block
  • Loading branch information
madninja authored Jan 13, 2022
2 parents 24e5010 + 17f1380 commit f6ce7ee
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 7 deletions.
12 changes: 10 additions & 2 deletions priv/rewards.sql
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
-- :reward_fields
r.block, r.transaction_hash, to_timestamp(r.time) as timestamp, r.account, r.gateway, r.amount
r.block, r.transaction_hash, to_timestamp(r.time) as timestamp, r.account, r.gateway, r.amount, r.type

-- Make sure that marker fields and fields are equivalent except for the marker
-- placeholder!
-- :reward_marker_fields
r.block, r.transaction_hash, to_timestamp(r.time) as timestamp, r.account, r.gateway, r.amount, :marker
r.block, r.transaction_hash, to_timestamp(r.time) as timestamp, r.account, r.gateway, r.amount, r.type, :marker

-- :reward_list_base
select :fields
Expand All @@ -20,6 +20,14 @@ from rewards r
and r.block = $2 and :marker> $3
order by :marker

-- :reward_block_list_base
select :fields
from rewards r
:scope
and r.block = $2
order by r.gateway, r.type
offset $3 fetch next $4 rows only

-- :reward_sum_hotspot_source
(select
sum(r.amount) as amount
Expand Down
12 changes: 12 additions & 0 deletions src/bh_route_accounts.erl
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,18 @@ handle('GET', [Account, <<"rewards">>], Req) ->
handle('GET', [Account, <<"rewards">>, <<"sum">>], Req) ->
Args = ?GET_ARGS([max_time, min_time, bucket], Req),
?MK_RESPONSE(bh_route_rewards:get_reward_sum({account, Account}, Args), block_time);
handle('GET', [Account, <<"rewards">>, Block], Req) ->
Args = ?GET_ARGS([cursor], Req),
bh_route_handler:try_or_else(
fun() -> binary_to_integer(Block) end,
fun(Height) ->
?MK_RESPONSE(
bh_route_rewards:get_reward_list({account, Account}, Args ++ [{block, Height}]),
infinity
)
end,
?RESPONSE_400
);
handle('GET', [Account, <<"pending_transactions">>], Req) ->
Args = ?GET_ARGS([cursor], Req),
?MK_RESPONSE(bh_route_pending_txns:get_pending_txn_list({actor, Account}, Args), never);
Expand Down
12 changes: 12 additions & 0 deletions src/bh_route_hotspots.erl
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,18 @@ handle('GET', [Address, <<"rewards">>], Req) ->
handle('GET', [Address, <<"rewards">>, <<"sum">>], Req) ->
Args = ?GET_ARGS([max_time, min_time, bucket], Req),
?MK_RESPONSE(bh_route_rewards:get_reward_sum({hotspot, Address}, Args), block_time);
handle('GET', [Address, <<"rewards">>, Block], Req) ->
Args = ?GET_ARGS([cursor], Req),
bh_route_handler:try_or_else(
fun() -> binary_to_integer(Block) end,
fun(Height) ->
?MK_RESPONSE(
bh_route_rewards:get_reward_list({hotspot, Address}, Args ++ [{block, Height}]),
infinity
)
end,
?RESPONSE_400
);
handle('GET', [<<"rewards">>, <<"sum">>], Req) ->
%% We do not allow bucketing across all hotspots as that takes way too long
Args = ?GET_ARGS([max_time, min_time], Req),
Expand Down
59 changes: 54 additions & 5 deletions src/bh_route_rewards.erl
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
-define(REWARD_LIST_LIMIT, 100).
-define(S_REWARD_LIST_HOTSPOT, "reward_list_hotspot").
-define(S_REWARD_LIST_HOTSPOT_REM, "reward_list_hotspot_rem").
-define(S_REWARD_LIST_HOTSPOT_BLOCK, "reward_list_hotspot_block").
-define(S_REWARD_LIST_ACCOUNT, "reward_list_account").
-define(S_REWARD_LIST_ACCOUNT_REM, "reward_list_account_rem").
-define(S_REWARD_LIST_ACCOUNT_BLOCK, "reward_list_account_block").
-define(S_REWARD_SUM_HOTSPOT, "reward_sum_hotstpot").
-define(S_REWARD_SUM_HOTSPOTS, "reward_sum_hotspots").
-define(S_REWARD_SUM_VALIDATOR, "reward_sum_validator").
Expand Down Expand Up @@ -52,6 +54,13 @@ prepare_conn(_Conn) ->
{marker, "r.transaction_hash"}
],
[text, int8, text]}},
{?S_REWARD_LIST_HOTSPOT_BLOCK,
{reward_block_list_base,
[
{fields, reward_fields},
{scope, "where r.gateway = $1"}
],
[text, int8, int8, int8]}},
{?S_REWARD_LIST_ACCOUNT,
{reward_list_base,
[
Expand All @@ -71,6 +80,13 @@ prepare_conn(_Conn) ->
{marker, "r.gateway"}
],
[text, int8, text]}},
{?S_REWARD_LIST_ACCOUNT_BLOCK,
{reward_block_list_base,
[
{fields, reward_fields},
{scope, "where r.account = $1"}
],
[text, int8, int8, int8]}},

{?S_REWARD_SUM_HOTSPOT,
{reward_sum_base,
Expand Down Expand Up @@ -199,10 +215,14 @@ get_full_reward_list(Args, Query, [{max_time, MaxTime}, {min_time, MinTime}]) ->

get_reward_list({hotspot, Address}, Args = [{cursor, _}, {max_time, _}, {min_time, _}]) ->
get_reward_list([Address], {?S_REWARD_LIST_HOTSPOT, ?S_REWARD_LIST_HOTSPOT_REM}, Args);
get_reward_list({hotspot, Address}, Args = [{cursor, _}, {block, _}]) ->
get_reward_list([Address], ?S_REWARD_LIST_HOTSPOT_BLOCK, Args);
get_reward_list({validator, Address}, Args = [{cursor, _}, {max_time, _}, {min_time, _}]) ->
get_reward_list([Address], {?S_REWARD_LIST_HOTSPOT, ?S_REWARD_LIST_HOTSPOT_REM}, Args);
get_reward_list({account, Address}, Args = [{cursor, _}, {max_time, _}, {min_time, _}]) ->
get_reward_list([Address], {?S_REWARD_LIST_ACCOUNT, ?S_REWARD_LIST_ACCOUNT_REM}, Args).
get_reward_list([Address], {?S_REWARD_LIST_ACCOUNT, ?S_REWARD_LIST_ACCOUNT_REM}, Args);
get_reward_list({account, Address}, Args = [{cursor, _}, {block, _}]) ->
get_reward_list([Address], ?S_REWARD_LIST_ACCOUNT_BLOCK, Args).

%% network
get_reward_sum(
Expand Down Expand Up @@ -318,6 +338,23 @@ calc_low_block(HighBlock, EndBlock) ->
max(EndBlock, Other)
end.

get_reward_list(
Args,
Query,
[{cursor, Cursor}, {block, Height}]
) ->
Offset =
case Cursor of
undefined ->
0;
C ->
case ?CURSOR_DECODE(C) of
{ok, #{<<"offset">> := V}} -> V;
_ -> throw(?RESPONSE_400)
end
end,
Result = ?PREPARED_QUERY(Query, Args ++ [Height, Offset, ?REWARD_LIST_LIMIT + 1]),
mk_reward_block_list_result(Offset, Result);
get_reward_list(
Args,
{Query, _RemQuery},
Expand Down Expand Up @@ -401,11 +438,20 @@ get_reward_sum_cache_time([{max_time, _MaxTime}, {min_time, _MinTime}, {bucket,
% But if min/max are specified, cache as long as possible
infinity.

mk_reward_block_list_result(Offset, {ok, _, Results}) when length(Results) > ?REWARD_LIST_LIMIT ->
{Trimmed, _Remainder} = lists:split(?REWARD_LIST_LIMIT, Results),
{ok, reward_list_to_json(Trimmed), mk_reward_block_list_cursor(Offset + length(Trimmed))};
mk_reward_block_list_result(_Offset, {ok, _, Results}) ->
{ok, reward_list_to_json(Results)}.

mk_reward_block_list_cursor(Offset) ->
#{offset => Offset}.

mk_reward_list_result(State = #state{results = Results}) when
length(Results) > ?REWARD_LIST_LIMIT
->
{Trimmed, _Remainder} = lists:split(?REWARD_LIST_LIMIT, Results),
{Block, _Hash, _Timestamp, _Account, _Gateway, _Amount, Marker} = lists:last(Trimmed),
{Block, _Hash, _Timestamp, _Account, _Gateway, _Amount, _Type, Marker} = lists:last(Trimmed),
{ok, reward_list_to_json(Trimmed), mk_reward_list_cursor(Block, Marker, State)};
mk_reward_list_result(State = #state{results = Results}) ->
{ok, reward_list_to_json(Results),
Expand Down Expand Up @@ -460,15 +506,18 @@ mk_reward_list_cursor(BeforeBlock, Marker, State = #state{}) ->
reward_list_to_json(Results) ->
lists:map(fun reward_to_json/1, Results).

reward_to_json({Block, Hash, Timestamp, Account, Gateway, Amount, _Marker}) ->
reward_to_json({Block, Hash, Timestamp, Account, Gateway, Amount, Type}) ->
#{
<<"block">> => Block,
<<"hash">> => Hash,
<<"timestamp">> => iso8601:format(Timestamp),
<<"account">> => Account,
<<"gateway">> => Gateway,
<<"amount">> => Amount
}.
<<"amount">> => Amount,
<<"type">> => Type
};
reward_to_json({Block, Hash, Timestamp, Account, Gateway, Amount, Type, _Marker}) ->
reward_to_json({Block, Hash, Timestamp, Account, Gateway, Amount, Type}).

reward_buckets_to_json(Results) ->
lists:map(fun reward_stat_to_json/1, Results).
Expand Down
24 changes: 24 additions & 0 deletions test/bh_route_accounts_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ all() ->
rewards_dupe_test,
rewards_sum_test,
rewards_buckets_test,
rewards_block_test,
rich_list_test
].

Expand Down Expand Up @@ -261,6 +262,29 @@ rewards_test(_Config) ->

ok.

rewards_block_test(_Config) ->
Account = "13ESLoXiie3eXoyitxryNQNamGAnJjKt2WkiB4gNq95knxAiGEp",
{ok, {_, _, Json}} =
?json_request([
"/v1/accounts/",
Account,
"/rewards/1167207"
]),
#{<<"data">> := Data, <<"cursor">> := Cursor} = Json,
?assert(length(Data) >= 0),

{ok, {_, _, CursorJson}} =
?json_request([
"/v1/accounts/",
Account,
"/rewards/1167207?cursor=",
Cursor
]),
#{<<"data">> := CursorData} = CursorJson,
?assert(length(CursorData) >= 0),

ok.

rewards_dupe_test(_Config) ->
% This account and time range was reported to have a duplicate between the
% two pages that build it up. This test ensures that the fetched
Expand Down
13 changes: 13 additions & 0 deletions test/bh_route_hotspots_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ all() ->
rewards_all_sum_test,
rewards_sum_test,
rewards_buckets_test,
rewards_block_test,
witnesses_test,
witnessed_test,
witnesses_buckets_test,
Expand Down Expand Up @@ -300,6 +301,18 @@ rewards_test(_Config) ->
end,
ok.

rewards_block_test(_Config) ->
Hotspot = "112WaLcxSnEQTSTiyB46ey4WVr9SUiYcCjrFRXYcv1mp9bdobDxR",
{ok, {_, _, Json}} =
?json_request([
"/v1/hotspots/",
Hotspot,
"/rewards/1167207"
]),
#{<<"data">> := Data} = Json,
?assert(length(Data) >= 0),
ok.

rewards_all_sum_test(_Config) ->
{ok, {_, _, Json}} =
?json_request([
Expand Down

0 comments on commit f6ce7ee

Please sign in to comment.