@@ -13,6 +13,7 @@ module BotPlutusInterface.Balance (
13
13
14
14
import BotPlutusInterface.BodyBuilder qualified as BodyBuilder
15
15
import BotPlutusInterface.CardanoCLI qualified as CardanoCLI
16
+ import BotPlutusInterface.CoinSelection (selectTxIns )
16
17
import BotPlutusInterface.Collateral (removeCollateralFromMap )
17
18
import BotPlutusInterface.Effects (
18
19
PABEffect ,
@@ -30,7 +31,6 @@ import BotPlutusInterface.Types (
30
31
PABConfig ,
31
32
collateralTxOutRef ,
32
33
)
33
-
34
34
import Cardano.Api (ExecutionUnitPrices (ExecutionUnitPrices ))
35
35
import Cardano.Api.Shelley (ProtocolParameters (protocolParamPrices ))
36
36
import Control.Monad (foldM , void , zipWithM )
@@ -40,14 +40,12 @@ import Control.Monad.Trans.Either (EitherT, hoistEither, newEitherT, runEitherT)
40
40
import Control.Monad.Trans.Except (throwE )
41
41
import Data.Bifunctor (bimap )
42
42
import Data.Coerce (coerce )
43
- import Data.Either.Combinators (rightToMaybe )
44
43
import Data.Kind (Type )
45
44
import Data.List ((\\) )
46
45
import Data.List qualified as List
47
46
import Data.Map (Map )
48
47
import Data.Map qualified as Map
49
48
import Data.Maybe (fromMaybe , mapMaybe )
50
- import Data.Set (Set )
51
49
import Data.Set qualified as Set
52
50
import Data.Text (Text )
53
51
import Data.Text qualified as Text
@@ -76,7 +74,6 @@ import Ledger.Tx qualified as Tx
76
74
import Ledger.Value (Value )
77
75
import Ledger.Value qualified as Value
78
76
import Plutus.V1.Ledger.Api (
79
- Credential (PubKeyCredential , ScriptCredential ),
80
77
CurrencySymbol (.. ),
81
78
TokenName (.. ),
82
79
)
@@ -168,6 +165,18 @@ balanceTxIO' balanceCfg pabConf ownPkh unbalancedTx =
168
165
-- Get the updated change, add it to the tx
169
166
let finalAdaChange = getAdaChange utxoIndex balancedTxWithChange
170
167
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
171
180
172
181
-- finally, we must update the signatories
173
182
hoistEither $ addSignatories ownPkh privKeys requiredSigs fullyBalancedTx
@@ -193,7 +202,7 @@ balanceTxIO' balanceCfg pabConf ownPkh unbalancedTx =
193
202
194
203
-- Calculate fees by pre-balancing the tx, building it, and running the CLI on result
195
204
txWithoutFees <-
196
- hoistEither $ balanceTxStep balanceCfg minUtxos utxoIndex changeAddr $ tx `withFee` 0
205
+ newEitherT $ balanceTxStep @ w balanceCfg minUtxos utxoIndex changeAddr $ tx `withFee` 0
197
206
198
207
exBudget <- newEitherT $ BodyBuilder. buildAndEstimateBudget @ w pabConf privKeys txWithoutFees
199
208
@@ -204,7 +213,7 @@ balanceTxIO' balanceCfg pabConf ownPkh unbalancedTx =
204
213
lift $ printBpiLog @ w (Debug [TxBalancingLog ]) $ " Fees:" <+> pretty fees
205
214
206
215
-- 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
208
217
209
218
if balancedTx == tx
210
219
then pure (balancedTx, minUtxos)
@@ -272,16 +281,18 @@ calculateMinUtxos pabConf datums txOuts =
272
281
zipWithM (fmap . (,)) txOuts <$> mapM (CardanoCLI. calculateMinUtxo @ w pabConf datums) txOuts
273
282
274
283
balanceTxStep ::
284
+ forall (w :: Type ) (effs :: [Type -> Type ]).
285
+ Member (PABEffect w ) effs =>
275
286
BalanceConfig ->
276
287
[(TxOut , Integer )] ->
277
288
Map TxOutRef TxOut ->
278
289
Address ->
279
290
Tx ->
280
- Either Text Tx
291
+ Eff effs ( Either Text Tx )
281
292
balanceTxStep 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
285
296
286
297
-- | Get change value of a transaction, taking inputs, outputs, mint and fees into account
287
298
getChange :: Map TxOutRef TxOut -> Tx -> Value
@@ -303,45 +314,6 @@ getAdaChange utxos = lovelaceValue . getChange utxos
303
314
getNonAdaChange :: Map TxOutRef TxOut -> Tx -> Value
304
315
getNonAdaChange utxos = Ledger. noAdaValue . getChange utxos
305
316
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
-
345
317
-- | Add min lovelaces to each tx output
346
318
addLovelaces :: [(TxOut , Integer )] -> Tx -> Tx
347
319
addLovelaces minLovelaces tx =
@@ -359,17 +331,23 @@ addLovelaces minLovelaces tx =
359
331
$ txOutputs tx
360
332
in tx {txOutputs = lovelacesAdded}
361
333
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 )
363
340
balanceTxIns 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}
373
351
374
352
-- | Set collateral or fail in case it's required but not available
375
353
addTxCollaterals :: CollateralUtxo -> Tx -> Tx
@@ -500,9 +478,6 @@ modifyFirst ::
500
478
modifyFirst _ m [] = m Nothing `consJust` []
501
479
modifyFirst p m (x : xs) = if p x then m (Just x) `consJust` xs else x : modifyFirst p m xs
502
480
503
- showText :: forall (a :: Type ). Show a => a -> Text
504
- showText = Text. pack . show
505
-
506
481
minus :: Value -> Value -> Value
507
482
minus x y =
508
483
let negativeValues = map (\ (c, t, a) -> (c, t, - a)) $ Value. flattenValue y
0 commit comments