Improve the README, add examples
This commit is contained in:
parent
6a2d0db674
commit
c4f4f20d8b
@ -17,6 +17,7 @@ env:
|
||||
- TARGET=x86_64-unknown-linux-gnu FEATURES=cli-utils,esplora NO_DEFAULT_FEATURES=1
|
||||
- TARGET=x86_64-unknown-linux-gnu FEATURES=compiler NO_DEFAULT_FEATURES=1 RUN_TESTS=1 # Test the `miniscriptc` example
|
||||
- TARGET=x86_64-unknown-linux-gnu FEATURES=test-electrum NO_DEFAULT_FEATURES=1 RUN_TESTS=1 RUN_CORE=1
|
||||
- TARGET=x86_64-unknown-linux-gnu FEATURES=test-md-docs NO_DEFAULT_FEATURES=1 RUN_TESTS=1 NIGHTLY=1
|
||||
- TARGET=wasm32-unknown-unknown FEATURES=cli-utils,esplora NO_DEFAULT_FEATURES=1
|
||||
before_script:
|
||||
- |
|
||||
@ -33,6 +34,11 @@ before_script:
|
||||
if [[ $CHECK_FMT -eq 1 ]]; then
|
||||
rustup component add rustfmt
|
||||
fi
|
||||
- |
|
||||
if [[ $NIGHTLY -eq 1 ]]; then
|
||||
rustup toolchain install nightly
|
||||
rustup default nightly
|
||||
fi
|
||||
- rustup target add "$TARGET"
|
||||
script:
|
||||
- |
|
||||
|
@ -51,6 +51,7 @@ async-interface = ["async-trait"]
|
||||
# Debug/Test features
|
||||
debug-proc-macros = ["magical-macros/debug", "testutils-macros/debug"]
|
||||
test-electrum = ["electrum"]
|
||||
test-md-docs = ["base64", "electrum"]
|
||||
|
||||
[dev-dependencies]
|
||||
testutils = { path = "./testutils" }
|
||||
|
146
README.md
146
README.md
@ -1,7 +1,145 @@
|
||||
# Magical Bitcoin Wallet
|
||||
<div align="center">
|
||||
<h1>Magical Bitcoin Library</h1>
|
||||
|
||||
A modern, lightweight, descriptor-based wallet written in Rust!
|
||||
<img src="./static/wizard.svg" width="220" />
|
||||
|
||||
## Getting Started
|
||||
<p>
|
||||
<strong>A modern, lightweight, descriptor-based wallet library written in Rust!</strong>
|
||||
</p>
|
||||
|
||||
See the documentation at [magicalbitcoin.org](https://magicalbitcoin.org)
|
||||
<p>
|
||||
<a href="https://crates.io/crates/magical"><img alt="Crate Info" src="https://img.shields.io/crates/v/magical.svg"/></a>
|
||||
<a href="https://docs.rs/magical/"><img alt="API Docs" src="https://img.shields.io/badge/docs.rs-magical-green"/></a>
|
||||
<a href="https://blog.rust-lang.org/2020/07/16/Rust-1.45.0.html"><img alt="Rustc Version 1.45+" src="https://img.shields.io/badge/rustc-1.45%2B-lightgrey.svg"/></a>
|
||||
</p>
|
||||
|
||||
<h4>
|
||||
<a href="https://magicalbitcoin.org">Project Homepage</a>
|
||||
<span> | </span>
|
||||
<a href="https://docs.rs/magical">Documentation</a>
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
## About
|
||||
|
||||
The `magical` library aims to be the core building block for Bitcoin wallets of any kind.
|
||||
|
||||
* It uses [Miniscript](https://github.com/rust-bitcoin/rust-miniscript) to support descriptors with generalized conditions. This exact same library can be used to build
|
||||
single-sig wallets, multisigs, timelocked contracts and more.
|
||||
* It supports multiple blockchain backends and databases, allowing developers to choose exactly what's right for their projects.
|
||||
* It's built to be cross-platform: the core logic works on desktop, mobile, and even WebAssembly.
|
||||
* It's very easy to extend: developers can implement customized logic for blockchain backends, databases, signers, coin selection, and more, without having to fork and modify this library.
|
||||
|
||||
## Examples
|
||||
|
||||
### Sync the balance of a descriptor
|
||||
|
||||
```no_run
|
||||
use magical::Wallet;
|
||||
use magical::database::MemoryDatabase;
|
||||
use magical::blockchain::{noop_progress, ElectrumBlockchain};
|
||||
|
||||
use magical::electrum_client::Client;
|
||||
|
||||
fn main() -> Result<(), magical::Error> {
|
||||
let client = Client::new("ssl://electrum.blockstream.info:60002", None)?;
|
||||
let wallet = Wallet::new(
|
||||
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
|
||||
Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
|
||||
bitcoin::Network::Testnet,
|
||||
MemoryDatabase::default(),
|
||||
ElectrumBlockchain::from(client)
|
||||
)?;
|
||||
|
||||
wallet.sync(noop_progress(), None)?;
|
||||
|
||||
println!("Descriptor balance: {} SAT", wallet.get_balance()?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
### Generate a few addresses
|
||||
|
||||
```
|
||||
use magical::{Wallet, OfflineWallet};
|
||||
use magical::database::MemoryDatabase;
|
||||
|
||||
fn main() -> Result<(), magical::Error> {
|
||||
let wallet: OfflineWallet<_> = Wallet::new_offline(
|
||||
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
|
||||
Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
|
||||
bitcoin::Network::Testnet,
|
||||
MemoryDatabase::default(),
|
||||
)?;
|
||||
|
||||
println!("Address #0: {}", wallet.get_new_address()?);
|
||||
println!("Address #1: {}", wallet.get_new_address()?);
|
||||
println!("Address #2: {}", wallet.get_new_address()?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
### Create a transaction
|
||||
|
||||
```no_run
|
||||
use magical::{FeeRate, TxBuilder, Wallet};
|
||||
use magical::database::MemoryDatabase;
|
||||
use magical::blockchain::{noop_progress, ElectrumBlockchain};
|
||||
|
||||
use magical::electrum_client::Client;
|
||||
|
||||
use bitcoin::consensus::serialize;
|
||||
|
||||
fn main() -> Result<(), magical::Error> {
|
||||
let client = Client::new("ssl://electrum.blockstream.info:60002", None)?;
|
||||
let wallet = Wallet::new(
|
||||
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
|
||||
Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
|
||||
bitcoin::Network::Testnet,
|
||||
MemoryDatabase::default(),
|
||||
ElectrumBlockchain::from(client)
|
||||
)?;
|
||||
|
||||
wallet.sync(noop_progress(), None)?;
|
||||
|
||||
let send_to = wallet.get_new_address()?;
|
||||
let (psbt, details) = wallet.create_tx(
|
||||
TxBuilder::with_recipients(vec![(send_to.script_pubkey(), 50_000)])
|
||||
.enable_rbf()
|
||||
.do_not_spend_change()
|
||||
.fee_rate(FeeRate::from_sat_per_vb(5.0))
|
||||
)?;
|
||||
|
||||
println!("Transaction details: {:#?}", details);
|
||||
println!("Unsigned PSBT: {}", base64::encode(&serialize(&psbt)));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
### Sign a transaction
|
||||
|
||||
```no_run
|
||||
use magical::{Wallet, OfflineWallet};
|
||||
use magical::database::MemoryDatabase;
|
||||
|
||||
use bitcoin::consensus::deserialize;
|
||||
|
||||
fn main() -> Result<(), magical::Error> {
|
||||
let wallet: OfflineWallet<_> = Wallet::new_offline(
|
||||
"wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
|
||||
Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
|
||||
bitcoin::Network::Testnet,
|
||||
MemoryDatabase::default(),
|
||||
)?;
|
||||
|
||||
let psbt = "...";
|
||||
let psbt = deserialize(&base64::decode(psbt).unwrap())?;
|
||||
|
||||
let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
3
src/doctest.rs
Normal file
3
src/doctest.rs
Normal file
@ -0,0 +1,3 @@
|
||||
#[doc(include = "../README.md")]
|
||||
#[cfg(doctest)]
|
||||
pub struct ReadmeDoctests;
|
@ -25,6 +25,9 @@
|
||||
// only enables the `doc_cfg` feature when
|
||||
// the `docsrs` configuration attribute is defined
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
// only enables the nightly `external_doc` feature when
|
||||
// `test-md-docs` is enabled
|
||||
#![cfg_attr(feature = "test-md-docs", feature(external_doc))]
|
||||
|
||||
pub extern crate bitcoin;
|
||||
extern crate log;
|
||||
@ -70,6 +73,8 @@ pub(crate) mod error;
|
||||
pub mod blockchain;
|
||||
pub mod database;
|
||||
pub mod descriptor;
|
||||
#[cfg(feature = "test-md-docs")]
|
||||
mod doctest;
|
||||
pub(crate) mod psbt;
|
||||
pub(crate) mod types;
|
||||
pub mod wallet;
|
||||
|
327
static/wizard.svg
Normal file
327
static/wizard.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 125 KiB |
Loading…
x
Reference in New Issue
Block a user