2018-06-25 08:25:12 +02:00
|
|
|
const assert = require('assert')
|
|
|
|
const bitcoin = require('../../')
|
2019-04-07 15:27:16 +02:00
|
|
|
const dhttpCallback = require('dhttp/200')
|
|
|
|
// use Promises
|
|
|
|
const dhttp = options => new Promise((resolve, reject) => {
|
|
|
|
return dhttpCallback(options, (err, data) => {
|
|
|
|
if (err) return reject(err)
|
|
|
|
else return resolve(data)
|
|
|
|
})
|
|
|
|
})
|
2018-01-31 02:46:35 +01:00
|
|
|
|
2018-06-25 08:25:12 +02:00
|
|
|
const APIPASS = process.env.APIPASS || 'satoshi'
|
2018-11-20 08:28:35 +01:00
|
|
|
const APIURL = 'https://regtest.bitbank.cc/1'
|
2018-07-18 06:00:53 +02:00
|
|
|
const NETWORK = bitcoin.networks.testnet
|
2018-01-31 02:46:35 +01:00
|
|
|
|
2019-04-07 15:27:16 +02:00
|
|
|
function broadcast (txHex) {
|
|
|
|
return dhttp({
|
2018-11-20 08:28:35 +01:00
|
|
|
method: 'POST',
|
2018-01-31 02:46:35 +01:00
|
|
|
url: APIURL + '/t/push',
|
|
|
|
body: txHex
|
2019-04-07 15:27:16 +02:00
|
|
|
})
|
2018-01-31 02:46:35 +01:00
|
|
|
}
|
|
|
|
|
2019-04-07 15:27:16 +02:00
|
|
|
function mine (count) {
|
|
|
|
return dhttp({
|
2018-01-31 02:46:35 +01:00
|
|
|
method: 'POST',
|
|
|
|
url: APIURL + '/r/generate?count=' + count + '&key=' + APIPASS
|
2019-04-07 15:27:16 +02:00
|
|
|
})
|
2018-01-31 02:46:35 +01:00
|
|
|
}
|
|
|
|
|
2019-04-07 15:27:16 +02:00
|
|
|
function height () {
|
|
|
|
return dhttp({
|
2018-02-01 02:54:20 +01:00
|
|
|
method: 'GET',
|
|
|
|
url: APIURL + '/b/best/height'
|
2019-04-07 15:27:16 +02:00
|
|
|
})
|
2018-02-01 02:54:20 +01:00
|
|
|
}
|
|
|
|
|
2019-04-07 15:27:16 +02:00
|
|
|
async function faucet (address, value) {
|
|
|
|
let count = 0
|
|
|
|
let _unspents = []
|
|
|
|
const sleep = ms => new Promise(r => setTimeout(r, ms))
|
|
|
|
do {
|
|
|
|
if (count > 0) {
|
|
|
|
if (count >= 5) throw new Error('Missing Inputs')
|
|
|
|
console.log('Missing Inputs, retry #' + count)
|
|
|
|
await sleep(200)
|
|
|
|
}
|
|
|
|
|
|
|
|
const txId = await dhttp({
|
|
|
|
method: 'POST',
|
|
|
|
url: APIURL + '/r/faucet?address=' + address + '&value=' + value + '&key=' + APIPASS
|
|
|
|
})
|
2018-01-31 02:46:35 +01:00
|
|
|
|
2019-04-07 15:27:16 +02:00
|
|
|
await sleep(100)
|
2018-01-31 02:46:35 +01:00
|
|
|
|
2019-04-07 15:27:16 +02:00
|
|
|
const results = await unspents(address)
|
2018-07-20 09:35:34 +02:00
|
|
|
|
2019-04-07 15:27:16 +02:00
|
|
|
_unspents = results.filter(x => x.txId === txId)
|
|
|
|
|
|
|
|
count++
|
|
|
|
} while (_unspents.length === 0)
|
|
|
|
|
|
|
|
return _unspents.pop()
|
2018-01-31 02:46:35 +01:00
|
|
|
}
|
|
|
|
|
2019-04-07 15:27:16 +02:00
|
|
|
async function faucetComplex (output, value) {
|
2018-07-18 06:00:53 +02:00
|
|
|
const keyPair = bitcoin.ECPair.makeRandom({ network: NETWORK })
|
|
|
|
const p2pkh = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network: NETWORK })
|
|
|
|
|
2019-04-07 15:27:16 +02:00
|
|
|
const unspent = await faucet(p2pkh.address, value * 2)
|
2018-07-18 06:00:53 +02:00
|
|
|
|
2019-04-07 15:27:16 +02:00
|
|
|
const txvb = new bitcoin.TransactionBuilder(NETWORK)
|
|
|
|
txvb.addInput(unspent.txId, unspent.vout, null, p2pkh.output)
|
|
|
|
txvb.addOutput(output, value)
|
|
|
|
txvb.sign(0, keyPair)
|
|
|
|
const txv = txvb.build()
|
2018-07-18 06:00:53 +02:00
|
|
|
|
2019-04-07 15:27:16 +02:00
|
|
|
await broadcast(txv.toHex())
|
2018-07-18 06:00:53 +02:00
|
|
|
|
2019-04-07 15:27:16 +02:00
|
|
|
return {
|
|
|
|
txId: txv.getId(),
|
|
|
|
vout: 0,
|
|
|
|
value
|
|
|
|
}
|
2018-07-18 06:00:53 +02:00
|
|
|
}
|
|
|
|
|
2019-04-07 15:27:16 +02:00
|
|
|
function fetch (txId) {
|
|
|
|
return dhttp({
|
2018-01-31 02:46:35 +01:00
|
|
|
method: 'GET',
|
2018-02-01 03:14:34 +01:00
|
|
|
url: APIURL + '/t/' + txId + '/json'
|
2019-04-07 15:27:16 +02:00
|
|
|
})
|
2018-01-31 02:46:35 +01:00
|
|
|
}
|
|
|
|
|
2019-04-07 15:27:16 +02:00
|
|
|
function unspents (address) {
|
|
|
|
return dhttp({
|
2018-01-31 02:46:35 +01:00
|
|
|
method: 'GET',
|
|
|
|
url: APIURL + '/a/' + address + '/unspents'
|
2019-04-07 15:27:16 +02:00
|
|
|
})
|
2018-01-31 02:46:35 +01:00
|
|
|
}
|
|
|
|
|
2019-04-07 15:27:16 +02:00
|
|
|
async function verify (txo) {
|
|
|
|
const tx = await fetch(txo.txId)
|
2018-01-31 02:46:35 +01:00
|
|
|
|
2019-04-07 15:27:16 +02:00
|
|
|
const txoActual = tx.outs[txo.vout]
|
|
|
|
if (txo.address) assert.strictEqual(txoActual.address, txo.address)
|
|
|
|
if (txo.value) assert.strictEqual(txoActual.value, txo.value)
|
2018-01-31 02:46:35 +01:00
|
|
|
}
|
|
|
|
|
2018-05-22 09:43:25 +02:00
|
|
|
function getAddress (node, network) {
|
2018-06-27 05:54:47 +02:00
|
|
|
return bitcoin.payments.p2pkh({ pubkey: node.publicKey, network }).address
|
2018-05-22 09:43:25 +02:00
|
|
|
}
|
|
|
|
|
2018-01-31 02:46:35 +01:00
|
|
|
function randomAddress () {
|
2018-05-22 09:43:25 +02:00
|
|
|
return getAddress(bitcoin.ECPair.makeRandom({
|
2018-01-31 02:46:35 +01:00
|
|
|
network: bitcoin.networks.testnet
|
2018-05-22 09:43:25 +02:00
|
|
|
}), bitcoin.networks.testnet)
|
2018-01-31 02:46:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = {
|
2018-07-18 06:00:53 +02:00
|
|
|
broadcast,
|
2019-04-07 15:27:16 +02:00
|
|
|
dhttp,
|
2018-07-18 06:00:53 +02:00
|
|
|
faucet,
|
|
|
|
faucetComplex,
|
|
|
|
fetch,
|
|
|
|
height,
|
|
|
|
mine,
|
|
|
|
network: NETWORK,
|
|
|
|
unspents,
|
|
|
|
verify,
|
|
|
|
randomAddress,
|
2018-01-31 02:46:35 +01:00
|
|
|
RANDOM_ADDRESS: randomAddress()
|
|
|
|
}
|