add blockcypher [WIP]

This commit is contained in:
Josh Harvey 2017-05-20 18:08:09 +03:00
parent b28c99aabb
commit 23458b6b56
10 changed files with 133 additions and 17 deletions

View file

@ -70,7 +70,8 @@
"fields": [ "fields": [
"ticker", "ticker",
"wallet", "wallet",
"exchange" "exchange",
"zeroConf"
] ]
}, },
{ {
@ -176,7 +177,7 @@
"displayBottom": "Limit", "displayBottom": "Limit",
"fieldType": "integer", "fieldType": "integer",
"fieldClass": "fiat", "fieldClass": "fiat",
"cryptoScope": "both", "cryptoScope": "global",
"machineScope": "both", "machineScope": "both",
"enabledIf": [ "enabledIf": [
"cashOutEnabled" "cashOutEnabled"
@ -213,6 +214,14 @@
"fieldValidation": [], "fieldValidation": [],
"default": "no-exchange" "default": "no-exchange"
}, },
{
"code": "zeroConf",
"displayBottom": "Zero Conf",
"fieldType": "account",
"fieldClass": "zeroConf",
"fieldValidation": [],
"default": "all-zero-conf"
},
{ {
"code": "fiatCurrency", "code": "fiatCurrency",
"displayBottom": "Fiat Currency", "displayBottom": "Fiat Currency",

View file

@ -153,7 +153,10 @@ function fetchData () {
{code: 'mock-sms', display: 'Mock SMS', class: 'sms'}, {code: 'mock-sms', display: 'Mock SMS', class: 'sms'},
{code: 'mock-id-verify', display: 'Mock ID verifier', class: 'idVerifier'}, {code: 'mock-id-verify', display: 'Mock ID verifier', class: 'idVerifier'},
{code: 'twilio', display: 'Twilio', class: 'sms'}, {code: 'twilio', display: 'Twilio', class: 'sms'},
{code: 'mailjet', display: 'Mailjet', class: 'email'} {code: 'mailjet', display: 'Mailjet', class: 'email'},
{code: 'all-zero-conf', display: 'All pass', class: 'zeroConf'},
{code: 'blockcypher', display: 'Blockcypher', class: 'zeroConf'},
{code: 'mock-zero-conf', display: 'Mock 0-conf', class: 'zeroConf'}
], ],
machines: machineList.map(machine => ({machine: machine.deviceId, display: machine.name})) machines: machineList.map(machine => ({machine: machine.deviceId, display: machine.name}))
})) }))

View file

@ -8,7 +8,8 @@ const pluginCodes = {
EXCHANGE: 'exchange', EXCHANGE: 'exchange',
WALLET: 'wallet', WALLET: 'wallet',
SMS: 'sms', SMS: 'sms',
EMAIL: 'email' EMAIL: 'email',
ZERO_CONF: 'zero-conf'
} }
module.exports = _.assign({load, loadSchemas}, pluginCodes) module.exports = _.assign({load, loadSchemas}, pluginCodes)

View file

@ -231,7 +231,7 @@ function plugins (settings, deviceId) {
} }
function getStatus (tx) { function getStatus (tx) {
return wallet.getStatus(settings, tx.toAddress, tx.cryptoAtoms, tx.cryptoCode) return wallet.getStatus(settings, tx.toAddress, tx.cryptoAtoms, tx.cryptoCode, tx.fiat, deviceId)
} }
function newAddress (tx) { function newAddress (tx) {
@ -471,6 +471,8 @@ function plugins (settings, deviceId) {
const config = configManager.machineScoped(_deviceId, settings.config) const config = configManager.machineScoped(_deviceId, settings.config)
const cryptoCodes = config.cryptoCurrencies const cryptoCodes = config.cryptoCurrencies
const fiatCode = config.fiatCurrency const fiatCode = config.fiatCurrency
console.log('DEBUG103: %j', cryptoCodes)
const fiatBalancePromises = cryptoCodes.map(c => fiatBalance(fiatCode, c)) const fiatBalancePromises = cryptoCodes.map(c => fiatBalance(fiatCode, c))
return Promise.all(fiatBalancePromises) return Promise.all(fiatBalancePromises)

View file

@ -0,0 +1,28 @@
const qs = require('querystring')
const axios = require('axios')
const _ = require('lodash/fp')
module.exports = {authorize}
function authorize (account, toAddress, cryptoAtoms, cryptoCode) {
return Promise.resolve()
.then(() => {
if (cryptoCode !== 'BTC') throw new Error('Unsupported crypto: ' + cryptoCode)
const query = qs.stringify({
token: account.token,
includeConfidence: true,
confidence: account.confidence
})
const url = `https://api.blockcypher.com/v1/btc/main/addrs/${toAddress}?${query}`
return axios.get(url)
.then(r => {
const data = r.data
const authorizedValue = _.sumBy('value', data.txrefs)
return cryptoAtoms.lte(authorizedValue)
})
})
}

View file

@ -0,0 +1,11 @@
module.exports = {authorize}
function authorize (account, toAddress, cryptoAtoms, cryptoCode) {
return Promise.resolve()
.then(() => {
if (cryptoCode !== 'BTC') throw new Error('Unsupported crypto: ' + cryptoCode)
const authorizedValue = 1e5 * 10
return cryptoAtoms.lte(authorizedValue)
})
}

View file

@ -26,6 +26,7 @@ function computeSeed (masterSeed) {
} }
function fetchWallet (settings, cryptoCode) { function fetchWallet (settings, cryptoCode) {
console.log('DEBUG102')
return fs.readFile(options.seedPath, 'utf8') return fs.readFile(options.seedPath, 'utf8')
.then(hex => { .then(hex => {
const masterSeed = Buffer.from(hex.trim(), 'hex') const masterSeed = Buffer.from(hex.trim(), 'hex')
@ -66,11 +67,39 @@ function newAddress (settings, info) {
.then(r => r.wallet.newAddress(r.account, info)) .then(r => r.wallet.newAddress(r.account, info))
} }
function getStatus (settings, toAddress, cryptoAtoms, cryptoCode) { function getWalletStatus (settings, toAddress, cryptoAtoms, cryptoCode) {
return fetchWallet(settings, cryptoCode) return fetchWallet(settings, cryptoCode)
.then(r => r.wallet.getStatus(r.account, toAddress, cryptoAtoms, cryptoCode)) .then(r => r.wallet.getStatus(r.account, toAddress, cryptoAtoms, cryptoCode))
} }
function authorizeZeroConf (settings, toAddress, cryptoAtoms, cryptoCode, fiat, machineId) {
const cryptoConfig = configManager.cryptoScoped(cryptoCode, settings.config)
const machineConfig = configManager.machineScoped(machineId, settings.config)
const plugin = cryptoConfig.zeroConf
const zeroConfLimit = machineConfig.zeroConfLimit
if (fiat.gt(zeroConfLimit)) return Promise.resolve(false)
if (cryptoCode !== 'BTC' || plugin === 'all-zero-conf') return Promise.resolve(true)
const zeroConf = ph.load(ph.ZERO_CONF, plugin)
const account = settings.accounts[plugin]
return zeroConf.authorize(account, toAddress, cryptoAtoms, cryptoCode)
}
function getStatus (settings, toAddress, cryptoAtoms, cryptoCode, fiat, machineId) {
const promises = [
getWalletStatus(settings, toAddress, cryptoAtoms, cryptoCode),
authorizeZeroConf(settings, toAddress, cryptoAtoms, cryptoCode, fiat, machineId)
]
return Promise.all(promises)
.then(([status, isAuthorized]) => {
if (status === 'authorized') return isAuthorized ? 'authorized' : 'published'
return status
})
}
function sweep (settings, cryptoCode, hdIndex) { function sweep (settings, cryptoCode, hdIndex) {
return fetchWallet(settings, cryptoCode) return fetchWallet(settings, cryptoCode)
.then(r => r.wallet.sweep(r.account, cryptoCode, hdIndex)) .then(r => r.wallet.sweep(r.account, cryptoCode, hdIndex))

View file

@ -1,8 +1,12 @@
var db = require('./db')
exports.up = function(next){ exports.up = function (next) {
next(); var sql = [
}; 'alter table cash_out_txs add column error_code text'
]
db.multi(sql, next)
}
exports.down = function(next){ exports.down = function (next) {
next(); next()
}; }

View file

@ -34010,19 +34010,28 @@ var _user$project$NavBar$view = F2(
ctor: '::', ctor: '::',
_0: { _0: {
ctor: '_Tuple3', ctor: '_Tuple3',
_0: 'Twilio', _0: 'Blockcypher',
_1: _user$project$CoreTypes$AccountRoute('twilio'), _1: _user$project$CoreTypes$AccountRoute('blockcypher'),
_2: true _2: true
}, },
_1: { _1: {
ctor: '::', ctor: '::',
_0: { _0: {
ctor: '_Tuple3', ctor: '_Tuple3',
_0: 'Mailjet', _0: 'Twilio',
_1: _user$project$CoreTypes$AccountRoute('mailjet'), _1: _user$project$CoreTypes$AccountRoute('twilio'),
_2: true _2: true
}, },
_1: {ctor: '[]'} _1: {
ctor: '::',
_0: {
ctor: '_Tuple3',
_0: 'Mailjet',
_1: _user$project$CoreTypes$AccountRoute('mailjet'),
_2: true
},
_1: {ctor: '[]'}
}
} }
} }
} }

20
schemas/blockcypher.json Normal file
View file

@ -0,0 +1,20 @@
{
"code": "blockcypher",
"display": "Blockcypher",
"fields": [
{
"code": "token",
"display": "API token",
"fieldType": "password",
"required": true,
"value": ""
},
{
"code": "confidenceFactor",
"display": "Confidence Factor",
"fieldType": "string",
"required": true,
"value": ""
}
]
}