Created
September 13, 2016 03:24
-
-
Save bachvtuan/a1fb6c745f2c6e56a57d1c4dbdede5a7 to your computer and use it in GitHub Desktop.
Send bitcoin transaction to multiple addresses
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* package.json | |
"devDependencies": { | |
"bitcore-lib": "^0.13.18", | |
"async": "0.9.0", | |
"request": "2.53.0" | |
} | |
*/ | |
var bitcore = require("bitcore-lib"); | |
var fs = require("fs"); | |
var request = require('request'); | |
var Async = require("async"); | |
/** END EXAMPLE INPUT, YOU SHOULD MODIFY TO YOUR CASE **/ | |
// Your public key | |
var from_public = "your_public_key_here"; | |
// Your private key | |
var private_key = 'your_private_key_here'; | |
// Define which addresses you wan to send, just 1 item or more, below are 2 example addresses | |
var send_addresses = [ | |
//adress and amount in satoshies | |
{ address: "1Hyxrc88gd6s9w1MpVz3e1NLf4FTZxBby6", amount: 327880 },//approximate 2$ | |
{ address: "19tqEocN86Y4rHyeB2G4ezUpYNxv94sdmM", amount: 163940 }, //approximate 1$ | |
]; | |
/** END EXAMPLE INPUT, YOU SHOULD MODIFY TO YOUR CASE **/ | |
const push_bitcoin_url = "https://blockchain.info/pushtx"; | |
const check_address_url = "https://api.blockcypher.com/v1/btc/main/addrs/{address}?unspentOnly=1"; | |
//According https://api.blockcypher.com/v1/btc/main | |
const fee_per_kb = 71050; // 71050 satoshies 0.43$/kb fee | |
const min_transaction_amount = 546; // request dust is 546 satoshies | |
Async.waterfall([ | |
function (callback) { | |
var check_url = check_address_url.replace('{address}', from_public); | |
console.log("check_url", check_url); | |
request(check_url, function (error, response, body) { | |
if (!error && response.statusCode == 200) { | |
//console.log(body); | |
var json = JSON.parse(body); | |
var unspend_transactions = []; | |
if (json.unconfirmed_txrefs) { | |
for (var i = 0; i < json.unconfirmed_txrefs.length; i++) { | |
var item = json.unconfirmed_txrefs[i]; | |
if (!item.double_spend) { | |
//if there is unconfirmation transaction but there is my public address here | |
if (item.address == from_public) { | |
unspend_transactions.push(item); | |
} | |
} | |
else { | |
console.log("detected double spend on unconfirmation transactions"); | |
} | |
} | |
} | |
if (json.txrefs) { | |
for (var i = 0; i < json.txrefs.length; i++) { | |
var item = json.txrefs[i]; | |
if (!item.double_spend) { | |
unspend_transactions.push(item); | |
} else { | |
console.log("detected double spend on confirmed transactions"); | |
} | |
} | |
} | |
callback(null, unspend_transactions); | |
} else { | |
callback("can not get input address information"); | |
} | |
}) | |
}, | |
function (input_transactions, callback) { | |
//console.log("input_transactions",input_transactions); | |
var script = new bitcore.Script(new bitcore.Address(from_public)).toHex(); | |
var privateKey = new bitcore.PrivateKey(private_key); | |
var total_value = 0; | |
var transaction = new bitcore.Transaction(); | |
for (var i = 0; i < input_transactions.length; i++) { | |
var item = input_transactions[i]; | |
var utxo = { | |
"txId": item.tx_hash, | |
"outputIndex": item.tx_output_n, | |
"address": from_public, | |
"script": script, | |
"satoshis": item.value | |
}; | |
total_value += item.value; | |
transaction.from(utxo) | |
} | |
//Total output amount by satoshies | |
var total_output = 0; | |
for (var i = 0; i < send_addresses.length; i++) { | |
var address_item = send_addresses[i]; | |
transaction.to(address_item.address, address_item.amount) | |
total_output += address_item.amount; | |
} | |
// estimate size of transaction and calculate fee | |
var fee = Math.floor(fee_per_kb * transaction._estimateSize() / 1024); | |
console.log("total_output", total_output); | |
console.log("total_value", total_value); | |
console.log("fee", fee); | |
if (total_value < total_output + fee) { | |
return callback("Not enough for create transaction"); | |
} | |
var change_amount = total_value - total_output - fee; | |
if (change_amount > 0 && change_amount < min_transaction_amount) { | |
return callback("The change amount is too small"); | |
} | |
console.log("change_amount", change_amount); | |
transaction.fee(fee); | |
if (change_amount > 0) { | |
transaction.change(from_public) | |
} | |
transaction.enableRBF() | |
.sign(privateKey); | |
var tx_hex = transaction.serialize(); | |
console.log("tx_hex", tx_hex); | |
/*console.log( JSON.stringify(transaction.toObject()), "end");*/ | |
var post_params = { | |
url: push_bitcoin_url, form: { tx: tx_hex } | |
}; | |
request.post(post_params, function (error, response, body) { | |
if (!error && response.statusCode == 200) { | |
console.log("body", body) // Show the HTML for the Google homepage. | |
} else { | |
console.log("body", body) // Show the HTML for the Google homepage. | |
console.log("statusCode", response.statusCode); | |
} | |
callback(null); | |
}); | |
} | |
], function (err, result) { | |
console.log('info', "END TASK"); | |
if (err) { | |
console.log('info', err); | |
} | |
process.exit(); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment