chore: update deps

This commit is contained in:
reya 2024-08-18 15:51:34 +07:00
parent 4cb49d44c7
commit beac1a189e
12 changed files with 930 additions and 743 deletions

View File

@ -10,7 +10,7 @@
"tauri": "tauri"
},
"dependencies": {
"@getalby/bitcoin-connect-react": "^3.6.1",
"@getalby/bitcoin-connect-react": "^3.6.2",
"@phosphor-icons/react": "^2.1.7",
"@radix-ui/react-avatar": "^1.1.0",
"@radix-ui/react-checkbox": "^1.1.1",
@ -21,12 +21,12 @@
"@radix-ui/react-tooltip": "^1.1.2",
"@tanstack/query-persist-client-core": "^5.51.21",
"@tanstack/react-query": "^5.51.23",
"@tanstack/react-router": "^1.47.1",
"@tauri-apps/api": "2.0.0-rc.0",
"@tanstack/react-router": "^1.48.1",
"@tauri-apps/api": "2.0.0-rc.1",
"@tauri-apps/plugin-clipboard-manager": "2.0.0-rc.0",
"@tauri-apps/plugin-dialog": "2.0.0-rc.0",
"@tauri-apps/plugin-fs": "2.0.0-rc.0",
"@tauri-apps/plugin-http": "2.0.0-rc.0",
"@tauri-apps/plugin-fs": "2.0.0-rc.1",
"@tauri-apps/plugin-http": "2.0.0-rc.1",
"@tauri-apps/plugin-os": "2.0.0-rc.0",
"@tauri-apps/plugin-process": "2.0.0-rc.0",
"@tauri-apps/plugin-shell": "2.0.0-rc.0",
@ -36,7 +36,7 @@
"bitcoin-units": "^1.0.0",
"dayjs": "^1.11.12",
"embla-carousel-react": "^8.1.8",
"i18next": "^23.12.2",
"i18next": "^23.13.0",
"i18next-resources-to-backend": "^1.2.1",
"light-bolt11-decoder": "^3.1.1",
"minidenticons": "^4.2.1",
@ -50,17 +50,17 @@
"react-string-replace": "^1.1.1",
"slate": "^0.103.0",
"slate-react": "^0.107.1",
"use-debounce": "^10.0.2",
"virtua": "^0.33.5"
"use-debounce": "^10.0.3",
"virtua": "^0.33.7"
},
"devDependencies": {
"@biomejs/biome": "^1.8.3",
"@evilmartians/harmony": "^1.2.0",
"@tailwindcss/forms": "^0.5.7",
"@tailwindcss/typography": "^0.5.14",
"@tanstack/router-devtools": "^1.47.1",
"@tanstack/router-devtools": "^1.48.1",
"@tanstack/router-plugin": "^1.47.0",
"@tauri-apps/cli": "2.0.0-rc.1",
"@tauri-apps/cli": "2.0.0-rc.4",
"@types/react": "npm:types-react@19.0.0-rc.1",
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
"@vitejs/plugin-react": "^4.3.1",
@ -69,12 +69,12 @@
"clsx": "^2.1.1",
"postcss": "^8.4.41",
"tailwind-gradient-mask-image": "^1.2.0",
"tailwind-merge": "^2.5.0",
"tailwind-merge": "^2.5.2",
"tailwind-scrollbar": "^3.1.0",
"tailwindcss": "^3.4.9",
"tailwindcss": "^3.4.10",
"tailwindcss-content-visibility": "^0.2.0",
"typescript": "^5.5.4",
"vite": "^5.4.0",
"vite": "^5.4.1",
"vite-tsconfig-paths": "^5.0.1"
},
"overrides": {

474
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

782
src-tauri/Cargo.lock generated

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -3443,6 +3443,13 @@
"core:webview:allow-create-webview-window"
]
},
{
"description": "core:webview:allow-get-all-webviews -> Enables the get_all_webviews command without any pre-configured scope.",
"type": "string",
"enum": [
"core:webview:allow-get-all-webviews"
]
},
{
"description": "core:webview:allow-internal-toggle-devtools -> Enables the internal_toggle_devtools command without any pre-configured scope.",
"type": "string",
@ -3527,6 +3534,13 @@
"core:webview:deny-create-webview-window"
]
},
{
"description": "core:webview:deny-get-all-webviews -> Denies the get_all_webviews command without any pre-configured scope.",
"type": "string",
"enum": [
"core:webview:deny-get-all-webviews"
]
},
{
"description": "core:webview:deny-internal-toggle-devtools -> Denies the internal_toggle_devtools command without any pre-configured scope.",
"type": "string",
@ -3653,6 +3667,13 @@
"core:window:allow-destroy"
]
},
{
"description": "core:window:allow-get-all-windows -> Enables the get_all_windows command without any pre-configured scope.",
"type": "string",
"enum": [
"core:window:allow-get-all-windows"
]
},
{
"description": "core:window:allow-hide -> Enables the hide command without any pre-configured scope.",
"type": "string",
@ -4108,6 +4129,13 @@
"core:window:deny-destroy"
]
},
{
"description": "core:window:deny-get-all-windows -> Denies the get_all_windows command without any pre-configured scope.",
"type": "string",
"enum": [
"core:window:deny-get-all-windows"
]
},
{
"description": "core:window:deny-hide -> Denies the hide command without any pre-configured scope.",
"type": "string",

View File

@ -3443,6 +3443,13 @@
"core:webview:allow-create-webview-window"
]
},
{
"description": "core:webview:allow-get-all-webviews -> Enables the get_all_webviews command without any pre-configured scope.",
"type": "string",
"enum": [
"core:webview:allow-get-all-webviews"
]
},
{
"description": "core:webview:allow-internal-toggle-devtools -> Enables the internal_toggle_devtools command without any pre-configured scope.",
"type": "string",
@ -3527,6 +3534,13 @@
"core:webview:deny-create-webview-window"
]
},
{
"description": "core:webview:deny-get-all-webviews -> Denies the get_all_webviews command without any pre-configured scope.",
"type": "string",
"enum": [
"core:webview:deny-get-all-webviews"
]
},
{
"description": "core:webview:deny-internal-toggle-devtools -> Denies the internal_toggle_devtools command without any pre-configured scope.",
"type": "string",
@ -3653,6 +3667,13 @@
"core:window:allow-destroy"
]
},
{
"description": "core:window:allow-get-all-windows -> Enables the get_all_windows command without any pre-configured scope.",
"type": "string",
"enum": [
"core:window:allow-get-all-windows"
]
},
{
"description": "core:window:allow-hide -> Enables the hide command without any pre-configured scope.",
"type": "string",
@ -4108,6 +4129,13 @@
"core:window:deny-destroy"
]
},
{
"description": "core:window:deny-get-all-windows -> Denies the get_all_windows command without any pre-configured scope.",
"type": "string",
"enum": [
"core:window:deny-get-all-windows"
]
},
{
"description": "core:window:deny-hide -> Denies the hide command without any pre-configured scope.",
"type": "string",

View File

@ -39,7 +39,10 @@ pub async fn get_event(id: &str, state: State<'_, Nostr>) -> Result<RichEvent, S
};
match client
.get_events_of(vec![Filter::new().id(event_id)], None)
.get_events_of(
vec![Filter::new().id(event_id)],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
Ok(events) => {
@ -88,7 +91,10 @@ pub async fn get_event_from(
if !settings.use_relay_hint {
match client
.get_events_of(vec![Filter::new().id(event_id)], None)
.get_events_of(
vec![Filter::new().id(event_id)],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
Ok(events) => {
@ -152,7 +158,13 @@ pub async fn get_replies(id: &str, state: State<'_, Nostr>) -> Result<Vec<RichEv
let filter = Filter::new().kinds(vec![Kind::TextNote]).event(event_id);
match client.get_events_of(vec![filter], None).await {
match client
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
Ok(events) => {
let futures = events.into_iter().map(|ev| async move {
let raw = ev.as_json();
@ -217,7 +229,13 @@ pub async fn get_events_by(
.limit(FETCH_LIMIT)
.until(until);
match client.get_events_of(vec![filter], None).await {
match client
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
Ok(events) => {
let futures = events.into_iter().map(|ev| async move {
let raw = ev.as_json();
@ -344,7 +362,10 @@ pub async fn get_group_events(
.authors(authors);
match client
.get_events_of(vec![filter], Some(Duration::from_secs(10)))
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
Ok(events) => {
@ -387,7 +408,10 @@ pub async fn get_global_events(
.until(as_of);
match client
.get_events_of(vec![filter], Some(Duration::from_secs(8)))
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
Ok(events) => {
@ -428,7 +452,13 @@ pub async fn get_hashtag_events(
.until(as_of)
.hashtags(hashtags);
match client.get_events_of(vec![filter], None).await {
match client
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
Ok(events) => {
let dedup = dedup_event(&events);
let futures = dedup.into_iter().map(|ev| async move {
@ -644,7 +674,7 @@ pub async fn user_to_bech32(user: &str, state: State<'_, Nostr>) -> Result<Strin
.author(public_key)
.kind(Kind::RelayList)
.limit(1)],
Some(Duration::from_secs(10)),
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{

View File

@ -3,22 +3,18 @@ use nostr_sdk::prelude::*;
use std::{str::FromStr, time::Duration};
use tauri::State;
use crate::common::get_latest_event;
use crate::{Nostr, Settings};
#[tauri::command]
#[specta::specta]
pub async fn get_current_profile(state: State<'_, Nostr>) -> Result<String, String> {
pub async fn get_profile(id: Option<String>, state: State<'_, Nostr>) -> Result<String, String> {
let client = &state.client;
let signer = match client.signer().await {
Ok(signer) => signer,
Err(err) => return Err(format!("Failed to get signer: {}", err)),
};
let public_key = match signer.public_key().await {
Ok(pk) => pk,
Err(err) => return Err(format!("Failed to get public key: {}", err)),
let public_key: PublicKey = match id {
Some(user_id) => match PublicKey::from_str(&user_id) {
Ok(val) => val,
Err(_) => return Err("Public Key is not valid".into()),
},
None => client.signer().await.unwrap().public_key().await.unwrap(),
};
let filter = Filter::new()
@ -26,70 +22,25 @@ pub async fn get_current_profile(state: State<'_, Nostr>) -> Result<String, Stri
.kind(Kind::Metadata)
.limit(1);
let events_result = client
.get_events_of(vec![filter], Some(Duration::from_secs(10)))
let query = client
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(3))),
)
.await;
match events_result {
Ok(events) => {
if let Some(event) = get_latest_event(&events) {
match Metadata::from_json(&event.content) {
Ok(metadata) => Ok(metadata.as_json()),
Err(_) => Err("Failed to parse metadata.".into()),
}
if let Ok(events) = query {
if let Some(event) = events.first() {
if let Ok(metadata) = Metadata::from_json(&event.content) {
Ok(metadata.as_json())
} else {
Err("No matching events found.".into())
}
}
Err(err) => Err(format!("Failed to get events: {}", err)),
}
}
#[tauri::command]
#[specta::specta]
pub async fn get_profile(id: &str, state: State<'_, Nostr>) -> Result<String, String> {
let client = &state.client;
let public_key: Option<PublicKey> = match Nip19::from_bech32(id) {
Ok(val) => match val {
Nip19::Pubkey(key) => Some(key),
Nip19::Profile(profile) => {
let relays = profile.relays;
for relay in relays.into_iter() {
let _ = client.add_relay(&relay).await.unwrap_or_default();
client.connect_relay(&relay).await.unwrap_or_default();
}
Some(profile.public_key)
}
_ => None,
},
Err(_) => match PublicKey::from_str(id) {
Ok(val) => Some(val),
Err(_) => None,
},
};
if let Some(author) = public_key {
let filter = Filter::new().author(author).kind(Kind::Metadata).limit(1);
let query = client
.get_events_of(vec![filter], Some(Duration::from_secs(10)))
.await;
if let Ok(events) = query {
if let Some(event) = events.first() {
if let Ok(metadata) = Metadata::from_json(&event.content) {
Ok(metadata.as_json())
} else {
Err("Parse metadata failed".into())
}
} else {
let rand_metadata = Metadata::new();
Ok(rand_metadata.as_json())
Err("Parse metadata failed".into())
}
} else {
Err("Get metadata failed".into())
Ok(Metadata::new().as_json())
}
} else {
Err("Public Key is not valid".into())
Err("Get metadata failed".into())
}
}
@ -185,10 +136,10 @@ pub async fn is_contact_list_empty(state: State<'_, Nostr>) -> Result<bool, ()>
#[tauri::command]
#[specta::specta]
pub async fn check_contact(hex: &str, state: State<'_, Nostr>) -> Result<bool, String> {
pub async fn check_contact(hex: String, state: State<'_, Nostr>) -> Result<bool, String> {
let contact_list = state.contact_list.lock().unwrap();
match PublicKey::from_str(hex) {
match PublicKey::from_str(&hex) {
Ok(public_key) => match contact_list.iter().position(|x| x.public_key == public_key) {
Some(_) => Ok(true),
None => Ok(false),
@ -244,27 +195,19 @@ pub async fn set_nstore(
state: State<'_, Nostr>,
) -> Result<String, String> {
let client = &state.client;
let signer = client.signer().await.map_err(|e| e.to_string())?;
let public_key = signer.public_key().await.map_err(|e| e.to_string())?;
match client.signer().await {
Ok(signer) => {
let public_key = match signer.public_key().await {
Ok(pk) => pk,
Err(err) => return Err(format!("Failed to get public key: {}", err)),
};
let encrypted = signer
.nip44_encrypt(public_key, content)
.await
.map_err(|e| e.to_string())?;
let encrypted = match signer.nip44_encrypt(public_key, content).await {
Ok(enc) => enc,
Err(err) => return Err(format!("Encryption failed: {}", err)),
};
let tag = Tag::identifier(key);
let builder = EventBuilder::new(Kind::ApplicationSpecificData, encrypted, vec![tag]);
let tag = Tag::identifier(key);
let builder = EventBuilder::new(Kind::ApplicationSpecificData, encrypted, vec![tag]);
match client.send_event_builder(builder).await {
Ok(event_id) => Ok(event_id.to_string()),
Err(err) => Err(err.to_string()),
}
}
match client.send_event_builder(builder).await {
Ok(event_id) => Ok(event_id.to_string()),
Err(err) => Err(err.to_string()),
}
}
@ -273,38 +216,34 @@ pub async fn set_nstore(
#[specta::specta]
pub async fn get_nstore(key: &str, state: State<'_, Nostr>) -> Result<String, String> {
let client = &state.client;
let signer = client.signer().await.map_err(|e| e.to_string())?;
let public_key = signer.public_key().await.map_err(|e| e.to_string())?;
if let Ok(signer) = client.signer().await {
let public_key = match signer.public_key().await {
Ok(pk) => pk,
Err(err) => return Err(format!("Failed to get public key: {}", err)),
};
let filter = Filter::new()
.author(public_key)
.kind(Kind::ApplicationSpecificData)
.identifier(key)
.limit(1);
let filter = Filter::new()
.author(public_key)
.kind(Kind::ApplicationSpecificData)
.identifier(key)
.limit(1);
match client
.get_events_of(vec![filter], Some(Duration::from_secs(5)))
.await
{
Ok(events) => {
if let Some(event) = events.first() {
let content = event.content();
match signer.nip44_decrypt(public_key, content).await {
Ok(decrypted) => Ok(decrypted),
Err(_) => Err(event.content.to_string()),
}
} else {
Err("Value not found".into())
match client
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
Ok(events) => {
if let Some(event) = events.first() {
let content = event.content();
match signer.nip44_decrypt(public_key, content).await {
Ok(decrypted) => Ok(decrypted),
Err(_) => Err(event.content.to_string()),
}
} else {
Err("Not found".into())
}
Err(err) => Err(err.to_string()),
}
} else {
Err("Signer is required".into())
Err(err) => Err(err.to_string()),
}
}
@ -329,7 +268,8 @@ pub async fn set_wallet(uri: &str, state: State<'_, Nostr>) -> Result<bool, Stri
#[specta::specta]
pub async fn load_wallet(state: State<'_, Nostr>) -> Result<String, String> {
let client = &state.client;
let keyring = Entry::new("Lume Secret", "Bitcoin Connect").unwrap();
let keyring =
Entry::new("Lume Secret Storage", "Bitcoin Connect").map_err(|e| e.to_string())?;
match keyring.get_password() {
Ok(val) => {
@ -353,16 +293,17 @@ pub async fn load_wallet(state: State<'_, Nostr>) -> Result<String, String> {
#[tauri::command]
#[specta::specta]
pub async fn remove_wallet(state: State<'_, Nostr>) -> Result<(), ()> {
pub async fn remove_wallet(state: State<'_, Nostr>) -> Result<(), String> {
let client = &state.client;
let keyring = Entry::new("Lume Secret", "Bitcoin Connect").unwrap();
let keyring =
Entry::new("Lume Secret Storage", "Bitcoin Connect").map_err(|e| e.to_string())?;
match keyring.delete_credential() {
Ok(_) => {
client.unset_zapper().await;
Ok(())
}
Err(_) => Err(()),
Err(e) => Err(e.to_string()),
}
}
@ -375,23 +316,10 @@ pub async fn zap_profile(
state: State<'_, Nostr>,
) -> Result<bool, String> {
let client = &state.client;
let public_key = match Nip19::from_bech32(id) {
Ok(val) => match val {
Nip19::Pubkey(key) => key,
Nip19::Profile(profile) => profile.public_key,
_ => return Err("Public Key is not valid.".into()),
},
Err(_) => match PublicKey::from_str(id) {
Ok(val) => val,
Err(_) => return Err("Public Key is not valid.".into()),
},
};
let public_key: PublicKey = PublicKey::from_str(id).map_err(|e| e.to_string())?;
let details = ZapDetails::new(ZapType::Private).message(message);
let num = match amount.parse::<u64>() {
Ok(val) => val,
Err(_) => return Err("Invalid amount.".into()),
};
let num = amount.parse::<u64>().map_err(|e| e.to_string())?;
if client.zap(public_key, num, Some(details)).await.is_ok() {
Ok(true)
@ -422,10 +350,7 @@ pub async fn zap_event(
};
let details = ZapDetails::new(ZapType::Private).message(message);
let num = match amount.parse::<u64>() {
Ok(val) => val,
Err(_) => return Err("Invalid amount.".into()),
};
let num = amount.parse::<u64>().map_err(|e| e.to_string())?;
if client.zap(event_id, num, Some(details)).await.is_ok() {
Ok(true)
@ -447,8 +372,12 @@ pub async fn friend_to_friend(npub: &str, state: State<'_, Nostr>) -> Result<boo
.kind(Kind::ContactList)
.limit(1);
if let Ok(contact_list_events) =
client.get_events_of(vec![contact_list_filter], None).await
if let Ok(contact_list_events) = client
.get_events_of(
vec![contact_list_filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
for event in contact_list_events.into_iter() {
for tag in event.into_iter_tags() {
@ -477,19 +406,22 @@ pub async fn friend_to_friend(npub: &str, state: State<'_, Nostr>) -> Result<boo
pub async fn get_following(
state: State<'_, Nostr>,
public_key: &str,
timeout: Option<u64>,
) -> Result<Vec<String>, String> {
let client = &state.client;
let public_key = match PublicKey::from_str(public_key) {
Ok(val) => val,
Err(err) => return Err(err.to_string()),
};
let duration = timeout.map(Duration::from_secs);
let public_key = PublicKey::from_str(public_key).map_err(|e| e.to_string())?;
let filter = Filter::new().kind(Kind::ContactList).author(public_key);
let events = match client.get_events_of(vec![filter], duration).await {
let events = match client
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
Ok(events) => events,
Err(err) => return Err(err.to_string()),
};
let mut ret: Vec<String> = vec![];
if let Some(latest_event) = events.iter().max_by_key(|event| event.created_at()) {
ret.extend(latest_event.tags().iter().filter_map(|tag| {
@ -503,33 +435,38 @@ pub async fn get_following(
}
}));
}
Ok(ret)
}
pub async fn get_followers(
state: State<'_, Nostr>,
public_key: &str,
timeout: Option<u64>,
) -> Result<Vec<String>, String> {
let client = &state.client;
let public_key = match PublicKey::from_str(public_key) {
Ok(val) => val,
Err(err) => return Err(err.to_string()),
};
let duration = timeout.map(Duration::from_secs);
let public_key = PublicKey::from_str(public_key).map_err(|e| e.to_string())?;
let filter = Filter::new().kind(Kind::ContactList).custom_tag(
SingleLetterTag::lowercase(Alphabet::P),
vec![public_key.to_hex()],
);
let events = match client.get_events_of(vec![filter], duration).await {
let events = match client
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
Ok(events) => events,
Err(err) => return Err(err.to_string()),
};
let ret: Vec<String> = events
.into_iter()
.map(|event| event.author().to_hex())
.collect();
Ok(ret)
// TODO: get more than 500 events
}

View File

@ -5,6 +5,7 @@ use specta::Type;
use std::{
fs::OpenOptions,
io::{self, BufRead, Write},
time::Duration,
};
use tauri::{path::BaseDirectory, Manager, State};
@ -36,7 +37,16 @@ pub async fn get_relays(state: State<'_, Nostr>) -> Result<Relays, String> {
.kind(Kind::RelayList)
.limit(1);
match client.get_events_of(vec![filter], None).await {
match client
.get_events_of(
vec![filter],
EventSource::Relays {
timeout: Some(Duration::from_secs(5)),
specific_relays: None,
},
)
.await
{
Ok(events) => {
if let Some(event) = events.first() {
let nip65_list = nip65::extract_relay_list(event).collect::<Vec<_>>();

View File

@ -5,6 +5,7 @@ use serde::Serialize;
use specta::Type;
use std::collections::HashSet;
use std::str::FromStr;
use std::time::Duration;
use crate::Settings;
@ -66,7 +67,13 @@ pub async fn init_nip65(client: &Client) {
.kind(Kind::RelayList)
.limit(1);
if let Ok(events) = client.get_events_of(vec![filter], None).await {
if let Ok(events) = client
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
if let Some(event) = events.first() {
let relay_list = nip65::extract_relay_list(event);
for (url, metadata) in relay_list {
@ -107,7 +114,13 @@ pub async fn get_user_settings(client: &Client) -> Result<Settings, String> {
.identifier(ident)
.limit(1);
match client.get_events_of(vec![filter], None).await {
match client
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
Ok(events) => {
if let Some(event) = events.first() {
let content = event.content();

View File

@ -89,7 +89,6 @@ fn main() {
connect_account,
delete_account,
login,
get_current_profile,
get_profile,
get_contact_list,
set_contact_list,

View File

@ -88,15 +88,7 @@ async login(account: string, password: string) : Promise<Result<string, string>>
else return { status: "error", error: e as any };
}
},
async getCurrentProfile() : Promise<Result<string, string>> {
try {
return { status: "ok", data: await TAURI_INVOKE("get_current_profile") };
} catch (e) {
if(e instanceof Error) throw e;
else return { status: "error", error: e as any };
}
},
async getProfile(id: string) : Promise<Result<string, string>> {
async getProfile(id: string | null) : Promise<Result<string, string>> {
try {
return { status: "ok", data: await TAURI_INVOKE("get_profile", { id }) };
} catch (e) {
@ -184,7 +176,7 @@ async loadWallet() : Promise<Result<string, string>> {
else return { status: "error", error: e as any };
}
},
async removeWallet() : Promise<Result<null, null>> {
async removeWallet() : Promise<Result<null, string>> {
try {
return { status: "ok", data: await TAURI_INVOKE("remove_wallet") };
} catch (e) {