From fc1dcbd9d099b1cc9d71b905cd0ddda603baec96 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 17 Apr 2014 12:38:03 -0300 Subject: [PATCH] fix and improve SendTx example --- README.md | 227 ++++++++++++++++++++++++--------------------- examples/SendTx.js | 127 +++++++++++++++---------- 2 files changed, 203 insertions(+), 151 deletions(-) diff --git a/README.md b/README.md index df162db..9ce5ebd 100644 --- a/README.md +++ b/README.md @@ -62,42 +62,43 @@ addrs.forEach(function(addr) { For this example you need a running bitcoind instance with RPC enabled. ```js -var bitcore = require('bitcore'); -var networks = bitcore.networks; -var Peer = bitcore.Peer; -var PeerManager = require('soop').load('../PeerManager', { - network: networks.testnet -}); + var bitcore = require('../bitcore'); + var Peer = bitcore.Peer; + var PeerManager = bitcore.PeerManager; -var handleBlock = function(info) { - console.log('** Block Received **'); - console.log(info.message); -}; + var handleBlock = function(info) { + console.log('** Block Received **'); + console.log(info.message); + }; -var handleTx = function(info) { - var tx = info.message.tx.getStandardizedObject(); - console.log('** TX Received **'); - console.log(tx); -}; + var handleTx = function(info) { + var tx = info.message.tx.getStandardizedObject(); -var handleInv = function(info) { - console.log('** Inv **'); - console.log(info.message); - var invs = info.message.invs; - info.conn.sendGetData(invs); -}; + console.log('** TX Received **'); + console.log(tx); + }; -var peerman = new PeerManager(); + var handleInv = function(info) { + console.log('** Inv **'); + console.log(info.message); -peerman.addPeer(new Peer('127.0.0.1', 18333)); + var invs = info.message.invs; + info.conn.sendGetData(invs); + }; -peerman.on('connection', function(conn) { - conn.on('inv', handleInv); - conn.on('block', handleBlock); - conn.on('tx', handleTx); -}); + var peerman = new PeerManager({ + network: 'testnet' + }); -peerman.start(); + peerman.addPeer(new Peer('127.0.0.1', 18333)); + + peerman.on('connection', function(conn) { + conn.on('inv', handleInv); + conn.on('block', handleBlock); + conn.on('tx', handleTx); + }); + + peerman.start(); ``` PeerManager will emit the following events: 'version', 'verack', 'addr', 'getaddr', 'error' 'disconnect'; and will relay events like: 'tx', 'block', 'inv'. Please see [PeerManager.js](PeerManager.js), [Peer.js](Peer.js) and [Connection.js](Connection.js) @@ -140,83 +141,101 @@ by the transaction size. Documentation on the parameters of `TransactionBuilder` can be found on the source file. ```js -var bitcore = require('bitcore'); -var networks = bitcore.networks; -var Peer = bitcore.Peer; -var TransactionBuilder = bitcore.TransactionBuilder; -var PeerManager = require('soop').load('../PeerManager', { - network: networks.testnet -}); - -// Unspent transactions can be found via the insight.bitcore.io or blockchain.info APIs -var unspent = [ - { - "address": "n4g2TFaQo8UgedwpkYdcQFF6xE2Ei9Czvy", - "txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1", - "scriptPubKey": "76a914fe021bac469a5c49915b2a8ffa7390a9ce5580f988ac", - "vout": 1, - "amount": 1.0101, - "confirmations":7 - }, - { - "address": "mhNCT9TwZAGF1tLPpZdqfkTmtBkY282YDW", - "txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc2", - "scriptPubKey": "76a9141448534cb1a1ec44665b0eb2326e570814afe3f188ac", - "vout": 0, - "confirmations": 1, - "amount": 10 - } -]; - -// Private keys in WIF format (see TransactionBuilder.js for other options) -var keys = [ - "cSq7yo4fvsbMyWVN945VUGUWMaSazZPWqBVJZyoGsHmNq6W4HVBV", - "cPa87VgwZfowGZYaEenoQeJgRfKW6PhZ1R65EHTkN1K19cSvc92G", - "cPQ9DSbBRLva9av5nqeF5AGrh3dsdW8p2E5jS4P8bDWZAoQTeeKB" -]; - -var peerman = new PeerManager(); -peerman.addPeer(new Peer('127.0.0.1', 18333)); - -peerman.on('connect', function() { - var conn = peerman.getActiveConnection(); - if (conn) { - var outs = [{address: toAddress, amount: amt}]; - var opts = {remainderOut: {address: changeAddressString}}; - var TransactionBuilder = bitcore.TransactionBuilder; - - var tx = new TransactionBuilder(opts) - .setUnspent(unspent) - .setOutputs(outs) - .sign(keys) - .build(); - - /* Create and signing can be done in multiple steps: - * - * var builder = new bitcore.TransactionBuilder(opts) - * .setUnspent(utxos) - * .setOutputs(outs); - * - * // Sign with the first key - * builder.sign(key1); - * var tx = builder.build(); // Partially signed transaction - * - * // Sign with the second key - * builder.sign(key2); - * if (builder.isFullySigned()){ - * var tx = builder.build(); - * } - * - * var selectedUnspent = build.getSelectedUnspent(); // Retrieve selected unspent outputs from the transaction - */ - conn.sendTx(tx.serialize().toString('hex')); - } - conn.on('reject', function() { - console.log('Transaction Rejected'); + var bitcore = require('bitcore'); + var Peer = bitcore.Peer; + var TransactionBuilder = bitcore.TransactionBuilder; + var PeerManager = bitcore.PeerManager; + + // Unspent transactions can be found via the insight.bitcore.io or blockchain.info APIs + var unspent = [{ + 'txid': '707108b5ba4f78dc951df4647a03365bf36432ea57fb641676045c5044daaea7', + 'vout': 0, + 'address': 'n3QDC7DzsMmN4mcyp3k7XGPX7zFXXHG387', + 'scriptPubKey': '76a914f00c4a92ee2314ab08ac0283dc8d07d9bf2be32388ac', + 'amount': 0.12345600, + 'confirmations': 43537 + }, { + 'txid': '87a158d32833cb555aea27b6a21af569ccaeb8f9b19691e05f1e6c2b3440bdb3', + 'vout': 1, + 'address': 'mxdrp9s4mVxS9X4RBYiLe99v59V81XA5C3', + 'scriptPubKey': '76a914bbc87986da6b17c7876db4efacf59a95e14f6cf588ac', + 'amount': 0.05749800, + 'confirmations': 43536 + } + + ]; + + // Private keys in WIF format (see TransactionBuilder.js for other options) + var keys = [ + 'cQA75LXhV5JkMT8wkkqjR87SnHK4doh3c21p7PAd5tp8tc1tRBAY', + 'cRz85dz9AiDieRpEwoucfXXQa1jdHHghcv6YnnVVGZ3MQyR1X4u2', + 'cSq7yo4fvsbMyWVN945VUGUWMaSazZPWqBVJZyoGsHmNq6W4HVBV', + 'cPa87VgwZfowGZYaEenoQeJgRfKW6PhZ1R65EHTkN1K19cSvc92G', + 'cPQ9DSbBRLva9av5nqeF5AGrh3dsdW8p2E5jS4P8bDWZAoQTeeKB' + ]; + + var peerman = new PeerManager({ + network: 'testnet' + }); + peerman.addPeer(new Peer('127.0.0.1', 18333)); + + peerman.on('connect', function() { + var conn = peerman.getActiveConnection(); + if (conn) { + // define transaction output + var outs = [{ + address: 'mhNCT9TwZAGF1tLPpZdqfkTmtBkY282YDW', + amount: 0.1337 + }]; + // set change address + var opts = { + remainderOut: { + address: 'n4g2TFaQo8UgedwpkYdcQFF6xE2Ei9Czvy' + } + }; + var tx = new TransactionBuilder(opts) + .setUnspent(unspent) + .setOutputs(outs) + .sign(keys) + .build(); + + /* Create and signing can be done in multiple steps: + * + * var builder = new bitcore.TransactionBuilder(opts) + * .setUnspent(utxos) + * .setOutputs(outs); + * + * // Sign with the first key + * builder.sign(key1); + * var tx = builder.build(); // Partially signed transaction + * + * // Sign with the second key + * builder.sign(key2); + * if (builder.isFullySigned()){ + * var tx = builder.build(); + * } + * + * var selectedUnspent = build.getSelectedUnspent(); // Retrieve selected unspent outputs from the transaction + */ + + var txid = tx.getHash().toString('hex'); + console.log('Created transaction with txid '+txid); + var raw_tx = tx.serialize().toString('hex'); + console.log('Transaction raw hex dump:'); + console.log('-------------------------------------'); + console.log(raw_tx); + console.log('-------------------------------------'); + // finally, send transaction to the bitcoin network + conn.sendTx(tx); + + // for now, the network won't respond in any case + // (transaction accepted, transaction rejected) + // in the future, we may listen to 'reject' message + // see https://gist.github.com/gavinandresen/7079034 + } }); -}); -peerman.start(); + peerman.start(); ``` ## Parsing a Script diff --git a/examples/SendTx.js b/examples/SendTx.js index 0eed1f1..b86eca6 100644 --- a/examples/SendTx.js +++ b/examples/SendTx.js @@ -4,67 +4,100 @@ var run = function() { // Replace '../bitcore' with 'bitcore' if you use this code elsewhere. var bitcore = require('../bitcore'); var Peer = bitcore.Peer; - var Transaction = bitcore.Transaction; - var Address = bitcore.Address; - var Script = bitcore.Script; - var coinUtil = bitcore.util; + var TransactionBuilder = bitcore.TransactionBuilder; var PeerManager = bitcore.PeerManager; - var createTx = function() { - var TXIN = 'd05f35e0bbc495f6dcab03e599c8f5e32a07cdb4bc76964de201d06a2a7d8265'; - var TXIN_N = 0; - var ADDR = 'muHct3YZ9Nd5Pq7uLYYhXRAxeW4EnpcaLz'; - var VAL = '0.001'; - - var txobj = { - version: 1, - lock_time: 0, - ins: [], - outs: [] - }; - - var txin = { - s: coinUtil.EMPTY_BUFFER, // Add signature - q: 0xffffffff - }; - - var hash = new Buffer(TXIN.split('').reverse(), 'hex'); - var vout = parseInt(TXIN_N); - var voutBuf = new Buffer(4); - - voutBuf.writeUInt32LE(vout, 0); - txin.o = Buffer.concat([hash, voutBuf]); - txobj.ins.push(txin); - - var addr = new Address(ADDR); - var script = Script.createPubKeyHashOut(addr.payload()); - var valueNum = coinUtil.parseValue(VAL); - var value = coinUtil.bigIntToValue(valueNum); - - var txout = { - v: value, - s: script.getBuffer(), - }; - txobj.outs.push(txout); + // Unspent transactions can be found via the insight.bitcore.io or blockchain.info APIs + var unspent = [{ + 'txid': '707108b5ba4f78dc951df4647a03365bf36432ea57fb641676045c5044daaea7', + 'vout': 0, + 'address': 'n3QDC7DzsMmN4mcyp3k7XGPX7zFXXHG387', + 'scriptPubKey': '76a914f00c4a92ee2314ab08ac0283dc8d07d9bf2be32388ac', + 'amount': 0.12345600, + 'confirmations': 43537 + }, { + 'txid': '87a158d32833cb555aea27b6a21af569ccaeb8f9b19691e05f1e6c2b3440bdb3', + 'vout': 1, + 'address': 'mxdrp9s4mVxS9X4RBYiLe99v59V81XA5C3', + 'scriptPubKey': '76a914bbc87986da6b17c7876db4efacf59a95e14f6cf588ac', + 'amount': 0.05749800, + 'confirmations': 43536 + } - return new Transaction(txobj); + ]; - }; + // Private keys in WIF format (see TransactionBuilder.js for other options) + var keys = [ + 'cQA75LXhV5JkMT8wkkqjR87SnHK4doh3c21p7PAd5tp8tc1tRBAY', + 'cRz85dz9AiDieRpEwoucfXXQa1jdHHghcv6YnnVVGZ3MQyR1X4u2', + 'cSq7yo4fvsbMyWVN945VUGUWMaSazZPWqBVJZyoGsHmNq6W4HVBV', + 'cPa87VgwZfowGZYaEenoQeJgRfKW6PhZ1R65EHTkN1K19cSvc92G', + 'cPQ9DSbBRLva9av5nqeF5AGrh3dsdW8p2E5jS4P8bDWZAoQTeeKB' + ]; - var peerman = new PeerManager(); + var peerman = new PeerManager({ + network: 'testnet' + }); peerman.addPeer(new Peer('127.0.0.1', 18333)); peerman.on('connect', function() { var conn = peerman.getActiveConnection(); if (conn) { - conn.sendTx(createTx()); + // define transaction output + var outs = [{ + address: 'mhNCT9TwZAGF1tLPpZdqfkTmtBkY282YDW', + amount: 0.1337 + }]; + // set change address + var opts = { + remainderOut: { + address: 'n4g2TFaQo8UgedwpkYdcQFF6xE2Ei9Czvy' + } + }; + var tx = new TransactionBuilder(opts) + .setUnspent(unspent) + .setOutputs(outs) + .sign(keys) + .build(); + + /* Create and signing can be done in multiple steps: + * + * var builder = new bitcore.TransactionBuilder(opts) + * .setUnspent(utxos) + * .setOutputs(outs); + * + * // Sign with the first key + * builder.sign(key1); + * var tx = builder.build(); // Partially signed transaction + * + * // Sign with the second key + * builder.sign(key2); + * if (builder.isFullySigned()){ + * var tx = builder.build(); + * } + * + * var selectedUnspent = build.getSelectedUnspent(); // Retrieve selected unspent outputs from the transaction + */ + + var txid = tx.getHash().toString('hex'); + console.log('Created transaction with txid '+txid); + var raw_tx = tx.serialize().toString('hex'); + console.log('Transaction raw hex dump:'); + console.log('-------------------------------------'); + console.log(raw_tx); + console.log('-------------------------------------'); + // finally, send transaction to the bitcoin network + conn.sendTx(tx); + + // for now, the network won't respond in any case + // (transaction accepted, transaction rejected) + // in the future, we may listen to 'reject' message + // see https://gist.github.com/gavinandresen/7079034 } - conn.on('reject', function() { - console.log('Transaction Rejected'); - }); }); peerman.start(); + }; module.exports.run = run;