diff --git a/crates/cashu/src/nuts/nut06.rs b/crates/cashu/src/nuts/nut06.rs index 48ddc7d9..264e7071 100644 --- a/crates/cashu/src/nuts/nut06.rs +++ b/crates/cashu/src/nuts/nut06.rs @@ -59,7 +59,7 @@ impl<'de> Deserialize<'de> for MintVersion { } } -/// Mint Info [NIP-06] +/// Mint Info [NUT-06] #[derive(Default, Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] #[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))] pub struct MintInfo { @@ -95,6 +95,9 @@ pub struct MintInfo { /// server unix timestamp #[serde(skip_serializing_if = "Option::is_none")] pub time: Option, + /// terms of url service of the mint + #[serde(skip_serializing_if = "Option::is_none")] + pub tos_url: Option, } impl MintInfo { @@ -197,6 +200,17 @@ impl MintInfo { ..self } } + + /// Set tos_url + pub fn tos_url(self, tos_url: S) -> Self + where + S: Into, + { + Self { + tos_url: Some(tos_url.into()), + ..self + } + } } /// Supported nuts and settings @@ -405,12 +419,12 @@ mod tests { #[test] fn test_des_mint_into() { let mint_info_str = r#"{ - "name": "Cashu mint", - "pubkey": "0296d0aa13b6a31cf0cd974249f28c7b7176d7274712c95a41c7d8066d3f29d679", - "version": "Nutshell/0.15.3", - "contact": [ - ["", ""], - ["", ""] +"name": "Cashu mint", +"pubkey": "0296d0aa13b6a31cf0cd974249f28c7b7176d7274712c95a41c7d8066d3f29d679", +"version": "Nutshell/0.15.3", +"contact": [ + ["", ""], + ["", ""] ], "nuts": { "4": { @@ -432,7 +446,8 @@ mod tests { "9": {"supported": true}, "10": {"supported": true}, "11": {"supported": true} - } + }, +"tos_url": "https://cashu.mint/tos" }"#; let _mint_info: MintInfo = serde_json::from_str(mint_info_str).unwrap(); @@ -455,7 +470,8 @@ mod tests { println!("{}", mint_info); */ - let mint_info_str = r#"{ + let mint_info_str = r#" +{ "name": "Bob's Cashu mint", "pubkey": "0283bf290884eed3a7ca2663fc0260de2e2064d6b355ea13f98dec004b7a7ead99", "version": "Nutshell/0.15.0", @@ -502,51 +518,54 @@ mod tests { "9": {"supported": true}, "10": {"supported": true}, "12": {"supported": true} - } + }, + "tos_url": "https://cashu.mint/tos" }"#; let info: MintInfo = serde_json::from_str(mint_info_str).unwrap(); - let mint_info_str = r#"{ - "name": "Bob's Cashu mint", - "pubkey": "0283bf290884eed3a7ca2663fc0260de2e2064d6b355ea13f98dec004b7a7ead99", - "version": "Nutshell/0.15.0", - "description": "The short mint description", - "description_long": "A description that can be a long piece of text.", - "contact": [ - ["nostr", "xxxxx"], - ["email", "contact@me.com"] - ], - "motd": "Message to display to users.", - "icon_url": "https://this-is-a-mint-icon-url.com/icon.png", - "nuts": { - "4": { - "methods": [ - { - "method": "bolt11", - "unit": "sat", - "min_amount": 0, - "max_amount": 10000, - "description": true - } - ], - "disabled": false - }, - "5": { - "methods": [ - { - "method": "bolt11", - "unit": "sat", - "min_amount": 0, - "max_amount": 10000 - } - ], - "disabled": false - }, - "7": {"supported": true}, - "8": {"supported": true}, - "9": {"supported": true}, - "10": {"supported": true}, - "12": {"supported": true} - } + let mint_info_str = r#" +{ + "name": "Bob's Cashu mint", + "pubkey": "0283bf290884eed3a7ca2663fc0260de2e2064d6b355ea13f98dec004b7a7ead99", + "version": "Nutshell/0.15.0", + "description": "The short mint description", + "description_long": "A description that can be a long piece of text.", + "contact": [ + ["nostr", "xxxxx"], + ["email", "contact@me.com"] + ], + "motd": "Message to display to users.", + "icon_url": "https://this-is-a-mint-icon-url.com/icon.png", + "nuts": { + "4": { + "methods": [ + { + "method": "bolt11", + "unit": "sat", + "min_amount": 0, + "max_amount": 10000, + "description": true + } + ], + "disabled": false + }, + "5": { + "methods": [ + { + "method": "bolt11", + "unit": "sat", + "min_amount": 0, + "max_amount": 10000 + } + ], + "disabled": false + }, + "7": {"supported": true}, + "8": {"supported": true}, + "9": {"supported": true}, + "10": {"supported": true}, + "12": {"supported": true} + }, + "tos_url": "https://cashu.mint/tos" }"#; let mint_info: MintInfo = serde_json::from_str(mint_info_str).unwrap(); diff --git a/crates/cdk-sqlite/src/wallet/migrations/20250214135017_mint_tos.sql b/crates/cdk-sqlite/src/wallet/migrations/20250214135017_mint_tos.sql new file mode 100644 index 00000000..2a912e96 --- /dev/null +++ b/crates/cdk-sqlite/src/wallet/migrations/20250214135017_mint_tos.sql @@ -0,0 +1 @@ +ALTER TABLE mint ADD tos_url TEXT; diff --git a/crates/cdk-sqlite/src/wallet/mod.rs b/crates/cdk-sqlite/src/wallet/mod.rs index 2b19f8eb..a40a9f8e 100644 --- a/crates/cdk-sqlite/src/wallet/mod.rs +++ b/crates/cdk-sqlite/src/wallet/mod.rs @@ -87,6 +87,7 @@ impl WalletDatabase for WalletSqliteDatabase { urls, motd, time, + tos_url, ) = match mint_info { Some(mint_info) => { let MintInfo { @@ -101,6 +102,7 @@ impl WalletDatabase for WalletSqliteDatabase { urls, motd, time, + tos_url, } = mint_info; ( @@ -115,18 +117,19 @@ impl WalletDatabase for WalletSqliteDatabase { urls.map(|c| serde_json::to_string(&c).ok()), motd, time, + tos_url, ) } None => ( - None, None, None, None, None, None, None, None, None, None, None, + None, None, None, None, None, None, None, None, None, None, None, None, ), }; sqlx::query( r#" INSERT INTO mint -(mint_url, name, pubkey, version, description, description_long, contact, nuts, icon_url, urls, motd, mint_time) -VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) +(mint_url, name, pubkey, version, description, description_long, contact, nuts, icon_url, urls, motd, mint_time, tos_url) +VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(mint_url) DO UPDATE SET name = excluded.name, pubkey = excluded.pubkey, @@ -138,7 +141,8 @@ ON CONFLICT(mint_url) DO UPDATE SET icon_url = excluded.icon_url, urls = excluded.urls, motd = excluded.motd, - mint_time = excluded.mint_time + mint_time = excluded.mint_time, + tos_url = excluded.tos_url ; "#, ) @@ -154,6 +158,7 @@ ON CONFLICT(mint_url) DO UPDATE SET .bind(urls) .bind(motd) .bind(time.map(|v| v as i64)) + .bind(tos_url) .execute(&self.pool) .await .map_err(Error::from)?; @@ -833,7 +838,7 @@ fn sqlite_row_to_mint_info(row: &SqliteRow) -> Result { let motd: Option = row.try_get("motd").map_err(Error::from)?; let row_urls: Option = row.try_get("urls").map_err(Error::from)?; let time: Option = row.try_get("mint_time").map_err(Error::from)?; - + let tos_url: Option = row.try_get("tos_url").map_err(Error::from)?; Ok(MintInfo { name, pubkey: row_pubkey.and_then(|p| PublicKey::from_slice(&p).ok()), @@ -848,6 +853,7 @@ fn sqlite_row_to_mint_info(row: &SqliteRow) -> Result { urls: row_urls.and_then(|c| serde_json::from_str(&c).ok()), motd, time: time.map(|t| t as u64), + tos_url, }) }