Skip to content

pythcoiner/joinstr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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

R&D Sponsored By Bull Bitcoin

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();

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages