This commit is contained in:
Neal Conner 2017-11-11 17:16:28 -05:00 committed by Josh Harvey
parent 28979e475c
commit 548d285e5b
20 changed files with 216 additions and 227 deletions

View file

@ -150,7 +150,7 @@ const mapLanguage = lang => {
const supportedLanguages = languageRec.supported
const languages = supportedLanguages.map(mapLanguage).filter(r => r)
const ALL_CRYPTOS = ['BTC', 'ETH', 'LTC', 'DASH', 'ZEC']
const ALL_CRYPTOS = ['BTC', 'ETH', 'LTC', 'DASH', 'ZEC', 'BCH']
function fetchData () {
return machineLoader.getMachineNames()
@ -161,13 +161,14 @@ function fetchData () {
{crypto: 'ETH', display: 'Ethereum'},
{crypto: 'LTC', display: 'Litecoin'},
{crypto: 'DASH', display: 'Dash'},
{crypto: 'ZEC', display: 'Zcash'}
{crypto: 'ZEC', display: 'Zcash'},
{crypto: 'BCH', display: 'BCH'}
],
languages: languages,
countries,
accounts: [
{code: 'bitpay', display: 'Bitpay', class: 'ticker', cryptos: ['BTC']},
{code: 'kraken', display: 'Kraken', class: 'ticker', cryptos: ['BTC', 'ETH', 'LTC', 'DASH', 'ZEC']},
{code: 'kraken', display: 'Kraken', class: 'ticker', cryptos: ['BTC', 'ETH', 'LTC', 'DASH', 'ZEC', 'BCH']},
{code: 'bitstamp', display: 'Bitstamp', class: 'ticker', cryptos: ['BTC', 'LTC']},
{code: 'coinbase', display: 'Coinbase', class: 'ticker', cryptos: ['BTC', 'ETH', 'LTC']},
{code: 'mock-ticker', display: 'Mock ticker', class: 'ticker', cryptos: ALL_CRYPTOS},
@ -176,9 +177,10 @@ function fetchData () {
{code: 'zcashd', display: 'zcashd', class: 'wallet', cryptos: ['ZEC']},
{code: 'litecoind', display: 'litecoind', class: 'wallet', cryptos: ['LTC']},
{code: 'dashd', display: 'dashd', class: 'wallet', cryptos: ['DASH']},
{code: 'bitcoincashd', display: 'bitcoincashd', class: 'wallet', cryptos: ['BCH']},
{code: 'bitgo', display: 'BitGo', class: 'wallet', cryptos: ['BTC']},
{code: 'bitstamp', display: 'Bitstamp', class: 'exchange', cryptos: ['BTC', 'LTC']},
{code: 'kraken', display: 'Kraken', class: 'exchange', cryptos: ['BTC', 'ETH', 'LTC', 'DASH', 'ZEC']},
{code: 'kraken', display: 'Kraken', class: 'exchange', cryptos: ['BTC', 'ETH', 'LTC', 'DASH', 'ZEC', 'BCH']},
{code: 'mock-wallet', display: 'Mock wallet', class: 'wallet', cryptos: ALL_CRYPTOS},
{code: 'no-exchange', display: 'No exchange', class: 'exchange', cryptos: ALL_CRYPTOS},
{code: 'mock-exchange', display: 'Mock exchange', class: 'exchange', cryptos: ALL_CRYPTOS},
@ -186,10 +188,10 @@ function fetchData () {
{code: 'mock-id-verify', display: 'Mock ID verifier', class: 'idVerifier'},
{code: 'twilio', display: 'Twilio', class: 'sms'},
{code: 'mailjet', display: 'Mailjet', class: 'email'},
{code: 'all-zero-conf', display: 'Always 0-conf', class: 'zeroConf', cryptos: ['BTC', 'ZEC', 'LTC', 'DASH']},
{code: 'all-zero-conf', display: 'Always 0-conf', class: 'zeroConf', cryptos: ['BTC', 'ZEC', 'LTC', 'DASH', 'BCH']},
{code: 'no-zero-conf', display: 'Always 1-conf', class: 'zeroConf', cryptos: ALL_CRYPTOS},
{code: 'blockcypher', display: 'Blockcypher', class: 'zeroConf', cryptos: ['BTC']},
{code: 'mock-zero-conf', display: 'Mock 0-conf', class: 'zeroConf', cryptos: ['BTC', 'ZEC', 'LTC', 'DASH']}
{code: 'mock-zero-conf', display: 'Mock 0-conf', class: 'zeroConf', cryptos: ['BTC', 'ZEC', 'LTC', 'DASH', 'BCH']}
],
machines: machineList.map(machine => ({machine: machine.deviceId, display: machine.name}))
}))

View file

@ -0,0 +1,31 @@
const path = require('path')
const coinUtils = require('../coin-utils')
const common = require('./common')
module.exports = {setup}
const coinRec = coinUtils.getCryptoCurrency('BCH')
function setup (dataDir) {
common.firewall([coinRec.defaultPort])
const config = buildConfig()
common.writeFile(path.resolve(dataDir, coinRec.configFile), config)
const cmd = `/usr/local/bin/${coinRec.daemon} -datadir=${dataDir} -conf=${dataDir}/bitcoincash.conf`
common.writeSupervisorConfig(coinRec, cmd)
}
function buildConfig () {
return `rpcuser=lamassuserver
rpcpassword=${common.randomPass()}
dbcache=500
server=1
connections=40
keypool=10000
prune=4000
daemon=0
bind=0.0.0.0:8334
rpcport=8335
`
}

View file

@ -3,6 +3,9 @@ const os = require('os')
const path = require('path')
const cp = require('child_process')
const fs = require('fs')
const _ = require('lodash/fp')
const logger = require('console-log-level')({level: 'info'})
module.exports = {
@ -18,8 +21,8 @@ module.exports = {
const BINARIES = {
BTC: {
url: 'https://bitcoin.org/bin/bitcoin-core-0.14.2/bitcoin-0.14.2-x86_64-linux-gnu.tar.gz',
dir: 'bitcoin-0.14.2/bin'
url: 'https://bitcoin.org/bin/bitcoin-core-0.15.1/bitcoin-0.15.1-x86_64-linux-gnu.tar.gz',
dir: 'bitcoin-0.15.1/bin'
},
ETH: {
url: 'https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.7.2-1db4ecdc.tar.gz',
@ -30,12 +33,17 @@ const BINARIES = {
dir: 'zcash-1.0.12/bin'
},
DASH: {
url: 'https://www.dash.org/binaries/dashcore-0.12.1.5-linux64.tar.gz',
dir: 'dashcore-0.12.1/bin'
url: 'https://github.com/dashpay/dash/releases/download/v0.12.2.1/dashcore-0.12.2.1-linux64.tar.gz',
dir: 'dashcore-0.12.2/bin'
},
LTC: {
url: 'https://download.litecoin.org/litecoin-0.14.2/linux/litecoin-0.14.2-x86_64-linux-gnu.tar.gz',
dir: 'litecoin-0.14.2/bin'
},
BCH: {
url: 'https://download.bitcoinabc.org/0.16.1/linux/bitcoin-abc-0.16.1-x86_64-linux-gnu.tar.gz',
dir: 'bitcoin-abc-0.16.1/bin',
files: [['bitcoind', 'bitcoincashd'], ['bitcoin-cli', 'bitcoincash-cli']]
}
}
@ -90,7 +98,15 @@ function fetchAndInstall (coinRec) {
es(`wget -q ${url}`)
es(`tar -xzf ${downloadFile}`)
es(`sudo cp ${binDir}/* /usr/local/bin`)
if (_.isEmpty(binaries.files)) {
es(`sudo cp ${binDir}/* /usr/local/bin`)
return
}
_.forEach(([source, target]) => {
es(`sudo cp ${binDir}/${source} /usr/local/bin/${target}`)
}, binaries.files)
}
function writeFile (path, content) {

View file

@ -21,7 +21,8 @@ const PLUGINS = {
LTC: require('./litecoin.js'),
ETH: require('./ethereum.js'),
DASH: require('./dash.js'),
ZEC: require('./zcash.js')
ZEC: require('./zcash.js'),
BCH: require('./bitcoincash.js')
}
module.exports = {run}

View file

@ -49,6 +49,15 @@ const CRYPTO_CURRENCIES = [
daemon: 'zcashd',
defaultPort: 8232,
unitScale: 8
},
{
cryptoCode: 'BCH',
display: 'BCH',
code: 'bitcoincash',
configFile: 'bitcoincash.conf',
daemon: 'bitcoincashd',
defaultPort: 8335,
unitScale: 8
}
]
@ -71,6 +80,7 @@ function buildUrl (cryptoCode, address) {
case 'ZEC': return `zcash:${address}`
case 'LTC': return `litecoin:${address}`
case 'DASH': return `dash:${address}`
case 'BCH': return `bitcoincash:${address}`
default: throw new Error(`Unsupported crypto: ${cryptoCode}`)
}
}

View file

@ -20,6 +20,10 @@ const PAIRS = {
DASH: {
USD: 'DASHUSD',
EUR: 'DASHEUR'
},
BCH: {
USD: 'BCHUSD',
EUR: 'BCHEUR'
}
}

View file

@ -0,0 +1,136 @@
const jsonRpc = require('../../common/json-rpc')
const bs58check = require('bs58check')
const BN = require('../../../bn')
const E = require('../../../error')
const coinUtils = require('../../../coin-utils')
const cryptoRec = coinUtils.getCryptoCurrency('BCH')
const configPath = coinUtils.configPath(cryptoRec)
const unitScale = cryptoRec.unitScale
const config = jsonRpc.parseConf(configPath)
const rpcConfig = {
username: config.rpcuser,
password: config.rpcpassword,
port: config.rpcport || cryptoRec.defaultPort
}
function fetch (method, params) {
return jsonRpc.fetch(rpcConfig, method, params)
}
function checkCryptoCode (cryptoCode) {
if (cryptoCode !== 'BCH') return Promise.reject(new Error('Unsupported crypto: ' + cryptoCode))
return Promise.resolve()
}
function accountBalance (account, cryptoCode, confirmations) {
return checkCryptoCode(cryptoCode)
.then(() => fetch('getbalance', ['', confirmations]))
.then(r => BN(r).shift(unitScale).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 accountBalance(account, cryptoCode, 1)
}
function bchToBtcVersion (version) {
if (version === 0x1c) return 0x00
if (version === 0x28) return 0x05
return version
}
// Bitcoin-ABC only accepts BTC style addresses at this point,
// so we need to convert
function bchToBtcAddress (address) {
const buf = bs58check.decode(address)
const version = buf[0]
buf[0] = bchToBtcVersion(version)
return bs58check.encode(buf)
}
function sendCoins (account, address, cryptoAtoms, cryptoCode) {
const coins = cryptoAtoms.shift(-unitScale).toFixed(8)
const btcAddress = bchToBtcAddress(address)
return checkCryptoCode(cryptoCode)
.then(() => fetch('sendtoaddress', [btcAddress, coins]))
.catch(err => {
if (err.code === -6) throw new E.InsufficientFundsError()
throw err
})
}
function newAddress (account, info) {
return checkCryptoCode(info.cryptoCode)
.then(() => fetch('getnewaddress'))
}
function addressBalance (address, confs) {
const btcAddress = bchToBtcAddress(address)
return fetch('getreceivedbyaddress', [btcAddress, confs])
.then(r => BN(r).shift(unitScale).round())
}
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 checkCryptoCode(cryptoCode)
.then(() => confirmedBalance(toAddress, cryptoCode))
.then(confirmed => {
if (confirmed.gte(requested)) return {status: 'confirmed'}
return pendingBalance(toAddress, cryptoCode)
.then(pending => {
if (pending.gte(requested)) return {status: 'authorized'}
if (pending.gt(0)) return {status: 'insufficientFunds'}
return {status: 'notSeen'}
})
})
}
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
}))
}
function cryptoNetwork (account, cryptoCode) {
return checkCryptoCode(cryptoCode)
.then(() => parseInt(rpcConfig.port, 10) === 18332 ? 'test' : 'main')
}
module.exports = {
balance,
sendCoins,
newAddress,
getStatus,
newFunding,
cryptoNetwork
}