migrations.rs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. use std::collections::HashMap;
  2. use std::sync::Arc;
  3. use cdk::mint_url::MintUrl;
  4. use cdk::nuts::{CurrencyUnit, MeltQuoteState, MintQuoteState};
  5. use cdk::Amount;
  6. use redb::{Database, ReadableTable, TableDefinition};
  7. use serde::{Deserialize, Serialize};
  8. use super::error::Error;
  9. const MINT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("mint_quotes");
  10. const MELT_QUOTES_TABLE: TableDefinition<&str, &str> = TableDefinition::new("melt_quotes");
  11. /// Mint Quote Info
  12. #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
  13. pub struct V0MintQuote {
  14. pub id: String,
  15. pub mint_url: MintUrl,
  16. pub amount: Amount,
  17. pub unit: CurrencyUnit,
  18. pub request: String,
  19. pub paid: bool,
  20. pub expiry: u64,
  21. }
  22. /// Mint Quote Info
  23. #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
  24. pub struct V1MintQuote {
  25. pub id: String,
  26. pub mint_url: MintUrl,
  27. pub amount: Amount,
  28. pub unit: CurrencyUnit,
  29. pub request: String,
  30. pub state: MintQuoteState,
  31. pub expiry: u64,
  32. }
  33. /// Melt Quote Info
  34. #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
  35. pub struct V1MeltQuote {
  36. /// Quote id
  37. pub id: String,
  38. /// Quote unit
  39. pub unit: CurrencyUnit,
  40. /// Quote amount
  41. pub amount: Amount,
  42. /// Quote Payment request e.g. bolt11
  43. pub request: String,
  44. /// Quote fee reserve
  45. pub fee_reserve: Amount,
  46. /// Quote state
  47. pub state: MeltQuoteState,
  48. /// Expiration time of quote
  49. pub expiry: u64,
  50. /// Payment preimage
  51. pub payment_preimage: Option<String>,
  52. }
  53. impl From<V0MintQuote> for V1MintQuote {
  54. fn from(quote: V0MintQuote) -> V1MintQuote {
  55. let state = match quote.paid {
  56. true => MintQuoteState::Paid,
  57. false => MintQuoteState::Unpaid,
  58. };
  59. V1MintQuote {
  60. id: quote.id,
  61. mint_url: quote.mint_url,
  62. amount: quote.amount,
  63. unit: quote.unit,
  64. request: quote.request.clone(),
  65. state,
  66. expiry: quote.expiry,
  67. }
  68. }
  69. }
  70. /// Melt Quote Info
  71. #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
  72. pub struct V0MeltQuote {
  73. pub id: String,
  74. pub unit: CurrencyUnit,
  75. pub amount: Amount,
  76. pub request: String,
  77. pub fee_reserve: Amount,
  78. pub paid: bool,
  79. pub expiry: u64,
  80. }
  81. impl From<V0MeltQuote> for V1MeltQuote {
  82. fn from(quote: V0MeltQuote) -> V1MeltQuote {
  83. let state = match quote.paid {
  84. true => MeltQuoteState::Paid,
  85. false => MeltQuoteState::Unpaid,
  86. };
  87. V1MeltQuote {
  88. id: quote.id,
  89. amount: quote.amount,
  90. unit: quote.unit,
  91. request: quote.request,
  92. state,
  93. expiry: quote.expiry,
  94. fee_reserve: quote.fee_reserve,
  95. payment_preimage: None,
  96. }
  97. }
  98. }
  99. fn migrate_mint_quotes_00_to_01(db: Arc<Database>) -> Result<(), Error> {
  100. let read_txn = db.begin_read().map_err(Error::from)?;
  101. let table = read_txn
  102. .open_table(MINT_QUOTES_TABLE)
  103. .map_err(Error::from)?;
  104. let mint_quotes: HashMap<String, Option<V0MintQuote>>;
  105. {
  106. mint_quotes = table
  107. .iter()
  108. .map_err(Error::from)?
  109. .flatten()
  110. .map(|(quote_id, mint_quote)| {
  111. (
  112. quote_id.value().to_string(),
  113. serde_json::from_str(mint_quote.value()).ok(),
  114. )
  115. })
  116. .collect();
  117. }
  118. let migrated_mint_quotes: HashMap<String, Option<V1MintQuote>> = mint_quotes
  119. .into_iter()
  120. .map(|(quote_id, quote)| (quote_id, quote.map(|q| q.into())))
  121. .collect();
  122. {
  123. let write_txn = db.begin_write()?;
  124. {
  125. let mut table = write_txn
  126. .open_table(MINT_QUOTES_TABLE)
  127. .map_err(Error::from)?;
  128. for (quote_id, quote) in migrated_mint_quotes {
  129. match quote {
  130. Some(quote) => {
  131. let quote_str = serde_json::to_string(&quote)?;
  132. table.insert(quote_id.as_str(), quote_str.as_str())?;
  133. }
  134. None => {
  135. table.remove(quote_id.as_str())?;
  136. }
  137. }
  138. }
  139. }
  140. write_txn.commit()?;
  141. }
  142. Ok(())
  143. }
  144. fn migrate_melt_quotes_00_to_01(db: Arc<Database>) -> Result<(), Error> {
  145. let read_txn = db.begin_read().map_err(Error::from)?;
  146. let table = read_txn
  147. .open_table(MELT_QUOTES_TABLE)
  148. .map_err(Error::from)?;
  149. let melt_quotes: HashMap<String, Option<V0MeltQuote>>;
  150. {
  151. melt_quotes = table
  152. .iter()
  153. .map_err(Error::from)?
  154. .flatten()
  155. .map(|(quote_id, melt_quote)| {
  156. (
  157. quote_id.value().to_string(),
  158. serde_json::from_str(melt_quote.value()).ok(),
  159. )
  160. })
  161. .collect();
  162. }
  163. let migrated_melt_quotes: HashMap<String, Option<V1MeltQuote>> = melt_quotes
  164. .into_iter()
  165. .map(|(quote_id, quote)| (quote_id, quote.map(|q| q.into())))
  166. .collect();
  167. {
  168. let write_txn = db.begin_write()?;
  169. {
  170. let mut table = write_txn
  171. .open_table(MELT_QUOTES_TABLE)
  172. .map_err(Error::from)?;
  173. for (quote_id, quote) in migrated_melt_quotes {
  174. match quote {
  175. Some(quote) => {
  176. let quote_str = serde_json::to_string(&quote)?;
  177. table.insert(quote_id.as_str(), quote_str.as_str())?;
  178. }
  179. None => {
  180. table.remove(quote_id.as_str())?;
  181. }
  182. }
  183. }
  184. }
  185. write_txn.commit()?;
  186. }
  187. Ok(())
  188. }
  189. pub(crate) fn migrate_00_to_01(db: Arc<Database>) -> Result<u32, Error> {
  190. tracing::info!("Starting Migrations of mint quotes from 00 to 01");
  191. migrate_mint_quotes_00_to_01(Arc::clone(&db))?;
  192. tracing::info!("Finished Migrations of mint quotes from 00 to 01");
  193. tracing::info!("Starting Migrations of melt quotes from 00 to 01");
  194. migrate_melt_quotes_00_to_01(Arc::clone(&db))?;
  195. tracing::info!("Finished Migrations of melt quotes from 00 to 01");
  196. Ok(1)
  197. }