1use std::str::FromStr;
5
6use bip351::*;
7use bitcoin::hashes::hex::{FromHex, ToHex};
8use bitcoin::Network;
9
10fn main() -> std::io::Result<()> {
11 let secp = bitcoin::secp256k1::Secp256k1::new();
12
13 let payment_code = prompt("Enter the recipient's payment code").unwrap();
14 let payment_code = PaymentCode::from_str(&payment_code).expect("Invalid payment code");
15
16 let sender_seed = prompt("Enter the sender's hex-encoded BIP39 seed").unwrap();
17 let sender_seed: Vec<u8> = FromHex::from_hex(&sender_seed).expect("Not a hex-encoded seed");
18
19 let network = prompt("Enter 0 for mainnet or 1 for testnet").unwrap();
20 let network = match network.as_str() {
21 "0" => Network::Bitcoin,
22 "1" => Network::Testnet,
23 _ => panic!("unknown network"),
24 };
25
26 let recipient_index = prompt("Enter a numerical recipient index").unwrap();
27 let recipient_index: u32 = recipient_index
28 .parse()
29 .expect("Not a valid unsigned integer");
30
31 let sender = Sender::from_seed(&secp, &sender_seed, network, 0).unwrap();
32
33 println!("The recipient supports the following address types:");
34 let accepted_addresses: Vec<_> = payment_code.address_types().iter().collect();
35 for (index, addr_type) in accepted_addresses.iter().enumerate() {
36 println!("({}): {:?}", index, addr_type);
37 }
38
39 let ordinal = prompt("Pick the number next to the address type you want to use").unwrap();
40 let addr_type = accepted_addresses
41 .into_iter()
42 .nth(ordinal.parse().expect("Not a valid integer"))
43 .expect("Index out of range")
44 .clone();
45
46 let (txout, _) = sender
47 .notify(&secp, &payment_code, recipient_index, addr_type)
48 .unwrap();
49 let payload = txout.script_pubkey.as_bytes()[2..].to_hex();
50 println!("The notification OP_RETURN payload is:\n{}", payload);
51
52 Ok(())
53}
54
55fn prompt(prompt: &str) -> std::io::Result<String> {
57 println!("{}:", prompt);
58 let mut value = String::new();
59 std::io::stdin().read_line(&mut value)?;
60 assert_eq!(Some('\n'), value.pop());
61 Ok(value)
62}