From 64911388f80d52d6dd53d707457a37fe386c194e Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Thu, 29 Sep 2022 15:05:13 -0700 Subject: address parsing --- src/components/Numpad.svelte | 153 +++++++++++ src/components/RegisterOrLogin.svelte | 6 +- src/components/index.js | 1 + src/lib/parse.js | 296 +++------------------- src/lib/utils.js | 4 +- src/routes/logout/+page.server.js | 25 +- src/routes/scan/+page.svelte | 7 +- src/routes/send/+page.svelte | 71 +++--- src/routes/send/bitcoin/[address]/+page.server.js | 8 + src/routes/send/bitcoin/[address]/+page.svelte | 39 +++ src/routes/send/lightning/+page.svelte | 0 src/routes/send/lnurl/+page.svelte | 0 12 files changed, 288 insertions(+), 322 deletions(-) create mode 100644 src/components/Numpad.svelte create mode 100644 src/routes/send/bitcoin/[address]/+page.server.js create mode 100644 src/routes/send/bitcoin/[address]/+page.svelte create mode 100644 src/routes/send/lightning/+page.svelte create mode 100644 src/routes/send/lnurl/+page.svelte (limited to 'src') diff --git a/src/components/Numpad.svelte b/src/components/Numpad.svelte new file mode 100644 index 00000000..f00f33c1 --- /dev/null +++ b/src/components/Numpad.svelte @@ -0,0 +1,153 @@ + + +
+ {#if $selectedRate} +
+ +
+
+ {useFiat ? `${symbol}${amountFiat}` : amountSatsFormatted}{useFiat ? $user.currency : 'SAT'} +
+ {useFiat ? `${amountSatsConverted} SAT` : amountFiatConverted} + +
+ + +
+ {#each numPad as value} + {#if value === '<'} + + {:else} + + {/if} + {/each} +
+
+ {:else} +
+ {/if} +
diff --git a/src/components/RegisterOrLogin.svelte b/src/components/RegisterOrLogin.svelte index fa805a1d..8f10fadd 100644 --- a/src/components/RegisterOrLogin.svelte +++ b/src/components/RegisterOrLogin.svelte @@ -3,7 +3,7 @@ import { page } from '$app/stores'; import { tick } from 'svelte'; import { Icon } from '$comp'; - import { post, failure } from '$lib/utils'; + import { focus, post, failure } from '$lib/utils'; import { redirect, user, token } from '$lib/store'; import { auth } from '$lib/socket'; import { goto } from '$app/navigation'; @@ -25,10 +25,6 @@ // TODO: move to server side $: if (browser && $user) goto(`/${$user.username}/receive`); - - let focus = (el) => setTimeout(() => el.focus()); - - console.log('REDIRECT STORE', $redirect);
diff --git a/src/components/index.js b/src/components/index.js index ba0f6516..48d5ecd0 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -1,3 +1,4 @@ +export { default as Numpad } from './Numpad.svelte'; export { default as Spinner } from './Spinner.svelte'; export { default as Check } from './Check.svelte'; export { default as Heart } from './Heart.svelte'; diff --git a/src/lib/parse.js b/src/lib/parse.js index 2a827956..2abc2cba 100644 --- a/src/lib/parse.js +++ b/src/lib/parse.js @@ -1,271 +1,39 @@ -export default (text) => { +// import bolt11 from 'bolt11'; +import validate from 'bitcoin-address-validation'; +import bip21 from 'bip21'; +import { get } from '$lib/utils'; +import { goto } from "$app/navigation"; + +let debounce; +export default async (text) => { if (!text) return; + console.log("parsing") - if (text.includes('@') && text.includes('.')) { - let [name, domain] = text.split('@'); - try { - clearTimeout(debounce); - await new Promise((r) => (debounce = setTimeout(r, 1500))); - ({ data: text } = await Vue.axios.get( - `/encode?domain=${domain}&name=${name}` - )); - } catch (e) {} + // lightning + if (text.startsWith('ln')) { + try { + console.log('lightning'); + } catch (e) {} } - try { - if (text.toLowerCase().slice(0, 10) === 'lightning:') - text = text.slice(10); - let payreq = text.toLowerCase(); - payment.payreq = payreq; - payment.payobj = bolt11.decode(payment.payreq); - let { - network: { bech32 }, - } = payment.payobj; - - if (!networks.includes('lightning')) - return commit('error', 'Lightning not supported in this account'); - - if (bech32 !== process.env.VUE_APP_NETWORK_BECH32) { - dispatch('clearPayment'); - commit( - 'error', - `Wrong network prefix '${bech32}' instead of '${process.env.VUE_APP_NETWORK_BECH32}'` - ); - throw new Error('Wrong network'); - } - - if (user.account.ticker !== 'BTC') - await dispatch( - 'shiftAccount', - user.accounts.find((a) => a.asset === BTC).id - ); - - let { tags, satoshis, millisatoshis } = payment.payobj; - let description = tags.find((t) => t.tagName === 'description'); - if (description) payment.memo = description.data; - payment.amount = millisatoshis - ? Math.round(millisatoshis / 1000) - : satoshis; - payment.fiatAmount = ((payment.amount * getters.rate) / SATS).toFixed( - 2 - ); - payment.network = 'lightning'; + // bitcoin + if (validate(text)) { + console.log('bitcoin'); + goto(`/send/bitcoin/${text}`); + } - await Vue.axios.post('/lightning/query', { payreq }); - if (!getters.payment.recipient) - go({ name: 'send', params: { keep: true } }); + // ln address + if (text.includes('@') && text.includes('.')) { + console.log("ln address") + let [name, domain] = text.split('@'); + try { + clearTimeout(debounce); + await new Promise((r) => (debounce = setTimeout(r, 1500))); + let lnurl = await get(`/encode?domain=${domain}&name=${name}`); + console.log('lnurl', lnurl); + } catch (e) {} + } - return; - } catch (e) { - if (e.response) commit('error', e.response.data); - } - // - // let url; - // try { - // if (nodes.includes('bitcoin')) { - // url = bip21.decode(text); - // if (!networks.includes('bitcoin')) - // return commit('error', 'Bitcoin not supported in this account'); - // payment.network = 'bitcoin'; - // url.options.asset = BTC; - // } - // } catch (e) { - // if (nodes.includes('liquid')) { - // try { - // url = bip21.decode(text, 'liquidnetwork'); - // if (!networks.includes('liquid')) - // return commit('error', 'Liquid not supported in this account'); - // payment.network = 'liquid'; - // } catch (e) { - // /**/ - // } - // } - // } - // - // if (url) { - // let { amount, asset, assetid, message } = url.options; - // if (assetid) asset = assetid; - // if (!asset) asset = BTC; - // let account = user.accounts.find((a) => a.asset === asset); - // if (account) { - // if (account.asset !== user.account.asset) - // await dispatch('shiftAccount', account.id); - // } else return commit('error', 'Unrecognized asset'); - // - // payment.address = url.address; - // - // if (message) payment.memo = message; - // - // if (amount) { - // payment.amount = parseInt((amount * SATS).toFixed(0)); - // payment.fiatAmount = ((payment.amount * getters.rate) / SATS).toFixed( - // 2 - // ); - // } - // - // await dispatch('isInternal'); - // await dispatch('estimateFee'); - // go({ name: 'send', params: { keep: true } }); - // return; - // } - // - // if (nodes.includes('bitcoin') && validate(text)) { - // if (!networks.includes('bitcoin')) - // return commit('error', 'Bitcoin not supported in this account'); - // payment.address = text; - // payment.network = 'bitcoin'; - // await dispatch('isInternal'); - // go({ name: 'send', params: { keep: true } }); - // return; - // } - // - // // Liquid - // if (nodes.includes('liquid') && isLiquid(text)) { - // if (!networks.includes('liquid')) - // return commit('error', 'Liquid not supported in this account'); - // payment.address = text; - // payment.network = 'liquid'; - // await dispatch('isInternal'); - // go({ name: 'send', params: { keep: true } }); - // return; - // } - // - // if (text.startsWith('6P')) { - // commit('text', text); - // return go('/decrypt'); - // } - // - // try { - // let ecpair = ECPair.fromWIF(text, { - // ...this._vm.$network, - // confidentialPrefix: 1, - // assetHash: '', - // }); - // commit('ecpair', ecpair); - // go('/sweep'); - // } catch (e) { - // /* */ - // } - // - // if (text.toLowerCase().startsWith('lnurl:')) { - // try { - // const { data: lnurl } = await Vue.axios.get(`/url?code=${text}`); - // await dispatch('handleScan', lnurl); - // return; - // } catch (e) { - // commit('error', e.response ? e.response.data : e.message); - // } - // } - // - // if (text.toLowerCase().includes('lnurl')) { - // commit('loading', true); - // let txt = text.toLowerCase().match(/lnurl[a-z0-9]+/); - // - // try { - // const { data: params } = await Vue.axios.get(`/decode?text=${txt}`); - // if (params.status === 'ERROR') { - // let { reason } = params; - // try { - // ({ reason } = JSON.parse(reason.replace(/.*{/, '{'))); - // } catch { - // /**/ - // } - // - // commit('loading', false); - // return commit('error', reason); - // } - // - // let { seed } = getters; - // - // switch (params.tag) { - // case 'channelRequest': - // await dispatch('openChannel', params); - // break; - // case 'login': - // if (!seed) ({ seed } = await dispatch('passwordPrompt')); - // try { - // const key = linkingKey(params.domain, seed); - // const signedMessage = secp256k1.ecdsaSign( - // hexToUint8Array(params.k1), - // key.privateKey - // ); - // const signedMessageDER = secp256k1.signatureExport( - // signedMessage.signature - // ); - // const linkingKeyPub = secp256k1.publicKeyCreate( - // key.privateKey, - // true - // ); - // const sig = bytesToHexString(signedMessageDER); - // - // const response = await Vue.axios.post('/login', { - // params, - // sig, - // key: bytesToHexString(linkingKeyPub), - // }); - // - // if (response.data.status === 'OK') { - // commit('snack', 'Login success'); - // } else { - // commit('error', response.status); - // } - // - // go('/home'); - // } catch (e) { - // commit('error', e.response ? e.response.data : e.message); - // } - // break; - // - // case 'withdrawRequest': - // commit('lnurl', params); - // go('/withdraw'); - // break; - // case 'payRequest': - // commit('lnurl', params); - // go('/pay'); - // break; - // } - // } catch (e) { - // commit('error', e.response ? e.response.data : e.message); - // } - // - // commit('loading', false); - // } - // - // if (isUuid(text)) { - // try { - // const { data: payment } = await Vue.axios.post('/checkRedeemCode', { - // redeemcode: text, - // }); - // - // if (payment) { - // window.location.href = `${window.location.protocol}//${window.location.host}/redeem/${text}`; - // return; - // } - // } catch (e) { - // commit('error', e.response ? e.response.data : e.message); - // } - // - // try { - // const { data: invoice } = await Vue.axios.get( - // `/invoice?uuid=${text}` - // ); - // await dispatch('handleScan', invoice.text); - // return; - // } catch (e) { - // commit('error', e.response ? e.response.data : e.message); - // } - // } - // - // if ( - // text.startsWith( - // `${window.location.protocol}//${window.location.host}/redeem` - // ) - // ) { - // window.location.href = text; - // } - // - // commit('stopScanning', true); - // - // return 'no'; + // user + console.log("username") }; diff --git a/src/lib/utils.js b/src/lib/utils.js index 61e2ddac..514e3adb 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -146,6 +146,8 @@ export const toggleFullscreen = (el) => export const sats = 100000000; -export const goBack = () => { +export const back = () => { browser && history.go(-1); }; + +export const focus = (el) => setTimeout(() => el.focus()); diff --git a/src/routes/logout/+page.server.js b/src/routes/logout/+page.server.js index 3eae005f..726094fd 100644 --- a/src/routes/logout/+page.server.js +++ b/src/routes/logout/+page.server.js @@ -7,19 +7,18 @@ const opts = { path: '/' }; -export async function load({ setHeaders }) { - setHeaders({ - 'set-cookie': [ - cookie.serialize('token', '', { - ...opts, - expires: new Date(0) - }), - cookie.serialize('refresh_token', '', { - ...opts, - expires: new Date(0) - }) - ] - }); +export async function load({ cookies }) { + console.log('COOKIES', cookies); + cookies.set('set-cookie', [ + cookies.serialize('token', '', { + ...opts, + expires: new Date(0) + }), + cookies.serialize('refresh_token', '', { + ...opts, + expires: new Date(0) + }) + ]); throw redirect(302, '/logout/done'); } diff --git a/src/routes/scan/+page.svelte b/src/routes/scan/+page.svelte index 5c8c09f6..9b1072e0 100644 --- a/src/routes/scan/+page.svelte +++ b/src/routes/scan/+page.svelte @@ -2,11 +2,12 @@ import { Icon } from "$comp"; import QrScanner from 'qr-scanner'; import { onMount } from 'svelte'; - import { goBack } from "$lib/utils"; + import { back } from "$lib/utils"; + import { goto } from "$app/navigation"; let scanner, vid; onMount(() => { - scanner = new QrScanner(vid, console.log); + scanner = new QrScanner(vid, (text) => goto(`/send/${text}`)); scanner.start(); }); @@ -14,7 +15,7 @@ diff --git a/src/routes/send/+page.svelte b/src/routes/send/+page.svelte index 777f9766..2162d76d 100644 --- a/src/routes/send/+page.svelte +++ b/src/routes/send/+page.svelte @@ -1,40 +1,32 @@ - +
- - + -
+
@@ -43,20 +35,27 @@
+ + {#if browser && navigator.clipboard} +
+ +
+ {/if}
- +
+ +
diff --git a/src/routes/send/bitcoin/[address]/+page.server.js b/src/routes/send/bitcoin/[address]/+page.server.js new file mode 100644 index 00000000..8cdf7276 --- /dev/null +++ b/src/routes/send/bitcoin/[address]/+page.server.js @@ -0,0 +1,8 @@ +import { redirect } from "@sveltejs/kit"; +export const actions = { + default: async ({ request }) => { + let form = Object.fromEntries(await request.formData()); + console.log('send bitcoin', form); + throw redirect(307, '/'); + } +}; diff --git a/src/routes/send/bitcoin/[address]/+page.svelte b/src/routes/send/bitcoin/[address]/+page.svelte new file mode 100644 index 00000000..fd635fd5 --- /dev/null +++ b/src/routes/send/bitcoin/[address]/+page.svelte @@ -0,0 +1,39 @@ + + + + +
+
+

Send to

+

{address}

+
+ + +
+ + +
+ +
+
+
diff --git a/src/routes/send/lightning/+page.svelte b/src/routes/send/lightning/+page.svelte new file mode 100644 index 00000000..e69de29b diff --git a/src/routes/send/lnurl/+page.svelte b/src/routes/send/lnurl/+page.svelte new file mode 100644 index 00000000..e69de29b -- cgit v1.2.3