├── .gitignore
├── .postcssrc.js
├── BUILDING.md
├── LICENSE
├── README.md
├── RELEASING.md
├── babel.config.js
├── bin
└── .gitkeep
├── build
├── download-binaries.js
├── entitlements.mac.plist
└── notarize.js
├── jsconfig.json
├── oldquasar.babelrc-old
├── package-lock.json
├── package.json
├── public
├── icon_512x512.png
├── qr-code-grey.svg
├── qr-code.svg
├── ryo-wallet.svg
└── scala.svg
├── quasar.conf.js
├── src-electron
├── build
│ ├── mosu_forge
│ └── scala-dmg.tiff
├── electron-flag.d.ts
├── icons
│ ├── icon.icns
│ ├── icon.ico
│ ├── icon_512x512.png
│ ├── linux-512x512.png
│ ├── macos-512x512.png
│ └── mrcuug.PNG
└── main-process
│ ├── auto-updater.js
│ ├── electron-main.dev.js
│ ├── electron-main.js
│ ├── menu.js
│ └── modules
│ ├── SCEE-Node.js
│ ├── backend.js
│ ├── daemon.js
│ ├── status-codes.js
│ └── wallet-rpc.js
└── src
├── App.vue
├── boot
├── .gitkeep
├── axios.js
├── gateway.js
├── i18n.js
├── timeago.js
└── vuelidate.js
├── components
├── .gitkeep
├── address_book_details.vue
├── address_details.vue
├── address_header.vue
├── check_transaction.vue
├── footer.vue
├── format_scala.vue
├── icons
│ └── copy_icon.vue
├── identicon.vue
├── language_select.vue
├── lns_input.vue
├── lns_input_form.vue
├── lns_record_list.vue
├── mainmenu.vue
├── prove_transaction.vue
├── receive_item.vue
├── scala_field.vue
├── service_node_details.vue
├── service_node_registration.vue
├── service_node_staking.vue
├── service_node_unlock.vue
├── settings.vue
├── settings_general.vue
├── tx_details.vue
├── tx_list.vue
├── tx_type_icon.vue
├── wallet_details.vue
└── wallet_settings.vue
├── css
├── app.styl
├── app_backup.styl
├── quasar.variables.styl
└── themes
│ ├── RobotoMono-Light.ttf
│ ├── common.variables.styl
│ ├── variables.ios.styl
│ └── variables.mat.styl
├── gateway
├── SCEE-Node.js
└── gateway.js
├── i18n
├── de.js
├── en-us.js
├── es.js
├── fr.js
├── index.js
├── pt-br.js
└── ru.js
├── index.template.html
├── layouts
├── init
│ ├── loading.vue
│ └── welcome.vue
├── wallet-select
│ └── main.vue
└── wallet
│ └── main.vue
├── mixins
└── wallet_password.js
├── pages
├── 404.vue
├── init
│ ├── index.vue
│ ├── quit.vue
│ └── welcome.vue
├── wallet-select
│ ├── create.vue
│ ├── created.vue
│ ├── import-legacy.vue
│ ├── import-old-gui.vue
│ ├── import-view-only.vue
│ ├── import.vue
│ ├── index.vue
│ └── restore.vue
└── wallet
│ ├── addressbook.vue
│ ├── advanced.vue
│ ├── blank.vue
│ ├── lns.vue
│ ├── receive.vue
│ ├── send.vue
│ ├── service-node.vue
│ └── txhistory.vue
├── plugins
├── .gitkeep
├── axios.js
├── gateway.js
├── i18n.js
├── timeago.js
└── vuelidate.js
├── router
├── index.js
└── routes.js
├── statics
├── icon_512x512.png
├── qr-code-grey.svg
├── qr-code.svg
├── ryo-wallet.svg
└── scala.svg
├── store
├── gateway
│ ├── actions.js
│ ├── getters.js
│ ├── index.js
│ ├── mutations.js
│ └── state.js
├── index.js
└── store-flag.d.ts
└── validators
├── address_tools.js
└── common.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .quasar
2 | .DS_Store
3 | .thumbs.db
4 | node_modules
5 | /dist
6 | /src-cordova/platforms
7 | /src-cordova/plugins
8 | /src-cordova/www
9 | npm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 |
13 | # Editor directories and files
14 | .idea
15 | .vscode
16 | *.suo
17 | *.ntvs*
18 | *.njsproj
19 | *.sln
20 | *~
21 | \#*\#
22 | .\#*
23 | *.bak
24 |
25 | # bin dir
26 | bin/*
27 | !bin/.gitkeep
28 |
29 | .env
30 |
--------------------------------------------------------------------------------
/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | plugins: [
5 | // to edit target browsers: use "browserslist" field in package.json
6 | require("autoprefixer")
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/BUILDING.md:
--------------------------------------------------------------------------------
1 | # Building
2 |
3 | Building scala electron wallet binaries is done using github actions. Windows and linux binaries will build right out of the box but there are some extra steps needed for Mac OS
4 |
5 | ## Mac OS
6 |
7 | The build script for Mac OS requires you to have a valid `Developer ID Application` certificate. Without this the build script cannot sign and notarize the mac binary which is needed for Catalina 10.15 and above.
8 | If you would like to disable this then comment out `"afterSign": "build/notarize.js",` in package.json.
9 |
10 | You will also need an [App-specific password](https://support.apple.com/en-al/HT204397) for the apple account you wish to notarize with
11 |
12 | ### Setup
13 |
14 | Once you have your `Developer ID Application` you need to export it into a `.p12` file. Keep a note of the password used to encrypt this file as it will be needed later.
15 |
16 | We need to Base64 encode this file, so run the following command:
17 |
18 | ```
19 | base64 -i certificate.p12 -o encoded.txt
20 | ```
21 |
22 | #### On GitHub:
23 |
24 | 1. Navigate to the main page of the repository.
25 | 2. Under your repository name, click **Settings**.
26 | 3. In the left sidebar, click **Secrets**.
27 | 4. Add the following secrets:
28 | 1. Certificate
29 | - Name: `MAC_CERTIFICATE`
30 | - Value: The encoded Base64 certificate
31 | 2. Certificate password
32 | - Name: `MAC_CERTIFICATE_PASSWORD`
33 | - Value: The password that was set when the certificate was exported.
34 | 3. Apple ID
35 | - Name: `SIGNING_APPLE_ID`
36 | - Value: The apple id (email) to use for signing
37 | 4. Apple Password
38 | - Name: `SIGNING_APP_PASSWORD`
39 | - Value: The app-specific password that was generated for the apple id
40 | 5. Team ID (Optional)
41 | - Name: `SIGNING_TEAM_ID`
42 | - Value: The apple team id if you're sigining the application for a team
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD-3
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions are met:
5 |
6 | 1. Redistributions of source code must retain the above copyright notice, this
7 | list of conditions and the following disclaimer.
8 |
9 | 2. Redistributions in binary form must reproduce the above copyright notice,
10 | this list of conditions and the following disclaimer in the documentation
11 | and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its contributors
14 | may be used to endorse or promote products derived from this software without
15 | specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
28 | ----------------------------------------------------------------------------------------
29 |
30 | BSD-licensed version of the code can be found at:
31 |
32 | https://github.com/monero-project/monero/tree/e2c39f6b59fcf5c623c814dfefc518ab0b7eca32
33 | https://github.com/ryo-currency/ryo-emergency/tree/9d1f51c453978badad21b2feaca2f4348ab26bfa
34 |
35 | Portions of this wallet have been released by the RYO wallet developers into public domain, we are thankful for their contributions
36 |
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # :warning: Repository Archived :warning:
2 |
3 | **Note**: This repository has been archived. The new repository for the Scala Electron GUI wallet can be found at [Scala GUI](https://github.com/scala-network/scala-gui). Please refer to the new repository for the latest updates and developments.
4 |
5 | ---
6 |
7 | # Scala Electron GUI Wallet
8 |
9 | 
10 |
11 | ### Introduction
12 | Scala is a private cryptocurrency based on Monero. Scala aims to provide everyone the ability to mine and transact with ease and security.
13 | More information on the project can be found on the [website](https://scalaproject.io).
14 |
15 | ### About this project
16 |
17 | This is the new electron GUI for Scala. It is open source and completely free to use without restrictions, anyone may create an alternative implementation of the Scala Electron GUI that uses the protocol and network in a compatible manner.
18 | Please submit any changes as pull requests to the development branch, all changes are assessed in the development branch before being merged to master, release tags are considered stable builds for the GUI.
19 |
20 | #### Pre-requisites
21 | - Download latest [Scalad](https://github.com/scala-network/scala/releases/latest)
22 |
23 | #### Build instructions
24 | ```
25 | nvm use 11.9.0
26 | npm install -g quasar-cli
27 | https://github.com/scala-network/scala-electron-gui/
28 | cd scala-electron-gui
29 | cp path_to_scala_binaries/scalad bin/
30 | cp path_to_scala_binaries/scala-wallet-rpc bin/
31 | npm install
32 | ```
33 |
34 | For dev:
35 | ```
36 | npm run dev
37 | ```
38 |
39 | For building:
40 |
41 | **Note:** This will only build the binaries for the system you run the command on. Running this command on `linux` will only make `linux` binaries, no `mac` or `windows` binaries.
42 | ```
43 | npm run build
44 | ```
--------------------------------------------------------------------------------
/RELEASING.md:
--------------------------------------------------------------------------------
1 | # Releasing
2 |
3 | Releasing the application to work with auto update is very simple.
4 |
5 | 1. Increment the application version in `package.json`.
6 | 2. Push changes to master to trigger github actions to build the binaries.
7 | - Ensure that `.yml` files aren't being left out in the artifacts. These are needed for auto-update to work correctly.
8 | 3. Create a github release with the **tag** being in the format `v[Version]`.
9 | - E.g if the version was `2.1.1` then the github tag would be `v2.1.1`
10 | 4. Add release notes
11 | 5. Publish the release!
12 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@quasar/babel-preset-app"]
3 | };
4 |
--------------------------------------------------------------------------------
/bin/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-network/scala-electron-gui/1eea8a5ab48541e4c6c0333316b85e18953d7f29/bin/.gitkeep
--------------------------------------------------------------------------------
/build/download-binaries.js:
--------------------------------------------------------------------------------
1 | const axios = require("axios").default;
2 | const fs = require("fs-extra");
3 | const path = require("path");
4 |
5 | async function download() {
6 | const { platform, env } = process;
7 | const repoUrl = "https://api.github.com/repos/scala-project/scala/releases/latest";
8 | try {
9 | const pwd = process.cwd();
10 | const downloadDir = path.join(pwd, "downloads");
11 | await fs.ensureDir(downloadDir);
12 |
13 | const headers = {
14 | "Content-Type": "application/json",
15 | "User-Agent": "Scala-Electron-Wallet"
16 | };
17 | if (env.GH_TOKEN) {
18 | headers.Authorisation = `Bearer ${env.GH_TOKEN}`;
19 | }
20 |
21 | const { data } = await axios.get(repoUrl, { headers });
22 | const { name } = data;
23 | console.log("Latest release: " + name);
24 |
25 | const url = (data.assets || [])
26 | .map(asset => asset["browser_download_url"])
27 | .find(url => {
28 | if (platform === "darwin") {
29 | return url.includes("osx") || url.includes("mac");
30 | } else if (platform === "win32") {
31 | return url.includes("win") || url.includes("windows");
32 | }
33 | return url.includes("linux");
34 | });
35 |
36 | if (!url) {
37 | throw new Error("Download url not found for " + process);
38 | }
39 | console.log("Downloading binary at url: " + url);
40 |
41 | const extension = path.extname(url);
42 | const filePath = path.join(downloadDir, "latest" + extension);
43 | const { data: artifact } = await axios.get(url, {
44 | responseType: "stream"
45 | });
46 | artifact.pipe(fs.createWriteStream(filePath));
47 | console.log("Downloaded binary to: " + filePath);
48 | } catch (err) {
49 | console.error("Failed to download file: " + err);
50 | process.exit(1);
51 | }
52 | }
53 |
54 | download();
55 |
--------------------------------------------------------------------------------
/build/entitlements.mac.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.cs.allow-unsigned-executable-memory
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/build/notarize.js:
--------------------------------------------------------------------------------
1 | require("dotenv").config();
2 | const { notarize } = require("electron-notarize");
3 |
4 | /*
5 | Pre-requisites: https://github.com/electron/electron-notarize#prerequisites
6 | 1. Generate an app specific password
7 | 2. Add SIGNING_APPLE_ID, SIGNING_APP_PASSWORD, SIGNING_TEAM_ID to .env file in the root directory (where quasar.conf.js is located)
8 | */
9 |
10 | /*
11 | Notarizing: https://kilianvalkhof.com/2019/electron/notarizing-your-electron-application/
12 | */
13 |
14 | const log = msg => console.log(`\n${msg}`);
15 | const isEmpty = v => !v || v.length === 0;
16 |
17 | exports.default = async function notarizing(context) {
18 | const { electronPlatformName, appOutDir } = context;
19 | if (electronPlatformName !== "darwin") {
20 | return;
21 | }
22 | log("Notarizing mac application");
23 |
24 | const appName = context.packager.appInfo.productFilename;
25 | const { SIGNING_APPLE_ID, SIGNING_APP_PASSWORD, SIGNING_TEAM_ID } = process.env;
26 |
27 | if (isEmpty(SIGNING_APPLE_ID) || isEmpty(SIGNING_APP_PASSWORD)) {
28 | log("SIGNING_APPLE_ID or SIGNING_APP_PASSWORD not set.\nTerminating noratization.");
29 | return;
30 | }
31 |
32 | const options = {
33 | appBundleId: "com.scala-project.electron-wallet",
34 | appPath: `${appOutDir}/${appName}.app`,
35 | appleId: SIGNING_APPLE_ID,
36 | appleIdPassword: SIGNING_APP_PASSWORD
37 | };
38 | if (!isEmpty(SIGNING_TEAM_ID)) options.ascProvider = SIGNING_TEAM_ID;
39 | return notarize(options);
40 | };
41 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "baseUrl": ".",
5 | "paths": {
6 | "src/*": ["./src/*"],
7 | "app/*": ["./*"],
8 | "components/*": ["./src/components/*"],
9 | "layouts/*": ["./src/layouts/*"],
10 | "pages/*": ["./src/pages/*"],
11 | "statics/*": ["./src/statics/*"]
12 | }
13 | },
14 | "exclude": ["node_modules", "dist", ".quasar", "downloads", ".vscode"]
15 | }
16 |
--------------------------------------------------------------------------------
/oldquasar.babelrc-old:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "modules": false,
7 | "loose": false,
8 | "useBuiltIns": "usage"
9 | }
10 | ],
11 | [
12 | "@babel/preset-stage-2",
13 | {
14 | "modules": false,
15 | "loose": false,
16 | "useBuiltIns": true,
17 | "decoratorsLegacy": true
18 | }
19 | ]
20 | ],
21 | "plugins": [
22 | [
23 | "@babel/transform-runtime",
24 | {
25 | "polyfill": false,
26 | "regenerator": false
27 | }
28 | ]
29 | ],
30 | "comments": false
31 | }
32 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "scala-electron-wallet",
3 | "version": "7.9.0",
4 | "description": "Modern GUI interface for Scala Currency",
5 | "productName": "Scala Electron Wallet",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/scala-project/scala-electron-gui-wallet.git"
9 | },
10 | "cordovaId": "com.scalanetwork.wallet",
11 | "author": {
12 | "name": "Scala",
13 | "email": "hello@scalaproject.io"
14 | },
15 | "private": true,
16 | "scripts": {
17 | "dev": "quasar dev -m electron",
18 | "build": "quasar build -m electron",
19 | "release": "quasar build -m electron --publish=always",
20 | "lint": "eslint --fix .",
21 | "format": "prettier --write \"**/*.+(js|jsx|json|yml|yaml|css|md|vue)\"",
22 | "ready": "npm run lint && npm run format"
23 | },
24 | "dependencies": {
25 | "@quasar/app": "^2.0.8",
26 | "@quasar/extras": "^1.9.4",
27 | "axios": "^0.21.1",
28 | "electron-is-dev": "^1.0.1",
29 | "electron-updater": "^4.2.0",
30 | "electron-window-state": "^5.0.3",
31 | "flag-icon-css": "^3.3.0",
32 | "fs-extra": "^8.1.0",
33 | "object-assign-deep": "^0.4.0",
34 | "portscanner": "^2.2.0",
35 | "promise-queue": "^2.2.5",
36 | "qrcode.vue": "^1.6.1",
37 | "quasar": "^1.13.1",
38 | "request": "^2.88.0",
39 | "request-promise": "^4.2.4",
40 | "upath": "^1.2.0",
41 | "vue-i18n": "^8.9.0",
42 | "vue-timeago": "^5.1.2",
43 | "vuelidate": "^0.7.4"
44 | },
45 | "devDependencies": {
46 | "babel-eslint": "^10.1.0",
47 | "devtron": "^1.4.0",
48 | "dotenv": "^8.1.0",
49 | "electron": "^8.5.2",
50 | "electron-builder": "^22.8.1",
51 | "electron-debug": "^2.1.0",
52 | "electron-devtools-installer": "^2.2.4",
53 | "electron-notarize": "^0.1.1",
54 | "eslint": "^5.16.0",
55 | "eslint-config-prettier": "^6.10.0",
56 | "eslint-friendly-formatter": "^4.0.1",
57 | "eslint-loader": "^2.2.1",
58 | "eslint-plugin-import": "^2.16.0",
59 | "eslint-plugin-node": "^8.0.1",
60 | "eslint-plugin-prettier": "^3.1.2",
61 | "eslint-plugin-promise": "^4.0.1",
62 | "eslint-plugin-vue": "^5.2.3",
63 | "husky": "^4.2.3",
64 | "lint-staged": "^10.0.8",
65 | "node-sass": "^4.13.1",
66 | "prettier": "^1.19.1",
67 | "sass-loader": "^7.1.0",
68 | "strip-ansi": "^3.0.1"
69 | },
70 | "lint-staged": {
71 | "*.+(js|jsx|vue)": [],
72 | "*.+(json|yml|yaml|css|md)": ""
73 | },
74 | "engines": {
75 | "node": ">= 8.9.0",
76 | "npm": ">= 5.6.0",
77 | "yarn": ">= 1.6.0"
78 | },
79 | "browserslist": [
80 | "> 1%",
81 | "last 2 versions",
82 | "not ie <= 10"
83 | ]
84 | }
85 |
--------------------------------------------------------------------------------
/public/icon_512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-network/scala-electron-gui/1eea8a5ab48541e4c6c0333316b85e18953d7f29/public/icon_512x512.png
--------------------------------------------------------------------------------
/public/qr-code-grey.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/public/qr-code.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/public/ryo-wallet.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/public/scala.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
56 |
--------------------------------------------------------------------------------
/quasar.conf.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-template-curly-in-string */
2 | // Configuration for your app
3 |
4 | module.exports = function() {
5 | return {
6 | // app boot (/src/boot)
7 | boot: ["i18n", "axios", "vuelidate", "gateway", "timeago"],
8 | css: ["app.styl", "~flag-icon-css/css/flag-icon.min.css"],
9 | extras: [
10 | // ctx.theme.mat ? "roboto-font" : null,
11 | "material-icons" // optional, you are not bound to it
12 | // "ionicons-v4",
13 | // "mdi-v5",
14 | // "fontawesome-v5"
15 | ],
16 | supportIE: false,
17 | build: {
18 | scopeHoisting: true,
19 | vueRouterMode: "history",
20 | // vueCompiler: true,
21 | // gzip: true,
22 | // analyze: true,
23 | // extractCSS: false,
24 | extendWebpack() {
25 | /*
26 | cfg.module.rules.push({
27 | enforce: "pre",
28 | test: /\.(js|vue)$/,
29 | loader: "eslint-loader",
30 | exclude: /(node_modules|quasar)/
31 | })
32 | */
33 | },
34 | chainWebpack(chain) {
35 | chain.module
36 | .rule("images")
37 | .use("url-loader")
38 | .tap(options => {
39 | options.name = "img/[path][name].[ext]";
40 | return options;
41 | });
42 | }
43 | },
44 | devServer: {
45 | // https: true,
46 | // port: 8080,
47 | open: true // opens browser window automatically
48 | },
49 | // framework: "all" --- includes everything; for dev only!
50 | framework: {
51 | components: [
52 | "QLayout",
53 | "QHeader",
54 | "QFooter",
55 | "QDrawer",
56 | "QPageContainer",
57 | "QPage",
58 | "QToolbar",
59 | "QToolbarTitle",
60 | "QTooltip",
61 | "QField",
62 | "QInput",
63 | "QRadio",
64 | "QOptionGroup",
65 | "QBtn",
66 | "QBtnToggle",
67 | "QIcon",
68 | "QTabs",
69 | "QTab",
70 | "QRouteTab",
71 | "QBtnDropdown",
72 | "QMenu",
73 | "QDialog",
74 | "QStep",
75 | "QStepper",
76 | "QStepperNavigation",
77 | "QSpinner",
78 | "QList",
79 | "QItemLabel",
80 | "QItem",
81 | "QSeparator",
82 | "QItemSection",
83 | "QSelect",
84 | "QToggle",
85 | "QPageSticky",
86 | "QExpansionItem",
87 | "QCheckbox",
88 | "QInnerLoading",
89 | "QInfiniteScroll",
90 | "QDate",
91 | "QTime",
92 | "QScrollArea"
93 | ],
94 | directives: ["Ripple"],
95 | // Quasar plugins
96 | plugins: ["Notify", "Loading", "LocalStorage", "Dialog"]
97 | // iconSet: ctx.theme.mat ? "material-icons" : "ionicons-v4"
98 | // i18n: "de" // Quasar language
99 | },
100 | // animations: "all" --- includes all animations
101 | animations: [],
102 | pwa: {
103 | // workboxPluginMode: "InjectManifest",
104 | // workboxOptions: {},
105 | manifest: {
106 | // name: "Quasar App",
107 | // short_name: "Quasar-PWA",
108 | // description: "Best PWA App in town!",
109 | display: "standalone",
110 | orientation: "portrait",
111 | background_color: "#ffffff",
112 | theme_color: "#43BD43",
113 | icons: [
114 | {
115 | src: "statics/icons/icon-128x128.png",
116 | sizes: "128x128",
117 | type: "image/png"
118 | },
119 | {
120 | src: "statics/icons/icon-192x192.png",
121 | sizes: "192x192",
122 | type: "image/png"
123 | },
124 | {
125 | src: "statics/icons/icon-256x256.png",
126 | sizes: "256x256",
127 | type: "image/png"
128 | },
129 | {
130 | src: "statics/icons/icon-384x384.png",
131 | sizes: "384x384",
132 | type: "image/png"
133 | },
134 | {
135 | src: "statics/icons/icon-512x512.png",
136 | sizes: "512x512",
137 | type: "image/png"
138 | }
139 | ]
140 | }
141 | },
142 | cordova: {
143 | // id: "org.cordova.quasar.app"
144 | },
145 | electron: {
146 | bundler: "builder", // or "packager"
147 | extendWebpack() {
148 | // cfg
149 | // do something with Electron process Webpack cfg
150 | },
151 | packager: {
152 | // https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options
153 |
154 | // OS X / Mac App Store
155 | // appBundleId: "",
156 | // appCategoryType: "",
157 | // osxSign: "",
158 | // protocol: "myapp://path",
159 |
160 | // Window only
161 | // win32metadata: { ... }
162 |
163 | extraResource: ["bin"]
164 | },
165 | builder: {
166 | // https://www.electron.build/configuration/configuration
167 |
168 | appId: "com.scala-project.electron-wallet",
169 | productName: "Scala Electron Wallet",
170 | copyright: "Copyright © 2018-2019 Scala Project, 2018 Ryo Currency Project",
171 | afterSign: "build/notarize.js",
172 | artifactName: "scala-electron-wallet-${version}-${os}.${ext}",
173 | publish: "github",
174 |
175 | linux: {
176 | target: ["AppImage", "deb"],
177 | icon: "src-electron/icons/icon_512x512.png",
178 | category: "Finance"
179 | },
180 |
181 | mac: {
182 | // We need zip for auto-updating
183 | // Ref: https://github.com/electron-userland/electron-builder/issues/2199
184 | target: ["dmg", "zip"],
185 | icon: "src-electron/icons/icon.icns",
186 | category: "public.app-category.finance",
187 | // Notarizing: https://kilianvalkhof.com/2019/electron/notarizing-your-electron-application/
188 | hardenedRuntime: true,
189 | gatekeeperAssess: false,
190 | entitlements: "build/entitlements.mac.plist",
191 | entitlementsInherit: "build/entitlements.mac.plist"
192 | },
193 |
194 | dmg: {
195 | background: "src-electron/build/scala-dmg.tiff",
196 | sign: false
197 | },
198 |
199 | nsis: {
200 | oneClick: false,
201 | allowToChangeInstallationDirectory: true
202 | },
203 |
204 | files: ["!build/*.js", "!.env", "!dev-app-update.yml"],
205 |
206 | extraResources: ["bin"]
207 | }
208 | }
209 | };
210 | };
211 |
--------------------------------------------------------------------------------
/src-electron/build/mosu_forge:
--------------------------------------------------------------------------------
1 | -----BEGIN PGP PUBLIC KEY BLOCK-----
2 |
3 | mQENBFsQeDEBCAC6FipGNqhvlplhjoFvqUqAxreOb4/qi5eSTnzoeGlb3XEBlifV
4 | z5d6aSQqZXjDSkrZqjh57Lkv1DugZpz/FLTVuy+b7stqxwvlQDyRxZg7871sTDh5
5 | ZG1CMN6rHU4wYq081+/gRDOz96TCl40geT/EKBXTPoXbVh6h1UWC5t47JqHYMFe1
6 | aqdqQDF+1pn5e5b1Dxe3U9B/rlTb1darb04ENNqGaaX2rrDn5d2DEv7a0/XLB2Nc
7 | VrzbUH+3LyxgO1smzDOJHn5dia7z4LUsE10KQijwOEZtxYuMWC+KTyVubGkOVYVp
8 | EQ4CAvHPHXWb0lyaJnP9jBlWvR1Mvznkdwi1ABEBAAG0Jm1vc3VfZm9yZ2UgPG1v
9 | c3UuZm9yZ2VAcHJvdG9ubWFpbC5jb20+iQFOBBMBCAA4FiEEx8qIjI7MgV9v9hnk
10 | g6LJxzvxIGMFAlsQeDECGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQg6LJ
11 | xzvxIGNNVgf/SdwxQegQEPKo7j2vj8UhtfFX3sAxpY4ko3YX88taEZlGSSBFtW1U
12 | 0WyfBi3kdeYs8zhN3ZjnjVtFJvnjDETLu4EPAuSrDyrz3rVaMqFha8mqFvHJUC26
13 | phoJC3bM1/9pgmvgUJfVj4i3hoAPNSBnB7OkefFnea/OGow4NHtcvOTRDNTbZ675
14 | 3kvmCMxv/iSfMm1oQmO4rlnBkBF5Hh7rF0hQyG3d+8iuzckaxy/zjXWRKzSX2LsZ
15 | KXHM6BTBNq6SXnXyJ5D8meT+0sMUsxN4yblwKtFosQpVOtoQc4YMq17NWifnBedZ
16 | qs50iIawUaBD/BBXXVOEfObxU1Ct1lGCErkBDQRbEHgxAQgArKfVkyltydCvCB11
17 | JERzpkvKOWEyyAA8Qrbb+6mbYlqT3Uf/+ypnj1/lJu5xfNhT9GIGR5vEDr2ERYlJ
18 | uQ8kqnKY41oaLXr2p1U0Wp42AJX4m9XUXsiGocZpDmAluOKtXJocUoMrT4zdkviS
19 | n2j3Vr1MPj8MOYmAg6Nl4/3nwYrHe1PN75kDjk49tf95VvnCIolilRAMXcgtKl/o
20 | WxXFUXndOBgV2ywY7v7IGBvqKGKCz95ItJ4EKhDWs1EiCHtrGnd+OHNBjecj95vh
21 | SRDdUFRpWIUpwjoGFKE5C0he4MS4+CDy5p8jAKUQgfWVhFmM3st8po0uTbLB5Za4
22 | 0wv6wwARAQABiQE2BBgBCAAgFiEEx8qIjI7MgV9v9hnkg6LJxzvxIGMFAlsQeDEC
23 | GwwACgkQg6LJxzvxIGPZ9wgAmYRdNADoPO4uxC4gP+0XjDd5W+vy1qDSXDCAqaAD
24 | aU+B22NOwx48XlcHSg5rvzoUqoXxtdiYMR9tQS2RF1OfzNIRnJy5Jqrv7ulOV63B
25 | n74gOGa2ypFiFj50i1Zvu/80CPDpc4Cg5csqtzslDMxiuNz+Wh+qQyYlVrV9r2N8
26 | ejaKFk9znjGw3fo/SxXMOncZb7yCaxeqT82/A+N9WMiUIJIhYyenYQ1uFK3lkzTK
27 | hl0wDD1Qnrwz49v1z60+7ARUltjog6TqcXPsxFarLLo1f0kx/YPBM2jcKQ1uBFtR
28 | 8xJ0CkjYof4QDMRI9/Dft+FOzNy92o3m1s6fXcISWJ1YNw==
29 | =ts23
30 | -----END PGP PUBLIC KEY BLOCK-----
31 |
--------------------------------------------------------------------------------
/src-electron/build/scala-dmg.tiff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-network/scala-electron-gui/1eea8a5ab48541e4c6c0333316b85e18953d7f29/src-electron/build/scala-dmg.tiff
--------------------------------------------------------------------------------
/src-electron/electron-flag.d.ts:
--------------------------------------------------------------------------------
1 | // THIS FEATURE-FLAG FILE IS AUTOGENERATED,
2 | // REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING
3 | import "quasar/dist/types/feature-flag";
4 |
5 | declare module "quasar/dist/types/feature-flag" {
6 | interface QuasarFeatureFlags {
7 | electron: true;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src-electron/icons/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-network/scala-electron-gui/1eea8a5ab48541e4c6c0333316b85e18953d7f29/src-electron/icons/icon.icns
--------------------------------------------------------------------------------
/src-electron/icons/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-network/scala-electron-gui/1eea8a5ab48541e4c6c0333316b85e18953d7f29/src-electron/icons/icon.ico
--------------------------------------------------------------------------------
/src-electron/icons/icon_512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-network/scala-electron-gui/1eea8a5ab48541e4c6c0333316b85e18953d7f29/src-electron/icons/icon_512x512.png
--------------------------------------------------------------------------------
/src-electron/icons/linux-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-network/scala-electron-gui/1eea8a5ab48541e4c6c0333316b85e18953d7f29/src-electron/icons/linux-512x512.png
--------------------------------------------------------------------------------
/src-electron/icons/macos-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-network/scala-electron-gui/1eea8a5ab48541e4c6c0333316b85e18953d7f29/src-electron/icons/macos-512x512.png
--------------------------------------------------------------------------------
/src-electron/icons/mrcuug.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-network/scala-electron-gui/1eea8a5ab48541e4c6c0333316b85e18953d7f29/src-electron/icons/mrcuug.PNG
--------------------------------------------------------------------------------
/src-electron/main-process/auto-updater.js:
--------------------------------------------------------------------------------
1 | import * as path from "path";
2 | import * as fs from "fs-extra";
3 | import { dialog } from "electron";
4 | import isDev from "electron-is-dev";
5 | import { autoUpdater } from "electron-updater";
6 | import { app } from "electron";
7 |
8 | let isUpdating = false;
9 |
10 | /*
11 | Check if we have the required files to auto update.
12 | These files won't exist inside certain formats such as a linux deb file.
13 | */
14 | async function canAutoUpdate() {
15 | const { isPackaged } = app;
16 |
17 | // On a production app, we need to use resources path to check for the file
18 | if (isPackaged && !process.resourcesPath) {
19 | return false;
20 | }
21 |
22 | // Taken from: https://github.com/electron-userland/electron-builder/blob/d4feb6d3c8b008f8b455c761d654c8088f90d8fa/packages/electron-updater/src/ElectronAppAdapter.ts#L25
23 | const updateFile = isPackaged ? "app-update.yml" : "dev-app-update.yml";
24 | const basePath = isPackaged && process.resourcesPath ? process.resourcesPath : app.getAppPath();
25 | const appUpdateConfigPath = path.join(basePath, updateFile);
26 |
27 | return new Promise(resolve => {
28 | try {
29 | // tslint:disable-next-line: non-literal-fs-path
30 | const exists = fs.existsSync(appUpdateConfigPath);
31 | resolve(exists);
32 | } catch (e) {
33 | resolve(false);
34 | }
35 | });
36 | }
37 |
38 | async function checkForUpdate(getMainWindow, onQuitAndInstall) {
39 | // Disable for development
40 | if (isDev) {
41 | return;
42 | }
43 |
44 | if (isUpdating) {
45 | return;
46 | }
47 |
48 | const canUpdate = await canAutoUpdate();
49 | if (!canUpdate) {
50 | return;
51 | }
52 |
53 | autoUpdater.logger = console;
54 |
55 | try {
56 | // Get the update using electron-updater
57 | const info = await autoUpdater.checkForUpdates();
58 | if (!info || !info.downloadPromise) {
59 | console.info("auto-update: no update to download");
60 |
61 | return;
62 | }
63 |
64 | try {
65 | await info.downloadPromise;
66 | } catch (error) {
67 | await showCannotUpdateDialog(getMainWindow());
68 | throw error;
69 | }
70 |
71 | // Update downloaded successfully, we should ask the user to update
72 | console.info("auto-update: showing update dialog...");
73 | const shouldUpdate = await showUpdateDialog(getMainWindow());
74 | if (!shouldUpdate) {
75 | return;
76 | }
77 |
78 | console.info("auto-update: calling quitAndInstall...");
79 | if (onQuitAndInstall) {
80 | onQuitAndInstall(autoUpdater);
81 | }
82 | } catch (error) {
83 | console.error("auto-update error:", getPrintableError(error));
84 | } finally {
85 | isUpdating = false;
86 | }
87 | }
88 |
89 | function getPrintableError(error) {
90 | return error && error.stack ? error.stack : error;
91 | }
92 |
93 | async function showUpdateDialog(mainWindow) {
94 | const RESTART_BUTTON = 0;
95 | const LATER_BUTTON = 1;
96 | const options = {
97 | type: "info",
98 | buttons: ["Restart Wallet", "Later"],
99 | title: "Scala Electron Wallet update available",
100 | message: "There is a new version of Scala Electron Wallet available.",
101 | detail: "Press Restart Wallet to apply the update",
102 | defaultId: LATER_BUTTON,
103 | cancelId: RESTART_BUTTON
104 | };
105 | return new Promise(resolve => {
106 | dialog.showMessageBox(mainWindow, options, response => {
107 | resolve(response === RESTART_BUTTON);
108 | });
109 | });
110 | }
111 |
112 | async function showCannotUpdateDialog(mainWindow) {
113 | const options = {
114 | type: "error",
115 | buttons: ["Ok"],
116 | title: "Cannot update",
117 | message:
118 | "Scala Electron Wallet failed to update but there is a new version available. Please go to https://scala.network/ and install the new version manually."
119 | };
120 |
121 | return new Promise(resolve => {
122 | dialog.showMessageBox(mainWindow, options, () => {
123 | resolve();
124 | });
125 | });
126 | }
127 |
128 | export { checkForUpdate };
129 |
--------------------------------------------------------------------------------
/src-electron/main-process/electron-main.dev.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is used specifically and only for development. It installs
3 | * `electron-debug` & `vue-devtools`. There shouldn"t be any need to
4 | * modify this file, but it can be used to extend your development
5 | * environment.
6 | */
7 |
8 | // Install `electron-debug` with `devtron`
9 | require("electron-debug")({
10 | showDevTools: true
11 | });
12 |
13 | // Install `vue-devtools`
14 | require("electron").app.on("ready", () => {
15 | let installExtension = require("electron-devtools-installer");
16 | installExtension
17 | .default(installExtension.VUEJS_DEVTOOLS)
18 | .then(() => {})
19 | .catch(err => {
20 | console.log("Unable to install `vue-devtools`: \n", err);
21 | });
22 | });
23 |
24 | // Require `main` process to boot app
25 | require("./electron-main");
26 |
--------------------------------------------------------------------------------
/src-electron/main-process/electron-main.js:
--------------------------------------------------------------------------------
1 | import { app, ipcMain, BrowserWindow, Menu, dialog } from "electron";
2 | import { version, productName } from "../../package.json";
3 | import { Backend } from "./modules/backend";
4 | import { checkForUpdate } from "./auto-updater";
5 | import menuTemplate from "./menu";
6 | import isDev from "electron-is-dev";
7 | const portscanner = require("portscanner");
8 | const windowStateKeeper = require("electron-window-state");
9 | const path = require("upath");
10 |
11 | /**
12 | * Set `__statics` path to static files in production;
13 | * The reason we are setting it here is that the path needs to be evaluated at runtime
14 | */
15 | if (process.env.PROD) {
16 | global.__statics = path.join(__dirname, "statics").replace(/\\/g, "\\\\");
17 | global.__ryo_bin = path.join(__dirname, "..", "bin").replace(/\\/g, "\\\\");
18 | } else {
19 | global.__ryo_bin = path.join(process.cwd(), "bin").replace(/\\/g, "\\\\");
20 | }
21 |
22 | let mainWindow, backend;
23 | let showConfirmClose = true;
24 | let forceQuit = false;
25 | let installUpdate = false;
26 |
27 | const title = `${productName} v${version}`;
28 |
29 | const selectionMenu = Menu.buildFromTemplate([{ role: "copy" }, { type: "separator" }, { role: "selectall" }]);
30 |
31 | const inputMenu = Menu.buildFromTemplate([
32 | { role: "cut" },
33 | { role: "copy" },
34 | { role: "paste" },
35 | { type: "separator" },
36 | { role: "selectall" }
37 | ]);
38 |
39 | function createWindow() {
40 | /**
41 | * Initial window options
42 | */
43 |
44 | let mainWindowState = windowStateKeeper({
45 | defaultWidth: 900,
46 | defaultHeight: 700
47 | });
48 |
49 | mainWindow = new BrowserWindow({
50 | x: mainWindowState.x,
51 | y: mainWindowState.y,
52 | width: mainWindowState.width,
53 | height: mainWindowState.height,
54 | minWidth: 640,
55 | minHeight: 480,
56 | icon: require("path").join(__statics, "icon_512x512.png"),
57 | title,
58 | webPreferences: {
59 | nodeIntegration: true
60 | }
61 | });
62 |
63 | mainWindow.on("close", e => {
64 | // Don't ask for confirmation if we're installing an update
65 | if (installUpdate) {
66 | return;
67 | }
68 |
69 | if (process.platform === "darwin") {
70 | if (forceQuit) {
71 | forceQuit = false;
72 | if (showConfirmClose) {
73 | e.preventDefault();
74 | mainWindow.show();
75 | mainWindow.webContents.send("confirmClose");
76 | } else {
77 | e.defaultPrevented = false;
78 | }
79 | } else {
80 | e.preventDefault();
81 | mainWindow.hide();
82 | }
83 | } else {
84 | if (showConfirmClose) {
85 | e.preventDefault();
86 | mainWindow.webContents.send("confirmClose");
87 | } else {
88 | e.defaultPrevented = false;
89 | }
90 | }
91 | });
92 |
93 | ipcMain.on("confirmClose", (e, restart) => {
94 | showConfirmClose = false;
95 |
96 | // In dev mode, this will launch a blank white screen
97 | if (restart && !isDev) app.relaunch();
98 |
99 | const promise = backend ? backend.quit() : Promise.resolve();
100 | promise.then(() => {
101 | backend = null;
102 | app.quit();
103 | });
104 | });
105 |
106 | mainWindow.webContents.on("did-finish-load", () => {
107 | // Set the title
108 | mainWindow.setTitle(title);
109 |
110 | require("crypto").randomBytes(64, (err, buffer) => {
111 | // if err, then we may have to use insecure token generation perhaps
112 | if (err) throw err;
113 |
114 | let config = {
115 | port: 12313,
116 | token: buffer.toString("hex")
117 | };
118 |
119 | portscanner.checkPortStatus(config.port, "127.0.0.1", (error, status) => {
120 | if (error) {
121 | console.error(error);
122 | }
123 |
124 | if (status === "closed") {
125 | backend = new Backend(mainWindow);
126 | backend.init(config);
127 | mainWindow.webContents.send("initialize", config);
128 | } else {
129 | dialog.showMessageBox(
130 | mainWindow,
131 | {
132 | title: "Startup error",
133 | message: `Scala Wallet is already open, or port ${config.port} is in use`,
134 | type: "error",
135 | buttons: ["ok"]
136 | },
137 | () => {
138 | showConfirmClose = false;
139 | app.quit();
140 | }
141 | );
142 | }
143 | });
144 | });
145 | });
146 |
147 | mainWindow.webContents.on("context-menu", (e, props) => {
148 | const { selectionText, isEditable } = props;
149 | if (isEditable) {
150 | inputMenu.popup(mainWindow);
151 | } else if (selectionText && selectionText.trim() !== "") {
152 | selectionMenu.popup(mainWindow);
153 | }
154 | });
155 |
156 | mainWindow.loadURL(process.env.APP_URL);
157 | mainWindowState.manage(mainWindow);
158 | }
159 |
160 | app.on("ready", () => {
161 | checkForUpdate(
162 | () => mainWindow,
163 | autoUpdater => {
164 | if (mainWindow) {
165 | mainWindow.webContents.send("showQuitScreen");
166 | }
167 |
168 | const promise = backend ? backend.quit() : Promise.resolve();
169 | promise.then(() => {
170 | installUpdate = true;
171 | backend = null;
172 | autoUpdater.quitAndInstall();
173 | });
174 | }
175 | );
176 | if (process.platform === "darwin") {
177 | const menu = Menu.buildFromTemplate(menuTemplate);
178 | Menu.setApplicationMenu(menu);
179 | }
180 | createWindow();
181 | });
182 |
183 | app.on("window-all-closed", () => {
184 | if (process.platform !== "darwin") {
185 | app.quit();
186 | }
187 | });
188 |
189 | app.on("activate", () => {
190 | if (mainWindow === null) {
191 | createWindow();
192 | } else if (process.platform === "darwin") {
193 | mainWindow.show();
194 | }
195 | });
196 |
197 | app.on("before-quit", () => {
198 | // Quit instantly if we are installing an update
199 | if (installUpdate) {
200 | return;
201 | }
202 |
203 | if (process.platform === "darwin") {
204 | forceQuit = true;
205 | } else {
206 | if (backend) {
207 | backend.quit().then(() => {
208 | mainWindow.close();
209 | });
210 | }
211 | }
212 | });
213 |
214 | app.on("quit", () => {});
215 |
--------------------------------------------------------------------------------
/src-electron/main-process/menu.js:
--------------------------------------------------------------------------------
1 | let template = [
2 | {
3 | label: "Edit",
4 | submenu: [
5 | { role: "undo" },
6 | { role: "redo" },
7 | { type: "separator" },
8 | { role: "cut" },
9 | { role: "copy" },
10 | { role: "paste" },
11 | { role: "pasteandmatchstyle" },
12 | { role: "delete" },
13 | { role: "selectall" }
14 | ]
15 | },
16 | {
17 | label: "View",
18 | submenu: [
19 | { role: "resetzoom" },
20 | { role: "zoomin" },
21 | { role: "zoomout" },
22 | { type: "separator" },
23 | { role: "togglefullscreen" }
24 | ]
25 | },
26 | {
27 | role: "window",
28 | submenu: [{ role: "minimize" }, { role: "close" }]
29 | },
30 | {
31 | role: "help",
32 | submenu: [
33 | {
34 | label: "Learn More",
35 | click() {
36 | require("electron").shell.openExternal("https://scala.network/");
37 | }
38 | }
39 | ]
40 | }
41 | ];
42 |
43 | if (process.platform === "darwin") {
44 | template.unshift({
45 | label: "Scala Electron Wallet",
46 | submenu: [
47 | { role: "about" },
48 | { type: "separator" },
49 | { role: "hide" },
50 | { role: "hideothers" },
51 | { role: "unhide" },
52 | { type: "separator" },
53 | { role: "quit" }
54 | ]
55 | });
56 |
57 | // Window menu
58 | template[3].submenu = [
59 | { role: "close" },
60 | { role: "minimize" },
61 | { role: "zoom" },
62 | { type: "separator" },
63 | { role: "front" }
64 | ];
65 | }
66 |
67 | export default template;
68 |
--------------------------------------------------------------------------------
/src-electron/main-process/modules/SCEE-Node.js:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2018 Luke Park
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 |
25 | const crypto = require("crypto");
26 |
27 | const ALGORITHM_NAME = "aes-128-gcm";
28 | const ALGORITHM_NONCE_SIZE = 12;
29 | const ALGORITHM_TAG_SIZE = 16;
30 | const ALGORITHM_KEY_SIZE = 16;
31 | const PBKDF2_NAME = "sha256";
32 | const PBKDF2_SALT_SIZE = 16;
33 | const PBKDF2_ITERATIONS = 32767;
34 |
35 | export class SCEE {
36 | encryptString(plaintext, password) {
37 | // Generate a 128-bit salt using a CSPRNG.
38 | let salt = crypto.randomBytes(PBKDF2_SALT_SIZE);
39 |
40 | // Derive a key using PBKDF2.
41 | let key = crypto.pbkdf2Sync(new Buffer(password, "utf8"), salt, PBKDF2_ITERATIONS, ALGORITHM_KEY_SIZE, PBKDF2_NAME);
42 |
43 | // Encrypt and prepend salt.
44 | let ciphertextAndNonceAndSalt = Buffer.concat([salt, this.encrypt(new Buffer(plaintext, "utf8"), key)]);
45 |
46 | // Return as base64 string.
47 | return ciphertextAndNonceAndSalt.toString("base64");
48 | }
49 |
50 | decryptString(base64CiphertextAndNonceAndSalt, password) {
51 | // Decode the base64.
52 | let ciphertextAndNonceAndSalt = new Buffer(base64CiphertextAndNonceAndSalt, "base64");
53 |
54 | // Create buffers of salt and ciphertextAndNonce.
55 | let salt = ciphertextAndNonceAndSalt.slice(0, PBKDF2_SALT_SIZE);
56 | let ciphertextAndNonce = ciphertextAndNonceAndSalt.slice(PBKDF2_SALT_SIZE);
57 |
58 | // Derive the key using PBKDF2.
59 | let key = crypto.pbkdf2Sync(new Buffer(password, "utf8"), salt, PBKDF2_ITERATIONS, ALGORITHM_KEY_SIZE, PBKDF2_NAME);
60 |
61 | // Decrypt and return result.
62 | return this.decrypt(ciphertextAndNonce, key).toString("utf8");
63 | }
64 |
65 | encrypt(plaintext, key) {
66 | // Generate a 96-bit nonce using a CSPRNG.
67 | let nonce = crypto.randomBytes(ALGORITHM_NONCE_SIZE);
68 |
69 | // Create the cipher instance.
70 | let cipher = crypto.createCipheriv(ALGORITHM_NAME, key, nonce);
71 |
72 | // Encrypt and prepend nonce.
73 | let ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
74 |
75 | return Buffer.concat([nonce, ciphertext, cipher.getAuthTag()]);
76 | }
77 |
78 | decrypt(ciphertextAndNonce, key) {
79 | // Create buffers of nonce, ciphertext and tag.
80 | let nonce = ciphertextAndNonce.slice(0, ALGORITHM_NONCE_SIZE);
81 | let ciphertext = ciphertextAndNonce.slice(ALGORITHM_NONCE_SIZE, ciphertextAndNonce.length - ALGORITHM_TAG_SIZE);
82 | let tag = ciphertextAndNonce.slice(ciphertext.length + ALGORITHM_NONCE_SIZE);
83 |
84 | // Create the cipher instance.
85 | let cipher = crypto.createDecipheriv(ALGORITHM_NAME, key, nonce);
86 |
87 | // Decrypt and return result.
88 | cipher.setAuthTag(tag);
89 | return Buffer.concat([cipher.update(ciphertext), cipher.final()]);
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src-electron/main-process/modules/status-codes.js:
--------------------------------------------------------------------------------
1 | export const WALLET_NOT_OPEN = -1;
2 | export const WALLET_OPEN = 0;
3 | export const WALLET_ERROR = 1;
4 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/boot/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-network/scala-electron-gui/1eea8a5ab48541e4c6c0333316b85e18953d7f29/src/boot/.gitkeep
--------------------------------------------------------------------------------
/src/boot/axios.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 |
3 | export default ({ Vue }) => {
4 | Vue.prototype.$axios = axios;
5 | };
6 |
--------------------------------------------------------------------------------
/src/boot/gateway.js:
--------------------------------------------------------------------------------
1 | import { Gateway } from "src/gateway/gateway";
2 |
3 | /* This plugin gets called early in the life-cycle
4 | In the future, we can detect what platform we
5 | are on and include the correct gateway.
6 |
7 | The gateway just gets stored into the app global
8 | object to be called from anywhere within the
9 | frontend
10 | */
11 |
12 | export default ({ app, router, Vue }) => {
13 | Vue.prototype.$gateway = new Gateway(app, router);
14 | };
15 |
--------------------------------------------------------------------------------
/src/boot/i18n.js:
--------------------------------------------------------------------------------
1 | import VueI18n from "vue-i18n";
2 | import messages from "src/i18n";
3 | import { Quasar } from "quasar";
4 |
5 | let i18n;
6 |
7 | export default ({ app, Vue }) => {
8 | Vue.use(VueI18n);
9 |
10 | // Set i18n instance on app
11 | app.i18n = new VueI18n({
12 | locale: "en-us",
13 | fallbackLocale: "en-us",
14 | messages
15 | });
16 |
17 | i18n = app.i18n;
18 | };
19 |
20 | const changeLanguage = lang => {
21 | const quasarLang = Quasar.lang;
22 | return new Promise((resolve, reject) => {
23 | import(`src/i18n/${lang}`)
24 | .then(({ default: messages }) => {
25 | i18n.locale = lang;
26 | i18n.setLocaleMessage(lang, messages);
27 |
28 | // Setting the quasar language is optional
29 | // There may be cases where they don't have the language
30 | import(`quasar/lang/${lang}`)
31 | .then(resultLang => {
32 | quasarLang.set(resultLang.default);
33 | })
34 | .catch(() => {
35 | console.warn(`Failed to set quasar language: ${lang}`);
36 | })
37 | .finally(() => {
38 | resolve(lang);
39 | });
40 | })
41 | .catch(() => {
42 | reject(new Error("Language not found"));
43 | });
44 | });
45 | };
46 |
47 | export { i18n, changeLanguage };
48 |
--------------------------------------------------------------------------------
/src/boot/timeago.js:
--------------------------------------------------------------------------------
1 | import VueTimeago from "vue-timeago";
2 | export default ({ Vue }) => {
3 | Vue.use(VueTimeago, {
4 | name: "Timeago",
5 | locale: "en",
6 | locales: {
7 | ru: require("date-fns/locale/ru"),
8 | de: require("date-fns/locale/de"),
9 | fr: require("date-fns/locale/fr"),
10 | es: require("date-fns/locale/es"),
11 | pt: require("date-fns/locale/pt")
12 | }
13 | });
14 | };
15 |
--------------------------------------------------------------------------------
/src/boot/vuelidate.js:
--------------------------------------------------------------------------------
1 | import Vuelidate from "vuelidate";
2 |
3 | export default ({ Vue }) => {
4 | Vue.use(Vuelidate);
5 | };
6 |
--------------------------------------------------------------------------------
/src/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-network/scala-electron-gui/1eea8a5ab48541e4c6c0333316b85e18953d7f29/src/components/.gitkeep
--------------------------------------------------------------------------------
/src/components/address_header.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ title }}
5 |
6 |
7 | {{ address }}
8 |
9 |
10 |
11 |
12 | {{ $t("menuItems.copyAddress") }}
13 |
14 |
15 |
16 |
17 | {{ $t("fieldLabels.paymentId") }}: {{ paymentId }}
18 |
19 |
20 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
103 |
104 |
142 |
--------------------------------------------------------------------------------
/src/components/check_transaction.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ $t("strings.checkTransaction.description") }}
5 |
6 |
7 |
15 |
16 |
17 |
25 |
26 |
27 |
34 |
35 |
36 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
{{ $t("strings.transactionID") }}
52 |
{{ status.state.txid }}
53 |
54 |
55 |
{{ $t("strings.checkTransaction.infoTitles.validTransaction") }}
56 |
{{ validTransaction }}
57 |
58 |
59 |
{{ $t("strings.checkTransaction.infoTitles.received") }}
60 |
61 |
62 |
63 |
64 |
65 |
{{ $t("strings.checkTransaction.infoTitles.inPool") }}
66 |
{{ status.state.in_pool }}
67 |
68 |
69 |
{{ $t("strings.checkTransaction.infoTitles.confirmations") }}
70 |
{{ status.state.confirmations }}
71 |
72 |
73 |
74 |
75 |
76 |
77 |
193 |
194 |
207 |
--------------------------------------------------------------------------------
/src/components/footer.vue:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
27 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/src/components/format_scala.vue:
--------------------------------------------------------------------------------
1 |
2 | {{ value }} SCALA
3 |
4 |
5 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/components/icons/copy_icon.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ $t("menuItems.copyAddress") }}
5 |
6 |
7 |
8 |
9 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/components/language_select.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ $t("strings.selectLanguage") }}:
4 |
5 |
13 |
14 | {{ option.label }}
15 |
16 |
17 |
18 |
19 |
20 |
45 |
46 |
57 |
--------------------------------------------------------------------------------
/src/components/lns_input.vue:
--------------------------------------------------------------------------------
1 |
2 |
21 |
22 |
23 |
177 |
178 |
185 |
--------------------------------------------------------------------------------
/src/components/mainmenu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
22 |
23 |
24 |
25 |

26 |
27 |
Wallet Version: v{{ version }}
28 |
Deaemon Version: v{{ daemonVersion }}
29 |
Copyright (c) 2019-2020, Scala Network
30 |
Copyright (c) 2018-2019, Loki Network
31 |
Copyright (c) 2018, Ryo Currency Project
32 |
All rights reserved.
33 |
34 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
137 |
138 |
158 |
--------------------------------------------------------------------------------
/src/components/prove_transaction.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ $t("strings.proveTransactionDescription") }}
6 |
7 |
8 |
9 |
17 |
18 |
19 |
27 |
28 |
29 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
{{ $t("strings.transactionID") }}
46 |
{{ status.state.txid }}
47 |
48 |
49 | {{ status.state.signature }}
50 |
51 |
52 |
53 |
54 |
55 |
56 |
160 |
161 |
185 |
--------------------------------------------------------------------------------
/src/components/receive_item.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ address.address }}
6 | {{ sublabel }}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{ $t("menuItems.showQRCode") }}
15 |
16 |
17 |
18 |
19 | {{ $t("menuItems.copyAddress") }}
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | {{ $t("strings.scalaBalance") }}
32 |
33 | {{ address.balance | currency }}
34 |
35 |
36 | {{ $t("strings.scalaUnlockedBalance") }}
37 |
38 | {{ address.unlocked_balance | currency }}
39 |
40 |
41 | {{ $t("strings.unspentOutputs") }}
42 |
43 | {{ address.num_unspent_outputs | toString }}
44 |
45 |
46 |
47 |
48 |
49 |
50 |
63 |
64 |
65 |
66 |
67 |
123 |
124 |
129 |
--------------------------------------------------------------------------------
/src/components/scala_field.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ label }}
5 | ({{ $t("fieldLabels.optional") }})
6 |
7 |
8 |
9 |
10 |
11 | {{ errorLabel }}
12 |
13 |
14 |
15 |
16 |
56 |
57 |
109 |
--------------------------------------------------------------------------------
/src/components/service_node_registration.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | register_service_node
6 | prepare_registration
7 |
8 |
13 |
25 |
26 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
142 |
143 |
148 |
--------------------------------------------------------------------------------
/src/components/settings.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{ $t("titles.settings.title") }}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
22 |
23 |
24 |
25 | {{ $t("strings.peerList") }}
26 |
27 |
33 |
34 | {{ entry.address }}
35 | {{ $t("strings.blockHeight") }}: {{ entry.height }}
36 |
37 |
38 |
39 |
40 | {{ $t("strings.bannedPeers.title") }}
41 |
42 |
43 | {{ entry.host }}
44 |
45 | {{
46 | $t("strings.bannedPeers.bannedUntil", {
47 | time: new Date(Date.now() + entry.seconds * 1000).toLocaleString()
48 | })
49 | }}
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
172 |
173 |
174 |
--------------------------------------------------------------------------------
/src/components/tx_type_icon.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
37 |
38 |
55 |
--------------------------------------------------------------------------------
/src/components/wallet_details.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
12 | {{ $t("strings.scalaBalance") }}
13 |
14 |
15 |
16 |
17 |
18 |
19 | {{ $t("strings.scalaUnlockedShort") }}:
20 |
21 |
22 |
23 |
24 |
{{ info.address }}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
49 |
50 |
92 |
--------------------------------------------------------------------------------
/src/css/quasar.variables.styl:
--------------------------------------------------------------------------------
1 | // App Shared Variables
2 | // --------------------------------------------------
3 | // To customize the look and feel of this app, you can override
4 | // the Stylus variables found in Quasar"s source Stylus files. Setting
5 | // variables before Quasar"s Stylus will use these variables rather than
6 | // Quasar"s default Stylus variable values. Stylus variables specific
7 | // to the themes belong in either the variables.ios.styl or variables.mat.styl files.
8 |
9 | // Check documentation for full list of Quasar variables
10 |
11 |
12 | // App Shared Color Variables
13 | // --------------------------------------------------
14 | // It"s highly recommended to change the default colors
15 | // to match your app"s branding.
16 |
17 | $primary = $scala-green
18 | $secondary = $scala-black-90
19 | $tertiary = $scala-black-80
20 |
21 | $neutral = #E0E1E2
22 | $positive = #2173BA
23 | $negative = #DB2828
24 | $info = #31CCEC
25 | $warning = #F2C037
26 |
27 | $scala-green = #2f333d
28 | $scala-green-solid = #5BBBCA;
29 | $scala-green-dark-solid = #307996;
30 |
31 | $scala-black-90 = #1b1e24
32 | $scala-black-80 = #1b1e24
33 | $scala-black-60 = #1b1e24
34 | $scala-black-50 = #1b1e24;
--------------------------------------------------------------------------------
/src/css/themes/RobotoMono-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-network/scala-electron-gui/1eea8a5ab48541e4c6c0333316b85e18953d7f29/src/css/themes/RobotoMono-Light.ttf
--------------------------------------------------------------------------------
/src/css/themes/common.variables.styl:
--------------------------------------------------------------------------------
1 | // App Shared Variables
2 | // --------------------------------------------------
3 | // To customize the look and feel of this app, you can override
4 | // the Stylus variables found in Quasar"s source Stylus files. Setting
5 | // variables before Quasar"s Stylus will use these variables rather than
6 | // Quasar"s default Stylus variable values. Stylus variables specific
7 | // to the themes belong in either the variables.ios.styl or variables.mat.styl files.
8 |
9 | // Check documentation for full list of Quasar variables
10 |
11 |
12 | // App Shared Color Variables
13 | // --------------------------------------------------
14 | // It"s highly recommended to change the default colors
15 | // to match your app"s branding.
16 |
17 | $primary = $scala-green
18 | $secondary = $scala-black-90
19 | $tertiary = $scala-black-80
20 |
21 | $neutral = #E0E1E2
22 | $positive = #2173BA
23 | $negative = #DB2828
24 | $info = #31CCEC
25 | $warning = #F2C037
26 |
27 | $scala-green = #2f333d
28 | $scala-green-solid = #5BBBCA;
29 | $scala-green-dark-solid = #307996;
30 |
31 | $scala-black-90 = #1b1e24
32 | $scala-black-80 = #1b1e24
33 | $scala-black-60 = #1b1e24
34 | $scala-black-50 = #1b1e24;
35 |
--------------------------------------------------------------------------------
/src/css/themes/variables.ios.styl:
--------------------------------------------------------------------------------
1 | // App Shared Variables
2 | // --------------------------------------------------
3 | // Shared Stylus variables go in the common.variables.styl file
4 | @import "common.variables"
5 |
6 | // iOS only Quasar variables overwrites
7 | // -----------------------------------------
8 |
--------------------------------------------------------------------------------
/src/css/themes/variables.mat.styl:
--------------------------------------------------------------------------------
1 | // App Shared Variables
2 | // --------------------------------------------------
3 | // Shared Stylus variables go in the common.variables.styl file
4 | @import "common.variables"
5 |
6 | // Material only Quasar variables overwrites
7 | // -----------------------------------------
8 |
--------------------------------------------------------------------------------
/src/gateway/SCEE-Node.js:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2018 Luke Park
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 |
25 | const crypto = require("crypto");
26 |
27 | const ALGORITHM_NAME = "aes-128-gcm";
28 | const ALGORITHM_NONCE_SIZE = 12;
29 | const ALGORITHM_TAG_SIZE = 16;
30 | const ALGORITHM_KEY_SIZE = 16;
31 | const PBKDF2_NAME = "sha256";
32 | const PBKDF2_SALT_SIZE = 16;
33 | const PBKDF2_ITERATIONS = 32767;
34 |
35 | export class SCEE {
36 | encryptString(plaintext, password) {
37 | // Generate a 128-bit salt using a CSPRNG.
38 | let salt = crypto.randomBytes(PBKDF2_SALT_SIZE);
39 |
40 | // Derive a key using PBKDF2.
41 | let key = crypto.pbkdf2Sync(new Buffer(password, "utf8"), salt, PBKDF2_ITERATIONS, ALGORITHM_KEY_SIZE, PBKDF2_NAME);
42 |
43 | // Encrypt and prepend salt.
44 | let ciphertextAndNonceAndSalt = Buffer.concat([salt, this.encrypt(new Buffer(plaintext, "utf8"), key)]);
45 |
46 | // Return as base64 string.
47 | return ciphertextAndNonceAndSalt.toString("base64");
48 | }
49 |
50 | decryptString(base64CiphertextAndNonceAndSalt, password) {
51 | // Decode the base64.
52 | let ciphertextAndNonceAndSalt = new Buffer(base64CiphertextAndNonceAndSalt, "base64");
53 |
54 | // Create buffers of salt and ciphertextAndNonce.
55 | let salt = ciphertextAndNonceAndSalt.slice(0, PBKDF2_SALT_SIZE);
56 | let ciphertextAndNonce = ciphertextAndNonceAndSalt.slice(PBKDF2_SALT_SIZE);
57 |
58 | // Derive the key using PBKDF2.
59 | let key = crypto.pbkdf2Sync(new Buffer(password, "utf8"), salt, PBKDF2_ITERATIONS, ALGORITHM_KEY_SIZE, PBKDF2_NAME);
60 |
61 | // Decrypt and return result.
62 | return this.decrypt(ciphertextAndNonce, key).toString("utf8");
63 | }
64 |
65 | encrypt(plaintext, key) {
66 | // Generate a 96-bit nonce using a CSPRNG.
67 | let nonce = crypto.randomBytes(ALGORITHM_NONCE_SIZE);
68 |
69 | // Create the cipher instance.
70 | let cipher = crypto.createCipheriv(ALGORITHM_NAME, key, nonce);
71 |
72 | // Encrypt and prepend nonce.
73 | let ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
74 |
75 | return Buffer.concat([nonce, ciphertext, cipher.getAuthTag()]);
76 | }
77 |
78 | decrypt(ciphertextAndNonce, key) {
79 | // Create buffers of nonce, ciphertext and tag.
80 | let nonce = ciphertextAndNonce.slice(0, ALGORITHM_NONCE_SIZE);
81 | let ciphertext = ciphertextAndNonce.slice(ALGORITHM_NONCE_SIZE, ciphertextAndNonce.length - ALGORITHM_TAG_SIZE);
82 | let tag = ciphertextAndNonce.slice(ciphertext.length + ALGORITHM_NONCE_SIZE);
83 |
84 | // Create the cipher instance.
85 | let cipher = crypto.createDecipheriv(ALGORITHM_NAME, key, nonce);
86 |
87 | // Decrypt and return result.
88 | cipher.setAuthTag(tag);
89 | return Buffer.concat([cipher.update(ciphertext), cipher.final()]);
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/i18n/index.js:
--------------------------------------------------------------------------------
1 | import enUS from "./en-us";
2 |
3 | // ADD LANGUAGES HERE
4 | const languages = [
5 | { name: "English", code: "en-us", flag: "gb" },
6 | { name: "Russian", code: "ru", flag: "ru" },
7 | { name: "German", code: "de", flag: "de" },
8 | { name: "French", code: "fr", flag: "fr" },
9 | { name: "Spanish", code: "es", flag: "es" },
10 | { name: "Portuguese", code: "pt-br", flag: "pt" }
11 | ];
12 |
13 | export { languages };
14 |
15 | // DO NOT MODIFY THIS EXPORT, LANGUAGE FILES CAN BE DYNAMICALLY LOADED
16 | export default {
17 | "en-us": enUS
18 | };
19 |
--------------------------------------------------------------------------------
/src/index.template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 | <%= htmlWebpackPlugin.options.productName %>
13 |
14 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/layouts/init/loading.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/layouts/init/welcome.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/layouts/wallet-select/main.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{ page_title }}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/src/layouts/wallet/main.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |

8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
78 |
79 |
134 |
--------------------------------------------------------------------------------
/src/mixins/wallet_password.js:
--------------------------------------------------------------------------------
1 | import { mapState } from "vuex";
2 |
3 | export default {
4 | computed: mapState({
5 | theme: state => state.gateway.app.config.appearance.theme
6 | }),
7 | methods: {
8 | hasPassword() {
9 | // Validate the address
10 | return new Promise(resolve => {
11 | this.$gateway.once("has_password", data => {
12 | resolve(!!data);
13 | });
14 | this.$gateway.send("wallet", "has_password");
15 | });
16 | },
17 |
18 | async showPasswordConfirmation(options) {
19 | const { noPasswordMessage, ...other } = options;
20 | return this.hasPassword()
21 | .then(hasPassword => {
22 | const sharedOpts = {
23 | cancel: {
24 | flat: true,
25 | label: this.$t("dialog.buttons.cancel"),
26 | color: this.theme === "dark" ? "white" : "dark"
27 | },
28 | ...other
29 | };
30 | const hasPasswordOpts = {
31 | ...sharedOpts,
32 | message: this.$t("dialog.password.message"),
33 | prompt: {
34 | model: "",
35 | type: "password"
36 | }
37 | };
38 | const noPasswordOpts = {
39 | ...sharedOpts,
40 | message: noPasswordMessage
41 | };
42 | let usedOpts = hasPassword ? hasPasswordOpts : noPasswordOpts;
43 | return this.$q.dialog(usedOpts);
44 | })
45 | .catch(() => {});
46 | }
47 | }
48 | };
49 |
--------------------------------------------------------------------------------
/src/pages/404.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | internal error
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/pages/init/quit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |

6 |
7 |
8 |
9 |
10 |
11 |
{{ $t("strings.closing") }}...
12 |
13 |
14 |
15 |
16 |
17 |
20 |
21 |
27 |
--------------------------------------------------------------------------------
/src/pages/init/welcome.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |

7 |
Wallet Version: v{{ version }}
8 |
Daemon Version: {{ daemonVersion }}
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
91 |
92 |
138 |
--------------------------------------------------------------------------------
/src/pages/wallet-select/create.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
30 |
31 |
32 |
33 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
176 |
177 |
--------------------------------------------------------------------------------
/src/pages/wallet-select/created.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ walletName }}
5 |
6 |
7 | {{ info.address }}
8 |
9 |
10 |
11 |
12 | {{ $t("menuItems.copyAddress") }}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
{{ $t("strings.seedWords") }}
22 |
23 | {{ secret.mnemonic }}
24 |
25 |
26 | {{ $t("strings.saveSeedWarning") }}
27 |
28 |
29 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | {{ $t("strings.viewKey") }}
43 |
44 |
45 | {{ secret.view_key }}
46 |
47 |
48 |
49 |
50 | {{ $t("menuItems.copyViewKey") }}
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | {{ $t("strings.spendKey") }}
59 |
60 |
61 | {{ secret.spend_key }}
62 |
63 |
64 |
65 |
66 | {{ $t("menuItems.copySpendKey") }}
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
168 |
169 |
211 |
--------------------------------------------------------------------------------
/src/pages/wallet-select/import-legacy.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
25 |
26 |
27 |
28 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/src/pages/wallet-select/import-old-gui.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | {{ state.directory }}
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
132 |
133 |
145 |
--------------------------------------------------------------------------------
/src/pages/wallet-select/import.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
16 |
17 |
25 |
26 |
32 |
33 |
34 |
35 |
44 |
45 |
46 |
47 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
165 |
166 |
180 |
--------------------------------------------------------------------------------
/src/pages/wallet/addressbook.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
15 |
16 | {{ entry.address }}
17 | {{ entry.name }}
18 |
19 |
20 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
52 |
53 |
54 |
55 |
56 |
57 | {{ $t("strings.addressBookIsEmpty") }}
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
156 |
157 |
186 |
--------------------------------------------------------------------------------
/src/pages/wallet/advanced.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
17 |
18 |
19 |
20 |
21 |
22 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/pages/wallet/blank.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/src/pages/wallet/lns.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/pages/wallet/receive.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ $t("strings.addresses.myPrimaryAddress") }}
5 |
16 |
17 |
18 | {{ $t("strings.addresses.myUsedAddresses") }}
19 |
32 |
33 |
34 |
35 | {{ $t("strings.addresses.myUnusedAddresses") }}
36 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
165 |
166 |
200 |
--------------------------------------------------------------------------------
/src/pages/wallet/service-node.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
20 |
21 |
22 |
23 |
24 |
25 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/pages/wallet/txhistory.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ $t("titles.transactions") }}
6 |
7 |
8 |
9 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/src/plugins/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-network/scala-electron-gui/1eea8a5ab48541e4c6c0333316b85e18953d7f29/src/plugins/.gitkeep
--------------------------------------------------------------------------------
/src/plugins/axios.js:
--------------------------------------------------------------------------------
1 | import axios from "axios"
2 |
3 | export default ({
4 | Vue
5 | }) => {
6 | Vue.prototype.$axios = axios
7 | }
8 |
--------------------------------------------------------------------------------
/src/plugins/gateway.js:
--------------------------------------------------------------------------------
1 | import { Gateway } from "src/gateway/gateway"
2 |
3 | /* This plugin gets called early in the life-cycle
4 | In the future, we can detect what platform we
5 | are on and include the correct gateway.
6 |
7 | The gateway just gets stored into the app global
8 | object to be called from anywhere within the
9 | frontend
10 | */
11 |
12 | export default ({
13 | app,
14 | router,
15 | store,
16 | Vue
17 | }) => {
18 | Vue.prototype.$gateway = new Gateway(app, router)
19 | }
20 |
--------------------------------------------------------------------------------
/src/plugins/i18n.js:
--------------------------------------------------------------------------------
1 | import VueI18n from "vue-i18n"
2 | import messages from "src/i18n"
3 | import { Quasar } from "quasar"
4 |
5 | let i18n
6 |
7 | export default ({
8 | app,
9 | Vue
10 | }) => {
11 | Vue.use(VueI18n)
12 |
13 | // Set i18n instance on app
14 | app.i18n = new VueI18n({
15 | locale: "en-us",
16 | fallbackLocale: "en-us",
17 | messages
18 | })
19 |
20 | i18n = app.i18n
21 | }
22 |
23 | const changeLanguage = (lang) => {
24 | const quasarLang = Quasar.i18n.lang
25 | return new Promise((resolve, reject) => {
26 | import(`src/i18n/${lang}`).then(({ default: messages }) => {
27 | i18n.locale = lang
28 | i18n.setLocaleMessage(lang, messages)
29 |
30 | // Setting the quasar language is optional
31 | // There may be cases where they don't have the language
32 | import(`quasar-framework/i18n/${lang}`).then(lang => {
33 | quasarLang.set(lang.default)
34 | }).catch(() => {
35 | console.warn(`Failed to set quasar language: ${lang}`)
36 | }).finally(() => {
37 | resolve(lang)
38 | })
39 | }).catch(() => {
40 | reject(new Error("Language not found"))
41 | })
42 | })
43 | }
44 |
45 | export { i18n, changeLanguage }
46 |
--------------------------------------------------------------------------------
/src/plugins/timeago.js:
--------------------------------------------------------------------------------
1 | import VueTimeago from "vue-timeago"
2 | export default ({
3 | app,
4 | router,
5 | store,
6 | Vue
7 | }) => {
8 | Vue.use(VueTimeago, {
9 | name: "Timeago",
10 | locale: "en",
11 | locales: {
12 | ru: require("date-fns/locale/ru"),
13 | de: require("date-fns/locale/de"),
14 | fr: require("date-fns/locale/fr"),
15 | es: require("date-fns/locale/es"),
16 | pt: require("date-fns/locale/pt")
17 | }
18 | })
19 | }
20 |
--------------------------------------------------------------------------------
/src/plugins/vuelidate.js:
--------------------------------------------------------------------------------
1 | import Vuelidate from "vuelidate"
2 |
3 | export default ({ Vue }) => {
4 | Vue.use(Vuelidate)
5 | }
6 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import VueRouter from "vue-router";
3 |
4 | import routes from "./routes";
5 |
6 | Vue.use(VueRouter);
7 |
8 | const Router = new VueRouter({
9 | /*
10 | * NOTE! Change Vue Router mode from quasar.conf.js -> build -> vueRouterMode
11 | *
12 | * When going with "history" mode, please also make sure "build.publicPath"
13 | * is set to something other than an empty string.
14 | * Example: "/" instead of ""
15 | */
16 |
17 | // Leave as is and change from quasar.conf.js instead!
18 | mode: process.env.VUE_ROUTER_MODE,
19 | base: process.env.VUE_ROUTER_BASE,
20 | scrollBehavior: () => ({
21 | y: 0
22 | }),
23 | routes
24 | });
25 |
26 | export default Router;
27 |
--------------------------------------------------------------------------------
/src/router/routes.js:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | path: "/",
4 | component: () => import("layouts/init/loading"),
5 | children: [
6 | {
7 | path: "",
8 | component: () => import("pages/init/index")
9 | },
10 | {
11 | path: "/quit",
12 | component: () => import("pages/init/quit")
13 | }
14 | ]
15 | },
16 | {
17 | path: "/welcome",
18 | component: () => import("layouts/init/welcome"),
19 | children: [
20 | {
21 | path: "",
22 | component: () => import("pages/init/welcome")
23 | }
24 | ]
25 | },
26 | {
27 | path: "/wallet-select",
28 | component: () => import("layouts/wallet-select/main"),
29 | children: [
30 | {
31 | path: "",
32 | name: "wallet-select",
33 | component: () => import("pages/wallet-select/index")
34 | },
35 | {
36 | path: "create",
37 | name: "wallet-create",
38 | component: () => import("pages/wallet-select/create")
39 | },
40 | {
41 | path: "restore",
42 | name: "wallet-restore",
43 | component: () => import("pages/wallet-select/restore")
44 | },
45 | {
46 | path: "import-view-only",
47 | name: "wallet-import-view-only",
48 | component: () => import("pages/wallet-select/import-view-only")
49 | },
50 | {
51 | path: "import",
52 | name: "wallet-import",
53 | component: () => import("pages/wallet-select/import")
54 | },
55 | {
56 | path: "import-legacy",
57 | name: "wallet-import-legacy",
58 | component: () => import("pages/wallet-select/import-legacy")
59 | },
60 | {
61 | path: "created",
62 | name: "wallet-created",
63 | component: () => import("pages/wallet-select/created")
64 | },
65 | {
66 | path: "import-old-gui",
67 | name: "wallet-import-old-gui",
68 | component: () => import("pages/wallet-select/import-old-gui")
69 | }
70 | ]
71 | },
72 | {
73 | path: "/wallet",
74 | component: () => import("layouts/wallet/main"),
75 | children: [
76 | {
77 | path: "",
78 | component: () => import("pages/wallet/txhistory")
79 | },
80 | {
81 | path: "receive",
82 | component: () => import("pages/wallet/receive")
83 | },
84 | {
85 | path: "send",
86 | component: () => import("pages/wallet/send")
87 | },
88 | {
89 | path: "addressbook",
90 | component: () => import("pages/wallet/addressbook")
91 | },
92 | {
93 | path: "servicenode",
94 | component: () => import("pages/wallet/service-node")
95 | },
96 | {
97 | path: "lns",
98 | component: () => import("pages/wallet/lns")
99 | },
100 | {
101 | path: "advanced",
102 | component: () => import("pages/wallet/advanced")
103 | }
104 | ]
105 | },
106 |
107 | {
108 | // Always leave this as last one
109 | path: "*",
110 | component: () => import("pages/404")
111 | }
112 | ];
113 |
--------------------------------------------------------------------------------
/src/statics/icon_512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scala-network/scala-electron-gui/1eea8a5ab48541e4c6c0333316b85e18953d7f29/src/statics/icon_512x512.png
--------------------------------------------------------------------------------
/src/statics/qr-code-grey.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/statics/qr-code.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/statics/ryo-wallet.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/src/statics/scala.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
56 |
--------------------------------------------------------------------------------
/src/store/gateway/actions.js:
--------------------------------------------------------------------------------
1 | export const resetWalletData = state => {
2 | state.commit("set_wallet_data", {
3 | status: {
4 | code: 1,
5 | message: null
6 | },
7 | info: {
8 | name: "",
9 | address: "",
10 | height: 0,
11 | balance: 0,
12 | unlocked_balance: 0,
13 | view_only: false
14 | },
15 | secret: {
16 | mnemonic: "",
17 | view_key: "",
18 | spend_key: ""
19 | },
20 | transactions: {
21 | tx_list: []
22 | },
23 | address_list: {
24 | used: [],
25 | unused: [],
26 | address_book: []
27 | }
28 | });
29 | };
30 |
31 | export const resetWalletStatus = state => {
32 | state.commit("set_wallet_data", {
33 | status: {
34 | code: 1,
35 | message: null
36 | }
37 | });
38 | };
39 |
40 | export const resetPendingConfig = state => {
41 | state.commit("set_app_data", {
42 | pending_config: state.state.app.config
43 | });
44 | };
45 |
--------------------------------------------------------------------------------
/src/store/gateway/getters.js:
--------------------------------------------------------------------------------
1 | export const isReady = state => {
2 | const { daemons, app } = state.app.config;
3 | const config_daemon = daemons[app.net_type];
4 |
5 | let target_height;
6 | if (config_daemon.type === "local") {
7 | target_height = Math.max(state.daemon.info.height, state.daemon.info.target_height);
8 | } else {
9 | target_height = state.daemon.info.height;
10 | }
11 |
12 | return state.wallet.info.height >= target_height - 1;
13 | };
14 |
15 | export const isAbleToSend = state => {
16 | const { daemons, app } = state.app.config;
17 | const config_daemon = daemons[app.net_type];
18 |
19 | let target_height;
20 | if (config_daemon.type === "local") {
21 | target_height = Math.max(state.daemon.info.height, state.daemon.info.target_height);
22 | } else {
23 | target_height = state.daemon.info.height;
24 | }
25 |
26 | if (config_daemon.type === "local_remote") {
27 | return state.daemon.info.height_without_bootstrap >= target_height && state.wallet.info.height >= target_height - 1;
28 | } else {
29 | return state.wallet.info.height >= target_height - 1;
30 | }
31 | };
32 |
--------------------------------------------------------------------------------
/src/store/gateway/index.js:
--------------------------------------------------------------------------------
1 | import state from "./state";
2 | import * as getters from "./getters";
3 | import * as mutations from "./mutations";
4 | import * as actions from "./actions";
5 |
6 | export default {
7 | namespaced: true,
8 | state,
9 | getters,
10 | mutations,
11 | actions
12 | };
13 |
--------------------------------------------------------------------------------
/src/store/gateway/mutations.js:
--------------------------------------------------------------------------------
1 | const objectAssignDeep = require("object-assign-deep");
2 |
3 | export const set_app_data = (state, data) => {
4 | state.app = objectAssignDeep.noMutate(state.app, data);
5 | };
6 | export const set_daemon_data = (state, data) => {
7 | state.daemon = objectAssignDeep.noMutate(state.daemon, data);
8 | };
9 | export const set_wallet_data = (state, data) => {
10 | state.wallet = objectAssignDeep.noMutate(state.wallet, data);
11 | };
12 | export const set_wallet_list = (state, data) => {
13 | state.wallets = objectAssignDeep.noMutate(state.wallets, data);
14 | };
15 | export const set_old_gui_import_status = (state, data) => {
16 | state.old_gui_import_status = data;
17 | };
18 | export const set_tx_status = (state, data) => {
19 | state.tx_status = data;
20 | };
21 | export const set_snode_status = (state, data) => {
22 | state.service_node_status = objectAssignDeep.noMutate(state.service_node_status, data);
23 | };
24 | export const set_prove_transaction_status = (state, data) => {
25 | state.prove_transaction_status = {
26 | ...state.prove_transaction_status,
27 | ...data
28 | };
29 | };
30 | export const set_check_transaction_status = (state, data) => {
31 | state.check_transaction_status = {
32 | ...state.check_transaction_status,
33 | ...data
34 | };
35 | };
36 | export const set_lns_status = (state, data) => {
37 | state.lns_status = data;
38 | };
39 |
--------------------------------------------------------------------------------
/src/store/gateway/state.js:
--------------------------------------------------------------------------------
1 | export default {
2 | app: {
3 | status: {
4 | code: 1 // Connecting to backend
5 | },
6 | config: {
7 | appearance: {
8 | theme: "dark"
9 | }
10 | },
11 | pending_config: {},
12 | remotes: {}
13 | },
14 | wallets: {
15 | list: [],
16 | legacy: [],
17 |
18 | // List of wallets that are in a sub folder (format of the old GUI)
19 | directories: []
20 | },
21 | old_gui_import_status: {
22 | code: 0, // Success
23 | failed_wallets: []
24 | },
25 | wallet: {
26 | status: {
27 | code: 1,
28 | message: null
29 | },
30 | info: {
31 | name: "",
32 | address: "",
33 | height: 0,
34 | balance: 0,
35 | unlocked_balance: 0,
36 | view_only: false
37 | },
38 | secret: {
39 | mnemonic: "",
40 | view_key: "",
41 | spend_key: ""
42 | },
43 | transactions: {
44 | tx_list: []
45 | },
46 | address_list: {
47 | used: [],
48 | unused: [],
49 | address_book: []
50 | },
51 | lnsRecords: [],
52 | isRPCSyncing: false
53 | },
54 | tx_status: {
55 | code: 0,
56 | message: "",
57 | i18n: "",
58 | sending: false
59 | },
60 | service_node_status: {
61 | stake: {
62 | code: 0,
63 | message: "",
64 | i18n: "",
65 | sending: false
66 | },
67 | registration: {
68 | code: 0,
69 | message: "",
70 | i18n: "",
71 | sending: false
72 | },
73 | unlock: {
74 | code: 0,
75 | message: "",
76 | i18n: "",
77 | sending: false
78 | }
79 | },
80 | prove_transaction_status: {
81 | code: 0,
82 | message: "",
83 | i18n: "",
84 | state: {}
85 | },
86 | check_transaction_status: {
87 | code: 0,
88 | message: "",
89 | i18n: "",
90 | state: {}
91 | },
92 | lns_status: {
93 | code: 0,
94 | message: "",
95 | i18n: "",
96 | sending: false
97 | },
98 | daemon: {
99 | info: {
100 | alt_blocks_count: 0,
101 | cumulative_difficulty: 0,
102 | difficulty: 0,
103 | grey_peerlist_size: 0,
104 | height: 0,
105 | height_without_bootstrap: 0,
106 | incoming_connections_count: 0,
107 | is_ready: false,
108 | outgoing_connections_count: 0,
109 | status: "OK",
110 | target: 240,
111 | target_height: 0,
112 | testnet: false,
113 | top_block_hash: null,
114 | tx_count: 0,
115 | tx_pool_size: 0,
116 | white_peerlist_size: 0
117 | },
118 | connections: [],
119 | bans: [],
120 | tx_pool_backlog: [],
121 | service_nodes: []
122 | }
123 | };
124 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Vuex from "vuex";
3 |
4 | import gateway from "./gateway";
5 |
6 | Vue.use(Vuex);
7 |
8 | const store = new Vuex.Store({
9 | modules: {
10 | gateway
11 | }
12 | });
13 |
14 | export default store;
15 |
--------------------------------------------------------------------------------
/src/store/store-flag.d.ts:
--------------------------------------------------------------------------------
1 | // THIS FEATURE-FLAG FILE IS AUTOGENERATED,
2 | // REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING
3 | import "quasar/dist/types/feature-flag";
4 |
5 | declare module "quasar/dist/types/feature-flag" {
6 | interface QuasarFeatureFlags {
7 | store: true;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/validators/common.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable prefer-promise-reject-errors */
2 |
3 | export const greater_than_zero = input => {
4 | return input > 0;
5 | };
6 |
7 | export const payment_id = input => {
8 | return input.length === 0 || (/^[0-9A-Fa-f]+$/.test(input) && (input.length == 16 || input.length == 64));
9 | };
10 |
11 | export const privkey = input => {
12 | return input.length === 0 || (/^[0-9A-Fa-f]+$/.test(input) && input.length == 64);
13 | };
14 |
15 | export const service_node_key = input => {
16 | return input.length === 64 && /^[0-9A-Za-z]+$/.test(input);
17 | };
18 |
19 | export const session_id = input => {
20 | return input.length == 66 && /^05[0-9A-Za-z]+$/.test(input);
21 | };
22 |
23 | export const lns_name = input => {
24 | return input.length === 0 || /^[a-z0-9_]([a-z0-9-_]*[a-z0-9_])?$/.test(input.toLowerCase());
25 | };
26 |
27 | export const address = (input, gateway) => {
28 | if (!/^[0-9A-Za-z]+$/.test(input)) return false;
29 |
30 | // Validate the address
31 | return new Promise((resolve, reject) => {
32 | gateway.once("validate_address", data => {
33 | if (data.address && data.address !== input) {
34 | reject();
35 | } else {
36 | if (data.valid) {
37 | resolve();
38 | } else {
39 | reject();
40 | }
41 | }
42 | });
43 | gateway.send("wallet", "validate_address", {
44 | address: input
45 | });
46 | });
47 | };
48 |
--------------------------------------------------------------------------------