Skip to content

Commit

Permalink
chore: Combine states into a single state file
Browse files Browse the repository at this point in the history
For testing I had to make the state mutable as otherwise I wasn't able to start a new app node.
  • Loading branch information
holzeis committed Nov 14, 2023
1 parent 59cc662 commit fa05863
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 55 deletions.
27 changes: 9 additions & 18 deletions mobile/native/src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
pub mod api;

use crate::config::api::Config;
use bdk::bitcoin;
use bdk::bitcoin::secp256k1::PublicKey;
use bdk::bitcoin::XOnlyPublicKey;
use ln_dlc_node::node::NodeInfo;
use ln_dlc_node::node::OracleInfo;
use state::Storage;
use std::net::SocketAddr;
use std::path::Path;
use std::time::Duration;

static CONFIG: Storage<ConfigInternal> = Storage::new();

#[derive(Clone)]
pub struct ConfigInternal {
coordinator_pubkey: PublicKey,
Expand All @@ -27,54 +23,49 @@ pub struct ConfigInternal {
seed_dir: String,
}

pub fn set(config: Config, app_dir: String, seed_dir: String) {
CONFIG.set((config, app_dir, seed_dir).into());
}

pub fn coordinator_health_endpoint() -> String {
let config = CONFIG.get();
let config = crate::state::get_config();
format!("http://{}/health", config.http_endpoint)
}

pub fn health_check_interval() -> Duration {
let config = CONFIG.get();
config.health_check_interval
crate::state::get_config().health_check_interval
}

pub fn get_coordinator_info() -> NodeInfo {
let config = CONFIG.get();
let config = crate::state::get_config();
NodeInfo {
pubkey: config.coordinator_pubkey,
address: config.p2p_endpoint,
}
}

pub fn get_esplora_endpoint() -> String {
CONFIG.get().esplora_endpoint.clone()
crate::state::get_config().esplora_endpoint
}

pub fn get_oracle_info() -> OracleInfo {
let config = CONFIG.get();
let config = crate::state::get_config();
OracleInfo {
endpoint: config.oracle_endpoint.clone(),
public_key: config.oracle_pubkey,
}
}

pub fn get_http_endpoint() -> SocketAddr {
CONFIG.get().http_endpoint
crate::state::get_config().http_endpoint
}

pub fn get_network() -> bitcoin::Network {
CONFIG.get().network
crate::state::get_config().network
}

pub fn get_data_dir() -> String {
CONFIG.get().data_dir.clone()
crate::state::get_config().data_dir
}

pub fn get_seed_dir() -> String {
CONFIG.get().seed_dir.clone()
crate::state::get_config().seed_dir
}

pub fn get_backup_dir() -> String {
Expand Down
1 change: 1 addition & 0 deletions mobile/native/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub mod event;
pub mod health;
pub mod logger;
pub mod schema;
pub mod state;

mod backup;
mod orderbook;
Expand Down
75 changes: 38 additions & 37 deletions mobile/native/src/ln_dlc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ use tokio::task::spawn_blocking;
use trade::ContractSymbol;

mod lightning_subscriber;
mod node;
pub mod node;
mod recover_rollover;
mod sync_position_to_dlc;

Expand All @@ -122,16 +122,12 @@ const ON_CHAIN_SYNC_INTERVAL: Duration = Duration::from_secs(300);
/// exact fee will be know.
pub const FUNDING_TX_WEIGHT_ESTIMATE: u64 = 220;

static NODE: Storage<Arc<Node>> = Storage::new();
static SEED: Storage<Bip39Seed> = Storage::new();
static STORAGE: Storage<TenTenOneNodeStorage> = Storage::new();

/// Trigger an on-chain sync followed by an update to the wallet balance and history.
///
/// We do not wait for the triggered task to finish, because the effect will be reflected
/// asynchronously on the UI.
pub async fn refresh_wallet_info() -> Result<()> {
let node = NODE.try_get().context("failed to get ln dlc node")?;
let node = crate::state::get_node();
let wallet = node.inner.wallet();

// Spawn into the blocking thread pool of the dedicated backend runtime to avoid blocking the UI
Expand All @@ -146,7 +142,7 @@ pub async fn refresh_wallet_info() -> Result<()> {
tracing::error!("Manually triggered Lightning wallet sync failed: {e:#}");
}

if let Err(e) = keep_wallet_balance_and_history_up_to_date(node) {
if let Err(e) = keep_wallet_balance_and_history_up_to_date(&node) {
tracing::error!("Failed to keep wallet history up to date: {e:#}");
}

Expand All @@ -157,16 +153,14 @@ pub async fn refresh_wallet_info() -> Result<()> {
}

pub fn get_seed_phrase() -> Vec<String> {
SEED.try_get()
.expect("SEED to be initialised")
.get_seed_phrase()
crate::state::get_seed().get_seed_phrase()
}

/// Gets the seed from the storage or from disk. However it will panic if the seed can not be found.
/// No new seed will be created.
fn get_seed() -> Bip39Seed {
match SEED.try_get() {
Some(seed) => seed.clone(),
match crate::state::try_get_seed() {
Some(seed) => seed,
None => {
let seed_dir = config::get_seed_dir();

Expand All @@ -175,14 +169,14 @@ fn get_seed() -> Bip39Seed {
assert!(seed_path.exists());

let seed = Bip39Seed::initialize(&seed_path).expect("to read seed file");
SEED.set(seed.clone());
crate::state::set_seed(seed.clone());
seed
}
}
}

pub fn get_node_key() -> SecretKey {
match NODE.try_get() {
match crate::state::try_get_node() {
Some(node) => node.inner.node_key(),
None => {
let seed = get_seed();
Expand All @@ -204,16 +198,16 @@ pub fn get_node_pubkey() -> PublicKey {
}

pub async fn update_node_settings(settings: LnDlcNodeSettings) {
let node = NODE.get();
let node = crate::state::get_node();
node.inner.update_settings(settings).await;
}

pub fn get_oracle_pubkey() -> XOnlyPublicKey {
NODE.get().inner.oracle_pk()
crate::state::get_node().inner.oracle_pk()
}

pub fn get_funding_transaction(channel_id: &ChannelId) -> Result<Txid> {
let node = NODE.get();
let node = crate::state::get_node();
let channel_details = node.inner.channel_manager.get_channel_details(channel_id);

let funding_transaction = match channel_details {
Expand Down Expand Up @@ -248,8 +242,8 @@ pub fn get_or_create_tokio_runtime() -> Result<&'static Runtime> {

/// Gets the 10101 node storage, initializes the storage if not found yet.
pub fn get_storage() -> TenTenOneNodeStorage {
match STORAGE.try_get() {
Some(storage) => storage.clone(),
match crate::state::try_get_storage() {
Some(storage) => storage,
None => {
// storage is only initialized before the node is started if a new wallet is created
// or restored.
Expand All @@ -259,7 +253,7 @@ pub fn get_storage() -> TenTenOneNodeStorage {
get_node_key(),
);
tracing::info!("Initialized 10101 storage!");
STORAGE.set(storage.clone());
crate::state::set_storage(storage.clone());
storage
}
}
Expand Down Expand Up @@ -290,7 +284,7 @@ pub fn run(seed_dir: String, runtime: &Runtime) -> Result<()> {
let seed_dir = Path::new(&seed_dir).join(network.to_string());
let seed_path = seed_dir.join("seed");
let seed = Bip39Seed::initialize(&seed_path)?;
SEED.set(seed.clone());
crate::state::set_seed(seed.clone());

let (event_sender, event_receiver) = watch::channel::<Option<Event>>(None);

Expand Down Expand Up @@ -412,7 +406,7 @@ pub fn run(seed_dir: String, runtime: &Runtime) -> Result<()> {
);
}

NODE.set(node);
crate::state::set_node(node);

event::publish(&EventInternal::Init("10101 is ready.".to_string()));

Expand All @@ -422,14 +416,14 @@ pub fn run(seed_dir: String, runtime: &Runtime) -> Result<()> {

pub fn init_new_mnemonic(target_seed_file: &Path) -> Result<()> {
let seed = Bip39Seed::initialize(target_seed_file)?;
SEED.set(seed);
crate::state::set_seed(seed);
Ok(())
}

#[tokio::main(flavor = "current_thread")]
pub async fn restore_from_mnemonic(seed_words: &str, target_seed_file: &Path) -> Result<()> {
let seed = Bip39Seed::restore_from_mnemonic(seed_words, target_seed_file)?;
SEED.set(seed);
crate::state::set_seed(seed);

let storage = get_storage();
storage.client.restore(storage.dlc_storage).await
Expand Down Expand Up @@ -732,11 +726,14 @@ fn compute_relative_contracts(order: &Order) -> Decimal {
}

pub fn get_unused_address() -> String {
NODE.get().inner.get_unused_address().to_string()
crate::state::get_node()
.inner
.get_unused_address()
.to_string()
}

pub fn close_channel(is_force_close: bool) -> Result<()> {
let node = NODE.try_get().context("failed to get ln dlc node")?;
let node = crate::state::try_get_node().context("failed to get ln dlc node")?;

let channels = node.inner.list_channels();
let channel_details = channels.first().context("No channel to close")?;
Expand All @@ -754,7 +751,7 @@ pub fn collaborative_revert_channel(
trader_amount: Amount,
execution_price: Decimal,
) -> Result<()> {
let node = NODE.try_get().context("Failed to get Node")?;
let node = crate::state::try_get_node().context("Failed to get Node")?;
let node = node.inner.clone();

let channel_id_hex = hex::encode(channel_id);
Expand Down Expand Up @@ -888,7 +885,7 @@ fn update_state_after_collab_revert(
sub_channel: SubChannel,
execution_price: Decimal,
) -> Result<()> {
let node = NODE.try_get().context("failed to get ln dlc node")?;
let node = crate::state::try_get_node().context("failed to get ln dlc node")?;
let positions = db::get_positions()?;

let position = match positions.first() {
Expand Down Expand Up @@ -958,22 +955,22 @@ fn update_state_after_collab_revert(
}

pub fn get_usable_channel_details() -> Result<Vec<ChannelDetails>> {
let node = NODE.try_get().context("failed to get ln dlc node")?;
let node = crate::state::try_get_node().context("failed to get ln dlc node")?;
let channels = node.inner.list_usable_channels();

Ok(channels)
}

pub fn get_fee_rate() -> Result<FeeRate> {
let node = NODE.try_get().context("failed to get ln dlc node")?;
let node = crate::state::try_get_node().context("failed to get ln dlc node")?;
Ok(node.inner.wallet().get_fee_rate(CONFIRMATION_TARGET))
}

/// Returns channel value or zero if there is no channel yet.
///
/// This is used when checking max tradeable amount
pub fn max_channel_value() -> Result<Amount> {
let node = NODE.try_get().context("failed to get ln dlc node")?;
let node = crate::state::try_get_node().context("failed to get ln dlc node")?;
if let Some(existing_channel) = node
.inner
.list_channels()
Expand Down Expand Up @@ -1014,7 +1011,7 @@ fn fetch_lsp_config() -> Result<LspConfig, Error> {
}

pub fn contract_tx_fee_rate() -> Result<u64> {
let node = NODE.try_get().context("failed to get ln dlc node")?;
let node = crate::state::try_get_node().context("failed to get ln dlc node")?;
if let Some(fee_rate_per_vb) = node
.inner
.list_dlc_channels()?
Expand Down Expand Up @@ -1046,7 +1043,7 @@ pub fn create_onboarding_invoice(
let runtime = get_or_create_tokio_runtime()?;

runtime.block_on(async {
let node = NODE.get();
let node = crate::state::get_node();
let client = reqwest_client();

// check if we have already announced a channel before. If so we can reuse the `user_channel_id`
Expand Down Expand Up @@ -1112,7 +1109,7 @@ pub fn create_onboarding_invoice(
}

pub fn create_invoice(amount_sats: Option<u64>) -> Result<Bolt11Invoice> {
let node = NODE.get();
let node = crate::state::get_node();

let final_route_hint_hop = node
.inner
Expand All @@ -1130,11 +1127,15 @@ pub fn send_payment(payment: SendPayment) -> Result<()> {
match payment {
SendPayment::Lightning { invoice, amount } => {
let invoice = Bolt11Invoice::from_str(&invoice)?;
NODE.get().inner.pay_invoice(&invoice, amount)?;
crate::state::get_node()
.inner
.pay_invoice(&invoice, amount)?;
}
SendPayment::OnChain { address, amount } => {
let address = Address::from_str(&address)?;
NODE.get().inner.send_to_address(&address, amount)?;
crate::state::get_node()
.inner
.send_to_address(&address, amount)?;
}
}
Ok(())
Expand Down Expand Up @@ -1170,7 +1171,7 @@ pub async fn trade(trade_params: TradeParams) -> Result<(), (FailureReason, Erro

/// initiates the rollover protocol with the coordinator
pub async fn rollover(contract_id: Option<String>) -> Result<()> {
let node = NODE.get();
let node = crate::state::get_node();

let dlc_channels = node
.inner
Expand Down
Loading

0 comments on commit fa05863

Please sign in to comment.