refactor capability building

This commit is contained in:
daywalker90 2025-11-09 16:02:15 +01:00
parent 4cc965bf0b
commit 53a3d37f02
No known key found for this signature in database
6 changed files with 81 additions and 54 deletions

View file

@ -47,16 +47,15 @@ pub const WALLET_READ_METHODS: [nip47::Method; 5] = [
nip47::Method::GetBalance,
nip47::Method::GetInfo,
];
pub const WALLET_ALL_METHODS: [nip47::Method; 9] = [
pub const WALLET_PAY_METHODS: [nip47::Method; 4] = [
nip47::Method::PayInvoice,
nip47::Method::MultiPayInvoice,
nip47::Method::PayKeysend,
nip47::Method::MultiPayKeysend,
WALLET_READ_METHODS[0],
WALLET_READ_METHODS[1],
WALLET_READ_METHODS[2],
WALLET_READ_METHODS[3],
WALLET_READ_METHODS[4],
];
pub const WALLET_NOTIFICATIONS: [nip47::NotificationType; 2] = [
nip47::NotificationType::PaymentReceived,
nip47::NotificationType::PaymentSent,
];
#[tokio::main]

View file

@ -8,8 +8,8 @@ use crate::nwc_lookups::{list_transactions, lookup_invoice};
use crate::nwc_pay::{multi_pay_invoice, pay_invoice};
use crate::structs::{NwcStore, PluginState};
use crate::tasks::budget_task;
use crate::util::is_read_only_nwc;
use crate::{OPT_NOTIFICATIONS, WALLET_ALL_METHODS, WALLET_READ_METHODS};
use crate::util::{build_capabilities, build_notifications_vec, is_read_only_nwc};
use crate::OPT_NOTIFICATIONS;
use anyhow::anyhow;
use cln_plugin::Plugin;
use nostr_sdk::client;
@ -39,11 +39,7 @@ pub async fn run_nwc(
label: String,
nwc_store: NwcStore,
) -> Result<(), client::Error> {
let capabilities = if is_read_only_nwc(&nwc_store) {
WALLET_READ_METHODS.map(|c| c.as_str().to_owned()).join(" ")
} else {
WALLET_ALL_METHODS.map(|c| c.as_str().to_owned()).join(" ")
};
let (method_capabilities, _) = build_capabilities(is_read_only_nwc(&nwc_store), &plugin);
let wallet_keys = Keys::new(
SecretKey::from_hex(&nwc_store.walletkey)
@ -93,9 +89,9 @@ pub async fn run_nwc(
}
if let Err(e) = send_nwc_info_event(
plugin_clone.clone(),
client_clone.clone(),
plugin_clone.option(&OPT_NOTIFICATIONS).unwrap(),
capabilities.clone(),
method_capabilities.clone(),
wallet_keys.clone(),
)
.await
@ -154,21 +150,22 @@ pub async fn run_nwc(
}
pub async fn send_nwc_info_event(
plugin: Plugin<PluginState>,
client: Client,
notifications: bool,
capabilities: String,
wallet_keys: Keys,
) -> Result<(), anyhow::Error> {
let mut capabilities = capabilities;
if notifications {
if plugin.option(&OPT_NOTIFICATIONS).unwrap() {
capabilities.push_str(" notifications");
}
let mut info_event_builder = EventBuilder::new(Kind::WalletConnectInfo, capabilities)
.tag(Tag::parse(vec!["encryption", "nip44_v2 nip04"]).unwrap());
if notifications {
if plugin.option(&OPT_NOTIFICATIONS).unwrap() {
let notification_capabilities = build_notifications_vec(&plugin).join(" ");
info_event_builder = info_event_builder
.tag(Tag::parse(vec!["notifications", "payment_received payment_sent"]).unwrap());
.tag(Tag::parse(vec!["notifications", &notification_capabilities]).unwrap());
}
let info_event = match info_event_builder.sign_with_keys(&wallet_keys) {

View file

@ -2,8 +2,7 @@ use cln_plugin::Plugin;
use cln_rpc::model::requests::GetinfoRequest;
use crate::structs::PluginState;
use crate::util::{is_read_only_nwc, load_nwc_store};
use crate::{OPT_NOTIFICATIONS, WALLET_ALL_METHODS, WALLET_READ_METHODS};
use crate::util::{build_methods_vec, build_notifications_vec, is_read_only_nwc, load_nwc_store};
use nostr_sdk::nips::nip47;
pub async fn get_info(
@ -26,11 +25,6 @@ pub async fn get_info(
"bitcoin" => "mainnet".to_owned(),
_ => get_info.network,
};
let notifications = if plugin.option(&OPT_NOTIFICATIONS).unwrap() {
vec!["payment_received".to_owned(), "payment_sent".to_owned()]
} else {
vec![]
};
let nwc_store = load_nwc_store(&mut rpc, label)
.await
@ -39,11 +33,9 @@ pub async fn get_info(
message: e.to_string(),
})?;
let methods = if is_read_only_nwc(&nwc_store) {
WALLET_READ_METHODS.to_vec()
} else {
WALLET_ALL_METHODS.to_vec()
};
let notifications = build_notifications_vec(&plugin);
let methods = build_methods_vec(is_read_only_nwc(&nwc_store), &plugin);
Ok(nip47::GetInfoResponse {
alias: get_info.alias,

View file

@ -14,8 +14,9 @@ use crate::nwc::{
};
use crate::parse::parse_time_period;
use crate::structs::{BudgetIntervalConfig, NwcStore, PluginState};
use crate::util::build_capabilities;
use crate::util::{is_read_only_nwc, load_nwc_store, update_nwc_store};
use crate::{OPT_NOTIFICATIONS, PLUGIN_NAME, WALLET_ALL_METHODS, WALLET_READ_METHODS};
use crate::PLUGIN_NAME;
pub async fn nwc_create(
plugin: Plugin<PluginState>,
@ -148,20 +149,16 @@ pub async fn nwc_budget(
if is_old_nwc_read_only != is_new_nwc_read_only {
let wallet_keys = Keys::new(SecretKey::from_hex(&nwc_store.walletkey)?);
let capabilities = if is_new_nwc_read_only {
WALLET_READ_METHODS.map(|c| c.as_str().to_owned()).join(" ")
} else {
WALLET_ALL_METHODS.map(|c| c.as_str().to_owned()).join(" ")
};
let (method_capabilities, _) = build_capabilities(is_new_nwc_read_only, &plugin);
let clients = plugin.state().handles.lock().await;
send_nwc_info_event(
plugin.clone(),
clients
.get(&label)
.ok_or_else(|| anyhow!("No client found for label: {label}"))?
.0
.clone(),
plugin.option(&OPT_NOTIFICATIONS).unwrap(),
capabilities,
method_capabilities,
wallet_keys,
)
.await?;

View file

@ -1,10 +1,16 @@
use anyhow::anyhow;
use cln_plugin::Plugin;
use cln_rpc::{
model::requests::{DatastoreMode, DatastoreRequest, ListdatastoreRequest},
ClnRpc,
};
use crate::{structs::NwcStore, PLUGIN_NAME};
use nostr_sdk::nips::nip47;
use crate::{
structs::{NwcStore, PluginState},
OPT_NOTIFICATIONS, PLUGIN_NAME, WALLET_NOTIFICATIONS, WALLET_PAY_METHODS, WALLET_READ_METHODS,
};
pub fn budget_amount_check(
request_amt_msat: Option<u64>,
@ -114,6 +120,42 @@ pub fn at_or_above_version(my_version: &str, min_version: &str) -> Result<bool,
Ok(my_version_parts.len() >= min_version_parts.len())
}
pub fn build_capabilities(is_read_only: bool, plugin: &Plugin<PluginState>) -> (String, String) {
let mut methods = WALLET_READ_METHODS.map(|m| m.to_string()).join(" ");
if !is_read_only {
methods.push(' ');
methods.push_str(WALLET_PAY_METHODS.map(|m| m.to_string()).join(" ").as_str());
}
let mut notifications = String::new();
if plugin.option(&OPT_NOTIFICATIONS).unwrap() {
notifications.push_str(
WALLET_NOTIFICATIONS
.map(|m| m.to_string())
.join(" ")
.as_str(),
);
}
(methods, notifications)
}
pub fn build_methods_vec(is_read_only: bool, _plugin: &Plugin<PluginState>) -> Vec<nip47::Method> {
let mut methods = WALLET_READ_METHODS.to_vec();
if !is_read_only {
methods.extend_from_slice(&WALLET_PAY_METHODS);
}
methods
}
pub fn build_notifications_vec(plugin: &Plugin<PluginState>) -> Vec<String> {
let mut notifications = Vec::new();
if plugin.option(&OPT_NOTIFICATIONS).unwrap() {
notifications.extend_from_slice(&WALLET_NOTIFICATIONS.map(|m| m.to_string()));
}
notifications
}
#[test]
fn test_budget_check() {
assert!(budget_amount_check(Some(1), Some(1), Some(2)).is_ok());

View file

@ -103,15 +103,15 @@ async def test_get_info(node_factory, get_plugin, nostr_client): # noqa: F811
assert get_info.block_height == node_get_info["blockheight"]
assert get_info.color == node_get_info["color"]
assert get_info.methods == [
Method.PAY_INVOICE,
Method.MULTI_PAY_INVOICE,
Method.PAY_KEYSEND,
Method.MULTI_PAY_KEYSEND,
Method.MAKE_INVOICE,
Method.LOOKUP_INVOICE,
Method.LIST_TRANSACTIONS,
Method.GET_BALANCE,
Method.GET_INFO,
Method.PAY_INVOICE,
Method.MULTI_PAY_INVOICE,
Method.PAY_KEYSEND,
Method.MULTI_PAY_KEYSEND,
]
assert get_info.network == "regtest"
assert get_info.notifications == ["payment_received", "payment_sent"]
@ -132,15 +132,15 @@ async def test_get_info(node_factory, get_plugin, nostr_client): # noqa: F811
assert get_info.block_height == node_get_info["blockheight"]
assert get_info.color == node_get_info["color"]
assert get_info.methods == [
Method.PAY_INVOICE,
Method.MULTI_PAY_INVOICE,
Method.PAY_KEYSEND,
Method.MULTI_PAY_KEYSEND,
Method.MAKE_INVOICE,
Method.LOOKUP_INVOICE,
Method.LIST_TRANSACTIONS,
Method.GET_BALANCE,
Method.GET_INFO,
Method.PAY_INVOICE,
Method.MULTI_PAY_INVOICE,
Method.PAY_KEYSEND,
Method.MULTI_PAY_KEYSEND,
]
assert get_info.network == "regtest"
assert get_info.notifications == []
@ -163,7 +163,7 @@ async def test_get_info(node_factory, get_plugin, nostr_client): # noqa: F811
events_vec = events.to_vec()
assert (
events_vec[0].content()
== "pay_invoice multi_pay_invoice pay_keysend multi_pay_keysend make_invoice lookup_invoice list_transactions get_balance get_info"
== "make_invoice lookup_invoice list_transactions get_balance get_info pay_invoice multi_pay_invoice pay_keysend multi_pay_keysend"
)
assert (
events_vec[0].tags().find(TagKind.UNKNOWN("encryption")).content()
@ -1245,15 +1245,15 @@ async def test_budget_command(node_factory, get_plugin, nostr_client): # noqa:
get_info = await nwc.get_info()
assert get_info.methods == [
Method.PAY_INVOICE,
Method.MULTI_PAY_INVOICE,
Method.PAY_KEYSEND,
Method.MULTI_PAY_KEYSEND,
Method.MAKE_INVOICE,
Method.LOOKUP_INVOICE,
Method.LIST_TRANSACTIONS,
Method.GET_BALANCE,
Method.GET_INFO,
Method.PAY_INVOICE,
Method.MULTI_PAY_INVOICE,
Method.PAY_KEYSEND,
Method.MULTI_PAY_KEYSEND,
]
signer = NostrSigner.keys(Keys(uri.secret()))
@ -1273,7 +1273,7 @@ async def test_budget_command(node_factory, get_plugin, nostr_client): # noqa:
events_vec = events.to_vec()
assert (
events_vec[0].content()
== "pay_invoice multi_pay_invoice pay_keysend multi_pay_keysend make_invoice lookup_invoice list_transactions get_balance get_info notifications"
== "make_invoice lookup_invoice list_transactions get_balance get_info pay_invoice multi_pay_invoice pay_keysend multi_pay_keysend notifications"
)
assert (
events_vec[0].tags().find(TagKind.UNKNOWN("encryption")).content()