@onetokenfe/coinselect 3.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +95 -0
- package/accumulative.js +38 -0
- package/blackjack.js +35 -0
- package/break.js +34 -0
- package/index.js +21 -0
- package/package.json +82 -0
- package/split.js +45 -0
- package/third-party/utils/addDashesToSpaces.d.ts +2 -0
- package/third-party/utils/addDashesToSpaces.js +6 -0
- package/third-party/utils/arrayDistinct.d.ts +2 -0
- package/third-party/utils/arrayDistinct.js +6 -0
- package/third-party/utils/arrayPartition.d.ts +7 -0
- package/third-party/utils/arrayPartition.js +6 -0
- package/third-party/utils/arrayShuffle.d.ts +4 -0
- package/third-party/utils/arrayShuffle.js +13 -0
- package/third-party/utils/arrayToDictionary.d.ts +10 -0
- package/third-party/utils/arrayToDictionary.js +27 -0
- package/third-party/utils/asciiUtils.d.ts +3 -0
- package/third-party/utils/asciiUtils.js +16 -0
- package/third-party/utils/bigNumber.d.ts +5 -0
- package/third-party/utils/bigNumber.js +9 -0
- package/third-party/utils/bufferUtils.d.ts +3 -0
- package/third-party/utils/bufferUtils.js +23 -0
- package/third-party/utils/bytesToHumanReadable.d.ts +2 -0
- package/third-party/utils/bytesToHumanReadable.js +15 -0
- package/third-party/utils/capitalizeFirstLetter.d.ts +2 -0
- package/third-party/utils/capitalizeFirstLetter.js +6 -0
- package/third-party/utils/cloneObject.d.ts +2 -0
- package/third-party/utils/cloneObject.js +32 -0
- package/third-party/utils/countBytesInString.d.ts +2 -0
- package/third-party/utils/countBytesInString.js +6 -0
- package/third-party/utils/createCooldown.d.ts +2 -0
- package/third-party/utils/createCooldown.js +16 -0
- package/third-party/utils/createDeferred.d.ts +14 -0
- package/third-party/utils/createDeferred.js +19 -0
- package/third-party/utils/createDeferredManager.d.ts +19 -0
- package/third-party/utils/createDeferredManager.js +67 -0
- package/third-party/utils/createLazy.d.ts +7 -0
- package/third-party/utils/createLazy.js +42 -0
- package/third-party/utils/createTimeoutPromise.d.ts +2 -0
- package/third-party/utils/createTimeoutPromise.js +6 -0
- package/third-party/utils/enumUtils.d.ts +6 -0
- package/third-party/utils/enumUtils.js +12 -0
- package/third-party/utils/extractUrlsFromText.d.ts +5 -0
- package/third-party/utils/extractUrlsFromText.js +28 -0
- package/third-party/utils/getLocaleSeparators.d.ts +5 -0
- package/third-party/utils/getLocaleSeparators.js +13 -0
- package/third-party/utils/getLocaleSeparators.native.d.ts +5 -0
- package/third-party/utils/getLocaleSeparators.native.js +17 -0
- package/third-party/utils/getMutex.d.ts +2 -0
- package/third-party/utils/getMutex.js +22 -0
- package/third-party/utils/getNumberFromPixelString.d.ts +2 -0
- package/third-party/utils/getNumberFromPixelString.js +6 -0
- package/third-party/utils/getRandomInt.d.ts +2 -0
- package/third-party/utils/getRandomInt.js +56 -0
- package/third-party/utils/getSynchronize.d.ts +4 -0
- package/third-party/utils/getSynchronize.js +10 -0
- package/third-party/utils/getWeakRandomId.d.ts +2 -0
- package/third-party/utils/getWeakRandomId.js +13 -0
- package/third-party/utils/getWeakRandomInt.d.ts +2 -0
- package/third-party/utils/getWeakRandomInt.js +11 -0
- package/third-party/utils/getWeakRandomNumberInRange.d.ts +2 -0
- package/third-party/utils/getWeakRandomNumberInRange.js +6 -0
- package/third-party/utils/hasUppercaseLetter.d.ts +2 -0
- package/third-party/utils/hasUppercaseLetter.js +7 -0
- package/third-party/utils/index.d.ts +52 -0
- package/third-party/utils/index.js +56 -0
- package/third-party/utils/isArrayMember.d.ts +2 -0
- package/third-party/utils/isArrayMember.js +6 -0
- package/third-party/utils/isFullPath.d.ts +2 -0
- package/third-party/utils/isFullPath.js +9 -0
- package/third-party/utils/isHex.d.ts +2 -0
- package/third-party/utils/isHex.js +9 -0
- package/third-party/utils/isNotUndefined.d.ts +2 -0
- package/third-party/utils/isNotUndefined.js +6 -0
- package/third-party/utils/isUrl.d.ts +2 -0
- package/third-party/utils/isUrl.js +7 -0
- package/third-party/utils/logs.d.ts +32 -0
- package/third-party/utils/logs.js +82 -0
- package/third-party/utils/logsManager.d.ts +17 -0
- package/third-party/utils/logsManager.js +53 -0
- package/third-party/utils/mergeDeepObject.d.ts +26 -0
- package/third-party/utils/mergeDeepObject.js +68 -0
- package/third-party/utils/objectPartition.d.ts +6 -0
- package/third-party/utils/objectPartition.js +12 -0
- package/third-party/utils/parseElectrumUrl.d.ts +6 -0
- package/third-party/utils/parseElectrumUrl.js +17 -0
- package/third-party/utils/parseHostname.d.ts +2 -0
- package/third-party/utils/parseHostname.js +7 -0
- package/third-party/utils/promiseAllSequence.d.ts +2 -0
- package/third-party/utils/promiseAllSequence.js +14 -0
- package/third-party/utils/redactUserPath.d.ts +3 -0
- package/third-party/utils/redactUserPath.js +7 -0
- package/third-party/utils/scheduleAction.d.ts +15 -0
- package/third-party/utils/scheduleAction.js +125 -0
- package/third-party/utils/splitStringEveryNCharacters.d.ts +2 -0
- package/third-party/utils/splitStringEveryNCharacters.js +12 -0
- package/third-party/utils/throttler.d.ts +11 -0
- package/third-party/utils/throttler.js +38 -0
- package/third-party/utils/throwError.d.ts +2 -0
- package/third-party/utils/throwError.js +8 -0
- package/third-party/utils/topologicalSort.d.ts +2 -0
- package/third-party/utils/topologicalSort.js +19 -0
- package/third-party/utils/truncateMiddle.d.ts +2 -0
- package/third-party/utils/truncateMiddle.js +12 -0
- package/third-party/utils/typedEventEmitter.d.ts +23 -0
- package/third-party/utils/typedEventEmitter.js +11 -0
- package/third-party/utils/urlToOnion.d.ts +4 -0
- package/third-party/utils/urlToOnion.js +12 -0
- package/third-party/utils/versionUtils.d.ts +9 -0
- package/third-party/utils/versionUtils.js +28 -0
- package/third-party/utils/xssFilters.d.ts +4 -0
- package/third-party/utils/xssFilters.js +13 -0
- package/third-party/utxo-lib/address.d.ts +17 -0
- package/third-party/utxo-lib/address.js +174 -0
- package/third-party/utxo-lib/bip32.d.ts +28 -0
- package/third-party/utxo-lib/bip32.js +253 -0
- package/third-party/utxo-lib/bs58check.d.ts +12 -0
- package/third-party/utxo-lib/bs58check.js +92 -0
- package/third-party/utxo-lib/bufferutils.d.ts +59 -0
- package/third-party/utxo-lib/bufferutils.js +219 -0
- package/third-party/utxo-lib/coinselect/coinselectUtils.d.ts +53 -0
- package/third-party/utxo-lib/coinselect/coinselectUtils.js +232 -0
- package/third-party/utxo-lib/coinselect/index.d.ts +3 -0
- package/third-party/utxo-lib/coinselect/index.js +19 -0
- package/third-party/utxo-lib/coinselect/inputs/accumulative.d.ts +3 -0
- package/third-party/utxo-lib/coinselect/inputs/accumulative.js +55 -0
- package/third-party/utxo-lib/coinselect/inputs/branchAndBound.d.ts +3 -0
- package/third-party/utxo-lib/coinselect/inputs/branchAndBound.js +123 -0
- package/third-party/utxo-lib/coinselect/outputs/split.d.ts +3 -0
- package/third-party/utxo-lib/coinselect/outputs/split.js +35 -0
- package/third-party/utxo-lib/coinselect/tryconfirmed.d.ts +3 -0
- package/third-party/utxo-lib/coinselect/tryconfirmed.js +65 -0
- package/third-party/utxo-lib/compose/index.d.ts +3 -0
- package/third-party/utxo-lib/compose/index.js +20 -0
- package/third-party/utxo-lib/compose/request.d.ts +5 -0
- package/third-party/utxo-lib/compose/request.js +168 -0
- package/third-party/utxo-lib/compose/result.d.ts +4 -0
- package/third-party/utxo-lib/compose/result.js +64 -0
- package/third-party/utxo-lib/compose/sorting/bip69SortingStrategy.d.ts +3 -0
- package/third-party/utxo-lib/compose/sorting/bip69SortingStrategy.js +32 -0
- package/third-party/utxo-lib/compose/sorting/convertOutput.d.ts +13 -0
- package/third-party/utxo-lib/compose/sorting/convertOutput.js +14 -0
- package/third-party/utxo-lib/compose/sorting/noneSortingStrategy.d.ts +3 -0
- package/third-party/utxo-lib/compose/sorting/noneSortingStrategy.js +19 -0
- package/third-party/utxo-lib/compose/sorting/randomSortingStrategy.d.ts +3 -0
- package/third-party/utxo-lib/compose/sorting/randomSortingStrategy.js +28 -0
- package/third-party/utxo-lib/compose/sorting/sortingStrategy.d.ts +9 -0
- package/third-party/utxo-lib/compose/sorting/sortingStrategy.js +3 -0
- package/third-party/utxo-lib/compose/transaction.d.ts +3 -0
- package/third-party/utxo-lib/compose/transaction.js +16 -0
- package/third-party/utxo-lib/crypto.d.ts +9 -0
- package/third-party/utxo-lib/crypto.js +44 -0
- package/third-party/utxo-lib/derivation.d.ts +24 -0
- package/third-party/utxo-lib/derivation.js +121 -0
- package/third-party/utxo-lib/discovery.d.ts +9 -0
- package/third-party/utxo-lib/discovery.js +30 -0
- package/third-party/utxo-lib/global.d.ts +62 -0
- package/third-party/utxo-lib/global.js +2 -0
- package/third-party/utxo-lib/index.d.ts +18 -0
- package/third-party/utxo-lib/index.js +28 -0
- package/third-party/utxo-lib/networks.d.ts +45 -0
- package/third-party/utxo-lib/networks.js +250 -0
- package/third-party/utxo-lib/payments/embed.d.ts +3 -0
- package/third-party/utxo-lib/payments/embed.js +49 -0
- package/third-party/utxo-lib/payments/index.d.ts +13 -0
- package/third-party/utxo-lib/payments/index.js +28 -0
- package/third-party/utxo-lib/payments/lazy.d.ts +3 -0
- package/third-party/utxo-lib/payments/lazy.js +33 -0
- package/third-party/utxo-lib/payments/p2ms.d.ts +3 -0
- package/third-party/utxo-lib/payments/p2ms.js +139 -0
- package/third-party/utxo-lib/payments/p2pk.d.ts +3 -0
- package/third-party/utxo-lib/payments/p2pk.js +72 -0
- package/third-party/utxo-lib/payments/p2pkh.d.ts +3 -0
- package/third-party/utxo-lib/payments/p2pkh.js +132 -0
- package/third-party/utxo-lib/payments/p2sh.d.ts +3 -0
- package/third-party/utxo-lib/payments/p2sh.js +171 -0
- package/third-party/utxo-lib/payments/p2tr.d.ts +3 -0
- package/third-party/utxo-lib/payments/p2tr.js +123 -0
- package/third-party/utxo-lib/payments/p2wpkh.d.ts +3 -0
- package/third-party/utxo-lib/payments/p2wpkh.js +137 -0
- package/third-party/utxo-lib/payments/p2wsh.d.ts +3 -0
- package/third-party/utxo-lib/payments/p2wsh.js +183 -0
- package/third-party/utxo-lib/payments/sstxchange.d.ts +3 -0
- package/third-party/utxo-lib/payments/sstxchange.js +79 -0
- package/third-party/utxo-lib/payments/sstxcommitment.d.ts +3 -0
- package/third-party/utxo-lib/payments/sstxcommitment.js +74 -0
- package/third-party/utxo-lib/payments/sstxpkh.d.ts +3 -0
- package/third-party/utxo-lib/payments/sstxpkh.js +79 -0
- package/third-party/utxo-lib/payments/sstxsh.d.ts +3 -0
- package/third-party/utxo-lib/payments/sstxsh.js +70 -0
- package/third-party/utxo-lib/script/index.d.ts +17 -0
- package/third-party/utxo-lib/script/index.js +167 -0
- package/third-party/utxo-lib/script/ops.d.ts +4 -0
- package/third-party/utxo-lib/script/ops.js +13 -0
- package/third-party/utxo-lib/script/scriptNumber.d.ts +3 -0
- package/third-party/utxo-lib/script/scriptNumber.js +62 -0
- package/third-party/utxo-lib/script/scriptSignature.d.ts +8 -0
- package/third-party/utxo-lib/script/scriptSignature.js +55 -0
- package/third-party/utxo-lib/transaction/base.d.ts +56 -0
- package/third-party/utxo-lib/transaction/base.js +108 -0
- package/third-party/utxo-lib/transaction/bitcoin.d.ts +4 -0
- package/third-party/utxo-lib/transaction/bitcoin.js +109 -0
- package/third-party/utxo-lib/transaction/dash.d.ts +8 -0
- package/third-party/utxo-lib/transaction/dash.js +105 -0
- package/third-party/utxo-lib/transaction/decred.d.ts +4 -0
- package/third-party/utxo-lib/transaction/decred.js +149 -0
- package/third-party/utxo-lib/transaction/index.d.ts +15 -0
- package/third-party/utxo-lib/transaction/index.js +44 -0
- package/third-party/utxo-lib/transaction/peercoin.d.ts +4 -0
- package/third-party/utxo-lib/transaction/peercoin.js +64 -0
- package/third-party/utxo-lib/transaction/zcash.d.ts +66 -0
- package/third-party/utxo-lib/transaction/zcash.js +451 -0
- package/third-party/utxo-lib/types/coinselect.d.ts +61 -0
- package/third-party/utxo-lib/types/coinselect.js +3 -0
- package/third-party/utxo-lib/types/compose.d.ts +98 -0
- package/third-party/utxo-lib/types/compose.js +10 -0
- package/third-party/utxo-lib/types/index.d.ts +5 -0
- package/third-party/utxo-lib/types/index.js +8 -0
- package/third-party/utxo-lib/types/payments.d.ts +30 -0
- package/third-party/utxo-lib/types/payments.js +3 -0
- package/third-party/utxo-lib/types/typeforce.d.ts +8 -0
- package/third-party/utxo-lib/types/typeforce.js +16 -0
- package/third-party/utxo-lib/vsize.d.ts +13 -0
- package/third-party/utxo-lib/vsize.js +50 -0
- package/utils.js +78 -0
- package/witness.d.ts +70 -0
- package/witness.js +30 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018 Daniel Cousens
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# coinselect
|
|
2
|
+
|
|
3
|
+
[](http://travis-ci.org/bitcoinjs/coinselect)
|
|
4
|
+
[](https://www.npmjs.org/package/coinselect)
|
|
5
|
+
|
|
6
|
+
[](https://github.com/feross/standard)
|
|
7
|
+
|
|
8
|
+
An unspent transaction output (UTXO) selection module for bitcoin.
|
|
9
|
+
|
|
10
|
+
**WARNING:** Value units are in `satoshi`s, **not** Bitcoin.
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## Algorithms
|
|
14
|
+
Module | Algorithm | Re-orders UTXOs?
|
|
15
|
+
-|-|-
|
|
16
|
+
`require('coinselect')` | Blackjack, with Accumulative fallback | By Descending Value
|
|
17
|
+
`require('coinselect/accumulative')` | Accumulative - accumulates inputs until the target value (+fees) is reached, skipping detrimental inputs | -
|
|
18
|
+
`require('coinselect/blackjack')` | Blackjack - accumulates inputs until the target value (+fees) is matched, does not accumulate inputs that go over the target value (within a threshold) | -
|
|
19
|
+
`require('coinselect/break')` | Break - breaks the input values into equal denominations of `output` (as provided) | -
|
|
20
|
+
`require('coinselect/split')` | Split - splits the input values evenly between all `outputs`, any provided `output` with `.value` remains unchanged | -
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
**Note:** Each algorithm will add a change output if the `input - output - fee` value difference is over a dust threshold.
|
|
24
|
+
This is calculated independently by `utils.finalize`, irrespective of the algorithm chosen, for the purposes of safety.
|
|
25
|
+
|
|
26
|
+
**Pro-tip:** if you want to send-all inputs to an output address, `coinselect/split` with a partial output (`.address` defined, no `.value`) can be used to send-all, while leaving an appropriate amount for the `fee`.
|
|
27
|
+
|
|
28
|
+
## Example
|
|
29
|
+
|
|
30
|
+
``` javascript
|
|
31
|
+
let coinSelect = require('coinselect')
|
|
32
|
+
let feeRate = 55 // satoshis per byte
|
|
33
|
+
let utxos = [
|
|
34
|
+
...,
|
|
35
|
+
{
|
|
36
|
+
txId: '...',
|
|
37
|
+
vout: 0,
|
|
38
|
+
...,
|
|
39
|
+
value: 10000,
|
|
40
|
+
// For use with PSBT:
|
|
41
|
+
// not needed for coinSelect, but will be passed on to inputs later
|
|
42
|
+
nonWitnessUtxo: Buffer.from('...full raw hex of txId tx...', 'hex'),
|
|
43
|
+
// OR
|
|
44
|
+
// if your utxo is a segwit output, you can use witnessUtxo instead
|
|
45
|
+
witnessUtxo: {
|
|
46
|
+
script: Buffer.from('... scriptPubkey hex...', 'hex'),
|
|
47
|
+
value: 10000 // 0.0001 BTC and is the exact same as the value above
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
let targets = [
|
|
52
|
+
...,
|
|
53
|
+
{
|
|
54
|
+
address: '1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm',
|
|
55
|
+
value: 5000
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
// ...
|
|
60
|
+
let { inputs, outputs, fee } = coinSelect(utxos, targets, feeRate)
|
|
61
|
+
|
|
62
|
+
// the accumulated fee is always returned for analysis
|
|
63
|
+
console.log(fee)
|
|
64
|
+
|
|
65
|
+
// .inputs and .outputs will be undefined if no solution was found
|
|
66
|
+
if (!inputs || !outputs) return
|
|
67
|
+
|
|
68
|
+
let psbt = new bitcoin.Psbt()
|
|
69
|
+
|
|
70
|
+
inputs.forEach(input =>
|
|
71
|
+
psbt.addInput({
|
|
72
|
+
hash: input.txId,
|
|
73
|
+
index: input.vout,
|
|
74
|
+
nonWitnessUtxo: input.nonWitnessUtxo,
|
|
75
|
+
// OR (not both)
|
|
76
|
+
witnessUtxo: input.witnessUtxo,
|
|
77
|
+
})
|
|
78
|
+
)
|
|
79
|
+
outputs.forEach(output => {
|
|
80
|
+
// watch out, outputs may have been added that you need to provide
|
|
81
|
+
// an output address/script for
|
|
82
|
+
if (!output.address) {
|
|
83
|
+
output.address = wallet.getChangeAddress()
|
|
84
|
+
wallet.nextChangeAddress()
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
psbt.addOutput({
|
|
88
|
+
address: output.address,
|
|
89
|
+
value: output.value,
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
## License [MIT](LICENSE)
|
package/accumulative.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
var utils = require('./utils')
|
|
2
|
+
|
|
3
|
+
// add inputs until we reach or surpass the target value (or deplete)
|
|
4
|
+
// worst-case: O(n)
|
|
5
|
+
module.exports = function accumulative (utxos, outputs, feeRate) {
|
|
6
|
+
if (!isFinite(utils.uintOrNaN(feeRate))) return {}
|
|
7
|
+
var bytesAccum = utils.transactionBytes([], outputs)
|
|
8
|
+
|
|
9
|
+
var inAccum = 0
|
|
10
|
+
var inputs = []
|
|
11
|
+
var outAccum = utils.sumOrNaN(outputs)
|
|
12
|
+
|
|
13
|
+
for (var i = 0; i < utxos.length; ++i) {
|
|
14
|
+
var utxo = utxos[i]
|
|
15
|
+
var utxoBytes = utils.inputBytes(utxo)
|
|
16
|
+
var utxoFee = feeRate * utxoBytes
|
|
17
|
+
var utxoValue = utils.uintOrNaN(utxo.value)
|
|
18
|
+
|
|
19
|
+
// skip detrimental input
|
|
20
|
+
if (utxoFee > utxo.value) {
|
|
21
|
+
if (i === utxos.length - 1) return { fee: feeRate * (bytesAccum + utxoBytes) }
|
|
22
|
+
continue
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
bytesAccum += utxoBytes
|
|
26
|
+
inAccum += utxoValue
|
|
27
|
+
inputs.push(utxo)
|
|
28
|
+
|
|
29
|
+
var fee = feeRate * bytesAccum
|
|
30
|
+
|
|
31
|
+
// go again?
|
|
32
|
+
if (inAccum < outAccum + fee) continue
|
|
33
|
+
|
|
34
|
+
return utils.finalize(inputs, outputs, feeRate)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return { fee: feeRate * bytesAccum }
|
|
38
|
+
}
|
package/blackjack.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
var utils = require('./utils')
|
|
2
|
+
|
|
3
|
+
// only add inputs if they don't bust the target value (aka, exact match)
|
|
4
|
+
// worst-case: O(n)
|
|
5
|
+
module.exports = function blackjack (utxos, outputs, feeRate) {
|
|
6
|
+
if (!isFinite(utils.uintOrNaN(feeRate))) return {}
|
|
7
|
+
|
|
8
|
+
var bytesAccum = utils.transactionBytes([], outputs)
|
|
9
|
+
|
|
10
|
+
var inAccum = 0
|
|
11
|
+
var inputs = []
|
|
12
|
+
var outAccum = utils.sumOrNaN(outputs)
|
|
13
|
+
var threshold = utils.dustThreshold({}, feeRate)
|
|
14
|
+
|
|
15
|
+
for (var i = 0; i < utxos.length; ++i) {
|
|
16
|
+
var input = utxos[i]
|
|
17
|
+
var inputBytes = utils.inputBytes(input)
|
|
18
|
+
var fee = feeRate * (bytesAccum + inputBytes)
|
|
19
|
+
var inputValue = utils.uintOrNaN(input.value)
|
|
20
|
+
|
|
21
|
+
// would it waste value?
|
|
22
|
+
if ((inAccum + inputValue) > (outAccum + fee + threshold)) continue
|
|
23
|
+
|
|
24
|
+
bytesAccum += inputBytes
|
|
25
|
+
inAccum += inputValue
|
|
26
|
+
inputs.push(input)
|
|
27
|
+
|
|
28
|
+
// go again?
|
|
29
|
+
if (inAccum < outAccum + fee) continue
|
|
30
|
+
|
|
31
|
+
return utils.finalize(inputs, outputs, feeRate)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return { fee: feeRate * bytesAccum }
|
|
35
|
+
}
|
package/break.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
var utils = require('./utils')
|
|
2
|
+
|
|
3
|
+
// break utxos into the maximum number of 'output' possible
|
|
4
|
+
module.exports = function broken (utxos, output, feeRate) {
|
|
5
|
+
if (!isFinite(utils.uintOrNaN(feeRate))) return {}
|
|
6
|
+
|
|
7
|
+
var bytesAccum = utils.transactionBytes(utxos, [])
|
|
8
|
+
var value = utils.uintOrNaN(output.value)
|
|
9
|
+
var inAccum = utils.sumOrNaN(utxos)
|
|
10
|
+
if (!isFinite(value) ||
|
|
11
|
+
!isFinite(inAccum)) return { fee: feeRate * bytesAccum }
|
|
12
|
+
|
|
13
|
+
var outputBytes = utils.outputBytes(output)
|
|
14
|
+
var outAccum = 0
|
|
15
|
+
var outputs = []
|
|
16
|
+
|
|
17
|
+
while (true) {
|
|
18
|
+
var fee = feeRate * (bytesAccum + outputBytes)
|
|
19
|
+
|
|
20
|
+
// did we bust?
|
|
21
|
+
if (inAccum < (outAccum + fee + value)) {
|
|
22
|
+
// premature?
|
|
23
|
+
if (outAccum === 0) return { fee: fee }
|
|
24
|
+
|
|
25
|
+
break
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
bytesAccum += outputBytes
|
|
29
|
+
outAccum += value
|
|
30
|
+
outputs.push(output)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return utils.finalize(utxos, outputs, feeRate)
|
|
34
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
var accumulative = require('./accumulative')
|
|
2
|
+
var blackjack = require('./blackjack')
|
|
3
|
+
var utils = require('./utils')
|
|
4
|
+
|
|
5
|
+
// order by descending value, minus the inputs approximate fee
|
|
6
|
+
function utxoScore (x, feeRate) {
|
|
7
|
+
return x.value - (feeRate * utils.inputBytes(x))
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
module.exports = function coinSelect (utxos, outputs, feeRate) {
|
|
11
|
+
utxos = utxos.concat().sort(function (a, b) {
|
|
12
|
+
return utxoScore(b, feeRate) - utxoScore(a, feeRate)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
// attempt to use the blackjack strategy first (no change output)
|
|
16
|
+
var base = blackjack(utxos, outputs, feeRate)
|
|
17
|
+
if (base.inputs) return base
|
|
18
|
+
|
|
19
|
+
// else, try the accumulative strategy
|
|
20
|
+
return accumulative(utxos, outputs, feeRate)
|
|
21
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@onetokenfe/coinselect",
|
|
3
|
+
"version": "3.1.16",
|
|
4
|
+
"description": "A transaction input selection module for bitcoin.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"coinselect",
|
|
7
|
+
"coin",
|
|
8
|
+
"unspents",
|
|
9
|
+
"wallet",
|
|
10
|
+
"BIP32",
|
|
11
|
+
"management",
|
|
12
|
+
"utxo",
|
|
13
|
+
"transaction",
|
|
14
|
+
"fee",
|
|
15
|
+
"optimization",
|
|
16
|
+
"optimizing",
|
|
17
|
+
"bitcoin"
|
|
18
|
+
],
|
|
19
|
+
"homepage": "https://github.com/bitcoinjs/coinselect",
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/bitcoinjs/coinselect/issues"
|
|
22
|
+
},
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"author": "Daniel Cousens",
|
|
25
|
+
"files": [
|
|
26
|
+
"accumulative.js",
|
|
27
|
+
"blackjack.js",
|
|
28
|
+
"break.js",
|
|
29
|
+
"index.js",
|
|
30
|
+
"split.js",
|
|
31
|
+
"utils.js",
|
|
32
|
+
"witness.js",
|
|
33
|
+
"witness.d.ts",
|
|
34
|
+
"third-party/**"
|
|
35
|
+
],
|
|
36
|
+
"main": "index.js",
|
|
37
|
+
"types": "index.d.ts",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/bitcoinjs/coinselect.git"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"coverage": "nyc --exclude='third-party/**' --check-coverage --branches 90 --functions 95 tape test/*.js",
|
|
44
|
+
"standard": "standard",
|
|
45
|
+
"standard:file": "standard --fix",
|
|
46
|
+
"test": "npm run standard && npm run unit",
|
|
47
|
+
"unit": "tape test/*.js",
|
|
48
|
+
"test-witness": "tape test/witness.js"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"nyc": "^15.0.0",
|
|
52
|
+
"standard": "17.1.2",
|
|
53
|
+
"tape": "^4.5.1"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"bchaddrjs": "^0.5.2",
|
|
57
|
+
"bech32": "^2.0.0",
|
|
58
|
+
"bip66": "^2.0.0",
|
|
59
|
+
"bitcoin-ops": "^1.4.1",
|
|
60
|
+
"blake-hash": "^2.0.0",
|
|
61
|
+
"blakejs": "^1.2.1",
|
|
62
|
+
"bn.js": "^5.2.3",
|
|
63
|
+
"bs58": "^6.0.0",
|
|
64
|
+
"bs58check": "^4.0.0",
|
|
65
|
+
"create-hmac": "^1.1.7",
|
|
66
|
+
"int64-buffer": "^1.0.1",
|
|
67
|
+
"pushdata-bitcoin": "^1.0.1",
|
|
68
|
+
"tiny-secp256k1": "^1.1.6",
|
|
69
|
+
"typeforce": "^1.18.0",
|
|
70
|
+
"varuint-bitcoin": "2.0.0",
|
|
71
|
+
"wif": "^5.0.0",
|
|
72
|
+
"bignumber.js": "9.1.2"
|
|
73
|
+
},
|
|
74
|
+
"peerDependencies": {
|
|
75
|
+
"tslib": "^2.6.2"
|
|
76
|
+
},
|
|
77
|
+
"standard": {
|
|
78
|
+
"ignore": [
|
|
79
|
+
"third-party/**"
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
}
|
package/split.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
var utils = require('./utils')
|
|
2
|
+
|
|
3
|
+
// split utxos between each output, ignores outputs with .value defined
|
|
4
|
+
module.exports = function split (utxos, outputs, feeRate) {
|
|
5
|
+
if (!isFinite(utils.uintOrNaN(feeRate))) return {}
|
|
6
|
+
|
|
7
|
+
var bytesAccum = utils.transactionBytes(utxos, outputs)
|
|
8
|
+
var fee = feeRate * bytesAccum
|
|
9
|
+
if (outputs.length === 0) return { fee: fee }
|
|
10
|
+
|
|
11
|
+
var inAccum = utils.sumOrNaN(utxos)
|
|
12
|
+
var outAccum = utils.sumForgiving(outputs)
|
|
13
|
+
var remaining = inAccum - outAccum - fee
|
|
14
|
+
if (!isFinite(remaining) || remaining < 0) return { fee: fee }
|
|
15
|
+
|
|
16
|
+
var unspecified = outputs.reduce(function (a, x) {
|
|
17
|
+
return a + !isFinite(x.value)
|
|
18
|
+
}, 0)
|
|
19
|
+
|
|
20
|
+
if (remaining === 0 && unspecified === 0) return utils.finalize(utxos, outputs, feeRate)
|
|
21
|
+
|
|
22
|
+
var splitOutputsCount = outputs.reduce(function (a, x) {
|
|
23
|
+
if (x.value !== undefined) return a
|
|
24
|
+
return a + 1
|
|
25
|
+
}, 0)
|
|
26
|
+
var splitValue = Math.floor(remaining / splitOutputsCount)
|
|
27
|
+
|
|
28
|
+
// ensure every output is either user defined, or over the threshold
|
|
29
|
+
if (!outputs.every(function (x) {
|
|
30
|
+
return x.value !== undefined || (splitValue > utils.dustThreshold(x, feeRate))
|
|
31
|
+
})) return { fee: fee }
|
|
32
|
+
|
|
33
|
+
// assign splitValue to outputs not user defined
|
|
34
|
+
outputs = outputs.map(function (x) {
|
|
35
|
+
if (x.value !== undefined) return x
|
|
36
|
+
|
|
37
|
+
// not user defined, but still copy over any non-value fields
|
|
38
|
+
var y = {}
|
|
39
|
+
for (var k in x) y[k] = x[k]
|
|
40
|
+
y.value = splitValue
|
|
41
|
+
return y
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
return utils.finalize(utxos, outputs, feeRate)
|
|
45
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.addDashesToSpaces = void 0;
|
|
4
|
+
const addDashesToSpaces = (inputString) => inputString.replace(/\s+/g, '-');
|
|
5
|
+
exports.addDashesToSpaces = addDashesToSpaces;
|
|
6
|
+
//# sourceMappingURL=addDashesToSpaces.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.arrayDistinct = void 0;
|
|
4
|
+
const arrayDistinct = (item, index, self) => self.indexOf(item) === index;
|
|
5
|
+
exports.arrayDistinct = arrayDistinct;
|
|
6
|
+
//# sourceMappingURL=arrayDistinct.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type ArrayPartition = {
|
|
2
|
+
<T, S extends T>(array: T[], condition: (elem: T) => elem is S): [S[], Exclude<T, S>[]];
|
|
3
|
+
<T>(array: T[], condition: (elem: T) => boolean): [T[], T[]];
|
|
4
|
+
};
|
|
5
|
+
export declare const arrayPartition: ArrayPartition;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=arrayPartition.d.ts.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.arrayPartition = void 0;
|
|
4
|
+
const arrayPartition = (array, condition) => array.reduce(([pass, fail], elem) => condition(elem) ? [[...pass, elem], fail] : [pass, [...fail, elem]], [[], []]);
|
|
5
|
+
exports.arrayPartition = arrayPartition;
|
|
6
|
+
//# sourceMappingURL=arrayPartition.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.arrayShuffle = void 0;
|
|
4
|
+
const arrayShuffle = (array, { randomInt }) => {
|
|
5
|
+
const shuffled = array.slice();
|
|
6
|
+
for (let i = shuffled.length - 1; i > 0; i--) {
|
|
7
|
+
const j = randomInt(0, i + 1);
|
|
8
|
+
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
|
|
9
|
+
}
|
|
10
|
+
return shuffled;
|
|
11
|
+
};
|
|
12
|
+
exports.arrayShuffle = arrayShuffle;
|
|
13
|
+
//# sourceMappingURL=arrayShuffle.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type DictionaryKey = string | number;
|
|
2
|
+
type GetKey<T> = (item: T) => unknown;
|
|
3
|
+
type Key<Fn extends GetKey<any>, R = ReturnType<Fn>> = R extends DictionaryKey ? R : never;
|
|
4
|
+
type ArrayToDictionary = {
|
|
5
|
+
<T, Fn extends GetKey<T>>(array: T[], getKey: Fn, multiple?: false): Record<Key<Fn>, T>;
|
|
6
|
+
<T, Fn extends GetKey<T>>(array: T[], getKey: Fn, multiple: true): Record<Key<Fn>, T[]>;
|
|
7
|
+
};
|
|
8
|
+
export declare const arrayToDictionary: ArrayToDictionary;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=arrayToDictionary.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.arrayToDictionary = void 0;
|
|
4
|
+
const validateKey = (key) => {
|
|
5
|
+
if (['string', 'number'].includes(typeof key)) {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
return false;
|
|
9
|
+
};
|
|
10
|
+
const arrayToDictionary = (array, getKey, multiple) => multiple
|
|
11
|
+
? array.reduce((prev, cur) => {
|
|
12
|
+
var _a;
|
|
13
|
+
const key = getKey(cur);
|
|
14
|
+
if (validateKey(key)) {
|
|
15
|
+
return Object.assign(Object.assign({}, prev), { [key]: [...((_a = prev[key]) !== null && _a !== void 0 ? _a : []), cur] });
|
|
16
|
+
}
|
|
17
|
+
return prev;
|
|
18
|
+
}, {})
|
|
19
|
+
: array.reduce((prev, cur) => {
|
|
20
|
+
const key = getKey(cur);
|
|
21
|
+
if (validateKey(key)) {
|
|
22
|
+
return Object.assign(Object.assign({}, prev), { [key]: cur });
|
|
23
|
+
}
|
|
24
|
+
return prev;
|
|
25
|
+
}, {});
|
|
26
|
+
exports.arrayToDictionary = arrayToDictionary;
|
|
27
|
+
//# sourceMappingURL=arrayToDictionary.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isAscii = isAscii;
|
|
4
|
+
exports.getNonAsciiChars = getNonAsciiChars;
|
|
5
|
+
const nonAsciiPattern = /[^\x20-\x7E]/g;
|
|
6
|
+
function isAscii(value) {
|
|
7
|
+
if (!value)
|
|
8
|
+
return true;
|
|
9
|
+
return !nonAsciiPattern.test(value);
|
|
10
|
+
}
|
|
11
|
+
function getNonAsciiChars(value) {
|
|
12
|
+
if (!value)
|
|
13
|
+
return null;
|
|
14
|
+
return value.match(nonAsciiPattern);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=asciiUtils.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BigNumber = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const bignumber_js_1 = tslib_1.__importDefault(require("bignumber.js"));
|
|
6
|
+
exports.BigNumber = bignumber_js_1.default.clone({
|
|
7
|
+
EXPONENTIAL_AT: 1e9,
|
|
8
|
+
});
|
|
9
|
+
//# sourceMappingURL=bigNumber.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getChunkSize = exports.reverseBuffer = void 0;
|
|
4
|
+
const reverseBuffer = (src) => {
|
|
5
|
+
if (src.length < 1)
|
|
6
|
+
return src;
|
|
7
|
+
const buffer = Buffer.alloc(src.length);
|
|
8
|
+
let j = buffer.length - 1;
|
|
9
|
+
for (let i = 0; i < buffer.length / 2; i++) {
|
|
10
|
+
buffer[i] = src[j];
|
|
11
|
+
buffer[j] = src[i];
|
|
12
|
+
j--;
|
|
13
|
+
}
|
|
14
|
+
return buffer;
|
|
15
|
+
};
|
|
16
|
+
exports.reverseBuffer = reverseBuffer;
|
|
17
|
+
const getChunkSize = (n) => {
|
|
18
|
+
const buf = Buffer.allocUnsafe(1);
|
|
19
|
+
buf.writeUInt8(n);
|
|
20
|
+
return buf;
|
|
21
|
+
};
|
|
22
|
+
exports.getChunkSize = getChunkSize;
|
|
23
|
+
//# sourceMappingURL=bufferUtils.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.bytesToHumanReadable = void 0;
|
|
4
|
+
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
5
|
+
const bytesToHumanReadable = (bytes) => {
|
|
6
|
+
let size = Math.abs(bytes);
|
|
7
|
+
let i = 0;
|
|
8
|
+
while (size >= 1024 || i >= units.length) {
|
|
9
|
+
size /= 1024;
|
|
10
|
+
i++;
|
|
11
|
+
}
|
|
12
|
+
return `${size.toFixed(1)} ${units[i]}`;
|
|
13
|
+
};
|
|
14
|
+
exports.bytesToHumanReadable = bytesToHumanReadable;
|
|
15
|
+
//# sourceMappingURL=bytesToHumanReadable.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.capitalizeFirstLetter = void 0;
|
|
4
|
+
const capitalizeFirstLetter = (str) => (str.charAt(0).toUpperCase() + str.slice(1));
|
|
5
|
+
exports.capitalizeFirstLetter = capitalizeFirstLetter;
|
|
6
|
+
//# sourceMappingURL=capitalizeFirstLetter.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cloneObject = void 0;
|
|
4
|
+
const cloneObject = (obj, seen = new WeakMap()) => {
|
|
5
|
+
if (obj === null || typeof obj !== 'object') {
|
|
6
|
+
return obj;
|
|
7
|
+
}
|
|
8
|
+
if (seen.has(obj)) {
|
|
9
|
+
return seen.get(obj);
|
|
10
|
+
}
|
|
11
|
+
if (obj instanceof ArrayBuffer) {
|
|
12
|
+
return obj.slice(0);
|
|
13
|
+
}
|
|
14
|
+
if (ArrayBuffer.isView(obj)) {
|
|
15
|
+
const TypedArrayConstructor = obj.constructor;
|
|
16
|
+
return new TypedArrayConstructor(obj);
|
|
17
|
+
}
|
|
18
|
+
const clone = Array.isArray(obj) ? [] : {};
|
|
19
|
+
seen.set(obj, clone);
|
|
20
|
+
for (const key in obj) {
|
|
21
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
22
|
+
const value = obj[key];
|
|
23
|
+
if (typeof value === 'function' || typeof value === 'symbol') {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
clone[key] = (0, exports.cloneObject)(value, seen);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return clone;
|
|
30
|
+
};
|
|
31
|
+
exports.cloneObject = cloneObject;
|
|
32
|
+
//# sourceMappingURL=cloneObject.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.countBytesInString = void 0;
|
|
4
|
+
const countBytesInString = (input) => encodeURI(input).split(/%..|./).length - 1;
|
|
5
|
+
exports.countBytesInString = countBytesInString;
|
|
6
|
+
//# sourceMappingURL=countBytesInString.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createCooldown = void 0;
|
|
4
|
+
const createCooldown = (cooldownMs) => {
|
|
5
|
+
let last = 0;
|
|
6
|
+
return () => {
|
|
7
|
+
const now = Date.now();
|
|
8
|
+
if (now - last >= cooldownMs) {
|
|
9
|
+
last = now;
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
return false;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
exports.createCooldown = createCooldown;
|
|
16
|
+
//# sourceMappingURL=createCooldown.js.map
|