@@ -360,6 +360,24 @@ defmodule AeMdw.Stats do
360
360
end
361
361
end
362
362
363
+ @ spec fetch_top_miners_stats ( State . t ( ) , pagination ( ) , query ( ) , range ( ) , cursor ( ) ) ::
364
+ { :ok , { pagination_cursor ( ) , [ statistic ( ) ] , pagination_cursor ( ) } } | { :error , reason ( ) }
365
+ def fetch_top_miners_stats ( state , pagination , query , range , cursor ) do
366
+ with { :ok , filters } <- Util . convert_params ( query , & convert_param / 1 ) ,
367
+ { :ok , cursor } <- deserialize_top_miners_cursor ( cursor ) do
368
+ paginated_top_miners =
369
+ state
370
+ |> build_top_miners_streamer ( filters , range , cursor )
371
+ |> Collection . paginate (
372
+ pagination ,
373
+ & render_top_miner_statistic ( state , & 1 ) ,
374
+ & serialize_top_miners_cursor / 1
375
+ )
376
+
377
+ { :ok , paginated_top_miners }
378
+ end
379
+ end
380
+
363
381
defp fetch_statistics ( state , pagination , filters , range , cursor , tag ) do
364
382
with { :ok , cursor } <- deserialize_statistic_cursor ( cursor ) do
365
383
paginated_statistics =
@@ -433,6 +451,21 @@ defmodule AeMdw.Stats do
433
451
{ { tag , interval_by , min_date } , { tag , interval_by , max_date } }
434
452
end
435
453
454
+ defp build_top_miners_streamer ( state , filters , _scope , cursor ) do
455
+ interval_by = Map . get ( filters , :interval_by , :day )
456
+ { start_network_date , end_network_date } = DbUtil . network_date_interval ( state )
457
+ min_date = filters |> Map . get ( :min_start_date , start_network_date ) |> to_interval ( interval_by )
458
+ max_date = filters |> Map . get ( :max_start_date , end_network_date ) |> to_interval ( interval_by )
459
+
460
+ key_boundary =
461
+ { { interval_by , min_date , 0 , Util . min_bin ( ) } ,
462
+ { interval_by , max_date , Util . max_int ( ) , Util . max_256bit_bin ( ) } }
463
+
464
+ fn direction ->
465
+ Collection . stream ( state , Model.TopMinerStats , direction , key_boundary , cursor )
466
+ end
467
+ end
468
+
436
469
defp fill_missing_dates ( stream , tag , interval_by , :backward , cursor , min_date , max_date ) do
437
470
max_date =
438
471
case cursor do
@@ -519,6 +552,42 @@ defmodule AeMdw.Stats do
519
552
render_statistic ( state , { :virtual , statistic_key , count } )
520
553
end
521
554
555
+ defp render_top_miner_statistic (
556
+ _state ,
557
+ { :month , interval_start , count , beneficiary_id }
558
+ ) do
559
+ % {
560
+ start_date: months_to_iso ( interval_start ) ,
561
+ end_date: months_to_iso ( interval_start + 1 ) ,
562
+ miner: :aeapi . format_account_pubkey ( beneficiary_id ) ,
563
+ blocks_mined: count
564
+ }
565
+ end
566
+
567
+ defp render_top_miner_statistic (
568
+ _state ,
569
+ { :week , interval_start , count , beneficiary_id }
570
+ ) do
571
+ % {
572
+ start_date: days_to_iso ( interval_start * @ days_per_week ) ,
573
+ end_date: days_to_iso ( ( interval_start + 1 ) * @ days_per_week ) ,
574
+ miner: :aeapi . format_account_pubkey ( beneficiary_id ) ,
575
+ blocks_mined: count
576
+ }
577
+ end
578
+
579
+ defp render_top_miner_statistic (
580
+ _state ,
581
+ { :day , interval_start , count , beneficiary_id }
582
+ ) do
583
+ % {
584
+ start_date: days_to_iso ( interval_start ) ,
585
+ end_date: days_to_iso ( interval_start + 1 ) ,
586
+ miner: :aeapi . format_account_pubkey ( beneficiary_id ) ,
587
+ blocks_mined: count
588
+ }
589
+ end
590
+
522
591
defp convert_blocks_param ( { "type" , "key" } ) , do: { :ok , { :block_type , :key } }
523
592
defp convert_blocks_param ( { "type" , "micro" } ) , do: { :ok , { :block_type , :micro } }
524
593
defp convert_blocks_param ( param ) , do: convert_param ( param )
@@ -558,6 +627,12 @@ defmodule AeMdw.Stats do
558
627
defp serialize_statistics_cursor ( { :virtual , { _tag , _interval_by , interval_start } , _count } ) ,
559
628
do: "#{ interval_start } "
560
629
630
+ defp serialize_top_miners_cursor ( { _interval_by , _interval_start , _count , _ben } = cursor ) do
631
+ cursor
632
+ |> :erlang . term_to_binary ( )
633
+ |> Base . encode64 ( )
634
+ end
635
+
561
636
defp deserialize_statistic_cursor ( nil ) , do: { :ok , nil }
562
637
563
638
defp deserialize_statistic_cursor ( cursor_bin ) do
@@ -567,6 +642,21 @@ defmodule AeMdw.Stats do
567
642
end
568
643
end
569
644
645
+ defp deserialize_top_miners_cursor ( nil ) , do: { :ok , nil }
646
+
647
+ defp deserialize_top_miners_cursor ( cursor_bin ) do
648
+ case Base . decode64 ( cursor_bin ) do
649
+ { :ok , bin } ->
650
+ case :erlang . binary_to_term ( bin ) do
651
+ cursor when is_tuple ( cursor ) -> { :ok , cursor }
652
+ _bad_cursor -> { :error , ErrInput.Cursor . exception ( value: cursor_bin ) }
653
+ end
654
+
655
+ :error ->
656
+ { :error , ErrInput.Cursor . exception ( value: cursor_bin ) }
657
+ end
658
+ end
659
+
570
660
defp render_delta_stats ( state , gens ) , do: Enum . map ( gens , & fetch_delta_stat! ( state , & 1 ) )
571
661
572
662
defp render_total_stats ( state , gens ) , do: Enum . map ( gens , & fetch_total_stat! ( state , & 1 ) )
0 commit comments