2017-08-09 08:03:12 +02:00
|
|
|
var async = require('async')
|
2016-10-12 05:31:41 +02:00
|
|
|
var bitcoin = require('../../')
|
2015-08-07 06:47:07 +02:00
|
|
|
var Blockchain = require('cb-http-client')
|
2016-10-12 05:31:41 +02:00
|
|
|
var coinSelect = require('coinselect')
|
2017-08-21 08:57:53 +02:00
|
|
|
var dhttp = require('dhttp/200')
|
2016-10-12 05:31:41 +02:00
|
|
|
var typeforce = require('typeforce')
|
|
|
|
var types = require('../../src/types')
|
2015-08-07 06:47:07 +02:00
|
|
|
|
2017-08-09 08:03:12 +02:00
|
|
|
var BLOCKTRAIL_API_KEY = process.env.BLOCKTRAIL_API_KEY || 'c0bd8155c66e3fb148bb1664adc1e4dacd872548'
|
|
|
|
var blockchain = new Blockchain('https://api.blocktrail.com/cb/v0.2.1/tBTC', { api_key: BLOCKTRAIL_API_KEY })
|
2016-10-12 05:31:41 +02:00
|
|
|
var kpNetwork = bitcoin.networks.testnet
|
2016-10-18 07:21:45 +02:00
|
|
|
var keyPair = bitcoin.ECPair.fromWIF('cQqjeq2rxqwnqwMewJhkNtJDixtX8ctA4bYoWHdxY4xRPVvAEjmk', kpNetwork)
|
2016-10-12 05:31:41 +02:00
|
|
|
var kpAddress = keyPair.getAddress()
|
2017-08-21 10:32:16 +02:00
|
|
|
var conflicts = {}
|
2016-10-12 05:31:41 +02:00
|
|
|
|
2016-10-13 08:01:08 +02:00
|
|
|
function fundAddress (unspents, outputs, callback) {
|
2017-04-18 06:03:09 +02:00
|
|
|
// avoid too-long-mempool-chain
|
|
|
|
unspents = unspents.filter(function (x) {
|
2017-08-21 10:32:16 +02:00
|
|
|
return x.confirmations > 0 && !conflicts[x.txId + x.vout]
|
2017-04-18 06:03:09 +02:00
|
|
|
})
|
|
|
|
|
2016-10-13 08:01:08 +02:00
|
|
|
var result = coinSelect(unspents, outputs, 10)
|
2016-10-12 05:31:41 +02:00
|
|
|
if (!result.inputs) return callback(new Error('Faucet empty'))
|
|
|
|
|
|
|
|
var txb = new bitcoin.TransactionBuilder(kpNetwork)
|
|
|
|
result.inputs.forEach(function (x) {
|
2017-08-21 10:32:16 +02:00
|
|
|
conflicts[x.txId + x.vout] = true
|
2016-10-12 05:31:41 +02:00
|
|
|
txb.addInput(x.txId, x.vout)
|
|
|
|
})
|
|
|
|
|
|
|
|
result.outputs.forEach(function (x) {
|
2017-08-21 08:57:53 +02:00
|
|
|
if (x.address) console.warn('funding ' + x.address + ' w/ ' + x.value)
|
2016-10-12 05:31:41 +02:00
|
|
|
txb.addOutput(x.address || kpAddress, x.value)
|
|
|
|
})
|
|
|
|
|
2017-01-06 03:47:41 +01:00
|
|
|
result.inputs.forEach(function (_, i) {
|
2016-10-12 05:31:41 +02:00
|
|
|
txb.sign(i, keyPair)
|
|
|
|
})
|
|
|
|
|
|
|
|
var tx = txb.build()
|
2016-10-13 08:01:08 +02:00
|
|
|
|
2017-08-09 08:03:12 +02:00
|
|
|
blockchain.transactions.propagate(tx.toHex(), function (err) {
|
2017-04-18 05:43:26 +02:00
|
|
|
if (err) return callback(err)
|
|
|
|
|
2017-08-21 08:57:53 +02:00
|
|
|
var txId = tx.getId()
|
|
|
|
callback(null, outputs.map(function (x, i) {
|
|
|
|
return { txId: txId, vout: i, value: x.value }
|
|
|
|
}))
|
2016-10-12 05:31:41 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-08-09 08:03:12 +02:00
|
|
|
blockchain.faucetMany = function faucetMany (outputs, callback) {
|
|
|
|
blockchain.addresses.unspents(kpAddress, function (err, unspents) {
|
2016-10-13 08:01:08 +02:00
|
|
|
if (err) return callback(err)
|
|
|
|
|
2016-10-12 05:31:41 +02:00
|
|
|
typeforce([{
|
|
|
|
txId: types.Hex,
|
|
|
|
vout: types.UInt32,
|
|
|
|
value: types.Satoshi
|
|
|
|
}], unspents)
|
2016-01-28 11:06:20 +01:00
|
|
|
|
2016-10-13 08:01:08 +02:00
|
|
|
fundAddress(unspents, outputs, callback)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-08-09 08:03:12 +02:00
|
|
|
blockchain.faucet = function faucet (address, value, callback) {
|
|
|
|
blockchain.faucetMany([{ address: address, value: value }], function (err, unspents) {
|
2016-10-13 08:01:08 +02:00
|
|
|
callback(err, unspents && unspents[0])
|
2016-01-28 11:06:20 +01:00
|
|
|
})
|
2015-08-07 06:47:07 +02:00
|
|
|
}
|
|
|
|
|
2017-08-09 08:03:12 +02:00
|
|
|
// verify TX was accepted
|
2017-08-21 10:32:16 +02:00
|
|
|
blockchain.verify = function verify (address, txId, value, done) {
|
2017-08-09 08:03:12 +02:00
|
|
|
async.retry(5, function (callback) {
|
|
|
|
setTimeout(function () {
|
|
|
|
// check that the above transaction included the intended address
|
2017-08-21 08:57:53 +02:00
|
|
|
dhttp({
|
|
|
|
method: 'POST',
|
|
|
|
url: 'https://api.ei8ht.com.au:9443/3/txs',
|
|
|
|
body: [txId]
|
|
|
|
}, function (err, result) {
|
2017-08-09 08:03:12 +02:00
|
|
|
if (err) return callback(err)
|
2017-08-21 08:57:53 +02:00
|
|
|
if (!result[txId]) return callback(new Error('Could not find ' + txId))
|
2017-08-09 08:03:12 +02:00
|
|
|
callback()
|
|
|
|
})
|
2017-08-21 08:57:53 +02:00
|
|
|
}, 400)
|
2017-08-09 08:03:12 +02:00
|
|
|
}, done)
|
2015-08-07 06:47:07 +02:00
|
|
|
}
|
2017-08-09 08:03:12 +02:00
|
|
|
|
2017-08-21 10:32:16 +02:00
|
|
|
blockchain.transactions.propagate = function broadcast (txHex, callback) {
|
2017-08-21 08:57:53 +02:00
|
|
|
dhttp({
|
|
|
|
method: 'POST',
|
|
|
|
url: 'https://api.ei8ht.com.au:9443/3/pushtx',
|
|
|
|
body: txHex
|
|
|
|
}, callback)
|
|
|
|
}
|
|
|
|
|
2017-08-09 08:03:12 +02:00
|
|
|
blockchain.RETURN_ADDRESS = kpAddress
|
|
|
|
module.exports = blockchain
|