1use anyhow::anyhow;
5use recall_fendermint_actor_blobs_shared::params::GetAccountParams;
6use recall_fendermint_actor_blobs_shared::Method::{GetAccount, GetStats};
7use recall_fendermint_vm_actor_interface::blobs::BLOBS_ACTOR_ADDR;
8
9use serde::{Deserialize, Serialize};
10use tendermint::abci::response::DeliverTx;
11
12use recall_provider::{
13 fvm_ipld_encoding,
14 fvm_shared::address::Address,
15 message::{local_message, RawBytes},
16 query::{FvmQueryHeight, QueryProvider},
17 response::decode_bytes,
18};
19
20#[derive(Clone, Debug, Serialize, Deserialize)]
30pub struct Usage {
31 pub capacity_used: String,
33}
34
35impl Default for Usage {
36 fn default() -> Self {
37 Self {
38 capacity_used: "0".into(),
39 }
40 }
41}
42
43impl From<recall_fendermint_actor_blobs_shared::state::AccountInfo> for Usage {
44 fn from(v: recall_fendermint_actor_blobs_shared::state::AccountInfo) -> Self {
45 Self {
46 capacity_used: v.capacity_used.to_string(),
47 }
48 }
49}
50
51#[derive(Clone, Debug, Serialize, Deserialize)]
53pub struct StorageStats {
54 pub capacity_free: String,
56 pub capacity_used: String,
58 pub num_blobs: u64,
60 pub num_resolving: u64,
62 pub num_accounts: u64,
64 pub bytes_resolving: u64,
66 pub num_added: u64,
68 pub bytes_added: u64,
70}
71
72impl From<recall_fendermint_actor_blobs_shared::params::GetStatsReturn> for StorageStats {
73 fn from(v: recall_fendermint_actor_blobs_shared::params::GetStatsReturn) -> Self {
74 Self {
75 capacity_free: v.capacity_free.to_string(),
76 capacity_used: v.capacity_used.to_string(),
77 num_blobs: v.num_blobs,
78 num_resolving: v.num_resolving,
79 num_accounts: v.num_accounts,
80 bytes_resolving: v.bytes_resolving,
81 num_added: v.num_added,
82 bytes_added: v.bytes_added,
83 }
84 }
85}
86
87pub struct Storage {}
89
90impl Storage {
91 pub async fn stats(
92 provider: &impl QueryProvider,
93 height: FvmQueryHeight,
94 ) -> anyhow::Result<StorageStats> {
95 let message = local_message(BLOBS_ACTOR_ADDR, GetStats as u64, Default::default());
96 let response = provider.call(message, height, decode_stats).await?;
97 Ok(response.value)
98 }
99
100 pub async fn usage(
101 provider: &impl QueryProvider,
102 address: Address,
103 height: FvmQueryHeight,
104 ) -> anyhow::Result<Usage> {
105 let params = GetAccountParams(address);
106 let params = RawBytes::serialize(params)?;
107 let message = local_message(BLOBS_ACTOR_ADDR, GetAccount as u64, params);
108 let response = provider.call(message, height, decode_usage).await?;
109 if let Some(account) = response.value {
110 Ok(account)
111 } else {
112 Ok(Usage::default())
113 }
114 }
115}
116
117fn decode_stats(deliver_tx: &DeliverTx) -> anyhow::Result<StorageStats> {
118 let data = decode_bytes(deliver_tx)?;
119 fvm_ipld_encoding::from_slice::<recall_fendermint_actor_blobs_shared::params::GetStatsReturn>(&data)
120 .map(|v| v.into())
121 .map_err(|e| anyhow!("error parsing as StorageStats: {e}"))
122}
123
124fn decode_usage(deliver_tx: &DeliverTx) -> anyhow::Result<Option<Usage>> {
125 let data = decode_bytes(deliver_tx)?;
126 fvm_ipld_encoding::from_slice::<Option<recall_fendermint_actor_blobs_shared::state::AccountInfo>>(
127 &data,
128 )
129 .map(|v| v.map(|v| v.into()))
130 .map_err(|e| anyhow!("error parsing as Option<Usage>: {e}"))
131}