Changeset View
Changeset View
Standalone View
Standalone View
web/explorer/explorer-server/src/server.rs
| Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | server_primitives::{ | ||||
| JsonBalance, JsonBlock, JsonBlocksResponse, JsonTx, JsonTxStats, | JsonBalance, JsonBlock, JsonBlocksResponse, JsonTx, JsonTxStats, | ||||
| JsonTxsResponse, JsonUtxo, | JsonTxsResponse, JsonUtxo, | ||||
| }, | }, | ||||
| templating::{ | templating::{ | ||||
| AddressTemplate, BlockTemplate, BlocksTemplate, MempoolTemplate, | AddressTemplate, BlockTemplate, BlocksTemplate, MempoolTemplate, | ||||
| TestnetFaucetTemplate, TokenEntryTemplate, TokenTemplate, | TestnetFaucetTemplate, TokenEntryTemplate, TokenTemplate, | ||||
| TransactionTemplate, | TransactionTemplate, | ||||
| }, | }, | ||||
| token_display::apply_token_display_overrides, | |||||
| }; | }; | ||||
| pub struct Server { | pub struct Server { | ||||
| chronik: ChronikClient, | chronik: ChronikClient, | ||||
| base_dir: PathBuf, | base_dir: PathBuf, | ||||
| chain: Chain, | chain: Chain, | ||||
| satoshi_addr_prefix: &'static str, | satoshi_addr_prefix: &'static str, | ||||
| tokens_addr_prefix: &'static str, | tokens_addr_prefix: &'static str, | ||||
| ▲ Show 20 Lines • Show All 221 Lines • ▼ Show 20 Lines | ) -> Result<JsonTxsResponse> { | ||||
| .get("take") | .get("take") | ||||
| .map(|s| s.as_str()) | .map(|s| s.as_str()) | ||||
| .unwrap_or("200") | .unwrap_or("200") | ||||
| .parse()?; | .parse()?; | ||||
| let tx_history = | let tx_history = | ||||
| self.chronik.token_history(token_id, page, take).await?; | self.chronik.token_history(token_id, page, take).await?; | ||||
| let token_hash = Sha256d::from_be_hex(token_id)?; | let token_hash = Sha256d::from_be_hex(token_id)?; | ||||
| let token = self.chronik.token(&token_hash).await?; | let token = apply_token_display_overrides( | ||||
| self.chronik.token(&token_hash).await?, | |||||
| ); | |||||
| let json_token = | let json_token = | ||||
| tokens_to_json(&HashMap::from([(token_id.to_string(), token)]))? | tokens_to_json(&HashMap::from([(token_id.to_string(), token)]))? | ||||
| .get(token_id) | .get(token_id) | ||||
| .cloned(); | .cloned(); | ||||
| let mut json_txs = Vec::new(); | let mut json_txs = Vec::new(); | ||||
| for tx in tx_history.txs.iter() { | for tx in tx_history.txs.iter() { | ||||
| let (block_height, timestamp) = match &tx.block { | let (block_height, timestamp) = match &tx.block { | ||||
| ▲ Show 20 Lines • Show All 290 Lines • ▼ Show 20 Lines | ) -> Result<TokenEntryTemplate<'a>> { | ||||
| .sum(); | .sum(); | ||||
| Ok(TokenEntryTemplate { | Ok(TokenEntryTemplate { | ||||
| token_section_title, | token_section_title, | ||||
| token_hex: token_id.hex_be(), | token_hex: token_id.hex_be(), | ||||
| entry: token_entry, | entry: token_entry, | ||||
| genesis_info: token_data | genesis_info: token_data | ||||
| .as_ref() | .as_ref() | ||||
| .and_then(|token_data| token_data.genesis_info.clone()), | .and_then(|token_data| token_data.genesis_info.clone()) | ||||
| .map(|genesis_info| { | |||||
| crate::token_display::apply_genesis_display_overrides( | |||||
| &token_entry.token_id, | |||||
| genesis_info, | |||||
| ) | |||||
| }), | |||||
| token_input, | token_input, | ||||
| token_output, | token_output, | ||||
| action_str, | action_str, | ||||
| specification, | specification, | ||||
| token_type: token_type_str, | token_type: token_type_str, | ||||
| }) | }) | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 168 Lines • ▼ Show 20 Lines | ) -> Result<HashMap<String, TokenInfo>> { | ||||
| } | } | ||||
| let tokens = future::join_all(token_calls).await; | let tokens = future::join_all(token_calls).await; | ||||
| // It is very possible to create a token tx with an invalid token id. In | // It is very possible to create a token tx with an invalid token id. In | ||||
| // this case chronik has no such token indexed and the call will fail. | // this case chronik has no such token indexed and the call will fail. | ||||
| let token_map: HashMap<String, TokenInfo> = tokens | let token_map: HashMap<String, TokenInfo> = tokens | ||||
| .into_iter() | .into_iter() | ||||
| .filter_map(|token| token.ok()) | .filter_map(|token| token.ok()) | ||||
| .map(|token| (token.token_id.clone(), token)) | .map(|token| { | ||||
| let token = apply_token_display_overrides(token); | |||||
| (token.token_id.clone(), token) | |||||
| }) | |||||
| .collect(); | .collect(); | ||||
| Ok(token_map) | Ok(token_map) | ||||
| } | } | ||||
| pub async fn address_qr(&self, address: &str) -> Result<Vec<u8>> { | pub async fn address_qr(&self, address: &str) -> Result<Vec<u8>> { | ||||
| use qrcode_generator::QrCodeEcc; | use qrcode_generator::QrCodeEcc; | ||||
| if address.len() > 60 { | if address.len() > 60 { | ||||
| ▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | pub async fn data_mempool(&self) -> Result<JsonTxsResponse> { | ||||
| let json_txs = mempool_txs_to_json(mempool_txs, &json_tokens)?; | let json_txs = mempool_txs_to_json(mempool_txs, &json_tokens)?; | ||||
| Ok(JsonTxsResponse { data: json_txs }) | Ok(JsonTxsResponse { data: json_txs }) | ||||
| } | } | ||||
| pub async fn token(&self, id: &str) -> Result<String> { | pub async fn token(&self, id: &str) -> Result<String> { | ||||
| let token_id = Sha256d::from_be_hex(id)?; | let token_id = Sha256d::from_be_hex(id)?; | ||||
| let token = self.chronik.token(&token_id).await?; | let token = | ||||
| apply_token_display_overrides(self.chronik.token(&token_id).await?); | |||||
| let token_type_inner = token | let token_type_inner = token | ||||
| .token_type | .token_type | ||||
| .clone() | .clone() | ||||
| .ok_or_else(|| eyre!("Malformed token.token_type"))? | .ok_or_else(|| eyre!("Malformed token.token_type"))? | ||||
| .token_type | .token_type | ||||
| .ok_or_else(|| eyre!("Malformed token.token_type"))?; | .ok_or_else(|| eyre!("Malformed token.token_type"))?; | ||||
| let (token_type_str, specification) = | let (token_type_str, specification) = | ||||
| Show All 19 Lines | |||||