Skip to content

Commit c4f4f20

Browse files
committed
Improve the README, add examples
1 parent 6a2d0db commit c4f4f20

File tree

6 files changed

+484
-4
lines changed

6 files changed

+484
-4
lines changed

.travis.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ env:
1717
- TARGET=x86_64-unknown-linux-gnu FEATURES=cli-utils,esplora NO_DEFAULT_FEATURES=1
1818
- TARGET=x86_64-unknown-linux-gnu FEATURES=compiler NO_DEFAULT_FEATURES=1 RUN_TESTS=1 # Test the `miniscriptc` example
1919
- TARGET=x86_64-unknown-linux-gnu FEATURES=test-electrum NO_DEFAULT_FEATURES=1 RUN_TESTS=1 RUN_CORE=1
20+
- TARGET=x86_64-unknown-linux-gnu FEATURES=test-md-docs NO_DEFAULT_FEATURES=1 RUN_TESTS=1 NIGHTLY=1
2021
- TARGET=wasm32-unknown-unknown FEATURES=cli-utils,esplora NO_DEFAULT_FEATURES=1
2122
before_script:
2223
- |
@@ -33,6 +34,11 @@ before_script:
3334
if [[ $CHECK_FMT -eq 1 ]]; then
3435
rustup component add rustfmt
3536
fi
37+
- |
38+
if [[ $NIGHTLY -eq 1 ]]; then
39+
rustup toolchain install nightly
40+
rustup default nightly
41+
fi
3642
- rustup target add "$TARGET"
3743
script:
3844
- |

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ async-interface = ["async-trait"]
5151
# Debug/Test features
5252
debug-proc-macros = ["magical-macros/debug", "testutils-macros/debug"]
5353
test-electrum = ["electrum"]
54+
test-md-docs = ["base64", "electrum"]
5455

5556
[dev-dependencies]
5657
testutils = { path = "./testutils" }

README.md

Lines changed: 142 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,145 @@
1-
# Magical Bitcoin Wallet
1+
<div align="center">
2+
<h1>Magical Bitcoin Library</h1>
23

3-
A modern, lightweight, descriptor-based wallet written in Rust!
4+
<img src="./static/wizard.svg" width="220" />
45

5-
## Getting Started
6+
<p>
7+
<strong>A modern, lightweight, descriptor-based wallet library written in Rust!</strong>
8+
</p>
69

7-
See the documentation at [magicalbitcoin.org](https://magicalbitcoin.org)
10+
<p>
11+
<a href="https://crates.io/crates/magical"><img alt="Crate Info" src="https://img.shields.io/crates/v/magical.svg"/></a>
12+
<a href="https://docs.rs/magical/"><img alt="API Docs" src="https://img.shields.io/badge/docs.rs-magical-green"/></a>
13+
<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>
14+
</p>
15+
16+
<h4>
17+
<a href="https://magicalbitcoin.org">Project Homepage</a>
18+
<span> | </span>
19+
<a href="https://docs.rs/magical">Documentation</a>
20+
</h4>
21+
</div>
22+
23+
## About
24+
25+
The `magical` library aims to be the core building block for Bitcoin wallets of any kind.
26+
27+
* 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
28+
single-sig wallets, multisigs, timelocked contracts and more.
29+
* It supports multiple blockchain backends and databases, allowing developers to choose exactly what's right for their projects.
30+
* It's built to be cross-platform: the core logic works on desktop, mobile, and even WebAssembly.
31+
* 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.
32+
33+
## Examples
34+
35+
### Sync the balance of a descriptor
36+
37+
```no_run
38+
use magical::Wallet;
39+
use magical::database::MemoryDatabase;
40+
use magical::blockchain::{noop_progress, ElectrumBlockchain};
41+
42+
use magical::electrum_client::Client;
43+
44+
fn main() -> Result<(), magical::Error> {
45+
let client = Client::new("ssl://electrum.blockstream.info:60002", None)?;
46+
let wallet = Wallet::new(
47+
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
48+
Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
49+
bitcoin::Network::Testnet,
50+
MemoryDatabase::default(),
51+
ElectrumBlockchain::from(client)
52+
)?;
53+
54+
wallet.sync(noop_progress(), None)?;
55+
56+
println!("Descriptor balance: {} SAT", wallet.get_balance()?);
57+
58+
Ok(())
59+
}
60+
```
61+
62+
### Generate a few addresses
63+
64+
```
65+
use magical::{Wallet, OfflineWallet};
66+
use magical::database::MemoryDatabase;
67+
68+
fn main() -> Result<(), magical::Error> {
69+
let wallet: OfflineWallet<_> = Wallet::new_offline(
70+
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
71+
Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
72+
bitcoin::Network::Testnet,
73+
MemoryDatabase::default(),
74+
)?;
75+
76+
println!("Address #0: {}", wallet.get_new_address()?);
77+
println!("Address #1: {}", wallet.get_new_address()?);
78+
println!("Address #2: {}", wallet.get_new_address()?);
79+
80+
Ok(())
81+
}
82+
```
83+
84+
### Create a transaction
85+
86+
```no_run
87+
use magical::{FeeRate, TxBuilder, Wallet};
88+
use magical::database::MemoryDatabase;
89+
use magical::blockchain::{noop_progress, ElectrumBlockchain};
90+
91+
use magical::electrum_client::Client;
92+
93+
use bitcoin::consensus::serialize;
94+
95+
fn main() -> Result<(), magical::Error> {
96+
let client = Client::new("ssl://electrum.blockstream.info:60002", None)?;
97+
let wallet = Wallet::new(
98+
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
99+
Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
100+
bitcoin::Network::Testnet,
101+
MemoryDatabase::default(),
102+
ElectrumBlockchain::from(client)
103+
)?;
104+
105+
wallet.sync(noop_progress(), None)?;
106+
107+
let send_to = wallet.get_new_address()?;
108+
let (psbt, details) = wallet.create_tx(
109+
TxBuilder::with_recipients(vec![(send_to.script_pubkey(), 50_000)])
110+
.enable_rbf()
111+
.do_not_spend_change()
112+
.fee_rate(FeeRate::from_sat_per_vb(5.0))
113+
)?;
114+
115+
println!("Transaction details: {:#?}", details);
116+
println!("Unsigned PSBT: {}", base64::encode(&serialize(&psbt)));
117+
118+
Ok(())
119+
}
120+
```
121+
122+
### Sign a transaction
123+
124+
```no_run
125+
use magical::{Wallet, OfflineWallet};
126+
use magical::database::MemoryDatabase;
127+
128+
use bitcoin::consensus::deserialize;
129+
130+
fn main() -> Result<(), magical::Error> {
131+
let wallet: OfflineWallet<_> = Wallet::new_offline(
132+
"wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
133+
Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
134+
bitcoin::Network::Testnet,
135+
MemoryDatabase::default(),
136+
)?;
137+
138+
let psbt = "...";
139+
let psbt = deserialize(&base64::decode(psbt).unwrap())?;
140+
141+
let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
142+
143+
Ok(())
144+
}
145+
```

src/doctest.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#[doc(include = "../README.md")]
2+
#[cfg(doctest)]
3+
pub struct ReadmeDoctests;

src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
// only enables the `doc_cfg` feature when
2626
// the `docsrs` configuration attribute is defined
2727
#![cfg_attr(docsrs, feature(doc_cfg))]
28+
// only enables the nightly `external_doc` feature when
29+
// `test-md-docs` is enabled
30+
#![cfg_attr(feature = "test-md-docs", feature(external_doc))]
2831

2932
pub extern crate bitcoin;
3033
extern crate log;
@@ -70,6 +73,8 @@ pub(crate) mod error;
7073
pub mod blockchain;
7174
pub mod database;
7275
pub mod descriptor;
76+
#[cfg(feature = "test-md-docs")]
77+
mod doctest;
7378
pub(crate) mod psbt;
7479
pub(crate) mod types;
7580
pub mod wallet;

0 commit comments

Comments
 (0)