@@ -67,6 +67,7 @@ export function determineUtxosForSpendAll ({ feeRate,
67
67
if ( ! validateBitcoinAddress ( recipient ) ) {
68
68
throw new Error ( 'Cannot calculate spend of invalid address type' ) ;
69
69
}
70
+ // TODO: Prevent dust limit when transferring all
70
71
71
72
const recipients = [ recipient ] ;
72
73
@@ -107,6 +108,15 @@ export function determineUtxosForSpend ({ amount,
107
108
throw new Error ( 'Cannot calculate spend of invalid address type' ) ;
108
109
}
109
110
111
+ const recipientAddressInfo = getBitcoinAddressInfo ( recipient ) ;
112
+ const recipientDustLimit = BTC_DUST_AMOUNT [ recipientAddressInfo . type ] || 546 ;
113
+
114
+ if ( amount < recipientDustLimit ) {
115
+ throw new Error (
116
+ `Transfer amount ${ amount } satoshis is below dust limit (${ recipientDustLimit } satoshis for ${ recipientAddressInfo . type } )`
117
+ ) ;
118
+ }
119
+
110
120
const orderedUtxos = utxos . sort ( ( a , b ) => b . value - a . value ) ;
111
121
const recipients = [ recipient , sender ] ;
112
122
const filteredUtxos = filterUneconomicalUtxos ( {
@@ -156,13 +166,33 @@ export function determineUtxosForSpend ({ amount,
156
166
throw new InsufficientFundsError ( ) ;
157
167
}
158
168
169
+ const senderAddressInfo = getBitcoinAddressInfo ( sender ) ;
170
+ const dustLimit = BTC_DUST_AMOUNT [ senderAddressInfo . type ] || 546 ;
171
+
159
172
const outputs = [
160
173
// outputs[0] = the desired amount going to recipient
161
- { value : amount , address : recipient } ,
162
- // outputs[1] = the remainder to be returned to a change address
163
- { value : amountLeft . toNumber ( ) , address : sender }
174
+ { value : amount , address : recipient }
164
175
] ;
165
176
177
+ if ( amountLeft . gte ( dustLimit ) ) {
178
+ // outputs[1] = the remainder to be returned to a change address
179
+ outputs . push ( { value : amountLeft . toNumber ( ) , address : sender } ) ;
180
+ } else {
181
+ console . warn (
182
+ `Change output of ${ amountLeft . toString ( ) } satoshis is below dust limit (${ dustLimit } satoshis for ${ senderAddressInfo . type } ). Omitting change output and adding to fee.`
183
+ ) ;
184
+ // Increase the fee to use the remaining balance
185
+ const newFee = sum . minus ( amount ) . toNumber ( ) ;
186
+
187
+ return {
188
+ filteredUtxos,
189
+ inputs : neededUtxos ,
190
+ outputs,
191
+ size : sizeInfo . txVBytes ,
192
+ fee : newFee
193
+ } ;
194
+ }
195
+
166
196
return {
167
197
filteredUtxos,
168
198
inputs : neededUtxos ,
0 commit comments