aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2024-11-26 13:08:08 -0800
committerAdam Soltys <[email protected]>2024-11-26 13:20:53 -0800
commit9b3e117eafbba224b86dd7f8b3c56a0370f72d5b (patch)
treea670c3ae954d5075c851126c2aca7a1a45d1b41d /src/lib
parent2761363d694d3f24600abbe656769f64d7a67605 (diff)
downloadcoinos-ui-9b3e117eafbba224b86dd7f8b3c56a0370f72d5b.tar.gz
coinos-ui-9b3e117eafbba224b86dd7f8b3c56a0370f72d5b.zip
bip21 and socket fixes
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/bip21.ts48
-rw-r--r--src/lib/invoice.ts1
-rw-r--r--src/lib/parse.ts32
-rw-r--r--src/lib/socket.ts24
-rw-r--r--src/lib/utils.ts4
5 files changed, 88 insertions, 21 deletions
diff --git a/src/lib/bip21.ts b/src/lib/bip21.ts
new file mode 100644
index 00000000..2642afab
--- /dev/null
+++ b/src/lib/bip21.ts
@@ -0,0 +1,48 @@
+export function decode(uri, allowedSchemes = ["bitcoin", "liquidnetwork"]) {
+ // Determine the scheme from the URI
+ const split = uri.indexOf(":");
+ if (split === -1) {
+ throw new Error("Invalid URI: Missing scheme");
+ }
+
+ const urnScheme = uri.slice(0, split).toLowerCase();
+ if (!allowedSchemes.includes(urnScheme)) {
+ throw new Error(`Invalid scheme: ${urnScheme}`);
+ }
+
+ // Extract address and query string
+ const queryStart = uri.indexOf("?");
+ const address = uri.slice(
+ split + 1,
+ queryStart === -1 ? undefined : queryStart,
+ );
+ const query = queryStart === -1 ? "" : uri.slice(queryStart + 1);
+ const options = Object.fromEntries(new URLSearchParams(query));
+
+ const n = Number(options?.amount);
+ if (!Number.isFinite(n)) throw new Error("Invalid amount");
+ if (n < 0) throw new Error("Invalid amount");
+
+ return { scheme: urnScheme, address, options };
+}
+
+export function encode(
+ address,
+ options = { amount: "" },
+ urnScheme = "bitcoin",
+) {
+ if (!address || typeof address !== "string") {
+ throw new TypeError("Invalid address");
+ }
+
+ if (!["bitcoin", "liquidnetwork"].includes(urnScheme)) {
+ throw new Error(`Unsupported scheme: ${urnScheme}`);
+ }
+
+ const n = Number(options?.amount);
+ if (!Number.isFinite(n)) throw new Error("Invalid amount");
+ if (n < 0) throw new Error("Invalid amount");
+
+ const query = new URLSearchParams(options).toString();
+ return `${urnScheme}:${address}${query ? `?${query}` : ""}`;
+}
diff --git a/src/lib/invoice.ts b/src/lib/invoice.ts
index 9563d924..a48e02a4 100644
--- a/src/lib/invoice.ts
+++ b/src/lib/invoice.ts
@@ -2,7 +2,6 @@ import { auth, get, post } from "$lib/utils";
import { redirect } from "@sveltejs/kit";
export default async ({ cookies, request }) => {
- console.log("LOADING");
const form = await request.formData();
const aid = form.get("aid") || cookies.get("aid");
diff --git a/src/lib/parse.ts b/src/lib/parse.ts
index 6483aaa0..7ddb2104 100644
--- a/src/lib/parse.ts
+++ b/src/lib/parse.ts
@@ -1,7 +1,7 @@
import { PUBLIC_DOMAIN } from "$env/static/public";
+import { decode } from "$lib/bip21";
import { get, isLiquid, post, sats } from "$lib/utils";
import { redirect } from "@sveltejs/kit";
-import bip21 from "bip21";
import { validate } from "bitcoin-address-validation";
export default async (s, host) => {
@@ -21,6 +21,23 @@ export default async (s, host) => {
} catch (e) {}
}
+ // bitcoin
+ if (
+ t.toLowerCase().startsWith("bitcoin:") ||
+ t.toLowerCase().startsWith("liquidnetwork:")
+ ) {
+ ({
+ address: t,
+ options: { amount },
+ } = decode(t));
+ }
+
+ if (validate(t) || isLiquid(t)) {
+ let r = `/send/bitcoin/${t}`;
+ if (amount) r += `/${Math.round(amount * sats)}`;
+ redirect(307, r);
+ }
+
// lightning
if (t.toLowerCase().startsWith("lightning:"))
t = t.toLowerCase().replace("lightning:", "");
@@ -47,19 +64,6 @@ export default async (s, host) => {
}
}
- // bitcoin
- if (t.toLowerCase().startsWith("bitcoin:"))
- ({
- address: t,
- options: { amount },
- } = bip21.decode(t));
-
- if (validate(t) || isLiquid(t)) {
- let r = `/send/bitcoin/${t}`;
- if (amount) r += `/${Math.round(amount * sats)}`;
- redirect(307, r);
- }
-
if (t.startsWith("cashu")) {
const { id } = await post("/cash", { token: t });
redirect(307, `/ecash/${id}`);
diff --git a/src/lib/socket.ts b/src/lib/socket.ts
index 566e989d..bd8494fa 100644
--- a/src/lib/socket.ts
+++ b/src/lib/socket.ts
@@ -3,9 +3,10 @@ import { navigating, page } from "$app/stores";
import { PUBLIC_SOCKET } from "$env/static/public";
import { event, invoice, last, request } from "$lib/store";
import { s, sleep, success, wait } from "$lib/utils";
+import cookies from "js-cookie";
import { get } from "svelte/store";
-let socket;
+export let socket;
let token;
export const auth = () => token && send("login", token);
@@ -13,8 +14,9 @@ export const auth = () => token && send("login", token);
export const send = async (type, data) => {
try {
await wait(() => socket && socket.readyState === 1, 1000, 10);
- } catch (e: any) {
- if (e.message === "timeout") reconnectToWebsocket();
+ } catch (e) {
+ const { message } = e as Error;
+ if (message === "timeout") reconnectToWebsocket();
}
await wait(() => socket.readyState === 1, 1000, 10);
@@ -47,8 +49,14 @@ export const messages = (data) => ({
url: { pathname },
} = get(page);
+ const username = cookies.get("username");
+
if (amount > 0) {
- if (pathname.includes("receive")) {
+ if (
+ pathname.includes(`/${username}`) ||
+ pathname.includes("/receive") ||
+ pathname.includes("/invoice")
+ ) {
await wait(() => !get(navigating));
await goto(`/invoice/${iid}`);
} else success(`${confirmed ? "Received" : "Detected"} ⚡️${s(amount)}!`);
@@ -63,7 +71,14 @@ const maxReconnectDelay = 16000;
let currentReconnectDelay = initialReconnectDelay;
+let connecting;
export function connect(t) {
+ if (connecting) return;
+ connecting = true;
+ setTimeout(() => {
+ connecting = false;
+ }, 5000);
+
token = t;
if (socket) return auth();
@@ -87,6 +102,7 @@ async function onWebsocketMessage(msg) {
function onWebsocketOpen() {
currentReconnectDelay = initialReconnectDelay;
+ send("heartbeat", token);
}
function onWebsocketClose() {
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index a15bb8e7..dc7182e3 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -151,7 +151,7 @@ export const info = (m: string) => {
export const login = async (
user: { username: string; password: string },
- cookies: any,
+ cookies,
ip: string,
) => {
const maxAge = 380 * 24 * 60 * 60;
@@ -182,7 +182,7 @@ export const login = async (
cookies.set("token", token, opts);
};
-export const auth = (cookies: any) => ({
+export const auth = (cookies) => ({
authorization: `Bearer ${cookies.get("token")}`,
});