├── version_build
├── assets
├── deps
│ └── confs
│ │ ├── .tmpmarker
│ │ ├── TAZ_peers.txt
│ │ ├── iguana.conf
│ │ ├── ZEC_peers.txt
│ │ ├── DGB_peers.txt
│ │ ├── GAME_peers.txt
│ │ ├── UNO_peers.txt
│ │ ├── ZET_peers.txt
│ │ ├── BLK_peers.txt
│ │ ├── CARB_peers.txt
│ │ ├── LTC_peers.txt
│ │ ├── KMD_peers.txt
│ │ ├── REVS_peers.txt
│ │ ├── SXC_peers.txt
│ │ ├── SYS_peers.txt
│ │ ├── ANC_peers.txt
│ │ ├── VIA_peers.txt
│ │ ├── BTM_peers.txt
│ │ ├── FRK_peers.txt
│ │ ├── MZC_peers.txt
│ │ ├── BTCD_peers.txt
│ │ └── DOGE_peers.txt
├── js
│ ├── startup.js
│ └── iguana.js
├── .DS_Store
└── icons
│ ├── vrsc.icns
│ ├── vrsc.ico
│ ├── vrsc_256x256x32.png
│ ├── vrsc_512x512x32.png
│ ├── agama_icons
│ ├── 16x16.png
│ ├── 24x24.png
│ ├── 32x32.png
│ ├── 48x48.png
│ ├── 64x64.png
│ ├── 96x96.png
│ ├── vrsc.icns
│ ├── vrsc.ico
│ ├── 128x128.png
│ └── 256x256.png
│ └── vrsc_1024x1024x32.png
├── .DS_Store
├── gui
├── .DS_Store
├── fetch-bootstrap
│ └── fetch-bootstrap.html
└── startup
│ ├── agama-instance-error.html
│ └── app-closing.html
├── routes
├── api
│ ├── utils
│ │ ├── constants
│ │ │ ├── math.js
│ │ │ ├── currency_flags.js
│ │ │ ├── web3.js
│ │ │ ├── index.js
│ │ │ ├── supported_dls.js
│ │ │ ├── dev_options.js
│ │ │ ├── daemons.js
│ │ │ ├── eth_networks.js
│ │ │ ├── urls.js
│ │ │ ├── allowed_paths.js
│ │ │ └── file_descriptors.js
│ │ ├── flags.js
│ │ ├── standardization
│ │ │ ├── standardization.js
│ │ │ ├── standardizeMiningInfo.js
│ │ │ └── standardizeInfo.js
│ │ ├── web3
│ │ │ ├── provider.js
│ │ │ ├── etherscan.js
│ │ │ └── web3Interface.js
│ │ ├── objectUtil
│ │ │ ├── objectUtil.js
│ │ │ ├── flattenObjectProps.js
│ │ │ ├── useStringAsKey.js
│ │ │ ├── removeElementByProperties.js
│ │ │ ├── getBytes.js
│ │ │ ├── addMerge.js
│ │ │ └── deepmerge.js
│ │ ├── cryptoConditions
│ │ │ └── cryptoConditionTxUtil.js
│ │ ├── dialog-shim.js
│ │ ├── unzip.js
│ │ ├── rpc
│ │ │ ├── rpcError.js
│ │ │ └── rpcStatusCodes.js
│ │ ├── hashFile.js
│ │ ├── auth
│ │ │ ├── pluginAuth.js
│ │ │ ├── rpcAuth.js
│ │ │ └── scalar.js
│ │ ├── verifySignature.js
│ │ ├── plugin
│ │ │ ├── builtin.js
│ │ │ └── permissions.js
│ │ ├── request
│ │ │ └── request.js
│ │ └── cache.js
│ ├── native
│ │ ├── verusid
│ │ │ ├── verusid.js
│ │ │ ├── login
│ │ │ │ ├── verifyRequest.js
│ │ │ │ └── signResponse.js
│ │ │ └── provision
│ │ │ │ ├── verifyIdProvisioningResponse.js
│ │ │ │ └── signIdProvisioningRequest.js
│ │ ├── closeoffers.js
│ │ ├── importwallet.js
│ │ ├── setidentitytimelock.js
│ │ ├── exportwallet.js
│ │ ├── makeoffer.js
│ │ ├── takeoffer.js
│ │ ├── currencyGraylist.js
│ │ ├── zoperations.js
│ │ ├── definedchains.js
│ │ ├── estimateConversion.js
│ │ ├── idRevocation.js
│ │ ├── info.js
│ │ ├── blockSubsidy.js
│ │ ├── sendcurrency.js
│ │ ├── getConversionPaths.js
│ │ ├── getBlock.js
│ │ ├── getVdxfId.js
│ │ ├── estimateSendcurrencyFee.js
│ │ ├── reservetransfers.js
│ │ ├── restart.js
│ │ ├── mininginfo.js
│ │ ├── getCurrency.js
│ │ ├── shieldcoinbase.js
│ │ └── cryptoConditions.js
│ ├── electrum
│ │ ├── parseTxAddresses.js
│ │ ├── remove.js
│ │ ├── utils.js
│ │ ├── info.js
│ │ ├── block.js
│ │ ├── proxy.js
│ │ ├── interest.js
│ │ └── addresses.js
│ ├── utility_apis
│ │ ├── alert.js
│ │ ├── pbaas.js
│ │ ├── cache.js
│ │ └── csvExport.js
│ ├── data_files
│ │ ├── secrets.js
│ │ ├── nameCommitments.js
│ │ ├── updateLog.js
│ │ └── backup.js
│ ├── eth
│ │ ├── keys.js
│ │ ├── info.js
│ │ ├── auth.js
│ │ ├── coins.js
│ │ ├── balances.js
│ │ ├── addresses.js
│ │ └── transactions.js
│ ├── focus.js
│ ├── network
│ │ ├── supply
│ │ │ ├── coinSupply.js
│ │ │ ├── vrsc
│ │ │ │ └── vrscCoinSupply.js
│ │ │ └── zec
│ │ │ │ └── zecCoinSupply.js
│ │ └── fees
│ │ │ ├── btc
│ │ │ └── btcFees.js
│ │ │ └── networkFees.js
│ ├── paths.js
│ ├── dlhandler.js
│ ├── numbers.js
│ ├── erc20
│ │ ├── auth.js
│ │ ├── info.js
│ │ ├── addresses.js
│ │ ├── balances.js
│ │ ├── transactions.js
│ │ └── coins.js
│ ├── explorer
│ │ └── remoteExplorers.js
│ ├── appInfo.js
│ ├── getSignatureInfo.js
│ ├── construct.js
│ ├── plugin
│ │ ├── builtin
│ │ │ ├── authenticator.js
│ │ │ └── pbaasvisualizer.js
│ │ └── stop.js
│ ├── downloadUtil.js
│ ├── system.js
│ ├── log.js
│ ├── confMaxconnections.js
│ └── binsUtils.js
├── ipc
│ └── index.js
├── electrumjs
│ ├── electrumjs.networks.js
│ └── electrumServersConfig.js
├── shepherd
│ ├── electrum
│ │ └── csv.js
│ └── deepmerge.js
├── deeplink
│ ├── removelink.js
│ ├── setuplink.js
│ └── openurlhandler.js
├── preloads
│ ├── keys.js
│ └── plugin
│ │ ├── preload-builtin.js
│ │ └── preload-default.js
├── fiatList.js
├── children
│ ├── fetch-bootstrap
│ │ └── window.js
│ └── userAgreement
│ │ └── window.js
├── zcashParamsSources.js
├── ports.js
├── workers
│ └── check_update.js
└── nativeCoind.js
├── Brewfile
├── .gitmodules
├── tslint.json
├── version.json
├── keys
├── infura.js
└── etherscan.js
├── check_submodule.sh
├── fetch-nspv-bins.sh
├── LICENSE
├── .gitignore
├── test
├── verusid-login.js
├── spec-kmd.js
├── spec-vrsc.js
└── spec.js
└── README.md
/version_build:
--------------------------------------------------------------------------------
1 | 1.2.13
--------------------------------------------------------------------------------
/assets/deps/confs/.tmpmarker:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/js/startup.js:
--------------------------------------------------------------------------------
1 | //startup separator for superNET iguana
2 |
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/.DS_Store
--------------------------------------------------------------------------------
/assets/deps/confs/TAZ_peers.txt:
--------------------------------------------------------------------------------
1 | 176.9.26.39
2 | 5.9.102.210
3 | 78.47.196.146
4 |
--------------------------------------------------------------------------------
/assets/deps/confs/iguana.conf:
--------------------------------------------------------------------------------
1 | { "exchanges":[{"name":"poloniex"},{"name":"btc38"}] }
--------------------------------------------------------------------------------
/gui/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/gui/.DS_Store
--------------------------------------------------------------------------------
/assets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/assets/.DS_Store
--------------------------------------------------------------------------------
/assets/icons/vrsc.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/assets/icons/vrsc.icns
--------------------------------------------------------------------------------
/assets/icons/vrsc.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/assets/icons/vrsc.ico
--------------------------------------------------------------------------------
/assets/deps/confs/ZEC_peers.txt:
--------------------------------------------------------------------------------
1 | 198.100.147.192
2 | 159.203.60.92
3 | 188.166.31.56
4 | 46.105.126.215
5 |
--------------------------------------------------------------------------------
/routes/api/utils/constants/math.js:
--------------------------------------------------------------------------------
1 | const SATOSHIS = 100000000
2 |
3 | module.exports = {
4 | SATOSHIS
5 | }
--------------------------------------------------------------------------------
/Brewfile:
--------------------------------------------------------------------------------
1 | tap "homebrew/bundle"
2 | tap "homebrew/cask"
3 | tap "homebrew/core"
4 | brew "gcc@5"
5 | brew "libidn2"
6 |
--------------------------------------------------------------------------------
/assets/icons/vrsc_256x256x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/assets/icons/vrsc_256x256x32.png
--------------------------------------------------------------------------------
/assets/icons/vrsc_512x512x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/assets/icons/vrsc_512x512x32.png
--------------------------------------------------------------------------------
/routes/ipc/index.js:
--------------------------------------------------------------------------------
1 | const { startIPCHandlers } = require('./ipc')
2 |
3 | module.exports = {
4 | startIPCHandlers
5 | }
--------------------------------------------------------------------------------
/assets/icons/agama_icons/16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/assets/icons/agama_icons/16x16.png
--------------------------------------------------------------------------------
/assets/icons/agama_icons/24x24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/assets/icons/agama_icons/24x24.png
--------------------------------------------------------------------------------
/assets/icons/agama_icons/32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/assets/icons/agama_icons/32x32.png
--------------------------------------------------------------------------------
/assets/icons/agama_icons/48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/assets/icons/agama_icons/48x48.png
--------------------------------------------------------------------------------
/assets/icons/agama_icons/64x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/assets/icons/agama_icons/64x64.png
--------------------------------------------------------------------------------
/assets/icons/agama_icons/96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/assets/icons/agama_icons/96x96.png
--------------------------------------------------------------------------------
/assets/icons/agama_icons/vrsc.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/assets/icons/agama_icons/vrsc.icns
--------------------------------------------------------------------------------
/assets/icons/agama_icons/vrsc.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/assets/icons/agama_icons/vrsc.ico
--------------------------------------------------------------------------------
/assets/icons/vrsc_1024x1024x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/assets/icons/vrsc_1024x1024x32.png
--------------------------------------------------------------------------------
/assets/icons/agama_icons/128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/assets/icons/agama_icons/128x128.png
--------------------------------------------------------------------------------
/assets/icons/agama_icons/256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/HEAD/assets/icons/agama_icons/256x256.png
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "gui/Verus-Desktop-GUI"]
2 | path = gui/Verus-Desktop-GUI
3 | url = https://github.com/VerusCoin/Verus-Desktop-GUI
4 |
--------------------------------------------------------------------------------
/routes/electrumjs/electrumjs.networks.js:
--------------------------------------------------------------------------------
1 | let networks = require('agama-wallet-lib/src/bitcoinjs-networks');
2 |
3 | module.exports = networks;
--------------------------------------------------------------------------------
/assets/deps/confs/DGB_peers.txt:
--------------------------------------------------------------------------------
1 | 212.129.1.77
2 | 157.161.128.58
3 | 178.33.228.14
4 | 108.61.10.90
5 | 104.236.32.184
6 | 66.228.56.115
7 | 167.160.36.126
8 |
--------------------------------------------------------------------------------
/assets/deps/confs/GAME_peers.txt:
--------------------------------------------------------------------------------
1 | 46.105.118.15
2 | 89.36.212.56
3 | 85.214.23.49
4 | 194.135.81.138
5 | 111.99.55.252
6 | 104.172.24.79
7 | 104.236.84.230
8 | 104.255.67.131
9 |
--------------------------------------------------------------------------------
/assets/deps/confs/UNO_peers.txt:
--------------------------------------------------------------------------------
1 | 195.154.223.134
2 | 85.25.217.233
3 | 104.172.24.79
4 | 188.165.42.51
5 | 45.32.244.201
6 | 52.23.179.46
7 | 192.95.29.72
8 | 185.50.213.123
9 |
--------------------------------------------------------------------------------
/assets/deps/confs/ZET_peers.txt:
--------------------------------------------------------------------------------
1 | 208.94.242.218
2 | 85.25.217.233
3 | 76.95.178.229
4 | 155.94.243.135
5 | 108.61.10.90
6 | 155.254.49.54
7 | 198.27.81.25
8 | 94.249.166.140
9 |
--------------------------------------------------------------------------------
/routes/api/utils/constants/currency_flags.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | IS_TOKEN_FLAG: 0x20,
3 | IS_FRACTIONAL_FLAG: 0x01,
4 | IS_PBAAS_FLAG: 0x100,
5 | IS_GATEWAY_FLAG: 0x80
6 | }
--------------------------------------------------------------------------------
/assets/deps/confs/BLK_peers.txt:
--------------------------------------------------------------------------------
1 | 188.112.70.36
2 | 1.34.180.245
3 | 104.131.248.191
4 | 104.174.97.3
5 | 104.204.109.11
6 | 106.68.86.178
7 | 108.174.171.46
8 | 108.219.100.78
9 | 112.198.64.34
10 |
--------------------------------------------------------------------------------
/routes/api/native/verusid/verusid.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.native.verusid = {}
3 | api.native.verusid.login = {}
4 | api.native.verusid.provision = {}
5 |
6 | return api;
7 | };
8 |
--------------------------------------------------------------------------------
/routes/shepherd/electrum/csv.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra');
2 | const { secondsToString } = require('agama-wallet-lib/src/time');
3 |
4 | module.exports = (shepherd) => {
5 | return shepherd;
6 | };
--------------------------------------------------------------------------------
/routes/api/utils/flags.js:
--------------------------------------------------------------------------------
1 | // Takes in an integer and checks it against a flag, returns true/false
2 | function checkFlag(integer, flag) {
3 | return (flag & integer) == flag
4 | }
5 |
6 | module.exports = checkFlag
--------------------------------------------------------------------------------
/assets/deps/confs/CARB_peers.txt:
--------------------------------------------------------------------------------
1 | 54.85.71.51
2 | 87.98.182.171
3 | 98.115.147.74
4 | 85.25.146.74
5 | 86.21.79.62
6 | 46.101.43.245
7 | 144.76.64.123
8 | 193.192.37.135
9 | 88.101.128.228
10 | 85.25.201.216
11 | 85.236.188.213
12 |
--------------------------------------------------------------------------------
/routes/deeplink/removelink.js:
--------------------------------------------------------------------------------
1 | const { WALLET_VDXF_KEY } = require("verus-typescript-primitives")
2 |
3 | function removelink(app) {
4 | return app.removeAsDefaultProtocolClient(WALLET_VDXF_KEY.vdxfid)
5 | }
6 |
7 | module.exports = removelink
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultSeverity": "error",
3 | "extends": [
4 | "tslint:recommended"
5 | ],
6 | "jsRules": {},
7 | "rules": {
8 | "no-console": false
9 | },
10 | "rulesDirectory": []
11 | }
--------------------------------------------------------------------------------
/version.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.2.13",
3 | "minVersion": "1.2.9-2",
4 | "versionUrl": "https://raw.githubusercontent.com/VerusCoin/Verus-Desktop/master/version.json",
5 | "repository": "https://github.com/VerusCoin/Verus-Desktop/"
6 | }
7 |
--------------------------------------------------------------------------------
/routes/api/electrum/parseTxAddresses.js:
--------------------------------------------------------------------------------
1 | const parseTransactionAddresses = require('agama-wallet-lib/src/transaction-type');
2 |
3 | module.exports = (api) => {
4 | api.parseTransactionAddresses = parseTransactionAddresses;
5 |
6 | return api;
7 | };
--------------------------------------------------------------------------------
/routes/api/utils/constants/web3.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | TRANSFER_SKIP_CALLSTATIC_TOKENS: ['0xdac17f958d2ee523a2206206994597c13d831ec7'],
3 | CONTRACT_SYMBOLS: {
4 | ["0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2".toLowerCase()]: "MKR"
5 | }
6 | }
--------------------------------------------------------------------------------
/routes/api/utils/constants/index.js:
--------------------------------------------------------------------------------
1 | const allowed_paths = require('./allowed_paths')
2 | const file_descriptors = require('./file_descriptors')
3 | const daemons = require('./daemons')
4 |
5 | module.exports = {
6 | ...allowed_paths,
7 | ...file_descriptors,
8 | ...daemons
9 | }
--------------------------------------------------------------------------------
/assets/deps/confs/LTC_peers.txt:
--------------------------------------------------------------------------------
1 | 37.97.159.116
2 | 5.9.67.48
3 | 86.107.207.194
4 | 46.28.206.204
5 | 91.232.188.3
6 | 209.180.247.49
7 | 61.150.109.231
8 | 24.217.216.92
9 | 219.117.248.55
10 | 131.161.120.110
11 | 122.224.51.104
12 | 78.25.32.206
13 | 46.63.26.63
14 | 200.79.231.62
15 |
--------------------------------------------------------------------------------
/keys/infura.js:
--------------------------------------------------------------------------------
1 | // THIS IS SENSITIVE DATA, DO NOT PUSH TO GIT!
2 |
3 | // API Keys for infura are stored here, if you fork Verus-Desktop, you need to use your
4 | // own here or ETH/ERC20 coins will not work
5 |
6 | module.exports = {
7 | INFURA_PROJECT_ID: process.env.INFURA_PROJECT_ID
8 | }
--------------------------------------------------------------------------------
/keys/etherscan.js:
--------------------------------------------------------------------------------
1 | // THIS IS SENSITIVE DATA, DO NOT PUSH TO GIT!
2 |
3 | // API Keys for etherscan are stored here, if you fork Verus-Desktop, you need to use your
4 | // own here or ETH/ERC20 coins will not work
5 |
6 | module.exports = {
7 | ETHERSCAN_API_KEY: process.env.ETHERSCAN_API_KEY
8 | }
--------------------------------------------------------------------------------
/routes/api/utility_apis/alert.js:
--------------------------------------------------------------------------------
1 | const { dialog } = require("../utils/dialog-shim");
2 |
3 | module.exports = (api, mainWindow) => {
4 | api.alertMainWindow = (messageBoxParams, callback) => {
5 | return dialog.showMessageBox(mainWindow, messageBoxParams, callback)
6 | }
7 |
8 | return api;
9 | };
--------------------------------------------------------------------------------
/assets/deps/confs/KMD_peers.txt:
--------------------------------------------------------------------------------
1 | 148.251.57.148
2 | 149.56.28.84
3 | 176.9.26.39
4 | 94.102.63.199
5 | 5.9.102.210
6 | 88.198.65.74
7 | 94.102.63.200
8 | 78.47.196.146
9 | 104.255.64.3
10 | 221.121.144.140
11 | 103.18.58.150
12 | 103.18.58.146
13 | 213.202.253.10
14 | 185.106.121.32
15 | 27.100.36.201
16 |
--------------------------------------------------------------------------------
/assets/deps/confs/REVS_peers.txt:
--------------------------------------------------------------------------------
1 | 148.251.57.148
2 | 149.56.28.84
3 | 176.9.26.39
4 | 94.102.63.199
5 | 5.9.102.210
6 | 88.198.65.74
7 | 94.102.63.200
8 | 78.47.196.146
9 | 104.255.64.3
10 | 221.121.144.140
11 | 103.18.58.150
12 | 103.18.58.146
13 | 213.202.253.10
14 | 185.106.121.32
15 | 27.100.36.201
16 |
--------------------------------------------------------------------------------
/assets/deps/confs/SXC_peers.txt:
--------------------------------------------------------------------------------
1 | 104.238.221.17:16814
2 | 148.163.102.28:16814
3 | 167.160.36.152:16814
4 | 192.227.158.136:16814
5 | 213.46.197.237:16814
6 | 87.204.149.94:16814
7 | 45.43.26.103:16814
8 | 172.110.18.177:16814
9 | 172.110.18.178:16814
10 | 185.116.238.204:16814
11 | 84.242.207.225:16814
12 |
--------------------------------------------------------------------------------
/routes/api/utils/constants/supported_dls.js:
--------------------------------------------------------------------------------
1 | const { LOGIN_CONSENT_REQUEST_VDXF_KEY } = require("verus-typescript-primitives")
2 |
3 | const CALLBACK_HOST = 'x-callback-url'
4 |
5 | const SUPPORTED_DLS = [LOGIN_CONSENT_REQUEST_VDXF_KEY.vdxfid]
6 |
7 | module.exports = {
8 | SUPPORTED_DLS,
9 | CALLBACK_HOST
10 | }
--------------------------------------------------------------------------------
/routes/api/utils/constants/dev_options.js:
--------------------------------------------------------------------------------
1 | const IS_TESTNET = false;
2 | const ROOT_SYSTEM_ID = IS_TESTNET ? "iJhCezBExJHvtyH3fGhNnt2NhU4Ztkf2yq" : "i5w5MuNik5NtLcYmNzcvaoixooEebB6MGV";
3 | const ROOT_SYSTEM_NAME = IS_TESTNET ? "VRSCTEST" : "VRSC";
4 |
5 | module.exports = {
6 | IS_TESTNET,
7 | ROOT_SYSTEM_ID,
8 | ROOT_SYSTEM_NAME
9 | }
--------------------------------------------------------------------------------
/routes/preloads/keys.js:
--------------------------------------------------------------------------------
1 | const { randomBytes } = require('crypto');
2 |
3 | const MasterSecret = randomBytes(32).toString('hex')
4 | const BuiltinSecret = randomBytes(32).toString('hex')
5 | const apiShieldKey = randomBytes(32).toString('hex')
6 |
7 | module.exports = {
8 | MasterSecret,
9 | apiShieldKey,
10 | BuiltinSecret
11 | }
--------------------------------------------------------------------------------
/routes/api/utils/standardization/standardization.js:
--------------------------------------------------------------------------------
1 | const standardizeMiningInfo = require('./standardizeMiningInfo')
2 | const standardizeInfo = require('./standardizeInfo')
3 | const standardizeEthTxObj = require('./standardizeEthTxObj')
4 |
5 | module.exports = {
6 | standardizeMiningInfo,
7 | standardizeInfo,
8 | standardizeEthTxObj
9 | }
--------------------------------------------------------------------------------
/routes/api/utils/constants/daemons.js:
--------------------------------------------------------------------------------
1 | const VERUS_DAEMON = 'verusd';
2 | const KOMODO_DAEMON = 'komodod';
3 | const PIRATE_DAEMON = 'pirated';
4 |
5 | const DAEMON_NAMES = [
6 | VERUS_DAEMON,
7 | KOMODO_DAEMON,
8 | PIRATE_DAEMON
9 | ];
10 |
11 | module.exports = {
12 | VERUS_DAEMON,
13 | KOMODO_DAEMON,
14 | PIRATE_DAEMON,
15 | DAEMON_NAMES
16 | }
--------------------------------------------------------------------------------
/routes/api/data_files/secrets.js:
--------------------------------------------------------------------------------
1 | const { BUILTIN_SECRET, BUILTIN_SECRET_DESC } = require('../utils/constants/index')
2 |
3 | module.exports = (api) => {
4 | api.loadBuiltinSecret = () => api.loadJsonFile(BUILTIN_SECRET, BUILTIN_SECRET_DESC, 0o600);
5 | api.saveBuiltinSecret = (secrets) => api.saveJsonFile(secrets, BUILTIN_SECRET, BUILTIN_SECRET_DESC, 0o600);
6 |
7 | return api;
8 | };
--------------------------------------------------------------------------------
/routes/api/utils/constants/eth_networks.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | ETH_HOMESTEAD: {
3 | key: "homestead",
4 | id: 1
5 | },
6 | ETH_ROPSTEN: {
7 | key: "ropsten",
8 | id: 3
9 | },
10 | ETH_RINKEBY: {
11 | key: "rinkeby",
12 | id: 4
13 | },
14 | ETH_GOERLI: {
15 | key: "goerli",
16 | id: 5
17 | },
18 | ETH_KOVAN: {
19 | key: "kovan",
20 | id: 42
21 | }
22 | }
--------------------------------------------------------------------------------
/routes/api/data_files/nameCommitments.js:
--------------------------------------------------------------------------------
1 | const { NAME_COMMITMENTS, NAME_COMMITMENTS_DESC } = require('../utils/constants/index')
2 |
3 | module.exports = (api) => {
4 | api.loadLocalCommitments = () =>
5 | api.loadJsonFile(NAME_COMMITMENTS, NAME_COMMITMENTS_DESC);
6 | api.saveLocalCommitments = (commitments) =>
7 | api.saveJsonFile(commitments, NAME_COMMITMENTS, NAME_COMMITMENTS_DESC);
8 |
9 | return api;
10 | };
--------------------------------------------------------------------------------
/routes/api/utils/web3/provider.js:
--------------------------------------------------------------------------------
1 | const Web3Interface = require('./web3Interface')
2 | const { ETHERSCAN_API_KEY } = require('../../../../keys/etherscan')
3 | const { INFURA_PROJECT_ID } = require('../../../../keys/infura')
4 |
5 | const createInterface = (network) => {
6 | return new Web3Interface(network, {
7 | etherscan: ETHERSCAN_API_KEY,
8 | infura: INFURA_PROJECT_ID
9 | })
10 | }
11 |
12 | module.exports = createInterface
--------------------------------------------------------------------------------
/assets/js/iguana.js:
--------------------------------------------------------------------------------
1 | //SuperNET iguana app launcher
2 |
3 | //var exec = require('child_process').exec
4 | //exec does not return obj with stream but instead the whole buffer output from proc
5 | //spawn returns objects with stderr and out streams
6 | //for question contact ca333@keemail.me
7 |
8 | const spawn = require('child_process').spawn;
9 | var iguana = path.join(__dirname, '/assets/iguana/iguana');
10 | //var os = require('os');
11 |
--------------------------------------------------------------------------------
/routes/api/eth/keys.js:
--------------------------------------------------------------------------------
1 | const {
2 | etherKeys,
3 | seedToPriv,
4 | } = require('agama-wallet-lib/src/keys');
5 |
6 | module.exports = (api) => {
7 | api.eth._keys = (seed) => {
8 | seed = seedToPriv(seed, 'eth');
9 | const signer = etherKeys(seed, true)
10 |
11 | return {
12 | address: signer.signingKey.address,
13 | pub: signer.signingKey.publicKey,
14 | signer
15 | }
16 | };
17 |
18 | return api;
19 | };
--------------------------------------------------------------------------------
/routes/api/utils/constants/urls.js:
--------------------------------------------------------------------------------
1 | const VERUS_WIKI_WALLET_BACKUPS = "https://wiki.verus.io/#!how-to/how-to_backup_my_wallet.md"
2 | const VERUS_DISCORD = 'https://discord.gg/VRKMP2S'
3 | const VERUS_WIKI = 'https://wiki.verus.io/#!index.md'
4 | const VERUS_DESKTOP_UPDATE_DL = "https://verus.io/wallet/desktop-wallet"
5 |
6 | module.exports = {
7 | VERUS_DESKTOP_UPDATE_DL,
8 | VERUS_WIKI,
9 | VERUS_DISCORD,
10 | VERUS_WIKI_WALLET_BACKUPS
11 | }
--------------------------------------------------------------------------------
/routes/api/utils/objectUtil/objectUtil.js:
--------------------------------------------------------------------------------
1 | const addMerge = require('./addMerge')
2 | const deepmerge = require('./deepmerge')
3 | const flattenObjectProps = require('./flattenObjectProps')
4 | const removeElementByProperties = require('./removeElementByProperties')
5 | const useStringAsKey = require('./useStringAsKey')
6 |
7 | module.exports = {
8 | addMerge,
9 | deepmerge,
10 | flattenObjectProps,
11 | removeElementByProperties,
12 | useStringAsKey
13 | }
--------------------------------------------------------------------------------
/assets/deps/confs/SYS_peers.txt:
--------------------------------------------------------------------------------
1 | 176.9.13.13
2 | 162.210.92.46
3 | 146.0.32.101
4 | 144.76.94.38
5 | 50.157.173.168
6 | 188.165.3.6
7 | 88.198.15.19
8 | 192.95.29.72
9 | 108.61.10.90
10 | 71.97.31.194
11 | 40.86.87.8
12 | 45.79.215.60
13 | 97.124.163.6
14 | 192.241.200.33
15 | 184.164.147.82
16 | 162.243.59.178
17 | 107.178.109.224
18 | 198.15.127.242
19 | 98.115.147.74
20 | 194.135.90.38
21 | 86.131.170.245
22 | 107.170.185.5
23 | 216.14.119.170
24 | 108.170.26.210
25 | 183.131.213.30
26 |
--------------------------------------------------------------------------------
/assets/deps/confs/ANC_peers.txt:
--------------------------------------------------------------------------------
1 | 84.73.4.183
2 | 98.115.147.74
3 | 192.241.187.222
4 | 159.203.208.102
5 | 85.25.44.119
6 | 178.32.251.114
7 | 109.155.227.178
8 | 146.0.32.101
9 | 108.61.10.90
10 | 198.27.82.134
11 | 80.74.157.31
12 | 192.241.183.16
13 | 164.132.25.194
14 | 128.199.47.200
15 | 173.255.197.64
16 | 46.101.136.168
17 | 207.192.70.250
18 | 54.201.183.106
19 | 211.149.175.37
20 | 128.199.192.241
21 | 216.146.143.177
22 | 82.164.213.27
23 | 107.170.167.218
24 | 195.154.223.134
25 |
--------------------------------------------------------------------------------
/assets/deps/confs/VIA_peers.txt:
--------------------------------------------------------------------------------
1 | 84.73.4.183
2 | 98.115.147.74
3 | 192.241.187.222
4 | 159.203.208.102
5 | 85.25.44.119
6 | 178.32.251.114
7 | 109.155.227.178
8 | 146.0.32.101
9 | 108.61.10.90
10 | 198.27.82.134
11 | 80.74.157.31
12 | 192.241.183.16
13 | 164.132.25.194
14 | 128.199.47.200
15 | 173.255.197.64
16 | 46.101.136.168
17 | 207.192.70.250
18 | 54.201.183.106
19 | 211.149.175.37
20 | 128.199.192.241
21 | 216.146.143.177
22 | 82.164.213.27
23 | 107.170.167.218
24 | 195.154.223.134
25 |
--------------------------------------------------------------------------------
/check_submodule.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | ### Script will check Verus-Desktop-GUI submodule in gui folder.
3 | ### If you used git clone without --recursive option this is way to go.
4 |
5 | PWD=`pwd`
6 | SIZE=`du -sk gui/Verus-Desktop-GUI`
7 |
8 | echo "Checking Verus-Desktop-GUI folder."
9 | cd gui/Verus-Desktop-GUI && \
10 | git submodule update --recursive && \
11 | cd ../.. && \
12 | echo "Folder looks fine." || \
13 | echo "Some problem with cloning submodule Verus-Desktop-GUI."
14 | echo
15 |
--------------------------------------------------------------------------------
/assets/deps/confs/BTM_peers.txt:
--------------------------------------------------------------------------------
1 | 70.168.53.153:9265
2 | 146.0.32.101:9265
3 | 24.143.47.161:9265
4 | 139.162.128.92:9265
5 | 85.24.169.215:9265
6 | 98.115.147.74:9265
7 | 192.124.224.254:9265
8 | 45.33.65.161:9265
9 | 184.166.27.254:9265
10 | 139.59.160.118:9265
11 | 98.127.109.96:9265
12 | 101.173.200.202:9265
13 | 157.161.128.55:9265
14 | 104.172.24.79:9265
15 | 158.69.216.182:9265
16 | 72.209.139.213:9265
17 | 198.205.118.181:9265
18 | 101.173.197.85:9265
19 | 174.36.9.130:9265
20 | 84.24.208.22:9265
21 |
--------------------------------------------------------------------------------
/routes/api/utils/cryptoConditions/cryptoConditionTxUtil.js:
--------------------------------------------------------------------------------
1 | // TODO: Fix and move to cryptoConditions native file
2 |
3 | const extractReserveTransfers = (txJson) => {
4 | let transfers = []
5 |
6 | txJson.vout.map(output => {
7 | if (output.scriptPubKey.type === 'cryptocondition' && output.scriptPubKey["reservetransfer"] != null) {
8 | transfers.push(output.scriptPubKey.reservetransfer)
9 | }
10 | })
11 |
12 | return transfers;
13 | }
14 |
15 | module.exports = { extractReserveTransfers }
--------------------------------------------------------------------------------
/routes/fiatList.js:
--------------------------------------------------------------------------------
1 | const fiatList = [
2 | 'usd',
3 | 'eur',
4 | 'aud',
5 | 'brl',
6 | 'gbp',
7 | 'bgn',
8 | 'cad',
9 | 'hrk',
10 | 'czk',
11 | 'cny',
12 | 'dkk',
13 | 'hkd',
14 | 'huf',
15 | 'inr',
16 | 'idr',
17 | 'ils',
18 | 'jpy',
19 | 'krw',
20 | 'myr',
21 | 'mxn',
22 | 'nzd',
23 | 'nok',
24 | 'php',
25 | 'pln',
26 | 'ron',
27 | 'rub',
28 | 'sgd',
29 | 'zar',
30 | 'sek',
31 | 'chf',
32 | 'thb',
33 | 'try'
34 | ];
35 |
36 | module.exports = fiatList;
--------------------------------------------------------------------------------
/routes/api/focus.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.setupFocusApis = (focusFunction) => {
3 | api.focusApp = focusFunction
4 |
5 | api.setPost('/plugin/focus', async (req, res, next) => {
6 | try {
7 | api.focusApp()
8 |
9 | res.send(JSON.stringify({
10 | msg: 'success'
11 | }))
12 | } catch(e) {
13 | res.send(JSON.stringify({
14 | msg: 'error',
15 | error: e.message
16 | }))
17 | }
18 | });
19 | }
20 |
21 | return api;
22 | };
--------------------------------------------------------------------------------
/routes/deeplink/setuplink.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const { WALLET_VDXF_KEY } = require('verus-typescript-primitives');
3 |
4 | function setuplink(app) {
5 | let res;
6 |
7 | if (process.defaultApp) {
8 | if (process.argv.length >= 2) {
9 | res = app.setAsDefaultProtocolClient(WALLET_VDXF_KEY.vdxfid, process.execPath, [path.resolve(process.argv[1])])
10 | }
11 | } else {
12 | res = app.setAsDefaultProtocolClient(WALLET_VDXF_KEY.vdxfid)
13 | }
14 |
15 | return res
16 | }
17 |
18 | module.exports = setuplink
--------------------------------------------------------------------------------
/fetch-nspv-bins.sh:
--------------------------------------------------------------------------------
1 | mkdir assets/bin
2 | mkdir assets/bin/win64
3 | mkdir assets/bin/linux64
4 | mkdir assets/bin/osx
5 | cd assets/bin/win64
6 | wget https://github.com/pbca26/libnspv/releases/download/v0.3/nspv-win.tar
7 | tar -xvf nspv-win.tar
8 | rm nspv-win.tar
9 | cd ../linux64
10 | wget https://github.com/pbca26/libnspv/releases/download/v0.3/nspv-linux.tar
11 | tar -xvf nspv-linux.tar
12 | rm nspv-linux.tar
13 | cd ../osx
14 | wget https://github.com/pbca26/libnspv/releases/download/v0.3/nspv-osx.tar
15 | tar -xvf nspv-osx.tar
16 | rm nspv-osx.tar
--------------------------------------------------------------------------------
/routes/api/network/supply/coinSupply.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = (api) => {
3 | api.get_coinsupply = (chainTicker) => {
4 | if (api.coinSupply[chainTicker] != null) {
5 | return new Promise(async (resolve, reject) => {
6 | api.coinSupply[chainTicker]()
7 | .then(coinSupply => resolve(coinSupply))
8 | .catch(e => reject(e))
9 | })
10 | } else {
11 | return new Promise((resolve, reject) => reject(new Error(`HTTP/HTTPS coin supply function not found for ${chainTicker}`)))
12 | }
13 | }
14 |
15 | return api;
16 | };
--------------------------------------------------------------------------------
/routes/api/electrum/remove.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.setPost('/electrum/remove_coin', (req, res) => {
3 | const _chain = req.body.chainTicker;
4 | delete api.electrum.coinData[_chain.toLowerCase()];
5 |
6 | if (Object.keys(api.electrum.coinData).length === 0) {
7 | api.electrumKeys = {};
8 | }
9 |
10 | api.eclManagerClear(_chain.toLowerCase());
11 |
12 | const retObj = {
13 | msg: 'success',
14 | result: true,
15 | };
16 |
17 | res.send(JSON.stringify(retObj));
18 | });
19 |
20 | return api;
21 | };
22 |
--------------------------------------------------------------------------------
/routes/api/utility_apis/pbaas.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | // TODO: Expand to work beyond just native mode
3 | api.is_pbaas = (chainTicker) => {
4 | return (
5 | chainTicker !== "VRSC" &&
6 | (api.native.launchConfigs[chainTicker] != null
7 | ? api.native.launchConfigs[chainTicker].daemon != null &&
8 | api.native.launchConfigs[chainTicker].daemon === "verusd"
9 | : false)
10 | );
11 | };
12 |
13 | api.is_vrsc = (chainTicker) => {
14 | return (chainTicker === "VRSC");
15 | };
16 |
17 | return api;
18 | };
19 |
--------------------------------------------------------------------------------
/routes/api/utils/dialog-shim.js:
--------------------------------------------------------------------------------
1 | // Shim for using old electron dialog format with new electron
2 | const { dialog } = require('electron');
3 |
4 | async function showMessageBox(browserWindow, options, callback) {
5 | const res = await dialog.showMessageBox(browserWindow, options)
6 |
7 | if (callback) callback(res.response, res.checkboxChecked)
8 | }
9 |
10 | async function showOpenDialog(browserWindow, options, callback) {
11 | const res = await dialog.showOpenDialog(browserWindow, options)
12 |
13 | if (callback) callback(res.filePaths)
14 | }
15 |
16 | module.exports = {
17 | dialog: {
18 | showOpenDialog,
19 | showMessageBox
20 | }
21 | }
--------------------------------------------------------------------------------
/routes/api/utils/unzip.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const unzip = require('unzipper')
3 |
4 | function unzipFile(input, output) {
5 | return new Promise((resolve, reject) => {
6 | try {
7 | const s = fs.createReadStream(input)
8 |
9 | const pipe = s.pipe(unzip.Extract({ path: output }))
10 |
11 | pipe.on('close', function () {
12 | return resolve();
13 | })
14 |
15 | pipe.on('error', function(error) {
16 | s.destroy(error)
17 | return reject(error)
18 | });
19 | } catch (error) {
20 | return reject(error);
21 | }
22 | });
23 | }
24 |
25 | module.exports = {
26 | unzipFile
27 | }
--------------------------------------------------------------------------------
/routes/api/utils/objectUtil/flattenObjectProps.js:
--------------------------------------------------------------------------------
1 | const flattenObjectProps = (obj) => {
2 | const isNonEmptyObject = val => typeof val === "object" && !Array.isArray(val) && Object.values(val).length > 0;
3 |
4 | const addDelimiter = (a, b) => (a ? `${a}.${b}` : b);
5 |
6 | const paths = (obj = {}, head = "") => {
7 | return Object.entries(obj).reduce((product, [key, value]) => {
8 | let fullPath = addDelimiter(head, key);
9 | return isNonEmptyObject(value)
10 | ? product.concat(paths(value, fullPath))
11 | : product.concat(fullPath);
12 | }, []);
13 | };
14 |
15 | return paths(obj);
16 | }
17 |
18 | module.exports = flattenObjectProps
--------------------------------------------------------------------------------
/routes/api/utils/rpc/rpcError.js:
--------------------------------------------------------------------------------
1 | const { RPC_ERROR_UNKNOWN } = require("./rpcStatusCodes")
2 |
3 | class RpcError extends Error {
4 | constructor(code = RPC_ERROR_UNKNOWN, ...params) {
5 | // Pass remaining arguments (including vendor specific ones) to parent constructor
6 | super(...params)
7 |
8 | // Maintains proper stack trace for where our error was thrown (only available on V8)
9 | if (Error.captureStackTrace) {
10 | Error.captureStackTrace(this, RpcError)
11 | }
12 |
13 | this.name = 'RpcError'
14 | // Custom debugging information
15 | this.code = code
16 | this.timestamp = (new Date()).getTime()
17 | }
18 | }
19 |
20 | module.exports = RpcError
--------------------------------------------------------------------------------
/routes/api/utils/hashFile.js:
--------------------------------------------------------------------------------
1 | const crypto = require('crypto'), fs = require('fs')
2 |
3 | function hashFile(filename, algorithm = 'sha256') {
4 | return new Promise((resolve, reject) => {
5 | let crypto_hash = crypto.createHash(algorithm);
6 |
7 | try {
8 | let stream = fs.ReadStream(filename)
9 |
10 | stream.on('data', function (data) {
11 | crypto_hash.update(data)
12 | })
13 |
14 | stream.on('end', function () {
15 | const hash = crypto_hash.digest('hex')
16 | return resolve(hash);
17 | })
18 |
19 | } catch (error) {
20 | return reject(error);
21 | }
22 | });
23 | }
24 |
25 | module.exports = {
26 | hashFile
27 | }
--------------------------------------------------------------------------------
/routes/api/native/closeoffers.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.native.closeoffers = async (chain, offers = []) => {
3 | return await api.native.callDaemon(chain, "closeoffers", [offers]);
4 | };
5 |
6 | api.setPost("/native/closeoffers", async (req, res, next) => {
7 | try {
8 | res.send(
9 | JSON.stringify({
10 | msg: "success",
11 | result: await api.native.closeoffers(req.body.chain, req.body.offers),
12 | })
13 | );
14 | } catch (e) {
15 | res.send(
16 | JSON.stringify({
17 | msg: "error",
18 | result: e.message,
19 | })
20 | );
21 | }
22 | });
23 |
24 | return api;
25 | };
26 |
--------------------------------------------------------------------------------
/routes/api/paths.js:
--------------------------------------------------------------------------------
1 | const {
2 | pathsAgama,
3 | pathsDaemons,
4 | setDaemonPath,
5 | setCoinDir
6 | } = require('./pathsUtil');
7 | const path = require('path');
8 | const fixPath = require('fix-path');
9 | const os = require('os');
10 |
11 | module.exports = (api) => {
12 | api.pathsAgama = () => {
13 | api = pathsAgama(api, global.HOME);
14 | }
15 |
16 | api.pathsDaemons = () => {
17 | api = pathsDaemons(api);
18 | }
19 |
20 | api.setDaemonPath = (daemonName) => {
21 | api = setDaemonPath(api, daemonName);
22 | }
23 |
24 | api.setCoinDir = (coin, dirNames, absolute = false) => {
25 | api = setCoinDir(api, coin, dirNames, absolute)
26 | }
27 |
28 | return api;
29 | };
--------------------------------------------------------------------------------
/routes/api/native/importwallet.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.native.importwallet = async (chain, filename) => {
3 | return await api.native.callDaemon(chain, "z_importwallet", [filename]);
4 | }
5 |
6 | api.setPost('/native/importwallet', async (req, res, next) => {
7 | const { chain, filename } = req.body;
8 |
9 | try {
10 | res.send(
11 | JSON.stringify({
12 | msg: "success",
13 | result: await api.native.importwallet(chain, filename),
14 | })
15 | );
16 | } catch (e) {
17 | res.send(JSON.stringify({
18 | msg: "error",
19 | result: e.message
20 | }));
21 | }
22 | });
23 |
24 | return api;
25 | };
--------------------------------------------------------------------------------
/routes/api/utils/auth/pluginAuth.js:
--------------------------------------------------------------------------------
1 | var blake2b = require('blake2b')
2 | const crypto = require('crypto')
3 |
4 | function generateAppSecret (permissions, masterSecret, appId) {
5 | let permissionsHashable = [...permissions]
6 | permissionsHashable.sort()
7 |
8 | var appSecret = blake2b(64)
9 | const handler = crypto.randomBytes(32)
10 |
11 | permissionsHashable.forEach(value => appSecret.update(Buffer.from(value)))
12 | appSecret.update(Buffer.from(masterSecret))
13 | appSecret.update(Buffer.from(appId))
14 | appSecret.update(Buffer.from(handler))
15 |
16 | return {
17 | secret: appSecret.digest('hex'),
18 | handler
19 | }
20 | }
21 |
22 | module.exports = {
23 | generateAppSecret
24 | }
--------------------------------------------------------------------------------
/routes/children/fetch-bootstrap/window.js:
--------------------------------------------------------------------------------
1 | const { dialog } = require('electron')
2 |
3 | async function canFetchBootstrap(chainTicker) {
4 | const supportedChains = [
5 | 'VRSC',
6 | 'VRSCTEST',
7 | 'VARRR',
8 | 'VDEX',
9 | 'CHIPS'
10 | ];
11 | return supportedChains.includes(chainTicker)
12 | ? (
13 | await dialog.showMessageBox({
14 | type: "question",
15 | title: `Bootstrap ${chainTicker}?`,
16 | message: `Would you like to speed up syncing to the ${chainTicker} blockchain by downloading blockchain data from the internet?`,
17 | buttons: ["Yes", "No"],
18 | })
19 | ).response === 0
20 | : false;
21 | }
22 |
23 | module.exports = {
24 | canFetchBootstrap,
25 | }
--------------------------------------------------------------------------------
/routes/api/native/setidentitytimelock.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.native.setidentitytimelock = async (chain, identity, lock) => {
3 | return await api.native.callDaemon(chain, "setidentitytimelock", [identity, lock]);
4 | }
5 |
6 | api.setPost('/native/setidentitytimelock', async (req, res, next) => {
7 | const { chain, identity, lock } = req.body;
8 |
9 | try {
10 | res.send(
11 | JSON.stringify({
12 | msg: "success",
13 | result: await api.native.setidentitytimelock(chain, identity, lock),
14 | })
15 | );
16 | } catch (e) {
17 | res.send(JSON.stringify({
18 | msg: "error",
19 | result: e.message
20 | }));
21 | }
22 | });
23 |
24 | return api;
25 | };
--------------------------------------------------------------------------------
/routes/api/utils/standardization/standardizeMiningInfo.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Standardizes the behaviour of the mining info object when passed in from
3 | * the KMD or VRSC daemon, so GUI can expect standard behaviour.
4 | *
5 | * @param {Object} mininginfo The mining info result object to standardize
6 | */
7 | const standardizeMiningInfo = (mininginfo) => {
8 | if (mininginfo.localsolps != null && mininginfo.localhashps == null)
9 | mininginfo.localhashps = mininginfo.localsolps;
10 |
11 | if (mininginfo.numthreads == null && mininginfo.genproclimit != null) {
12 | mininginfo.numthreads = mininginfo.genproclimit
13 | }
14 |
15 | if (mininginfo.numthreads === -1) mininginfo.numthreads = 0
16 |
17 | return mininginfo
18 | }
19 |
20 | module.exports = standardizeMiningInfo
--------------------------------------------------------------------------------
/routes/api/native/exportwallet.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.native.exportwallet = async (chain, filename, omitemptyaddresses) => {
3 | return await api.native.callDaemon(chain, "z_exportwallet", [filename, omitemptyaddresses]);
4 | }
5 |
6 | api.setPost('/native/exportwallet', async (req, res, next) => {
7 | const { chain, filename, omitemptyaddresses } = req.body;
8 |
9 | try {
10 | res.send(
11 | JSON.stringify({
12 | msg: "success",
13 | result: await api.native.exportwallet(chain, filename, omitemptyaddresses),
14 | })
15 | );
16 | } catch (e) {
17 | res.send(JSON.stringify({
18 | msg: "error",
19 | result: e.message
20 | }));
21 | }
22 | });
23 |
24 | return api;
25 | };
--------------------------------------------------------------------------------
/routes/api/native/makeoffer.js:
--------------------------------------------------------------------------------
1 | const { MakeOfferRequest, MakeOfferResponse } = require("verus-typescript-primitives");
2 |
3 | module.exports = (api) => {
4 | api.native.makeoffer = async (offer) => {
5 | return await api.native.callDaemon(...(offer.prepare()));
6 | }
7 |
8 | api.setPost('/native/makeoffer', async (req, res, next) => {
9 | const offer = MakeOfferRequest.fromJson(req.body)
10 |
11 | try {
12 | res.send(
13 | JSON.stringify({
14 | msg: "success",
15 | result: new MakeOfferResponse(await api.native.makeoffer(offer)).toJson(),
16 | })
17 | );
18 | } catch (e) {
19 | res.send(JSON.stringify({
20 | msg: "error",
21 | result: e.message
22 | }));
23 | }
24 | });
25 |
26 | return api;
27 | };
--------------------------------------------------------------------------------
/routes/api/eth/info.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.setGet('/eth/get_info', (req, res, next) => {
3 | let retObj = {}
4 |
5 | try {
6 | const { network } = api.eth.get_info()
7 |
8 | retObj = {
9 | msg: 'success',
10 | result: {
11 | network: network.key,
12 | chainId: network.id
13 | }
14 | }
15 | } catch (e) {
16 | retObj = {
17 | msg: 'error',
18 | result: e.message
19 | }
20 | }
21 |
22 | res.send(JSON.stringify(retObj));
23 | });
24 |
25 | api.eth.get_info = () => {
26 | if (api.eth.interface != null) {
27 | return api.eth.interface.getInfo()
28 | } else {
29 | throw new Error('No interface to connect to ETH for getinfo call')
30 | }
31 | }
32 |
33 | return api;
34 | };
--------------------------------------------------------------------------------
/routes/api/utils/constants/allowed_paths.js:
--------------------------------------------------------------------------------
1 | // Identities
2 | const NAME_COMMITMENTS = 'nameCommits.json'
3 |
4 | // API Secrets
5 | const BUILTIN_SECRET = 'builtinsecret.json'
6 |
7 | // Currencies
8 | const CURRENCY_BLACKLIST = 'shepherd/currencies/blacklist.json'
9 | const CURRENCY_WHITELIST = 'shepherd/currencies/whitelist.json'
10 | const CURRENCY_GRAYLIST = 'shepherd/currencies/graylist.json'
11 |
12 | // Updates
13 | const UPDATE_LOG = 'updatelog.json'
14 |
15 | const ALLOWED_PATHS_ARR = [
16 | NAME_COMMITMENTS,
17 | CURRENCY_BLACKLIST,
18 | CURRENCY_GRAYLIST,
19 | CURRENCY_WHITELIST,
20 | UPDATE_LOG,
21 | BUILTIN_SECRET
22 | ];
23 |
24 | module.exports = {
25 | NAME_COMMITMENTS,
26 | CURRENCY_BLACKLIST,
27 | CURRENCY_GRAYLIST,
28 | CURRENCY_WHITELIST,
29 | ALLOWED_PATHS_ARR,
30 | UPDATE_LOG,
31 | BUILTIN_SECRET
32 | }
--------------------------------------------------------------------------------
/routes/api/utils/objectUtil/useStringAsKey.js:
--------------------------------------------------------------------------------
1 | //ref: https://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key
2 | /**
3 | * Uses a string as a key to search through an object and find a property.
4 | * E.g. the string "animalNoises.cat" would return "meow" on { animalNoises: { cat: "meow" }}
5 | * @param {Object} o The object to search through
6 | * @param {String} s The string to use as a key
7 | */
8 | const useStringAsKey = (o, s) => {
9 | s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
10 | s = s.replace(/^\./, ''); // strip a leading dot
11 | var a = s.split('.');
12 | for (var i = 0, n = a.length; i < n; ++i) {
13 | var k = a[i];
14 | if (k in o) {
15 | o = o[k];
16 | } else {
17 | return;
18 | }
19 | }
20 | return o;
21 | }
22 |
23 | module.exports = useStringAsKey
--------------------------------------------------------------------------------
/routes/zcashParamsSources.js:
--------------------------------------------------------------------------------
1 | const zcashParamsSources = {
2 | 'agama.komodoplatform.com': {
3 | spend: 'https://agama.komodoplatform.com/file/komodo/sapling-params/sapling-spend.params',
4 | output: 'https://agama.komodoplatform.com/file/komodo/sapling-params/sapling-output.params',
5 | groth16: 'https://agama.komodoplatform.com/file/komodo/sapling-params/sprout-groth16.params',
6 | },
7 | 'z.cash': {
8 | spend: 'https://z.cash/downloads/sapling-spend.params',
9 | output: 'https://z.cash/downloads/sapling-output.params',
10 | groth16: 'https://z.cash/downloads/sprout-groth16.params',
11 | },
12 | 'verus.io': {
13 | spend: 'https://verus.io/zcparams/sapling-spend.params',
14 | output: 'https://verus.io/zcparams/sapling-output.params',
15 | groth16: 'https://verus.io/zcparams/sprout-groth16.params',
16 | },
17 | }
18 |
19 | module.exports = zcashParamsSources;
20 |
--------------------------------------------------------------------------------
/routes/deeplink/openurlhandler.js:
--------------------------------------------------------------------------------
1 | const { dialog } = require('electron')
2 | const { URL } = require('url');
3 | const { SUPPORTED_DLS, CALLBACK_HOST } = require('../api/utils/constants/supported_dls');
4 |
5 | function openurlhandler(event, urlstring, apihandler) {
6 | try {
7 | const url = new URL(urlstring);
8 |
9 | if (url.host !== CALLBACK_HOST) throw new Error("Unsupported host url.");
10 | if (!SUPPORTED_DLS.includes(url.pathname.replace(/\//g, "")))
11 | throw new Error("Unsupported url path.");
12 |
13 | return apihandler(url);
14 | } catch (e) {
15 | setTimeout(() => {
16 | // This avoids crashing 20 seconds after the error box has been left open.
17 | dialog.showErrorBox(
18 | "Something went wrong?",
19 | `Error: "${e.message}". For url string: "${urlstring}".`
20 | );
21 | }, 0);
22 | }
23 | }
24 |
25 | module.exports = openurlhandler
--------------------------------------------------------------------------------
/routes/api/utils/objectUtil/removeElementByProperties.js:
--------------------------------------------------------------------------------
1 | //ref: https://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key
2 | /**
3 | * Uses an array of properties (in parent -> child order)
4 | * as a key to search through an object and remove an
5 | * element, assuming the property list correctly maps the object.
6 | * Returns the modified object.
7 | *
8 | * @param {Object} o The object to search through
9 | * @param {String[]} propList The property list
10 | */
11 | const removeElementByProperties = (o, propList) => {
12 | if (propList.length === 1) {
13 | let newO = { ...o }
14 | delete newO[propList[0]]
15 | return newO
16 | } else {
17 | let newProps = propList.slice()
18 | const newProp = newProps.shift()
19 |
20 | return {...o, [newProp]: removeElementByProperties(o[newProp], newProps)}
21 | }
22 | }
23 |
24 | module.exports = removeElementByProperties
--------------------------------------------------------------------------------
/routes/api/utils/verifySignature.js:
--------------------------------------------------------------------------------
1 | const request = require('request');
2 |
3 | // TODO: Implement when endpoint is complete
4 | function verifyHash(hash, id, signature) {
5 | return new Promise((resolve, reject) => {
6 | const options = {
7 | url: '',
8 | method: "POST",
9 | body: JSON.stringify({
10 | Hash: hash,
11 | Signature: signature,
12 | Identity: id
13 | })
14 | };
15 |
16 | request(options, (error, response, body) => {
17 | if (response &&
18 | response.statusCode &&
19 | response.statusCode === 200) {
20 | try {
21 | const _json = JSON.parse(body);
22 |
23 | resolve(true)
24 | } catch (e) {
25 | reject(e)
26 | }
27 | } else {
28 | reject(new Error(`Unable to request ${options.url}`))
29 | }
30 | });
31 | });
32 | }
33 |
34 | module.exports = {
35 | verifyHash
36 | }
--------------------------------------------------------------------------------
/assets/deps/confs/FRK_peers.txt:
--------------------------------------------------------------------------------
1 | 193.227.134.111:7912
2 | 85.24.169.215:7912
3 | 195.154.223.134:7912
4 | 175.33.51.90:7912
5 | 91.153.109.149:7912
6 | 84.242.139.4:7912
7 | 73.211.90.130:7912
8 | 123.56.194.66:7912
9 | 157.161.128.55:7912
10 | 91.134.120.210:7912
11 | 80.219.59.25:7912
12 | 173.65.129.85:7912
13 | 198.27.97.180:7912
14 | 178.140.25.85:7912
15 | 104.172.24.79:7912
16 | 198.27.81.114:7912
17 | 104.236.163.203:7912
18 | 98.115.147.74:7912
19 | 155.254.32.17:7912
20 | 198.27.97.172:7912
21 | 108.61.10.90:7912
22 | 104.236.26.26:7912
23 | 144.76.91.109:7912
24 | 158.69.238.230:7912
25 | 86.174.4.251:7912
26 | 151.80.9.33:7912
27 | 198.50.217.13:7912
28 | 193.192.37.135:7912
29 | 80.219.59.42:7912
30 | 68.117.4.111:7912
31 | 109.145.33.45:7912
32 | 74.196.59.103:7912
33 | 84.107.181.197:7912
34 | 80.219.59.98:7912
35 | 104.236.59.76:7912
36 | 81.89.56.170:7912
37 | 157.161.128.58:7912
38 | 158.69.27.82:7912
39 | 209.126.119.209:7912
40 | 104.238.171.32:7912
41 |
--------------------------------------------------------------------------------
/routes/api/network/fees/btc/btcFees.js:
--------------------------------------------------------------------------------
1 | const { checkTimestamp } = require('agama-wallet-lib/src/time');
2 | const { requestJson } = require('../../../utils/request/request');
3 |
4 | let btcFees = {
5 | recommended: {},
6 | lastUpdated: null,
7 | };
8 |
9 | const BTC_FEES_MIN_ELAPSED_TIME = 120;
10 |
11 | module.exports = (api) => {
12 | api.networkFees['BTC'] = () => {
13 | return new Promise(async (resolve, reject) => {
14 | if (checkTimestamp(btcFees.lastUpdated) > BTC_FEES_MIN_ELAPSED_TIME) {
15 | try {
16 | const res = await requestJson(
17 | "GET",
18 | "https://api.blockchain.com/mempool/fees"
19 | );
20 |
21 | const { priority, regular } = res;
22 | resolve({low: regular, mid: regular, max: priority});
23 | } catch(e) {
24 | reject(e)
25 | }
26 | } else {
27 | resolve(btcFees)
28 | }
29 | });
30 | }
31 |
32 | return api;
33 | };
--------------------------------------------------------------------------------
/routes/api/native/takeoffer.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.native.takeoffer = async ({
3 | chain,
4 | fromaddress,
5 | offer: { txid, changeaddress, deliver, accept },
6 | }) => {
7 | return await api.native.callDaemon(chain, "takeoffer", [
8 | fromaddress,
9 | { txid, changeaddress, deliver, accept },
10 | ]);
11 | };
12 |
13 | api.setPost("/native/takeoffer", async (req, res, next) => {
14 | try {
15 | res.send(
16 | JSON.stringify({
17 | msg: "success",
18 | result: await api.native.takeoffer({
19 | chain: req.body.chain,
20 | fromaddress: req.body.fromaddress,
21 | offer: req.body.offer,
22 | }),
23 | })
24 | );
25 | } catch (e) {
26 | res.send(
27 | JSON.stringify({
28 | msg: "error",
29 | result: e.message,
30 | })
31 | );
32 | }
33 | });
34 |
35 | return api;
36 | };
37 |
--------------------------------------------------------------------------------
/routes/api/dlhandler.js:
--------------------------------------------------------------------------------
1 | const { LOGIN_CONSENT_REQUEST_VDXF_KEY, LoginConsentRequest } = require('verus-typescript-primitives');
2 | const base64url = require("base64url");
3 | const { ROOT_SYSTEM_NAME } = require('./utils/constants/dev_options');
4 |
5 | module.exports = (api) => {
6 | api.dlhandler = (url) => {
7 | const handlers = {
8 | [LOGIN_CONSENT_REQUEST_VDXF_KEY.vdxfid]: (url) => {
9 | const value = url.searchParams.get(LOGIN_CONSENT_REQUEST_VDXF_KEY.vdxfid)
10 | const req = new LoginConsentRequest();
11 | req.fromBuffer(base64url.toBuffer(value));
12 |
13 | return api.loginConsentUi.request(
14 | req.toJson(),
15 | {
16 | id: "VERUS_DESKTOP_MAIN",
17 | search_builtin: true,
18 | main_chain_ticker: ROOT_SYSTEM_NAME
19 | }
20 | )
21 | }
22 | }
23 |
24 | return handlers[url.pathname.replace(/\//g, "")](url)
25 | }
26 |
27 | return api;
28 | };
--------------------------------------------------------------------------------
/routes/api/utils/objectUtil/getBytes.js:
--------------------------------------------------------------------------------
1 |
2 | const getObjBytes = (obj) => {
3 | let bytes = 0;
4 |
5 | function sizeOf(obj) {
6 | if (obj !== null && obj !== undefined) {
7 | switch (typeof obj) {
8 | case "number":
9 | bytes += 8;
10 | break;
11 | case "string":
12 | bytes += obj.length * 2;
13 | break;
14 | case "boolean":
15 | bytes += 4;
16 | break;
17 | case "object":
18 | let objClass = Object.prototype.toString.call(obj).slice(8, -1);
19 | if (objClass === "Array" || objClass === "Object") {
20 | for (let key in obj) {
21 | if (!obj.hasOwnProperty(key)) continue;
22 | sizeOf(obj[key]);
23 | }
24 | } else bytes += obj.toString().length * 2;
25 | break;
26 | }
27 | }
28 | return bytes;
29 | }
30 |
31 | return sizeOf(obj);
32 | }
33 |
34 | module.exports = getObjBytes
--------------------------------------------------------------------------------
/routes/api/native/currencyGraylist.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | // api.setGet('/native/get_currency_graylist', (req, res, next) => {
3 | // const { token } = req.body
4 |
5 | // if (api.checkToken(token)) {
6 | // api.native.loadCurrencyGraylist()
7 | // .then((graylist) => {
8 | // const retObj = {
9 | // msg: 'success',
10 | // result: graylist,
11 | // };
12 |
13 | // res.send(JSON.stringify(retObj));
14 | // })
15 | // .catch(error => {
16 | // const retObj = {
17 | // msg: 'error',
18 | // result: error.message,
19 | // };
20 |
21 | // res.send(JSON.stringify(retObj));
22 | // })
23 | // } else {
24 | // const retObj = {
25 | // msg: 'error',
26 | // result: 'unauthorized access',
27 | // };
28 |
29 | // res.send(JSON.stringify(retObj));
30 | // }
31 | // });
32 |
33 | return api;
34 | };
--------------------------------------------------------------------------------
/routes/api/numbers.js:
--------------------------------------------------------------------------------
1 | const scientificToDecimal = function(number) {
2 | let numberHasSign = number.startsWith("-") || number.startsWith("+");
3 | let sign = numberHasSign ? number[0] : "";
4 | number = numberHasSign ? number.replace(sign, "") : number;
5 |
6 |
7 | if (/\d+\.?\d*e[\+\-]*\d+/i.test(number)) {
8 | let zero = '0';
9 | let parts = String(number).toLowerCase().split('e');
10 | let e = parts.pop();
11 | let l = Math.abs(e);
12 | let sign = e / l;
13 | let coeff_array = parts[0].split('.');
14 |
15 | if (sign === -1) {
16 | coeff_array[0] = Math.abs(coeff_array[0]);
17 | number = zero + '.' + new Array(l).join(zero) + coeff_array.join('');
18 | } else {
19 | let dec = coeff_array[1];
20 | if (dec) l = l - dec.length;
21 | number = coeff_array.join('') + new Array(l + 1).join(zero);
22 | }
23 | }
24 |
25 | return `${sign}${number}`;
26 | };
27 |
28 | module.exports = {
29 | scientificToDecimal
30 | }
--------------------------------------------------------------------------------
/routes/api/network/supply/vrsc/vrscCoinSupply.js:
--------------------------------------------------------------------------------
1 | const { checkTimestamp } = require('agama-wallet-lib/src/time');
2 | const { requestJson } = require('../../../utils/request/request');
3 |
4 | let coinSupply = {
5 | result: null,
6 | lastUpdated: null,
7 | };
8 |
9 | const COIN_SUPPLY_MIN_ELAPSED_TIME = 60;
10 |
11 | module.exports = (api) => {
12 | api.coinSupply['VRSC'] = () => {
13 | return new Promise(async (resolve, reject) => {
14 | if (checkTimestamp(coinSupply.lastUpdated) > COIN_SUPPLY_MIN_ELAPSED_TIME) {
15 | try {
16 | const res = await requestJson(
17 | "GET",
18 | 'https://explorer.verus.io/api/coinsupply'
19 | );
20 |
21 | resolve(res);
22 | } catch(e) {
23 | reject(e)
24 | }
25 | } else {
26 | api.log('vrsc coinsupply, use cache', 'network.coinSupply');
27 |
28 | resolve(coinSupply.result)
29 | }
30 | });
31 | }
32 |
33 | return api;
34 | };
35 |
--------------------------------------------------------------------------------
/routes/api/native/zoperations.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = (api) => {
3 | api.native.get_zoperations = (coin) => {
4 | return new Promise((resolve, reject) => {
5 | api.native.callDaemon(coin, 'z_getoperationstatus', [])
6 | .then((zoperations) => {
7 | resolve(zoperations)
8 | })
9 | .catch(err => {
10 | reject(err)
11 | })
12 | });
13 | };
14 |
15 | api.setPost('/native/get_zoperations', (req, res, next) => {
16 | const coin = req.body.chainTicker;
17 |
18 | api.native.get_zoperations(coin)
19 | .then((zoperations) => {
20 | const retObj = {
21 | msg: 'success',
22 | result: zoperations,
23 | };
24 |
25 | res.send(JSON.stringify(retObj));
26 | })
27 | .catch(error => {
28 | const retObj = {
29 | msg: 'error',
30 | result: error.message,
31 | };
32 |
33 | res.send(JSON.stringify(retObj));
34 | })
35 | });
36 |
37 | return api;
38 | };
--------------------------------------------------------------------------------
/routes/api/eth/auth.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.setPost('/eth/auth', (req, res, next) => {
3 | let seed = req.body.seed;
4 |
5 | if (!api.seed) {
6 | api.seed = seed;
7 | }
8 |
9 | api.eth.wallet = api.eth._keys(seed, true);
10 |
11 | const retObj = {
12 | msg: 'success',
13 | result: 'success',
14 | };
15 |
16 | res.send(JSON.stringify(retObj));
17 | }, true);
18 |
19 | api.setGet('/eth/check_auth', (req, res, next) => {
20 | res.send(JSON.stringify({
21 | msg: 'success',
22 | result: api.eth.wallet != null && api.eth.wallet.signer != null && api.eth.wallet.signer.signingKey != null,
23 | }));
24 | });
25 |
26 | api.setPost('/eth/logout', (req, res, next) => {
27 | api.eth.wallet = null
28 | api.eth.interface = null
29 |
30 | const retObj = {
31 | msg: 'success',
32 | result: 'success',
33 | };
34 |
35 | res.send(JSON.stringify(retObj));
36 | });
37 |
38 | return api;
39 | };
40 |
--------------------------------------------------------------------------------
/routes/api/native/definedchains.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = (api) => {
3 | api.native.get_definedchains = (coin) => {
4 | return new Promise((resolve, reject) => {
5 | api.native.callDaemon(coin, 'getdefinedchains', [])
6 | .then((definedchains) => {
7 | resolve(definedchains)
8 | })
9 | .catch(err => {
10 | reject(err)
11 | })
12 | });
13 | };
14 |
15 | api.setPost('/native/get_definedchains', (req, res, next) => {
16 | const coin = req.body.chainTicker;
17 |
18 | api.native.get_definedchains(coin)
19 | .then((definedchains) => {
20 | const retObj = {
21 | msg: 'success',
22 | result: definedchains,
23 | };
24 |
25 | res.send(JSON.stringify(retObj));
26 | })
27 | .catch(error => {
28 | const retObj = {
29 | msg: 'error',
30 | result: error.message,
31 | };
32 |
33 | res.send(JSON.stringify(retObj));
34 | })
35 | });
36 |
37 | return api;
38 | };
--------------------------------------------------------------------------------
/routes/api/erc20/auth.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.setPost('/erc20/auth', (req, res, next) => {
3 | let seed = req.body.seed;
4 |
5 | if (!api.seed) {
6 | api.seed = seed;
7 | }
8 |
9 | api.erc20.wallet = api.eth._keys(seed, true);
10 |
11 | const retObj = {
12 | msg: 'success',
13 | result: 'success',
14 | };
15 |
16 | res.send(JSON.stringify(retObj));
17 | }, true);
18 |
19 | api.setGet('/erc20/check_auth', (req, res, next) => {
20 | res.send(JSON.stringify({
21 | msg: 'success',
22 | result: api.erc20.wallet != null && api.erc20.wallet.signer != null && api.erc20.wallet.signer.signingKey != null,
23 | }));
24 | });
25 |
26 | api.setPost('/erc20/logout', (req, res, next) => {
27 | api.erc20.wallet = null
28 | api.erc20.interface = null
29 |
30 | const retObj = {
31 | msg: 'success',
32 | result: 'success',
33 | };
34 |
35 | res.send(JSON.stringify(retObj));
36 | });
37 |
38 | return api;
39 | };
40 |
--------------------------------------------------------------------------------
/routes/api/native/estimateConversion.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | /**
3 | * @param {string} chain
4 | * @param {{currency: string, amount: number, convertto: string, preconvert: boolean, via: string}} params
5 | */
6 | api.native.estimate_conversion = async (chain, params) => {
7 | try {
8 | return await api.native.callDaemon(chain, 'estimateconversion', [params]);
9 | } catch(e) {
10 | throw e
11 | }
12 | };
13 |
14 | api.setPost('/native/estimate_conversion', async (req, res, next) => {
15 | const { chainTicker, params } = req.body
16 |
17 | try {
18 | const retObj = {
19 | msg: 'success',
20 | result: await api.native.estimate_conversion(chainTicker, params),
21 | };
22 |
23 | res.send(JSON.stringify(retObj));
24 | } catch(e) {
25 | const retObj = {
26 | msg: 'error',
27 | result: e.message,
28 | };
29 |
30 | res.send(JSON.stringify(retObj));
31 | }
32 | });
33 |
34 | return api;
35 | };
--------------------------------------------------------------------------------
/routes/api/native/idRevocation.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = (api) => {
3 | api.native.revoke_id = (coin, name) => {
4 | return new Promise((resolve, reject) => {
5 | api.native.callDaemon(coin, 'revokeidentity', [name])
6 | .then((txid) => {
7 | resolve({
8 | name,
9 | txid
10 | })
11 | })
12 | .catch(err => {
13 | reject(err)
14 | })
15 | });
16 | };
17 |
18 | api.setPost('/native/revoke_id', (req, res, next) => {
19 | const { chainTicker, name } = req.body
20 |
21 | api.native.revoke_id(chainTicker, name)
22 | .then((revocationResult) => {
23 | const retObj = {
24 | msg: 'success',
25 | result: revocationResult,
26 | };
27 |
28 | res.send(JSON.stringify(retObj));
29 | })
30 | .catch(error => {
31 | const retObj = {
32 | msg: 'error',
33 | result: error.message,
34 | };
35 |
36 | res.send(JSON.stringify(retObj));
37 | })
38 | });
39 |
40 | return api
41 | };
--------------------------------------------------------------------------------
/routes/api/network/supply/zec/zecCoinSupply.js:
--------------------------------------------------------------------------------
1 | const { checkTimestamp } = require('agama-wallet-lib/src/time');
2 | const { requestJson } = require('../../../utils/request/request');
3 |
4 | let coinSupply = {
5 | result: null,
6 | lastUpdated: null,
7 | };
8 |
9 | const COIN_SUPPLY_MIN_ELAPSED_TIME = 60;
10 |
11 | module.exports = (api) => {
12 | api.coinSupply['ZEC'] = () => {
13 | return new Promise(async (resolve, reject) => {
14 | if (checkTimestamp(coinSupply.lastUpdated) > COIN_SUPPLY_MIN_ELAPSED_TIME) {
15 | try {
16 | const res = await requestJson(
17 | "GET",
18 | 'https://api.zcha.in/v2/mainnet/network'
19 | );
20 |
21 | resolve({ total: res.totalAmount, private: res.sproutPool + res.saplingPool });
22 | } catch(e) {
23 | reject(e)
24 | }
25 | } else {
26 | api.log('zec coinsupply, use cache', 'network.coinSupply');
27 |
28 | resolve(coinSupply.result)
29 | }
30 | });
31 | }
32 |
33 | return api;
34 | };
--------------------------------------------------------------------------------
/routes/api/explorer/remoteExplorers.js:
--------------------------------------------------------------------------------
1 | const remoteExplorers = {
2 | KMD: 'http://kmd.komodochainz.info',
3 | MSHARK: 'http://MSHARK.explorer.supernet.org',
4 | REVS: 'http://revs.explorer.supernet.org',
5 | SUPERNET: 'http://SUPERNET.explorer.supernet.org',
6 | DEX: 'http://DEX.explorer.supernet.org',
7 | PANGEA: 'http://PANGEA.explorer.supernet.org',
8 | JUMBLR: 'http://JUMBLR.explorer.supernet.org',
9 | BET: 'http://BET.explorer.supernet.org',
10 | CRYPTO: 'http://CRYPTO.explorer.supernet.org',
11 | HODL: 'http://HODL.explorer.supernet.org',
12 | SHARK: 'http://SHARK.explorer.supernet.org',
13 | BOTS: 'http://BOTS.explorer.supernet.org',
14 | MGW: 'http://MGW.explorer.supernet.org',
15 | WLC: 'http://WIRELESS.explorer.supernet.org',
16 | COQUI: 'https://explorer.coqui.cash',
17 | MNZ: 'https://www.mnzexplorer.com',
18 | VRSC: 'https://explorer.verus.io/',
19 | PIRATE: 'https://pirate.kmdexplorer.io',
20 | VRSCTEST: 'https://testex.verus.io'
21 | };
22 | // TODO Our landing page gets added to this list
23 | module.exports = remoteExplorers;
24 |
--------------------------------------------------------------------------------
/routes/api/native/info.js:
--------------------------------------------------------------------------------
1 | const { standardizeInfo } = require('../utils/standardization/standardization')
2 |
3 | module.exports = (api) => {
4 | api.native.get_info = (coin) => {
5 | return new Promise((resolve, reject) => {
6 | api.native.callDaemon(coin, 'getinfo', [])
7 | .then((info) => {
8 | return standardizeInfo(info, coin, api)
9 | })
10 | .then(info => resolve(info))
11 | .catch(err => {
12 | reject(err)
13 | })
14 | });
15 | };
16 |
17 | api.setPost('/native/get_info', (req, res, next) => {
18 | const coin = req.body.chainTicker;
19 |
20 | api.native.get_info(coin)
21 | .then((info) => {
22 | const retObj = {
23 | msg: 'success',
24 | result: info,
25 | };
26 |
27 | res.send(JSON.stringify(retObj));
28 | })
29 | .catch(error => {
30 | const retObj = {
31 | msg: 'error',
32 | result: error.message,
33 | };
34 |
35 | res.send(JSON.stringify(retObj));
36 | })
37 | });
38 |
39 | return api;
40 | };
--------------------------------------------------------------------------------
/routes/api/native/blockSubsidy.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = (api) => {
3 | api.native.get_blocksubsidy = (coin, height) => {
4 | return new Promise((resolve, reject) => {
5 | api.native.callDaemon(coin, 'getblocksubsidy', height == null ? [] : [height])
6 | .then((blocksubsidy) => {
7 | resolve(blocksubsidy)
8 | })
9 | .catch(err => {
10 | reject(err)
11 | })
12 | });
13 | };
14 |
15 | api.setPost('/native/get_blocksubsidy', (req, res, next) => {
16 | const { height } = req.body
17 | const coin = req.body.chainTicker;
18 |
19 | api.native.get_blocksubsidy(coin, height)
20 | .then((blocksubsidy) => {
21 | const retObj = {
22 | msg: 'success',
23 | result: blocksubsidy,
24 | };
25 |
26 | res.send(JSON.stringify(retObj));
27 | })
28 | .catch(error => {
29 | const retObj = {
30 | msg: 'error',
31 | result: error.message,
32 | };
33 |
34 | res.send(JSON.stringify(retObj));
35 | })
36 | });
37 |
38 | return api;
39 | };
--------------------------------------------------------------------------------
/routes/api/electrum/utils.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.sortTransactions = (transactions, sortBy) => {
3 | if (transactions && typeof transactions === 'object' && transactions[0]) {
4 | return transactions.sort((b, a) => {
5 | if (a[sortBy ? sortBy : 'height'] < b[sortBy ? sortBy : 'height'] &&
6 | a[sortBy ? sortBy : 'height'] &&
7 | b[sortBy ? sortBy : 'height']) {
8 | return -1;
9 | }
10 |
11 | if (a[sortBy ? sortBy : 'height'] > b[sortBy ? sortBy : 'height'] &&
12 | a[sortBy ? sortBy : 'height'] &&
13 | b[sortBy ? sortBy : 'height']) {
14 | return 1;
15 | }
16 |
17 | if (!a[sortBy ? sortBy : 'height'] &&
18 | b[sortBy ? sortBy : 'height']) {
19 | return 1;
20 | }
21 |
22 | if (!b[sortBy ? sortBy : 'height'] &&
23 | a[sortBy ? sortBy : 'height']) {
24 | return -1;
25 | }
26 |
27 | return 0;
28 | });
29 | } else {
30 | return transactions;
31 | }
32 | }
33 |
34 | return api;
35 | };
--------------------------------------------------------------------------------
/gui/fetch-bootstrap/fetch-bootstrap.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Loading bootstrap script...
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/routes/api/native/sendcurrency.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.native.sendcurrency = async (chainTicker, from = "*", outputs = [], feeamount = null) => {
3 | try {
4 | return await api.native.callDaemon(
5 | chainTicker,
6 | "sendcurrency",
7 | feeamount === null ? [from, outputs] : [from, outputs, feeamount]
8 | );
9 | } catch(e) {
10 | throw e
11 | }
12 | }
13 |
14 | api.setPost('/native/sendcurrency', async (req, res, next) => {
15 | const { from, outputs, feeamount, chainTicker } = req.body;
16 |
17 | try {
18 | res.send(JSON.stringify({
19 | msg: "success",
20 | result: await api.native.sendcurrency(chainTicker, from, outputs.map(x => {
21 | Object.keys(x).map(y => {
22 | if (x[y] == null || x[y].length === 0) delete x[y]
23 | })
24 |
25 | return x
26 | }), feeamount)
27 | }));
28 | } catch (e) {
29 | res.send(
30 | JSON.stringify({
31 | msg: "error",
32 | result: e.message,
33 | })
34 | );
35 | }
36 | });
37 |
38 | return api;
39 | };
--------------------------------------------------------------------------------
/routes/api/electrum/info.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.setGet('/electrum/get_info', (req, res, next) => {
3 | if (!req.query.chainTicker) {
4 | res.send(JSON.stringify({
5 | msg: 'error',
6 | result: 'No coin passed to electrum get_info'
7 | }));
8 | }
9 | const coinLc = req.query.chainTicker.toLowerCase();
10 |
11 | if (!api.electrum.coinData[coinLc]) {
12 | res.send(JSON.stringify({
13 | msg: 'error',
14 | result: `No coin data found for ${req.query.chainTicker}`
15 | }));
16 | }
17 |
18 | const { name, txfee, server, serverList, nspv } = api.electrum.coinData[coinLc];
19 |
20 | res.send(JSON.stringify({msg: 'success', result: nspv ? {
21 | protocol: "nSPV",
22 | name,
23 | txfee,
24 | server: `${server.ip}:${server.port}:${server.proto}`,
25 | serverList: serverList.toString(),
26 | } : {
27 | protocol: "Electrum",
28 | name,
29 | txfee,
30 | server: `${server.ip}:${server.port}:${server.proto}`,
31 | serverList: serverList.toString(),
32 | nspv,
33 | }}));
34 | });
35 |
36 | return api;
37 | };
--------------------------------------------------------------------------------
/routes/ports.js:
--------------------------------------------------------------------------------
1 | // default daemon ports
2 |
3 | const assetChainPorts = {
4 | KMD: 7771,
5 | //marketmaker: 7783,
6 | OOT: 12467,
7 | PIZZA: 11608,
8 | BEER: 8923,
9 | SUPERNET: 11341,
10 | REVS: 10196,
11 | WLC: 12167,
12 | WLC21: 38808,
13 | PANGEA: 14068,
14 | DEX: 11890,
15 | JUMBLR: 15106,
16 | BET: 14250,
17 | CRYPTO: 8516,
18 | HODL: 14431,
19 | MSHARK: 8846,
20 | BOTS: 11964,
21 | MGW: 12386,
22 | COQUI: 14276,
23 | CHAIN: 15587,
24 | KMDICE: 30177,
25 | GLXT: 13109,
26 | MVP: 11676,
27 | KV: 8299,
28 | CEAL: 11116,
29 | MESH: 9455,
30 | AXO: 12927,
31 | ETOMIC: 10271,
32 | NINJA: 8427,
33 | BNTN: 14358,
34 | EQL: 10306,
35 | PRLPAY: 9679,
36 | PGT: 46705,
37 | ZILLA: 10041,
38 | DSEC: 11557,
39 | MGNX: 20731,
40 | PIRATE: 45453,
41 | CCL: 20849,
42 | KOIN: 10702,
43 | DION: 23895,
44 | PTX: 61939,
45 | KSB: 21066,
46 | OUR: 45672,
47 | RICK: 28223,
48 | MORTY: 63812,
49 | MTST3: 56141,
50 | ZEXO: 33970,
51 | LABS: 40265,
52 | DP: 28388,
53 | VRSCTEST: 18843,
54 | VRSC: 27486,
55 | VOTE2020: 44249,
56 | VOTE2021: 55638
57 | };
58 |
59 | module.exports = assetChainPorts;
60 |
--------------------------------------------------------------------------------
/routes/api/network/fees/networkFees.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = (api) => {
3 | api.setGet('/get_networkfees', (req, res, next) => {
4 | if (!req.query.chainTicker) {
5 | res.send(JSON.stringify({msg: 'error', result: "No coin passed to get_networkfees"}));
6 | }
7 |
8 | api.electrum.get_networkfees(req.query.chainTicker)
9 | .then(feesObj => {
10 | const retObj = {
11 | msg: 'success',
12 | result: feesObj
13 | };
14 |
15 | res.send(JSON.stringify(retObj));
16 | })
17 | .catch(e => {
18 | const retObj = {
19 | msg: 'error',
20 | result: e.message
21 | };
22 |
23 | res.send(JSON.stringify(retObj));
24 | })
25 | });
26 |
27 | api.electrum.get_networkfees = (chainTicker) => {
28 | if (api.networkFees[chainTicker] != null) {
29 | return new Promise(async (resolve, reject) => {
30 | api.networkFees[chainTicker]()
31 | .then(fees => resolve(fees))
32 | .catch(e => reject(e))
33 | })
34 | } else {
35 | return new Promise((resolve, reject) => {reject(new Error(`Network fee function not found`))})
36 | }
37 | }
38 |
39 | return api;
40 | };
--------------------------------------------------------------------------------
/routes/api/utils/objectUtil/addMerge.js:
--------------------------------------------------------------------------------
1 | const deepmerge = require('./deepmerge')
2 | const flattenObjectProps = require('./flattenObjectProps')
3 |
4 | /**
5 | * Adds properties object 2 includes that object 1 may be missing into
6 | * object 1 and returns the modified object
7 | * @param {Object} obj1 Object 1
8 | * @param {Object} obj2 Object 2
9 | */
10 | const addMerge = (obj1, obj2) => {
11 | const flatObj1 = flattenObjectProps(obj1);
12 | const flatObj2 = flattenObjectProps(obj2);
13 | let resObj = obj1;
14 |
15 | flatObj2.forEach(propertyList => {
16 | if (!flatObj1.includes(propertyList)) {
17 | const propertyArr = propertyList.split(".");
18 | let updateObj = propertyArr.reduce(function(
19 | accumulator,
20 | currentValue
21 | ) {
22 | return accumulator[currentValue];
23 | },
24 | obj2);
25 |
26 | propertyArr
27 | .slice()
28 | .reverse()
29 | .forEach((property, index) => {
30 | updateObj = { [property]: updateObj };
31 | });
32 |
33 | resObj = deepmerge(updateObj, resObj);
34 | }
35 | });
36 |
37 | return resObj;
38 | }
39 |
40 | module.exports = addMerge
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 - 2018 SuperNET
4 | Copyright (c) 2019 - 2020 Verus Coin Foundation
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 |
--------------------------------------------------------------------------------
/routes/api/utils/constants/file_descriptors.js:
--------------------------------------------------------------------------------
1 | // Identities
2 | const NAME_COMMITMENTS_DESC = "DO NOT EDIT. This file contains the saved name commitments that you can use to create VerusIDs. Editing it will most likely cause your VerusID creation to fail."
3 |
4 | // Secrets
5 | const BUILTIN_SECRET_DESC = "DO NOT EDIT"
6 |
7 | // Currencies
8 | const BLACKLIST_DESC = "This file contains currencies you have chosen to blacklist, i.e. never see again. They will not appear in any part of your wallet, on the chains they are children of here."
9 |
10 | const WHITELIST_DESC = "This file contains currencies you have chosen to whitelist, i.e. always track. They will always appear in your coin wallet screen in the currency dropdown."
11 |
12 | const GRAYLIST_DESC = "This file contains a list of curated currencies that will appear in your wallet if they aren't blacklisted, and you have a balance above 0 of them."
13 |
14 | // Update Log
15 | const UPDATE_LOG_DESC = "This file contains a history of all version-required updates performed on data in the Verus Desktop folder."
16 |
17 | module.exports = {
18 | NAME_COMMITMENTS_DESC,
19 | UPDATE_LOG_DESC,
20 | BLACKLIST_DESC,
21 | WHITELIST_DESC,
22 | GRAYLIST_DESC,
23 | BUILTIN_SECRET_DESC
24 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Builtin Plugins
7 | assets/plugins/builtin/*
8 |
9 | # Runtime data
10 | pids
11 | *.pid
12 | *.seed
13 |
14 | #ide
15 | /.idea
16 |
17 | # Directory for instrumented libs generated by jscoverage/JSCover
18 | lib-cov
19 |
20 | # Coverage directory used by tools like istanbul
21 | coverage
22 |
23 | # nyc test coverage
24 | .nyc_output
25 |
26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
27 | .grunt
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (http://nodejs.org/api/addons.html)
33 | build/Release
34 | assets/bin/*
35 |
36 | # Dependency directories
37 | node_modules
38 | jspm_packages
39 |
40 | # Optional npm cache directory
41 | .npm
42 |
43 | # electron cache directory
44 | .electron
45 |
46 | # Optional REPL history
47 | .node_repl_history
48 |
49 | # Ignore node.js modules folder
50 | node_modules
51 |
52 | # Ignore any igauna made directories or files in repo folder
53 | tmp
54 | help
55 | debug.log
56 | genesis
57 | DB
58 |
59 | # Electron-builder related folders
60 | build
61 |
62 | #MacOSX hidden cache files
63 | __MACOSX
64 | react/package.json
65 |
66 | # Build files
67 | dist/*
--------------------------------------------------------------------------------
/routes/api/erc20/info.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.setGet('/erc20/get_info', (req, res, next) => {
3 | let retObj = {}
4 |
5 | try {
6 | const { network, address, decimals } = api.erc20.get_info(
7 | req.query.chainTicker
8 | );
9 |
10 | retObj = {
11 | msg: 'success',
12 | result: {
13 | network: network.key,
14 | chainId: network.id,
15 | contract: address,
16 | decimals,
17 | }
18 | }
19 | } catch (e) {
20 | retObj = {
21 | msg: 'error',
22 | result: e.message
23 | }
24 | }
25 |
26 | res.send(JSON.stringify(retObj));
27 | });
28 |
29 | api.erc20.get_info = (contractId) => {
30 | if (api.erc20.contracts[contractId] != null) {
31 | return {
32 | ...api.erc20.contracts[contractId].interface.getInfo(),
33 | address: contractId,
34 | decimals:
35 | api.erc20.contracts[contractId].decimals != null
36 | ? api.erc20.contracts[contractId].decimals.toString()
37 | : "18",
38 | };
39 | } else {
40 | throw new Error(`No interface to connect to ${contractId} for getinfo call`)
41 | }
42 | }
43 |
44 | return api;
45 | };
--------------------------------------------------------------------------------
/routes/electrumjs/electrumServersConfig.js:
--------------------------------------------------------------------------------
1 | const disableCoins = [
2 | 'aby',
3 | 'vot',
4 | 'mac',
5 | 'bdl',
6 | 'mzc', // no servers
7 | 'zet', // no servers
8 | 'jbs', // no servers
9 | 'grs',
10 | 'wc', // needs kv edit
11 | 'xwc', // needs kv edit
12 | 'put', // needs kv edit
13 | 'ecn', // needs kv edit
14 | 'ac',
15 | //'btcp', // sort out kv
16 | 'blk',
17 | // untested coins
18 | 'smart',
19 | 'usc',
20 | 'bca',
21 | 'mnx',
22 | 'xvc',
23 | 'nro',
24 | 'uno',
25 | 'bela',
26 | 'ldcn',
27 | 'hnc',
28 | 'nrg',
29 | 'smly',
30 | 'nsr',
31 | 'defc',
32 | 'brit',
33 | 'lynx',
34 | 'vpn',
35 | 'sdc',
36 | 'club',
37 | 'posw',
38 | 'psb',
39 | 'gcr',
40 | 'nyc',
41 | 'frst',
42 | // decode error coins
43 | 'omni',
44 | 'strat',
45 | 'clam',
46 | 'excl',
47 | 'nav',
48 | 'neos',
49 | 'ok',
50 | 'rdd',
51 | 'xvg',
52 | 'zen',
53 | 'slr',
54 | 'rby',
55 | 'pot',
56 | 'usnbt',
57 | 'ppc',
58 | 'thc',
59 | 'grc',
60 | 'pink',
61 | 'toa',
62 | 'wc',
63 | 'nvc',
64 | 'kobo',
65 | 'insn',
66 | 'edrc',
67 | 'ccn',
68 | 'cmp',
69 | // temp disable
70 | 'mue',
71 | 'xbc',
72 | 'pac',
73 | 'lcc',
74 | 'axe',
75 | ];
76 |
77 | module.exports = disableCoins;
--------------------------------------------------------------------------------
/routes/api/appInfo.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra');
2 | const os = require('os');
3 | const { formatBytes } = require('agama-wallet-lib/src/utils');
4 |
5 | module.exports = (api) => {
6 | api.SystemInfo = () => {
7 | const os_data = {
8 | totalmem_bytes: os.totalmem(),
9 | totalmem_readable: formatBytes(os.totalmem()),
10 | arch: os.arch(),
11 | cpu: os.cpus()[0].model,
12 | cpu_cores: os.cpus().length,
13 | platform: os.platform(),
14 | os_release: os.release(),
15 | os_type: os.type(),
16 | };
17 |
18 | return os_data;
19 | }
20 |
21 | api.appInfo = () => {
22 | const sysInfo = api.SystemInfo();
23 | const releaseInfo = api.appBasicInfo;
24 | const dirs = {
25 | agamaDir: api.paths.agamaDir,
26 | kmdDataDir: api.paths.kmdDataDir,
27 | komododBin: api.komododBin,
28 | configLocation: `${api.paths.agamaDir}/config.json`,
29 | cacheLocation: `${api.paths.agamaDir}/spv-cache.json`,
30 | };
31 | let spvCacheSize = '2 Bytes';
32 |
33 | try {
34 | spvCacheSize = formatBytes(fs.lstatSync(`${api.paths.agamaDir}/spv-cache.json`).size);
35 | } catch (e) {}
36 |
37 | return {
38 | sysInfo,
39 | releaseInfo,
40 | dirs,
41 | cacheSize: spvCacheSize,
42 | };
43 | }
44 |
45 | return api;
46 | };
--------------------------------------------------------------------------------
/routes/api/native/verusid/login/verifyRequest.js:
--------------------------------------------------------------------------------
1 | const { LoginConsentRequest } = require("verus-typescript-primitives")
2 |
3 | module.exports = (api) => {
4 | /**
5 | * Verifies a login request
6 | * @param {LoginConsentRequest} Request
7 | */
8 | api.native.verusid.login.verify_request = async (request) => {
9 | const loginConsentRequest = new LoginConsentRequest(request);
10 | const chainTicker = request.chainTicker
11 |
12 | const verified = await api.native.verify_hash(
13 | chainTicker,
14 | loginConsentRequest.signing_id,
15 | loginConsentRequest.challenge.toSha256().toString('hex'),
16 | loginConsentRequest.signature.signature
17 | );
18 |
19 | return verified ? { verified } : { verified, message: "Failed to verify signature" };
20 | };
21 |
22 | api.setPost("/native/verusid/login/verify_request", async (req, res, next) => {
23 | const { request } = req.body;
24 |
25 | try {
26 | res.send(
27 | JSON.stringify({
28 | msg: "success",
29 | result: await api.native.verusid.login.verify_request(request),
30 | })
31 | );
32 | } catch (e) {
33 | res.send(
34 | JSON.stringify({
35 | msg: "error",
36 | result: e.message,
37 | })
38 | );
39 | }
40 | });
41 |
42 | return api;
43 | };
44 |
--------------------------------------------------------------------------------
/routes/api/utils/web3/etherscan.js:
--------------------------------------------------------------------------------
1 | const { EtherscanProvider, Networkish, BlockTag } = require('ethers');
2 |
3 | class HistorySupportingEtherscanProvider extends EtherscanProvider {
4 | /**
5 | * Creates an etherscan provider that supports getting tx history
6 | * @param {Networkish} networkish
7 | * @param {string} apiKey
8 | * @returns {HistorySupportingEtherscanProvider}
9 | */
10 | constructor(networkish, apiKey) {
11 | super(networkish, apiKey);
12 | }
13 |
14 | /**
15 | * Gets the transaction history for a given address from startBlock to endBlock
16 | * @param {string} address
17 | * @param {BlockTag} startBlock
18 | * @param {BlockTag} endBlock
19 | * @param {string} contractAddress
20 | * @returns {Promise>}
21 | */
22 | async getHistory(address, startBlock, endBlock, contractAddress) {
23 | const params = {
24 | action: contractAddress != null ? "tokentx" : "txlist",
25 | address,
26 | startblock: ((startBlock == null) ? 0 : startBlock),
27 | endblock: ((endBlock == null) ? 99999999 : endBlock),
28 | sort: "asc"
29 | };
30 |
31 | if (contractAddress != null) params.contractAddress = contractAddress;
32 |
33 | return this.fetch("account", params);
34 | }
35 | }
36 |
37 | module.exports = {
38 | HistorySupportingEtherscanProvider
39 | }
--------------------------------------------------------------------------------
/routes/api/native/getConversionPaths.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.native.get_conversion_paths = (
3 | chain,
4 | src
5 | ) => {
6 | return new Promise(async (resolve, reject) => {
7 | try {
8 | const chainCurrency = await api.native.get_currency(chain, chain);
9 |
10 | const interface = await api.native.getRpcInterface(chain, chainCurrency.currencyid);
11 | const source = typeof src === "string" ? await api.native.get_currency(chain, src) : src;
12 |
13 | const paths = await interface.getCurrencyConversionPaths(source);
14 |
15 | delete paths[source.currencyid]
16 |
17 | resolve(paths);
18 | } catch(e) {
19 | reject(e)
20 | }
21 | });
22 | };
23 |
24 | api.setPost('/native/get_conversion_paths', (req, res, next) => {
25 | const coin = req.body.chainTicker;
26 | const src = req.body.src;
27 |
28 | api.native.get_conversion_paths(coin, src)
29 | .then((paths) => {
30 | res.send(JSON.stringify({
31 | msg: 'success',
32 | result: paths,
33 | }));
34 | })
35 | .catch(error => {
36 | const retObj = {
37 | msg: 'error',
38 | result: error.message,
39 | };
40 |
41 | res.send(JSON.stringify(retObj));
42 | })
43 | });
44 |
45 | return api;
46 | };
--------------------------------------------------------------------------------
/routes/children/userAgreement/window.js:
--------------------------------------------------------------------------------
1 | const { dialog } = require('electron')
2 |
3 | async function userAgreesToTerms(window) {
4 | const result = await dialog.showMessageBox(window, {
5 | message: 'Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The enclosed copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.',
6 | buttons: ["I Understand", "Cancel"],
7 | textWidth: 600
8 | })
9 |
10 | return result.response === 0
11 | }
12 |
13 | module.exports = {
14 | userAgreesToTerms,
15 | }
--------------------------------------------------------------------------------
/routes/workers/check_update.js:
--------------------------------------------------------------------------------
1 | const version_json = require('../../version.json')
2 | const versionCompare = require('../api/utils/version/versionCompare');
3 | const { requestJson } = require('../api/utils/request/request');
4 |
5 | function updateAvailable() {
6 | return new Promise(async (resolve, reject) => {
7 | try {
8 | const res = await requestJson("GET", version_json.versionUrl);
9 |
10 | if (versionCompare.compare(res.version, version_json.version, ">")) {
11 | const mandatory =
12 | res.minVersion != null &&
13 | versionCompare.compare(res.minVersion, version_json.version, ">");
14 |
15 | const newRes = await requestJson(
16 | "GET",
17 | version_json.repository + `releases/tag/v${res.version}`,
18 | {},
19 | {},
20 | true
21 | );
22 |
23 | if (newRes.status === 200) {
24 | resolve({ update_available: true, version: res.version, mandatory });
25 | } else if (newRes.status === 404) {
26 | resolve({ update_available: false, version: res.version, mandatory });
27 | } else reject(new Error("Error fetching update data, status " + res.status));
28 | } else resolve({ update_available: false, version: res.version, mandatory: false });
29 | } catch (e) {
30 | reject(e);
31 | }
32 | })
33 | }
34 |
35 | module.exports = updateAvailable
--------------------------------------------------------------------------------
/routes/api/data_files/updateLog.js:
--------------------------------------------------------------------------------
1 | const {
2 | UPDATE_LOG,
3 | UPDATE_LOG_DESC
4 | } = require("../utils/constants/index");
5 |
6 | module.exports = (api) => {
7 | // Blacklist
8 | api.loadUpdateLog = () =>
9 | api.loadJsonFile(UPDATE_LOG, UPDATE_LOG_DESC);
10 | api.saveUpdateLog = (history) =>
11 | api.saveJsonFile({ time: (new Date()).getTime(), history }, UPDATE_LOG, UPDATE_LOG_DESC);
12 |
13 | api.setGet('/load_update_log', async (req, res, next) => {
14 | api.loadUpdateLog()
15 | .then((log) => {
16 | const retObj = {
17 | msg: 'success',
18 | result: log,
19 | };
20 |
21 | res.send(JSON.stringify(retObj));
22 | })
23 | .catch(error => {
24 | const retObj = {
25 | msg: 'error',
26 | result: error.message,
27 | };
28 |
29 | res.send(JSON.stringify(retObj));
30 | })
31 | });
32 |
33 | api.setPost('/save_update_log', async (req, res, next) => {
34 | const { history } = req.body
35 |
36 | try {
37 | const retObj = {
38 | msg: 'success',
39 | result: await api.saveUpdateLog(history),
40 | };
41 |
42 | res.send(JSON.stringify(retObj));
43 | } catch (e) {
44 | const retObj = {
45 | msg: 'error',
46 | result: e.message,
47 | };
48 |
49 | res.send(JSON.stringify(retObj));
50 | }
51 | });
52 |
53 | return api;
54 | };
--------------------------------------------------------------------------------
/assets/deps/confs/MZC_peers.txt:
--------------------------------------------------------------------------------
1 | 188.226.195.226
2 | 72.49.184.206
3 | 84.22.108.241
4 | 75.128.211.140
5 | 176.31.53.252
6 | 212.5.143.185
7 | 205.197.252.41
8 | 195.154.223.134
9 | 142.4.218.174
10 | 72.46.152.250
11 | 45.63.65.112
12 | 104.236.167.70
13 | 142.4.218.175
14 | 108.61.164.199
15 | 107.170.173.232
16 | 98.117.92.108
17 | 192.95.29.153
18 | 97.88.116.115
19 | 24.206.113.66
20 | 173.239.208.6
21 | 24.107.101.162
22 | 88.198.49.154
23 | 193.107.94.202
24 | 86.26.119.177
25 | 198.27.97.172
26 | 73.240.243.108
27 | 98.127.109.96
28 | 27.109.250.186
29 | 79.64.13.216
30 | 81.102.95.39
31 | 92.14.74.221
32 | 68.42.79.115
33 | 85.169.119.123
34 | 24.107.102.70
35 | 151.80.206.101
36 | 107.170.167.218
37 | 151.80.9.33
38 | 82.46.79.119
39 | 63.247.147.166
40 | 95.145.252.94
41 | 113.52.87.159
42 | 192.99.35.133
43 | 12.35.68.211
44 | 46.105.158.205
45 | 72.84.241.101
46 | 37.59.18.108
47 | 104.172.24.79
48 | 174.107.118.81
49 | 76.106.178.145
50 | 75.128.193.117
51 | 158.69.27.82
52 | 45.32.233.30
53 | 84.22.106.192
54 | 74.132.6.75
55 | 45.55.153.77
56 | 89.156.223.223
57 | 94.23.32.109
58 | 180.94.191.62
59 | 45.55.220.222
60 | 73.192.202.185
61 | 186.90.15.65
62 | 108.224.49.4
63 | 84.237.85.210
64 | 76.19.242.156
65 | 73.157.167.155
66 | 68.117.4.111
67 | 98.18.22.32
68 | 69.59.214.109
69 | 198.84.218.9
70 | 98.115.147.74
71 | 71.7.124.80
72 | 65.15.37.140
73 | 217.44.16.102
74 | 73.240.162.49
75 | 23.80.94.149
76 | 151.80.206.110
77 | 50.254.73.158
78 | 92.14.75.139
79 | 188.124.91.76
80 | 66.189.11.251
81 | 184.17.228.71
82 |
--------------------------------------------------------------------------------
/gui/startup/agama-instance-error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |

22 |
Another Verus Desktop instance is already running!
23 |
Please close all other instances and restart the app.
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/routes/api/utils/auth/rpcAuth.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2019, Amalie Due Jensen
3 |
4 | Permission to use, copy, modify, and/or distribute this software for any
5 | purpose with or without fee is hereby granted, provided that the above
6 | copyright notice and this permission notice appear in all copies.
7 |
8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 | */
16 |
17 | const crypto = require('crypto')
18 |
19 | function generateSalt (size) {
20 | const buf = crypto.randomBytes(size)
21 | const salt = buf.toString('hex')
22 | return salt
23 | }
24 |
25 | function generateRpcPassword () {
26 | const buf = crypto.randomBytes(32)
27 | const password = Buffer.from(buf).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '')
28 | return password
29 | }
30 |
31 | function passwordToHmac (salt, password) {
32 | const hmac = crypto.createHmac('sha256', salt)
33 | hmac.update(password)
34 | return hmac.digest('hex')
35 | }
36 |
37 | module.exports = {
38 | generateSalt,
39 | generateRpcPassword,
40 | passwordToHmac
41 | }
--------------------------------------------------------------------------------
/routes/api/getSignatureInfo.js:
--------------------------------------------------------------------------------
1 | const {
2 | IdentitySignature,
3 | networks,
4 | } = require("@bitgo/utxo-lib");
5 |
6 | module.exports = (api) => {
7 | /**
8 | * Gets the version, hashtype and height from a signature.
9 | *
10 | * @param {String} coin The chainTicker of the coin to make the call on
11 | * @param {String} systemId The iaddress of the system
12 | * @param {String} signature The signature to process
13 | * @param {String} iaddress The iaddress associated with the signature
14 | */
15 | api.getSignatureInfo = (coin, systemId, signature, iaddress) => {
16 | const network = networks.verus;
17 |
18 | const sig = new IdentitySignature(network);
19 |
20 | sig.fromBuffer(Buffer.from(signature, "base64"), 0, systemId, iaddress);
21 |
22 | return {
23 | version: sig.version,
24 | hashtype: sig.hashType,
25 | height: sig.blockHeight,
26 | };
27 | }
28 |
29 | api.setPost('/lite/get_signature_info', (req, res, next) => {
30 | const {
31 | chainTicker,
32 | systemId,
33 | signature,
34 | iaddress
35 | } = req.body;
36 |
37 | try {
38 | res.send(
39 | JSON.stringify({
40 | msg: "success",
41 | result: api.getSignatureInfo(chainTicker, systemId, signature, iaddress),
42 | })
43 | );
44 | } catch (e) {
45 | res.send(
46 | JSON.stringify({
47 | msg: "error",
48 | result: e.message,
49 | })
50 | );
51 | }
52 | });
53 |
54 | return api;
55 | }
--------------------------------------------------------------------------------
/routes/api/utils/auth/scalar.js:
--------------------------------------------------------------------------------
1 | const { secp256k1 } = require('@noble/curves/secp256k1');
2 | const crypto = require('crypto');
3 | const bigi = require('bigi');
4 |
5 | // Derive 32-byte hash, optional clamp, and validate scalar range.
6 | // - Throws on zero scalar
7 | // - Warns but continues on scalar >= n (for legacy compatibility)
8 | // Returns: { bytes: Buffer, dBigi: bigi.BigInteger }
9 | function deriveScalarFromSeed(input, { iguana = false, logWarn } = {}) {
10 | const bytes = crypto.createHash('sha256').update(input).digest();
11 | if (bytes.length !== 32) {
12 | throw new Error('sha256 must return 32 bytes');
13 | }
14 |
15 | if (iguana) { // kept for legacy compatibility
16 | bytes[0] &= 248;
17 | bytes[31] &= 127;
18 | bytes[31] |= 64;
19 | }
20 |
21 | const dBig = BigInt('0x' + bytes.toString('hex'));
22 | const n = secp256k1.CURVE.n;
23 |
24 | if (dBig === BigInt(0)) {
25 | throw new Error('derived private key scalar is out of range (zero)');
26 | }
27 | if (dBig >= n) {
28 | // compatibility: warn but do not alter bytes/scalar
29 | const warn = 'Warning: derived private key scalar is ≥ secp256k1 order; some wallets may behave inconsistently when importing it, and it is less secure. Consider generating a new seed.';
30 | if (typeof logWarn === 'function') {
31 | logWarn(warn);
32 | } else {
33 | console.warn(warn);
34 | }
35 | }
36 |
37 | return {
38 | bytes,
39 | dBigi: bigi.fromBuffer(bytes),
40 | };
41 | }
42 |
43 | module.exports = deriveScalarFromSeed
--------------------------------------------------------------------------------
/routes/api/construct.js:
--------------------------------------------------------------------------------
1 | const { BuiltinPlugins } = require('./utils/plugin/builtin.js');
2 |
3 | module.exports = (api) => {
4 | api.construct = function () {
5 | api.appConfig = api._appConfig.config;
6 | api.pathsAgama();
7 | api.pathsDaemons();
8 |
9 | api.initMainCache();
10 |
11 | api.firstRun = api.createAgamaDirs();
12 | api.appConfig = api.loadLocalConfig();
13 | api.plugins = {
14 | registry: api.loadLocalPluginRegistry(),
15 | builtin: BuiltinPlugins,
16 | };
17 |
18 | api.appConfigSchema = api._appConfig.schema;
19 | api.defaultAppConfig = Object.assign({}, api.appConfig);
20 | api.kmdMainPassiveMode = false;
21 |
22 | api.native.cache.currency_definition_cache = api.create_sub_cache(
23 | "native.cache.currency_definition_cache"
24 | );
25 |
26 | api.seed = null;
27 |
28 | // init electrum connection manager loop
29 | api.initElectrumManager();
30 |
31 | api.printDirs();
32 |
33 | // default route
34 | api.setGet("/", (req, res, next) => {
35 | res.send("Agama app server2");
36 | });
37 |
38 | // expose sockets obj
39 | api.setIO = (io) => {
40 | api.io = io;
41 | };
42 |
43 | api.setVar = (_name, _body) => {
44 | api[_name] = _body;
45 | };
46 |
47 | if (api.appConfig.general.electrum && api.appConfig.general.electrum.customServers) {
48 | api.loadElectrumServersList();
49 | } else {
50 | api.mergeLocalKvElectrumServers();
51 | }
52 |
53 | api.checkCoinConfigIntegrity();
54 | };
55 |
56 | return api;
57 | };
58 |
--------------------------------------------------------------------------------
/gui/startup/app-closing.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |

24 |
25 | App is closing. Please wait...
26 | This may take a while depending on your system resources and current state of daemon applications.
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/routes/api/eth/coins.js:
--------------------------------------------------------------------------------
1 | const { ETH_HOMESTEAD } = require('../utils/constants/eth_networks');
2 | const createInterface = require('../utils/web3/provider');
3 |
4 | module.exports = (api) => {
5 | api.setPost('/eth/coins/activate', (req, res, next) => {
6 | const { chainTicker, network } = req.body;
7 |
8 | try {
9 | if (chainTicker && chainTicker === 'ETH') {
10 | if (api.eth.interface == null) {
11 | api.eth.interface = createInterface(
12 | network == null ? ETH_HOMESTEAD : network
13 | );
14 |
15 | const retObj = {
16 | msg: 'success',
17 | result: 'true',
18 | };
19 | res.send(JSON.stringify(retObj));
20 | } else {
21 | const retObj = {
22 | msg: 'error',
23 | result: 'ETH already active!',
24 | };
25 | res.send(JSON.stringify(retObj));
26 | }
27 | } else {
28 | const retObj = {
29 | msg: 'error',
30 | result: 'cannot activate non-eth coin on ETH network',
31 | };
32 | res.send(JSON.stringify(retObj));
33 | }
34 | } catch(e) {
35 | const retObj = {
36 | msg: 'error',
37 | result: e.message,
38 | };
39 | res.send(JSON.stringify(retObj));
40 | }
41 | });
42 |
43 | api.setPost('/eth/remove_coin', (req, res) => {
44 | api.eth.interface = null
45 |
46 | const retObj = {
47 | msg: 'success',
48 | result: true,
49 | };
50 |
51 | res.send(JSON.stringify(retObj));
52 | });
53 |
54 | return api;
55 | };
--------------------------------------------------------------------------------
/routes/api/eth/balances.js:
--------------------------------------------------------------------------------
1 | const ethers = require('ethers');
2 |
3 | module.exports = (api) => {
4 | api.setGet("/eth/get_balances", async (req, res, next) => {
5 | try {
6 | res.send(
7 | JSON.stringify({
8 | msg: "success",
9 | result: {
10 | native: {
11 | public: {
12 | //TODO: Return string instead
13 | confirmed: Number(ethers.formatEther(
14 | await api.eth.get_wallet_balance()
15 | )),
16 | unconfirmed: null,
17 | immature: null,
18 | interest: null,
19 | },
20 | private: {
21 | confirmed: null,
22 | },
23 | },
24 | reserve: {},
25 | },
26 | })
27 | );
28 | } catch (e) {
29 | res.send(
30 | JSON.stringify({
31 | msg: "error",
32 | result: e.message,
33 | })
34 | );
35 | }
36 | });
37 |
38 | api.eth.get_address_balance = async (address) => {
39 | if (api.eth.interface != null) {
40 | return api.eth.interface.DefaultProvider.getBalance(address)
41 | } else {
42 | throw new Error("Cannot get balance for inactive coin ETH")
43 | }
44 | }
45 |
46 | api.eth.get_wallet_balance = async () => {
47 | if (api.eth.wallet != null) {
48 | return await api.eth.get_address_balance(api.eth.wallet.address)
49 | } else {
50 | throw new Error("No wallet authenticated, cannot get wallet balance for ETH")
51 | }
52 | }
53 |
54 | return api;
55 | };
--------------------------------------------------------------------------------
/routes/preloads/plugin/preload-builtin.js:
--------------------------------------------------------------------------------
1 | const {
2 | contextBridge,
3 | shell,
4 | ipcRenderer
5 | } = require("electron");
6 | const fs = require('fs')
7 | const os = require('os')
8 | const url = require('url')
9 |
10 | const generateOpenExternalSafe = require('../../workers/openExternalSafe')
11 | const arch = require('arch');
12 | const chainParams = require("../../chainParams")
13 | const assetChainPorts = require("../../ports")
14 | const version = require('../../../version.json');
15 | const { pathsAgama } = require("../../api/pathsUtil");
16 | const appConfig = require("../../appConfig").config
17 |
18 | let apiShell = {}
19 | pathsAgama(apiShell, os.platform() === "win32" ? process.env.APPDATA : process.env.HOME)
20 |
21 | contextBridge.exposeInMainWorld("bridge", {
22 | getConfigSync: () =>
23 | JSON.parse(
24 | fs.readFileSync(`${apiShell.paths.agamaDir}/config.json`, "utf8")
25 | ),
26 | getSecretSync: () => JSON.parse(fs.readFileSync(`${apiShell.paths.agamaDir}/builtinsecret.json`, "utf8")).data,
27 | defaultConfig: appConfig,
28 | shell: {
29 | openExternal: generateOpenExternalSafe(shell, url),
30 | },
31 | assetChainPorts,
32 | appBasicInfo: {
33 | name: "Verus Desktop",
34 | mode: global.USB_MODE ? "usb" : "standard",
35 | version: version.version,
36 | },
37 | arch: arch(),
38 | chainParams
39 | });
40 |
41 | ipcRenderer.on('ipc', (_, msg) => {
42 | try {
43 | if (msg.type === 'response' || msg.type === 'push'|| msg.type === 'init') {
44 | window.postMessage(JSON.stringify(msg), '*');
45 | }
46 | } catch (err) {
47 | console.error(err);
48 | }
49 | });
--------------------------------------------------------------------------------
/routes/api/eth/addresses.js:
--------------------------------------------------------------------------------
1 | const { ethers } = require("ethers");
2 |
3 | module.exports = (api) => {
4 | api.eth.get_address = () => {
5 | if (api.eth.wallet != null) {
6 | return api.eth.wallet.address
7 | } else {
8 | throw new Error("No wallet authenticated, cannot get wallet address for ETH")
9 | }
10 | };
11 |
12 | api.eth.get_addresses = async () => {
13 | return {
14 | public: [{
15 | address: api.eth.get_address(),
16 | tag: "eth",
17 | balances: {
18 | native: ethers.formatEther(await api.eth.get_wallet_balance()),
19 | reserve: {}
20 | }
21 | }],
22 | private: []
23 | }
24 | };
25 |
26 | api.setGet('/eth/get_addresses', (req, res, next) => {
27 | api.eth.get_addresses()
28 | .then((addresses) => {
29 | const retObj = {
30 | msg: 'success',
31 | result: addresses,
32 | };
33 |
34 | res.send(JSON.stringify(retObj));
35 | })
36 | .catch(error => {
37 | const retObj = {
38 | msg: 'error',
39 | result: error.message,
40 | };
41 |
42 | res.send(JSON.stringify(retObj));
43 | })
44 | });
45 |
46 | api.setPost('/eth/get_privkey', (req, res, next) => {
47 | if (api.eth.wallet != null) {
48 | res.send(JSON.stringify({
49 | msg: 'success',
50 | result: api.eth.wallet.signer.signingKey.privateKey,
51 | }));
52 | } else {
53 | res.send(JSON.stringify({
54 | msg: 'error',
55 | result: `No ETH privkey found`
56 | }));
57 | }
58 | }, true);
59 |
60 | return api;
61 | };
--------------------------------------------------------------------------------
/routes/api/plugin/builtin/authenticator.js:
--------------------------------------------------------------------------------
1 | const { pushMessage } = require('../../../ipc/ipc');
2 | const { ReservedPluginTypes } = require('../../utils/plugin/builtin');
3 |
4 | module.exports = (api) => {
5 | api.authenticator = {}
6 |
7 | api.authenticator.authenticate = async (chainTicker, mode, originAppId, originBuiltin) => {
8 | return new Promise((resolve, reject) => {
9 | try {
10 | api.startPlugin(ReservedPluginTypes.VERUS_DESKTOP_AUTHENTICATOR, true, (data = {authorized: false}) => {
11 | resolve(data)
12 | }, (pluginWindow) => {
13 | pushMessage(pluginWindow, {
14 | ticker: chainTicker,
15 | mode: mode,
16 | origin_app_info: {
17 | id: originAppId,
18 | search_builtin: originBuiltin
19 | },
20 | launch_config: {}
21 | }, "VERUS_DESKTOP_AUTHENTICATOR_COIN_REQUEST")
22 | }, 630, 350, false)
23 | } catch(e) {reject(e)}
24 | })
25 | }
26 |
27 | api.setPost('/plugin/builtin/authenticator/authenticate', async (req, res, next) => {
28 | const { chainTicker, mode } = req.body
29 | const { app_id, builtin } = req.api_header
30 |
31 | try {
32 | const retObj = {
33 | msg: 'success',
34 | result: await api.authenticator.authenticate(chainTicker, mode, app_id, builtin),
35 | };
36 |
37 | res.send(JSON.stringify(retObj));
38 | } catch (e) {
39 | const retObj = {
40 | msg: 'error',
41 | result: e.message,
42 | };
43 |
44 | res.send(JSON.stringify(retObj));
45 | }
46 | });
47 |
48 | return api;
49 | };
--------------------------------------------------------------------------------
/routes/api/utils/plugin/builtin.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | const ReservedPluginTypes = {
4 | VERUS_DESKTOP_MAIN: "VERUS_DESKTOP_MAIN",
5 | VERUS_DESKTOP_AUTHENTICATOR: "VERUS_DESKTOP_AUTHENTICATOR",
6 | VERUS_LOGIN_CONSENT_UI: "VERUS_LOGIN_CONSENT_UI",
7 | VERUS_PBAAS_VISUALIZER: "VERUS_PBAAS_VISUALIZER"
8 | }
9 |
10 | // Builtin plugins have access to all permissions by default
11 | const BuiltinPlugins = {
12 | [ReservedPluginTypes.VERUS_DESKTOP_MAIN]: {
13 | name: "Verus Desktop",
14 | devPort: 3000
15 | },
16 | [ReservedPluginTypes.VERUS_DESKTOP_AUTHENTICATOR]: {
17 | name: "Authenticator",
18 | path: path.join(
19 | __dirname,
20 | "../",
21 | "../",
22 | "../",
23 | "../",
24 | "assets",
25 | "plugins",
26 | "builtin",
27 | "verus-desktop-authenticator"
28 | ),
29 | devPort: 3001
30 | },
31 | [ReservedPluginTypes.VERUS_LOGIN_CONSENT_UI]: {
32 | name: "VerusID Authentication",
33 | path: path.join(
34 | __dirname,
35 | "../",
36 | "../",
37 | "../",
38 | "../",
39 | "assets",
40 | "plugins",
41 | "builtin",
42 | "verus-login-consent-client"
43 | ),
44 | devPort: 3001
45 | },
46 | [ReservedPluginTypes.VERUS_PBAAS_VISUALIZER]: {
47 | name: "Visualizer",
48 | path: path.join(
49 | __dirname,
50 | "../",
51 | "../",
52 | "../",
53 | "../",
54 | "assets",
55 | "plugins",
56 | "builtin",
57 | "verus-pbaas-visualizer"
58 | ),
59 | devPort: 3003
60 | }
61 | };
62 |
63 | module.exports = {
64 | BuiltinPlugins,
65 | ReservedPluginTypes
66 | }
--------------------------------------------------------------------------------
/routes/api/native/getBlock.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | /**
3 | * Gets a block given a height.
4 | *
5 | * @param {String} coin The chainTicker of the coin to make the call on
6 | * @param {String} hashorheight The block hash or height
7 | * @param {String} verbosity The verbosity of the result. 0 for hex encoded data, 1 for a json object, and 2 for json object with transaction data
8 | */
9 | api.native.get_block = (
10 | coin,
11 | hashorheight,
12 | verbosity = 1,
13 | ) => {
14 | return new Promise((resolve, reject) => {
15 | api.native
16 | .callDaemon(
17 | coin,
18 | "getblock",
19 | [
20 | hashorheight,
21 | verbosity
22 | ]
23 | )
24 | .then(resultObj => {
25 | resolve(resultObj)
26 | })
27 | .catch(err => {
28 | reject(err);
29 | });
30 | });
31 | };
32 |
33 | api.setPost('/native/get_block', (req, res, next) => {
34 | const {
35 | chainTicker,
36 | hashorheight,
37 | verbosity
38 | } = req.body;
39 |
40 | api.native
41 | .get_block(
42 | chainTicker,
43 | hashorheight,
44 | verbosity
45 | )
46 | .then(resultObj => {
47 | const retObj = {
48 | msg: "success",
49 | result: resultObj
50 | };
51 |
52 | res.send(JSON.stringify(retObj));
53 | })
54 | .catch(error => {
55 | const retObj = {
56 | msg: "error",
57 | result: error.message
58 | };
59 |
60 | res.send(JSON.stringify(retObj));
61 | });
62 | });
63 |
64 | return api;
65 | }
--------------------------------------------------------------------------------
/routes/api/native/getVdxfId.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | /**
3 | * Returns the VDXF key of the URI string.
4 | *
5 | * @param {String} coin The chainTicker of the coin to make the call on
6 | * @param {String} vdxfuri This message is converted from hex, the data is hashed, then returned
7 | * @param {Object} initialvdxfdata The optional data of (vdxfkey, uint256, indexnum) that is combined.
8 | */
9 | api.native.get_vdxf_id = (
10 | coin,
11 | vdxfuri,
12 | initialvdxfdata = {},
13 | ) => {
14 | return new Promise((resolve, reject) => {
15 | api.native
16 | .callDaemon(
17 | coin,
18 | "getvdxfid",
19 | [
20 | vdxfuri,
21 | initialvdxfdata
22 | ]
23 | )
24 | .then(resultObj => {
25 | resolve(resultObj)
26 | })
27 | .catch(err => {
28 | reject(err);
29 | });
30 | });
31 | };
32 |
33 | api.setPost('/native/get_vdxf_id', (req, res, next) => {
34 | const {
35 | chainTicker,
36 | vdxfuri,
37 | initialvdxfdata
38 | } = req.body;
39 |
40 | api.native
41 | .get_vdxf_id(
42 | chainTicker,
43 | vdxfuri,
44 | initialvdxfdata
45 | )
46 | .then(resultObj => {
47 | const retObj = {
48 | msg: "success",
49 | result: resultObj
50 | };
51 |
52 | res.send(JSON.stringify(retObj));
53 | })
54 | .catch(error => {
55 | const retObj = {
56 | msg: "error",
57 | result: error.message
58 | };
59 |
60 | res.send(JSON.stringify(retObj));
61 | });
62 | });
63 |
64 | return api;
65 | }
--------------------------------------------------------------------------------
/routes/api/utils/request/request.js:
--------------------------------------------------------------------------------
1 | const axios = require('axios')
2 |
3 | function parseError(error) {
4 | return error.response ? error.response.data.message : error.toString()
5 | }
6 |
7 | async function formatResponse(call, returnFull) {
8 | try {
9 | const res = await call();
10 | return returnFull ? res : res.data;
11 | } catch (error) {
12 | throw new Error(parseError(error));
13 | }
14 | };
15 |
16 | function requestContentType(contentType, method, url, body = {}, options = {}, returnFull = false) {
17 | return formatResponse(() => {
18 | switch (method) {
19 | case "GET":
20 | return axios.get(url, {
21 | ...options,
22 | headers:
23 | options.headers != null
24 | ? { ...options.headers, "Content-Type": contentType }
25 | : { "Content-Type": contentType },
26 | });
27 | case "POST":
28 | return axios.post(url, body, {
29 | ...options,
30 | headers:
31 | options.headers != null
32 | ? { ...options.headers, "Content-Type": contentType }
33 | : { "Content-Type": contentType },
34 | });
35 | default:
36 | throw new Error(method + " is not a valid method type.");
37 | }
38 | }, returnFull);
39 | }
40 |
41 | function requestJson(method, url, body = {}, options = {}, returnFull = false) {
42 | return requestContentType("application/json", method, url, body, options, returnFull)
43 | }
44 |
45 | function requestXml(method, url, body = {}, options = {}, returnFull = false) {
46 | return requestContentType("application/xml", method, url, body, options, returnFull)
47 | }
48 |
49 | module.exports = {
50 | requestJson,
51 | requestXml
52 | }
--------------------------------------------------------------------------------
/routes/api/utils/standardization/standardizeInfo.js:
--------------------------------------------------------------------------------
1 | const { requestJson } = require('../request/request');
2 |
3 | const standardizeZecInfo = (info) => {
4 | return new Promise(async (resolve, reject) => {
5 | try {
6 | const res = await requestJson(
7 | "GET",
8 | "https://api.zcha.in/v2/mainnet/network"
9 | );
10 |
11 | resolve({...info, longestchain: res.blockNumber})
12 | } catch(e) {
13 | reject(e)
14 | }
15 | })
16 | }
17 |
18 | const standardizationFns = {
19 | ['ZEC']: standardizeZecInfo
20 | }
21 |
22 | /**
23 | * Standardizes the behaviour of the get_info call to always include
24 | * utilized important values like 'longestchain' when they may not be
25 | * present, e.g., in ZEC. Returns a promise resolving to the standardized
26 | * info object.
27 | *
28 | * @param {Object} info The info result object to standardize
29 | * @param {String} coin The coin ticker to standardize
30 | * @param {Object} api The api object (for logging purposes)
31 | */
32 | const standardizeInfo = (info, coin, api) => {
33 | let standardizationPromises = []
34 |
35 | if (standardizationFns[coin] != null) {
36 | standardizationPromises.push(
37 | standardizationFns[coin](info)
38 | );
39 | } else {
40 | standardizationPromises = [info]
41 | }
42 |
43 | return new Promise((resolve, reject) => {
44 | Promise.all(standardizationPromises)
45 | .then(infoArr => resolve(infoArr[0]))
46 | .catch(e => {
47 | api.log(`info standardization failed for ${coin}, returning regular info object:`, 'standardizeInfo');
48 | api.log(e, 'standardizeInfo')
49 | resolve(info);
50 | });
51 | });
52 | }
53 |
54 | module.exports = standardizeInfo
--------------------------------------------------------------------------------
/routes/api/native/verusid/provision/verifyIdProvisioningResponse.js:
--------------------------------------------------------------------------------
1 | const { LoginConsentProvisioningResponse } = require("verus-typescript-primitives");
2 | const { ROOT_SYSTEM_NAME } = require("../../../utils/constants/dev_options");
3 |
4 | module.exports = (api) => {
5 | /**
6 | * Verifies a provisioning response
7 | * @param {LoginConsentProvisioningResponse} Response
8 | */
9 | api.native.verusid.provision.verify_id_provisioning_response = async (response) => {
10 | const provisioningResponse = new LoginConsentProvisioningResponse(response);
11 |
12 | // Convert the system id to the chain name.
13 | const currencyObject = await api.native.get_currency(
14 | ROOT_SYSTEM_NAME,
15 | response.system_id
16 | );
17 | const chainTicker = currencyObject.name.toUpperCase();
18 |
19 | const verified = await api.native.verify_hash(
20 | chainTicker,
21 | provisioningResponse.signing_id,
22 | provisioningResponse.decision.toSha256().toString('hex'),
23 | provisioningResponse.signature.signature
24 | );
25 |
26 | return verified ? { verified } : { verified, message: "Failed to verify signature" };
27 | };
28 |
29 | api.setPost("/native/verusid/provision/verify_id_provisioning_response", async (req, res, next) => {
30 | const { response } = req.body;
31 |
32 | try {
33 | res.send(
34 | JSON.stringify({
35 | msg: "success",
36 | result: await api.native.verusid.provision.verify_id_provisioning_response(response),
37 | })
38 | );
39 | } catch (e) {
40 | res.send(
41 | JSON.stringify({
42 | msg: "error",
43 | result: e.message,
44 | })
45 | );
46 | }
47 | });
48 |
49 | return api;
50 | };
51 |
--------------------------------------------------------------------------------
/routes/preloads/plugin/preload-default.js:
--------------------------------------------------------------------------------
1 | /*
2 | Reasonably Secure Electron
3 | Copyright (C) 2019 Bishop Fox
4 | This program is free software; you can redistribute it and/or
5 | modify it under the terms of the GNU General Public License
6 | as published by the Free Software Foundation; either version 2
7 | of the License, or (at your option) any later version.
8 | This program is distributed in the hope that it will be useful,
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | GNU General Public License for more details.
12 | You should have received a copy of the GNU General Public License
13 | along with this program; if not, write to the Free Software
14 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 | -------------------------------------------------------------------------
16 | This preload script is callable from within the sandbox via postMessage,
17 | but should not be directly accessible since it itself is not sandboxed.
18 | */
19 |
20 | const { ipcRenderer } = require('electron');
21 |
22 |
23 | window.addEventListener('message', (event) => {
24 | try {
25 | const msg = JSON.parse(event.data);
26 | if (msg.type === 'request') {
27 | if (['fs_'].some(prefix => msg.method.startsWith(prefix))) {
28 | ipcRenderer.send('ipc', msg);
29 | }
30 | }
31 | } catch (err) {
32 | console.error(err);
33 | }
34 | });
35 |
36 | ipcRenderer.on('ipc', (_, msg) => {
37 | try {
38 | if (msg.type === 'response' || msg.type === 'push' || msg.type === 'init') {
39 | console.log(JSON.parse(msg.data))
40 |
41 | window.postMessage(JSON.stringify(msg), '*');
42 | }
43 | } catch (err) {
44 | console.error(err);
45 | }
46 | });
--------------------------------------------------------------------------------
/routes/api/plugin/builtin/pbaasvisualizer.js:
--------------------------------------------------------------------------------
1 | const { pushMessage } = require('../../../ipc/ipc');
2 | const { ReservedPluginTypes } = require('../../utils/plugin/builtin');
3 |
4 | module.exports = (api) => {
5 | api.pbaasVisualizer = {}
6 |
7 | api.pbaasVisualizer.visualize = async (
8 | request,
9 | originInfo
10 | ) => {
11 | return new Promise((resolve, reject) => {
12 | try {
13 | api.startPlugin(
14 | ReservedPluginTypes.VERUS_PBAAS_VISUALIZER,
15 | true,
16 | () => {},
17 | (pluginWindow) => {
18 | pushMessage(
19 | pluginWindow,
20 | {
21 | request: request,
22 | origin_app_info: originInfo,
23 | },
24 | "VERUS_PBAAS_VISUALIZER_REQUEST"
25 | );
26 | },
27 | 1280,
28 | 850
29 | );
30 |
31 | // No need to wait for any data to be returned, visualization is static
32 | resolve()
33 | } catch (e) {
34 | reject(e);
35 | }
36 | });
37 | };
38 |
39 | api.setPost('/plugin/builtin/verus_pbaas_visualizer/visualize', async (req, res, next) => {
40 | const { request } = req.body;
41 | const { app_id, builtin } = req.api_header
42 |
43 | try {
44 | const retObj = {
45 | msg: "success",
46 | result: await api.pbaasVisualizer.visualize(
47 | request,
48 | {
49 | id: app_id,
50 | search_builtin: builtin,
51 | }
52 | ),
53 | };
54 |
55 | res.send(JSON.stringify(retObj));
56 | } catch (e) {
57 | const retObj = {
58 | msg: 'error',
59 | result: e.message,
60 | };
61 |
62 | res.send(JSON.stringify(retObj));
63 | }
64 | });
65 |
66 | return api;
67 | };
--------------------------------------------------------------------------------
/routes/api/erc20/addresses.js:
--------------------------------------------------------------------------------
1 | const { ethers } = require("ethers");
2 |
3 | module.exports = (api) => {
4 | api.erc20.get_address = () => {
5 | if (api.erc20.wallet != null) {
6 | return api.erc20.wallet.address
7 | } else {
8 | throw new Error("No wallet authenticated, cannot get wallet address for ERC20")
9 | }
10 | };
11 |
12 | api.erc20.get_addresses = async (contractId) => {
13 | return {
14 | public: [
15 | {
16 | address: api.erc20.get_address(),
17 | tag: "eth",
18 | balances: {
19 | native: ethers.formatUnits(
20 | await api.erc20.get_wallet_balance(contractId),
21 | api.erc20.contracts[contractId].decimals
22 | ),
23 | reserve: {},
24 | },
25 | },
26 | ],
27 | private: [],
28 | };
29 | };
30 |
31 | api.setGet('/erc20/get_addresses', (req, res, next) => {
32 | api.erc20.get_addresses(req.query.chainTicker)
33 | .then((addresses) => {
34 | const retObj = {
35 | msg: 'success',
36 | result: addresses,
37 | };
38 |
39 | res.send(JSON.stringify(retObj));
40 | })
41 | .catch(error => {
42 | const retObj = {
43 | msg: 'error',
44 | result: error.message,
45 | };
46 |
47 | res.send(JSON.stringify(retObj));
48 | })
49 | });
50 |
51 | api.setPost('/erc20/get_privkey', (req, res, next) => {
52 | if (api.erc20.wallet != null) {
53 | res.send(JSON.stringify({
54 | msg: 'success',
55 | result: api.erc20.wallet.signer.signingKey.privateKey,
56 | }));
57 | } else {
58 | res.send(JSON.stringify({
59 | msg: 'error',
60 | result: `No ETH privkey found`
61 | }));
62 | }
63 | }, true);
64 |
65 | return api;
66 | };
--------------------------------------------------------------------------------
/routes/api/native/estimateSendcurrencyFee.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.native.estimate_sendcurrency_fee = async (chain, _params, minconfs = 1, sendfee = 0.0001) => {
3 | try {
4 | let feecurrency;
5 |
6 | const vETH = await api.native.get_currency(chain, 'vETH');
7 |
8 | // These are throwaway addresses, without any funds, to ensure this
9 | // tx would fail if it were to be broadcasted, or at least not spend
10 | // any user funds in the absolute worst case scenario.
11 | const raddr = "RGM3raQ1McqQYZpFyuBrqUpLnmgK7h8k4A"
12 | const address = _params.exportto === vETH.currencyid ?
13 | "0xd62971620094e8244F1ed3B12a8D31bC969081fA"
14 | :
15 | raddr;
16 |
17 | const params = {..._params, amount: 0, address};
18 |
19 | const res = await api.native.callDaemon(chain, 'sendcurrency', [raddr, [params], minconfs, sendfee, true]);
20 |
21 | if (params.feecurrency == null) {
22 | const chainCurrency = await api.native.get_currency(chain, chain);
23 | feecurrency = chainCurrency.currencyid;
24 | } else feecurrency = params.feecurrency;
25 |
26 | return res.outputtotals[feecurrency];
27 | } catch(e) {
28 | throw e
29 | }
30 | };
31 |
32 | api.setPost('/native/estimate_sendcurrency_fee', async (req, res, next) => {
33 | const { chainTicker, params, minconfs, sendfee } = req.body;
34 |
35 | try {
36 | const retObj = {
37 | msg: 'success',
38 | result: await api.native.estimate_sendcurrency_fee(chainTicker, params, minconfs, sendfee),
39 | };
40 |
41 | res.send(JSON.stringify(retObj));
42 | } catch(e) {
43 | const retObj = {
44 | msg: 'error',
45 | result: e.message,
46 | };
47 |
48 | res.send(JSON.stringify(retObj));
49 | }
50 | });
51 |
52 | return api;
53 | };
--------------------------------------------------------------------------------
/routes/api/downloadUtil.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra');
2 | const http = require('http')
3 | const https = require('https')
4 | const axios = require('axios')
5 |
6 | module.exports = (api) => {
7 | /**
8 | * Promise based download file method
9 | */
10 | api.downloadFile = (configuration) => {
11 | return new Promise(async (resolve, reject) => {
12 | try {
13 | // Save variable to know progress
14 | let receivedBytes = 0;
15 | let totalBytes = 0;
16 | const httpAgent = new http.Agent({ keepAlive: true });
17 | const httpsAgent = new https.Agent({ keepAlive: true });
18 |
19 | const req = await axios({
20 | method: 'get',
21 | url: configuration.remoteFile,
22 | responseType: 'stream',
23 | httpAgent,
24 | httpsAgent,
25 | })
26 |
27 | let out = fs.createWriteStream(configuration.localFile);
28 | req.data.pipe(out);
29 |
30 | req.data.on("response", (data) => {
31 | // Change the total bytes value to get progress later.
32 | totalBytes = parseInt(data.headers["content-length"]);
33 | });
34 |
35 | // Get progress if callback exists
36 | if (configuration.hasOwnProperty("onProgress")) {
37 | req.data.on("data", (chunk) => {
38 | // Update the received bytes
39 | receivedBytes += chunk.length;
40 | configuration.onProgress(receivedBytes, totalBytes);
41 | });
42 | } else {
43 | req.data.on("data", (chunk) => {
44 | // Update the received bytes
45 | receivedBytes += chunk.length;
46 | });
47 | }
48 |
49 | req.data.on("end", () => {
50 | resolve();
51 | });
52 | } catch (e) {
53 | reject(e);
54 | }
55 |
56 | });
57 | }
58 |
59 | return api;
60 | };
--------------------------------------------------------------------------------
/routes/api/native/verusid/provision/signIdProvisioningRequest.js:
--------------------------------------------------------------------------------
1 | const { VerusIDSignature, IDENTITY_AUTH_SIG_VDXF_KEY } = require("verus-typescript-primitives");
2 | const { ProvisioningRequest } = require("verus-typescript-primitives/dist/vdxf/classes/provisioning/ProvisioningRequest");
3 |
4 | module.exports = (api) => {
5 | /**
6 | * Signs a provisioning request using an r-address.
7 | *
8 | * @param {String} coin The chainTicker of the coin to make the call on
9 | * @param {String} request The provisioning request to sign
10 | * @param {String} raddress The raddress to sign the provioning requset with
11 | */
12 | api.native.verusid.provision.sign_id_provisioning_request = async (coin, request, raddress) => {
13 |
14 | const provisioningRequest = new ProvisioningRequest(request);
15 |
16 | const signdataResult = await api.native.sign_data(coin,
17 | {
18 | "address": raddress,
19 | "datahash": provisioningRequest.challenge.toSha256().toString("hex")
20 | }
21 | )
22 |
23 | provisioningRequest.signature = new VerusIDSignature(
24 | { signature: signdataResult.signature },
25 | IDENTITY_AUTH_SIG_VDXF_KEY
26 | );
27 |
28 | return provisioningRequest;
29 | }
30 |
31 | api.setPost('/native/verusid/provision/sign_id_provisioning_request', async (req, res, next) => {
32 | const {
33 | chainTicker,
34 | request,
35 | raddress
36 | } = req.body;
37 |
38 | try {
39 | res.send(
40 | JSON.stringify({
41 | msg: "success",
42 | result: await api.native.verusid.provision.sign_id_provisioning_request(chainTicker, request, raddress),
43 | })
44 | );
45 | } catch (e) {
46 | res.send(
47 | JSON.stringify({
48 | msg: "error",
49 | result: e.message,
50 | })
51 | );
52 | }
53 | });
54 |
55 | return api;
56 | }
--------------------------------------------------------------------------------
/routes/api/electrum/block.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = (api) => {
3 | api.setGet('/electrum/getblockinfo', (req, res, next) => {
4 | api.electrumGetBlockInfo(req.query.height, req.query.network)
5 | .then((json) => {
6 | const retObj = {
7 | msg: 'success',
8 | result: json,
9 | };
10 |
11 | res.send(JSON.stringify(retObj));
12 | });
13 | });
14 |
15 | api.electrumGetBlockInfo = (height, network) => {
16 | return new Promise((resolve, reject) => {
17 | async function _electrumGetBlockInfo() {
18 | const ecl = await api.ecl(network);
19 |
20 | ecl.blockchainBlockGetHeader(height).then((json) => {
21 | api.log("electrum getblockinfo ==>", "spv.getblockinfo");
22 | api.log(json, "spv.getblockinfo");
23 |
24 | resolve(json);
25 | });
26 | }
27 | _electrumGetBlockInfo();
28 | });
29 | }
30 |
31 | api.setGet('/electrum/getcurrentblock', (req, res, next) => {
32 | api.electrumGetCurrentBlock(req.query.network)
33 | .then((json) => {
34 | const retObj = {
35 | msg: 'success',
36 | result: json,
37 | };
38 |
39 | res.send(JSON.stringify(retObj));
40 | });
41 | });
42 |
43 | api.electrumGetCurrentBlock = (network, returnNspvReq) => {
44 | return new Promise((resolve, reject) => {
45 | async function _electrumGetCurrentBlock() {
46 | const ecl = await api.ecl(network);
47 |
48 | ecl.blockchainHeadersSubscribe().then((json) => {
49 | if (json && json.hasOwnProperty("block_height")) {
50 | resolve(json.block_height);
51 | } else if (json && json.hasOwnProperty("height")) {
52 | resolve(json.height);
53 | } else {
54 | resolve(json);
55 | }
56 | });
57 | };
58 | _electrumGetCurrentBlock();
59 | });
60 | }
61 |
62 | return api;
63 | };
--------------------------------------------------------------------------------
/routes/api/system.js:
--------------------------------------------------------------------------------
1 | const si = require('systeminformation')
2 |
3 | module.exports = (api) => {
4 | /*
5 | * type: GET
6 | */
7 | api.setGet('/get_static_system_data', (req, res, next) => {
8 | si.getStaticData()
9 | .then(data => {
10 | res.send(JSON.stringify({
11 | msg: 'success',
12 | result: data
13 | }));
14 | })
15 | .catch(e => {
16 | res.send(JSON.stringify({
17 | msg: 'error',
18 | result: e.message
19 | }));
20 | })
21 | });
22 |
23 | /*
24 | * type: GET
25 | */
26 | api.setGet('/get_cpu_temp', (req, res, next) => {
27 | const CPU_TEMP_UNSUPPORTED = null
28 |
29 | si.cpuTemperature()
30 | .then(data => {
31 | if (data.main && data.main === CPU_TEMP_UNSUPPORTED) throw new Error('unsupported_operation')
32 |
33 | res.send(JSON.stringify({
34 | msg: 'success',
35 | result: data
36 | }));
37 | })
38 | .catch(e => {
39 | res.send(JSON.stringify({
40 | msg: 'error',
41 | result: e.message
42 | }));
43 | })
44 | });
45 |
46 | /*
47 | * type: GET
48 | */
49 | api.setGet('/get_cpu_load', (req, res, next) => {
50 | si.currentLoad()
51 | .then(data => {
52 | res.send(JSON.stringify({
53 | msg: 'success',
54 | result: data
55 | }));
56 | })
57 | .catch(e => {
58 | res.send(JSON.stringify({
59 | msg: 'error',
60 | result: e.message
61 | }));
62 | })
63 | });
64 |
65 | /*
66 | * type: GET
67 | */
68 | api.setGet('/get_sys_time', (req, res, next) => {
69 | try {
70 | res.send(JSON.stringify({
71 | msg: 'success',
72 | result: si.time()
73 | }));
74 | } catch (e) {
75 | res.send(JSON.stringify({
76 | msg: 'error',
77 | result: e.message
78 | }));
79 | }
80 | });
81 |
82 | return api;
83 | };
84 |
--------------------------------------------------------------------------------
/test/verusid-login.js:
--------------------------------------------------------------------------------
1 | const test_request = {
2 | chain_id: "VRSCTEST",
3 | signing_id: "login-consent-server@",
4 | signature: {
5 | signature:
6 | "AaYuAAABQSD/UR9NIeimLYyUrkJ7kfjXJz0QiuVsFIt+lEu+KSELCX5zxAlIiciuIHLIzKLsuqMFL3XDapg/1TnV0b6hXoSX",
7 | },
8 | challenge: {
9 | uuid: "7bb518c4eec2454dbb289f5fdb4c0ee2",
10 | requested_scope: ["vrsc::system.identity.authentication.scope.read-id-name"],
11 | requested_access_token_audience: null,
12 | skip: false,
13 | oidc_context: {},
14 | request_url: "http://127.0.0.1:4444/oauth2?full=request&url=",
15 | client: {
16 | client_id: "auth-code-client",
17 | name: "Online Service",
18 | redirect_uris: ["http://127.0.0.1:5555/callback"],
19 | grant_types: ["authorization_code", "refresh_token"],
20 | response_types: ["code", "id_token"],
21 | scope: "vrsc::system.identity.authentication.scope.read-id-name",
22 | audience: null,
23 | owner: "",
24 | policy_uri: "https://verus.io/privacy-policy",
25 | allowed_cors_origins: null,
26 | tos_uri: "https://en.wikipedia.org/wiki/Lorem_ipsum",
27 | client_uri: "https://verus.io/",
28 | logo_uri:
29 | "https://github.com/VerusCoin/Media-Assets/blob/master/Logos/PNG%20(pixel)/Logo/verus-icon-blue-500px.png",
30 | contacts: null,
31 | client_secret_expires_at: 0,
32 | subject_type: "public",
33 | token_endpoint_auth_method: "client_secret_basic",
34 | userinfo_signed_response_alg: "none",
35 | created_at: "2020-07-08T12:31:47Z",
36 | updated_at: "2020-07-08T12:31:47Z",
37 | },
38 | },
39 | };
40 |
41 | const test_response_no_sig = {
42 | chain_id: "VRSCTEST",
43 | signing_id: "login-consent-server@",
44 | decision: {
45 | subject: "Client@",
46 | remember: true,
47 | remember_for: 7200,
48 | force_subject_identifier: "string",
49 | request: test_request,
50 | },
51 | };
52 |
--------------------------------------------------------------------------------
/routes/api/data_files/backup.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra');
2 |
3 | module.exports = (api) => {
4 | /**
5 | * Backs up all necessary app data stored for Verus Desktop
6 | */
7 | api.backupAppData = async (backupName) => {
8 | if (
9 | backupName.includes(".") ||
10 | backupName.includes("/") ||
11 | backupName.includes("\\") ||
12 | backupName.includes("*") ||
13 | backupName.includes("~") ||
14 | backupName == null
15 | ) {
16 | throw new Error(`Backup data name (${backupName}) cannot include any of the following: ./\\*~`)
17 | }
18 |
19 | try {
20 | await fs.access(api.paths.agamaDir, fs.constants.R_OK);
21 | } catch (e) {
22 | if (e.code == "EACCES") {
23 | await fs.chmod(path, "0666");
24 | } else if (e.code === "ENOENT") {
25 | api.handleFileProblem(`Verus Desktop directory not found`, !handleErrors)
26 | return
27 | }
28 | }
29 |
30 | try {
31 | const backupPath = `${api.paths.backupDir}/${backupName}`
32 |
33 | if (await fs.exists(backupPath)) {
34 | throw new Error(`Backup at ${backupPath} already exists!`)
35 | }
36 |
37 | await fs.copy(api.paths.agamaDir, backupPath);
38 |
39 | api.log(
40 | `appdata backup created at ${backupPath}`,
41 | "backup"
42 | );
43 | return
44 | } catch (e) {
45 | api.log(e, 'backup');
46 | throw e
47 | }
48 | };
49 |
50 | api.setPost('/backup_appdata', async (req, res, next) => {
51 | const { dirName } = req.body
52 |
53 | try {
54 | const retObj = {
55 | msg: 'success',
56 | result: await api.backupAppData(dirName),
57 | };
58 |
59 | res.send(JSON.stringify(retObj));
60 | } catch (e) {
61 | const retObj = {
62 | msg: 'error',
63 | result: e.message,
64 | };
65 |
66 | res.send(JSON.stringify(retObj));
67 | }
68 | });
69 |
70 | return api;
71 | };
--------------------------------------------------------------------------------
/test/spec-kmd.js:
--------------------------------------------------------------------------------
1 | const Application = require('spectron').Application
2 | const assert = require('assert')
3 | const electronPath = require('electron') // Require Electron from the binaries included in node_modules.
4 | const path = require('path')
5 | const chai = require('chai')
6 | const timeout = 7500;
7 | describe('Application launch testing native KMD coin', function () {
8 | this.timeout(timeout)
9 | before(function () {
10 | this.gotDomReadyCount = 0
11 | this.app = new Application({
12 | path: electronPath,
13 | // The following line tells spectron to look and use the main.js file
14 | // and the package.json located 1 level above.
15 | args: [path.join(__dirname, '..')],
16 | startTimeout: timeout,
17 | waitTimeout: timeout
18 | })
19 | return this.app.start()
20 | })
21 |
22 | after(function () {
23 | if (this.app && this.app.isRunning()) {
24 | return this.app.stop()
25 | }
26 | })
27 |
28 | it('opens a window', function (done) {
29 | this.app.client.waitUntilWindowLoaded()
30 | .getWindowCount().then(function (count) {
31 | assert.equal(count, 1)
32 | done()
33 | })
34 | })
35 |
36 | it('has a native coin list that takes kmd', function (done) {
37 | // Wait for the left button for native mode coins is visible
38 | this.app.client.element('#react-select-3--value').waitForVisible(3000)
39 | // Click on it and enter kmd
40 | this.app.client.element('#react-select-3--value').click().keys('kmd\r\n').then(function () {
41 | done()
42 | })
43 | })
44 |
45 | it('delays for a bit', function() {
46 | return new Promise(function(resolve) {
47 | setTimeout(resolve, 500, true);
48 | });
49 | })
50 |
51 | it('has KMD in the HTML body', function(done) {
52 | this.app.client.getHTML('body').then(function (html) {
53 | assert(html.includes('KMD'), 'Did not find KMD coin')
54 | done()
55 | })
56 | })
57 | })
58 |
59 |
--------------------------------------------------------------------------------
/routes/api/native/verusid/login/signResponse.js:
--------------------------------------------------------------------------------
1 | const {
2 | VerusIDSignature,
3 | LoginConsentResponse,
4 | LOGIN_CONSENT_RESPONSE_SIG_VDXF_KEY,
5 | } = require("verus-typescript-primitives");
6 |
7 | module.exports = (api) => {
8 | api.native.verusid.login.sign_response = async (response) => {
9 | const loginResponse = new LoginConsentResponse(response);
10 | const chainTicker = response.chainTicker
11 | // Add the chainTicker when checking the request since the verify request needs it.
12 | let decisionRequest = loginResponse.decision.request
13 | decisionRequest.chainTicker = chainTicker
14 |
15 | const verificatonCheck = await api.native.verusid.login.verify_request(
16 | decisionRequest
17 | );
18 |
19 | if (!verificatonCheck.verified) {
20 | throw new Error(verificatonCheck.message);
21 | }
22 |
23 | const signdataResult = await api.native.sign_data(chainTicker,
24 | {
25 | "address": loginResponse.signing_id,
26 | "datahash": loginResponse.decision.toSha256().toString("hex")
27 | }
28 | )
29 |
30 | loginResponse.signature = new VerusIDSignature(
31 | { signature: signdataResult.signature },
32 | LOGIN_CONSENT_RESPONSE_SIG_VDXF_KEY
33 | );
34 |
35 | // Remove the chainTicker field since it's not normally part of the response.
36 | delete decisionRequest.chainTicker
37 |
38 | return { response: loginResponse};
39 | };
40 |
41 | api.setPost("/native/verusid/login/sign_response", async (req, res, next) => {
42 | const { response } = req.body;
43 |
44 | try {
45 | res.send(
46 | JSON.stringify({
47 | msg: "success",
48 | result: await api.native.verusid.login.sign_response(response),
49 | })
50 | );
51 | } catch (e) {
52 | res.send(
53 | JSON.stringify({
54 | msg: "error",
55 | result: e.message,
56 | })
57 | );
58 | }
59 | });
60 |
61 | return api;
62 | };
63 |
--------------------------------------------------------------------------------
/test/spec-vrsc.js:
--------------------------------------------------------------------------------
1 | const Application = require('spectron').Application
2 | const assert = require('assert')
3 | const electronPath = require('electron') // Require Electron from the binaries included in node_modules.
4 | const path = require('path')
5 | const chai = require('chai')
6 | const timeout = 7500;
7 | describe('Application launch testing native VRSC coin', function () {
8 | this.timeout(timeout)
9 | before(function () {
10 | this.gotDomReadyCount = 0
11 | this.app = new Application({
12 | path: electronPath,
13 | // The following line tells spectron to look and use the main.js file
14 | // and the package.json located 1 level above.
15 | args: [path.join(__dirname, '..')],
16 | startTimeout: timeout,
17 | waitTimeout: timeout
18 | })
19 | return this.app.start()
20 | })
21 |
22 | after(function () {
23 | if (this.app && this.app.isRunning()) {
24 | return this.app.stop()
25 | }
26 | })
27 |
28 | it('opens a window', function (done) {
29 | this.app.client.waitUntilWindowLoaded()
30 | .getWindowCount().then(function (count) {
31 | assert.equal(count, 1)
32 | done()
33 | })
34 | })
35 |
36 | it('has a native coin list that takes vrsc', function (done) {
37 | // Wait for the left button for native mode coins is visible
38 | this.app.client.element('#react-select-3--value').waitForVisible(3000)
39 | // Click on it and enter vrsc
40 | this.app.client.element('#react-select-3--value').click().keys('vrsc\r\n').then(function () {
41 | done()
42 | })
43 | })
44 |
45 | it('delays for a bit', function() {
46 | return new Promise(function(resolve) {
47 | setTimeout(resolve, 500, true);
48 | });
49 | })
50 |
51 | it('has VRSC in the HTML body', function(done) {
52 | this.app.client.getHTML('body').then(function (html) {
53 | assert(html.includes('VRSC'), 'Did not find VRSC coin')
54 | done()
55 | })
56 | })
57 | })
58 |
59 |
--------------------------------------------------------------------------------
/routes/nativeCoind.js:
--------------------------------------------------------------------------------
1 | const nativeCoind = {
2 | 'btc': {
3 | name: 'Bitcoin',
4 | bin: 'bitcoin',
5 | fullMode: true,
6 | port: 8332,
7 | },
8 | 'btcd': {
9 | name: 'BitcoinDark',
10 | bin: 'bitcoindarkd',
11 | fullMode: true,
12 | port: 14632,
13 | },
14 | 'ltc': {
15 | name: 'Litecoin',
16 | bin: 'litecoin',
17 | fullMode: true,
18 | port: 9332,
19 | },
20 | 'sys': {
21 | name: 'Syscoin',
22 | bin: 'syscoin',
23 | fullMode: true,
24 | port: 8368,
25 | },
26 | 'uno': {
27 | name: 'Unobtanium',
28 | bin: 'unobtanium',
29 | fullMode: true,
30 | port: 65535,
31 | },
32 | 'nmc': {
33 | name: 'Namecoin',
34 | bin: 'namecoin',
35 | fullMode: true,
36 | port: 8336,
37 | },
38 | 'game': {
39 | name: 'GameCredits',
40 | bin: 'gamecredits',
41 | fullMode: true,
42 | port: 40001,
43 | },
44 | 'mzc': {
45 | name: 'MazaCoin',
46 | bin: 'maza',
47 | fullMode: true,
48 | port: 12832,
49 | },
50 | 'frk': {
51 | name: 'Franko',
52 | bin: 'franko',
53 | fullMode: true,
54 | port: 7913,
55 | },
56 | 'doge': {
57 | name: 'Dogecoin',
58 | bin: 'dogecoin',
59 | fullMode: true,
60 | port: 22555,
61 | },
62 | 'dgb': {
63 | name: 'Digibyte',
64 | bin: 'digibyte',
65 | port: 14022,
66 | },
67 | 'zet': {
68 | name: 'Zetacoin',
69 | bin: 'zetacoin',
70 | fullMode: true,
71 | port: 17335,
72 | },
73 | 'btm': {
74 | name: 'Bitmark',
75 | bin: 'bitmark',
76 | fullMode: true,
77 | port: 9266,
78 | },
79 | 'carb': {
80 | name: 'Carboncoin',
81 | bin: 'carboncoin',
82 | fullMode: true,
83 | port: 9351,
84 | },
85 | 'anc': {
86 | name: 'Anoncoin',
87 | bin: 'anoncoin',
88 | fullMode: true,
89 | port: 28332,
90 | },
91 | 'lbc': {
92 | name: 'LBRY Credits',
93 | bin: 'lbrycrd',
94 | port: 9245,
95 | }
96 | };
97 |
98 | module.exports = nativeCoind;
--------------------------------------------------------------------------------
/test/spec.js:
--------------------------------------------------------------------------------
1 | const Application = require('spectron').Application
2 | const assert = require('assert')
3 | const electronPath = require('electron') // Require Electron from the binaries included in node_modules.
4 | const path = require('path')
5 | const chai = require('chai')
6 | const timeout = 7500;
7 | describe('Application launch testing native MORTY coin', function () {
8 | this.timeout(timeout)
9 | before(function () {
10 | this.gotDomReadyCount = 0
11 | this.app = new Application({
12 | path: electronPath,
13 | // The following line tells spectron to look and use the main.js file
14 | // and the package.json located 1 level above.
15 | args: [path.join(__dirname, '..')],
16 | startTimeout: timeout,
17 | waitTimeout: timeout
18 | })
19 | return this.app.start()
20 | })
21 |
22 | after(function () {
23 | if (this.app && this.app.isRunning()) {
24 | return this.app.stop()
25 | }
26 | })
27 |
28 | it('opens a window', function (done) {
29 | this.app.client.waitUntilWindowLoaded()
30 | .getWindowCount().then(function (count) {
31 | assert.equal(count, 1)
32 | done()
33 | })
34 | })
35 |
36 | it('has a native coin list that takes MORTY', function (done) {
37 | // Wait for the left button for native mode coins is visible
38 | this.app.client.element('#react-select-3--value').waitForVisible(3000)
39 | // Click on it and enter MORTY
40 | this.app.client.element('#react-select-3--value').click().keys('MORTY\r\n').then(function () {
41 | done()
42 | })
43 | })
44 |
45 | it('delays for a bit', function() {
46 | return new Promise(function(resolve) {
47 | setTimeout(resolve, 500, true);
48 | });
49 | })
50 |
51 | it('has MORTY in the HTML body', function(done) {
52 | this.app.client.getHTML('body').then(function (html) {
53 | assert(html.includes('MORTY'), 'Did not find MORTY coin')
54 | done()
55 | })
56 | })
57 | })
58 |
59 |
--------------------------------------------------------------------------------
/assets/deps/confs/BTCD_peers.txt:
--------------------------------------------------------------------------------
1 | 89.248.160.237
2 | 89.248.160.238
3 | 89.248.160.239
4 | 89.248.160.240
5 | 89.248.160.241
6 | 89.248.160.242
7 | 89.248.160.243
8 | 89.248.160.244
9 | 89.248.160.245
10 | 5.9.102.210
11 | 78.47.196.146
12 | 85.25.217.233:14631
13 | 88.198.53.194:55692
14 | 88.206.186.58:37299
15 | 162.255.117.105:63084
16 | 115.28.42.60:60878
17 | 82.176.15.155:35026
18 | 88.198.15.19:48150
19 | 176.9.13.13:14631
20 | 217.8.62.188:52714
21 | 162.13.4.69:55410
22 | 211.58.177.43:35581
23 | 63.247.147.166:50266
24 | 24.168.17.50:50793
25 | 46.231.137.186:56963
26 | 178.62.185.131:35572
27 | 62.75.145.171:14631
28 | 89.212.19.49:48018
29 | 192.99.233.217:42232
30 | 68.190.213.46:14631
31 | 162.210.92.46:14631
32 | 98.118.105.12:60805
33 | 75.130.163.51:56719
34 | 51.255.38.28:14631
35 | 88.110.117.18:52158
36 | 24.101.114.249:55457
37 | 99.44.222.86:62377
38 | 108.61.166.209:58365
39 | 98.208.113.72:62065
40 | 72.133.226.130:14631
41 | 5.189.144.97:58243
42 | 14.203.46.202:57987
43 | 98.202.147.55:60460
44 | 24.45.172.109:14631
45 | 89.114.38.65:52768
46 | 68.59.64.126:50633
47 | 68.43.220.127:4303
48 | 81.205.30.207:63077
49 | 113.87.28.142:62764
50 | 73.211.90.130:41271
51 | 110.174.129.213:49252
52 | 68.45.147.145:57803
53 | 95.232.175.161:62633
54 | 73.229.133.160:38440
55 | 124.191.14.253:54342
56 | 167.114.249.196:52705
57 | 92.24.168.248:52892
58 | 93.158.216.201:14631
59 | 158.69.27.82:46643
60 | 104.204.109.11:63390
61 | 68.157.88.187:56711
62 | 71.53.152.87:5234
63 | 82.229.201.131:63466
64 | 59.147.42.146:57461
65 | 81.0.91.211:53187
66 | 82.241.71.230:51945
67 | 108.247.198.39:64094
68 | 77.22.227.8:65093
69 | 122.166.169.11:49325
70 | 173.76.182.122:14631
71 | 173.24.82.253:14631
72 | 100.13.54.119:14631
73 | 2.26.181.208:14631
74 | 94.242.213.3:14631
75 | 87.149.45.42:36077
76 | 98.207.117.83:50955
77 | 71.1.8.48:14631
78 | 71.1.8.48:50439
79 | 101.166.241.31:14631
80 | 178.143.154.142:27497
81 | 103.255.7.59:58660
82 | 156.57.132.119:62428
83 | 60.225.171.82:36834
84 | 46.223.149.120:43358
85 | 37.157.215.75:4162
86 |
--------------------------------------------------------------------------------
/routes/api/erc20/balances.js:
--------------------------------------------------------------------------------
1 | const ethers = require('ethers');
2 |
3 | module.exports = (api) => {
4 | api.setGet("/erc20/get_balances", async (req, res, next) => {
5 | try {
6 | res.send(
7 | JSON.stringify({
8 | msg: "success",
9 | result: {
10 | native: {
11 | public: {
12 | //TODO: Return string instead
13 | confirmed: Number(ethers.formatUnits(
14 | await api.erc20.get_wallet_balance(req.query.chainTicker),
15 | api.erc20.contracts[req.query.chainTicker].decimals
16 | )),
17 | unconfirmed: null,
18 | immature: null,
19 | interest: null,
20 | },
21 | private: {
22 | confirmed: null,
23 | },
24 | },
25 | reserve: {},
26 | },
27 | })
28 | );
29 | } catch (e) {
30 | res.send(
31 | JSON.stringify({
32 | msg: "error",
33 | result: e.message,
34 | })
35 | );
36 | }
37 | });
38 |
39 | api.erc20.get_address_balance = async (contractId, address) => {
40 | if (api.erc20.contracts[contractId] != null) {
41 | if (api.erc20.contracts[contractId].contract.balanceOf) {
42 | return await api.erc20.contracts[contractId].contract.balanceOf(address)
43 | } else {
44 | throw new Error(`ERC20 contract ${contractId} does not support the balanceOf function`)
45 | }
46 | } else {
47 | throw new Error(`Cannot get balance for inactive coin ${contractId}`)
48 | }
49 | }
50 |
51 | api.erc20.get_wallet_balance = async (contractId) => {
52 | if (api.erc20.wallet != null) {
53 | return await api.erc20.get_address_balance(
54 | contractId,
55 | api.erc20.wallet.address
56 | );
57 | } else {
58 | throw new Error(`No wallet authenticated, cannot get wallet balance for ${contractId}`)
59 | }
60 | }
61 |
62 | return api;
63 | };
--------------------------------------------------------------------------------
/routes/api/utils/plugin/permissions.js:
--------------------------------------------------------------------------------
1 | const READ_CORE = "READ_CORE"
2 | const WRITE_CORE = "WRITE_CORE"
3 | const EXECUTE_CORE = "EXECUTE_CORE"
4 |
5 | const READ_NATIVE = "READ_NATIVE"
6 | const WRITE_NATIVE = "WRITE_NATIVE"
7 | const EXECUTE_NATIVE = "EXECUTE_NATIVE"
8 |
9 | const READ_ELECTRUM = "READ_ELECTRUM"
10 | const WRITE_ELECTRUM = "WRITE_ELECTRUM"
11 | const EXECUTE_ELECTRUM = "EXECUTE_ELECTRUM"
12 |
13 | const READ_ETH = "READ_ETH"
14 | const WRITE_ETH = "WRITE_ETH"
15 | const EXECUTE_ETH = "EXECUTE_ETH"
16 |
17 | const READ_WALLET = "READ_WALLET"
18 | const WRITE_WALLET = "WRITE_WALLET"
19 | const EXECUTE_WALLET = "EXECUTE_WALLET"
20 |
21 | const READ_SENSITIVE = "READ_SENSITIVE"
22 | const WRITE_SENSITIVE = "WRITE_SENSITIVE"
23 | const EXECUTE_SENSITIVE = "EXECUTE_SENSITIVE"
24 |
25 | const READ_PLUGINS = "READ_PLUGINS"
26 | const WRITE_PLUGINS = "WRITE_PLUGINS"
27 | const EXECUTE_PLUGINS = "EXECUTE_PLUGINS"
28 |
29 | const READ_FS = "READ_FS"
30 | const WRITE_FS = "WRITE_FS"
31 | const EXECUTE_FS = "EXECUTE_FS"
32 |
33 | const READ_UTILITIES = "READ_UTILITIES"
34 | const WRITE_UTILITIES = "WRITE_UTILITIES"
35 | const EXECUTE_UTILITIES = "EXECUTE_UTILITIES"
36 |
37 | const READ_SYSDATA = "READ_SYSDATA"
38 | const WRITE_SYSDATA = "WRITE_SYSDATA"
39 | const EXECUTE_SYSDATA = "EXECUTE_SYSDATA"
40 |
41 | const SIGN = "SIGN"
42 |
43 | module.exports = {
44 | READ_CORE,
45 | WRITE_CORE,
46 | EXECUTE_CORE,
47 |
48 | READ_NATIVE,
49 | WRITE_NATIVE,
50 | EXECUTE_NATIVE,
51 |
52 | READ_ELECTRUM,
53 | WRITE_ELECTRUM,
54 | EXECUTE_ELECTRUM,
55 |
56 | READ_ETH,
57 | WRITE_ETH,
58 | EXECUTE_ETH,
59 |
60 | READ_WALLET,
61 | WRITE_WALLET,
62 | EXECUTE_WALLET,
63 |
64 | READ_SENSITIVE,
65 | WRITE_SENSITIVE,
66 | EXECUTE_SENSITIVE,
67 |
68 | READ_PLUGINS,
69 | WRITE_PLUGINS,
70 | EXECUTE_PLUGINS,
71 |
72 | READ_FS,
73 | WRITE_FS,
74 | EXECUTE_FS,
75 |
76 | READ_UTILITIES,
77 | WRITE_UTILITIES,
78 | EXECUTE_UTILITIES,
79 |
80 | READ_SYSDATA,
81 | WRITE_SYSDATA,
82 | EXECUTE_SYSDATA,
83 |
84 | SIGN,
85 | }
86 |
87 |
--------------------------------------------------------------------------------
/routes/api/utility_apis/cache.js:
--------------------------------------------------------------------------------
1 | var blake2b = require('blake2b');
2 | const LFUCache = require('../utils/cache');
3 |
4 | const BYTES_PER_MB = 1000000
5 |
6 | module.exports = (api) => {
7 | api.derive_cache_key = (cache, query) => {
8 | var hash = blake2b(64)
9 |
10 | for (const type of cache.split('.')) {
11 | hash.update(type)
12 | }
13 |
14 | hash.update(query)
15 |
16 | return hash.digest('hex')
17 | }
18 |
19 | api.initMainCache = () => {
20 | api.internal_cache = new LFUCache(
21 | !isNaN(api.appConfig.general.main.cacheMbLimit)
22 | ? api.appConfig.general.main.cacheMbLimit * BYTES_PER_MB
23 | : 10000000
24 | )
25 |
26 | api.main_cache = {
27 | del: (cache, query) =>
28 | api.internal_cache.del(api.derive_cache_key(cache, query)),
29 | set: (cache, query, value) => {
30 | try {
31 | return api.internal_cache.set(api.derive_cache_key(cache, query), value)
32 | } catch(e) {
33 | api.log(
34 | "Failed to set cache value for the following cache, query, and value, recived the following error.",
35 | "main_cache"
36 | );
37 | api.log(cache, "main_cache")
38 | api.log(query, "main_cache")
39 | api.log(value, "main_cache")
40 | api.log(e, "main_cache")
41 |
42 | return false
43 | }
44 | },
45 | get: (cache, query) =>
46 | api.internal_cache.get(api.derive_cache_key(cache, query)),
47 | has: (cache, query) =>
48 | api.internal_cache.has(api.derive_cache_key(cache, query)),
49 | getStats: () => api.internal_cache.getStats(),
50 | };
51 |
52 | Object.freeze(api.main_cache);
53 | }
54 |
55 | api.create_sub_cache = (id) => {
56 | return {
57 | del: (query) => api.main_cache.del(id, query),
58 | set: (query, value) => api.main_cache.set(id, query, value),
59 | get: (query) => api.main_cache.get(id, query),
60 | has: (query) => api.main_cache.has(id, query),
61 | }
62 | }
63 |
64 | return api;
65 | };
--------------------------------------------------------------------------------
/routes/api/log.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra');
2 | const path = require('path')
3 | const { secondsToString } = require('agama-wallet-lib/src/time');
4 |
5 | module.exports = (api) => {
6 | api.log = (msg, type) => {
7 | if (api.appConfig.general.main.dev ||
8 | api.appConfig.general.main.debug ||
9 | process.argv.indexOf('devmode') > -1) {
10 | if (type) {
11 | console.log(`\x1b[94m${type}`, '\x1b[0m', msg);
12 | } else {
13 | console.log(msg);
14 | }
15 | }
16 |
17 | if (api.appConfig.general.main.livelog) {
18 | api.writeLog(msg, type)
19 | }
20 |
21 | api.appRuntimeLog.push({
22 | time: Date.now(),
23 | msg: msg,
24 | type: type,
25 | });
26 | }
27 |
28 | api.writeLog = (data, type) => {
29 | const logLocation = api.paths.agamaDir;
30 | const timeFormatted = new Date(Date.now()).toLocaleString('en-US', { hour12: false });
31 | const livelogPath = path.join(logLocation, 'Verus-Desktop.log')
32 |
33 | if (fs.existsSync(livelogPath)) {
34 | fs.appendFile(livelogPath, `${timeFormatted} [${type}] ${data}\r\n`, (err) => {
35 | if (err) {
36 | api.log('error appending live log file');
37 | }
38 | });
39 | } else {
40 | fs.writeFile(livelogPath, `${timeFormatted} [${type}] ${data}\r\n`, (err) => {
41 | if (err) {
42 | api.log('error writing live log file');
43 | }
44 | });
45 | }
46 | }
47 |
48 | api.clearWriteLog = () => {
49 | const logLocation = api.paths.agamaDir;
50 | const livelogPath = path.join(logLocation, 'Verus-Desktop.log')
51 |
52 | if (fs.existsSync(livelogPath)) {
53 | fs.writeFileSync(livelogPath, '');
54 | }
55 | }
56 |
57 | api.getAppRuntimeLog = () => {
58 | return new Promise((resolve, reject) => {
59 | resolve(api.appRuntimeLog);
60 | });
61 | };
62 |
63 | api.printDirs = () => {
64 | api.log("DIR PATHS:", 'env')
65 | for (const pathType in api.paths) {
66 | api.log(`${pathType}: ${api.paths[pathType]}`, 'env')
67 | }
68 | }
69 |
70 | return api;
71 | };
--------------------------------------------------------------------------------
/routes/api/confMaxconnections.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra');
2 |
3 | module.exports = (api) => {
4 | api.getMaxconKMDConf = () => {
5 | return new Promise((resolve, reject) => {
6 | fs.readFile(`${api.paths.kmdDataDir}/komodo.conf`, 'utf8', (err, data) => {
7 | if (err) {
8 | api.log('kmd conf maxconnections param read failed', 'native.confd');
9 | resolve('unset');
10 | } else {
11 | const _maxcon = data.match(/maxconnections=\s*(.*)/);
12 |
13 | if (!_maxcon) {
14 | api.log('kmd conf maxconnections param is unset', 'native.confd');
15 | resolve(false);
16 | } else {
17 | api.log(`kmd conf maxconnections param is already set to ${_maxcon[1]}`, 'native.confd');
18 | resolve(_maxcon[1]);
19 | }
20 | }
21 | });
22 | });
23 | }
24 |
25 | api.setMaxconKMDConf = (limit) => {
26 | return new Promise((resolve, reject) => {
27 | fs.readFile(`${api.paths.kmdDataDir}/komodo.conf`, 'utf8', (err, data) => {
28 | const _maxconVal = limit ? 1 : 10;
29 |
30 | if (err) {
31 | api.log(`error reading ${api.paths.kmdDataDir}/komodo.conf`, 'native.confd');
32 | resolve(false);
33 | } else {
34 | if (data.indexOf('maxconnections=') > -1) {
35 | const _maxcon = data.match(/maxconnections=\s*(.*)/);
36 |
37 | data = data.replace(`maxconnections=${_maxcon[1]}`, `maxconnections=${_maxconVal}`);
38 | } else {
39 | data = `${data}\nmaxconnections=${_maxconVal}\n`;
40 | }
41 |
42 | fs.writeFile(`${api.paths.kmdDataDir}/komodo.conf`, data, (err) => {
43 | if (err) {
44 | api.log(`error writing ${api.paths.kmdDataDir}/komodo.conf maxconnections=${_maxconVal}`, 'native.confd');
45 | resolve(false);
46 | } else {
47 | api.log(`kmd conf maxconnections is set to ${_maxconVal}`, 'native.confd');
48 | resolve(true);
49 | }
50 | });
51 | }
52 | });
53 | });
54 | }
55 |
56 | return api;
57 | };
--------------------------------------------------------------------------------
/routes/api/plugin/stop.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.stopPlugin = async (app_id, window_id, builtin, data) => {
3 | try {
4 | let plugin;
5 | let pluginWindow;
6 | let onComplete;
7 | const category = builtin ? "builtin" : "registry"
8 |
9 | try {
10 | plugin = await api.getPlugin(app_id, builtin)
11 | } catch(e) {
12 | api.log("failed to get plugin info for plugin with id " + app_id, "stopPlugin")
13 | throw e
14 | }
15 |
16 | try {
17 | pluginWindow = api.pluginWindows[category][app_id][window_id]
18 |
19 | if (!pluginWindow) throw new Error(`plugin (id: ${app_id}) is not running with window (id: ${window_id})`)
20 | } catch(e) {
21 | api.log(`plugin (id: ${app_id}) is not running with window (id: ${window_id})`, "stopPlugin")
22 | throw new Error(`plugin (id: ${app_id}) is not running with window (id: ${window_id})`)
23 | }
24 |
25 | try {
26 | onComplete = api.pluginOnCompletes[category][app_id][window_id]
27 | } catch(e) {}
28 |
29 | if (onComplete != null) {
30 | try {
31 | await onComplete(data)
32 | } catch(e) {
33 | api.log(`plugin (id: ${app_id}) onComplete failed to execute, closing anyway...`, "stopPlugin")
34 | api.log(e, "stopPlugin")
35 | }
36 | }
37 |
38 | pluginWindow.close()
39 | return;
40 | } catch(e) {
41 | api.log(`Error stopping plugin with id ${app_id}.`, 'stopPlugin')
42 | api.log(e, 'stopPlugin')
43 | throw e
44 | }
45 | }
46 |
47 | api.setPost('/plugin/close', async (req, res, next) => {
48 | const { app_id, window_id, builtin, data } = req.body
49 |
50 | try {
51 | const retObj = {
52 | msg: 'success',
53 | result: await api.stopPlugin(app_id, window_id, builtin, data),
54 | };
55 |
56 | res.send(JSON.stringify(retObj));
57 | } catch (e) {
58 | const retObj = {
59 | msg: 'error',
60 | result: e.message,
61 | };
62 |
63 | res.send(JSON.stringify(retObj));
64 | }
65 | });
66 |
67 | return api;
68 | };
--------------------------------------------------------------------------------
/routes/api/eth/transactions.js:
--------------------------------------------------------------------------------
1 | const standardizeEthTxObj = require('../utils/standardization/standardizeEthTxObj');
2 |
3 | module.exports = (api) => {
4 | api.setGet('/eth/get_transactions', async (req, res, next) => {
5 | try {
6 | res.send(JSON.stringify({
7 | msg: 'success',
8 | result: await api.eth.get_standardized_wallet_transactions(),
9 | }));
10 | } catch(e) {
11 | res.send(JSON.stringify({
12 | msg: 'error',
13 | result: e.message,
14 | }));
15 | }
16 | });
17 |
18 | api.eth.get_transactions = async (address) => {
19 | if (api.eth.interface != null) {
20 | let txs = await api.eth.interface.EtherscanProvider.getHistory(address)
21 |
22 | Object.values(api.eth.temp.pending_txs).forEach(pendingTx => {
23 | if (!(txs.some(tx => tx.hash === pendingTx.hash))) {
24 | txs.unshift(pendingTx)
25 | } else delete api.eth.temp.pending_txs[pendingTx.hash]
26 | })
27 |
28 | return txs
29 | } else {
30 | throw new Error("Cannot get transaction list for inactive coin ETH")
31 | }
32 | };
33 |
34 | api.eth.get_standardized_wallet_transactions = async () => {
35 | if (api.eth.wallet != null) {
36 | return standardizeEthTxObj(
37 | await api.eth.get_transactions(api.eth.wallet.address),
38 | api.eth.wallet.address
39 | );
40 | } else {
41 | throw new Error("No wallet authenticated, cannot get wallet transactions for ETH")
42 | }
43 | }
44 |
45 | api.eth.get_transaction = async (txid) => {
46 | if (api.eth.interface != null) {
47 | // let cachedReceipts = api.eth.cache.tx_cache;
48 |
49 | // if (cachedReceipts[txid] != null) {
50 | // return cachedReceipts[txid]
51 | // }
52 |
53 | const txReceipt = await api.eth.interface.DefaultProvider.getTransactionReceipt(txid)
54 |
55 | // if (txReceipt.confirmations >= 100) {
56 | // api.eth.cache.tx_cache[txid] = txReceipt
57 | // }
58 |
59 | return txReceipt
60 | } else {
61 | throw new Error("Cannot get transaction for inactive coin ETH")
62 | }
63 | }
64 |
65 | return api;
66 | };
--------------------------------------------------------------------------------
/routes/api/electrum/proxy.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = (api) => {
3 | api.proxyActiveCoin = {};
4 |
5 | api.proxy = (network) => {
6 | if (network) {
7 | api.proxyActiveCoin = network;
8 | }
9 |
10 | return {
11 | connect: () => {
12 | return new Promise((resolve, reject) => reject("Using electrum proxy servers is deprecated."));
13 | },
14 | close: () => {
15 | return new Promise((resolve, reject) => reject("Using electrum proxy servers is deprecated."));
16 | },
17 | blockchainAddressGetBalance: (address) => {
18 | return new Promise((resolve, reject) => reject("Using electrum proxy servers is deprecated."));
19 | },
20 | blockchainAddressListunspent: (address) => {
21 | return new Promise((resolve, reject) => reject("Using electrum proxy servers is deprecated."));
22 | },
23 | blockchainAddressGetHistory: (address) => {
24 | return new Promise((resolve, reject) => reject("Using electrum proxy servers is deprecated."));
25 | },
26 | blockchainEstimatefee: (blocks) => {
27 | return new Promise((resolve, reject) => reject("Using electrum proxy servers is deprecated."));
28 | },
29 | blockchainBlockGetHeader: (height) => {
30 | return new Promise((resolve, reject) => reject("Using electrum proxy servers is deprecated."));
31 | },
32 | blockchainHeadersSubscribe: () => {
33 | return new Promise((resolve, reject) => reject("Using electrum proxy servers is deprecated."));
34 | },
35 | blockchainTransactionGet: (txid) => {
36 | return new Promise((resolve, reject) => reject("Using electrum proxy servers is deprecated."));
37 | },
38 | blockchainTransactionGetMerkle: (txid, height) => {
39 | return new Promise((resolve, reject) => reject("Using electrum proxy servers is deprecated."));
40 | },
41 | serverVersion: () => {
42 | return new Promise((resolve, reject) => reject("Using electrum proxy servers is deprecated."));
43 | },
44 | blockchainTransactionBroadcast: (rawtx) => {
45 | return new Promise((resolve, reject) => reject("Using electrum proxy servers is deprecated."));
46 | },
47 | };
48 | };
49 |
50 | return api;
51 | }
--------------------------------------------------------------------------------
/routes/api/utils/web3/web3Interface.js:
--------------------------------------------------------------------------------
1 | const ethers = require('ethers');
2 | const { HistorySupportingEtherscanProvider } = require('./etherscan');
3 | const { DEFAULT_ERC20_ABI } = require('./abi');
4 |
5 | class Web3Interface {
6 | constructor(network, apiKeys) {
7 | this.network = network;
8 | this.keys = apiKeys;
9 |
10 | this.DefaultProvider = new ethers.getDefaultProvider(
11 | this.network.key,
12 | {
13 | etherscan: apiKeys.etherscan,
14 | infura: apiKeys.infura,
15 | exclusive: [ "etherscan", "infura" ]
16 | }
17 | );
18 |
19 | this.EtherscanProvider = new HistorySupportingEtherscanProvider(
20 | this.network.key,
21 | apiKeys.etherscan
22 | );
23 |
24 | this.InfuraProvider = new ethers.InfuraProvider(
25 | this.network.key,
26 | apiKeys.infura
27 | );
28 | }
29 |
30 | static decodeWeb3Error(errorString) {
31 | try {
32 | let errorJsonString = "{";
33 | let index = errorString.indexOf("error={") + 7;
34 | let openers = 1;
35 | let closers = 0;
36 |
37 | while (openers != closers && index < errorString.length) {
38 | errorJsonString = errorJsonString + errorString[index];
39 |
40 | if (errorString[index] === "{") openers++;
41 | else if (errorString[index] === "}") closers++;
42 |
43 | index++;
44 | }
45 |
46 | const firstJson = JSON.parse(errorJsonString)
47 | const secondJson = JSON.parse(firstJson.body != null ? firstJson.body : firstJson.result)
48 | const errorMessage = secondJson.error != null ? secondJson.error.message : secondJson.result
49 |
50 | return {
51 | unparsed: errorString,
52 | message: errorMessage.charAt(0).toUpperCase() + errorMessage.slice(1),
53 | };
54 | } catch (e) {
55 | return {
56 | unparsed: errorString,
57 | message: "Unknown error",
58 | };
59 | }
60 | }
61 |
62 | initContract = async (contractAddress) => {
63 | return [contractAddress, DEFAULT_ERC20_ABI];
64 | };
65 |
66 | getContract = (contractAddress, abi) => {
67 | return new ethers.Contract(contractAddress, abi, this.DefaultProvider);
68 | };
69 |
70 | getInfo = () => {
71 | return {
72 | network: this.network,
73 | };
74 | };
75 | }
76 |
77 | module.exports = Web3Interface
--------------------------------------------------------------------------------
/routes/api/native/reservetransfers.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.native.getreservetransfers = async (chainTicker) => {
3 | try {
4 | const z_operations = await api.native.callDaemon(chainTicker, 'z_getoperationstatus', [])
5 | let transfers = []
6 |
7 | for (const z_operation of z_operations) {
8 | if (
9 | z_operation.method === "sendcurrency" &&
10 | (z_operation.params[0].convertto != null || z_operation.params[0].exportto != null)
11 | ) {
12 | let from = [];
13 | let to = [];
14 | let via = [];
15 |
16 | for (const param of z_operation.params) {
17 | const ownCurrency = await api.native.callDaemon(chainTicker, "getcurrency", [param.currency])
18 |
19 | from.push(ownCurrency);
20 | to.push(
21 | param.convertto != null
22 | ? await api.native.callDaemon(chainTicker, "getcurrency", [param.convertto])
23 | : ownCurrency
24 | );
25 | via.push(
26 | param.via
27 | ? await api.native.callDaemon(chainTicker, "getcurrency", [param.via])
28 | : null
29 | );
30 | }
31 |
32 | let tx = null;
33 |
34 | try {
35 | if (z_operation.result.txid) {
36 | tx = await api.native.callDaemon(chainTicker, "getrawtransaction", [
37 | z_operation.result.txid,
38 | 1,
39 | ]);
40 | }
41 | } catch (e) {}
42 |
43 | transfers.push({
44 | from,
45 | to,
46 | via,
47 | tx,
48 | operation: z_operation,
49 | });
50 | }
51 | }
52 |
53 | return transfers
54 | } catch(e) {
55 | throw e
56 | }
57 | }
58 |
59 | api.setPost('/native/get_reserve_transfers', async (req, res, next) => {
60 | const {
61 | chainTicker
62 | } = req.body;
63 |
64 | try {
65 | res.send(JSON.stringify({
66 | msg: "success",
67 | result: await api.native.getreservetransfers(chainTicker)
68 | }));
69 | } catch (e) {
70 | res.send(JSON.stringify({
71 | msg: "error",
72 | result: e.message
73 | }));
74 | }
75 | });
76 |
77 | return api;
78 | };
--------------------------------------------------------------------------------
/routes/api/native/restart.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.native.restartCoin = async (chainTicker, launchConfig, startupOptions) => {
3 | if (!api.coinsInitializing[chainTicker]) {
4 | api.log('initiating restart for ' + chainTicker, 'restartCoin')
5 | api.coinsInitializing[chainTicker] = true
6 |
7 | await api.quitDaemon(chainTicker === 'KMD' ? 'komodod' : chainTicker, 30000)
8 |
9 | return new Promise((resolve, reject) => {
10 | let tries = 0
11 |
12 | const intervalId = setInterval(async () => {
13 | api.log('checking if ' + launchConfig.daemon + " process has finished", 'restartCoin')
14 |
15 | const resolveInterval = async () => {
16 | clearInterval(intervalId)
17 | try {
18 | delete api.native.launchConfigs[chainTicker]
19 | api.native.launchConfigs[chainTicker] = launchConfig
20 |
21 | resolve(await api.native.addCoin(chainTicker, launchConfig, startupOptions))
22 | } catch(e) {
23 | reject(e)
24 | }
25 | }
26 |
27 | if (!(await api.isDaemonRunning(launchConfig.daemon))) {
28 | api.log(`${launchConfig.daemon} no longer running, starting ${launchConfig.daemon}`, 'restartCoin')
29 | await resolveInterval()
30 | } else if (tries >= 20) {
31 | api.log(`${tries * 2} seconds have passed, trying to launch daemon anyways`, 'restartCoin')
32 | await resolveInterval()
33 | } else tries++
34 | }, 1000)
35 | })
36 | } else {
37 | api.log('cannot restart ' + chainTicker + ' while it is being initialized', 'restartCoin')
38 | return Promise.reject(new Error(`Cannot restart ${chainTicker} daemon while it is being initialized`))
39 | }
40 | }
41 |
42 | api.setPost('/native/coins/restart', (req, res) => {
43 | const { chainTicker, launchConfig, startupOptions } = req.body
44 |
45 | api.native.restartCoin(chainTicker, launchConfig, startupOptions)
46 | .then(result => {
47 | res.send(JSON.stringify({
48 | msg: 'success',
49 | result,
50 | }));
51 | })
52 | .catch(e => {
53 | const retObj = {
54 | msg: "error",
55 | result: e.message,
56 | };
57 |
58 | res.send(JSON.stringify(retObj));
59 | })
60 | });
61 |
62 | return api;
63 | };
--------------------------------------------------------------------------------
/routes/api/utility_apis/csvExport.js:
--------------------------------------------------------------------------------
1 |
2 | const createCsvWriter = require('csv-writer').createObjectCsvWriter;
3 | const { dialog } = require('electron')
4 | const path = require('path');
5 |
6 | module.exports = (api) => {
7 | /**
8 | * Takes in formatted transactions, and saves the
9 | * transaction csv to a folder chosen by the user
10 | * @param {Object[]} transactions Array of {type, amount, fee, date, address, confirmations, affected_balance, txid, coin}
11 | */
12 | api.saveTransactionCsv = async (transactions) => {
13 | const res = await dialog.showOpenDialog({ properties: ['openDirectory'] })
14 |
15 | if (res.canceled) {
16 | return
17 | } else {
18 | const csvPath = path.join(res.filePaths[0], `tx_export_${new Date().getTime()}.csv`);
19 |
20 | try {
21 | const csvWriter = createCsvWriter({
22 | path: csvPath,
23 | header: [
24 | {id: 'type', title: 'Type'},
25 | {id: 'amount', title: 'Amount'},
26 | {id: 'fee', title: 'Fee'},
27 | {id: 'date', title: 'Date'},
28 | {id: 'address', title: 'Address'},
29 | {id: 'confirmations', title: 'Confirmations'},
30 | {id: 'affected_balance', title: 'Balance'},
31 | {id: 'txid', title: 'TxID'},
32 | {id: 'coin', title: 'Coin'}
33 | ]
34 | });
35 |
36 | await csvWriter.writeRecords(transactions)
37 |
38 | dialog.showMessageBox({
39 | title: "Success!",
40 | message: "CSV file saved to " + csvPath,
41 | buttons: ["OK"],
42 | })
43 | } catch (e) {
44 | dialog.showMessageBox({
45 | type: "error",
46 | title: "Error",
47 | message: "Error saving CSV file to " + csvPath,
48 | buttons: ["OK"],
49 | })
50 |
51 | throw e
52 | }
53 | }
54 | }
55 |
56 | api.setPost('/export_transaction_csv', async (req, res, next) => {
57 | const { transactions } = req.body
58 |
59 | try {
60 | const retObj = {
61 | msg: 'success',
62 | result: await api.saveTransactionCsv(transactions),
63 | };
64 |
65 | res.send(JSON.stringify(retObj));
66 | } catch (e) {
67 | const retObj = {
68 | msg: 'error',
69 | result: e.message,
70 | };
71 |
72 | res.send(JSON.stringify(retObj));
73 | }
74 | });
75 |
76 | return api;
77 | };
--------------------------------------------------------------------------------
/assets/deps/confs/DOGE_peers.txt:
--------------------------------------------------------------------------------
1 | 144.76.71.141
2 | 63.231.239.212
3 | 76.178.149.124
4 | 50.168.159.133
5 | 85.172.79.190
6 | 109.239.49.207
7 | 23.92.25.116
8 | 104.236.136.96
9 | 83.163.222.19
10 | 47.88.34.118
11 | 85.24.244.205
12 | 104.222.120.12
13 | 109.233.58.55
14 | 1.32.70.66
15 | 125.205.136.247
16 | 52.23.175.47
17 | 188.0.80.142
18 | 189.27.147.140
19 | 211.149.148.151
20 | 179.185.112.222
21 | 81.5.71.115
22 | 62.76.15.208
23 | 204.91.28.100
24 | 84.18.118.27
25 | 198.27.81.24
26 | 52.76.154.206
27 | 52.69.7.50
28 | 52.192.155.175
29 | 82.24.81.133
30 | 5.100.250.140
31 | 114.55.5.204
32 | 31.179.43.191
33 | 194.135.90.38
34 | 198.50.242.34
35 | 176.9.31.178
36 | 85.25.41.70
37 | 123.57.60.66
38 | 5.196.82.175
39 | 148.251.88.245
40 | 163.172.19.96
41 | 192.30.138.66
42 | 72.207.111.81
43 | 98.115.147.74
44 | 174.50.64.101
45 | 159.203.107.139
46 | 50.191.229.7
47 | 220.135.22.146
48 | 120.55.80.212
49 | 157.161.128.62
50 | 96.48.162.59
51 | 73.253.240.20
52 | 149.210.242.48
53 | 71.181.42.73
54 | 178.32.9.103
55 | 107.170.82.106
56 | 210.28.136.11
57 | 82.78.191.165
58 | 96.126.123.143
59 | 23.239.31.246
60 | 176.9.50.227
61 | 101.200.156.61
62 | 31.41.40.25
63 | 94.254.62.188
64 | 107.170.86.160
65 | 203.74.121.63
66 | 121.40.17.150
67 | 79.109.198.106
68 | 192.95.56.199
69 | 172.249.137.148
70 | 24.249.152.169
71 | 95.174.187.112
72 | 146.0.32.101
73 | 67.171.207.32
74 | 76.185.84.244
75 | 108.241.66.106
76 | 31.184.195.115
77 | 176.9.113.75
78 | 178.63.18.3
79 | 73.225.31.99
80 | 139.196.9.71
81 | 173.28.134.245
82 | 192.95.29.153
83 | 182.92.183.58
84 | 173.236.240.49
85 | 142.217.48.137
86 | 192.99.11.57
87 | 198.23.230.253
88 | 85.243.255.154
89 | 87.189.43.165
90 | 54.201.183.106
91 | 84.230.4.177
92 | 220.240.96.156
93 | 111.201.159.247
94 | 78.84.100.95
95 | 71.207.13.6
96 | 84.253.125.186
97 | 180.229.32.149
98 | 121.42.206.214
99 | 213.65.111.18
100 | 65.13.189.227
101 | 98.127.32.237
102 | 65.28.164.248
103 | 71.236.237.133
104 | 24.22.225.211
105 | 86.21.9.55
106 | 144.76.239.66
107 | 85.25.200.102
108 | 92.255.199.98
109 | 67.170.74.103
110 | 98.162.199.30
111 | 145.131.3.54
112 | 81.7.3.24
113 | 77.201.157.202
114 | 104.131.40.196
115 | 70.79.168.92
116 | 71.80.233.61
117 | 78.102.123.56
118 | 120.146.143.87
119 | 174.115.20.94
120 | 24.255.204.177
121 | 69.145.193.96
122 | 80.68.90.161
123 | 24.121.141.96
124 | 176.9.65.41
125 | 173.63.255.25
126 | 69.42.223.118
127 | 91.83.69.247
128 |
--------------------------------------------------------------------------------
/routes/api/utils/cache.js:
--------------------------------------------------------------------------------
1 | const NodeCache = require("node-cache");
2 |
3 | class LFUCache {
4 | constructor(maxBytes, cacheOptions = {}, logger = (request, params) => {}) {
5 | this.cacheOptions = cacheOptions
6 | this.cache = new NodeCache(cacheOptions);
7 | this.frequencyMap = {}
8 | this.maxBytes = maxBytes
9 | this.logger = logger
10 | }
11 |
12 | del(key) {
13 | this.logger("DEL", { key })
14 |
15 | delete this.frequencyMap[key]
16 | return this.cache.del(key)
17 | }
18 |
19 | canHoldValue(key, value) {
20 | const testCache = new NodeCache(this.cacheOptions)
21 | let returnVal = false
22 |
23 | try {
24 | testCache.set(key, value)
25 | const stats = testCache.getStats()
26 |
27 | if ((stats.vsize + stats.ksize) <= this.maxBytes) {
28 | returnVal = true
29 | }
30 | } catch(e) {}
31 |
32 | testCache.flushAll()
33 | return returnVal
34 | }
35 |
36 | set(key, value) {
37 | this.logger("SET", { key, value })
38 |
39 | if (this.canHoldValue(key, value)) {
40 | this.frequencyMap[key] = 0
41 | const result = this.cache.set(key, value)
42 | let stats = this.cache.getStats()
43 |
44 | if ((stats.vsize + stats.ksize) > this.maxBytes) {
45 | let keys = Object.keys(this.frequencyMap).sort((a, b) => {
46 | if (a == key) return 1
47 | else if (b == key) return -1
48 | else return this.frequencyMap[a] - this.frequencyMap[b]
49 | })
50 |
51 | for (const toDelete of keys) {
52 | this.del(toDelete)
53 | stats = this.cache.getStats()
54 |
55 | if ((stats.vsize + stats.ksize) <= this.maxBytes) break;
56 | }
57 | }
58 |
59 | return result
60 | } else {
61 | throw new Error("Cannot set key value pair for provided data")
62 | }
63 | }
64 |
65 | get(key) {
66 | this.logger("GET", { key })
67 |
68 | const value = this.cache.get(key)
69 |
70 | if (value != null && this.frequencyMap[key] != null) {
71 | this.frequencyMap[key] = this.frequencyMap[key] + 1
72 | } else this.frequencyMap[key] = 1
73 |
74 | return this.cache.get(key)
75 | }
76 |
77 | has(key) {
78 | this.logger("HAS", { key })
79 |
80 | return this.cache.has(key)
81 | }
82 |
83 | keys() {
84 | this.logger("KEYS")
85 |
86 | return this.cache.keys()
87 | }
88 |
89 | getStats() {
90 | return this.cache.getStats()
91 | }
92 | }
93 |
94 | module.exports = LFUCache
--------------------------------------------------------------------------------
/routes/api/erc20/transactions.js:
--------------------------------------------------------------------------------
1 | const standardizeEthTxObj = require('../utils/standardization/standardizeEthTxObj');
2 |
3 | module.exports = (api) => {
4 | api.setGet('/erc20/get_transactions', async (req, res, next) => {
5 | try {
6 | res.send(
7 | JSON.stringify({
8 | msg: "success",
9 | result: await api.erc20.get_standardized_wallet_transactions(
10 | req.query.chainTicker
11 | ),
12 | })
13 | );
14 | } catch(e) {
15 | res.send(JSON.stringify({
16 | msg: 'error',
17 | result: e.message,
18 | }));
19 | }
20 | });
21 |
22 | api.erc20.get_transactions = async (contractId, address) => {
23 | if (api.erc20.contracts[contractId] != null) {
24 | let txs = await api.erc20.contracts[
25 | contractId
26 | ].interface.EtherscanProvider.getHistory(
27 | address,
28 | null,
29 | null,
30 | contractId
31 | );
32 |
33 | Object.values(api.erc20.contracts[contractId].temp.pending_txs).forEach(pendingTx => {
34 | if (!(txs.some(tx => tx.hash === pendingTx.hash))) {
35 | txs.unshift(pendingTx)
36 | } else delete api.erc20.contracts[contractId].temp.pending_txs[pendingTx.hash]
37 | })
38 |
39 | return txs
40 | } else {
41 | throw new Error(`Cannot get transaction list for inactive coin ${contractId}`)
42 | }
43 | };
44 |
45 | api.erc20.get_standardized_wallet_transactions = async (contractId) => {
46 | if (api.erc20.contracts[contractId] != null) {
47 | if (api.erc20.wallet != null) {
48 | return standardizeEthTxObj(
49 | await api.erc20.get_transactions(contractId, api.erc20.wallet.address),
50 | api.erc20.wallet.address,
51 | api.erc20.contracts[contractId].decimals
52 | );
53 | } else {
54 | throw new Error(
55 | `No wallet authenticated, cannot get wallet transactions for ${contractId}`
56 | );
57 | }
58 | } else {
59 | throw new Error(
60 | `Cannot get transaction list for inactive coin ${contractId}`
61 | );
62 | }
63 | };
64 |
65 | api.erc20.get_transaction = async (contractId, txid) => {
66 | if (api.erc20.contracts[contractId] != null) {
67 | const txReceipt = await api.erc20.contracts[
68 | contractId
69 | ].interface.DefaultProvider.getTransactionReceipt(txid);
70 |
71 | return txReceipt
72 | } else {
73 | throw new Error(`Cannot get transaction for inactive coin ${contractId}`)
74 | }
75 | }
76 |
77 | return api;
78 | };
--------------------------------------------------------------------------------
/routes/api/native/mininginfo.js:
--------------------------------------------------------------------------------
1 | const { standardizeMiningInfo } = require('../utils/standardization/standardization')
2 |
3 | module.exports = (api) => {
4 | api.native.get_mininginfo = (coin, includeBridgekeeper) => {
5 | return new Promise((resolve, reject) => {
6 | api.native.callDaemon(coin, 'getmininginfo', [])
7 | .then(async (mininginfo) => {
8 | try {
9 | // If mergemining with parent, set hashrate = parent hashrate
10 | if (mininginfo.mergemining != null && mininginfo.mergemining > 0) {
11 | const currentCurrency = await api.native.callDaemon(coin, 'getcurrency', [coin])
12 |
13 | if (
14 | currentCurrency.currencyid !== currentCurrency.parent &&
15 | currentCurrency.parent != null
16 | ) {
17 | const parentCurrency = await api.native.callDaemon(coin, "getcurrency", [
18 | currentCurrency.parent,
19 | ]);
20 | const parentMiningInfo = await api.native.callDaemon(
21 | parentCurrency.name,
22 | "getmininginfo",
23 | []
24 | );
25 |
26 | if (parentMiningInfo.localhashps > 0) {
27 | mininginfo.localhashps = parentMiningInfo.localhashps;
28 | }
29 | }
30 | }
31 | } catch(e) {
32 | api.log("Could not process mergemining hashrate")
33 | api.log(e, 'get_mininginfo')
34 | }
35 | let retval = standardizeMiningInfo(mininginfo)
36 | if (includeBridgekeeper) {
37 | const bridgeKeeperStatus = await api.native.bridgekeeper_status(coin)
38 | if (bridgeKeeperStatus) {
39 | retval.bridgekeeperstatus = bridgeKeeperStatus;
40 | }
41 | }
42 | resolve(retval)
43 | })
44 | .catch(err => {
45 | reject(err)
46 | })
47 | });
48 | };
49 |
50 | api.setPost('/native/get_mininginfo', (req, res, next) => {
51 | const coin = req.body.chainTicker;
52 | const includeBridgekeeper = req.body?.includeBridgekeeper;
53 | api.native.get_mininginfo(coin, includeBridgekeeper)
54 | .then((mininginfo) => {
55 | const retObj = {
56 | msg: 'success',
57 | result: mininginfo,
58 | };
59 |
60 | res.send(JSON.stringify(retObj));
61 | })
62 | .catch(error => {
63 | const retObj = {
64 | msg: 'error',
65 | result: error.message,
66 | };
67 |
68 | res.send(JSON.stringify(retObj));
69 | })
70 | });
71 |
72 | return api;
73 | };
--------------------------------------------------------------------------------
/routes/api/erc20/coins.js:
--------------------------------------------------------------------------------
1 | const { ETH_HOMESTEAD } = require('../utils/constants/eth_networks');
2 | const { CONTRACT_SYMBOLS } = require('../utils/constants/web3');
3 | const createInterface = require('../utils/web3/provider');
4 |
5 | module.exports = (api) => {
6 | api.setPost('/erc20/coins/activate', async (req, res, next) => {
7 | // chainTicker represents contract ID
8 | const { chainTicker, network } = req.body;
9 |
10 | try {
11 | if (chainTicker) {
12 | if (api.erc20.contracts[chainTicker] == null) {
13 | const interface = createInterface(
14 | network == null ? ETH_HOMESTEAD : network
15 | );
16 | const contractData = await interface.initContract(chainTicker)
17 |
18 | const contract = interface.getContract(...contractData)
19 |
20 | let symbol
21 |
22 | if (CONTRACT_SYMBOLS[chainTicker.toLowerCase()]) {
23 | symbol = CONTRACT_SYMBOLS[chainTicker.toLowerCase()]
24 | } else if (contract.symbol) {
25 | try {
26 | symbol = await contract.symbol();
27 | } catch(e) {
28 | symbol = chainTicker
29 | }
30 | } else {
31 | symbol = chainTicker
32 | }
33 |
34 | api.erc20.contracts[chainTicker] = {
35 | interface,
36 | contract,
37 | temp: {
38 | pending_txs: {}
39 | },
40 | decimals:
41 | contract.decimals != null
42 | ? Number(await contract.decimals())
43 | : 18,
44 | symbol
45 | };
46 |
47 | const retObj = {
48 | msg: 'success',
49 | result: 'true',
50 | };
51 | res.send(JSON.stringify(retObj));
52 | } else {
53 | const retObj = {
54 | msg: 'error',
55 | result: `${chainTicker} already active!`,
56 | };
57 | res.send(JSON.stringify(retObj));
58 | }
59 | } else {
60 | const retObj = {
61 | msg: 'error',
62 | result: 'no contract id provided to activate',
63 | };
64 | res.send(JSON.stringify(retObj));
65 | }
66 | } catch(e) {
67 | const retObj = {
68 | msg: 'error',
69 | result: e.message,
70 | };
71 | res.send(JSON.stringify(retObj));
72 | }
73 | });
74 |
75 | api.setPost('/erc20/remove_coin', (req, res) => {
76 | api.erc20.contracts[req.body.chainTicker] = null
77 |
78 | const retObj = {
79 | msg: 'success',
80 | result: true,
81 | };
82 |
83 | res.send(JSON.stringify(retObj));
84 | });
85 |
86 | return api;
87 | };
--------------------------------------------------------------------------------
/routes/api/binsUtils.js:
--------------------------------------------------------------------------------
1 | const os = require('os');
2 | const fsnode = require('fs');
3 | const _fs = require('graceful-fs');
4 | const { DAEMON_NAMES } = require('./utils/constants');
5 | const exec = require('child_process').exec;
6 |
7 | module.exports = (api) => {
8 | api.killRogueProcess = (processName) => {
9 | // kill rogue process copies on start
10 | const osPlatform = os.platform();
11 | let processGrep;
12 |
13 | switch (osPlatform) {
14 | case 'darwin':
15 | processGrep = "ps -p $(ps -A | grep -m1 " + processName + " | awk '{print $1}') | grep -i " + processName;
16 | break;
17 | case 'linux':
18 | processGrep = 'ps -p $(pidof ' + processName + ') | grep -i ' + processName;
19 | break;
20 | case 'win32':
21 | processGrep = 'tasklist';
22 | break;
23 | }
24 |
25 | exec(processGrep, (error, stdout, stderr) => {
26 | if (stdout.indexOf(processName) > -1) {
27 | const pkillCmd = osPlatform === 'win32' ? `taskkill /f /im ${processName}.exe` : `pkill -15 ${processName}`;
28 |
29 | api.log(`found another ${processName} process(es)`, 'native.process');
30 |
31 | exec(pkillCmd, (error, stdout, stderr) => {
32 | api.log(`${pkillCmd} is issued`, 'native.process');
33 |
34 | if (error !== null) {
35 | api.log(`${pkillCmd} exec error: ${error}`, 'native.process');
36 | };
37 | });
38 | }
39 |
40 | if (error !== null) {
41 | api.log(`${processGrep} exec error: ${error}`, 'native.process');
42 | };
43 | });
44 | }
45 |
46 | api.isDaemonRunning = (daemonName) => {
47 | return new Promise((resolve, reject) => {
48 | let platform = os.platform();
49 | let cmd = '';
50 | switch (platform) {
51 | case 'win32' : cmd = `tasklist`; break;
52 | case 'darwin' : cmd = `ps -ax | grep ${daemonName}`; break;
53 | case 'linux' : cmd = `ps -A`; break;
54 | default: break;
55 | }
56 |
57 | exec(cmd, (err, stdout, stderr) => {
58 | if (platform === 'darwin') {
59 | resolve(stdout.toLowerCase().indexOf(`assets/bin/osx/${daemonName}`) > -1)
60 | } else {
61 | resolve(stdout.toLowerCase().indexOf(daemonName.toLowerCase()) > -1)
62 | }
63 | });
64 | })
65 | }
66 |
67 | api.isAnyDaemonRunning = async () => {
68 | for (const daemon of DAEMON_NAMES) {
69 | if (await api.isDaemonRunning(daemon)) {
70 | api.log(`${daemon} is currently running...`, 'native.process');
71 | return true;
72 | } else {
73 | api.log(`${daemon} is not currently running...`, 'native.process');
74 | }
75 | }
76 | }
77 |
78 | return api;
79 | };
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### This is experimental and unfinished software. Use at your own risk! No warranty for any kind of damage!
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
9 | # Verus Wallet
10 | The Verus Multicoin Wallet and Ecosystem GUI
11 |
12 | ## Build & Installation
13 |
14 | #### Prerequirements:
15 |
16 | 1) [Install yarn](https://yarnpkg.com/)
17 |
18 | 2) [Install git](https://git-scm.com/)
19 |
20 |
21 | #### Build & Start Verus-Desktop-GUI (frontend)
22 |
23 | ```shell
24 | git clone --recursive https://github.com/VerusCoin/Verus --branch master --single-branch
25 | cd Verus/gui/Verus-Desktop-GUI/react/
26 | yarn install
27 | ```
28 | Leave the above process running and use a new terminal windows/tab when proceeding with the below steps.
29 |
30 | Now please create a directory called `bin` inside `assets/` and afterwards copy `komodod` and `komodo-cli` to a new subfolder named after the operating system you are building Agama for: `linux64`, `osx` or `win64`. Inside this subfolder, create another directory called `verusd`
31 | and copy `verusd` and `verus-cli` into it.
32 |
33 | From within `Verus/` the structure will be `assets/bin/linux64` (for example on linux).
34 |
35 |
36 | #### Start Verus App (electron)
37 |
38 | ```shell
39 | cd Verus
40 | yarn install
41 | yarn start
42 | ```
43 | To use debug/dev mode please stop the Verus App (electron) and either set `dev: true` and `debug: true` in `~/.verus/config.json` and then restart the app or replace step 3) from above with the start command below:
44 |
45 | ```shell
46 | yarn start devmode
47 | ```
48 |
49 | You are ready to dev!
50 |
51 |
52 | ## Bundling & packaging:
53 |
54 | ```shell
55 | yarn run dist
56 | ```
57 | We refer to the original [electron-builder](https://www.electron.build) website for more detailed information and further documentation.
58 |
59 |
60 |
--------------------------------------------------------------------------------
/routes/shepherd/deepmerge.js:
--------------------------------------------------------------------------------
1 | // ref: https://davidwalsh.name/javascript-deep-merge
2 | const isMergeableObject = (val) => {
3 | const nonNullObject = val && typeof val === 'object';
4 |
5 | return nonNullObject
6 | && Object.prototype.toString.call(val) !== '[object RegExp]'
7 | && Object.prototype.toString.call(val) !== '[object Date]';
8 | }
9 |
10 | const emptyTarget = (val) => {
11 | return Array.isArray(val) ? [] : {};
12 | }
13 |
14 | const cloneIfNecessary = (value, optionsArgument) => {
15 | const clone = optionsArgument && optionsArgument.clone === true;
16 | return (clone && isMergeableObject(value)) ? deepmerge(emptyTarget(value), value, optionsArgument) : value;
17 | }
18 |
19 | const defaultArrayMerge = (target, source, optionsArgument) => {
20 | let destination = target.slice();
21 |
22 | source.forEach((e, i) => {
23 | if (typeof destination[i] === 'undefined') {
24 | destination[i] = cloneIfNecessary(e, optionsArgument);
25 | } else if (isMergeableObject(e)) {
26 | destination[i] = deepmerge(target[i], e, optionsArgument);
27 | } else if (target.indexOf(e) === -1) {
28 | destination.push(cloneIfNecessary(e, optionsArgument));
29 | }
30 | });
31 |
32 | return destination;
33 | }
34 |
35 | const mergeObject = (target, source, optionsArgument) => {
36 | let destination = {};
37 |
38 | if (isMergeableObject(target)) {
39 | Object.keys(target).forEach((key) => {
40 | destination[key] = cloneIfNecessary(target[key], optionsArgument);
41 | });
42 | }
43 |
44 | Object.keys(source).forEach((key) => {
45 | if (!isMergeableObject(source[key]) ||
46 | !target[key]) {
47 | destination[key] = cloneIfNecessary(source[key], optionsArgument);
48 | } else {
49 | destination[key] = deepmerge(target[key], source[key], optionsArgument);
50 | }
51 | });
52 |
53 | return destination;
54 | }
55 |
56 | let deepmerge = (target, source, optionsArgument) => {
57 | const array = Array.isArray(source);
58 | const options = optionsArgument || { arrayMerge: defaultArrayMerge };
59 | const arrayMerge = options.arrayMerge || defaultArrayMerge;
60 |
61 | if (array) {
62 | return Array.isArray(target) ? arrayMerge(target, source, optionsArgument) : cloneIfNecessary(source, optionsArgument);
63 | } else {
64 | return mergeObject(target, source, optionsArgument);
65 | }
66 | }
67 |
68 | deepmerge.all = (array, optionsArgument) => {
69 | if (!Array.isArray(array) ||
70 | array.length < 2) {
71 | throw new Error('first argument should be an array with at least two elements');
72 | }
73 |
74 | // we are sure there are at least 2 values, so it is safe to have no initial value
75 | return array.reduce((prev, next) => {
76 | return deepmerge(prev, next, optionsArgument);
77 | });
78 | }
79 |
80 | module.exports = deepmerge;
--------------------------------------------------------------------------------
/routes/api/utils/objectUtil/deepmerge.js:
--------------------------------------------------------------------------------
1 | // ref: https://davidwalsh.name/javascript-deep-merge
2 | const isMergeableObject = (val) => {
3 | const nonNullObject = val && typeof val === 'object';
4 |
5 | return nonNullObject
6 | && Object.prototype.toString.call(val) !== '[object RegExp]'
7 | && Object.prototype.toString.call(val) !== '[object Date]';
8 | }
9 |
10 | const emptyTarget = (val) => {
11 | return Array.isArray(val) ? [] : {};
12 | }
13 |
14 | const cloneIfNecessary = (value, optionsArgument) => {
15 | const clone = optionsArgument && optionsArgument.clone === true;
16 | return (clone && isMergeableObject(value)) ? deepmerge(emptyTarget(value), value, optionsArgument) : value;
17 | }
18 |
19 | const defaultArrayMerge = (target, source, optionsArgument) => {
20 | let destination = target.slice();
21 |
22 | source.forEach((e, i) => {
23 | if (typeof destination[i] === 'undefined') {
24 | destination[i] = cloneIfNecessary(e, optionsArgument);
25 | } else if (isMergeableObject(e)) {
26 | destination[i] = deepmerge(target[i], e, optionsArgument);
27 | } else if (target.indexOf(e) === -1) {
28 | destination.push(cloneIfNecessary(e, optionsArgument));
29 | }
30 | });
31 |
32 | return destination;
33 | }
34 |
35 | const mergeObject = (target, source, optionsArgument) => {
36 | let destination = {};
37 |
38 | if (isMergeableObject(target)) {
39 | Object.keys(target).forEach((key) => {
40 | destination[key] = cloneIfNecessary(target[key], optionsArgument);
41 | });
42 | }
43 |
44 | Object.keys(source).forEach((key) => {
45 | if (!isMergeableObject(source[key]) ||
46 | !target[key]) {
47 | destination[key] = cloneIfNecessary(source[key], optionsArgument);
48 | } else {
49 | destination[key] = deepmerge(target[key], source[key], optionsArgument);
50 | }
51 | });
52 |
53 | return destination;
54 | }
55 |
56 | let deepmerge = (target, source, optionsArgument) => {
57 | const array = Array.isArray(source);
58 | const options = optionsArgument || { arrayMerge: defaultArrayMerge };
59 | const arrayMerge = options.arrayMerge || defaultArrayMerge;
60 |
61 | if (array) {
62 | return Array.isArray(target) ? arrayMerge(target, source, optionsArgument) : cloneIfNecessary(source, optionsArgument);
63 | } else {
64 | return mergeObject(target, source, optionsArgument);
65 | }
66 | }
67 |
68 | deepmerge.all = (array, optionsArgument) => {
69 | if (!Array.isArray(array) ||
70 | array.length < 2) {
71 | throw new Error('first argument should be an array with at least two elements');
72 | }
73 |
74 | // we are sure there are at least 2 values, so it is safe to have no initial value
75 | return array.reduce((prev, next) => {
76 | return deepmerge(prev, next, optionsArgument);
77 | });
78 | }
79 |
80 | module.exports = deepmerge;
--------------------------------------------------------------------------------
/routes/api/native/getCurrency.js:
--------------------------------------------------------------------------------
1 | const { ROOT_SYSTEM_ID } = require("../utils/constants/dev_options");
2 |
3 | module.exports = (api) => {
4 | // The only difference between this and get_currency is that this cannot
5 | // be used to derive non-static properties of a currency like bestcurrencystate
6 | api.native.get_currency_definition = async (chain, currencyid = ROOT_SYSTEM_ID) => {
7 | if (api.native.cache.currency_definition_cache.has(currencyid)) {
8 | return api.native.cache.currency_definition_cache.get(currencyid)
9 | } else {
10 | const definition = await api.native.callDaemon(chain, 'getcurrency', [currencyid])
11 | let { name } = definition
12 |
13 | if (
14 | definition.currencyid !== definition.systemid &&
15 | definition.parent !== ROOT_SYSTEM_ID
16 | ) {
17 | name = `${name}.${
18 | (await api.native.get_currency_definition(chain, definition.parent))
19 | .name
20 | }`;
21 | }
22 |
23 | const processedDefinition = {
24 | ...definition,
25 | name,
26 | }
27 |
28 | api.native.cache.currency_definition_cache.set(currencyid, processedDefinition)
29 | return processedDefinition
30 | }
31 | }
32 |
33 | api.native.get_currency = async (chain, currencyid = ROOT_SYSTEM_ID) => {
34 | try {
35 | const currencyObject = await api.native.callDaemon(chain, 'getcurrency', [currencyid])
36 | const parent = await api.native.get_currency_definition(chain, currencyObject.parent)
37 | const spotter = await api.native.get_currency_definition(chain, chain)
38 |
39 | const processedCurrencyObject = {
40 | ...currencyObject,
41 | systemname: parent.name.toUpperCase(),
42 | spottername: chain,
43 | spotterid: spotter.currencyid,
44 | name:
45 | (currencyObject.systemid !== currencyObject.currencyid &&
46 | currencyObject.parent !== ROOT_SYSTEM_ID)
47 | ? `${currencyObject.name}.${parent.name}`
48 | : currencyObject.name,
49 | };
50 |
51 | if (!api.native.cache.currency_definition_cache.has(currencyid)) {
52 | api.native.cache.currency_definition_cache.set(currencyid, processedCurrencyObject)
53 | }
54 |
55 | return processedCurrencyObject
56 | } catch(e) {
57 | throw e
58 | }
59 | };
60 |
61 | api.setPost('/native/get_currency', async (req, res, next) => {
62 | const { chainTicker, name } = req.body
63 |
64 | try {
65 | const retObj = {
66 | msg: 'success',
67 | result: await api.native.get_currency(chainTicker, name),
68 | };
69 |
70 | res.send(JSON.stringify(retObj));
71 | } catch(e) {
72 | const retObj = {
73 | msg: 'error',
74 | result: e.message,
75 | };
76 |
77 | res.send(JSON.stringify(retObj));
78 | }
79 | });
80 |
81 | return api;
82 | };
--------------------------------------------------------------------------------
/routes/api/native/shieldcoinbase.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | /**
3 | * Readies the parameters to pass to z_shieldcoinbase and returns
4 | * the inputted information for the user to double check it
5 | * @param {String} chainTicker The chainticker to call z_shieldcoinbase on
6 | * @param {String} toAddress The Z address to shield coinbases to
7 | * @param {String} fromAddress The from address, leave undefined to get all addresses
8 | * @param {Number} fee (Optional) A custom fee
9 | * @param {Number} limit (Optional) A custom limit of UTXOs to shield
10 | */
11 | api.native.shieldCoinbasePreflight = (
12 | chainTicker,
13 | toAddress,
14 | fromAddress,
15 | fee,
16 | limit
17 | ) => {
18 | const FROM_ADDR_INDEX = 0
19 | let inputParams = [fromAddress, toAddress, fee, limit]
20 | let txParams = []
21 |
22 | inputParams.map((inputParam, index) => {
23 | if (index === FROM_ADDR_INDEX && inputParam === null) txParams.push("*")
24 | else if (inputParam != null) {
25 | txParams.push(inputParam)
26 | }
27 | })
28 |
29 | return {
30 | chainTicker,
31 | fromAddress,
32 | toAddress,
33 | fee,
34 | limit,
35 | txParams
36 | };
37 | };
38 |
39 | api.setPost('/native/shieldcoinbase', (req, res, next) => {
40 | const {
41 | chainTicker,
42 | fromAddress,
43 | toAddress,
44 | fee,
45 | limit
46 | } = req.body;
47 |
48 | const preflightRes = api.native.shieldCoinbasePreflight(
49 | chainTicker,
50 | toAddress,
51 | fromAddress,
52 | fee,
53 | limit
54 | )
55 |
56 | api.native.callDaemon(chainTicker, 'z_shieldcoinbase', preflightRes.txParams)
57 | .then(shieldObj => {
58 | const retObj = {
59 | msg: "success",
60 | result: { ...preflightRes, ...shieldObj }
61 | };
62 | res.send(JSON.stringify(retObj));
63 | }).catch(e => {
64 | const retObj = {
65 | msg: "error",
66 | result: e.message
67 | };
68 | res.send(JSON.stringify(retObj));
69 | })
70 | });
71 |
72 | api.setPost("/native/shieldcoinbase_preflight", (req, res, next) => {
73 | const {
74 | chainTicker,
75 | fromAddress,
76 | toAddress,
77 | fee,
78 | limit
79 | } = req.body;
80 |
81 | try {
82 | res.send(
83 | JSON.stringify({
84 | msg: "success",
85 | result: api.native.shieldCoinbasePreflight(
86 | chainTicker,
87 | toAddress,
88 | fromAddress,
89 | fee,
90 | limit
91 | )
92 | })
93 | );
94 | } catch (e) {
95 | const retObj = {
96 | msg: "error",
97 | result: e.message
98 | };
99 | res.send(JSON.stringify(retObj));
100 | }
101 | });
102 |
103 | return api;
104 | };
--------------------------------------------------------------------------------
/routes/api/utils/rpc/rpcStatusCodes.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // Non BTC default errors
3 | RPC_OK : 0,
4 | RPC_TIMEOUT : -32,
5 | RPC_WORK_QUEUE_DEPTH_EXCEEDED : -33,
6 | RPC_ERROR_UNKNOWN : -34,
7 | RPC_PARSE_ERROR : -35,
8 |
9 | RPC_MISC_ERROR : -1, //!< std::exception thrown in command handling
10 | RPC_FORBIDDEN_BY_SAFE_MODE : -2, //!< Server is in safe mode, and command is not allowed in safe mode
11 | RPC_TYPE_ERROR : -3, //!< Unexpected type was passed as parameter
12 | RPC_INVALID_ADDRESS_OR_KEY : -5, //!< Invalid address or key
13 | RPC_OUT_OF_MEMORY : -7, //!< Ran out of memory during operation
14 | RPC_INVALID_PARAMETER : -8, //!< Invalid, missing or duplicate parameter
15 | RPC_DATABASE_ERROR : -20, //!< Database error
16 | RPC_DESERIALIZATION_ERROR : -22, //!< Error parsing or validating structure in raw format
17 | RPC_VERIFY_ERROR : -25, //!< General error during transaction or block submission
18 | RPC_VERIFY_REJECTED : -26, //!< Transaction or block was rejected by network rules
19 | RPC_VERIFY_ALREADY_IN_CHAIN : -27, //!< Transaction already in chain
20 | RPC_IN_WARMUP : -28, //!< Client still warming up
21 |
22 | //! P2P client errors
23 | RPC_CLIENT_NOT_CONNECTED : -9, //!< Bitcoin is not connected
24 | RPC_CLIENT_IN_INITIAL_DOWNLOAD : -10, //!< Still downloading initial blocks
25 | RPC_CLIENT_NODE_ALREADY_ADDED : -23, //!< Node is already added
26 | RPC_CLIENT_NODE_NOT_ADDED : -24, //!< Node has not been added before
27 | RPC_CLIENT_NODE_NOT_CONNECTED : -29, //!< Node to disconnect not found in connected nodes
28 | RPC_CLIENT_INVALID_IP_OR_SUBNET : -30, //!< Invalid IP/Subnet
29 | RPC_CLIENT_P2P_DISABLED : -31, //!< No valid connection manager instance found
30 |
31 | //! Wallet errors
32 | RPC_WALLET_ERROR : -4, //!< Unspecified problem with wallet (key not found etc.)
33 | RPC_WALLET_INSUFFICIENT_FUNDS : -6, //!< Not enough funds in wallet or account
34 | RPC_WALLET_INVALID_ACCOUNT_NAME : -11, //!< Invalid account name
35 | RPC_WALLET_KEYPOOL_RAN_OUT : -12, //!< Keypool ran out, call keypoolrefill first
36 | RPC_WALLET_UNLOCK_NEEDED : -13, //!< Enter the wallet passphrase with walletpassphrase first
37 | RPC_WALLET_PASSPHRASE_INCORRECT : -14, //!< The wallet passphrase entered was incorrect
38 | RPC_WALLET_WRONG_ENC_STATE : -15, //!< Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.)
39 | RPC_WALLET_ENCRYPTION_FAILED : -16, //!< Failed to encrypt the wallet
40 | RPC_WALLET_ALREADY_UNLOCKED : -17, //!< Wallet is already unlocked
41 | RPC_WALLET_NOT_FOUND : -18, //!< Invalid wallet specified
42 | RPC_WALLET_NOT_SPECIFIED : -19, //!< No wallet specified (error when there are multiple wallets loaded)
43 | }
--------------------------------------------------------------------------------
/routes/api/native/cryptoConditions.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | module.exports = (api) => {
4 | //TODO: Finish when API call for estimatefee is completed
5 | api.native.parse_reserve_transfer = async (chainTicker, rawTx) => {
6 | let totalIn, totalOut, totalTransferFees, totalNetworkFees, conversionFee = 0
7 | let isConversion, currencyNotChainticker = false
8 |
9 | const decodedTx = await api.native.callDaemon(
10 | chainTicker,
11 | "decoderawtransaction",
12 | [rawTx]
13 | );
14 |
15 | let outs = decodedTx.vout
16 | let ins = decodedTx.vin
17 |
18 | for (let i = 0; i < outs.length; i++) {
19 | let output = outs[i]
20 |
21 | if (
22 | output.scriptPubKey != null &&
23 | output.scriptPubKey.type === "cryptocondition" &&
24 | output.scriptPubKey.reservetransfer != null
25 | ) {
26 | totalOut += (output.scriptPubKey.reservetransfer.value + output.scriptPubKey.reservetransfer.fees)
27 | totalTransferFees += output.scriptPubKey.reservetransfer.fees
28 |
29 | if (!currencyNotChainticker && await api.native.get_currency_definition(chain, currency).name !== chainTicker) {
30 | currencyNotChainticker = true
31 | }
32 |
33 | if (!isConversion && output.scriptPubKey.reservetransfer.convert) {
34 | isConversion = true
35 | }
36 | }
37 | }
38 |
39 | for (let i = 0; i < ins.length; i++) {
40 | let input = ins[i]
41 |
42 | if (input.txid != null) {
43 | const inputTx = await api.native.callDaemon(
44 | chainTicker,
45 | "decoderawtransaction",
46 | [await api.native.callDaemon(
47 | chainTicker,
48 | "getrawtransaction",
49 | [input.txid]
50 | )]
51 | );
52 |
53 | let inouts = inputTx.vout
54 |
55 | for (let i = 0; i < inouts.length; i++) {
56 | let output = inouts[i]
57 |
58 | if (
59 | currencyNotChainticker &&
60 | output.scriptPubKey != null &&
61 | output.scriptPubKey.type === "cryptocondition" &&
62 | output.scriptPubKey.reservetransfer != null
63 | ) {
64 | totalOut += (output.scriptPubKey.reservetransfer.value + output.scriptPubKey.reservetransfer.fees)
65 | totalTransferFees += output.scriptPubKey.reservetransfer.fees
66 |
67 | if (!currencyNotChainticker && await api.native.get_currency_definition(chain, currency).name !== chainTicker) {
68 | currencyNotChainticker = true
69 | }
70 |
71 | if (!isConversion && output.scriptPubKey.reservetransfer.convert) {
72 | isConversion = true
73 | }
74 | } else if (!currencyNotChainticker &&
75 | output.scriptPubKey != null &&
76 | output.scriptPubKey.value) {
77 | // TODO: Finish calculating fee
78 | }
79 | }
80 | }
81 | }
82 | };
83 |
84 | return api;
85 | };
--------------------------------------------------------------------------------
/routes/api/electrum/interest.js:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2018 - 2019 Atomic Labs, Luke Childs
5 | Copyright (c) 2019 - 2022 Komodo Platform
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | */
25 |
26 | const KOMODO_ENDOFERA = 7777777;
27 | const LOCKTIME_THRESHOLD = 500000000;
28 | const MIN_SATOSHIS = 1000000000;
29 | const ONE_MONTH_CAP_HARDFORK = 1000000;
30 | const ONE_HOUR = 60;
31 | const ONE_MONTH = 31 * 24 * 60;
32 | const ONE_YEAR = 365 * 24 * 60;
33 | const DEVISOR = 10512000;
34 | const N_S7_HARDFORK_HEIGHT = 3484958;
35 |
36 | module.exports = (api) => {
37 | api.kmdCalcInterest = (locktime, value, height) => {
38 | const tiptime = Math.floor(Date.now() / 1000) - 777;
39 | const satoshis = value;
40 |
41 | // Calculate coinage
42 | const coinage = Math.floor((tiptime - locktime) / ONE_HOUR);
43 |
44 | // Return early if UTXO is not eligible for rewards
45 | if (
46 | (height >= KOMODO_ENDOFERA) ||
47 | (locktime < LOCKTIME_THRESHOLD) ||
48 | (satoshis < MIN_SATOSHIS) ||
49 | (coinage < ONE_HOUR) ||
50 | (!height)
51 | ) {
52 | return 0;
53 | }
54 |
55 | // Cap reward periods
56 | const limit = (height >= ONE_MONTH_CAP_HARDFORK) ? ONE_MONTH : ONE_YEAR;
57 | let rewardPeriod = Math.min(coinage, limit);
58 |
59 | // The first hour of coinage should not accrue rewards
60 | rewardPeriod -= 59;
61 |
62 | // Calculate rewards
63 | let rewards = Math.floor(satoshis / DEVISOR) * rewardPeriod;
64 |
65 | // Vote-KIP0001 resulted in a reduction of the AUR from 5% to 0.01%
66 | // https://github.com/KomodoPlatform/kips/blob/main/kip-0001.mediawiki
67 | // https://github.com/KomodoPlatform/komodo/pull/584
68 | if (height >= N_S7_HARDFORK_HEIGHT) {
69 | rewards = Math.floor(rewards / 500);
70 | }
71 |
72 | // Ensure reward value is never negative
73 | if (rewards < 0) {
74 | throw new Error('Reward should never be negative');
75 | }
76 |
77 | return rewards;
78 | };
79 |
80 | return api;
81 | };
--------------------------------------------------------------------------------
/routes/api/electrum/addresses.js:
--------------------------------------------------------------------------------
1 | module.exports = (api) => {
2 | api.electrum.get_addresses = async (coin) => {
3 | const coinLc = coin.toLowerCase()
4 | let addresses = {
5 | public: [],
6 | private: []
7 | }
8 |
9 | if (!api.electrumKeys[coinLc] || !api.electrumKeys[coinLc].pub) {
10 | throw new Error(`No address found for ${coin}`);
11 | }
12 |
13 | addresses.public.push({address: api.electrumKeys[coinLc].pub, tag: 'public'})
14 |
15 | for (let i = 0; i < addresses.public.length; i++) {
16 | const addressObj = addresses.public[i];
17 |
18 | try {
19 | const addressBalances = await api.electrum.get_balances(addressObj.address, coin)
20 |
21 | addresses.public[i] = {
22 | ...addressObj,
23 | balances: { native: addressBalances.confirmed, reserve: {} },
24 | };
25 | } catch(e) {
26 | api.log("Error fetching balance for " + addressObj.address, "electrum.get_addresses")
27 | api.log(e, "electrum.get_addresses")
28 |
29 | addresses.public[i] = {
30 | ...addressObj,
31 | balances: null
32 | };
33 | }
34 | }
35 |
36 | return addresses
37 | };
38 |
39 | api.setPost('/electrum/get_pubkey', (req, res, next) => {
40 | const coin = req.body.chainTicker;
41 | const coinLc = coin.toLowerCase()
42 |
43 | if (api.electrumKeys[coinLc] && api.electrumKeys[coinLc].pubHex) {
44 | res.send(JSON.stringify({
45 | msg: 'success',
46 | result: api.electrumKeys[coinLc].pubHex
47 | }));
48 | } else {
49 | res.send(JSON.stringify({
50 | msg: 'error',
51 | result: `No pubkey found for electrum coin ${coin}`
52 | }));
53 | }
54 | });
55 |
56 | api.setPost('/electrum/get_privkey', (req, res, next) => {
57 | const coin = req.body.chainTicker;
58 | const coinLc = coin.toLowerCase()
59 |
60 | if (api.electrumKeys[coinLc] && api.electrumKeys[coinLc].priv) {
61 | res.send(JSON.stringify({
62 | msg: 'success',
63 | result: api.electrumKeys[coinLc].priv
64 | }));
65 | } else {
66 | res.send(JSON.stringify({
67 | msg: 'error',
68 | result: `No privkey found for electrum coin ${coin}`
69 | }));
70 | }
71 | }, true);
72 |
73 | api.setGet('/electrum/get_addresses', (req, res, next) => {
74 | const coin = req.query.chainTicker;
75 |
76 | if (!req.query.chainTicker) {
77 | res.send(JSON.stringify({msg: 'error', result: "No coin passed to electrum get_addresses"}));
78 | }
79 |
80 | api.electrum.get_addresses(coin)
81 | .then((addresses) => {
82 | const retObj = {
83 | msg: 'success',
84 | result: addresses,
85 | };
86 |
87 | res.send(JSON.stringify(retObj));
88 | })
89 | .catch(error => {
90 | const retObj = {
91 | msg: 'error',
92 | result: error.message,
93 | };
94 |
95 | res.send(JSON.stringify(retObj));
96 | })
97 | });
98 |
99 | return api;
100 | };
--------------------------------------------------------------------------------