mirror of
https://github.com/aljazceru/cdk.git
synced 2025-12-21 06:34:59 +01:00
refactor: v1 MeltRequest
TODO: ffi bindings
This commit is contained in:
@@ -6,6 +6,12 @@ interface CashuError {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
|
|
||||||
|
[Enum]
|
||||||
|
interface CurrencyUnit {
|
||||||
|
Sat();
|
||||||
|
Custom(string unit);
|
||||||
|
};
|
||||||
|
|
||||||
interface Bolt11Invoice {
|
interface Bolt11Invoice {
|
||||||
[Throws=CashuError]
|
[Throws=CashuError]
|
||||||
@@ -88,11 +94,11 @@ interface MintProofs {
|
|||||||
|
|
||||||
interface Token {
|
interface Token {
|
||||||
[Throws=CashuError]
|
[Throws=CashuError]
|
||||||
constructor(string mint, sequence<Proof> token, string? unit, string? memo);
|
constructor(string mint, sequence<Proof> token, string? memo, string? unit);
|
||||||
sequence<MintProofs> token();
|
sequence<MintProofs> token();
|
||||||
string? memo();
|
string? memo();
|
||||||
[Throws=CashuError]
|
string? unit();
|
||||||
string as_string();
|
string to_string();
|
||||||
[Throws=CashuError, Name=from_string]
|
[Throws=CashuError, Name=from_string]
|
||||||
constructor(string token);
|
constructor(string token);
|
||||||
|
|
||||||
@@ -144,6 +150,32 @@ interface KeySetResponse {
|
|||||||
sequence<KeySetInfo> keysets();
|
sequence<KeySetInfo> keysets();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// NUT-05
|
||||||
|
|
||||||
|
interface MeltQuoteBolt11Response {
|
||||||
|
[Throws=CashuError]
|
||||||
|
constructor(string quote, u64 amount, u64 fee_reserve, boolean paid, u64 expiry);
|
||||||
|
string quote();
|
||||||
|
u64 amount();
|
||||||
|
u64 fee_reserve();
|
||||||
|
boolean paid();
|
||||||
|
u64 expiry();
|
||||||
|
};
|
||||||
|
|
||||||
|
interface MeltQuoteBolt11Request {
|
||||||
|
[Throws=CashuError]
|
||||||
|
constructor(string request, string unit);
|
||||||
|
string request();
|
||||||
|
string unit();
|
||||||
|
};
|
||||||
|
|
||||||
|
interface MeltBolt11Request {
|
||||||
|
[Throws=CashuError]
|
||||||
|
constructor(sequence<Proof> inputs, string quote);
|
||||||
|
sequence<Proof> inputs();
|
||||||
|
string quote();
|
||||||
|
};
|
||||||
|
|
||||||
interface RequestMintResponse {
|
interface RequestMintResponse {
|
||||||
[Throws=CashuError]
|
[Throws=CashuError]
|
||||||
constructor(string invoice, string hash);
|
constructor(string invoice, string hash);
|
||||||
@@ -162,30 +194,6 @@ interface PostMintResponse {
|
|||||||
sequence<BlindedSignature> promises();
|
sequence<BlindedSignature> promises();
|
||||||
};
|
};
|
||||||
|
|
||||||
interface CheckFeesRequest {
|
|
||||||
[Throws=CashuError]
|
|
||||||
constructor(string invoice);
|
|
||||||
string invoice();
|
|
||||||
};
|
|
||||||
|
|
||||||
interface CheckFeesResponse {
|
|
||||||
constructor(Amount amount);
|
|
||||||
Amount amount();
|
|
||||||
};
|
|
||||||
|
|
||||||
interface Nut05MeltRequest {
|
|
||||||
[Throws=CashuError]
|
|
||||||
constructor(sequence<Proof> proofs, string Invoice);
|
|
||||||
sequence<Proof> proofs();
|
|
||||||
string invoice();
|
|
||||||
};
|
|
||||||
|
|
||||||
interface Nut05MeltResponse {
|
|
||||||
constructor(boolean paid, string? preimage);
|
|
||||||
boolean paid();
|
|
||||||
string? preimage();
|
|
||||||
};
|
|
||||||
|
|
||||||
interface SplitRequest {
|
interface SplitRequest {
|
||||||
constructor(sequence<Proof> proofs, sequence<BlindedMessage> outputs);
|
constructor(sequence<Proof> proofs, sequence<BlindedMessage> outputs);
|
||||||
sequence<Proof> proofs();
|
sequence<Proof> proofs();
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ mod ffi {
|
|||||||
pub use crate::nuts::nut00::premint_secrets::PreMintSecrets;
|
pub use crate::nuts::nut00::premint_secrets::PreMintSecrets;
|
||||||
pub use crate::nuts::nut00::proof::mint::Proof as MintProof;
|
pub use crate::nuts::nut00::proof::mint::Proof as MintProof;
|
||||||
pub use crate::nuts::nut00::proof::Proof;
|
pub use crate::nuts::nut00::proof::Proof;
|
||||||
pub use crate::nuts::nut00::token::Token;
|
pub use crate::nuts::nut00::token::{CurrencyUnit, Token};
|
||||||
pub use crate::nuts::nut01::key_pair::KeyPair;
|
pub use crate::nuts::nut01::key_pair::KeyPair;
|
||||||
pub use crate::nuts::nut01::keys::{Keys, KeysResponse};
|
pub use crate::nuts::nut01::keys::{Keys, KeysResponse};
|
||||||
pub use crate::nuts::nut01::public_key::PublicKey;
|
pub use crate::nuts::nut01::public_key::PublicKey;
|
||||||
@@ -21,11 +21,11 @@ mod ffi {
|
|||||||
pub use crate::nuts::nut03::{RequestMintResponse, SplitRequest, SplitResponse};
|
pub use crate::nuts::nut03::{RequestMintResponse, SplitRequest, SplitResponse};
|
||||||
pub use crate::nuts::nut04::{MintRequest, PostMintResponse};
|
pub use crate::nuts::nut04::{MintRequest, PostMintResponse};
|
||||||
pub use crate::nuts::nut05::{
|
pub use crate::nuts::nut05::{
|
||||||
CheckFeesRequest, CheckFeesResponse, MeltRequest as Nut05MeltRequest,
|
MeltBolt11Request as Nut05MeltBolt11Request, MeltBolt11Response as Nut05MeltBolt11Response,
|
||||||
MeltResponse as Nut05MeltResponse,
|
MeltQuoteBolt11Request,
|
||||||
};
|
};
|
||||||
pub use crate::nuts::nut07::{CheckSpendableRequest, CheckSpendableResponse};
|
pub use crate::nuts::nut07::{CheckSpendableRequest, CheckSpendableResponse};
|
||||||
pub use crate::nuts::nut08::{MeltRequest, MeltResponse};
|
pub use crate::nuts::nut08::{MeltBolt11Request, MeltBolt11Response};
|
||||||
pub use crate::nuts::nut09::{MintInfo, MintVersion};
|
pub use crate::nuts::nut09::{MintInfo, MintVersion};
|
||||||
pub use crate::types::amount::Amount;
|
pub use crate::types::amount::Amount;
|
||||||
pub use crate::types::{Bolt11Invoice, KeySetInfo, Secret};
|
pub use crate::types::{Bolt11Invoice, KeySetInfo, Secret};
|
||||||
|
|||||||
@@ -9,6 +9,13 @@ pub struct BlindedSignature {
|
|||||||
inner: BlindedSignatureSdk,
|
inner: BlindedSignatureSdk,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Deref for BlindedSignature {
|
||||||
|
type Target = BlindedSignatureSdk;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl BlindedSignature {
|
impl BlindedSignature {
|
||||||
pub fn new(id: Arc<Id>, amount: Arc<Amount>, c: Arc<PublicKey>) -> Self {
|
pub fn new(id: Arc<Id>, amount: Arc<Amount>, c: Arc<PublicKey>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|||||||
@@ -1,12 +1,37 @@
|
|||||||
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use cashu::nuts::nut00::wallet::Token as TokenSdk;
|
use cashu::nuts::nut00::wallet::Token as TokenSdk;
|
||||||
|
use cashu::nuts::CurrencyUnit as CurrencyUnitSdk;
|
||||||
use cashu::url::UncheckedUrl;
|
use cashu::url::UncheckedUrl;
|
||||||
|
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::{MintProofs, Proof};
|
use crate::{MintProofs, Proof};
|
||||||
|
|
||||||
|
pub enum CurrencyUnit {
|
||||||
|
Sat,
|
||||||
|
Custom { unit: String },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&CurrencyUnit> for CurrencyUnitSdk {
|
||||||
|
fn from(unit: &CurrencyUnit) -> CurrencyUnitSdk {
|
||||||
|
match unit {
|
||||||
|
CurrencyUnit::Sat => CurrencyUnitSdk::Sat,
|
||||||
|
CurrencyUnit::Custom { unit } => CurrencyUnitSdk::Custom(unit.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CurrencyUnitSdk> for CurrencyUnit {
|
||||||
|
fn from(unit: CurrencyUnitSdk) -> CurrencyUnit {
|
||||||
|
match unit {
|
||||||
|
CurrencyUnitSdk::Sat => CurrencyUnit::Sat,
|
||||||
|
CurrencyUnitSdk::Custom(unit) => CurrencyUnit::Custom { unit: unit.clone() },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Token {
|
pub struct Token {
|
||||||
inner: TokenSdk,
|
inner: TokenSdk,
|
||||||
}
|
}
|
||||||
@@ -15,13 +40,16 @@ impl Token {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
mint: String,
|
mint: String,
|
||||||
proofs: Vec<Arc<Proof>>,
|
proofs: Vec<Arc<Proof>>,
|
||||||
unit: Option<String>,
|
|
||||||
memo: Option<String>,
|
memo: Option<String>,
|
||||||
|
unit: Option<String>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let mint = UncheckedUrl::from_str(&mint)?;
|
let mint = UncheckedUrl::from_str(&mint)?;
|
||||||
let proofs = proofs.into_iter().map(|p| p.as_ref().into()).collect();
|
let proofs = proofs.into_iter().map(|p| p.as_ref().into()).collect();
|
||||||
|
|
||||||
|
let unit = unit.map(|u| CurrencyUnitSdk::from_str(&u).unwrap_or_default().into());
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner: TokenSdk::new(mint, proofs, unit, memo)?,
|
inner: TokenSdk::new(mint, proofs, memo, unit)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,14 +66,23 @@ impl Token {
|
|||||||
self.inner.memo.clone()
|
self.inner.memo.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unit(&self) -> Option<String> {
|
||||||
|
self.inner
|
||||||
|
.unit
|
||||||
|
.clone()
|
||||||
|
.map(|u| Into::<CurrencyUnitSdk>::into(u).to_string())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_string(token: String) -> Result<Self> {
|
pub fn from_string(token: String) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner: TokenSdk::from_str(&token)?,
|
inner: TokenSdk::from_str(&token)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn as_string(&self) -> Result<String> {
|
impl fmt::Display for Token {
|
||||||
Ok(self.inner.to_string())
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.inner.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,100 +2,130 @@ use std::ops::Deref;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use cashu::nuts::nut05::{
|
use cashu::nuts::{
|
||||||
CheckFeesRequest as CheckFeesRequestSdk, CheckFeesResponse as CheckFeesResponseSdk,
|
CurrencyUnit, MeltBolt11Request as MeltBolt11RequestSdk,
|
||||||
MeltRequest as MeltRequestSdk, MeltResponse as MeltResponseSdk,
|
MeltBolt11Response as MeltBolt11ResponseSdk,
|
||||||
|
MeltQuoteBolt11Request as MeltQuoteBolt11RequestSdk,
|
||||||
|
MeltQuoteBolt11Response as MeltQuoteBolt11ResponseSdk,
|
||||||
};
|
};
|
||||||
use cashu::Bolt11Invoice;
|
use cashu::Bolt11Invoice;
|
||||||
|
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::{Amount, Proof};
|
use crate::{BlindedMessage, BlindedSignature, Proof};
|
||||||
|
|
||||||
pub struct CheckFeesRequest {
|
pub struct MeltQuoteBolt11Response {
|
||||||
inner: CheckFeesRequestSdk,
|
inner: MeltQuoteBolt11ResponseSdk,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CheckFeesRequest {
|
impl MeltQuoteBolt11Response {
|
||||||
pub fn new(invoice: String) -> Result<Self> {
|
pub fn new(
|
||||||
|
quote: String,
|
||||||
|
amount: u64,
|
||||||
|
fee_reserve: u64,
|
||||||
|
paid: bool,
|
||||||
|
expiry: u64,
|
||||||
|
) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner: CheckFeesRequestSdk {
|
inner: MeltQuoteBolt11ResponseSdk {
|
||||||
pr: Bolt11Invoice::from_str(&invoice)?,
|
quote,
|
||||||
|
amount,
|
||||||
|
fee_reserve,
|
||||||
|
paid,
|
||||||
|
expiry,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn invoice(&self) -> String {
|
pub fn quote(&self) -> String {
|
||||||
self.inner.pr.to_string()
|
self.inner.quote.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn amount(&self) -> u64 {
|
||||||
|
self.inner.amount
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fee_reserve(&self) -> u64 {
|
||||||
|
self.inner.fee_reserve
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn paid(&self) -> bool {
|
||||||
|
self.inner.paid
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expiry(&self) -> u64 {
|
||||||
|
self.inner.expiry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CheckFeesResponse {
|
pub struct MeltQuoteBolt11Request {
|
||||||
inner: CheckFeesResponseSdk,
|
inner: MeltQuoteBolt11RequestSdk,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CheckFeesResponse {
|
impl MeltQuoteBolt11Request {
|
||||||
pub fn new(amount: Arc<Amount>) -> Self {
|
pub fn new(request: String, unit: String) -> Result<Self> {
|
||||||
Self {
|
|
||||||
inner: CheckFeesResponseSdk {
|
|
||||||
fee: *amount.as_ref().deref(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn amount(&self) -> Arc<Amount> {
|
|
||||||
Arc::new(self.inner.fee.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<cashu::nuts::nut05::CheckFeesResponse> for CheckFeesResponse {
|
|
||||||
fn from(inner: cashu::nuts::nut05::CheckFeesResponse) -> CheckFeesResponse {
|
|
||||||
Self { inner }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CheckFeesResponse> for cashu::nuts::nut05::CheckFeesResponse {
|
|
||||||
fn from(res: CheckFeesResponse) -> cashu::nuts::nut05::CheckFeesResponse {
|
|
||||||
res.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct MeltRequest {
|
|
||||||
inner: MeltRequestSdk,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MeltRequest {
|
|
||||||
pub fn new(proofs: Vec<Arc<Proof>>, invoice: String) -> Result<Self> {
|
|
||||||
let pr = Bolt11Invoice::from_str(&invoice)?;
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner: MeltRequestSdk {
|
inner: MeltQuoteBolt11RequestSdk {
|
||||||
pr,
|
request: Bolt11Invoice::from_str(&request)?,
|
||||||
proofs: proofs.into_iter().map(|p| p.as_ref().into()).collect(),
|
unit: CurrencyUnit::from_str(&unit)?,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn proofs(&self) -> Vec<Arc<Proof>> {
|
pub fn request(&self) -> String {
|
||||||
|
self.inner.request.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unit(&self) -> String {
|
||||||
|
self.inner.unit.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MeltBolt11Request {
|
||||||
|
inner: MeltBolt11RequestSdk,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MeltBolt11Request {
|
||||||
|
pub fn new(
|
||||||
|
quote: String,
|
||||||
|
inputs: Vec<Arc<Proof>>,
|
||||||
|
outputs: Option<Vec<Arc<BlindedMessage>>>,
|
||||||
|
) -> Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
inner: MeltBolt11RequestSdk {
|
||||||
|
quote,
|
||||||
|
inputs: inputs.into_iter().map(|p| p.as_ref().into()).collect(),
|
||||||
|
outputs: outputs
|
||||||
|
.map(|o| o.into_iter().map(|p| p.as_ref().deref().clone()).collect()),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inputs(&self) -> Vec<Arc<Proof>> {
|
||||||
self.inner
|
self.inner
|
||||||
.proofs
|
.inputs
|
||||||
.clone()
|
.clone()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|p| Arc::new(p.into()))
|
.map(|p| Arc::new(p.into()))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn invoice(&self) -> String {
|
pub fn quote(&self) -> String {
|
||||||
self.inner.pr.to_string()
|
self.inner.quote
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MeltResponse {
|
pub struct MeltBolt11Response {
|
||||||
inner: MeltResponseSdk,
|
inner: MeltBolt11ResponseSdk,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MeltResponse {
|
impl MeltBolt11Response {
|
||||||
pub fn new(paid: bool, preimage: Option<String>) -> Self {
|
pub fn new(paid: bool, proof: String, change: Option<Vec<Arc<BlindedSignature>>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: MeltResponseSdk { paid, preimage },
|
inner: MeltBolt11ResponseSdk {
|
||||||
|
paid,
|
||||||
|
proof,
|
||||||
|
change: change.map(|c| c.into_iter().map(|b| b.as_ref().deref().clone()).collect()),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +133,7 @@ impl MeltResponse {
|
|||||||
self.inner.paid
|
self.inner.paid
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn preimage(&self) -> Option<String> {
|
pub fn proof(&self) -> String {
|
||||||
self.inner.preimage.clone()
|
self.inner.proof.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,53 +1,51 @@
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::str::FromStr;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use cashu::nuts::nut08::{MeltRequest as MeltRequestSdk, MeltResponse as MeltResponseSdk};
|
use cashu::nuts::nut08::{
|
||||||
use cashu::Bolt11Invoice;
|
MeltBolt11Request as MeltBolt11RequestSdk, MeltBolt11Response as MeltBolt11ResponseSdk,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::{BlindedMessage, BlindedSignature, Proof};
|
use crate::{BlindedMessage, BlindedSignature, Proof};
|
||||||
|
|
||||||
pub struct MeltRequest {
|
pub struct MeltBolt11Request {
|
||||||
inner: MeltRequestSdk,
|
inner: MeltBolt11RequestSdk,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for MeltRequest {
|
impl Deref for MeltBolt11Request {
|
||||||
type Target = MeltRequestSdk;
|
type Target = MeltBolt11RequestSdk;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.inner
|
&self.inner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MeltRequest {
|
impl MeltBolt11Request {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
quote: String,
|
||||||
proofs: Vec<Arc<Proof>>,
|
proofs: Vec<Arc<Proof>>,
|
||||||
invoice: String,
|
|
||||||
outputs: Option<Vec<Arc<BlindedMessage>>>,
|
outputs: Option<Vec<Arc<BlindedMessage>>>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let pr = Bolt11Invoice::from_str(&invoice)?;
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner: MeltRequestSdk {
|
inner: MeltBolt11RequestSdk {
|
||||||
proofs: proofs.iter().map(|p| p.as_ref().into()).collect(),
|
quote,
|
||||||
pr,
|
inputs: proofs.iter().map(|p| p.as_ref().into()).collect(),
|
||||||
outputs: outputs
|
outputs: outputs
|
||||||
.map(|outputs| outputs.into_iter().map(|o| o.as_ref().into()).collect()),
|
.map(|outputs| outputs.into_iter().map(|o| o.as_ref().into()).collect()),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn proofs(&self) -> Vec<Arc<Proof>> {
|
pub fn inputs(&self) -> Vec<Arc<Proof>> {
|
||||||
self.inner
|
self.inner
|
||||||
.proofs
|
.inputs
|
||||||
.clone()
|
.clone()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|o| Arc::new(o.into()))
|
.map(|o| Arc::new(o.into()))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn invoice(&self) -> String {
|
pub fn quote(&self) -> String {
|
||||||
self.inner.pr.to_string()
|
self.inner.quote.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn outputs(&self) -> Option<Vec<Arc<BlindedMessage>>> {
|
pub fn outputs(&self) -> Option<Vec<Arc<BlindedMessage>>> {
|
||||||
@@ -58,39 +56,35 @@ impl MeltRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MeltResponse {
|
pub struct MeltBolt11Response {
|
||||||
inner: MeltResponseSdk,
|
inner: MeltBolt11ResponseSdk,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for MeltResponse {
|
impl Deref for MeltBolt11Response {
|
||||||
type Target = MeltResponseSdk;
|
type Target = MeltBolt11ResponseSdk;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.inner
|
&self.inner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<cashu::nuts::nut08::MeltResponse> for MeltResponse {
|
impl From<cashu::nuts::nut08::MeltBolt11Response> for MeltBolt11Response {
|
||||||
fn from(inner: cashu::nuts::nut08::MeltResponse) -> MeltResponse {
|
fn from(inner: cashu::nuts::nut08::MeltBolt11Response) -> MeltBolt11Response {
|
||||||
MeltResponse { inner }
|
MeltBolt11Response { inner }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<MeltResponse> for cashu::nuts::nut08::MeltResponse {
|
impl From<MeltBolt11Response> for cashu::nuts::nut08::MeltBolt11Response {
|
||||||
fn from(res: MeltResponse) -> cashu::nuts::nut08::MeltResponse {
|
fn from(res: MeltBolt11Response) -> cashu::nuts::nut08::MeltBolt11Response {
|
||||||
res.inner
|
res.inner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MeltResponse {
|
impl MeltBolt11Response {
|
||||||
pub fn new(
|
pub fn new(paid: bool, proof: String, change: Option<Vec<Arc<BlindedSignature>>>) -> Self {
|
||||||
paid: bool,
|
|
||||||
preimage: Option<String>,
|
|
||||||
change: Option<Vec<Arc<BlindedSignature>>>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
inner: MeltResponseSdk {
|
inner: MeltBolt11ResponseSdk {
|
||||||
paid,
|
paid,
|
||||||
preimage,
|
proof,
|
||||||
change: change
|
change: change
|
||||||
.map(|change| change.into_iter().map(|bs| bs.as_ref().into()).collect()),
|
.map(|change| change.into_iter().map(|bs| bs.as_ref().into()).collect()),
|
||||||
},
|
},
|
||||||
@@ -101,8 +95,8 @@ impl MeltResponse {
|
|||||||
self.inner.paid
|
self.inner.paid
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn preimage(&self) -> Option<String> {
|
pub fn proof(&self) -> String {
|
||||||
self.inner.preimage.clone()
|
self.inner.proof.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn change(&self) -> Option<Vec<Arc<BlindedSignature>>> {
|
pub fn change(&self) -> Option<Vec<Arc<BlindedSignature>>> {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use std::ops::Deref;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use cashu::nuts::nut00::wallet::Token;
|
use cashu::nuts::nut00::wallet::Token;
|
||||||
|
use cashu::nuts::CurrencyUnit;
|
||||||
use cashu::url::UncheckedUrl;
|
use cashu::url::UncheckedUrl;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
@@ -31,13 +32,18 @@ impl JsToken {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
mint: String,
|
mint: String,
|
||||||
proofs: JsValue,
|
proofs: JsValue,
|
||||||
unit: Option<String>,
|
|
||||||
memo: Option<String>,
|
memo: Option<String>,
|
||||||
|
unit: Option<String>,
|
||||||
) -> Result<JsToken> {
|
) -> Result<JsToken> {
|
||||||
let mint = UncheckedUrl::from_str(&mint).map_err(into_err)?;
|
let mint = UncheckedUrl::from_str(&mint).map_err(into_err)?;
|
||||||
let proofs = serde_wasm_bindgen::from_value(proofs).map_err(into_err)?;
|
let proofs = serde_wasm_bindgen::from_value(proofs).map_err(into_err)?;
|
||||||
|
let unit = unit.map(|u| {
|
||||||
|
CurrencyUnit::from_str(&u)
|
||||||
|
.map_err(into_err)
|
||||||
|
.unwrap_or_default()
|
||||||
|
});
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner: Token::new(mint, proofs, unit, memo).map_err(into_err)?,
|
inner: Token::new(mint, proofs, memo, unit).map_err(into_err)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,79 +1 @@
|
|||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
use cashu::nuts::nut05::{CheckFeesRequest, CheckFeesResponse};
|
|
||||||
use wasm_bindgen::prelude::*;
|
|
||||||
|
|
||||||
use crate::error::Result;
|
|
||||||
use crate::types::{JsAmount, JsBolt11Invoice};
|
|
||||||
|
|
||||||
#[wasm_bindgen(js_name = CheckFeesRequest)]
|
|
||||||
pub struct JsCheckFeesRequest {
|
|
||||||
inner: CheckFeesRequest,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for JsCheckFeesRequest {
|
|
||||||
type Target = CheckFeesRequest;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CheckFeesRequest> for JsCheckFeesRequest {
|
|
||||||
fn from(inner: CheckFeesRequest) -> JsCheckFeesRequest {
|
|
||||||
JsCheckFeesRequest { inner }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen(js_class = CheckFeesRequest)]
|
|
||||||
impl JsCheckFeesRequest {
|
|
||||||
#[wasm_bindgen(constructor)]
|
|
||||||
pub fn new(invoice: JsBolt11Invoice) -> Result<JsCheckFeesRequest> {
|
|
||||||
Ok(JsCheckFeesRequest {
|
|
||||||
inner: CheckFeesRequest {
|
|
||||||
pr: invoice.clone(),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get Amount
|
|
||||||
#[wasm_bindgen(getter)]
|
|
||||||
pub fn invoice(&self) -> JsBolt11Invoice {
|
|
||||||
self.inner.pr.clone().into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen(js_name = CheckFeesResponse)]
|
|
||||||
pub struct JsCheckFeesResponse {
|
|
||||||
inner: CheckFeesResponse,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for JsCheckFeesResponse {
|
|
||||||
type Target = CheckFeesResponse;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CheckFeesResponse> for JsCheckFeesResponse {
|
|
||||||
fn from(inner: CheckFeesResponse) -> JsCheckFeesResponse {
|
|
||||||
JsCheckFeesResponse { inner }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[wasm_bindgen(js_class = CheckFeesResponse)]
|
|
||||||
impl JsCheckFeesResponse {
|
|
||||||
#[wasm_bindgen(constructor)]
|
|
||||||
pub fn new(amount: JsAmount) -> Result<JsCheckFeesResponse> {
|
|
||||||
Ok(JsCheckFeesResponse {
|
|
||||||
inner: CheckFeesResponse {
|
|
||||||
fee: *amount.deref(),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get Amount
|
|
||||||
#[wasm_bindgen(getter)]
|
|
||||||
pub fn amount(&self) -> JsAmount {
|
|
||||||
self.inner.fee.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use cashu::nuts::nut00::{BlindedMessage, BlindedSignature, Proof};
|
use cashu::nuts::nut00::{BlindedMessage, BlindedSignature, Proof};
|
||||||
use cashu::nuts::nut08::{MeltRequest, MeltResponse};
|
use cashu::nuts::nut08::{MeltBolt11Request, MeltBolt11Response};
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
use crate::error::{into_err, Result};
|
use crate::error::{into_err, Result};
|
||||||
use crate::types::{JsAmount, JsBolt11Invoice};
|
use crate::types::JsAmount;
|
||||||
|
|
||||||
#[wasm_bindgen(js_name = MeltRequest)]
|
#[wasm_bindgen(js_name = MeltRequest)]
|
||||||
pub struct JsMeltRequest {
|
pub struct JsMeltRequest {
|
||||||
inner: MeltRequest,
|
inner: MeltBolt11Request,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for JsMeltRequest {
|
impl Deref for JsMeltRequest {
|
||||||
type Target = MeltRequest;
|
type Target = MeltBolt11Request;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.inner
|
&self.inner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<MeltRequest> for JsMeltRequest {
|
impl From<MeltBolt11Request> for JsMeltRequest {
|
||||||
fn from(inner: MeltRequest) -> JsMeltRequest {
|
fn from(inner: MeltBolt11Request) -> JsMeltRequest {
|
||||||
JsMeltRequest { inner }
|
JsMeltRequest { inner }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,12 +28,8 @@ impl From<MeltRequest> for JsMeltRequest {
|
|||||||
#[wasm_bindgen(js_class = MeltRequest)]
|
#[wasm_bindgen(js_class = MeltRequest)]
|
||||||
impl JsMeltRequest {
|
impl JsMeltRequest {
|
||||||
#[wasm_bindgen(constructor)]
|
#[wasm_bindgen(constructor)]
|
||||||
pub fn new(
|
pub fn new(quote: String, inputs: JsValue, outputs: JsValue) -> Result<JsMeltRequest> {
|
||||||
proofs: JsValue,
|
let inputs: Vec<Proof> = serde_wasm_bindgen::from_value(inputs).map_err(into_err)?;
|
||||||
invoice: JsBolt11Invoice,
|
|
||||||
outputs: JsValue,
|
|
||||||
) -> Result<JsMeltRequest> {
|
|
||||||
let proofs: Vec<Proof> = serde_wasm_bindgen::from_value(proofs).map_err(into_err)?;
|
|
||||||
let outputs: Option<Vec<BlindedMessage>> = if !outputs.is_null() {
|
let outputs: Option<Vec<BlindedMessage>> = if !outputs.is_null() {
|
||||||
Some(serde_wasm_bindgen::from_value(outputs).map_err(into_err)?)
|
Some(serde_wasm_bindgen::from_value(outputs).map_err(into_err)?)
|
||||||
} else {
|
} else {
|
||||||
@@ -41,9 +37,9 @@ impl JsMeltRequest {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Ok(JsMeltRequest {
|
Ok(JsMeltRequest {
|
||||||
inner: MeltRequest {
|
inner: MeltBolt11Request {
|
||||||
proofs,
|
quote,
|
||||||
pr: invoice.deref().clone(),
|
inputs,
|
||||||
outputs,
|
outputs,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -51,14 +47,14 @@ impl JsMeltRequest {
|
|||||||
|
|
||||||
/// Get Proofs
|
/// Get Proofs
|
||||||
#[wasm_bindgen(getter)]
|
#[wasm_bindgen(getter)]
|
||||||
pub fn proofs(&self) -> Result<JsValue> {
|
pub fn inputs(&self) -> Result<JsValue> {
|
||||||
serde_wasm_bindgen::to_value(&self.inner.proofs).map_err(into_err)
|
serde_wasm_bindgen::to_value(&self.inner.inputs).map_err(into_err)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get Invoice
|
/// Get Invoice
|
||||||
#[wasm_bindgen(getter)]
|
#[wasm_bindgen(getter)]
|
||||||
pub fn invoice(&self) -> JsBolt11Invoice {
|
pub fn quote(&self) -> String {
|
||||||
self.inner.pr.clone().into()
|
self.inner.quote.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get outputs
|
/// Get outputs
|
||||||
@@ -70,18 +66,18 @@ impl JsMeltRequest {
|
|||||||
|
|
||||||
#[wasm_bindgen(js_name = MeltResponse)]
|
#[wasm_bindgen(js_name = MeltResponse)]
|
||||||
pub struct JsMeltResponse {
|
pub struct JsMeltResponse {
|
||||||
inner: MeltResponse,
|
inner: MeltBolt11Response,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for JsMeltResponse {
|
impl Deref for JsMeltResponse {
|
||||||
type Target = MeltResponse;
|
type Target = MeltBolt11Response;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.inner
|
&self.inner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<MeltResponse> for JsMeltResponse {
|
impl From<MeltBolt11Response> for JsMeltResponse {
|
||||||
fn from(inner: MeltResponse) -> JsMeltResponse {
|
fn from(inner: MeltBolt11Response) -> JsMeltResponse {
|
||||||
JsMeltResponse { inner }
|
JsMeltResponse { inner }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,7 +85,7 @@ impl From<MeltResponse> for JsMeltResponse {
|
|||||||
#[wasm_bindgen(js_class = MeltResponse)]
|
#[wasm_bindgen(js_class = MeltResponse)]
|
||||||
impl JsMeltResponse {
|
impl JsMeltResponse {
|
||||||
#[wasm_bindgen(constructor)]
|
#[wasm_bindgen(constructor)]
|
||||||
pub fn new(paid: bool, preimage: Option<String>, change: JsValue) -> Result<JsMeltResponse> {
|
pub fn new(paid: bool, proof: String, change: JsValue) -> Result<JsMeltResponse> {
|
||||||
let change: Option<Vec<BlindedSignature>> = if change.is_null() {
|
let change: Option<Vec<BlindedSignature>> = if change.is_null() {
|
||||||
Some(serde_wasm_bindgen::from_value(change).map_err(into_err)?)
|
Some(serde_wasm_bindgen::from_value(change).map_err(into_err)?)
|
||||||
} else {
|
} else {
|
||||||
@@ -97,9 +93,9 @@ impl JsMeltResponse {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Ok(JsMeltResponse {
|
Ok(JsMeltResponse {
|
||||||
inner: MeltResponse {
|
inner: MeltBolt11Response {
|
||||||
|
proof,
|
||||||
paid,
|
paid,
|
||||||
preimage,
|
|
||||||
change,
|
change,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -113,8 +109,8 @@ impl JsMeltResponse {
|
|||||||
|
|
||||||
/// Get Preimage
|
/// Get Preimage
|
||||||
#[wasm_bindgen(getter)]
|
#[wasm_bindgen(getter)]
|
||||||
pub fn preimage(&self) -> Option<String> {
|
pub fn proof(&self) -> String {
|
||||||
self.inner.preimage.clone()
|
self.inner.proof.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get Change
|
/// Get Change
|
||||||
@@ -125,7 +121,7 @@ impl JsMeltResponse {
|
|||||||
|
|
||||||
/// Change Amount
|
/// Change Amount
|
||||||
#[wasm_bindgen(js_name = "changeAmount")]
|
#[wasm_bindgen(js_name = "changeAmount")]
|
||||||
pub fn change_amount(&self) -> JsAmount {
|
pub fn change_amount(&self) -> Option<JsAmount> {
|
||||||
self.inner.change_amount().into()
|
self.inner.change_amount().map(|a| a.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,13 @@ interface CashuError {
|
|||||||
|
|
||||||
// Types
|
// Types
|
||||||
|
|
||||||
|
|
||||||
|
[Enum]
|
||||||
|
interface CurrencyUnit {
|
||||||
|
Sat();
|
||||||
|
Custom(string unit);
|
||||||
|
};
|
||||||
|
|
||||||
interface Bolt11Invoice {
|
interface Bolt11Invoice {
|
||||||
[Throws=CashuError]
|
[Throws=CashuError]
|
||||||
constructor(string bolt11);
|
constructor(string bolt11);
|
||||||
@@ -91,11 +98,11 @@ interface MintProofs {
|
|||||||
|
|
||||||
interface Token {
|
interface Token {
|
||||||
[Throws=CashuError]
|
[Throws=CashuError]
|
||||||
constructor(string mint, sequence<Proof> token, string? unit, string? memo);
|
constructor(string mint, sequence<Proof> token, string? memo, CurrencyUnit? unit);
|
||||||
sequence<MintProofs> token();
|
sequence<MintProofs> token();
|
||||||
string? memo();
|
string? memo();
|
||||||
[Throws=CashuError]
|
CurrencyUnit? unit();
|
||||||
string as_string();
|
string to_string();
|
||||||
[Throws=CashuError, Name=from_string]
|
[Throws=CashuError, Name=from_string]
|
||||||
constructor(string token);
|
constructor(string token);
|
||||||
|
|
||||||
@@ -148,6 +155,32 @@ interface KeySetResponse {
|
|||||||
sequence<KeySetInfo> keysets();
|
sequence<KeySetInfo> keysets();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// NUT-05
|
||||||
|
|
||||||
|
interface MeltQuoteBolt11Response {
|
||||||
|
[Throws=CashuError]
|
||||||
|
constructor(string quote, u64 amount, u64 fee_reserve, boolean paid, u64 expiry);
|
||||||
|
string quote();
|
||||||
|
u64 amount();
|
||||||
|
u64 fee_reserve();
|
||||||
|
boolean paid();
|
||||||
|
u64 expiry();
|
||||||
|
};
|
||||||
|
|
||||||
|
interface MeltQuoteBolt11Request {
|
||||||
|
[Throws=CashuError]
|
||||||
|
constructor(string request, string unit);
|
||||||
|
string request();
|
||||||
|
string unit();
|
||||||
|
};
|
||||||
|
|
||||||
|
interface MeltBolt11Request {
|
||||||
|
[Throws=CashuError]
|
||||||
|
constructor(sequence<Proof> inputs, string quote);
|
||||||
|
sequence<Proof> inputs();
|
||||||
|
string quote();
|
||||||
|
};
|
||||||
|
|
||||||
interface RequestMintResponse {
|
interface RequestMintResponse {
|
||||||
[Throws=CashuError]
|
[Throws=CashuError]
|
||||||
constructor(string invoice, string hash);
|
constructor(string invoice, string hash);
|
||||||
@@ -166,30 +199,6 @@ interface PostMintResponse {
|
|||||||
sequence<BlindedSignature> promises();
|
sequence<BlindedSignature> promises();
|
||||||
};
|
};
|
||||||
|
|
||||||
interface CheckFeesRequest {
|
|
||||||
[Throws=CashuError]
|
|
||||||
constructor(string invoice);
|
|
||||||
string invoice();
|
|
||||||
};
|
|
||||||
|
|
||||||
interface CheckFeesResponse {
|
|
||||||
constructor(Amount amount);
|
|
||||||
Amount amount();
|
|
||||||
};
|
|
||||||
|
|
||||||
interface Nut05MeltRequest {
|
|
||||||
[Throws=CashuError]
|
|
||||||
constructor(sequence<Proof> proofs, string Invoice);
|
|
||||||
sequence<Proof> proofs();
|
|
||||||
string invoice();
|
|
||||||
};
|
|
||||||
|
|
||||||
interface Nut05MeltResponse {
|
|
||||||
constructor(boolean paid, string? preimage);
|
|
||||||
boolean paid();
|
|
||||||
string? preimage();
|
|
||||||
};
|
|
||||||
|
|
||||||
interface SplitRequest {
|
interface SplitRequest {
|
||||||
constructor(sequence<Proof> proofs, sequence<BlindedMessage> outputs);
|
constructor(sequence<Proof> proofs, sequence<BlindedMessage> outputs);
|
||||||
sequence<Proof> proofs();
|
sequence<Proof> proofs();
|
||||||
@@ -205,31 +214,6 @@ interface SplitResponse {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
interface CheckSpendableRequest {
|
|
||||||
constructor(sequence<MintProof> proofs);
|
|
||||||
sequence<MintProof> proofs();
|
|
||||||
};
|
|
||||||
|
|
||||||
interface CheckSpendableResponse {
|
|
||||||
constructor(sequence<boolean> spendable, sequence<boolean> pending);
|
|
||||||
sequence<boolean> spendable();
|
|
||||||
sequence<boolean> pending();
|
|
||||||
};
|
|
||||||
|
|
||||||
interface MeltRequest {
|
|
||||||
[Throws=CashuError]
|
|
||||||
constructor(sequence<Proof> proofs, string Invoice, sequence<BlindedMessage>? outputs);
|
|
||||||
sequence<Proof> proofs();
|
|
||||||
string invoice();
|
|
||||||
sequence<BlindedMessage>? outputs();
|
|
||||||
};
|
|
||||||
|
|
||||||
interface MeltResponse {
|
|
||||||
constructor(boolean paid, string? preimage, sequence<BlindedSignature>? change);
|
|
||||||
boolean paid();
|
|
||||||
string? preimage();
|
|
||||||
sequence<BlindedSignature>? change();
|
|
||||||
};
|
|
||||||
|
|
||||||
interface MintVersion {
|
interface MintVersion {
|
||||||
constructor(string name, string version);
|
constructor(string name, string version);
|
||||||
|
|||||||
@@ -38,16 +38,20 @@ impl JsMint {
|
|||||||
secret: String,
|
secret: String,
|
||||||
keyset_info: JsValue,
|
keyset_info: JsValue,
|
||||||
spent_secrets: JsValue,
|
spent_secrets: JsValue,
|
||||||
|
quotes: JsValue,
|
||||||
min_fee_reserve: JsAmount,
|
min_fee_reserve: JsAmount,
|
||||||
percent_fee_reserve: f32,
|
percent_fee_reserve: f32,
|
||||||
) -> Result<JsMint> {
|
) -> Result<JsMint> {
|
||||||
let keyset_info = serde_wasm_bindgen::from_value(keyset_info).map_err(into_err)?;
|
let keyset_info = serde_wasm_bindgen::from_value(keyset_info).map_err(into_err)?;
|
||||||
let spent_secrets = serde_wasm_bindgen::from_value(spent_secrets).map_err(into_err)?;
|
let spent_secrets = serde_wasm_bindgen::from_value(spent_secrets).map_err(into_err)?;
|
||||||
|
|
||||||
|
let quotes = serde_wasm_bindgen::from_value(quotes).map_err(into_err)?;
|
||||||
Ok(JsMint {
|
Ok(JsMint {
|
||||||
inner: Mint::new(
|
inner: Mint::new(
|
||||||
&secret,
|
&secret,
|
||||||
keyset_info,
|
keyset_info,
|
||||||
spent_secrets,
|
spent_secrets,
|
||||||
|
quotes,
|
||||||
*min_fee_reserve.deref(),
|
*min_fee_reserve.deref(),
|
||||||
percent_fee_reserve,
|
percent_fee_reserve,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use cashu_js::nuts::nut00::{JsBlindedMessages, JsToken};
|
use cashu_js::nuts::nut00::{JsBlindedMessages, JsToken};
|
||||||
use cashu_js::nuts::nut01::JsKeys;
|
use cashu_js::nuts::nut01::JsKeys;
|
||||||
use cashu_js::nuts::nut03::JsRequestMintResponse;
|
use cashu_js::nuts::nut03::JsRequestMintResponse;
|
||||||
|
use cashu_js::JsAmount;
|
||||||
#[cfg(feature = "nut07")]
|
#[cfg(feature = "nut07")]
|
||||||
use cashu_js::JsProofsStatus;
|
use cashu_js::JsProofsStatus;
|
||||||
use cashu_js::{JsAmount, JsBolt11Invoice};
|
|
||||||
use cashu_sdk::client::gloo_client::HttpClient;
|
use cashu_sdk::client::gloo_client::HttpClient;
|
||||||
|
use cashu_sdk::nuts::CurrencyUnit;
|
||||||
use cashu_sdk::wallet::Wallet;
|
use cashu_sdk::wallet::Wallet;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
@@ -72,12 +74,14 @@ impl JsWallet {
|
|||||||
&self,
|
&self,
|
||||||
amount: JsAmount,
|
amount: JsAmount,
|
||||||
hash: String,
|
hash: String,
|
||||||
unit: Option<String>,
|
|
||||||
memo: Option<String>,
|
memo: Option<String>,
|
||||||
|
unit: Option<String>,
|
||||||
) -> Result<JsToken> {
|
) -> Result<JsToken> {
|
||||||
|
let unit = unit.map(|u| CurrencyUnit::from_str(&u).unwrap_or_default());
|
||||||
|
|
||||||
Ok(self
|
Ok(self
|
||||||
.inner
|
.inner
|
||||||
.mint_token(*amount.deref(), &hash, unit, memo)
|
.mint_token(*amount.deref(), &hash, memo, unit)
|
||||||
.await
|
.await
|
||||||
.map_err(into_err)?
|
.map_err(into_err)?
|
||||||
.into())
|
.into())
|
||||||
@@ -96,17 +100,6 @@ impl JsWallet {
|
|||||||
.map_err(into_err)
|
.map_err(into_err)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check Fee
|
|
||||||
#[wasm_bindgen(js_name = checkFee)]
|
|
||||||
pub async fn check_fee(&self, invoice: JsBolt11Invoice) -> Result<JsAmount> {
|
|
||||||
Ok(self
|
|
||||||
.inner
|
|
||||||
.check_fee(invoice.deref().clone())
|
|
||||||
.await
|
|
||||||
.map_err(into_err)?
|
|
||||||
.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Receive
|
/// Receive
|
||||||
#[wasm_bindgen(js_name = receive)]
|
#[wasm_bindgen(js_name = receive)]
|
||||||
pub async fn receive(&self, token: String) -> Result<JsValue> {
|
pub async fn receive(&self, token: String) -> Result<JsValue> {
|
||||||
@@ -149,7 +142,7 @@ impl JsWallet {
|
|||||||
#[wasm_bindgen(js_name = melt)]
|
#[wasm_bindgen(js_name = melt)]
|
||||||
pub async fn melt(
|
pub async fn melt(
|
||||||
&self,
|
&self,
|
||||||
invoice: JsBolt11Invoice,
|
quote: String,
|
||||||
proofs: JsValue,
|
proofs: JsValue,
|
||||||
fee_reserve: JsAmount,
|
fee_reserve: JsAmount,
|
||||||
) -> Result<JsMelted> {
|
) -> Result<JsMelted> {
|
||||||
@@ -157,7 +150,7 @@ impl JsWallet {
|
|||||||
|
|
||||||
Ok(self
|
Ok(self
|
||||||
.inner
|
.inner
|
||||||
.melt(invoice.deref().clone(), proofs, *fee_reserve.deref())
|
.melt(quote, proofs, *fee_reserve.deref())
|
||||||
.await
|
.await
|
||||||
.map_err(into_err)?
|
.map_err(into_err)?
|
||||||
.into())
|
.into())
|
||||||
@@ -173,8 +166,14 @@ impl JsWallet {
|
|||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let proofs = serde_wasm_bindgen::from_value(proofs).map_err(into_err)?;
|
let proofs = serde_wasm_bindgen::from_value(proofs).map_err(into_err)?;
|
||||||
|
|
||||||
|
let unit = unit.map(|u| {
|
||||||
|
CurrencyUnit::from_str(&u)
|
||||||
|
.map_err(into_err)
|
||||||
|
.unwrap_or_default()
|
||||||
|
});
|
||||||
|
|
||||||
self.inner
|
self.inner
|
||||||
.proofs_to_token(proofs, unit, memo)
|
.proofs_to_token(proofs, memo, unit)
|
||||||
.map_err(into_err)
|
.map_err(into_err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,12 @@ use async_trait::async_trait;
|
|||||||
#[cfg(feature = "nut09")]
|
#[cfg(feature = "nut09")]
|
||||||
use cashu::nuts::MintInfo;
|
use cashu::nuts::MintInfo;
|
||||||
use cashu::nuts::{
|
use cashu::nuts::{
|
||||||
BlindedMessage, CheckFeesRequest, CheckFeesResponse, Keys, MeltRequest, MeltResponse,
|
BlindedMessage, Keys, MeltBolt11Request, MeltBolt11Response, MintRequest, PostMintResponse,
|
||||||
MintRequest, PostMintResponse, PreMintSecrets, Proof, RequestMintResponse, SplitRequest,
|
PreMintSecrets, Proof, RequestMintResponse, SplitRequest, SplitResponse, *,
|
||||||
SplitResponse, *,
|
|
||||||
};
|
};
|
||||||
#[cfg(feature = "nut07")]
|
#[cfg(feature = "nut07")]
|
||||||
use cashu::nuts::{CheckSpendableRequest, CheckSpendableResponse};
|
use cashu::nuts::{CheckSpendableRequest, CheckSpendableResponse};
|
||||||
use cashu::{Amount, Bolt11Invoice};
|
use cashu::Amount;
|
||||||
use gloo::net::http::Request;
|
use gloo::net::http::Request;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
@@ -118,49 +117,20 @@ impl Client for HttpClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check Max expected fee [NUT-05]
|
|
||||||
async fn post_check_fees(
|
|
||||||
&self,
|
|
||||||
mint_url: Url,
|
|
||||||
invoice: Bolt11Invoice,
|
|
||||||
) -> Result<CheckFeesResponse, Error> {
|
|
||||||
let url = join_url(mint_url, "checkfees")?;
|
|
||||||
|
|
||||||
let request = CheckFeesRequest { pr: invoice };
|
|
||||||
|
|
||||||
let res = Request::post(url.as_str())
|
|
||||||
.json(&request)
|
|
||||||
.map_err(|err| Error::Gloo(err.to_string()))?
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
.map_err(|err| Error::Gloo(err.to_string()))?
|
|
||||||
.json::<Value>()
|
|
||||||
.await
|
|
||||||
.map_err(|err| Error::Gloo(err.to_string()))?;
|
|
||||||
|
|
||||||
let response: Result<CheckFeesResponse, serde_json::Error> =
|
|
||||||
serde_json::from_value(res.clone());
|
|
||||||
|
|
||||||
match response {
|
|
||||||
Ok(res) => Ok(res),
|
|
||||||
Err(_) => Err(Error::from_json(&res.to_string())?),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Melt [NUT-05]
|
/// Melt [NUT-05]
|
||||||
/// [Nut-08] Lightning fee return if outputs defined
|
/// [Nut-08] Lightning fee return if outputs defined
|
||||||
async fn post_melt(
|
async fn post_melt(
|
||||||
&self,
|
&self,
|
||||||
mint_url: Url,
|
mint_url: Url,
|
||||||
proofs: Vec<Proof>,
|
quote: String,
|
||||||
invoice: Bolt11Invoice,
|
inputs: Vec<Proof>,
|
||||||
outputs: Option<Vec<BlindedMessage>>,
|
outputs: Option<Vec<BlindedMessage>>,
|
||||||
) -> Result<MeltResponse, Error> {
|
) -> Result<MeltBolt11Response, Error> {
|
||||||
let url = join_url(mint_url, "melt")?;
|
let url = join_url(mint_url, "melt")?;
|
||||||
|
|
||||||
let request = MeltRequest {
|
let request = MeltBolt11Request {
|
||||||
proofs,
|
quote,
|
||||||
pr: invoice,
|
inputs,
|
||||||
outputs,
|
outputs,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -174,7 +144,7 @@ impl Client for HttpClient {
|
|||||||
.await
|
.await
|
||||||
.map_err(|err| Error::Gloo(err.to_string()))?;
|
.map_err(|err| Error::Gloo(err.to_string()))?;
|
||||||
|
|
||||||
let response: Result<MeltResponse, serde_json::Error> =
|
let response: Result<MeltBolt11Response, serde_json::Error> =
|
||||||
serde_json::from_value(value.clone());
|
serde_json::from_value(value.clone());
|
||||||
|
|
||||||
match response {
|
match response {
|
||||||
|
|||||||
@@ -6,13 +6,12 @@ use async_trait::async_trait;
|
|||||||
#[cfg(feature = "nut09")]
|
#[cfg(feature = "nut09")]
|
||||||
use cashu::nuts::MintInfo;
|
use cashu::nuts::MintInfo;
|
||||||
use cashu::nuts::{
|
use cashu::nuts::{
|
||||||
BlindedMessage, CheckFeesRequest, CheckFeesResponse, Keys, MeltRequest, MeltResponse,
|
BlindedMessage, Keys, MeltBolt11Request, MeltBolt11Response, MintRequest, PostMintResponse,
|
||||||
MintRequest, PostMintResponse, PreMintSecrets, Proof, RequestMintResponse, SplitRequest,
|
PreMintSecrets, Proof, RequestMintResponse, SplitRequest, SplitResponse, *,
|
||||||
SplitResponse, *,
|
|
||||||
};
|
};
|
||||||
#[cfg(feature = "nut07")]
|
#[cfg(feature = "nut07")]
|
||||||
use cashu::nuts::{CheckSpendableRequest, CheckSpendableResponse};
|
use cashu::nuts::{CheckSpendableRequest, CheckSpendableResponse};
|
||||||
use cashu::{Amount, Bolt11Invoice};
|
use cashu::Amount;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
@@ -96,44 +95,20 @@ impl Client for HttpClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check Max expected fee [NUT-05]
|
|
||||||
async fn post_check_fees(
|
|
||||||
&self,
|
|
||||||
mint_url: Url,
|
|
||||||
invoice: Bolt11Invoice,
|
|
||||||
) -> Result<CheckFeesResponse, Error> {
|
|
||||||
let url = join_url(mint_url, "checkfees")?;
|
|
||||||
|
|
||||||
let request = CheckFeesRequest { pr: invoice };
|
|
||||||
|
|
||||||
let res = minreq::post(url)
|
|
||||||
.with_json(&request)?
|
|
||||||
.send()?
|
|
||||||
.json::<Value>()?;
|
|
||||||
|
|
||||||
let response: Result<CheckFeesResponse, serde_json::Error> =
|
|
||||||
serde_json::from_value(res.clone());
|
|
||||||
|
|
||||||
match response {
|
|
||||||
Ok(res) => Ok(res),
|
|
||||||
Err(_) => Err(Error::from_json(&res.to_string())?),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Melt [NUT-05]
|
/// Melt [NUT-05]
|
||||||
/// [Nut-08] Lightning fee return if outputs defined
|
/// [Nut-08] Lightning fee return if outputs defined
|
||||||
async fn post_melt(
|
async fn post_melt(
|
||||||
&self,
|
&self,
|
||||||
mint_url: Url,
|
mint_url: Url,
|
||||||
proofs: Vec<Proof>,
|
quote: String,
|
||||||
invoice: Bolt11Invoice,
|
inputs: Vec<Proof>,
|
||||||
outputs: Option<Vec<BlindedMessage>>,
|
outputs: Option<Vec<BlindedMessage>>,
|
||||||
) -> Result<MeltResponse, Error> {
|
) -> Result<MeltBolt11Response, Error> {
|
||||||
let url = join_url(mint_url, "melt")?;
|
let url = join_url(mint_url, "melt")?;
|
||||||
|
|
||||||
let request = MeltRequest {
|
let request = MeltBolt11Request {
|
||||||
proofs,
|
quote,
|
||||||
pr: invoice,
|
inputs,
|
||||||
outputs,
|
outputs,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -142,7 +117,7 @@ impl Client for HttpClient {
|
|||||||
.send()?
|
.send()?
|
||||||
.json::<Value>()?;
|
.json::<Value>()?;
|
||||||
|
|
||||||
let response: Result<MeltResponse, serde_json::Error> =
|
let response: Result<MeltBolt11Response, serde_json::Error> =
|
||||||
serde_json::from_value(value.clone());
|
serde_json::from_value(value.clone());
|
||||||
|
|
||||||
match response {
|
match response {
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ use cashu::nuts::CheckSpendableResponse;
|
|||||||
#[cfg(feature = "nut09")]
|
#[cfg(feature = "nut09")]
|
||||||
use cashu::nuts::MintInfo;
|
use cashu::nuts::MintInfo;
|
||||||
use cashu::nuts::{
|
use cashu::nuts::{
|
||||||
BlindedMessage, CheckFeesResponse, Keys, KeysetResponse, MeltResponse, PostMintResponse,
|
BlindedMessage, Keys, KeysetResponse, MeltBolt11Response, PostMintResponse, PreMintSecrets,
|
||||||
PreMintSecrets, Proof, RequestMintResponse, SplitRequest, SplitResponse,
|
Proof, RequestMintResponse, SplitRequest, SplitResponse,
|
||||||
};
|
};
|
||||||
use cashu::{utils, Amount};
|
use cashu::{utils, Amount};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -103,19 +103,13 @@ pub trait Client {
|
|||||||
hash: &str,
|
hash: &str,
|
||||||
) -> Result<PostMintResponse, Error>;
|
) -> Result<PostMintResponse, Error>;
|
||||||
|
|
||||||
async fn post_check_fees(
|
|
||||||
&self,
|
|
||||||
mint_url: Url,
|
|
||||||
invoice: Bolt11Invoice,
|
|
||||||
) -> Result<CheckFeesResponse, Error>;
|
|
||||||
|
|
||||||
async fn post_melt(
|
async fn post_melt(
|
||||||
&self,
|
&self,
|
||||||
mint_url: Url,
|
mint_url: Url,
|
||||||
proofs: Vec<Proof>,
|
quote: String,
|
||||||
invoice: Bolt11Invoice,
|
inputs: Vec<Proof>,
|
||||||
outputs: Option<Vec<BlindedMessage>>,
|
outputs: Option<Vec<BlindedMessage>>,
|
||||||
) -> Result<MeltResponse, Error>;
|
) -> Result<MeltBolt11Response, Error>;
|
||||||
|
|
||||||
// REVIEW: Should be consistent aboue passing in the Request struct or the
|
// REVIEW: Should be consistent aboue passing in the Request struct or the
|
||||||
// compnatants and making it within the function. Here the struct is passed
|
// compnatants and making it within the function. Here the struct is passed
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet};
|
|||||||
use cashu::dhke::{sign_message, verify_message};
|
use cashu::dhke::{sign_message, verify_message};
|
||||||
pub use cashu::error::mint::Error;
|
pub use cashu::error::mint::Error;
|
||||||
use cashu::nuts::{
|
use cashu::nuts::{
|
||||||
BlindedMessage, BlindedSignature, MeltRequest, MeltResponse, Proof, SplitRequest,
|
BlindedMessage, BlindedSignature, MeltBolt11Request, MeltBolt11Response, Proof, SplitRequest,
|
||||||
SplitResponse, *,
|
SplitResponse, *,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "nut07")]
|
#[cfg(feature = "nut07")]
|
||||||
@@ -13,6 +13,8 @@ use cashu::Amount;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tracing::{debug, info};
|
use tracing::{debug, info};
|
||||||
|
|
||||||
|
use crate::types::Quote;
|
||||||
|
|
||||||
pub struct Mint {
|
pub struct Mint {
|
||||||
// pub pubkey: PublicKey
|
// pub pubkey: PublicKey
|
||||||
secret: String,
|
secret: String,
|
||||||
@@ -21,6 +23,7 @@ pub struct Mint {
|
|||||||
pub spent_secrets: HashSet<Secret>,
|
pub spent_secrets: HashSet<Secret>,
|
||||||
pub pending_secrets: HashSet<Secret>,
|
pub pending_secrets: HashSet<Secret>,
|
||||||
pub fee_reserve: FeeReserve,
|
pub fee_reserve: FeeReserve,
|
||||||
|
pub quotes: HashMap<String, Quote>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mint {
|
impl Mint {
|
||||||
@@ -28,6 +31,7 @@ impl Mint {
|
|||||||
secret: &str,
|
secret: &str,
|
||||||
keysets_info: HashSet<MintKeySetInfo>,
|
keysets_info: HashSet<MintKeySetInfo>,
|
||||||
spent_secrets: HashSet<Secret>,
|
spent_secrets: HashSet<Secret>,
|
||||||
|
quotes: Vec<Quote>,
|
||||||
min_fee_reserve: Amount,
|
min_fee_reserve: Amount,
|
||||||
percent_fee_reserve: f32,
|
percent_fee_reserve: f32,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@@ -36,6 +40,8 @@ impl Mint {
|
|||||||
|
|
||||||
let mut active_units: HashSet<String> = HashSet::default();
|
let mut active_units: HashSet<String> = HashSet::default();
|
||||||
|
|
||||||
|
let quotes = quotes.into_iter().map(|q| (q.id.clone(), q)).collect();
|
||||||
|
|
||||||
// Check that there is only one active keyset per unit
|
// Check that there is only one active keyset per unit
|
||||||
for keyset_info in keysets_info {
|
for keyset_info in keysets_info {
|
||||||
if keyset_info.active && !active_units.insert(keyset_info.unit.clone()) {
|
if keyset_info.active && !active_units.insert(keyset_info.unit.clone()) {
|
||||||
@@ -58,6 +64,7 @@ impl Mint {
|
|||||||
Self {
|
Self {
|
||||||
secret: secret.to_string(),
|
secret: secret.to_string(),
|
||||||
keysets,
|
keysets,
|
||||||
|
quotes,
|
||||||
keysets_info: info,
|
keysets_info: info,
|
||||||
spent_secrets,
|
spent_secrets,
|
||||||
pending_secrets: HashSet::new(),
|
pending_secrets: HashSet::new(),
|
||||||
@@ -222,41 +229,28 @@ impl Mint {
|
|||||||
Ok(CheckSpendableResponse { spendable, pending })
|
Ok(CheckSpendableResponse { spendable, pending })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_melt_request(&mut self, melt_request: &MeltRequest) -> Result<(), Error> {
|
pub fn verify_melt_request(&mut self, melt_request: &MeltBolt11Request) -> Result<(), Error> {
|
||||||
let proofs_total = melt_request.proofs_amount();
|
let quote = self.quotes.get(&melt_request.quote).unwrap();
|
||||||
|
let proofs_total = melt_request.proofs_amount().to_sat();
|
||||||
|
|
||||||
let percent_fee_reserve = Amount::from_sat(
|
let required_total = quote.amount + quote.fee_reserve;
|
||||||
(proofs_total.to_sat() as f32 * self.fee_reserve.percent_fee_reserve) as u64,
|
|
||||||
);
|
|
||||||
|
|
||||||
let fee_reserve = if percent_fee_reserve > self.fee_reserve.min_fee_reserve {
|
|
||||||
percent_fee_reserve
|
|
||||||
} else {
|
|
||||||
self.fee_reserve.min_fee_reserve
|
|
||||||
};
|
|
||||||
|
|
||||||
let required_total = melt_request
|
|
||||||
.invoice_amount()
|
|
||||||
.map_err(|_| Error::InvoiceAmountUndefined)?
|
|
||||||
+ fee_reserve;
|
|
||||||
|
|
||||||
if proofs_total < required_total {
|
if proofs_total < required_total {
|
||||||
debug!(
|
debug!(
|
||||||
"Insufficient Proofs: Got: {}, Required: {}",
|
"Insufficient Proofs: Got: {}, Required: {}",
|
||||||
proofs_total.to_sat().to_string(),
|
proofs_total, required_total
|
||||||
required_total.to_sat().to_string()
|
|
||||||
);
|
);
|
||||||
return Err(Error::Amount);
|
return Err(Error::Amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
let secrets: HashSet<&Secret> = melt_request.proofs.iter().map(|p| &p.secret).collect();
|
let secrets: HashSet<&Secret> = melt_request.inputs.iter().map(|p| &p.secret).collect();
|
||||||
|
|
||||||
// Ensure proofs are unique and not being double spent
|
// Ensure proofs are unique and not being double spent
|
||||||
if melt_request.proofs.len().ne(&secrets.len()) {
|
if melt_request.inputs.len().ne(&secrets.len()) {
|
||||||
return Err(Error::DuplicateProofs);
|
return Err(Error::DuplicateProofs);
|
||||||
}
|
}
|
||||||
|
|
||||||
for proof in &melt_request.proofs {
|
for proof in &melt_request.inputs {
|
||||||
self.verify_proof(proof)?
|
self.verify_proof(proof)?
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,13 +259,13 @@ impl Mint {
|
|||||||
|
|
||||||
pub fn process_melt_request(
|
pub fn process_melt_request(
|
||||||
&mut self,
|
&mut self,
|
||||||
melt_request: &MeltRequest,
|
melt_request: &MeltBolt11Request,
|
||||||
preimage: &str,
|
preimage: &str,
|
||||||
total_spent: Amount,
|
total_spent: Amount,
|
||||||
) -> Result<MeltResponse, Error> {
|
) -> Result<MeltBolt11Response, Error> {
|
||||||
self.verify_melt_request(melt_request)?;
|
self.verify_melt_request(melt_request)?;
|
||||||
|
|
||||||
let secrets = Vec::with_capacity(melt_request.proofs.len());
|
let secrets = Vec::with_capacity(melt_request.inputs.len());
|
||||||
for secret in secrets {
|
for secret in secrets {
|
||||||
self.spent_secrets.insert(secret);
|
self.spent_secrets.insert(secret);
|
||||||
}
|
}
|
||||||
@@ -312,9 +306,9 @@ impl Mint {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(MeltResponse {
|
Ok(MeltBolt11Response {
|
||||||
paid: true,
|
paid: true,
|
||||||
preimage: Some(preimage.to_string()),
|
proof: preimage.to_string(),
|
||||||
change,
|
change,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ use cashu::dhke::{construct_proofs, unblind_message};
|
|||||||
#[cfg(feature = "nut07")]
|
#[cfg(feature = "nut07")]
|
||||||
use cashu::nuts::nut00::mint;
|
use cashu::nuts::nut00::mint;
|
||||||
use cashu::nuts::{
|
use cashu::nuts::{
|
||||||
BlindedSignature, Keys, PreMintSecrets, PreSplit, Proof, Proofs, RequestMintResponse,
|
BlindedSignature, CurrencyUnit, Keys, PreMintSecrets, PreSplit, Proof, Proofs,
|
||||||
SplitRequest, Token,
|
RequestMintResponse, SplitRequest, Token,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "nut07")]
|
#[cfg(feature = "nut07")]
|
||||||
use cashu::types::ProofsStatus;
|
use cashu::types::ProofsStatus;
|
||||||
@@ -95,12 +95,12 @@ impl<C: Client> Wallet<C> {
|
|||||||
&self,
|
&self,
|
||||||
amount: Amount,
|
amount: Amount,
|
||||||
hash: &str,
|
hash: &str,
|
||||||
unit: Option<String>,
|
|
||||||
memo: Option<String>,
|
memo: Option<String>,
|
||||||
|
unit: Option<CurrencyUnit>,
|
||||||
) -> Result<Token, Error> {
|
) -> Result<Token, Error> {
|
||||||
let proofs = self.mint(amount, hash).await?;
|
let proofs = self.mint(amount, hash).await?;
|
||||||
|
|
||||||
let token = Token::new(self.mint_url.clone(), proofs, unit, memo);
|
let token = Token::new(self.mint_url.clone(), proofs, memo, unit);
|
||||||
Ok(token?)
|
Ok(token?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,15 +127,6 @@ impl<C: Client> Wallet<C> {
|
|||||||
Ok(proofs)
|
Ok(proofs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check fee
|
|
||||||
pub async fn check_fee(&self, invoice: Bolt11Invoice) -> Result<Amount, Error> {
|
|
||||||
Ok(self
|
|
||||||
.client
|
|
||||||
.post_check_fees(self.mint_url.clone().try_into()?, invoice)
|
|
||||||
.await?
|
|
||||||
.fee)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Receive
|
/// Receive
|
||||||
pub async fn receive(&self, encoded_token: &str) -> Result<Proofs, Error> {
|
pub async fn receive(&self, encoded_token: &str) -> Result<Proofs, Error> {
|
||||||
let token_data = Token::from_str(encoded_token)?;
|
let token_data = Token::from_str(encoded_token)?;
|
||||||
@@ -300,7 +291,7 @@ impl<C: Client> Wallet<C> {
|
|||||||
|
|
||||||
pub async fn melt(
|
pub async fn melt(
|
||||||
&self,
|
&self,
|
||||||
invoice: Bolt11Invoice,
|
quote: String,
|
||||||
proofs: Proofs,
|
proofs: Proofs,
|
||||||
fee_reserve: Amount,
|
fee_reserve: Amount,
|
||||||
) -> Result<Melted, Error> {
|
) -> Result<Melted, Error> {
|
||||||
@@ -309,8 +300,8 @@ impl<C: Client> Wallet<C> {
|
|||||||
.client
|
.client
|
||||||
.post_melt(
|
.post_melt(
|
||||||
self.mint_url.clone().try_into()?,
|
self.mint_url.clone().try_into()?,
|
||||||
|
quote,
|
||||||
proofs,
|
proofs,
|
||||||
invoice,
|
|
||||||
Some(blinded.blinded_messages()),
|
Some(blinded.blinded_messages()),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -327,7 +318,7 @@ impl<C: Client> Wallet<C> {
|
|||||||
|
|
||||||
let melted = Melted {
|
let melted = Melted {
|
||||||
paid: true,
|
paid: true,
|
||||||
preimage: melt_response.preimage,
|
preimage: Some(melt_response.proof),
|
||||||
change: change_proofs,
|
change: change_proofs,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -337,10 +328,10 @@ impl<C: Client> Wallet<C> {
|
|||||||
pub fn proofs_to_token(
|
pub fn proofs_to_token(
|
||||||
&self,
|
&self,
|
||||||
proofs: Proofs,
|
proofs: Proofs,
|
||||||
unit: Option<String>,
|
|
||||||
memo: Option<String>,
|
memo: Option<String>,
|
||||||
|
unit: Option<CurrencyUnit>,
|
||||||
) -> Result<String, Error> {
|
) -> Result<String, Error> {
|
||||||
Ok(Token::new(self.mint_url.clone(), proofs, unit, memo)?.to_string())
|
Ok(Token::new(self.mint_url.clone(), proofs, memo, unit)?.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ pub mod nut09;
|
|||||||
|
|
||||||
#[cfg(feature = "wallet")]
|
#[cfg(feature = "wallet")]
|
||||||
pub use nut00::wallet::{PreMint, PreMintSecrets, Token};
|
pub use nut00::wallet::{PreMint, PreMintSecrets, Token};
|
||||||
pub use nut00::{BlindedMessage, BlindedSignature, Proof};
|
pub use nut00::{BlindedMessage, BlindedSignature, CurrencyUnit, Proof};
|
||||||
pub use nut01::{Keys, KeysResponse, PublicKey, SecretKey};
|
pub use nut01::{Keys, KeysResponse, PublicKey, SecretKey};
|
||||||
pub use nut02::mint::KeySet as MintKeySet;
|
pub use nut02::mint::KeySet as MintKeySet;
|
||||||
pub use nut02::{Id, KeySet, KeySetInfo, KeysetResponse};
|
pub use nut02::{Id, KeySet, KeySetInfo, KeysetResponse};
|
||||||
@@ -21,14 +21,14 @@ pub use nut02::{Id, KeySet, KeySetInfo, KeysetResponse};
|
|||||||
pub use nut03::PreSplit;
|
pub use nut03::PreSplit;
|
||||||
pub use nut03::{RequestMintResponse, SplitRequest, SplitResponse};
|
pub use nut03::{RequestMintResponse, SplitRequest, SplitResponse};
|
||||||
pub use nut04::{MintRequest, PostMintResponse};
|
pub use nut04::{MintRequest, PostMintResponse};
|
||||||
pub use nut05::{CheckFeesRequest, CheckFeesResponse};
|
|
||||||
#[cfg(not(feature = "nut08"))]
|
#[cfg(not(feature = "nut08"))]
|
||||||
pub use nut05::{MeltRequest, MeltResponse};
|
pub use nut05::{MeltBolt11Request, MeltBolt11Response};
|
||||||
|
pub use nut05::{MeltQuoteBolt11Request, MeltQuoteBolt11Response};
|
||||||
#[cfg(feature = "wallet")]
|
#[cfg(feature = "wallet")]
|
||||||
#[cfg(feature = "nut07")]
|
#[cfg(feature = "nut07")]
|
||||||
pub use nut07::{CheckSpendableRequest, CheckSpendableResponse};
|
pub use nut07::{CheckSpendableRequest, CheckSpendableResponse};
|
||||||
#[cfg(feature = "nut08")]
|
#[cfg(feature = "nut08")]
|
||||||
pub use nut08::{MeltRequest, MeltResponse};
|
pub use nut08::{MeltBolt11Request, MeltBolt11Response};
|
||||||
#[cfg(feature = "nut09")]
|
#[cfg(feature = "nut09")]
|
||||||
pub use nut09::MintInfo;
|
pub use nut09::MintInfo;
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
//! Notation and Models
|
//! Notation and Models
|
||||||
// https://github.com/cashubtc/nuts/blob/main/00.md
|
// https://github.com/cashubtc/nuts/blob/main/00.md
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{Id, Proofs, PublicKey};
|
use super::{Id, Proofs, PublicKey};
|
||||||
|
use crate::error::Error;
|
||||||
use crate::secret::Secret;
|
use crate::secret::Secret;
|
||||||
use crate::url::UncheckedUrl;
|
use crate::url::UncheckedUrl;
|
||||||
use crate::Amount;
|
use crate::Amount;
|
||||||
@@ -20,6 +24,33 @@ pub struct BlindedMessage {
|
|||||||
pub keyset_id: Id,
|
pub keyset_id: Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum CurrencyUnit {
|
||||||
|
#[default]
|
||||||
|
Sat,
|
||||||
|
Custom(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for CurrencyUnit {
|
||||||
|
type Err = Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"sat" => Ok(Self::Sat),
|
||||||
|
_ => Ok(Self::Custom(s.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for CurrencyUnit {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
CurrencyUnit::Sat => write!(f, "sat"),
|
||||||
|
CurrencyUnit::Custom(unit) => write!(f, "{}", unit),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "wallet")]
|
#[cfg(feature = "wallet")]
|
||||||
pub mod wallet {
|
pub mod wallet {
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
@@ -31,7 +62,7 @@ pub mod wallet {
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use super::MintProofs;
|
use super::{CurrencyUnit, MintProofs};
|
||||||
use crate::dhke::blind_message;
|
use crate::dhke::blind_message;
|
||||||
use crate::error::wallet;
|
use crate::error::wallet;
|
||||||
use crate::nuts::{BlindedMessage, Id, Proofs, SecretKey};
|
use crate::nuts::{BlindedMessage, Id, Proofs, SecretKey};
|
||||||
@@ -201,8 +232,9 @@ pub mod wallet {
|
|||||||
/// Memo for token
|
/// Memo for token
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub memo: Option<String>,
|
pub memo: Option<String>,
|
||||||
|
/// Token Unit
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub unit: Option<String>,
|
pub unit: Option<CurrencyUnit>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Token {
|
impl Token {
|
||||||
@@ -210,7 +242,7 @@ pub mod wallet {
|
|||||||
mint_url: UncheckedUrl,
|
mint_url: UncheckedUrl,
|
||||||
proofs: Proofs,
|
proofs: Proofs,
|
||||||
memo: Option<String>,
|
memo: Option<String>,
|
||||||
unit: Option<String>,
|
unit: Option<CurrencyUnit>,
|
||||||
) -> Result<Self, wallet::Error> {
|
) -> Result<Self, wallet::Error> {
|
||||||
if proofs.is_empty() {
|
if proofs.is_empty() {
|
||||||
return Err(wallet::Error::ProofsRequired);
|
return Err(wallet::Error::ProofsRequired);
|
||||||
|
|||||||
@@ -3,48 +3,54 @@
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::error::Error;
|
use super::CurrencyUnit;
|
||||||
use crate::nuts::Proofs;
|
use crate::nuts::Proofs;
|
||||||
use crate::{Amount, Bolt11Invoice};
|
use crate::{Amount, Bolt11Invoice};
|
||||||
|
|
||||||
/// Check Fees Response [NUT-05]
|
/// Melt quote request [NUT-05]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct CheckFeesResponse {
|
pub struct MeltQuoteBolt11Request {
|
||||||
/// Expected Mac Fee in satoshis
|
/// Bolt11 invoice to be paid
|
||||||
pub fee: Amount,
|
pub request: Bolt11Invoice,
|
||||||
|
/// Unit wallet would like to pay with
|
||||||
|
pub unit: CurrencyUnit,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check Fees request [NUT-05]
|
/// Melt quote response [NUT-05]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct CheckFeesRequest {
|
pub struct MeltQuoteBolt11Response {
|
||||||
/// Lighting Invoice
|
/// Quote Id
|
||||||
pub pr: Bolt11Invoice,
|
pub quote: String,
|
||||||
|
/// The amount that needs to be provided
|
||||||
|
pub amount: u64,
|
||||||
|
/// The fee reserve that is required
|
||||||
|
pub fee_reserve: u64,
|
||||||
|
/// Whether the the request haas be paid
|
||||||
|
pub paid: bool,
|
||||||
|
/// Unix timestamp until the quote is valid
|
||||||
|
pub expiry: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Melt Request [NUT-05]
|
/// Melt Bolt11 Request [NUT-05]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct MeltRequest {
|
pub struct MeltBolt11Request {
|
||||||
pub proofs: Proofs,
|
/// Quote ID
|
||||||
/// bollt11
|
pub quote: String,
|
||||||
pub pr: Bolt11Invoice,
|
/// Proofs
|
||||||
|
pub inputs: Proofs,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MeltRequest {
|
impl MeltBolt11Request {
|
||||||
pub fn proofs_amount(&self) -> Amount {
|
pub fn proofs_amount(&self) -> Amount {
|
||||||
self.proofs.iter().map(|proof| proof.amount).sum()
|
self.inputs.iter().map(|proof| proof.amount).sum()
|
||||||
}
|
|
||||||
|
|
||||||
pub fn invoice_amount(&self) -> Result<Amount, Error> {
|
|
||||||
match self.pr.amount_milli_satoshis() {
|
|
||||||
Some(value) => Ok(Amount::from_sat(value)),
|
|
||||||
None => Err(Error::InvoiceAmountUndefined),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Melt Response [NUT-05]
|
/// Melt Response [NUT-05]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct MeltResponse {
|
pub struct MeltBolt11Response {
|
||||||
|
/// Indicate if payment was successful
|
||||||
pub paid: bool,
|
pub paid: bool,
|
||||||
pub preimage: Option<String>,
|
/// Bolt11 preimage
|
||||||
|
pub payment_preimage: String,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,51 +1,49 @@
|
|||||||
//! Lightning fee return
|
//! Lightning fee return
|
||||||
// https://github.com/cashubtc/nuts/blob/main/08.md
|
// https://github.com/cashubtc/nuts/blob/main/08.md
|
||||||
|
|
||||||
use lightning_invoice::Bolt11Invoice;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{BlindedMessage, BlindedSignature, Proofs};
|
use super::{BlindedMessage, BlindedSignature, Proofs};
|
||||||
use crate::error::Error;
|
|
||||||
use crate::Amount;
|
use crate::Amount;
|
||||||
|
|
||||||
/// Melt Request [NUT-08]
|
/// Melt Bolt11 Request [NUT-08]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct MeltRequest {
|
pub struct MeltBolt11Request {
|
||||||
pub proofs: Proofs,
|
/// Quote ID
|
||||||
/// bollt11
|
pub quote: String,
|
||||||
pub pr: Bolt11Invoice,
|
/// Proofs
|
||||||
|
pub inputs: Proofs,
|
||||||
/// Blinded Message that can be used to return change [NUT-08]
|
/// Blinded Message that can be used to return change [NUT-08]
|
||||||
/// Amount field of blindedMessages `SHOULD` be set to zero
|
/// Amount field of blindedMessages `SHOULD` be set to zero
|
||||||
pub outputs: Option<Vec<BlindedMessage>>,
|
pub outputs: Option<Vec<BlindedMessage>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MeltRequest {
|
impl MeltBolt11Request {
|
||||||
pub fn proofs_amount(&self) -> Amount {
|
pub fn proofs_amount(&self) -> Amount {
|
||||||
self.proofs.iter().map(|proof| proof.amount).sum()
|
self.inputs.iter().map(|proof| proof.amount).sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn invoice_amount(&self) -> Result<Amount, Error> {
|
pub fn output_amount(&self) -> Option<Amount> {
|
||||||
match self.pr.amount_milli_satoshis() {
|
self.outputs
|
||||||
Some(value) => Ok(Amount::from_msat(value)),
|
.as_ref()
|
||||||
None => Err(Error::InvoiceAmountUndefined),
|
.map(|o| o.iter().map(|proof| proof.amount).sum())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Melt Response [NUT-08]
|
/// Melt Response [NUT-08]
|
||||||
/// Lightning fee return [NUT-08] if change is defined
|
/// Lightning fee return [NUT-08] if change is defined
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct MeltResponse {
|
pub struct MeltBolt11Response {
|
||||||
pub paid: bool,
|
pub paid: bool,
|
||||||
pub preimage: Option<String>,
|
// REVIEW: https://github.com/cashubtc/nuts/pull/55#discussion_r1419991818
|
||||||
|
pub proof: String,
|
||||||
pub change: Option<Vec<BlindedSignature>>,
|
pub change: Option<Vec<BlindedSignature>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MeltResponse {
|
impl MeltBolt11Response {
|
||||||
pub fn change_amount(&self) -> Amount {
|
pub fn change_amount(&self) -> Option<Amount> {
|
||||||
match &self.change {
|
self.change
|
||||||
Some(change) => change.iter().map(|c| c.amount).sum(),
|
.as_ref()
|
||||||
None => Amount::ZERO,
|
.map(|c| c.iter().map(|b| b.amount).sum())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::nuts::{Id, KeySetInfo, Proofs};
|
use crate::nuts::{CurrencyUnit, Proofs};
|
||||||
|
use crate::Bolt11Invoice;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct ProofsStatus {
|
pub struct ProofsStatus {
|
||||||
@@ -32,3 +33,15 @@ pub enum InvoiceStatus {
|
|||||||
Expired,
|
Expired,
|
||||||
InFlight,
|
InFlight,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Quote
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
||||||
|
pub struct Quote {
|
||||||
|
pub id: String,
|
||||||
|
pub amount: u64,
|
||||||
|
pub request: Bolt11Invoice,
|
||||||
|
pub unit: CurrencyUnit,
|
||||||
|
pub fee_reserve: u64,
|
||||||
|
pub paid: bool,
|
||||||
|
pub expiry: u64,
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user