Daniel Cousens
7 years ago
8 changed files with 299 additions and 311 deletions
@ -1,3 +0,0 @@ |
|||
var Blockchain = require('cb-http-client') |
|||
var BLOCKTRAIL_API_KEY = process.env.BLOCKTRAIL_API_KEY || 'c0bd8155c66e3fb148bb1664adc1e4dacd872548' |
|||
module.exports = new Blockchain('https://api.blocktrail.com/cb/v0.2.1/BTC', { api_key: BLOCKTRAIL_API_KEY }) |
@ -0,0 +1,78 @@ |
|||
var bitcoin = require('../../') |
|||
var dhttp = require('dhttp/200') |
|||
|
|||
var APIPASS = process.env.APIPASS || 'satoshi' |
|||
var APIURL = 'https://api.dcousens.cloud/1' |
|||
|
|||
function broadcast (txHex, callback) { |
|||
dhttp({ |
|||
method: 'PUT', |
|||
url: APIURL + '/t/push', |
|||
body: txHex |
|||
}, callback) |
|||
} |
|||
|
|||
function mine (count, callback) { |
|||
dhttp({ |
|||
method: 'POST', |
|||
url: APIURL + '/r/generate?count=' + count + '&key=' + APIPASS |
|||
}, callback) |
|||
} |
|||
|
|||
function faucet (address, value, callback) { |
|||
dhttp({ |
|||
method: 'POST', |
|||
url: APIURL + '/r/faucet?address=' + address + '&value=' + value + '&key=' + APIPASS |
|||
}, function (err, txId) { |
|||
if (err) return callback(err) |
|||
|
|||
unspents(address, function (err, results) { |
|||
if (err) return callback(err) |
|||
|
|||
callback(null, results.filter(x => x.txId === txId).pop()) |
|||
}) |
|||
}) |
|||
} |
|||
|
|||
function fetch (txId, callback) { |
|||
dhttp({ |
|||
method: 'GET', |
|||
url: APIURL + '/t/' + txId |
|||
}, callback) |
|||
} |
|||
|
|||
function unspents (address, callback) { |
|||
dhttp({ |
|||
method: 'GET', |
|||
url: APIURL + '/a/' + address + '/unspents' |
|||
}, callback) |
|||
} |
|||
|
|||
function verify (txo, callback) { |
|||
let { txId } = txo |
|||
|
|||
fetch(txId, function (err, txHex) { |
|||
if (err) return callback(err) |
|||
|
|||
// TODO: verify address and value
|
|||
callback() |
|||
}) |
|||
} |
|||
|
|||
function randomAddress () { |
|||
return bitcoin.ECPair.makeRandom({ |
|||
network: bitcoin.networks.testnet |
|||
}).getAddress() |
|||
} |
|||
|
|||
module.exports = { |
|||
broadcast: broadcast, |
|||
faucet: faucet, |
|||
fetch: fetch, |
|||
mine: mine, |
|||
network: bitcoin.networks.testnet, |
|||
unspents: unspents, |
|||
verify: verify, |
|||
randomAddress: randomAddress, |
|||
RANDOM_ADDRESS: randomAddress() |
|||
} |
@ -1,99 +0,0 @@ |
|||
var async = require('async') |
|||
var bitcoin = require('../../') |
|||
var Blockchain = require('cb-http-client') |
|||
var coinSelect = require('coinselect') |
|||
var dhttp = require('dhttp/200') |
|||
var typeforce = require('typeforce') |
|||
var types = require('../../src/types') |
|||
|
|||
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 }) |
|||
var kpNetwork = bitcoin.networks.testnet |
|||
var keyPair = bitcoin.ECPair.fromWIF('cQqjeq2rxqwnqwMewJhkNtJDixtX8ctA4bYoWHdxY4xRPVvAEjmk', kpNetwork) |
|||
var kpAddress = keyPair.getAddress() |
|||
var conflicts = {} |
|||
|
|||
function fundAddress (unspents, outputs, callback) { |
|||
// avoid too-long-mempool-chain
|
|||
unspents = unspents.filter(function (x) { |
|||
return x.confirmations > 0 && !conflicts[x.txId + x.vout] |
|||
}) |
|||
|
|||
var result = coinSelect(unspents, outputs, 10) |
|||
if (!result.inputs) return callback(new Error('Faucet empty')) |
|||
|
|||
var txb = new bitcoin.TransactionBuilder(kpNetwork) |
|||
result.inputs.forEach(function (x) { |
|||
conflicts[x.txId + x.vout] = true |
|||
txb.addInput(x.txId, x.vout) |
|||
}) |
|||
|
|||
result.outputs.forEach(function (x) { |
|||
if (x.address) console.warn('funding ' + x.address + ' w/ ' + x.value) |
|||
txb.addOutput(x.address || kpAddress, x.value) |
|||
}) |
|||
|
|||
result.inputs.forEach(function (_, i) { |
|||
txb.sign(i, keyPair) |
|||
}) |
|||
|
|||
var tx = txb.build() |
|||
|
|||
blockchain.transactions.propagate(tx.toHex(), function (err) { |
|||
if (err) return callback(err) |
|||
|
|||
var txId = tx.getId() |
|||
callback(null, outputs.map(function (x, i) { |
|||
return { txId: txId, vout: i, value: x.value } |
|||
})) |
|||
}) |
|||
} |
|||
|
|||
blockchain.faucetMany = function faucetMany (outputs, callback) { |
|||
blockchain.addresses.unspents(kpAddress, function (err, unspents) { |
|||
if (err) return callback(err) |
|||
|
|||
typeforce([{ |
|||
txId: types.Hex, |
|||
vout: types.UInt32, |
|||
value: types.Satoshi |
|||
}], unspents) |
|||
|
|||
fundAddress(unspents, outputs, callback) |
|||
}) |
|||
} |
|||
|
|||
blockchain.faucet = function faucet (address, value, callback) { |
|||
blockchain.faucetMany([{ address: address, value: value }], function (err, unspents) { |
|||
callback(err, unspents && unspents[0]) |
|||
}) |
|||
} |
|||
|
|||
// verify TX was accepted
|
|||
blockchain.verify = function verify (address, txId, value, done) { |
|||
async.retry(5, function (callback) { |
|||
setTimeout(function () { |
|||
// check that the above transaction included the intended address
|
|||
dhttp({ |
|||
method: 'POST', |
|||
url: 'https://api.ei8ht.com.au:9443/3/txs', |
|||
body: [txId] |
|||
}, function (err, result) { |
|||
if (err) return callback(err) |
|||
if (!result[txId]) return callback(new Error('Could not find ' + txId)) |
|||
callback() |
|||
}) |
|||
}, 400) |
|||
}, done) |
|||
} |
|||
|
|||
blockchain.transactions.propagate = function broadcast (txHex, callback) { |
|||
dhttp({ |
|||
method: 'POST', |
|||
url: 'https://api.ei8ht.com.au:9443/3/pushtx', |
|||
body: txHex |
|||
}, callback) |
|||
} |
|||
|
|||
blockchain.RETURN_ADDRESS = kpAddress |
|||
module.exports = blockchain |
Loading…
Reference in new issue