toggle anon zaps

This commit is contained in:
Paul Miller
2024-01-13 19:02:56 +00:00
parent 6404e00086
commit ae44a83087
7 changed files with 143 additions and 49 deletions

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
<path d="M9.8585 7.5L12.5002 10.1333V10C12.5002 9.33696 12.2368 8.70107 11.7679 8.23223C11.2991 7.76339 10.6632 7.5 10.0002 7.5H9.8585ZM6.27516 8.16667L7.56683 9.45833C7.52516 9.63333 7.50016 9.80833 7.50016 10C7.50016 10.663 7.76356 11.2989 8.2324 11.7678C8.70124 12.2366 9.33712 12.5 10.0002 12.5C10.1835 12.5 10.3668 12.475 10.5418 12.4333L11.8335 13.725C11.2752 14 10.6585 14.1667 10.0002 14.1667C8.89509 14.1667 7.83529 13.7277 7.05388 12.9463C6.27248 12.1649 5.8335 11.1051 5.8335 10C5.8335 9.34167 6.00016 8.725 6.27516 8.16667ZM1.66683 3.55833L3.56683 5.45833L3.94183 5.83333C2.56683 6.91667 1.4835 8.33333 0.833496 10C2.27516 13.6583 5.8335 16.25 10.0002 16.25C11.2918 16.25 12.5252 16 13.6502 15.55L14.0085 15.9L16.4418 18.3333L17.5002 17.275L2.72516 2.5M10.0002 5.83333C11.1052 5.83333 12.165 6.27232 12.9464 7.05372C13.7278 7.83512 14.1668 8.89493 14.1668 10C14.1668 10.5333 14.0585 11.05 13.8668 11.5167L16.3085 13.9583C17.5585 12.9167 18.5585 11.55 19.1668 10C17.7252 6.34167 14.1668 3.75 10.0002 3.75C8.8335 3.75 7.71683 3.95833 6.66683 4.33333L8.47516 6.125C8.95016 5.94167 9.4585 5.83333 10.0002 5.83333Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -7,7 +7,7 @@ import {
Show
} from "solid-js";
import { AmountSats, BigMoney } from "~/components";
import { AmountSats, BigMoney, SharpButton } from "~/components";
import { useMegaStore } from "~/state/megaStore";
import {
btcFloatRounding,
@@ -106,7 +106,6 @@ export const AmountEditable: ParentComponent<{
);
}
} else {
console.log("we're in the fiat branch");
sane = fiatInputSanitizer(
value.replace(",", "."),
state.fiat.maxFractionalDigits
@@ -270,20 +269,17 @@ function MethodChooser(props: {
props.setChosenMethod && props.setChosenMethod(nextMethod);
}
return (
<button
onClick={setNextMethod}
disabled={props.methods.length === 1}
class="flex gap-2 rounded px-2 py-1 text-sm font-light text-m-grey-400 md:text-base"
classList={{
"border-b border-t border-b-white/10 border-t-white/50 bg-neutral-700":
props.methods?.length > 1
}}
>
<AmountSats
amountSats={props.activeMethod.maxAmountSats!}
denominationSize="sm"
icon={methodToIcon(props.activeMethod.method)}
/>
</button>
<>
<SharpButton
onClick={setNextMethod}
disabled={props.methods.length === 1}
>
<AmountSats
amountSats={props.activeMethod.maxAmountSats!}
denominationSize="sm"
icon={methodToIcon(props.activeMethod.method)}
/>
</SharpButton>
</>
);
}

View File

@@ -103,7 +103,7 @@ export function BigMoney(props: {
<div
class="mb-2 mt-4 h-[2px] w-full rounded-full"
classList={{
"bg-m-blue animate-pulse": props.inputFocused,
"bg-m-blue": props.inputFocused,
"bg-m-blue/0": !props.inputFocused
}}
/>

View File

@@ -0,0 +1,21 @@
import { JSX } from "solid-js";
export function SharpButton(props: {
onClick: () => void;
children: JSX.Element;
disabled?: boolean;
}) {
return (
<button
onClick={() => props.onClick()}
disabled={props.disabled}
class="flex gap-2 rounded px-2 py-1 text-sm font-light text-m-grey-400 md:text-base"
classList={{
"border-b border-t border-b-white/10 border-t-white/50 bg-neutral-700":
!props.disabled
}}
>
{props.children}
</button>
);
}

View File

@@ -50,3 +50,4 @@ export * from "./FeeDisplay";
export * from "./ReceiveWarnings";
export * from "./SimpleInput";
export * from "./LabelCircle";
export * from "./SharpButton";

View File

@@ -126,6 +126,7 @@ export default {
sats_sent: "sats sent"
},
what_for: "What's this for?",
zap_note: "Zap note",
error_low_balance:
"We do not have enough balance to pay the given amount.",
error_invoice_match:
@@ -144,7 +145,9 @@ export default {
payment_pending_description:
"It's taking a while, but it's possible this payment may still go through. Please check 'Activity' for the current status.",
hodl_invoice_warning:
"This is a hodl invoice. Payments to hodl invoices can cause channel force closes, which results in high on-chain fees. Pay at your own risk!"
"This is a hodl invoice. Payments to hodl invoices can cause channel force closes, which results in high on-chain fees. Pay at your own risk!",
private: "Private",
anonzap: "Anon Zap"
},
feedback: {
header: "Give us feedback!",

View File

@@ -1,4 +1,4 @@
import { MutinyInvoice } from "@mutinywallet/mutiny-wasm";
import { MutinyInvoice, TagItem } from "@mutinywallet/mutiny-wasm";
import { A, useNavigate, useSearchParams } from "@solidjs/router";
import {
createEffect,
@@ -16,6 +16,7 @@ import {
import bolt from "~/assets/icons/bolt.svg";
import chain from "~/assets/icons/chain.svg";
import close from "~/assets/icons/close.svg";
import privateEye from "~/assets/icons/private-eye.svg";
import {
ActivityDetailsModal,
AmountEditable,
@@ -36,6 +37,7 @@ import {
MethodChoice,
MutinyWalletGuard,
NavBar,
SharpButton,
showToast,
SimpleInput,
SmallHeader,
@@ -72,36 +74,18 @@ function DestinationShower(props: {
nodePubkey?: string;
lnurl?: string;
lightning_address?: string;
contact_id?: string;
contact?: TagItem;
}) {
const [state, _actions] = useMegaStore();
async function getContact(id: string) {
console.log("fetching contact", id);
try {
const contact = state.mutiny_wallet?.get_tag_item(id);
console.log("fetching contact", contact);
// This shouldn't happen
if (!contact) throw new Error("Contact not found");
return contact;
} catch (e) {
console.error(e);
showToast(eify(e));
}
}
const [contact] = createResource(() => props.contact_id, getContact);
return (
<Switch>
<Match when={contact.latest}>
<Match when={props.contact}>
<DestinationItem
title={contact()?.name || ""}
value={contact()?.ln_address}
title={props.contact?.name || ""}
value={props.contact?.ln_address}
icon={
<LabelCircle
name={contact()?.name || ""}
image_url={contact()?.image_url}
name={props.contact?.name || ""}
image_url={props.contact?.image_url}
contact
label={false}
/>
@@ -253,6 +237,7 @@ export function Send() {
// These can be derived from the destination or set by the user
const [amountSats, setAmountSats] = createSignal(0n);
const [unparsedAmount, setUnparsedAmount] = createSignal(true);
// These are derived from the incoming destination
const [isAmtEditable, setIsAmtEditable] = createSignal(true);
@@ -509,8 +494,14 @@ export function Send() {
} else {
const parsed = BigInt(amountInput());
console.log("parsed", parsed);
if (!parsed) {
setUnparsedAmount(true);
}
if (parsed > 0n) {
setAmountSats(parsed);
setUnparsedAmount(false);
} else {
setUnparsedAmount(true);
}
}
});
@@ -574,12 +565,18 @@ export function Send() {
sentDetails.fee_estimate = payment?.fees_paid || 0;
}
} else if (source() === "lightning" && lnurlp()) {
const zapNpub =
visibility() === "anonzap" && contact()?.npub
? contact()?.npub
: undefined;
console.log("zapnpub", zapNpub);
const comment = zapNpub ? whatForInput() : undefined;
const payment = await state.mutiny_wallet?.lnurl_pay(
lnurlp()!,
amountSats(),
undefined, // zap_npub
zapNpub, // zap_npub
tags,
undefined // comment
comment // comment
);
sentDetails.payment_hash = payment?.payment_hash;
@@ -646,9 +643,11 @@ export function Send() {
const sendButtonDisabled = createMemo(() => {
return (
unparsedAmount() ||
parsingDestination() ||
sending() ||
amountSats() === 0n ||
amountSats() == 0n ||
amountSats() === undefined ||
!!error()
);
});
@@ -706,6 +705,34 @@ export function Send() {
}
});
const [visibility, setVisibility] = createSignal<"private" | "anonzap">(
"private"
);
function toggleVisibility() {
if (visibility() === "private") {
setVisibility("anonzap");
} else {
setVisibility("private");
}
}
async function getContact(id: string) {
console.log("fetching contact", id);
try {
const contact = state.mutiny_wallet?.get_tag_item(id);
console.log("fetching contact", contact);
// This shouldn't happen
if (!contact) throw new Error("Contact not found");
return contact;
} catch (e) {
console.error(e);
showToast(eify(e));
}
}
const [contact] = createResource(contactId, getContact);
return (
<MutinyWalletGuard>
<DefaultMain>
@@ -786,7 +813,7 @@ export function Send() {
nodePubkey={nodePubkey()}
lnurl={lnurlp()}
lightning_address={lnAddress()}
contact_id={contactId()}
contact={contact()}
/>
</Suspense>
<div class="flex-1" />
@@ -843,6 +870,45 @@ export function Send() {
<div class="flex-1" />
<VStack>
<Suspense>
<div class="flex w-full">
<SharpButton
onClick={toggleVisibility}
disabled={!contact()?.npub}
>
<div class="flex items-center gap-2">
<Switch>
<Match
when={
visibility() === "private"
}
>
<img
src={privateEye}
alt="Private"
/>
<span>
{i18n.t("send.private")}
</span>
</Match>
<Match
when={
visibility() === "anonzap"
}
>
<img
src={bolt}
alt="Anon Zap"
/>
<span>
{i18n.t("send.anonzap")}
</span>
</Match>
</Switch>
</div>
</SharpButton>
</div>
</Suspense>
<form
onSubmit={async (e) => {
e.preventDefault();
@@ -853,7 +919,11 @@ export function Send() {
>
<SimpleInput
type="text"
placeholder={i18n.t("send.what_for")}
placeholder={
visibility() === "private"
? i18n.t("send.what_for")
: i18n.t("send.zap_note")
}
onInput={(e) =>
setWhatForInput(e.currentTarget.value)
}