more tx refactoring.
This commit is contained in:
parent
b147951a83
commit
c94457cf1f
103
lib/bcoin/tx.js
103
lib/bcoin/tx.js
@ -41,10 +41,6 @@ function TX(data, block) {
|
||||
|
||||
this._lock = this.lock;
|
||||
|
||||
this._fee = !(data instanceof bcoin.tx)
|
||||
? data.fee
|
||||
: data._fee;
|
||||
|
||||
if (data.inputs) {
|
||||
data.inputs.forEach(function(input) {
|
||||
this.input(input, null);
|
||||
@ -64,8 +60,9 @@ function TX(data, block) {
|
||||
}
|
||||
}
|
||||
|
||||
this.hardFee = data.hardFee || null;
|
||||
this.changeAddress = data.changeAddress || null;
|
||||
this.changeOutput = data.changeOutput || null;
|
||||
this.changeIndex = data.changeIndex || -1;
|
||||
|
||||
// ps = Pending Since
|
||||
this.ps = this.ts === 0 ? utils.now() : 0;
|
||||
@ -785,7 +782,7 @@ TX.prototype.maxSize = function maxSize() {
|
||||
return total;
|
||||
};
|
||||
|
||||
TX.prototype.getUnspent = function getUnspent(unspent, fee) {
|
||||
TX.prototype.getUnspent = function getUnspent(unspent, address, fee) {
|
||||
var tx = this.clone();
|
||||
var cost = tx.funds('out');
|
||||
var totalkb = 1;
|
||||
@ -794,12 +791,9 @@ TX.prototype.getUnspent = function getUnspent(unspent, fee) {
|
||||
var lastAdded = 0;
|
||||
var size, newkb, change;
|
||||
|
||||
if (!fee)
|
||||
fee = this._fee;
|
||||
|
||||
if (fee) {
|
||||
total = cost.add(fee);
|
||||
this._fee = fee;
|
||||
this.hardFee = fee;
|
||||
}
|
||||
|
||||
function addInput(unspent) {
|
||||
@ -819,7 +813,7 @@ TX.prototype.getUnspent = function getUnspent(unspent, fee) {
|
||||
// Add dummy output (for `change`) to
|
||||
// calculate maximum TX size.
|
||||
tx.output({
|
||||
script: [],
|
||||
address: address,
|
||||
value: new bn(0)
|
||||
});
|
||||
|
||||
@ -839,15 +833,13 @@ TX.prototype.getUnspent = function getUnspent(unspent, fee) {
|
||||
} while (tx.funds('in').cmp(total) < 0 && lastAdded < unspent.length);
|
||||
}
|
||||
|
||||
// Expose `total`. Useful for error messages.
|
||||
this.total = total;
|
||||
|
||||
// Still failing to get enough funds.
|
||||
if (tx.funds('in').cmp(total) < 0)
|
||||
return;
|
||||
|
||||
// How much money is left after filling outputs.
|
||||
change = tx.funds('in').sub(total);
|
||||
if (tx.funds('in').cmp(total) < 0) {
|
||||
// Still failing to get enough funds.
|
||||
inputs = null;
|
||||
} else {
|
||||
// How much money is left after filling outputs.
|
||||
change = tx.funds('in').sub(total);
|
||||
}
|
||||
|
||||
// Return necessary inputs and change.
|
||||
return {
|
||||
@ -855,22 +847,26 @@ TX.prototype.getUnspent = function getUnspent(unspent, fee) {
|
||||
change: change,
|
||||
cost: cost,
|
||||
fee: total.sub(cost),
|
||||
total: total
|
||||
total: total,
|
||||
kb: totalkb
|
||||
};
|
||||
};
|
||||
|
||||
TX.prototype.fillUnspent = function fillUnspent(unspent, changeAddress, fee) {
|
||||
var result = this.getUnspent(unspent, fee);
|
||||
TX.prototype.fillUnspent = function fillUnspent(unspent, address, fee) {
|
||||
var result;
|
||||
|
||||
if (address)
|
||||
this.changeAddress = address;
|
||||
|
||||
if (fee)
|
||||
this._fee = fee;
|
||||
this.hardFee = fee;
|
||||
|
||||
if (!result)
|
||||
return;
|
||||
assert(this.changeAddress);
|
||||
|
||||
this.changeAddress = changeAddress
|
||||
|| this.changeAddress
|
||||
|| result.inputs[0].output.address;
|
||||
result = this.getUnspent(unspent, this.changeAddress, this.hardFee);
|
||||
|
||||
if (!result.inputs)
|
||||
return result;
|
||||
|
||||
result.inputs.forEach(function(input) {
|
||||
this.input(input);
|
||||
@ -882,27 +878,24 @@ TX.prototype.fillUnspent = function fillUnspent(unspent, changeAddress, fee) {
|
||||
this.getFee().toNumber(),
|
||||
result.fee.add(result.change).toNumber()
|
||||
);
|
||||
this.changeOutput = null;
|
||||
this.changeIndex = -1;
|
||||
} else {
|
||||
if (!this.changeAddress)
|
||||
throw new Error('No change address');
|
||||
|
||||
this.output({
|
||||
address: this.changeAddress,
|
||||
value: result.change
|
||||
});
|
||||
|
||||
this.changeOutput = this.outputs[this.outputs.length - 1];
|
||||
this.changeIndex = this.outputs.length - 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
TX.prototype._recalculateFee = function recalculateFee() {
|
||||
var output = this.changeOutput;
|
||||
var output = this.outputs[this.changeIndex];
|
||||
var size, real, fee;
|
||||
|
||||
if (this._fee)
|
||||
if (this.hardFee)
|
||||
return;
|
||||
|
||||
if (!output) {
|
||||
@ -918,7 +911,7 @@ TX.prototype._recalculateFee = function recalculateFee() {
|
||||
fee = this.getFee().toNumber();
|
||||
|
||||
if (real === fee) {
|
||||
if (!this.changeOutput)
|
||||
if (this.changeIndex === -1)
|
||||
this.outputs.pop();
|
||||
return;
|
||||
}
|
||||
@ -926,7 +919,7 @@ TX.prototype._recalculateFee = function recalculateFee() {
|
||||
if (real > fee) {
|
||||
if (output.value.cmpn(real - fee) < 0) {
|
||||
this.outputs.pop();
|
||||
this.changeOutput = null;
|
||||
this.changeIndex = -1;
|
||||
return;
|
||||
}
|
||||
output.value.isubn(real - fee);
|
||||
@ -936,11 +929,11 @@ TX.prototype._recalculateFee = function recalculateFee() {
|
||||
|
||||
if (output.value.cmpn(constants.tx.dust) < 0) {
|
||||
this.outputs.pop();
|
||||
this.changeOutput = null;
|
||||
this.changeIndex = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
this.changeOutput = output;
|
||||
this.changeIndex = this.outputs.indexOf(output);
|
||||
};
|
||||
|
||||
TX.prototype.getFee = function getFee() {
|
||||
@ -1247,7 +1240,9 @@ TX.prototype.toJSON = function toJSON() {
|
||||
block: this.block,
|
||||
network: this.network,
|
||||
relayedBy: this.relayedBy,
|
||||
changeIndex: this.outputs.indexOf(this.changeOutput),
|
||||
changeAddress: this.changeAddress,
|
||||
changeIndex: this.changeIndex,
|
||||
hardFee: this.hardFee ? utils.btc(this.hardFee) : null,
|
||||
tx: utils.toHex(this.render())
|
||||
};
|
||||
};
|
||||
@ -1264,6 +1259,12 @@ TX.fromJSON = function fromJSON(json) {
|
||||
data.network = json.network;
|
||||
data.relayedBy = json.relayedBy;
|
||||
|
||||
data.changeAddress = json.changeAddress;
|
||||
data.changeIndex = json.changeIndex;
|
||||
|
||||
if (json.hardFee)
|
||||
data.hardFee = utils.satoshi(json.hardFee);
|
||||
|
||||
data._raw = raw;
|
||||
data._size = raw.length;
|
||||
|
||||
@ -1272,14 +1273,24 @@ TX.fromJSON = function fromJSON(json) {
|
||||
tx.block = json.block || null;
|
||||
tx.ps = json.ps;
|
||||
|
||||
if (data.changeIndex >= 0) {
|
||||
tx.changeOutput = tx.outputs[data.changeIndex];
|
||||
assert(tx.changeOutput);
|
||||
}
|
||||
|
||||
return tx;
|
||||
};
|
||||
|
||||
TX.prototype.toRaw = function toRaw(enc) {
|
||||
var raw = this.render();
|
||||
|
||||
if (enc === 'hex')
|
||||
return utils.toHex(raw);
|
||||
|
||||
return raw;
|
||||
};
|
||||
|
||||
TX.fromRaw = function fromRaw(raw, enc) {
|
||||
if (enc === 'hex')
|
||||
raw = utils.toArray(raw, 'hex');
|
||||
return new bcoin.protocol.parser().parseTX(raw);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
@ -436,16 +436,11 @@ Wallet.prototype.ownInput = function ownInput(tx, index) {
|
||||
return inputs;
|
||||
};
|
||||
|
||||
Wallet.prototype.scriptOutputs = function scriptOutputs(tx, options) {
|
||||
outputs.forEach(function(output) {
|
||||
tx.scriptOutput(output, output);
|
||||
});
|
||||
return outputs.length;
|
||||
};
|
||||
Wallet.prototype.fillUnspent = function fillUnspent(tx, address, fee) {
|
||||
if (!address)
|
||||
address = this.changeAddress || this.getAddress();
|
||||
|
||||
Wallet.prototype.fillUnspent = function fillUnspent(tx, changeAddress) {
|
||||
changeAddress = changeAddress || this.changeAddress || this.getAddress();
|
||||
return tx.fillUnspent(this.unspent(), changeAddress);
|
||||
return tx.fillUnspent(this.unspent(), address, fee);
|
||||
};
|
||||
|
||||
Wallet.prototype.fillTX = function fillTX(tx) {
|
||||
@ -546,9 +541,9 @@ Wallet.prototype.fill = function fill(tx, changeAddress, cb) {
|
||||
|
||||
result = this.fillUnspent(tx, changeAddress);
|
||||
|
||||
if (!result) {
|
||||
if (!result.inputs) {
|
||||
err = new Error('Not enough funds');
|
||||
err.minBalance = tx.total;
|
||||
err.minBalance = result.total;
|
||||
cb(err);
|
||||
return null;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user