3 changed files with 14 additions and 151 deletions
@ -1,156 +1,9 @@ |
|||||
const assert = require('assert') |
const { RegtestUtils } = require('regtest-client') |
||||
const bitcoin = require('../../') |
|
||||
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) |
|
||||
}) |
|
||||
}) |
|
||||
|
|
||||
|
const bitcoin = require('../..') |
||||
const APIPASS = process.env.APIPASS || 'satoshi' |
const APIPASS = process.env.APIPASS || 'satoshi' |
||||
const APIURL = process.env.APIURL || 'https://regtest.bitbank.cc/1' |
const APIURL = process.env.APIURL || 'https://regtest.bitbank.cc/1' |
||||
const NETWORK = bitcoin.networks.testnet |
|
||||
|
|
||||
function broadcast (txHex) { |
const regtestUtils = new RegtestUtils(bitcoin, { APIPASS, APIURL }) |
||||
return dhttp({ |
|
||||
method: 'POST', |
|
||||
url: APIURL + '/t/push', |
|
||||
body: txHex |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
function mine (count) { |
module.exports = regtestUtils; |
||||
return dhttp({ |
|
||||
method: 'POST', |
|
||||
url: APIURL + '/r/generate?count=' + count + '&key=' + APIPASS |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
function height () { |
|
||||
return dhttp({ |
|
||||
method: 'GET', |
|
||||
url: APIURL + '/b/best/height' |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
function _faucetRequest (address, value) { |
|
||||
return dhttp({ |
|
||||
method: 'POST', |
|
||||
url: APIURL + '/r/faucet?address=' + address + '&value=' + value + '&key=' + APIPASS |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
async function faucet (address, value) { |
|
||||
let count = 0 |
|
||||
let _unspents = [] |
|
||||
const sleep = ms => new Promise((resolve, reject) => setTimeout(resolve, ms)) |
|
||||
const randInt = (min, max) => min + Math.floor((max - min + 1) * Math.random()) |
|
||||
while (_unspents.length === 0) { |
|
||||
if (count > 0) { |
|
||||
if (count >= 5) throw new Error('Missing Inputs') |
|
||||
console.log('Missing Inputs, retry #' + count) |
|
||||
await sleep(randInt(150, 250)) |
|
||||
} |
|
||||
|
|
||||
const txId = await _faucetRequest(address, value) |
|
||||
.then( |
|
||||
v => v, // Pass success value as is
|
|
||||
async err => { |
|
||||
// Bad Request error is fixed by making sure height is >= 432
|
|
||||
const currentHeight = await height() |
|
||||
if (err.message === 'Bad Request' && currentHeight < 432) { |
|
||||
await mine(432 - currentHeight) |
|
||||
return _faucetRequest(address, value) |
|
||||
} else if (err.message === 'Bad Request' && currentHeight >= 432) { |
|
||||
return _faucetRequest(address, value) |
|
||||
} else { |
|
||||
throw err |
|
||||
} |
|
||||
} |
|
||||
) |
|
||||
|
|
||||
await sleep(randInt(10, 40)) |
|
||||
|
|
||||
const results = await unspents(address) |
|
||||
|
|
||||
_unspents = results.filter(x => x.txId === txId) |
|
||||
|
|
||||
count++ |
|
||||
} |
|
||||
|
|
||||
return _unspents.pop() |
|
||||
} |
|
||||
|
|
||||
async function faucetComplex (output, value) { |
|
||||
const keyPair = bitcoin.ECPair.makeRandom({ network: NETWORK }) |
|
||||
const p2pkh = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network: NETWORK }) |
|
||||
|
|
||||
const unspent = await faucet(p2pkh.address, value * 2) |
|
||||
|
|
||||
const txvb = new bitcoin.TransactionBuilder(NETWORK) |
|
||||
txvb.addInput(unspent.txId, unspent.vout, null, p2pkh.output) |
|
||||
txvb.addOutput(output, value) |
|
||||
txvb.sign({ |
|
||||
prevOutScriptType: 'p2pkh', |
|
||||
vin: 0, |
|
||||
keyPair |
|
||||
}) |
|
||||
const txv = txvb.build() |
|
||||
|
|
||||
await broadcast(txv.toHex()) |
|
||||
|
|
||||
return { |
|
||||
txId: txv.getId(), |
|
||||
vout: 0, |
|
||||
value |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
function fetch (txId) { |
|
||||
return dhttp({ |
|
||||
method: 'GET', |
|
||||
url: APIURL + '/t/' + txId + '/json' |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
function unspents (address) { |
|
||||
return dhttp({ |
|
||||
method: 'GET', |
|
||||
url: APIURL + '/a/' + address + '/unspents' |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
async function verify (txo) { |
|
||||
const tx = await fetch(txo.txId) |
|
||||
|
|
||||
const txoActual = tx.outs[txo.vout] |
|
||||
if (txo.address) assert.strictEqual(txoActual.address, txo.address) |
|
||||
if (txo.value) assert.strictEqual(txoActual.value, txo.value) |
|
||||
} |
|
||||
|
|
||||
function getAddress (node, network) { |
|
||||
return bitcoin.payments.p2pkh({ pubkey: node.publicKey, network }).address |
|
||||
} |
|
||||
|
|
||||
function randomAddress () { |
|
||||
return getAddress(bitcoin.ECPair.makeRandom({ |
|
||||
network: bitcoin.networks.testnet |
|
||||
}), bitcoin.networks.testnet) |
|
||||
} |
|
||||
|
|
||||
module.exports = { |
|
||||
broadcast, |
|
||||
dhttp, |
|
||||
faucet, |
|
||||
faucetComplex, |
|
||||
fetch, |
|
||||
height, |
|
||||
mine, |
|
||||
network: NETWORK, |
|
||||
unspents, |
|
||||
verify, |
|
||||
randomAddress, |
|
||||
RANDOM_ADDRESS: randomAddress() |
|
||||
} |
|
||||
|
Loading…
Reference in new issue