diff --git a/.env.example b/.env.example index a569c76f..8169b70f 100644 --- a/.env.example +++ b/.env.example @@ -9,7 +9,7 @@ VITE_NETWORK="signet" VITE_PROXY="wss://p.mutinywallet.com" VITE_ESPLORA="https://mutinynet.com/api" -VITE_LSP="https://signet-lsp.mutinywallet.com" +VITE_LSP="https://mutinynet-flow.lnolymp.us" VITE_RGS="https://rgs.mutinynet.com/snapshot/" # VITE_SELFHOSTED="true" // Removes Mutiny+ VITE_AUTH="https://auth-staging.mutinywallet.com" diff --git a/.env.mainnet b/.env.mainnet index b07943e3..f05f147d 100644 --- a/.env.mainnet +++ b/.env.mainnet @@ -3,7 +3,7 @@ VITE_NETWORK="bitcoin" VITE_PROXY="wss://p.mutinywallet.com" VITE_ESPLORA="https://mutiny.mempool.space/api" -VITE_LSP="https://lsp.voltageapi.com" +VITE_LSP="https://0conf.lnolymp.us" VITE_RGS="https://scorer.mutinywallet.com/v1/rgs/snapshot/" # VITE_SELFHOSTED="true" // Removes Mutiny+ VITE_AUTH="https://auth.mutinywallet.com" diff --git a/.env.signet b/.env.signet index 13596368..69d2d55f 100644 --- a/.env.signet +++ b/.env.signet @@ -3,7 +3,7 @@ VITE_NETWORK="signet" VITE_PROXY="wss://p.mutinywallet.com" VITE_ESPLORA="https://mutinynet.com/api" -VITE_LSP="https://signet-lsp.mutinywallet.com" +VITE_LSP="https://mutinynet-flow.lnolymp.us" VITE_RGS="https://rgs.mutinynet.com/snapshot/" # VITE_SELFHOSTED="true" // Removes Mutiny+ VITE_AUTH="https://auth-staging.mutinywallet.com" diff --git a/.github/workflows/android-build.yml b/.github/workflows/android-build.yml index 087e065a..57900d6e 100644 --- a/.github/workflows/android-build.yml +++ b/.github/workflows/android-build.yml @@ -64,7 +64,7 @@ jobs: VITE_NETWORK: signet VITE_PROXY: wss://p.mutinywallet.com VITE_ESPLORA: https://mutinynet.com/api - VITE_LSP: https://signet-lsp.mutinywallet.com + VITE_LSP: https://mutinynet-flow.lnolymp.us VITE_RGS: https://rgs.mutinynet.com/snapshot/ VITE_AUTH: https://auth-staging.mutinywallet.com VITE_SUBSCRIPTIONS: https://subscriptions-staging.mutinywallet.com diff --git a/.github/workflows/android-prod.yml b/.github/workflows/android-prod.yml index ca28aa17..0af16fee 100644 --- a/.github/workflows/android-prod.yml +++ b/.github/workflows/android-prod.yml @@ -60,7 +60,7 @@ jobs: VITE_NETWORK: bitcoin VITE_PROXY: wss://p.mutinywallet.com VITE_ESPLORA: https://mutiny.mempool.space/api - VITE_LSP: https://lsp.voltageapi.com + VITE_LSP: https://0conf.lnolymp.us VITE_RGS: https://scorer.mutinywallet.com/v1/rgs/snapshot/ VITE_AUTH: https://auth.mutinywallet.com VITE_SUBSCRIPTIONS: https://subscriptions.mutinywallet.com diff --git a/.github/workflows/android-staging.yml b/.github/workflows/android-staging.yml index f426769e..f2bc26d9 100644 --- a/.github/workflows/android-staging.yml +++ b/.github/workflows/android-staging.yml @@ -61,7 +61,7 @@ jobs: VITE_NETWORK: signet VITE_PROXY: wss://p.mutinywallet.com VITE_ESPLORA: https://mutinynet.com/api - VITE_LSP: https://signet-lsp.mutinywallet.com + VITE_LSP: https://mutinynet-flow.lnolymp.us VITE_RGS: https://rgs.mutinynet.com/snapshot/ VITE_AUTH: https://auth-staging.mutinywallet.com VITE_SUBSCRIPTIONS: https://subscriptions-staging.mutinywallet.com diff --git a/.github/workflows/ios-prod.yml b/.github/workflows/ios-prod.yml index 12be3b0a..023f487c 100644 --- a/.github/workflows/ios-prod.yml +++ b/.github/workflows/ios-prod.yml @@ -37,7 +37,7 @@ jobs: VITE_NETWORK: bitcoin VITE_PROXY: wss://p.mutinywallet.com VITE_ESPLORA: https://mutiny.mempool.space/api - VITE_LSP: https://lsp.voltageapi.com + VITE_LSP: https://0conf.lnolymp.us VITE_RGS: https://scorer.mutinywallet.com/v1/rgs/snapshot/ VITE_AUTH: https://auth.mutinywallet.com VITE_SUBSCRIPTIONS: https://subscriptions.mutinywallet.com diff --git a/.github/workflows/ios-staging.yml b/.github/workflows/ios-staging.yml index d63cfb99..bb455e78 100644 --- a/.github/workflows/ios-staging.yml +++ b/.github/workflows/ios-staging.yml @@ -37,7 +37,7 @@ jobs: VITE_NETWORK: signet VITE_PROXY: wss://p.mutinywallet.com VITE_ESPLORA: https://mutinynet.com/api - VITE_LSP: https://signet-lsp.mutinywallet.com + VITE_LSP: https://mutinynet-flow.lnolymp.us VITE_RGS: https://rgs.mutinynet.com/snapshot/ VITE_AUTH: https://auth-staging.mutinywallet.com VITE_SUBSCRIPTIONS: https://subscriptions-staging.mutinywallet.com diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index f3d5fc18..a5a84927 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -56,7 +56,7 @@ jobs: VITE_NETWORK: signet VITE_PROXY: wss://p.mutinywallet.com VITE_ESPLORA: https://mutinynet.com/api - VITE_LSP: https://signet-lsp.mutinywallet.com + VITE_LSP: https://mutinynet-flow.lnolymp.us VITE_RGS: https://rgs.mutinynet.com/snapshot/ VITE_AUTH: https://auth-staging.mutinywallet.com VITE_SUBSCRIPTIONS: https://subscriptions-staging.mutinywallet.com diff --git a/Dockerfile b/Dockerfile index 246afd9c..768f71e9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ ARG VITE_PROXY="/_services/proxy" ARG VITE_PRIMAL="https://primal-cache.mutinywallet.com/api" ARG VITE_ESPLORA ARG VITE_SCORER="https://scorer.mutinywallet.com" -ARG VITE_LSP="https://lsp.voltageapi.com" +ARG VITE_LSP="https://0conf.lnolymp.us" ARG VITE_RGS ARG VITE_AUTH ARG VITE_STORAGE="/_services/vss/v2" diff --git a/android/app/build.gradle b/android/app/build.gradle index 6ba5b424..a82374e7 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "com.mutinywallet.mutinywallet" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 71 - versionName "1.7.10" + versionCode 72 + versionName "1.7.11" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. diff --git a/e2e/fedimint.spec.ts b/e2e/fedimint.spec.ts index 453f448f..2e368f50 100644 --- a/e2e/fedimint.spec.ts +++ b/e2e/fedimint.spec.ts @@ -22,8 +22,6 @@ test("fedmint join, receive, send", async ({ page }) => { // Fill the input with the federation code await page.fill("input[name='federation_code']", SIGNET_INVITE_CODE); - await page.getByText("Mutinynet Signet Federation").waitFor(); - const addButton = await page.getByRole("button", { name: "Add" }).first(); // Click the "Add" button diff --git a/e2e/roundtrip.spec.ts b/e2e/roundtrip.spec.ts index 32aecb31..ca1eab9a 100644 --- a/e2e/roundtrip.spec.ts +++ b/e2e/roundtrip.spec.ts @@ -7,6 +7,8 @@ test.beforeEach(async ({ page }) => { }); test("rountrip receive and send", async ({ page }) => { + test.slow(); // tell playwright that this test is slow + await loadHome(page); await page.locator("#fab").click(); @@ -109,12 +111,9 @@ test("rountrip receive and send", async ({ page }) => { // Wait for an h1 to appear in the dom that says "Payment Sent" await page.waitForSelector("text=Payment Sent", { timeout: 30000 }); - // Click the "Nice" button + // Click the "Nice" button to go home await page.click("text=Nice"); - // Go home - await page.click("text=Home"); - // Click settings await visitSettings(page); @@ -133,6 +132,9 @@ test("rountrip receive and send", async ({ page }) => { await page.click("text=Confirm"); + // wait for the channel to close + await page.waitForTimeout(5000); + await page .getByText( "It looks like you don't have any channels yet. To get started, receive some sats over lightning, or swap some on-chain funds into a channel. Get your hands dirty!" diff --git a/e2e/routes.spec.ts b/e2e/routes.spec.ts index b10672a5..0a755452 100644 --- a/e2e/routes.spec.ts +++ b/e2e/routes.spec.ts @@ -19,7 +19,6 @@ const settingsRoutes = [ "/connections", "/currency", "/emergencykit", - "/plus", "/restore", "/servers", "/nostrkeys" @@ -62,10 +61,6 @@ test("visit each route", async ({ page }) => { checklist.set("/settings", true); - // Mutiny+ - await checkRoute(page, "/settings/plus", "Mutiny+", checklist); - await page.goBack(); - // Lightning Channels await checkRoute( page, diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index e34d2acb..7e60c9a9 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -360,7 +360,7 @@ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.finance"; IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MARKETING_VERSION = 1.7.10; + MARKETING_VERSION = 1.7.11; OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; PRODUCT_BUNDLE_IDENTIFIER = "com.mutinywallet.mutiny-test"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -387,7 +387,7 @@ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.finance"; IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - MARKETING_VERSION = 1.7.10; + MARKETING_VERSION = 1.7.11; PRODUCT_BUNDLE_IDENTIFIER = com.mutinywallet.mutiny; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/package.json b/package.json index 727ee1eb..65dc6e8a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mutiny-wallet", - "version": "1.7.10", + "version": "1.7.11", "license": "MIT", "packageManager": "pnpm@8.6.6", "scripts": { @@ -56,7 +56,7 @@ "@kobalte/core": "^0.12.6", "@kobalte/tailwindcss": "^0.9.0", "@modular-forms/solid": "^0.20.0", - "@mutinywallet/mutiny-wasm": "1.7.9", + "@mutinywallet/mutiny-wasm": "1.7.10", "@sentry/browser": "^8.7.0", "@sentry/vite-plugin": "^2.18.0", "@solid-primitives/upload": "^0.0.117", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f492e7ed..fd959566 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -54,8 +54,8 @@ dependencies: specifier: ^0.20.0 version: 0.20.0(solid-js@1.8.16) '@mutinywallet/mutiny-wasm': - specifier: 1.7.9 - version: 1.7.9 + specifier: 1.7.10 + version: 1.7.10 '@sentry/browser': specifier: ^8.7.0 version: 8.7.0 @@ -2177,8 +2177,8 @@ packages: solid-js: 1.8.16 dev: false - /@mutinywallet/mutiny-wasm@1.7.9: - resolution: {integrity: sha512-MO6D4ZkJyEfTjEe2ZJVuDkQ+C+jpo1w2msDFNCqnV3B6sUSomkTwVvQPJA++D/WFqrgRiDJTKJPNkKEozOnx9g==} + /@mutinywallet/mutiny-wasm@1.7.10: + resolution: {integrity: sha512-jWL70psg50CrdSO4t78rNo5MkYW2W4dgXkbWqVJ8+PojojrN9m0wCfYELByEQuWWVaytfJXJZAR5yFzPZ/9eqw==} dev: false /@nodelib/fs.scandir@2.1.5: diff --git a/public/i18n/en.json b/public/i18n/en.json index bc83fd37..8994bbd1 100644 --- a/public/i18n/en.json +++ b/public/i18n/en.json @@ -40,7 +40,10 @@ "just_me": "Just Me", "friends": "Friends", "requests": "Requests" - } + }, + "federations_warn_generic": "Due to temporary issues with your current federation, we recommend you transfer your funds to a lightning channel or withdraw to another bitcoin wallet.", + "transfer_lightning": "Transfer to lightning", + "sent_to_another_wallet": "Send to another wallet" }, "profile": { "profile": "Profile", @@ -49,6 +52,7 @@ "edit_profile": "Edit Profile", "join_federation": "Join a federation", "manage_federation": "Manage Federations", + "leave_federation": "Leave Federation", "federated_custody": "Federated Custody", "self_custody": "Self Custody", "social": "Social", @@ -541,7 +545,8 @@ "storage_caption": "Encrypted VSS backup service.", "error_lsp": "That doesn't look like a URL", "error_tor": "Tor URLs are not currently supported", - "save": "Save" + "save": "Save", + "error_lsp_change_failed": "Unable to change LSP. Maybe you have open channels?" }, "nostr_contacts": { "title": "Sync Nostr Contacts", diff --git a/src/components/Activity.tsx b/src/components/Activity.tsx index e9781991..588a7d4e 100644 --- a/src/components/Activity.tsx +++ b/src/components/Activity.tsx @@ -1,6 +1,6 @@ import { TagItem } from "@mutinywallet/mutiny-wasm"; import { cache, createAsync, useNavigate } from "@solidjs/router"; -import { Plus, Save, Search, Shuffle, Users } from "lucide-solid"; +import { Plus, Save, Search, Shuffle } from "lucide-solid"; import { createEffect, createMemo, diff --git a/src/components/FederationPopup.tsx b/src/components/FederationPopup.tsx index 44d46516..074259d0 100644 --- a/src/components/FederationPopup.tsx +++ b/src/components/FederationPopup.tsx @@ -1,8 +1,13 @@ import { useNavigate } from "@solidjs/router"; -import { Users } from "lucide-solid"; -import { createSignal } from "solid-js"; +import { ArrowLeftRight, ArrowUpRight, Users } from "lucide-solid"; +import { createSignal, Show } from "solid-js"; -import { ButtonCard, NiceP, SimpleDialog } from "~/components/layout"; +import { + ButtonCard, + ExternalLink, + NiceP, + SimpleDialog +} from "~/components/layout"; import { useI18n } from "~/i18n/context"; import { useMegaStore } from "~/state/megaStore"; @@ -16,9 +21,11 @@ export function FederationPopup() { const i18n = useI18n(); const navigate = useNavigate(); + const name = state.expiration_warning?.federationName; + return ( { if (!open) { @@ -27,7 +34,41 @@ export function FederationPopup() { } }} > - {state.expiration_warning?.expiresMessage} + + {state.expiration_warning?.expiresMessage || + i18n.t("home.federations_warn_generic")} + + + + + {i18n.t("settings.manage_federations.learn_more")} + + + + { + actions.clearExpirationWarning(); + setShowFederationExpirationWarning(false); + navigate("/swaplightning"); + }} + > + + + {i18n.t("home.transfer_lightning")} + + + { + actions.clearExpirationWarning(); + setShowFederationExpirationWarning(false); + navigate("/send"); + }} + > + + + {i18n.t("home.sent_to_another_wallet")} + + { actions.clearExpirationWarning(); @@ -37,7 +78,7 @@ export function FederationPopup() { > - {i18n.t("profile.manage_federation")} + {i18n.t("profile.leave_federation")} diff --git a/src/routes/Profile.tsx b/src/routes/Profile.tsx index b8860827..9e1c06b7 100644 --- a/src/routes/Profile.tsx +++ b/src/routes/Profile.tsx @@ -1,5 +1,5 @@ import { createAsync, useNavigate } from "@solidjs/router"; -import { AtSign, Edit, Import } from "lucide-solid"; +import { Edit, Import } from "lucide-solid"; import { createMemo, Show, Suspense } from "solid-js"; import { @@ -47,21 +47,6 @@ export function Profile() { return profile()?.deleted === true || profile()?.deleted === "true"; }); - const hasMutinyAddress = createMemo(() => { - if (profile()?.lud16) { - const hermes = import.meta.env.VITE_HERMES; - if (!hermes) { - return false; - } - const hermesDomain = new URL(hermes).hostname; - const afterAt = profile()?.lud16!.split("@")[1]; - if (afterAt && afterAt.includes(hermesDomain)) { - return true; - } - } - return false; - }); - return ( @@ -89,26 +74,6 @@ export function Profile() { {i18n.t("profile.edit_profile")} - - - navigate("/settings/lightningaddress") - } - > - - - - {i18n.t( - "settings.lightning_address.create" - )} - - - - { setSentDetails(undefined); const state = location.state as { previous?: string }; - if (state?.previous) { + // If we're coming from a chat, we want to go back to the chat + // Otherwise we want to go home + if ( + state?.previous && + state?.previous.includes("chat/") + ) { navigate(state?.previous); } else { navigate("/"); diff --git a/src/routes/SwapLightning.tsx b/src/routes/SwapLightning.tsx index ef0df62a..87845104 100644 --- a/src/routes/SwapLightning.tsx +++ b/src/routes/SwapLightning.tsx @@ -119,7 +119,7 @@ export function SwapLightning() { return feeSats() !== 0n; }); - const [feeEstimateWarning, setFeeEstimateWarning] = createSignal(); + const [feeEstimateWarning, setFeeEstimateWarning] = createSignal(); const feeEstimate = async () => { try { @@ -146,7 +146,14 @@ export function SwapLightning() { setStage("preview"); } catch (e) { console.error(e); - setFeeEstimateWarning(i18n.t("swap_lightning.too_small")); + const err = eify(e); + if (err.message === "Satoshi amount is invalid") { + setFeeEstimateWarning( + new Error(i18n.t("swap_lightning.too_small")) + ); + } else { + setFeeEstimateWarning(err); + } } finally { setLoading(false); } @@ -256,7 +263,7 @@ export function SwapLightning() { - {feeEstimateWarning()} + {feeEstimateWarning()?.message} diff --git a/src/routes/settings/ManageFederations.tsx b/src/routes/settings/ManageFederations.tsx index 2b8bf97c..24b529cb 100644 --- a/src/routes/settings/ManageFederations.tsx +++ b/src/routes/settings/ManageFederations.tsx @@ -7,9 +7,8 @@ import { } from "@modular-forms/solid"; import { FederationBalance, TagItem } from "@mutinywallet/mutiny-wasm"; import { A, useNavigate, useSearchParams } from "@solidjs/router"; -import { ArrowLeftRight, BadgeCheck, LogOut, Scan, Trash } from "lucide-solid"; +import { BadgeCheck, LogOut, Scan, Trash } from "lucide-solid"; import { - createMemo, createResource, createSignal, For, @@ -32,9 +31,7 @@ import { FederationPopup, InfoBox, KeyValue, - LabelCircle, LargeHeader, - LoadingShimmer, MediumHeader, MiniStringShower, MutinyWalletGuard, @@ -100,8 +97,6 @@ export function AddFederationForm(props: { const [error, setError] = createSignal(); const [success, setSuccess] = createSignal(""); - const [loadingFederation, setLoadingFederation] = createSignal(""); - const [params, setParams] = useSearchParams(); onMount(() => { @@ -126,16 +121,6 @@ export function AddFederationForm(props: { await onSelect([federation_code]); }; - const [federations] = createResource(async () => { - try { - const federations = await sw.discover_federations(); - return federations; - } catch (e) { - console.error(e); - return []; - } - }); - const onSelect = async (inviteCodes: string[]) => { setSuccess(""); setError(undefined); @@ -143,7 +128,6 @@ export function AddFederationForm(props: { for (const inviteCode of inviteCodes) { try { console.log("Adding federation:", inviteCode); - setLoadingFederation(inviteCode); const newFederation = await sw.new_federation(inviteCode); console.log("New federation added:", newFederation); break; @@ -168,6 +152,8 @@ export function AddFederationForm(props: { setSuccess( i18n.t("settings.manage_federations.federation_added_success") ); + // Reset the expiration warning seen state + actions.resetExpirationWarning(); await actions.refreshFederations(); if (props.refetch) { await props.refetch(); @@ -180,7 +166,6 @@ export function AddFederationForm(props: { console.error("Error submitting federation:", e); setError(eify(e)); } - setLoadingFederation(""); }; return ( @@ -233,125 +218,10 @@ export function AddFederationForm(props: { - - - {i18n.t("settings.manage_federations.discover")} - - - - - - - - - - - - - {(fed) => ( - - )} - - - - ); } -function FederationFormItem(props: { - fed: DiscoveredFederation; - onSelect: (invite_codes: string[]) => void; - loadingFederation: string; - setup: boolean; -}) { - const [state, _actions, _sw] = useMegaStore(); - const i18n = useI18n(); - - const alreadyAdded = createMemo(() => { - const matches = state.federations?.find((f) => - props.fed.invite_codes.includes(f.invite_code) - ); - return matches !== undefined; - }); - return ( - - - - - - - {props.fed.metadata?.name} - - - {props.fed.metadata?.about} - - - - - - - - - - - {timeAgo(props.fed.created_at)} - - - 0}> - - - - {(contact) => ( - - )} - - - - - - props.onSelect(props.fed.invite_codes)} - loading={props.fed.invite_codes.includes( - props.loadingFederation - )} - > - {i18n.t("settings.manage_federations.add")} - - - - - ); -} - function RecommendButton(props: { fed: MutinyFederationIdentity }) { const [_state, _actions, sw] = useMegaStore(); const i18n = useI18n(); @@ -435,8 +305,7 @@ function FederationListItem(props: { balance?: bigint; }) { const i18n = useI18n(); - const [state, actions, sw] = useMegaStore(); - const navigate = useNavigate(); + const [_state, actions, sw] = useMegaStore(); async function removeFederation() { setConfirmLoading(true); @@ -455,15 +324,6 @@ function FederationListItem(props: { const [transferDialogOpen, setTransferDialogOpen] = createSignal(false); - async function transferFunds() { - // If there's only one federation we need to let them know to add another - if (state.federations?.length && state.federations.length < 2) { - setTransferDialogOpen(true); - } else { - navigate("/transfer?from=" + props.fed.federation_id); - } - } - const [confirmOpen, setConfirmOpen] = createSignal(false); const [confirmLoading, setConfirmLoading] = createSignal(false); @@ -525,10 +385,6 @@ function FederationListItem(props: { inviteCode={props.fed.invite_code} /> - - - {i18n.t("settings.manage_federations.transfer_funds")} - diff --git a/src/routes/settings/Plus.tsx b/src/routes/settings/Plus.tsx index ee6aedc7..12a6d9fd 100644 --- a/src/routes/settings/Plus.tsx +++ b/src/routes/settings/Plus.tsx @@ -1,5 +1,4 @@ -import { A, useNavigate } from "@solidjs/router"; -import { AtSign } from "lucide-solid"; +import { A } from "@solidjs/router"; import { createResource, createSignal, @@ -13,7 +12,6 @@ import party from "~/assets/party.gif"; import { BackLink, Button, - ButtonCard, ConfirmDialog, DefaultMain, ExternalLink, @@ -170,8 +168,6 @@ export function Plus() { const i18n = useI18n(); const [state, _actions] = useMegaStore(); - const navigate = useNavigate(); - return ( @@ -198,22 +194,6 @@ export function Plus() { {i18n.t("settings.plus.wallet_connection")} - - - navigate("/settings/lightningaddress") - } - > - - - - {i18n.t( - "settings.lightning_address.create" - )} - - - - diff --git a/src/routes/settings/Root.tsx b/src/routes/settings/Root.tsx index 5b720c3d..8c0fe4c2 100644 --- a/src/routes/settings/Root.tsx +++ b/src/routes/settings/Root.tsx @@ -1,4 +1,3 @@ -import { Capacitor } from "@capacitor/core"; import { A } from "@solidjs/router"; import { ChevronRight } from "lucide-solid"; import { For, Show } from "solid-js"; @@ -8,7 +7,6 @@ import { DefaultMain, ExternalLink, LargeHeader, - MutinyPlusCta, NavBar, SettingsCard, TinyText, @@ -73,18 +71,11 @@ export function Settings() { // @ts-ignore const COMMIT_HASH = import.meta.env.__COMMIT_HASH__; - const selfHosted = state.settings?.selfhosted === "true"; - - const ios = Capacitor.getPlatform() === "ios"; - return ( {i18n.t("settings.header")} - - - { @@ -46,6 +48,7 @@ const validateNotTorUrl = async (value?: string) => { function SettingsStringsEditor(props: { initialSettings: MutinyWalletSettingStrings; }) { + const [_state, _actions, sw] = useMegaStore(); const i18n = useI18n(); const [settingsForm, { Form, Field }] = createForm({ @@ -54,15 +57,66 @@ function SettingsStringsEditor(props: { async function handleSubmit(values: MutinyWalletSettingStrings) { try { + if (values.lsp !== props.initialSettings.lsp) { + await sw.change_lsp( + values.lsp ? values.lsp : undefined, + undefined, + undefined + ); + } + await setSettings(values); window.location.reload(); } catch (e) { console.error(e); - showToast(eify(e)); + const err = eify(e); + if (err.message === "Failed to make a request to the LSP.") { + showToast( + new Error( + i18n.t("settings.servers.error_lsp_change_failed") + ) + ); + } else { + showToast(eify(e)); + } } - console.log(values); } + const MAINNET_LSP_OPTIONS = [ + { + value: "https://0conf.lnolymp.us", + label: "Olympus by Zeus" + }, + { + value: "https://lsp.voltageapi.com", + label: "Flow 2.0 by Voltage" + }, + { + value: "", + label: "None" + } + ]; + + const SIGNET_LSP_OPTIONS = [ + { + value: "https://mutinynet-flow.lnolymp.us", + label: "Olympus by Zeus" + }, + { + value: "https://signet-lsp.mutinywallet.com", + label: "Flow 2.0 by Voltage" + }, + { + value: "", + label: "None" + } + ]; + + const LSP_OPTIONS = + props.initialSettings.network === "signet" + ? SIGNET_LSP_OPTIONS + : MAINNET_LSP_OPTIONS; + return ( @@ -71,6 +125,42 @@ function SettingsStringsEditor(props: { {i18n.t("settings.servers.link")} + + + {(field, props) => ( + + + {i18n.t("settings.servers.lsp_label")} + + + + {({ value, label }) => ( + + {label} + + )} + + + + {i18n.t("settings.servers.lsp_caption")} + + + )} + { // Get federations const federations = await sw.list_federations(); - let expiration_warning: - | { - expiresTimestamp: number; - expiresMessage: string; - federationName: string; - } - | undefined = undefined; - - federations.forEach((f) => { - if (f.popup_countdown_message && f.popup_end_timestamp) { - expiration_warning = { - expiresTimestamp: f.popup_end_timestamp, - expiresMessage: f.popup_countdown_message, - federationName: f.federation_name - }; - } - }); + const expiration_warning = federationWarning(federations); setState({ wallet_loading: false, @@ -576,23 +561,7 @@ export const makeMegaStoreContext = () => { async refreshFederations() { const federations = await sw.list_federations(); - let expiration_warning: - | { - expiresTimestamp: number; - expiresMessage: string; - federationName: string; - } - | undefined = undefined; - - federations.forEach((f) => { - if (f.popup_countdown_message && f.popup_end_timestamp) { - expiration_warning = { - expiresTimestamp: f.popup_end_timestamp, - expiresMessage: f.popup_countdown_message, - federationName: f.federation_name - }; - } - }); + const expiration_warning = federationWarning(federations); setState({ federations, expiration_warning }); }, @@ -638,6 +607,9 @@ export const makeMegaStoreContext = () => { // Only show the expiration warning once per session clearExpirationWarning() { setState({ expiration_warning_seen: true }); + }, + resetExpirationWarning() { + setState({ expiration_warning_seen: false }); } }; diff --git a/src/utils/federationWarning.ts b/src/utils/federationWarning.ts new file mode 100644 index 00000000..8b13d53c --- /dev/null +++ b/src/utils/federationWarning.ts @@ -0,0 +1,37 @@ +import { MutinyFederationIdentity } from "~/routes/settings"; + +export function federationWarning(federations: MutinyFederationIdentity[]) { + const FEDERATIONS_WITH_WARNINGS = [ + // Freedom One + "c944b2fd1e7fe04ca87f9a57d7894cb69116cec6264cb52faa71228f4ec54cd6", + // Bitcoin Principles + "b21068c84f5b12ca4fdf93f3e443d3bd7c27e8642d0d52ea2e4dce6fdbbee9df" + ]; + + let expiration_warning: + | { + expiresTimestamp: number; + expiresMessage: string; + federationName: string; + } + | undefined = undefined; + + federations.forEach((f) => { + if (f.popup_countdown_message && f.popup_end_timestamp) { + expiration_warning = { + expiresTimestamp: f.popup_end_timestamp, + expiresMessage: f.popup_countdown_message, + federationName: f.federation_name + }; + } else if (FEDERATIONS_WITH_WARNINGS.includes(f.federation_id)) { + // If the federation has no expiration warning we'll do a generic one + expiration_warning = { + expiresTimestamp: 0, + expiresMessage: "", + federationName: "" + }; + } + }); + + return expiration_warning; +} diff --git a/src/utils/index.ts b/src/utils/index.ts index fbd8ef85..c79b328b 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -21,3 +21,4 @@ export * from "./bech32"; export * from "./keypad"; export * from "./debounce"; export * from "./blobToBase64"; +export * from "./federationWarning";
{props.fed.metadata?.about}