import { browser } from '$app/environment'; import { toast } from '@zerodevx/svelte-toast'; import { goto } from '$app/navigation'; import { PUBLIC_COINOS_URL } from '$env/static/public'; export function scroll(section) { section.scrollIntoView({ behavior: 'smooth' }); } const base = browser ? '' : PUBLIC_COINOS_URL; export const runner = (k) => { return Math.round(((parseInt(k[0], 16) - 1) / 15) * 7) + 1 + '.webp'; }; export const g = (url, fetch, headers) => fetch(base + url, { headers }) .then((r) => r.text()) .then((body) => { try { return JSON.parse(body); } catch (e) { throw new Error(body); } }); export const get = (url, headers = {}) => 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 const post = (url, body, headers) => { headers = { ...headers, 'content-type': 'application/json', accept: 'application/json' }; return fetch(base + url, { method: 'POST', body: JSON.stringify(body), headers }) .then(async (r) => { if (r.ok) return r.text(); throw new Error(await r.text()); }) .then((body) => { try { body = JSON.parse(body); } catch (e) { throw new Error(body); } if (body.error) throw body.error; if (body instanceof Error) throw body; if (body.name === 'Error') throw new Error(body.message); return body; }); }; export const copy = (text) => { navigator.clipboard.writeText(text); success('Copied!'); }; export function reverseFormat(val, locale) { 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 = [/customers/, /dashboard/, /settings/, /transactions/]; export const success = (m) => { toast.pop(); toast.push(m, { theme: { '--toastBarBackground': '#F5F7FA' } }); }; export const warning = (m) => { toast.pop(); toast.push(m, { theme: { '--toastBarBackground': '#FFCE22' } }); }; export const failure = (m) => { toast.pop(); toast.push(m, { theme: { '--toastBarBackground': '#E93535' } }); }; export const info = (m) => { toast.pop(); toast.push(m, { theme: { '--toastBarBackground': 'white' } }); }; export const login = async (user, cookies) => { let maxAge = 30 * 24 * 60 * 60; let res = await fetch(base + '/login', { method: 'POST', body: JSON.stringify(user), headers: { 'content-type': 'application/json', accept: 'application/json' } }); if (res.status === 401) { let text = await res.text(); if (text.startsWith('2fa')) throw new Error('2fa'); } let { token } = await res.json(); if (!token) throw new Error('Login failed'); let expires = new Date(); expires.setSeconds(expires.getSeconds() + maxAge); cookies.set('username', user.username, { path: '/', expires }); cookies.set('token', token, { path: '/', expires }); }; export const auth = (cookies) => ({ authorization: `Bearer ${cookies.get('token')}` }); export const f = (s, currency) => new Intl.NumberFormat('en-US', { style: 'currency', currency }) .format(s) .replace('CA', ''); export const s = (s) => new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format(s); export const sat = (s) => { s = Math.abs(s); let p = Math.floor(Math.log(s) / Math.LN10 + 0.000000001); let d = Math.floor((p + 1) / 3); return ( '⚡️' + (parseInt(s) > 0 ? new Intl.NumberFormat('en-US', { maximumFractionDigits: 1 }).format(s / Math.pow(1000, d)) + ['', 'K', 'M', 'G'][d] : 0 ).toString() ); }; export const sats = 100000000; export const back = () => browser && history.go(-1); export const focus = (el) => setTimeout(() => el.focus()); export const wait = async (f, s = 300) => { let i = 0; while (!(await f()) && i < s) (await sleep(1000)) && i++; if (i >= s) throw new Error('timeout'); return f(); };