Skip to content

Commit

Permalink
Merge pull request #29 from MutinyWallet/hookup-db
Browse files Browse the repository at this point in the history
Hookup database to tx items
  • Loading branch information
TonyGiorgio authored May 16, 2024
2 parents 8e65060 + c7f8bfe commit 00960a1
Show file tree
Hide file tree
Showing 13 changed files with 571 additions and 58 deletions.
4 changes: 2 additions & 2 deletions migrations/2024-05-13-234832_create_config/up.sql
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ CREATE TABLE on_chain_receives
operation_id TEXT PRIMARY KEY NOT NULL,
fedimint_id TEXT NOT NULL REFERENCES fedimint (id),
address TEXT NOT NULL,
amount_sats BIGINT NOT NULL,
fee_sats BIGINT NOT NULL,
amount_sats BIGINT,
fee_sats BIGINT,
txid TEXT,
status INTEGER NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
Expand Down
3 changes: 3 additions & 0 deletions src/bridge.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::components::TransactionItem;
use bitcoin::{Address, Txid};
use fedimint_core::api::InviteCode;
use fedimint_core::Amount;
Expand Down Expand Up @@ -37,6 +38,8 @@ pub enum CoreUIMsg {
ReceiveSuccess(ReceiveSuccessMsg),
ReceiveFailed(String),
BalanceUpdated(Amount),
// todo probably want a way to incrementally add items to the history
TransactionHistoryUpdated(Vec<TransactionItem>),
AddFederationFailed(String),
AddFederationSuccess,
Unlocking,
Expand Down
8 changes: 4 additions & 4 deletions src/components/transaction_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ pub enum TransactionDirection {

#[derive(Debug, Clone, Copy)]
pub struct TransactionItem {
kind: TransactionItemKind,
amount: u64,
direction: TransactionDirection,
timestamp: u64,
pub kind: TransactionItemKind,
pub amount: u64,
pub direction: TransactionDirection,
pub timestamp: u64,
}

impl TransactionItem {
Expand Down
109 changes: 92 additions & 17 deletions src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use fedimint_core::api::InviteCode;
use fedimint_core::config::FederationId;
use fedimint_core::Amount;
use fedimint_ln_client::{LightningClientModule, PayType};
use fedimint_ln_common::config::FeeToAmount;
use fedimint_ln_common::lightning_invoice::{Bolt11Invoice, Bolt11InvoiceDescription, Description};
use fedimint_wallet_client::WalletClientModule;
use std::collections::HashMap;
Expand Down Expand Up @@ -42,7 +43,6 @@ use crate::{
const PEG_IN_TIMEOUT_YEAR: Duration = Duration::from_secs(86400 * 365);

struct HarborCore {
balance: Amount,
network: Network,
mnemonic: Mnemonic,
tx: Sender<Message>,
Expand All @@ -62,7 +62,16 @@ impl HarborCore {

// Sends updates to the UI to refelect the initial state
async fn init_ui_state(&self) {
self.msg(CoreUIMsg::BalanceUpdated(self.balance)).await;
let mut balance = Amount::ZERO;
for client in self.clients.read().await.values() {
balance += client.fedimint_client.get_balance().await;
}

self.msg(CoreUIMsg::BalanceUpdated(balance)).await;

let history = self.storage.get_transaction_history().unwrap();
self.msg(CoreUIMsg::TransactionHistoryUpdated(history))
.await;
}

// todo for now just use the first client, but eventually we'll want to have a way to select a client
Expand All @@ -71,6 +80,11 @@ impl HarborCore {
}

async fn send_lightning(&self, invoice: Bolt11Invoice) -> anyhow::Result<()> {
if invoice.amount_milli_satoshis().is_none() {
return Err(anyhow!("Invoice must have an amount"));
}
let amount = Amount::from_msats(invoice.amount_milli_satoshis().expect("must have amount"));

// todo go through all clients and select the first one that has enough balance
let client = self.get_client().await.fedimint_client;
let lightning_module = client.get_first_module::<LightningClientModule>();
Expand All @@ -79,18 +93,44 @@ impl HarborCore {
.await
.ok_or(anyhow!("Internal error: No gateway found for federation"))?;

let fees = gateway.fees.to_amount(&amount);

log::info!("Sending lightning invoice: {invoice}, paying fees: {fees}");

let outgoing = lightning_module
.pay_bolt11_invoice(Some(gateway), invoice, ())
.pay_bolt11_invoice(Some(gateway), invoice.clone(), ())
.await?;

self.storage.create_lightning_payment(
outgoing.payment_type.operation_id(),
client.federation_id(),
invoice,
amount,
fees,
)?;

match outgoing.payment_type {
PayType::Internal(op_id) => {
let sub = lightning_module.subscribe_internal_pay(op_id).await?;
spawn_internal_payment_subscription(self.tx.clone(), client.clone(), sub).await;
spawn_internal_payment_subscription(
self.tx.clone(),
client.clone(),
self.storage.clone(),
op_id,
sub,
)
.await;
}
PayType::Lightning(op_id) => {
let sub = lightning_module.subscribe_ln_pay(op_id).await?;
spawn_invoice_payment_subscription(self.tx.clone(), client.clone(), sub).await;
spawn_invoice_payment_subscription(
self.tx.clone(),
client.clone(),
self.storage.clone(),
op_id,
sub,
)
.await;
}
}

Expand All @@ -108,7 +148,7 @@ impl HarborCore {
.ok_or(anyhow!("Internal error: No gateway found for federation"))?;

let desc = Description::new(String::new()).expect("empty string is valid");
let (op_id, invoice, _) = lightning_module
let (op_id, invoice, preimage) = lightning_module
.create_bolt11_invoice(
amount,
Bolt11InvoiceDescription::Direct(&desc),
Expand All @@ -118,11 +158,27 @@ impl HarborCore {
)
.await?;

println!("{}", invoice);
log::info!("Invoice created: {invoice}");

self.storage.create_ln_receive(
op_id,
client.federation_id(),
invoice.clone(),
amount,
Amount::ZERO, // todo one day there will be receive fees
preimage,
)?;

// Create subscription to operation if it exists
if let Ok(subscription) = lightning_module.subscribe_ln_receive(op_id).await {
spawn_invoice_receive_subscription(self.tx.clone(), client.clone(), subscription).await;
spawn_invoice_receive_subscription(
self.tx.clone(),
client.clone(),
self.storage.clone(),
op_id,
subscription,
)
.await;
} else {
error!("Could not create subscription to lightning receive");
}
Expand All @@ -141,12 +197,27 @@ impl HarborCore {
let fees = onchain.get_withdraw_fees(address.clone(), amount).await?;

let op_id = onchain
.withdraw(address, bitcoin::Amount::from_sat(sats), fees, ())
.withdraw(address.clone(), bitcoin::Amount::from_sat(sats), fees, ())
.await?;

self.storage.create_onchain_payment(
op_id,
client.federation_id(),
address,
amount.to_sat(),
fees.amount().to_sat(),
)?;

let sub = onchain.subscribe_withdraw_updates(op_id).await?;

spawn_onchain_payment_subscription(self.tx.clone(), client.clone(), sub).await;
spawn_onchain_payment_subscription(
self.tx.clone(),
client.clone(),
self.storage.clone(),
op_id,
sub,
)
.await;

Ok(())
}
Expand All @@ -161,9 +232,19 @@ impl HarborCore {

let (op_id, address) = onchain.get_deposit_address(valid_until, ()).await?;

self.storage
.create_onchain_receive(op_id, client.federation_id(), address.clone())?;

let sub = onchain.subscribe_deposit_updates(op_id).await?;

spawn_onchain_receive_subscription(self.tx.clone(), client.clone(), sub).await;
spawn_onchain_receive_subscription(
self.tx.clone(),
client.clone(),
self.storage.clone(),
op_id,
sub,
)
.await;

Ok(address)
}
Expand Down Expand Up @@ -268,14 +349,8 @@ pub fn run_core() -> Subscription<Message> {
clients.insert(client.fedimint_client.federation_id(), client);
}

let mut balance = Amount::ZERO;
for client in clients.values() {
balance += client.fedimint_client.get_balance().await;
}

let core = HarborCore {
storage: db.clone(),
balance,
tx: tx.clone(),
mnemonic,
network,
Expand Down
Loading

0 comments on commit 00960a1

Please sign in to comment.