Skip to content

Commit

Permalink
add transfer & receive tab, rpc to remove tx from mempool
Browse files Browse the repository at this point in the history
  • Loading branch information
Ash-L2L committed Mar 25, 2024
1 parent dd48135 commit d2fad89
Show file tree
Hide file tree
Showing 14 changed files with 269 additions and 22 deletions.
7 changes: 5 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ authors = [
"Nikita Chashchinskii <[email protected]>"
]
edition = "2021"
version = "0.5.1"
version = "0.5.2"

[workspace.dependencies.bip300301]
git = "https://github.com/Ash-L2L/bip300301.git"
Expand Down
17 changes: 16 additions & 1 deletion app/gui/coins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,39 @@ use strum::{EnumIter, IntoEnumIterator};

use crate::app::App;

mod transfer_receive;
mod tx_builder;
mod tx_creator;
mod utxo_creator;
mod utxo_selector;

use transfer_receive::TransferReceive;
use tx_builder::TxBuilder;

#[derive(Default, EnumIter, Eq, PartialEq, strum::Display)]
enum Tab {
#[default]
#[strum(to_string = "Transfer & Receive")]
TransferReceive,
#[strum(to_string = "Transaction Builder")]
TransactionBuilder,
}

#[derive(Default)]
pub struct Coins {
transfer_receive: TransferReceive,
tab: Tab,
tx_builder: TxBuilder,
}

impl Coins {
pub fn new(app: &App) -> Self {
Self {
transfer_receive: TransferReceive::new(app),
tab: Tab::default(),
tx_builder: TxBuilder::default(),
}
}

pub fn show(&mut self, app: &mut App, ui: &mut egui::Ui) {
egui::TopBottomPanel::top("coins_tabs").show(ui.ctx(), |ui| {
ui.horizontal(|ui| {
Expand All @@ -34,6 +46,9 @@ impl Coins {
});
});
egui::CentralPanel::default().show(ui.ctx(), |ui| match self.tab {
Tab::TransferReceive => {
let () = self.transfer_receive.show(app, ui);
}
Tab::TransactionBuilder => {
let () = self.tx_builder.show(app, ui).unwrap();
}
Expand Down
153 changes: 153 additions & 0 deletions app/gui/coins/transfer_receive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
use bip300301::bitcoin;
use eframe::egui;
use thunder::types::Address;

use crate::{app::App, gui::util::UiExt};

#[derive(Debug, Default)]
struct Transfer {
dest: String,
amount: String,
fee: String,
}

fn create_transfer(
app: &App,
dest: Address,
amount: bitcoin::Amount,
fee: bitcoin::Amount,
) -> anyhow::Result<()> {
let accumulator = app.node.get_accumulator()?;
let tx = app.wallet.create_transaction(
&accumulator,
dest,
amount.to_sat(),
fee.to_sat(),
)?;
app.sign_and_send(tx)?;
Ok(())
}

impl Transfer {
fn show(&mut self, app: &App, ui: &mut egui::Ui) {
ui.add_sized((250., 10.), |ui: &mut egui::Ui| {
ui.horizontal(|ui| {
let dest_edit = egui::TextEdit::singleline(&mut self.dest)
.hint_text("destination address")
.desired_width(150.);
ui.add(dest_edit);
})
.response
});
ui.add_sized((110., 10.), |ui: &mut egui::Ui| {
ui.horizontal(|ui| {
let amount_edit = egui::TextEdit::singleline(&mut self.amount)
.hint_text("amount")
.desired_width(80.);
ui.add(amount_edit);
ui.label("BTC");
})
.response
});
ui.add_sized((110., 10.), |ui: &mut egui::Ui| {
ui.horizontal(|ui| {
let fee_edit = egui::TextEdit::singleline(&mut self.fee)
.hint_text("fee")
.desired_width(80.);
ui.add(fee_edit);
ui.label("BTC");
})
.response
});
let dest: Option<Address> = self.dest.parse().ok();
let amount = bitcoin::Amount::from_str_in(
&self.amount,
bitcoin::Denomination::Bitcoin,
);
let fee = bitcoin::Amount::from_str_in(
&self.fee,
bitcoin::Denomination::Bitcoin,
);
if ui
.add_enabled(
dest.is_some() && amount.is_ok() && fee.is_ok(),
egui::Button::new("transfer"),
)
.clicked()
{
if let Err(err) = create_transfer(
app,
dest.expect("should not happen"),
amount.expect("should not happen"),
fee.expect("should not happen"),
) {
tracing::error!("{err:#}");
} else {
*self = Self::default();
}
}
}
}

#[derive(Debug)]
struct Receive {
address: anyhow::Result<Address>,
}

impl Receive {
fn new(app: &App) -> Self {
let address = app
.wallet
.get_new_address()
.map_err(anyhow::Error::from)
.inspect_err(|err| tracing::error!("{err:#}"));
Self { address }
}

fn show(&mut self, app: &App, ui: &mut egui::Ui) {
match &self.address {
Ok(address) => {
ui.monospace_selectable_singleline(false, address.to_string());
}
Err(err) => {
ui.monospace_selectable_multiline(format!("{err:#}"));
}
}
if ui.button("generate").clicked() {
*self = Self::new(app)
}
}
}

#[derive(Debug)]
pub(super) struct TransferReceive {
transfer: Transfer,
receive: Receive,
}

impl TransferReceive {
pub fn new(app: &App) -> Self {
Self {
transfer: Transfer::default(),
receive: Receive::new(app),
}
}

pub fn show(&mut self, app: &mut App, ui: &mut egui::Ui) {
egui::SidePanel::left("transfer")
.exact_width(ui.available_width() / 2.)
.resizable(false)
.show_inside(ui, |ui| {
ui.vertical_centered(|ui| {
ui.heading("Transfer");
self.transfer.show(app, ui);
})
});
egui::CentralPanel::default().show_inside(ui, |ui| {
ui.vertical_centered(|ui| {
ui.heading("Receive");
self.receive.show(app, ui);
})
});
}
}
3 changes: 2 additions & 1 deletion app/gui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,13 @@ impl EguiApp {
// Restore app state using cc.storage (requires the "persistence" feature).
// Use the cc.gl (a glow::Context) to create graphics shaders and buffers that you can use
// for e.g. egui::PaintCallback.
let coins = Coins::new(&app);
let height = app.node.get_height().unwrap_or(0);
let parent_chain = ParentChain::new(&app);
Self {
app,
block_explorer: BlockExplorer::new(height),
coins: Coins::default(),
coins,
logs: Logs::new(logs_capture),
mempool_explorer: MemPoolExplorer::default(),
miner: Miner::default(),
Expand Down
1 change: 0 additions & 1 deletion app/gui/parent_chain/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ impl Withdrawal {
.hint_text("mainchain address")
.desired_width(150.);
ui.add(mainchain_address_edit);
ui.label("BTC");
if ui.button("generate").clicked() {
match app.get_new_main_address() {
Ok(main_address) => {
Expand Down
12 changes: 12 additions & 0 deletions app/rpc_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ pub trait Rpc {
#[method(name = "mine")]
async fn mine(&self, fee: Option<u64>) -> RpcResult<()>;

/// Remove a tx from the mempool
#[method(name = "remove_from_mempool")]
async fn remove_from_mempool(&self, txid: Txid) -> RpcResult<()>;

#[method(name = "set_seed_from_mnemonic")]
async fn set_seed_from_mnemonic(&self, mnemonic: String) -> RpcResult<()>;

Expand All @@ -43,6 +47,14 @@ pub trait Rpc {
#[method(name = "stop")]
async fn stop(&self);

#[method(name = "transfer")]
async fn transfer(
&self,
dest: Address,
value_sats: u64,
fee_sats: u64,
) -> RpcResult<Txid>;

#[method(name = "withdraw")]
async fn withdraw(
&self,
Expand Down
25 changes: 25 additions & 0 deletions app/rpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ impl RpcServer for RpcServerImpl {
self.app.mine(fee).await.map_err(convert_app_err)
}

async fn remove_from_mempool(&self, txid: Txid) -> RpcResult<()> {
self.app
.node
.remove_from_mempool(txid)
.map_err(convert_node_err)
}

async fn set_seed_from_mnemonic(&self, mnemonic: String) -> RpcResult<()> {
let mnemonic =
bip39::Mnemonic::from_phrase(&mnemonic, bip39::Language::English)
Expand All @@ -119,6 +126,24 @@ impl RpcServer for RpcServerImpl {
std::process::exit(0);
}

async fn transfer(
&self,
dest: Address,
value_sats: u64,
fee_sats: u64,
) -> RpcResult<Txid> {
let accumulator =
self.app.node.get_accumulator().map_err(convert_node_err)?;
let tx = self
.app
.wallet
.create_transaction(&accumulator, dest, value_sats, fee_sats)
.map_err(convert_wallet_err)?;
let txid = tx.txid();
self.app.sign_and_send(tx).map_err(convert_app_err)?;
Ok(txid)
}

async fn withdraw(
&self,
mainchain_address: bitcoin::Address<bitcoin::address::NetworkUnchecked>,
Expand Down
2 changes: 1 addition & 1 deletion lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ bytes = "1.4.0"
ed25519-dalek = { version = "2.1.1", features = ["batch", "serde"] }
ed25519-dalek-bip32 = "0.3.0"
heed = { git = "https://github.com/meilisearch/heed", tag = "v0.12.4", version = "0.12.4" }
hex = "0.4.3"
hex = { version = "0.4.3", features = ["serde"] }
quinn = "0.10.1"
rayon = "1.7.0"
rcgen = "0.11.1"
Expand Down
15 changes: 10 additions & 5 deletions lib/mempool.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use heed::{
types::{OwnedType, SerdeBincode, Unit},
types::{SerdeBincode, Unit},
Database, RoTxn, RwTxn,
};
use rustreexo::accumulator::pollard::Pollard;
Expand All @@ -19,7 +19,7 @@ pub enum Error {
#[derive(Clone)]
pub struct MemPool {
pub transactions:
Database<OwnedType<[u8; 32]>, SerdeBincode<AuthorizedTransaction>>,
Database<SerdeBincode<Txid>, SerdeBincode<AuthorizedTransaction>>,
pub spent_utxos: Database<SerdeBincode<OutPoint>, Unit>,
}

Expand Down Expand Up @@ -52,14 +52,19 @@ impl MemPool {
}
self.transactions.put(
txn,
&transaction.transaction.txid().into(),
&transaction.transaction.txid(),
transaction,
)?;
Ok(())
}

pub fn delete(&self, txn: &mut RwTxn, txid: &Txid) -> Result<(), Error> {
self.transactions.delete(txn, txid.into())?;
pub fn delete(&self, rwtxn: &mut RwTxn, txid: &Txid) -> Result<(), Error> {
if let Some(tx) = self.transactions.get(rwtxn, txid)? {
for (outpoint, _) in &tx.transaction.inputs {
self.spent_utxos.delete(rwtxn, outpoint)?;
}
self.transactions.delete(rwtxn, txid)?;
}
Ok(())
}

Expand Down
7 changes: 7 additions & 0 deletions lib/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,13 @@ impl Node {
Ok(self.state.get_pending_withdrawal_bundle(&txn)?)
}

pub fn remove_from_mempool(&self, txid: Txid) -> Result<(), Error> {
let mut rwtxn = self.env.write_txn()?;
let () = self.mempool.delete(&mut rwtxn, &txid)?;
rwtxn.commit()?;
Ok(())
}

pub async fn submit_block(
&self,
header: &Header,
Expand Down
Loading

0 comments on commit d2fad89

Please sign in to comment.