Skip to content

Commit

Permalink
load xprv from json
Browse files Browse the repository at this point in the history
  • Loading branch information
RGGH committed Dec 4, 2023
1 parent 9e36083 commit 147aab7
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 114 deletions.
87 changes: 87 additions & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2021"
# See more keys: and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bdk = { version = "0.28.1", default-feature = false, features = ["all-keys"] }
bdk = { version = "0.28.1", features = ["all-keys"] }
tokio = { version = "1.0", features = ["full"] }
axum = "0.7"
serde = { version = "1.0.192", features = ["derive"] }
Expand All @@ -15,6 +15,7 @@ serde_json = "1.0.108"
tower-cookies = "0.9.0"
rstml-component-axum = "0.2.4"
rstml-component = "0.2.1"
env_logger = "0.10.1"

[dev-dependencies]
anyhow = "1"
Expand Down
6 changes: 5 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![allow(unused)]
use env_logger;
use axum::extract::Path;
use axum::extract::{Extension, Query};
use axum::middleware;
Expand All @@ -8,8 +9,8 @@ use axum::routing::get;
use axum::routing::get_service;
use axum::Router;
use serde::Deserialize;
use tower_http::services::ServeDir;
use tokio::net::TcpListener;
use tower_http::services::ServeDir;

pub use self::error::{Error, Result};

Expand All @@ -23,6 +24,9 @@ struct HelloParams {

#[tokio::main]
async fn main() {

env_logger::init();

let app = Router::new()
.merge(web::routes_login::routes())
.layer(middleware::map_response(main_response_mapper));
Expand Down
106 changes: 80 additions & 26 deletions src/web/routes_login.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,57 @@
use rstml_component::{move_html, write_html, For, HtmlComponent, HtmlContent};
use rstml_component_axum::HtmlContentAxiosExt;

use std::net::SocketAddr;
use std::collections::HashMap;
use std::net::SocketAddr;

use std::fs::File;
use std::io::{self, Read, Write};
use std::path::Path;

use crate::web;
use crate::web::AUTH_TOKEN;
use crate::{Error, Result};
use axum::body::Body;
use axum::extract::Query;
use axum::http::{Response, StatusCode};
use axum::response::IntoResponse;
use axum::routing::{get, post};
use axum::Router;
use axum::response::IntoResponse;
use axum::{Extension, Json};
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};

use bdk::bitcoin::Network;
use bdk::database::MemoryDatabase;
use bdk::keys::{
bip39::{Language, Mnemonic, WordCount},
DerivableKey, ExtendedKey, GeneratableKey, GeneratedKey,
};
use bdk::database::MemoryDatabase;
use bdk::template::Bip84;
use bdk::wallet::AddressIndex;
use bdk::{miniscript, KeychainKind, Wallet};
use bdk::bitcoin::Network;

// Define the constant for the configuration file path
const CONFIG_PATH: &str = "wallet_config.json";

fn read_file_content(file_path: &str) -> io::Result<String> {
// Open the file in read-only mode
let mut config_file = File::open(file_path)?;

// Create a buffer to store the file content
let mut config_content = String::new();

// Read the contents of the file into the buffer
config_file.read_to_string(&mut config_content)?;

Ok(config_content)
}

pub fn routes() -> Router {
Router::new()
.route("/api/login", post(api_login))
.route("/api/gen_wallet", get(gen_wallet))
.route("/api/load_wallet", get(load_wallet))
}

async fn api_login(payload: Json<LoginPayload>) -> Result<Json<Value>> {
Expand All @@ -56,7 +77,13 @@ struct LoginPayload {
password: String,
}

// Handler for "/api/wallet" route
#[derive(Debug, Serialize, Deserialize)]
struct WalletConfig {
xprv: String,
network: Network,
}

// Handler for "/api/genwallet" route
async fn gen_wallet(Query(params): Query<HashMap<String, String>>) -> Json<Value> {
let network = Network::Testnet;
let mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
Expand Down Expand Up @@ -88,26 +115,53 @@ async fn gen_wallet(Query(params): Query<HashMap<String, String>>) -> Json<Value
}))
}

#[derive(HtmlComponent)]
struct Book {
title: &'static str,
author: &'static str,
}
async fn load_wallet(Query(params): Query<HashMap<String, String>>) -> Json<Value> {
// Read the file content and handle the result
let config_content_result = read_file_content(CONFIG_PATH);

impl Book {
fn new(title: &'static str, author: &'static str) -> Self {
Self { title, author }
}
}
// Check if reading the file was successful
let config_content = match config_content_result {
Ok(content) => content,
Err(err) => {
// Handle the error, e.g., print an error message and return an error response
eprintln!("Error reading config file: {}", err);
return Json(json!({
"error": "Failed to read configuration file",
}));
}
};

impl HtmlContent for Book {
fn fmt(self, formatter: &mut rstml_component::HtmlFormatter) -> std::fmt::Result {
write_html!(formatter,
<div>
<h1>{self.title}</h1>
<h2>"("{self.author}")"</h2>
</div>
)
}
}
let wallet_config: WalletConfig = serde_json::from_str(&config_content).unwrap();

// Extract values from the configuration
let xprv = &wallet_config.xprv;
let network = wallet_config.network;

let mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
Mnemonic::generate((WordCount::Words12, Language::English)).unwrap();
let mnemonic_words = mnemonic.to_string();
let mnemonic = Mnemonic::parse(&mnemonic_words).unwrap();
// Generate the extended key
let xkey: ExtendedKey = mnemonic.into_extended_key().unwrap();
// Get xprv from the extended key
let xprv = xkey.into_xprv(network).unwrap();
// Create a BDK wallet structure using BIP 84 descriptor ("m/84h/1h/0h/0" and "m/84h/1h/0h/1")
let wallet = Wallet::new(
Bip84(xprv, KeychainKind::External),
Some(Bip84(xprv, KeychainKind::Internal)),
network,
MemoryDatabase::default(),
)
.unwrap();

let new_wallet = wallet.get_address(AddressIndex::New).unwrap();
// get a new address (this increments revealed derivation index)
println!("revealed (loaded) address: {:?}", new_wallet.address);

let amount: Option<&String> = params.get("amount");

Json(json!({
"message": new_wallet.address,
"amount": amount,
}))
}
Loading

0 comments on commit 147aab7

Please sign in to comment.