Skip to content

Commit a2dea2f

Browse files
committed
Enhance deposits page functionality with improved error handling and market index validation
- Introduced logging to track API requests and errors, enhancing debuggability. - Added a new function `get_market_symbol` to validate market indices and format market symbols. - Improved user experience by ensuring valid market indices are selected and providing default values when necessary. - Enhanced error handling for API responses, including checks for empty data and logging warnings for invalid inputs. - Updated the deposits page layout to maintain clarity and usability while integrating new features.
1 parent 9f2a6b1 commit a2dea2f

File tree

1 file changed

+183
-135
lines changed

1 file changed

+183
-135
lines changed

src/page/deposits.py

Lines changed: 183 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -1,155 +1,203 @@
11
import pandas as pd
22
import streamlit as st
3+
import logging
4+
from typing import Optional
35
from driftpy.constants.spot_markets import mainnet_spot_market_configs
46

57
from lib.api import fetch_api_data
68

9+
# Configure logging
10+
logging.basicConfig(level=logging.INFO)
11+
logger = logging.getLogger(__name__)
712

813
def format_authority(authority: str) -> str:
914
"""Format authority to show first and last 4 chars"""
1015
return f"{authority[:4]}...{authority[-4:]}"
1116

17+
def get_market_symbol(market_index: int) -> str:
18+
"""
19+
Get market symbol for a given market index with validation.
20+
21+
Args:
22+
market_index: The market index to look up
23+
24+
Returns:
25+
str: Formatted string with market index and symbol
26+
"""
27+
try:
28+
if not isinstance(market_index, (int, float)):
29+
raise ValueError(f"Invalid market index type: {type(market_index)}")
30+
31+
market_index = int(market_index)
32+
valid_indices = [x.market_index for x in mainnet_spot_market_configs]
33+
34+
if market_index not in valid_indices:
35+
logger.error(f"Invalid market index: {market_index}. Valid indices: {valid_indices}")
36+
return f"{market_index} (Unknown)"
37+
38+
return f"{market_index} ({mainnet_spot_market_configs[market_index].symbol})"
39+
except Exception as e:
40+
logger.error(f"Error processing market index {market_index}: {str(e)}")
41+
return f"{market_index} (Error)"
1242

1343
def deposits_page():
14-
params = st.query_params
15-
market_index = int(params.get("market_index", 0))
16-
17-
radio_option = st.radio(
18-
"Aggregate by",
19-
["All", "By Market"],
20-
index=0,
21-
)
22-
col1, col2 = st.columns([2, 2])
23-
24-
if radio_option == "All":
25-
market_index = 0
26-
else:
27-
with col2:
28-
market_index = st.selectbox(
29-
"Market index",
30-
[x.market_index for x in mainnet_spot_market_configs],
31-
index=[x.market_index for x in mainnet_spot_market_configs].index(
32-
market_index
33-
),
34-
format_func=lambda x: f"{x} ({mainnet_spot_market_configs[int(x)].symbol})",
35-
)
36-
st.query_params.update({"market_index": str(market_index)})
37-
38-
if radio_option == "All":
39-
result = fetch_api_data(
40-
"deposits",
41-
"deposits",
42-
params={"market_index": None},
43-
retry=True,
44-
)
45-
else:
46-
result = fetch_api_data(
47-
"deposits",
48-
"deposits",
49-
params={"market_index": market_index},
50-
retry=True,
51-
)
52-
53-
if result is None:
54-
st.error("No deposits found")
55-
return
56-
57-
df = pd.DataFrame(result["deposits"])
58-
total_number_of_deposited = sum([x["balance"] for x in result["deposits"]])
59-
60-
exclude_vaults = st.checkbox("Exclude Vaults", value=True)
61-
62-
if exclude_vaults:
63-
df = df[~df["authority"].isin(result["vaults"])]
64-
65-
with col1:
66-
min_balance = st.number_input(
67-
"Minimum Balance",
68-
min_value=0.0,
69-
max_value=float(df["balance"].max()),
70-
value=0.0,
71-
step=0.1,
44+
try:
45+
params = st.query_params
46+
market_index = int(params.get("market_index", 0))
47+
48+
radio_option = st.radio(
49+
"Aggregate by",
50+
["All", "By Market"],
51+
index=0,
7252
)
53+
col1, col2 = st.columns([2, 2])
54+
55+
if radio_option == "All":
56+
market_index = 0
57+
else:
58+
valid_indices = [x.market_index for x in mainnet_spot_market_configs]
59+
if market_index not in valid_indices:
60+
logger.warning(f"Invalid market index in params: {market_index}. Defaulting to first available market.")
61+
market_index = valid_indices[0] if valid_indices else 0
62+
63+
with col2:
64+
market_index = st.selectbox(
65+
"Market index",
66+
valid_indices,
67+
index=valid_indices.index(market_index) if market_index in valid_indices else 0,
68+
format_func=lambda x: get_market_symbol(x),
69+
)
70+
st.query_params.update({"market_index": str(market_index)})
71+
72+
# Log API request parameters
73+
logger.info(f"Fetching deposits for market_index: {market_index if radio_option == 'By Market' else 'All'}")
74+
75+
if radio_option == "All":
76+
result = fetch_api_data(
77+
"deposits",
78+
"deposits",
79+
params={"market_index": None},
80+
retry=True,
81+
)
82+
else:
83+
result = fetch_api_data(
84+
"deposits",
85+
"deposits",
86+
params={"market_index": market_index},
87+
retry=True,
88+
)
7389

74-
tabs = st.tabs(["By Position", "By Authority"])
90+
if result is None:
91+
logger.error("API returned no deposits data")
92+
st.error("No deposits found")
93+
return
94+
95+
df = pd.DataFrame(result["deposits"])
96+
if df.empty:
97+
logger.warning("Empty deposits dataframe created")
98+
st.warning("No deposits data available")
99+
return
100+
101+
total_number_of_deposited = sum([x["balance"] for x in result["deposits"]])
102+
103+
exclude_vaults = st.checkbox("Exclude Vaults", value=True)
104+
105+
if exclude_vaults:
106+
original_len = len(df)
107+
df = df[~df["authority"].isin(result["vaults"])]
108+
logger.info(f"Excluded {original_len - len(df)} vault entries")
109+
110+
with col1:
111+
min_balance = st.number_input(
112+
"Minimum Balance",
113+
min_value=0.0,
114+
max_value=float(df["balance"].max()),
115+
value=0.0,
116+
step=0.1,
117+
)
75118

76-
with tabs[0]:
77-
filtered_df = df[df["balance"] >= min_balance]
78-
st.write(f"Total deposits value: **${filtered_df['value'].sum():,.2f}**")
79-
st.write(f"Number of depositor user accounts: **{len(filtered_df):,}**")
119+
tabs = st.tabs(["By Position", "By Authority"])
80120

81-
csv = filtered_df.to_csv(index=False)
82-
st.download_button(
83-
"Download All Deposits CSV",
84-
csv,
85-
"all_deposits.csv",
86-
"text/csv",
87-
key="download-all-deposits",
88-
)
89-
filtered_df["market_index"] = filtered_df["market_index"].map(
90-
lambda x: f"{x} ({mainnet_spot_market_configs[x].symbol})"
91-
)
121+
with tabs[0]:
122+
filtered_df = df[df["balance"] >= min_balance]
123+
st.write(f"Total deposits value: **${filtered_df['value'].sum():,.2f}**")
124+
st.write(f"Number of depositor user accounts: **{len(filtered_df):,}**")
92125

93-
st.dataframe(
94-
filtered_df.sort_values("value", ascending=False),
95-
column_config={
96-
"authority": st.column_config.TextColumn(
97-
"Authority",
98-
help="Account authority",
99-
),
100-
"user_account": st.column_config.TextColumn(
101-
"User Account",
102-
help="User account address",
103-
),
104-
"value": st.column_config.NumberColumn(
105-
"Value (USD)",
106-
step=0.01,
107-
),
108-
"balance": st.column_config.NumberColumn(
109-
"Balance (USD)",
110-
step=0.01,
111-
),
112-
},
113-
hide_index=True,
114-
)
126+
csv = filtered_df.to_csv(index=False)
127+
st.download_button(
128+
"Download All Deposits CSV",
129+
csv,
130+
"all_deposits.csv",
131+
"text/csv",
132+
key="download-all-deposits",
133+
)
134+
135+
# Safely map market indices to symbols
136+
filtered_df["market_index"] = filtered_df["market_index"].map(get_market_symbol)
137+
138+
st.dataframe(
139+
filtered_df.sort_values("value", ascending=False),
140+
column_config={
141+
"authority": st.column_config.TextColumn(
142+
"Authority",
143+
help="Account authority",
144+
),
145+
"user_account": st.column_config.TextColumn(
146+
"User Account",
147+
help="User account address",
148+
),
149+
"value": st.column_config.NumberColumn(
150+
"Value (USD)",
151+
step=0.01,
152+
),
153+
"balance": st.column_config.NumberColumn(
154+
"Balance (USD)",
155+
step=0.01,
156+
),
157+
},
158+
hide_index=True,
159+
)
115160

116-
with tabs[1]:
117-
grouped_df = (
118-
df.groupby("authority")
119-
.agg({"value": "sum", "balance": "sum", "user_account": "count"})
120-
.reset_index()
121-
)
122-
grouped_df = grouped_df[grouped_df["value"] >= min_balance]
123-
st.write(f"Total deposits value: **${grouped_df['value'].sum():,.2f}**")
124-
st.write(f"Total number of authorities with deposits: **{len(grouped_df):,}**")
125-
grouped_df = grouped_df.rename(columns={"user_account": "num_accounts"})
126-
grouped_df = grouped_df.sort_values("value", ascending=False)
127-
grouped_df.drop(columns=["balance"], inplace=True)
128-
129-
csv_grouped = grouped_df.to_csv(index=False)
130-
st.download_button(
131-
"Download Authority Summary CSV",
132-
csv_grouped,
133-
"deposits_by_authority.csv",
134-
"text/csv",
135-
key="download-grouped-deposits",
136-
)
161+
with tabs[1]:
162+
grouped_df = (
163+
df.groupby("authority")
164+
.agg({"value": "sum", "balance": "sum", "user_account": "count"})
165+
.reset_index()
166+
)
167+
grouped_df = grouped_df[grouped_df["value"] >= min_balance]
168+
st.write(f"Total deposits value: **${grouped_df['value'].sum():,.2f}**")
169+
st.write(f"Total number of authorities with deposits: **{len(grouped_df):,}**")
170+
grouped_df = grouped_df.rename(columns={"user_account": "num_accounts"})
171+
grouped_df = grouped_df.sort_values("value", ascending=False)
172+
grouped_df.drop(columns=["balance"], inplace=True)
173+
174+
csv_grouped = grouped_df.to_csv(index=False)
175+
st.download_button(
176+
"Download Authority Summary CSV",
177+
csv_grouped,
178+
"deposits_by_authority.csv",
179+
"text/csv",
180+
key="download-grouped-deposits",
181+
)
137182

138-
st.dataframe(
139-
grouped_df,
140-
column_config={
141-
"authority": st.column_config.TextColumn(
142-
"Authority",
143-
help="Account authority",
144-
),
145-
"value": st.column_config.NumberColumn(
146-
"Total Value (USD)",
147-
step=0.01,
148-
),
149-
"num_accounts": st.column_config.NumberColumn(
150-
"Number of Accounts",
151-
step=1,
152-
),
153-
},
154-
hide_index=True,
155-
)
183+
st.dataframe(
184+
grouped_df,
185+
column_config={
186+
"authority": st.column_config.TextColumn(
187+
"Authority",
188+
help="Account authority",
189+
),
190+
"value": st.column_config.NumberColumn(
191+
"Total Value (USD)",
192+
step=0.01,
193+
),
194+
"num_accounts": st.column_config.NumberColumn(
195+
"Number of Accounts",
196+
step=1,
197+
),
198+
},
199+
hide_index=True,
200+
)
201+
except Exception as e:
202+
logger.exception("Unexpected error in deposits_page")
203+
st.error(f"An unexpected error occurred: {str(e)}")

0 commit comments

Comments
 (0)