Skip to content

Commit 9babfb2

Browse files
committed
Add token balances to the address endpoint in Api Server
1 parent bb3c7fb commit 9babfb2

File tree

11 files changed

+392
-65
lines changed

11 files changed

+392
-65
lines changed

api-server/api-server-common/src/storage/impls/in_memory/mod.rs

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use super::CURRENT_STORAGE_VERSION;
4444
struct ApiServerInMemoryStorage {
4545
block_table: BTreeMap<Id<Block>, BlockWithExtraData>,
4646
block_aux_data_table: BTreeMap<Id<Block>, BlockAuxData>,
47-
address_balance_table: BTreeMap<String, BTreeMap<(CoinOrTokenId, BlockHeight), Amount>>,
47+
address_balance_table: BTreeMap<String, BTreeMap<CoinOrTokenId, BTreeMap<BlockHeight, Amount>>>,
4848
address_locked_balance_table: BTreeMap<String, BTreeMap<(CoinOrTokenId, BlockHeight), Amount>>,
4949
address_transactions_table: BTreeMap<String, BTreeMap<BlockHeight, Vec<Id<Transaction>>>>,
5050
delegation_table: BTreeMap<DelegationId, BTreeMap<BlockHeight, Delegation>>,
@@ -62,6 +62,7 @@ struct ApiServerInMemoryStorage {
6262
orders_table: BTreeMap<OrderId, BTreeMap<BlockHeight, Order>>,
6363
best_block: BlockAuxData,
6464
genesis_block: Arc<WithId<Genesis>>,
65+
number_of_coin_decimals: u8,
6566
storage_version: u32,
6667
}
6768

@@ -91,6 +92,7 @@ impl ApiServerInMemoryStorage {
9192
0.into(),
9293
chain_config.genesis_block().timestamp(),
9394
),
95+
number_of_coin_decimals: chain_config.coin_decimals(),
9496
storage_version: super::CURRENT_STORAGE_VERSION,
9597
};
9698
result
@@ -108,15 +110,49 @@ impl ApiServerInMemoryStorage {
108110
address: &str,
109111
coin_or_token_id: CoinOrTokenId,
110112
) -> Result<Option<Amount>, ApiServerStorageError> {
111-
self.address_balance_table.get(address).map_or_else(
112-
|| Ok(None),
113-
|balance| {
114-
let range_begin = (coin_or_token_id, BlockHeight::zero());
115-
let range_end = (coin_or_token_id, BlockHeight::max());
116-
let range = balance.range(range_begin..=range_end);
117-
Ok(range.last().map(|(_, v)| *v))
118-
},
119-
)
113+
self.address_balance_table
114+
.get(address)
115+
.and_then(|by_coin_or_token| by_coin_or_token.get(&coin_or_token_id))
116+
.map_or_else(
117+
|| Ok(None),
118+
|by_height| Ok(by_height.values().last().copied()),
119+
)
120+
}
121+
122+
fn get_address_balances(
123+
&self,
124+
address: &str,
125+
) -> Result<Vec<(CoinOrTokenId, Amount, u8)>, ApiServerStorageError> {
126+
let res =
127+
self.address_balance_table
128+
.get(address)
129+
.map_or_else(Vec::new, |by_coin_or_token| {
130+
by_coin_or_token
131+
.iter()
132+
.map(|(coin_or_token_id, by_height)| {
133+
let number_of_decimals = match coin_or_token_id {
134+
CoinOrTokenId::Coin => self.number_of_coin_decimals,
135+
CoinOrTokenId::TokenId(token_id) => self
136+
.fungible_token_issuances
137+
.get(token_id)
138+
.map_or(0, |by_height| {
139+
by_height
140+
.values()
141+
.last()
142+
.expect("not empty")
143+
.number_of_decimals
144+
}),
145+
};
146+
147+
(
148+
*coin_or_token_id,
149+
*by_height.values().last().expect("not empty"),
150+
number_of_decimals,
151+
)
152+
})
153+
.collect()
154+
});
155+
Ok(res)
120156
}
121157

122158
fn get_address_locked_balance(
@@ -749,16 +785,12 @@ impl ApiServerInMemoryStorage {
749785
) -> Result<(), ApiServerStorageError> {
750786
// Inefficient, but acceptable for testing with InMemoryStorage
751787

752-
self.address_balance_table.iter_mut().for_each(|(_, balance)| {
753-
balance
754-
.iter()
755-
.filter(|((_, height), _)| *height > block_height)
756-
.map(|(key, _)| *key)
757-
.collect::<Vec<_>>()
758-
.iter()
759-
.for_each(|key| {
760-
balance.remove(key);
761-
})
788+
self.address_balance_table.retain(|_, by_coin_or_token| {
789+
by_coin_or_token.retain(|_, by_block_height| {
790+
by_block_height.retain(|height, _| height <= &block_height);
791+
!by_block_height.is_empty()
792+
});
793+
!by_coin_or_token.is_empty()
762794
});
763795

764796
Ok(())
@@ -815,7 +847,9 @@ impl ApiServerInMemoryStorage {
815847
self.address_balance_table
816848
.entry(address.to_string())
817849
.or_default()
818-
.entry((coin_or_token_id, block_height))
850+
.entry(coin_or_token_id)
851+
.or_default()
852+
.entry(block_height)
819853
.and_modify(|e| *e = amount)
820854
.or_insert(amount);
821855

api-server/api-server-common/src/storage/impls/in_memory/transactional/read.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ impl ApiServerStorageRead for ApiServerInMemoryStorageTransactionalRo<'_> {
4545
self.transaction.get_address_balance(address, coin_or_token_id)
4646
}
4747

48+
async fn get_address_balances(
49+
&self,
50+
address: &str,
51+
) -> Result<Vec<(CoinOrTokenId, Amount, u8)>, ApiServerStorageError> {
52+
self.transaction.get_address_balances(address)
53+
}
54+
4855
async fn get_address_locked_balance(
4956
&self,
5057
address: &str,

api-server/api-server-common/src/storage/impls/in_memory/transactional/write.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,13 @@ impl ApiServerStorageWrite for ApiServerInMemoryStorageTransactionalRw<'_> {
237237
self.transaction.del_nft_issuance_above_height(block_height)
238238
}
239239

240+
async fn del_coin_or_token_decimals_above_height(
241+
&mut self,
242+
_block_height: BlockHeight,
243+
) -> Result<(), ApiServerStorageError> {
244+
Ok(())
245+
}
246+
240247
async fn set_statistic(
241248
&mut self,
242249
statistic: CoinOrTokenStatistic,
@@ -290,6 +297,13 @@ impl ApiServerStorageRead for ApiServerInMemoryStorageTransactionalRw<'_> {
290297
self.transaction.get_address_balance(address, coin_or_token_id)
291298
}
292299

300+
async fn get_address_balances(
301+
&self,
302+
address: &str,
303+
) -> Result<Vec<(CoinOrTokenId, Amount, u8)>, ApiServerStorageError> {
304+
self.transaction.get_address_balances(address)
305+
}
306+
293307
async fn get_address_locked_balance(
294308
&self,
295309
address: &str,

0 commit comments

Comments
 (0)