├── test ├── src ├── components │ ├── RegisterAsset.vue │ ├── Tor.vue │ ├── PrivacyPolicy.vue │ ├── Confirm.vue │ ├── NetworkIcon.vue │ ├── Accept.vue │ ├── InvoiceCustomerControls.vue │ ├── Social.vue │ ├── Text.vue │ ├── PaymentDetails.vue │ ├── Deposit.vue │ ├── Lnurl.vue │ ├── SendToUser.vue │ ├── TwoFa.vue │ ├── Methods.vue │ ├── MarketConflict.vue │ ├── WithdrawUrl.vue │ ├── BottomNav.vue │ ├── SnackBar.vue │ ├── Recipient.vue │ ├── Decrypt.vue │ ├── Seed.vue │ ├── Home.vue │ ├── Password.vue │ ├── Pin.vue │ ├── Withdraw.vue │ ├── Qr.vue │ ├── SetFee.vue │ ├── Voucher.vue │ ├── Asset.vue │ ├── Register.vue │ ├── Send.vue │ ├── LastTrades.vue │ ├── Support.vue │ ├── Orders.vue │ ├── LinkingKeys.vue │ ├── Pay.vue │ ├── Faucet.vue │ ├── CurrencyList.vue │ ├── Scan.vue │ ├── Documents.vue │ ├── To.vue │ ├── Info.vue │ ├── User.vue │ ├── MarketList.vue │ ├── Proposal.vue │ ├── OrderBook.vue │ ├── LightningNode.vue │ ├── Received.vue │ ├── Redeem.vue │ ├── InvoiceBalance.vue │ ├── Sent.vue │ ├── Receive.vue │ ├── TipPad.vue │ ├── Swaps.vue │ ├── Balance.vue │ ├── LightningPayment.vue │ ├── Login.vue │ ├── Paper.vue │ ├── SetPin.vue │ └── About.vue ├── version.js ├── publicPaths.js ├── assets │ ├── authy.png │ ├── bitcoin.png │ ├── coinos.png │ ├── coinos_logo.png │ ├── canada.svg │ ├── bitcoin.svg │ └── liquid.svg ├── restrictedPaths.js ├── window.js ├── mixins │ ├── Copy.vue │ ├── DynamicLoad.vue │ ├── FullScreen.vue │ └── CustomSequelize.vue ├── icons │ ├── Canada.vue │ ├── Bitcoin.vue │ ├── Liquid.vue │ └── Interac.vue ├── format.js ├── main.js ├── plugins │ └── coinos.js ├── config │ └── index.js └── App.vue ├── .browserslistrc ├── .eslintignore ├── babel.config.js ├── cypress.json ├── public ├── adam.png ├── fav.png ├── badge.png ├── coinos.png ├── coinos.webp ├── favicon.ico ├── intro.png ├── coinos96.png ├── coinos-logo.jpg ├── robots.txt ├── favicon-16x16.png ├── favicon-32x32.png ├── mstile-150x150.png ├── apple-touch-icon.png ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── browserconfig.xml ├── sitemap.xml ├── manifest.json ├── safari-pinned-tab.svg ├── service-worker.js ├── index.html └── coinos.svg ├── tests ├── unit │ ├── .eslintrc.js │ └── example.spec.js └── e2e │ ├── specs │ └── test.js │ └── support │ ├── index.js │ └── commands.js ├── postcss.config.js ├── .prettierignore ├── .prettierrc.js ├── Dockerfile.base ├── .editorconfig ├── .env.development.sample ├── Dockerfile ├── .dockerignore ├── Dockerfile.dev ├── .eslintrc.js ├── git_hooks └── pre-commit ├── .env.staging ├── .gitignore ├── .env.production ├── .env.development ├── README.md ├── vue.config.js └── package.json /test: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /src/components/RegisterAsset.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | cordova 3 | dist 4 | -------------------------------------------------------------------------------- /src/version.js: -------------------------------------------------------------------------------- 1 | f90555a1b90c7d7849f3a23ef2f0dd14f5bfd588 2 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['@vue/app'], 3 | }; 4 | -------------------------------------------------------------------------------- /cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "pluginsFile": "tests/e2e/plugins/index.js" 3 | } 4 | -------------------------------------------------------------------------------- /public/adam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/public/adam.png -------------------------------------------------------------------------------- /public/fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/public/fav.png -------------------------------------------------------------------------------- /src/publicPaths.js: -------------------------------------------------------------------------------- 1 | export default ['/login', '/register', '/about', '/support']; 2 | -------------------------------------------------------------------------------- /public/badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/public/badge.png -------------------------------------------------------------------------------- /public/coinos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/public/coinos.png -------------------------------------------------------------------------------- /public/coinos.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/public/coinos.webp -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/public/intro.png -------------------------------------------------------------------------------- /public/coinos96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/public/coinos96.png -------------------------------------------------------------------------------- /src/assets/authy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/src/assets/authy.png -------------------------------------------------------------------------------- /tests/unit/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | mocha: true, 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {}, 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /public/coinos-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/public/coinos-logo.jpg -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: / 3 | Sitemap: https://classic.coinos.io/sitemap.xml 4 | -------------------------------------------------------------------------------- /src/assets/bitcoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/src/assets/bitcoin.png -------------------------------------------------------------------------------- /src/assets/coinos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/src/assets/coinos.png -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .git/ 3 | .vscode/ 4 | dist/ 5 | static/ 6 | node_modules/ 7 | public/ 8 | -------------------------------------------------------------------------------- /public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/public/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/public/favicon-32x32.png -------------------------------------------------------------------------------- /public/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/public/mstile-150x150.png -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/public/apple-touch-icon.png -------------------------------------------------------------------------------- /src/assets/coinos_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/src/assets/coinos_logo.png -------------------------------------------------------------------------------- /public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coinos/coinos-classic/HEAD/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 80, 3 | tabWidth: 2, 4 | singleQuote: true, 5 | trailingComma: 'es5', 6 | }; 7 | -------------------------------------------------------------------------------- /Dockerfile.base: -------------------------------------------------------------------------------- 1 | FROM node:18-alpine 2 | 3 | RUN npm i -g pnpm 4 | 5 | WORKDIR /deps 6 | COPY package.json . 7 | RUN NODE_ENV=development pnpm i 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.env.development.sample: -------------------------------------------------------------------------------- 1 | NODE_ENV=development 2 | PORT=8085 3 | VUE_APP_BASEURL=/api 4 | VUE_APP_GRAPHQL=/api/graphql 5 | VUE_APP_SOCKETIO=/ 6 | VUE_APP_FACEBOOK=555555555555555 7 | VUE_APP_STRIPE=pk_test_hGaa6lIOnbf33Dn11oesX2xA 8 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gcr.io/coinos-326717/github.com/coinos/coinos-classic:base 2 | 3 | ARG NODE_ENV=production 4 | ENV NODE_ENV $NODE_ENV 5 | 6 | WORKDIR /app 7 | COPY . . 8 | RUN mv /deps/node_modules /app 9 | RUN pnpm build 10 | -------------------------------------------------------------------------------- /tests/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // https://docs.cypress.io/api/introduction/api.html 2 | 3 | describe('My First Test', () => { 4 | it('Visits the app root url', () => { 5 | cy.visit('/'); 6 | cy.contains('h1', 'Welcome to Your Vue.js App'); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .env 3 | yarn-error.log 4 | .pnp* 5 | .yarn* 6 | tls.* 7 | leveldb 8 | swaps 9 | exceptions 10 | fx 11 | uploads 12 | verified 13 | data 14 | lnurl-server.sqlite3 15 | watcher.log 16 | mysql 17 | config/bitcoin 18 | config/liquid 19 | config/lightning 20 | -------------------------------------------------------------------------------- /public/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #da532c 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/restrictedPaths.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | '/', 3 | '/asset', 4 | '/decrypt', 5 | '/home', 6 | '/logout', 7 | '/payments', 8 | '/receive', 9 | '/scan', 10 | '/send', 11 | '/settings', 12 | '/sweep', 13 | '/text', 14 | '/pay', 15 | '/propose', 16 | '/wallets', 17 | '/withdraw', 18 | ]; 19 | -------------------------------------------------------------------------------- /public/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://classic.coinos.io/ 5 | 2024-03-07 6 | monthly 7 | 0.1 8 | 9 | 10 | -------------------------------------------------------------------------------- /Dockerfile.dev: -------------------------------------------------------------------------------- 1 | FROM node:17-alpine 2 | 3 | ARG NODE_ENV=production 4 | ENV NODE_ENV $NODE_ENV 5 | 6 | ENV NODE_OPTIONS --openssl-legacy-provider 7 | 8 | RUN apk add git python3 9 | RUN npm i -g pnpm 10 | 11 | WORKDIR /app 12 | 13 | COPY package.json . 14 | RUN pnpm i 15 | 16 | COPY . . 17 | RUN pnpm i 18 | 19 | CMD ["pnpm", "start"] 20 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true, 5 | }, 6 | globals: { 7 | cordova: true, 8 | }, 9 | extends: ['plugin:vue/essential'], 10 | rules: { 11 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 12 | }, 13 | parserOptions: { 14 | parser: 'babel-eslint', 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /git_hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | FILES=$(git diff --cached --name-only --diff-filter=ACMR | sed 's| |\\ |g') 3 | [ -z "$FILES" ] && exit 0 4 | 5 | # Prettify all selected files 6 | echo "$FILES" | xargs ./node_modules/.bin/prettier --ignore-unknown --write 7 | 8 | # Add back the modified/prettified files to staging 9 | echo "$FILES" | xargs git add 10 | 11 | exit 0 12 | -------------------------------------------------------------------------------- /src/components/Tor.vue: -------------------------------------------------------------------------------- 1 | 2 | 10 | -------------------------------------------------------------------------------- /src/components/PrivacyPolicy.vue: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "coinos", 3 | "name": "coinos", 4 | "icons": [ 5 | { 6 | "src": "/coinos.webp", 7 | "type": "image/webp", 8 | "sizes": "1024x1024", 9 | "purpose": "any maskable" 10 | } 11 | ], 12 | "start_url": "/", 13 | "background_color": "#000000", 14 | "display": "standalone", 15 | "scope": "/", 16 | "theme_color": "#000000" 17 | } 18 | -------------------------------------------------------------------------------- /src/window.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | 3 | const Window = new Vue({ 4 | data() { 5 | return { 6 | prompt: null, 7 | }; 8 | }, 9 | created() { 10 | window.addEventListener('beforeinstallprompt', e => { 11 | if (!window.matchMedia('(display-mode: standalone)').matches) { 12 | this.prompt = e; 13 | } 14 | }); 15 | }, 16 | }); 17 | 18 | export default Window; 19 | -------------------------------------------------------------------------------- /.env.staging: -------------------------------------------------------------------------------- 1 | NODE_ENV=production 2 | VUE_APP_LBTC=5ac9f65c0efcc4775e0baec4ec03abdde22473cd3cf33c0419ca290e0751b225 3 | VUE_APP_LCAD=e749f7326d0ba155ec1d878e23458bc3f740a38bf91bbce955945ee10d6ab523 4 | VUE_APP_VAPID_PUBKEY=BAYPri863liuj7SMk536eOXWvfFwzJNgjheVe_C-HOM8pjX6gmRXUAMH5SXYZvDtnU4p3uQLUFTHU7fBR0kLYJQ 5 | VUE_APP_VERSION=3b96359d6a6ce68fe4a32f495fc9a6f78af0aa63 6 | VUE_APP_COINTYPE=regtest 7 | VUE_APP_NETWORK_BECH32=bcrt 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | /tests/e2e/videos/ 6 | /tests/e2e/screenshots/ 7 | 8 | # local env files 9 | .env.local 10 | .env.*.local 11 | 12 | # Log files 13 | npm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | 17 | # Editor directories and files 18 | .idea 19 | .vscode 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | cordova 26 | bump.sh 27 | deploy.sh 28 | stage.sh 29 | .yarn* 30 | .pnpm* 31 | -------------------------------------------------------------------------------- /tests/unit/example.spec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { shallowMount } from '@vue/test-utils'; 3 | import HelloWorld from '@/components/HelloWorld.vue'; 4 | 5 | describe('HelloWorld.vue', () => { 6 | it('renders props.msg when passed', () => { 7 | const msg = 'new message'; 8 | const wrapper = shallowMount(HelloWorld, { 9 | propsData: { msg }, 10 | }); 11 | expect(wrapper.text()).to.include(msg); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /src/components/Confirm.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 21 | 22 | -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | NODE_ENV=production 2 | VUE_APP_LBTC=6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d 3 | VUE_APP_LCAD=a0a3925bca98f2b1f28d0ca9031dd3b8073884fe8884e5b458ce9819f235899f 4 | VUE_APP_USDT=ce091c998b83c78bb71a632313ba3760f1763d9cfcffae02258ffa9865a37bd2 5 | VUE_APP_EUR=366fabc27dba6bad636717b33a535084bc822e8a90976be2c87f886a6182f3c5 6 | VUE_APP_VAPID_PUBKEY=BAYPri863liuj7SMk536eOXWvfFwzJNgjheVe_C-HOM8pjX6gmRXUAMH5SXYZvDtnU4p3uQLUFTHU7fBR0kLYJQ 7 | VUE_APP_VERSION=b2cd8d7f1d7035e3aa47745e9c523bf0e364428a 8 | VUE_APP_NETWORK_BECH32=bc 9 | -------------------------------------------------------------------------------- /src/mixins/Copy.vue: -------------------------------------------------------------------------------- 1 | 25 | -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | NODE_ENV=development 2 | PORT=8085 3 | VUE_APP_FACEBOOK=290368338058652 4 | VUE_APP_LBTC=5ac9f65c0efcc4775e0baec4ec03abdde22473cd3cf33c0419ca290e0751b225 5 | VUE_APP_LCAD=e749f7326d0ba155ec1d878e23458bc3f740a38bf91bbce955945ee10d6ab523 6 | VUE_APP_USDT=4dddd1d0d0beeaee17df7722b512906cc5bc660c81225083b72b05820ecd3d91 7 | VUE_APP_EUR=35faa1ff38ccba0dec676284186a00a7f99e8acf9aa9d918d9d14bd2c968a6ba 8 | VUE_APP_VAPID_PUBKEY=BAYPri863liuj7SMk536eOXWvfFwzJNgjheVe_C-HOM8pjX6gmRXUAMH5SXYZvDtnU4p3uQLUFTHU7fBR0kLYJQ 9 | VUE_APP_VERSION=3b96359d6a6ce68fe4a32f495fc9a6f78af0aa63 10 | VUE_APP_NETWORK_BECH32=bcrt 11 | -------------------------------------------------------------------------------- /src/assets/canada.svg: -------------------------------------------------------------------------------- 1 | 2 | maple leaf from the flag of Canada 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/icons/Canada.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /src/components/NetworkIcon.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /public/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.14, written by Peter Selinger 2001-2017 9 | 10 | 12 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/components/Accept.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 35 | -------------------------------------------------------------------------------- /tests/e2e/support/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands'; 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | -------------------------------------------------------------------------------- /src/format.js: -------------------------------------------------------------------------------- 1 | export default function(n, p) { 2 | if (!parseInt(p)) return parseInt(n).toFixed(0); 3 | else { 4 | let x = n / 10 ** p; 5 | if (Math.abs(x) < 1.0) { 6 | let e = parseInt(x.toString().split('e-')[1]); 7 | if (e) { 8 | x *= Math.pow(10, e); 9 | if (x.toString().indexOf('.') > -1) 10 | x = x.toString().replace('.', ''); 11 | x = '0.' + new Array(e).join('0') + x; 12 | } 13 | } else { 14 | let e = parseInt(x.toString().split('+')[1]); 15 | if (e > 20) { 16 | e -= 20; 17 | x /= Math.pow(10, e); 18 | x += new Array(e + 1).join('0'); 19 | } 20 | } 21 | if (x.toString().split('.')[1] > p && x.toFixed) return parseFloat(x.toFixed(p)).toString(); 22 | return x; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/components/InvoiceCustomerControls.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 31 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import VueAxios from 'vue-axios'; 3 | import VueMeta from 'vue-meta' 4 | import Axios from 'axios'; 5 | import App from './App'; 6 | import router from './router'; 7 | import store from './store'; 8 | import FastClick from 'fastclick'; 9 | import coinos from './plugins/coinos'; 10 | import vuetify from './plugins/vuetify'; 11 | 12 | Axios.defaults.baseURL = '/api'; 13 | 14 | Vue.use(VueAxios, Axios); 15 | Vue.use(coinos); 16 | Vue.use(VueMeta, { keyName: 'head' }) 17 | 18 | const app = new Vue({ 19 | render: h => h(App), 20 | router, 21 | vuetify, 22 | store, 23 | }).$mount('#app'); 24 | 25 | if ('addEventListener' in document) { 26 | document.addEventListener( 27 | 'DOMContentLoaded', 28 | async function() { 29 | FastClick.attach(document.body); 30 | }, 31 | false 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /src/components/Social.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 33 | -------------------------------------------------------------------------------- /src/components/Text.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 38 | -------------------------------------------------------------------------------- /src/components/PaymentDetails.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 39 | -------------------------------------------------------------------------------- /tests/e2e/support/commands.js: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | // 11 | // 12 | // -- This is a parent command -- 13 | // Cypress.Commands.add("login", (email, password) => { ... }) 14 | // 15 | // 16 | // -- This is a child command -- 17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 18 | // 19 | // 20 | // -- This is a dual command -- 21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 22 | // 23 | // 24 | // -- This is will overwrite an existing command -- 25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 26 | -------------------------------------------------------------------------------- /src/mixins/DynamicLoad.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Deposit.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 39 | -------------------------------------------------------------------------------- /src/plugins/coinos.js: -------------------------------------------------------------------------------- 1 | import format from '../format'; 2 | import { networks } from 'bitcoinjs-lib'; 3 | import { networks as lqnetworks } from 'liquidjs-lib'; 4 | 5 | const Coinos = { 6 | install(Vue, options) { 7 | (Vue.prototype.$format = function (n, p) { 8 | if (p === undefined) 9 | p = this.user.unit === 'SAT' ? 0 : this.user.account.precision; 10 | return format(n, p); 11 | }), 12 | (Vue.prototype.$go = function (path) { 13 | this.$router 14 | .push(path) 15 | .then() 16 | .catch(() => {}); 17 | }), 18 | (Vue.prototype.$network = 19 | process.env.NODE_ENV === 'production' 20 | ? networks['bitcoin'] 21 | : networks['regtest']), 22 | (Vue.prototype.$lqnetwork = 23 | process.env.NODE_ENV === 'production' 24 | ? lqnetworks['liquid'] 25 | : lqnetworks['regtest']), 26 | (Vue.prototype.$prod = process.env.NODE_ENV === 'production'); 27 | (Vue.prototype.$conversion = 1000); 28 | }, 29 | }; 30 | 31 | export default Coinos; 32 | -------------------------------------------------------------------------------- /src/components/Lnurl.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /public/service-worker.js: -------------------------------------------------------------------------------- 1 | self.addEventListener('install', function(event) { 2 | event.waitUntil( 3 | caches.open('sw-cache').then(function(cache) { 4 | return cache.add('index.html'); 5 | }) 6 | ); 7 | }); 8 | 9 | self.addEventListener('push', function(e) { 10 | const payload = e.data ? e.data.text() : ''; 11 | var options = { 12 | body: payload, 13 | badge: '/badge.png', 14 | icon: '/coinos.webp', 15 | }; 16 | e.waitUntil(self.registration.showNotification('coinos', options)); 17 | }); 18 | 19 | self.addEventListener('notificationclick', function(event) { 20 | console.log('On notification click: ', event.notification.tag); 21 | event.notification.close(); 22 | 23 | // This looks to see if the current is already open and 24 | // focuses if it is 25 | event.waitUntil( 26 | clients 27 | .matchAll({ 28 | type: 'window', 29 | }) 30 | .then(function(clientList) { 31 | for (var i = 0; i < clientList.length; i++) { 32 | var client = clientList[i]; 33 | if ('focus' in client) return client.focus(); 34 | } 35 | if (clients.openWindow) return clients.openWindow('/'); 36 | }) 37 | ); 38 | }); 39 | -------------------------------------------------------------------------------- /src/components/SendToUser.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 49 | 50 | 53 | -------------------------------------------------------------------------------- /src/mixins/FullScreen.vue: -------------------------------------------------------------------------------- 1 | 42 | -------------------------------------------------------------------------------- /src/components/TwoFa.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 51 | -------------------------------------------------------------------------------- /src/components/Methods.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # coinos 2 | 3 | Coinos is a bitcoin wallet app that supports payments over the bitcoin, liquid and lightning networks. Try it out at coinos.io. 4 | 5 | This repository contains the code for the frontend user interface which is a progressive web application built with VueJS. If you intend to run it yourself you'll also need to host an instance of coinos-server which provides a REST/Websocket API and interfaces with bitcoind, elementsd, and lnd. 6 | 7 | ## Getting Started 8 | 9 | git clone https://github.com/coinos/coinos-ui 10 | cd coinos-ui 11 | yarn 12 | yarn start 13 | 14 | ### Setup pre-commit git hooks 15 | 16 | We have a pre-commit git hook for running prettier on all files to keep the formatting consistent. 17 | 18 | `git config core.hooksPath "./git_hooks"` - This will set the git config path to use this directory for hooks. 19 | 20 | `chmod +x ./git_hooks/pre-commit` - This will give the hook the necessary permissions to run. 21 | -------------------------------------------------------------------------------- /src/components/MarketConflict.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 53 | -------------------------------------------------------------------------------- /src/components/WithdrawUrl.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 55 | -------------------------------------------------------------------------------- /src/assets/bitcoin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/components/BottomNav.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 47 | 48 | 56 | -------------------------------------------------------------------------------- /src/components/SnackBar.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 57 | 58 | 63 | -------------------------------------------------------------------------------- /src/components/Recipient.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 58 | -------------------------------------------------------------------------------- /src/icons/Bitcoin.vue: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /src/components/Decrypt.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 63 | -------------------------------------------------------------------------------- /src/components/Seed.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 57 | -------------------------------------------------------------------------------- /src/components/Home.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 60 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 40 | 41 | 42 |
43 | 44 | 45 | -------------------------------------------------------------------------------- /src/components/Password.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 74 | -------------------------------------------------------------------------------- /src/components/Pin.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 74 | 75 | 79 | -------------------------------------------------------------------------------- /src/components/Withdraw.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 72 | -------------------------------------------------------------------------------- /src/components/Qr.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 75 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development'; 2 | const IS_PRODUCTION = !['development', 'test'].includes(process.env.NODE_ENV); 3 | 4 | module.exports = IS_PRODUCTION 5 | ? { 6 | configureWebpack: { 7 | resolve: { aliasFields: ['browser', 'browser.esm'] } 8 | }, 9 | pluginOptions: { 10 | webpackBundleAnalyzer: { 11 | openAnalyzer: false, 12 | }, 13 | }, 14 | chainWebpack: config => { 15 | config.module 16 | .rule('vue') 17 | .use('vue-loader') 18 | .loader('vue-loader') 19 | .tap(options => { 20 | // modify the options... 21 | options.compilerOptions.whitespace = 'preserve'; 22 | return options; 23 | }); 24 | }, 25 | } 26 | : { 27 | configureWebpack: { 28 | resolve: { aliasFields: ['browser', 'browser.esm'] } 29 | }, 30 | pluginOptions: { 31 | webpackBundleAnalyzer: { 32 | analyzerMode: 'disabled', 33 | }, 34 | }, 35 | runtimeCompiler: true, 36 | chainWebpack: config => { 37 | config.module 38 | .rule('vue') 39 | .use('vue-loader') 40 | .loader('vue-loader') 41 | .tap(options => { 42 | // modify the options... 43 | options.compilerOptions.whitespace = 'preserve'; 44 | return options; 45 | }); 46 | }, 47 | devServer: { 48 | host: '0.0.0.0', 49 | disableHostCheck: true, 50 | proxy: { 51 | '/api/electrs': { 52 | target: 'http://electrsb:3095', 53 | pathRewrite: { '^/api/electrs': '' }, 54 | secure: false, 55 | }, 56 | '/lnurl': { 57 | target: 'http://app:3118', 58 | secure: false, 59 | }, 60 | '/api': { 61 | target: 'http://app:3119', 62 | pathRewrite: { '^/api': '' }, 63 | secure: false, 64 | }, 65 | '/ws': { 66 | target: 'http://app:3119', 67 | ws: true, 68 | }, 69 | }, 70 | }, 71 | }; 72 | -------------------------------------------------------------------------------- /src/config/index.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | provinces: [ 4 | { 5 | text: 'Alberta', 6 | value: 'AB', 7 | }, 8 | { 9 | text: 'British Columbia', 10 | value: 'BC', 11 | }, 12 | { 13 | text: 'Manitoba', 14 | value: 'MB', 15 | }, 16 | { 17 | text: 'New Brunswick', 18 | value: 'NB', 19 | }, 20 | { 21 | text: 'Newfoundland and Labrador', 22 | value: 'NL', 23 | }, 24 | { 25 | text: 'Northwest Territories', 26 | value: 'NT', 27 | }, 28 | { 29 | text: 'Nova Scotia', 30 | value: 'NS', 31 | }, 32 | { 33 | text: 'Nunavut', 34 | value: 'NU', 35 | }, 36 | { 37 | text: 'Ontario', 38 | value: 'ON', 39 | }, 40 | { 41 | text: 'Prince Edward Island', 42 | value: 'PE', 43 | }, 44 | { 45 | text: 'Quebec', 46 | value: 'QC', 47 | }, 48 | { 49 | text: 'Saskatchewan', 50 | value: 'SK', 51 | }, 52 | { 53 | text: 'Yukon Territory', 54 | value: 'YT', 55 | } 56 | ], 57 | 58 | rules: { 59 | email: [ 60 | v => !!v || 'Email is required', 61 | v => /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/.test(v) || 'E-mail must be valid' 62 | ], 63 | NAPhone: [ 64 | v => !v || /^(\+?1 |)\(\d\d\d\) \d\d\d\-\d\d\d\d$/.test(v) || 'Phone must be valid and include area code' 65 | ], 66 | internationalPhone: [ 67 | v => !v || /^\+\d+ [\d\s\-\(\)]{5,15}$/.test(v) || 'Phone must be valid and include country and area code' 68 | ], 69 | phone: [ 70 | v => !v || /^(\+\d+ |)\(?\d\d\d(\) | |-)\d\d\d(\-| )\d\d\d\d$/.test(v) || 'phone must include area code eg 604 123-4567' 71 | ], 72 | username: [ 73 | v => !!v || 'Name is required', 74 | v => v && v.length >= 3 && v.length <= 32 || 'Name must be between 3 and 32 characters', 75 | v => /^[a-zA-Z0-9]+$/.test(v) || 'Name may only contain alphanumeric characters' 76 | ], 77 | password: [ 78 | v => !!v || 'Password is required', 79 | v => v && v.length >= 8 || 'Password must be at least 8 characters' 80 | ] 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/components/SetFee.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | 84 | -------------------------------------------------------------------------------- /src/components/Voucher.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | 82 | -------------------------------------------------------------------------------- /src/components/Asset.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | 82 | -------------------------------------------------------------------------------- /src/components/Register.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 82 | -------------------------------------------------------------------------------- /src/components/Send.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 91 | 92 | 98 | -------------------------------------------------------------------------------- /src/components/LastTrades.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 78 | -------------------------------------------------------------------------------- /src/components/Support.vue: -------------------------------------------------------------------------------- 1 | 49 | 50 | 81 | -------------------------------------------------------------------------------- /src/assets/liquid.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | Created with Sketch. 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | 30 | 31 | 34 | 35 | 36 | 37 | 38 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/components/Orders.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 76 | 77 | 85 | -------------------------------------------------------------------------------- /src/components/LinkingKeys.vue: -------------------------------------------------------------------------------- 1 | 49 | 50 | 82 | -------------------------------------------------------------------------------- /public/coinos.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 56 | coinos 73 | 74 | 75 | -------------------------------------------------------------------------------- /src/components/Pay.vue: -------------------------------------------------------------------------------- 1 | 46 | 47 | 90 | -------------------------------------------------------------------------------- /src/components/Faucet.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 91 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "coinos.io", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service build --report", 8 | "buildtor": "vue-cli-service build --mode tor", 9 | "stage": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service build --mode staging", 10 | "dev": "vue-cli-service build --mode development", 11 | "lint": "vue-cli-service lint", 12 | "format": "prettier --write '**/*.{js,mjs,json,vue,gql}'", 13 | "start": "npm run serve" 14 | }, 15 | "dependencies": { 16 | "aes-js": "^3.1.2", 17 | "axios": "^0.19.0", 18 | "bech32": "^1.1.3", 19 | "bip21": "^2.0.2", 20 | "bip32": "^2.0.5", 21 | "bip38": "^3.1.0", 22 | "bip39": "^3.0.2", 23 | "bip84": "^0.2.2", 24 | "bitcoin-address-validation": "^2.1.1", 25 | "bitcoinjs-lib": "^5.1.10", 26 | "bolt11": "^1.2.6", 27 | "core-js": "^2.6.9", 28 | "crypto-js": "^4.0.0", 29 | "date-fns": "^2.26.0", 30 | "ecpair": "^2.0.1", 31 | "fast-sha256": "^1.3.0", 32 | "fastclick": "^1.0.6", 33 | "gsap": "^2.1.3", 34 | "js-lnurl": "^0.2.2", 35 | "jsqr": "^1.3.1", 36 | "liquidjs-lib": "^5.2.3", 37 | "prettier": "^2.3.0", 38 | "qrcode": "^1.3.4", 39 | "secp256k1": "^4.0.1", 40 | "setimmediate": "^1.0.5", 41 | "slip77": "^0.1.1", 42 | "tiny-secp256k1": "^2.1.2", 43 | "uuid": "^8.3.0", 44 | "vue": "^2.6.14", 45 | "vue-axios": "^2.1.4", 46 | "vue-material-design-icons": "^3.3.1", 47 | "vue-meta": "^2.4.0", 48 | "vue-pincode-input": "^0.0.4", 49 | "vue-router": "^3.0.7", 50 | "vue-scrollto": "^2.17.1", 51 | "vuetify": "^2.6.0", 52 | "vuex": "^3.1.1", 53 | "vuex-pathify": "^1.2.4", 54 | "vuex-persist": "^3.1.3", 55 | "wif": "^2.0.6" 56 | }, 57 | "devDependencies": { 58 | "@mdi/font": "^4.4.95", 59 | "@prettier/plugin-pug": "^1.15.2", 60 | "@vue/cli-plugin-babel": "^3.9.0", 61 | "@vue/cli-plugin-eslint": "^3.9.1", 62 | "@vue/cli-plugin-unit-mocha": "^3.9.0", 63 | "@vue/cli-service": "^4.1.2", 64 | "@vue/eslint-config-prettier": "^4.0.1", 65 | "@vue/test-utils": "1.0.0-beta.29", 66 | "autoprefixer": "^9.0.0", 67 | "babel-eslint": "^10.0.2", 68 | "chai": "^4.2.0", 69 | "eslint": "6", 70 | "eslint-loader": "^3.0.3", 71 | "eslint-plugin-vue": "^6.1.2", 72 | "postcss": "8", 73 | "pug": "^3.0.2", 74 | "pug-plain-loader": "^1.1.0", 75 | "sass": "^1.17.4", 76 | "sass-loader": "^8.0.2", 77 | "stylus": "^0.54.5", 78 | "stylus-loader": "^3.0.2", 79 | "vue-cli-plugin-vuetify": "^0.6.3", 80 | "vue-cli-plugin-webpack-bundle-analyzer": "~2.0.0", 81 | "vue-loader": "^15.9.8", 82 | "vue-template-compiler": "^2.6.10", 83 | "vuetify-loader": "^1.6.0", 84 | "webpack": "^4" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/icons/Liquid.vue: -------------------------------------------------------------------------------- 1 | 71 | 72 | 73 | 81 | -------------------------------------------------------------------------------- /src/components/CurrencyList.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 100 | -------------------------------------------------------------------------------- /src/components/Scan.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 112 | -------------------------------------------------------------------------------- /src/components/Documents.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 101 | -------------------------------------------------------------------------------- /src/components/To.vue: -------------------------------------------------------------------------------- 1 | 59 | 60 | 106 | 107 | 118 | -------------------------------------------------------------------------------- /src/components/Info.vue: -------------------------------------------------------------------------------- 1 | 55 | 56 | 89 | 90 | 102 | -------------------------------------------------------------------------------- /src/components/User.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 110 | -------------------------------------------------------------------------------- /src/components/MarketList.vue: -------------------------------------------------------------------------------- 1 | 51 | 52 | 100 | -------------------------------------------------------------------------------- /src/components/Proposal.vue: -------------------------------------------------------------------------------- 1 | 48 | 49 | 115 | -------------------------------------------------------------------------------- /src/components/OrderBook.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 93 | 94 | 115 | -------------------------------------------------------------------------------- /src/components/LightningNode.vue: -------------------------------------------------------------------------------- 1 | 65 | 66 | 112 | 113 | 119 | -------------------------------------------------------------------------------- /src/components/Received.vue: -------------------------------------------------------------------------------- 1 | 48 | 49 | 113 | -------------------------------------------------------------------------------- /src/components/Redeem.vue: -------------------------------------------------------------------------------- 1 | 70 | 71 | 116 | -------------------------------------------------------------------------------- /src/mixins/CustomSequelize.vue: -------------------------------------------------------------------------------- 1 | 98 | -------------------------------------------------------------------------------- /src/components/InvoiceBalance.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 112 | 113 | 119 | -------------------------------------------------------------------------------- /src/components/Sent.vue: -------------------------------------------------------------------------------- 1 | 88 | 89 | 141 | -------------------------------------------------------------------------------- /src/components/Receive.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 138 | -------------------------------------------------------------------------------- /src/components/TipPad.vue: -------------------------------------------------------------------------------- 1 | 71 | 72 | 149 | 150 | 158 | -------------------------------------------------------------------------------- /src/components/Swaps.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 157 | 158 | 163 | 164 | -------------------------------------------------------------------------------- /src/components/Balance.vue: -------------------------------------------------------------------------------- 1 | 46 | 47 | 169 | -------------------------------------------------------------------------------- /src/icons/Interac.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/components/LightningPayment.vue: -------------------------------------------------------------------------------- 1 | 68 | 69 | 144 | 145 | 169 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 118 | 119 | 206 | -------------------------------------------------------------------------------- /src/components/Login.vue: -------------------------------------------------------------------------------- 1 | 86 | 87 | 174 | 175 | 182 | -------------------------------------------------------------------------------- /src/components/Paper.vue: -------------------------------------------------------------------------------- 1 | 88 | 89 | 171 | -------------------------------------------------------------------------------- /src/components/SetPin.vue: -------------------------------------------------------------------------------- 1 | 80 | 81 | 183 | 184 | 188 | -------------------------------------------------------------------------------- /src/components/About.vue: -------------------------------------------------------------------------------- 1 | 128 | 129 | 148 | 149 | 156 | --------------------------------------------------------------------------------