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