@@ -13,6 +13,7 @@ module BotPlutusInterface.Balance (
1313
1414import BotPlutusInterface.BodyBuilder qualified as BodyBuilder
1515import BotPlutusInterface.CardanoCLI qualified as CardanoCLI
16+ import BotPlutusInterface.CoinSelection (selectTxIns )
1617import BotPlutusInterface.Collateral (removeCollateralFromMap )
1718import BotPlutusInterface.Effects (
1819 PABEffect ,
@@ -30,7 +31,6 @@ import BotPlutusInterface.Types (
3031 PABConfig ,
3132 collateralTxOutRef ,
3233 )
33-
3434import Cardano.Api (ExecutionUnitPrices (ExecutionUnitPrices ))
3535import Cardano.Api.Shelley (ProtocolParameters (protocolParamPrices ))
3636import Control.Monad (foldM , void , zipWithM )
@@ -40,14 +40,12 @@ import Control.Monad.Trans.Either (EitherT, hoistEither, newEitherT, runEitherT)
4040import Control.Monad.Trans.Except (throwE )
4141import Data.Bifunctor (bimap )
4242import Data.Coerce (coerce )
43- import Data.Either.Combinators (rightToMaybe )
4443import Data.Kind (Type )
4544import Data.List ((\\) )
4645import Data.List qualified as List
4746import Data.Map (Map )
4847import Data.Map qualified as Map
4948import Data.Maybe (fromMaybe , mapMaybe )
50- import Data.Set (Set )
5149import Data.Set qualified as Set
5250import Data.Text (Text )
5351import Data.Text qualified as Text
@@ -76,7 +74,6 @@ import Ledger.Tx qualified as Tx
7674import Ledger.Value (Value )
7775import Ledger.Value qualified as Value
7876import Plutus.V1.Ledger.Api (
79- Credential (PubKeyCredential , ScriptCredential ),
8077 CurrencySymbol (.. ),
8178 TokenName (.. ),
8279 )
@@ -168,6 +165,18 @@ balanceTxIO' balanceCfg pabConf ownPkh unbalancedTx =
168165 -- Get the updated change, add it to the tx
169166 let finalAdaChange = getAdaChange utxoIndex balancedTxWithChange
170167 fullyBalancedTx = addAdaChange balanceCfg changeAddr finalAdaChange balancedTxWithChange
168+ txInfoLog =
169+ printBpiLog @ w (Debug [TxBalancingLog ]) $
170+ " UnbalancedTx TxInputs: "
171+ <+> pretty (length $ txInputs preBalancedTx)
172+ <+> " UnbalancedTx TxOutputs: "
173+ <+> pretty (length $ txOutputs preBalancedTx)
174+ <+> " TxInputs: "
175+ <+> pretty (length $ txInputs fullyBalancedTx)
176+ <+> " TxOutputs: "
177+ <+> pretty (length $ txOutputs fullyBalancedTx)
178+
179+ lift txInfoLog
171180
172181 -- finally, we must update the signatories
173182 hoistEither $ addSignatories ownPkh privKeys requiredSigs fullyBalancedTx
@@ -193,7 +202,7 @@ balanceTxIO' balanceCfg pabConf ownPkh unbalancedTx =
193202
194203 -- Calculate fees by pre-balancing the tx, building it, and running the CLI on result
195204 txWithoutFees <-
196- hoistEither $ balanceTxStep balanceCfg minUtxos utxoIndex changeAddr $ tx `withFee` 0
205+ newEitherT $ balanceTxStep @ w balanceCfg minUtxos utxoIndex changeAddr $ tx `withFee` 0
197206
198207 exBudget <- newEitherT $ BodyBuilder. buildAndEstimateBudget @ w pabConf privKeys txWithoutFees
199208
@@ -204,7 +213,7 @@ balanceTxIO' balanceCfg pabConf ownPkh unbalancedTx =
204213 lift $ printBpiLog @ w (Debug [TxBalancingLog ]) $ " Fees:" <+> pretty fees
205214
206215 -- Rebalance the initial tx with the above fees
207- balancedTx <- hoistEither $ balanceTxStep balanceCfg minUtxos utxoIndex changeAddr $ tx `withFee` fees
216+ balancedTx <- newEitherT $ balanceTxStep @ w balanceCfg minUtxos utxoIndex changeAddr $ tx `withFee` fees
208217
209218 if balancedTx == tx
210219 then pure (balancedTx, minUtxos)
@@ -272,16 +281,18 @@ calculateMinUtxos pabConf datums txOuts =
272281 zipWithM (fmap . (,)) txOuts <$> mapM (CardanoCLI. calculateMinUtxo @ w pabConf datums) txOuts
273282
274283balanceTxStep ::
284+ forall (w :: Type ) (effs :: [Type -> Type ]).
285+ Member (PABEffect w ) effs =>
275286 BalanceConfig ->
276287 [(TxOut , Integer )] ->
277288 Map TxOutRef TxOut ->
278289 Address ->
279290 Tx ->
280- Either Text Tx
291+ Eff effs ( Either Text Tx )
281292balanceTxStep balanceCfg minUtxos utxos changeAddr tx =
282- Right (addLovelaces minUtxos tx)
283- >>= balanceTxIns utxos
284- >>= handleNonAdaChange balanceCfg changeAddr utxos
293+ runEitherT $
294+ (newEitherT . balanceTxIns @ w utxos) (addLovelaces minUtxos tx)
295+ >>= hoistEither . handleNonAdaChange balanceCfg changeAddr utxos
285296
286297-- | Get change value of a transaction, taking inputs, outputs, mint and fees into account
287298getChange :: Map TxOutRef TxOut -> Tx -> Value
@@ -303,45 +314,6 @@ getAdaChange utxos = lovelaceValue . getChange utxos
303314getNonAdaChange :: Map TxOutRef TxOut -> Tx -> Value
304315getNonAdaChange utxos = Ledger. noAdaValue . getChange utxos
305316
306- -- | Getting the necessary utxos to cover the fees for the transaction
307- collectTxIns :: Set TxIn -> Map TxOutRef TxOut -> Value -> Either Text (Set TxIn )
308- collectTxIns originalTxIns utxos value =
309- if isSufficient updatedInputs
310- then Right updatedInputs
311- else
312- Left $
313- Text. unlines
314- [ " Insufficient tx inputs, needed: "
315- , showText (Value. flattenValue value)
316- , " got:"
317- , showText (Value. flattenValue (txInsValue updatedInputs))
318- ]
319- where
320- updatedInputs =
321- foldl
322- ( \ acc txIn ->
323- if isSufficient acc
324- then acc
325- else Set. insert txIn acc
326- )
327- originalTxIns
328- $ mapMaybe (rightToMaybe . txOutToTxIn) $ Map. toList utxos
329-
330- isSufficient :: Set TxIn -> Bool
331- isSufficient txIns' =
332- not (Set. null txIns') && txInsValue txIns' `Value.geq` value
333-
334- txInsValue :: Set TxIn -> Value
335- txInsValue txIns' =
336- mconcat $ map Tx. txOutValue $ mapMaybe ((`Map.lookup` utxos) . Tx. txInRef) $ Set. toList txIns'
337-
338- -- Converting a chain index transaction output to a transaction input type
339- txOutToTxIn :: (TxOutRef , TxOut ) -> Either Text TxIn
340- txOutToTxIn (txOutRef, txOut) =
341- case addressCredential (txOutAddress txOut) of
342- PubKeyCredential _ -> Right $ Tx. pubKeyTxIn txOutRef
343- ScriptCredential _ -> Left " Cannot covert a script output to TxIn"
344-
345317-- | Add min lovelaces to each tx output
346318addLovelaces :: [(TxOut , Integer )] -> Tx -> Tx
347319addLovelaces minLovelaces tx =
@@ -359,17 +331,23 @@ addLovelaces minLovelaces tx =
359331 $ txOutputs tx
360332 in tx {txOutputs = lovelacesAdded}
361333
362- balanceTxIns :: Map TxOutRef TxOut -> Tx -> Either Text Tx
334+ balanceTxIns ::
335+ forall (w :: Type ) (effs :: [Type -> Type ]).
336+ Member (PABEffect w ) effs =>
337+ Map TxOutRef TxOut ->
338+ Tx ->
339+ Eff effs (Either Text Tx )
363340balanceTxIns utxos tx = do
364- let txOuts = Tx. txOutputs tx
365- nonMintedValue = mconcat (map Tx. txOutValue txOuts) `minus` txMint tx
366- minSpending =
367- mconcat
368- [ txFee tx
369- , nonMintedValue
370- ]
371- txIns <- collectTxIns (txInputs tx) utxos minSpending
372- pure $ tx {txInputs = txIns <> txInputs tx}
341+ runEitherT $ do
342+ let txOuts = Tx. txOutputs tx
343+ nonMintedValue = mconcat (map Tx. txOutValue txOuts) `minus` txMint tx
344+ minSpending =
345+ mconcat
346+ [ txFee tx
347+ , nonMintedValue
348+ ]
349+ txIns <- newEitherT $ selectTxIns @ w (txInputs tx) utxos minSpending
350+ pure $ tx {txInputs = txIns <> txInputs tx}
373351
374352-- | Set collateral or fail in case it's required but not available
375353addTxCollaterals :: CollateralUtxo -> Tx -> Tx
@@ -500,9 +478,6 @@ modifyFirst ::
500478modifyFirst _ m [] = m Nothing `consJust` []
501479modifyFirst p m (x : xs) = if p x then m (Just x) `consJust` xs else x : modifyFirst p m xs
502480
503- showText :: forall (a :: Type ). Show a => a -> Text
504- showText = Text. pack . show
505-
506481minus :: Value -> Value -> Value
507482minus x y =
508483 let negativeValues = map (\ (c, t, a) -> (c, t, - a)) $ Value. flattenValue y
0 commit comments