Skip to content

Commit

Permalink
feat: send giftwraps
Browse files Browse the repository at this point in the history
  • Loading branch information
thesimplekid committed Oct 24, 2024
1 parent 9e375bd commit 96374a6
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 6 deletions.
3 changes: 2 additions & 1 deletion crates/cdk-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ rand = "0.8.5"
home = "0.5.5"
nostr-sdk = { version = "0.35.0", default-features = false, features = [
"nip04",
"nip44"
"nip44",
"nip59"
]}
reqwest = { version = "0.12", default-features = false, features = [
"json",
Expand Down
13 changes: 9 additions & 4 deletions crates/cdk-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,10 @@ enum Commands {
UpdateMintUrl(sub_commands::update_mint_url::UpdateMintUrlSubCommand),
/// Get proofs from mint.
ListMintProofs,
/// Decode a token
DecodePaymentRequest(sub_commands::decode_payment_request::DecodePaymentRequestSubCommand),
/// Decode a payment request
DecodeRequest(sub_commands::decode_request::DecodePaymentRequestSubCommand),
/// Pay a payment request
PayRequest(sub_commands::pay_request::PayRequestSubCommand),
}

#[tokio::main]
Expand Down Expand Up @@ -206,8 +208,11 @@ async fn main() -> Result<()> {
Commands::ListMintProofs => {
sub_commands::list_mint_proofs::proofs(&multi_mint_wallet).await
}
Commands::DecodePaymentRequest(sub_command_args) => {
sub_commands::decode_payment_request::decode_payment_request(sub_command_args)
Commands::DecodeRequest(sub_command_args) => {
sub_commands::decode_request::decode_payment_request(sub_command_args)
}
Commands::PayRequest(sub_command_args) => {
sub_commands::pay_request::pay_request(&multi_mint_wallet, sub_command_args).await
}
}
}
3 changes: 2 additions & 1 deletion crates/cdk-cli/src/sub_commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
pub mod balance;
pub mod burn;
pub mod check_spent;
pub mod decode_payment_request;
pub mod decode_request;
pub mod decode_token;
pub mod list_mint_proofs;
pub mod melt;
pub mod mint;
pub mod mint_info;
pub mod pay_request;
pub mod pending_mints;
pub mod receive;
pub mod restore;
Expand Down
177 changes: 177 additions & 0 deletions crates/cdk-cli/src/sub_commands/pay_request.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
use std::io::{self, Write};

use anyhow::{anyhow, Result};
use cdk::{
amount::SplitTarget,
nuts::{nut18::TransportType, PaymentRequest, PaymentRequestPayload},
wallet::{MultiMintWallet, SendKind},
};
use clap::Args;
use nostr_sdk::{nips::nip19::Nip19Profile, Client as NostrClient, EventBuilder, FromBech32, Keys};
use reqwest::Client;

#[derive(Args)]
pub struct PayRequestSubCommand {
payment_request: PaymentRequest,
}

pub async fn pay_request(
multi_mint_wallet: &MultiMintWallet,
sub_command_args: &PayRequestSubCommand,
) -> Result<()> {
let payment_request = &sub_command_args.payment_request;

let unit = payment_request.unit;

let amount = match payment_request.amount {
Some(amount) => amount,
None => {
println!("Enter the amount you would like to pay");

let mut user_input = String::new();
let stdin = io::stdin();
io::stdout().flush().unwrap();
stdin.read_line(&mut user_input)?;

let amount: u64 = user_input.trim().parse()?;

amount.into()
}
};

let request_mints = &payment_request.mints;

let wallet_mints = multi_mint_wallet.get_wallets().await;

// Wallets where unit, balance and mint match request
let mut matching_wallets = vec![];

for wallet in wallet_mints.iter() {
let balance = wallet.total_balance().await?;

if let Some(request_mints) = request_mints {
if !request_mints.contains(&wallet.mint_url) {
continue;
}
}

if let Some(unit) = unit {
if wallet.unit != unit {
continue;
}
}

if balance >= amount {
matching_wallets.push(wallet);
}
}

let matching_wallet = matching_wallets.first().unwrap();

// We prefer nostr transport if it is available to hide ip.
let transport = payment_request
.transports
.iter()
.find(|t| t._type == TransportType::Nostr)
.or_else(|| {
payment_request
.transports
.iter()
.find(|t| t._type == TransportType::HttpPost)
})
.ok_or(anyhow!("No supported transport method found"))?;

let proofs = matching_wallet
.send(
amount,
None,
None,
&SplitTarget::default(),
&SendKind::default(),
true,
)
.await?
.proofs()
.get(&matching_wallet.mint_url)
.unwrap()
.clone();

let payload = PaymentRequestPayload {
id: payment_request.payment_id.clone(),
memo: None,
mint: matching_wallet.mint_url.clone(),
unit: matching_wallet.unit,
proofs,
};

match transport._type {
TransportType::Nostr => {
let keys = Keys::generate();
let client = NostrClient::new(keys);
let nprofile = Nip19Profile::from_bech32(&transport.target)?;

println!("{:?}", nprofile.relays);

let rumor = EventBuilder::new(
nostr_sdk::Kind::from_u16(14),
serde_json::to_string(&payload)?,
[],
);

let relays = nprofile.relays;

for relay in relays.iter() {
client.add_write_relay(relay).await?;
}

client.connect().await;

let gift_wrap = client
.gift_wrap_to(relays, &nprofile.public_key, rumor, None)
.await?;

println!(
"Published event {} succufully to {}",
gift_wrap.val,
gift_wrap
.success
.iter()
.map(|s| s.to_string())
.collect::<Vec<_>>()
.join(", ")
);

if !gift_wrap.failed.is_empty() {
println!(
"Could not publish to {:?}",
gift_wrap
.failed
.iter()
.map(|(relay, _s)| relay.to_string())
.collect::<Vec<_>>()
.join(", ")
);
}
}

TransportType::HttpPost => {
let client = Client::new();

let res = client
.post(transport.target.clone())
.json(&payload)
.send()
.await?;

let status = res.status();
if status.is_success() {
println!("Successfully posted payment");
} else {
println!("{:?}", res);
println!("Error posting payment");
}
}
}

Ok(())
}

0 comments on commit 96374a6

Please sign in to comment.