From 60b24b3d5951e159d09f42ed766c404e4b1acc4e Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Sat, 11 Feb 2023 00:38:55 -0800 Subject: invoice type toggle --- src/lib/invoice.js | 2 +- src/lib/utils.js | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src/lib') diff --git a/src/lib/invoice.js b/src/lib/invoice.js index bb75d4cb..23ce1757 100644 --- a/src/lib/invoice.js +++ b/src/lib/invoice.js @@ -11,7 +11,7 @@ export default async ({ cookies, request, url }) => { let invoice = { amount, - tip: parseInt(form.get('tip')), + tip: parseInt(form.get('tip')) || 0, type: form.get('type'), prompt: form.get('prompt') === 'true', rate: parseFloat(form.get('rate')) || rates[form.get('currency')], diff --git a/src/lib/utils.js b/src/lib/utils.js index 80f7fe07..b3bb29ec 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -231,3 +231,11 @@ export function ss(str1, str2) { return 0.0; } + +export const types = { + bitcoin: 'bitcoin', + lightning: 'lightning', + internal: 'internal', + pot: 'pot', + classic: 'classic' +}; -- cgit v1.2.3 From 979d9dd27a147bae13ba953a7e260412fa024f57 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Tue, 14 Feb 2023 11:19:12 -0800 Subject: handle sending to user --- src/lib/utils.js | 2 ++ src/routes/(app)/[username]/(profile)/+page.svelte | 1 - src/routes/(app)/payment/[id]/+page.svelte | 42 ++++++++++++++++------ src/routes/(app)/send/[...text]/+page.server.js | 5 +-- 4 files changed, 36 insertions(+), 14 deletions(-) (limited to 'src/lib') diff --git a/src/lib/utils.js b/src/lib/utils.js index b3bb29ec..86f722b9 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -147,6 +147,8 @@ export const login = async (user, cookies) => { export const auth = (cookies) => ({ authorization: `Bearer ${cookies.get('token')}` }); +export const fiat = (amount, rate) => (amount * rate) / sats; + export const f = (s, currency) => new Intl.NumberFormat('en-US', { style: 'currency', diff --git a/src/routes/(app)/[username]/(profile)/+page.svelte b/src/routes/(app)/[username]/(profile)/+page.svelte index baab8ba1..c704c00d 100644 --- a/src/routes/(app)/[username]/(profile)/+page.svelte +++ b/src/routes/(app)/[username]/(profile)/+page.svelte @@ -5,7 +5,6 @@ export let data; let { events, invoices, sent, received, subject, user } = data; - console.log(invoices);
diff --git a/src/routes/(app)/payment/[id]/+page.svelte b/src/routes/(app)/payment/[id]/+page.svelte index da21400a..7b2bdb26 100644 --- a/src/routes/(app)/payment/[id]/+page.svelte +++ b/src/routes/(app)/payment/[id]/+page.svelte @@ -1,6 +1,6 @@ -
+

{$t(amount < 0 ? 'payments.sent' : 'payments.received')}

@@ -34,13 +32,33 @@ {/if}
-
- {f(fiat, currency)} - ⚡️{`${s(total)}`} + Amount +
+ {f(fiat(amount, rate), currency)} + ⚡️{`${s(amount)}`} +
+
+ +
+ Network fee +
+ {f(fiat(fee, rate), currency)} + ⚡️{`${s(fee)}`}
+ {#if ourfee > 0} +
+ Platform fee +
+ {f(fiat(ourfee, rate), currency)} + ⚡️{`${s(ourfee)}`} +
+
+ {/if} +
+ Date
{format(new Date(created), 'MMMM d')}, {format(new Date(created), 'h:mm aaa')} @@ -49,6 +67,7 @@ {#if type === 'lightning'}
+ Proof
{$t('payments.preimage')}
{ref} @@ -56,12 +75,13 @@
{:else if type === 'bitcoin'}
+ Txid
-
diff --git a/src/routes/(app)/send/[...text]/+page.server.js b/src/routes/(app)/send/[...text]/+page.server.js index d09b4da9..b1089a5b 100644 --- a/src/routes/(app)/send/[...text]/+page.server.js +++ b/src/routes/(app)/send/[...text]/+page.server.js @@ -45,14 +45,15 @@ let parse = async (t, host) => { // bitcoin if (validate(t)) { try { - ({ id } = await get(`/invoice/${t}`)); + ({ id, user } = await get(`/invoice/${t}`)); } catch (e) { let r = `/send/bitcoin/${t}`; if (amount) r += '/' + amount; throw redirect(307, r); } - if (id) throw redirect(307, `/send/${id}`); + if (user) throw redirect(307, `/send/${user.username}`); + else if (id) throw redirect(307, `/send/${id}`); } // user -- cgit v1.2.3 From 3403bf5c6090109725493b4c7a4fef28266beda8 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 15 Feb 2023 19:57:47 -0800 Subject: messages on dashboard --- src/components/Balance.svelte | 2 +- src/lib/nostr.js | 3 +- .../(app)/[username]/(profile)/+page.server.js | 23 ++- src/routes/(app)/[username]/(profile)/+page.svelte | 191 +++++++++++++++------ .../[username]/settings/[...tab]/+page.server.js | 1 + src/routes/(app)/buy/+page.server.js | 19 ++ src/routes/(app)/buy/+page.svelte | 126 ++++++++++++++ .../(app)/send/lightning/[payreq]/+page.svelte | 2 +- 8 files changed, 306 insertions(+), 61 deletions(-) create mode 100644 src/routes/(app)/buy/+page.server.js create mode 100644 src/routes/(app)/buy/+page.svelte (limited to 'src/lib') diff --git a/src/components/Balance.svelte b/src/components/Balance.svelte index e95e5dde..5d993c28 100644 --- a/src/components/Balance.svelte +++ b/src/components/Balance.svelte @@ -9,7 +9,7 @@
{#if isNaN($animatedRate)} -
---
+
—
{:else} {f((user.balance * $animatedRate) / sats, user.currency)} {/if} diff --git a/src/lib/nostr.js b/src/lib/nostr.js index de19b477..13251856 100644 --- a/src/lib/nostr.js +++ b/src/lib/nostr.js @@ -80,7 +80,7 @@ export let decrypt = async ({ event, user }) => { return Buffer.from(message).toString('utf8'); } catch (e) { - console.log(e); + // console.log(e); } }; @@ -119,6 +119,7 @@ let getPrivateKey = async (user) => { seed = mnemonicToSeedSync(mnemonic); key = bip32.fromSeed(seed); child = key.derivePath("m/44'/1237'/0'/0/0"); + return child.privateKey; }; diff --git a/src/routes/(app)/[username]/(profile)/+page.server.js b/src/routes/(app)/[username]/(profile)/+page.server.js index c68cfecc..d1fa2f41 100644 --- a/src/routes/(app)/[username]/(profile)/+page.server.js +++ b/src/routes/(app)/[username]/(profile)/+page.server.js @@ -1,22 +1,33 @@ import { auth, get } from '$lib/utils'; export async function load({ cookies, params, parent, url }) { - let { subject } = await parent(); + let { user, subject } = await parent(); let { pubkey } = subject; + let { since = 0 } = params; - let events = []; + let messages = []; + + if (user) { + try { + messages = await get(`/${user.pubkey}/${since}/messages`); + } catch (e) { + console.log(`failed to fetch nostr messages`, e); + } + } + + let notes = []; try { - events = await get(`/${pubkey}/notes`); + notes = await get(`/${pubkey}/notes`); } catch (e) { - console.log(`failed to fetch nostr events for ${pubkey}`, e); + console.log(`failed to fetch nostr notes for ${pubkey}`, e); } - events.map((e) => { + notes.map((e) => { e.seen = e.created_at; }); let { invoices, sent, received } = await get('/requests', auth(cookies)); - return { invoices, events, sent, received }; + return { invoices, messages, notes, sent, received }; } diff --git a/src/routes/(app)/[username]/(profile)/+page.svelte b/src/routes/(app)/[username]/(profile)/+page.svelte index c704c00d..45fe1d84 100644 --- a/src/routes/(app)/[username]/(profile)/+page.svelte +++ b/src/routes/(app)/[username]/(profile)/+page.svelte @@ -1,75 +1,162 @@ -
+
{#if user?.id === subject.id} - - {/if} -
+
+ {#if user.balance > 0 && false} +

Balance

+
+ +
+ {:else} +
+

Welcome

+ +

+ Get started by making a deposit or getting someone to pay you in Bitcoin! +

-
- {#each invoices as { amount, currency, rate, request: { requester, recipient }, hash }} - {@const requested = user.username === requester?.username} - -
-
-
- {#if requested} - + {/if} + + {#if invoices.length} +
+

Invoices

+ {#each invoices as { amount, currency, rate, request: { requester, recipient }, hash }} + {@const requested = user.username === requester?.username} + + + {/if} + {#if received.length} +
+

Requests

- {#each received as { id, invoice, memo, requester: r }} - -
-
-
+ {#each received as { id, invoice, memo, requester: r }} + +
- -
-

{r.username}

-

{memo}

+
+
+ +
+

{r.username}

+

{memo}

+
+
+
+
+
-
- + + {/each} +
+ {/if} + + {#if latest.length} +
+

Messages

+ {#each latest as { content, user }} +
+
+
+
{user.username}
+ {content}
-
- - {/each} + {/each} +
+ {/if}
+ + diff --git a/src/routes/(app)/[username]/settings/[...tab]/+page.server.js b/src/routes/(app)/[username]/settings/[...tab]/+page.server.js index dd16459f..94240adc 100644 --- a/src/routes/(app)/[username]/settings/[...tab]/+page.server.js +++ b/src/routes/(app)/[username]/settings/[...tab]/+page.server.js @@ -9,6 +9,7 @@ export function load({ params, url }) { export const actions = { default: async ({ cookies, request }) => { let form = Object.fromEntries(await request.formData()); + form.prompt = form.prompt === 'on' let user = { ...(await get('/me', auth(cookies))), ...form }; try { diff --git a/src/routes/(app)/buy/+page.server.js b/src/routes/(app)/buy/+page.server.js new file mode 100644 index 00000000..e03d6c0a --- /dev/null +++ b/src/routes/(app)/buy/+page.server.js @@ -0,0 +1,19 @@ +import { env } from '$env/dynamic/private'; +import { error, redirect } from '@sveltejs/kit'; +import { post, auth } from '$lib/utils'; +import { createTicket } from '$lib/ticket'; + +export const actions = { + default: async ({ cookies, request }) => { + let form = await request.formData(); + + await post('/buy', { + number: form.get('number').replace(/\s+/g, ''), + month: form.get('expiry').slice(0, 2), + year: form.get('expiry').slice(-2), + cvc: form.get('cvc') + }, auth(cookies)); + + throw redirect(307, `/launch/thanks/${asset}`); + } +}; diff --git a/src/routes/(app)/buy/+page.svelte b/src/routes/(app)/buy/+page.svelte new file mode 100644 index 00000000..34cfc2e5 --- /dev/null +++ b/src/routes/(app)/buy/+page.svelte @@ -0,0 +1,126 @@ + + +
+
+ + + +
+ +
+
+
+ +

Buy Bitcoin

+
+

Purchase up to $500 worth of Bitcoin from us.

+ +

+ If you want more, try Kraken + or + ShakePay or ask + around at our next + meetup. +

+ +
{ + loading = true; + return ({ update }) => update() && (loading = false); + }} + > + + + + + + + + + + +
+ +
+
+
+
+
diff --git a/src/routes/(app)/send/lightning/[payreq]/+page.svelte b/src/routes/(app)/send/lightning/[payreq]/+page.svelte index 6ae699d2..e9502636 100644 --- a/src/routes/(app)/send/lightning/[payreq]/+page.svelte +++ b/src/routes/(app)/send/lightning/[payreq]/+page.svelte @@ -89,7 +89,7 @@
{/if} {:else} -
+ - - - - - - - - + {#if user.eligible} + + + + {/if}
{/if} @@ -138,17 +146,23 @@
{/if} - {#if latest.length} -
-

Messages

- {#each latest as { content, user }} -
-
- + {#if latest.length && user.id === subject.id} +
+ {#each latest as { content, pubkey, author, recipient }} + {@const user = author.id === user.id ? recipient : author} + +
+
+ +
+
+
{user.username}
+
+ {content} +
+
-
{user.username}
- {content} -
+ {/each}
{/if} diff --git a/src/routes/(app)/[username]/(profile)/messages/+page.server.js b/src/routes/(app)/[username]/(profile)/messages/+page.server.js deleted file mode 100644 index 63116099..00000000 --- a/src/routes/(app)/[username]/(profile)/messages/+page.server.js +++ /dev/null @@ -1,16 +0,0 @@ -import { get } from '$lib/utils'; - -export async function load({ params, parent, url }) { - let { user, subject } = await parent(); - let { since = 0 } = params; - - let messages = []; - - try { - messages = await get(`/nostr/${user.pubkey}/${subject.pubkey}/${since}/messages`); - } catch (e) { - console.log(`failed to fetch nostr messages`, e); - } - - return { newMessages: messages }; -} diff --git a/src/routes/(app)/[username]/(profile)/messages/+page.svelte b/src/routes/(app)/[username]/(profile)/messages/+page.svelte deleted file mode 100644 index db7b1ced..00000000 --- a/src/routes/(app)/[username]/(profile)/messages/+page.svelte +++ /dev/null @@ -1,123 +0,0 @@ - - -
-

- {$t('payments.sendMessage')} -

- -
- {#each events as data} - {@const ours = data.pubkey === user.pubkey} - {@const theirs = !ours} -
- {#if data.message} - {data.message} - {:else} - - - {/if} -
-
- {format(new Date(data.created_at * 1000), 'MMM d')}, - {format(new Date(data.created_at * 1000), 'h:mm aa')} -
- {/each} -
- - - - - - - -
- - diff --git a/src/routes/(app)/[username]/invoice/[hash]/+page.svelte b/src/routes/(app)/[username]/invoice/[hash]/+page.svelte index b5571f23..2ff92687 100644 --- a/src/routes/(app)/[username]/invoice/[hash]/+page.svelte +++ b/src/routes/(app)/[username]/invoice/[hash]/+page.svelte @@ -152,9 +152,9 @@ {/if}
- {txt.substr(0, 10)}...{txt.substr(-10)}
diff --git a/src/routes/(app)/[username]/messages/+page.server.js b/src/routes/(app)/[username]/messages/+page.server.js new file mode 100644 index 00000000..7b651389 --- /dev/null +++ b/src/routes/(app)/[username]/messages/+page.server.js @@ -0,0 +1,19 @@ +import { get } from '$lib/utils'; + +export async function load({ params, parent, url }) { + let { user, subject } = await parent(); + let { since = 0 } = params; + + let messages = []; + + try { + messages = await get(`/${user.pubkey}/${since}/messages`); + messages = messages + .filter((m) => m.recipient.id === subject.id || m.author.id === subject.id) + .sort((a, b) => a.created_at - b.created_at); + } catch (e) { + console.log(`failed to fetch nostr messages`, e); + } + + return { messages, user }; +} diff --git a/src/routes/(app)/[username]/messages/+page.svelte b/src/routes/(app)/[username]/messages/+page.svelte new file mode 100644 index 00000000..f8f64aea --- /dev/null +++ b/src/routes/(app)/[username]/messages/+page.svelte @@ -0,0 +1,126 @@ + + +
+ {#if messages.length && ready} +
+ {#each messages as event} + {@const ours = event.pubkey === user.pubkey} + {@const theirs = !ours} +
+
+ {#await decrypt({ event, user })} + - + {:then message} + {message} + {/await} +
+
+ +
+
+
+ {format(new Date(event.created_at * 1000), 'MMM d')}, + {format(new Date(event.created_at * 1000), 'h:mm aa')} +
+ {/each} +
+ {/if} + +
+ + + + +
+
+ + diff --git a/src/routes/(app)/[username]/payments/[...page]/+page.svelte b/src/routes/(app)/[username]/payments/[...page]/+page.svelte index 2068c306..aacba81e 100644 --- a/src/routes/(app)/[username]/payments/[...page]/+page.svelte +++ b/src/routes/(app)/[username]/payments/[...page]/+page.svelte @@ -182,7 +182,7 @@ {:else if p.with}
- +
{p.with.username}
diff --git a/src/routes/(app)/buy/+page.svelte b/src/routes/(app)/buy/+page.svelte index 323d5ef0..2f556ada 100644 --- a/src/routes/(app)/buy/+page.svelte +++ b/src/routes/(app)/buy/+page.svelte @@ -1,13 +1,33 @@
@@ -114,6 +134,17 @@
+ +
+
+
+
1
+ Bitcoin +
+
= {f($animatedRate, currency)}
+
+

3% credit card fee applies

+
diff --git a/src/routes/(app)/login/+page.svelte b/src/routes/(app)/login/+page.svelte index 9a1e41da..75998cd0 100644 --- a/src/routes/(app)/login/+page.svelte +++ b/src/routes/(app)/login/+page.svelte @@ -1,5 +1,4 @@ + + + + diff --git a/src/components/index.js b/src/components/index.js index ab54e09f..0d1d8d1d 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -1,3 +1,4 @@ +export { default as Slider } from './Slider.svelte'; export { default as Pinpad } from './Pinpad.svelte'; export { default as Balance } from './Balance.svelte'; export { default as Lnurlp } from './Lnurlp.svelte'; diff --git a/src/lib/utils.js b/src/lib/utils.js index 86f722b9..1d064c9a 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -148,6 +148,11 @@ export const login = async (user, cookies) => { export const auth = (cookies) => ({ authorization: `Bearer ${cookies.get('token')}` }); export const fiat = (amount, rate) => (amount * rate) / sats; +export const fd = async (req) => { + let obj = 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 const f = (s, currency) => new Intl.NumberFormat('en-US', { diff --git a/src/routes/(app)/[username]/(profile)/request/+page.server.js b/src/routes/(app)/[username]/(profile)/request/+page.server.js index 2c1d6bde..e7ad6a8f 100644 --- a/src/routes/(app)/[username]/(profile)/request/+page.server.js +++ b/src/routes/(app)/[username]/(profile)/request/+page.server.js @@ -1,15 +1,15 @@ import { redirect } from '@sveltejs/kit'; -import { auth, post } from '$lib/utils'; +import { fd, auth, post } from '$lib/utils'; export const actions = { create: async ({ cookies, params, request, url }) => { - let form = Object.fromEntries(await request.formData()); + let form = await fd(request); let { id, requester } = await post('/requests', form, auth(cookies)); throw redirect(307, `/${params.username}/request/${id}`); }, delete: async ({ cookies, request }) => { - let form = Object.fromEntries(await request.formData()); + let form = await fd(request); let r = await post('/requests/delete', form, auth(cookies)); } }; diff --git a/src/routes/(app)/[username]/invoice/[hash]/tip/+page.svelte b/src/routes/(app)/[username]/invoice/[hash]/tip/+page.svelte index d033c413..296ef9c6 100644 --- a/src/routes/(app)/[username]/invoice/[hash]/tip/+page.svelte +++ b/src/routes/(app)/[username]/invoice/[hash]/tip/+page.svelte @@ -3,7 +3,7 @@ import { browser } from '$app/environment'; import { invoice as inv, request } from '$lib/store'; import { copy, focus, f, sat, get, reverseFormat, s, sats } from '$lib/utils'; - import { Icon } from '$comp'; + import { Icon, Slider } from '$comp'; import { goto } from '$app/navigation'; import { t } from '$lib/translations'; import { enhance } from '$app/forms'; @@ -37,9 +37,6 @@ customInput.value = ''; } tipPercent = e.target.value; - - clearTimeout(timeout); - timeout = setTimeout(update, 800); }; let submitting; @@ -56,10 +53,6 @@ }; let submit; - let update = async () => { - await tick(); - //submit.click(); - }; export let data; $: refresh(data); @@ -123,16 +116,7 @@ {#if !showCustomAmount}
{Math.round(tipPercent)}%
- +
@@ -201,43 +185,6 @@
diff --git a/src/lib/samples.js b/src/lib/samples.js index 4af61822..93b9aa24 100644 --- a/src/lib/samples.js +++ b/src/lib/samples.js @@ -1,13 +1,13 @@ export default { - register: `curl -s "https://coinos.io/api/register" -H "application/json" -d '{ + register: `curl "https://coinos.io/api/register" -H "application/json" -d '{ "username": "adam", "password": "hunter2" }'`, - login: `curl -s "https://coinos.io/api/login" -H "application/json" -d '{ + login: `curl "https://coinos.io/api/login" -H "application/json" -d '{ "username": "adam", "password": "hunter2" }'`, - invoice: `curl -s "https://coinos.io/api/invoice" + invoice: `curl "https://coinos.io/api/invoice" -H "application/json" -H "Authorization: Bearer $token" -d '{ @@ -18,5 +18,6 @@ export default { "secret": "hunter2" }, }'`, - fetchInvoice: `curl -s "https://coinos.io/api/invoice/bc1qmhfk9stzffhd9umzmld92vff7zg3mdlh7rvvaj" -H "application/json" }'` + fetchInvoice: `curl "https://coinos.io/api/invoice/bc1qmhfk9stzffhd9umzmld92vff7zg3mdlh7rvvaj" + -H "application/json"'` }; diff --git a/src/routes/(static)/docs/+page.svelte b/src/routes/(static)/docs/+page.svelte index d44204d8..cb82bd05 100644 --- a/src/routes/(static)/docs/+page.svelte +++ b/src/routes/(static)/docs/+page.svelte @@ -1,10 +1,16 @@ -
+

API Documentation

@@ -16,15 +22,19 @@

Base URL

-
https://coinos.io/api
-
+
{api}
+

Auth Token

This JWT authorizes you to use the API

-
export token="{token}"
-
+
{tokenSample}
+

POST /register

@@ -42,17 +52,17 @@ type: bitcoin or lightning
- amount: integer satoshis (optional) + amount: amount in satoshis
- webhook: a URL that we'll POST to when the invoice is - paid (optional) + webhook: an endpoint to hit when the invoice is paid
- secret: a secret to send with the POST (optional) + secret: a secret string for the webhook to check
+ hey

GET /invoice/:hash

@@ -123,4 +133,5 @@ + -- cgit v1.2.3 From 0f44e3283c25c9783a52cf20957661da49d2f90b Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Fri, 3 Mar 2023 21:40:27 -0800 Subject: chinese language file --- src/lib/translations/index.js | 5 + src/lib/translations/lang.json | 3 +- src/locales/zh.json | 291 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 298 insertions(+), 1 deletion(-) create mode 100644 src/locales/zh.json (limited to 'src/lib') diff --git a/src/lib/translations/index.js b/src/lib/translations/index.js index 9c798530..dfd7f47f 100644 --- a/src/lib/translations/index.js +++ b/src/lib/translations/index.js @@ -46,6 +46,11 @@ const config = { locale: 'de', key: '', loader: async () => (await import('../../locales/de.json')).default + }, + { + locale: 'zh', + key: '', + loader: async () => (await import('../../locales/zh.json')).default } ] }; diff --git a/src/lib/translations/lang.json b/src/lib/translations/lang.json index c537d4cf..c607ebd0 100644 --- a/src/lib/translations/lang.json +++ b/src/lib/translations/lang.json @@ -3,5 +3,6 @@ "fr": "Français", "es": "Español", "de": "Deutsch", - "pt": "Português" + "pt": "Português", + "zh": "中国人" } diff --git a/src/locales/zh.json b/src/locales/zh.json new file mode 100644 index 00000000..402f0214 --- /dev/null +++ b/src/locales/zh.json @@ -0,0 +1,291 @@ +{ + "404": { + "404": "404", + "pageNotFound": "Page not found." + }, + "about": { + "header": "About", + "p1": "Coinos is an open source bitcoin payment app. Development started in Vancouver in September 2012 as a way to provide local merchants with a convenient way to accept bitcoin payments.", + "p2": "You can download the source code to run an instance and connect it to your own bitcoin and lightning nodes. We'll help you get started being a benevolent custodian and payments provider for your community.", + "p3": "Account transfers amongst users on our server are done off-chain so they're completely free, instant, and unlimited.", + "team": { + "header": "The Team", + "adam": { + "name": "Adam Soltys", + "position": "Chief Technical Officer", + "bio": "Adam is a web developer and bitcoin enthusiast who believes sound money is key to increasing global prosperity. He lives in North Vancouver with his wife Chelsea and two children." + }, + "shauna": { + "name": "Shauna", + "position": "Operations & Marketing", + "bio": "Strategic & Project Management. Jack of all Trades. Can always find time to meet for coffee." + }, + "cole": { + "name": "Cole", + "position": "Certified Bitcoin Professional", + "bio": "Cole is a driven individual with a passion for freedom. He came across bitcoin in 2016 and studied it in depth. Now he wants to introduce the lightning network to as many users as possible." + }, + "john": { + "name": "John Barratt", + "position": "Full Stack Web Developer", + "bio": "When not coding you can find John out in the woods hiking all the great trails that BC has to offer." + } + }, + "locations": { + "header": "Locations", + "description": "Here are some businesses that are accepting bitcoin with Coinos. We hope that yours will be next!" + } + }, + "error": { + "header": "Error", + "message": "Please try again or contact support.", + "signIn": "Please sign in to continue." + }, + "faq": { + "header": "FAQ", + "cost": { + "question": "What does it cost?", + "answer": "It's free to register an account and receive payments over the lightning network. We charge a 0.1% fee to convert from lightning to bitcoin." + }, + "compatibility": { + "question": "Do I need any special device or software?", + "answer": "No. Coinos is web-based, so as long as you have an internet connection, you can use it on any device. Retail merchants might use it on a phone or a tablet." + }, + "safety": { + "question": "When do my funds settle?", + "answer": "Lightning payments are settled instantly. You can withdraw your balance to another wallet or exchange right after payments are received." + } + }, + "footer": { + "company": "Company", + "followUs": "Follow Us", + "github": "GitHub", + "jobs": "Jobs", + "support": "Support", + "telegram": "Telegram", + "twitter": "Twitter", + "documentation": "Documentation" + }, + "howItWorks": { + "header": "How it works", + "step1": { + "header": "1. Create your account", + "description": "A username and password is all you need to get started." + }, + "step2": { + "header": "2. Ask for payments", + "description": "The same as you normally would, but with bitcoin." + }, + "step3": { + "header": "3. That's all!", + "description": "Spend your coin at other merchants or save it for a rainy day, the choice is yours." + } + }, + "invoice": { + "addTip": "Add a tip", + "addTipq": "Add a tip?", + "done": "Done", + "paymentSuccessful": "Payment received!", + "invoice": "Invoice", + "total": "Total", + "tip": "Tip" + }, + "jobs": { + "header": "Jobs", + "subheader": "Current Openings", + "pitch1": "Coinos is actively looking for developers to join our growing team (full-time or part-time, remote working OK).", + "pitch2": "Excited about working on open source bitcoin? Then take a look at our repositories on", + "github": "GitHub", + "pitch3": "If you think you can make an impact, we'd love to hear from you. Send us your resume to" + }, + "landing": { + "header_before_icon": "The", + "header_with_icon": "easiest", + "header_after_icon": "way to accept bitcoin in your store.", + "subheader": "Grow your customer base and revenue by accepting bitcoin with an easy-to-use web app. No software or hardware required.", + "info1": { + "title": "Instant payments via Lightning", + "description": "The moment your customer sends a payment, it’s there. No waiting for bank settlements or worrying about chargebacks. Instant settlement, in seconds. Say goodbye to 3% credit card processing fees." + }, + "info2": { + "title": "Simple to use", + "description1": "Just enter an amount in your local currency, share the QR code and you’re done.", + "description2": "We do all the heavy lifting so you can focus on your business.", + "description3": "You always have the option of taking custody of your funds by withdrawing instantly at any time." + }, + "info3": { + "title": "Brand it your way!", + "description": "Customize your point of sale look and feel, or keep it on default - it's totally up to you." + } + }, + "login": { + "optional": "Optional", + "token": "2FA Token", + "username": "Username", + "password": "Password", + "email": "Email", + "passwordRecommendation": "We recommend a long, random password generated with a password manager.", + "forgotUserOrPassword": "Forgot Username or Password?", + "haveAccount": "Already have an account?", + "noAccount": "Don't have an account?", + "register": "Register", + "signIn": "Sign In", + "failed": "Login failed" + }, + "nav": { + "profile": "Profile", + "startInSeconds": "Start in Seconds", + "account": "Account", + "signIn": "Sign In", + "signOut": "Sign Out", + "dashboard": "Dashboard", + "settings": "Settings", + "support": "Support" + }, + "newSiteHeader": "Join us at our launch party in Vancouver on October 26! Looking for the old coinos? Visit classic.coinos.io", + "news": { + "header": "News", + "subheader": "Latest Updates", + "update1": "" + }, + "user": { + "bitcoin": "Bitcoin", + "lightning": "Lightning", + "invoice": "Invoice", + "unfollow": "Unfollow", + "following": "Following", + "follow": "Follow", + "followers": "Followers", + "remove": "Remove", + "noNotes": "No notes yet", + "message": "Message", + "messages": "Messages", + "feed": "Feed", + "notes": "Notes", + "pay": "Pay", + "scanToPayBTC": "Scan to pay with bitcoin", + "this": "This", + "lightningAddress": "lightning address", + "likeAnEmail": "is like an email for bitcoin. You can publish it on your website or business cards and use it multiple times.", + "dashboard": { + "go": "Go", + "dashboard": "Dashboard", + "accountBalance": "Account Balance", + "bitcoinPrice": "bitcoin Price:", + "conversionFeeWarning": "You will be charged a 1% withdrawal fee on the amount.", + "dataFromBinance": "Data from Binance.", + "fetchingRate": "fetching rate...", + "optionalNote": "Note (Optional)", + "send": "Send", + "receive": "Receive", + "withdraw": "Send", + "deposit": "Deposit", + "voucher": "Voucher" + }, + "receive": { + "lessThan1BTCWarning": "Please enter an amount less than 1 bitcoin.", + "showQR": "Show QR" + }, + "send": { + "contacts": "Contacts", + "scan": "Scan", + "paste": "Paste", + "next": "Next", + "placeholder": "Paste a bitcoin address, lightning invoice or coinos username" + }, + "settings": { + "bannerImage": "Banner Image", + "profileImage": "Profile Image", + "oneTimeCode": "Enter one-time code", + "accountId": "Account Secret", + "header": "Settings", + "ACCOUNT": "ACCOUNT", + "POINT_OF_SALE": "PREFERENCES", + "SECURITY": "SECURITY", + "locale": "Language", + "username": "Username", + "email": "Email", + "newPassword": "Change Password", + "about": "About", + "aboutPlaceholder": "A little something about you or your business address and hours", + "emailNotifications": "Email Notifications", + "emailNotificationsDescription": "Get notified via email when a change occurs on your account or when people send you payments.", + "smsNotifications": "SMS Notifications", + "smsNotificationsDescription": "Coinos will send you text notifications when this is enabled.", + "theme": "Color Theme", + "tipPrompt": "Prompt for tips", + "tipPromptDescription": "Ask people if they want to add a tip before paying their invoices", + "displayName": "Display name", + "themeDescription": "Select from the default color themes.", + "localCurrency": "Currency", + "btcUnit": "Display bitcoin in:", + "bitcoin": "bitcoin", + "minutes": "minutes", + "hour": "hour", + "hours": "hours", + "satoshis": "Satoshis", + "securityPIN": "Security PIN", + "securityPINDescription": "Set a security pin that will be used to unlock your settings and to send outgoing payments.", + "setPIN": "Set PIN", + "autoLock": "Auto-Lock Timer", + "autoLockDescription": "Your account will go into a secure mode, requiring you to re-enter your credentials after a specified time:", + "twofa": "2-Factor Authentication", + "twofaDescription": "Add an extra level of security to your device by enabling 2-factor authentication.", + "twofaSetup": "Set up 2FA", + "twofaDisable": "Disable 2FA", + "select": "Select", + "verifyPIN": "Verify PIN", + "enablePIN": "Enable PIN", + "disablePIN": "Disable PIN" + }, + "support": { + "header": "Support", + "email": "Email", + "accountName": "Account Name", + "message": "Message", + "send": "Send" + } + }, + "payments": { + "amount": "Amount", + "date": "Date", + "id": "Transaction ID", + "details": "Transaction Details", + "header": "Payments", + "preimage": "Proof of payment", + "type": "Type", + "time": "Time", + "sent": "Sent", + "received": "Received", + "empty": "No transactions yet.", + "send": "Send", + "next": "Next", + "sendersChoice": "Sender's choice", + "sendTo": "Send to", + "to": "to", + "pay": "Pay", + "requesting": "is requesting", + "sentInvoiceTo": "Sent invoice to", + "sentRequestTo": "Request sent!", + "pleasePay": "Please pay", + "day": "Day", + "week": "Week", + "month": "Month", + "all": "All", + "export": "Export", + "invoice": "Invoice", + "readyToPay": "is ready to pay", + "describeOrder": "Use this field to describe your order", + "requestAnInvoice": "Request Invoice", + "submit": "Submit", + "isRequesting": "is requesting", + "invoiceFrom": "Invoice from", + "awaiting": "Awaiting", + "tapAnywhere": "Tap anywhere to continue", + "from": "from", + "redeem": "Redeem", + "redeemed": "Redeemed", + "redeemedBy": "Redeemed by", + "sendMessage": "Write a message..." + } +} -- cgit v1.2.3