forked from bitcoinjs/coinselect
-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.js
74 lines (61 loc) · 2.04 KB
/
utils.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// baseline estimates, used to improve performance
var TX_EMPTY_SIZE = 4 + 1 + 1 + 4
var TX_INPUT_BASE = 32 + 4 + 1 + 4
var TX_INPUT_PUBKEYHASH = 107
var TX_OUTPUT_BASE = 8 + 1
var TX_OUTPUT_PUBKEYHASH = 25
function inputBytes (input) {
return TX_INPUT_BASE + (input.script ? input.script.length : TX_INPUT_PUBKEYHASH)
}
function outputBytes (output) {
return TX_OUTPUT_BASE + (output.script ? output.script.length : TX_OUTPUT_PUBKEYHASH)
}
function dustThreshold (output, feeRate) {
/* ... classify the output for input estimate */
return inputBytes({}) * feeRate
}
function transactionBytes (inputs, outputs) {
return TX_EMPTY_SIZE +
inputs.reduce(function (a, x) { return a + inputBytes(x) }, 0) +
outputs.reduce(function (a, x) { return a + outputBytes(x) }, 0)
}
function uintOrNaN (v) {
if (typeof v !== 'number') return NaN
if (!isFinite(v)) return NaN
if (Math.floor(v) !== v) return NaN
if (v < 0) return NaN
return v
}
function sumForgiving (range) {
return range.reduce(function (a, x) { return a + (isFinite(x.value) ? x.value : 0) }, 0)
}
function sumOrNaN (range) {
return range.reduce(function (a, x) { return a + uintOrNaN(x.value) }, 0)
}
var BLANK_OUTPUT = outputBytes({})
function finalize (inputs, outputs, feeRate) {
var bytesAccum = transactionBytes(inputs, outputs)
var feeAfterExtraOutput = feeRate * (bytesAccum + BLANK_OUTPUT)
var remainderAfterExtraOutput = sumOrNaN(inputs) - (sumOrNaN(outputs) + feeAfterExtraOutput)
// is it worth a change output?
if (remainderAfterExtraOutput > dustThreshold({}, feeRate)) {
outputs = outputs.concat({ value: remainderAfterExtraOutput })
}
var fee = sumOrNaN(inputs) - sumOrNaN(outputs)
if (!isFinite(fee)) return { fee: feeRate * bytesAccum }
return {
inputs: inputs,
outputs: outputs,
fee: fee
}
}
module.exports = {
dustThreshold: dustThreshold,
finalize: finalize,
inputBytes: inputBytes,
outputBytes: outputBytes,
sumOrNaN: sumOrNaN,
sumForgiving: sumForgiving,
transactionBytes: transactionBytes,
uintOrNaN: uintOrNaN
}