Skip to content

Commit b00d078

Browse files
committed
Add mempool transactions to API Server
1 parent 184291a commit b00d078

21 files changed

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

847989
impl ApiServerInMemoryStorage {
@@ -1294,4 +1436,154 @@ impl ApiServerInMemoryStorage {
12941436

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

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

0 commit comments

Comments
 (0)