11use std:: sync:: Arc ;
22
3+ use crate :: types:: AddressTotalsREST ;
34use crate :: { handlers_config:: HandlersConfig , types:: AddressInfoREST } ;
45use acropolis_common:: queries:: errors:: QueryError ;
56use acropolis_common:: rest_error:: RESTError ;
@@ -20,35 +21,19 @@ pub async fn handle_address_single_blockfrost(
2021 params : Vec < String > ,
2122 handlers_config : Arc < HandlersConfig > ,
2223) -> Result < RESTResponse , RESTError > {
23- let [ address_str] = & params[ ..] else {
24- return Err ( RESTError :: param_missing ( "address" ) ) ;
25- } ;
26-
27- let ( address, stake_address) = match Address :: from_string ( address_str) {
28- Ok ( Address :: None ) | Ok ( Address :: Stake ( _) ) => {
29- return Err ( RESTError :: invalid_param (
30- "address" ,
31- "must be a payment address" ,
32- ) ) ;
33- }
34- Ok ( Address :: Byron ( byron) ) => ( Address :: Byron ( byron) , None ) ,
35- Ok ( Address :: Shelley ( shelley) ) => {
36- let stake_addr = shelley
37- . stake_address_string ( )
38- . map_err ( |e| RESTError :: invalid_param ( "address" , & e. to_string ( ) ) ) ?;
39-
40- ( Address :: Shelley ( shelley) , stake_addr)
41- }
42- Err ( e) => {
43- return Err ( RESTError :: invalid_param ( "address" , & e. to_string ( ) ) ) ;
44- }
24+ let address = parse_address ( & params) ?;
25+ let stake_address = match address {
26+ Address :: Shelley ( ref addr) => addr. stake_address_string ( ) ?,
27+ _ => None ,
4528 } ;
4629
4730 let address_type = address. kind ( ) . to_string ( ) ;
4831 let is_script = address. is_script ( ) ;
4932
5033 let address_query_msg = Arc :: new ( Message :: StateQuery ( StateQuery :: Addresses (
51- AddressStateQuery :: GetAddressUTxOs { address } ,
34+ AddressStateQuery :: GetAddressUTxOs {
35+ address : address. clone ( ) ,
36+ } ,
5237 ) ) ) ;
5338
5439 let utxo_identifiers = query_state (
@@ -77,7 +62,7 @@ pub async fn handle_address_single_blockfrost(
7762 None => {
7863 // Empty address - return zero balance (Blockfrost behavior)
7964 let rest_response = AddressInfoREST {
80- address : address_str . to_string ( ) ,
65+ address : address . to_string ( ) ? ,
8166 amount : Value {
8267 lovelace : 0 ,
8368 assets : Vec :: new ( ) ,
@@ -116,7 +101,7 @@ pub async fn handle_address_single_blockfrost(
116101 . await ?;
117102
118103 let rest_response = AddressInfoREST {
119- address : address_str . to_string ( ) ,
104+ address : address . to_string ( ) ? ,
120105 amount : address_balance. into ( ) ,
121106 stake_address,
122107 address_type,
@@ -138,11 +123,45 @@ pub async fn handle_address_extended_blockfrost(
138123
139124/// Handle `/addresses/{address}/totals` Blockfrost-compatible endpoint
140125pub async fn handle_address_totals_blockfrost (
141- _context : Arc < Context < Message > > ,
142- _params : Vec < String > ,
143- _handlers_config : Arc < HandlersConfig > ,
126+ context : Arc < Context < Message > > ,
127+ params : Vec < String > ,
128+ handlers_config : Arc < HandlersConfig > ,
144129) -> Result < RESTResponse , RESTError > {
145- Err ( RESTError :: not_implemented ( "Address totals endpoint" ) )
130+ let address = parse_address ( & params) ?;
131+
132+ // Get totals from address state
133+ let msg = Arc :: new ( Message :: StateQuery ( StateQuery :: Addresses (
134+ AddressStateQuery :: GetAddressTotals {
135+ address : address. clone ( ) ,
136+ } ,
137+ ) ) ) ;
138+ let totals = query_state (
139+ & context,
140+ & handlers_config. addresses_query_topic ,
141+ msg,
142+ |message| match message {
143+ Message :: StateQueryResponse ( StateQueryResponse :: Addresses (
144+ AddressStateQueryResponse :: AddressTotals ( totals) ,
145+ ) ) => Ok ( totals) ,
146+ Message :: StateQueryResponse ( StateQueryResponse :: Addresses (
147+ AddressStateQueryResponse :: Error ( e) ,
148+ ) ) => Err ( e) ,
149+ _ => Err ( QueryError :: internal_error (
150+ "Unexpected message type while retrieving address totals" ,
151+ ) ) ,
152+ } ,
153+ )
154+ . await ?;
155+
156+ let rest_response = AddressTotalsREST {
157+ address : address. to_string ( ) ?,
158+ received_sum : totals. received . into ( ) ,
159+ sent_sum : totals. sent . into ( ) ,
160+ tx_count : totals. tx_count ,
161+ } ;
162+
163+ let json = serde_json:: to_string_pretty ( & rest_response) ?;
164+ Ok ( RESTResponse :: with_json ( 200 , & json) )
146165}
147166
148167/// Handle `/addresses/{address}/utxos` Blockfrost-compatible endpoint
@@ -171,3 +190,11 @@ pub async fn handle_address_transactions_blockfrost(
171190) -> Result < RESTResponse , RESTError > {
172191 Err ( RESTError :: not_implemented ( "Address transactions endpoint" ) )
173192}
193+
194+ fn parse_address ( params : & [ String ] ) -> Result < Address , RESTError > {
195+ let Some ( address_str) = params. first ( ) else {
196+ return Err ( RESTError :: param_missing ( "address" ) ) ;
197+ } ;
198+
199+ Ok ( Address :: from_string ( address_str) ?)
200+ }
0 commit comments