hashtree_cli/
cashu_helper.rs1pub use cashu_service::{
2 base_helper_args, helper_binary_name, helper_binary_path, run_helper_status, CashuHelperClient,
3 CashuMintBalance, CashuPaymentClient, CashuReceivedPayment, CashuSentPayment, CARGO_HELPER_ENV,
4 CASHU_HELPER_ENV,
5};
6
7#[cfg(test)]
8mod tests {
9 use super::*;
10 use crate::test_support::test_env_lock;
11 use serde_json::json;
12 use std::env;
13 #[cfg(unix)]
14 use std::os::unix::fs::PermissionsExt;
15 use std::path::Path;
16
17 #[test]
18 fn test_helper_binary_path_prefers_env_override() {
19 let _guard = test_env_lock()
20 .lock()
21 .unwrap_or_else(|err| err.into_inner());
22 let temp_dir = tempfile::tempdir().unwrap();
23 let override_path = temp_dir.path().join("custom-helper");
24 std::fs::write(&override_path, b"").unwrap();
25
26 env::set_var(CASHU_HELPER_ENV, &override_path);
27 env::remove_var(CARGO_HELPER_ENV);
28
29 let resolved = helper_binary_path(Path::new("/tmp/htree")).unwrap();
30 assert_eq!(resolved, override_path);
31
32 env::remove_var(CASHU_HELPER_ENV);
33 }
34
35 #[test]
36 fn test_helper_binary_path_falls_back_to_sibling_binary() {
37 let _guard = test_env_lock()
38 .lock()
39 .unwrap_or_else(|err| err.into_inner());
40 env::remove_var(CASHU_HELPER_ENV);
41 env::remove_var(CARGO_HELPER_ENV);
42
43 let temp_dir = tempfile::tempdir().unwrap();
44 let current_exe = temp_dir.path().join("htree");
45 std::fs::write(¤t_exe, b"").unwrap();
46 let sibling = temp_dir.path().join(helper_binary_name());
47 std::fs::write(&sibling, b"").unwrap();
48
49 let resolved = helper_binary_path(¤t_exe).unwrap();
50 assert_eq!(resolved, sibling);
51 }
52
53 #[cfg(unix)]
54 #[tokio::test]
55 #[allow(clippy::await_holding_lock)]
56 async fn test_cashu_helper_client_send_and_receive_json() {
57 let _guard = test_env_lock()
58 .lock()
59 .unwrap_or_else(|err| err.into_inner());
60 env::remove_var(CARGO_HELPER_ENV);
61
62 let temp_dir = tempfile::tempdir().unwrap();
63 let helper_path = temp_dir.path().join("htree-cashu-stub");
64 let script = format!(
65 "#!/bin/sh\nif [ \"$3\" = \"internal\" ] && [ \"$4\" = \"send\" ]; then\n printf '%s' '{}'\nelif [ \"$3\" = \"internal\" ] && [ \"$4\" = \"receive\" ]; then\n cat >/dev/null\n printf '%s' '{}'\nelse\n printf '%s' '{}'\nfi\n",
66 json!({
67 "mint_url": "https://mint.example",
68 "unit": "sat",
69 "amount_sat": 3,
70 "send_fee_sat": 1,
71 "operation_id": "op-123",
72 "token": "cashuBtoken"
73 }),
74 json!({
75 "mint_url": "https://mint.example",
76 "unit": "sat",
77 "amount_sat": 3
78 }),
79 json!({"ok": true}),
80 );
81 std::fs::write(&helper_path, script).unwrap();
82 let mut perms = std::fs::metadata(&helper_path).unwrap().permissions();
83 perms.set_mode(0o755);
84 std::fs::set_permissions(&helper_path, perms).unwrap();
85
86 env::set_var(CASHU_HELPER_ENV, &helper_path);
87 let client = CashuHelperClient::discover(temp_dir.path()).unwrap();
88
89 let sent = client
90 .send_payment("https://mint.example", 3)
91 .await
92 .unwrap();
93 assert_eq!(sent.amount_sat, 3);
94 assert_eq!(sent.send_fee_sat, 1);
95 assert_eq!(sent.operation_id, "op-123");
96
97 let received = client.receive_payment("cashuBtoken").await.unwrap();
98 assert_eq!(received.amount_sat, 3);
99 assert_eq!(received.mint_url, "https://mint.example");
100
101 client
102 .revoke_payment("https://mint.example", "op-123")
103 .await
104 .unwrap();
105
106 env::remove_var(CASHU_HELPER_ENV);
107 }
108
109 #[cfg(unix)]
110 #[tokio::test]
111 #[allow(clippy::await_holding_lock)]
112 async fn test_cashu_helper_client_queries_mint_balance_json() {
113 let _guard = test_env_lock()
114 .lock()
115 .unwrap_or_else(|err| err.into_inner());
116 env::remove_var(CARGO_HELPER_ENV);
117
118 let temp_dir = tempfile::tempdir().unwrap();
119 let helper_path = temp_dir.path().join("htree-cashu-stub");
120 let script = format!(
121 "#!/bin/sh\nif [ \"$3\" = \"internal\" ] && [ \"$4\" = \"balance\" ]; then\n printf '%s' '{}'\nelse\n printf '%s' '{}'\nfi\n",
122 json!({
123 "mint_url": "https://mint.example",
124 "unit": "sat",
125 "balance_sat": 21
126 }),
127 json!({"ok": true}),
128 );
129 std::fs::write(&helper_path, script).unwrap();
130 let mut perms = std::fs::metadata(&helper_path).unwrap().permissions();
131 perms.set_mode(0o755);
132 std::fs::set_permissions(&helper_path, perms).unwrap();
133
134 env::set_var(CASHU_HELPER_ENV, &helper_path);
135 let client = CashuHelperClient::discover(temp_dir.path()).unwrap();
136 let balance = client.mint_balance("https://mint.example").await.unwrap();
137 assert_eq!(balance.mint_url, "https://mint.example");
138 assert_eq!(balance.unit, "sat");
139 assert_eq!(balance.balance_sat, 21);
140
141 env::remove_var(CASHU_HELPER_ENV);
142 }
143}