@@ -120,7 +120,7 @@ def test_tx_builder_multi_asset(chain_context):
120
120
121
121
# Add sender address as input
122
122
tx_builder .add_input_address (sender ).add_output (
123
- TransactionOutput .from_primitive ([sender , 1000000 ])
123
+ TransactionOutput .from_primitive ([sender , 3000000 ])
124
124
).add_output (
125
125
TransactionOutput .from_primitive (
126
126
[sender , [2000000 , {b"1" * 28 : {b"Token1" : 1 }}]]
@@ -136,7 +136,7 @@ def test_tx_builder_multi_asset(chain_context):
136
136
],
137
137
1 : [
138
138
# First output
139
- [sender_address .to_primitive (), 1000000 ],
139
+ [sender_address .to_primitive (), 3000000 ],
140
140
# Second output
141
141
[
142
142
sender_address .to_primitive (),
@@ -145,7 +145,7 @@ def test_tx_builder_multi_asset(chain_context):
145
145
# Third output as change
146
146
[
147
147
sender_address .to_primitive (),
148
- [7827767 , {b"1111111111111111111111111111" : {b"Token2" : 2 }}],
148
+ [5827767 , {b"1111111111111111111111111111" : {b"Token2" : 2 }}],
149
149
],
150
150
],
151
151
2 : 172233 ,
@@ -171,7 +171,8 @@ def test_tx_builder_raises_utxo_selection(chain_context):
171
171
with pytest .raises (UTxOSelectionException ) as e :
172
172
tx_body = tx_builder .build (change_address = sender_address )
173
173
assert "Unfulfilled amount:" in e .value .args [0 ]
174
- assert "'coin': 991000000" in e .value .args [0 ]
174
+ # The unfulfilled amount includes requested (991000000) and estimated fees (161101)
175
+ assert "'coin': 991161101" in e .value .args [0 ]
175
176
assert "{AssetName(b'NewToken'): 1}" in e .value .args [0 ]
176
177
177
178
@@ -189,6 +190,92 @@ def test_tx_too_big_exception(chain_context):
189
190
tx_body = tx_builder .build (change_address = sender_address )
190
191
191
192
193
+ def test_tx_small_utxo_precise_fee (chain_context ):
194
+ tx_builder = TransactionBuilder (chain_context )
195
+ sender = "addr_test1vrm9x2zsux7va6w892g38tvchnzahvcd9tykqf3ygnmwtaqyfg52x"
196
+ sender_address = Address .from_primitive (sender )
197
+
198
+ tx_in1 = TransactionInput .from_primitive ([b"1" * 32 , 3 ])
199
+ tx_out1 = TransactionOutput .from_primitive ([sender , 4000000 ])
200
+ utxo1 = UTxO (tx_in1 , tx_out1 )
201
+
202
+ tx_builder .add_input (utxo1 ).add_output (
203
+ TransactionOutput .from_primitive ([sender , 2500000 ])
204
+ )
205
+
206
+ # This will not fail as we replace max fee constraint with more precise fee calculation
207
+ # And remainder is greater than minimum ada required for change
208
+ tx_body = tx_builder .build (change_address = sender_address )
209
+
210
+ expect = {
211
+ 0 : [
212
+ [b"11111111111111111111111111111111" , 3 ],
213
+ ],
214
+ 1 : [
215
+ # First output
216
+ [sender_address .to_primitive (), 2500000 ],
217
+ # Second output as change
218
+ [sender_address .to_primitive (), 1334587 ],
219
+ ],
220
+ 2 : 165413 ,
221
+ }
222
+
223
+ expect == tx_body .to_primitive ()
224
+
225
+
226
+ def test_tx_small_utxo_balance_fail (chain_context ):
227
+ tx_builder = TransactionBuilder (chain_context )
228
+ sender = "addr_test1vrm9x2zsux7va6w892g38tvchnzahvcd9tykqf3ygnmwtaqyfg52x"
229
+ sender_address = Address .from_primitive (sender )
230
+
231
+ tx_in1 = TransactionInput .from_primitive ([b"1" * 32 , 3 ])
232
+ tx_out1 = TransactionOutput .from_primitive ([sender , 4000000 ])
233
+ utxo1 = UTxO (tx_in1 , tx_out1 )
234
+
235
+ tx_builder .add_input (utxo1 ).add_output (
236
+ TransactionOutput .from_primitive ([sender , 3000000 ])
237
+ )
238
+
239
+ # Balance is smaller than minimum ada required in change
240
+ # No more UTxO is available, throwing UTxO selection exception
241
+ with pytest .raises (UTxOSelectionException ):
242
+ tx_body = tx_builder .build (change_address = sender_address )
243
+
244
+
245
+ def test_tx_small_utxo_balance_pass (chain_context ):
246
+ tx_builder = TransactionBuilder (chain_context )
247
+ sender = "addr_test1vrm9x2zsux7va6w892g38tvchnzahvcd9tykqf3ygnmwtaqyfg52x"
248
+ sender_address = Address .from_primitive (sender )
249
+
250
+ tx_in1 = TransactionInput .from_primitive ([b"1" * 32 , 3 ])
251
+ tx_out1 = TransactionOutput .from_primitive ([sender , 4000000 ])
252
+ utxo1 = UTxO (tx_in1 , tx_out1 )
253
+
254
+ tx_builder .add_input (utxo1 ).add_input_address (sender_address ).add_output (
255
+ TransactionOutput .from_primitive ([sender , 3000000 ])
256
+ )
257
+
258
+ # Balance is smaller than minimum ada required in change
259
+ # Additional UTxOs are selected from the input address
260
+ tx_body = tx_builder .build (change_address = sender_address )
261
+
262
+ expected = {
263
+ 0 : [
264
+ [b"11111111111111111111111111111111" , 3 ],
265
+ [b"11111111111111111111111111111111" , 1 ],
266
+ ],
267
+ 1 : [
268
+ # First output
269
+ [sender_address .to_primitive (), 3000000 ],
270
+ # Second output as change
271
+ [sender_address .to_primitive (), 5833003 ],
272
+ ],
273
+ 2 : 166997 ,
274
+ }
275
+
276
+ expected == tx_body .to_primitive ()
277
+
278
+
192
279
def test_tx_builder_mint_multi_asset (chain_context ):
193
280
vk1 = VerificationKey .from_cbor (
194
281
"58206443a101bdb948366fc87369336224595d36d8b0eee5602cba8b81a024e58473"
@@ -210,7 +297,7 @@ def test_tx_builder_mint_multi_asset(chain_context):
210
297
# Add sender address as input
211
298
mint = {policy_id .payload : {b"Token1" : 1 }}
212
299
tx_builder .add_input_address (sender ).add_output (
213
- TransactionOutput .from_primitive ([sender , 1000000 ])
300
+ TransactionOutput .from_primitive ([sender , 3000000 ])
214
301
).add_output (TransactionOutput .from_primitive ([sender , [2000000 , mint ]]))
215
302
tx_builder .mint = MultiAsset .from_primitive (mint )
216
303
tx_builder .native_scripts = [script ]
@@ -225,14 +312,14 @@ def test_tx_builder_mint_multi_asset(chain_context):
225
312
],
226
313
1 : [
227
314
# First output
228
- [sender_address .to_primitive (), 1000000 ],
315
+ [sender_address .to_primitive (), 3000000 ],
229
316
# Second output
230
317
[sender_address .to_primitive (), [2000000 , mint ]],
231
318
# Third output as change
232
319
[
233
320
sender_address .to_primitive (),
234
321
[
235
- 7811267 ,
322
+ 5811267 ,
236
323
{b"1111111111111111111111111111" : {b"Token1" : 1 , b"Token2" : 2 }},
237
324
],
238
325
],
@@ -332,7 +419,7 @@ def test_not_enough_input_amount(chain_context):
332
419
TransactionOutput .from_primitive ([sender , input_utxo .output .amount ])
333
420
)
334
421
335
- with pytest .raises (InvalidTransactionException ):
422
+ with pytest .raises (UTxOSelectionException ):
336
423
# Tx builder must fail here because there is not enough amount of input ADA to pay tx fee
337
424
tx_body = tx_builder .build (change_address = sender_address )
338
425
0 commit comments