@ -186,8 +186,12 @@ thinwalletCtrls.controller('SendCoinsCtrl', function($scope, $http, $q, AccountS
}
} ) ( deferred , target ) ;
}
// Transaction will need at least 1KB fee (13KB for RingCT)
var neededFee = rct ? config . feePerKB . multiply ( 13 ) : config . feePerKB ;
var feePerKB = new JSBigInt ( config . feePerKB ) ;
var neededFee = rct ? feePerKB . multiply ( 13 ) : feePerKB ;
var totalAmountWithoutFee ;
var unspentOuts ;
var pid _encrypt = false ; //don't encrypt payment ID unless we find an integrated one
@ -247,6 +251,10 @@ thinwalletCtrls.controller('SendCoinsCtrl', function($scope, $http, $q, AccountS
unused _outs = unspentOuts . slice ( 0 ) ;
using _outs = [ ] ;
using _outs _amount = new JSBigInt ( 0 ) ;
if ( data . per _kb _fee )
{
feePerKB = new JSBigInt ( data . per _kb _fee ) ;
}
transfer ( ) . then ( transferSuccess , transferFailure ) ;
} )
. error ( function ( data ) {
@ -297,7 +305,7 @@ thinwalletCtrls.controller('SendCoinsCtrl', function($scope, $http, $q, AccountS
numKB ++ ;
}
console . log ( txBlobBytes + " bytes <= " + numKB + " KB (current fee: " + cnUtil . formatMoneyFull ( prevFee ) + ")" ) ;
neededFee = config. feePerKB. multiply ( numKB ) ;
neededFee = feePerKB. multiply ( numKB ) ;
// if we need a higher fee
if ( neededFee . compare ( prevFee ) > 0 ) {
console . log ( "Previous fee: " + cnUtil . formatMoneyFull ( prevFee ) + " New fee: " + cnUtil . formatMoneyFull ( neededFee ) ) ;
@ -387,28 +395,37 @@ thinwalletCtrls.controller('SendCoinsCtrl', function($scope, $http, $q, AccountS
select _outputs ( totalAmount ) ;
//compute fee as closely as possible before hand
if ( using _outs . length > 1 && rct ) {
var newNeededFee = JSBigInt ( Math . ceil ( cnUtil . estimateRctSize ( using _outs . length , mixin , 2 ) / 1024 ) ) . multiply ( config . feePerKB ) ;
if ( using _outs . length > 1 && rct )
{
var newNeededFee = JSBigInt ( Math . ceil ( cnUtil . estimateRctSize ( using _outs . length , mixin , 2 ) / 1024 ) ) . multiply ( feePerKB ) ;
totalAmount = totalAmountWithoutFee . add ( newNeededFee ) ;
//add outputs 1 at a time till we either have them all or can meet the fee
while ( using _outs _amount . compare ( totalAmount ) < 0 && unused _outs . length > 0 ) {
while ( using _outs _amount . compare ( totalAmount ) < 0 && unused _outs . length > 0 )
{
var out = pop _random _value ( unused _outs ) ;
using _outs . push ( out ) ;
using _outs _amount = using _outs _amount . add ( out . amount ) ;
console . log ( "Using output: " + cnUtil . formatMoney ( out . amount ) + " - " + JSON . stringify ( out ) ) ;
newNeededFee = JSBigInt ( Math . ceil ( cnUtil . estimateRctSize ( using _outs . length , mixin , 2 ) / 1024 ) ) . multiply ( config. feePerKB) ;
newNeededFee = JSBigInt ( Math . ceil ( cnUtil . estimateRctSize ( using _outs . length , mixin , 2 ) / 1024 ) ) . multiply ( feePerKB) ;
totalAmount = totalAmountWithoutFee . add ( newNeededFee ) ;
}
console . log ( "New fee: " + cnUtil . formatMoneySymbol ( newNeededFee ) + " for " + using _outs . length + " inputs" ) ;
neededFee = newNeededFee ;
}
if ( using _outs _amount . compare ( totalAmount ) < 0 ) {
deferred . reject ( "Not enough spendable outputs / balance too low (have: " + cnUtil . formatMoneyFull ( using _outs _amount ) + " need: " + cnUtil . formatMoneyFull ( totalAmount ) + ")" ) ;
if ( using _outs _amount . compare ( totalAmount ) < 0 )
{
deferred . reject ( "Not enough spendable outputs / balance too low (have: "
+ cnUtil . formatMoneyFull ( using _outs _amount ) + " need: "
+ cnUtil . formatMoneyFull ( totalAmount ) + ")" ) ;
return ;
} else if ( using _outs _amount . compare ( totalAmount ) > 0 ) {
}
else if ( using _outs _amount . compare ( totalAmount ) > 0 )
{
var changeAmount = using _outs _amount . subtract ( totalAmount ) ;
if ( ! rct ) { //for rct we don't presently care about dustiness
if ( ! rct )
{ //for rct we don't presently care about dustiness
//do not give ourselves change < dust threshold
var changeAmountDivRem = changeAmount . divRem ( config . dustThreshold ) ;
if ( changeAmountDivRem [ 1 ] . toString ( ) !== "0" ) {
@ -424,15 +441,20 @@ thinwalletCtrls.controller('SendCoinsCtrl', function($scope, $http, $q, AccountS
amount : usableChange
} ) ;
}
} else {
}
else
{
//add entire change for rct
console . log ( "Sending change of " + cnUtil . formatMoneySymbol ( changeAmount ) + " to " + AccountService . getAddress ( ) ) ;
console . log ( "Sending change of " + cnUtil . formatMoneySymbol ( changeAmount )
+ " to " + AccountService . getAddress ( ) ) ;
dsts . push ( {
address : AccountService . getAddress ( ) ,
amount : changeAmount
} ) ;
}
} else if ( using _outs _amount . compare ( totalAmount ) === 0 && rct ) {
}
else if ( using _outs _amount . compare ( totalAmount ) === 0 && rct )
{
//create random destination to keep 2 outputs always in case of 0 change
var fakeAddress = cnUtil . create _address ( cnUtil . random _scalar ( ) ) . public _addr ;
console . log ( "Sending 0 XMR to a fake address to keep tx uniform (no change exists): " + fakeAddress ) ;
@ -442,9 +464,11 @@ thinwalletCtrls.controller('SendCoinsCtrl', function($scope, $http, $q, AccountS
} ) ;
}
if ( mixin > 0 ) {
if ( mixin > 0 )
{
var amounts = [ ] ;
for ( var l = 0 ; l < using _outs . length ; l ++ ) {
for ( var l = 0 ; l < using _outs . length ; l ++ )
{
amounts . push ( using _outs [ l ] . rct ? "0" : using _outs [ l ] . amount . toString ( ) ) ;
}
var request = {
@ -470,18 +494,24 @@ thinwalletCtrls.controller('SendCoinsCtrl', function($scope, $http, $q, AccountS
}
// Create & serialize transaction
function createTx ( mix _outs ) {
function createTx ( mix _outs )
{
var signed ;
try {
console . log ( 'Destinations: ' ) ;
cnUtil . printDsts ( dsts ) ;
//need to get viewkey for encrypting here, because of splitting and sorting
if ( pid _encrypt ) {
if ( pid _encrypt )
{
var realDestViewKey = cnUtil . decode _address ( dsts [ 0 ] . address ) . view ;
}
var splittedDsts = cnUtil . decompose _tx _destinations ( dsts , rct ) ;
console . log ( 'Decomposed destinations:' ) ;
cnUtil . printDsts ( splittedDsts ) ;
signed = cnUtil . create _transaction (
AccountService . getPublicKeys ( ) ,
AccountService . getSecretKeys ( ) ,