@@ -312,7 +312,9 @@ def _calc_change(
312
312
# when there is only ADA left, simply use remaining coin value as change
313
313
if not change .multi_asset :
314
314
if change .coin < min_lovelace (change , self .context ):
315
- raise InsufficientUTxOBalanceException ("Not enough ADA left for change" )
315
+ raise InsufficientUTxOBalanceException (
316
+ f"Not enough ADA left for change: { change .coin } but needs { min_lovelace (change , self .context )} "
317
+ )
316
318
lovelace_change = change .coin
317
319
change_output_arr .append (TransactionOutput (address , lovelace_change ))
318
320
@@ -347,17 +349,42 @@ def _calc_change(
347
349
return change_output_arr
348
350
349
351
def _add_change_and_fee (
350
- self , change_address : Optional [Address ]
352
+ self ,
353
+ change_address : Optional [Address ],
354
+ merge_change : Optional [bool ] = False ,
351
355
) -> TransactionBuilder :
352
- original_outputs = self .outputs [:]
356
+ original_outputs = deepcopy (self .outputs )
357
+ change_output_index = None
358
+
359
+ def _merge_changes (changes ):
360
+ if change_output_index is not None and len (changes ) == 1 :
361
+ # Add the leftover change to the TransactionOutput containing the change address
362
+ self ._outputs [change_output_index ].amount = (
363
+ changes [0 ].amount + self ._outputs [change_output_index ].amount
364
+ )
365
+ # if we enforce that TransactionOutputs must use Values for `amount`, we can use += here
366
+
367
+ else :
368
+ self ._outputs += changes
353
369
354
370
if change_address :
371
+
372
+ if merge_change :
373
+
374
+ for idx , output in enumerate (original_outputs ):
375
+
376
+ # Find any transaction outputs which already contain the change address
377
+ if change_address == output .address :
378
+ if change_output_index is None or output .lovelace == 0 :
379
+ change_output_index = idx
380
+
355
381
# Set fee to max
356
382
self .fee = self ._estimate_fee ()
357
383
changes = self ._calc_change (
358
384
self .fee , self .inputs , self .outputs , change_address , precise_fee = True
359
385
)
360
- self ._outputs += changes
386
+
387
+ _merge_changes (changes )
361
388
362
389
# With changes included, we can estimate the fee more precisely
363
390
self .fee = self ._estimate_fee ()
@@ -367,7 +394,8 @@ def _add_change_and_fee(
367
394
changes = self ._calc_change (
368
395
self .fee , self .inputs , self .outputs , change_address , precise_fee = True
369
396
)
370
- self ._outputs += changes
397
+
398
+ _merge_changes (changes )
371
399
372
400
return self
373
401
@@ -649,12 +677,18 @@ def _estimate_fee(self):
649
677
650
678
return estimated_fee
651
679
652
- def build (self , change_address : Optional [Address ] = None ) -> TransactionBody :
680
+ def build (
681
+ self ,
682
+ change_address : Optional [Address ] = None ,
683
+ merge_change : Optional [bool ] = False ,
684
+ ) -> TransactionBody :
653
685
"""Build a transaction body from all constraints set through the builder.
654
686
655
687
Args:
656
688
change_address (Optional[Address]): Address to which changes will be returned. If not provided, the
657
689
transaction body will likely be unbalanced (sum of inputs is greater than the sum of outputs).
690
+ merge_change (Optional[bool]): If the change address match one of the transaction output, the change amount
691
+ will be directly added to that transaction output, instead of being added as a separate output.
658
692
659
693
Returns:
660
694
TransactionBody: A transaction body.
@@ -773,7 +807,7 @@ def build(self, change_address: Optional[Address] = None) -> TransactionBody:
773
807
774
808
self ._set_redeemer_index ()
775
809
776
- self ._add_change_and_fee (change_address )
810
+ self ._add_change_and_fee (change_address , merge_change = merge_change )
777
811
778
812
tx_body = self ._build_tx_body ()
779
813
@@ -820,6 +854,7 @@ def build_and_sign(
820
854
self ,
821
855
signing_keys : List [Union [SigningKey , ExtendedSigningKey ]],
822
856
change_address : Optional [Address ] = None ,
857
+ merge_change : Optional [bool ] = False ,
823
858
) -> Transaction :
824
859
"""Build a transaction body from all constraints set through the builder and sign the transaction with
825
860
provided signing keys.
@@ -829,12 +864,14 @@ def build_and_sign(
829
864
sign the transaction.
830
865
change_address (Optional[Address]): Address to which changes will be returned. If not provided, the
831
866
transaction body will likely be unbalanced (sum of inputs is greater than the sum of outputs).
867
+ merge_change (Optional[bool]): If the change address match one of the transaction output, the change amount
868
+ will be directly added to that transaction output, instead of being added as a separate output.
832
869
833
870
Returns:
834
871
Transaction: A signed transaction.
835
872
"""
836
873
837
- tx_body = self .build (change_address = change_address )
874
+ tx_body = self .build (change_address = change_address , merge_change = merge_change )
838
875
witness_set = self .build_witness_set ()
839
876
witness_set .vkey_witnesses = []
840
877
0 commit comments