1 unstable release
Uses old Rust 2015
0.0.0 | Dec 26, 2024 |
---|
#366 in #pool
125 downloads per month
2KB
Disclaimer
This library is at (very) experimental stage, we do not advice to use it on mainnet. There is still some minor differences at the protocol level between this implementation and the python & kotlin implementations, but we should fix it soon.
Sponsorship
Joinstr protocol
Transaction Inputs/Outputs types
As of now, we have only implemented the protocol for using Segwitv0 inputs & outputs.
VPN/Tor
For now there is no plan to implement VPN or Tor support in this lib, as it's expected to be handled at consumer or OS level.
Build
Install Rust toolchain (see here)
and run this from this repo:
cargo run --release
Run the tests
cargo tests
Usage
Run a standalone coordinator
let mut coordinator = Joinstr::new_initiator(
Keys::generate(),
&vec!["wss://relay.nostr".into()],
("127.0.0.1", 2121),
Network::Regtest,
"initiator",
)
.await
.unwrap()
.denomination(0.01)
.unwrap()
.fee(10)
.unwrap()
.simple_timeout(now() + 3 * 60 * 60)
.unwrap()
.min_peers(5)
.unwrap();
coordinator
.start_coinjoin(None, Option::<&WpkhHotSigner>::None)
.await
.unwrap();
Initiate a pool
// create an electrum client
let client = Client::new_local("127.0.0.1", 2121).unwrap();
// create the signer
let mnemonic =
"define jealous drill wrap item shallow chest balcony domain dignity runway year";
let mut signer = WpkhHotSigner::new_from_mnemonics(Network::Regtest, mnemonic).unwrap();
signer.set_client(client);
// fetch the coin you want to add to the pool
let coins = signer
.get_coins_at(CoinPath {
depth: 0,
index: Some(0),
})
.unwrap();
assert_eq!(coins, 1);
let coin = signer.list_coins().into_iter().next().unwrap();
// generate the output address
let address = signer
.address_at(&CoinPath {
depth: 0,
index: Some(100),
})
.unwrap()
.as_unchecked()
.clone();
// create a peer that will also be a coordinator
let mut peer = Joinstr::new_peer(
&vec!["wss://relay.nostr".into()],
&pool,
coin.1,
address,
Network::Regtest,
"peer_a",
)
.await
.unwrap()
.denomination(0.01)
.unwrap()
.fee(10)
.unwrap()
.simple_timeout(now() + 3 * 60 * 60)
.unwrap()
.min_peers(5)
.unwrap();
// try to run the coinjoin
peer.start_coinjoin(None, Some(&signer))
.await
.unwrap();
Join a pool as peer
// create a nostr client and listen for pool notification
let mut pool_listener = NostrClient::new("pool_listener")
.relays(&vec!["wss://relay.nostr".into()])
.unwrap()
.keys(Keys::generate())
.unwrap();
pool_listener.connect_nostr().await.unwrap();
// subscribe to pool notifications that have been initiated 2 hours back in time
pool_listener.subscribe_pools(2 * 60 * 60).await.unwrap();
// wait to receive notifications
sleep(Duration::from_millis(3000)).await;
// list received notifications
let mut pools = Vec::new();
while let Some(pool) = pool_listener.receive_pool_notification().unwrap() {
pools.push(pool)
}
// select the pool you want to join (like by pool denomination and network config)
let pool = pools.into_iter().next().unwrap();
// create an electrum client
let client = Client::new_local("127.0.0.1", 2121).unwrap();
// create the signer
let mnemonic =
"define jealous drill wrap item shallow chest balcony domain dignity runway year";
let mut signer = WpkhHotSigner::new_from_mnemonics(Network::Regtest, mnemonic).unwrap();
signer.set_client(client);
// fetch the coin you want to add to the pool
let coins = signer
.get_coins_at(CoinPath {
depth: 0,
index: Some(0),
})
.unwrap();
assert_eq!(coins, 1);
let coin = signer.list_coins().into_iter().next().unwrap();
// generate the output address
let address = signer
.address_at(&CoinPath {
depth: 0,
index: Some(100),
})
.unwrap()
.as_unchecked()
.clone();
// create a peer that will also be a coordinator
let mut peer = Joinstr::new_peer(
&vec!["wss://relay.nostr".into()],
&pool,
coin.1,
address,
Network::Regtest,
"peer_a",
)
.await
.unwrap();
// try to run the coinjoin
peer.start_coinjoin(Some(pool), Some(&signer))
.await
.unwrap();