Skip to content

Commit ae44a83

Browse files
committed
toggle anon zaps
1 parent 6404e00 commit ae44a83

File tree

7 files changed

+143
-49
lines changed

7 files changed

+143
-49
lines changed

src/assets/icons/private-eye.svg

Lines changed: 3 additions & 0 deletions
Loading

src/components/AmountEditable.tsx

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
Show
88
} from "solid-js";
99

10-
import { AmountSats, BigMoney } from "~/components";
10+
import { AmountSats, BigMoney, SharpButton } from "~/components";
1111
import { useMegaStore } from "~/state/megaStore";
1212
import {
1313
btcFloatRounding,
@@ -106,7 +106,6 @@ export const AmountEditable: ParentComponent<{
106106
);
107107
}
108108
} else {
109-
console.log("we're in the fiat branch");
110109
sane = fiatInputSanitizer(
111110
value.replace(",", "."),
112111
state.fiat.maxFractionalDigits
@@ -270,20 +269,17 @@ function MethodChooser(props: {
270269
props.setChosenMethod && props.setChosenMethod(nextMethod);
271270
}
272271
return (
273-
<button
274-
onClick={setNextMethod}
275-
disabled={props.methods.length === 1}
276-
class="flex gap-2 rounded px-2 py-1 text-sm font-light text-m-grey-400 md:text-base"
277-
classList={{
278-
"border-b border-t border-b-white/10 border-t-white/50 bg-neutral-700":
279-
props.methods?.length > 1
280-
}}
281-
>
282-
<AmountSats
283-
amountSats={props.activeMethod.maxAmountSats!}
284-
denominationSize="sm"
285-
icon={methodToIcon(props.activeMethod.method)}
286-
/>
287-
</button>
272+
<>
273+
<SharpButton
274+
onClick={setNextMethod}
275+
disabled={props.methods.length === 1}
276+
>
277+
<AmountSats
278+
amountSats={props.activeMethod.maxAmountSats!}
279+
denominationSize="sm"
280+
icon={methodToIcon(props.activeMethod.method)}
281+
/>
282+
</SharpButton>
283+
</>
288284
);
289285
}

src/components/BigMoney.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export function BigMoney(props: {
103103
<div
104104
class="mb-2 mt-4 h-[2px] w-full rounded-full"
105105
classList={{
106-
"bg-m-blue animate-pulse": props.inputFocused,
106+
"bg-m-blue": props.inputFocused,
107107
"bg-m-blue/0": !props.inputFocused
108108
}}
109109
/>

src/components/SharpButton.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { JSX } from "solid-js";
2+
3+
export function SharpButton(props: {
4+
onClick: () => void;
5+
children: JSX.Element;
6+
disabled?: boolean;
7+
}) {
8+
return (
9+
<button
10+
onClick={() => props.onClick()}
11+
disabled={props.disabled}
12+
class="flex gap-2 rounded px-2 py-1 text-sm font-light text-m-grey-400 md:text-base"
13+
classList={{
14+
"border-b border-t border-b-white/10 border-t-white/50 bg-neutral-700":
15+
!props.disabled
16+
}}
17+
>
18+
{props.children}
19+
</button>
20+
);
21+
}

src/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,4 @@ export * from "./FeeDisplay";
5050
export * from "./ReceiveWarnings";
5151
export * from "./SimpleInput";
5252
export * from "./LabelCircle";
53+
export * from "./SharpButton";

src/i18n/en/translations.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ export default {
126126
sats_sent: "sats sent"
127127
},
128128
what_for: "What's this for?",
129+
zap_note: "Zap note",
129130
error_low_balance:
130131
"We do not have enough balance to pay the given amount.",
131132
error_invoice_match:
@@ -144,7 +145,9 @@ export default {
144145
payment_pending_description:
145146
"It's taking a while, but it's possible this payment may still go through. Please check 'Activity' for the current status.",
146147
hodl_invoice_warning:
147-
"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!"
148+
"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!",
149+
private: "Private",
150+
anonzap: "Anon Zap"
148151
},
149152
feedback: {
150153
header: "Give us feedback!",

src/routes/Send.tsx

Lines changed: 100 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { MutinyInvoice } from "@mutinywallet/mutiny-wasm";
1+
import { MutinyInvoice, TagItem } from "@mutinywallet/mutiny-wasm";
22
import { A, useNavigate, useSearchParams } from "@solidjs/router";
33
import {
44
createEffect,
@@ -16,6 +16,7 @@ import {
1616
import bolt from "~/assets/icons/bolt.svg";
1717
import chain from "~/assets/icons/chain.svg";
1818
import close from "~/assets/icons/close.svg";
19+
import privateEye from "~/assets/icons/private-eye.svg";
1920
import {
2021
ActivityDetailsModal,
2122
AmountEditable,
@@ -36,6 +37,7 @@ import {
3637
MethodChoice,
3738
MutinyWalletGuard,
3839
NavBar,
40+
SharpButton,
3941
showToast,
4042
SimpleInput,
4143
SmallHeader,
@@ -72,36 +74,18 @@ function DestinationShower(props: {
7274
nodePubkey?: string;
7375
lnurl?: string;
7476
lightning_address?: string;
75-
contact_id?: string;
77+
contact?: TagItem;
7678
}) {
77-
const [state, _actions] = useMegaStore();
78-
79-
async function getContact(id: string) {
80-
console.log("fetching contact", id);
81-
try {
82-
const contact = state.mutiny_wallet?.get_tag_item(id);
83-
console.log("fetching contact", contact);
84-
// This shouldn't happen
85-
if (!contact) throw new Error("Contact not found");
86-
return contact;
87-
} catch (e) {
88-
console.error(e);
89-
showToast(eify(e));
90-
}
91-
}
92-
93-
const [contact] = createResource(() => props.contact_id, getContact);
94-
9579
return (
9680
<Switch>
97-
<Match when={contact.latest}>
81+
<Match when={props.contact}>
9882
<DestinationItem
99-
title={contact()?.name || ""}
100-
value={contact()?.ln_address}
83+
title={props.contact?.name || ""}
84+
value={props.contact?.ln_address}
10185
icon={
10286
<LabelCircle
103-
name={contact()?.name || ""}
104-
image_url={contact()?.image_url}
87+
name={props.contact?.name || ""}
88+
image_url={props.contact?.image_url}
10589
contact
10690
label={false}
10791
/>
@@ -253,6 +237,7 @@ export function Send() {
253237

254238
// These can be derived from the destination or set by the user
255239
const [amountSats, setAmountSats] = createSignal(0n);
240+
const [unparsedAmount, setUnparsedAmount] = createSignal(true);
256241

257242
// These are derived from the incoming destination
258243
const [isAmtEditable, setIsAmtEditable] = createSignal(true);
@@ -509,8 +494,14 @@ export function Send() {
509494
} else {
510495
const parsed = BigInt(amountInput());
511496
console.log("parsed", parsed);
497+
if (!parsed) {
498+
setUnparsedAmount(true);
499+
}
512500
if (parsed > 0n) {
513501
setAmountSats(parsed);
502+
setUnparsedAmount(false);
503+
} else {
504+
setUnparsedAmount(true);
514505
}
515506
}
516507
});
@@ -574,12 +565,18 @@ export function Send() {
574565
sentDetails.fee_estimate = payment?.fees_paid || 0;
575566
}
576567
} else if (source() === "lightning" && lnurlp()) {
568+
const zapNpub =
569+
visibility() === "anonzap" && contact()?.npub
570+
? contact()?.npub
571+
: undefined;
572+
console.log("zapnpub", zapNpub);
573+
const comment = zapNpub ? whatForInput() : undefined;
577574
const payment = await state.mutiny_wallet?.lnurl_pay(
578575
lnurlp()!,
579576
amountSats(),
580-
undefined, // zap_npub
577+
zapNpub, // zap_npub
581578
tags,
582-
undefined // comment
579+
comment // comment
583580
);
584581
sentDetails.payment_hash = payment?.payment_hash;
585582

@@ -646,9 +643,11 @@ export function Send() {
646643

647644
const sendButtonDisabled = createMemo(() => {
648645
return (
646+
unparsedAmount() ||
649647
parsingDestination() ||
650648
sending() ||
651-
amountSats() === 0n ||
649+
amountSats() == 0n ||
650+
amountSats() === undefined ||
652651
!!error()
653652
);
654653
});
@@ -706,6 +705,34 @@ export function Send() {
706705
}
707706
});
708707

708+
const [visibility, setVisibility] = createSignal<"private" | "anonzap">(
709+
"private"
710+
);
711+
712+
function toggleVisibility() {
713+
if (visibility() === "private") {
714+
setVisibility("anonzap");
715+
} else {
716+
setVisibility("private");
717+
}
718+
}
719+
720+
async function getContact(id: string) {
721+
console.log("fetching contact", id);
722+
try {
723+
const contact = state.mutiny_wallet?.get_tag_item(id);
724+
console.log("fetching contact", contact);
725+
// This shouldn't happen
726+
if (!contact) throw new Error("Contact not found");
727+
return contact;
728+
} catch (e) {
729+
console.error(e);
730+
showToast(eify(e));
731+
}
732+
}
733+
734+
const [contact] = createResource(contactId, getContact);
735+
709736
return (
710737
<MutinyWalletGuard>
711738
<DefaultMain>
@@ -786,7 +813,7 @@ export function Send() {
786813
nodePubkey={nodePubkey()}
787814
lnurl={lnurlp()}
788815
lightning_address={lnAddress()}
789-
contact_id={contactId()}
816+
contact={contact()}
790817
/>
791818
</Suspense>
792819
<div class="flex-1" />
@@ -843,6 +870,45 @@ export function Send() {
843870
<div class="flex-1" />
844871

845872
<VStack>
873+
<Suspense>
874+
<div class="flex w-full">
875+
<SharpButton
876+
onClick={toggleVisibility}
877+
disabled={!contact()?.npub}
878+
>
879+
<div class="flex items-center gap-2">
880+
<Switch>
881+
<Match
882+
when={
883+
visibility() === "private"
884+
}
885+
>
886+
<img
887+
src={privateEye}
888+
alt="Private"
889+
/>
890+
<span>
891+
{i18n.t("send.private")}
892+
</span>
893+
</Match>
894+
<Match
895+
when={
896+
visibility() === "anonzap"
897+
}
898+
>
899+
<img
900+
src={bolt}
901+
alt="Anon Zap"
902+
/>
903+
<span>
904+
{i18n.t("send.anonzap")}
905+
</span>
906+
</Match>
907+
</Switch>
908+
</div>
909+
</SharpButton>
910+
</div>
911+
</Suspense>
846912
<form
847913
onSubmit={async (e) => {
848914
e.preventDefault();
@@ -853,7 +919,11 @@ export function Send() {
853919
>
854920
<SimpleInput
855921
type="text"
856-
placeholder={i18n.t("send.what_for")}
922+
placeholder={
923+
visibility() === "private"
924+
? i18n.t("send.what_for")
925+
: i18n.t("send.zap_note")
926+
}
857927
onInput={(e) =>
858928
setWhatForInput(e.currentTarget.value)
859929
}

0 commit comments

Comments
 (0)