diff --git a/src/assets/icons/help.svg b/src/assets/icons/help.svg new file mode 100644 index 0000000..b571eb4 --- /dev/null +++ b/src/assets/icons/help.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icons/megacheck.png b/src/assets/icons/megacheck.png index 7206e56..a3bb4ec 100644 Binary files a/src/assets/icons/megacheck.png and b/src/assets/icons/megacheck.png differ diff --git a/src/assets/icons/megaex.png b/src/assets/icons/megaex.png index ed75667..aa179c0 100644 Binary files a/src/assets/icons/megaex.png and b/src/assets/icons/megaex.png differ diff --git a/src/components/Activity.tsx b/src/components/Activity.tsx index 00d1c56..3c7044e 100644 --- a/src/components/Activity.tsx +++ b/src/components/Activity.tsx @@ -87,8 +87,6 @@ function UnifiedActivityItem(props: { ); } - - export function CombinedActivity(props: { limit?: number }) { const [state, _actions] = useMegaStore(); const i18n = useI18n(); diff --git a/src/components/ActivityItem.tsx b/src/components/ActivityItem.tsx index d396898..57511eb 100644 --- a/src/components/ActivityItem.tsx +++ b/src/components/ActivityItem.tsx @@ -1,11 +1,4 @@ -import { - Match, - ParentComponent, - Switch, - createMemo, - createResource -} from "solid-js"; -import { satsToUsd } from "~/utils/conversions"; +import { Match, ParentComponent, Switch, createResource } from "solid-js"; import bolt from "~/assets/icons/bolt.svg"; import chain from "~/assets/icons/chain.svg"; import shuffle from "~/assets/icons/shuffle.svg"; @@ -16,6 +9,7 @@ import { timeAgo } from "~/utils/prettyPrintTime"; import { generateGradient } from "~/utils/gradientHash"; import { useMegaStore } from "~/state/megaStore"; import { Contact } from "@mutinywallet/mutiny-wasm"; +import { Amount } from "~/components/Amount"; export const ActivityAmount: ParentComponent<{ amount: string; @@ -23,24 +17,6 @@ export const ActivityAmount: ParentComponent<{ positive?: boolean; center?: boolean; }> = (props) => { - const amountInUsd = createMemo(() => { - const parsed = Number(props.amount); - if (isNaN(parsed)) { - return props.amount; - } else { - return satsToUsd(props.price, parsed, true); - } - }); - - const prettyPrint = createMemo(() => { - const parsed = Number(props.amount); - if (isNaN(parsed)) { - return props.amount; - } else { - return parsed.toLocaleString(); - } - }); - return (
-
- {props.positive && "+ "} - {prettyPrint()} SATS -
-
- ≈ {amountInUsd()}  - USD -
+
); }; diff --git a/src/components/Amount.tsx b/src/components/Amount.tsx index a479c93..1c134e1 100644 --- a/src/components/Amount.tsx +++ b/src/components/Amount.tsx @@ -15,9 +15,11 @@ export function Amount(props: { amountSats: bigint | number | undefined; showFiat?: boolean; loading?: boolean; - centered?: boolean; - icon?: "lightning" | "chain"; whiteBg?: boolean; + align?: "left" | "center" | "right"; + icon?: "lightning" | "chain" | "plus" | "minus"; + size?: "small" | "large" | "xl"; + green?: boolean; }) { const [state, _] = useMegaStore(); @@ -28,7 +30,9 @@ export function Amount(props: {
@@ -39,28 +43,78 @@ export function Amount(props: { chain

+ + + + + + - + {props.loading ? "..." : prettyPrintAmount(props.amountSats)}   - SATS + + 1 || + Number(props.amountSats) === 0 + } + > + SATS + + + SAT + +

- ≈ {props.loading ? "..." : amountInUsd()}  - USD + ~ + +   + + {props.loading ? "..." : amountInUsd()} + +  USD +

diff --git a/src/components/AmountFiat.tsx b/src/components/AmountFiat.tsx new file mode 100644 index 0000000..f1e2a76 --- /dev/null +++ b/src/components/AmountFiat.tsx @@ -0,0 +1,22 @@ +import { useMegaStore } from "~/state/megaStore"; +import { satsToUsd } from "~/utils/conversions"; + +export function AmountFiat(props: { + amountSats: bigint | number | undefined; + loading?: boolean; + classes?: string; +}) { + const [state, _] = useMegaStore(); + + const amountInUsd = () => + satsToUsd(state.price, Number(props.amountSats) || 0, true); + + return ( +
+

+ ~{props.loading ? "..." : amountInUsd()} +  USD +

+
+ ); +} diff --git a/src/components/BalanceBox.tsx b/src/components/BalanceBox.tsx index 1876ceb..ae32a4b 100644 --- a/src/components/BalanceBox.tsx +++ b/src/components/BalanceBox.tsx @@ -45,6 +45,7 @@ export default function BalanceBox(props: { loading?: boolean }) { amountSats={state.balance?.lightning || 0} showFiat icon="lightning" + size="xl" />
@@ -54,6 +55,7 @@ export default function BalanceBox(props: { loading?: boolean }) { amountSats={totalOnchain()} showFiat icon="chain" + size="xl" />
diff --git a/src/components/MoreInfoModal.tsx b/src/components/MoreInfoModal.tsx index b75d30d..afcbaaf 100644 --- a/src/components/MoreInfoModal.tsx +++ b/src/components/MoreInfoModal.tsx @@ -1,20 +1,26 @@ import { Dialog } from "@kobalte/core"; -import { ParentComponent, createSignal } from "solid-js"; +import { ParentComponent, createSignal, JSXElement } from "solid-js"; import { DIALOG_CONTENT, DIALOG_POSITIONER, OVERLAY } from "./DetailsModal"; import { ModalCloseButton, SmallHeader } from "./layout"; import { ExternalLink } from "./layout/ExternalLink"; +import help from "~/assets/icons/help.svg"; import { useI18n } from "~/i18n/context"; -export function FeesModal() { +export function FeesModal(props: { icon?: boolean }) { const i18n = useI18n(); return ( - -

- {i18n.t("more_info_modal_p1")} -

-

- {i18n.t("more_info_modal_p2")} -

+ + ) : ( + i18n.t("why?") + ) + } + > +

{i18n.t("more_info_modal_p1")}

+

{i18n.t("more_info_modal_p2")}

{i18n.t("learn_more_about_liquidity")} @@ -25,7 +31,7 @@ export function FeesModal() { } export const MoreInfoModal: ParentComponent<{ - linkText: string; + linkText: string | JSXElement; title: string; }> = (props) => { const [open, setOpen] = createSignal(false); diff --git a/src/components/ResetRouter.tsx b/src/components/ResetRouter.tsx index c58034c..27e9da3 100644 --- a/src/components/ResetRouter.tsx +++ b/src/components/ResetRouter.tsx @@ -16,7 +16,8 @@ export function ResetRouter() { - Failing to make payments? Try resetting the lightning router. + Failing to make payments? Try resetting the lightning + router.

diff --git a/src/i18n/context.ts b/src/i18n/context.ts index f992da2..3dfc723 100644 --- a/src/i18n/context.ts +++ b/src/i18n/context.ts @@ -1,12 +1,12 @@ -import { createContext, useContext } from 'solid-js'; +import { createContext, useContext } from "solid-js"; import { i18n } from "i18next"; export const I18nContext = createContext(); export function useI18n() { const context = useContext(I18nContext); - - if (!context) throw new ReferenceError('I18nContext'); - + + if (!context) throw new ReferenceError("I18nContext"); + return context; } diff --git a/src/logic/mutinyWalletSetup.ts b/src/logic/mutinyWalletSetup.ts index 68b245e..4fe5996 100644 --- a/src/logic/mutinyWalletSetup.ts +++ b/src/logic/mutinyWalletSetup.ts @@ -83,7 +83,16 @@ export async function setAndGetMutinySettings( ); storage && localStorage.setItem("MUTINY_SETTINGS_storage", storage); - return { network, proxy, esplora, rgs, lsp, auth, subscriptions, storage }; + return { + network, + proxy, + esplora, + rgs, + lsp, + auth, + subscriptions, + storage + }; } catch (error) { console.error(error); throw error; diff --git a/src/root.css b/src/root.css index 6b709e9..98a6e15 100644 --- a/src/root.css +++ b/src/root.css @@ -65,5 +65,5 @@ select { } strong { -@apply font-semibold text-m-red; -} \ No newline at end of file + @apply font-semibold text-m-red; +} diff --git a/src/routes/Receive.tsx b/src/routes/Receive.tsx index 11a10ef..1756d65 100644 --- a/src/routes/Receive.tsx +++ b/src/routes/Receive.tsx @@ -121,28 +121,6 @@ function FeeWarning(props: { fee: bigint; flavor: ReceiveFlavor }) { ); } -function FeeExplanation(props: { fee: bigint }) { - return ( - // TODO: probably won't always be a fixed 2500? - - 1000n}> - - A lightning setup fee of{" "} - was charged for this - receive. - - - 0n}> - - A lightning service fee of{" "} - was charged for this - receive. - - - - ); -} - export default function Receive() { const [state, _actions] = useMegaStore(); const navigate = useNavigate(); @@ -448,14 +426,8 @@ export default function Receive() { - + { if (!open) clearAll(); @@ -466,45 +438,66 @@ export default function Receive() { }} > - +

+ {receiveState() === "paid" && + paidState() === "lightning_paid" + ? "Payment Received" + : "Payment Initiated"} +

-
-
- - { - if (!open) clearAll(); - }} - onConfirm={() => { - clearAll(); - navigate("/"); - }} - > - - - + - View Transaction - +
+

+ Fee +

+
+ +
+ {/*TODO: Add different fee hints insode of */} + +
+
+
+ + {/*TODO: Confirmation time estimate still not possible needs to be implemented in mutiny-node first + {/*TODO: add internal payment detail page* for lightning*/} + + + View payment details + +
diff --git a/src/routes/Send.tsx b/src/routes/Send.tsx index 6d76505..0f0eef1 100644 --- a/src/routes/Send.tsx +++ b/src/routes/Send.tsx @@ -28,8 +28,8 @@ import { Contact, MutinyInvoice } from "@mutinywallet/mutiny-wasm"; import { StyledRadioGroup } from "~/components/layout/Radio"; import { showToast } from "~/components/Toaster"; import eify from "~/utils/eify"; -import megacheck from "~/assets/icons/megacheck.png"; -import megaex from "~/assets/icons/megaex.png"; +import { MegaCheck } from "~/components/successfail/MegaCheck"; +import { MegaEx } from "~/components/successfail/MegaEx"; import mempoolTxUrl from "~/utils/mempoolTxUrl"; import { BackLink } from "~/components/layout/BackLink"; import { useNavigate } from "solid-start"; @@ -44,6 +44,7 @@ import { ExternalLink } from "~/components/layout/ExternalLink"; import { InfoBox } from "~/components/InfoBox"; import { useI18n } from "~/i18n/context"; import { ParsedParams, toParsedParams } from "~/logic/waila"; +import { FeesModal } from "~/components/MoreInfoModal"; export type SendSource = "lightning" | "onchain"; @@ -56,6 +57,7 @@ type SentDetails = { destination?: string; txid?: string; failure_reason?: string; + fee_estimate?: bigint | number; }; export function MethodChooser(props: { @@ -504,6 +506,7 @@ export default function Send() { sentDetails.amount = amountSats(); sentDetails.destination = address(); sentDetails.txid = txid; + sentDetails.fee_estimate = feeEstimate() ?? 0; } else { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const txid = await state.mutiny_wallet?.send_to_address( @@ -514,6 +517,7 @@ export default function Send() { sentDetails.amount = amountSats(); sentDetails.destination = address(); sentDetails.txid = txid; + sentDetails.fee_estimate = feeEstimate() ?? 0; } } setSentDetails(sentDetails as SentDetails); @@ -562,10 +566,7 @@ export default function Send() { {i18n.t("send_bitcoin")} { if (!open) setSentDetails(undefined); @@ -577,26 +578,47 @@ export default function Send() { > - fail -

- {sentDetails()?.failure_reason} -

+ +

+ {sentDetails()?.amount + ? "Payment Initiated" + : sentDetails()?.failure_reason} +

+ {/*TODO: add failure hint logic for different failure conditions*/}
- success + +

+ {sentDetails()?.amount + ? "Payment Initiated" + : sentDetails()?.failure_reason} +

+
+
+

+ Fees +

+
+ +
+ +
+
+
- {i18n.t("private_tags")} + + {i18n.t("private_tags")} + ("onchain"); const [amountSats, setAmountSats] = createSignal(0n); @@ -265,13 +268,8 @@ export default function Swap() { Swap to Lightning { @@ -284,35 +282,37 @@ export default function Swap() { > - fail - -

- { - channelOpenResult()?.failure_reason - ?.message - } -

+ +

+ {channelOpenResult()?.failure_reason + ? channelOpenResult()?.failure_reason + ?.message + : ""} +

+ {/*TODO: Error hint needs to be added for possible failure reasons*/}
- - success - + + +
+

+ Swap Initiated +

+

+ + + {channelOpenResult()?.channel?.balance.toLocaleString() ?? + "0"}{" "} + sats will be added to your Lightning + balance +

+ +
+
- View Transaction + {i18n.t("view_transaction")}
{/*
{JSON.stringify(channelOpenResult()?.channel?.value, null, 2)}
*/} diff --git a/src/routes/settings/Restore.tsx b/src/routes/settings/Restore.tsx index 0ea827e..a527245 100644 --- a/src/routes/settings/Restore.tsx +++ b/src/routes/settings/Restore.tsx @@ -241,13 +241,11 @@ export default function RestorePage() {

- You can restore an existing Mutiny Wallet from your 12 - word seed phrase. This will replace your existing + You can restore an existing Mutiny Wallet from your + 12 word seed phrase. This will replace your existing wallet, so make sure you know what you're doing!

-

- Do not use on multiple browsers at the same time. -

+

Do not use on multiple browsers at the same time.

@@ -256,4 +254,3 @@ export default function RestorePage() { ); } - diff --git a/src/routes/settings/index.tsx b/src/routes/settings/index.tsx index c29139a..ede803d 100644 --- a/src/routes/settings/index.tsx +++ b/src/routes/settings/index.tsx @@ -10,7 +10,6 @@ import NavBar from "~/components/NavBar"; import { A } from "solid-start"; import { For, Show } from "solid-js"; import forward from "~/assets/icons/forward.svg"; -import { useMegaStore } from "~/state/megaStore"; function SettingsLinkList(props: { header: string; @@ -58,8 +57,6 @@ function SettingsLinkList(props: { } export default function Settings() { - const [state, _actions] = useMegaStore(); - return ( diff --git a/tailwind.config.cjs b/tailwind.config.cjs index a983d9f..8a861de 100644 --- a/tailwind.config.cjs +++ b/tailwind.config.cjs @@ -25,6 +25,7 @@ module.exports = { "m-green": "hsla(163, 70%, 38%, 1)", "m-green-dark": "hsla(163, 70%, 28%, 1)", "m-blue": "hsla(220, 59%, 52%, 1)", + "m-blue-400": "hsla(219, 57%, 52%, 1)", "m-blue-dark": "hsla(220, 59%, 42%, 1)", "m-red": "hsla(343, 92%, 54%, 1)", "m-red-dark": "hsla(343, 92%, 44%, 1)", @@ -33,7 +34,9 @@ module.exports = { "m-grey-700": "hsla(0, 0%, 25%, 1)", "m-grey-750": "hsla(0, 0%, 17%, 1)", "m-grey-800": "hsla(0, 0%, 12%, 1)", - "m-grey-900": "hsla(0, 0%, 9%, 1)" + "m-grey-900": "hsla(0, 0%, 9%, 1)", + "m-grey-750": "hsla(0, 0%, 17%, 1)", + "m-grey-400": "hsla(0, 0%, 64%, 1)" }, backgroundImage: { "fade-to-blue": @@ -52,7 +55,9 @@ module.exports = { "inner-button-disabled": "2px 2px 4px rgba(0, 0, 0, 0.05), inset 2px 2px 4px rgba(255, 255, 255, 0.05), inset -2px -2px 6px rgba(0, 0, 0, 0.1)", "fancy-card": "0px 4px 4px rgba(0, 0, 0, 0.1)", - above: "0px -4px 10px rgba(0, 0, 0, 0.25)" + "subtle-bevel": + "inset -4px -4px 6px 0 rgba(0, 0, 0, 0.10), inset 4px 4px 4px 0 rgba(255, 255, 255, 0.10)", + above: "0px -4px 10px rgba(0, 0, 0, 0.25)", }, textShadow: { button: "1px 1px 0px rgba(0, 0, 0, 0.4)"