If the inputs to the transaction are known to the Bitcoin Core wallet, then you can use the
fundrawtransaction command to skip fee estimation and input selection. The process then becomes:
createrawtransaction with only the outputs you want (i.e. no change, only the recipients).
If you are not using Bitcoin Core's wallet, you can use effective values.
Presumably you know the amounts in the inputs before you actual create the transaction. So you can then calculate how large the inputs will be, calculate how much in fees that will cost based on the output of
estimatesmartfee, and subtract that fee amount from the actual value of the input. This is your effective value.
When you create the outputs, you calculate the total size of the non-input data and calculate the fees for those data. Now you have how much total value your inputs must cover. You can then select coins that way.
So the process is:
- For each potential input, calculate the fee for that input and compute the effective value.
- For each output (including change if you assume that there will be change) and for the extra fixed size transaction overhead, calculate the non-input fees.
- Add the non-input fees to the amount you want to send, this is the amount that your inputs will need to cover the total cost.
- Choose the inputs you want to spend based upon their effective values.
The size of inputs in vbytes are as follows:
P2PKH: 148 vbytes
P2WPKH: 37 vbytes
P2SH-P2WPKH: 60 vbytes
For P2SH and P2WSH inputs, it depends on the script that you are using. Most people though will be using P2PKH, P2WPKH, or P2SH-P2WPKH.