Skip to content

Commit

Permalink
Add coin charm (#2821)
Browse files Browse the repository at this point in the history
  • Loading branch information
casey authored Dec 5, 2023
1 parent c2e644a commit d06eaca
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 41 deletions.
60 changes: 32 additions & 28 deletions src/charm.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#[derive(Copy, Clone)]
pub(crate) enum Charm {
Coin,
Cursed,
Epic,
Legendary,
Expand All @@ -12,16 +13,17 @@ pub(crate) enum Charm {
}

impl Charm {
pub(crate) const ALL: [Charm; 9] = [
Charm::Uncommon,
Charm::Rare,
Charm::Epic,
Charm::Legendary,
Charm::Nineball,
Charm::Reinscription,
Charm::Cursed,
Charm::Unbound,
Charm::Lost,
pub(crate) const ALL: [Charm; 10] = [
Self::Coin,
Self::Uncommon,
Self::Rare,
Self::Epic,
Self::Legendary,
Self::Nineball,
Self::Reinscription,
Self::Cursed,
Self::Unbound,
Self::Lost,
];

fn flag(self) -> u16 {
Expand All @@ -38,29 +40,31 @@ impl Charm {

pub(crate) fn icon(self) -> &'static str {
match self {
Charm::Cursed => "👹",
Charm::Epic => "🪻",
Charm::Legendary => "🌝",
Charm::Lost => "🤔",
Charm::Nineball => "9️⃣",
Charm::Rare => "🧿",
Charm::Reinscription => "♻️",
Charm::Unbound => "🔓",
Charm::Uncommon => "🌱",
Self::Coin => "🪙",
Self::Cursed => "👹",
Self::Epic => "🪻",
Self::Legendary => "🌝",
Self::Lost => "🤔",
Self::Nineball => "9️⃣",
Self::Rare => "🧿",
Self::Reinscription => "♻️",
Self::Unbound => "🔓",
Self::Uncommon => "🌱",
}
}

pub(crate) fn title(self) -> &'static str {
match self {
Charm::Cursed => "cursed",
Charm::Epic => "epic",
Charm::Legendary => "legendary",
Charm::Lost => "lost",
Charm::Nineball => "nineball",
Charm::Rare => "rare",
Charm::Reinscription => "reinscription",
Charm::Unbound => "unbound",
Charm::Uncommon => "uncommon",
Self::Coin => "coin",
Self::Cursed => "cursed",
Self::Epic => "epic",
Self::Legendary => "legendary",
Self::Lost => "lost",
Self::Nineball => "nineball",
Self::Rare => "rare",
Self::Reinscription => "reinscription",
Self::Unbound => "unbound",
Self::Uncommon => "uncommon",
}
}
}
2 changes: 1 addition & 1 deletion src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1749,7 +1749,7 @@ impl Index {
.any(|entry| entry.unwrap().value() == sequence_number));

// we do not track common sats (only the sat ranges)
if !Sat(sat).is_common() {
if !Sat(sat).common() {
assert_eq!(
SatPoint::load(
*rtx
Expand Down
4 changes: 2 additions & 2 deletions src/index/updater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ impl<'index> Updater<'_> {
.unwrap_or_default();

for (start, end) in coinbase_inputs {
if !Sat(start).is_common() {
if !Sat(start).common() {
sat_to_satpoint.insert(
&start,
&SatPoint {
Expand Down Expand Up @@ -642,7 +642,7 @@ impl<'index> Updater<'_> {
.pop_front()
.ok_or_else(|| anyhow!("insufficient inputs for transaction outputs"))?;

if !Sat(range.0).is_common() {
if !Sat(range.0).common() {
sat_to_satpoint.insert(
&range.0,
&SatPoint {
Expand Down
4 changes: 4 additions & 0 deletions src/index/updater/inscription_updater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,10 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> {
Charm::Nineball.set(&mut charms);
}

if sat.coin() {
Charm::Coin.set(&mut charms);
}

match sat.rarity() {
Rarity::Common | Rarity::Mythic => {}
Rarity::Uncommon => Charm::Uncommon.set(&mut charms),
Expand Down
18 changes: 15 additions & 3 deletions src/sat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,15 @@ impl Sat {
/// `Sat::rarity` is expensive and is called frequently when indexing.
/// Sat::is_common only checks if self is `Rarity::Common` but is
/// much faster.
pub(crate) fn is_common(self) -> bool {
pub(crate) fn common(self) -> bool {
let epoch = self.epoch();
(self.0 - epoch.starting_sat().0) % epoch.subsidy() != 0
}

pub(crate) fn coin(self) -> bool {
self.n() % COIN_VALUE == 0
}

pub(crate) fn name(self) -> String {
let mut x = Self::SUPPLY - self.0;
let mut name = String::new();
Expand Down Expand Up @@ -615,10 +619,10 @@ mod tests {
}

#[test]
fn is_common() {
fn common() {
#[track_caller]
fn case(n: u64) {
assert_eq!(Sat(n).is_common(), Sat(n).rarity() == Rarity::Common);
assert_eq!(Sat(n).common(), Sat(n).rarity() == Rarity::Common);
}

case(0);
Expand All @@ -631,6 +635,14 @@ mod tests {
case(2067187500000000 + 1);
}

#[test]
fn coin() {
assert!(Sat(0).coin());
assert!(!Sat(COIN_VALUE - 1).coin());
assert!(Sat(COIN_VALUE).coin());
assert!(!Sat(COIN_VALUE + 1).coin());
}

#[test]
fn nineball() {
for height in 0..10 {
Expand Down
42 changes: 35 additions & 7 deletions src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4217,6 +4217,39 @@ next
);
}

#[test]
fn charm_coin() {
let server = TestServer::new_with_regtest_with_index_sats();

server.mine_blocks(2);

let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate {
inputs: &[(1, 0, 0, inscription("text/plain", "foo").to_witness())],
..Default::default()
});

let id = InscriptionId { txid, index: 0 };

server.mine_blocks(1);

server.assert_response_regex(
format!("/inscription/{id}"),
StatusCode::OK,
format!(
".*<h1>Inscription 0</h1>.*
<dl>
<dt>id</dt>
<dd class=monospace>{id}</dd>
<dt>charms</dt>
<dd>.*<span title=coin>🪙</span>.*</dd>
.*
</dl>
.*
"
),
);
}

#[test]
fn charm_uncommon() {
let server = TestServer::new_with_regtest_with_index_sats();
Expand All @@ -4241,9 +4274,7 @@ next
<dt>id</dt>
<dd class=monospace>{id}</dd>
<dt>charms</dt>
<dd>
<span title=uncommon>🌱</span>
</dd>
<dd>.*<span title=uncommon>🌱</span>.*</dd>
.*
</dl>
.*
Expand Down Expand Up @@ -4276,10 +4307,7 @@ next
<dt>id</dt>
<dd class=monospace>{id}</dd>
<dt>charms</dt>
<dd>
<span title=uncommon>🌱</span>
<span title=nineball>9️⃣</span>
</dd>
<dd>.*<span title=nineball>9️⃣</span>.*</dd>
.*
</dl>
.*
Expand Down

0 comments on commit d06eaca

Please sign in to comment.