Skip to content

Commit 35285d6

Browse files
Display charms on /sat (ordinals#3340)
1 parent 556189e commit 35285d6

File tree

16 files changed

+230
-165
lines changed

16 files changed

+230
-165
lines changed

bin/forbid

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
set -euo pipefail
44

5-
which rg > /dev/null
5+
if ! which rg > /dev/null; then
6+
echo "error: ripgrep (rg) not found"
7+
exit 1
8+
fi
69

710
! rg \
811
--glob '!bin/forbid' \

crates/ordinals/src/charm.rs

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
use super::*;
2+
3+
#[derive(Copy, Clone, Debug, PartialEq, DeserializeFromStr, SerializeDisplay)]
4+
pub enum Charm {
5+
Coin = 0,
6+
Cursed = 1,
7+
Epic = 2,
8+
Legendary = 3,
9+
Lost = 4,
10+
Nineball = 5,
11+
Rare = 6,
12+
Reinscription = 7,
13+
Unbound = 8,
14+
Uncommon = 9,
15+
Vindicated = 10,
16+
Mythic = 11,
17+
}
18+
19+
impl Charm {
20+
pub const ALL: [Charm; 12] = [
21+
Self::Coin,
22+
Self::Uncommon,
23+
Self::Rare,
24+
Self::Epic,
25+
Self::Legendary,
26+
Self::Mythic,
27+
Self::Nineball,
28+
Self::Reinscription,
29+
Self::Cursed,
30+
Self::Unbound,
31+
Self::Lost,
32+
Self::Vindicated,
33+
];
34+
35+
fn flag(self) -> u16 {
36+
1 << self as u16
37+
}
38+
39+
pub fn set(self, charms: &mut u16) {
40+
*charms |= self.flag();
41+
}
42+
43+
pub fn is_set(self, charms: u16) -> bool {
44+
charms & self.flag() != 0
45+
}
46+
47+
pub fn unset(self, charms: u16) -> u16 {
48+
charms & !self.flag()
49+
}
50+
51+
pub fn icon(self) -> &'static str {
52+
match self {
53+
Self::Coin => "🪙",
54+
Self::Cursed => "👹",
55+
Self::Epic => "🪻",
56+
Self::Legendary => "🌝",
57+
Self::Lost => "🤔",
58+
Self::Mythic => "🎃",
59+
Self::Nineball => "9️⃣",
60+
Self::Rare => "🧿",
61+
Self::Reinscription => "♻️",
62+
Self::Unbound => "🔓",
63+
Self::Uncommon => "🌱",
64+
Self::Vindicated => "❤️‍🔥",
65+
}
66+
}
67+
68+
pub fn charms(charms: u16) -> Vec<Charm> {
69+
Self::ALL
70+
.iter()
71+
.filter(|charm| charm.is_set(charms))
72+
.copied()
73+
.collect()
74+
}
75+
}
76+
77+
impl Display for Charm {
78+
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
79+
write!(
80+
f,
81+
"{}",
82+
match self {
83+
Self::Coin => "coin",
84+
Self::Cursed => "cursed",
85+
Self::Epic => "epic",
86+
Self::Legendary => "legendary",
87+
Self::Lost => "lost",
88+
Self::Mythic => "mythic",
89+
Self::Nineball => "nineball",
90+
Self::Rare => "rare",
91+
Self::Reinscription => "reinscription",
92+
Self::Unbound => "unbound",
93+
Self::Uncommon => "uncommon",
94+
Self::Vindicated => "vindicated",
95+
}
96+
)
97+
}
98+
}
99+
100+
impl FromStr for Charm {
101+
type Err = String;
102+
103+
fn from_str(s: &str) -> Result<Self, Self::Err> {
104+
Ok(match s {
105+
"coin" => Self::Coin,
106+
"cursed" => Self::Cursed,
107+
"epic" => Self::Epic,
108+
"legendary" => Self::Legendary,
109+
"lost" => Self::Lost,
110+
"mythic" => Self::Mythic,
111+
"nineball" => Self::Nineball,
112+
"rare" => Self::Rare,
113+
"reinscription" => Self::Reinscription,
114+
"unbound" => Self::Unbound,
115+
"uncommon" => Self::Uncommon,
116+
"vindicated" => Self::Vindicated,
117+
_ => return Err(format!("invalid charm `{s}`")),
118+
})
119+
}
120+
}
121+
122+
#[cfg(test)]
123+
mod tests {
124+
use super::*;
125+
126+
#[test]
127+
fn flag() {
128+
assert_eq!(Charm::Coin.flag(), 0b1);
129+
assert_eq!(Charm::Cursed.flag(), 0b10);
130+
}
131+
132+
#[test]
133+
fn set() {
134+
let mut flags = 0;
135+
assert!(!Charm::Coin.is_set(flags));
136+
Charm::Coin.set(&mut flags);
137+
assert!(Charm::Coin.is_set(flags));
138+
}
139+
140+
#[test]
141+
fn unset() {
142+
let mut flags = 0;
143+
Charm::Coin.set(&mut flags);
144+
assert!(Charm::Coin.is_set(flags));
145+
let flags = Charm::Coin.unset(flags);
146+
assert!(!Charm::Coin.is_set(flags));
147+
}
148+
}

crates/ordinals/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ use {
2323
pub const CYCLE_EPOCHS: u32 = 6;
2424

2525
pub use {
26-
decimal_sat::DecimalSat, degree::Degree, epoch::Epoch, height::Height, rarity::Rarity, sat::Sat,
27-
sat_point::SatPoint,
26+
charm::Charm, decimal_sat::DecimalSat, degree::Degree, epoch::Epoch, height::Height,
27+
rarity::Rarity, sat::Sat, sat_point::SatPoint,
2828
};
2929

30+
mod charm;
3031
mod decimal_sat;
3132
mod degree;
3233
mod epoch;

crates/ordinals/src/sat.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,29 @@ impl Sat {
8484
name.chars().rev().collect()
8585
}
8686

87+
pub fn charms(self) -> u16 {
88+
let mut charms = 0;
89+
90+
if self.nineball() {
91+
Charm::Nineball.set(&mut charms);
92+
}
93+
94+
if self.coin() {
95+
Charm::Coin.set(&mut charms);
96+
}
97+
98+
match self.rarity() {
99+
Rarity::Common => {}
100+
Rarity::Epic => Charm::Epic.set(&mut charms),
101+
Rarity::Legendary => Charm::Legendary.set(&mut charms),
102+
Rarity::Mythic => Charm::Mythic.set(&mut charms),
103+
Rarity::Rare => Charm::Rare.set(&mut charms),
104+
Rarity::Uncommon => Charm::Uncommon.set(&mut charms),
105+
}
106+
107+
charms
108+
}
109+
87110
fn from_name(s: &str) -> Result<Self, Error> {
88111
let mut x = 0;
89112
for c in s.chars() {

src/api.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ pub struct Children {
7676
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
7777
pub struct Inscription {
7878
pub address: Option<String>,
79-
pub charms: Vec<String>,
79+
pub charms: Vec<Charm>,
8080
pub children: Vec<InscriptionId>,
8181
pub content_length: Option<usize>,
8282
pub content_type: Option<String>,
@@ -96,7 +96,7 @@ pub struct Inscription {
9696

9797
#[derive(Debug, PartialEq, Serialize, Deserialize)]
9898
pub struct InscriptionRecursive {
99-
pub charms: Vec<String>,
99+
pub charms: Vec<Charm>,
100100
pub content_type: Option<String>,
101101
pub content_length: Option<usize>,
102102
pub fee: u64,
@@ -160,20 +160,21 @@ impl Output {
160160

161161
#[derive(Debug, PartialEq, Serialize, Deserialize)]
162162
pub struct Sat {
163-
pub number: u64,
164-
pub decimal: String,
165-
pub degree: String,
166-
pub name: String,
167163
pub block: u32,
164+
pub charms: Vec<Charm>,
168165
pub cycle: u32,
166+
pub decimal: String,
167+
pub degree: String,
169168
pub epoch: u32,
170-
pub period: u32,
169+
pub inscriptions: Vec<InscriptionId>,
170+
pub name: String,
171+
pub number: u64,
171172
pub offset: u64,
172-
pub rarity: Rarity,
173173
pub percentile: String,
174+
pub period: u32,
175+
pub rarity: Rarity,
174176
pub satpoint: Option<SatPoint>,
175177
pub timestamp: i64,
176-
pub inscriptions: Vec<InscriptionId>,
177178
}
178179

179180
#[derive(Debug, PartialEq, Serialize, Deserialize)]

src/index/updater/inscription_updater.rs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -462,21 +462,7 @@ impl<'a, 'tx> InscriptionUpdater<'a, 'tx> {
462462
}
463463

464464
if let Some(sat) = sat {
465-
if sat.nineball() {
466-
Charm::Nineball.set(&mut charms);
467-
}
468-
469-
if sat.coin() {
470-
Charm::Coin.set(&mut charms);
471-
}
472-
473-
match sat.rarity() {
474-
Rarity::Common | Rarity::Mythic => {}
475-
Rarity::Uncommon => Charm::Uncommon.set(&mut charms),
476-
Rarity::Rare => Charm::Rare.set(&mut charms),
477-
Rarity::Epic => Charm::Epic.set(&mut charms),
478-
Rarity::Legendary => Charm::Legendary.set(&mut charms),
479-
}
465+
charms |= sat.charms();
480466
}
481467

482468
if new_satpoint.outpoint == OutPoint::null() {

src/inscriptions.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@ use super::*;
22

33
use tag::Tag;
44

5-
pub(crate) use self::{charm::Charm, envelope::ParsedEnvelope, media::Media};
5+
pub(crate) use self::{envelope::ParsedEnvelope, media::Media};
66

77
pub use self::{envelope::Envelope, inscription::Inscription, inscription_id::InscriptionId};
88

9-
mod charm;
109
mod envelope;
1110
mod inscription;
1211
pub(crate) mod inscription_id;

0 commit comments

Comments
 (0)