diff --git a/src/components/DeleteEverything.tsx b/src/components/DeleteEverything.tsx
index 135e504..2a90794 100644
--- a/src/components/DeleteEverything.tsx
+++ b/src/components/DeleteEverything.tsx
@@ -1,3 +1,4 @@
+import initMutinyWallet, { MutinyWallet } from "@mutinywallet/mutiny-wasm";
import { createSignal } from "solid-js";
import { ConfirmDialog } from "~/components/Dialog";
import { Button } from "~/components/layout";
@@ -5,8 +6,8 @@ import { showToast } from "~/components/Toaster";
import { useMegaStore } from "~/state/megaStore";
import eify from "~/utils/eify";
-export function DeleteEverything() {
- const [_state, actions] = useMegaStore();
+export function DeleteEverything(props: { emergency?: boolean }) {
+ const [state, actions] = useMegaStore();
async function confirmReset() {
setConfirmOpen(true);
@@ -18,7 +19,21 @@ export function DeleteEverything() {
async function resetNode() {
try {
setConfirmLoading(true);
- await actions.deleteMutinyWallet();
+ // If we're in a context where the wallet is loaded we want to use the regular action to delete it
+ // Otherwise we just call the import_json method directly
+ if (state.mutiny_wallet && !props.emergency) {
+ try {
+ await actions.deleteMutinyWallet();
+ } catch (e) {
+ // If we can't stop we want to keep going
+ console.error(e);
+ }
+ } else {
+ // If there's no mutiny_wallet loaded we might need to initialize WASM
+ await initMutinyWallet();
+ await MutinyWallet.import_json("{}");
+ }
+
showToast({ title: "Deleted", description: `Deleted all data` });
setTimeout(() => {
diff --git a/src/components/ErrorDisplay.tsx b/src/components/ErrorDisplay.tsx
index 8c76195..70234fe 100644
--- a/src/components/ErrorDisplay.tsx
+++ b/src/components/ErrorDisplay.tsx
@@ -1,11 +1,13 @@
-import { Title } from "solid-start";
+import { A, Title } from "solid-start";
import {
Button,
DefaultMain,
LargeHeader,
+ NiceP,
SafeArea,
SmallHeader
} from "~/components/layout";
+import { ExternalLink } from "./layout/ExternalLink";
export default function ErrorDisplay(props: { error: Error }) {
return (
@@ -18,6 +20,17 @@ export default function ErrorDisplay(props: { error: Error }) {
{props.error.name} :{" "}
{props.error.message}
+
+ Try reloading this page or clicking the "Dangit" button. If
+ you keep having problems,{" "}
+
+ reach out to us for support.
+
+
+
+ Getting desperate? Try the{" "}
+ emergency kit.
+
(window.location.href = "/")}
diff --git a/src/components/ImportExport.tsx b/src/components/ImportExport.tsx
index 9a0ab8f..2a646ca 100644
--- a/src/components/ImportExport.tsx
+++ b/src/components/ImportExport.tsx
@@ -6,13 +6,13 @@ import { showToast } from "./Toaster";
import { downloadTextFile } from "~/utils/download";
import { createFileUploader } from "@solid-primitives/upload";
import { ConfirmDialog } from "./Dialog";
-import { MutinyWallet } from "@mutinywallet/mutiny-wasm";
+import initMutinyWallet, { MutinyWallet } from "@mutinywallet/mutiny-wasm";
-export function ImportExport() {
+export function ImportExport(props: { emergency?: boolean }) {
const [state, _] = useMegaStore();
async function handleSave() {
- const json = await state.mutiny_wallet?.export_json();
+ const json = await MutinyWallet.export_json();
downloadTextFile(json || "", "mutiny-state.json");
}
@@ -39,17 +39,28 @@ export function ImportExport() {
fileReader.readAsText(file, "UTF-8");
});
+ if (state.mutiny_wallet && !props.emergency) {
+ console.log("Mutiny wallet loaded, stopping");
+ try {
+ await state.mutiny_wallet.stop();
+ } catch (e) {
+ console.error(e);
+ }
+ } else {
+ // If there's no mutiny wallet loaded we need to initialize WASM
+ console.log("Initializing WASM");
+ await initMutinyWallet();
+ }
+
// This should throw if there's a parse error, so we won't end up clearing
if (text) {
JSON.parse(text);
- MutinyWallet.import_json(text);
+ await MutinyWallet.import_json(text);
}
- if (state.mutiny_wallet) {
- await state.mutiny_wallet.stop();
- }
-
- window.location.href = "/";
+ setTimeout(() => {
+ window.location.href = "/";
+ }, 1000);
} catch (e) {
showToast(eify(e));
} finally {
diff --git a/src/components/Logs.tsx b/src/components/Logs.tsx
index 15468d1..0eb0eff 100644
--- a/src/components/Logs.tsx
+++ b/src/components/Logs.tsx
@@ -1,13 +1,12 @@
+import { MutinyWallet } from "@mutinywallet/mutiny-wasm";
import { Button, InnerCard, NiceP, VStack } from "~/components/layout";
-import { useMegaStore } from "~/state/megaStore";
import { downloadTextFile } from "~/utils/download";
export function Logs() {
- const [state, _] = useMegaStore();
-
async function handleSave() {
try {
- const logs = await state.mutiny_wallet?.get_logs();
+ const logs = await MutinyWallet.get_logs();
+
downloadTextFile(
logs.join("") || "",
"mutiny-logs.txt",
diff --git a/src/components/SetupErrorDisplay.tsx b/src/components/SetupErrorDisplay.tsx
index 619bed3..bd5e722 100644
--- a/src/components/SetupErrorDisplay.tsx
+++ b/src/components/SetupErrorDisplay.tsx
@@ -1,7 +1,32 @@
import { Title } from "solid-start";
-import { DefaultMain, LargeHeader, NiceP, SafeArea } from "~/components/layout";
+import {
+ DefaultMain,
+ LargeHeader,
+ NiceP,
+ SafeArea,
+ SmallHeader
+} from "~/components/layout";
import { ExternalLink } from "./layout/ExternalLink";
import { Match, Switch } from "solid-js";
+import { ImportExport } from "./ImportExport";
+import { Logs } from "./Logs";
+import { DeleteEverything } from "./DeleteEverything";
+
+function ErrorFooter() {
+ return (
+ <>
+
+
+ Bugs? Feedback?{" "}
+
+
+ Create an issue
+
+
+
+ >
+ );
+}
export default function SetupErrorDisplay(props: { error: Error }) {
return (
@@ -22,18 +47,10 @@ export default function SetupErrorDisplay(props: { error: Error }) {
this page, or close this tab and refresh the other
one.
-
-
- Bugs? Feedback?{" "}
-
-
- Create an issue
-
-
-
+
-
+
Incompatible browser
Incompatible browser detected
@@ -61,15 +78,39 @@ export default function SetupErrorDisplay(props: { error: Error }) {
Supported Browsers
-
-
- Bugs? Feedback?{" "}
-
-
- Create an issue
-
-
+
+
+
+
+ Failed to load
+
+ Failed to load Mutiny
+
+ {props.error.name} :{" "}
+ {props.error.message}
+
+ Something went wrong while booting up Mutiny Wallet.
+
+
+ If your wallet seems broken, here are some tools to
+ try to debug and repair it.
+
+
+ If you have any questions on what these buttons do,
+ please{" "}
+
+ reach out to us for support.
+
+
+
+
+
+ Danger zone
+
+
+
+
diff --git a/src/components/layout/index.tsx b/src/components/layout/index.tsx
index a49b42a..290d626 100644
--- a/src/components/layout/index.tsx
+++ b/src/components/layout/index.tsx
@@ -1,4 +1,11 @@
-import { JSX, ParentComponent, Show, Suspense, createResource } from "solid-js";
+import {
+ JSX,
+ ParentComponent,
+ Show,
+ Suspense,
+ createResource,
+ createSignal
+} from "solid-js";
import Linkify from "./Linkify";
import { Button, ButtonLink } from "./Button";
import { Checkbox as KCheckbox, Separator } from "@kobalte/core";
@@ -7,6 +14,7 @@ import check from "~/assets/icons/check.svg";
import { MutinyTagItem } from "~/utils/tags";
import { generateGradient } from "~/utils/gradientHash";
import close from "~/assets/icons/close.svg";
+import { A } from "solid-start";
export { Button, ButtonLink, Linkify };
@@ -84,9 +92,24 @@ export const DefaultMain: ParentComponent = (props) => {
};
export const FullscreenLoader = () => {
+ const [waitedTooLong, setWaitedTooLong] = createSignal(false);
+
+ setTimeout(() => {
+ setWaitedTooLong(true);
+ }, 10000);
+
return (
-
+
+
+
+ Stuck on this screen? Try reloading. If that doesn't work,
+ check out the{" "}
+
+ emergency kit.
+
+
+
);
};
diff --git a/src/logic/browserCompatibility.ts b/src/logic/browserCompatibility.ts
index d7ed2ea..fae5ca9 100644
--- a/src/logic/browserCompatibility.ts
+++ b/src/logic/browserCompatibility.ts
@@ -6,7 +6,7 @@ export async function checkBrowserCompatibility(): Promise
{
localStorage.removeItem("test");
} catch (e) {
console.error(e);
- throw new Error("LocalStorage is not supported.");
+ throw new Error("Browser error: LocalStorage is not supported.");
}
// Check if the browser supports WebAssembly
@@ -17,7 +17,7 @@ export async function checkBrowserCompatibility(): Promise {
Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00)
)
) {
- throw new Error("WebAssembly is not supported.");
+ throw new Error("Browser error: WebAssembly is not supported.");
}
console.debug("Checking indexedDB");
@@ -26,7 +26,7 @@ export async function checkBrowserCompatibility(): Promise {
await openDatabase();
} catch (e) {
console.error(e);
- throw new Error("IndexedDB is not supported.");
+ throw new Error("Browser error: IndexedDB is not supported.");
}
return true;
diff --git a/src/logic/mutinyWalletSetup.ts b/src/logic/mutinyWalletSetup.ts
index 6e9cde7..810e0d0 100644
--- a/src/logic/mutinyWalletSetup.ts
+++ b/src/logic/mutinyWalletSetup.ts
@@ -117,15 +117,18 @@ export async function setupMutinyWallet(
console.log("Using esplora address", esplora);
console.log("Using rgs address", rgs);
console.log("Using lsp address", lsp);
-
const mutinyWallet = await new MutinyWallet(
+ // Password
"",
+ // Mnemonic
undefined,
proxy,
network,
esplora,
rgs,
- lsp
+ lsp,
+ // Do not connect peers
+ undefined
);
const nodes = await mutinyWallet.list_nodes();
diff --git a/src/routes/EmergencyKit.tsx b/src/routes/EmergencyKit.tsx
new file mode 100644
index 0000000..0d074da
--- /dev/null
+++ b/src/routes/EmergencyKit.tsx
@@ -0,0 +1,45 @@
+import { DeleteEverything } from "~/components/DeleteEverything";
+import { ImportExport } from "~/components/ImportExport";
+import { Logs } from "~/components/Logs";
+import NavBar from "~/components/NavBar";
+import {
+ DefaultMain,
+ LargeHeader,
+ NiceP,
+ SafeArea,
+ SmallHeader,
+ VStack
+} from "~/components/layout";
+import { BackLink } from "~/components/layout/BackLink";
+import { ExternalLink } from "~/components/layout/ExternalLink";
+
+export default function EmergencyKit() {
+ return (
+
+
+
+ Emergency Kit
+
+
+ If your wallet seems broken, here are some tools to try
+ to debug and repair it.
+
+
+ If you have any questions on what these buttons do,
+ please{" "}
+
+ reach out to us for support.
+
+
+
+
+
+ Danger zone
+
+
+
+
+
+
+ );
+}
diff --git a/src/routes/Settings.tsx b/src/routes/Settings.tsx
index d022326..8bf5cb4 100644
--- a/src/routes/Settings.tsx
+++ b/src/routes/Settings.tsx
@@ -14,6 +14,8 @@ import { SeedWords } from "~/components/SeedWords";
import { SettingsStringsEditor } from "~/components/SettingsStringsEditor";
import { useMegaStore } from "~/state/megaStore";
import { LiquidityMonitor } from "~/components/LiquidityMonitor";
+import { A } from "solid-start";
+import { Suspense } from "solid-js";
export default function Settings() {
const [store, _actions] = useMegaStore();
@@ -41,6 +43,13 @@ export default function Settings() {
+
+
+ Having some serious problems with your wallet?
+ Check out the{" "}
+ emergency kit.
+
+
diff --git a/src/state/megaStore.tsx b/src/state/megaStore.tsx
index 6699a39..a20ccae 100644
--- a/src/state/megaStore.tsx
+++ b/src/state/megaStore.tsx
@@ -151,17 +151,23 @@ export const Provider: ParentComponent = (props) => {
});
} catch (e) {
console.error(e);
+ setState({ setup_error: eify(e) });
}
},
async deleteMutinyWallet(): Promise {
- await state.mutiny_wallet?.stop();
- setState((prevState) => ({
- ...prevState,
- mutiny_wallet: undefined,
- deleting: true
- }));
- MutinyWallet.import_json("{}");
- localStorage.clear();
+ try {
+ if (state.mutiny_wallet) {
+ await state.mutiny_wallet?.stop();
+ }
+ setState((prevState) => ({
+ ...prevState,
+ mutiny_wallet: undefined,
+ deleting: true
+ }));
+ MutinyWallet.import_json("{}");
+ } catch (e) {
+ console.error(e);
+ }
},
setWaitlistId(waitlist_id: string) {
setState({ waitlist_id });