Skip to content
This repository was archived by the owner on Feb 3, 2025. It is now read-only.

Commit 6a68884

Browse files
committed
Refactor primal apis to single PrimalClient
1 parent 5692c67 commit 6a68884

File tree

4 files changed

+169
-105
lines changed

4 files changed

+169
-105
lines changed

mutiny-core/src/lib.rs

Lines changed: 41 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ use crate::{
7676
use crate::{nostr::NostrManager, utils::sleep};
7777
use ::nostr::nips::nip57;
7878
use ::nostr::prelude::ZapRequestData;
79-
use ::nostr::{Event, EventId, JsonUtil, Kind, Metadata};
79+
use ::nostr::{EventId, JsonUtil, Kind};
8080
use async_lock::RwLock;
8181
use bdk_chain::ConfirmationTime;
8282
use bip39::Mnemonic;
@@ -103,7 +103,7 @@ use moksha_core::token::TokenV3;
103103
use nostr_sdk::{Client, RelayPoolNotification};
104104
use reqwest::multipart::{Form, Part};
105105
use serde::{Deserialize, Serialize};
106-
use serde_json::{json, Value};
106+
use serde_json::Value;
107107
use std::sync::Arc;
108108
#[cfg(not(target_arch = "wasm32"))]
109109
use std::time::Instant;
@@ -114,7 +114,6 @@ use uuid::Uuid;
114114
use crate::labels::LabelItem;
115115
use crate::nostr::NostrKeySource;
116116
use crate::storage::{persist_payment_info, SUBSCRIPTION_TIMESTAMP};
117-
use crate::utils::parse_profile_metadata;
118117
#[cfg(test)]
119118
use mockall::{automock, predicate::*};
120119

@@ -790,6 +789,7 @@ impl<S: MutinyStorage> MutinyWalletBuilder<S> {
790789
self.xprivkey,
791790
self.nostr_key_source,
792791
self.storage.clone(),
792+
config.primal_url.clone(),
793793
logger.clone(),
794794
stop.clone(),
795795
)?);
@@ -1733,24 +1733,6 @@ impl<S: MutinyStorage> MutinyWallet<S> {
17331733
Err(MutinyError::NostrError)
17341734
}
17351735

1736-
/// Makes a request to the primal api
1737-
async fn primal_request(
1738-
client: &reqwest::Client,
1739-
url: &str,
1740-
body: Value,
1741-
) -> Result<Vec<Value>, MutinyError> {
1742-
client
1743-
.post(url)
1744-
.header("Content-Type", "application/json")
1745-
.body(body.to_string())
1746-
.send()
1747-
.await
1748-
.map_err(|_| MutinyError::NostrError)?
1749-
.json()
1750-
.await
1751-
.map_err(|_| MutinyError::NostrError)
1752-
}
1753-
17541736
/// Syncs all of our nostr data from the configured primal instance
17551737
pub async fn sync_nostr(&self) -> Result<(), MutinyError> {
17561738
let contacts_fut = self.sync_nostr_contacts(self.nostr.public_key);
@@ -1766,24 +1748,12 @@ impl<S: MutinyStorage> MutinyWallet<S> {
17661748

17671749
/// Fetches our latest nostr profile from primal and saves to storage
17681750
async fn sync_nostr_profile(&self) -> Result<(), MutinyError> {
1769-
let url = self
1770-
.config
1771-
.primal_url
1772-
.as_deref()
1773-
.unwrap_or("https://primal-cache.mutinywallet.com/api");
1774-
let client = reqwest::Client::new();
1775-
1776-
let body = json!(["user_profile", { "pubkey": self.nostr.public_key } ]);
1777-
let data: Vec<Value> = Self::primal_request(&client, url, body).await?;
1778-
1779-
if let Some(json) = data.first().cloned() {
1780-
let event: Event = serde_json::from_value(json).map_err(|_| MutinyError::NostrError)?;
1781-
if event.kind != Kind::Metadata {
1782-
return Ok(());
1783-
}
1784-
1785-
let metadata: Metadata =
1786-
serde_json::from_str(&event.content).map_err(|_| MutinyError::NostrError)?;
1751+
if let Some(metadata) = self
1752+
.nostr
1753+
.primal_client
1754+
.get_user_profile(self.nostr.public_key)
1755+
.await?
1756+
{
17871757
self.storage.set_nostr_profile(metadata)?;
17881758
}
17891759

@@ -1792,35 +1762,28 @@ impl<S: MutinyStorage> MutinyWallet<S> {
17921762

17931763
/// Get contacts from the given npub and sync them to the wallet
17941764
pub async fn sync_nostr_contacts(&self, npub: ::nostr::PublicKey) -> Result<(), MutinyError> {
1795-
let url = self
1796-
.config
1797-
.primal_url
1798-
.as_deref()
1799-
.unwrap_or("https://primal-cache.mutinywallet.com/api");
1800-
let client = reqwest::Client::new();
1801-
1802-
let body = json!(["contact_list", { "pubkey": npub } ]);
1803-
let data: Vec<Value> = Self::primal_request(&client, url, body).await?;
1804-
let mut metadata = parse_profile_metadata(data);
1765+
let mut metadata = self.nostr.primal_client.get_nostr_contacts(npub).await?;
18051766

18061767
let contacts = self.storage.get_contacts()?;
18071768

18081769
// get contacts that weren't in our npub contacts list
1809-
let missing_pks: Vec<String> = contacts
1770+
let missing_pks: Vec<::nostr::PublicKey> = contacts
18101771
.iter()
18111772
.filter_map(|(_, c)| {
18121773
if c.npub.is_some_and(|n| metadata.get(&n).is_none()) {
1813-
c.npub.map(|n| n.to_hex())
1774+
c.npub
18141775
} else {
18151776
None
18161777
}
18171778
})
18181779
.collect();
18191780

18201781
if !missing_pks.is_empty() {
1821-
let body = json!(["user_infos", {"pubkeys": missing_pks }]);
1822-
let data: Vec<Value> = Self::primal_request(&client, url, body).await?;
1823-
let missing_metadata = parse_profile_metadata(data);
1782+
let missing_metadata = self
1783+
.nostr
1784+
.primal_client
1785+
.get_user_profiles(missing_pks)
1786+
.await?;
18241787
metadata.extend(missing_metadata);
18251788
}
18261789

@@ -1872,60 +1835,33 @@ impl<S: MutinyStorage> MutinyWallet<S> {
18721835
until: Option<u64>,
18731836
since: Option<u64>,
18741837
) -> Result<Vec<DirectMessage>, MutinyError> {
1875-
let url = self
1876-
.config
1877-
.primal_url
1878-
.as_deref()
1879-
.unwrap_or("https://primal-cache.mutinywallet.com/api");
1880-
let client = reqwest::Client::new();
1838+
let events = self
1839+
.nostr
1840+
.primal_client
1841+
.get_dm_conversation(npub, self.nostr.public_key, limit, until, since)
1842+
.await?;
18811843

1882-
// api is a little weird, has sender and receiver but still gives full conversation
1883-
let sender = npub.to_hex();
1884-
let receiver = self.nostr.public_key.to_hex();
1885-
let body = match (until, since) {
1886-
(Some(until), Some(since)) => {
1887-
json!(["get_directmsgs", { "sender": sender, "receiver": receiver, "limit": limit, "until": until, "since": since }])
1888-
}
1889-
(None, Some(since)) => {
1890-
json!(["get_directmsgs", { "sender": sender, "receiver": receiver, "limit": limit, "since": since }])
1891-
}
1892-
(Some(until), None) => {
1893-
json!(["get_directmsgs", { "sender": sender, "receiver": receiver, "limit": limit, "until": until }])
1894-
}
1895-
(None, None) => {
1896-
json!(["get_directmsgs", { "sender": sender, "receiver": receiver, "limit": limit, "since": 0 }])
1844+
let mut messages = Vec::with_capacity(events.len());
1845+
for event in events {
1846+
if event.verify().is_err() {
1847+
continue;
18971848
}
1898-
};
1899-
let data: Vec<Value> = Self::primal_request(&client, url, body).await?;
1900-
1901-
let mut messages = Vec::with_capacity(data.len());
1902-
for d in data {
1903-
let event = Event::from_value(d)
1904-
.ok()
1905-
.filter(|e| e.kind == Kind::EncryptedDirectMessage);
19061849

1907-
if let Some(event) = event {
1908-
// verify signature
1909-
if event.verify().is_err() {
1910-
continue;
1911-
}
1912-
1913-
// if decryption fails, skip this message, just a bad dm
1914-
if let Ok(message) = self.nostr.decrypt_dm(npub, &event.content).await {
1915-
let to = if event.pubkey == npub {
1916-
self.nostr.public_key
1917-
} else {
1918-
npub
1919-
};
1920-
let dm = DirectMessage {
1921-
from: event.pubkey,
1922-
to,
1923-
message,
1924-
date: event.created_at.as_u64(),
1925-
event_id: event.id,
1926-
};
1927-
messages.push(dm);
1928-
}
1850+
// if decryption fails, skip this message, just a bad dm
1851+
if let Ok(message) = self.nostr.decrypt_dm(npub, &event.content).await {
1852+
let to = if event.pubkey == npub {
1853+
self.nostr.public_key
1854+
} else {
1855+
npub
1856+
};
1857+
let dm = DirectMessage {
1858+
from: event.pubkey,
1859+
to,
1860+
message,
1861+
date: event.created_at.as_u64(),
1862+
event_id: event.id,
1863+
};
1864+
messages.push(dm);
19291865
}
19301866
}
19311867

mutiny-core/src/nostr/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::nostr::nwc::{
55
NwcProfile, NwcProfileTag, PendingNwcInvoice, Profile, SingleUseSpendingConditions,
66
SpendingConditions, PENDING_NWC_EVENTS_KEY,
77
};
8+
use crate::nostr::primal::PrimalClient;
89
use crate::storage::MutinyStorage;
910
use crate::{error::MutinyError, utils::get_random_bip32_child_index};
1011
use crate::{labels::LabelStorage, InvoiceHandler};
@@ -32,6 +33,7 @@ use url::Url;
3233

3334
pub mod nip49;
3435
pub mod nwc;
36+
mod primal;
3537

3638
const PROFILE_ACCOUNT_INDEX: u32 = 0;
3739
const NWC_ACCOUNT_INDEX: u32 = 1;
@@ -96,6 +98,8 @@ pub struct NostrManager<S: MutinyStorage> {
9698
pub stop: Arc<AtomicBool>,
9799
/// Nostr client
98100
pub client: Client,
101+
/// Primal client
102+
pub primal_client: PrimalClient,
99103
}
100104

101105
impl<S: MutinyStorage> NostrManager<S> {
@@ -1223,6 +1227,7 @@ impl<S: MutinyStorage> NostrManager<S> {
12231227
xprivkey: ExtendedPrivKey,
12241228
key_source: NostrKeySource,
12251229
storage: S,
1230+
primal_url: Option<String>,
12261231
logger: Arc<MutinyLogger>,
12271232
stop: Arc<AtomicBool>,
12281233
) -> Result<Self, MutinyError> {
@@ -1261,13 +1266,18 @@ impl<S: MutinyStorage> NostrManager<S> {
12611266

12621267
let client = Client::new(primary_key.clone());
12631268

1269+
let primal_client = PrimalClient::new(
1270+
primal_url.unwrap_or("https://primal-cache.mutinywallet.com/api".to_string()),
1271+
);
1272+
12641273
Ok(Self {
12651274
xprivkey,
12661275
primary_key,
12671276
public_key,
12681277
nwc: Arc::new(RwLock::new(nwc)),
12691278
storage,
12701279
pending_nwc_lock: Arc::new(Mutex::new(())),
1280+
primal_client,
12711281
logger,
12721282
stop,
12731283
client,

mutiny-core/src/nostr/nwc.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,7 @@ mod wasm_test {
12231223
xprivkey,
12241224
NostrKeySource::Derived,
12251225
storage.clone(),
1226+
None,
12261227
mw.logger.clone(),
12271228
stop,
12281229
)
@@ -1280,6 +1281,7 @@ mod wasm_test {
12801281
xprivkey,
12811282
NostrKeySource::Derived,
12821283
storage.clone(),
1284+
None,
12831285
logger.clone(),
12841286
stop,
12851287
)
@@ -1475,6 +1477,7 @@ mod wasm_test {
14751477
xprivkey,
14761478
NostrKeySource::Derived,
14771479
storage.clone(),
1480+
None,
14781481
Arc::new(MutinyLogger::default()),
14791482
stop,
14801483
)
@@ -1527,6 +1530,7 @@ mod wasm_test {
15271530
xprivkey,
15281531
NostrKeySource::Derived,
15291532
storage.clone(),
1533+
None,
15301534
mw.logger.clone(),
15311535
stop,
15321536
)
@@ -1614,6 +1618,7 @@ mod wasm_test {
16141618
xprivkey,
16151619
NostrKeySource::Derived,
16161620
storage.clone(),
1621+
None,
16171622
logger,
16181623
stop,
16191624
)

0 commit comments

Comments
 (0)