1
1
import pandas as pd
2
2
import streamlit as st
3
+ import time
3
4
4
5
from lib .api import fetch_api_data
6
+ from src .utils import get_current_slot
7
+
8
+ RETRY_DELAY_SECONDS = 10
9
+
10
+
11
+ def is_processing (result ):
12
+ """Checks if the API result indicates backend processing."""
13
+ return isinstance (result , dict ) and result .get ("result" ) == "processing"
14
+
15
+
16
+ def has_error (result ):
17
+ """Checks if the API result indicates an error."""
18
+ return result is None or (
19
+ isinstance (result , dict ) and result .get ("result" ) == "error"
20
+ ) or ("data" not in result if isinstance (result , dict ) else False )
5
21
6
22
7
23
def vaults_page ():
@@ -11,15 +27,37 @@ def vaults_page():
11
27
"This page may be out of date up to 30 minutes."
12
28
)
13
29
14
- with st .spinner ("Loading vault data..." ):
15
- response = fetch_api_data ("vaults" , "data" , retry = True , max_wait_time = 60 )
16
- if not response or "data" not in response :
17
- st .error ("Failed to load vault data" )
18
- return
30
+ response = fetch_api_data ("vaults" , "data" , retry = False )
19
31
20
- data = response ["data" ]
21
- analytics = data ["analytics" ]
22
- all_depositors = data ["depositors" ]
32
+ if is_processing (response ):
33
+ st .info (
34
+ f"Backend is processing vault data. Auto-refreshing in { RETRY_DELAY_SECONDS } seconds..."
35
+ )
36
+ with st .spinner ("Please wait..." ):
37
+ time .sleep (RETRY_DELAY_SECONDS )
38
+ st .rerun ()
39
+ return
40
+
41
+ if has_error (response ):
42
+ error_msg = "Invalid response from backend."
43
+ if isinstance (response , dict ) and "message" in response :
44
+ error_msg = response ["message" ]
45
+ elif has_error (response ):
46
+ error_msg = "Could not connect or fetch vault data."
47
+ st .error (f"Failed to load vault data: { error_msg } " )
48
+ if st .button ("Retry" ):
49
+ st .rerun ()
50
+ return
51
+
52
+ slot = response .get ("slot" , 0 )
53
+ current_slot = get_current_slot ()
54
+ if slot > 0 and current_slot > 0 :
55
+ slot_age = current_slot - slot
56
+ st .info (f"Data from slot { slot } , which is { slot_age } slots old." )
57
+
58
+ data = response ["data" ]
59
+ analytics = data ["analytics" ]
60
+ all_depositors = data ["depositors" ]
23
61
24
62
unique_depositors = set ()
25
63
for depositors in all_depositors .values ():
@@ -60,10 +98,21 @@ def vaults_page():
60
98
61
99
st .subheader ("Vault Depositor Details" )
62
100
101
+ all_vaults_df_indexed = all_vaults_df .set_index ("pubkey" )
102
+
103
+ def format_vault_option (pubkey : str ) -> str :
104
+ try :
105
+ vault_info = all_vaults_df_indexed .loc [pubkey ]
106
+ name = vault_info ["name" ]
107
+ net_deposits = vault_info ["true_net_deposits" ]
108
+ return f"{ name } (${ net_deposits :,.2f} USD) - { pubkey [:4 ]} ...{ pubkey [- 4 :]} "
109
+ except KeyError :
110
+ return f"Unknown Vault - { pubkey [:4 ]} ...{ pubkey [- 4 :]} "
111
+
63
112
selected_vault = st .selectbox (
64
113
"Select Vault" ,
65
- [ vault [ "pubkey" ] for vault in all_vaults_df . to_dict ( orient = "records" )] ,
66
- format_func = lambda x : f" { all_vaults_df [ all_vaults_df [ 'pubkey' ] == x ][ 'name' ]. values [ 0 ] } ($ { all_vaults_df [ all_vaults_df [ 'pubkey' ] == x ][ 'true_net_deposits' ]. values [ 0 ]:,.2f } USD) - { x [: 4 ] } ... { x [ - 4 :] } " ,
114
+ all_vaults_df [ "pubkey" ]. tolist () ,
115
+ format_func = format_vault_option ,
67
116
)
68
117
69
118
if selected_vault :
0 commit comments