Skip to content

Instantly share code, notes, and snippets.

@justinmoon
Created July 27, 2020 21:46
Show Gist options
  • Save justinmoon/245d78764f4b8219fb1c33ac475ff2d4 to your computer and use it in GitHub Desktop.
Save justinmoon/245d78764f4b8219fb1c33ac475ff2d4 to your computer and use it in GitHub Desktop.
use bitcoin::Network;
use std::path::PathBuf;
use magical_bitcoin_wallet::bitcoincore_rpc::{Auth as RpcAuth, Client as RpcClient};
use magical_bitcoin_wallet::blockchain::{
BitcoinRpcBlockchain, Blockchain, Capability, ElectrumBlockchain, OnlineBlockchain, Progress,
};
use magical_bitcoin_wallet::Client as ElectrumClient;
use std::collections::HashSet;
#[allow(unused_imports)]
use bitcoin::{
util::bip32::{ChildNumber, DerivationPath},
Address, OutPoint, Transaction, Txid,
};
use magical_bitcoin_wallet::database::{BatchDatabase, DatabaseUtils};
use magical_bitcoin_wallet::error::Error;
pub struct ElectrumNode {
pub url: String,
pub network: Network,
}
impl ElectrumNode {
pub fn new(url: String, network: Network) -> Self {
Self { url, network }
}
pub fn blockchain(&self, wallet: &str) -> ElectrumBlockchain {
let client = ElectrumClient::new(&self.url, None).unwrap();
ElectrumBlockchain::from(client)
}
}
pub struct CoreNode {
pub url: String,
pub network: Network,
pub user_pass: Option<(String, String)>,
}
impl CoreNode {
pub fn new(url: String, network: Network, user_pass: Option<(String, String)>) -> Self {
Self {
url,
network,
user_pass,
}
}
pub fn blockchain(&self, wallet: &str) -> BitcoinRpcBlockchain {
let auth = match self.user_pass.clone() {
None => RpcAuth::CookieFile(PathBuf::from("/home/justin/.bitcoin/regtest/.cookie")),
Some((user, pass)) => RpcAuth::UserPass(user, pass),
};
let client = RpcClient::new(self.url.clone(), auth, None).unwrap();
BitcoinRpcBlockchain::new(Some(client))
}
}
pub enum Node {
Electrum(ElectrumNode),
Core(CoreNode),
}
impl Blockchain for Node {
fn offline() -> Self {
panic!("not implemented");
}
fn is_online(&self) -> bool {
match self {
Node::Electrum(node) => node.blockchain("").is_online(),
Node::Core(node) => node.blockchain("").is_online(),
}
}
}
impl OnlineBlockchain for Node {
fn get_capabilities(&self) -> HashSet<Capability> {
match self {
Node::Electrum(node) => node.blockchain("").get_capabilities(),
Node::Core(node) => node.blockchain("").get_capabilities(),
}
}
fn setup<D: BatchDatabase + DatabaseUtils, P: Progress>(
&mut self,
stop_gap: Option<usize>,
database: &mut D,
progress_update: P,
) -> Result<(), Error> {
match self {
Node::Electrum(node) => node
.blockchain("")
.setup(stop_gap, database, progress_update),
Node::Core(node) => node
.blockchain("")
.setup(stop_gap, database, progress_update),
}
}
fn get_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
match self {
Node::Electrum(node) => node.blockchain("").get_tx(txid),
Node::Core(node) => node.blockchain("").get_tx(txid),
}
}
fn broadcast(&mut self, tx: &Transaction) -> Result<(), Error> {
match self {
Node::Electrum(node) => node.blockchain("").broadcast(tx),
Node::Core(node) => node.blockchain("").broadcast(tx),
}
}
fn get_height(&mut self) -> Result<usize, Error> {
match self {
Node::Electrum(node) => node.blockchain("").get_height(),
Node::Core(node) => node.blockchain("").get_height(),
}
}
}
fn main() {
// Core
let mut node = Node::Core(CoreNode::new(
"http://127.0.0.1:18443".to_string(),
Network::Regtest,
None,
));
let height = node.get_height();
println!("core: {:?}", height);
// Electrum
let mut node = Node::Electrum(ElectrumNode::new(
"tcp://electrum.blockstream.info:60001".to_string(),
Network::Testnet,
));
let height = node.get_height();
println!("electrum: {:?}", height);
// Electrum
println!("Hello, world!");
}
@afilini
Copy link

afilini commented Jul 27, 2020

macro_rules! node_call_method {
    ($node:expr, $method:ident $(, $arg:expr )*) => {
        match $node {
            Node::Electrum(inner) => inner.blockchain("").$method( $( $arg, )* ),
            Node::Core(inner) => inner.blockchain("").$method( $( $arg, )* ),
        }
    }
}

and then you call methods with:

let height = node_call_method!(node, get_height);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment