aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/utils.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/utils.ts')
-rw-r--r--src/lib/utils.ts480
1 files changed, 242 insertions, 238 deletions
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index 2ecd332b..96d07703 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -6,355 +6,359 @@ import { page } from "$app/stores";
import { get as getStore } from "svelte/store";
export function scroll(section: any) {
- if (getStore(page).url.pathname !== "/") goto("/");
- setTimeout(() => section.scrollIntoView({ behavior: "smooth" }), 500);
+ if (getStore(page).url.pathname !== "/") goto("/");
+ setTimeout(() => section.scrollIntoView({ behavior: "smooth" }), 500);
}
let base = browser ? "" : PUBLIC_COINOS_URL;
export let punk = (k: string) =>
- Math.floor((parseInt(k.slice(-2), 16) / 256) * 64) + 1 + ".webp";
+ Math.floor((parseInt(k.slice(-2), 16) / 256) * 64) + 1 + ".webp";
export let g = (url: string, fetch: any, headers: object) =>
- fetch(base + url, { headers })
- .then((r: Response) => r.text())
- .then((body: string) => {
- try {
- return JSON.parse(body);
- } catch (e) {
- throw new Error(body);
- }
- });
+ fetch(base + url, { headers })
+ .then((r: Response) => r.text())
+ .then((body: string) => {
+ try {
+ return JSON.parse(body);
+ } catch (e) {
+ throw new Error(body);
+ }
+ });
export let get = (url: string, headers = {}) => {
- return fetch(base + url, { headers })
- .then(async (r) => {
- if (r.ok) return r.text();
- throw new Error(await r.text());
- })
- .then((body) => {
- try {
- return JSON.parse(body);
- } catch (e) {
- return body;
- }
- });
+ return fetch(base + url, { headers })
+ .then(async (r) => {
+ if (r.ok) return r.text();
+ throw new Error(await r.text());
+ })
+ .then((body) => {
+ try {
+ return JSON.parse(body);
+ } catch (e) {
+ return body;
+ }
+ });
};
export let post = async (
- url: string,
- body: object,
- headers: HeadersInit | undefined = undefined
+ url: string,
+ body: object,
+ headers: HeadersInit | undefined = undefined,
) => {
- headers = {
- "content-type": "application/json",
- accept: "application/json",
- ...headers,
- };
+ headers = {
+ "content-type": "application/json",
+ accept: "application/json",
+ ...headers,
+ };
- let response = await fetch(base + url, {
- method: "POST",
- body: JSON.stringify(body),
- headers,
- })
- .then(async (r) => {
- if (r.ok) return r.text();
- let text = await r.text();
+ let response = await fetch(base + url, {
+ method: "POST",
+ body: JSON.stringify(body),
+ headers,
+ })
+ .then(async (r) => {
+ if (r.ok) return r.text();
+ let text = await r.text();
- let message;
- try {
- ({ message } = JSON.parse(text));
- } catch (e) {}
+ let message;
+ try {
+ ({ message } = JSON.parse(text));
+ } catch (e) {}
- if (message) throw new Error(message);
- throw new Error(text);
- })
- .then((body) => {
- let json;
- try {
- json = JSON.parse(body);
- } catch (e) {
- throw new Error(body);
- }
+ if (message) throw new Error(message);
+ throw new Error(text);
+ })
+ .then((body) => {
+ let json;
+ try {
+ json = JSON.parse(body);
+ } catch (e) {
+ throw new Error(body);
+ }
- if (json.error instanceof Error) throw json.error;
- if (json instanceof Error) throw body;
- if (json.name === "Error") throw new Error(json.message);
+ if (json.error instanceof Error) throw json.error;
+ if (json instanceof Error) throw body;
+ if (json.name === "Error") throw new Error(json.message);
- return json;
- });
+ return json;
+ });
- return response;
+ return response;
};
export let copy = (text: string) => {
- navigator.clipboard.writeText(text);
- success("Copied!");
+ navigator.clipboard.writeText(text);
+ success("Copied!");
};
export let copyNoNewlines = (text: string) => {
- let stripped = text.replace(/\n/g, " ").replace(/\s+/g, " ");
- navigator.clipboard.writeText(stripped);
- success("Copied!");
+ let stripped = text.replace(/\n/g, " ").replace(/\s+/g, " ");
+ navigator.clipboard.writeText(stripped);
+ success("Copied!");
};
export function reverseFormat(val: string, locale: string): number {
- let parts = new Intl.NumberFormat(locale).formatToParts(1111.1);
- let group = parts.find((part) => part.type === "group")!.value;
- let decimal = parts.find((part) => part.type === "decimal")!.value;
- let reversedVal = val.replace(new RegExp("\\" + group, "g"), "");
- reversedVal = reversedVal.replace(new RegExp("\\" + decimal, "g"), ".");
- return Number.isNaN(reversedVal) ? 0 : +reversedVal;
+ let parts = new Intl.NumberFormat(locale).formatToParts(1111.1);
+ let group = parts.find((part) => part.type === "group")!.value;
+ let decimal = parts.find((part) => part.type === "decimal")!.value;
+ let reversedVal = val.replace(new RegExp("\\" + group, "g"), "");
+ reversedVal = reversedVal.replace(new RegExp("\\" + decimal, "g"), ".");
+ return Number.isNaN(reversedVal) ? 0 : +reversedVal;
}
export let protectedRoutes: RegExp[] = [/customers/, /settings/, /payments/];
let recent: string[] = [];
export let success = (m: string, clear: boolean = true) => {
- if (recent.includes(m)) return;
- recent.push(m);
- setTimeout(() => (recent = []), 5000);
- if (clear) toast.pop();
- toast.push(m, {
- theme: {
- "--toastBarBackground": "#F5F7FA",
- },
- });
+ if (recent.includes(m)) return;
+ recent.push(m);
+ setTimeout(() => (recent = []), 5000);
+ if (clear) toast.pop();
+ toast.push(m, {
+ theme: {
+ "--toastBarBackground": "#F5F7FA",
+ },
+ });
};
export let warning = (m: string, clear: boolean = true) => {
- if (clear) toast.pop();
- toast.push(m, {
- theme: {
- "--toastBarBackground": "#FFCE22",
- },
- });
+ if (clear) toast.pop();
+ toast.push(m, {
+ theme: {
+ "--toastBarBackground": "#FFCE22",
+ },
+ });
};
export let fail = (m: string, clear: boolean = true) => {
- if (clear) toast.pop();
- toast.push(m, {
- theme: {
- "--toastBarBackground": "#E93535",
- },
- });
+ if (clear) toast.pop();
+ toast.push(m, {
+ theme: {
+ "--toastBarBackground": "#E93535",
+ },
+ });
};
export let info = (m: string) => {
- toast.pop();
- toast.push(m, {
- theme: {
- "--toastBarBackground": "white",
- },
- });
+ toast.pop();
+ toast.push(m, {
+ theme: {
+ "--toastBarBackground": "white",
+ },
+ });
};
export let login = async (
- user: { username: string; password: string },
- cookies: any,
- ip: string
+ user: { username: string; password: string },
+ cookies: any,
+ ip: string,
) => {
- let maxAge = 380 * 24 * 60 * 60;
+ let maxAge = 380 * 24 * 60 * 60;
- let res = await fetch(base + "/login", {
- method: "POST",
- body: JSON.stringify(user),
- headers: {
- "content-type": "application/json",
- accept: "application/json",
- "cf-connecting-ip": ip,
- },
- });
- if (res.status === 401) {
- let text = await res.text();
- if (text.startsWith("2fa")) throw new Error("2fa");
- }
+ let res = await fetch(base + "/login", {
+ method: "POST",
+ body: JSON.stringify(user),
+ headers: {
+ "content-type": "application/json",
+ accept: "application/json",
+ "cf-connecting-ip": ip,
+ },
+ });
+ if (res.status === 401) {
+ let text = await res.text();
+ if (text.startsWith("2fa")) throw new Error("2fa");
+ }
- let { user: u, token } = await res.json();
- if (!token) throw new Error("Login failed");
+ let { user: u, token } = await res.json();
+ if (!token) throw new Error("Login failed");
- let expires = new Date();
- expires.setSeconds(expires.getSeconds() + maxAge);
+ let expires = new Date();
+ expires.setSeconds(expires.getSeconds() + maxAge);
- let opts = { path: "/", expires };
- if (u.language) cookies.set("lang", u.language, opts);
- cookies.set("username", user.username, opts);
- cookies.set("token", token, opts);
+ let opts = { path: "/", expires };
+ if (u.language) cookies.set("lang", u.language, opts);
+ cookies.set("username", user.username, opts);
+ cookies.set("token", token, opts);
};
export let auth = (cookies: any) => ({
- authorization: `Bearer ${cookies.get("token")}`,
+ authorization: `Bearer ${cookies.get("token")}`,
});
export let btc = (fiat: number, rate: number): number =>
- Math.round((fiat * sats) / rate);
+ Math.round((fiat * sats) / rate);
export let fiat = (amount: number, rate: number): number =>
- (amount * rate) / sats;
+ (amount * rate) / sats;
export let fd = async (req: Request): Promise<any> => {
- let obj: Record<string, any> = Object.fromEntries(await req.formData());
- for (let k in obj)
- (obj[k] === "undefined" && (obj[k] = undefined)) ||
- (obj[k] === "false" && (obj[k] = false));
- return obj;
+ let obj: Record<string, any> = Object.fromEntries(await req.formData());
+ for (let k in obj)
+ (obj[k] === "undefined" && (obj[k] = undefined)) ||
+ (obj[k] === "false" && (obj[k] = false));
+ return obj;
};
export let f = (s: number, currency: string): string => {
- try {
- return new Intl.NumberFormat("en-US", {
- style: "currency",
- currency,
- })
- .format(s)
- .replace("CA", "");
- } catch (e) {
- return "";
- }
+ try {
+ return new Intl.NumberFormat("en-US", {
+ style: "currency",
+ currency,
+ })
+ .format(s)
+ .replace("CA", "");
+ } catch (e) {
+ return "";
+ }
};
export let s = (s: number): string =>
- new Intl.NumberFormat("en-US", { maximumFractionDigits: 0 }).format(s);
+ new Intl.NumberFormat("en-US", { maximumFractionDigits: 0 }).format(s);
export let sat = (s: number): string => "⚡️" + si(Math.abs(s)).toString();
export let si = (s: number) => {
- if (s < 1000) return s.toString(); // Return the original number if it's less than 1000
+ if (s < 1000) return s.toString(); // Return the original number if it's less than 1000
- const units = ["", "K", "M", "G", "T", "P", "E", "Z"];
- const d = Math.floor(Math.log10(s) / 3); // Calculate the unit index
- const scaled = s / Math.pow(1000, d); // Scale the number to the correct unit
+ const units = ["", "K", "M", "G", "T", "P", "E", "Z"];
+ const d = Math.floor(Math.log10(s) / 3); // Calculate the unit index
+ const scaled = s / Math.pow(1000, d); // Scale the number to the correct unit
- return new Intl.NumberFormat("en-US", { maximumFractionDigits: 2 }).format(scaled) + units[d];
+ return (
+ new Intl.NumberFormat("en-US", { maximumFractionDigits: 2 }).format(
+ scaled,
+ ) + units[d]
+ );
};
export let sats = 100000000;
export let back = (): any =>
- browser && (history.length ? history.go(-1) : goto("/"));
+ browser && (history.length ? history.go(-1) : goto("/"));
export let focus = (el: HTMLElement): any =>
- browser && screen.width > 1280 && setTimeout(() => el.focus(), 1);
+ browser && screen.width > 1280 && setTimeout(() => el.focus(), 1);
export let select = (el: HTMLInputElement): any =>
- browser && screen.width > 1280 && setTimeout(() => el.select(), 1);
+ browser && screen.width > 1280 && setTimeout(() => el.select(), 1);
export let sleep = (n: number): Promise<void> =>
- new Promise((r) => setTimeout(r, n));
+ new Promise((r) => setTimeout(r, n));
export let wait = async (
- f: () => boolean | Promise<boolean>,
- n: number = 100,
- s: number = 300
+ f: () => boolean | Promise<boolean>,
+ n: number = 100,
+ s: number = 300,
): Promise<boolean> => {
- let i = 0;
- while (!(await f()) && i < s) {
- await sleep(n);
- i++;
- }
- if (i >= s) throw new Error("timeout");
- return f();
+ let i = 0;
+ while (!(await f()) && i < s) {
+ await sleep(n);
+ i++;
+ }
+ if (i >= s) throw new Error("timeout");
+ return f();
};
export let stretch = async (password: string, salt: Uint8Array) =>
- crypto.subtle.deriveKey(
- {
- name: "PBKDF2",
- salt,
- iterations: 100000,
- hash: "SHA-256",
- },
- await crypto.subtle.importKey(
- "raw",
- new TextEncoder().encode(password),
- { name: "PBKDF2" },
- false,
- ["deriveBits", "deriveKey"]
- ),
- { name: "AES-GCM", length: 256 },
- true,
- ["encrypt", "decrypt"]
- );
+ crypto.subtle.deriveKey(
+ {
+ name: "PBKDF2",
+ salt,
+ iterations: 100000,
+ hash: "SHA-256",
+ },
+ await crypto.subtle.importKey(
+ "raw",
+ new TextEncoder().encode(password),
+ { name: "PBKDF2" },
+ false,
+ ["deriveBits", "deriveKey"],
+ ),
+ { name: "AES-GCM", length: 256 },
+ true,
+ ["encrypt", "decrypt"],
+ );
export let types = {
- bitcoin: "bitcoin",
- liquid: "liquid",
- lightning: "lightning",
- internal: "internal",
- fund: "fund",
- ecash: "ecash",
- reconcile: "reconcile",
+ bitcoin: "bitcoin",
+ liquid: "liquid",
+ lightning: "lightning",
+ internal: "internal",
+ fund: "fund",
+ ecash: "ecash",
+ reconcile: "reconcile",
};
export let ease = (t: number): number =>
- t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t;
+ t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t;
export function shuffleArray<T>(array: T[]): void {
- for (let i = array.length - 1; i > 0; i--) {
- const j = Math.floor(Math.random() * (i + 1));
- [array[i], array[j]] = [array[j], array[i]];
- }
+ for (let i = array.length - 1; i > 0; i--) {
+ const j = Math.floor(Math.random() * (i + 1));
+ [array[i], array[j]] = [array[j], array[i]];
+ }
}
export let closest = (a: number[], n: number): number =>
- a.reduce((prev, curr) =>
- Math.abs(curr - n) < Math.abs(prev - n) ? curr : prev
- );
+ a.reduce((prev, curr) =>
+ Math.abs(curr - n) < Math.abs(prev - n) ? curr : prev,
+ );
export let isLiquid = (text: string): boolean =>
- text.startsWith("Az") ||
- text.startsWith("lq1") ||
- text.startsWith("VJL") ||
- text.startsWith("VT") ||
- text.startsWith("XR") ||
- text.startsWith("XC") ||
- ((text.startsWith("H") || text.startsWith("G") || text.startsWith("Q")) &&
- text.length === 34) ||
- (text.startsWith("ert1q") && text.length === 43) ||
- (text.startsWith("ex1q") && text.length === 42) ||
- text.startsWith("el1qq") ||
- text.startsWith("lq1qq");
+ text.startsWith("Az") ||
+ text.startsWith("lq1") ||
+ text.startsWith("VJL") ||
+ text.startsWith("VT") ||
+ text.startsWith("XR") ||
+ text.startsWith("XC") ||
+ ((text.startsWith("H") || text.startsWith("G") || text.startsWith("Q")) &&
+ text.length === 34) ||
+ (text.startsWith("ert1q") && text.length === 43) ||
+ (text.startsWith("ex1q") && text.length === 42) ||
+ text.startsWith("el1qq") ||
+ text.startsWith("lq1qq");
export function getCookie(name: string): string | null {
- let nameEQ = name + "=";
- let ca = document.cookie.split(";");
- for (let i = 0; i < ca.length; i++) {
- let c = ca[i];
- while (c.charAt(0) === " ") c = c.substring(1);
- if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
- }
- return null;
+ let nameEQ = name + "=";
+ let ca = document.cookie.split(";");
+ for (let i = 0; i < ca.length; i++) {
+ let c = ca[i];
+ while (c.charAt(0) === " ") c = c.substring(1);
+ if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
+ }
+ return null;
}
export function setCookie(name: string, value: string, seconds: number): void {
- const now = new Date();
- now.setTime(now.getTime() + seconds * 1000);
- const expires = "expires=" + now.toUTCString();
- document.cookie = name + "=" + value + ";" + expires + ";path=/";
+ const now = new Date();
+ now.setTime(now.getTime() + seconds * 1000);
+ const expires = "expires=" + now.toUTCString();
+ document.cookie = name + "=" + value + ";" + expires + ";path=/";
}
export let network = {
- bitcoin: {
- bech32: "bc",
- pubKeyHash: 0x00,
- scriptHash: 0x05,
- wif: 0x80,
- },
- regtest: {
- bech32: "bcrt",
- pubKeyHash: 0x6f,
- scriptHash: 0xc4,
- wif: 0xef,
- },
+ bitcoin: {
+ bech32: "bc",
+ pubKeyHash: 0x00,
+ scriptHash: 0x05,
+ wif: 0x80,
+ },
+ regtest: {
+ bech32: "bcrt",
+ pubKeyHash: 0x6f,
+ scriptHash: 0xc4,
+ wif: 0xef,
+ },
}[PUBLIC_COINOS_NETWORK];
export let versions = {
- bitcoin: {
- private: 0x0488ade4,
- public: 0x0488b21e,
- },
- regtest: {
- private: 0x04358394,
- public: 0x043587cf,
- },
+ bitcoin: {
+ private: 0x0488ade4,
+ public: 0x0488b21e,
+ },
+ regtest: {
+ private: 0x04358394,
+ public: 0x043587cf,
+ },
}[PUBLIC_COINOS_NETWORK];