1
1
package com .bloxbean .cardano .client .function .helper ;
2
2
3
+ import com .bloxbean .cardano .client .address .Address ;
4
+ import com .bloxbean .cardano .client .api .AddressIterator ;
5
+ import com .bloxbean .cardano .client .api .common .AddressIterators ;
3
6
import com .bloxbean .cardano .client .api .exception .ApiException ;
4
7
import com .bloxbean .cardano .client .api .exception .ApiRuntimeException ;
5
8
import com .bloxbean .cardano .client .api .model .Utxo ;
9
+ import com .bloxbean .cardano .client .api .model .WalletUtxo ;
6
10
import com .bloxbean .cardano .client .coinselection .UtxoSelector ;
7
11
import com .bloxbean .cardano .client .function .MinAdaChecker ;
8
12
import com .bloxbean .cardano .client .function .TxBuilder ;
@@ -52,7 +56,7 @@ public class ChangeOutputAdjustments {
52
56
* @throws ApiRuntimeException If api call error
53
57
*/
54
58
public static TxBuilder adjustChangeOutput (String changeAddress ) {
55
- return adjustChangeOutput (changeAddress , changeAddress , 1 );
59
+ return adjustChangeOutput (AddressIterators . of ( changeAddress ) , changeAddress , 1 );
56
60
}
57
61
58
62
/**
@@ -73,7 +77,29 @@ public static TxBuilder adjustChangeOutput(String changeAddress) {
73
77
* @throws ApiRuntimeException If api call error
74
78
*/
75
79
public static TxBuilder adjustChangeOutput (String changeAddress , int noOfSigners ) {
76
- return adjustChangeOutput (changeAddress , changeAddress , noOfSigners );
80
+ return adjustChangeOutput (AddressIterators .of (changeAddress ), changeAddress , noOfSigners );
81
+ }
82
+
83
+ /**
84
+ * Function to adjust change output in a <code>Transaction</code> to meet min ada requirement.
85
+ * Finds a change output specific to given change address.
86
+ * If multiple change outputs with less than min required ada are found for the change address, it throws <code>{@link TxBuildException}</code>
87
+ * Get additional utxos from change address and update the change output.
88
+ * Re-calculates fee and checks min ada in change output.
89
+ * Retry if required, upto 3 times.
90
+ * <p>
91
+ * <br>Default values:
92
+ * <br> Change Output Address = First address in senderAddressIter
93
+ * </p>
94
+ *
95
+ * @param senderAddressIter Addresses to select additional utxos. The first address in the iterator is selected as change output address.
96
+ * @param noOfSigners The number of signers required for the transaction.
97
+ * @return A TxBuilder instance with the modified change output configuration.
98
+ */
99
+ public static TxBuilder adjustChangeOutput (AddressIterator senderAddressIter , int noOfSigners ) {
100
+ var changeAddress = senderAddressIter .getFirst ().getAddress ();
101
+
102
+ return adjustChangeOutput (senderAddressIter .clone (), changeAddress , noOfSigners );
77
103
}
78
104
79
105
/**
@@ -84,14 +110,14 @@ public static TxBuilder adjustChangeOutput(String changeAddress, int noOfSigners
84
110
* Re-calculates fee and checks min ada in change output.
85
111
* Retry if required, upto 3 times.
86
112
*
87
- * @param senderAddress Address to select additional utxos
113
+ * @param senderAddressIter Addresses to select additional utxos
88
114
* @param changeAddress Address for change output selection
89
115
* @param noOfSigners No of required signers. Required for fee calculation after adjustment
90
116
* @return <code>TxBuilder</code> function
91
117
* @throws TxBuildException If multiple change outputs with less than min required ada are found for the change address.
92
118
* @throws ApiRuntimeException If api call error
93
119
*/
94
- public static TxBuilder adjustChangeOutput (String senderAddress , String changeAddress , int noOfSigners ) {
120
+ public static TxBuilder adjustChangeOutput (AddressIterator senderAddressIter , String changeAddress , int noOfSigners ) {
95
121
return (context , transaction ) -> {
96
122
int counter = 0 ;
97
123
while (true ) {
@@ -124,7 +150,7 @@ else if (outputsWithLessAda.size() > 1) {
124
150
125
151
//check outputs for minAda and balance if required
126
152
try {
127
- adjust (context , transaction , outputsWithLessAda .get (0 )._1 , outputsWithLessAda .get (0 )._2 , senderAddress , changeAddress );
153
+ adjust (context , transaction , outputsWithLessAda .get (0 )._1 , outputsWithLessAda .get (0 )._2 , senderAddressIter . clone () );
128
154
} catch (ApiException apiException ) {
129
155
throw new ApiRuntimeException ("Error in api call" , apiException );
130
156
}
@@ -137,7 +163,7 @@ else if (outputsWithLessAda.size() > 1) {
137
163
}
138
164
139
165
private static void adjust (TxBuilderContext context , Transaction transaction , TransactionOutput outputToAdjust , BigInteger additionalRequiredAmt ,
140
- String senderAddress , String changeAddress ) throws ApiException {
166
+ AddressIterator senderAddressItr ) throws ApiException {
141
167
Objects .requireNonNull (context );
142
168
Objects .requireNonNull (transaction );
143
169
@@ -171,22 +197,32 @@ private static void adjust(TxBuilderContext context, Transaction transaction, Tr
171
197
172
198
List <Utxo > newUtxos = new ArrayList <>();
173
199
UtxoSelector utxoSelector = context .getUtxoSelector ();
200
+
201
+ Address sender = senderAddressItr .getFirst ();
202
+ String senderAddr = sender .getAddress ();
203
+
174
204
//Try to find ada only utxo
175
- Optional <Utxo > utxoOptional = utxoSelector .findFirst (senderAddress , utxo ->
205
+ Optional <Utxo > utxoOptional = utxoSelector .findFirst (senderAddr , utxo ->
176
206
!existingUtxos .contains (utxo ) && utxo .getAmount ().size () == 1
177
207
&& utxo .getAmount ().get (0 ).getQuantity ().compareTo (totalRequiredWithBuffer ) == 1 );
178
208
179
209
if (utxoOptional .isPresent ()) {
180
- newUtxos .add (utxoOptional .get ());
210
+ if (sender .getDerivationPath ().isPresent ()) {
211
+ var walletUtxo = WalletUtxo .from (utxoOptional .get ());
212
+ walletUtxo .setDerivationPath (sender .getDerivationPath ().get ());
213
+ newUtxos .add (walletUtxo );
214
+ } else {
215
+ newUtxos .add (utxoOptional .get ());
216
+ }
181
217
} else { //Not Found
182
218
//Use utxo selection strategy
183
219
List <Utxo > utxosFound = null ;
184
220
185
221
try {
186
- utxosFound = context .getUtxoSelectionStrategy ().selectUtxos (senderAddress , LOVELACE , totalRequiredWithBuffer , existingUtxos );
222
+ utxosFound = context .getUtxoSelectionStrategy ().selectUtxos (senderAddressItr . clone () , LOVELACE , totalRequiredWithBuffer , existingUtxos );
187
223
} catch (ApiException ex ) {
188
224
//Not found... check without Buffer
189
- utxosFound = context .getUtxoSelectionStrategy ().selectUtxos (senderAddress , LOVELACE , additionalRequiredAmt , existingUtxos );
225
+ utxosFound = context .getUtxoSelectionStrategy ().selectUtxos (senderAddressItr . clone () , LOVELACE , additionalRequiredAmt , existingUtxos );
190
226
}
191
227
192
228
if (utxosFound != null && utxosFound .size () > 0 )
0 commit comments