diff --git a/src/api.rs b/src/api.rs index e9cee4730d..c788afad9f 100644 --- a/src/api.rs +++ b/src/api.rs @@ -178,11 +178,11 @@ pub struct Output { impl Output { pub fn new( chain: Chain, - inscriptions: Vec, + inscriptions: Option>, outpoint: OutPoint, tx_out: TxOut, indexed: bool, - runes: BTreeMap, + runes: Option>, sat_ranges: Option>, spent: bool, ) -> Self { @@ -239,7 +239,7 @@ pub struct SatInscriptions { #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct AddressInfo { pub outputs: Vec, - pub inscriptions: Vec, + pub inscriptions: Option>, pub sat_balance: u64, - pub runes_balances: Vec<(SpacedRune, Decimal, Option)>, + pub runes_balances: Option)>>, } diff --git a/src/index.rs b/src/index.rs index 924c795391..b5e035b668 100644 --- a/src/index.rs +++ b/src/index.rs @@ -91,6 +91,7 @@ pub(crate) enum Statistic { Runes = 13, SatRanges = 14, UnboundInscriptions = 16, + LastSavepointHeight = 17, } impl Statistic { @@ -1019,7 +1020,11 @@ impl Index { pub fn get_rune_balances_for_output( &self, outpoint: OutPoint, - ) -> Result> { + ) -> Result>> { + if !self.index_runes { + return Ok(None); + } + let rtx = self.database.begin_read()?; let outpoint_to_balances = rtx.open_table(OUTPOINT_TO_RUNE_BALANCES)?; @@ -1027,7 +1032,7 @@ impl Index { let id_to_rune_entries = rtx.open_table(RUNE_ID_TO_RUNE_ENTRY)?; let Some(balances) = outpoint_to_balances.get(&outpoint.store())? else { - return Ok(BTreeMap::new()); + return Ok(Some(BTreeMap::new())); }; let balances_buffer = balances.value(); @@ -1050,7 +1055,7 @@ impl Index { ); } - Ok(balances) + Ok(Some(balances)) } pub fn get_rune_balance_map(&self) -> Result>> { @@ -1533,7 +1538,11 @@ impl Index { pub fn get_inscriptions_on_output_with_satpoints( &self, outpoint: OutPoint, - ) -> Result> { + ) -> Result>> { + if !self.index_inscriptions { + return Ok(None); + } + let rtx = self.database.begin_read()?; let outpoint_to_utxo_entry = rtx.open_table(OUTPOINT_TO_UTXO_ENTRY)?; let sequence_number_to_inscription_entry = @@ -1546,31 +1555,40 @@ impl Index { ) } - pub fn get_inscriptions_for_output(&self, outpoint: OutPoint) -> Result> { - Ok( - self - .get_inscriptions_on_output_with_satpoints(outpoint)? + pub fn get_inscriptions_for_output( + &self, + outpoint: OutPoint, + ) -> Result>> { + let Some(inscriptions) = self.get_inscriptions_on_output_with_satpoints(outpoint)? else { + return Ok(None); + }; + + Ok(Some( + inscriptions .iter() .map(|(_satpoint, inscription_id)| *inscription_id) .collect(), - ) + )) } pub fn get_inscriptions_for_outputs( &self, outpoints: &Vec, - ) -> Result> { - let mut inscriptions = Vec::new(); + ) -> Result>> { + let mut result = Vec::new(); for outpoint in outpoints { - inscriptions.extend( - self - .get_inscriptions_on_output_with_satpoints(*outpoint)? + let Some(inscriptions) = self.get_inscriptions_on_output_with_satpoints(*outpoint)? else { + return Ok(None); + }; + + result.extend( + inscriptions .iter() .map(|(_satpoint, inscription_id)| *inscription_id), ); } - Ok(inscriptions) + Ok(Some(result)) } pub fn get_transaction(&self, txid: Txid) -> Result> { @@ -2246,13 +2264,13 @@ impl Index { outpoint_to_utxo_entry: &'a impl ReadableTable<&'static OutPointValue, &'static UtxoEntry>, sequence_number_to_inscription_entry: &'a impl ReadableTable, outpoint: OutPoint, - ) -> Result> { + ) -> Result>> { if !self.index_inscriptions { - return Ok(Vec::new()); + return Ok(None); } let Some(utxo_entry) = outpoint_to_utxo_entry.get(&outpoint.store())? else { - return Ok(Vec::new()); + return Ok(Some(Vec::new())); }; let mut inscriptions = utxo_entry.value().parse(self).parse_inscriptions(); @@ -2265,10 +2283,13 @@ impl Index { let entry = sequence_number_to_inscription_entry .get(sequence_number)? .unwrap(); + let satpoint = SatPoint { outpoint, offset }; + Ok((satpoint, InscriptionEntry::load(entry.value()).id)) }) .collect::>() + .map(Some) } pub fn get_address_info(&self, address: &Address) -> Result> { @@ -2288,11 +2309,13 @@ impl Index { pub(crate) fn get_aggregated_rune_balances_for_outputs( &self, outputs: &Vec, - ) -> Result)>> { + ) -> Result)>>> { let mut runes = BTreeMap::new(); for output in outputs { - let rune_balances = self.get_rune_balances_for_output(*output)?; + let Some(rune_balances) = self.get_rune_balances_for_output(*output)? else { + return Ok(None); + }; for (spaced_rune, pile) in rune_balances { runes @@ -2311,12 +2334,12 @@ impl Index { } } - Ok( + Ok(Some( runes .into_iter() .map(|(spaced_rune, (decimal, symbol))| (spaced_rune, decimal, symbol)) .collect(), - ) + )) } pub(crate) fn get_sat_balances_for_outputs(&self, outputs: &Vec) -> Result { @@ -3475,7 +3498,8 @@ mod tests { context .index .get_inscriptions_for_output(OutPoint { txid, vout: 0 }) - .unwrap(), + .unwrap() + .unwrap_or_default(), [] ); @@ -3485,7 +3509,8 @@ mod tests { context .index .get_inscriptions_for_output(OutPoint { txid, vout: 0 }) - .unwrap(), + .unwrap() + .unwrap_or_default(), [inscription_id] ); @@ -3500,7 +3525,8 @@ mod tests { context .index .get_inscriptions_for_output(OutPoint { txid, vout: 0 }) - .unwrap(), + .unwrap() + .unwrap_or_default(), [] ); @@ -3511,7 +3537,8 @@ mod tests { txid: send_id, vout: 0, }) - .unwrap(), + .unwrap() + .unwrap_or_default(), [inscription_id] ); } @@ -3541,7 +3568,8 @@ mod tests { txid: first, vout: 0 }) - .unwrap(), + .unwrap() + .unwrap_or_default(), [inscription_id] ); @@ -4419,6 +4447,7 @@ mod tests { .index .get_inscriptions_on_output_with_satpoints(OutPoint { txid, vout: 0 }) .unwrap() + .unwrap_or_default() .iter() .map(|(_satpoint, inscription_id)| *inscription_id) .collect::>() @@ -4483,6 +4512,7 @@ mod tests { .index .get_inscriptions_on_output_with_satpoints(OutPoint { txid, vout: 0 }) .unwrap() + .unwrap_or_default() ) } } @@ -4532,6 +4562,7 @@ mod tests { vout: 0 }) .unwrap() + .unwrap_or_default() ) } } diff --git a/src/index/reorg.rs b/src/index/reorg.rs index 1a7ed999cf..9a1ff58b06 100644 --- a/src/index/reorg.rs +++ b/src/index/reorg.rs @@ -83,17 +83,21 @@ impl Reorg { return Ok(()); } - if (height < SAVEPOINT_INTERVAL || height % SAVEPOINT_INTERVAL == 0) - && u32::try_from( - index - .settings - .bitcoin_rpc_client(None)? - .get_blockchain_info()? - .headers, - ) - .unwrap() - .saturating_sub(height) - <= CHAIN_TIP_DISTANCE + let height = u64::from(height); + + let last_savepoint_height = index + .begin_read()? + .0 + .open_table(STATISTIC_TO_COUNT)? + .get(&Statistic::LastSavepointHeight.key())? + .map(|last_savepoint_height| last_savepoint_height.value()) + .unwrap_or(0); + + let blocks = index.client.get_blockchain_info()?.headers; + + if (height < SAVEPOINT_INTERVAL.into() + || height.saturating_sub(last_savepoint_height) >= SAVEPOINT_INTERVAL.into()) + && blocks.saturating_sub(height) <= CHAIN_TIP_DISTANCE.into() { let wtx = index.begin_write()?; @@ -111,6 +115,10 @@ impl Reorg { log::debug!("creating savepoint at height {}", height); wtx.persistent_savepoint()?; + wtx + .open_table(STATISTIC_TO_COUNT)? + .insert(&Statistic::LastSavepointHeight.key(), &height)?; + Index::increment_statistic(&wtx, Statistic::Commits, 1)?; wtx.commit()?; } diff --git a/src/subcommand/list.rs b/src/subcommand/list.rs index b790a621e8..d5892e36c1 100644 --- a/src/subcommand/list.rs +++ b/src/subcommand/list.rs @@ -10,8 +10,8 @@ pub(crate) struct List { pub struct Output { pub address: Option>, pub indexed: bool, - pub inscriptions: Vec, - pub runes: BTreeMap, + pub inscriptions: Option>, + pub runes: Option>, pub sat_ranges: Option>, pub script_pubkey: String, pub spent: bool, diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index bd79a21f6c..b523541f53 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -774,13 +774,21 @@ impl Server { OutputType::Cardinal => { index .get_inscriptions_on_output_with_satpoints(output)? + .unwrap_or_default() .is_empty() - && index.get_rune_balances_for_output(output)?.is_empty() + && index + .get_rune_balances_for_output(output)? + .unwrap_or_default() + .is_empty() } OutputType::Inscribed => !index .get_inscriptions_on_output_with_satpoints(output)? + .unwrap_or_default() + .is_empty(), + OutputType::Runic => !index + .get_rune_balances_for_output(output)? + .unwrap_or_default() .is_empty(), - OutputType::Runic => !index.get_rune_balances_for_output(output)?.is_empty(), }; if include { @@ -3744,21 +3752,23 @@ mod tests { transaction: txid, sat_ranges: None, indexed: true, - inscriptions: Vec::new(), + inscriptions: Some(Vec::new()), outpoint: output, - runes: vec![( - SpacedRune { - rune: Rune(RUNE), - spacers: 0 - }, - Pile { - amount: 340282366920938463463374607431768211455, - divisibility: 1, - symbol: None, - } - )] - .into_iter() - .collect(), + runes: Some( + vec![( + SpacedRune { + rune: Rune(RUNE), + spacers: 0 + }, + Pile { + amount: 340282366920938463463374607431768211455, + divisibility: 1, + symbol: None, + } + )] + .into_iter() + .collect() + ), spent: false, } ); diff --git a/src/subcommand/wallet/addresses.rs b/src/subcommand/wallet/addresses.rs index f8db7b3a06..2119bf3133 100644 --- a/src/subcommand/wallet/addresses.rs +++ b/src/subcommand/wallet/addresses.rs @@ -16,16 +16,12 @@ pub(crate) fn run(wallet: Wallet) -> SubcommandResult { for (output, txout) in wallet.utxos() { let address = wallet.chain().address_from_script(&txout.script_pubkey)?; - let inscriptions = if wallet.has_inscription_index() { - Some(wallet.get_inscriptions_in_output(output)) - } else { - None - }; + let inscriptions = wallet.get_inscriptions_in_output(output); - let runes = if wallet.has_rune_index() { - Some( - wallet - .get_runes_balances_in_output(output)? + let runes = wallet + .get_runes_balances_in_output(output)? + .map(|balances| { + balances .iter() .map(|(rune, pile)| { ( @@ -36,11 +32,8 @@ pub(crate) fn run(wallet: Wallet) -> SubcommandResult { }, ) }) - .collect(), - ) - } else { - None - }; + .collect() + }); let output = Output { output: *output, diff --git a/src/subcommand/wallet/balance.rs b/src/subcommand/wallet/balance.rs index bda1b72cf5..b7a5445532 100644 --- a/src/subcommand/wallet/balance.rs +++ b/src/subcommand/wallet/balance.rs @@ -26,7 +26,9 @@ pub(crate) fn run(wallet: Wallet) -> SubcommandResult { let mut runic = 0; for (output, txout) in unspent_outputs { - let rune_balances = wallet.get_runes_balances_in_output(output)?; + let rune_balances = wallet + .get_runes_balances_in_output(output)? + .unwrap_or_default(); let is_ordinal = inscription_outputs.contains(output); let is_runic = !rune_balances.is_empty(); diff --git a/src/subcommand/wallet/batch_command.rs b/src/subcommand/wallet/batch_command.rs index 43e4c79133..5d6500cb22 100644 --- a/src/subcommand/wallet/batch_command.rs +++ b/src/subcommand/wallet/batch_command.rs @@ -64,7 +64,7 @@ impl Batch { } .inscribe( &locked_utxos.into_keys().collect(), - wallet.get_runic_outputs()?, + wallet.get_runic_outputs()?.unwrap_or_default(), utxos, &wallet, ) diff --git a/src/subcommand/wallet/burn.rs b/src/subcommand/wallet/burn.rs index bdf4e70bc2..93eb804645 100644 --- a/src/subcommand/wallet/burn.rs +++ b/src/subcommand/wallet/burn.rs @@ -144,7 +144,7 @@ impl Burn { script_pubkey: ScriptBuf, burn_amount: Amount, ) -> Result { - let runic_outputs = wallet.get_runic_outputs()?; + let runic_outputs = wallet.get_runic_outputs()?.unwrap_or_default(); ensure!( !runic_outputs.contains(&satpoint.outpoint), diff --git a/src/subcommand/wallet/cardinals.rs b/src/subcommand/wallet/cardinals.rs index bceeba421c..5f061dc607 100644 --- a/src/subcommand/wallet/cardinals.rs +++ b/src/subcommand/wallet/cardinals.rs @@ -15,7 +15,7 @@ pub(crate) fn run(wallet: Wallet) -> SubcommandResult { .map(|satpoint| satpoint.outpoint) .collect::>(); - let runic_utxos = wallet.get_runic_outputs()?; + let runic_utxos = wallet.get_runic_outputs()?.unwrap_or_default(); let cardinal_utxos = unspent_outputs .iter() diff --git a/src/subcommand/wallet/inscribe.rs b/src/subcommand/wallet/inscribe.rs index c71c652318..13a2c332dd 100644 --- a/src/subcommand/wallet/inscribe.rs +++ b/src/subcommand/wallet/inscribe.rs @@ -95,7 +95,7 @@ impl Inscribe { } .inscribe( &wallet.locked_utxos().clone().into_keys().collect(), - wallet.get_runic_outputs()?, + wallet.get_runic_outputs()?.unwrap_or_default(), wallet.utxos(), &wallet, ) diff --git a/src/subcommand/wallet/outputs.rs b/src/subcommand/wallet/outputs.rs index 1bddcaeff1..1254fc2316 100644 --- a/src/subcommand/wallet/outputs.rs +++ b/src/subcommand/wallet/outputs.rs @@ -30,16 +30,12 @@ impl Outputs { .ok() .map(|address| address.as_unchecked().clone()); - let inscriptions = if wallet.has_inscription_index() { - Some(wallet.get_inscriptions_in_output(output)) - } else { - None - }; + let inscriptions = wallet.get_inscriptions_in_output(output); - let runes = if wallet.has_rune_index() { - Some( - wallet - .get_runes_balances_in_output(output)? + let runes = wallet + .get_runes_balances_in_output(output)? + .map(|balances| { + balances .iter() .map(|(rune, pile)| { ( @@ -50,11 +46,8 @@ impl Outputs { }, ) }) - .collect(), - ) - } else { - None - }; + .collect() + }); let sat_ranges = if wallet.has_sat_index() && self.ranges { Some( diff --git a/src/subcommand/wallet/runics.rs b/src/subcommand/wallet/runics.rs index 12631e0e70..689fbb547d 100644 --- a/src/subcommand/wallet/runics.rs +++ b/src/subcommand/wallet/runics.rs @@ -8,13 +8,19 @@ pub struct RunicUtxo { pub(crate) fn run(wallet: Wallet) -> SubcommandResult { let unspent_outputs = wallet.utxos(); - let runic_utxos = wallet.get_runic_outputs()?; + let Some(runic_utxos) = wallet.get_runic_outputs()? else { + bail!("`ord wallet runics` requires index created with `--index-runes`") + }; let runic_utxos = unspent_outputs .iter() .filter_map(|(output, _)| { if runic_utxos.contains(output) { - let rune_balances = wallet.get_runes_balances_in_output(output).ok()?; + let rune_balances = wallet + .get_runes_balances_in_output(output) + .ok()? + .unwrap_or_default(); + let mut runes = BTreeMap::new(); for (spaced_rune, pile) in rune_balances { diff --git a/src/subcommand/wallet/split.rs b/src/subcommand/wallet/split.rs index 1342a34fea..3e498b3f80 100644 --- a/src/subcommand/wallet/split.rs +++ b/src/subcommand/wallet/split.rs @@ -113,6 +113,7 @@ impl Split { let balances = wallet .get_runic_outputs()? + .unwrap_or_default() .into_iter() .filter(|output| !inscribed_outputs.contains(output)) .map(|output| { @@ -120,6 +121,7 @@ impl Split { ( output, balance + .unwrap_or_default() .into_iter() .map(|(spaced_rune, pile)| (spaced_rune.rune, pile.amount)) .collect(), diff --git a/src/templates/address.rs b/src/templates/address.rs index 6eb8ebe5e0..9b9214ea30 100644 --- a/src/templates/address.rs +++ b/src/templates/address.rs @@ -4,9 +4,9 @@ use super::*; pub(crate) struct AddressHtml { pub(crate) address: Address, pub(crate) outputs: Vec, - pub(crate) inscriptions: Vec, + pub(crate) inscriptions: Option>, pub(crate) sat_balance: u64, - pub(crate) runes_balances: Vec<(SpacedRune, Decimal, Option)>, + pub(crate) runes_balances: Option)>>, } impl PageContent for AddressHtml { @@ -26,9 +26,9 @@ mod tests { .require_network(Network::Bitcoin) .unwrap(), outputs: vec![outpoint(1), outpoint(2)], - inscriptions: vec![inscription_id(1)], + inscriptions: Some(vec![inscription_id(1)]), sat_balance: 99, - runes_balances: vec![ + runes_balances: Some(vec![ ( SpacedRune { rune: Rune::from_str("TEEEEEEEEESTRUNE").unwrap(), @@ -51,7 +51,7 @@ mod tests { }, Some('F'), ), - ], + ]), } } diff --git a/src/templates/output.rs b/src/templates/output.rs index 235403cff8..23da2b64e9 100644 --- a/src/templates/output.rs +++ b/src/templates/output.rs @@ -3,10 +3,10 @@ use super::*; #[derive(Boilerplate)] pub(crate) struct OutputHtml { pub(crate) chain: Chain, - pub(crate) inscriptions: Vec, + pub(crate) inscriptions: Option>, pub(crate) outpoint: OutPoint, pub(crate) output: TxOut, - pub(crate) runes: BTreeMap, + pub(crate) runes: Option>, pub(crate) sat_ranges: Option>, pub(crate) spent: bool, } @@ -29,10 +29,10 @@ mod tests { assert_regex_match!( OutputHtml { chain: Chain::Mainnet, - inscriptions: Vec::new(), + inscriptions: Some(Vec::new()), outpoint: outpoint(1), output: TxOut { value: Amount::from_sat(3), script_pubkey: ScriptBuf::new_p2pkh(&PubkeyHash::all_zeros()), }, - runes: BTreeMap::new(), + runes: Some(BTreeMap::new()), sat_ranges: Some(vec![(0, 1), (1, 3)]), spent: false, }, @@ -60,13 +60,13 @@ mod tests { assert_regex_match!( OutputHtml { chain: Chain::Mainnet, - inscriptions: Vec::new(), + inscriptions: None, outpoint: outpoint(1), output: TxOut { value: Amount::from_sat(1), script_pubkey: script::Builder::new().push_int(0).into_script(), }, - runes: BTreeMap::new(), + runes: None, sat_ranges: None, spent: true, }, @@ -88,10 +88,10 @@ mod tests { assert_regex_match!( OutputHtml { chain: Chain::Mainnet, - inscriptions: Vec::new(), + inscriptions: None, outpoint: outpoint(1), output: TxOut { value: Amount::from_sat(3), script_pubkey: ScriptBuf::new_p2pkh(&PubkeyHash::all_zeros()), }, - runes: BTreeMap::new(), + runes: None, sat_ranges: Some(vec![(0, 1), (1, 3)]), spent: true, }, @@ -119,10 +119,10 @@ mod tests { assert_regex_match!( OutputHtml { chain: Chain::Mainnet, - inscriptions: Vec::new(), + inscriptions: None, outpoint: outpoint(1), output: TxOut { value: Amount::from_sat(3), script_pubkey: ScriptBuf::new_p2pkh(&PubkeyHash::all_zeros()), }, - runes: BTreeMap::new(), + runes: None, sat_ranges: None, spent: false, } @@ -146,13 +146,13 @@ mod tests { assert_regex_match!( OutputHtml { chain: Chain::Mainnet, - inscriptions: vec![inscription_id(1)], + inscriptions: Some(vec![inscription_id(1)]), outpoint: outpoint(1), output: TxOut { value: Amount::from_sat(3), script_pubkey: ScriptBuf::new_p2pkh(&PubkeyHash::all_zeros()), }, - runes: BTreeMap::new(), + runes: None, sat_ranges: None, spent: false, }, @@ -175,25 +175,27 @@ mod tests { assert_regex_match!( OutputHtml { chain: Chain::Mainnet, - inscriptions: Vec::new(), + inscriptions: None, outpoint: outpoint(1), output: TxOut { value: Amount::from_sat(3), script_pubkey: ScriptBuf::new_p2pkh(&PubkeyHash::all_zeros()), }, - runes: vec![( - SpacedRune { - rune: Rune(26), - spacers: 1 - }, - Pile { - amount: 11, - divisibility: 1, - symbol: None, - } - )] - .into_iter() - .collect(), + runes: Some( + vec![( + SpacedRune { + rune: Rune(26), + spacers: 1 + }, + Pile { + amount: 11, + divisibility: 1, + symbol: None, + } + )] + .into_iter() + .collect() + ), sat_ranges: None, spent: false, }, diff --git a/src/wallet.rs b/src/wallet.rs index f45fc9dd6a..6dae9a4228 100644 --- a/src/wallet.rs +++ b/src/wallet.rs @@ -75,7 +75,6 @@ pub(crate) enum Maturity { pub(crate) struct Wallet { bitcoin_client: Client, database: Database, - has_inscription_index: bool, has_rune_index: bool, has_sat_index: bool, rpc_url: Url, @@ -181,7 +180,7 @@ impl Wallet { .utxos() .keys() .filter(|utxo| inscriptions.contains(utxo)) - .chain(self.get_runic_outputs()?.iter()) + .chain(self.get_runic_outputs()?.unwrap_or_default().iter()) .cloned() .filter(|utxo| !locked.contains(utxo)) .collect::>(); @@ -217,7 +216,7 @@ impl Wallet { ) } - pub(crate) fn get_inscriptions_in_output(&self, output: &OutPoint) -> Vec { + pub(crate) fn get_inscriptions_in_output(&self, output: &OutPoint) -> Option> { self.output_info.get(output).unwrap().inscriptions.clone() } @@ -251,21 +250,25 @@ impl Wallet { Ok(parent_info) } - pub(crate) fn get_runic_outputs(&self) -> Result> { + pub(crate) fn get_runic_outputs(&self) -> Result>> { let mut runic_outputs = BTreeSet::new(); - for (output, info) in self.output_info.iter() { - if !info.runes.is_empty() { + for (output, info) in &self.output_info { + let Some(runes) = &info.runes else { + return Ok(None); + }; + + if !runes.is_empty() { runic_outputs.insert(*output); } } - Ok(runic_outputs) + Ok(Some(runic_outputs)) } pub(crate) fn get_runes_balances_in_output( &self, output: &OutPoint, - ) -> Result> { + ) -> Result>> { Ok( self .output_info @@ -311,10 +314,6 @@ impl Wallet { ) } - pub(crate) fn has_inscription_index(&self) -> bool { - self.has_inscription_index - } - pub(crate) fn has_sat_index(&self) -> bool { self.has_sat_index } @@ -879,7 +878,7 @@ impl Wallet { } } - let runic_outputs = self.get_runic_outputs()?; + let runic_outputs = self.get_runic_outputs()?.unwrap_or_default(); ensure!( !runic_outputs.contains(&satpoint.outpoint), @@ -940,6 +939,7 @@ impl Wallet { let balances = self .get_runic_outputs()? + .unwrap_or_default() .into_iter() .filter(|output| !inscribed_outputs.contains(output)) .map(|output| { @@ -947,6 +947,7 @@ impl Wallet { ( output, balance + .unwrap_or_default() .into_iter() .map(|(spaced_rune, pile)| (spaced_rune.rune, pile.amount)) .collect(), diff --git a/src/wallet/wallet_constructor.rs b/src/wallet/wallet_constructor.rs index b5e43c84fe..7d6108c565 100644 --- a/src/wallet/wallet_constructor.rs +++ b/src/wallet/wallet_constructor.rs @@ -118,7 +118,7 @@ impl WalletConstructor { let inscriptions = output_info .iter() - .flat_map(|(_output, info)| info.inscriptions.clone()) + .flat_map(|(_output, info)| info.inscriptions.clone().unwrap_or_default()) .collect::>(); let (inscriptions, inscription_info) = self.get_inscriptions(&inscriptions)?; @@ -128,7 +128,6 @@ impl WalletConstructor { Ok(Wallet { bitcoin_client, database, - has_inscription_index: status.inscription_index, has_rune_index: status.rune_index, has_sat_index: status.sat_index, inscription_info, diff --git a/static/preview-video.js b/static/preview-video.js new file mode 100644 index 0000000000..e4a41bc2bd --- /dev/null +++ b/static/preview-video.js @@ -0,0 +1,3 @@ +document.getElementsByTagName('video')[0].addEventListener('click', (event) => { + event.target.controls = true; +}); diff --git a/templates/address.html b/templates/address.html index 6b7146ae65..883da13ee8 100644 --- a/templates/address.html +++ b/templates/address.html @@ -2,21 +2,25 @@

Address {{ self.address }}

sat balance
{{ self.sat_balance }}
-%% if !self.inscriptions.is_empty() { +%% let inscriptions = self.inscriptions.clone().unwrap_or_default(); +%% if !inscriptions.is_empty() {
inscriptions
-%% for inscription in &self.inscriptions { +%% for inscription in &inscriptions { {{Iframe::thumbnail(*inscription)}} %% }
%% } +%% let runes_balances = self.runes_balances.clone().unwrap_or_default(); +%% if !runes_balances.is_empty() {
runes balances
-%% for (rune, decimal, symbol) in self.runes_balances.iter() { +%% for (rune, decimal, symbol) in runes_balances.iter() { %% if let Some(symbol) = symbol {
{{ rune }}: {{ decimal }}{{ symbol }}
%% } else {
{{ rune }}: {{ decimal }}ยค
%% } +%% } %% }
outputs
diff --git a/templates/output.html b/templates/output.html index 2cd281a162..7c97557d87 100644 --- a/templates/output.html +++ b/templates/output.html @@ -1,14 +1,16 @@

Output {{self.outpoint}}

-%% if !self.inscriptions.is_empty() { +%% let inscriptions = self.inscriptions.clone().unwrap_or_default(); +%% if !inscriptions.is_empty() {
inscriptions
-%% for inscription in &self.inscriptions { +%% for inscription in &inscriptions { {{Iframe::thumbnail(*inscription)}} %% }
%% } -%% if !self.runes.is_empty() { +%% let runes = self.runes.clone().unwrap_or_default(); +%% if !runes.is_empty() {
runes
@@ -16,7 +18,7 @@

Output {{self.outpoint}}

-%% for (rune, balance) in &self.runes { +%% for (rune, balance) in &runes { diff --git a/templates/preview-video.html b/templates/preview-video.html index 3ca99c47b6..820d8409d5 100644 --- a/templates/preview-video.html +++ b/templates/preview-video.html @@ -3,9 +3,10 @@ + -
rune balance
{{ rune }} {{ balance }}