chore: formatting
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Kieran 2024-01-04 16:11:10 +00:00
parent 7bc00b4624
commit 47d92fe171
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
8 changed files with 217 additions and 132 deletions

View File

@ -20,12 +20,15 @@ const ConnectCashu = () => {
} }
const { CashuWallet } = await import("@/Wallet/Cashu"); const { CashuWallet } = await import("@/Wallet/Cashu");
const connection = new CashuWallet({ const connection = new CashuWallet(
url: config, {
keys: {}, url: config,
proofs: [], keys: {},
keysets: [] proofs: [],
}, () => { }); keysets: [],
},
() => {},
);
await connection.login(); await connection.login();
const info = await connection.getInfo(); const info = await connection.getInfo();
const newWallet = { const newWallet = {

View File

@ -89,16 +89,17 @@ export default function WalletPage(props: { showHistory: boolean }) {
function walletList() { function walletList() {
if (walletState.configs.length === 0) { if (walletState.configs.length === 0) {
return (<div className="flex flex-col gap-4"> return (
<div> <div className="flex flex-col gap-4">
<button onClick={() => navigate("/settings/wallet")}> <div>
<FormattedMessage defaultMessage="Connect Wallet" id="cg1VJ2" /> <button onClick={() => navigate("/settings/wallet")}>
</button> <FormattedMessage defaultMessage="Connect Wallet" id="cg1VJ2" />
</button>
</div>
<small>
<FormattedMessage defaultMessage="Connect a wallet to send instant payments" id="Yf3DwC" />
</small>
</div> </div>
<small>
<FormattedMessage defaultMessage="Connect a wallet to send instant payments" id="Yf3DwC" />
</small>
</div>
); );
} }
return ( return (
@ -129,9 +130,11 @@ export default function WalletPage(props: { showHistory: boolean }) {
<h3> <h3>
<FormattedMessage defaultMessage="Payments" id="pukxg/" description="Wallet transation history" /> <FormattedMessage defaultMessage="Payments" id="pukxg/" description="Wallet transation history" />
</h3> </h3>
{history === undefined && <small> {history === undefined && (
<FormattedMessage defaultMessage="Your sent and received payments will show up here." id="i5gBFz" /> <small>
</small>} <FormattedMessage defaultMessage="Your sent and received payments will show up here." id="i5gBFz" />
</small>
)}
{history?.map(a => { {history?.map(a => {
const dirClassname = { const dirClassname = {
"text-[--success]": a.direction === "in", "text-[--success]": a.direction === "in",
@ -231,14 +234,18 @@ export default function WalletPage(props: { showHistory: boolean }) {
/> />
</div> </div>
<div className="flex gap-2"> <div className="flex gap-2">
{wallet?.canCreateInvoice() && <AsyncButton className="secondary" onClick={() => navigate("/wallet/receive")}> {wallet?.canCreateInvoice() && (
<FormattedMessage defaultMessage="Receive" id="ULXFfP" /> <AsyncButton className="secondary" onClick={() => navigate("/wallet/receive")}>
<Icon name="arrow-up-right" className="rotate-180" /> <FormattedMessage defaultMessage="Receive" id="ULXFfP" />
</AsyncButton>} <Icon name="arrow-up-right" className="rotate-180" />
{wallet?.canPayInvoice() && <AsyncButton onClick={() => navigate("/wallet/send")}> </AsyncButton>
<FormattedMessage defaultMessage="Send" id="9WRlF4" /> )}
<Icon name="arrow-up-right" /> {wallet?.canPayInvoice() && (
</AsyncButton>} <AsyncButton onClick={() => navigate("/wallet/send")}>
<FormattedMessage defaultMessage="Send" id="9WRlF4" />
<Icon name="arrow-up-right" />
</AsyncButton>
)}
</div> </div>
</div> </div>
{walletHistory()} {walletHistory()}

View File

@ -6,50 +6,64 @@ import { useState } from "react";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
export function WalletReceivePage() { export function WalletReceivePage() {
const wallets = useWallet(); const wallets = useWallet();
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
const [invoice, setInvoice] = useState(""); const [invoice, setInvoice] = useState("");
const [error, setError] = useState(""); const [error, setError] = useState("");
const [amount, setAmount] = useState(0); const [amount, setAmount] = useState(0);
const [comment, setComment] = useState(""); const [comment, setComment] = useState("");
return <div className="p flex flex-col gap-4"> return (
<div className="text-2xl font-bold"> <div className="p flex flex-col gap-4">
<FormattedMessage defaultMessage="Receive" id="ULXFfP" /> <div className="text-2xl font-bold">
</div> <FormattedMessage defaultMessage="Receive" id="ULXFfP" />
<p> </div>
<FormattedMessage defaultMessage="Receiving to <b>{wallet}</b>" id="PXQ0z0" values={{ <p>
b: b => <b>&quot;{b}&quot;</b>, <FormattedMessage
wallet: wallets.config?.info.alias defaultMessage="Receiving to <b>{wallet}</b>"
}} /> id="PXQ0z0"
</p> values={{
<input type="text" placeholder={formatMessage({ defaultMessage: "Comment", id: 'LgbKvU' })} value={comment} onChange={e => setComment(e.target.value)} /> b: b => <b>&quot;{b}&quot;</b>,
<div className="flex flex-col"> wallet: wallets.config?.info.alias,
<small> }}
<FormattedMessage defaultMessage="Amount in sats" id="djLctd" /> />
</small> </p>
<input type="number" value={amount} onChange={e => setAmount(Number(e.target.value))} /> <input
</div> type="text"
<AsyncButton onClick={async () => { placeholder={formatMessage({ defaultMessage: "Comment", id: "LgbKvU" })}
try { value={comment}
if (wallets.wallet) { onChange={e => setComment(e.target.value)}
const inv = await wallets.wallet.createInvoice({ />
amount: amount, <div className="flex flex-col">
memo: comment, <small>
expiry: 600 <FormattedMessage defaultMessage="Amount in sats" id="djLctd" />
}); </small>
setInvoice(inv.pr); <input type="number" value={amount} onChange={e => setAmount(Number(e.target.value))} />
} </div>
} catch (e) { <AsyncButton
setError((e as Error).message); onClick={async () => {
try {
if (wallets.wallet) {
const inv = await wallets.wallet.createInvoice({
amount: amount,
memo: comment,
expiry: 600,
});
setInvoice(inv.pr);
} }
} catch (e) {
setError((e as Error).message);
}
}}> }}>
<FormattedMessage defaultMessage="Generate Invoice" id="ipHVx5" /> <FormattedMessage defaultMessage="Generate Invoice" id="ipHVx5" />
</AsyncButton> </AsyncButton>
{error && <b className="warning">{error}</b>} {error && <b className="warning">{error}</b>}
{invoice && <div className="flex flex-col gap-2 items-center"> {invoice && (
<QrCode data={invoice} link={`lightning:${invoice}`} /> <div className="flex flex-col gap-2 items-center">
<Copy text={invoice} /> <QrCode data={invoice} link={`lightning:${invoice}`} />
</div>} <Copy text={invoice} />
</div>
)}
</div> </div>
} );
}

View File

@ -1,75 +1,100 @@
import AsyncButton from "@/Components/Button/AsyncButton"; import AsyncButton from "@/Components/Button/AsyncButton";
import Icon from "@/Components/Icons/Icon"; import Icon from "@/Components/Icons/Icon";
import { formatShort } from "@/Utils/Number"; import { formatShort } from "@/Utils/Number";
import { WalletInvoice, useWallet } from "@/Wallet" import { WalletInvoice, useWallet } from "@/Wallet";
import { LNURL } from "@snort/shared"; import { LNURL } from "@snort/shared";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { FormattedMessage, FormattedNumber, useIntl } from "react-intl"; import { FormattedMessage, FormattedNumber, useIntl } from "react-intl";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
export function WalletSendPage() { export function WalletSendPage() {
const wallets = useWallet(); const wallets = useWallet();
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
const [invoice, setInvoice] = useState(""); const [invoice, setInvoice] = useState("");
const [error, setError] = useState(""); const [error, setError] = useState("");
const [lnurl, isLnurl] = useState(true); const [lnurl, isLnurl] = useState(true);
const [amount, setAmount] = useState(0); const [amount, setAmount] = useState(0);
const [comment, setComment] = useState(""); const [comment, setComment] = useState("");
const [result, setResult] = useState<WalletInvoice>(); const [result, setResult] = useState<WalletInvoice>();
useEffect(() => { useEffect(() => {
isLnurl(!invoice.startsWith("lnbc")) isLnurl(!invoice.startsWith("lnbc"));
}, [invoice]); }, [invoice]);
return <div className="p flex flex-col gap-4"> return (
<div className="text-2xl font-bold"> <div className="p flex flex-col gap-4">
<FormattedMessage defaultMessage="Send" id="9WRlF4" /> <div className="text-2xl font-bold">
</div> <FormattedMessage defaultMessage="Send" id="9WRlF4" />
<p> </div>
<FormattedMessage defaultMessage="Sending from <b>{wallet}</b>" id="Xnimz0" values={{ <p>
b: b => <b>&quot;{b}&quot;</b>, <FormattedMessage
wallet: wallets.config?.info.alias defaultMessage="Sending from <b>{wallet}</b>"
}} /> id="Xnimz0"
</p> values={{
<input type="text" placeholder={formatMessage({ defaultMessage: "Invoice / Lightning Address", id: 'EHqHsu' })} value={invoice} onChange={e => setInvoice(e.target.value)} /> b: b => <b>&quot;{b}&quot;</b>,
{lnurl && <> wallet: wallets.config?.info.alias,
<input type="text" placeholder={formatMessage({ defaultMessage: "Comment", id: 'LgbKvU' })} value={comment} onChange={e => setComment(e.target.value)} /> }}
<div className="flex flex-col"> />
<small> </p>
<FormattedMessage defaultMessage="Amount in sats" id="djLctd" /> <input
</small> type="text"
<input type="number" value={amount} onChange={e => setAmount(Number(e.target.value))} /> placeholder={formatMessage({ defaultMessage: "Invoice / Lightning Address", id: "EHqHsu" })}
</div> value={invoice}
</>} onChange={e => setInvoice(e.target.value)}
<AsyncButton onClick={async () => { />
try { {lnurl && (
if (wallets.wallet) { <>
if (!isLnurl) { <input
const res = await wallets.wallet.payInvoice(invoice); type="text"
setResult(res); placeholder={formatMessage({ defaultMessage: "Comment", id: "LgbKvU" })}
} else { value={comment}
const lnurl = new LNURL(invoice); onChange={e => setComment(e.target.value)}
await lnurl.load(); />
const pr = await lnurl.getInvoice(amount, comment); <div className="flex flex-col">
if (pr.pr) { <small>
const res = await wallets.wallet.payInvoice(pr.pr); <FormattedMessage defaultMessage="Amount in sats" id="djLctd" />
setResult(res); </small>
} <input type="number" value={amount} onChange={e => setAmount(Number(e.target.value))} />
} </div>
</>
)}
<AsyncButton
onClick={async () => {
try {
if (wallets.wallet) {
if (!isLnurl) {
const res = await wallets.wallet.payInvoice(invoice);
setResult(res);
} else {
const lnurl = new LNURL(invoice);
await lnurl.load();
const pr = await lnurl.getInvoice(amount, comment);
if (pr.pr) {
const res = await wallets.wallet.payInvoice(pr.pr);
setResult(res);
} }
} catch (e) { }
setError((e as Error).message);
} }
} catch (e) {
setError((e as Error).message);
}
}}> }}>
<FormattedMessage defaultMessage="Pay" id="lD3+8a" /> <FormattedMessage defaultMessage="Pay" id="lD3+8a" />
</AsyncButton> </AsyncButton>
{error && <b className="warning">{error}</b>} {error && <b className="warning">{error}</b>}
{result && <div className="flex gap-2"> {result && (
<Icon name="check" className="success" /> <div className="flex gap-2">
<FormattedMessage defaultMessage="Paid {amount} sats, fee {fee} sats" id="aRex7h" values={{ <Icon name="check" className="success" />
amount: <FormattedNumber value={result.amount / 1000} />, <FormattedMessage
fee: <FormattedNumber value={result.fees / 1000} /> defaultMessage="Paid {amount} sats, fee {fee} sats"
}} /> id="aRex7h"
</div>} values={{
amount: <FormattedNumber value={result.amount / 1000} />,
fee: <FormattedNumber value={result.fees / 1000} />,
}}
/>
</div>
)}
</div> </div>
} );
}

View File

@ -35,7 +35,7 @@ export default class AlbyWallet implements LNWallet {
canGetBalance() { canGetBalance() {
return this.#token.scope.includes("balance:read"); return this.#token.scope.includes("balance:read");
} }
canCreateInvoice() { canCreateInvoice() {
return true; return true;
} }

View File

@ -150,11 +150,11 @@ const mainRoutes = [
}, },
{ {
path: "/wallet/send", path: "/wallet/send",
element: <WalletSendPage /> element: <WalletSendPage />,
}, },
{ {
path: "/wallet/receive", path: "/wallet/receive",
element: <WalletReceivePage /> element: <WalletReceivePage />,
}, },
...OnboardingRoutes, ...OnboardingRoutes,
...SettingsRoutes, ...SettingsRoutes,

View File

@ -467,6 +467,9 @@
"E5ZIPD": { "E5ZIPD": {
"defaultMessage": "<big>{amount}</big> <small>sats</small>" "defaultMessage": "<big>{amount}</big> <small>sats</small>"
}, },
"EHqHsu": {
"defaultMessage": "Invoice / Lightning Address"
},
"EJbFi7": { "EJbFi7": {
"defaultMessage": "Search notes" "defaultMessage": "Search notes"
}, },
@ -810,6 +813,9 @@
"defaultMessage": "Summary", "defaultMessage": "Summary",
"description": "Notifications summary" "description": "Notifications summary"
}, },
"PXQ0z0": {
"defaultMessage": "Receiving to <b>{wallet}</b>"
},
"PamNxw": { "PamNxw": {
"defaultMessage": "Unknown file header: {name}" "defaultMessage": "Unknown file header: {name}"
}, },
@ -930,6 +936,9 @@
"UJTWqI": { "UJTWqI": {
"defaultMessage": "Remove from my relays" "defaultMessage": "Remove from my relays"
}, },
"ULXFfP": {
"defaultMessage": "Receive"
},
"UNjfWJ": { "UNjfWJ": {
"defaultMessage": "Check all event signatures received from relays" "defaultMessage": "Check all event signatures received from relays"
}, },
@ -1017,6 +1026,9 @@
"XhpBfA": { "XhpBfA": {
"defaultMessage": "{site} is an open source project built by passionate people in their free time, your donations are greatly appreciated" "defaultMessage": "{site} is an open source project built by passionate people in their free time, your donations are greatly appreciated"
}, },
"Xnimz0": {
"defaultMessage": "Sending from <b>{wallet}</b>"
},
"Xopqkl": { "Xopqkl": {
"defaultMessage": "Your default zap amount is {number} sats, example values are calculated from this." "defaultMessage": "Your default zap amount is {number} sats, example values are calculated from this."
}, },
@ -1033,6 +1045,9 @@
"YXA3AH": { "YXA3AH": {
"defaultMessage": "Enable reactions" "defaultMessage": "Enable reactions"
}, },
"Yf3DwC": {
"defaultMessage": "Connect a wallet to send instant payments"
},
"Z4BMCZ": { "Z4BMCZ": {
"defaultMessage": "Enter pairing phrase" "defaultMessage": "Enter pairing phrase"
}, },
@ -1063,6 +1078,9 @@
"aMaLBK": { "aMaLBK": {
"defaultMessage": "Supported Extensions" "defaultMessage": "Supported Extensions"
}, },
"aRex7h": {
"defaultMessage": "Paid {amount} sats, fee {fee} sats"
},
"aSGz4J": { "aSGz4J": {
"defaultMessage": "Connect to your own LND node with Lightning Node Connect" "defaultMessage": "Connect to your own LND node with Lightning Node Connect"
}, },
@ -1163,6 +1181,9 @@
"deEeEI": { "deEeEI": {
"defaultMessage": "Register" "defaultMessage": "Register"
}, },
"djLctd": {
"defaultMessage": "Amount in sats"
},
"djNL6D": { "djNL6D": {
"defaultMessage": "Read-only" "defaultMessage": "Read-only"
}, },
@ -1295,6 +1316,9 @@
"i/dBAR": { "i/dBAR": {
"defaultMessage": "Zap Pool" "defaultMessage": "Zap Pool"
}, },
"i5gBFz": {
"defaultMessage": "Your sent and received payments will show up here."
},
"iCqGww": { "iCqGww": {
"defaultMessage": "Reactions ({n})" "defaultMessage": "Reactions ({n})"
}, },
@ -1319,6 +1343,9 @@
"ieGrWo": { "ieGrWo": {
"defaultMessage": "Follow" "defaultMessage": "Follow"
}, },
"ipHVx5": {
"defaultMessage": "Generate Invoice"
},
"itPgxd": { "itPgxd": {
"defaultMessage": "Profile" "defaultMessage": "Profile"
}, },

View File

@ -154,6 +154,7 @@
"DtYelJ": "Transfer", "DtYelJ": "Transfer",
"Dx4ey3": "Toggle all", "Dx4ey3": "Toggle all",
"E5ZIPD": "<big>{amount}</big> <small>sats</small>", "E5ZIPD": "<big>{amount}</big> <small>sats</small>",
"EHqHsu": "Invoice / Lightning Address",
"EJbFi7": "Search notes", "EJbFi7": "Search notes",
"ELbg9p": "Data Providers", "ELbg9p": "Data Providers",
"EQKRE4": "Show badges on profile pages", "EQKRE4": "Show badges on profile pages",
@ -267,6 +268,7 @@
"P7nJT9": "Total today (UTC): {amount} sats", "P7nJT9": "Total today (UTC): {amount} sats",
"PCSt5T": "Preferences", "PCSt5T": "Preferences",
"PJeJFc": "Summary", "PJeJFc": "Summary",
"PXQ0z0": "Receiving to <b>{wallet}</b>",
"PamNxw": "Unknown file header: {name}", "PamNxw": "Unknown file header: {name}",
"Pe0ogR": "Theme", "Pe0ogR": "Theme",
"PrsIg7": "Reactions will be shown on every page, if disabled no reactions will be shown", "PrsIg7": "Reactions will be shown on every page, if disabled no reactions will be shown",
@ -306,6 +308,7 @@
"U1aPPi": "Stop listening", "U1aPPi": "Stop listening",
"UDYlxu": "Pending Subscriptions", "UDYlxu": "Pending Subscriptions",
"UJTWqI": "Remove from my relays", "UJTWqI": "Remove from my relays",
"ULXFfP": "Receive",
"UNjfWJ": "Check all event signatures received from relays", "UNjfWJ": "Check all event signatures received from relays",
"UT7Nkj": "New Chat", "UT7Nkj": "New Chat",
"UUPFlt": "Users must accept the content warning to show the content of your note.", "UUPFlt": "Users must accept the content warning to show the content of your note.",
@ -335,11 +338,13 @@
"XXm7jJ": "Trending Hashtags", "XXm7jJ": "Trending Hashtags",
"XgWvGA": "Reactions", "XgWvGA": "Reactions",
"XhpBfA": "{site} is an open source project built by passionate people in their free time, your donations are greatly appreciated", "XhpBfA": "{site} is an open source project built by passionate people in their free time, your donations are greatly appreciated",
"Xnimz0": "Sending from <b>{wallet}</b>",
"Xopqkl": "Your default zap amount is {number} sats, example values are calculated from this.", "Xopqkl": "Your default zap amount is {number} sats, example values are calculated from this.",
"XrSk2j": "Redeem", "XrSk2j": "Redeem",
"YDURw6": "Service URL", "YDURw6": "Service URL",
"YR2I9M": "No keys, no {app}, There is no way to reset it if you don't back up. It only takes a minute.", "YR2I9M": "No keys, no {app}, There is no way to reset it if you don't back up. It only takes a minute.",
"YXA3AH": "Enable reactions", "YXA3AH": "Enable reactions",
"Yf3DwC": "Connect a wallet to send instant payments",
"Z4BMCZ": "Enter pairing phrase", "Z4BMCZ": "Enter pairing phrase",
"ZKORll": "Activate Now", "ZKORll": "Activate Now",
"ZLmyG9": "Contributors", "ZLmyG9": "Contributors",
@ -350,6 +355,7 @@
"a7TDNm": "Notes will stream in real time into global and notes tab", "a7TDNm": "Notes will stream in real time into global and notes tab",
"aHje0o": "Name or nym", "aHje0o": "Name or nym",
"aMaLBK": "Supported Extensions", "aMaLBK": "Supported Extensions",
"aRex7h": "Paid {amount} sats, fee {fee} sats",
"aSGz4J": "Connect to your own LND node with Lightning Node Connect", "aSGz4J": "Connect to your own LND node with Lightning Node Connect",
"aWpBzj": "Show more", "aWpBzj": "Show more",
"b12Goz": "Mnemonic", "b12Goz": "Mnemonic",
@ -383,6 +389,7 @@
"dOQCL8": "Display name", "dOQCL8": "Display name",
"ddd3JX": "Popular Hashtags", "ddd3JX": "Popular Hashtags",
"deEeEI": "Register", "deEeEI": "Register",
"djLctd": "Amount in sats",
"djNL6D": "Read-only", "djNL6D": "Read-only",
"dmsiLv": "A default Zap Pool split of {n} has been configured for {site} developers, you can disable it at any time in {link}", "dmsiLv": "A default Zap Pool split of {n} has been configured for {site} developers, you can disable it at any time in {link}",
"e61Jf3": "Coming soon", "e61Jf3": "Coming soon",
@ -427,6 +434,7 @@
"hniz8Z": "here", "hniz8Z": "here",
"hvFRBo": "Interaction", "hvFRBo": "Interaction",
"i/dBAR": "Zap Pool", "i/dBAR": "Zap Pool",
"i5gBFz": "Your sent and received payments will show up here.",
"iCqGww": "Reactions ({n})", "iCqGww": "Reactions ({n})",
"iEoXYx": "DeepL translations", "iEoXYx": "DeepL translations",
"iGT1eE": "Prevent fake accounts from imitating you", "iGT1eE": "Prevent fake accounts from imitating you",
@ -435,6 +443,7 @@
"iXPL0Z": "Can't login with private key on an insecure connection, please use a Nostr key manager extension instead", "iXPL0Z": "Can't login with private key on an insecure connection, please use a Nostr key manager extension instead",
"iYc3Ld": "Payments", "iYc3Ld": "Payments",
"ieGrWo": "Follow", "ieGrWo": "Follow",
"ipHVx5": "Generate Invoice",
"itPgxd": "Profile", "itPgxd": "Profile",
"izWS4J": "Unfollow", "izWS4J": "Unfollow",
"j9xbzF": "Already backed up", "j9xbzF": "Already backed up",