-
+
:
{daysToExpire >= 1 && (
-
+
:
)}
{daysToExpire >= 0 && daysToExpire < 1 && (
-
+
:
)}
{isExpired && (
-
+
)}
{isNew && (
-
+
)}
diff --git a/packages/app/src/Wallet/LNDHub.ts b/packages/app/src/Wallet/LNDHub.ts
index 79a3f23d..40d53b27 100644
--- a/packages/app/src/Wallet/LNDHub.ts
+++ b/packages/app/src/Wallet/LNDHub.ts
@@ -23,7 +23,10 @@ export default class LNDHubWallet implements LNWallet {
password: string;
auth?: AuthResponse;
- constructor(url: string) {
+ constructor(
+ url: string,
+ readonly changed: () => void,
+ ) {
if (url.startsWith("lndhub://")) {
const regex = /^lndhub:\/\/([\S-]+):([\S-]+)@(.*)$/i;
const parsedUrl = url.match(regex);
@@ -60,25 +63,31 @@ export default class LNDHubWallet implements LNWallet {
}
async getInfo() {
+ await this.login();
return await this.getJson
("GET", "/getinfo");
}
async login() {
+ if (this.auth) return true;
+
const rsp = await this.getJson("POST", "/auth?type=auth", {
login: this.user,
password: this.password,
});
this.auth = rsp as AuthResponse;
+ this.changed();
return true;
}
async getBalance(): Promise {
+ await this.login();
const rsp = await this.getJson("GET", "/balance");
const bal = Math.floor((rsp as GetBalanceResponse).BTC.AvailableBalance);
return bal as Sats;
}
async createInvoice(req: InvoiceRequest) {
+ await this.login();
const rsp = await this.getJson("POST", "/addinvoice", {
amt: req.amount,
memo: req.memo,
@@ -95,6 +104,7 @@ export default class LNDHubWallet implements LNWallet {
}
async payInvoice(pr: string) {
+ await this.login();
const rsp = await this.getJson("POST", "/payinvoice", {
invoice: pr,
});
@@ -113,6 +123,7 @@ export default class LNDHubWallet implements LNWallet {
}
async getInvoices(): Promise {
+ await this.login();
const rsp = await this.getJson("GET", "/getuserinvoices");
return (rsp as UserInvoicesResponse[])
.sort((a, b) => (a.timestamp > b.timestamp ? -1 : 1))
diff --git a/packages/app/src/Wallet/NostrWalletConnect.ts b/packages/app/src/Wallet/NostrWalletConnect.ts
index 91f56741..c592a556 100644
--- a/packages/app/src/Wallet/NostrWalletConnect.ts
+++ b/packages/app/src/Wallet/NostrWalletConnect.ts
@@ -81,7 +81,10 @@ export class NostrConnectWallet implements LNWallet {
#info?: WalletInfo;
#supported_methods: Array = DefaultSupported;
- constructor(cfg: string) {
+ constructor(
+ cfg: string,
+ readonly changed: () => void,
+ ) {
this.#config = NostrConnectWallet.parseConfigUrl(cfg);
this.#commandQueue = new Map();
}
@@ -147,9 +150,9 @@ export class NostrConnectWallet implements LNWallet {
async login() {
if (this.#conn) return true;
- return await new Promise(resolve => {
+ await new Promise(resolve => {
this.#conn = new Connection(this.#config.relayUrl, { read: true, write: true });
- this.#conn.on("connected", () => resolve(true));
+ this.#conn.on("connected", () => resolve());
this.#conn.on("auth", async (c, r, cb) => {
const eb = new EventBuilder();
eb.kind(EventKind.Auth).tag(["relay", r]).tag(["challenge", c]);
@@ -161,6 +164,9 @@ export class NostrConnectWallet implements LNWallet {
});
this.#conn.Connect();
});
+ await this.getInfo();
+ this.changed();
+ return true;
}
async close() {
@@ -232,6 +238,7 @@ export class NostrConnectWallet implements LNWallet {
timestamp: typeof a.created_at === "string" ? new Date(a.created_at).getTime() / 1000 : a.created_at,
preimage: a.preimage,
state: WalletInvoiceState.Paid,
+ direction: a.type === "incoming" ? "in" : "out",
}) as WalletInvoice,
) ?? []
);
diff --git a/packages/app/src/Wallet/index.ts b/packages/app/src/Wallet/index.ts
index a52fdf7d..88fed313 100644
--- a/packages/app/src/Wallet/index.ts
+++ b/packages/app/src/Wallet/index.ts
@@ -80,6 +80,7 @@ export interface WalletInvoice {
timestamp: number;
preimage?: string;
state: WalletInvoiceState;
+ direction: "in" | "out";
}
export function prToWalletInvoice(pr: string) {
@@ -92,6 +93,7 @@ export function prToWalletInvoice(pr: string) {
timestamp: parsedInvoice.timestamp ?? 0,
state: parsedInvoice.expired ? WalletInvoiceState.Expired : WalletInvoiceState.Pending,
pr,
+ direction: "in",
} as WalletInvoice;
}
}
@@ -163,6 +165,9 @@ export class WalletStore extends ExternalStore {
this.notifyChange();
});
return undefined;
+ } else {
+ this.#instance.set(activeConfig.id, w);
+ this.notifyChange();
}
return w;
} else {
@@ -230,10 +235,10 @@ export class WalletStore extends ExternalStore {
return new WebLNWallet();
}
case WalletKind.LNDHub: {
- return new LNDHubWallet(unwrap(cfg.data));
+ return new LNDHubWallet(unwrap(cfg.data), () => this.notifyChange());
}
case WalletKind.NWC: {
- return new NostrConnectWallet(unwrap(cfg.data));
+ return new NostrConnectWallet(unwrap(cfg.data), () => this.notifyChange());
}
}
}
diff --git a/packages/app/src/icons.svg b/packages/app/src/icons.svg
index fce18f1e..bdf5fb6e 100644
--- a/packages/app/src/icons.svg
+++ b/packages/app/src/icons.svg
@@ -454,5 +454,12 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/app/src/index.css b/packages/app/src/index.css
index afe0cd46..6e1c6748 100644
--- a/packages/app/src/index.css
+++ b/packages/app/src/index.css
@@ -480,22 +480,6 @@ input:disabled {
cursor: not-allowed;
}
-.f-1 {
- flex: 1;
-}
-
-.f-2 {
- flex: 2;
-}
-
-.f-3 {
- flex: 3;
-}
-
-.f-4 {
- flex: 4;
-}
-
.f-ellipsis {
min-width: 0;
white-space: nowrap;
diff --git a/packages/app/src/index.tsx b/packages/app/src/index.tsx
index e1650340..54b6ee4e 100644
--- a/packages/app/src/index.tsx
+++ b/packages/app/src/index.tsx
@@ -64,6 +64,7 @@ import { setupWebLNWalletConfig } from "@/Wallet/WebLN";
import { Wallets } from "@/Wallet";
import Fuse from "fuse.js";
import NetworkGraph from "@/Pages/NetworkGraph";
+import WalletPage from "./Pages/WalletPage";
declare global {
interface Window {
@@ -279,6 +280,14 @@ const mainRoutes = [
path: "/graph",
element: ,
},
+ {
+ path: "/wallet",
+ element: (
+
+
+
+ ),
+ },
...OnboardingRoutes,
...SettingsRoutes,
] as Array;
diff --git a/packages/app/src/lang.json b/packages/app/src/lang.json
index ccd15f99..ef118706 100644
--- a/packages/app/src/lang.json
+++ b/packages/app/src/lang.json
@@ -156,6 +156,9 @@
"3KNMbJ": {
"defaultMessage": "Articles"
},
+ "3QwfJR": {
+ "defaultMessage": "~{amount}"
+ },
"3cc4Ct": {
"defaultMessage": "Light"
},
@@ -455,6 +458,9 @@
"Dx4ey3": {
"defaultMessage": "Toggle all"
},
+ "E5ZIPD": {
+ "defaultMessage": "{amount} sats"
+ },
"EJbFi7": {
"defaultMessage": "Search notes"
},
@@ -945,9 +951,6 @@
"VL900k": {
"defaultMessage": "Recommended Relays"
},
- "VN0+Fz": {
- "defaultMessage": "Balance: {amount} sats"
- },
"VOjC1i": {
"defaultMessage": "Pick which upload service you want to upload attachments to"
},
@@ -1130,10 +1133,6 @@
"d2ebEu": {
"defaultMessage": "Not Subscribed to Push"
},
- "d6CyG5": {
- "defaultMessage": "History",
- "description": "Wallet transation history"
- },
"d7d0/x": {
"defaultMessage": "LN Address"
},
@@ -1468,6 +1467,10 @@
"puLNUJ": {
"defaultMessage": "Pin"
},
+ "pukxg/": {
+ "defaultMessage": "Payments",
+ "description": "Wallet transation history"
+ },
"pzTOmv": {
"defaultMessage": "Followers"
},
@@ -1558,6 +1561,9 @@
"thnRpU": {
"defaultMessage": "Getting NIP-05 verified can help:"
},
+ "tj6kdX": {
+ "defaultMessage": "{sign} {amount} sats"
+ },
"tjpYlr": {
"defaultMessage": "Relay Metrics"
},
@@ -1618,9 +1624,6 @@
"voxBKC": {
"defaultMessage": "Followed by friends"
},
- "vrTOHJ": {
- "defaultMessage": "{amount} sats"
- },
"vxwnbh": {
"defaultMessage": "Amount of work to apply to all published events"
},
diff --git a/packages/app/src/translations/en.json b/packages/app/src/translations/en.json
index 1ee603a9..950232c6 100644
--- a/packages/app/src/translations/en.json
+++ b/packages/app/src/translations/en.json
@@ -51,6 +51,7 @@
"2zJXeA": "Profiles",
"39AHJm": "Sign Up",
"3KNMbJ": "Articles",
+ "3QwfJR": "~{amount}",
"3cc4Ct": "Light",
"3gOsZq": "Translators",
"3qnJlS": "You are voting with {amount} sats",
@@ -150,6 +151,7 @@
"DrZqav": "About must be less than {limit} characters",
"DtYelJ": "Transfer",
"Dx4ey3": "Toggle all",
+ "E5ZIPD": "{amount} sats",
"EJbFi7": "Search notes",
"ELbg9p": "Data Providers",
"EQKRE4": "Show badges on profile pages",
@@ -311,7 +313,6 @@
"UrKTqQ": "You have an active iris.to account",
"UxgyeY": "Your referral code is {code}",
"VL900k": "Recommended Relays",
- "VN0+Fz": "Balance: {amount} sats",
"VOjC1i": "Pick which upload service you want to upload attachments to",
"VR5eHw": "Public key (npub/nprofile)",
"VcwrfF": "Yes please",
@@ -372,7 +373,6 @@
"cyR7Kh": "Back",
"d+6YsV": "Lists to mute:",
"d2ebEu": "Not Subscribed to Push",
- "d6CyG5": "History",
"d7d0/x": "LN Address",
"d8gpCh": "Try to use less than 5 hashtags to stay on topic 🙏",
"dOQCL8": "Display name",
@@ -484,6 +484,7 @@
"pI+77w": "Downloadable backups from Snort relay",
"pRess9": "ZapPool",
"puLNUJ": "Pin",
+ "pukxg/": "Payments",
"pzTOmv": "Followers",
"qD9EUF": "Email <> DM bridge for your Snort nostr address",
"qDwvZ4": "Unknown error",
@@ -514,6 +515,7 @@
"tOdNiY": "Dark",
"th5lxp": "Send note to a subset of your write relays",
"thnRpU": "Getting NIP-05 verified can help:",
+ "tj6kdX": "{sign} {amount} sats",
"tjpYlr": "Relay Metrics",
"ttxS0b": "Supporter Badge",
"u+LyXc": "Interactions",
@@ -534,7 +536,6 @@
"vhlWFg": "Poll Options",
"vlbWtt": "Get a free one",
"voxBKC": "Followed by friends",
- "vrTOHJ": "{amount} sats",
"vxwnbh": "Amount of work to apply to all published events",
"w1Fanr": "Business",
"w6qrwX": "NSFW",