Skip to content

Commit

Permalink
Add WebLN::make_invoice
Browse files Browse the repository at this point in the history
  • Loading branch information
yukibtc committed Jan 19, 2024
1 parent 27ba8ad commit 6defdc8
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 5 deletions.
16 changes: 15 additions & 1 deletion webln-js/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ use webln::WebLN;
pub mod error;
pub mod get_info;
pub mod keysend;
pub mod request_invoice;
pub mod send_payment;

use self::error::{into_err, Result};
use self::get_info::JsGetInfoResponse;
use self::keysend::JsKeysendArgs;
use self::request_invoice::{JsRequestInvoiceArgs, JsRequestInvoiceResponse};
use self::send_payment::JsSendPaymentResponse;

#[wasm_bindgen(start)]
Expand Down Expand Up @@ -72,7 +74,19 @@ impl JsWebLN {
.into())
}

// TODO: add `make_invoice`
/// Request that the user creates an invoice to be used by the web app
#[wasm_bindgen(js_name = makeInvoice)]
pub async fn make_invoice(
&self,
args: &JsRequestInvoiceArgs,
) -> Result<JsRequestInvoiceResponse> {
Ok(self
.inner
.make_invoice(args.deref())
.await
.map_err(into_err)?
.into())
}

/// Request that the user sends a payment for an invoice.
#[wasm_bindgen(js_name = sendPayment)]
Expand Down
79 changes: 79 additions & 0 deletions webln-js/src/request_invoice.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (c) 2024 Yuki Kishimoto
// Distributed under the MIT software license

use std::ops::Deref;

use wasm_bindgen::prelude::*;
use webln::{RequestInvoiceArgs, RequestInvoiceResponse};

#[wasm_bindgen(js_name = RequestInvoiceArgs)]
pub struct JsRequestInvoiceArgs {
inner: RequestInvoiceArgs,
}

impl Deref for JsRequestInvoiceArgs {
type Target = RequestInvoiceArgs;

fn deref(&self) -> &Self::Target {
&self.inner
}
}

impl From<RequestInvoiceArgs> for JsRequestInvoiceArgs {
fn from(inner: RequestInvoiceArgs) -> Self {
Self { inner }
}
}

#[wasm_bindgen(js_class = RequestInvoiceArgs)]
impl JsRequestInvoiceArgs {
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Self {
inner: RequestInvoiceArgs::default(),
}
}

pub fn amount(self, amount: u32) -> Self {
self.inner.amount(amount as u64).into()
}

#[wasm_bindgen(js_name = defaultAmount)]
pub fn default_amount(self, default_amount: u32) -> Self {
self.inner.default_amount(default_amount as u64).into()
}

#[wasm_bindgen(js_name = minimumAmount)]
pub fn minimum_amount(self, minimum_amount: u32) -> Self {
self.inner.minimum_amount(minimum_amount as u64).into()
}

#[wasm_bindgen(js_name = maximumAmount)]
pub fn maximum_amount(self, maximum_amount: u32) -> Self {
self.inner.maximum_amount(maximum_amount as u64).into()
}

#[wasm_bindgen(js_name = defaultMemo)]
pub fn default_memo(self, default_memo: String) -> Self {
self.inner.default_memo(default_memo).into()
}
}

#[wasm_bindgen(js_name = RequestInvoiceResponse)]
pub struct JsRequestInvoiceResponse {
inner: RequestInvoiceResponse,
}

impl From<RequestInvoiceResponse> for JsRequestInvoiceResponse {
fn from(inner: RequestInvoiceResponse) -> Self {
Self { inner }
}
}

#[wasm_bindgen(js_class = RequestInvoiceResponse)]
impl JsRequestInvoiceResponse {
#[wasm_bindgen(getter)]
pub fn invoice(&self) -> String {
self.inner.invoice.clone()
}
}
128 changes: 124 additions & 4 deletions webln/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub const IS_ENABLED: &str = "isEnabled";
pub const ENABLE: &str = "enable";
pub const GET_INFO: &str = "getInfo";
pub const KEYSEND: &str = "keysend";
// pub const MAKE_INVOICE: &str = "makeInvoice";
pub const MAKE_INVOICE: &str = "makeInvoice";
pub const SEND_PAYMENT: &str = "sendPayment";
pub const SEND_PAYMENT_ASYNC: &str = "sendPaymentAsync";

Expand Down Expand Up @@ -92,7 +92,7 @@ where
ENABLE => Self::Enable,
GET_INFO => Self::GetInfo,
KEYSEND => Self::Keysend,
"makeInvoice" => Self::MakeInvoice,
MAKE_INVOICE => Self::MakeInvoice,
SEND_PAYMENT => Self::SendPayment,
SEND_PAYMENT_ASYNC => Self::SendPaymentAsync,
"signMessage" => Self::SignMessage,
Expand All @@ -114,7 +114,7 @@ impl fmt::Display for GetInfoMethod {
Self::Enable => write!(f, "{ENABLE}"),
Self::GetInfo => write!(f, "{GET_INFO}"),
Self::Keysend => write!(f, "{KEYSEND}"),
Self::MakeInvoice => write!(f, "makeInvoice"),
Self::MakeInvoice => write!(f, "{MAKE_INVOICE}"),
Self::SendPayment => write!(f, "{SEND_PAYMENT}"),
Self::SendPaymentAsync => write!(f, "{SEND_PAYMENT_ASYNC}"),
Self::SignMessage => write!(f, "signMessage"),
Expand Down Expand Up @@ -152,6 +152,104 @@ pub struct SendPaymentResponse {
pub preimage: String,
}

/// Request invoice args
///
/// **All amounts are denominated in SAT.**
#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RequestInvoiceArgs {
pub amount: Option<u64>,
pub default_amount: Option<u64>,
pub minimum_amount: Option<u64>,
pub maximum_amount: Option<u64>,
pub default_memo: Option<String>,
}

impl RequestInvoiceArgs {
pub fn new() -> Self {
Self::default()
}

pub fn amount(mut self, amount: u64) -> Self {
self.amount = Some(amount);
self
}

pub fn default_amount(mut self, default_amount: u64) -> Self {
self.default_amount = Some(default_amount);
self
}

pub fn minimum_amount(mut self, minimum_amount: u64) -> Self {
self.minimum_amount = Some(minimum_amount);
self
}

pub fn maximum_amount(mut self, maximum_amount: u64) -> Self {
self.maximum_amount = Some(maximum_amount);
self
}

pub fn default_memo(mut self, default_memo: String) -> Self {
self.default_memo = Some(default_memo);
self
}
}

impl TryFrom<&RequestInvoiceArgs> for Object {
type Error = Error;

fn try_from(args: &RequestInvoiceArgs) -> Result<Self, Self::Error> {
let obj = Self::new();

if let Some(amount) = args.amount {
Reflect::set(
&obj,
&JsValue::from_str("amount"),
&amount.to_string().into(),
)?;
}

if let Some(default_amount) = args.default_amount {
Reflect::set(
&obj,
&JsValue::from_str("defaultAmount"),
&default_amount.to_string().into(),
)?;
}

if let Some(minimum_amount) = args.minimum_amount {
Reflect::set(
&obj,
&JsValue::from_str("minimumAmount"),
&minimum_amount.to_string().into(),
)?;
}

if let Some(maximum_amount) = args.maximum_amount {
Reflect::set(
&obj,
&JsValue::from_str("maximumAmount"),
&maximum_amount.to_string().into(),
)?;
}

if let Some(default_memo) = &args.default_memo {
Reflect::set(
&obj,
&JsValue::from_str("defaultMemo"),
&default_memo.into(),
)?;
}

Ok(obj)
}
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RequestInvoiceResponse {
pub invoice: String,
}

/// WebLN instance
#[derive(Debug, Clone)]
pub struct WebLN {
Expand Down Expand Up @@ -268,7 +366,29 @@ impl WebLN {
})
}

// TODO: add `make_invoice`
/// Request that the user creates an invoice to be used by the web app
pub async fn make_invoice(
&self,
args: &RequestInvoiceArgs,
) -> Result<RequestInvoiceResponse, Error> {
let func: Function = self.get_func(&self.webln_obj, MAKE_INVOICE)?;

let request_invoice_obj: Object = args.try_into()?;

let promise: Promise =
Promise::resolve(&func.call1(&self.webln_obj, &request_invoice_obj.into())?);
let result: JsValue = JsFuture::from(promise).await?;
let request_invoice_response_obj: Object = result.dyn_into()?;

Ok(RequestInvoiceResponse {
invoice: self
.get_value_by_key(&request_invoice_response_obj, "paymentRequest")?
.as_string()
.ok_or_else(|| {
Error::TypeMismatch(String::from("expected a string [paymentRequest]"))
})?,
})
}

/// Request that the user sends a payment for an invoice.
pub async fn send_payment(&self, invoice: String) -> Result<SendPaymentResponse, Error> {
Expand Down

0 comments on commit 6defdc8

Please sign in to comment.