@@ -13,7 +13,7 @@ module BotPlutusInterface.Balance (
1313
1414import BotPlutusInterface.BodyBuilder qualified as BodyBuilder
1515import BotPlutusInterface.CardanoCLI qualified as CardanoCLI
16- import BotPlutusInterface.CardanoNode.Effects (NodeQuery (UtxosAt ))
16+ import BotPlutusInterface.CardanoNode.Effects (NodeQuery (MinUtxo , UtxosAt ))
1717import BotPlutusInterface.CoinSelection (selectTxIns )
1818import BotPlutusInterface.Collateral (removeCollateralFromMap )
1919import BotPlutusInterface.Effects (
@@ -160,10 +160,11 @@ balanceTxIO' balanceCfg pabConf ownPkh unbalancedTx =
160160
161161 -- Balance the tx
162162 balancedTx <- balanceTxLoop utxoIndex privKeys preBalancedTx
163+ changeTxOutWithMinAmt <- newEitherT $ addOutput @ w changeAddr balancedTx
163164
164165 -- Get current Ada change
165166 let adaChange = getAdaChange utxoIndex balancedTx
166- bTx = balanceTxLoop utxoIndex privKeys (addOutput changeAddr balancedTx)
167+ bTx = balanceTxLoop utxoIndex privKeys changeTxOutWithMinAmt
167168
168169 -- Checks if there's ada change left, if there is then we check
169170 -- if `bcSeparateChange` is true, if this is the case then we create a new UTxO at
@@ -289,7 +290,7 @@ balanceTxStep ::
289290balanceTxStep balanceCfg utxos changeAddr tx =
290291 runEitherT $
291292 (newEitherT . balanceTxIns @ w utxos) tx
292- >>= hoistEither . handleNonAdaChange balanceCfg changeAddr utxos
293+ >>= newEitherT . handleNonAdaChange @ w balanceCfg changeAddr utxos
293294
294295-- | Get change value of a transaction, taking inputs, outputs, mint and fees into account
295296getChange :: Map TxOutRef TxOut -> Tx -> Value
@@ -347,9 +348,19 @@ txUsesScripts Tx {txInputs, txMintScripts} =
347348 txInputs
348349
349350-- | Ensures all non ada change goes back to user
350- handleNonAdaChange :: BalanceConfig -> Address -> Map TxOutRef TxOut -> Tx -> Either Text Tx
351- handleNonAdaChange balanceCfg changeAddr utxos tx =
352- let nonAdaChange = getNonAdaChange utxos tx
351+ handleNonAdaChange ::
352+ forall (w :: Type ) (effs :: [Type -> Type ]).
353+ Member (PABEffect w ) effs =>
354+ BalanceConfig ->
355+ Address ->
356+ Map TxOutRef TxOut ->
357+ Tx ->
358+ Eff effs (Either Text Tx )
359+ handleNonAdaChange balanceCfg changeAddr utxos tx = runEitherT $ do
360+ let nonAdaChange :: Value
361+ nonAdaChange = getNonAdaChange utxos tx
362+
363+ predicate :: TxOut -> Bool
353364 predicate =
354365 if bcSeparateChange balanceCfg
355366 then
@@ -358,20 +369,30 @@ handleNonAdaChange balanceCfg changeAddr utxos tx =
358369 && not (justLovelace $ Tx. txOutValue txout)
359370 )
360371 else (\ txout -> Tx. txOutAddress txout == changeAddr)
372+
373+ newOutput :: TxOut
361374 newOutput =
362375 TxOut
363376 { txOutAddress = changeAddr
364377 , txOutValue = nonAdaChange
365378 , txOutDatumHash = Nothing
366379 }
380+
381+ newOutputWithMinAmt <-
382+ firstEitherT (Text. pack . show ) $
383+ newEitherT $
384+ queryNode @ w (MinUtxo newOutput)
385+
386+ let outputs :: [TxOut ]
367387 outputs =
368388 modifyFirst
369389 predicate
370- (Just . maybe newOutput (addValueToTxOut nonAdaChange))
390+ (Just . maybe newOutputWithMinAmt (addValueToTxOut nonAdaChange))
371391 (txOutputs tx)
372- in if isValueNat nonAdaChange
373- then Right $ if Value. isZero nonAdaChange then tx else tx {txOutputs = outputs}
374- else Left " Not enough inputs to balance tokens."
392+
393+ if isValueNat nonAdaChange
394+ then return $ if Value. isZero nonAdaChange then tx else tx {txOutputs = outputs}
395+ else throwE " Not enough inputs to balance tokens."
375396
376397{- | `addAdaChange` checks if `bcSeparateChange` is true,
377398 if it is then we add the ada change to seperate `TxOut` at changeAddr that contains only ada,
@@ -401,16 +422,29 @@ addAdaChange balanceCfg changeAddr change tx
401422addValueToTxOut :: Value -> TxOut -> TxOut
402423addValueToTxOut val txOut = txOut {txOutValue = txOutValue txOut <> val}
403424
404- -- | Adds a 1 lovelace output to a transaction
405- addOutput :: Address -> Tx -> Tx
406- addOutput changeAddr tx = tx {txOutputs = txOutputs tx ++ [changeTxOut]}
407- where
408- changeTxOut =
409- TxOut
410- { txOutAddress = changeAddr
411- , txOutValue = Ada. lovelaceValueOf 1
412- , txOutDatumHash = Nothing
413- }
425+ -- | creates a Tx output with min lovelace.
426+ addOutput ::
427+ forall (w :: Type ) (effs :: [Type -> Type ]).
428+ Member (PABEffect w ) effs =>
429+ Address ->
430+ Tx ->
431+ Eff effs (Either Text Tx )
432+ addOutput changeAddr tx =
433+ runEitherT $ do
434+ let changeTxOut :: TxOut
435+ changeTxOut =
436+ TxOut
437+ { txOutAddress = changeAddr
438+ , txOutValue = Ada. lovelaceValueOf 1
439+ , txOutDatumHash = Nothing
440+ }
441+
442+ changeTxOutWithMinAmt <-
443+ firstEitherT (Text. pack . show ) $
444+ newEitherT $
445+ queryNode @ w (MinUtxo changeTxOut)
446+
447+ return $ tx {txOutputs = txOutputs tx ++ [changeTxOutWithMinAmt]}
414448
415449{- | Add the required signatories to the transaction. Be aware the the signature itself is invalid,
416450 and will be ignored. Only the pub key hashes are used, mapped to signing key files on disk.
0 commit comments