Skip to content

Commit 50ad659

Browse files
committed
Add mempool transactions to API Server
1 parent 83205de commit 50ad659

22 files changed

Lines changed: 4968 additions & 227 deletions

File tree

CHANGELOG.md

Lines changed: 170 additions & 163 deletions
Large diffs are not rendered by default.

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

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,17 @@ struct ApiServerInMemoryStorage {
8282
statistics:
8383
BTreeMap<CoinOrTokenStatistic, BTreeMap<CoinOrTokenId, BTreeMap<BlockHeight, Amount>>>,
8484
orders_table: BTreeMap<OrderId, BTreeMap<BlockHeight, Order>>,
85+
mempool_transaction_table: BTreeMap<Id<Transaction>, TransactionInfo>,
86+
mempool_utxo_table: BTreeMap<UtxoOutPoint, (Utxo, bool)>,
87+
mempool_address_utxos: BTreeMap<String, BTreeSet<UtxoOutPoint>>,
88+
mempool_address_balance_table: BTreeMap<String, BTreeMap<CoinOrTokenId, AmountWithDecimals>>,
89+
mempool_locked_address_balance_table:
90+
BTreeMap<String, BTreeMap<CoinOrTokenId, AmountWithDecimals>>,
91+
mempool_address_transactions_table: BTreeMap<String, BTreeSet<Id<Transaction>>>,
92+
mempool_token_transactions_table: BTreeMap<TokenId, BTreeSet<Id<Transaction>>>,
93+
mempool_fungible_token_data: BTreeMap<TokenId, FungibleTokenData>,
94+
mempool_nft_token_issuances: BTreeMap<TokenId, NftWithOwner>,
95+
mempool_orders_table: BTreeMap<OrderId, Order>,
8596
genesis_block: Arc<WithId<Genesis>>,
8697
number_of_coin_decimals: u8,
8798
storage_version: u32,
@@ -109,6 +120,16 @@ impl ApiServerInMemoryStorage {
109120
nft_token_issuances: BTreeMap::new(),
110121
statistics: BTreeMap::new(),
111122
orders_table: BTreeMap::new(),
123+
mempool_transaction_table: BTreeMap::new(),
124+
mempool_utxo_table: BTreeMap::new(),
125+
mempool_address_utxos: BTreeMap::new(),
126+
mempool_address_balance_table: BTreeMap::new(),
127+
mempool_locked_address_balance_table: BTreeMap::new(),
128+
mempool_address_transactions_table: BTreeMap::new(),
129+
mempool_token_transactions_table: BTreeMap::new(),
130+
mempool_fungible_token_data: BTreeMap::new(),
131+
mempool_nft_token_issuances: BTreeMap::new(),
132+
mempool_orders_table: BTreeMap::new(),
112133
genesis_block: chain_config.genesis_block().clone(),
113134
number_of_coin_decimals: chain_config.coin_decimals(),
114135
storage_version: CURRENT_STORAGE_VERSION,
@@ -840,6 +861,127 @@ impl ApiServerInMemoryStorage {
840861
});
841862
Ok(())
842863
}
864+
865+
fn get_utxo_mempool_fallback(
866+
&self,
867+
outpoint: &UtxoOutPoint,
868+
) -> Result<Option<Utxo>, ApiServerStorageError> {
869+
if let Some(res) = self.mempool_utxo_table.get(outpoint).map(|(utxo, _)| utxo.clone()) {
870+
return Ok(Some(res));
871+
}
872+
873+
self.get_utxo(outpoint.clone())
874+
}
875+
876+
fn get_mempool_address_balance(
877+
&self,
878+
address: &str,
879+
coin_or_token_id: CoinOrTokenId,
880+
) -> Result<Option<Amount>, ApiServerStorageError> {
881+
let mempool_balance = self
882+
.mempool_address_balance_table
883+
.get(address)
884+
.and_then(|by_coin| by_coin.get(&coin_or_token_id).map(|amount| amount.amount));
885+
886+
if mempool_balance.is_some() {
887+
return Ok(mempool_balance);
888+
}
889+
890+
self.get_address_balance(address, coin_or_token_id)
891+
}
892+
893+
fn get_mempool_locked_address_balance(
894+
&self,
895+
address: &str,
896+
coin_or_token_id: CoinOrTokenId,
897+
) -> Result<Option<Amount>, ApiServerStorageError> {
898+
let mempool_balance = self
899+
.mempool_locked_address_balance_table
900+
.get(address)
901+
.and_then(|by_coin| by_coin.get(&coin_or_token_id).map(|amount| amount.amount));
902+
903+
if mempool_balance.is_some() {
904+
return Ok(mempool_balance);
905+
}
906+
907+
self.get_address_locked_balance(address, coin_or_token_id)
908+
}
909+
910+
fn get_mempool_transaction(
911+
&self,
912+
transaction_id: Id<Transaction>,
913+
) -> Result<Option<TransactionInfo>, ApiServerStorageError> {
914+
Ok(self.mempool_transaction_table.get(&transaction_id).cloned())
915+
}
916+
917+
fn get_mempool_transactions(
918+
&self,
919+
len: u32,
920+
offset: u64,
921+
) -> Result<Vec<TransactionInfo>, ApiServerStorageError> {
922+
Ok(self
923+
.mempool_transaction_table
924+
.values()
925+
.skip(offset as usize)
926+
.take(len as usize)
927+
.cloned()
928+
.collect())
929+
}
930+
931+
fn get_mempool_address_transactions(
932+
&self,
933+
address: &str,
934+
) -> Result<Vec<Id<common::chain::Transaction>>, ApiServerStorageError> {
935+
Ok(self
936+
.mempool_address_transactions_table
937+
.get(address)
938+
.map(|txs| txs.iter().copied().collect())
939+
.unwrap_or_default())
940+
}
941+
942+
fn get_mempool_address_balances(
943+
&self,
944+
address: &str,
945+
) -> Result<BTreeMap<CoinOrTokenId, AmountWithDecimals>, ApiServerStorageError> {
946+
Ok(self
947+
.mempool_address_balance_table
948+
.get(address)
949+
.cloned()
950+
.map(|balances| balances.into_iter().collect())
951+
.unwrap_or_default())
952+
}
953+
954+
fn get_mempool_address_all_utxos(
955+
&self,
956+
address: &str,
957+
) -> Result<Vec<(UtxoOutPoint, UtxoWithExtraInfo)>, ApiServerStorageError> {
958+
let result = self
959+
.mempool_address_utxos
960+
.get(address)
961+
.unwrap_or(&BTreeSet::new())
962+
// TODO:
963+
.union(self.address_locked_utxos.get(address).unwrap_or(&BTreeSet::new()))
964+
.filter_map(|outpoint| {
965+
if let Some(utxo) = self.get_utxo_mempool_fallback(outpoint).expect("no error") {
966+
(!utxo.spent())
967+
.then_some((outpoint.clone(), utxo.utxo_with_extra_info().clone()))
968+
} else {
969+
Some((
970+
outpoint.clone(),
971+
self.locked_utxo_table
972+
.get(outpoint)
973+
.expect("must exit")
974+
.values()
975+
.last()
976+
.expect("not empty")
977+
.utxo_with_extra_info()
978+
.clone(),
979+
))
980+
}
981+
})
982+
.collect();
983+
Ok(result)
984+
}
843985
}
844986

845987
impl ApiServerInMemoryStorage {
@@ -1292,4 +1434,154 @@ impl ApiServerInMemoryStorage {
12921434

12931435
Ok(())
12941436
}
1437+
1438+
fn set_mempool_transaction(
1439+
&mut self,
1440+
transaction_id: Id<Transaction>,
1441+
transaction: &TransactionInfo,
1442+
) -> Result<(), ApiServerStorageError> {
1443+
self.mempool_transaction_table.insert(transaction_id, transaction.clone());
1444+
Ok(())
1445+
}
1446+
1447+
fn set_mempool_utxo(
1448+
&mut self,
1449+
outpoint: UtxoOutPoint,
1450+
utxo: Utxo,
1451+
spent: bool,
1452+
addresses: &[&str],
1453+
) -> Result<(), ApiServerStorageError> {
1454+
self.mempool_utxo_table.insert(outpoint.clone(), (utxo, spent));
1455+
for address in addresses {
1456+
self.mempool_address_utxos
1457+
.entry((*address).into())
1458+
.or_default()
1459+
.insert(outpoint.clone());
1460+
}
1461+
Ok(())
1462+
}
1463+
1464+
fn set_mempool_address_balance(
1465+
&mut self,
1466+
address: &str,
1467+
coin_or_token_id: CoinOrTokenId,
1468+
amount: Amount,
1469+
decimals: u8,
1470+
) -> Result<(), ApiServerStorageError> {
1471+
self.mempool_address_balance_table
1472+
.entry(address.to_string())
1473+
.or_default()
1474+
.insert(coin_or_token_id, AmountWithDecimals { amount, decimals });
1475+
Ok(())
1476+
}
1477+
1478+
fn set_mempool_locked_address_balance(
1479+
&mut self,
1480+
address: &str,
1481+
coin_or_token_id: CoinOrTokenId,
1482+
amount: Amount,
1483+
decimals: u8,
1484+
) -> Result<(), ApiServerStorageError> {
1485+
self.mempool_locked_address_balance_table
1486+
.entry(address.to_string())
1487+
.or_default()
1488+
.insert(coin_or_token_id, AmountWithDecimals { amount, decimals });
1489+
Ok(())
1490+
}
1491+
1492+
fn set_mempool_address_transaction(
1493+
&mut self,
1494+
address: &str,
1495+
transaction_id: Id<Transaction>,
1496+
) -> Result<(), ApiServerStorageError> {
1497+
self.mempool_address_transactions_table
1498+
.entry(address.to_string())
1499+
.or_default()
1500+
.insert(transaction_id);
1501+
Ok(())
1502+
}
1503+
1504+
fn set_mempool_token_transaction(
1505+
&mut self,
1506+
token_id: TokenId,
1507+
transaction_id: Id<Transaction>,
1508+
) -> Result<(), ApiServerStorageError> {
1509+
self.mempool_token_transactions_table
1510+
.entry(token_id)
1511+
.or_default()
1512+
.insert(transaction_id);
1513+
Ok(())
1514+
}
1515+
1516+
fn set_mempool_fungible_token_issuance(
1517+
&mut self,
1518+
token_id: TokenId,
1519+
issuance: FungibleTokenData,
1520+
) -> Result<(), ApiServerStorageError> {
1521+
self.mempool_fungible_token_data.insert(token_id, issuance);
1522+
Ok(())
1523+
}
1524+
1525+
fn set_mempool_nft_issuance(
1526+
&mut self,
1527+
token_id: TokenId,
1528+
issuance: NftIssuance,
1529+
owner: &Destination,
1530+
) -> Result<(), ApiServerStorageError> {
1531+
self.mempool_nft_token_issuances.insert(
1532+
token_id,
1533+
NftWithOwner {
1534+
nft: issuance,
1535+
owner: Some(owner.clone()),
1536+
},
1537+
);
1538+
Ok(())
1539+
}
1540+
1541+
fn get_mempool_token_num_decimals(
1542+
&self,
1543+
token_id: TokenId,
1544+
) -> Result<Option<u8>, ApiServerStorageError> {
1545+
let decimals = self
1546+
.mempool_fungible_token_data
1547+
.get(&token_id)
1548+
.map(|data| data.number_of_decimals)
1549+
.or_else(|| self.mempool_nft_token_issuances.get(&token_id).map(|_| 0));
1550+
1551+
if decimals.is_some() {
1552+
return Ok(decimals);
1553+
}
1554+
1555+
self.get_token_num_decimals(token_id)
1556+
}
1557+
1558+
fn get_mempool_order(&self, order_id: OrderId) -> Result<Option<Order>, ApiServerStorageError> {
1559+
let order_result = self.mempool_orders_table.get(&order_id).cloned();
1560+
if order_result.is_some() {
1561+
return Ok(order_result);
1562+
}
1563+
1564+
self.get_order(order_id)
1565+
}
1566+
1567+
fn set_mempool_order(
1568+
&mut self,
1569+
order_id: OrderId,
1570+
order: Order,
1571+
) -> Result<(), ApiServerStorageError> {
1572+
self.mempool_orders_table.insert(order_id, order);
1573+
Ok(())
1574+
}
1575+
1576+
fn clear_mempool_data(&mut self) -> Result<(), ApiServerStorageError> {
1577+
self.mempool_transaction_table.clear();
1578+
self.mempool_utxo_table.clear();
1579+
self.mempool_address_utxos.clear();
1580+
self.mempool_address_balance_table.clear();
1581+
self.mempool_address_transactions_table.clear();
1582+
self.mempool_token_transactions_table.clear();
1583+
self.mempool_fungible_token_data.clear();
1584+
self.mempool_nft_token_issuances.clear();
1585+
Ok(())
1586+
}
12951587
}

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

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,4 +317,77 @@ impl ApiServerStorageRead for ApiServerInMemoryStorageTransactionalRo<'_> {
317317
) -> Result<Vec<(OrderId, Order)>, ApiServerStorageError> {
318318
self.transaction.get_orders_for_trading_pair(pair, len, offset)
319319
}
320+
321+
async fn get_utxo_mempool_fallback(
322+
&self,
323+
outpoint: &UtxoOutPoint,
324+
) -> Result<Option<Utxo>, ApiServerStorageError> {
325+
self.transaction.get_utxo_mempool_fallback(outpoint)
326+
}
327+
328+
async fn get_mempool_address_balance(
329+
&self,
330+
address: &str,
331+
coin_or_token_id: CoinOrTokenId,
332+
) -> Result<Option<Amount>, ApiServerStorageError> {
333+
self.transaction.get_mempool_address_balance(address, coin_or_token_id)
334+
}
335+
336+
async fn get_mempool_locked_address_balance(
337+
&self,
338+
address: &str,
339+
coin_or_token_id: CoinOrTokenId,
340+
) -> Result<Option<Amount>, ApiServerStorageError> {
341+
self.transaction.get_mempool_locked_address_balance(address, coin_or_token_id)
342+
}
343+
344+
async fn get_mempool_transaction(
345+
&self,
346+
transaction_id: Id<Transaction>,
347+
) -> Result<Option<TransactionInfo>, ApiServerStorageError> {
348+
self.transaction.get_mempool_transaction(transaction_id)
349+
}
350+
351+
async fn get_mempool_transactions(
352+
&self,
353+
len: u32,
354+
offset: u64,
355+
) -> Result<Vec<TransactionInfo>, ApiServerStorageError> {
356+
self.transaction.get_mempool_transactions(len, offset)
357+
}
358+
359+
async fn get_mempool_address_transactions(
360+
&self,
361+
address: &str,
362+
) -> Result<Vec<Id<common::chain::Transaction>>, ApiServerStorageError> {
363+
self.transaction.get_mempool_address_transactions(address)
364+
}
365+
366+
async fn get_mempool_address_balances(
367+
&self,
368+
address: &str,
369+
) -> Result<BTreeMap<CoinOrTokenId, AmountWithDecimals>, ApiServerStorageError> {
370+
self.transaction.get_mempool_address_balances(address)
371+
}
372+
373+
async fn get_mempool_address_all_utxos(
374+
&self,
375+
address: &str,
376+
) -> Result<Vec<(UtxoOutPoint, UtxoWithExtraInfo)>, ApiServerStorageError> {
377+
self.transaction.get_mempool_address_all_utxos(address)
378+
}
379+
380+
async fn get_mempool_token_num_decimals(
381+
&self,
382+
token_id: TokenId,
383+
) -> Result<Option<u8>, ApiServerStorageError> {
384+
self.transaction.get_mempool_token_num_decimals(token_id)
385+
}
386+
387+
async fn get_mempool_order(
388+
&self,
389+
order_id: OrderId,
390+
) -> Result<Option<Order>, ApiServerStorageError> {
391+
self.transaction.get_mempool_order(order_id)
392+
}
320393
}

0 commit comments

Comments
 (0)