Skip to content

Commit

Permalink
Add GetAuctionEntryByName endpoint (#4259)
Browse files Browse the repository at this point in the history
* GH4128: Add GetAuctionEntryByName endpoint

* Remove stray logging
  • Loading branch information
hanssv committed Feb 21, 2024
1 parent 240f4fe commit 01dd226
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 3 deletions.
12 changes: 11 additions & 1 deletion apps/aecore/src/aec_chain.erl
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@
]).

%%% NS API
-export([ name_entry/1
-export([ auction_entry/1
, name_entry/1
, resolve_name/2
, resolve_namehash/2
]).
Expand Down Expand Up @@ -259,6 +260,15 @@ get_channel_at_hash(ChannelPubkey, Hash) ->
%%% Name service
%%%===================================================================

-spec auction_entry(binary()) ->
{'ok', map()} |
{'error', atom()}.
auction_entry(Name) ->
case get_top_state() of
{ok, Trees} -> aens:get_auction_entry(Name, aec_trees:ns(Trees));
error -> {error, no_state_trees}
end.

-spec name_entry(binary()) ->
{'ok', map()} |
{'error', atom()}.
Expand Down
53 changes: 53 additions & 0 deletions apps/aehttp/priv/oas3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,41 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/Error"
"/auctions/{name}":
get:
tags:
- external
- name_service
operationId: GetAuctionEntryByName
description: Get auction entry from naming system
parameters:
- $ref: '#/components/parameters/intAsString'
- in: path
name: name
description: The name key of the name entry
required: true
schema:
type: string
example: "dimitar.chain"
responses:
"200":
description: Successful operation
content:
application/json:
schema:
$ref: "#/components/schemas/AuctionEntry"
"400":
description: Invalid name
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
"404":
description: Name not found
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
"/names/{name}":
get:
tags:
Expand Down Expand Up @@ -2473,6 +2508,24 @@ components:
required:
- type
- value
AuctionEntry:
type: object
properties:
id:
$ref: "#/components/schemas/EncodedValue"
started_at:
$ref: "#/components/schemas/UInt64"
ends_at:
$ref: "#/components/schemas/UInt64"
highest_bidder:
$ref: "#/components/schemas/EncodedPubkey"
highest_bid:
$ref: "#/components/schemas/UInt"
required:
- id
- ends_at
- highest_bidder
- highest_bid
NameEntry:
type: object
properties:
Expand Down
46 changes: 46 additions & 0 deletions apps/aehttp/priv/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,34 @@ paths:
description: 'Oracle query not found'
schema:
$ref: '#/definitions/Error'
/auctions/{name}:
get:
tags:
- external
- name_service
operationId: GetAuctionEntryByName
description: 'Get auction entry from naming system'
produces:
- application/json
parameters:
- in: path
name: name
description: 'The name key of the name entry'
required: true
type: string
responses:
'200':
description: 'Successful operation'
schema:
$ref: '#/definitions/AuctionEntry'
'400':
description: 'Invalid name'
schema:
$ref: '#/definitions/Error'
'404':
description: 'Name not found'
schema:
$ref: '#/definitions/Error'
/names/{name}:
get:
tags:
Expand Down Expand Up @@ -2356,6 +2384,24 @@ definitions:
required:
- type
- value
AuctionEntry:
type: object
properties:
id:
$ref: '#/definitions/EncodedValue'
started_at:
$ref: '#/definitions/UInt64'
ends_at:
$ref: '#/definitions/UInt64'
highest_bidder:
$ref: '#/definitions/EncodedPubkey'
highest_bid:
$ref: '#/definitions/UInt'
required:
- id
- ends_at
- highest_bidder
- highest_bid
NameEntry:
type: object
properties:
Expand Down
24 changes: 23 additions & 1 deletion apps/aehttp/src/aehttp_dispatch_ext.erl
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ queue('GetOracleByPubkey') -> ?READ_Q;
queue('GetOracleQueriesByPubkey') -> ?READ_Q;
queue('GetOracleQueryByPubkeyAndQueryId') -> ?READ_Q;
queue('GetNameEntryByName') -> ?READ_Q;
queue('GetAuctionEntryByName') -> ?READ_Q;
queue('GetChannelByPubkey') -> ?READ_Q;
queue('GetPeerPubkey') -> ?READ_Q;
queue('GetStatus') -> ?READ_Q;
Expand Down Expand Up @@ -609,6 +610,27 @@ handle_request_('GetOracleQueryByPubkeyAndQueryId', Params, _Context) ->
{400, [], #{reason => <<"Invalid public key or query ID">>}}
end;

handle_request_('GetAuctionEntryByName', Params, _Context) ->
Name = maps:get(name, Params),
case aec_chain:auction_entry(Name) of
{ok, #{id := Id,
bidder := Bidder,
started := Started,
ttl := TTL,
bid := Bid}} ->
{200, [], #{<<"id">> => aeser_api_encoder:encode(id_hash, Id),
<<"started_at">> => Started,
<<"ends_at">> => TTL,
<<"highest_bidder">> => aeser_api_encoder:encode(account_pubkey, Bidder),
<<"highest_bid">> => Bid
}};
{error, name_not_found} ->
{404, [], #{reason => <<"Name not found">>}};
{error, Reason} ->
ReasonBin = atom_to_binary(Reason, utf8),
{400, [], #{reason => <<"Name validation failed with a reason: ", ReasonBin/binary>>}}
end;

handle_request_('GetNameEntryByName', Params, _Context) ->
Name = maps:get(name, Params),
case aec_chain:name_entry(Name) of
Expand Down Expand Up @@ -731,7 +753,7 @@ handle_request_('GetCurrency', _Params, _Context) ->
{ok, FileBin} ->
case filename:extension(FileName) of
<<_,Ext/binary>> ->
maps:put(<<"logo">>,
maps:put(<<"logo">>,
#{<<"type">> => Ext,
<<"data">> => base64:encode(FileBin)}, Display0);
_ ->
Expand Down
5 changes: 5 additions & 0 deletions apps/aehttp/test/aehttp_integration_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
, initialize_account/2
, get_name_preclaim/1
, get_name_claim/1
, get_auctions_entry_by_name_sut/1
, get_names_entry_by_name_sut/1
, get_commitment_id/2
, get_accounts_by_pubkey_sut/1
Expand Down Expand Up @@ -1875,6 +1876,10 @@ get_name_entry_by_name(_Config) ->
"example.com" = proplists:get_value("access-control-allow-origin", Headers),
ok.

get_auctions_entry_by_name_sut(Name) ->
Host = external_address(),
http_request(Host, get, "auctions/" ++ Name, []).

get_names_entry_by_name_sut(Name) ->
Host = external_address(),
http_request(Host, get, "names/" ++ Name, []).
Expand Down
13 changes: 13 additions & 0 deletions apps/aehttp/test/aehttp_ns_auction_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ naming_system_auction(Config) ->
%% Check that name entry is absent as there is auction ongoing
{ok, 404, #{<<"reason">> := <<"Name not found">>}} = ?HTTP_INT:get_names_entry_by_name_sut(Name),

%% Check that auction entry is present as there is auction ongoing
{ok, 200, AuctionMap} = ?HTTP_INT:get_auctions_entry_by_name_sut(Name),
?assertEqual(maps:get(<<"highest_bid">>, AuctionMap), FirstNameFee),
?assertEqual(maps:get(<<"highest_bidder">>, AuctionMap), PubKey1Enc),

{ok, 200, #{<<"balance">> := PubKey2BalPreAuction}} = ?HTTP_INT:get_accounts_by_pubkey_sut(PubKey2Enc),
ct:log("Balance PubKey2 before counter bid: ~p", [PubKey2BalPreAuction]),

Expand Down Expand Up @@ -181,6 +186,11 @@ naming_system_auction(Config) ->
ct:log("Balance PubKey1 post counter bid: ~p", [PubKey1BalPostAuction]),
ct:log("Balance PubKey2 post counter bid: ~p", [PubKey2BalPostAuction]),

%% Check that auction entry is present and updated
{ok, 200, AuctionMap2} = ?HTTP_INT:get_auctions_entry_by_name_sut(Name),
?assertEqual(maps:get(<<"highest_bid">>, AuctionMap2), NextMinPrice),
?assertEqual(maps:get(<<"highest_bidder">>, AuctionMap2), PubKey2Enc),

%% Return first bid to PubKey1
?assertEqual(PubKey1BalPostAuction, PubKey1BalPreAuction + FirstNameFee),
%% The second bidder, PubKey2, is now charged
Expand All @@ -193,6 +203,9 @@ naming_system_auction(Config) ->
{ok, 404, #{<<"reason">> := <<"Name not found">>}} = ?HTTP_INT:get_names_entry_by_name_sut(Name),
aecore_suite_utils:mine_key_blocks(aecore_suite_utils:node_name(?NODE), ?BID_TIMEOUT),

%% Assert the auction is no longer there
{ok, 404, #{<<"reason">> := <<"Name not found">>}} = ?HTTP_INT:get_auctions_entry_by_name_sut(Name),

%% Check if we get correct name from the API
{ok, 200, RespMap} = ?HTTP_INT:get_names_entry_by_name_sut(Name),
{ok, NameAscii} = aens_utils:to_ascii(Name),
Expand Down
22 changes: 22 additions & 0 deletions apps/aens/src/aens.erl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
resolve_hash/3,
resolve_from_name_object/2,
get_commitment_hash/2,
get_auction_entry/2,
get_name_entry/2,
get_name_hash/1]).

Expand Down Expand Up @@ -65,6 +66,14 @@ get_commitment_hash(Name, Salt) when is_binary(Name) andalso is_integer(Salt) ->
{error, _} = E -> E
end.

-spec get_auction_entry(binary(), aens_state_tree:tree()) ->
{ok, map()} | {error, atom()}.
get_auction_entry(Name, NSTree) when is_binary(Name) ->
case name_to_name_hash(Name) of
{ok, NameHash} -> name_hash_to_name_auction(aens_hash:to_auction_hash(NameHash), NSTree);
{error, _} = Error -> Error
end.

-spec get_name_entry(binary(), aens_state_tree:tree()) ->
{ok, map()} | {error, atom()}.
get_name_entry(Name, NSTree) when is_binary(Name) ->
Expand Down Expand Up @@ -97,12 +106,25 @@ name_to_name_hash(Name) ->
Error
end.

name_hash_to_name_auction(NameHash, NSTree) ->
case aens_state_tree:lookup_name_auction(NameHash, NSTree) of
{value, NameRecord} -> auction_entry(NameRecord);
none -> {error, name_not_found}
end.

name_hash_to_name_entry(NameHash, NSTree) ->
case aens_state_tree:lookup_name(NameHash, NSTree) of
{value, NameRecord} -> name_entry(NameRecord);
none -> {error, name_not_found}
end.

auction_entry(AuctionRecord) ->
{ok, #{id => aens_auctions:id(AuctionRecord),
bidder => aens_auctions:bidder_pubkey(AuctionRecord),
started => aens_auctions:started(AuctionRecord),
ttl => aens_auctions:ttl(AuctionRecord),
bid => aens_auctions:name_fee(AuctionRecord)}}.

name_entry(NameRecord) ->
case aens_names:status(NameRecord) of
claimed ->
Expand Down
7 changes: 6 additions & 1 deletion apps/aens/src/aens_auctions.erl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
]).

%% Getters
-export([hash/1,
-export([id/1,
hash/1,
bidder_pubkey/1,
ttl/1,
name_fee/1,
Expand Down Expand Up @@ -135,6 +136,10 @@ serialization_type() -> ?AUCTION_TYPE.
%%% Getters
%%%===================================================================

-spec id(auction()) -> id().
id(#auction{id = Id}) ->
Id.

-spec hash(auction()) -> aens_hash:auction_hash().
hash(#auction{id = Id}) ->
NameHash = aeser_id:specialize(Id, name),
Expand Down

0 comments on commit 01dd226

Please sign in to comment.