Skip to content

Commit a4fe3d3

Browse files
committed
testing/integration/examples: isolate to addresses/transactions
examples, use public broadcast endpoints
1 parent 798ec35 commit a4fe3d3

File tree

12 files changed

+359
-296
lines changed

12 files changed

+359
-296
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ The definitions are complete and up to date with version 2.2.0. The definitions
100100
The below examples are implemented as integration tests, they should be very easy to understand. Otherwise, pull requests are appreciated.
101101

102102
- [Generate a random address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/basic.js#L9)
103-
- [Generate a address from a SHA256 hash](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/basic.js#L20)
104-
- [Generate a address and WIF for Litecoin](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/basic.js#L30)
103+
- [Generate an address from a SHA256 hash](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/basic.js#L20)
104+
- [Generate an address and WIF for Litecoin](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/basic.js#L30)
105105
- [Import an address via WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/basic.js#L43)
106106
- [Create a Transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/basic.js#L50)
107107
- [Create an OP RETURN transaction](https://github.com/bitcoinjs/bitcoinjs-lib/blob/d853806/test/integration/advanced.js#L24)

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
"pushdata-bitcoin": "^1.0.1",
6363
"randombytes": "^2.0.1",
6464
"safe-buffer": "^5.0.1",
65-
"typeforce": "^1.8.7",
65+
"typeforce": "^1.11.3",
6666
"varuint-bitcoin": "^1.0.4",
6767
"wif": "^2.0.1"
6868
},
@@ -72,6 +72,7 @@
7272
"bs58": "^4.0.0",
7373
"cb-http-client": "^0.2.0",
7474
"coinselect": "^3.1.1",
75+
"dhttp": "^2.3.5",
7576
"minimaldata": "^1.0.2",
7677
"mocha": "^3.1.0",
7778
"nyc": "^10.2.0",

test/integration/_mainnet.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
var Blockchain = require('cb-http-client')
2+
var BLOCKTRAIL_API_KEY = process.env.BLOCKTRAIL_API_KEY || 'c0bd8155c66e3fb148bb1664adc1e4dacd872548'
3+
module.exports = new Blockchain('https://api.blocktrail.com/cb/v0.2.1/BTC', { api_key: BLOCKTRAIL_API_KEY })

test/integration/_blockchain.js renamed to test/integration/_testnet.js

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1+
var async = require('async')
12
var bitcoin = require('../../')
23
var Blockchain = require('cb-http-client')
3-
var BLOCKTRAIL_API_KEY = process.env.BLOCKTRAIL_API_KEY || 'c0bd8155c66e3fb148bb1664adc1e4dacd872548'
44
var coinSelect = require('coinselect')
55
var typeforce = require('typeforce')
66
var types = require('../../src/types')
77

8-
var mainnet = new Blockchain('https://api.blocktrail.com/cb/v0.2.1/BTC', { api_key: BLOCKTRAIL_API_KEY })
9-
var testnet = new Blockchain('https://api.blocktrail.com/cb/v0.2.1/tBTC', { api_key: BLOCKTRAIL_API_KEY })
10-
8+
var BLOCKTRAIL_API_KEY = process.env.BLOCKTRAIL_API_KEY || 'c0bd8155c66e3fb148bb1664adc1e4dacd872548'
9+
var blockchain = new Blockchain('https://api.blocktrail.com/cb/v0.2.1/tBTC', { api_key: BLOCKTRAIL_API_KEY })
1110
var kpNetwork = bitcoin.networks.testnet
1211
var keyPair = bitcoin.ECPair.fromWIF('cQqjeq2rxqwnqwMewJhkNtJDixtX8ctA4bYoWHdxY4xRPVvAEjmk', kpNetwork)
1312
var kpAddress = keyPair.getAddress()
@@ -37,20 +36,20 @@ function fundAddress (unspents, outputs, callback) {
3736
var tx = txb.build()
3837
var txId = tx.getId()
3938

40-
testnet.transactions.propagate(tx.toHex(), function (err) {
39+
blockchain.transactions.propagate(tx.toHex(), function (err) {
4140
if (err) return callback(err)
4241

4342
// FIXME: @blocktrail can be very slow, give it time
44-
setTimeout(() => {
43+
setTimeout(function () {
4544
callback(null, outputs.map(function (_, i) {
4645
return { txId: txId, vout: i }
4746
}))
4847
}, 3000)
4948
})
5049
}
5150

52-
testnet.faucetMany = function faucetMany (outputs, callback) {
53-
testnet.addresses.unspents(kpAddress, function (err, unspents) {
51+
blockchain.faucetMany = function faucetMany (outputs, callback) {
52+
blockchain.addresses.unspents(kpAddress, function (err, unspents) {
5453
if (err) return callback(err)
5554

5655
typeforce([{
@@ -63,15 +62,28 @@ testnet.faucetMany = function faucetMany (outputs, callback) {
6362
})
6463
}
6564

66-
testnet.faucet = function faucet (address, value, callback) {
67-
testnet.faucetMany([{ address: address, value: value }], function (err, unspents) {
65+
blockchain.faucet = function faucet (address, value, callback) {
66+
blockchain.faucetMany([{ address: address, value: value }], function (err, unspents) {
6867
callback(err, unspents && unspents[0])
6968
})
7069
}
7170

72-
testnet.RETURN = kpAddress
73-
74-
module.exports = {
75-
m: mainnet,
76-
t: testnet
71+
// verify TX was accepted
72+
blockchain.verify = function (address, txId, value, done) {
73+
async.retry(5, function (callback) {
74+
setTimeout(function () {
75+
// check that the above transaction included the intended address
76+
blockchain.addresses.unspents(blockchain.RETURN_ADDRESS, function (err, unspents) {
77+
if (err) return callback(err)
78+
if (!unspents.some(function (x) {
79+
return x.txId === txId && x.value === value
80+
})) return callback(new Error('Could not find unspent'))
81+
82+
callback()
83+
})
84+
}, 600)
85+
}, done)
7786
}
87+
88+
blockchain.RETURN_ADDRESS = kpAddress
89+
module.exports = blockchain

test/integration/addresses.js

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/* global describe, it */
2+
3+
var assert = require('assert')
4+
var bigi = require('bigi')
5+
var bitcoin = require('../../')
6+
var dhttp = require('dhttp/200')
7+
8+
// deterministic RNG for testing only
9+
function rng () { return Buffer.from('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz') }
10+
11+
describe('bitcoinjs-lib (addresses)', function () {
12+
it('can generate a random address', function () {
13+
var keyPair = bitcoin.ECPair.makeRandom({ rng: rng })
14+
var address = keyPair.getAddress()
15+
16+
assert.strictEqual(address, '1F5VhMHukdnUES9kfXqzPzMeF1GPHKiF64')
17+
})
18+
19+
it('can generate an address from a SHA256 hash', function () {
20+
var hash = bitcoin.crypto.sha256('correct horse battery staple')
21+
var d = bigi.fromBuffer(hash)
22+
23+
var keyPair = new bitcoin.ECPair(d)
24+
var address = keyPair.getAddress()
25+
26+
assert.strictEqual(address, '1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8')
27+
})
28+
29+
it('can import an address via WIF', function () {
30+
var keyPair = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct')
31+
var address = keyPair.getAddress()
32+
33+
assert.strictEqual(address, '19AAjaTUbRjQCMuVczepkoPswiZRhjtg31')
34+
})
35+
36+
it('can generate a 2-of-3 multisig P2SH address', function () {
37+
var pubKeys = [
38+
'026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01',
39+
'02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9',
40+
'03c6103b3b83e4a24a0e33a4df246ef11772f9992663db0c35759a5e2ebf68d8e9'
41+
].map(function (hex) {
42+
return Buffer.from(hex, 'hex')
43+
})
44+
45+
var redeemScript = bitcoin.script.multisig.output.encode(2, pubKeys) // 2 of 3
46+
var scriptPubKey = bitcoin.script.scriptHash.output.encode(bitcoin.crypto.hash160(redeemScript))
47+
var address = bitcoin.address.fromOutputScript(scriptPubKey)
48+
49+
assert.strictEqual(address, '36NUkt6FWUi3LAWBqWRdDmdTWbt91Yvfu7')
50+
})
51+
52+
it('can support the retrieval of transactions for an address (3rd party blockchain)', function (done) {
53+
var keyPair = bitcoin.ECPair.makeRandom()
54+
var address = keyPair.getAddress()
55+
56+
dhttp({
57+
method: 'POST',
58+
url: 'https://api.ei8ht.com.au/3/addrtxs',
59+
body: {
60+
addrs: [address],
61+
height: 0
62+
}
63+
}, function (err, transactions) {
64+
if (err) return done(err)
65+
66+
// random private keys [probably] have no transactions
67+
assert.strictEqual(Object.keys(transactions).length, 0)
68+
done()
69+
})
70+
})
71+
72+
// other networks
73+
it('can generate a Testnet address', function () {
74+
var testnet = bitcoin.networks.testnet
75+
var keyPair = bitcoin.ECPair.makeRandom({ network: testnet, rng: rng })
76+
var wif = keyPair.toWIF()
77+
var address = keyPair.getAddress()
78+
79+
assert.strictEqual(address, 'mubSzQNtZfDj1YdNP6pNDuZy6zs6GDn61L')
80+
assert.strictEqual(wif, 'cRgnQe9MUu1JznntrLaoQpB476M8PURvXVQB5R2eqms5tXnzNsrr')
81+
})
82+
83+
it('can generate a Litecoin address', function () {
84+
var litecoin = bitcoin.networks.litecoin
85+
var keyPair = bitcoin.ECPair.makeRandom({ network: litecoin, rng: rng })
86+
var wif = keyPair.toWIF()
87+
var address = keyPair.getAddress()
88+
89+
assert.strictEqual(address, 'LZJSxZbjqJ2XVEquqfqHg1RQTDdfST5PTn')
90+
assert.strictEqual(wif, 'T7A4PUSgTDHecBxW1ZiYFrDNRih2o7M8Gf9xpoCgudPF9gDiNvuS')
91+
})
92+
})

test/integration/advanced.js

Lines changed: 0 additions & 30 deletions
This file was deleted.

test/integration/basic.js

Lines changed: 0 additions & 94 deletions
This file was deleted.

test/integration/bip32.js

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
/* global describe, it */
22

33
var assert = require('assert')
4-
var bigi = require('bigi')
54
var bip39 = require('bip39')
65
var bitcoin = require('../../')
7-
var crypto = require('crypto')
8-
9-
var ecurve = require('ecurve')
10-
var secp256k1 = ecurve.getCurveByName('secp256k1')
116

127
describe('bitcoinjs-lib (BIP32)', function () {
138
it('can import a BIP32 testnet xpriv and export to WIF', function () {
@@ -66,53 +61,6 @@ describe('bitcoinjs-lib (BIP32)', function () {
6661
assert.equal(address, '2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2')
6762
})
6863

69-
it('can recover a BIP32 parent private key from the parent public key, and a derived, non-hardened child private key', function () {
70-
function recoverParent (master, child) {
71-
assert(!master.keyPair.d, 'You already have the parent private key')
72-
assert(child.keyPair.d, 'Missing child private key')
73-
74-
var curve = secp256k1
75-
var QP = master.keyPair.Q
76-
var serQP = master.keyPair.getPublicKeyBuffer()
77-
78-
var d1 = child.keyPair.d
79-
var d2
80-
var data = Buffer.alloc(37)
81-
serQP.copy(data, 0)
82-
83-
// search index space until we find it
84-
for (var i = 0; i < bitcoin.HDNode.HIGHEST_BIT; ++i) {
85-
data.writeUInt32BE(i, 33)
86-
87-
// calculate I
88-
var I = crypto.createHmac('sha512', master.chainCode).update(data).digest()
89-
var IL = I.slice(0, 32)
90-
var pIL = bigi.fromBuffer(IL)
91-
92-
// See hdnode.js:273 to understand
93-
d2 = d1.subtract(pIL).mod(curve.n)
94-
95-
var Qp = new bitcoin.ECPair(d2).Q
96-
if (Qp.equals(QP)) break
97-
}
98-
99-
var node = new bitcoin.HDNode(new bitcoin.ECPair(d2), master.chainCode, master.network)
100-
node.depth = master.depth
101-
node.index = master.index
102-
node.masterFingerprint = master.masterFingerprint
103-
return node
104-
}
105-
106-
var seed = crypto.randomBytes(32)
107-
var master = bitcoin.HDNode.fromSeedBuffer(seed)
108-
var child = master.derive(6) // m/6
109-
110-
// now for the recovery
111-
var neuteredMaster = master.neutered()
112-
var recovered = recoverParent(neuteredMaster, child)
113-
assert.strictEqual(recovered.toBase58(), master.toBase58())
114-
})
115-
11664
it('can use BIP39 to generate BIP32 wallet address', function () {
11765
// var mnemonic = bip39.generateMnemonic()
11866
var mnemonic = 'praise you muffin lion enable neck grocery crumble super myself license ghost'

0 commit comments

Comments
 (0)