diff --git a/lib/admin/admin-server.js b/lib/admin/admin-server.js index 02cb7080..8ad7ddaa 100644 --- a/lib/admin/admin-server.js +++ b/lib/admin/admin-server.js @@ -27,6 +27,7 @@ const login = require('./login') const pairing = require('./pairing') const server = require('./server') const transactions = require('./transactions') +const funding = require('./funding') const NEVER = new Date(Date.now() + 100 * T.years) const REAUTHENTICATE_INTERVAL = T.minute @@ -122,6 +123,18 @@ app.post('/api/machines', (req, res) => { .then(() => dbNotify()) }) +app.get('/api/funding', (req, res) => { + return funding.getFunding() + .then(r => res.json(r)) +}) + +app.get('/api/funding/:cryptoCode', (req, res) => { + const cryptoCode = req.params.cryptoCode + + return funding.getFunding(cryptoCode) + .then(r => res.json(r)) +}) + app.get('/api/status', (req, res, next) => { return Promise.all([server.status(), config.validateCurrentConfig()]) .then(([serverStatus, invalidConfigGroups]) => res.send({ diff --git a/lib/admin/funding.js b/lib/admin/funding.js new file mode 100644 index 00000000..5e085078 --- /dev/null +++ b/lib/admin/funding.js @@ -0,0 +1,61 @@ +const BN = require('../bn') +const settingsLoader = require('../settings-loader') +const configManager = require('../config-manager') +const wallet = require('../wallet') +const ticker = require('../ticker') +const coinUtils = require('../coin-utils') + +module.exports = {getFunding} + +function computeCrypto (cryptoCode, _balance) { + const unitScale = coinUtils.coins[cryptoCode].unitScale + + return BN(_balance).shift(-unitScale).round(5) +} + +function computeFiat (rate, cryptoCode, _balance) { + const unitScale = coinUtils.coins[cryptoCode].unitScale + + return BN(_balance).shift(-unitScale).mul(rate).round(5) +} + +function getFunding (cryptoCode) { + cryptoCode = cryptoCode || 'BTC' + const cryptoDisplays = coinUtils.cryptoDisplays + + if (!coinUtils.coins[cryptoCode]) throw new Error(`Unsupported coin: ${cryptoCode}`) + return settingsLoader.loadLatest() + .then(settings => { + const config = configManager.unscoped(settings.config) + const fiatCode = config.fiatCurrency + + const promises = [ + wallet.newFunding(settings, cryptoCode), + ticker.getRates(settings, fiatCode, cryptoCode) + ] + + return Promise.all(promises) + .then(([fundingRec, ratesRec]) => { + const rates = ratesRec.rates + const rate = (rates.ask.add(rates.bid)).div(2) + const fundingConfirmedBalance = fundingRec.fundingConfirmedBalance + const fiatConfirmedBalance = computeFiat(rate, cryptoCode, fundingConfirmedBalance) + const pending = fundingRec.fundingPendingBalance.sub(fundingConfirmedBalance) + const fiatPending = computeFiat(rate, cryptoCode, pending) + const fundingAddress = fundingRec.fundingAddress + const fundingAddressUrl = coinUtils.buildUrl(cryptoCode, fundingAddress) + + return { + cryptoCode, + cryptoDisplays, + fundingAddress, + fundingAddressUrl, + confirmedBalance: computeCrypto(cryptoCode, fundingConfirmedBalance).toFormat(5), + pending: computeCrypto(cryptoCode, pending).toFormat(5), + fiatConfirmedBalance: fiatConfirmedBalance.toFormat(2), + fiatPending: fiatPending.toFormat(2), + fiatCode + } + }) + }) +} diff --git a/lib/coin-utils.js b/lib/coin-utils.js new file mode 100644 index 00000000..df069925 --- /dev/null +++ b/lib/coin-utils.js @@ -0,0 +1,19 @@ +const coins = { + BTC: {unitScale: 8}, + ETH: {unitScale: 18} +} + +const cryptoDisplays = [ + {cryptoCode: 'BTC', display: 'Bitcoin'}, + {cryptoCode: 'ETH', display: 'Ethereum'} +] + +module.exports = {coins, cryptoDisplays, buildUrl} + +function buildUrl (cryptoCode, address) { + switch (cryptoCode) { + case 'BTC': return `bitcoin:${address}` + case 'ETH': return `ethereum:${address}` + default: throw new Error(`Unsupported crypto: ${cryptoCode}`) + } +} diff --git a/lib/plugin-helper.js b/lib/plugin-helper.js index d9c9b6f5..15003260 100644 --- a/lib/plugin-helper.js +++ b/lib/plugin-helper.js @@ -19,6 +19,8 @@ function load (type, pluginCode) { throw new Error(`Unallowed plugin type: ${type}`) } + if (!pluginCode) throw new Error(`No plugin defined for ${type}`) + if (pluginCode.search(/[a-z0-9\-]/) === -1) { throw new Error(`Unallowed plugin name: ${pluginCode}`) } diff --git a/lib/plugins.js b/lib/plugins.js index 8109de26..72f0071e 100644 --- a/lib/plugins.js +++ b/lib/plugins.js @@ -17,6 +17,7 @@ const sms = require('./sms') const email = require('./email') const cashOutHelper = require('./cash-out-helper') const machineLoader = require('./machine-loader') +const coinUtils = require('./coin-utils') const mapValuesWithKey = _.mapValues.convert({cap: false}) @@ -26,10 +27,7 @@ const STALE_BALANCE = 3 * T.minutes const PONG_TTL = '1 week' const tradesQueues = {} -const coins = { - BTC: {unitScale: 8}, - ETH: {unitScale: 18} -} +const coins = coinUtils.coins function plugins (settings, deviceId) { function buildRates (tickers) { diff --git a/lib/plugins/wallet/bitcoind/bitcoind.js b/lib/plugins/wallet/bitcoind/bitcoind.js index b307dbd0..34d90f66 100644 --- a/lib/plugins/wallet/bitcoind/bitcoind.js +++ b/lib/plugins/wallet/bitcoind/bitcoind.js @@ -50,25 +50,30 @@ function parseConf (confPath) { } function checkCryptoCode (cryptoCode) { - if (cryptoCode !== 'BTC') throw new Error('Unsupported crypto: ' + cryptoCode) + if (cryptoCode !== 'BTC') return Promise.reject(new Error('Unsupported crypto: ' + cryptoCode)) + return Promise.resolve() +} + +function accountBalance (account, cryptoCode, confirmations) { + return checkCryptoCode(cryptoCode) + .then(() => { + const rpc = initRpc() + + return new Promise((resolve, reject) => { + rpc.getBalance(pluginConfig.account, confirmations, (err, result) => { + if (err) return reject(err) + if (result.error) reject(new Error(err)) + + return resolve(BN(result.result).shift(SATOSHI_SHIFT).round()) + }) + }) + }) } // We want a balance that includes all spends (0 conf) but only deposits that // have at least 1 confirmation. getbalance does this for us automatically. function balance (account, cryptoCode) { - return new Promise((resolve, reject) => { - checkCryptoCode(cryptoCode) - const rpc = initRpc() - rpc.getBalance(pluginConfig.account, 1, (err, result) => { - if (err) return reject(err) - - if (result.error) { - return reject(err) - } - - resolve(BN(result.result).shift(SATOSHI_SHIFT).round()) - }) - }) + return accountBalance(account, cryptoCode, 1) } function sendCoins (account, address, cryptoAtoms, cryptoCode) { @@ -76,26 +81,30 @@ function sendCoins (account, address, cryptoAtoms, cryptoCode) { const confirmations = 1 const bitcoins = cryptoAtoms.shift(-SATOSHI_SHIFT).toFixed(8) - return new Promise((resolve, reject) => { - checkCryptoCode(cryptoCode) - rpc.sendFrom(pluginConfig.account, address, bitcoins, confirmations, (err, result) => { - if (err) { - if (err.code === -6) return reject(new E.InsufficientFundsError()) - return reject(err) - } + return checkCryptoCode(cryptoCode) + .then(() => { + return new Promise((resolve, reject) => { + rpc.sendFrom(pluginConfig.account, address, bitcoins, confirmations, (err, result) => { + if (err) { + if (err.code === -6) return reject(new E.InsufficientFundsError()) + return reject(err) + } - resolve(result.result) + resolve(result.result) + }) }) }) } function newAddress (account, info) { - return new Promise((resolve, reject) => { - checkCryptoCode(info.cryptoCode) - const rpc = initRpc() - rpc.getNewAddress((err, result) => { - if (err) return reject(err) - resolve(result.result) + return checkCryptoCode(info.cryptoCode) + .then(() => { + return new Promise((resolve, reject) => { + const rpc = initRpc() + rpc.getNewAddress((err, result) => { + if (err) return reject(err) + resolve(result.result) + }) }) }) } @@ -106,17 +115,23 @@ function addressBalance (address, confs) { .then(r => BN(r.result).shift(SATOSHI_SHIFT).round()) } -const confirmedBalance = address => addressBalance(address, 1) -const pendingBalance = address => addressBalance(address, 0) +function confirmedBalance (address, cryptoCode) { + return checkCryptoCode(cryptoCode) + .then(() => addressBalance(address, 1)) +} + +function pendingBalance (address, cryptoCode) { + return checkCryptoCode(cryptoCode) + .then(() => addressBalance(address, 0)) +} function getStatus (account, toAddress, requested, cryptoCode) { - return Promise.resolve() - .then(() => checkCryptoCode(cryptoCode)) - .then(() => confirmedBalance(toAddress)) + return checkCryptoCode(cryptoCode) + .then(() => confirmedBalance(toAddress, cryptoCode)) .then(confirmed => { if (confirmed.gte(requested)) return {status: 'confirmed'} - return pendingBalance(toAddress) + return pendingBalance(toAddress, cryptoCode) .then(pending => { if (pending.gte(requested)) return {status: 'authorized'} if (pending.gt(0)) return {status: 'insufficientFunds'} @@ -125,10 +140,31 @@ function getStatus (account, toAddress, requested, cryptoCode) { }) } +function newFunding (account, cryptoCode) { + return checkCryptoCode(cryptoCode) + .then(() => { + const promises = [ + accountBalance(account, cryptoCode, 0), + accountBalance(account, cryptoCode, 1), + newAddress(account, {cryptoCode}) + ] + + return Promise.all(promises) + }) + .then(([fundingPendingBalance, fundingConfirmedBalance, fundingAddress]) => ({ + fundingPendingBalance, + fundingConfirmedBalance, + fundingAddress + })) +} + module.exports = { NAME, balance, + pendingBalance, + confirmedBalance, sendCoins, newAddress, - getStatus + getStatus, + newFunding } diff --git a/lib/plugins/wallet/bitgo/bitgo.js b/lib/plugins/wallet/bitgo/bitgo.js index ec0ff1c0..7bc8b351 100644 --- a/lib/plugins/wallet/bitgo/bitgo.js +++ b/lib/plugins/wallet/bitgo/bitgo.js @@ -84,10 +84,30 @@ function getStatus (account, toAddress, requested, cryptoCode) { }) } +function newFunding (account, cryptoCode) { + return checkCryptoCode(cryptoCode) + .then(() => { + return getWallet(account) + .then(wallet => { + return wallet.createAddress() + .then(result => { + const fundingAddress = result.address + return wallet.setLabel({address: fundingAddress, label: 'Funding Address'}) + .then(() => ({ + fundingPendingBalance: BN(wallet.wallet.balance), + fundingConfirmedBalance: BN(wallet.wallet.confirmedBalance), + fundingAddress + })) + }) + }) + }) +} + module.exports = { NAME, balance, sendCoins, newAddress, - getStatus + getStatus, + newFunding } diff --git a/lib/plugins/wallet/geth/geth.js b/lib/plugins/wallet/geth/geth.js index 030a3473..328223b0 100644 --- a/lib/plugins/wallet/geth/geth.js +++ b/lib/plugins/wallet/geth/geth.js @@ -21,7 +21,8 @@ module.exports = { getStatus, sweep, defaultAddress, - supportsHd: true + supportsHd: true, + newFunding } if (!web3.isConnected()) { @@ -36,13 +37,13 @@ function sendCoins (account, toAddress, cryptoAtoms, cryptoCode) { .then(pify(web3.eth.sendRawTransaction)) } -function validateCrypto (cryptoCode) { +function checkCryptoCode (cryptoCode) { if (cryptoCode === 'ETH') return Promise.resolve() return Promise.reject(new Error('cryptoCode must be ETH')) } function balance (account, cryptoCode) { - return validateCrypto(cryptoCode) + return checkCryptoCode(cryptoCode) .then(() => pendingBalance(defaultAddress(account))) } @@ -136,7 +137,7 @@ function newAddress (account, info) { } function getStatus (account, toAddress, cryptoAtoms, cryptoCode) { - return validateCrypto(cryptoCode) + return checkCryptoCode(cryptoCode) .then(() => confirmedBalance(toAddress)) .then(confirmed => { if (confirmed.gte(cryptoAtoms)) return {status: 'confirmed'} @@ -164,3 +165,22 @@ function defaultHdNode (account) { const key = hdkey.fromMasterSeed(masterSeed) return key.derivePath(defaultPrefixPath) } + +function newFunding (account, cryptoCode) { + return checkCryptoCode(cryptoCode) + .then(() => { + const fundingAddress = defaultAddress(account) + + const promises = [ + pendingBalance(fundingAddress), + confirmedBalance(fundingAddress) + ] + + return Promise.all(promises) + .then(([fundingPendingBalance, fundingConfirmedBalance]) => ({ + fundingPendingBalance, + fundingConfirmedBalance, + fundingAddress + })) + }) +} diff --git a/lib/plugins/wallet/mock-wallet/mock-wallet.js b/lib/plugins/wallet/mock-wallet/mock-wallet.js index 09ba58b8..4773fc2a 100644 --- a/lib/plugins/wallet/mock-wallet/mock-wallet.js +++ b/lib/plugins/wallet/mock-wallet/mock-wallet.js @@ -19,6 +19,24 @@ function balance (account, cryptoCode) { }) } +function pendingBalance (account, cryptoCode) { + return Promise.resolve() + .then(() => { + if (cryptoCode === 'BTC') return BN(1e8 * 10.1) + if (cryptoCode === 'ETH') return BN(1e18 * 10.1) + throw new Error('Unsupported crypto: ' + cryptoCode) + }) +} + +function confirmedBalance (account, cryptoCode) { + return Promise.resolve() + .then(() => { + if (cryptoCode === 'BTC') return BN(1e8 * 10) + if (cryptoCode === 'ETH') return BN(1e18 * 10) + throw new Error('Unsupported crypto: ' + cryptoCode) + }) +} + // Note: This makes it easier to test insufficient funds errors let sendCount = 0 @@ -50,6 +68,21 @@ function newAddress () { return Promise.resolve('') } +function newFunding (account, cryptoCode) { + const promises = [ + pendingBalance(account, cryptoCode), + confirmedBalance(account, cryptoCode), + newAddress(account, {cryptoCode}) + ] + + return Promise.all(promises) + .then(([fundingPendingBalance, fundingConfirmedBalance, fundingAddress]) => ({ + fundingPendingBalance, + fundingConfirmedBalance, + fundingAddress + })) +} + function getStatus (account, toAddress, cryptoAtoms, cryptoCode) { const elapsed = Date.now() - t0 @@ -66,5 +99,6 @@ module.exports = { balance, sendCoins, newAddress, - getStatus + getStatus, + newFunding } diff --git a/lib/wallet.js b/lib/wallet.js index 3ac24dd8..3c882f02 100644 --- a/lib/wallet.js +++ b/lib/wallet.js @@ -68,6 +68,16 @@ function newAddress (settings, info) { .then(r => r.wallet.newAddress(r.account, info)) } +function newFunding (settings, cryptoCode, address) { + return fetchWallet(settings, cryptoCode) + .then(r => { + const wallet = r.wallet + const account = r.account + + return wallet.newFunding(account, cryptoCode) + }) +} + function getWalletStatus (settings, tx) { return fetchWallet(settings, tx.cryptoCode) .then(r => r.wallet.getStatus(r.account, tx.toAddress, tx.cryptoAtoms, tx.cryptoCode)) @@ -135,5 +145,6 @@ module.exports = { newAddress, getStatus, sweep, - isHd + isHd, + newFunding } diff --git a/package-lock.json b/package-lock.json index e7e4eeb3..ee477457 100644 --- a/package-lock.json +++ b/package-lock.json @@ -479,6 +479,11 @@ "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", "dev": true }, + "bignumber.js": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.0.2.tgz", + "integrity": "sha1-LR3DfuWWiGfs6pC22k0W5oYI0h0=" + }, "binary-extensions": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.8.0.tgz", @@ -595,12 +600,6 @@ } } }, - "capture-stack-trace": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", - "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", - "dev": true - }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -709,18 +708,6 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, - "color-convert": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", - "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", - "dev": true - }, - "color-name": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.2.tgz", - "integrity": "sha1-XIq3K2S9IhXWF66VWeuxSEdc+Y0=", - "dev": true - }, "common-path-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-1.0.0.tgz", @@ -775,12 +762,6 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, - "create-error-class": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "dev": true - }, "cross-spawn": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", @@ -795,20 +776,6 @@ } } }, - "cross-spawn-async": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", - "integrity": "sha1-hF/wwINKPe2dFg2sptOQkGuyiMw=", - "dev": true, - "dependencies": { - "lru-cache": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.0.tgz", - "integrity": "sha512-aHGs865JXz6bkB4AHL+3AhyvTFKL3iZamKVWjIUKnXOXyasJvqPK8WAjOnAQKQZVpeXDVz19u1DD0r/12bWAdQ==", - "dev": true - } - } - }, "crypto-random-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", @@ -875,12 +842,6 @@ "integrity": "sha1-qEk/C3te7sglJbXHWH+n3nyoWcE=", "dev": true }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, "empower-core": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/empower-core/-/empower-core-0.6.2.tgz", @@ -1015,12 +976,6 @@ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "dev": true }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, "fsevents": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.1.tgz", @@ -1784,12 +1739,6 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true }, - "has-color": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", - "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", - "dev": true - }, "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", @@ -1852,12 +1801,6 @@ "integrity": "sha1-CP9DNGAziDmbMp5rlTjcejz13n0=", "dev": true }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true - }, "inherits": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", @@ -2014,18 +1957,6 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, - "is-redirect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", - "dev": true - }, - "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", - "dev": true - }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -2246,12 +2177,6 @@ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dev": true }, - "lowercase-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", - "dev": true - }, "make-dir": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.0.0.tgz", @@ -2459,12 +2384,6 @@ } } }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true - }, "onetime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", @@ -2557,12 +2476,6 @@ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true }, - "parse-ms": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-1.0.1.tgz", - "integrity": "sha1-VjRtR0nXjyNDDKDHE4UK75GqNh0=", - "dev": true - }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -2639,12 +2552,6 @@ "integrity": "sha1-dIJFLBoPUI4+NE6uwxLJHCncZVo=", "dev": true }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", @@ -2677,12 +2584,6 @@ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", "dev": true }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", @@ -2961,12 +2862,6 @@ "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", "dev": true }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, "stack-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.1.tgz", @@ -3125,12 +3020,6 @@ } } }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true - }, "to-fast-properties": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", @@ -3173,12 +3062,6 @@ "integrity": "sha1-G1g3z5DAc22IYncytmHBOPht5y8=", "dev": true }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -3203,12 +3086,6 @@ "integrity": "sha1-DAnIXCqUaD0Nfq+O4JfVZL8OEFw=", "dev": true }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, "write-file-atomic": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.1.0.tgz", @@ -3252,12 +3129,6 @@ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true } } } diff --git a/package.json b/package.json index d08c1e07..5c71298b 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "@fczbkk/uuid4": "^3.0.0", "axios": "^0.16.1", "base-x": "^3.0.2", - "bignumber.js": "^4.0.1", + "bignumber.js": "^4.0.2", "bip39": "^2.3.1", "bitcoind-rpc": "^0.7.0", "bitgo": "^3.3.6", diff --git a/public/elm.js b/public/elm.js index 3710a66a..93f94c2e 100644 --- a/public/elm.js +++ b/public/elm.js @@ -30949,6 +30949,8 @@ var _user$project$Css_Admin$className = function ($class) { return A2(_rtfeldman$elm_css_util$Css_Helpers$identifierToString, _user$project$Css_Admin$name, $class); }; +var _user$project$Css_Classes$BalanceSection = {ctor: 'BalanceSection'}; +var _user$project$Css_Classes$CryptoAddress = {ctor: 'CryptoAddress'}; var _user$project$Css_Classes$ReadOnly = {ctor: 'ReadOnly'}; var _user$project$Css_Classes$CashIn = {ctor: 'CashIn'}; var _user$project$Css_Classes$CashOut = {ctor: 'CashOut'}; @@ -30999,8 +31001,10 @@ var _user$project$Css_Classes$ConfigTableGlobalRow = {ctor: 'ConfigTableGlobalRo var _user$project$Css_Classes$ConfigTable = {ctor: 'ConfigTable'}; var _user$project$Css_Classes$SectionLabel = {ctor: 'SectionLabel'}; var _user$project$Css_Classes$CryptoTabsActive = {ctor: 'CryptoTabsActive'}; +var _user$project$Css_Classes$CryptoTab = {ctor: 'CryptoTab'}; var _user$project$Css_Classes$CryptoTabs = {ctor: 'CryptoTabs'}; var _user$project$Css_Classes$Content = {ctor: 'Content'}; +var _user$project$Css_Classes$Container = {ctor: 'Container'}; var _user$project$Css_Classes$NavBarRoute = {ctor: 'NavBarRoute'}; var _user$project$Css_Classes$NavBarCategory = {ctor: 'NavBarCategory'}; var _user$project$Css_Classes$NavBarCategoryContainer = {ctor: 'NavBarCategoryContainer'}; @@ -31470,10 +31474,6 @@ var _user$project$AccountsDecoder$accountsDecoder = A2( 'accounts', _elm_lang$core$Json_Decode$list(_user$project$AccountsDecoder$accountDecoder))); -var _user$project$BasicTypes$StringDecimal = F2( - function (a, b) { - return {integral: a, fractional: b}; - }); var _user$project$BasicTypes$NotSaving = {ctor: 'NotSaving'}; var _user$project$BasicTypes$Editing = {ctor: 'Editing'}; var _user$project$BasicTypes$Saved = {ctor: 'Saved'}; @@ -32340,11 +32340,19 @@ var _user$project$Selectize$view = F5( } }); +var _user$project$ConfigTypes$cryptoToString = function (crypto) { + var _p0 = crypto; + if (_p0.ctor === 'GlobalCrypto') { + return 'global'; + } else { + return _p0._0; + } +}; var _user$project$ConfigTypes$fieldHolderMap = F3( function ($default, mapper, fieldHolder) { - var _p0 = fieldHolder; - if (_p0.ctor === 'FieldOk') { - return mapper(_p0._0); + var _p1 = fieldHolder; + if (_p1.ctor === 'FieldOk') { + return mapper(_p1._0); } else { return $default; } @@ -32353,7 +32361,7 @@ var _user$project$ConfigTypes$groupMember = F2( function (configGroup, fieldCode) { return A2( _elm_lang$core$List$any, - function (_p1) { + function (_p2) { return A2( F2( function (x, y) { @@ -32362,24 +32370,24 @@ var _user$project$ConfigTypes$groupMember = F2( fieldCode, function (_) { return _.code; - }(_p1)); + }(_p2)); }, configGroup.schema.entries); }); var _user$project$ConfigTypes$fieldHolderToMaybe = function (fieldHolder) { - var _p2 = fieldHolder; - if (_p2.ctor === 'FieldOk') { - return _elm_lang$core$Maybe$Just(_p2._0); + var _p3 = fieldHolder; + if (_p3.ctor === 'FieldOk') { + return _elm_lang$core$Maybe$Just(_p3._0); } else { return _elm_lang$core$Maybe$Nothing; } }; var _user$project$ConfigTypes$fieldHolderToCryptoStrings = function (fieldHolder) { - var _p3 = fieldHolder; - if (_p3.ctor === 'FieldOk') { - var _p4 = _p3._0; - if (_p4.ctor === 'FieldCryptoCurrencyValue') { - return _p4._0; + var _p4 = fieldHolder; + if (_p4.ctor === 'FieldOk') { + var _p5 = _p4._0; + if (_p5.ctor === 'FieldCryptoCurrencyValue') { + return _p5._0; } else { return {ctor: '[]'}; } @@ -32389,11 +32397,11 @@ var _user$project$ConfigTypes$fieldHolderToCryptoStrings = function (fieldHolder }; var _user$project$ConfigTypes$isCrypto = F2( function (cryptoString, cryptoDisplay) { - var _p5 = cryptoDisplay.crypto; - if (_p5.ctor === 'GlobalCrypto') { + var _p6 = cryptoDisplay.crypto; + if (_p6.ctor === 'GlobalCrypto') { return _elm_lang$core$Native_Utils.eq(cryptoString, 'global'); } else { - return _elm_lang$core$Native_Utils.eq(cryptoString, _p5._0); + return _elm_lang$core$Native_Utils.eq(cryptoString, _p6._0); } }); var _user$project$ConfigTypes$lookupCryptoDisplay = F2( @@ -32404,14 +32412,6 @@ var _user$project$ConfigTypes$lookupCryptoDisplay = F2( _user$project$ConfigTypes$isCrypto(cryptoString), cryptoDisplays)); }); -var _user$project$ConfigTypes$cryptoToString = function (crypto) { - var _p6 = crypto; - if (_p6.ctor === 'GlobalCrypto') { - return 'global'; - } else { - return _p6._0; - } -}; var _user$project$ConfigTypes$machineToString = function (machine) { var _p7 = machine; if (_p7.ctor === 'GlobalMachine') { @@ -32468,10 +32468,6 @@ var _user$project$ConfigTypes$MachineDisplay = F2( function (a, b) { return {machine: a, display: b}; }); -var _user$project$ConfigTypes$CryptoDisplay = F2( - function (a, b) { - return {crypto: a, display: b}; - }); var _user$project$ConfigTypes$FieldScope = F2( function (a, b) { return {crypto: a, machine: b}; @@ -32541,59 +32537,15 @@ var _user$project$ConfigTypes$FieldCollection = F2( function (a, b) { return {fields: a, fieldInstances: b}; }); -var _user$project$ConfigTypes$GlobalCrypto = {ctor: 'GlobalCrypto'}; -var _user$project$ConfigTypes$globalCryptoDisplay = {crypto: _user$project$ConfigTypes$GlobalCrypto, display: 'Global'}; -var _user$project$ConfigTypes$allCryptos = F3( - function (cryptoDisplays, cryptoScope, cryptoStrings) { - var allSpecificCryptos = A2( - _elm_lang$core$List$filterMap, - _user$project$ConfigTypes$lookupCryptoDisplay(cryptoDisplays), - cryptoStrings); - var _p10 = cryptoScope; - switch (_p10.ctor) { - case 'Global': - return { - ctor: '::', - _0: _user$project$ConfigTypes$globalCryptoDisplay, - _1: {ctor: '[]'} - }; - case 'Specific': - return allSpecificCryptos; - default: - return {ctor: '::', _0: _user$project$ConfigTypes$globalCryptoDisplay, _1: allSpecificCryptos}; - } +var _user$project$ConfigTypes$CryptoDisplay = F2( + function (a, b) { + return {crypto: a, display: b}; }); -var _user$project$ConfigTypes$listCryptos = function (configGroup) { - var _p11 = configGroup.schema.cryptoScope; - switch (_p11.ctor) { - case 'Specific': - return configGroup.data.cryptoCurrencies; - case 'Global': - return { - ctor: '::', - _0: _user$project$ConfigTypes$globalCryptoDisplay, - _1: {ctor: '[]'} - }; - default: - return {ctor: '::', _0: _user$project$ConfigTypes$globalCryptoDisplay, _1: configGroup.data.cryptoCurrencies}; - } -}; -var _user$project$ConfigTypes$CryptoCode = function (a) { - return {ctor: 'CryptoCode', _0: a}; -}; -var _user$project$ConfigTypes$stringToCrypto = function (string) { - var _p12 = string; - if (_p12 === 'global') { - return _user$project$ConfigTypes$GlobalCrypto; - } else { - return _user$project$ConfigTypes$CryptoCode(string); - } -}; var _user$project$ConfigTypes$GlobalMachine = {ctor: 'GlobalMachine'}; var _user$project$ConfigTypes$globalMachineDisplay = {machine: _user$project$ConfigTypes$GlobalMachine, display: 'Global'}; var _user$project$ConfigTypes$listMachines = function (configGroup) { - var _p13 = configGroup.schema.machineScope; - switch (_p13.ctor) { + var _p10 = configGroup.schema.machineScope; + switch (_p10.ctor) { case 'Specific': return configGroup.data.machines; case 'Global': @@ -32606,29 +32558,6 @@ var _user$project$ConfigTypes$listMachines = function (configGroup) { return {ctor: '::', _0: _user$project$ConfigTypes$globalMachineDisplay, _1: configGroup.data.machines}; } }; -var _user$project$ConfigTypes$fieldScopes = function (configGroup) { - var cryptos = A2( - _elm_lang$core$List$map, - function (_) { - return _.crypto; - }, - _user$project$ConfigTypes$listCryptos(configGroup)); - var machines = A2( - _elm_lang$core$List$map, - function (_) { - return _.machine; - }, - _user$project$ConfigTypes$listMachines(configGroup)); - var cryptoScopes = function (crypto) { - return A2( - _elm_lang$core$List$map, - function (machine) { - return {machine: machine, crypto: crypto}; - }, - machines); - }; - return A2(_elm_lang$core$List$concatMap, cryptoScopes, cryptos); -}; var _user$project$ConfigTypes$MachineId = function (a) { return {ctor: 'MachineId', _0: a}; }; @@ -32646,11 +32575,11 @@ var _user$project$ConfigTypes$ParsingError = function (a) { return {ctor: 'ParsingError', _0: a}; }; var _user$project$ConfigTypes$resultToFieldHolder = function (result) { - var _p14 = result; - if (_p14.ctor === 'Ok') { - return _user$project$ConfigTypes$FieldOk(_p14._0); + var _p11 = result; + if (_p11.ctor === 'Ok') { + return _user$project$ConfigTypes$FieldOk(_p11._0); } else { - return _user$project$ConfigTypes$ParsingError(_p14._0); + return _user$project$ConfigTypes$ParsingError(_p11._0); } }; var _user$project$ConfigTypes$SelectizeComponent = function (a) { @@ -32702,8 +32631,8 @@ var _user$project$ConfigTypes$stringToFieldHolder = F2( if (_elm_lang$core$String$isEmpty(s)) { return _user$project$ConfigTypes$FieldEmpty; } else { - var _p15 = fieldType; - switch (_p15.ctor) { + var _p12 = fieldType; + switch (_p12.ctor) { case 'FieldStringType': return _user$project$ConfigTypes$FieldOk( _user$project$ConfigTypes$FieldStringValue(s)); @@ -32726,8 +32655,8 @@ var _user$project$ConfigTypes$stringToFieldHolder = F2( _user$project$ConfigTypes$FieldDecimalValue, _elm_lang$core$String$toFloat(s))); case 'FieldOnOffType': - var _p16 = s; - switch (_p16) { + var _p13 = s; + switch (_p13) { case 'on': return _user$project$ConfigTypes$FieldOk( _user$project$ConfigTypes$FieldOnOffValue(true)); @@ -32781,6 +32710,77 @@ var _user$project$ConfigTypes$DisplayTopLeader = F2( function (a, b) { return {ctor: 'DisplayTopLeader', _0: a, _1: b}; }); +var _user$project$ConfigTypes$GlobalCrypto = {ctor: 'GlobalCrypto'}; +var _user$project$ConfigTypes$globalCryptoDisplay = {crypto: _user$project$ConfigTypes$GlobalCrypto, display: 'Global'}; +var _user$project$ConfigTypes$allCryptos = F3( + function (cryptoDisplays, cryptoScope, cryptoStrings) { + var allSpecificCryptos = A2( + _elm_lang$core$List$filterMap, + _user$project$ConfigTypes$lookupCryptoDisplay(cryptoDisplays), + cryptoStrings); + var _p14 = cryptoScope; + switch (_p14.ctor) { + case 'Global': + return { + ctor: '::', + _0: _user$project$ConfigTypes$globalCryptoDisplay, + _1: {ctor: '[]'} + }; + case 'Specific': + return allSpecificCryptos; + default: + return {ctor: '::', _0: _user$project$ConfigTypes$globalCryptoDisplay, _1: allSpecificCryptos}; + } + }); +var _user$project$ConfigTypes$listCryptos = function (configGroup) { + var _p15 = configGroup.schema.cryptoScope; + switch (_p15.ctor) { + case 'Specific': + return configGroup.data.cryptoCurrencies; + case 'Global': + return { + ctor: '::', + _0: _user$project$ConfigTypes$globalCryptoDisplay, + _1: {ctor: '[]'} + }; + default: + return {ctor: '::', _0: _user$project$ConfigTypes$globalCryptoDisplay, _1: configGroup.data.cryptoCurrencies}; + } +}; +var _user$project$ConfigTypes$fieldScopes = function (configGroup) { + var cryptos = A2( + _elm_lang$core$List$map, + function (_) { + return _.crypto; + }, + _user$project$ConfigTypes$listCryptos(configGroup)); + var machines = A2( + _elm_lang$core$List$map, + function (_) { + return _.machine; + }, + _user$project$ConfigTypes$listMachines(configGroup)); + var cryptoScopes = function (crypto) { + return A2( + _elm_lang$core$List$map, + function (machine) { + return {machine: machine, crypto: crypto}; + }, + machines); + }; + return A2(_elm_lang$core$List$concatMap, cryptoScopes, cryptos); +}; +var _user$project$ConfigTypes$CryptoCode = function (a) { + return {ctor: 'CryptoCode', _0: a}; +}; +var _user$project$ConfigTypes$stringToCrypto = function (string) { + var _p16 = string; + if (_p16 === 'global') { + return _user$project$ConfigTypes$GlobalCrypto; + } else { + return _user$project$ConfigTypes$CryptoCode(string); + } +}; var _user$project$ConfigDecoder$displayTopDecoderHelper = function (maybeDisplayTopCount) { var _p0 = maybeDisplayTopCount; @@ -35110,9 +35110,18 @@ var _user$project$Config$cryptoView = F2( _0: activeClass, _1: { ctor: '::', - _0: _elm_lang$html$Html_Events$onClick( - _user$project$Config$CryptoSwitch(cryptoDisplay.crypto)), - _1: {ctor: '[]'} + _0: _user$project$Css_Admin$class( + { + ctor: '::', + _0: _user$project$Css_Classes$CryptoTab, + _1: {ctor: '[]'} + }), + _1: { + ctor: '::', + _0: _elm_lang$html$Html_Events$onClick( + _user$project$Config$CryptoSwitch(cryptoDisplay.crypto)), + _1: {ctor: '[]'} + } } }, { @@ -36304,10 +36313,17 @@ var _user$project$MaintenanceMachines_Types$Action = {ctor: 'Action'}; var _user$project$MaintenanceMachines_Types$Bottom = {ctor: 'Bottom'}; var _user$project$MaintenanceMachines_Types$Top = {ctor: 'Top'}; -var _user$project$MaintenanceFunding_Types$SubModel = F5( - function (a, b, c, d, e) { - return {cryptoCode: a, address: b, balance: c, fiatBalance: d, fiatCode: e}; +var _user$project$MaintenanceFunding_Types$CryptoDisplay = F2( + function (a, b) { + return {cryptoCode: a, display: b}; }); +var _user$project$MaintenanceFunding_Types$SubModel = F9( + function (a, b, c, d, e, f, g, h, i) { + return {cryptoCode: a, cryptoDisplays: b, fundingAddress: c, fundingAddressUrl: d, confirmedBalance: e, pending: f, fiatConfirmedBalance: g, fiatPending: h, fiatCode: i}; + }); +var _user$project$MaintenanceFunding_Types$CryptoSwitch = function (a) { + return {ctor: 'CryptoSwitch', _0: a}; +}; var _user$project$MaintenanceFunding_Types$Load = function (a) { return {ctor: 'Load', _0: a}; }; @@ -37268,12 +37284,17 @@ var _user$project$NavBar$linkClasses = F3( function (linkRoute, route, isValid) { var active = function () { var _p4 = route; - if (_p4.ctor === 'ConfigRoute') { - return _elm_lang$core$Native_Utils.eq( - linkRoute, - A2(_user$project$CoreTypes$ConfigRoute, _p4._0, _elm_lang$core$Maybe$Nothing)); - } else { - return _elm_lang$core$Native_Utils.eq(linkRoute, route); + switch (_p4.ctor) { + case 'ConfigRoute': + return _elm_lang$core$Native_Utils.eq( + linkRoute, + A2(_user$project$CoreTypes$ConfigRoute, _p4._0, _elm_lang$core$Maybe$Nothing)); + case 'MaintenanceFundingRoute': + return _elm_lang$core$Native_Utils.eq( + linkRoute, + _user$project$CoreTypes$MaintenanceFundingRoute(_elm_lang$core$Maybe$Nothing)); + default: + return _elm_lang$core$Native_Utils.eq(linkRoute, route); } }(); var validityClass = isValid ? {ctor: '[]'} : { @@ -38342,19 +38363,52 @@ var _user$project$MaintenanceMachines_View$view = function (model) { } }; -var _user$project$MaintenanceFunding_Rest$stringDecimalDecoder = A3( - _elm_lang$core$Json_Decode$map2, - _user$project$BasicTypes$StringDecimal, - A2(_elm_lang$core$Json_Decode$field, 'integral', _elm_lang$core$Json_Decode$string), - A2(_elm_lang$core$Json_Decode$field, 'fractional', _elm_lang$core$Json_Decode$string)); -var _user$project$MaintenanceFunding_Rest$subModelDecoder = A6( - _elm_lang$core$Json_Decode$map5, - _user$project$MaintenanceFunding_Types$SubModel, - A2(_elm_lang$core$Json_Decode$field, 'cryptoCode', _elm_lang$core$Json_Decode$string), - A2(_elm_lang$core$Json_Decode$field, 'address', _elm_lang$core$Json_Decode$string), - A2(_elm_lang$core$Json_Decode$field, 'balance', _user$project$MaintenanceFunding_Rest$stringDecimalDecoder), - A2(_elm_lang$core$Json_Decode$field, 'fiatBalance', _user$project$MaintenanceFunding_Rest$stringDecimalDecoder), - A2(_elm_lang$core$Json_Decode$field, 'fiatCode', _elm_lang$core$Json_Decode$string)); +var _user$project$MaintenanceFunding_Rest$cryptoDisplayDecoder = A3( + _NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required, + 'display', + _elm_lang$core$Json_Decode$string, + A3( + _NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required, + 'cryptoCode', + _elm_lang$core$Json_Decode$string, + _NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$decode(_user$project$MaintenanceFunding_Types$CryptoDisplay))); +var _user$project$MaintenanceFunding_Rest$subModelDecoder = A3( + _NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required, + 'fiatCode', + _elm_lang$core$Json_Decode$string, + A3( + _NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required, + 'fiatPending', + _elm_lang$core$Json_Decode$string, + A3( + _NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required, + 'fiatConfirmedBalance', + _elm_lang$core$Json_Decode$string, + A3( + _NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required, + 'pending', + _elm_lang$core$Json_Decode$string, + A3( + _NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required, + 'confirmedBalance', + _elm_lang$core$Json_Decode$string, + A3( + _NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required, + 'fundingAddressUrl', + _elm_lang$core$Json_Decode$string, + A3( + _NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required, + 'fundingAddress', + _elm_lang$core$Json_Decode$string, + A3( + _NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required, + 'cryptoDisplays', + _elm_lang$core$Json_Decode$list(_user$project$MaintenanceFunding_Rest$cryptoDisplayDecoder), + A3( + _NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required, + 'cryptoCode', + _elm_lang$core$Json_Decode$string, + _NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$decode(_user$project$MaintenanceFunding_Types$SubModel)))))))))); var _user$project$MaintenanceFunding_Rest$getForm = function (maybeCrypto) { return A2( _elm_lang$core$Platform_Cmd$map, @@ -38372,6 +38426,15 @@ var _user$project$MaintenanceFunding_Rest$getForm = function (maybeCrypto) { A2(_elm_lang$core$Maybe$withDefault, '', maybeCrypto)))))); }; +var _user$project$MaintenanceFunding_State$switchCrypto = F2( + function (crypto, model) { + return { + ctor: '_Tuple2', + _0: _krisajenkins$remotedata$RemoteData$Loading, + _1: _user$project$MaintenanceFunding_Rest$getForm( + _elm_lang$core$Maybe$Just(crypto)) + }; + }); var _user$project$MaintenanceFunding_State$fundingUpdate = function (model) { return A2( _elm_lang$core$Platform_Cmd_ops['!'], @@ -38381,7 +38444,11 @@ var _user$project$MaintenanceFunding_State$fundingUpdate = function (model) { var _user$project$MaintenanceFunding_State$update = F2( function (msg, model) { var _p0 = msg; - return A2(_krisajenkins$remotedata$RemoteData$update, _user$project$MaintenanceFunding_State$fundingUpdate, _p0._0); + if (_p0.ctor === 'Load') { + return A2(_krisajenkins$remotedata$RemoteData$update, _user$project$MaintenanceFunding_State$fundingUpdate, _p0._0); + } else { + return A2(_user$project$MaintenanceFunding_State$switchCrypto, _p0._0, model); + } }); var _user$project$MaintenanceFunding_State$load = function (maybeCrypto) { return { @@ -38392,9 +38459,232 @@ var _user$project$MaintenanceFunding_State$load = function (maybeCrypto) { }; var _user$project$MaintenanceFunding_State$init = _krisajenkins$remotedata$RemoteData$NotAsked; +var _user$project$MaintenanceFunding_View$cryptoView = F2( + function (maybeActiveCrypto, cryptoDisplay) { + var url = A2(_elm_lang$core$Basics_ops['++'], '/#funding/', cryptoDisplay.cryptoCode); + var activeClass = function () { + var _p0 = maybeActiveCrypto; + if (_p0.ctor === 'Nothing') { + return _user$project$Css_Admin$class( + {ctor: '[]'}); + } else { + return _elm_lang$core$Native_Utils.eq(_p0._0, cryptoDisplay.cryptoCode) ? _user$project$Css_Admin$class( + { + ctor: '::', + _0: _user$project$Css_Classes$Active, + _1: {ctor: '[]'} + }) : _user$project$Css_Admin$class( + {ctor: '[]'}); + } + }(); + return A2( + _elm_lang$html$Html$a, + { + ctor: '::', + _0: activeClass, + _1: { + ctor: '::', + _0: _user$project$Css_Admin$class( + { + ctor: '::', + _0: _user$project$Css_Classes$CryptoTab, + _1: {ctor: '[]'} + }), + _1: { + ctor: '::', + _0: _elm_lang$html$Html_Attributes$href(url), + _1: {ctor: '[]'} + } + } + }, + { + ctor: '::', + _0: _elm_lang$html$Html$text(cryptoDisplay.display), + _1: {ctor: '[]'} + }); + }); +var _user$project$MaintenanceFunding_View$cryptosView = F2( + function (cryptos, activeCrypto) { + return A2( + _elm_lang$html$Html$nav, + { + ctor: '::', + _0: _user$project$Css_Admin$class( + { + ctor: '::', + _0: _user$project$Css_Classes$CryptoTabs, + _1: {ctor: '[]'} + }), + _1: {ctor: '[]'} + }, + A2( + _elm_lang$core$List$map, + _user$project$MaintenanceFunding_View$cryptoView(activeCrypto), + cryptos)); + }); +var _user$project$MaintenanceFunding_View$qrCode = function (s) { + var resultQRCode = A2(_pablohirafuji$elm_qrcode$QRCode$toSvgWithECLevel, s, _pablohirafuji$elm_qrcode$QRCode_ECLevel$L); + var _p1 = resultQRCode; + if (_p1.ctor === 'Ok') { + return _p1._0; + } else { + return _elm_lang$html$Html$text( + _elm_lang$core$Basics$toString(_p1._0)); + } +}; +var _user$project$MaintenanceFunding_View$fundingView = function (subModel) { + return A2( + _elm_lang$html$Html$div, + {ctor: '[]'}, + { + ctor: '::', + _0: A2( + _user$project$MaintenanceFunding_View$cryptosView, + subModel.cryptoDisplays, + _elm_lang$core$Maybe$Just(subModel.cryptoCode)), + _1: { + ctor: '::', + _0: A2( + _elm_lang$html$Html$section, + { + ctor: '::', + _0: _user$project$Css_Admin$class( + { + ctor: '::', + _0: _user$project$Css_Classes$Container, + _1: {ctor: '[]'} + }), + _1: {ctor: '[]'} + }, + { + ctor: '::', + _0: A2( + _elm_lang$html$Html$div, + {ctor: '[]'}, + { + ctor: '::', + _0: _elm_lang$html$Html$text( + A2( + _elm_lang$core$Basics_ops['++'], + 'Deposit ', + A2(_elm_lang$core$Basics_ops['++'], subModel.cryptoCode, ' to this address.'))), + _1: {ctor: '[]'} + }), + _1: { + ctor: '::', + _0: A2( + _elm_lang$html$Html$div, + {ctor: '[]'}, + { + ctor: '::', + _0: _user$project$MaintenanceFunding_View$qrCode(subModel.fundingAddressUrl), + _1: {ctor: '[]'} + }), + _1: { + ctor: '::', + _0: A2( + _elm_lang$html$Html$div, + { + ctor: '::', + _0: _user$project$Css_Admin$class( + { + ctor: '::', + _0: _user$project$Css_Classes$CryptoAddress, + _1: {ctor: '[]'} + }), + _1: {ctor: '[]'} + }, + { + ctor: '::', + _0: _elm_lang$html$Html$text(subModel.fundingAddress), + _1: {ctor: '[]'} + }), + _1: { + ctor: '::', + _0: A2( + _elm_lang$html$Html$section, + { + ctor: '::', + _0: _user$project$Css_Admin$class( + { + ctor: '::', + _0: _user$project$Css_Classes$BalanceSection, + _1: {ctor: '[]'} + }), + _1: {ctor: '[]'} + }, + { + ctor: '::', + _0: A2( + _elm_lang$html$Html$h2, + {ctor: '[]'}, + { + ctor: '::', + _0: _elm_lang$html$Html$text('Balance'), + _1: {ctor: '[]'} + }), + _1: { + ctor: '::', + _0: A2( + _elm_lang$html$Html$div, + {ctor: '[]'}, + { + ctor: '::', + _0: _elm_lang$html$Html$text( + A2( + _elm_lang$core$Basics_ops['++'], + subModel.confirmedBalance, + A2( + _elm_lang$core$Basics_ops['++'], + ' ', + A2( + _elm_lang$core$Basics_ops['++'], + subModel.cryptoCode, + A2( + _elm_lang$core$Basics_ops['++'], + ' (', + A2(_elm_lang$core$Basics_ops['++'], subModel.pending, ' pending)')))))), + _1: {ctor: '[]'} + }), + _1: { + ctor: '::', + _0: A2( + _elm_lang$html$Html$div, + {ctor: '[]'}, + { + ctor: '::', + _0: _elm_lang$html$Html$text( + A2( + _elm_lang$core$Basics_ops['++'], + subModel.fiatConfirmedBalance, + A2( + _elm_lang$core$Basics_ops['++'], + ' ', + A2( + _elm_lang$core$Basics_ops['++'], + subModel.fiatCode, + A2( + _elm_lang$core$Basics_ops['++'], + ' (', + A2(_elm_lang$core$Basics_ops['++'], subModel.fiatPending, ' pending)')))))), + _1: {ctor: '[]'} + }), + _1: {ctor: '[]'} + } + } + }), + _1: {ctor: '[]'} + } + } + } + }), + _1: {ctor: '[]'} + } + }); +}; var _user$project$MaintenanceFunding_View$view = function (model) { - var _p0 = model; - switch (_p0.ctor) { + var _p2 = model; + switch (_p2.ctor) { case 'NotAsked': return A2( _elm_lang$html$Html$div, @@ -38416,18 +38706,11 @@ var _user$project$MaintenanceFunding_View$view = function (model) { { ctor: '::', _0: _elm_lang$html$Html$text( - _elm_lang$core$Basics$toString(_p0._0)), + _elm_lang$core$Basics$toString(_p2._0)), _1: {ctor: '[]'} }); default: - return A2( - _elm_lang$html$Html$div, - {ctor: '[]'}, - { - ctor: '::', - _0: _elm_lang$html$Html$text('Success!'), - _1: {ctor: '[]'} - }); + return _user$project$MaintenanceFunding_View$fundingView(_p2._0); } }; @@ -39108,7 +39391,7 @@ var _user$project$Main$Model = function (a) { var Elm = {}; Elm['Main'] = Elm['Main'] || {}; if (typeof _user$project$Main$main !== 'undefined') { - _user$project$Main$main(Elm['Main'], 'Main', {"types":{"unions":{"Selectize.Status":{"args":[],"tags":{"Editing":[],"Idle":[],"Blurred":[],"Cleared":[],"Initial":[]}},"BasicTypes.SavingStatus":{"args":[],"tags":{"Saving":[],"Editing":[],"NotSaving":[],"Saved":[]}},"Dict.LeafColor":{"args":[],"tags":{"LBBlack":[],"LBlack":[]}},"Account.SavingStatus":{"args":[],"tags":{"Saving":[],"Editing":[],"NotSaving":[],"Saved":[]}},"ConfigTypes.ConfigScope":{"args":[],"tags":{"Specific":[],"Both":[],"Global":[]}},"FieldSet.Types.Msg":{"args":[],"tags":{"Input":["String","String"]}},"ConfigTypes.FieldType":{"args":[],"tags":{"FieldOnOffType":[],"FieldPercentageType":[],"FieldLanguageType":[],"FieldCryptoCurrencyType":[],"FieldDecimalType":[],"FieldIntegerType":[],"FieldFiatCurrencyType":[],"FieldStringType":[],"FieldCountryType":[],"FieldAccountType":[]}},"Pair.Msg":{"args":[],"tags":{"SubmitName":[],"Load":["RemoteData.WebData String"],"InputName":["String"]}},"Transaction.Msg":{"args":[],"tags":{"Load":["Transaction.Model"]}},"Dict.Dict":{"args":["k","v"],"tags":{"RBNode_elm_builtin":["Dict.NColor","k","v","Dict.Dict k v","Dict.Dict k v"],"RBEmpty_elm_builtin":["Dict.LeafColor"]}},"ConfigTypes.DisplayTop":{"args":[],"tags":{"DisplayTopSolo":["String"],"DisplayTopLeader":["Int","String"],"DisplayTopNone":[]}},"Date.Date":{"args":[],"tags":{"Date":[]}},"Account.Msg":{"args":[],"tags":{"Load":["Account.Model"],"FieldSetMsg":["FieldSet.Types.Msg"],"Submit":[],"HideSaveIndication":[]}},"MaintenanceFunding.Types.Msg":{"args":[],"tags":{"Load":["MaintenanceFunding.Types.Model"]}},"Maybe.Maybe":{"args":["a"],"tags":{"Just":["a"],"Nothing":[]}},"RemoteData.RemoteData":{"args":["e","a"],"tags":{"NotAsked":[],"Success":["a"],"Loading":[],"Failure":["e"]}},"MaintenanceMachines.Types.Msg":{"args":[],"tags":{"Action":[],"Load":["MaintenanceMachines.Types.Model"],"InputCassette":["MaintenanceMachines.Types.Machine","MaintenanceMachines.Types.Position","String"],"Submit":["MaintenanceMachines.Types.MachineAction"],"HideSaveIndication":[]}},"ConfigTypes.Crypto":{"args":[],"tags":{"GlobalCrypto":[],"CryptoCode":["String"]}},"CoreTypes.Msg":{"args":[],"tags":{"WebSocketMsg":["String"],"ConfigMsg":["Config.Msg"],"LoadAccounts":["List ( String, String )"],"NewUrl":["String"],"Interval":[],"MaintenanceMachinesMsg":["MaintenanceMachines.Types.Msg"],"LoadStatus":["StatusTypes.WebStatus"],"UrlChange":["Navigation.Location"],"TransactionMsg":["Transaction.Msg"],"MaintenanceFundingMsg":["MaintenanceFunding.Types.Msg"],"AccountMsg":["Account.Msg"],"PairMsg":["Pair.Msg"]}},"Dict.NColor":{"args":[],"tags":{"BBlack":[],"Red":[],"NBlack":[],"Black":[]}},"FieldSet.Types.FieldValue":{"args":[],"tags":{"FieldInteger":["Int"],"FieldString":["String"],"FieldPassword":["FieldSet.Types.FieldPasswordType"]}},"ConfigTypes.Machine":{"args":[],"tags":{"MachineId":["String"],"GlobalMachine":[]}},"Config.Msg":{"args":[],"tags":{"Focus":["ConfigTypes.FieldLocator"],"BlurSelectize":["ConfigTypes.FieldLocator","Selectize.State"],"Remove":["ConfigTypes.FieldLocator","Selectize.State"],"Load":["Config.WebConfigGroup"],"Input":["ConfigTypes.FieldLocator","String"],"Blur":["ConfigTypes.FieldLocator"],"Add":["ConfigTypes.FieldLocator","String","Selectize.State"],"Submit":[],"SelectizeMsg":["ConfigTypes.FieldLocator","Selectize.State"],"FocusSelectize":["ConfigTypes.FieldLocator","Selectize.State"],"HideSaveIndication":[],"NoOp":[],"CryptoSwitch":["ConfigTypes.Crypto"]}},"TransactionTypes.Tx":{"args":[],"tags":{"CashInTx":["TransactionTypes.CashInTxRec"],"CashOutTx":["TransactionTypes.CashOutTxRec"]}},"ConfigTypes.FieldValidator":{"args":[],"tags":{"FieldRequired":[],"FieldMin":["Int"],"FieldMax":["Int"]}},"MaintenanceMachines.Types.MachineAction":{"args":[],"tags":{"RebootMachine":["MaintenanceMachines.Types.Machine"],"ResetCashOutBills":["MaintenanceMachines.Types.Machine"],"UnpairMachine":["MaintenanceMachines.Types.Machine"]}},"Http.Error":{"args":[],"tags":{"BadUrl":["String"],"NetworkError":[],"Timeout":[],"BadStatus":["Http.Response String"],"BadPayload":["String","Http.Response String"]}},"ConfigTypes.FieldValue":{"args":[],"tags":{"FieldIntegerValue":["Int"],"FieldDecimalValue":["Float"],"FieldCryptoCurrencyValue":["List String"],"FieldCountryValue":["String"],"FieldFiatCurrencyValue":["String"],"FieldStringValue":["String"],"FieldOnOffValue":["Bool"],"FieldAccountValue":["String"],"FieldLanguageValue":["List String"],"FieldPercentageValue":["Float"]}},"FieldSet.Types.FieldPasswordType":{"args":[],"tags":{"PasswordEmpty":[],"PasswordHidden":[],"Password":["String"]}},"MaintenanceMachines.Types.Position":{"args":[],"tags":{"Bottom":[],"Top":[]}}},"aliases":{"ConfigTypes.ConfigSchema":{"args":[],"type":"{ code : String , display : String , cryptoScope : ConfigTypes.ConfigScope , machineScope : ConfigTypes.ConfigScope , entries : List ConfigTypes.FieldDescriptor }"},"Selectize.State":{"args":[],"type":"{ boxPosition : Int, status : Selectize.Status, string : String }"},"TransactionTypes.CashInTxRec":{"args":[],"type":"{ id : String , machineName : String , toAddress : String , cryptoAtoms : Int , cryptoCode : String , fiat : Float , fiatCode : String , txHash : Maybe.Maybe String , phone : Maybe.Maybe String , error : Maybe.Maybe String , created : Date.Date }"},"RemoteData.WebData":{"args":["a"],"type":"RemoteData.RemoteData Http.Error a"},"ConfigTypes.FieldLocator":{"args":[],"type":"{ fieldScope : ConfigTypes.FieldScope , code : String , fieldType : ConfigTypes.FieldType , fieldClass : Maybe.Maybe String }"},"AccountTypes.Account":{"args":[],"type":"{ code : String , display : String , fields : List FieldSet.Types.Field }"},"Http.Response":{"args":["body"],"type":"{ url : String , status : { code : Int, message : String } , headers : Dict.Dict String String , body : body }"},"StatusTypes.WebStatus":{"args":[],"type":"RemoteData.WebData StatusTypes.StatusRec"},"MaintenanceMachines.Types.Machine":{"args":[],"type":"{ deviceId : String , name : String , cashbox : Int , cassette1 : Int , cassette2 : Int , paired : Bool , cashOut : Bool }"},"ConfigTypes.ConfigData":{"args":[],"type":"{ cryptoCurrencies : List ConfigTypes.CryptoDisplay , currencies : List ConfigTypes.DisplayRec , languages : List ConfigTypes.DisplayRec , countries : List ConfigTypes.DisplayRec , accounts : List ConfigTypes.AccountRec , machines : List ConfigTypes.MachineDisplay }"},"Account.Model":{"args":[],"type":"RemoteData.WebData Account.SubModel"},"MaintenanceFunding.Types.Model":{"args":[],"type":"RemoteData.WebData MaintenanceFunding.Types.SubModel"},"ConfigTypes.CryptoDisplay":{"args":[],"type":"{ crypto : ConfigTypes.Crypto, display : String }"},"Config.WebConfigGroup":{"args":[],"type":"RemoteData.WebData ConfigTypes.ConfigGroup"},"FieldSet.Types.Field":{"args":[],"type":"{ code : String , display : String , placeholder : String , required : Bool , value : FieldSet.Types.FieldValue , loadedValue : FieldSet.Types.FieldValue }"},"ConfigTypes.DisplayRec":{"args":[],"type":"{ code : String, display : String }"},"Account.SubModel":{"args":[],"type":"{ status : Account.SavingStatus, account : AccountTypes.Account }"},"MaintenanceFunding.Types.SubModel":{"args":[],"type":"{ cryptoCode : String , address : String , balance : BasicTypes.StringDecimal , fiatBalance : BasicTypes.StringDecimal , fiatCode : String }"},"ConfigTypes.FieldScope":{"args":[],"type":"{ crypto : ConfigTypes.Crypto, machine : ConfigTypes.Machine }"},"MaintenanceMachines.Types.Model":{"args":[],"type":"RemoteData.WebData MaintenanceMachines.Types.SubModel"},"ConfigTypes.ConfigGroup":{"args":[],"type":"{ schema : ConfigTypes.ConfigSchema , values : List ConfigTypes.Field , selectedCryptos : List String , data : ConfigTypes.ConfigData }"},"ConfigTypes.AccountRec":{"args":[],"type":"{ code : String , display : String , class : String , cryptos : Maybe.Maybe (List ConfigTypes.Crypto) }"},"Transaction.Model":{"args":[],"type":"RemoteData.WebData Transaction.Txs"},"ConfigTypes.Field":{"args":[],"type":"{ fieldLocator : ConfigTypes.FieldLocator , fieldValue : ConfigTypes.FieldValue , fieldEnabledIfAny : List String , fieldEnabledIfAll : List String , inScope : Bool }"},"Transaction.Txs":{"args":[],"type":"List TransactionTypes.Tx"},"ConfigTypes.MachineDisplay":{"args":[],"type":"{ machine : ConfigTypes.Machine, display : String }"},"StatusTypes.ServerRec":{"args":[],"type":"{ up : Bool , lastPing : Maybe.Maybe String , rates : List StatusTypes.Rate , machineStatus : String , wasConfigured : Bool }"},"MaintenanceMachines.Types.SubModel":{"args":[],"type":"{ status : BasicTypes.SavingStatus , machines : MaintenanceMachines.Types.Machines }"},"StatusTypes.Rate":{"args":[],"type":"{ crypto : String, bid : Float, ask : Float }"},"MaintenanceMachines.Types.Machines":{"args":[],"type":"List MaintenanceMachines.Types.Machine"},"TransactionTypes.CashOutTxRec":{"args":[],"type":"{ id : String , machineName : String , toAddress : String , cryptoAtoms : Int , cryptoCode : String , fiat : Float , fiatCode : String , status : String , dispense : Bool , notified : Bool , redeemed : Bool , phone : Maybe.Maybe String , error : Maybe.Maybe String , created : Date.Date , confirmed : Bool }"},"ConfigTypes.FieldDescriptor":{"args":[],"type":"{ code : String , cryptoScope : ConfigTypes.ConfigScope , machineScope : ConfigTypes.ConfigScope , displayTop : ConfigTypes.DisplayTop , displayBottom : String , displayCount : Maybe.Maybe Int , fieldType : ConfigTypes.FieldType , fieldValidation : List ConfigTypes.FieldValidator , fieldClass : Maybe.Maybe String , fieldEnabledIfAny : List String , fieldEnabledIfAll : List String , readOnly : Bool }"},"StatusTypes.StatusRec":{"args":[],"type":"{ server : StatusTypes.ServerRec, invalidConfigGroups : List String }"},"Navigation.Location":{"args":[],"type":"{ href : String , host : String , hostname : String , protocol : String , origin : String , port_ : String , pathname : String , search : String , hash : String , username : String , password : String }"},"BasicTypes.StringDecimal":{"args":[],"type":"{ integral : String, fractional : String }"}},"message":"CoreTypes.Msg"},"versions":{"elm":"0.18.0"}}); + _user$project$Main$main(Elm['Main'], 'Main', {"types":{"unions":{"Selectize.Status":{"args":[],"tags":{"Editing":[],"Idle":[],"Blurred":[],"Cleared":[],"Initial":[]}},"BasicTypes.SavingStatus":{"args":[],"tags":{"Saving":[],"Editing":[],"NotSaving":[],"Saved":[]}},"Dict.LeafColor":{"args":[],"tags":{"LBBlack":[],"LBlack":[]}},"Account.SavingStatus":{"args":[],"tags":{"Saving":[],"Editing":[],"NotSaving":[],"Saved":[]}},"ConfigTypes.ConfigScope":{"args":[],"tags":{"Specific":[],"Both":[],"Global":[]}},"FieldSet.Types.Msg":{"args":[],"tags":{"Input":["String","String"]}},"ConfigTypes.FieldType":{"args":[],"tags":{"FieldOnOffType":[],"FieldPercentageType":[],"FieldLanguageType":[],"FieldCryptoCurrencyType":[],"FieldDecimalType":[],"FieldIntegerType":[],"FieldFiatCurrencyType":[],"FieldStringType":[],"FieldCountryType":[],"FieldAccountType":[]}},"Pair.Msg":{"args":[],"tags":{"SubmitName":[],"Load":["RemoteData.WebData String"],"InputName":["String"]}},"Transaction.Msg":{"args":[],"tags":{"Load":["Transaction.Model"]}},"Dict.Dict":{"args":["k","v"],"tags":{"RBNode_elm_builtin":["Dict.NColor","k","v","Dict.Dict k v","Dict.Dict k v"],"RBEmpty_elm_builtin":["Dict.LeafColor"]}},"ConfigTypes.DisplayTop":{"args":[],"tags":{"DisplayTopSolo":["String"],"DisplayTopLeader":["Int","String"],"DisplayTopNone":[]}},"Date.Date":{"args":[],"tags":{"Date":[]}},"Account.Msg":{"args":[],"tags":{"Load":["Account.Model"],"FieldSetMsg":["FieldSet.Types.Msg"],"Submit":[],"HideSaveIndication":[]}},"MaintenanceFunding.Types.Msg":{"args":[],"tags":{"Load":["MaintenanceFunding.Types.Model"],"CryptoSwitch":["String"]}},"Maybe.Maybe":{"args":["a"],"tags":{"Just":["a"],"Nothing":[]}},"RemoteData.RemoteData":{"args":["e","a"],"tags":{"NotAsked":[],"Success":["a"],"Loading":[],"Failure":["e"]}},"MaintenanceMachines.Types.Msg":{"args":[],"tags":{"Action":[],"Load":["MaintenanceMachines.Types.Model"],"InputCassette":["MaintenanceMachines.Types.Machine","MaintenanceMachines.Types.Position","String"],"Submit":["MaintenanceMachines.Types.MachineAction"],"HideSaveIndication":[]}},"ConfigTypes.Crypto":{"args":[],"tags":{"GlobalCrypto":[],"CryptoCode":["String"]}},"CoreTypes.Msg":{"args":[],"tags":{"WebSocketMsg":["String"],"ConfigMsg":["Config.Msg"],"LoadAccounts":["List ( String, String )"],"NewUrl":["String"],"Interval":[],"MaintenanceMachinesMsg":["MaintenanceMachines.Types.Msg"],"LoadStatus":["StatusTypes.WebStatus"],"UrlChange":["Navigation.Location"],"TransactionMsg":["Transaction.Msg"],"MaintenanceFundingMsg":["MaintenanceFunding.Types.Msg"],"AccountMsg":["Account.Msg"],"PairMsg":["Pair.Msg"]}},"Dict.NColor":{"args":[],"tags":{"BBlack":[],"Red":[],"NBlack":[],"Black":[]}},"FieldSet.Types.FieldValue":{"args":[],"tags":{"FieldInteger":["Int"],"FieldString":["String"],"FieldPassword":["FieldSet.Types.FieldPasswordType"]}},"ConfigTypes.Machine":{"args":[],"tags":{"MachineId":["String"],"GlobalMachine":[]}},"Config.Msg":{"args":[],"tags":{"Focus":["ConfigTypes.FieldLocator"],"BlurSelectize":["ConfigTypes.FieldLocator","Selectize.State"],"Remove":["ConfigTypes.FieldLocator","Selectize.State"],"Load":["Config.WebConfigGroup"],"Input":["ConfigTypes.FieldLocator","String"],"Blur":["ConfigTypes.FieldLocator"],"Add":["ConfigTypes.FieldLocator","String","Selectize.State"],"Submit":[],"SelectizeMsg":["ConfigTypes.FieldLocator","Selectize.State"],"FocusSelectize":["ConfigTypes.FieldLocator","Selectize.State"],"HideSaveIndication":[],"NoOp":[],"CryptoSwitch":["ConfigTypes.Crypto"]}},"TransactionTypes.Tx":{"args":[],"tags":{"CashInTx":["TransactionTypes.CashInTxRec"],"CashOutTx":["TransactionTypes.CashOutTxRec"]}},"ConfigTypes.FieldValidator":{"args":[],"tags":{"FieldRequired":[],"FieldMin":["Int"],"FieldMax":["Int"]}},"MaintenanceMachines.Types.MachineAction":{"args":[],"tags":{"RebootMachine":["MaintenanceMachines.Types.Machine"],"ResetCashOutBills":["MaintenanceMachines.Types.Machine"],"UnpairMachine":["MaintenanceMachines.Types.Machine"]}},"Http.Error":{"args":[],"tags":{"BadUrl":["String"],"NetworkError":[],"Timeout":[],"BadStatus":["Http.Response String"],"BadPayload":["String","Http.Response String"]}},"ConfigTypes.FieldValue":{"args":[],"tags":{"FieldIntegerValue":["Int"],"FieldDecimalValue":["Float"],"FieldCryptoCurrencyValue":["List String"],"FieldCountryValue":["String"],"FieldFiatCurrencyValue":["String"],"FieldStringValue":["String"],"FieldOnOffValue":["Bool"],"FieldAccountValue":["String"],"FieldLanguageValue":["List String"],"FieldPercentageValue":["Float"]}},"FieldSet.Types.FieldPasswordType":{"args":[],"tags":{"PasswordEmpty":[],"PasswordHidden":[],"Password":["String"]}},"MaintenanceMachines.Types.Position":{"args":[],"tags":{"Bottom":[],"Top":[]}}},"aliases":{"ConfigTypes.ConfigSchema":{"args":[],"type":"{ code : String , display : String , cryptoScope : ConfigTypes.ConfigScope , machineScope : ConfigTypes.ConfigScope , entries : List ConfigTypes.FieldDescriptor }"},"Selectize.State":{"args":[],"type":"{ boxPosition : Int, status : Selectize.Status, string : String }"},"TransactionTypes.CashInTxRec":{"args":[],"type":"{ id : String , machineName : String , toAddress : String , cryptoAtoms : Int , cryptoCode : String , fiat : Float , fiatCode : String , txHash : Maybe.Maybe String , phone : Maybe.Maybe String , error : Maybe.Maybe String , created : Date.Date }"},"RemoteData.WebData":{"args":["a"],"type":"RemoteData.RemoteData Http.Error a"},"ConfigTypes.FieldLocator":{"args":[],"type":"{ fieldScope : ConfigTypes.FieldScope , code : String , fieldType : ConfigTypes.FieldType , fieldClass : Maybe.Maybe String }"},"AccountTypes.Account":{"args":[],"type":"{ code : String , display : String , fields : List FieldSet.Types.Field }"},"Http.Response":{"args":["body"],"type":"{ url : String , status : { code : Int, message : String } , headers : Dict.Dict String String , body : body }"},"StatusTypes.WebStatus":{"args":[],"type":"RemoteData.WebData StatusTypes.StatusRec"},"MaintenanceMachines.Types.Machine":{"args":[],"type":"{ deviceId : String , name : String , cashbox : Int , cassette1 : Int , cassette2 : Int , paired : Bool , cashOut : Bool }"},"ConfigTypes.ConfigData":{"args":[],"type":"{ cryptoCurrencies : List ConfigTypes.CryptoDisplay , currencies : List ConfigTypes.DisplayRec , languages : List ConfigTypes.DisplayRec , countries : List ConfigTypes.DisplayRec , accounts : List ConfigTypes.AccountRec , machines : List ConfigTypes.MachineDisplay }"},"Account.Model":{"args":[],"type":"RemoteData.WebData Account.SubModel"},"MaintenanceFunding.Types.Model":{"args":[],"type":"RemoteData.WebData MaintenanceFunding.Types.SubModel"},"MaintenanceFunding.Types.CryptoDisplay":{"args":[],"type":"{ cryptoCode : String, display : String }"},"ConfigTypes.CryptoDisplay":{"args":[],"type":"{ crypto : ConfigTypes.Crypto, display : String }"},"Config.WebConfigGroup":{"args":[],"type":"RemoteData.WebData ConfigTypes.ConfigGroup"},"FieldSet.Types.Field":{"args":[],"type":"{ code : String , display : String , placeholder : String , required : Bool , value : FieldSet.Types.FieldValue , loadedValue : FieldSet.Types.FieldValue }"},"ConfigTypes.DisplayRec":{"args":[],"type":"{ code : String, display : String }"},"Account.SubModel":{"args":[],"type":"{ status : Account.SavingStatus, account : AccountTypes.Account }"},"MaintenanceFunding.Types.SubModel":{"args":[],"type":"{ cryptoCode : String , cryptoDisplays : List MaintenanceFunding.Types.CryptoDisplay , fundingAddress : String , fundingAddressUrl : String , confirmedBalance : String , pending : String , fiatConfirmedBalance : String , fiatPending : String , fiatCode : String }"},"ConfigTypes.FieldScope":{"args":[],"type":"{ crypto : ConfigTypes.Crypto, machine : ConfigTypes.Machine }"},"MaintenanceMachines.Types.Model":{"args":[],"type":"RemoteData.WebData MaintenanceMachines.Types.SubModel"},"ConfigTypes.ConfigGroup":{"args":[],"type":"{ schema : ConfigTypes.ConfigSchema , values : List ConfigTypes.Field , selectedCryptos : List String , data : ConfigTypes.ConfigData }"},"ConfigTypes.AccountRec":{"args":[],"type":"{ code : String , display : String , class : String , cryptos : Maybe.Maybe (List ConfigTypes.Crypto) }"},"Transaction.Model":{"args":[],"type":"RemoteData.WebData Transaction.Txs"},"ConfigTypes.Field":{"args":[],"type":"{ fieldLocator : ConfigTypes.FieldLocator , fieldValue : ConfigTypes.FieldValue , fieldEnabledIfAny : List String , fieldEnabledIfAll : List String , inScope : Bool }"},"Transaction.Txs":{"args":[],"type":"List TransactionTypes.Tx"},"ConfigTypes.MachineDisplay":{"args":[],"type":"{ machine : ConfigTypes.Machine, display : String }"},"StatusTypes.ServerRec":{"args":[],"type":"{ up : Bool , lastPing : Maybe.Maybe String , rates : List StatusTypes.Rate , machineStatus : String , wasConfigured : Bool }"},"MaintenanceMachines.Types.SubModel":{"args":[],"type":"{ status : BasicTypes.SavingStatus , machines : MaintenanceMachines.Types.Machines }"},"StatusTypes.Rate":{"args":[],"type":"{ crypto : String, bid : Float, ask : Float }"},"MaintenanceMachines.Types.Machines":{"args":[],"type":"List MaintenanceMachines.Types.Machine"},"TransactionTypes.CashOutTxRec":{"args":[],"type":"{ id : String , machineName : String , toAddress : String , cryptoAtoms : Int , cryptoCode : String , fiat : Float , fiatCode : String , status : String , dispense : Bool , notified : Bool , redeemed : Bool , phone : Maybe.Maybe String , error : Maybe.Maybe String , created : Date.Date , confirmed : Bool }"},"ConfigTypes.FieldDescriptor":{"args":[],"type":"{ code : String , cryptoScope : ConfigTypes.ConfigScope , machineScope : ConfigTypes.ConfigScope , displayTop : ConfigTypes.DisplayTop , displayBottom : String , displayCount : Maybe.Maybe Int , fieldType : ConfigTypes.FieldType , fieldValidation : List ConfigTypes.FieldValidator , fieldClass : Maybe.Maybe String , fieldEnabledIfAny : List String , fieldEnabledIfAll : List String , readOnly : Bool }"},"StatusTypes.StatusRec":{"args":[],"type":"{ server : StatusTypes.ServerRec, invalidConfigGroups : List String }"},"Navigation.Location":{"args":[],"type":"{ href : String , host : String , hostname : String , protocol : String , origin : String , port_ : String , pathname : String , search : String , hash : String , username : String , password : String }"}},"message":"CoreTypes.Msg"},"versions":{"elm":"0.18.0"}}); } if (typeof define === "function" && define['amd']) diff --git a/public/styles.css b/public/styles.css index f4cd69b2..3fb32497 100644 --- a/public/styles.css +++ b/public/styles.css @@ -117,36 +117,57 @@ p { border-radius: 5px; } +.lamassuAdminContainer { + padding: 30px; + background-color: #f6f6f4; + border-radius: 0px 5px 5px 5px; + width: 30em; +} + +.lamassuAdminCryptoAddress { + font-family: Inconsolata, monospace; +} + +.lamassuAdminBalanceSection { + margin-top: 2em; +} + +.lamassuAdminBalanceSection h2 { + font-size: 1.2em; + margin-bottom: 0.2em; +} + .lamassuAdminCryptoTabs { display: flex; } -.lamassuAdminCryptoTabs > div { +.lamassuAdminCryptoTabs > .lamassuAdminCryptoTab { padding: 10px 15px; color: #5f5f56; font-weight: bold; cursor: pointer; background-color: #E6E6E3; + text-decoration: none; } -.lamassuAdminCryptoTabs > div:hover { +.lamassuAdminCryptoTabs > .lamassuAdminCryptoTab:hover { background-color: #fcfcfa; } -.lamassuAdminCryptoTabs > div:active { +.lamassuAdminCryptoTabs > .lamassuAdminCryptoTab:active { color: #5f5f56; } -.lamassuAdminCryptoTabs > div.lamassuAdminActive { +.lamassuAdminCryptoTabs > .lamassuAdminCryptoTab.lamassuAdminActive { color: #5f5f56; background-color: #f6f6f4; } -.lamassuAdminCryptoTabs > div:first-child { +.lamassuAdminCryptoTabs > .lamassuAdminCryptoTab:first-child { border-radius: 5px 0px 0px 0px; } -.lamassuAdminCryptoTabs > div:last-child { +.lamassuAdminCryptoTabs > .lamassuAdminCryptoTab:last-child { border-radius: 0px 5px 0px 0px; } diff --git a/yarn.lock b/yarn.lock index f332a212..7b75a44f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -916,7 +916,7 @@ bignumber.js@^2.0.3, "bignumber.js@git+https://github.com/debris/bignumber.js.gi version "2.0.7" resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" -bignumber.js@^4.0.0, bignumber.js@^4.0.1, bignumber.js@~4.0.2: +bignumber.js@^4.0.0, bignumber.js@^4.0.2, bignumber.js@~4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-4.0.2.tgz#2d1dc37ee5968867ecea90b6da4d16e68608d21d" @@ -2004,9 +2004,9 @@ ethereumjs-tx@^1.3.0: ethereum-common "^0.0.18" ethereumjs-util "^5.0.0" -ethereumjs-util@^4.3.0, ethereumjs-util@^4.4.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" +ethereumjs-util@^4.3.0, ethereumjs-util@^4.4.0, ethereumjs-util@~4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.4.1.tgz#6316bfbc8a01c8767a78620928ed79ef424c3f92" dependencies: bn.js "^4.8.0" create-hash "^1.1.2" @@ -2027,16 +2027,6 @@ ethereumjs-util@^5.0.0: rlp "^2.0.0" secp256k1 "^3.0.1" -ethereumjs-util@~4.4.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.4.1.tgz#6316bfbc8a01c8767a78620928ed79ef424c3f92" - dependencies: - bn.js "^4.8.0" - create-hash "^1.1.2" - keccakjs "^0.2.0" - rlp "^2.0.0" - secp256k1 "^3.0.1" - ethereumjs-wallet@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.0.tgz#82763b1697ee7a796be7155da9dfb49b2f98cfdb" @@ -2277,11 +2267,7 @@ form-data@^2.1.1, form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" -formidable@^1.0.17: - version "1.0.17" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.0.17.tgz#ef5491490f9433b705faa77249c99029ae348559" - -formidable@^1.1.1: +formidable@^1.0.17, formidable@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.1.1.tgz#96b8886f7c3c3508b932d6bd70c4d3a88f35f1a9"