diff --git a/fedimint-clientd/src/main.rs b/fedimint-clientd/src/main.rs index 024c4b3..18d348a 100644 --- a/fedimint-clientd/src/main.rs +++ b/fedimint-clientd/src/main.rs @@ -195,10 +195,11 @@ async fn main() -> Result<()> { /// Lightning network related commands: /// - `/fedimint/v2/ln/invoice`: Create a lightning invoice to receive payment /// via gateway. -/// - `/fedimint/v2/ln/invoice-external-pubkey`: Create a lightning invoice to -/// receive payment via gateway with external pubkey. +/// - `/fedimint/v2/ln/invoice-external-pubkey-tweaked`: Create a lightning +/// invoice to receive payment via gateway with external pubkey. /// - `/fedimint/v2/ln/await-invoice`: Wait for incoming invoice to be paid. -/// - `/fedimint/v2/ln/claim-external-receive`: Claim an external receive. +/// - `/fedimint/v2/ln/claim-external-receive-tweaked`: Claim an external +/// receive. /// - `/fedimint/v2/ln/pay`: Pay a lightning invoice or lnurl via a gateway. /// - `/fedimint/v2/ln/await-pay`: Wait for a lightning payment to complete. /// - `/fedimint/v2/ln/list-gateways`: List registered gateways. @@ -228,10 +229,6 @@ fn fedimint_v2_rest() -> Router { let ln_router = Router::new() .route("/invoice", post(fedimint::ln::invoice::handle_rest)) - .route( - "/invoice-external-pubkey", - post(fedimint::ln::invoice_external_pubkey::handle_rest), - ) .route( "/invoice-external-pubkey-tweaked", post(fedimint::ln::invoice_external_pubkey_tweaked::handle_rest), @@ -240,10 +237,6 @@ fn fedimint_v2_rest() -> Router { "/await-invoice", post(fedimint::ln::await_invoice::handle_rest), ) - .route( - "/claim-external-receive", - post(fedimint::ln::claim_external_receive::handle_rest), - ) .route( "/claim-external-receive-tweaked", post(fedimint::ln::claim_external_receive_tweaked::handle_rest), diff --git a/fedimint-clientd/src/router/handlers/fedimint/admin/mod.rs b/fedimint-clientd/src/router/handlers/fedimint/admin/mod.rs index c10c96d..a0d6dd7 100644 --- a/fedimint-clientd/src/router/handlers/fedimint/admin/mod.rs +++ b/fedimint-clientd/src/router/handlers/fedimint/admin/mod.rs @@ -13,7 +13,7 @@ use fedimint_mint_client::MintClientModule; use fedimint_wallet_client::WalletClientModule; use info::InfoResponse; -pub async fn get_note_summary(client: &ClientHandleArc) -> anyhow::Result { +pub async fn _get_note_summary(client: &ClientHandleArc) -> anyhow::Result { let mint_client = client.get_first_module::(); let wallet_client = client.get_first_module::(); let summary = mint_client diff --git a/fedimint-clientd/src/router/handlers/fedimint/ln/await_invoice.rs b/fedimint-clientd/src/router/handlers/fedimint/ln/await_invoice.rs index e284209..51b9c24 100644 --- a/fedimint-clientd/src/router/handlers/fedimint/ln/await_invoice.rs +++ b/fedimint-clientd/src/router/handlers/fedimint/ln/await_invoice.rs @@ -7,13 +7,11 @@ use fedimint_core::config::FederationId; use fedimint_core::core::OperationId; use fedimint_ln_client::{LightningClientModule, LnReceiveState}; use futures_util::StreamExt; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; -use tracing::info; +use tracing::{debug, error, info}; use crate::error::AppError; -use crate::router::handlers::fedimint::admin::get_note_summary; -use crate::router::handlers::fedimint::admin::info::InfoResponse; use crate::state::AppState; #[derive(Debug, Deserialize)] @@ -23,31 +21,37 @@ pub struct AwaitInvoiceRequest { pub federation_id: FederationId, } +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct AwaitInvoiceResponse { + pub status: LnReceiveState, +} + async fn _await_invoice( client: ClientHandleArc, req: AwaitInvoiceRequest, -) -> Result { +) -> Result { let lightning_module = &client.get_first_module::(); let mut updates = lightning_module .subscribe_ln_receive(req.operation_id) .await? .into_stream(); + info!( + "Created await invoice stream for operation id: {}", + req.operation_id + ); while let Some(update) = updates.next().await { - info!("Update: {update:?}"); - match update { + debug!("Update: {update:?}"); + match &update { LnReceiveState::Claimed => { - return Ok(get_note_summary(&client).await?); + return Ok(AwaitInvoiceResponse { status: update }); } LnReceiveState::Canceled { reason } => { - return Err(AppError::new( - StatusCode::INTERNAL_SERVER_ERROR, - anyhow!(reason), - )) + error!("Invoice canceled: {}", reason); + return Ok(AwaitInvoiceResponse { status: update }); } _ => {} } - - info!("Update: {update:?}"); } Err(AppError::new( @@ -60,17 +64,16 @@ pub async fn handle_ws(state: AppState, v: Value) -> Result { let v = serde_json::from_value::(v) .map_err(|e| AppError::new(StatusCode::BAD_REQUEST, anyhow!("Invalid request: {}", e)))?; let client = state.get_client(v.federation_id).await?; - let invoice = _await_invoice(client, v).await?; - let invoice_json = json!(invoice); - Ok(invoice_json) + let invoice_response = _await_invoice(client, v).await?; + Ok(json!(invoice_response)) } #[axum_macros::debug_handler] pub async fn handle_rest( State(state): State, Json(req): Json, -) -> Result, AppError> { +) -> Result, AppError> { let client = state.get_client(req.federation_id).await?; - let invoice = _await_invoice(client, req).await?; - Ok(Json(invoice)) + let invoice_response = _await_invoice(client, req).await?; + Ok(Json(invoice_response)) } diff --git a/fedimint-clientd/src/router/handlers/fedimint/ln/claim_external_receive.rs b/fedimint-clientd/src/router/handlers/fedimint/ln/claim_external_receive.rs deleted file mode 100644 index 18e0417..0000000 --- a/fedimint-clientd/src/router/handlers/fedimint/ln/claim_external_receive.rs +++ /dev/null @@ -1,81 +0,0 @@ -use anyhow::anyhow; -use axum::extract::State; -use axum::http::StatusCode; -use axum::Json; -use bitcoin::secp256k1::{Secp256k1, SecretKey}; -use bitcoin::util::key::KeyPair; -use fedimint_client::ClientHandleArc; -use fedimint_core::config::FederationId; -use fedimint_ln_client::{LightningClientModule, LnReceiveState}; -use futures_util::StreamExt; -use serde::Deserialize; -use serde_json::{json, Value}; -use tracing::info; - -use crate::error::AppError; -use crate::router::handlers::fedimint::admin::get_note_summary; -use crate::router::handlers::fedimint::admin::info::InfoResponse; -use crate::state::AppState; - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ClaimExternalReceiveRequest { - pub private_key: SecretKey, - pub federation_id: FederationId, -} - -async fn _await_claim_external_receive( - client: ClientHandleArc, - req: ClaimExternalReceiveRequest, -) -> Result { - let secp = Secp256k1::new(); - let key_pair = KeyPair::from_secret_key(&secp, &req.private_key); - let lightning_module = &client.get_first_module::(); - let operation_id = lightning_module.scan_receive_for_user(key_pair, ()).await?; - let mut updates = lightning_module - .subscribe_ln_claim(operation_id) - .await? - .into_stream(); - - while let Some(update) = updates.next().await { - info!("Update: {update:?}"); - match update { - LnReceiveState::Claimed => { - return Ok(get_note_summary(&client).await?); - } - LnReceiveState::Canceled { reason } => { - return Err(AppError::new( - StatusCode::INTERNAL_SERVER_ERROR, - anyhow!(reason), - )) - } - _ => {} - } - - info!("Update: {update:?}"); - } - - Err(AppError::new( - StatusCode::INTERNAL_SERVER_ERROR, - anyhow!("Unexpected end of stream"), - )) -} - -pub async fn handle_ws(state: AppState, v: Value) -> Result { - let v = serde_json::from_value::(v) - .map_err(|e| AppError::new(StatusCode::BAD_REQUEST, anyhow!("Invalid request: {}", e)))?; - let client = state.get_client(v.federation_id).await?; - let invoice = _await_claim_external_receive(client, v).await?; - let invoice_json = json!(invoice); - Ok(invoice_json) -} - -#[axum_macros::debug_handler] -pub async fn handle_rest( - State(state): State, - Json(req): Json, -) -> Result, AppError> { - let client = state.get_client(req.federation_id).await?; - let invoice = _await_claim_external_receive(client, req).await?; - Ok(Json(invoice)) -} diff --git a/fedimint-clientd/src/router/handlers/fedimint/ln/claim_external_receive_tweaked.rs b/fedimint-clientd/src/router/handlers/fedimint/ln/claim_external_receive_tweaked.rs index 4affc3a..e4e00f1 100644 --- a/fedimint-clientd/src/router/handlers/fedimint/ln/claim_external_receive_tweaked.rs +++ b/fedimint-clientd/src/router/handlers/fedimint/ln/claim_external_receive_tweaked.rs @@ -8,13 +8,11 @@ use fedimint_client::ClientHandleArc; use fedimint_core::config::FederationId; use fedimint_ln_client::{LightningClientModule, LnReceiveState}; use futures_util::StreamExt; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; -use tracing::info; +use tracing::{debug, error, info}; use crate::error::AppError; -use crate::router::handlers::fedimint::admin::get_note_summary; -use crate::router::handlers::fedimint::admin::info::InfoResponse; use crate::state::AppState; #[derive(Debug, Deserialize)] @@ -25,10 +23,16 @@ pub struct ClaimExternalReceiveTweakedRequest { pub federation_id: FederationId, } +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct ClaimExternalReceiveTweakedResponse { + pub status: LnReceiveState, +} + async fn _await_claim_external_receive_tweaked( client: ClientHandleArc, req: ClaimExternalReceiveTweakedRequest, -) -> Result { +) -> Result { let secp = Secp256k1::new(); let key_pair = KeyPair::from_secret_key(&secp, &req.private_key); let lightning_module = &client.get_first_module::(); @@ -36,33 +40,34 @@ async fn _await_claim_external_receive_tweaked( .scan_receive_for_user_tweaked(key_pair, req.tweaks, ()) .await; - let mut final_response = get_note_summary(&client).await?; for operation_id in operation_id { let mut updates = lightning_module .subscribe_ln_claim(operation_id) .await? .into_stream(); - + info!( + "Created claim external receive tweaked stream for operation id: {}", + operation_id + ); while let Some(update) = updates.next().await { - info!("Update: {update:?}"); - match update { + debug!("Update: {update:?}"); + match &update { LnReceiveState::Claimed => { - final_response = get_note_summary(&client).await?; + return Ok(ClaimExternalReceiveTweakedResponse { status: update }); } LnReceiveState::Canceled { reason } => { - return Err(AppError::new( - StatusCode::INTERNAL_SERVER_ERROR, - anyhow!(reason), - )) + error!("Claim canceled: {}", reason); + return Ok(ClaimExternalReceiveTweakedResponse { status: update }); } _ => {} } - - info!("Update: {update:?}"); } } - Ok(final_response) + Err(AppError::new( + StatusCode::INTERNAL_SERVER_ERROR, + anyhow!("Unexpected end of stream"), + )) } pub async fn handle_ws(state: AppState, v: Value) -> Result { @@ -78,8 +83,8 @@ pub async fn handle_ws(state: AppState, v: Value) -> Result { pub async fn handle_rest( State(state): State, Json(req): Json, -) -> Result, AppError> { +) -> Result, AppError> { let client = state.get_client(req.federation_id).await?; - let invoice = _await_claim_external_receive_tweaked(client, req).await?; - Ok(Json(invoice)) + let invoice_response = _await_claim_external_receive_tweaked(client, req).await?; + Ok(Json(invoice_response)) } diff --git a/fedimint-clientd/src/router/handlers/fedimint/ln/invoice_external_pubkey.rs b/fedimint-clientd/src/router/handlers/fedimint/ln/invoice_external_pubkey.rs deleted file mode 100644 index eaa7dc3..0000000 --- a/fedimint-clientd/src/router/handlers/fedimint/ln/invoice_external_pubkey.rs +++ /dev/null @@ -1,86 +0,0 @@ -use anyhow::anyhow; -use axum::extract::State; -use axum::http::StatusCode; -use axum::Json; -use bitcoin::secp256k1::PublicKey; -use fedimint_client::ClientHandleArc; -use fedimint_core::config::FederationId; -use fedimint_core::core::OperationId; -use fedimint_core::Amount; -use fedimint_ln_client::LightningClientModule; -use lightning_invoice::{Bolt11InvoiceDescription, Description}; -use serde::{Deserialize, Serialize}; -use serde_json::{json, Value}; -use tracing::error; - -use crate::error::AppError; -use crate::state::AppState; - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct LnInvoiceExternalPubkeyRequest { - pub amount_msat: Amount, - pub description: String, - pub expiry_time: Option, - pub external_pubkey: PublicKey, - pub gateway_id: PublicKey, - pub federation_id: FederationId, -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct LnInvoiceExternalPubkeyResponse { - pub operation_id: OperationId, - pub invoice: String, -} - -async fn _invoice( - client: ClientHandleArc, - req: LnInvoiceExternalPubkeyRequest, -) -> Result { - let lightning_module = client.get_first_module::(); - let gateway = lightning_module - .select_gateway(&req.gateway_id) - .await - .ok_or_else(|| { - error!("Failed to select gateway: {}", req.gateway_id); - AppError::new( - StatusCode::INTERNAL_SERVER_ERROR, - anyhow!("Failed to select gateway"), - ) - })?; - - let (operation_id, invoice, _) = lightning_module - .create_bolt11_invoice_for_user( - req.amount_msat, - Bolt11InvoiceDescription::Direct(&Description::new(req.description)?), - req.expiry_time, - req.external_pubkey.clone(), - (), - Some(gateway), - ) - .await?; - Ok(LnInvoiceExternalPubkeyResponse { - operation_id, - invoice: invoice.to_string(), - }) -} - -pub async fn handle_ws(state: AppState, v: Value) -> Result { - let v = serde_json::from_value::(v) - .map_err(|e| AppError::new(StatusCode::BAD_REQUEST, anyhow!("Invalid request: {}", e)))?; - let client = state.get_client(v.federation_id).await?; - let invoice = _invoice(client, v).await?; - let invoice_json = json!(invoice); - Ok(invoice_json) -} - -#[axum_macros::debug_handler] -pub async fn handle_rest( - State(state): State, - Json(req): Json, -) -> Result, AppError> { - let client = state.get_client(req.federation_id).await?; - let invoice = _invoice(client, req).await?; - Ok(Json(invoice)) -} diff --git a/fedimint-clientd/src/router/handlers/fedimint/ln/mod.rs b/fedimint-clientd/src/router/handlers/fedimint/ln/mod.rs index 41ccb05..4c36030 100644 --- a/fedimint-clientd/src/router/handlers/fedimint/ln/mod.rs +++ b/fedimint-clientd/src/router/handlers/fedimint/ln/mod.rs @@ -11,10 +11,8 @@ use tracing::{debug, info}; use self::pay::{LnPayRequest, LnPayResponse}; pub mod await_invoice; -pub mod claim_external_receive; pub mod claim_external_receive_tweaked; pub mod invoice; -pub mod invoice_external_pubkey; pub mod invoice_external_pubkey_tweaked; pub mod list_gateways; pub mod pay; diff --git a/fedimint-clientd/src/router/ws.rs b/fedimint-clientd/src/router/ws.rs index 334623e..c972a2c 100644 --- a/fedimint-clientd/src/router/ws.rs +++ b/fedimint-clientd/src/router/ws.rs @@ -67,10 +67,8 @@ pub enum JsonRpcMethod { MintSplit, MintCombine, LnInvoice, - LnInvoiceExternalPubkey, LnInvoiceExternalPubkeyTweaked, LnAwaitInvoice, - LnClaimExternalReceive, LnClaimExternalReceiveTweaked, LnPay, LnListGateways, @@ -213,10 +211,6 @@ async fn match_method(req: JsonRpcRequest, state: AppState) -> Result { handlers::fedimint::ln::invoice::handle_ws(state.clone(), req.params).await } - JsonRpcMethod::LnInvoiceExternalPubkey => { - handlers::fedimint::ln::invoice_external_pubkey::handle_ws(state.clone(), req.params) - .await - } JsonRpcMethod::LnInvoiceExternalPubkeyTweaked => { handlers::fedimint::ln::invoice_external_pubkey_tweaked::handle_ws( state.clone(), @@ -227,10 +221,6 @@ async fn match_method(req: JsonRpcRequest, state: AppState) -> Result { handlers::fedimint::ln::await_invoice::handle_ws(state.clone(), req.params).await } - JsonRpcMethod::LnClaimExternalReceive => { - handlers::fedimint::ln::claim_external_receive::handle_ws(state.clone(), req.params) - .await - } JsonRpcMethod::LnClaimExternalReceiveTweaked => { handlers::fedimint::ln::claim_external_receive_tweaked::handle_ws( state.clone(), diff --git a/wrappers/fedimint-go/pkg/fedimint/client.go b/wrappers/fedimint-go/pkg/fedimint/client.go index 8c3a1fc..13d1f79 100644 --- a/wrappers/fedimint-go/pkg/fedimint/client.go +++ b/wrappers/fedimint-go/pkg/fedimint/client.go @@ -522,46 +522,32 @@ func (ln *LnModule) CreateInvoiceForPubkeyTweak(pubkey string, tweak uint64, amo return &invoiceResp, nil } -func (ln *LnModule) ClaimPubkeyReceive(privateKey string, gatewayId string, federationId *string) (*types.InfoResponse, error) { - request := modules.LnClaimPubkeyReceiveRequest{PrivateKey: privateKey} - resp, err := ln.Client.postWithGatewayIdAndFederationId("/ln/claim-external-receive", request, &gatewayId, federationId) - if err != nil { - return nil, err - } - var infoResp types.InfoResponse - err = json.Unmarshal(resp, &infoResp) - if err != nil { - return nil, err - } - return &infoResp, nil -} - -func (ln *LnModule) ClaimPubkeyTweakReceive(privateKey string, tweaks []uint64, gatewayId *string, federationId *string) (*types.InfoResponse, error) { +func (ln *LnModule) ClaimPubkeyTweakReceive(privateKey string, tweaks []uint64, gatewayId *string, federationId *string) (*modules.LnPaymentResponse, error) { request := modules.LnClaimPubkeyTweakedRequest{PrivateKey: privateKey, Tweaks: tweaks} resp, err := ln.Client.postWithGatewayIdAndFederationId("/ln/claim-external-receive-tweaked", request, gatewayId, federationId) if err != nil { return nil, err } - var infoResp types.InfoResponse - err = json.Unmarshal(resp, &infoResp) + var paymentResp modules.LnPaymentResponse + err = json.Unmarshal(resp, &paymentResp) if err != nil { return nil, err } - return &infoResp, nil + return &paymentResp, nil } -func (ln *LnModule) AwaitInvoice(operationId string, gatewayId string, federationId *string) (*types.InfoResponse, error) { +func (ln *LnModule) AwaitInvoice(operationId string, gatewayId string, federationId *string) (*modules.LnPaymentResponse, error) { request := modules.LnAwaitInvoiceRequest{OperationId: operationId} resp, err := ln.Client.postWithGatewayIdAndFederationId("/ln/await-invoice", request, &gatewayId, federationId) if err != nil { return nil, err } - var infoResp types.InfoResponse - err = json.Unmarshal(resp, &infoResp) + var paymentResp modules.LnPaymentResponse + err = json.Unmarshal(resp, &paymentResp) if err != nil { return nil, err } - return &infoResp, nil + return &paymentResp, nil } func (ln *LnModule) Pay(paymentInfo string, gatewayId *string, amountMsat *uint64, lnurlComment *string, federationId *string) (*modules.LnPayResponse, error) { diff --git a/wrappers/fedimint-go/pkg/fedimint/types/modules/ln.go b/wrappers/fedimint-go/pkg/fedimint/types/modules/ln.go index 1ecebda..33559cd 100644 --- a/wrappers/fedimint-go/pkg/fedimint/types/modules/ln.go +++ b/wrappers/fedimint-go/pkg/fedimint/types/modules/ln.go @@ -1,5 +1,10 @@ package modules +import ( + "encoding/json" + "errors" +) + type LnInvoiceRequest struct { AmountMsat uint64 `json:"amountMsat"` Description string `json:"description"` @@ -91,3 +96,42 @@ type Gateway struct { } type ListGatewaysResponse map[string][]Gateway + +type LnReceiveState interface { + isLnReceiveState() +} + +type Claimed struct{} + +func (Claimed) isLnReceiveState() {} + +type Canceled struct { + Reason string `json:"reason"` +} + +func (Canceled) isLnReceiveState() {} + +type LnPaymentResponse struct { + Status LnReceiveState `json:"status"` +} + +func (r *LnPaymentResponse) UnmarshalJSON(data []byte) error { + aux := struct { + Status string `json:"status"` + Reason string `json:"reason,omitempty"` + }{} + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + + switch aux.Status { + case "claimed": + r.Status = Claimed{} + case "canceled": + r.Status = Canceled{Reason: aux.Reason} + default: + return errors.New("unknown status") + } + + return nil +} diff --git a/wrappers/fedimint-py/AsyncFedimintClient.py b/wrappers/fedimint-py/AsyncFedimintClient.py index bd08e22..2a6883d 100644 --- a/wrappers/fedimint-py/AsyncFedimintClient.py +++ b/wrappers/fedimint-py/AsyncFedimintClient.py @@ -23,6 +23,7 @@ LightningPayRequest, LightningPayResponse, LightningAwaitPayRequest, + LightningPaymentResponse, ) from models.onchain import ( @@ -255,7 +256,7 @@ async def claim_pubkey_tweak_receives( private_key: str, tweaks: List[int], federation_id: str = None, - ) -> InfoResponse: + ) -> LightningPaymentResponse: request: LightningClaimPubkeReceivesRequest = { "privateKey": private_key, "tweaks": tweaks, @@ -269,7 +270,7 @@ async def claim_pubkey_tweak_receives( async def await_invoice( self, operation_id: str, federation_id: str = None - ) -> InfoResponse: + ) -> LightningPaymentResponse: request: LightningAwaitInvoiceRequest = {"operationId": operation_id} return await self.client._post_with_gateway_id_and_federation_id( "/ln/await-invoice", request, federation_id=federation_id diff --git a/wrappers/fedimint-py/FedimintClient.py b/wrappers/fedimint-py/FedimintClient.py index 07b4c57..9c0c520 100644 --- a/wrappers/fedimint-py/FedimintClient.py +++ b/wrappers/fedimint-py/FedimintClient.py @@ -20,6 +20,7 @@ LightningInvoiceForPubkeyTweakResponse, LightningPayRequest, LightningPayResponse, + LightningPaymentResponse, ) from models.onchain import ( @@ -201,7 +202,7 @@ def create_invoice( def await_invoice( self, operation_id: str, federation_id: str = None - ) -> InfoResponse: + ) -> LightningPaymentResponse: request: LightningAwaitInvoiceRequest = {"operationId": operation_id} return self.client._post_with_federation_id( "/ln/await-invoice", request, federation_id @@ -237,7 +238,7 @@ def claim_pubkey_tweak_receives( private_key: str, tweaks: List[int], federation_id: str = None, - ) -> InfoResponse: + ) -> LightningPaymentResponse: request: LightningClaimPubkeReceivesRequest = { "privateKey": private_key, "tweaks": tweaks, diff --git a/wrappers/fedimint-py/models/lightning.py b/wrappers/fedimint-py/models/lightning.py index b291d52..fa5966d 100644 --- a/wrappers/fedimint-py/models/lightning.py +++ b/wrappers/fedimint-py/models/lightning.py @@ -1,5 +1,6 @@ from pydantic import BaseModel -from typing import Any, List, Optional +from typing import Any, List, Optional, Union +from enum import Enum class LightningCreateInvoiceRequest(BaseModel): @@ -52,6 +53,29 @@ class LightningAwaitPayRequest(BaseModel): operationId: str +class LnReceiveState(Enum): + Created = "Created" + WaitingForPayment = "WaitingForPayment" + Canceled = "Canceled" + Funded = "Funded" + AwaitingFunds = "AwaitingFunds" + Claimed = "Claimed" + + +class WaitingForPayment(BaseModel): + invoice: str + timeout: int + + +class Canceled(BaseModel): + reason: str + + +class LightningPaymentResponse(BaseModel): + state: LnReceiveState + details: Optional[Union[WaitingForPayment, Canceled]] = None + + class GatewayFees(BaseModel): baseMsat: int proportionalMillionths: int diff --git a/wrappers/fedimint-ts/src/FedimintClient.ts b/wrappers/fedimint-ts/src/FedimintClient.ts index 43ea1ec..7a9606d 100644 --- a/wrappers/fedimint-ts/src/FedimintClient.ts +++ b/wrappers/fedimint-ts/src/FedimintClient.ts @@ -38,6 +38,7 @@ import { LightningInvoiceResponse, LightningInvoiceExternalPubkeyTweakedResponse, LightningPayResponse, + LightningPaymentResponse, } from "./types"; /** @@ -439,8 +440,8 @@ export class FedimintClient { claimPubkeyTweakReceives: async ( request: LightningClaimPubkeyTweakReceivesRequest, federationId: string - ): Promise => { - return await this.postWithFederationId( + ): Promise => { + return await this.postWithFederationId( "/ln/claim-external-receive-tweaked", request, federationId @@ -455,10 +456,10 @@ export class FedimintClient { awaitInvoice: async ( operationId: string, federationId?: string - ): Promise => { + ): Promise => { const request: LightningAwaitInvoiceRequest = { operationId }; - return await this.postWithFederationId( + return await this.postWithFederationId( "/ln/await-invoice", request, federationId diff --git a/wrappers/fedimint-ts/src/types.ts b/wrappers/fedimint-ts/src/types.ts index 2b1fa2c..2961b51 100644 --- a/wrappers/fedimint-ts/src/types.ts +++ b/wrappers/fedimint-ts/src/types.ts @@ -154,6 +154,32 @@ export interface LightningAwaitInvoiceRequest { operationId: string; } +export enum LnReceiveState { + Created, + WaitingForPayment, + Canceled, + Funded, + AwaitingFunds, + Claimed, +} + +export interface WaitingForPayment { + invoice: string; + timeout: number; +} + +export interface Canceled { + reason: string; +} + +export type LightningPaymentResponse = + | { state: LnReceiveState.Created } + | { state: LnReceiveState.WaitingForPayment; details: WaitingForPayment } + | { state: LnReceiveState.Canceled; details: Canceled } + | { state: LnReceiveState.Funded } + | { state: LnReceiveState.AwaitingFunds } + | { state: LnReceiveState.Claimed }; + export interface LightningPayRequest { paymentInfo: string; amountMsat?: number; diff --git a/wrappers/fedimint-ts/tests/test.ts b/wrappers/fedimint-ts/tests/test.ts index 7754253..ad60439 100644 --- a/wrappers/fedimint-ts/tests/test.ts +++ b/wrappers/fedimint-ts/tests/test.ts @@ -43,7 +43,8 @@ const newKeyPair = (): KeyPair => { }; async function buildTestClient() { - const baseUrl = process.env.FEDIMINT_CLIENTD_BASE_URL || "127.0.0.1:3333"; + const baseUrl = + process.env.FEDIMINT_CLIENTD_BASE_URL || "http://127.0.0.1:3333"; const password = process.env.FEDIMINT_CLIENTD_PASSWORD || "password"; const activeFederationId = process.env.FEDIMINT_CLIENTD_ACTIVE_FEDERATION_ID || @@ -55,7 +56,14 @@ async function buildTestClient() { .setActiveFederationId(activeFederationId); const client = await builder.build(); - + console.log( + "Created client. Base url: ", + baseUrl, + ", password: ", + password, + "Active federation id: ", + client.getActiveFederationId() + ); await client.useDefaultGateway(); console.log("Default gateway id: ", client.getActiveGatewayId());