module Cooked.MockChain.Balancing
( Body,
ExtendedTxSkel (..),
balanceTxSkel,
getMinAndMaxFee,
estimateTxSkelFee,
)
where
import Cardano.Api qualified as Cardano
import Cardano.Api.Ledger qualified as Cardano
import Cardano.Ledger.Conway.Core qualified as Conway
import Cardano.Ledger.Conway.PParams qualified as Conway
import Cardano.Node.Emulator.Internal.Node.Params qualified as Emulator
import Control.Monad
import Cooked.MockChain.AutoFilling
import Cooked.MockChain.Common
import Cooked.MockChain.Error
import Cooked.MockChain.GenerateTx.Body
import Cooked.MockChain.GenerateTx.Output
import Cooked.MockChain.Log
import Cooked.MockChain.Read
import Cooked.MockChain.UtxoSearch
import Cooked.Skeleton
import Data.ByteString qualified as BS
import Data.Function
import Data.List (find, partition)
import Data.Map qualified as Map
import Data.Maybe (fromMaybe)
import Data.Ratio qualified as Rat
import Data.Set qualified as Set
import Ledger.Tx qualified as Ledger
import Ledger.Tx.CardanoAPI qualified as Ledger
import Lens.Micro.Extras qualified as Micro
import Lens.Micro.Extras qualified as MicroLens
import Optics.Core
import Optics.Core.Extras
import Plutus.Script.Utils.Address qualified as Script
import Plutus.Script.Utils.Value qualified as Script
import PlutusLedgerApi.V1.Value qualified as Api
import PlutusLedgerApi.V3 qualified as Api
import PlutusTx.Prelude qualified as PlutusTx
import Polysemy
import Polysemy.Error
import Polysemy.Fail
type Body = Cardano.TxBody Cardano.ConwayEra
data ExtendedTxSkel = ExtendedTxSkel
{
ExtendedTxSkel -> TxSkel
eSkel :: TxSkel,
ExtendedTxSkel -> Fee
eFee :: Fee,
ExtendedTxSkel -> Maybe Collaterals
eMCollaterals :: Maybe Collaterals,
ExtendedTxSkel -> Body
eBody :: Body
}
balanceTxSkel ::
(Members '[MockChainRead, MockChainLog, Error MockChainError, Error Ledger.ToCardanoError, Fail] effs) =>
TxSkel ->
Sem effs ExtendedTxSkel
balanceTxSkel :: forall (effs :: EffectRow).
Members
'[MockChainRead, MockChainLog, Error MockChainError,
Error ToCardanoError, Fail]
effs =>
TxSkel -> Sem effs ExtendedTxSkel
balanceTxSkel skelUnbal :: TxSkel
skelUnbal@TxSkel {[TxSkelSignatory]
[TxSkelProposal]
[TxSkelCertificate]
[TxSkelOut]
Set TxOutRef
Set TxSkelLabel
Map TxOutRef TxSkelRedeemer
SlotRange
TxSkelOpts
TxSkelWithdrawals
TxSkelMints
txSkelLabels :: Set TxSkelLabel
txSkelOpts :: TxSkelOpts
txSkelMints :: TxSkelMints
txSkelSignatories :: [TxSkelSignatory]
txSkelValidityRange :: SlotRange
txSkelIns :: Map TxOutRef TxSkelRedeemer
txSkelInsReference :: Set TxOutRef
txSkelOuts :: [TxSkelOut]
txSkelProposals :: [TxSkelProposal]
txSkelWithdrawals :: TxSkelWithdrawals
txSkelCertificates :: [TxSkelCertificate]
txSkelLabels :: TxSkel -> Set TxSkelLabel
txSkelOpts :: TxSkel -> TxSkelOpts
txSkelMints :: TxSkel -> TxSkelMints
txSkelSignatories :: TxSkel -> [TxSkelSignatory]
txSkelValidityRange :: TxSkel -> SlotRange
txSkelIns :: TxSkel -> Map TxOutRef TxSkelRedeemer
txSkelInsReference :: TxSkel -> Set TxOutRef
txSkelOuts :: TxSkel -> [TxSkelOut]
txSkelProposals :: TxSkel -> [TxSkelProposal]
txSkelWithdrawals :: TxSkel -> TxSkelWithdrawals
txSkelCertificates :: TxSkel -> [TxSkelCertificate]
..} = do
Maybe (User 'IsPubKey 'Allocation)
balancingUser <- case TxSkelOpts -> BalancingPolicy
txSkelOptBalancingPolicy TxSkelOpts
txSkelOpts of
BalancingPolicy
BalanceWithFirstSignatory -> case [TxSkelSignatory]
txSkelSignatories of
[] -> MockChainError -> Sem effs (Maybe (User 'IsPubKey 'Allocation))
forall e (r :: EffectRow) a. Member (Error e) r => e -> Sem r a
throw (MockChainError -> Sem effs (Maybe (User 'IsPubKey 'Allocation)))
-> MockChainError -> Sem effs (Maybe (User 'IsPubKey 'Allocation))
forall a b. (a -> b) -> a -> b
$ BalancingError -> MockChainError
MCEBalancingError BalancingError
MissingBalancingUser
TxSkelSignatory
bw : [TxSkelSignatory]
_ -> Maybe (User 'IsPubKey 'Allocation)
-> Sem effs (Maybe (User 'IsPubKey 'Allocation))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (User 'IsPubKey 'Allocation)
-> Sem effs (Maybe (User 'IsPubKey 'Allocation)))
-> Maybe (User 'IsPubKey 'Allocation)
-> Sem effs (Maybe (User 'IsPubKey 'Allocation))
forall a b. (a -> b) -> a -> b
$ User 'IsPubKey 'Allocation -> Maybe (User 'IsPubKey 'Allocation)
forall a. a -> Maybe a
Just (User 'IsPubKey 'Allocation -> Maybe (User 'IsPubKey 'Allocation))
-> User 'IsPubKey 'Allocation -> Maybe (User 'IsPubKey 'Allocation)
forall a b. (a -> b) -> a -> b
$ TxSkelSignatory -> User 'IsPubKey 'Allocation
forall pkh (a :: UserKind) (b :: UserMode).
(a ∈ '[ 'IsPubKey, 'IsEither], ToPubKeyHash pkh, Typeable pkh) =>
pkh -> User a b
UserPubKey TxSkelSignatory
bw
BalanceWith pkh
bUser -> Maybe (User 'IsPubKey 'Allocation)
-> Sem effs (Maybe (User 'IsPubKey 'Allocation))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (User 'IsPubKey 'Allocation)
-> Sem effs (Maybe (User 'IsPubKey 'Allocation)))
-> Maybe (User 'IsPubKey 'Allocation)
-> Sem effs (Maybe (User 'IsPubKey 'Allocation))
forall a b. (a -> b) -> a -> b
$ User 'IsPubKey 'Allocation -> Maybe (User 'IsPubKey 'Allocation)
forall a. a -> Maybe a
Just (User 'IsPubKey 'Allocation -> Maybe (User 'IsPubKey 'Allocation))
-> User 'IsPubKey 'Allocation -> Maybe (User 'IsPubKey 'Allocation)
forall a b. (a -> b) -> a -> b
$ pkh -> User 'IsPubKey 'Allocation
forall pkh (a :: UserKind) (b :: UserMode).
(a ∈ '[ 'IsPubKey, 'IsEither], ToPubKeyHash pkh, Typeable pkh) =>
pkh -> User a b
UserPubKey pkh
bUser
BalancingPolicy
DoNotBalance -> Maybe (User 'IsPubKey 'Allocation)
-> Sem effs (Maybe (User 'IsPubKey 'Allocation))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (User 'IsPubKey 'Allocation)
forall a. Maybe a
Nothing
Fee
nbOfScripts <- Int -> Fee
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Fee) -> ([VScript] -> Int) -> [VScript] -> Fee
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [VScript] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([VScript] -> Fee) -> Sem effs [VScript] -> Sem effs Fee
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TxSkel -> Sem effs [VScript]
forall (effs :: EffectRow).
Member MockChainRead effs =>
TxSkel -> Sem effs [VScript]
txSkelAllScripts TxSkel
skelUnbal
(Fee
minFee, Fee
maxFee) <- Fee -> Sem effs (Fee, Fee)
forall (effs :: EffectRow).
Members '[MockChainRead] effs =>
Fee -> Sem effs (Fee, Fee)
getMinAndMaxFee Fee
nbOfScripts
Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
mCollaterals <- do
case (Fee
nbOfScripts Fee -> Fee -> Bool
forall a. Eq a => a -> a -> Bool
== Fee
0, TxSkelOpts -> CollateralUtxos
txSkelOptCollateralUtxos TxSkelOpts
txSkelOpts) of
(Bool
True, CollateralUtxosFromSet Set TxOutRef
utxos pkh
_) -> MockChainLogEntry -> Sem effs ()
forall (effs :: EffectRow).
Member MockChainLog effs =>
MockChainLogEntry -> Sem effs ()
logEvent (Either (User 'IsPubKey 'Allocation) (Set TxOutRef)
-> MockChainLogEntry
MCLogUnusedCollaterals (Either (User 'IsPubKey 'Allocation) (Set TxOutRef)
-> MockChainLogEntry)
-> Either (User 'IsPubKey 'Allocation) (Set TxOutRef)
-> MockChainLogEntry
forall a b. (a -> b) -> a -> b
$ Set TxOutRef -> Either (User 'IsPubKey 'Allocation) (Set TxOutRef)
forall a b. b -> Either a b
Right Set TxOutRef
utxos) Sem effs ()
-> Sem effs (Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
-> Sem effs (Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
forall a b. Sem effs a -> Sem effs b -> Sem effs b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> Sem effs (Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
forall a. Maybe a
Nothing
(Bool
True, CollateralUtxosFromUser pkh
cUser) -> MockChainLogEntry -> Sem effs ()
forall (effs :: EffectRow).
Member MockChainLog effs =>
MockChainLogEntry -> Sem effs ()
logEvent (Either (User 'IsPubKey 'Allocation) (Set TxOutRef)
-> MockChainLogEntry
MCLogUnusedCollaterals (Either (User 'IsPubKey 'Allocation) (Set TxOutRef)
-> MockChainLogEntry)
-> Either (User 'IsPubKey 'Allocation) (Set TxOutRef)
-> MockChainLogEntry
forall a b. (a -> b) -> a -> b
$ User 'IsPubKey 'Allocation
-> Either (User 'IsPubKey 'Allocation) (Set TxOutRef)
forall a b. a -> Either a b
Left (User 'IsPubKey 'Allocation
-> Either (User 'IsPubKey 'Allocation) (Set TxOutRef))
-> User 'IsPubKey 'Allocation
-> Either (User 'IsPubKey 'Allocation) (Set TxOutRef)
forall a b. (a -> b) -> a -> b
$ pkh -> User 'IsPubKey 'Allocation
forall pkh (a :: UserKind) (b :: UserMode).
(a ∈ '[ 'IsPubKey, 'IsEither], ToPubKeyHash pkh, Typeable pkh) =>
pkh -> User a b
UserPubKey pkh
cUser) Sem effs ()
-> Sem effs (Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
-> Sem effs (Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
forall a b. Sem effs a -> Sem effs b -> Sem effs b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> Sem effs (Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
forall a. Maybe a
Nothing
(Bool
True, CollateralUtxos
CollateralUtxosFromBalancingUser) -> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> Sem effs (Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
forall a. Maybe a
Nothing
(Bool
False, CollateralUtxosFromSet Set TxOutRef
utxos pkh
rUser) -> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> Sem effs (Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> Sem effs (Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)))
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> Sem effs (Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
forall a b. (a -> b) -> a -> b
$ (Set TxOutRef, User 'IsPubKey 'Allocation)
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
forall a. a -> Maybe a
Just (Set TxOutRef
utxos, pkh -> User 'IsPubKey 'Allocation
forall pkh (a :: UserKind) (b :: UserMode).
(a ∈ '[ 'IsPubKey, 'IsEither], ToPubKeyHash pkh, Typeable pkh) =>
pkh -> User a b
UserPubKey pkh
rUser)
(Bool
False, CollateralUtxosFromUser (pkh -> PubKeyHash
forall a. ToPubKeyHash a => a -> PubKeyHash
Script.toPubKeyHash -> PubKeyHash
cUser)) ->
(Set TxOutRef, User 'IsPubKey 'Allocation)
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
forall a. a -> Maybe a
Just ((Set TxOutRef, User 'IsPubKey 'Allocation)
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
-> ([TxOutRef] -> (Set TxOutRef, User 'IsPubKey 'Allocation))
-> [TxOutRef]
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (,PubKeyHash -> User 'IsPubKey 'Allocation
forall pkh (a :: UserKind) (b :: UserMode).
(a ∈ '[ 'IsPubKey, 'IsEither], ToPubKeyHash pkh, Typeable pkh) =>
pkh -> User a b
UserPubKey PubKeyHash
cUser) (Set TxOutRef -> (Set TxOutRef, User 'IsPubKey 'Allocation))
-> ([TxOutRef] -> Set TxOutRef)
-> [TxOutRef]
-> (Set TxOutRef, User 'IsPubKey 'Allocation)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [TxOutRef] -> Set TxOutRef
forall a. Ord a => [a] -> Set a
Set.fromList
([TxOutRef] -> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
-> Sem effs [TxOutRef]
-> Sem effs (Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Sem effs (UtxoSearchResult NoIx) -> Sem effs [TxOutRef]
forall (effs :: EffectRow) (elems :: IxList).
Sem effs (UtxoSearchResult elems) -> Sem effs [TxOutRef]
getTxOutRefs (PubKeyHash
-> (Sem effs (UtxoSearchResult NoIx)
-> Sem effs (UtxoSearchResult NoIx))
-> Sem effs (UtxoSearchResult NoIx)
forall (effs :: EffectRow) pkh (els :: IxList).
(Member MockChainRead effs, ToCredential pkh) =>
pkh
-> (UtxoSearch effs NoIx -> UtxoSearch effs els)
-> UtxoSearch effs els
utxosAtSearch PubKeyHash
cUser Sem effs (UtxoSearchResult NoIx)
-> Sem effs (UtxoSearchResult NoIx)
forall (effs :: EffectRow) (els :: IxList).
UtxoSearch effs els -> UtxoSearch effs els
ensureOnlyValueOutputs)
(Bool
False, CollateralUtxos
CollateralUtxosFromBalancingUser) -> case Maybe (User 'IsPubKey 'Allocation)
balancingUser of
Maybe (User 'IsPubKey 'Allocation)
Nothing -> MockChainError
-> Sem effs (Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
forall e (r :: EffectRow) a. Member (Error e) r => e -> Sem r a
throw (MockChainError
-> Sem effs (Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)))
-> MockChainError
-> Sem effs (Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
forall a b. (a -> b) -> a -> b
$ BalancingError -> MockChainError
MCEBalancingError BalancingError
MissingBalancingUser
Just User 'IsPubKey 'Allocation
bUser -> (Set TxOutRef, User 'IsPubKey 'Allocation)
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
forall a. a -> Maybe a
Just ((Set TxOutRef, User 'IsPubKey 'Allocation)
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
-> ([TxOutRef] -> (Set TxOutRef, User 'IsPubKey 'Allocation))
-> [TxOutRef]
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (,User 'IsPubKey 'Allocation
bUser) (Set TxOutRef -> (Set TxOutRef, User 'IsPubKey 'Allocation))
-> ([TxOutRef] -> Set TxOutRef)
-> [TxOutRef]
-> (Set TxOutRef, User 'IsPubKey 'Allocation)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [TxOutRef] -> Set TxOutRef
forall a. Ord a => [a] -> Set a
Set.fromList ([TxOutRef] -> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
-> Sem effs [TxOutRef]
-> Sem effs (Maybe (Set TxOutRef, User 'IsPubKey 'Allocation))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Sem effs (UtxoSearchResult NoIx) -> Sem effs [TxOutRef]
forall (effs :: EffectRow) (elems :: IxList).
Sem effs (UtxoSearchResult elems) -> Sem effs [TxOutRef]
getTxOutRefs (User 'IsPubKey 'Allocation
-> (Sem effs (UtxoSearchResult NoIx)
-> Sem effs (UtxoSearchResult NoIx))
-> Sem effs (UtxoSearchResult NoIx)
forall (effs :: EffectRow) pkh (els :: IxList).
(Member MockChainRead effs, ToCredential pkh) =>
pkh
-> (UtxoSearch effs NoIx -> UtxoSearch effs els)
-> UtxoSearch effs els
utxosAtSearch User 'IsPubKey 'Allocation
bUser Sem effs (UtxoSearchResult NoIx)
-> Sem effs (UtxoSearchResult NoIx)
forall (effs :: EffectRow) (els :: IxList).
UtxoSearch effs els -> UtxoSearch effs els
ensureOnlyValueOutputs)
case Maybe (User 'IsPubKey 'Allocation)
balancingUser of
Maybe (User 'IsPubKey 'Allocation)
Nothing -> do
let fee :: Fee
fee = case TxSkelOpts -> FeePolicy
txSkelOptFeePolicy TxSkelOpts
txSkelOpts of
FeePolicy
AutoFeeComputation -> Fee
maxFee
ManualFee Fee
fee' -> Fee
fee'
Maybe Collaterals
mCols <- Fee
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> Sem effs (Maybe Collaterals)
forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError]
effs =>
Fee
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> Sem effs (Maybe Collaterals)
collateralsFromFee Fee
fee Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
mCollaterals
Body
cBody <- TxSkel -> Fee -> Maybe Collaterals -> Sem effs Body
forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError, Fail]
effs =>
TxSkel -> Fee -> Maybe Collaterals -> Sem effs Body
txSkelToTxBody TxSkel
skelUnbal Fee
fee Maybe Collaterals
mCols
ExtendedTxSkel -> Sem effs ExtendedTxSkel
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (ExtendedTxSkel -> Sem effs ExtendedTxSkel)
-> ExtendedTxSkel -> Sem effs ExtendedTxSkel
forall a b. (a -> b) -> a -> b
$ TxSkel -> Fee -> Maybe Collaterals -> Body -> ExtendedTxSkel
ExtendedTxSkel TxSkel
skelUnbal Fee
fee Maybe Collaterals
mCols Body
cBody
Just User 'IsPubKey 'Allocation
bUser -> do
[Utxo]
balancingUtxos <-
case TxSkelOpts -> BalancingUtxos
txSkelOptBalancingUtxos TxSkelOpts
txSkelOpts of
BalancingUtxos
BalancingUtxosFromBalancingUser -> Sem effs (UtxoSearchResult NoIx) -> Sem effs [Utxo]
forall (effs :: EffectRow) (elems :: IxList).
Sem effs (UtxoSearchResult elems) -> Sem effs [Utxo]
getTxOutRefsAndOutputs (Sem effs (UtxoSearchResult NoIx) -> Sem effs [Utxo])
-> Sem effs (UtxoSearchResult NoIx) -> Sem effs [Utxo]
forall a b. (a -> b) -> a -> b
$ User 'IsPubKey 'Allocation
-> (Sem effs (UtxoSearchResult NoIx)
-> Sem effs (UtxoSearchResult NoIx))
-> Sem effs (UtxoSearchResult NoIx)
forall (effs :: EffectRow) pkh (els :: IxList).
(Member MockChainRead effs, ToCredential pkh) =>
pkh
-> (UtxoSearch effs NoIx -> UtxoSearch effs els)
-> UtxoSearch effs els
utxosAtSearch User 'IsPubKey 'Allocation
bUser Sem effs (UtxoSearchResult NoIx)
-> Sem effs (UtxoSearchResult NoIx)
forall (effs :: EffectRow) (els :: IxList).
UtxoSearch effs els -> UtxoSearch effs els
ensureOnlyValueOutputs
BalancingUtxosFromSet Set TxOutRef
utxos ->
Sem effs (UtxoSearchResult NoIx) -> Sem effs [Utxo]
forall (effs :: EffectRow) (elems :: IxList).
Sem effs (UtxoSearchResult elems) -> Sem effs [Utxo]
getTxOutRefsAndOutputs ([TxOutRef] -> Sem effs (UtxoSearchResult NoIx)
forall (effs :: EffectRow).
Member MockChainRead effs =>
[TxOutRef] -> UtxoSearch effs NoIx
txSkelOutByRefSearch' (Set TxOutRef -> [TxOutRef]
forall a. Set a -> [a]
Set.toList Set TxOutRef
utxos))
Sem effs [Utxo] -> ([Utxo] -> Sem effs [Utxo]) -> Sem effs [Utxo]
forall a b. Sem effs a -> (a -> Sem effs b) -> Sem effs b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Utxo -> Bool) -> String -> [Utxo] -> Sem effs [Utxo]
forall {effs :: EffectRow} {a}.
Member MockChainLog effs =>
(a -> Bool) -> String -> [a] -> Sem effs [a]
filterAndWarn (Optic' An_AffineTraversal NoIx TxSkelOut PubKeyHash
-> TxSkelOut -> Bool
forall k (is :: IxList) s a.
Is k An_AffineFold =>
Optic' k is s a -> s -> Bool
is (Lens' TxSkelOut (User 'IsEither 'Allocation)
txSkelOutOwnerL Lens' TxSkelOut (User 'IsEither 'Allocation)
-> Optic
An_AffineTraversal
NoIx
(User 'IsEither 'Allocation)
(User 'IsEither 'Allocation)
PubKeyHash
PubKeyHash
-> Optic' An_AffineTraversal NoIx TxSkelOut PubKeyHash
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Optic
An_AffineTraversal
NoIx
(User 'IsEither 'Allocation)
(User 'IsEither 'Allocation)
PubKeyHash
PubKeyHash
forall (kind :: UserKind) (mode :: UserMode).
AffineTraversal' (User kind mode) PubKeyHash
userPubKeyHashAT) (TxSkelOut -> Bool) -> (Utxo -> TxSkelOut) -> Utxo -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Utxo -> TxSkelOut
forall a b. (a, b) -> b
snd) String
"They belong to scripts."
Sem effs [Utxo] -> ([Utxo] -> Sem effs [Utxo]) -> Sem effs [Utxo]
forall a b. Sem effs a -> (a -> Sem effs b) -> Sem effs b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Utxo -> Bool) -> String -> [Utxo] -> Sem effs [Utxo]
forall {effs :: EffectRow} {a}.
Member MockChainLog effs =>
(a -> Bool) -> String -> [a] -> Sem effs [a]
filterAndWarn ((TxOutRef -> Set TxOutRef -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` TxSkel -> Set TxOutRef
txSkelKnownTxOutRefs TxSkel
skelUnbal) (TxOutRef -> Bool) -> (Utxo -> TxOutRef) -> Utxo -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Utxo -> TxOutRef
forall a b. (a, b) -> a
fst) String
"They are already used in the skeleton."
case TxSkelOpts -> FeePolicy
txSkelOptFeePolicy TxSkelOpts
txSkelOpts of
FeePolicy
AutoFeeComputation ->
User 'IsPubKey 'Allocation
-> Fee
-> Fee
-> [Utxo]
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> TxSkel
-> Sem effs ExtendedTxSkel
forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError, Fail]
effs =>
User 'IsPubKey 'Allocation
-> Fee
-> Fee
-> [Utxo]
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> TxSkel
-> Sem effs ExtendedTxSkel
computeFeeAndBalance User 'IsPubKey 'Allocation
bUser Fee
minFee Fee
maxFee [Utxo]
balancingUtxos Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
mCollaterals TxSkel
skelUnbal
ManualFee Fee
fee -> do
Maybe Collaterals
mCols <- Fee
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> Sem effs (Maybe Collaterals)
forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError]
effs =>
Fee
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> Sem effs (Maybe Collaterals)
collateralsFromFee Fee
fee Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
mCollaterals
TxSkel
balancedSkel <- User 'IsPubKey 'Allocation
-> [Utxo] -> TxSkel -> Fee -> Sem effs TxSkel
forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError]
effs =>
User 'IsPubKey 'Allocation
-> [Utxo] -> TxSkel -> Fee -> Sem effs TxSkel
computeBalancedTxSkel User 'IsPubKey 'Allocation
bUser [Utxo]
balancingUtxos TxSkel
skelUnbal Fee
fee
Body
cBody <- TxSkel -> Fee -> Maybe Collaterals -> Sem effs Body
forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError, Fail]
effs =>
TxSkel -> Fee -> Maybe Collaterals -> Sem effs Body
txSkelToTxBody TxSkel
balancedSkel Fee
fee Maybe Collaterals
mCols
ExtendedTxSkel -> Sem effs ExtendedTxSkel
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (ExtendedTxSkel -> Sem effs ExtendedTxSkel)
-> ExtendedTxSkel -> Sem effs ExtendedTxSkel
forall a b. (a -> b) -> a -> b
$ TxSkel -> Fee -> Maybe Collaterals -> Body -> ExtendedTxSkel
ExtendedTxSkel TxSkel
balancedSkel Fee
fee Maybe Collaterals
mCols Body
cBody
where
filterAndWarn :: (a -> Bool) -> String -> [a] -> Sem effs [a]
filterAndWarn a -> Bool
f String
s [a]
l
| ([a]
ok, Int -> Fee
forall a. Integral a => a -> Fee
toInteger (Int -> Fee) -> ([a] -> Int) -> [a] -> Fee
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length -> Fee
koLength) <- (a -> Bool) -> [a] -> ([a], [a])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition a -> Bool
f [a]
l =
Bool -> Sem effs () -> Sem effs ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Fee
koLength Fee -> Fee -> Bool
forall a. Eq a => a -> a -> Bool
== Fee
0) (MockChainLogEntry -> Sem effs ()
forall (effs :: EffectRow).
Member MockChainLog effs =>
MockChainLogEntry -> Sem effs ()
logEvent (MockChainLogEntry -> Sem effs ())
-> MockChainLogEntry -> Sem effs ()
forall a b. (a -> b) -> a -> b
$ Fee -> String -> MockChainLogEntry
MCLogDiscardedUtxos Fee
koLength String
s) Sem effs () -> Sem effs [a] -> Sem effs [a]
forall a b. Sem effs a -> Sem effs b -> Sem effs b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [a] -> Sem effs [a]
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return [a]
ok
computeFeeAndBalance ::
(Members '[MockChainRead, Error MockChainError, Error Ledger.ToCardanoError, Fail] effs) =>
Peer ->
Fee ->
Fee ->
Utxos ->
Maybe (CollateralIns, Peer) ->
TxSkel ->
Sem effs ExtendedTxSkel
computeFeeAndBalance :: forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError, Fail]
effs =>
User 'IsPubKey 'Allocation
-> Fee
-> Fee
-> [Utxo]
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> TxSkel
-> Sem effs ExtendedTxSkel
computeFeeAndBalance User 'IsPubKey 'Allocation
_ Fee
minFee Fee
maxFee [Utxo]
_ Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
_ TxSkel
_
| Fee
minFee Fee -> Fee -> Bool
forall a. Ord a => a -> a -> Bool
> Fee
maxFee =
String -> Sem effs ExtendedTxSkel
forall a. String -> Sem effs a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Unreachable case, please report a bug at https://github.com/tweag/cooked-validators/issues"
computeFeeAndBalance User 'IsPubKey 'Allocation
balancingUser Fee
minFee Fee
maxFee [Utxo]
balancingUtxos Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
mCollaterals TxSkel
skel = do
let fee :: Fee
fee = (Fee
minFee Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
+ Fee
maxFee) Fee -> Fee -> Fee
forall a. Integral a => a -> a -> a
`div` Fee
2
Sem effs ExtendedTxSkel
-> (MockChainError -> Sem effs ExtendedTxSkel)
-> Sem effs ExtendedTxSkel
forall e (r :: EffectRow) a.
Member (Error e) r =>
Sem r a -> (e -> Sem r a) -> Sem r a
catch
( do
TxSkel
newSkel <- User 'IsPubKey 'Allocation
-> [Utxo] -> TxSkel -> Fee -> Sem effs TxSkel
forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError]
effs =>
User 'IsPubKey 'Allocation
-> [Utxo] -> TxSkel -> Fee -> Sem effs TxSkel
computeBalancedTxSkel User 'IsPubKey 'Allocation
balancingUser [Utxo]
balancingUtxos TxSkel
skel Fee
fee
Maybe Collaterals
mCols <- Fee
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> Sem effs (Maybe Collaterals)
forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError]
effs =>
Fee
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> Sem effs (Maybe Collaterals)
collateralsFromFee Fee
fee Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
mCollaterals
(Fee
newFee, Body
body) <- TxSkel -> Fee -> Maybe Collaterals -> Sem effs (Fee, Body)
forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError, Fail]
effs =>
TxSkel -> Fee -> Maybe Collaterals -> Sem effs (Fee, Body)
estimateTxSkelFee TxSkel
newSkel Fee
fee Maybe Collaterals
mCols
if
| Fee
minFee Fee -> Fee -> Bool
forall a. Eq a => a -> a -> Bool
== Fee
maxFee Bool -> Bool -> Bool
&& Fee
newFee Fee -> Fee -> Bool
forall a. Ord a => a -> a -> Bool
<= Fee
fee -> ExtendedTxSkel -> Sem effs ExtendedTxSkel
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (ExtendedTxSkel -> Sem effs ExtendedTxSkel)
-> ExtendedTxSkel -> Sem effs ExtendedTxSkel
forall a b. (a -> b) -> a -> b
$ TxSkel -> Fee -> Maybe Collaterals -> Body -> ExtendedTxSkel
ExtendedTxSkel TxSkel
newSkel Fee
newFee Maybe Collaterals
mCols Body
body
| Fee
minFee Fee -> Fee -> Bool
forall a. Eq a => a -> a -> Bool
== Fee
maxFee -> MockChainError -> Sem effs ExtendedTxSkel
forall e (r :: EffectRow) a. Member (Error e) r => e -> Sem r a
throw (MockChainError -> Sem effs ExtendedTxSkel)
-> MockChainError -> Sem effs ExtendedTxSkel
forall a b. (a -> b) -> a -> b
$ BalancingError -> MockChainError
MCEBalancingError (BalancingError -> MockChainError)
-> BalancingError -> MockChainError
forall a b. (a -> b) -> a -> b
$ User 'IsPubKey 'Allocation -> BalancingError
NotEnoughFundForProperFee User 'IsPubKey 'Allocation
balancingUser
| Fee
newFee Fee -> Fee -> Bool
forall a. Ord a => a -> a -> Bool
> Fee
fee -> User 'IsPubKey 'Allocation
-> Fee
-> Fee
-> [Utxo]
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> TxSkel
-> Sem effs ExtendedTxSkel
forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError, Fail]
effs =>
User 'IsPubKey 'Allocation
-> Fee
-> Fee
-> [Utxo]
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> TxSkel
-> Sem effs ExtendedTxSkel
computeFeeAndBalance User 'IsPubKey 'Allocation
balancingUser Fee
newFee Fee
maxFee [Utxo]
balancingUtxos Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
mCollaterals TxSkel
skel
| TxSkel -> Value
txSkelValueInOutputs TxSkel
newSkel Value -> Value -> Bool
forall a. Eq a => a -> a -> Bool
== TxSkel -> Value
txSkelValueInOutputs TxSkel
skel -> User 'IsPubKey 'Allocation
-> Fee
-> Fee
-> [Utxo]
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> TxSkel
-> Sem effs ExtendedTxSkel
forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError, Fail]
effs =>
User 'IsPubKey 'Allocation
-> Fee
-> Fee
-> [Utxo]
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> TxSkel
-> Sem effs ExtendedTxSkel
computeFeeAndBalance User 'IsPubKey 'Allocation
balancingUser Fee
minFee Fee
fee [Utxo]
balancingUtxos Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
mCollaterals TxSkel
skel
| Bool
otherwise -> User 'IsPubKey 'Allocation
-> Fee
-> Fee
-> [Utxo]
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> TxSkel
-> Sem effs ExtendedTxSkel
forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError, Fail]
effs =>
User 'IsPubKey 'Allocation
-> Fee
-> Fee
-> [Utxo]
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> TxSkel
-> Sem effs ExtendedTxSkel
computeFeeAndBalance User 'IsPubKey 'Allocation
balancingUser Fee
minFee Fee
newFee [Utxo]
balancingUtxos Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
mCollaterals TxSkel
skel
)
((MockChainError -> Sem effs ExtendedTxSkel)
-> Sem effs ExtendedTxSkel)
-> (MockChainError -> Sem effs ExtendedTxSkel)
-> Sem effs ExtendedTxSkel
forall a b. (a -> b) -> a -> b
$ \case
MCEBalancingError {} | Fee
fee Fee -> Fee -> Bool
forall a. Ord a => a -> a -> Bool
> Fee
minFee -> User 'IsPubKey 'Allocation
-> Fee
-> Fee
-> [Utxo]
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> TxSkel
-> Sem effs ExtendedTxSkel
forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError, Fail]
effs =>
User 'IsPubKey 'Allocation
-> Fee
-> Fee
-> [Utxo]
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> TxSkel
-> Sem effs ExtendedTxSkel
computeFeeAndBalance User 'IsPubKey 'Allocation
balancingUser Fee
minFee (Fee
fee Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
- Fee
1) [Utxo]
balancingUtxos Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
mCollaterals TxSkel
skel
MockChainError
err -> MockChainError -> Sem effs ExtendedTxSkel
forall e (r :: EffectRow) a. Member (Error e) r => e -> Sem r a
throw MockChainError
err
collateralsFromFee ::
(Members '[MockChainRead, Error MockChainError, Error Ledger.ToCardanoError] effs) =>
Fee ->
Maybe (CollateralIns, Peer) ->
Sem effs (Maybe Collaterals)
collateralsFromFee :: forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError]
effs =>
Fee
-> Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
-> Sem effs (Maybe Collaterals)
collateralsFromFee Fee
_ Maybe (Set TxOutRef, User 'IsPubKey 'Allocation)
Nothing = Maybe Collaterals -> Sem effs (Maybe Collaterals)
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Collaterals
forall a. Maybe a
Nothing
collateralsFromFee Fee
fee (Just (Set TxOutRef
collateralIns, User 'IsPubKey 'Allocation
returnCollateralUser)) = do
PParams
params <- Params -> PParams
Emulator.pEmulatorPParams (Params -> PParams) -> Sem effs Params -> Sem effs PParams
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Sem effs Params
forall (effs :: EffectRow).
Member MockChainRead effs =>
Sem effs Params
getParams
let nbMax :: Fee
nbMax = Natural -> Fee
forall a. Integral a => a -> Fee
toInteger (Natural -> Fee) -> Natural -> Fee
forall a b. (a -> b) -> a -> b
$ Getting Natural PParams Natural -> PParams -> Natural
forall a s. Getting a s a -> s -> a
MicroLens.view Getting Natural PParams Natural
forall era. AlonzoEraPParams era => Lens' (PParams era) Natural
Lens' PParams Natural
Conway.ppMaxCollateralInputsL PParams
params
let percentage :: Fee
percentage = Natural -> Fee
forall a. Integral a => a -> Fee
toInteger (Natural -> Fee) -> Natural -> Fee
forall a b. (a -> b) -> a -> b
$ Getting Natural PParams Natural -> PParams -> Natural
forall a s. Getting a s a -> s -> a
MicroLens.view Getting Natural PParams Natural
forall era. AlonzoEraPParams era => Lens' (PParams era) Natural
Lens' PParams Natural
Conway.ppCollateralPercentageL PParams
params
let totalCollateral :: Value
totalCollateral = Fee -> Value
Script.lovelace (Fee -> Value) -> (Fee -> Fee) -> Fee -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
+ Fee
1) (Fee -> Fee) -> (Fee -> Fee) -> Fee -> Fee
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Fee -> Fee -> Fee
forall a. Integral a => a -> a -> a
`div` Fee
100) (Fee -> Fee) -> (Fee -> Fee) -> Fee -> Fee
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
* Fee
percentage) (Fee -> Value) -> Fee -> Value
forall a b. (a -> b) -> a -> b
$ Fee
fee
[Utxo]
collateralTxOuts <- Sem effs (UtxoSearchResult NoIx) -> Sem effs [Utxo]
forall (effs :: EffectRow) (elems :: IxList).
Sem effs (UtxoSearchResult elems) -> Sem effs [Utxo]
getTxOutRefsAndOutputs (Sem effs (UtxoSearchResult NoIx) -> Sem effs [Utxo])
-> Sem effs (UtxoSearchResult NoIx) -> Sem effs [Utxo]
forall a b. (a -> b) -> a -> b
$ [TxOutRef] -> Sem effs (UtxoSearchResult NoIx)
forall (effs :: EffectRow).
Member MockChainRead effs =>
[TxOutRef] -> UtxoSearch effs NoIx
txSkelOutByRefSearch' ([TxOutRef] -> Sem effs (UtxoSearchResult NoIx))
-> [TxOutRef] -> Sem effs (UtxoSearchResult NoIx)
forall a b. (a -> b) -> a -> b
$ Set TxOutRef -> [TxOutRef]
forall a. Set a -> [a]
Set.toList Set TxOutRef
collateralIns
Maybe ([TxOutRef], Maybe TxSkelOut)
reachedValue <- [Utxo]
-> Value
-> Fee
-> Either TxSkelOut (User 'IsPubKey 'Allocation)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut))
forall (effs :: EffectRow).
Members '[MockChainRead, Error ToCardanoError] effs =>
[Utxo]
-> Value
-> Fee
-> Either TxSkelOut (User 'IsPubKey 'Allocation)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut))
reachValue [Utxo]
collateralTxOuts Value
totalCollateral Fee
nbMax (Either TxSkelOut (User 'IsPubKey 'Allocation)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut)))
-> Either TxSkelOut (User 'IsPubKey 'Allocation)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut))
forall a b. (a -> b) -> a -> b
$ User 'IsPubKey 'Allocation
-> Either TxSkelOut (User 'IsPubKey 'Allocation)
forall a b. b -> Either a b
Right User 'IsPubKey 'Allocation
returnCollateralUser
case Maybe ([TxOutRef], Maybe TxSkelOut)
reachedValue of
Maybe ([TxOutRef], Maybe TxSkelOut)
Nothing -> MockChainError -> Sem effs (Maybe Collaterals)
forall e (r :: EffectRow) a. Member (Error e) r => e -> Sem r a
throw (MockChainError -> Sem effs (Maybe Collaterals))
-> MockChainError -> Sem effs (Maybe Collaterals)
forall a b. (a -> b) -> a -> b
$ BalancingError -> MockChainError
MCEBalancingError (BalancingError -> MockChainError)
-> BalancingError -> MockChainError
forall a b. (a -> b) -> a -> b
$ Fee -> Fee -> Value -> BalancingError
NoSuitableCollateral Fee
fee Fee
percentage Value
totalCollateral
Just ([TxOutRef]
oRefs, Maybe TxSkelOut
returnOutput) -> Maybe Collaterals -> Sem effs (Maybe Collaterals)
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Collaterals -> Sem effs (Maybe Collaterals))
-> Maybe Collaterals -> Sem effs (Maybe Collaterals)
forall a b. (a -> b) -> a -> b
$ Collaterals -> Maybe Collaterals
forall a. a -> Maybe a
Just ([TxOutRef] -> Set TxOutRef
forall a. Ord a => [a] -> Set a
Set.fromList [TxOutRef]
oRefs, Maybe TxSkelOut
returnOutput)
reachValue ::
forall effs.
(Members '[MockChainRead, Error Ledger.ToCardanoError] effs) =>
Utxos ->
Api.Value ->
Integer ->
Either TxSkelOut Peer ->
Sem effs (Maybe ([Api.TxOutRef], Maybe TxSkelOut))
reachValue :: forall (effs :: EffectRow).
Members '[MockChainRead, Error ToCardanoError] effs =>
[Utxo]
-> Value
-> Fee
-> Either TxSkelOut (User 'IsPubKey 'Allocation)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut))
reachValue [Utxo]
utxos Value
target Fee
fuel Either TxSkelOut (User 'IsPubKey 'Allocation)
outputOrUser = do
Cardano.ProtVer Version
majorVersion Natural
_ <- Getting ProtVer PParams ProtVer -> PParams -> ProtVer
forall a s. Getting a s a -> s -> a
Micro.view Getting ProtVer PParams ProtVer
forall era. EraPParams era => Lens' (PParams era) ProtVer
Lens' PParams ProtVer
Conway.ppProtocolVersionL (PParams -> ProtVer) -> (Params -> PParams) -> Params -> ProtVer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Params -> PParams
Emulator.emulatorPParams (Params -> ProtVer) -> Sem effs Params -> Sem effs ProtVer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Sem effs Params
forall (effs :: EffectRow).
Member MockChainRead effs =>
Sem effs Params
getParams
Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
outputOrUser' <- case Either TxSkelOut (User 'IsPubKey 'Allocation)
outputOrUser of
Left TxSkelOut
output -> (TxSkelOut, Fee)
-> Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
forall a b. a -> Either a b
Left ((TxSkelOut, Fee)
-> Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation))
-> (Fee -> (TxSkelOut, Fee))
-> Fee
-> Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TxSkelOut
output,) (Fee -> Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation))
-> Sem effs Fee
-> Sem effs (Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Version -> TxSkelOut -> Sem effs Fee
outputSize Version
majorVersion TxSkelOut
output
Right User 'IsPubKey 'Allocation
user -> Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
-> Sem effs (Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
-> Sem effs (Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)))
-> Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
-> Sem effs (Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation))
forall a b. (a -> b) -> a -> b
$ User 'IsPubKey 'Allocation
-> Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
forall a b. b -> Either a b
Right User 'IsPubKey 'Allocation
user
[(TxOutRef, Fee, Value)]
utxos' <- [Utxo]
-> (Utxo -> Sem effs (TxOutRef, Fee, Value))
-> Sem effs [(TxOutRef, Fee, Value)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [Utxo]
utxos ((Utxo -> Sem effs (TxOutRef, Fee, Value))
-> Sem effs [(TxOutRef, Fee, Value)])
-> (Utxo -> Sem effs (TxOutRef, Fee, Value))
-> Sem effs [(TxOutRef, Fee, Value)]
forall a b. (a -> b) -> a -> b
$ \(TxOutRef
oRef, TxSkelOut
output) -> (TxOutRef
oRef,,Optic' A_Lens NoIx TxSkelOut Value -> TxSkelOut -> Value
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' A_Lens NoIx TxSkelOut Value
txSkelOutValueL TxSkelOut
output) (Fee -> (TxOutRef, Fee, Value))
-> Sem effs Fee -> Sem effs (TxOutRef, Fee, Value)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Version -> TxOutRef -> Sem effs Fee
inputSize Version
majorVersion TxOutRef
oRef
(([TxOutRef], Maybe TxSkelOut, Fee)
-> ([TxOutRef], Maybe TxSkelOut))
-> Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Maybe ([TxOutRef], Maybe TxSkelOut)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\([TxOutRef]
oRefs, Maybe TxSkelOut
mOut, Fee
_) -> ([TxOutRef]
oRefs, Maybe TxSkelOut
mOut))
(Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Maybe ([TxOutRef], Maybe TxSkelOut))
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Version
-> [(TxOutRef, Fee, Value)]
-> Value
-> Fee
-> Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
-> Value
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
go Version
majorVersion [(TxOutRef, Fee, Value)]
utxos' Value
target Fee
fuel Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
outputOrUser' ([Value] -> Value
forall a. Monoid a => [a] -> a
mconcat ((\(TxOutRef
_, Fee
_, Value
val) -> Value
val) ((TxOutRef, Fee, Value) -> Value)
-> [(TxOutRef, Fee, Value)] -> [Value]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(TxOutRef, Fee, Value)]
utxos'))
where
go ::
Cardano.Version ->
[(Api.TxOutRef, Integer, Api.Value)] ->
Api.Value ->
Integer ->
Either (TxSkelOut, Integer) Peer ->
Api.Value ->
Sem effs (Maybe ([Api.TxOutRef], Maybe TxSkelOut, Integer))
go :: Version
-> [(TxOutRef, Fee, Value)]
-> Value
-> Fee
-> Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
-> Value
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
go Version
majorVersion [(TxOutRef, Fee, Value)]
goUtxos Value
goTarget Fee
goFuel Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
goOutputOrUser Value
goAvailable | Value
goTarget Value -> Value -> Bool
`Api.leq` Value
forall a. Monoid a => a
mempty = do
let remainder :: Value
remainder = Value -> Value
forall a. AdditiveGroup a => a -> a
PlutusTx.negate Value
goTarget
newOutput :: TxSkelOut
newOutput = ((TxSkelOut, Fee) -> TxSkelOut)
-> (User 'IsPubKey 'Allocation -> TxSkelOut)
-> Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
-> TxSkelOut
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Optic' A_Lens NoIx TxSkelOut Value
-> (Value -> Value) -> TxSkelOut -> TxSkelOut
forall k (is :: IxList) s t a b.
Is k A_Setter =>
Optic k is s t a b -> (a -> b) -> s -> t
over Optic' A_Lens NoIx TxSkelOut Value
txSkelOutValueL (Value -> Value -> Value
forall a. Semigroup a => a -> a -> a
<> Value
remainder) (TxSkelOut -> TxSkelOut)
-> ((TxSkelOut, Fee) -> TxSkelOut) -> (TxSkelOut, Fee) -> TxSkelOut
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TxSkelOut, Fee) -> TxSkelOut
forall a b. (a, b) -> a
fst) (User 'IsPubKey 'Allocation -> Payable '[ 'IsValue] -> TxSkelOut
forall owner (els :: [PayableKind]).
IsTxSkelOutAllowedOwner owner =>
owner -> Payable els -> TxSkelOut
`receives` Value -> Payable '[ 'IsValue]
forall a1. ToValue a1 => a1 -> Payable '[ 'IsValue]
Value Value
remainder) Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
goOutputOrUser
newOutputValue :: Value
newOutputValue = Optic' A_Lens NoIx TxSkelOut Value -> TxSkelOut -> Value
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' A_Lens NoIx TxSkelOut Value
txSkelOutValueL TxSkelOut
newOutput
Lovelace
minAda <- Fee -> Lovelace
Api.Lovelace (Fee -> Lovelace) -> Sem effs Fee -> Sem effs Lovelace
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TxSkelOut -> Sem effs Fee
forall (effs :: EffectRow).
Members '[MockChainRead, Error ToCardanoError] effs =>
TxSkelOut -> Sem effs Fee
getTxSkelOutMinAda TxSkelOut
newOutput
case Value
newOutputValue of
Value
newVal | Value
newVal Value -> Value -> Bool
forall a. Eq a => a -> a -> Bool
== Value
forall a. Monoid a => a
mempty -> Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee)))
-> Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
forall a b. (a -> b) -> a -> b
$ ([TxOutRef], Maybe TxSkelOut, Fee)
-> Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
forall a. a -> Maybe a
Just ([], Maybe TxSkelOut
forall a. Maybe a
Nothing, Fee
0)
Value
newVal | Optic' A_Lens NoIx Value Lovelace -> Value -> Lovelace
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' A_Lens NoIx Value Lovelace
valueLovelaceL Value
newVal Lovelace -> Lovelace -> Bool
forall a. Ord a => a -> a -> Bool
>= Lovelace
minAda -> do
Fee
newCost <- Version -> TxSkelOut -> Sem effs Fee
outputSize Version
majorVersion TxSkelOut
newOutput
Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee)))
-> Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
forall a b. (a -> b) -> a -> b
$ ([TxOutRef], Maybe TxSkelOut, Fee)
-> Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
forall a. a -> Maybe a
Just ([], TxSkelOut -> Maybe TxSkelOut
forall a. a -> Maybe a
Just TxSkelOut
newOutput, ((TxSkelOut, Fee) -> Fee)
-> (User 'IsPubKey 'Allocation -> Fee)
-> Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
-> Fee
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ((Fee
newCost Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
-) (Fee -> Fee)
-> ((TxSkelOut, Fee) -> Fee) -> (TxSkelOut, Fee) -> Fee
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TxSkelOut, Fee) -> Fee
forall a b. (a, b) -> b
snd) (Fee -> User 'IsPubKey 'Allocation -> Fee
forall a b. a -> b -> a
const Fee
newCost) Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
goOutputOrUser)
(Lovelace -> Value
forall a. ToValue a => a -> Value
Script.toValue (Lovelace -> Value) -> (Value -> Lovelace) -> Value -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Lovelace
minAda Lovelace -> Lovelace -> Lovelace
forall a. Num a => a -> a -> a
-) (Lovelace -> Lovelace) -> (Value -> Lovelace) -> Value -> Lovelace
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Optic' A_Lens NoIx Value Lovelace -> Value -> Lovelace
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' A_Lens NoIx Value Lovelace
valueLovelaceL -> Value
missingAdaValue) -> do
(Fee
sizeAdded, Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
goOutputOrUser') <- case Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
goOutputOrUser of
Left (TxSkelOut
output, Fee
existingSize) -> do
let enlargedOutput :: TxSkelOut
enlargedOutput = Optic' A_Lens NoIx TxSkelOut Value
-> (Value -> Value) -> TxSkelOut -> TxSkelOut
forall k (is :: IxList) s t a b.
Is k A_Setter =>
Optic k is s t a b -> (a -> b) -> s -> t
over Optic' A_Lens NoIx TxSkelOut Value
txSkelOutValueL (Value -> Value -> Value
forall a. Semigroup a => a -> a -> a
<> Value
missingAdaValue) TxSkelOut
output
Fee
newSize <- Version -> TxSkelOut -> Sem effs Fee
outputSize Version
majorVersion TxSkelOut
enlargedOutput
(Fee, Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation))
-> Sem
effs (Fee, Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (Fee
newSize Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
- Fee
existingSize, (TxSkelOut, Fee)
-> Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
forall a b. a -> Either a b
Left (TxSkelOut
enlargedOutput, Fee
newSize))
Right User 'IsPubKey 'Allocation
user -> do
let output :: TxSkelOut
output = User 'IsPubKey 'Allocation
user User 'IsPubKey 'Allocation -> Payable '[ 'IsValue] -> TxSkelOut
forall owner (els :: [PayableKind]).
IsTxSkelOutAllowedOwner owner =>
owner -> Payable els -> TxSkelOut
`receives` Value -> Payable '[ 'IsValue]
forall a1. ToValue a1 => a1 -> Payable '[ 'IsValue]
Value Value
missingAdaValue
Fee
size <- Version -> TxSkelOut -> Sem effs Fee
outputSize Version
majorVersion TxSkelOut
output
(Fee, Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation))
-> Sem
effs (Fee, Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (Fee
size, (TxSkelOut, Fee)
-> Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
forall a b. a -> Either a b
Left (TxSkelOut
output, Fee
size))
Optic
An_AffineTraversal
NoIx
(Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
(Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
Fee
Fee
-> (Fee -> Fee)
-> Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
forall k (is :: IxList) s t a b.
Is k A_Setter =>
Optic k is s t a b -> (a -> b) -> s -> t
over (Prism
(Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
(Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
([TxOutRef], Maybe TxSkelOut, Fee)
([TxOutRef], Maybe TxSkelOut, Fee)
forall a b. Prism (Maybe a) (Maybe b) a b
_Just Prism
(Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
(Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
([TxOutRef], Maybe TxSkelOut, Fee)
([TxOutRef], Maybe TxSkelOut, Fee)
-> Optic
A_Lens
NoIx
([TxOutRef], Maybe TxSkelOut, Fee)
([TxOutRef], Maybe TxSkelOut, Fee)
Fee
Fee
-> Optic
An_AffineTraversal
NoIx
(Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
(Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
Fee
Fee
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Optic
A_Lens
NoIx
([TxOutRef], Maybe TxSkelOut, Fee)
([TxOutRef], Maybe TxSkelOut, Fee)
Fee
Fee
forall s t a b. Field3 s t a b => Lens s t a b
_3) (Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
+ Fee
sizeAdded)
(Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Version
-> [(TxOutRef, Fee, Value)]
-> Value
-> Fee
-> Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
-> Value
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
go Version
majorVersion [(TxOutRef, Fee, Value)]
goUtxos (Value
goTarget Value -> Value -> Value
forall a. Semigroup a => a -> a -> a
<> Value
missingAdaValue) Fee
goFuel Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
goOutputOrUser' Value
goAvailable
go Version
_ [(TxOutRef, Fee, Value)]
_ Value
_ Fee
goFuel Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
_ Value
_ | Fee
goFuel Fee -> Fee -> Bool
forall a. Ord a => a -> a -> Bool
<= Fee
0 = Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
forall a. Maybe a
Nothing
go Version
_ [] Value
_ Fee
_ Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
_ Value
_ = Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
forall a. Maybe a
Nothing
go Version
_ [(TxOutRef, Fee, Value)]
_ Value
goTarget Fee
_ Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
_ Value
goAvailable | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Value
goTarget Value -> Value -> Bool
`Api.leq` Value
goAvailable = Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
forall a. Maybe a
Nothing
go Version
majorVersion ((TxOutRef
hOref, Fee
hSize, Value
hValue) : [(TxOutRef, Fee, Value)]
t) Value
goTarget Fee
goFuel Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
goOutputOrUser ((Value -> Value -> Value
forall a. Semigroup a => a -> a -> a
<> Value -> Value
forall a. AdditiveGroup a => a -> a
PlutusTx.negate Value
hValue) -> Value
goAvailable) = do
Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
dropH <- Version
-> [(TxOutRef, Fee, Value)]
-> Value
-> Fee
-> Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
-> Value
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
go Version
majorVersion [(TxOutRef, Fee, Value)]
t Value
goTarget Fee
goFuel Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
goOutputOrUser Value
goAvailable
Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
pickH <-
if (Value, Value) -> Value
forall a b. (a, b) -> b
snd (Value -> (Value, Value)
Api.split Value
goTarget) Value -> Value -> Value
forall a. MeetSemiLattice a => a -> a -> a
PlutusTx./\ Value
hValue Value -> Value -> Bool
forall a. Eq a => a -> a -> Bool
== Value
forall a. Monoid a => a
mempty
then Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
forall a. Maybe a
Nothing
else do
Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
pickH' <- Version
-> [(TxOutRef, Fee, Value)]
-> Value
-> Fee
-> Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
-> Value
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
go Version
majorVersion [(TxOutRef, Fee, Value)]
t (Value
goTarget Value -> Value -> Value
forall a. Semigroup a => a -> a -> a
<> Value -> Value
forall a. AdditiveGroup a => a -> a
PlutusTx.negate Value
hValue) (Fee
goFuel Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
- Fee
1) Either (TxSkelOut, Fee) (User 'IsPubKey 'Allocation)
goOutputOrUser Value
goAvailable
Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee)))
-> Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
forall a b. (a -> b) -> a -> b
$ (\([TxOutRef]
oRefs, Maybe TxSkelOut
mOut, Fee
size) -> (TxOutRef
hOref TxOutRef -> [TxOutRef] -> [TxOutRef]
forall a. a -> [a] -> [a]
: [TxOutRef]
oRefs, Maybe TxSkelOut
mOut, Fee
hSize Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
+ Fee
size)) (([TxOutRef], Maybe TxSkelOut, Fee)
-> ([TxOutRef], Maybe TxSkelOut, Fee))
-> Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
pickH'
Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee)))
-> Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut, Fee))
forall a b. (a -> b) -> a -> b
$ case (Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
dropH, Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
pickH) of
(Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
Nothing, Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
_) -> Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
pickH
(Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
_, Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
Nothing) -> Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
dropH
(Just ([TxOutRef]
_, Maybe TxSkelOut
_, Fee
sizeDrop), Just ([TxOutRef]
_, Maybe TxSkelOut
_, Fee
sizePick)) -> if Fee
sizeDrop Fee -> Fee -> Bool
forall a. Ord a => a -> a -> Bool
<= Fee
sizePick then Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
dropH else Maybe ([TxOutRef], Maybe TxSkelOut, Fee)
pickH
computeSize :: Version -> a -> c
computeSize Version
majorVersion = Int -> c
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> c) -> (a -> Int) -> a -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Int
BS.length (ByteString -> Int) -> (a -> ByteString) -> a -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Version -> a -> ByteString
forall a. EncCBOR a => Version -> a -> ByteString
Cardano.serialize' Version
majorVersion
outputSize :: Cardano.Version -> TxSkelOut -> Sem effs Integer
outputSize :: Version -> TxSkelOut -> Sem effs Fee
outputSize Version
majorVersion = (TxOut CtxTx ConwayEra -> Fee)
-> Sem effs (TxOut CtxTx ConwayEra) -> Sem effs Fee
forall a b. (a -> b) -> Sem effs a -> Sem effs b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Version -> BabbageTxOut EmulatorEra -> Fee
forall {c} {a}. (Num c, EncCBOR a) => Version -> a -> c
computeSize Version
majorVersion (BabbageTxOut EmulatorEra -> Fee)
-> (TxOut CtxTx ConwayEra -> BabbageTxOut EmulatorEra)
-> TxOut CtxTx ConwayEra
-> Fee
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShelleyBasedEra ConwayEra
-> TxOut CtxTx ConwayEra -> TxOut EmulatorEra
forall ctx era ledgerera.
(HasCallStack, ShelleyLedgerEra era ~ ledgerera) =>
ShelleyBasedEra era -> TxOut ctx era -> TxOut ledgerera
Cardano.toShelleyTxOutAny ShelleyBasedEra ConwayEra
Cardano.ShelleyBasedEraConway) (Sem effs (TxOut CtxTx ConwayEra) -> Sem effs Fee)
-> (TxSkelOut -> Sem effs (TxOut CtxTx ConwayEra))
-> TxSkelOut
-> Sem effs Fee
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxSkelOut -> Sem effs (TxOut CtxTx ConwayEra)
forall (effs :: EffectRow).
Members '[MockChainRead, Error ToCardanoError] effs =>
TxSkelOut -> Sem effs (TxOut CtxTx ConwayEra)
toCardanoTxOut
inputSize :: Cardano.Version -> Api.TxOutRef -> Sem effs Integer
inputSize :: Version -> TxOutRef -> Sem effs Fee
inputSize Version
majorVersion = (TxIn -> Fee) -> Sem effs TxIn -> Sem effs Fee
forall a b. (a -> b) -> Sem effs a -> Sem effs b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Version -> TxIn -> Fee
forall {c} {a}. (Num c, EncCBOR a) => Version -> a -> c
computeSize Version
majorVersion (TxIn -> Fee) -> (TxIn -> TxIn) -> TxIn -> Fee
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxIn -> TxIn
Cardano.toShelleyTxIn) (Sem effs TxIn -> Sem effs Fee)
-> (TxOutRef -> Sem effs TxIn) -> TxOutRef -> Sem effs Fee
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either ToCardanoError TxIn -> Sem effs TxIn
forall e (r :: EffectRow) a.
Member (Error e) r =>
Either e a -> Sem r a
fromEither (Either ToCardanoError TxIn -> Sem effs TxIn)
-> (TxOutRef -> Either ToCardanoError TxIn)
-> TxOutRef
-> Sem effs TxIn
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxOutRef -> Either ToCardanoError TxIn
Ledger.toCardanoTxIn
estimateTxSkelFee ::
(Members '[MockChainRead, Error MockChainError, Error Ledger.ToCardanoError, Fail] effs) =>
TxSkel ->
Fee ->
Maybe Collaterals ->
Sem effs (Fee, Body)
estimateTxSkelFee :: forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError, Fail]
effs =>
TxSkel -> Fee -> Maybe Collaterals -> Sem effs (Fee, Body)
estimateTxSkelFee TxSkel
skel Fee
fee Maybe Collaterals
mCollaterals = do
PParams
params <- Params -> PParams
Emulator.pEmulatorPParams (Params -> PParams) -> Sem effs Params -> Sem effs PParams
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Sem effs Params
forall (effs :: EffectRow).
Member MockChainRead effs =>
Sem effs Params
getParams
UTxO ConwayEra
index <- TxSkel -> Maybe Collaterals -> Sem effs (UTxO ConwayEra)
forall (effs :: EffectRow).
Members '[MockChainRead, Error ToCardanoError] effs =>
TxSkel -> Maybe Collaterals -> Sem effs (UTxO ConwayEra)
txSkelToIndex TxSkel
skel Maybe Collaterals
mCollaterals
Body
txBody <- TxSkel -> Fee -> Maybe Collaterals -> Sem effs Body
forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError, Fail]
effs =>
TxSkel -> Fee -> Maybe Collaterals -> Sem effs Body
txSkelToTxBody TxSkel
skel Fee
fee Maybe Collaterals
mCollaterals
let nbOfSignatories :: Word
nbOfSignatories = Int -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word) -> Int -> Word
forall a b. (a -> b) -> a -> b
$ [TxSkelSignatory] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([TxSkelSignatory] -> Int) -> [TxSkelSignatory] -> Int
forall a b. (a -> b) -> a -> b
$ TxSkel -> [TxSkelSignatory]
txSkelSignatories TxSkel
skel
let Cardano.Coin Fee
newFee = ShelleyBasedEra ConwayEra
-> PParams (ShelleyLedgerEra ConwayEra)
-> UTxO ConwayEra
-> Body
-> Word
-> Coin
forall era.
ShelleyBasedEra era
-> PParams (ShelleyLedgerEra era)
-> UTxO era
-> TxBody era
-> Word
-> Coin
Cardano.calculateMinTxFee ShelleyBasedEra ConwayEra
Cardano.ShelleyBasedEraConway PParams (ShelleyLedgerEra ConwayEra)
PParams
params UTxO ConwayEra
index Body
txBody Word
nbOfSignatories
(Fee, Body) -> Sem effs (Fee, Body)
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (Fee
newFee, Body
txBody)
computeBalancedTxSkel ::
(Members '[MockChainRead, Error MockChainError, Error Ledger.ToCardanoError] effs) =>
Peer ->
Utxos ->
TxSkel ->
Fee ->
Sem effs TxSkel
computeBalancedTxSkel :: forall (effs :: EffectRow).
Members
'[MockChainRead, Error MockChainError, Error ToCardanoError]
effs =>
User 'IsPubKey 'Allocation
-> [Utxo] -> TxSkel -> Fee -> Sem effs TxSkel
computeBalancedTxSkel User 'IsPubKey 'Allocation
balancingUser [Utxo]
balancingUtxos txSkel :: TxSkel
txSkel@TxSkel {[TxSkelSignatory]
[TxSkelProposal]
[TxSkelCertificate]
[TxSkelOut]
Set TxOutRef
Set TxSkelLabel
Map TxOutRef TxSkelRedeemer
SlotRange
TxSkelOpts
TxSkelWithdrawals
TxSkelMints
txSkelLabels :: TxSkel -> Set TxSkelLabel
txSkelOpts :: TxSkel -> TxSkelOpts
txSkelMints :: TxSkel -> TxSkelMints
txSkelSignatories :: TxSkel -> [TxSkelSignatory]
txSkelValidityRange :: TxSkel -> SlotRange
txSkelIns :: TxSkel -> Map TxOutRef TxSkelRedeemer
txSkelInsReference :: TxSkel -> Set TxOutRef
txSkelOuts :: TxSkel -> [TxSkelOut]
txSkelProposals :: TxSkel -> [TxSkelProposal]
txSkelWithdrawals :: TxSkel -> TxSkelWithdrawals
txSkelCertificates :: TxSkel -> [TxSkelCertificate]
txSkelLabels :: Set TxSkelLabel
txSkelOpts :: TxSkelOpts
txSkelMints :: TxSkelMints
txSkelSignatories :: [TxSkelSignatory]
txSkelValidityRange :: SlotRange
txSkelIns :: Map TxOutRef TxSkelRedeemer
txSkelInsReference :: Set TxOutRef
txSkelOuts :: [TxSkelOut]
txSkelProposals :: [TxSkelProposal]
txSkelWithdrawals :: TxSkelWithdrawals
txSkelCertificates :: [TxSkelCertificate]
..} (Fee -> Value
Script.lovelace -> Value
feeValue) = do
let (Value
burnedValue, Value
mintedValue) = Value -> (Value, Value)
Api.split (Value -> (Value, Value)) -> Value -> (Value, Value)
forall a b. (a -> b) -> a -> b
$ TxSkelMints -> Value
forall a. ToValue a => a -> Value
Script.toValue TxSkelMints
txSkelMints
outValue :: Value
outValue = TxSkel -> Value
txSkelValueInOutputs TxSkel
txSkel
withdrawnValue :: Value
withdrawnValue = TxSkel -> Value
txSkelWithdrawnValue TxSkel
txSkel
Value
inValue <- TxSkel -> Sem effs Value
forall (effs :: EffectRow).
Member MockChainRead effs =>
TxSkel -> Sem effs Value
txSkelInputValue TxSkel
txSkel
Value
certificatesDepositedValue <- Lovelace -> Value
forall a. ToValue a => a -> Value
Script.toValue (Lovelace -> Value) -> Sem effs Lovelace -> Sem effs Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TxSkel -> Sem effs Lovelace
forall (effs :: EffectRow).
Member MockChainRead effs =>
TxSkel -> Sem effs Lovelace
txSkelDepositedValueInCertificates TxSkel
txSkel
Value
proposalsDepositedValue <- Lovelace -> Value
forall a. ToValue a => a -> Value
Script.toValue (Lovelace -> Value) -> Sem effs Lovelace -> Sem effs Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TxSkel -> Sem effs Lovelace
forall (effs :: EffectRow).
Member MockChainRead effs =>
TxSkel -> Sem effs Lovelace
txSkelDepositedValueInProposals TxSkel
txSkel
let (Value
missingRight', Value
missingLeft') =
Value -> (Value, Value)
Api.split (Value -> (Value, Value)) -> Value -> (Value, Value)
forall a b. (a -> b) -> a -> b
$
[Value] -> Value
forall a. Monoid a => [a] -> a
mconcat
[ Value
outValue,
Value
burnedValue,
Value
feeValue,
Value
proposalsDepositedValue,
Value
certificatesDepositedValue,
Value -> Value
forall a. AdditiveGroup a => a -> a
PlutusTx.negate Value
inValue,
Value -> Value
forall a. AdditiveGroup a => a -> a
PlutusTx.negate Value
mintedValue,
Value -> Value
forall a. AdditiveGroup a => a -> a
PlutusTx.negate Value
withdrawnValue
]
let noInputs :: Bool
noInputs = Value
inValue Value -> Value -> Bool
forall a. Eq a => a -> a -> Bool
== Value
forall a. Monoid a => a
mempty Bool -> Bool -> Bool
&& Value
missingLeft' Value -> Value -> Bool
forall a. Eq a => a -> a -> Bool
== Value
forall a. Monoid a => a
mempty
missingLeft :: Value
missingLeft = if Bool
noInputs then Fee -> Value
Script.lovelace Fee
1 else Value
missingLeft'
missingRight :: Value
missingRight = if Bool
noInputs then Value
missingRight' Value -> Value -> Value
forall a. Semigroup a => a -> a -> a
<> Fee -> Value
Script.lovelace Fee
1 else Value
missingRight'
let surplusOutputOrUser :: Either TxSkelOut (User 'IsPubKey 'Allocation)
surplusOutputOrUser = case TxSkelOpts -> BalanceOutputPolicy
txSkelOptBalanceOutputPolicy TxSkelOpts
txSkelOpts of
BalanceOutputPolicy
AdjustExistingOutput
| Just TxSkelOut
txSkelOut <-
(TxSkelOut -> Bool) -> [TxSkelOut] -> Maybe TxSkelOut
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ((Credential -> Credential -> Bool
forall a. Eq a => a -> a -> Bool
== User 'IsPubKey 'Allocation -> Credential
forall a. ToCredential a => a -> Credential
Script.toCredential User 'IsPubKey 'Allocation
balancingUser) (Credential -> Bool)
-> (TxSkelOut -> Credential) -> TxSkelOut -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Optic' A_Getter NoIx TxSkelOut Credential
-> TxSkelOut -> Credential
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' A_Getter NoIx TxSkelOut Credential
txSkelOutCredentialG) [TxSkelOut]
txSkelOuts ->
TxSkelOut -> Either TxSkelOut (User 'IsPubKey 'Allocation)
forall a b. a -> Either a b
Left (Optic' A_Lens NoIx TxSkelOut Value
-> (Value -> Value) -> TxSkelOut -> TxSkelOut
forall k (is :: IxList) s t a b.
Is k A_Setter =>
Optic k is s t a b -> (a -> b) -> s -> t
over Optic' A_Lens NoIx TxSkelOut Value
txSkelOutValueL (Value -> Value -> Value
forall a. Semigroup a => a -> a -> a
<> Value
missingRight) TxSkelOut
txSkelOut)
BalanceOutputPolicy
_ | Value
missingRight Value -> Value -> Bool
forall a. Eq a => a -> a -> Bool
== Value
forall a. Monoid a => a
mempty -> User 'IsPubKey 'Allocation
-> Either TxSkelOut (User 'IsPubKey 'Allocation)
forall a b. b -> Either a b
Right User 'IsPubKey 'Allocation
balancingUser
BalanceOutputPolicy
_ -> TxSkelOut -> Either TxSkelOut (User 'IsPubKey 'Allocation)
forall a b. a -> Either a b
Left (User 'IsPubKey 'Allocation
balancingUser User 'IsPubKey 'Allocation -> Payable '[ 'IsValue] -> TxSkelOut
forall owner (els :: [PayableKind]).
IsTxSkelOutAllowedOwner owner =>
owner -> Payable els -> TxSkelOut
`receives` Value -> Payable '[ 'IsValue]
forall a1. ToValue a1 => a1 -> Payable '[ 'IsValue]
Value Value
missingRight)
let maxNbOfBalancingUtxos :: Fee
maxNbOfBalancingUtxos = Fee -> Maybe Fee -> Fee
forall a. a -> Maybe a -> a
fromMaybe (Int -> Fee
forall a. Integral a => a -> Fee
toInteger (Int -> Fee) -> Int -> Fee
forall a b. (a -> b) -> a -> b
$ [Utxo] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Utxo]
balancingUtxos) (TxSkelOpts -> Maybe Fee
txSkelOptMaxNbOfBalancingUtxos TxSkelOpts
txSkelOpts)
Maybe ([TxOutRef], Maybe TxSkelOut)
solution <- [Utxo]
-> Value
-> Fee
-> Either TxSkelOut (User 'IsPubKey 'Allocation)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut))
forall (effs :: EffectRow).
Members '[MockChainRead, Error ToCardanoError] effs =>
[Utxo]
-> Value
-> Fee
-> Either TxSkelOut (User 'IsPubKey 'Allocation)
-> Sem effs (Maybe ([TxOutRef], Maybe TxSkelOut))
reachValue [Utxo]
balancingUtxos Value
missingLeft Fee
maxNbOfBalancingUtxos Either TxSkelOut (User 'IsPubKey 'Allocation)
surplusOutputOrUser
([TxOutRef]
additionalInsTxOutRefs, [TxSkelOut]
newTxSkelOuts) <- case Maybe ([TxOutRef], Maybe TxSkelOut)
solution of
Maybe ([TxOutRef], Maybe TxSkelOut)
Nothing -> do
let totalValue :: Value
totalValue = [Value] -> Value
forall a. Monoid a => [a] -> a
mconcat ([Value] -> Value) -> [Value] -> Value
forall a b. (a -> b) -> a -> b
$ Optic' A_Lens NoIx TxSkelOut Value -> TxSkelOut -> Value
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' A_Lens NoIx TxSkelOut Value
txSkelOutValueL (TxSkelOut -> Value) -> (Utxo -> TxSkelOut) -> Utxo -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Utxo -> TxSkelOut
forall a b. (a, b) -> b
snd (Utxo -> Value) -> [Utxo] -> [Value]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Utxo]
balancingUtxos
difference :: Value
difference = (Value, Value) -> Value
forall a b. (a, b) -> b
snd ((Value, Value) -> Value) -> (Value, Value) -> Value
forall a b. (a -> b) -> a -> b
$ Value -> (Value, Value)
Api.split (Value -> (Value, Value)) -> Value -> (Value, Value)
forall a b. (a -> b) -> a -> b
$ Value
missingLeft Value -> Value -> Value
forall a. Semigroup a => a -> a -> a
<> Value -> Value
forall a. AdditiveGroup a => a -> a
PlutusTx.negate Value
totalValue
MockChainError -> Sem effs ([TxOutRef], [TxSkelOut])
forall e (r :: EffectRow) a. Member (Error e) r => e -> Sem r a
throw (MockChainError -> Sem effs ([TxOutRef], [TxSkelOut]))
-> MockChainError -> Sem effs ([TxOutRef], [TxSkelOut])
forall a b. (a -> b) -> a -> b
$
BalancingError -> MockChainError
MCEBalancingError (BalancingError -> MockChainError)
-> BalancingError -> MockChainError
forall a b. (a -> b) -> a -> b
$
if Value
difference Value -> Value -> Bool
forall a. Eq a => a -> a -> Bool
== Value
forall a. Monoid a => a
mempty
then User 'IsPubKey 'Allocation -> BalancingError
NotEnoughFundForExtraMinAda User 'IsPubKey 'Allocation
balancingUser
else User 'IsPubKey 'Allocation -> Value -> BalancingError
NotEnoughFund User 'IsPubKey 'Allocation
balancingUser Value
difference
Just ([TxOutRef]
newORefs, Maybe TxSkelOut
Nothing) -> ([TxOutRef], [TxSkelOut]) -> Sem effs ([TxOutRef], [TxSkelOut])
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return ([TxOutRef]
newORefs, [TxSkelOut]
txSkelOuts)
Just ([TxOutRef]
newORefs, Just TxSkelOut
newTxSkelOut)
| BalanceOutputPolicy
AdjustExistingOutput <- TxSkelOpts -> BalanceOutputPolicy
txSkelOptBalanceOutputPolicy TxSkelOpts
txSkelOpts,
([TxSkelOut]
before, TxSkelOut
_ : [TxSkelOut]
after) <- (TxSkelOut -> Bool) -> [TxSkelOut] -> ([TxSkelOut], [TxSkelOut])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break ((Credential -> Credential -> Bool
forall a. Eq a => a -> a -> Bool
== User 'IsPubKey 'Allocation -> Credential
forall a. ToCredential a => a -> Credential
Script.toCredential User 'IsPubKey 'Allocation
balancingUser) (Credential -> Bool)
-> (TxSkelOut -> Credential) -> TxSkelOut -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Optic' A_Getter NoIx TxSkelOut Credential
-> TxSkelOut -> Credential
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' A_Getter NoIx TxSkelOut Credential
txSkelOutCredentialG) [TxSkelOut]
txSkelOuts ->
([TxOutRef], [TxSkelOut]) -> Sem effs ([TxOutRef], [TxSkelOut])
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return ([TxOutRef]
newORefs, [TxSkelOut]
before [TxSkelOut] -> [TxSkelOut] -> [TxSkelOut]
forall a. [a] -> [a] -> [a]
++ (TxSkelOut
newTxSkelOut TxSkelOut -> [TxSkelOut] -> [TxSkelOut]
forall a. a -> [a] -> [a]
: [TxSkelOut]
after))
Just ([TxOutRef]
newORefs, Just TxSkelOut
newTxSkelOut) -> ([TxOutRef], [TxSkelOut]) -> Sem effs ([TxOutRef], [TxSkelOut])
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return ([TxOutRef]
newORefs, [TxSkelOut]
txSkelOuts [TxSkelOut] -> [TxSkelOut] -> [TxSkelOut]
forall a. [a] -> [a] -> [a]
++ [TxSkelOut
newTxSkelOut])
let newTxSkelIns :: Map TxOutRef TxSkelRedeemer
newTxSkelIns = Map TxOutRef TxSkelRedeemer
txSkelIns Map TxOutRef TxSkelRedeemer
-> Map TxOutRef TxSkelRedeemer -> Map TxOutRef TxSkelRedeemer
forall a. Semigroup a => a -> a -> a
<> [(TxOutRef, TxSkelRedeemer)] -> Map TxOutRef TxSkelRedeemer
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ((,TxSkelRedeemer
emptyTxSkelRedeemer) (TxOutRef -> (TxOutRef, TxSkelRedeemer))
-> [TxOutRef] -> [(TxOutRef, TxSkelRedeemer)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [TxOutRef]
additionalInsTxOutRefs)
TxSkel -> Sem effs TxSkel
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (TxSkel -> Sem effs TxSkel) -> TxSkel -> Sem effs TxSkel
forall a b. (a -> b) -> a -> b
$ (TxSkel
txSkel TxSkel -> (TxSkel -> TxSkel) -> TxSkel
forall a b. a -> (a -> b) -> b
& Lens' TxSkel [TxSkelOut]
txSkelOutsL Lens' TxSkel [TxSkelOut] -> [TxSkelOut] -> TxSkel -> TxSkel
forall k (is :: IxList) s t a b.
Is k A_Setter =>
Optic k is s t a b -> b -> s -> t
.~ [TxSkelOut]
newTxSkelOuts) TxSkel -> (TxSkel -> TxSkel) -> TxSkel
forall a b. a -> (a -> b) -> b
& Lens' TxSkel (Map TxOutRef TxSkelRedeemer)
txSkelInsL Lens' TxSkel (Map TxOutRef TxSkelRedeemer)
-> Map TxOutRef TxSkelRedeemer -> TxSkel -> TxSkel
forall k (is :: IxList) s t a b.
Is k A_Setter =>
Optic k is s t a b -> b -> s -> t
.~ Map TxOutRef TxSkelRedeemer
newTxSkelIns
getMinAndMaxFee ::
(Members '[MockChainRead] effs) =>
Integer ->
Sem effs (Fee, Fee)
getMinAndMaxFee :: forall (effs :: EffectRow).
Members '[MockChainRead] effs =>
Fee -> Sem effs (Fee, Fee)
getMinAndMaxFee Fee
nbOfScripts = do
PParams
params <- Params -> PParams
Emulator.pEmulatorPParams (Params -> PParams) -> Sem effs Params -> Sem effs PParams
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Sem effs Params
forall (effs :: EffectRow).
Member MockChainRead effs =>
Sem effs Params
getParams
let maxTxSize :: Fee
maxTxSize = Word32 -> Fee
forall a. Integral a => a -> Fee
toInteger (Word32 -> Fee) -> Word32 -> Fee
forall a b. (a -> b) -> a -> b
$ Getting Word32 PParams Word32 -> PParams -> Word32
forall a s. Getting a s a -> s -> a
MicroLens.view Getting Word32 PParams Word32
forall era. EraPParams era => Lens' (PParams era) Word32
Lens' PParams Word32
Conway.ppMaxTxSizeL PParams
params
Cardano.Coin Fee
txFeePerByte = Getting Coin PParams Coin -> PParams -> Coin
forall a s. Getting a s a -> s -> a
MicroLens.view Getting Coin PParams Coin
forall era. EraPParams era => Lens' (PParams era) Coin
Lens' PParams Coin
Conway.ppMinFeeAL PParams
params
Cardano.Coin Fee
txFeeFixed = Getting Coin PParams Coin -> PParams -> Coin
forall a s. Getting a s a -> s -> a
MicroLens.view Getting Coin PParams Coin
forall era. EraPParams era => Lens' (PParams era) Coin
Lens' PParams Coin
Conway.ppMinFeeBL PParams
params
Cardano.Prices (NonNegativeInterval -> Rational
forall r. BoundedRational r => r -> Rational
Cardano.unboundRational -> Rational
priceESteps) (NonNegativeInterval -> Rational
forall r. BoundedRational r => r -> Rational
Cardano.unboundRational -> Rational
priceEMem) = Getting Prices PParams Prices -> PParams -> Prices
forall a s. Getting a s a -> s -> a
MicroLens.view Getting Prices PParams Prices
forall era. AlonzoEraPParams era => Lens' (PParams era) Prices
Lens' PParams Prices
Conway.ppPricesL PParams
params
Cardano.ExUnits (Natural -> Fee
forall a. Integral a => a -> Fee
toInteger -> Fee
eSteps) (Natural -> Fee
forall a. Integral a => a -> Fee
toInteger -> Fee
eMem) = Getting ExUnits PParams ExUnits -> PParams -> ExUnits
forall a s. Getting a s a -> s -> a
MicroLens.view Getting ExUnits PParams ExUnits
forall era. AlonzoEraPParams era => Lens' (PParams era) ExUnits
Lens' PParams ExUnits
Conway.ppMaxTxExUnitsL PParams
params
(NonNegativeInterval -> Rational
forall r. BoundedRational r => r -> Rational
Cardano.unboundRational -> Rational
refScriptFeePerByte) = Getting NonNegativeInterval PParams NonNegativeInterval
-> PParams -> NonNegativeInterval
forall a s. Getting a s a -> s -> a
MicroLens.view Getting NonNegativeInterval PParams NonNegativeInterval
forall era.
ConwayEraPParams era =>
Lens' (PParams era) NonNegativeInterval
Lens' PParams NonNegativeInterval
Conway.ppMinFeeRefScriptCostPerByteL PParams
params
let txSizeMaxFee :: Fee
txSizeMaxFee = Fee
maxTxSize Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
* Fee
txFeePerByte
let eStepsMaxFee :: Fee
eStepsMaxFee = (Fee
eSteps Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
* Rational -> Fee
forall a. Ratio a -> a
Rat.numerator Rational
priceESteps) Fee -> Fee -> Fee
forall a. Integral a => a -> a -> a
`div` Rational -> Fee
forall a. Ratio a -> a
Rat.denominator Rational
priceESteps
let eMemMaxFee :: Fee
eMemMaxFee = (Fee
eMem Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
* Rational -> Fee
forall a. Ratio a -> a
Rat.numerator Rational
priceEMem) Fee -> Fee -> Fee
forall a. Integral a => a -> a -> a
`div` Rational -> Fee
forall a. Ratio a -> a
Rat.denominator Rational
priceEMem
let refScriptsMaxFee :: Fee
refScriptsMaxFee = (Fee
maxTxSize Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
* Rational -> Fee
forall a. Ratio a -> a
Rat.numerator Rational
refScriptFeePerByte) Fee -> Fee -> Fee
forall a. Integral a => a -> a -> a
`div` Rational -> Fee
forall a. Ratio a -> a
Rat.denominator Rational
refScriptFeePerByte
(Fee, Fee) -> Sem effs (Fee, Fee)
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return
(
Fee
txFeeFixed,
Fee
txFeeFixed Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
+ Fee
txSizeMaxFee Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
+ Fee
nbOfScripts Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
* (Fee
eStepsMaxFee Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
+ Fee
eMemMaxFee) Fee -> Fee -> Fee
forall a. Num a => a -> a -> a
+ Fee
refScriptsMaxFee
)