@ -3,8 +3,8 @@
var _ = require ( 'lodash' ) ;
var $ = require ( '../util/preconditions' ) ;
var buffer = require ( 'buffer' ) ;
var assert = require ( 'assert' ) ;
var errors = require ( '../errors' ) ;
var util = require ( '../util/js' ) ;
var bufferUtil = require ( '../util/buffer' ) ;
var JSUtil = require ( '../util/js' ) ;
@ -98,12 +98,46 @@ Transaction.prototype._getHash = function() {
* Retrieve a hexa string that can be used with bitcoind ' s CLI interface
* ( decoderawtransaction , sendrawtransaction )
*
* @ param { boolean = } unsafe if true , skip testing for fees that are too high
* @ return { string }
* /
Transaction . prototype . serialize = Transaction . prototype . toString = function ( ) {
Transaction . prototype . serialize = function ( unsafe ) {
if ( unsafe ) {
return this . uncheckedSerialize ( ) ;
} else {
return this . checkedSerialize ( ) ;
}
} ;
Transaction . prototype . uncheckedSerialize = Transaction . prototype . toString = function ( ) {
return this . toBuffer ( ) . toString ( 'hex' ) ;
} ;
Transaction . prototype . checkedSerialize = Transaction . prototype . toString = function ( ) {
var feeError = this . _ validateFees ( ) ;
if ( feeError ) {
var changeError = this . _ validateChange ( ) ;
if ( changeError ) {
throw new errors . Transaction . ChangeAddressMissing ( ) ;
} else {
throw new errors . Transaction . FeeError ( feeError ) ;
}
}
return this . uncheckedSerialize ( ) ;
} ;
Transaction . prototype . _ validateFees = function ( ) {
if ( this . getFee ( ) > Transaction . FEE_SECURITY_MARGIN * this . _ estimateFee ( ) ) {
return 'Fee is more than ' + Transaction . FEE_SECURITY_MARGIN + ' times the suggested amount' ;
}
} ;
Transaction . prototype . _ validateChange = function ( ) {
if ( ! this . _ change ) {
return 'Missing change address' ;
}
} ;
Transaction . prototype . inspect = function ( ) {
return '<Transaction: ' + this . toString ( ) + '>' ;
} ;
@ -327,10 +361,9 @@ Transaction.prototype._fromMultisigOldUtxo = function(utxo, pubkeys, threshold)
} ;
Transaction . prototype . _ fromMultisigNewUtxo = function ( utxo , pubkeys , threshold ) {
this . _ changeSetup = false ;
utxo . address = utxo . address && new Address ( utxo . address ) ;
utxo . script = new Script ( util . isHexa ( utxo . script ) ? new buffer . Buffer ( utxo . script , 'hex' ) : utxo . script ) ;
this . inputs . push ( new MultiSigScriptHashInput ( {
this . addInput ( new MultiSigScriptHashInput ( {
output : new Output ( {
script : utxo . script ,
satoshis : utxo . satoshis
@ -340,7 +373,35 @@ Transaction.prototype._fromMultisigNewUtxo = function(utxo, pubkeys, threshold)
sequenceNumber : DEFAULT_SEQNUMBER ,
script : Script . empty ( )
} , pubkeys , threshold ) ) ;
this . _ inputAmount += utxo . satoshis ;
} ;
/ * *
* Add an input to this transaction . The input must be an instance of the ` Input ` class .
* It should have information about the Output that it 's spending, but if it' s not already
* set , two additional parameters , ` outputScript ` and ` satoshis ` can be provided .
*
* @ param { Input } input
* @ param { String | Script } outputScript
* @ param { number } satoshis
* @ return Transaction this , for chaining
* /
Transaction . prototype . addInput = function ( input , outputScript , satoshis ) {
$ . checkArgumentType ( input , Input , 'input' ) ;
if ( ! input . output || ! ( input . output instanceof Output ) && ! outputScript && ! satoshis ) {
throw new Transaction . NeedMoreInfo ( 'Need information about the UTXO script and satoshis' ) ;
}
if ( ! input . output && outputScript && satoshis ) {
outputScript = outputScript instanceof Script ? outputScript : new Script ( outputScript ) ;
$ . checkArgumentType ( satoshis , 'number' , 'satoshis' ) ;
input . output = new Output ( {
script : outputScript ,
satoshis : satoshis
} ) ;
}
this . _ changeSetup = false ;
this . inputs . push ( input ) ;
this . _ inputAmount += input . output . satoshis ;
return this ;
} ;
/ * *
@ -396,7 +457,7 @@ Transaction.prototype.change = function(address) {
* @ return { Transaction } this , for chaining
* /
Transaction . prototype . to = function ( address , amount ) {
this . _ addOutput ( new Output ( {
this . addOutput ( new Output ( {
script : Script ( new Address ( address ) ) ,
satoshis : amount
} ) ) ;
@ -414,14 +475,15 @@ Transaction.prototype.to = function(address, amount) {
* @ return { Transaction } this , for chaining
* /
Transaction . prototype . addData = function ( value ) {
this . _ addOutput ( new Output ( {
this . addOutput ( new Output ( {
script : Script . buildDataOut ( value ) ,
satoshis : 0
} ) ) ;
return this ;
} ;
Transaction . prototype . _ addOutput = function ( output ) {
Transaction . prototype . addOutput = function ( output ) {
$ . checkArgumentType ( output , Output , 'output' ) ;
this . outputs . push ( output ) ;
this . _ changeSetup = false ;
this . _ outputAmount += output . satoshis ;
@ -440,12 +502,11 @@ Transaction.prototype._updateChangeOutput = function() {
if ( ! _ . isUndefined ( this . _ changeOutput ) ) {
this . removeOutput ( this . _ changeOutput ) ;
}
var estimatedSize = this . _ estimateSize ( ) ;
var available = this . _ inputAmount - this . _ outputAmount ;
var fee = this . _ fee || Transaction . _ estimateFee ( estimatedSize , available ) ;
var available = this . _ getUnspentValue ( ) ;
var fee = this . getFee ( ) ;
if ( available - fee > 0 ) {
this . _ changeOutput = this . outputs . length ;
this . _ addOutput ( new Output ( {
this . addOutput ( new Output ( {
script : Script . fromAddress ( this . _ change ) ,
satoshis : available - fee
} ) ) ;
@ -455,6 +516,20 @@ Transaction.prototype._updateChangeOutput = function() {
this . _ changeSetup = true ;
} ;
Transaction . prototype . getFee = function ( ) {
return this . _ fee || this . _ estimateFee ( ) ;
} ;
Transaction . prototype . _ estimateFee = function ( ) {
var estimatedSize = this . _ estimateSize ( ) ;
var available = this . _ getUnspentValue ( ) ;
return Transaction . _ estimateFee ( estimatedSize , available ) ;
} ;
Transaction . prototype . _ getUnspentValue = function ( ) {
return this . _ inputAmount - this . _ outputAmount ;
} ;
Transaction . prototype . _ clearSignatures = function ( ) {
_ . each ( this . inputs , function ( input ) {
input . clearSignatures ( ) ;