From 7ebf75fd823fda8838e1968e340aa961d0ea513a Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Mon, 6 May 2024 20:00:34 +0400 Subject: [PATCH 01/52] Simplify TxConstraints type --- src/Contract/TxConstraints.purs | 3 +- src/Internal/ProcessConstraints.purs | 5 +-- src/Internal/Test/KeyDir.purs | 3 +- src/Internal/Types/TxConstraints.purs | 65 ++++++++------------------- 4 files changed, 22 insertions(+), 54 deletions(-) diff --git a/src/Contract/TxConstraints.purs b/src/Contract/TxConstraints.purs index cd87d375ea..dc7c9288a0 100644 --- a/src/Contract/TxConstraints.purs +++ b/src/Contract/TxConstraints.purs @@ -7,7 +7,7 @@ import Ctl.Internal.Types.TxConstraints , InputConstraint(InputConstraint) , InputWithScriptRef(RefInput, SpendInput) , OutputConstraint(OutputConstraint) - , TxConstraints(TxConstraints) + , TxConstraints , mustBeSignedBy , mustDelegateStakeNativeScript , mustDelegateStakePlutusScript @@ -55,5 +55,4 @@ import Ctl.Internal.Types.TxConstraints , mustWithdrawStakeNativeScript , mustWithdrawStakePlutusScript , mustWithdrawStakePubKey - , singleton ) as TxConstraints diff --git a/src/Internal/ProcessConstraints.purs b/src/Internal/ProcessConstraints.purs index 226db39013..dab93d21c7 100644 --- a/src/Internal/ProcessConstraints.purs +++ b/src/Internal/ProcessConstraints.purs @@ -166,7 +166,7 @@ import Ctl.Internal.Types.TxConstraints , MustValidateIn , MustIncludeDatum ) - , TxConstraints(TxConstraints) + , TxConstraints , utxoWithScriptRef ) import Ctl.Internal.Types.Val as Val @@ -207,8 +207,7 @@ import Prelude (join) as Bind processLookupsAndConstraints :: TxConstraints -> ConstraintsM (Either MkUnbalancedTxError Unit) -processLookupsAndConstraints - (TxConstraints { constraints }) = runExceptT do +processLookupsAndConstraints constraints = runExceptT do -- Hash all the MintingPolicys and Scripts beforehand. These maps are lost -- after we `runReaderT`, unlike Plutus that has a `Map` instead of `Array`. lookups <- use _lookups <#> unwrap diff --git a/src/Internal/Test/KeyDir.purs b/src/Internal/Test/KeyDir.purs index 12495fa548..a623be215a 100644 --- a/src/Internal/Test/KeyDir.purs +++ b/src/Internal/Test/KeyDir.purs @@ -68,10 +68,9 @@ import Ctl.Internal.Types.TxConstraints , mustBeSignedBy , mustPayToPubKeyAddress , mustSpendPubKeyOutput - , singleton ) import Ctl.Internal.Wallet.Key (KeyWallet) -import Data.Array (catMaybes) +import Data.Array (catMaybes, singleton) import Data.Array as Array import Data.Either (Either(Right, Left), hush) import Data.Foldable (fold, sum) diff --git a/src/Internal/Types/TxConstraints.purs b/src/Internal/Types/TxConstraints.purs index de6d268690..141a42b6f8 100644 --- a/src/Internal/Types/TxConstraints.purs +++ b/src/Internal/Types/TxConstraints.purs @@ -35,7 +35,7 @@ module Ctl.Internal.Types.TxConstraints , MustWithdrawStakeNativeScript , MustWithdrawStakePubKey ) - , TxConstraints(TxConstraints) + , TxConstraints , mustBeSignedBy , mustDelegateStakeNativeScript , mustDelegateStakePlutusScript @@ -83,7 +83,6 @@ module Ctl.Internal.Types.TxConstraints , mustWithdrawStakeNativeScript , mustWithdrawStakePlutusScript , mustWithdrawStakePubKey - , singleton , utxoWithScriptRef ) where @@ -119,6 +118,8 @@ import Data.Foldable (class Foldable) import Data.Generic.Rep (class Generic) import Data.Map (Map) import Data.Map (singleton) as Map +import Data.Array (singleton) as X +import Data.Array (singleton) import Data.Maybe (Maybe(Just, Nothing)) import Data.Monoid (guard) import Data.Newtype (class Newtype, over, unwrap) @@ -247,28 +248,12 @@ instance Show OutputConstraint where show = genericShow -- | Restrictions placed on the allocation of funds to outputs of transactions. -newtype TxConstraints = TxConstraints - { constraints :: Array TxConstraint - } - -derive instance Generic TxConstraints _ -derive instance Newtype TxConstraints _ -derive newtype instance Eq TxConstraints --- Array concatenation allowing duplicates like Plutus -derive newtype instance Semigroup TxConstraints -derive newtype instance Monoid TxConstraints - -instance Show TxConstraints where - show = genericShow +type TxConstraints = Array TxConstraint -------------------------------------------------------------------------------- -- Helpers -------------------------------------------------------------------------------- -singleton - :: TxConstraint -> TxConstraints -singleton a = over TxConstraints _ { constraints = Array.singleton a } mempty - -- | `mustValidateIn r` requires the transaction's time range to be contained -- | in `r`. mustValidateIn @@ -421,8 +406,7 @@ mustPayToScriptWithScriptRef vh dt dtp scriptRef vl = -- | Note that the provided reference script does *not* necessarily need to -- | control the spending of the output, i.e. both scripts can be different. mustPayToScriptAddressWithScriptRef - :: forall (i :: Type) (o :: Type) - . ScriptHash + :: ScriptHash -> Credential -> PlutusData -> DatumPresence @@ -434,16 +418,14 @@ mustPayToScriptAddressWithScriptRef vh credential dt dtp scriptRef vl = <> guard (dtp == DatumWitness) (singleton $ MustIncludeDatum dt) mustPayToNativeScript - :: forall (i :: Type) (o :: Type) - . ScriptHash + :: ScriptHash -> Value -> TxConstraints mustPayToNativeScript nsHash vl = singleton (MustPayToNativeScript nsHash Nothing vl) mustPayToNativeScriptAddress - :: forall (i :: Type) (o :: Type) - . ScriptHash + :: ScriptHash -> Credential -> Value -> TxConstraints @@ -458,8 +440,7 @@ mustMintValue = mustMintValueWithRedeemer RedeemerDatum.unit -- | Mint the given `Value` by accessing non-Ada assets. -- | The amount to mint must not be zero. mustMintValueWithRedeemer - :: forall (i :: Type) (o :: Type) - . RedeemerDatum + :: RedeemerDatum -> Mint -> TxConstraints mustMintValueWithRedeemer redeemer = @@ -481,8 +462,7 @@ mustMintCurrency mph = mustMintCurrencyWithRedeemer mph RedeemerDatum.unit mustMintCurrencyUsingNativeScript - :: forall (i :: Type) (o :: Type) - . NativeScript + :: NativeScript -> AssetName -> Int.Int -> TxConstraints @@ -578,16 +558,14 @@ mustRegisterStakeScript mustRegisterStakeScript = singleton <<< MustRegisterStakeScript mustDeregisterStakePlutusScript - :: forall (i :: Type) (o :: Type) - . PlutusScript + :: PlutusScript -> RedeemerDatum -> TxConstraints mustDeregisterStakePlutusScript sv = singleton <<< MustDeregisterStakePlutusScript sv mustDeregisterStakeNativeScript - :: forall (i :: Type) (o :: Type) - . NativeScript + :: NativeScript -> TxConstraints mustDeregisterStakeNativeScript = singleton <<< MustDeregisterStakeNativeScript @@ -596,23 +574,20 @@ mustRegisterPool mustRegisterPool = singleton <<< MustRegisterPool mustRetirePool - :: forall (i :: Type) (o :: Type) - . PoolPubKeyHash + :: PoolPubKeyHash -> Epoch -> TxConstraints mustRetirePool poolPubKeyHash = singleton <<< MustRetirePool poolPubKeyHash mustDelegateStakePubKey - :: forall (i :: Type) (o :: Type) - . StakePubKeyHash + :: StakePubKeyHash -> PoolPubKeyHash -> TxConstraints mustDelegateStakePubKey spkh ppkh = singleton $ MustDelegateStakePubKey spkh ppkh mustDelegateStakePlutusScript - :: forall (i :: Type) (o :: Type) - . PlutusScript + :: PlutusScript -> RedeemerDatum -> PoolPubKeyHash -> TxConstraints @@ -620,8 +595,7 @@ mustDelegateStakePlutusScript sv redeemer ppkh = singleton $ MustDelegateStakePlutusScript sv redeemer ppkh mustDelegateStakeNativeScript - :: forall (i :: Type) (o :: Type) - . NativeScript + :: NativeScript -> PoolPubKeyHash -> TxConstraints mustDelegateStakeNativeScript sv ppkh = @@ -632,16 +606,14 @@ mustWithdrawStakePubKey mustWithdrawStakePubKey spkh = singleton $ MustWithdrawStakePubKey spkh mustWithdrawStakePlutusScript - :: forall (i :: Type) (o :: Type) - . PlutusScript + :: PlutusScript -> RedeemerDatum -> TxConstraints mustWithdrawStakePlutusScript validator redeemer = singleton $ MustWithdrawStakePlutusScript validator redeemer mustWithdrawStakeNativeScript - :: forall (i :: Type) (o :: Type) - . NativeScript + :: NativeScript -> TxConstraints mustWithdrawStakeNativeScript = singleton <<< MustWithdrawStakeNativeScript @@ -651,13 +623,12 @@ mustWithdrawStakeNativeScript = -- | `mustSatisfyaAnyOf` is just a way to define a chain of try-catch expressions -- | in a declarative manner. It does not do any analysis of the constraints' semantics. mustSatisfyAnyOf - :: forall (f :: Type -> Type) (i :: Type) (o :: Type) + :: forall (f :: Type -> Type) . Foldable f => f (TxConstraints) -> TxConstraints mustSatisfyAnyOf = Array.fromFoldable - >>> map (_.constraints <<< unwrap) >>> MustSatisfyAnyOf >>> singleton From 1353a315131793299499e04808558b8b73bbf0cf Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Wed, 8 May 2024 21:42:26 +0400 Subject: [PATCH 02/52] WIP: new constraints interface --- src/Contract/ClientError.purs | 1 + src/Contract/Constraints.purs | 143 +++++++++ src/Contract/Transaction.purs | 1 + src/Internal/BalanceTx/RedeemerIndex.purs | 2 + src/Internal/Lens.purs | 5 + src/Internal/Types/TxConstraints.purs | 4 +- src/Internal/UseConstraints.purs | 337 ++++++++++++++++++++++ 7 files changed, 491 insertions(+), 2 deletions(-) create mode 100644 src/Contract/Constraints.purs create mode 100644 src/Internal/UseConstraints.purs diff --git a/src/Contract/ClientError.purs b/src/Contract/ClientError.purs index cbac2a82e2..f6633e2e11 100644 --- a/src/Contract/ClientError.purs +++ b/src/Contract/ClientError.purs @@ -13,4 +13,5 @@ import Ctl.Internal.Service.Error ( ServiceBlockfrostError , ServiceOtherError ) + , pprintClientError ) as X diff --git a/src/Contract/Constraints.purs b/src/Contract/Constraints.purs new file mode 100644 index 0000000000..d011cc1a34 --- /dev/null +++ b/src/Contract/Constraints.purs @@ -0,0 +1,143 @@ +module Contract.Constraints where + +import Prelude + +import Cardano.Types.Epoch (Epoch(..)) +import Cardano.Types.NativeScript (NativeScript) +import Cardano.Types.PaymentPubKeyHash (PaymentPubKeyHash(..)) +import Cardano.Types.PlutusData (PlutusData) +import Cardano.Types.PlutusScript (PlutusScript) +import Cardano.Types.PoolParams (PoolParams(..)) +import Cardano.Types.PoolPubKeyHash (PoolPubKeyHash) +import Cardano.Types.ScriptHash (ScriptHash(..)) +import Cardano.Types.StakePubKeyHash (StakePubKeyHash) +import Cardano.Types.TransactionInput (TransactionInput(..)) +import Cardano.Types.TransactionUnspentOutput (TransactionUnspentOutput(..)) +import Ctl.Internal.Types.RedeemerDatum (RedeemerDatum) +import Ctl.Internal.Types.TxConstraints (TxConstraint(..), TxConstraints(..)) +import Data.Array (singleton) +import Data.Either (Either(..)) +import Data.Maybe (Maybe(..)) + +-- Spending + +-- | Datums in UTxOs can be stored in two forms: inline datums or datum hashes. +-- | When there's a hash, we need to provide a datum corresponding to this hash, +-- | which can be done by either providing the value literally, or using a +-- | reference input where it is stored inline. +data DatumWitness + = DatumValue PlutusData + | DatumReference TransactionInput RefInputAction + +-- | Gives the user options for specifying everything needed to spend an UTxO +-- | located at an address with a ScriptHash payment credential. +-- | +-- | - `ScriptValue` contains a script for the witness set. +-- | +-- | - `ScriptReference` contains a CIP-31 reference input where the inline script should be available at, and a flag to either spend the referenced input or just reference it. +data ScriptWitness a + = ScriptValue a + | ScriptReference TransactionInput RefInputAction + +-- | Inputs can be referenced or spent in a transaction (See CIP-31). +-- | Inline datums (CIP-32) and reference scripts (CIP-33) contained within +-- | transaction outputs become visible to the script context of the +-- | transaction, regardless of whether the output is spent or just +-- | referenced. This data type lets the developer to specify, which +-- | action to perform with a referenced input. +data RefInputAction + = ReferenceInput + | SpendInput + +data SpendWitness + = PubKeyOutput + | NativeScriptOutput (ScriptWitness NativeScript) + | PlutusScriptOutput (ScriptWitness PlutusScript) RedeemerDatum + (Maybe DatumWitness) + +data StakeWitness + = PubKeyHashStakeWitness StakePubKeyHash + | PlutusScriptStakeWitness (ScriptWitness PlutusScript) + | NativeScriptStakeWitness (ScriptWitness NativeScript) + +data StakeRegistration + = StakePubKeyRegistration StakePubKeyHash + | StakeScriptRegistration ScriptHash + +data StakeAction + = Delegate PoolPubKeyHash + | Withdraw + | Deregister + +data Constraint + = SpendOutput TransactionUnspentOutput SpendWitness + | RegisterStake StakeRegistration + | Stake StakeAction StakeWitness + | RequireSignature PaymentPubKeyHash + | RegisterPool PoolParams + | RetirePool PoolPubKeyHash Epoch + +type Constraints = Array Constraint + +requireSignature :: PaymentPubKeyHash -> TxConstraints +requireSignature = singleton <<< MustBeSignedBy + +-- Stake Pool operations + +registerPool :: PoolParams -> TxConstraints +registerPool = singleton <<< MustRegisterPool + +retirePool + :: PoolPubKeyHash + -> Epoch + -> TxConstraints +retirePool poolPubKeyHash = singleton <<< MustRetirePool poolPubKeyHash + +-- Stake operations + +-- registerStake :: StakeRegistration -> TxConstraints +-- registerStake = singleton <<< case _ of +-- StakePubKeyRegistration spkh -> MustRegisterStakePubKey spkh +-- StakeScriptRegistration ssh -> MustRegisterStakeScript ssh + +-- delegateStake :: PoolPubKeyHash -> StakeDelegation -> TxConstraints +-- delegateStake ppkh = singleton <<< case _ of +-- DelegatePubKeyHashStake spkh -> +-- MustDelegateStakePubKey spkh ppkh +-- DelegateNativeScriptStake ns -> +-- MustDelegateStakeNativeScript ns ppkh +-- DelegatePlutusScriptStake ps redeemer -> +-- MustDelegateStakePlutusScript ps redeemer ppkh + +-- withdrawStake :: StakeWithdrawal -> TxConstraints +-- withdrawStake = singleton <<< case _ of +-- WithdrawNativeScriptStake ns -> +-- MustWithdrawStakeNativeScript ns +-- WithdrawPlutusScriptStake ps redeemer -> +-- MustWithdrawStakePlutusScript ps redeemer +-- WithdrawPubKeyStake spkh -> +-- MustWithdrawStakePubKey spkh + +-- data StakeDelegation +-- = DelegatePubKeyHashStake StakePubKeyHash +-- | DelegateNativeScriptStake NativeScriptWitness +-- | DelegatePlutusScriptStake PlutusScriptWitness + +-- data StakeWithdrawal +-- = WithdrawNativeScriptStake NativeScriptWitness +-- | WithdrawPlutusScriptStake PlutusScriptWitness +-- | WithdrawPubKeyStake StakePubKeyHash + +-- data DeregisterStake +-- = DeregisterNativeScriptStake NativeScriptWitness +-- | DeregisterPlutusScriptStake PlutusScriptWitness +-- | DeregisterPubKeyStake StakePubKeyHash + +-- deregisterStake :: DeregisterStake -> TxConstraints +-- deregisterStake = singleton <<< case _ of +-- DeregisterNativeScriptStake ns -> +-- MustDeregisterStakeNativeScript ns +-- DeregisterPlutusScriptStake ps redeemer -> +-- MustDeregisterStakePlutusScript ps redeemer +-- DeregisterPubKeyStake spkh -> +-- MustDeregisterStakePubKey spkh diff --git a/src/Contract/Transaction.purs b/src/Contract/Transaction.purs index 1c038632f9..b5f7227e7d 100644 --- a/src/Contract/Transaction.purs +++ b/src/Contract/Transaction.purs @@ -120,6 +120,7 @@ import Ctl.Internal.Lens , _inputs , _isValid , _mint + , _nativeScripts , _networkId , _output , _outputs diff --git a/src/Internal/BalanceTx/RedeemerIndex.purs b/src/Internal/BalanceTx/RedeemerIndex.purs index 1b4182808b..7bcf257571 100644 --- a/src/Internal/BalanceTx/RedeemerIndex.purs +++ b/src/Internal/BalanceTx/RedeemerIndex.purs @@ -64,6 +64,7 @@ newtype UnindexedRedeemer = UnindexedRedeemer derive instance Generic UnindexedRedeemer _ derive instance Newtype UnindexedRedeemer _ derive newtype instance Eq UnindexedRedeemer +derive newtype instance Ord UnindexedRedeemer derive newtype instance EncodeAeson UnindexedRedeemer instance Show UnindexedRedeemer where @@ -123,6 +124,7 @@ data RedeemerPurpose derive instance Generic RedeemerPurpose _ derive instance Eq RedeemerPurpose +derive instance Ord RedeemerPurpose instance EncodeAeson RedeemerPurpose where encodeAeson = case _ of diff --git a/src/Internal/Lens.purs b/src/Internal/Lens.purs index 94a9bf7866..bbfe9a8e73 100644 --- a/src/Internal/Lens.purs +++ b/src/Internal/Lens.purs @@ -13,6 +13,7 @@ module Ctl.Internal.Lens , _inputs , _isValid , _mint + , _nativeScripts , _networkId , _output , _outputs @@ -42,6 +43,7 @@ import Cardano.Types , Coin , Ed25519KeyHash , Mint + , NativeScript , NetworkId , OutputDatum , PlutusData @@ -169,5 +171,8 @@ _plutusData = _Newtype <<< prop (Proxy :: Proxy "plutusData") _plutusScripts :: Lens' TransactionWitnessSet (Array PlutusScript) _plutusScripts = _Newtype <<< prop (Proxy :: Proxy "plutusScripts") +_nativeScripts :: Lens' TransactionWitnessSet (Array NativeScript) +_nativeScripts = _Newtype <<< prop (Proxy :: Proxy "nativeScripts") + _vkeys :: Lens' TransactionWitnessSet (Array Vkeywitness) _vkeys = _Newtype <<< prop (Proxy :: Proxy "vkeys") diff --git a/src/Internal/Types/TxConstraints.purs b/src/Internal/Types/TxConstraints.purs index 141a42b6f8..a6185715be 100644 --- a/src/Internal/Types/TxConstraints.purs +++ b/src/Internal/Types/TxConstraints.purs @@ -113,13 +113,13 @@ import Cardano.Types.Mint as Mint import Ctl.Internal.Types.Interval (POSIXTimeRange) import Ctl.Internal.Types.RedeemerDatum (RedeemerDatum) import Ctl.Internal.Types.RedeemerDatum as RedeemerDatum +import Data.Array (singleton) +import Data.Array (singleton) as X import Data.Array as Array import Data.Foldable (class Foldable) import Data.Generic.Rep (class Generic) import Data.Map (Map) import Data.Map (singleton) as Map -import Data.Array (singleton) as X -import Data.Array (singleton) import Data.Maybe (Maybe(Just, Nothing)) import Data.Monoid (guard) import Data.Newtype (class Newtype, over, unwrap) diff --git a/src/Internal/UseConstraints.purs b/src/Internal/UseConstraints.purs new file mode 100644 index 0000000000..99011cda27 --- /dev/null +++ b/src/Internal/UseConstraints.purs @@ -0,0 +1,337 @@ +module Ctl.Internal.UseConstraints where + +import Data.Lens +import Prelude + +import Cardano.AsCbor (encodeCbor) +import Cardano.Types + ( Certificate + ( StakeDelegation + , PoolRetirement + , PoolRegistration + , StakeDeregistration + , StakeRegistration + ) + , DataHash + , NetworkId + , PlutusData + , PlutusScript + , ScriptHash + , ScriptRef(NativeScriptRef, PlutusScriptRef) + , StakeCredential(StakeCredential) + , Transaction + , TransactionInput + , TransactionOutput(TransactionOutput) + , TransactionUnspentOutput(TransactionUnspentOutput) + , TransactionWitnessSet(TransactionWitnessSet) + , Value(Value) + ) +import Cardano.Types.Address + ( Address(BaseAddress, EnterpriseAddress) + , getPaymentCredential + ) +import Cardano.Types.Coin as Coin +import Cardano.Types.CostModel (CostModel(..)) +import Cardano.Types.Credential + ( Credential(PubKeyHashCredential, ScriptHashCredential) + , asScriptHash + ) +import Cardano.Types.Credential as Credential +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.DataHash as Datum +import Cardano.Types.DataHash as PlutusData +import Cardano.Types.Int as Int +import Cardano.Types.Language (Language) +import Cardano.Types.Mint as Mint +import Cardano.Types.MultiAsset as MultiAsset +import Cardano.Types.NativeScript as NativeScript +import Cardano.Types.OutputDatum (OutputDatum(OutputDatumHash, OutputDatum)) +import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.Transaction as Transaction +import Cardano.Types.TransactionBody (TransactionBody(..)) +import Contract.Constraints + ( Constraint(..) + , Constraints + , DatumWitness(..) + , RefInputAction(..) + , ScriptWitness(..) + , SpendWitness(..) + ) +import Contract.Log (logWarn') +import Control.Monad (unless) +import Control.Monad.Error.Class (catchError, throwError) +import Control.Monad.Except (Except) +import Control.Monad.Except.Trans (ExceptT(ExceptT), except, runExceptT) +import Control.Monad.Reader.Class (asks) +import Control.Monad.State (StateT(..)) +import Control.Monad.State.Trans (get, gets, put, runStateT) +import Control.Monad.Trans.Class (lift) +import Ctl.Internal.BalanceTx.RedeemerIndex + ( RedeemerPurpose(ForReward, ForCert, ForMint, ForSpend) + , UnindexedRedeemer(UnindexedRedeemer) + , unindexedRedeemerToRedeemer + ) +import Ctl.Internal.Contract (getProtocolParameters) +import Ctl.Internal.Contract.Monad (Contract, getQueryHandle, wrapQueryM) +import Ctl.Internal.Helpers (liftEither, liftM, unsafeFromJust) +import Ctl.Internal.Lens + ( _address + , _body + , _certs + , _datum + , _inputs + , _isValid + , _mint + , _nativeScripts + , _networkId + , _output + , _outputs + , _plutusData + , _plutusScripts + , _referenceInputs + , _requiredSigners + , _scriptDataHash + , _withdrawals + , _witnessSet + ) +import Ctl.Internal.ProcessConstraints.Error + ( MkUnbalancedTxError + ( CannotSatisfyAny + , CannotWithdrawRewardsNativeScript + , CannotWithdrawRewardsPlutusScript + , CannotWithdrawRewardsPubKey + , DatumWrongHash + , CannotMintZero + , ExpectedPlutusScriptGotNativeScript + , CannotFindDatum + , CannotQueryDatum + , CannotGetValidatorHashFromAddress + , TxOutRefWrongType + , CannotConvertPOSIXTimeRange + , NumericOverflow + , WrongRefScriptHash + , ValidatorHashNotFound + , MintingPolicyNotFound + , DatumNotFound + , TxOutRefNotFound + , CannotSolveTimeConstraints + , OwnPubKeyAndStakeKeyMissing + ) + ) +import Ctl.Internal.ProcessConstraints.UnbalancedTx (UnbalancedTx) +import Ctl.Internal.QueryM.Pools + ( getPubKeyHashDelegationsAndRewards + , getValidatorHashDelegationsAndRewards + ) +import Ctl.Internal.Service.Error (ClientError, pprintClientError) +import Ctl.Internal.Transaction + ( attachDatum + , attachNativeScript + , attachPlutusScript + , setScriptDataHash + ) +import Ctl.Internal.Types.Interval + ( POSIXTimeRange + , always + , intersection + , isEmpty + , posixTimeRangeToTransactionValidity + ) +import Ctl.Internal.Types.ScriptLookups (ScriptLookups) +import Ctl.Internal.Types.Val as Val +import Data.Array (cons, nub, partition, toUnfoldable, zip) +import Data.Array (mapMaybe, singleton, (:)) as Array +import Data.Bifunctor (lmap) +import Data.ByteArray (byteArrayToHex) +import Data.Either (Either(Left, Right), either, hush, isRight, note) +import Data.Foldable (foldM) +import Data.Lens (Lens', (%=), (%~), (.=), (.~), (<>=)) +import Data.Lens.Getter (to, use) +import Data.Lens.Iso.Newtype (_Newtype) +import Data.Lens.Record (prop) +import Data.List (List(Nil, Cons)) +import Data.Map (Map, empty, fromFoldable, lookup, union) +import Data.Map as Map +import Data.Maybe (Maybe(Nothing, Just), fromMaybe, isJust, maybe) +import Data.Newtype (over, unwrap, wrap) +import Data.Set as Set +import Data.Traversable (for, traverse_) +import Data.Tuple.Nested (type (/\), (/\)) +import Effect (Effect) +import Effect.Aff.Class (liftAff) +import Effect.Class (liftEffect) +import Effect.Exception (throw) +import Partial.Unsafe (unsafePartial) +import Prelude (join) as Bind +import Type.Proxy (Proxy(..)) + +type Context = + { transaction :: Transaction + , costModels :: Map Language CostModel + , redeemers :: Array UnindexedRedeemer + , datums :: Array PlutusData + } + +_transaction + :: Lens' Context Transaction +_transaction = prop (Proxy :: Proxy "transaction") + +_redeemers + :: Lens' Context (Array UnindexedRedeemer) +_redeemers = prop (Proxy :: Proxy "redeemers") + +_datums + :: Lens' Context (Array PlutusData) +_datums = prop (Proxy :: Proxy "datums") + +data ExpectedOutputType = ScriptHashOutput | PubKeyHashOutput + +data TxBuildError + = WrongSpendWitnessType TransactionUnspentOutput + | QueryError ClientError + | DatumHashLookupError DataHash + | IncorrectDatumHash TransactionUnspentOutput PlutusData DataHash + | WrongOutputType ExpectedOutputType TransactionUnspentOutput + +explainTxBuildError :: TxBuildError -> String +explainTxBuildError (WrongSpendWitnessType utxo) = + "SpendWitness is incompatible with the given output. The output does not contain a datum: " + <> show utxo +explainTxBuildError (QueryError clientError) = + "Query error: " <> pprintClientError clientError +explainTxBuildError (DatumHashLookupError dataHash) = + "The UTxO you are trying to spend contains a datum hash. You didn't provide a `DatumWitness` value corresponding to this hash, so CTL tried to look it up, using a database of datums observed on-chain. This lookup failed. Datum hash: " + <> show dataHash +explainTxBuildError (IncorrectDatumHash utxo datum datumHash) = + "You provided a `DatumWitness` with a datum that does not match the datum hash present in a transaction output.\n Datum: " + <> show datum + <> " (CBOR: " + <> byteArrayToHex (unwrap $ encodeCbor datum) + <> ")\n Datum hash: " + <> byteArrayToHex (unwrap $ encodeCbor datumHash) + <> "\n UTxO: " + <> show utxo +explainTxBuildError _ = "TODO" + +type M a = StateT Context (ExceptT TxBuildError Contract) a + +processConstraints :: Constraints -> M Unit +processConstraints = traverse_ processConstraint + +processConstraint :: Constraint -> M Unit +processConstraint = case _ of + SpendOutput utxo spendWitness -> do + _transaction <<< _body <<< _inputs + %= pushUnique (unwrap utxo).input + useSpendWitness utxo spendWitness + RequireSignature ppkh -> do + _transaction <<< _body <<< _requiredSigners <>= + [ wrap $ unwrap $ unwrap ppkh ] + _ -> pure unit + +assertOutputType :: ExpectedOutputType -> TransactionUnspentOutput -> M Unit +assertOutputType outputType utxo = do + let + mbCredential = + (getPaymentCredential (utxo ^. _output <<< _address) <#> unwrap) + >>= case outputType of + ScriptHashOutput -> Credential.asScriptHash >>> void + PubKeyHashOutput -> Credential.asPubKeyHash >>> void + unless (isJust mbCredential) do + throwError $ WrongOutputType outputType utxo + +-- | Tries to modify the transaction to make it consume a given output. +-- | Uses a `SpendWitness` to try to satisfy spending requirements. +useSpendWitness :: TransactionUnspentOutput -> SpendWitness -> M Unit +useSpendWitness utxo = case _ of + PubKeyOutput -> do + assertOutputType PubKeyHashOutput utxo + NativeScriptOutput nsWitness -> do + assertOutputType ScriptHashOutput utxo + -- attach the script + case nsWitness of + ScriptValue ns -> do + _transaction <<< _witnessSet <<< _nativeScripts + %= pushUnique ns + ScriptReference refInput refInputAction -> do + _transaction <<< _body <<< refInputActionToLens refInputAction + %= pushUnique refInput + PlutusScriptOutput plutusScriptWitness redeemerDatum mbDatumWitness -> do + assertOutputType ScriptHashOutput utxo + -- attach the script + case plutusScriptWitness of + ScriptValue ps -> do + _transaction <<< _witnessSet <<< _plutusScripts + %= pushUnique ps + ScriptReference input action -> do + _transaction <<< _body <<< refInputActionToLens action + %= pushUnique input + -- attach the datum + useDatumWitnessForUtxo utxo mbDatumWitness + -- attach the redeemer + let + uiRedeemer = UnindexedRedeemer + { purpose: ForSpend (unwrap utxo).input + , datum: unwrap redeemerDatum + } + _redeemers %= pushUnique uiRedeemer + +-- | Tries to modify the transaction state to make it consume a given script output. +-- | Uses a `DatumWitness` if the UTxO datum is provided as a hash. +useDatumWitnessForUtxo + :: TransactionUnspentOutput -> Maybe DatumWitness -> M Unit +useDatumWitnessForUtxo utxo datumWitness = do + case utxo ^. _output <<< _datum of + -- script outputs must have a datum + Nothing -> throwError $ WrongSpendWitnessType utxo + -- if the datum is inline, we don't need to attach it as witness + Just (OutputDatum providedDatum) -> do + when (isJust datumWitness) do + logWarn' $ + "You've provided an optional `DatumWitness` in `PlutusScriptWitness`, but the output you are spending already contains an inline datum (not just a datum hash). You can omit the provided datum witness. You provided: " + <> show providedDatum + -- if the datum is provided as hash, + Just (OutputDatumHash datumHash) -> + case datumWitness of + -- if the datum witness was not provided, look the datum up + Nothing -> do + queryHandle <- lift $ lift $ getQueryHandle + mbDatum <- liftEither =<< lmap QueryError <$> do + liftAff $ queryHandle.getDatumByHash datumHash + datum <- liftM (DatumHashLookupError datumHash) mbDatum + _datums %= pushUnique datum + _transaction <<< _witnessSet <<< _plutusData %= pushUnique datum + -- if the datum was provided, check it's hash. if it matches the one + -- specified in the output, use that datum. + Just (DatumValue providedDatum) + | datumHash == PlutusData.hashPlutusData providedDatum -> do + _datums %= pushUnique providedDatum + _transaction <<< _witnessSet <<< _plutusData + %= pushUnique providedDatum + -- otherwise, fail + Just (DatumValue providedDatum) -> do + throwError $ IncorrectDatumHash utxo providedDatum datumHash + -- if a reference input is provided, we just attach it. + -- TODO: consider querying for the inline datum to check if it matches. + Just (DatumReference datumWitnessRef refInputAction) -> do + _transaction <<< _body <<< refInputActionToLens refInputAction + %= pushUnique datumWitnessRef + +-- | Depending on `RefInputAction` value, we either want to spend a reference +-- | UTxO, or just reference it. +refInputActionToLens + :: RefInputAction + -> Lens' TransactionBody (Array TransactionInput) +refInputActionToLens = + case _ of + ReferenceInput -> _referenceInputs + SpendInput -> _inputs + +-- | Ensures uniqueness of an element +pushUnique :: forall a. Ord a => a -> Array a -> Array a +pushUnique x xs = nub $ xs <> [ x ] + +-- Ensures uniqueness +appendInput + :: TransactionInput -> Array TransactionInput -> Array TransactionInput +appendInput a b = Set.toUnfoldable (Set.singleton a <> Set.fromFoldable b) From 5311586cf8c8cf776968db76f37359bee6c385f6 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Thu, 9 May 2024 02:19:39 +0400 Subject: [PATCH 03/52] Add new-style constraints (up to minting) --- src/Contract/Constraints.purs | 132 +++++++----- src/Internal/UseConstraints.purs | 345 ++++++++++++++++--------------- 2 files changed, 261 insertions(+), 216 deletions(-) diff --git a/src/Contract/Constraints.purs b/src/Contract/Constraints.purs index d011cc1a34..7ee63d16c7 100644 --- a/src/Contract/Constraints.purs +++ b/src/Contract/Constraints.purs @@ -2,32 +2,69 @@ module Contract.Constraints where import Prelude -import Cardano.Types.Epoch (Epoch(..)) +import Cardano.Types.Certificate (Certificate) +import Cardano.Types.Coin (Coin) +import Cardano.Types.Epoch (Epoch) import Cardano.Types.NativeScript (NativeScript) -import Cardano.Types.PaymentPubKeyHash (PaymentPubKeyHash(..)) +import Cardano.Types.PaymentPubKeyHash (PaymentPubKeyHash) import Cardano.Types.PlutusData (PlutusData) import Cardano.Types.PlutusScript (PlutusScript) -import Cardano.Types.PoolParams (PoolParams(..)) +import Cardano.Types.PoolParams (PoolParams) import Cardano.Types.PoolPubKeyHash (PoolPubKeyHash) -import Cardano.Types.ScriptHash (ScriptHash(..)) +import Cardano.Types.StakeCredential (StakeCredential) import Cardano.Types.StakePubKeyHash (StakePubKeyHash) -import Cardano.Types.TransactionInput (TransactionInput(..)) -import Cardano.Types.TransactionUnspentOutput (TransactionUnspentOutput(..)) +import Cardano.Types.TransactionInput (TransactionInput) +import Cardano.Types.TransactionUnspentOutput (TransactionUnspentOutput) import Ctl.Internal.Types.RedeemerDatum (RedeemerDatum) -import Ctl.Internal.Types.TxConstraints (TxConstraint(..), TxConstraints(..)) -import Data.Array (singleton) -import Data.Either (Either(..)) -import Data.Maybe (Maybe(..)) +import Data.Generic.Rep (class Generic) +import Data.Maybe (Maybe) +import Data.Show.Generic (genericShow) --- Spending +type Constraints = Array Constraint --- | Datums in UTxOs can be stored in two forms: inline datums or datum hashes. --- | When there's a hash, we need to provide a datum corresponding to this hash, --- | which can be done by either providing the value literally, or using a --- | reference input where it is stored inline. -data DatumWitness - = DatumValue PlutusData - | DatumReference TransactionInput RefInputAction +data Constraint + = SpendOutput TransactionUnspentOutput OutputWitness + | RegisterStake StakeCredential + | IssueCertificate Certificate CredentialWitness + | WithdrawStake StakeCredential Coin CredentialWitness + | RequireSignature PaymentPubKeyHash + | RegisterPool PoolParams + | RetirePool PoolPubKeyHash Epoch + +derive instance Generic Constraint _ +instance Show Constraint where + show = genericShow + +-- | `OutputWitness` is used to provide the evidence needed to consume an +-- | output. It must correspond to a `TransactionUnspentOutput` address' +-- | payment credential to unlock it. +data OutputWitness + = PubKeyOutput + | NativeScriptOutput (ScriptWitness NativeScript) + | PlutusScriptOutput (ScriptWitness PlutusScript) RedeemerDatum + (Maybe DatumWitness) + +derive instance Generic OutputWitness _ +instance Show OutputWitness where + show = genericShow + +-- | `CredentialWitness` is used to provide the evidence needed to perform +-- | operations on behalf of a credential, which include: +-- | +-- | - Minting +-- | - Certificate witnessing +-- | - Rewards withdrawal +-- | +-- | Unlike `OutputWitness`, it does not include a `DatumWitness`, because +-- | minting policies and stake scripts do not have a datum. +data CredentialWitness + = PubKeyCredential + | NativeScriptCredential (ScriptWitness NativeScript) + | PlutusScriptCredential (ScriptWitness PlutusScript) RedeemerDatum + +derive instance Generic CredentialWitness _ +instance Show CredentialWitness where + show = genericShow -- | Gives the user options for specifying everything needed to spend an UTxO -- | located at an address with a ScriptHash payment credential. @@ -39,6 +76,10 @@ data ScriptWitness a = ScriptValue a | ScriptReference TransactionInput RefInputAction +derive instance Show a => Generic (ScriptWitness a) _ +instance Show a => Show (ScriptWitness a) where + show = genericShow + -- | Inputs can be referenced or spent in a transaction (See CIP-31). -- | Inline datums (CIP-32) and reference scripts (CIP-33) contained within -- | transaction outputs become visible to the script context of the @@ -49,49 +90,30 @@ data RefInputAction = ReferenceInput | SpendInput -data SpendWitness - = PubKeyOutput - | NativeScriptOutput (ScriptWitness NativeScript) - | PlutusScriptOutput (ScriptWitness PlutusScript) RedeemerDatum - (Maybe DatumWitness) +derive instance Generic RefInputAction _ +instance Show RefInputAction where + show = genericShow + +-- | Datums in UTxOs can be stored in two forms: inline datums or datum hashes. +-- | When there's a hash, we need to provide a datum corresponding to this hash, +-- | which can be done by either providing the value literally, or using a +-- | reference input where it is stored inline. +data DatumWitness + = DatumValue PlutusData + | DatumReference TransactionInput RefInputAction + +derive instance Generic DatumWitness _ +instance Show DatumWitness where + show = genericShow data StakeWitness = PubKeyHashStakeWitness StakePubKeyHash | PlutusScriptStakeWitness (ScriptWitness PlutusScript) | NativeScriptStakeWitness (ScriptWitness NativeScript) -data StakeRegistration - = StakePubKeyRegistration StakePubKeyHash - | StakeScriptRegistration ScriptHash - -data StakeAction - = Delegate PoolPubKeyHash - | Withdraw - | Deregister - -data Constraint - = SpendOutput TransactionUnspentOutput SpendWitness - | RegisterStake StakeRegistration - | Stake StakeAction StakeWitness - | RequireSignature PaymentPubKeyHash - | RegisterPool PoolParams - | RetirePool PoolPubKeyHash Epoch - -type Constraints = Array Constraint - -requireSignature :: PaymentPubKeyHash -> TxConstraints -requireSignature = singleton <<< MustBeSignedBy - --- Stake Pool operations - -registerPool :: PoolParams -> TxConstraints -registerPool = singleton <<< MustRegisterPool - -retirePool - :: PoolPubKeyHash - -> Epoch - -> TxConstraints -retirePool poolPubKeyHash = singleton <<< MustRetirePool poolPubKeyHash +derive instance Generic StakeWitness _ +instance Show StakeWitness where + show = genericShow -- Stake operations diff --git a/src/Internal/UseConstraints.purs b/src/Internal/UseConstraints.purs index 99011cda27..6aeb930f46 100644 --- a/src/Internal/UseConstraints.purs +++ b/src/Internal/UseConstraints.purs @@ -1,168 +1,70 @@ module Ctl.Internal.UseConstraints where -import Data.Lens import Prelude import Cardano.AsCbor (encodeCbor) import Cardano.Types - ( Certificate - ( StakeDelegation - , PoolRetirement - , PoolRegistration - , StakeDeregistration - , StakeRegistration - ) - , DataHash + ( DataHash , NetworkId , PlutusData , PlutusScript - , ScriptHash - , ScriptRef(NativeScriptRef, PlutusScriptRef) - , StakeCredential(StakeCredential) + , StakeCredential , Transaction , TransactionInput - , TransactionOutput(TransactionOutput) - , TransactionUnspentOutput(TransactionUnspentOutput) - , TransactionWitnessSet(TransactionWitnessSet) - , Value(Value) - ) -import Cardano.Types.Address - ( Address(BaseAddress, EnterpriseAddress) - , getPaymentCredential - ) -import Cardano.Types.Coin as Coin -import Cardano.Types.CostModel (CostModel(..)) -import Cardano.Types.Credential - ( Credential(PubKeyHashCredential, ScriptHashCredential) - , asScriptHash + , TransactionUnspentOutput ) +import Cardano.Types.Address (getPaymentCredential) +import Cardano.Types.Certificate (Certificate(..)) +import Cardano.Types.Coin (Coin) +import Cardano.Types.CostModel (CostModel) import Cardano.Types.Credential as Credential -import Cardano.Types.DataHash (hashPlutusData) -import Cardano.Types.DataHash as Datum import Cardano.Types.DataHash as PlutusData -import Cardano.Types.Int as Int import Cardano.Types.Language (Language) -import Cardano.Types.Mint as Mint -import Cardano.Types.MultiAsset as MultiAsset -import Cardano.Types.NativeScript as NativeScript +import Cardano.Types.NativeScript (NativeScript) import Cardano.Types.OutputDatum (OutputDatum(OutputDatumHash, OutputDatum)) -import Cardano.Types.PlutusScript as PlutusScript -import Cardano.Types.Transaction as Transaction -import Cardano.Types.TransactionBody (TransactionBody(..)) +import Cardano.Types.TransactionBody (TransactionBody) import Contract.Constraints ( Constraint(..) , Constraints + , CredentialWitness(..) , DatumWitness(..) + , OutputWitness(..) , RefInputAction(..) , ScriptWitness(..) - , SpendWitness(..) ) -import Contract.Log (logWarn') -import Control.Monad (unless) -import Control.Monad.Error.Class (catchError, throwError) +import Control.Monad.Error.Class (throwError) import Control.Monad.Except (Except) -import Control.Monad.Except.Trans (ExceptT(ExceptT), except, runExceptT) -import Control.Monad.Reader.Class (asks) -import Control.Monad.State (StateT(..)) -import Control.Monad.State.Trans (get, gets, put, runStateT) -import Control.Monad.Trans.Class (lift) +import Control.Monad.State (StateT) +import Control.Monad.State.Trans (gets) import Ctl.Internal.BalanceTx.RedeemerIndex - ( RedeemerPurpose(ForReward, ForCert, ForMint, ForSpend) + ( RedeemerPurpose(ForSpend, ForCert) , UnindexedRedeemer(UnindexedRedeemer) - , unindexedRedeemerToRedeemer ) -import Ctl.Internal.Contract (getProtocolParameters) -import Ctl.Internal.Contract.Monad (Contract, getQueryHandle, wrapQueryM) -import Ctl.Internal.Helpers (liftEither, liftM, unsafeFromJust) import Ctl.Internal.Lens ( _address , _body , _certs , _datum , _inputs - , _isValid - , _mint , _nativeScripts - , _networkId , _output - , _outputs , _plutusData , _plutusScripts , _referenceInputs , _requiredSigners - , _scriptDataHash , _withdrawals , _witnessSet ) -import Ctl.Internal.ProcessConstraints.Error - ( MkUnbalancedTxError - ( CannotSatisfyAny - , CannotWithdrawRewardsNativeScript - , CannotWithdrawRewardsPlutusScript - , CannotWithdrawRewardsPubKey - , DatumWrongHash - , CannotMintZero - , ExpectedPlutusScriptGotNativeScript - , CannotFindDatum - , CannotQueryDatum - , CannotGetValidatorHashFromAddress - , TxOutRefWrongType - , CannotConvertPOSIXTimeRange - , NumericOverflow - , WrongRefScriptHash - , ValidatorHashNotFound - , MintingPolicyNotFound - , DatumNotFound - , TxOutRefNotFound - , CannotSolveTimeConstraints - , OwnPubKeyAndStakeKeyMissing - ) - ) -import Ctl.Internal.ProcessConstraints.UnbalancedTx (UnbalancedTx) -import Ctl.Internal.QueryM.Pools - ( getPubKeyHashDelegationsAndRewards - , getValidatorHashDelegationsAndRewards - ) -import Ctl.Internal.Service.Error (ClientError, pprintClientError) -import Ctl.Internal.Transaction - ( attachDatum - , attachNativeScript - , attachPlutusScript - , setScriptDataHash - ) -import Ctl.Internal.Types.Interval - ( POSIXTimeRange - , always - , intersection - , isEmpty - , posixTimeRangeToTransactionValidity - ) -import Ctl.Internal.Types.ScriptLookups (ScriptLookups) -import Ctl.Internal.Types.Val as Val -import Data.Array (cons, nub, partition, toUnfoldable, zip) -import Data.Array (mapMaybe, singleton, (:)) as Array -import Data.Bifunctor (lmap) +import Data.Array (nub) import Data.ByteArray (byteArrayToHex) -import Data.Either (Either(Left, Right), either, hush, isRight, note) -import Data.Foldable (foldM) -import Data.Lens (Lens', (%=), (%~), (.=), (.~), (<>=)) -import Data.Lens.Getter (to, use) -import Data.Lens.Iso.Newtype (_Newtype) +import Data.Lens (Lens', (%=), (<>=), (^.)) import Data.Lens.Record (prop) -import Data.List (List(Nil, Cons)) -import Data.Map (Map, empty, fromFoldable, lookup, union) +import Data.Map (Map) import Data.Map as Map -import Data.Maybe (Maybe(Nothing, Just), fromMaybe, isJust, maybe) -import Data.Newtype (over, unwrap, wrap) +import Data.Maybe (Maybe(Just, Nothing), isJust) +import Data.Newtype (unwrap, wrap) import Data.Set as Set -import Data.Traversable (for, traverse_) -import Data.Tuple.Nested (type (/\), (/\)) -import Effect (Effect) -import Effect.Aff.Class (liftAff) -import Effect.Class (liftEffect) -import Effect.Exception (throw) -import Partial.Unsafe (unsafePartial) -import Prelude (join) as Bind +import Data.Traversable (traverse_) import Type.Proxy (Proxy(..)) type Context = @@ -170,6 +72,7 @@ type Context = , costModels :: Map Language CostModel , redeemers :: Array UnindexedRedeemer , datums :: Array PlutusData + , networkId :: NetworkId } _transaction @@ -184,21 +87,33 @@ _datums :: Lens' Context (Array PlutusData) _datums = prop (Proxy :: Proxy "datums") -data ExpectedOutputType = ScriptHashOutput | PubKeyHashOutput +data ExpectedWitnessType = ScriptHashWitness | PubKeyHashWitness + +explainExpectedWitnessType :: ExpectedWitnessType -> String +explainExpectedWitnessType ScriptHashWitness = "ScriptHash" +explainExpectedWitnessType PubKeyHashWitness = "PubKeyHash" + +data CredentialAction = StakeCert | Withdrawal | Minting + +explainCredentialAction :: CredentialAction -> String +explainCredentialAction StakeCert = "This stake certificate" +explainCredentialAction Withdrawal = "This stake rewards withdrawal" +explainCredentialAction Minting = "This mint" data TxBuildError = WrongSpendWitnessType TransactionUnspentOutput - | QueryError ClientError | DatumHashLookupError DataHash | IncorrectDatumHash TransactionUnspentOutput PlutusData DataHash - | WrongOutputType ExpectedOutputType TransactionUnspentOutput + | WrongOutputType ExpectedWitnessType TransactionUnspentOutput + | WrongStakeCredentialType CredentialAction ExpectedWitnessType + StakeCredential + | DatumWitnessNotProvided TransactionUnspentOutput + | UnneededDatumWitness TransactionUnspentOutput DatumWitness explainTxBuildError :: TxBuildError -> String explainTxBuildError (WrongSpendWitnessType utxo) = - "SpendWitness is incompatible with the given output. The output does not contain a datum: " + "`OutputWitness` is incompatible with the given output. The output does not contain a datum: " <> show utxo -explainTxBuildError (QueryError clientError) = - "Query error: " <> pprintClientError clientError explainTxBuildError (DatumHashLookupError dataHash) = "The UTxO you are trying to spend contains a datum hash. You didn't provide a `DatumWitness` value corresponding to this hash, so CTL tried to look it up, using a database of datums observed on-chain. This lookup failed. Datum hash: " <> show dataHash @@ -211,9 +126,29 @@ explainTxBuildError (IncorrectDatumHash utxo datum datumHash) = <> byteArrayToHex (unwrap $ encodeCbor datumHash) <> "\n UTxO: " <> show utxo +explainTxBuildError (WrongOutputType ScriptHashWitness utxo) = + "The UTxO you provided requires a Script witness to unlock. UTxO: " <> show + utxo +explainTxBuildError (WrongOutputType PubKeyHashWitness utxo) = + "The UTxO you provided requires a PubKeyHash witness to unlock. UTxO: " <> + show utxo +explainTxBuildError + (WrongStakeCredentialType operation expWitnessType stakeCredential) = + explainCredentialAction operation <> " requires a " + <> explainExpectedWitnessType expWitnessType + <> " witness: " + <> show stakeCredential +explainTxBuildError (DatumWitnessNotProvided utxo) = + "The UTxO you are trying to spend contains a datum hash. A matching `DatumWitness` is required. Use `getDatumByHash`. UTxO: " + <> show utxo +explainTxBuildError (UnneededDatumWitness utxo witness) = + "You've provided an optional `DatumWitness`, but the output you are spending already contains an inline datum (not just a datum hash). You should omit the provided datum witness. You provided: " + <> show witness + <> " for the UTxO: " + <> show utxo explainTxBuildError _ = "TODO" -type M a = StateT Context (ExceptT TxBuildError Contract) a +type M a = StateT Context (Except TxBuildError) a processConstraints :: Constraints -> M Unit processConstraints = traverse_ processConstraint @@ -224,48 +159,121 @@ processConstraint = case _ of _transaction <<< _body <<< _inputs %= pushUnique (unwrap utxo).input useSpendWitness utxo spendWitness + RegisterStake stakeCredential -> do + _transaction <<< _body <<< _certs %= pushUnique + (StakeRegistration stakeCredential) + IssueCertificate cert witness -> do + useCertificateWitness cert witness + WithdrawStake stakeCredential amount witness -> do + useWithdrawRewardsWitness stakeCredential amount witness RequireSignature ppkh -> do _transaction <<< _body <<< _requiredSigners <>= [ wrap $ unwrap $ unwrap ppkh ] - _ -> pure unit + RegisterPool poolParams -> do + _transaction <<< _body <<< _certs %= pushUnique + (PoolRegistration poolParams) + RetirePool poolKeyHash epoch -> do + _transaction <<< _body <<< _certs %= pushUnique + (PoolRetirement { poolKeyHash, epoch }) -assertOutputType :: ExpectedOutputType -> TransactionUnspentOutput -> M Unit +assertOutputType :: ExpectedWitnessType -> TransactionUnspentOutput -> M Unit assertOutputType outputType utxo = do let mbCredential = (getPaymentCredential (utxo ^. _output <<< _address) <#> unwrap) >>= case outputType of - ScriptHashOutput -> Credential.asScriptHash >>> void - PubKeyHashOutput -> Credential.asPubKeyHash >>> void + ScriptHashWitness -> Credential.asScriptHash >>> void + PubKeyHashWitness -> Credential.asPubKeyHash >>> void unless (isJust mbCredential) do throwError $ WrongOutputType outputType utxo +assertStakeCredentialType + :: CredentialAction -> ExpectedWitnessType -> StakeCredential -> M Unit +assertStakeCredentialType action expectedType credential = do + let + mbCredential = + case expectedType of + ScriptHashWitness -> + void $ Credential.asScriptHash $ unwrap credential + PubKeyHashWitness -> + void $ Credential.asPubKeyHash $ unwrap credential + unless (isJust mbCredential) do + throwError $ WrongStakeCredentialType action expectedType credential + +useCertificateWitness :: Certificate -> CredentialWitness -> M Unit +useCertificateWitness cert witness = do + _transaction <<< _body <<< _certs %= pushUnique cert + case cert of + StakeDeregistration stakeCredential -> do + useCertificateCredentialWitness cert witness + useCredentialWitness StakeCert stakeCredential witness + StakeDelegation stakeCredential _ -> do + useCertificateCredentialWitness cert witness + useCredentialWitness StakeCert stakeCredential witness + StakeRegistration _ -> pure unit + PoolRegistration _ -> pure unit + PoolRetirement _ -> pure unit + GenesisKeyDelegation _ -> pure unit + MoveInstantaneousRewardsCert _ -> pure unit + +useCertificateCredentialWitness :: Certificate -> CredentialWitness -> M Unit +useCertificateCredentialWitness cert witness = do + case witness of + PubKeyCredential -> pure unit + NativeScriptCredential _nsWitness -> pure unit + PlutusScriptCredential _plutusScriptWitness redeemerDatum -> do + -- attach the redeemer + let + uiRedeemer = UnindexedRedeemer + { purpose: ForCert cert + , datum: unwrap redeemerDatum + } + _redeemers %= pushUnique uiRedeemer + +useCredentialWitness + :: CredentialAction -> StakeCredential -> CredentialWitness -> M Unit +useCredentialWitness credentialAction stakeCredential witness = do + case witness of + PubKeyCredential -> do + assertStakeCredentialType credentialAction PubKeyHashWitness + stakeCredential + NativeScriptCredential nsWitness -> do + assertStakeCredentialType credentialAction ScriptHashWitness + stakeCredential + useNativeScriptWitness nsWitness + PlutusScriptCredential plutusScriptWitness _ -> do + assertStakeCredentialType credentialAction ScriptHashWitness + stakeCredential + usePlutusScriptWitness plutusScriptWitness + +useWithdrawRewardsWitness + :: StakeCredential -> Coin -> CredentialWitness -> M Unit +useWithdrawRewardsWitness stakeCredential amount witness = do + useCredentialWitness Withdrawal stakeCredential witness + networkId <- gets _.networkId + let + rewardAddress = + { networkId + , stakeCredential + } + _transaction <<< _body <<< _withdrawals %= + Map.insert rewardAddress amount + pure unit + -- | Tries to modify the transaction to make it consume a given output. -- | Uses a `SpendWitness` to try to satisfy spending requirements. -useSpendWitness :: TransactionUnspentOutput -> SpendWitness -> M Unit +useSpendWitness :: TransactionUnspentOutput -> OutputWitness -> M Unit useSpendWitness utxo = case _ of PubKeyOutput -> do - assertOutputType PubKeyHashOutput utxo + assertOutputType PubKeyHashWitness utxo NativeScriptOutput nsWitness -> do - assertOutputType ScriptHashOutput utxo + assertOutputType ScriptHashWitness utxo -- attach the script - case nsWitness of - ScriptValue ns -> do - _transaction <<< _witnessSet <<< _nativeScripts - %= pushUnique ns - ScriptReference refInput refInputAction -> do - _transaction <<< _body <<< refInputActionToLens refInputAction - %= pushUnique refInput + useNativeScriptWitness nsWitness PlutusScriptOutput plutusScriptWitness redeemerDatum mbDatumWitness -> do - assertOutputType ScriptHashOutput utxo + assertOutputType ScriptHashWitness utxo -- attach the script - case plutusScriptWitness of - ScriptValue ps -> do - _transaction <<< _witnessSet <<< _plutusScripts - %= pushUnique ps - ScriptReference input action -> do - _transaction <<< _body <<< refInputActionToLens action - %= pushUnique input + usePlutusScriptWitness plutusScriptWitness -- attach the datum useDatumWitnessForUtxo utxo mbDatumWitness -- attach the redeemer @@ -276,31 +284,46 @@ useSpendWitness utxo = case _ of } _redeemers %= pushUnique uiRedeemer +usePlutusScriptWitness :: ScriptWitness PlutusScript -> M Unit +usePlutusScriptWitness = + case _ of + ScriptValue ps -> do + _transaction <<< _witnessSet <<< _plutusScripts + %= pushUnique ps + ScriptReference input action -> do + _transaction <<< _body <<< refInputActionToLens action + %= pushUnique input + +useNativeScriptWitness :: ScriptWitness NativeScript -> M Unit +useNativeScriptWitness = + case _ of + ScriptValue ns -> do + _transaction <<< _witnessSet <<< _nativeScripts + %= pushUnique ns + ScriptReference refInput refInputAction -> do + _transaction <<< _body <<< refInputActionToLens refInputAction + %= pushUnique refInput + -- | Tries to modify the transaction state to make it consume a given script output. -- | Uses a `DatumWitness` if the UTxO datum is provided as a hash. useDatumWitnessForUtxo :: TransactionUnspentOutput -> Maybe DatumWitness -> M Unit -useDatumWitnessForUtxo utxo datumWitness = do +useDatumWitnessForUtxo utxo mbDatumWitness = do case utxo ^. _output <<< _datum of -- script outputs must have a datum Nothing -> throwError $ WrongSpendWitnessType utxo -- if the datum is inline, we don't need to attach it as witness - Just (OutputDatum providedDatum) -> do - when (isJust datumWitness) do - logWarn' $ - "You've provided an optional `DatumWitness` in `PlutusScriptWitness`, but the output you are spending already contains an inline datum (not just a datum hash). You can omit the provided datum witness. You provided: " - <> show providedDatum + Just (OutputDatum _providedDatum) -> do + case mbDatumWitness of + Just datumWitness -> + throwError $ UnneededDatumWitness utxo datumWitness + Nothing -> pure unit -- if the datum is provided as hash, Just (OutputDatumHash datumHash) -> - case datumWitness of + case mbDatumWitness of -- if the datum witness was not provided, look the datum up Nothing -> do - queryHandle <- lift $ lift $ getQueryHandle - mbDatum <- liftEither =<< lmap QueryError <$> do - liftAff $ queryHandle.getDatumByHash datumHash - datum <- liftM (DatumHashLookupError datumHash) mbDatum - _datums %= pushUnique datum - _transaction <<< _witnessSet <<< _plutusData %= pushUnique datum + throwError $ DatumWitnessNotProvided utxo -- if the datum was provided, check it's hash. if it matches the one -- specified in the output, use that datum. Just (DatumValue providedDatum) From a960e9478a05a5dff8e817f06bd436deed24ab53 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Thu, 9 May 2024 02:21:10 +0400 Subject: [PATCH 04/52] Improve staking test: use an actually failing script --- test/Plutip/Staking.purs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/Plutip/Staking.purs b/test/Plutip/Staking.purs index 630a407d17..0a9882b2bf 100644 --- a/test/Plutip/Staking.purs +++ b/test/Plutip/Staking.purs @@ -7,10 +7,12 @@ import Prelude import Cardano.AsCbor (decodeCbor) import Cardano.Types (PoolParams(PoolParams), UnitInterval(UnitInterval)) +import Cardano.Types.BigInt as BigInt import Cardano.Types.Credential ( Credential(ScriptHashCredential, PubKeyHashCredential) ) import Cardano.Types.NativeScript as NativeScript +import Cardano.Types.PlutusData (PlutusData(Integer)) import Cardano.Types.PlutusScript as PlutusScript import Contract.Address (getNetworkId) import Contract.Backend.Ogmios (getPoolParameters) @@ -22,7 +24,7 @@ import Contract.PlutusData (unitDatum, unitRedeemer) import Contract.Prelude (liftM) import Contract.Prim.ByteArray (hexToByteArray) import Contract.ScriptLookups as Lookups -import Contract.Scripts (NativeScript(ScriptPubkey, ScriptAny)) +import Contract.Scripts (NativeScript(ScriptPubkey, ScriptAny), applyArgs) import Contract.Staking ( getPoolIds , getPubKeyHashDelegationsAndRewards @@ -70,6 +72,7 @@ import Ctl.Examples.Helpers (submitAndLog) import Ctl.Examples.IncludeDatum (only42Script) import Data.Array (head, (!!)) import Data.Array as Array +import Data.Either (hush) import Data.Foldable (for_) import Data.Maybe (Maybe(Just, Nothing)) import Data.Newtype (unwrap, wrap) @@ -180,7 +183,10 @@ suite = do liftedM "Failed to get Stake PKH" (join <<< head <$> ownStakePubKeyHashes) validator1 <- alwaysSucceedsScript - validator2 <- only42Script + validator2 <- do + only42 <- only42Script + liftM (error "failed to apply args") do + applyArgs only42 [ Integer $ BigInt.fromInt 42 ] # hush let validatorHash1 = PlutusScript.hash validator1 validatorHash2 = PlutusScript.hash validator2 From 0576feabc1c7ec03eceb0d65a09fec4b26939322 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Thu, 9 May 2024 14:56:59 +0300 Subject: [PATCH 05/52] Fix developer portal link --- doc/blockfrost.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/blockfrost.md b/doc/blockfrost.md index 66e4aa314a..72efd58bf9 100644 --- a/doc/blockfrost.md +++ b/doc/blockfrost.md @@ -47,7 +47,7 @@ Go to https://blockfrost.io to generate a new API key and specify it as `BLOCKFR ### Generating private keys -Follow https://developers.cardano.org/docs/stake-pool-course/handbook/keys-addresses/ to generate a private payment key (and, optionally, a stake key). You can use [this script](https://github.com/Plutonomicon/cardano-transaction-lib/blob/develop/scripts/generate-keys.sh) for convenience instead of following instructions in this section manually. +Follow [this guide](https://developers.cardano.org/docs/operate-a-stake-pool/generating-wallet-keys) to generate a private payment key (and, optionally, a stake key). You can use [this script](https://github.com/Plutonomicon/cardano-transaction-lib/blob/develop/scripts/generate-keys.sh) for convenience instead of following instructions in this section manually. The generated keys should look like this: From 7d9d1e0c2a99a65923a59518961e5a35ebd529b2 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Thu, 9 May 2024 18:18:26 +0400 Subject: [PATCH 06/52] Add more trivial constraints --- src/Contract/Constraints.purs | 8 ++++++++ src/Internal/Plutip/Server.purs | 1 - src/Internal/UseConstraints.purs | 21 ++++++++++++++++++++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/Contract/Constraints.purs b/src/Contract/Constraints.purs index 7ee63d16c7..c7b2dbc3fc 100644 --- a/src/Contract/Constraints.purs +++ b/src/Contract/Constraints.purs @@ -2,6 +2,7 @@ module Contract.Constraints where import Prelude +import Cardano.Types (Slot) import Cardano.Types.Certificate (Certificate) import Cardano.Types.Coin (Coin) import Cardano.Types.Epoch (Epoch) @@ -14,6 +15,7 @@ import Cardano.Types.PoolPubKeyHash (PoolPubKeyHash) import Cardano.Types.StakeCredential (StakeCredential) import Cardano.Types.StakePubKeyHash (StakePubKeyHash) import Cardano.Types.TransactionInput (TransactionInput) +import Cardano.Types.TransactionOutput (TransactionOutput) import Cardano.Types.TransactionUnspentOutput (TransactionUnspentOutput) import Ctl.Internal.Types.RedeemerDatum (RedeemerDatum) import Data.Generic.Rep (class Generic) @@ -22,14 +24,20 @@ import Data.Show.Generic (genericShow) type Constraints = Array Constraint +-- TODO: consider using Maybe for witnesses data Constraint = SpendOutput TransactionUnspentOutput OutputWitness + | PayTo TransactionOutput | RegisterStake StakeCredential | IssueCertificate Certificate CredentialWitness | WithdrawStake StakeCredential Coin CredentialWitness | RequireSignature PaymentPubKeyHash | RegisterPool PoolParams | RetirePool PoolPubKeyHash Epoch + | IncludeDatum PlutusData + | SetTTL (Maybe Slot) + | SetValidityStartInterval (Maybe Slot) + | SetIsValid Boolean derive instance Generic Constraint _ instance Show Constraint where diff --git a/src/Internal/Plutip/Server.purs b/src/Internal/Plutip/Server.purs index 104314d085..7eea80025d 100644 --- a/src/Internal/Plutip/Server.purs +++ b/src/Internal/Plutip/Server.purs @@ -368,7 +368,6 @@ startPlutipContractEnv plutipCfg distr cleanupRef = do (stopChildProcessWithPortAndRemoveOnSignal plutipCfg.kupoConfig.port) \(process /\ workdir /\ _) -> do liftEffect $ cleanupTmpDir process workdir - pure unit mkWallets' :: ContractEnv diff --git a/src/Internal/UseConstraints.purs b/src/Internal/UseConstraints.purs index 6aeb930f46..19144534d9 100644 --- a/src/Internal/UseConstraints.purs +++ b/src/Internal/UseConstraints.purs @@ -46,18 +46,22 @@ import Ctl.Internal.Lens , _certs , _datum , _inputs + , _isValid , _nativeScripts , _output + , _outputs , _plutusData , _plutusScripts , _referenceInputs , _requiredSigners + , _ttl + , _validityStartInterval , _withdrawals , _witnessSet ) import Data.Array (nub) import Data.ByteArray (byteArrayToHex) -import Data.Lens (Lens', (%=), (<>=), (^.)) +import Data.Lens (Lens', (%=), (.=), (<>=), (^.)) import Data.Lens.Record (prop) import Data.Map (Map) import Data.Map as Map @@ -159,6 +163,11 @@ processConstraint = case _ of _transaction <<< _body <<< _inputs %= pushUnique (unwrap utxo).input useSpendWitness utxo spendWitness + PayTo utxo -> do + _transaction <<< _body <<< _outputs + -- intentionally not using pushUnique: we can + -- create multiple outputs of the same shape + %= flip append [ utxo ] RegisterStake stakeCredential -> do _transaction <<< _body <<< _certs %= pushUnique (StakeRegistration stakeCredential) @@ -175,6 +184,16 @@ processConstraint = case _ of RetirePool poolKeyHash epoch -> do _transaction <<< _body <<< _certs %= pushUnique (PoolRetirement { poolKeyHash, epoch }) + IncludeDatum datum -> do + _datums %= pushUnique datum + _transaction <<< _witnessSet <<< _plutusData + %= pushUnique datum + SetTTL slot -> do + _transaction <<< _body <<< _ttl .= slot + SetValidityStartInterval slot -> do + _transaction <<< _body <<< _validityStartInterval .= slot + SetIsValid isValid -> do + _transaction <<< _isValid .= isValid assertOutputType :: ExpectedWitnessType -> TransactionUnspentOutput -> M Unit assertOutputType outputType utxo = do From 7c450d75626ddecab1a26f852db127a54b0ce18d Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Mon, 20 May 2024 21:39:50 +0300 Subject: [PATCH 07/52] Update plutip-testing.md: use BigNum --- doc/plutip-testing.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/plutip-testing.md b/doc/plutip-testing.md index 39f223080f..e95ef09a77 100644 --- a/doc/plutip-testing.md +++ b/doc/plutip-testing.md @@ -183,10 +183,10 @@ An example `Contract` with two actors using nested tuples: let distribution :: Array BigInt /\ Array BigInt distribution = - [ BigInt.fromInt 1_000_000_000 - , BigInt.fromInt 2_000_000_000 + [ BigNum.fromInt 1_000_000_000 + , BigNum.fromInt 2_000_000_000 ] /\ - [ BigInt.fromInt 2_000_000_000 ] + [ BigNum.fromInt 2_000_000_000 ] runPlutipContract config distribution \(alice /\ bob) -> do withKeyWallet alice do pure unit -- sign, balance, submit, etc. @@ -201,9 +201,9 @@ let distribution :: Array (Array BigInt) distribution = -- wallet one: two UTxOs - [ [ BigInt.fromInt 1_000_000_000, BigInt.fromInt 2_000_000_000] + [ [ BigNum.fromInt 1_000_000_000, BigNum.fromInt 2_000_000_000] -- wallet two: one UTxO - , [ BigInt.fromInt 2_000_000_000 ] + , [ BigNum.fromInt 2_000_000_000 ] ] runPlutipContract config distribution \wallets -> do traverse_ ( \wallet -> do @@ -343,8 +343,8 @@ let $ privateKeyFromBytes =<< hexToRawBytes "633b1c4c4a075a538d37e062c1ed0706d3f0a94b013708e8f5ab0a0ca1df163d" aliceUtxos = - [ BigInt.fromInt 2_000_000_000 - , BigInt.fromInt 2_000_000_000 + [ BigNum.fromInt 2_000_000_000 + , BigNum.fromInt 2_000_000_000 ] distribution = withStakeKey privateStakeKey aliceUtxos ``` From 4e967d2a97c90f1662c2e22234f3983aa1c8e226 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Tue, 28 May 2024 15:07:39 +0300 Subject: [PATCH 08/52] Try to fix github pages deployment --- .github/workflows/pages.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index f0250567f0..cf22b92771 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -17,6 +17,7 @@ jobs: run: | npm install -g spago npm install -g purescript@0.15.8 + rm -rf package.json # remove package.json so that we are no more in an ESM module. A hack to make 'spago docs' work spago docs - name: Deploy uses: JamesIves/github-pages-deploy-action@v4.3.3 From 3ba8f616b4c2ee2c5e17112145fbfbb374ea6f80 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Tue, 28 May 2024 17:40:08 +0400 Subject: [PATCH 09/52] Remove datums from UnbalancedTx --- src/Contract/Transaction.purs | 3 +-- src/Internal/BalanceTx/ExUnitsAndMinFee.purs | 11 +++-------- src/Internal/BalanceTx/UnattachedTx.purs | 4 +--- src/Internal/ProcessConstraints.purs | 8 ++++---- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/Contract/Transaction.purs b/src/Contract/Transaction.purs index b5f7227e7d..9018e192ad 100644 --- a/src/Contract/Transaction.purs +++ b/src/Contract/Transaction.purs @@ -298,12 +298,11 @@ unUnbalancedTx unUnbalancedTx ( UnbalancedTx { transaction - , datums , redeemers , usedUtxos } ) = - { transaction, datums, redeemers } /\ usedUtxos + { transaction, redeemers } /\ usedUtxos -- | Attempts to balance an `UnbalancedTx` using the specified -- | balancer constraints. diff --git a/src/Internal/BalanceTx/ExUnitsAndMinFee.purs b/src/Internal/BalanceTx/ExUnitsAndMinFee.purs index ebfe61123c..625c43d4f3 100644 --- a/src/Internal/BalanceTx/ExUnitsAndMinFee.purs +++ b/src/Internal/BalanceTx/ExUnitsAndMinFee.purs @@ -191,18 +191,13 @@ finalizeTransaction tx utxos = do reattachDatumsAndFakeRedeemers :: IndexedTx -> Transaction reattachDatumsAndFakeRedeemers - { transaction, datums, redeemers } = + { transaction, redeemers } = reattachDatumsAndRedeemers - { transaction, datums, redeemers: indexedRedeemerToRedeemer <$> redeemers } + { transaction, redeemers: indexedRedeemerToRedeemer <$> redeemers } reattachDatumsAndRedeemers :: EvaluatedTx -> Transaction reattachDatumsAndRedeemers - ({ transaction, datums, redeemers }) = - let - transaction' = attachRedeemers redeemers transaction - in - transaction' - # _witnessSet <<< _plutusData .~ datums + ({ transaction, redeemers }) = attachRedeemers redeemers transaction updateTxExecutionUnits :: IndexedTx diff --git a/src/Internal/BalanceTx/UnattachedTx.purs b/src/Internal/BalanceTx/UnattachedTx.purs index f613e8d4a2..f5439f5760 100644 --- a/src/Internal/BalanceTx/UnattachedTx.purs +++ b/src/Internal/BalanceTx/UnattachedTx.purs @@ -25,7 +25,6 @@ import Type.Proxy (Proxy(Proxy)) type UnattachedTx redeemer = { transaction :: Transaction - , datums :: Array PlutusData , redeemers :: Array redeemer } @@ -39,11 +38,10 @@ type IndexedTx = UnattachedTx IndexedRedeemer type EvaluatedTx = UnattachedTx Redeemer indexTx :: UnindexedTx -> Either UnindexedRedeemer IndexedTx -indexTx { transaction, datums, redeemers } = do +indexTx { transaction, redeemers } = do redeemers' <- indexRedeemers (mkRedeemersContext transaction) redeemers pure { transaction: attachIndexedRedeemers redeemers' transaction - , datums , redeemers: redeemers' } diff --git a/src/Internal/ProcessConstraints.purs b/src/Internal/ProcessConstraints.purs index dab93d21c7..ad5d1eeed2 100644 --- a/src/Internal/ProcessConstraints.purs +++ b/src/Internal/ProcessConstraints.purs @@ -907,7 +907,7 @@ mkUnbalancedTxImpl scriptLookups txConstraints = runConstraintsM scriptLookups txConstraints <#> map \{ transaction, datums, redeemers, usedUtxos } -> wrap - { transaction: stripDatumsRedeemers $ stripScriptDataHash transaction + { transaction: stripRedeemers $ stripScriptDataHash transaction , datums , redeemers , usedUtxos @@ -917,7 +917,7 @@ mkUnbalancedTxImpl scriptLookups txConstraints = stripScriptDataHash = _body <<< _scriptDataHash .~ Nothing - stripDatumsRedeemers :: Transaction -> Transaction - stripDatumsRedeemers = _witnessSet %~ + stripRedeemers :: Transaction -> Transaction + stripRedeemers = _witnessSet %~ over TransactionWitnessSet - _ { plutusData = [], redeemers = [] } + _ { redeemers = [] } From 94bc85cae893473b06751ed99eaf02a9c3cc1159 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Tue, 28 May 2024 17:47:28 +0400 Subject: [PATCH 10/52] Remove datums from UnbalancedTx --- src/Internal/ProcessConstraints.purs | 3 +-- src/Internal/ProcessConstraints/UnbalancedTx.purs | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Internal/ProcessConstraints.purs b/src/Internal/ProcessConstraints.purs index ad5d1eeed2..0e12ded53b 100644 --- a/src/Internal/ProcessConstraints.purs +++ b/src/Internal/ProcessConstraints.purs @@ -905,10 +905,9 @@ mkUnbalancedTxImpl -> Contract (Either MkUnbalancedTxError UnbalancedTx) mkUnbalancedTxImpl scriptLookups txConstraints = runConstraintsM scriptLookups txConstraints <#> map - \{ transaction, datums, redeemers, usedUtxos } -> + \{ transaction, redeemers, usedUtxos } -> wrap { transaction: stripRedeemers $ stripScriptDataHash transaction - , datums , redeemers , usedUtxos } diff --git a/src/Internal/ProcessConstraints/UnbalancedTx.purs b/src/Internal/ProcessConstraints/UnbalancedTx.purs index deee552482..c90c3d626c 100644 --- a/src/Internal/ProcessConstraints/UnbalancedTx.purs +++ b/src/Internal/ProcessConstraints/UnbalancedTx.purs @@ -4,7 +4,6 @@ module Ctl.Internal.ProcessConstraints.UnbalancedTx import Prelude hiding (join) -import Cardano.Types.PlutusData (PlutusData) import Cardano.Types.Transaction (Transaction) import Cardano.Types.TransactionInput (TransactionInput) import Cardano.Types.TransactionOutput (TransactionOutput) @@ -19,8 +18,6 @@ import Data.Show.Generic (genericShow) newtype UnbalancedTx = UnbalancedTx { transaction :: Transaction -- the unbalanced tx created , usedUtxos :: Map TransactionInput TransactionOutput - , datums :: - Array PlutusData -- the array of ordered datums that require attaching , redeemers :: Array UnindexedRedeemer } From b3c753b14bfaf703a4b4ee44b37d7c6a8147b6ee Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Mon, 3 Jun 2024 20:24:27 +0300 Subject: [PATCH 11/52] Add Intersect to funding acknowledgements --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8b14c7907d..eec34028f3 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ CTL is being developed by MLabs. The following companies/funds have contributed - [Catalyst Fund8](https://cardano.ideascale.com/c/idea/396607) - [Catalyst Fund9](https://cardano.ideascale.com/c/idea/420791) - [Catalyst Fund10](https://cardano.ideascale.com/c/idea/101478) +- [Intersect MBO](https://docs.intersectmbo.org/intersect-community-grants/grant-projects) - [MLabs](https://mlabs.city/) - [Indigo Protocol](https://indigoprotocol.io/) - [Equine](https://www.equine.gg/) From fabc6619ee72459561f96bf4a4db60dd40ada50d Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Mon, 3 Jun 2024 20:27:50 +0300 Subject: [PATCH 12/52] Add fourierlabs to acknowledgements --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index eec34028f3..ea7377c6f2 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ You can find help, more information and ongoing discusion about the project here ## Funding acknowledgements -CTL is being developed by MLabs. The following companies/funds have contributed significant resources to development: +CTL is being developed by MLabs. The following companies/funds have contributed significant resources (development time or funding) to development: - [IOHK](https://iohk.io/en/about/) - [Catalyst Fund8](https://cardano.ideascale.com/c/idea/396607) @@ -89,6 +89,7 @@ CTL is being developed by MLabs. The following companies/funds have contributed - [Equine](https://www.equine.gg/) - [Liqwid Labs](https://liqwid.finance/) - [PlayerMint](https://www.playermint.com/) +- [Fourier Labs](https://fourierlabs.io/) - Ardana ## Use in production From bff8bf9c0247c32d931fc0c18ec5fab909e18e8e Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Mon, 3 Jun 2024 20:29:08 +0300 Subject: [PATCH 13/52] Update: README.md wording --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ea7377c6f2..a4ded1dce8 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ You can find help, more information and ongoing discusion about the project here ## Funding acknowledgements -CTL is being developed by MLabs. The following companies/funds have contributed significant resources (development time or funding) to development: +CTL is being developed by MLabs. The following companies/funds have contributed significant resources (development time or funding): - [IOHK](https://iohk.io/en/about/) - [Catalyst Fund8](https://cardano.ideascale.com/c/idea/396607) From 69b59bb7f01cd6e0dafb078ad89c22ff9cda88d5 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Thu, 13 Jun 2024 19:29:54 +0400 Subject: [PATCH 14/52] Update @mlabs-haskell/uplc-apply-args version --- package-lock.json | 62 ++++++++++++------------ package.json | 2 +- templates/ctl-scaffold/package-lock.json | 62 ++++++++++++------------ templates/ctl-scaffold/package.json | 2 +- 4 files changed, 64 insertions(+), 64 deletions(-) diff --git a/package-lock.json b/package-lock.json index 962c3453ec..7732cd60b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@mlabs-haskell/cardano-message-signing": "^1.0.1", "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", "@mlabs-haskell/json-bigint": "2.0.0", - "@mlabs-haskell/uplc-apply-args": "1.0.0", + "@mlabs-haskell/uplc-apply-args": "2.0.0", "@noble/secp256k1": "^1.7.0", "base64-js": "^1.5.1", "bignumber.js": "^9.1.1", @@ -521,14 +521,24 @@ "integrity": "sha512-JX9TON+nZbt+1TJ5MNV1Gcpxp3/m56x1/glDwzGtydrzQzyZbKg4XFw9Frib6fh89YVqjSFJ9xmVeIyDJ5DxTQ==" }, "node_modules/@mlabs-haskell/uplc-apply-args": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-1.0.0.tgz", - "integrity": "sha512-jygKgElPSmrjBifiec8lLAjcKAPDOvDTv0hCW6jfX+/hnlaI8p9w5amv6jeCMmnr3/ncRzE9JrcuVJoB5lBwLA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-2.0.0.tgz", + "integrity": "sha512-EAm/VsD29/4B16q7c32G1C00RHKhpL3R6XQOpw7Bek92/X+jNoTeY1I9zrWi3FPk6/f5MRwW6R9QfN4ZMTNBjA==", "dependencies": { - "apply-args-browser": "^0.0.1", - "apply-args-nodejs": "^0.0.1" + "@mlabs-haskell/uplc-apply-args-browser": "^0.0.3", + "@mlabs-haskell/uplc-apply-args-nodejs": "^0.0.3" } }, + "node_modules/@mlabs-haskell/uplc-apply-args-browser": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-browser/-/uplc-apply-args-browser-0.0.3.tgz", + "integrity": "sha512-U2GFMN2Q2KLwTKjrwDXcOBznIvib3Jvdg79xmXDx3/L94PGoBfLN9bBByfVTwKP+ETRfJgRXwi5xxctwKXvT+g==" + }, + "node_modules/@mlabs-haskell/uplc-apply-args-nodejs": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-nodejs/-/uplc-apply-args-nodejs-0.0.3.tgz", + "integrity": "sha512-0uLz+67U1yiXvt3qu/7NBd0WK6LWXf9XteaInQk56RqRbxi4WKA/1Rm73VuciZzLWohXMDNbVNCiirmXi6k+9A==" + }, "node_modules/@noble/hashes": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", @@ -1148,16 +1158,6 @@ "node": ">= 8" } }, - "node_modules/apply-args-browser": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/apply-args-browser/-/apply-args-browser-0.0.1.tgz", - "integrity": "sha512-gq4ldo4Fk5SEVpeW/0yBe0v5g3VDEWAm9LB80zGarYtDvojTD7ar0Y/WvIy9gYAkKmlE3USu5wYwKKCqOXfNkg==" - }, - "node_modules/apply-args-nodejs": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/apply-args-nodejs/-/apply-args-nodejs-0.0.1.tgz", - "integrity": "sha512-JwZPEvEDrL+4y16Un6FcNjDSITpsBykchgwPh8UtxnziYrbxKAc2BUfyC5uvA6ZVIhQjiO4r+Kg1MQ3nqWk+1Q==" - }, "node_modules/array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -6645,14 +6645,24 @@ "integrity": "sha512-JX9TON+nZbt+1TJ5MNV1Gcpxp3/m56x1/glDwzGtydrzQzyZbKg4XFw9Frib6fh89YVqjSFJ9xmVeIyDJ5DxTQ==" }, "@mlabs-haskell/uplc-apply-args": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-1.0.0.tgz", - "integrity": "sha512-jygKgElPSmrjBifiec8lLAjcKAPDOvDTv0hCW6jfX+/hnlaI8p9w5amv6jeCMmnr3/ncRzE9JrcuVJoB5lBwLA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-2.0.0.tgz", + "integrity": "sha512-EAm/VsD29/4B16q7c32G1C00RHKhpL3R6XQOpw7Bek92/X+jNoTeY1I9zrWi3FPk6/f5MRwW6R9QfN4ZMTNBjA==", "requires": { - "apply-args-browser": "^0.0.1", - "apply-args-nodejs": "^0.0.1" + "@mlabs-haskell/uplc-apply-args-browser": "^0.0.3", + "@mlabs-haskell/uplc-apply-args-nodejs": "^0.0.3" } }, + "@mlabs-haskell/uplc-apply-args-browser": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-browser/-/uplc-apply-args-browser-0.0.3.tgz", + "integrity": "sha512-U2GFMN2Q2KLwTKjrwDXcOBznIvib3Jvdg79xmXDx3/L94PGoBfLN9bBByfVTwKP+ETRfJgRXwi5xxctwKXvT+g==" + }, + "@mlabs-haskell/uplc-apply-args-nodejs": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-nodejs/-/uplc-apply-args-nodejs-0.0.3.tgz", + "integrity": "sha512-0uLz+67U1yiXvt3qu/7NBd0WK6LWXf9XteaInQk56RqRbxi4WKA/1Rm73VuciZzLWohXMDNbVNCiirmXi6k+9A==" + }, "@noble/hashes": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", @@ -7195,16 +7205,6 @@ "picomatch": "^2.0.4" } }, - "apply-args-browser": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/apply-args-browser/-/apply-args-browser-0.0.1.tgz", - "integrity": "sha512-gq4ldo4Fk5SEVpeW/0yBe0v5g3VDEWAm9LB80zGarYtDvojTD7ar0Y/WvIy9gYAkKmlE3USu5wYwKKCqOXfNkg==" - }, - "apply-args-nodejs": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/apply-args-nodejs/-/apply-args-nodejs-0.0.1.tgz", - "integrity": "sha512-JwZPEvEDrL+4y16Un6FcNjDSITpsBykchgwPh8UtxnziYrbxKAc2BUfyC5uvA6ZVIhQjiO4r+Kg1MQ3nqWk+1Q==" - }, "array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", diff --git a/package.json b/package.json index f7b5ed7cad..84970282d7 100755 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@mlabs-haskell/cardano-message-signing": "^1.0.1", "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", "@mlabs-haskell/json-bigint": "2.0.0", - "@mlabs-haskell/uplc-apply-args": "1.0.0", + "@mlabs-haskell/uplc-apply-args": "2.0.0", "@noble/secp256k1": "^1.7.0", "base64-js": "^1.5.1", "bignumber.js": "^9.1.1", diff --git a/templates/ctl-scaffold/package-lock.json b/templates/ctl-scaffold/package-lock.json index aa87d088ad..b8720387b4 100644 --- a/templates/ctl-scaffold/package-lock.json +++ b/templates/ctl-scaffold/package-lock.json @@ -12,7 +12,7 @@ "@mlabs-haskell/cardano-message-signing": "^1.0.1", "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", "@mlabs-haskell/json-bigint": "2.0.0", - "@mlabs-haskell/uplc-apply-args": "1.0.0", + "@mlabs-haskell/uplc-apply-args": "2.0.0", "@noble/secp256k1": "^1.7.0", "base64-js": "^1.5.1", "bignumber.js": "^9.1.1", @@ -519,14 +519,24 @@ "integrity": "sha512-JX9TON+nZbt+1TJ5MNV1Gcpxp3/m56x1/glDwzGtydrzQzyZbKg4XFw9Frib6fh89YVqjSFJ9xmVeIyDJ5DxTQ==" }, "node_modules/@mlabs-haskell/uplc-apply-args": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-1.0.0.tgz", - "integrity": "sha512-jygKgElPSmrjBifiec8lLAjcKAPDOvDTv0hCW6jfX+/hnlaI8p9w5amv6jeCMmnr3/ncRzE9JrcuVJoB5lBwLA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-2.0.0.tgz", + "integrity": "sha512-EAm/VsD29/4B16q7c32G1C00RHKhpL3R6XQOpw7Bek92/X+jNoTeY1I9zrWi3FPk6/f5MRwW6R9QfN4ZMTNBjA==", "dependencies": { - "apply-args-browser": "^0.0.1", - "apply-args-nodejs": "^0.0.1" + "@mlabs-haskell/uplc-apply-args-browser": "^0.0.3", + "@mlabs-haskell/uplc-apply-args-nodejs": "^0.0.3" } }, + "node_modules/@mlabs-haskell/uplc-apply-args-browser": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-browser/-/uplc-apply-args-browser-0.0.3.tgz", + "integrity": "sha512-U2GFMN2Q2KLwTKjrwDXcOBznIvib3Jvdg79xmXDx3/L94PGoBfLN9bBByfVTwKP+ETRfJgRXwi5xxctwKXvT+g==" + }, + "node_modules/@mlabs-haskell/uplc-apply-args-nodejs": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-nodejs/-/uplc-apply-args-nodejs-0.0.3.tgz", + "integrity": "sha512-0uLz+67U1yiXvt3qu/7NBd0WK6LWXf9XteaInQk56RqRbxi4WKA/1Rm73VuciZzLWohXMDNbVNCiirmXi6k+9A==" + }, "node_modules/@noble/hashes": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", @@ -1099,16 +1109,6 @@ "node": ">= 8" } }, - "node_modules/apply-args-browser": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/apply-args-browser/-/apply-args-browser-0.0.1.tgz", - "integrity": "sha512-gq4ldo4Fk5SEVpeW/0yBe0v5g3VDEWAm9LB80zGarYtDvojTD7ar0Y/WvIy9gYAkKmlE3USu5wYwKKCqOXfNkg==" - }, - "node_modules/apply-args-nodejs": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/apply-args-nodejs/-/apply-args-nodejs-0.0.1.tgz", - "integrity": "sha512-JwZPEvEDrL+4y16Un6FcNjDSITpsBykchgwPh8UtxnziYrbxKAc2BUfyC5uvA6ZVIhQjiO4r+Kg1MQ3nqWk+1Q==" - }, "node_modules/array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -5772,14 +5772,24 @@ "integrity": "sha512-JX9TON+nZbt+1TJ5MNV1Gcpxp3/m56x1/glDwzGtydrzQzyZbKg4XFw9Frib6fh89YVqjSFJ9xmVeIyDJ5DxTQ==" }, "@mlabs-haskell/uplc-apply-args": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-1.0.0.tgz", - "integrity": "sha512-jygKgElPSmrjBifiec8lLAjcKAPDOvDTv0hCW6jfX+/hnlaI8p9w5amv6jeCMmnr3/ncRzE9JrcuVJoB5lBwLA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-2.0.0.tgz", + "integrity": "sha512-EAm/VsD29/4B16q7c32G1C00RHKhpL3R6XQOpw7Bek92/X+jNoTeY1I9zrWi3FPk6/f5MRwW6R9QfN4ZMTNBjA==", "requires": { - "apply-args-browser": "^0.0.1", - "apply-args-nodejs": "^0.0.1" + "@mlabs-haskell/uplc-apply-args-browser": "^0.0.3", + "@mlabs-haskell/uplc-apply-args-nodejs": "^0.0.3" } }, + "@mlabs-haskell/uplc-apply-args-browser": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-browser/-/uplc-apply-args-browser-0.0.3.tgz", + "integrity": "sha512-U2GFMN2Q2KLwTKjrwDXcOBznIvib3Jvdg79xmXDx3/L94PGoBfLN9bBByfVTwKP+ETRfJgRXwi5xxctwKXvT+g==" + }, + "@mlabs-haskell/uplc-apply-args-nodejs": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-nodejs/-/uplc-apply-args-nodejs-0.0.3.tgz", + "integrity": "sha512-0uLz+67U1yiXvt3qu/7NBd0WK6LWXf9XteaInQk56RqRbxi4WKA/1Rm73VuciZzLWohXMDNbVNCiirmXi6k+9A==" + }, "@noble/hashes": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", @@ -6275,16 +6285,6 @@ "picomatch": "^2.0.4" } }, - "apply-args-browser": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/apply-args-browser/-/apply-args-browser-0.0.1.tgz", - "integrity": "sha512-gq4ldo4Fk5SEVpeW/0yBe0v5g3VDEWAm9LB80zGarYtDvojTD7ar0Y/WvIy9gYAkKmlE3USu5wYwKKCqOXfNkg==" - }, - "apply-args-nodejs": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/apply-args-nodejs/-/apply-args-nodejs-0.0.1.tgz", - "integrity": "sha512-JwZPEvEDrL+4y16Un6FcNjDSITpsBykchgwPh8UtxnziYrbxKAc2BUfyC5uvA6ZVIhQjiO4r+Kg1MQ3nqWk+1Q==" - }, "array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", diff --git a/templates/ctl-scaffold/package.json b/templates/ctl-scaffold/package.json index c1325f4fe6..6b85c768aa 100644 --- a/templates/ctl-scaffold/package.json +++ b/templates/ctl-scaffold/package.json @@ -28,7 +28,7 @@ "@mlabs-haskell/cardano-message-signing": "^1.0.1", "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", "@mlabs-haskell/json-bigint": "2.0.0", - "@mlabs-haskell/uplc-apply-args": "1.0.0", + "@mlabs-haskell/uplc-apply-args": "2.0.0", "@noble/secp256k1": "^1.7.0", "base64-js": "^1.5.1", "bignumber.js": "^9.1.1", From a9ebef4b1c1b5d3cb0b9bff7646bcf4fde02b420 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Thu, 13 Jun 2024 19:57:04 +0400 Subject: [PATCH 15/52] Update the dependencies (once more) --- package-lock.json | 14 +++++++------- package.json | 2 +- templates/ctl-scaffold/package-lock.json | 14 +++++++------- templates/ctl-scaffold/package.json | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7732cd60b6..a9845f2b0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@mlabs-haskell/cardano-message-signing": "^1.0.1", "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", "@mlabs-haskell/json-bigint": "2.0.0", - "@mlabs-haskell/uplc-apply-args": "2.0.0", + "@mlabs-haskell/uplc-apply-args": "2.0.1", "@noble/secp256k1": "^1.7.0", "base64-js": "^1.5.1", "bignumber.js": "^9.1.1", @@ -521,9 +521,9 @@ "integrity": "sha512-JX9TON+nZbt+1TJ5MNV1Gcpxp3/m56x1/glDwzGtydrzQzyZbKg4XFw9Frib6fh89YVqjSFJ9xmVeIyDJ5DxTQ==" }, "node_modules/@mlabs-haskell/uplc-apply-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-2.0.0.tgz", - "integrity": "sha512-EAm/VsD29/4B16q7c32G1C00RHKhpL3R6XQOpw7Bek92/X+jNoTeY1I9zrWi3FPk6/f5MRwW6R9QfN4ZMTNBjA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-2.0.1.tgz", + "integrity": "sha512-of0zlgBEk9vpTBFISDHADoYRzfbw84MQBMnGCXFhdSvdOIWsoGV4kvQJBdufYYh8BJNSyy0MLJ9uX7ARr7reig==", "dependencies": { "@mlabs-haskell/uplc-apply-args-browser": "^0.0.3", "@mlabs-haskell/uplc-apply-args-nodejs": "^0.0.3" @@ -6645,9 +6645,9 @@ "integrity": "sha512-JX9TON+nZbt+1TJ5MNV1Gcpxp3/m56x1/glDwzGtydrzQzyZbKg4XFw9Frib6fh89YVqjSFJ9xmVeIyDJ5DxTQ==" }, "@mlabs-haskell/uplc-apply-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-2.0.0.tgz", - "integrity": "sha512-EAm/VsD29/4B16q7c32G1C00RHKhpL3R6XQOpw7Bek92/X+jNoTeY1I9zrWi3FPk6/f5MRwW6R9QfN4ZMTNBjA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-2.0.1.tgz", + "integrity": "sha512-of0zlgBEk9vpTBFISDHADoYRzfbw84MQBMnGCXFhdSvdOIWsoGV4kvQJBdufYYh8BJNSyy0MLJ9uX7ARr7reig==", "requires": { "@mlabs-haskell/uplc-apply-args-browser": "^0.0.3", "@mlabs-haskell/uplc-apply-args-nodejs": "^0.0.3" diff --git a/package.json b/package.json index 84970282d7..4cb9d98924 100755 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@mlabs-haskell/cardano-message-signing": "^1.0.1", "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", "@mlabs-haskell/json-bigint": "2.0.0", - "@mlabs-haskell/uplc-apply-args": "2.0.0", + "@mlabs-haskell/uplc-apply-args": "2.0.1", "@noble/secp256k1": "^1.7.0", "base64-js": "^1.5.1", "bignumber.js": "^9.1.1", diff --git a/templates/ctl-scaffold/package-lock.json b/templates/ctl-scaffold/package-lock.json index b8720387b4..561dc93e3a 100644 --- a/templates/ctl-scaffold/package-lock.json +++ b/templates/ctl-scaffold/package-lock.json @@ -12,7 +12,7 @@ "@mlabs-haskell/cardano-message-signing": "^1.0.1", "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", "@mlabs-haskell/json-bigint": "2.0.0", - "@mlabs-haskell/uplc-apply-args": "2.0.0", + "@mlabs-haskell/uplc-apply-args": "2.0.1", "@noble/secp256k1": "^1.7.0", "base64-js": "^1.5.1", "bignumber.js": "^9.1.1", @@ -519,9 +519,9 @@ "integrity": "sha512-JX9TON+nZbt+1TJ5MNV1Gcpxp3/m56x1/glDwzGtydrzQzyZbKg4XFw9Frib6fh89YVqjSFJ9xmVeIyDJ5DxTQ==" }, "node_modules/@mlabs-haskell/uplc-apply-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-2.0.0.tgz", - "integrity": "sha512-EAm/VsD29/4B16q7c32G1C00RHKhpL3R6XQOpw7Bek92/X+jNoTeY1I9zrWi3FPk6/f5MRwW6R9QfN4ZMTNBjA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-2.0.1.tgz", + "integrity": "sha512-of0zlgBEk9vpTBFISDHADoYRzfbw84MQBMnGCXFhdSvdOIWsoGV4kvQJBdufYYh8BJNSyy0MLJ9uX7ARr7reig==", "dependencies": { "@mlabs-haskell/uplc-apply-args-browser": "^0.0.3", "@mlabs-haskell/uplc-apply-args-nodejs": "^0.0.3" @@ -5772,9 +5772,9 @@ "integrity": "sha512-JX9TON+nZbt+1TJ5MNV1Gcpxp3/m56x1/glDwzGtydrzQzyZbKg4XFw9Frib6fh89YVqjSFJ9xmVeIyDJ5DxTQ==" }, "@mlabs-haskell/uplc-apply-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-2.0.0.tgz", - "integrity": "sha512-EAm/VsD29/4B16q7c32G1C00RHKhpL3R6XQOpw7Bek92/X+jNoTeY1I9zrWi3FPk6/f5MRwW6R9QfN4ZMTNBjA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-2.0.1.tgz", + "integrity": "sha512-of0zlgBEk9vpTBFISDHADoYRzfbw84MQBMnGCXFhdSvdOIWsoGV4kvQJBdufYYh8BJNSyy0MLJ9uX7ARr7reig==", "requires": { "@mlabs-haskell/uplc-apply-args-browser": "^0.0.3", "@mlabs-haskell/uplc-apply-args-nodejs": "^0.0.3" diff --git a/templates/ctl-scaffold/package.json b/templates/ctl-scaffold/package.json index 6b85c768aa..f34f4d9e34 100644 --- a/templates/ctl-scaffold/package.json +++ b/templates/ctl-scaffold/package.json @@ -28,7 +28,7 @@ "@mlabs-haskell/cardano-message-signing": "^1.0.1", "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", "@mlabs-haskell/json-bigint": "2.0.0", - "@mlabs-haskell/uplc-apply-args": "2.0.0", + "@mlabs-haskell/uplc-apply-args": "2.0.1", "@noble/secp256k1": "^1.7.0", "base64-js": "^1.5.1", "bignumber.js": "^9.1.1", From 5bf278436b46d910ae4339add6942bf362ef4a82 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Fri, 21 Jun 2024 18:03:12 +0300 Subject: [PATCH 16/52] Update comparisons.md --- doc/comparisons.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/comparisons.md b/doc/comparisons.md index 25311bd304..504ad2ca12 100644 --- a/doc/comparisons.md +++ b/doc/comparisons.md @@ -79,5 +79,6 @@ Additionally, CTL supports [testing with real wallets](./e2e-testing.md) via hea Lucid aims for simplicity, while CTL allows more fine-grained control over transaction building process without losing the benefits of declarativeness. -- CTL uses [`cardano-serialization-lib`](https://github.com/Emurgo/cardano-serialization-lib/), while Lucid uses a fork of [`cardano-multiplatform-lib`](https://github.com/berry-pool/cardano-multiplatform-lib). Lucid allows to use CML's `TxBuilder` or [call CML directly](https://lucid.spacebudz.io/docs/advanced/cml/), while CTL allows to alter the transaction arbitrarily as PureScript data type either before or after balancing. In CTL, CSL types and method wrappers are a part of the internal interface, but technically they can be used as well. +- CTL uses [`cardano-serialization-lib`](https://github.com/Emurgo/cardano-serialization-lib/), while Lucid uses a fork of [`cardano-multiplatform-lib`](https://github.com/berry-pool/cardano-multiplatform-lib). Lucid allows to use CML's `TxBuilder` or [call CML directly](https://lucid.spacebudz.io/docs/advanced/cml/), while CTL allows to alter the transaction arbitrarily as PureScript data type either before or after balancing. +- In CTL, CSL types and method wrappers are used via [`purescript-cardano-serialization-lib`](https://github.com/mlabs-haskell/purescript-cardano-serialization-lib) and [`purescript-cardano-types`](https://github.com/mlabs-haskell/purescript-cardano-types). However, `TxBuilder` APIs from CSL are not provided by these packages. - Plutus Data conversion is handled via a [schema-enabled API](https://lucid.spacebudz.io/docs/advanced/type-casting/) in Lucid. CTL allows for automatic `ToData` / `FromData` deriving for some types, via `HasPlutusSchema`. From 49bf3c4b124bc8cf3463dd5c57d5ddbda6ae33ae Mon Sep 17 00:00:00 2001 From: Marcus Fernandes Date: Wed, 26 Jun 2024 09:49:52 -0300 Subject: [PATCH 17/52] Remove `Contract.Scripts.applyArgs` and add `purescript-uplc-apply-args` dependency --- CHANGELOG.md | 14 +- examples/ByUrl.purs | 2 - examples/OneShotMinting.purs | 3 +- flake.nix | 9 +- packages.dhall | 25 ++ spago-packages.nix | 13 + spago.dhall | 1 + src/Contract/Scripts.purs | 1 - src/Internal/ApplyArgs.js | 32 -- src/Internal/ApplyArgs.purs | 31 -- templates/ctl-scaffold/package-lock.json | 39 --- templates/ctl-scaffold/package.json | 1 - test/ApplyArgs.purs | 380 ----------------------- test/Plutip/Contract.purs | 2 +- test/Unit.purs | 2 - 15 files changed, 57 insertions(+), 498 deletions(-) delete mode 100644 src/Internal/ApplyArgs.js delete mode 100644 src/Internal/ApplyArgs.purs delete mode 100644 test/ApplyArgs.purs diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b5ae290e8..3e8bbf623b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,6 +73,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Removed +- `Contract.Scripts.applyArgs` - use `Cardano.Plutus.ApplyArgs.applyArgs` from [purescript-uplc-apply-args](https://github.com/mlabs-haskell/purescript-uplc-apply-args) + ### Changed ### Fixed @@ -409,7 +411,7 @@ Then consult with [the template's build scripts](./templates/ctl-scaffold/esbuil - `startPlutipCluster` error message now includes cluster startup failure details. ([#1407](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1407)) - `PlutipTest` is now known as `Contract.Test.ContractTest`. It has been semantically untied from Plutip, because we now have another test runner for tests that rely on particular funds distributions - [Blockfrost](./doc/blockfrost.md). See `Contract.Test.Blockfrost.runContractTestsWithBlockfrost` ([#1260](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1260)) - `Contract.Staking.getPoolParameters` has been moved to `Contract.Backend.Ogmios.getPoolParameters`. This function only runs with Ogmios backend, because Blockfrost [does not provide](https://github.com/blockfrost/blockfrost-backend-ryo/issues/82) all the required values ([#1260](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1260)) -- Use of [CIP-40](https://cips.cardano.org/cip/CIP-0040/) collateral output is now enabled with CIP-30 wallets ([#1260](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1260)). +- Use of [CIP-40](https://chips.cardano.org/cip/CIP-0040/) collateral output is now enabled with CIP-30 wallets ([#1260](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1260)). - `reindexSpentScriptRedeemers` is no longer in Contract (it's pure) ([#1260](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1260)) ### Removed @@ -466,7 +468,7 @@ Then consult with [the template's build scripts](./templates/ctl-scaffold/esbuil ### Fixed -- Added missing `stakePoolTargetNum` ("`nOpt`") protocol parameter (see [CIP-9](https://cips.cardano.org/cip/CIP-0009)) ([#571](https://github.com/Plutonomicon/cardano-transaction-lib/issues/571)) +- Added missing `stakePoolTargetNum` ("`nOpt`") protocol parameter (see [CIP-9](https://chips.cardano.org/cip/CIP-0009)) ([#571](https://github.com/Plutonomicon/cardano-transaction-lib/issues/571)) - CIP-30 `signData` response handling ([#1289](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1289)) ### Runtime Dependencies @@ -481,7 +483,7 @@ Then consult with [the template's build scripts](./templates/ctl-scaffold/esbuil ### Added -- Support passing the inital UTxO distribution as an Array and also get the KeyWallets as an Array when writing Plutip tests. ([#1018](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1018)). An usage example can be found [here](doc/plutip-testing.md). +- Support passing the initial UTxO distribution as an Array and also get the KeyWallets as an Array when writing Plutip tests. ([#1018](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1018)). An usage example can be found [here](doc/plutip-testing.md). - New `Contract.Test.Utils` assertions and checks: `assertOutputHasRefScript`, `checkOutputHasRefScript`, `checkTxHasMetadata` ([#1044](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1044)) - `Parallel` instance to `Contract` monad. Parallel capabilities are in the associated `ParContract` datatype ([#1037](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1037)) - Balancer constraints interface (check [Building and submitting transactions](https://github.com/Plutonomicon/cardano-transaction-lib/blob/95bdd213eff16a5e00df82fb27bbe2479e8b4196/doc/getting-started.md#building-and-submitting-transactions) and `examples/BalanceTxConstraints.purs` for reference) ([#1053](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1053)) @@ -533,7 +535,7 @@ Then consult with [the template's build scripts](./templates/ctl-scaffold/esbuil - Adapted Gero wallet extension to `preview` network in E2E test suite ([#1086](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1086)) - `Contact.TextEnvelope` how provides more type safe interface with simplified error handling ([#988](https://github.com/Plutonomicon/cardano-transaction-lib/issues/988)) - Forbid minting zero tokens. ([#1156](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1156)) -- Modified functions `getWalletAddress`, `ownPubKeyHash`, `ownStakePubKeyHash`, `getWalletAddressWithNetworkTag` and `ownPaymentPubKeyHash` to return `Contract r (Array Adress)`. ([#1045](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1045)) +- Modified functions `getWalletAddress`, `ownPubKeyHash`, `ownStakePubKeyHash`, `getWalletAddressWithNetworkTag` and `ownPaymentPubKeyHash` to return `Contract r (Array Address)`. ([#1045](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1045)) - `pubKeyHashAddress` and `scriptHashAddress` now both accept an optional `Credential` that corresponds to the staking component of the address ([#1060](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1060)) - `utxosAt` and `getUtxo` now use Kupo internally, `utxosAt` returns `UtxoMap` without `Maybe` context. The users will need to set `kupoConfig` in `ConfigParams`. ([#1185](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1185)) - `Interval` type is redesigned to restrain some finite intervals to be expressed in the system ([#1041](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1041)) @@ -621,7 +623,7 @@ Then consult with [the template's build scripts](./templates/ctl-scaffold/esbuil - Constraint for attaching a reference input to a transaction: `mustReferenceOutput` ([#946](https://github.com/Plutonomicon/cardano-transaction-lib/pull/946)) - `DatumPresence` data type, which tags paying constraints that accept datum, to mark whether the datum should be inline or hashed in the transaction output. ([#931](https://github.com/Plutonomicon/cardano-transaction-lib/pull/931)) - Utility conversion functions `serializeData` and `deserializeData` between `PlutusData` and `CborBytes` to `Contract.PlutusData`. ([#1001](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1001)) -- Added [CIP-30](https://cips.cardano.org/cip/CIP-0030) methods: `getNetworkId`, `getChangeAddress`, `getRewardAddresses`, `getUnusedAddresses`, `signData`, `isWalletAvailable`, `isEnabled`, `apiVersion`, `name` and `icon` to `Contract.Wallet` ([#974](https://github.com/Plutonomicon/cardano-transaction-lib/issues/974)) +- Added [CIP-30](https://chips.cardano.org/cip/CIP-0030) methods: `getNetworkId`, `getChangeAddress`, `getRewardAddresses`, `getUnusedAddresses`, `signData`, `isWalletAvailable`, `isEnabled`, `apiVersion`, `name` and `icon` to `Contract.Wallet` ([#974](https://github.com/Plutonomicon/cardano-transaction-lib/issues/974)) ### Changed @@ -674,7 +676,7 @@ Then consult with [the template's build scripts](./templates/ctl-scaffold/esbuil - We do not split strings in pieces when encoding to JSON - We require a `"version": 2` tag - `policy_id` must be 28 bytes - - `asset_name` is up to 32 bytes. See https://github.com/cardano-foundation/CIPs/issues/303 for motivation + - `asset_name` is up to 32 bytes. See https://github.com/cardano-foundation/chips/issues/303 for motivation - `ogmios-datum-cache` now works on `x86_64-darwin` - `TypedValidator` interface ([#808](https://github.com/Plutonomicon/cardano-transaction-lib/issues/808)) - `Contract.Address.getWalletCollateral` now works with `KeyWallet`. diff --git a/examples/ByUrl.purs b/examples/ByUrl.purs index 3119dff8d5..f13fcd5e52 100644 --- a/examples/ByUrl.purs +++ b/examples/ByUrl.purs @@ -67,7 +67,6 @@ import Data.Time.Duration (Seconds(Seconds)) import Data.Tuple.Nested (type (/\), (/\)) import Effect (Effect) import Effect.Console as Console -import Test.Ctl.ApplyArgs as ApplyArgs import Web.HTML (window) import Web.HTML.Window (localStorage) import Web.Storage.Storage (getItem) @@ -217,7 +216,6 @@ examples = addSuccessLog <$> Map.fromFoldable , "ReferenceInputs" /\ ReferenceInputsV2.contract , "ReferenceInputsAndScripts" /\ ReferenceInputsAndScriptsV2.contract , "Utxos" /\ Utxos.contract - , "ApplyArgs" /\ ApplyArgs.contract , "Schnorr" /\ Schnorr.contract , "ECDSA" /\ ECDSA.contract , "PaysWithDatum" /\ PaysWithDatum.contract diff --git a/examples/OneShotMinting.purs b/examples/OneShotMinting.purs index 0ed28bc989..3b8a83485a 100644 --- a/examples/OneShotMinting.purs +++ b/examples/OneShotMinting.purs @@ -12,6 +12,7 @@ module Ctl.Examples.OneShotMinting import Contract.Prelude +import Cardano.Plutus.ApplyArgs (applyArgs) import Cardano.Types.BigNum as BigNum import Cardano.Types.Int as Int import Cardano.Types.Mint as Mint @@ -28,7 +29,7 @@ import Contract.Monad ) import Contract.PlutusData (PlutusData, toData) import Contract.ScriptLookups as Lookups -import Contract.Scripts (PlutusScript, applyArgs) +import Contract.Scripts (PlutusScript) import Contract.Test.Assert ( ContractCheck , checkLossInWallet diff --git a/flake.nix b/flake.nix index 8869b614cd..2bae547d0a 100644 --- a/flake.nix +++ b/flake.nix @@ -391,7 +391,10 @@ nativeBuildInputs = [ pkgs.jq ]; } '' cd ${self} - diff <(jq -S .dependencies <<< $ctlPackageJson) <(jq -S .dependencies <<< $ctlScaffoldPackageJson) + # We don't want to include `uplc-apply-args` in the template dependencies. + diff \ + <(jq -S '.dependencies | del(."@mlabs-haskell/uplc-apply-args")' <<< $ctlPackageJson) \ + <(jq -S .dependencies <<< $ctlScaffoldPackageJson) # We don't want to include `doctoc` in the template dev dependencies. diff \ <(jq -S '.devDependencies | del(.jssha) | del(.blakejs) | del(.doctoc)' <<< $ctlPackageJson) \ @@ -403,7 +406,9 @@ let ctlPkgsExp = import ./spago-packages.nix { inherit pkgs; }; ctlScaffoldPkgsExp = import ./templates/ctl-scaffold/spago-packages.nix { inherit pkgs; }; - ctlPs = attrValues ctlPkgsExp.inputs; + # We don't include `uplc-apply-args` in the template dependencies. + ctlPs = filter (p: p.name != "uplc-apply-args") + (attrValues ctlPkgsExp.inputs); ctlScaffoldPs = filter (p: p.name != "cardano-transaction-lib") (attrValues ctlScaffoldPkgsExp.inputs); intersection = pkgs.lib.lists.intersectLists ctlPs ctlScaffoldPs; diff --git a/packages.dhall b/packages.dhall index 459932df51..7506c80e49 100644 --- a/packages.dhall +++ b/packages.dhall @@ -318,6 +318,31 @@ let additions = , repo = "https://github.com/mlabs-haskell/purescript-plutus-types" , version = "v1.0.1" } + , uplc-apply-args = + { dependencies = + [ "aff" + , "bytearrays" + , "cardano-serialization-lib" + , "cardano-types" + , "effect" + , "either" + , "foldable-traversable" + , "foreign-object" + , "js-bigints" + , "lists" + , "maybe" + , "mote" + , "mote-testplan" + , "partial" + , "prelude" + , "profunctor" + , "spec" + , "transformers" + , "tuples" + ] + , repo = "https://github.com/mlabs-haskell/purescript-uplc-apply-args" + , version = "master" + } , cardano-types = { dependencies = [ "aeson" diff --git a/spago-packages.nix b/spago-packages.nix index 081d8d7895..ac4291c950 100644 --- a/spago-packages.nix +++ b/spago-packages.nix @@ -1565,6 +1565,19 @@ let installPhase = "ln -s $src $out"; }; + "uplc-apply-args" = pkgs.stdenv.mkDerivation { + name = "uplc-apply-args"; + version = "master"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-uplc-apply-args.git"; + rev = "aa528d5310cbfbd01b4d94557f404d95cfb6bb3c"; + sha256 = "1r064ca2m16hkbcswrvlng032ax1ygbpr2gxrlaqmjlf2gnin280"; + + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "variant" = pkgs.stdenv.mkDerivation { name = "variant"; version = "v8.0.0"; diff --git a/spago.dhall b/spago.dhall index 3fa172ac8a..957f2487e0 100644 --- a/spago.dhall +++ b/spago.dhall @@ -19,6 +19,7 @@ You can edit this file as you like. , "bytearrays" , "cardano-hd-wallet" , "cardano-message-signing" + , "uplc-apply-args" , "cardano-plutus-data-schema" , "cardano-serialization-lib" , "cardano-types" diff --git a/src/Contract/Scripts.purs b/src/Contract/Scripts.purs index 8133e8fece..4e68d3a082 100644 --- a/src/Contract/Scripts.purs +++ b/src/Contract/Scripts.purs @@ -32,7 +32,6 @@ import Cardano.Types.PlutusScript as PlutusScript import Cardano.Types.ScriptRef (ScriptRef) import Contract.Monad (Contract) import Control.Parallel (parTraverse) -import Ctl.Internal.ApplyArgs (applyArgs) as X import Ctl.Internal.Contract.Monad (getQueryHandle) import Ctl.Internal.Service.Error (ClientError) import Data.Either (Either) diff --git a/src/Internal/ApplyArgs.js b/src/Internal/ApplyArgs.js deleted file mode 100644 index 5866d7bf74..0000000000 --- a/src/Internal/ApplyArgs.js +++ /dev/null @@ -1,32 +0,0 @@ -import * as lib from "@mlabs-haskell/cardano-serialization-lib-gc"; -import * as apply_args from "@mlabs-haskell/uplc-apply-args"; - -/** - * @param {} left - * @param {} right - * @param {PlutusData} args - * @param {PlutusScript} script - * @returns {Either String PlutusScript} - */ -export function apply_params_to_script(left) { - return right => args => script => { - let version = script.language_version(); - let appliedScript; - try { - let scriptBytes = script.bytes(); // raw bytes - let argsBytes = args.to_bytes(); // cbor - - try { - appliedScript = apply_args.apply_params_to_script_no_panic( - argsBytes, - scriptBytes - ); - } catch (e) { - return left("Error applying argument to script: ".concat(e.toString())); - } - } catch (e1) { - return left("Error serializing arguments: ".concat(e1.toString())); - } - return right(lib.PlutusScript.new_with_version(appliedScript, version)); - }; -} diff --git a/src/Internal/ApplyArgs.purs b/src/Internal/ApplyArgs.purs deleted file mode 100644 index 625dddb705..0000000000 --- a/src/Internal/ApplyArgs.purs +++ /dev/null @@ -1,31 +0,0 @@ -module Ctl.Internal.ApplyArgs - ( applyArgs - ) where - -import Prelude - -import Cardano.Serialization.Lib as CSL -import Cardano.Types.PlutusData (PlutusData(List)) -import Cardano.Types.PlutusData as PlutusData -import Cardano.Types.PlutusScript (PlutusScript) -import Cardano.Types.PlutusScript as PlutusScript -import Data.Either (Either(Left, Right)) - -foreign import apply_params_to_script - :: (forall (x :: Type). x -> Either x CSL.PlutusScript) - -> (forall (x :: Type). x -> Either String x) - -> CSL.PlutusData - -> CSL.PlutusScript - -> Either String CSL.PlutusScript - -apply_params_to_script_either - :: CSL.PlutusData -> CSL.PlutusScript -> Either String CSL.PlutusScript -apply_params_to_script_either = apply_params_to_script Left Right - -applyArgs - :: PlutusScript -> Array PlutusData -> Either String PlutusScript -applyArgs script paramsList = do - let params = PlutusData.toCsl (List paramsList) - appliedScript <- apply_params_to_script_either params - (PlutusScript.toCsl script) - Right $ PlutusScript.fromCsl appliedScript diff --git a/templates/ctl-scaffold/package-lock.json b/templates/ctl-scaffold/package-lock.json index 561dc93e3a..bc61dd3b53 100644 --- a/templates/ctl-scaffold/package-lock.json +++ b/templates/ctl-scaffold/package-lock.json @@ -12,7 +12,6 @@ "@mlabs-haskell/cardano-message-signing": "^1.0.1", "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", "@mlabs-haskell/json-bigint": "2.0.0", - "@mlabs-haskell/uplc-apply-args": "2.0.1", "@noble/secp256k1": "^1.7.0", "base64-js": "^1.5.1", "bignumber.js": "^9.1.1", @@ -518,25 +517,6 @@ "resolved": "https://registry.npmjs.org/@mlabs-haskell/json-bigint/-/json-bigint-2.0.0.tgz", "integrity": "sha512-JX9TON+nZbt+1TJ5MNV1Gcpxp3/m56x1/glDwzGtydrzQzyZbKg4XFw9Frib6fh89YVqjSFJ9xmVeIyDJ5DxTQ==" }, - "node_modules/@mlabs-haskell/uplc-apply-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-2.0.1.tgz", - "integrity": "sha512-of0zlgBEk9vpTBFISDHADoYRzfbw84MQBMnGCXFhdSvdOIWsoGV4kvQJBdufYYh8BJNSyy0MLJ9uX7ARr7reig==", - "dependencies": { - "@mlabs-haskell/uplc-apply-args-browser": "^0.0.3", - "@mlabs-haskell/uplc-apply-args-nodejs": "^0.0.3" - } - }, - "node_modules/@mlabs-haskell/uplc-apply-args-browser": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-browser/-/uplc-apply-args-browser-0.0.3.tgz", - "integrity": "sha512-U2GFMN2Q2KLwTKjrwDXcOBznIvib3Jvdg79xmXDx3/L94PGoBfLN9bBByfVTwKP+ETRfJgRXwi5xxctwKXvT+g==" - }, - "node_modules/@mlabs-haskell/uplc-apply-args-nodejs": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-nodejs/-/uplc-apply-args-nodejs-0.0.3.tgz", - "integrity": "sha512-0uLz+67U1yiXvt3qu/7NBd0WK6LWXf9XteaInQk56RqRbxi4WKA/1Rm73VuciZzLWohXMDNbVNCiirmXi6k+9A==" - }, "node_modules/@noble/hashes": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", @@ -5771,25 +5751,6 @@ "resolved": "https://registry.npmjs.org/@mlabs-haskell/json-bigint/-/json-bigint-2.0.0.tgz", "integrity": "sha512-JX9TON+nZbt+1TJ5MNV1Gcpxp3/m56x1/glDwzGtydrzQzyZbKg4XFw9Frib6fh89YVqjSFJ9xmVeIyDJ5DxTQ==" }, - "@mlabs-haskell/uplc-apply-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-2.0.1.tgz", - "integrity": "sha512-of0zlgBEk9vpTBFISDHADoYRzfbw84MQBMnGCXFhdSvdOIWsoGV4kvQJBdufYYh8BJNSyy0MLJ9uX7ARr7reig==", - "requires": { - "@mlabs-haskell/uplc-apply-args-browser": "^0.0.3", - "@mlabs-haskell/uplc-apply-args-nodejs": "^0.0.3" - } - }, - "@mlabs-haskell/uplc-apply-args-browser": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-browser/-/uplc-apply-args-browser-0.0.3.tgz", - "integrity": "sha512-U2GFMN2Q2KLwTKjrwDXcOBznIvib3Jvdg79xmXDx3/L94PGoBfLN9bBByfVTwKP+ETRfJgRXwi5xxctwKXvT+g==" - }, - "@mlabs-haskell/uplc-apply-args-nodejs": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-nodejs/-/uplc-apply-args-nodejs-0.0.3.tgz", - "integrity": "sha512-0uLz+67U1yiXvt3qu/7NBd0WK6LWXf9XteaInQk56RqRbxi4WKA/1Rm73VuciZzLWohXMDNbVNCiirmXi6k+9A==" - }, "@noble/hashes": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", diff --git a/templates/ctl-scaffold/package.json b/templates/ctl-scaffold/package.json index f34f4d9e34..fccdce6b9f 100644 --- a/templates/ctl-scaffold/package.json +++ b/templates/ctl-scaffold/package.json @@ -28,7 +28,6 @@ "@mlabs-haskell/cardano-message-signing": "^1.0.1", "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", "@mlabs-haskell/json-bigint": "2.0.0", - "@mlabs-haskell/uplc-apply-args": "2.0.1", "@noble/secp256k1": "^1.7.0", "base64-js": "^1.5.1", "bignumber.js": "^9.1.1", diff --git a/test/ApplyArgs.purs b/test/ApplyArgs.purs deleted file mode 100644 index 8fab91ce51..0000000000 --- a/test/ApplyArgs.purs +++ /dev/null @@ -1,380 +0,0 @@ -module Test.Ctl.ApplyArgs (main, suite, contract) where - -import Contract.Prelude - -import Contract.Monad (Contract, launchAff_) -import Contract.Numeric.BigNum as BigNum -import Contract.PlutusData (PlutusData(List, Map, Bytes, Constr), toData) -import Contract.Prim.ByteArray (hexToByteArrayUnsafe) -import Contract.Scripts (PlutusScript) -import Contract.TextEnvelope - ( decodeTextEnvelope - , plutusScriptFromEnvelope - ) -import Control.Monad.Error.Class (class MonadError) -import Ctl.Internal.ApplyArgs (applyArgs) -import Ctl.Internal.Cardano.TextEnvelope (TextEnvelope) -import Data.List.Lazy (replicate) -import Data.Profunctor.Choice (left) -import Effect.Aff (Error, error, throwError) -import Foreign.Object (Object) -import Foreign.Object as Object -import JS.BigInt (fromInt) -import Mote (group, test) -import Mote.TestPlanM (TestPlanM, interpret) -import Test.Spec.Assertions (shouldEqual) - -scriptSources :: Object String -scriptSources = - Object.fromFoldable - [ "always-fails" /\ - """ -{ - "type": "PlutusScriptV1", - "description": "", - "cborHex": "581e581c01000033223232222350040071235002353003001498498480048005" -} - """ - , "always-fails-big-arg" /\ - """ -{ - "type": "PlutusScriptV1", - "description": "", - "cborHex": "58ff58fd0100003333333332232322223500400712350023530030014984984800480053010107004c0103d87980004c01089fd87980424d5fff004c01465f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dff004c0107a20507424d5f08004c0154d9055f9f079fd87980424d5f5f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dffffff004c0114d87e9f809f01ffa0a201d8798002d87b9f02ffff0001" -} -""" - , "always-fails-no-args" /\ - """ -{ - "type": "PlutusScriptV1", - "description": "", - "cborHex": "581e581c01000033223232222350040071235002353003001498498480048005" -} -""" - , "always-fails-unit" /\ - """ -{ - "type": "PlutusScriptV1", - "description": "", - "cborHex": "5826582401000033322323222235004007123500235300300149849848004800530103d879800001" -} -""" - - , "include-datum" /\ - """ -{ - "type": "PlutusScriptV1", - "description": "include-datum", - "cborHex": "55540100002225333573466e1cdd6801a40a82930b01" -} -""" - , "include-datum-big-arg" /\ - """ -{ - "type": "PlutusScriptV1", - "description": "", - "cborHex": "58f658f401000033333332225333573466e1cdd6801a40a82930b2610107004c0103d87980004c01089fd87980424d5fff004c01465f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dff004c0107a20507424d5f08004c0154d9055f9f079fd87980424d5f5f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dffffff004c0114d87e9f809f01ffa0a201d8798002d87b9f02ffff0001" -} -""" - , "include-datum-no-args" /\ - """ -{ - "type": "PlutusScriptV1", - "description": "", - "cborHex": "55540100002225333573466e1cdd6801a40a82930b01" -} -""" - , "include-datum-unit" /\ - """ -{ - "type": "PlutusScriptV1", - "description": "", - "cborHex": "581d581b01000032225333573466e1cdd6801a40a82930b26103d879800001" -} -""" - - , "one-shot-minting" /\ - """ -{ - "type": "PlutusScriptV1", - "description": "one-shot-minting", - "cborHex": "5908d75908d401000033232332233223232323232323232323232323232323232323222223232323232325335533533355300b120013232123300122333500522002002001002350012200112330012253350021022100101f2325335333573466e3cd400488008d4014880080840804ccd5cd19b873500122001350052200102102010203500122002355001222222222200a101e101f1326353357389201115574786f206e6f7420636f6e73756d65640001b0191533553355335323301d50220013550012222222222007101e22135002222533500415335333573466e3c00cd401c88cccd40048c98d4cd5ce2481024c680002302120012326353357389201024c68000230212326353357389201024c680002302102402315335333573466e3c00802409008c4ccd5cd19b870014800809008c408c408c8840944078407c4c98d4cd5ce24811357726f6e6720616d6f756e74206d696e7465640001b019101b135001220023333573466e1cd55cea8022400046644246600200600464646464646464646464646666ae68cdc39aab9d500a480008cccccccccc888888888848cccccccccc00402c02802402001c01801401000c008cd40648c8c8cccd5cd19b8735573aa0049000119910919800801801180d9aba15002301e357426ae8940088c98d4cd5ce01481501401389aab9e5001137540026ae854028cd4064068d5d0a804999aa80e3ae501b35742a010666aa038eb9406cd5d0a80399a80c8101aba15006335019335502302175a6ae854014c8c8c8cccd5cd19b8735573aa00490001199109198008018011919191999ab9a3370e6aae754009200023322123300100300233502675a6ae854008c09cd5d09aba2500223263533573805a05c05805626aae7940044dd50009aba150023232323333573466e1cd55cea8012400046644246600200600466a04ceb4d5d0a80118139aba135744a004464c6a66ae700b40b80b00ac4d55cf280089baa001357426ae8940088c98d4cd5ce01481501401389aab9e5001137540026ae854010cd4065d71aba15003335019335502375c40026ae854008c060d5d09aba2500223263533573804a04c04804626ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226aae7940044dd50009aba150043232323333573466e1d400520062321222230040053018357426aae79400c8cccd5cd19b875002480108c848888c008014c068d5d09aab9e500423333573466e1d400d20022321222230010053011357426aae7940148cccd5cd19b875004480008c848888c00c014dd71aba135573ca00c464c6a66ae7008008407c07807407006c4d55cea80089baa001357426ae8940108c98d4cd5ce00c80d00c00b98048031bae006135573ca00226ea8004c8004d5406088448894cd40044d400c88004884ccd401488008c010008ccd54c01c480040140100048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931a99ab9c012013011010135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98d4cd5ce00800880780709baa0011232230023758002640026aa02c446666aae7c0049405c8cd4058c010d5d080118019aba200201023232323333573466e1cd55cea801a40004666444246660020080060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008c044d5d0a80119a8060081aba135744a004464c6a66ae7005005404c0484d55cf280089baa00135742a006666aa00eeb94018d5d0a80119a8043ae357426ae8940088c98d4cd5ce00800880780709aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa02844646666aae7c008940588cd4054cd5405cc018d55cea80118029aab9e500230043574400601e26ae84004488c8c8cccd5cd19b875001480008c8488c00800cc014d5d09aab9e500323333573466e1d40092002212200123263533573801c01e01a01801626aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6a66ae7003803c03403002c0284d55cea80089baa0012323333573466e1d40052002200e23333573466e1d40092000200e23263533573801401601201000e26aae74dd5000919191919191999ab9a3370ea002900610911111100191999ab9a3370ea004900510911111100211999ab9a3370ea00690041199109111111198008048041bae35742a00a6eb4d5d09aba2500523333573466e1d40112006233221222222233002009008375c6ae85401cdd71aba135744a00e46666ae68cdc3a802a400846644244444446600c01201060186ae854024dd71aba135744a01246666ae68cdc3a8032400446424444444600e010601a6ae84d55cf280591999ab9a3370ea00e900011909111111180280418071aba135573ca018464c6a66ae7004804c04404003c03803403002c0284d55cea80209aab9e5003135573ca00426aae7940044dd50009191919191999ab9a3370ea002900111999110911998008028020019bad35742a0086eb4d5d0a8019bad357426ae89400c8cccd5cd19b875002480008c8488c00800cc020d5d09aab9e500623263533573801601801401201026aae75400c4d5d1280089aab9e500113754002464646666ae68cdc3a800a400446424460020066eb8d5d09aab9e500323333573466e1d400920002321223002003375c6ae84d55cf280211931a99ab9c008009007006005135573aa00226ea800444888c8c8cccd5cd19b8735573aa0049000119aa80818031aba150023005357426ae8940088c98d4cd5ce00400480380309aab9e5001137540029324903505431001200132001355007222533500110022213500222330073330080020060010033200135500622225335001100222135002225335333573466e1c005200000a0091333008007006003133300800733500b1233300100800300200600312200212200111220021221223300100400311221233001003002112323001001223300330020020014c1074643544c4e46540001" -} -""" - , "one-shot-minting-big-arg" /\ - """ -{ - "type": "PlutusScriptV1", - "description": "", - "cborHex": "5909b75909b4010000333333333232332233223232323232323232323232323232323232323222223232323232325335533533355300b120013232123300122333500522002002001002350012200112330012253350021022100101f2325335333573466e3cd400488008d4014880080840804ccd5cd19b873500122001350052200102102010203500122002355001222222222200a101e101f132635335738921115574786f206e6f7420636f6e73756d65640001b0191533553355335323301d50220013550012222222222007101e22135002222533500415335333573466e3c00cd401c88cccd40048c98d4cd5ce2481024c680002302120012326353357389201024c68000230212326353357389201024c680002302102402315335333573466e3c00802409008c4ccd5cd19b870014800809008c408c408c8840944078407c4c98d4cd5ce24811357726f6e6720616d6f756e74206d696e7465640001b019101b135001220023333573466e1cd55cea8022400046644246600200600464646464646464646464646666ae68cdc39aab9d500a480008cccccccccc888888888848cccccccccc00402c02802402001c01801401000c008cd40648c8c8cccd5cd19b8735573aa0049000119910919800801801180d9aba15002301e357426ae8940088c98d4cd5ce01481501401389aab9e5001137540026ae854028cd4064068d5d0a804999aa80e3ae501b35742a010666aa038eb9406cd5d0a80399a80c8101aba15006335019335502302175a6ae854014c8c8c8cccd5cd19b8735573aa00490001199109198008018011919191999ab9a3370e6aae754009200023322123300100300233502675a6ae854008c09cd5d09aba2500223263533573805a05c05805626aae7940044dd50009aba150023232323333573466e1cd55cea8012400046644246600200600466a04ceb4d5d0a80118139aba135744a004464c6a66ae700b40b80b00ac4d55cf280089baa001357426ae8940088c98d4cd5ce01481501401389aab9e5001137540026ae854010cd4065d71aba15003335019335502375c40026ae854008c060d5d09aba2500223263533573804a04c04804626ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226aae7940044dd50009aba150043232323333573466e1d400520062321222230040053018357426aae79400c8cccd5cd19b875002480108c848888c008014c068d5d09aab9e500423333573466e1d400d20022321222230010053011357426aae7940148cccd5cd19b875004480008c848888c00c014dd71aba135573ca00c464c6a66ae7008008407c07807407006c4d55cea80089baa001357426ae8940108c98d4cd5ce00c80d00c00b98048031bae006135573ca00226ea8004c8004d5406088448894cd40044d400c88004884ccd401488008c010008ccd54c01c480040140100048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931a99ab9c012013011010135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98d4cd5ce00800880780709baa0011232230023758002640026aa02c446666aae7c0049405c8cd4058c010d5d080118019aba200201023232323333573466e1cd55cea801a40004666444246660020080060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008c044d5d0a80119a8060081aba135744a004464c6a66ae7005005404c0484d55cf280089baa00135742a006666aa00eeb94018d5d0a80119a8043ae357426ae8940088c98d4cd5ce00800880780709aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa02844646666aae7c008940588cd4054cd5405cc018d55cea80118029aab9e500230043574400601e26ae84004488c8c8cccd5cd19b875001480008c8488c00800cc014d5d09aab9e500323333573466e1d40092002212200123263533573801c01e01a01801626aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6a66ae7003803c03403002c0284d55cea80089baa0012323333573466e1d40052002200e23333573466e1d40092000200e23263533573801401601201000e26aae74dd5000919191919191999ab9a3370ea002900610911111100191999ab9a3370ea004900510911111100211999ab9a3370ea00690041199109111111198008048041bae35742a00a6eb4d5d09aba2500523333573466e1d40112006233221222222233002009008375c6ae85401cdd71aba135744a00e46666ae68cdc3a802a400846644244444446600c01201060186ae854024dd71aba135744a01246666ae68cdc3a8032400446424444444600e010601a6ae84d55cf280591999ab9a3370ea00e900011909111111180280418071aba135573ca018464c6a66ae7004804c04404003c03803403002c0284d55cea80209aab9e5003135573ca00426aae7940044dd50009191919191999ab9a3370ea002900111999110911998008028020019bad35742a0086eb4d5d0a8019bad357426ae89400c8cccd5cd19b875002480008c8488c00800cc020d5d09aab9e500623263533573801601801401201026aae75400c4d5d1280089aab9e500113754002464646666ae68cdc3a800a400446424460020066eb8d5d09aab9e500323333573466e1d400920002321223002003375c6ae84d55cf280211931a99ab9c008009007006005135573aa00226ea800444888c8c8cccd5cd19b8735573aa0049000119aa80818031aba150023005357426ae8940088c98d4cd5ce00400480380309aab9e5001137540029324903505431001200132001355007222533500110022213500222330073330080020060010033200135500622225335001100222135002225335333573466e1c005200000a0091333008007006003133300800733500b1233300100800300200600312200212200111220021221223300100400311221233001003002112323001001223300330020020014c1074643544c4e4654004c010107004c0103d87980004c01089fd87980424d5fff004c01465f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dff004c0107a20507424d5f08004c0154d9055f9f079fd87980424d5f5f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dffffff004c0114d87e9f809f01ffa0a201d8798002d87b9f02ffff0001" -} -""" - , "one-shot-minting-no-args" /\ - """ -{ - "type": "PlutusScriptV1", - "description": "", - "cborHex": "5908d75908d401000033232332233223232323232323232323232323232323232323222223232323232325335533533355300b120013232123300122333500522002002001002350012200112330012253350021022100101f2325335333573466e3cd400488008d4014880080840804ccd5cd19b873500122001350052200102102010203500122002355001222222222200a101e101f1326353357389201115574786f206e6f7420636f6e73756d65640001b0191533553355335323301d50220013550012222222222007101e22135002222533500415335333573466e3c00cd401c88cccd40048c98d4cd5ce2481024c680002302120012326353357389201024c68000230212326353357389201024c680002302102402315335333573466e3c00802409008c4ccd5cd19b870014800809008c408c408c8840944078407c4c98d4cd5ce24811357726f6e6720616d6f756e74206d696e7465640001b019101b135001220023333573466e1cd55cea8022400046644246600200600464646464646464646464646666ae68cdc39aab9d500a480008cccccccccc888888888848cccccccccc00402c02802402001c01801401000c008cd40648c8c8cccd5cd19b8735573aa0049000119910919800801801180d9aba15002301e357426ae8940088c98d4cd5ce01481501401389aab9e5001137540026ae854028cd4064068d5d0a804999aa80e3ae501b35742a010666aa038eb9406cd5d0a80399a80c8101aba15006335019335502302175a6ae854014c8c8c8cccd5cd19b8735573aa00490001199109198008018011919191999ab9a3370e6aae754009200023322123300100300233502675a6ae854008c09cd5d09aba2500223263533573805a05c05805626aae7940044dd50009aba150023232323333573466e1cd55cea8012400046644246600200600466a04ceb4d5d0a80118139aba135744a004464c6a66ae700b40b80b00ac4d55cf280089baa001357426ae8940088c98d4cd5ce01481501401389aab9e5001137540026ae854010cd4065d71aba15003335019335502375c40026ae854008c060d5d09aba2500223263533573804a04c04804626ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226aae7940044dd50009aba150043232323333573466e1d400520062321222230040053018357426aae79400c8cccd5cd19b875002480108c848888c008014c068d5d09aab9e500423333573466e1d400d20022321222230010053011357426aae7940148cccd5cd19b875004480008c848888c00c014dd71aba135573ca00c464c6a66ae7008008407c07807407006c4d55cea80089baa001357426ae8940108c98d4cd5ce00c80d00c00b98048031bae006135573ca00226ea8004c8004d5406088448894cd40044d400c88004884ccd401488008c010008ccd54c01c480040140100048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931a99ab9c012013011010135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98d4cd5ce00800880780709baa0011232230023758002640026aa02c446666aae7c0049405c8cd4058c010d5d080118019aba200201023232323333573466e1cd55cea801a40004666444246660020080060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008c044d5d0a80119a8060081aba135744a004464c6a66ae7005005404c0484d55cf280089baa00135742a006666aa00eeb94018d5d0a80119a8043ae357426ae8940088c98d4cd5ce00800880780709aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa02844646666aae7c008940588cd4054cd5405cc018d55cea80118029aab9e500230043574400601e26ae84004488c8c8cccd5cd19b875001480008c8488c00800cc014d5d09aab9e500323333573466e1d40092002212200123263533573801c01e01a01801626aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6a66ae7003803c03403002c0284d55cea80089baa0012323333573466e1d40052002200e23333573466e1d40092000200e23263533573801401601201000e26aae74dd5000919191919191999ab9a3370ea002900610911111100191999ab9a3370ea004900510911111100211999ab9a3370ea00690041199109111111198008048041bae35742a00a6eb4d5d09aba2500523333573466e1d40112006233221222222233002009008375c6ae85401cdd71aba135744a00e46666ae68cdc3a802a400846644244444446600c01201060186ae854024dd71aba135744a01246666ae68cdc3a8032400446424444444600e010601a6ae84d55cf280591999ab9a3370ea00e900011909111111180280418071aba135573ca018464c6a66ae7004804c04404003c03803403002c0284d55cea80209aab9e5003135573ca00426aae7940044dd50009191919191999ab9a3370ea002900111999110911998008028020019bad35742a0086eb4d5d0a8019bad357426ae89400c8cccd5cd19b875002480008c8488c00800cc020d5d09aab9e500623263533573801601801401201026aae75400c4d5d1280089aab9e500113754002464646666ae68cdc3a800a400446424460020066eb8d5d09aab9e500323333573466e1d400920002321223002003375c6ae84d55cf280211931a99ab9c008009007006005135573aa00226ea800444888c8c8cccd5cd19b8735573aa0049000119aa80818031aba150023005357426ae8940088c98d4cd5ce00400480380309aab9e5001137540029324903505431001200132001355007222533500110022213500222330073330080020060010033200135500622225335001100222135002225335333573466e1c005200000a0091333008007006003133300800733500b1233300100800300200600312200212200111220021221223300100400311221233001003002112323001001223300330020020014c1074643544c4e46540001" -} -""" - , "one-shot-minting-unit" /\ - """ -{ - "type": "PlutusScriptV1", - "description": "", - "cborHex": "5908de5908db010000333232332233223232323232323232323232323232323232323222223232323232325335533533355300b120013232123300122333500522002002001002350012200112330012253350021022100101f2325335333573466e3cd400488008d4014880080840804ccd5cd19b873500122001350052200102102010203500122002355001222222222200a101e101f132635335738921115574786f206e6f7420636f6e73756d65640001b0191533553355335323301d50220013550012222222222007101e22135002222533500415335333573466e3c00cd401c88cccd40048c98d4cd5ce2481024c680002302120012326353357389201024c68000230212326353357389201024c680002302102402315335333573466e3c00802409008c4ccd5cd19b870014800809008c408c408c8840944078407c4c98d4cd5ce24811357726f6e6720616d6f756e74206d696e7465640001b019101b135001220023333573466e1cd55cea8022400046644246600200600464646464646464646464646666ae68cdc39aab9d500a480008cccccccccc888888888848cccccccccc00402c02802402001c01801401000c008cd40648c8c8cccd5cd19b8735573aa0049000119910919800801801180d9aba15002301e357426ae8940088c98d4cd5ce01481501401389aab9e5001137540026ae854028cd4064068d5d0a804999aa80e3ae501b35742a010666aa038eb9406cd5d0a80399a80c8101aba15006335019335502302175a6ae854014c8c8c8cccd5cd19b8735573aa00490001199109198008018011919191999ab9a3370e6aae754009200023322123300100300233502675a6ae854008c09cd5d09aba2500223263533573805a05c05805626aae7940044dd50009aba150023232323333573466e1cd55cea8012400046644246600200600466a04ceb4d5d0a80118139aba135744a004464c6a66ae700b40b80b00ac4d55cf280089baa001357426ae8940088c98d4cd5ce01481501401389aab9e5001137540026ae854010cd4065d71aba15003335019335502375c40026ae854008c060d5d09aba2500223263533573804a04c04804626ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226aae7940044dd50009aba150043232323333573466e1d400520062321222230040053018357426aae79400c8cccd5cd19b875002480108c848888c008014c068d5d09aab9e500423333573466e1d400d20022321222230010053011357426aae7940148cccd5cd19b875004480008c848888c00c014dd71aba135573ca00c464c6a66ae7008008407c07807407006c4d55cea80089baa001357426ae8940108c98d4cd5ce00c80d00c00b98048031bae006135573ca00226ea8004c8004d5406088448894cd40044d400c88004884ccd401488008c010008ccd54c01c480040140100048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931a99ab9c012013011010135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98d4cd5ce00800880780709baa0011232230023758002640026aa02c446666aae7c0049405c8cd4058c010d5d080118019aba200201023232323333573466e1cd55cea801a40004666444246660020080060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008c044d5d0a80119a8060081aba135744a004464c6a66ae7005005404c0484d55cf280089baa00135742a006666aa00eeb94018d5d0a80119a8043ae357426ae8940088c98d4cd5ce00800880780709aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa02844646666aae7c008940588cd4054cd5405cc018d55cea80118029aab9e500230043574400601e26ae84004488c8c8cccd5cd19b875001480008c8488c00800cc014d5d09aab9e500323333573466e1d40092002212200123263533573801c01e01a01801626aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6a66ae7003803c03403002c0284d55cea80089baa0012323333573466e1d40052002200e23333573466e1d40092000200e23263533573801401601201000e26aae74dd5000919191919191999ab9a3370ea002900610911111100191999ab9a3370ea004900510911111100211999ab9a3370ea00690041199109111111198008048041bae35742a00a6eb4d5d09aba2500523333573466e1d40112006233221222222233002009008375c6ae85401cdd71aba135744a00e46666ae68cdc3a802a400846644244444446600c01201060186ae854024dd71aba135744a01246666ae68cdc3a8032400446424444444600e010601a6ae84d55cf280591999ab9a3370ea00e900011909111111180280418071aba135573ca018464c6a66ae7004804c04404003c03803403002c0284d55cea80209aab9e5003135573ca00426aae7940044dd50009191919191999ab9a3370ea002900111999110911998008028020019bad35742a0086eb4d5d0a8019bad357426ae89400c8cccd5cd19b875002480008c8488c00800cc020d5d09aab9e500623263533573801601801401201026aae75400c4d5d1280089aab9e500113754002464646666ae68cdc3a800a400446424460020066eb8d5d09aab9e500323333573466e1d400920002321223002003375c6ae84d55cf280211931a99ab9c008009007006005135573aa00226ea800444888c8c8cccd5cd19b8735573aa0049000119aa80818031aba150023005357426ae8940088c98d4cd5ce00400480380309aab9e5001137540029324903505431001200132001355007222533500110022213500222330073330080020060010033200135500622225335001100222135002225335333573466e1c005200000a0091333008007006003133300800733500b1233300100800300200600312200212200111220021221223300100400311221233001003002112323001001223300330020020014c1074643544c4e4654004c0103d879800001" -} -""" - - , "always-succeeds-v2" /\ - """ -{ - "cborHex": "4e4d01000033222220051200120011", - "description": "always-succeeds", - "type": "PlutusScriptV2" -} -""" - , "always-succeeds-v2-big-arg" /\ - """ -{ - "type": "PlutusScriptV2", - "description": "", - "cborHex": "58f058ee010000333333333222220051200120014c010107004c0103d87980004c01089fd87980424d5fff004c01465f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dff004c0107a20507424d5f08004c0154d9055f9f079fd87980424d5f5f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dffffff004c0114d87e9f809f01ffa0a201d8798002d87b9f02ffff0001" -} -""" - , "always-succeeds-v2-no-args" /\ - """ -{ - "type": "PlutusScriptV2", - "description": "", - "cborHex": "4e4d01000033222220051200120011" -} -""" - , "always-succeeds-v2-unit" /\ - """ -{ - "type": "PlutusScriptV2", - "description": "", - "cborHex": "5655010000333222220051200120014c0103d879800001" -} -""" - - , "check-datum-is-inline" /\ - """ -{ - "type": "PlutusScriptV2", - "description": "", - "cborHex": "59088859088501000032332232323233223232323232323232323322323232323232322223232533532325335001101b13357389211d556e657870656374656420646174756d206174206f776e20696e7075740001a323253335002153335001101c2101c2101c2153335002101c21333573466ebc00800407807484074854ccd400840708407484ccd5cd19b8f00200101e01d323500122220023235001220013553353500222350022222222222223333500d2501e2501e2501e233355302d12001321233001225335002210031001002501e2350012253355335333573466e3cd400888008d4010880080b40b04ccd5cd19b873500222001350042200102d02c102c1350220031502100d21123001002162001300a0053333573466e1cd55cea80124000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4054058d5d0a80619a80a80b1aba1500b33501501735742a014666aa034eb94064d5d0a804999aa80d3ae501935742a01066a02a0426ae85401cccd54068089d69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b1d69aba15002302d357426ae8940088c98c80bccd5ce01901881689aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a8163ad35742a004605a6ae84d5d1280111931901799ab9c03203102d135573ca00226ea8004d5d09aba2500223263202b33573805c05a05226aae7940044dd50009aba1500533501575c6ae854010ccd540680788004d5d0a801999aa80d3ae200135742a00460406ae84d5d1280111931901399ab9c02a029025135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00460206ae84d5d1280111931900c99ab9c01c01b017101a132632018335738921035054350001a135573ca00226ea800448c88c008dd6000990009aa80d111999aab9f0012501c233501b30043574200460066ae8800805c8c8c8cccd5cd19b8735573aa004900011991091980080180118069aba150023005357426ae8940088c98c8054cd5ce00c00b80989aab9e5001137540024646464646666ae68cdc39aab9d5004480008cccc888848cccc00401401000c008c8c8c8cccd5cd19b8735573aa0049000119910919800801801180b1aba1500233500e015357426ae8940088c98c8068cd5ce00e80e00c09aab9e5001137540026ae854010ccd54025d728041aba150033232323333573466e1d400520042300b357426aae79400c8cccd5cd19b875002480088c84888c004010dd71aba135573ca00846666ae68cdc3a801a400042444006464c6403866ae7007c0780680640604d55cea80089baa00135742a00466a014eb8d5d09aba2500223263201633573803203002826ae8940044d5d1280089aab9e500113754002424446004008266aa002eb9d6889119118011bab00132001355016223233335573e0044a032466a03066442466002006004600c6aae754008c014d55cf280118021aba200301413574200224464646666ae68cdc3a800a400046a00e600a6ae84d55cf280191999ab9a3370ea00490011280391931900919ab9c01501401000f135573aa00226ea800448488c00800c44880048c8c8cccd5cd19b875001480188c848888c010014c01cd5d09aab9e500323333573466e1d400920042321222230020053009357426aae7940108cccd5cd19b875003480088c848888c004014c01cd5d09aab9e500523333573466e1d40112000232122223003005375c6ae84d55cf280311931900819ab9c01301200e00d00c00b135573aa00226ea80048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931900619ab9c00f00e00a135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98c8028cd5ce00680600409baa001232323232323333573466e1d4005200c21222222200323333573466e1d4009200a21222222200423333573466e1d400d2008233221222222233001009008375c6ae854014dd69aba135744a00a46666ae68cdc3a8022400c4664424444444660040120106eb8d5d0a8039bae357426ae89401c8cccd5cd19b875005480108cc8848888888cc018024020c030d5d0a8049bae357426ae8940248cccd5cd19b875006480088c848888888c01c020c034d5d09aab9e500b23333573466e1d401d2000232122222223005008300e357426aae7940308c98c804ccd5ce00b00a80880800780700680600589aab9d5004135573ca00626aae7940084d55cf280089baa0012323232323333573466e1d400520022333222122333001005004003375a6ae854010dd69aba15003375a6ae84d5d1280191999ab9a3370ea0049000119091180100198041aba135573ca00c464c6401866ae7003c0380280244d55cea80189aba25001135573ca00226ea80048c8c8cccd5cd19b875001480088c8488c00400cdd71aba135573ca00646666ae68cdc3a8012400046424460040066eb8d5d09aab9e500423263200933573801801600e00c26aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6401466ae7003403002001c0184d55cea80089baa0012323333573466e1d40052002200623333573466e1d40092000200623263200633573801201000800626aae74dd5000a4c24400424400224002920103505431003200135500322112225335001135003220012213335005220023004002333553007120010050040011122002122122330010040031123230010012233003300200200101" -} -""" - , "check-datum-is-inline-big-arg" /\ - """ -{ - "type": "PlutusScriptV2", - "description": "", - "cborHex": "590969590966010000333333332332232323233223232323232323232323322323232323232322223232533532325335001101b133573892011d556e657870656374656420646174756d206174206f776e20696e7075740001a323253335002153335001101c2101c2101c2153335002101c21333573466ebc00800407807484074854ccd400840708407484ccd5cd19b8f00200101e01d323500122220023235001220013553353500222350022222222222223333500d2501e2501e2501e233355302d12001321233001225335002210031001002501e2350012253355335333573466e3cd400888008d4010880080b40b04ccd5cd19b873500222001350042200102d02c102c1350220031502100d21123001002162001300a0053333573466e1cd55cea80124000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4054058d5d0a80619a80a80b1aba1500b33501501735742a014666aa034eb94064d5d0a804999aa80d3ae501935742a01066a02a0426ae85401cccd54068089d69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b1d69aba15002302d357426ae8940088c98c80bccd5ce01901881689aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a8163ad35742a004605a6ae84d5d1280111931901799ab9c03203102d135573ca00226ea8004d5d09aba2500223263202b33573805c05a05226aae7940044dd50009aba1500533501575c6ae854010ccd540680788004d5d0a801999aa80d3ae200135742a00460406ae84d5d1280111931901399ab9c02a029025135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00460206ae84d5d1280111931900c99ab9c01c01b017101a132632018335738921035054350001a135573ca00226ea800448c88c008dd6000990009aa80d111999aab9f0012501c233501b30043574200460066ae8800805c8c8c8cccd5cd19b8735573aa004900011991091980080180118069aba150023005357426ae8940088c98c8054cd5ce00c00b80989aab9e5001137540024646464646666ae68cdc39aab9d5004480008cccc888848cccc00401401000c008c8c8c8cccd5cd19b8735573aa0049000119910919800801801180b1aba1500233500e015357426ae8940088c98c8068cd5ce00e80e00c09aab9e5001137540026ae854010ccd54025d728041aba150033232323333573466e1d400520042300b357426aae79400c8cccd5cd19b875002480088c84888c004010dd71aba135573ca00846666ae68cdc3a801a400042444006464c6403866ae7007c0780680640604d55cea80089baa00135742a00466a014eb8d5d09aba2500223263201633573803203002826ae8940044d5d1280089aab9e500113754002424446004008266aa002eb9d6889119118011bab00132001355016223233335573e0044a032466a03066442466002006004600c6aae754008c014d55cf280118021aba200301413574200224464646666ae68cdc3a800a400046a00e600a6ae84d55cf280191999ab9a3370ea00490011280391931900919ab9c01501401000f135573aa00226ea800448488c00800c44880048c8c8cccd5cd19b875001480188c848888c010014c01cd5d09aab9e500323333573466e1d400920042321222230020053009357426aae7940108cccd5cd19b875003480088c848888c004014c01cd5d09aab9e500523333573466e1d40112000232122223003005375c6ae84d55cf280311931900819ab9c01301200e00d00c00b135573aa00226ea80048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931900619ab9c00f00e00a135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98c8028cd5ce00680600409baa001232323232323333573466e1d4005200c21222222200323333573466e1d4009200a21222222200423333573466e1d400d2008233221222222233001009008375c6ae854014dd69aba135744a00a46666ae68cdc3a8022400c4664424444444660040120106eb8d5d0a8039bae357426ae89401c8cccd5cd19b875005480108cc8848888888cc018024020c030d5d0a8049bae357426ae8940248cccd5cd19b875006480088c848888888c01c020c034d5d09aab9e500b23333573466e1d401d2000232122222223005008300e357426aae7940308c98c804ccd5ce00b00a80880800780700680600589aab9d5004135573ca00626aae7940084d55cf280089baa0012323232323333573466e1d400520022333222122333001005004003375a6ae854010dd69aba15003375a6ae84d5d1280191999ab9a3370ea0049000119091180100198041aba135573ca00c464c6401866ae7003c0380280244d55cea80189aba25001135573ca00226ea80048c8c8cccd5cd19b875001480088c8488c00400cdd71aba135573ca00646666ae68cdc3a8012400046424460040066eb8d5d09aab9e500423263200933573801801600e00c26aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6401466ae7003403002001c0184d55cea80089baa0012323333573466e1d40052002200623333573466e1d40092000200623263200633573801201000800626aae74dd5000a4c2440042440022400292010350543100320013550032211222533500113500322001221333500522002300400233355300712001005004001112200212212233001004003112323001001223300330020020014c010107004c0103d87980004c01089fd87980424d5fff004c01465f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dff004c0107a20507424d5f08004c0154d9055f9f079fd87980424d5f5f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dffffff004c0114d87e9f809f01ffa0a201d8798002d87b9f02ffff0001" -} -""" - , "check-datum-is-inline-no-args" /\ - """ -{ - "type": "PlutusScriptV2", - "description": "", - "cborHex": "59088859088501000032332232323233223232323232323232323322323232323232322223232533532325335001101b13357389211d556e657870656374656420646174756d206174206f776e20696e7075740001a323253335002153335001101c2101c2101c2153335002101c21333573466ebc00800407807484074854ccd400840708407484ccd5cd19b8f00200101e01d323500122220023235001220013553353500222350022222222222223333500d2501e2501e2501e233355302d12001321233001225335002210031001002501e2350012253355335333573466e3cd400888008d4010880080b40b04ccd5cd19b873500222001350042200102d02c102c1350220031502100d21123001002162001300a0053333573466e1cd55cea80124000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4054058d5d0a80619a80a80b1aba1500b33501501735742a014666aa034eb94064d5d0a804999aa80d3ae501935742a01066a02a0426ae85401cccd54068089d69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b1d69aba15002302d357426ae8940088c98c80bccd5ce01901881689aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a8163ad35742a004605a6ae84d5d1280111931901799ab9c03203102d135573ca00226ea8004d5d09aba2500223263202b33573805c05a05226aae7940044dd50009aba1500533501575c6ae854010ccd540680788004d5d0a801999aa80d3ae200135742a00460406ae84d5d1280111931901399ab9c02a029025135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00460206ae84d5d1280111931900c99ab9c01c01b017101a132632018335738921035054350001a135573ca00226ea800448c88c008dd6000990009aa80d111999aab9f0012501c233501b30043574200460066ae8800805c8c8c8cccd5cd19b8735573aa004900011991091980080180118069aba150023005357426ae8940088c98c8054cd5ce00c00b80989aab9e5001137540024646464646666ae68cdc39aab9d5004480008cccc888848cccc00401401000c008c8c8c8cccd5cd19b8735573aa0049000119910919800801801180b1aba1500233500e015357426ae8940088c98c8068cd5ce00e80e00c09aab9e5001137540026ae854010ccd54025d728041aba150033232323333573466e1d400520042300b357426aae79400c8cccd5cd19b875002480088c84888c004010dd71aba135573ca00846666ae68cdc3a801a400042444006464c6403866ae7007c0780680640604d55cea80089baa00135742a00466a014eb8d5d09aba2500223263201633573803203002826ae8940044d5d1280089aab9e500113754002424446004008266aa002eb9d6889119118011bab00132001355016223233335573e0044a032466a03066442466002006004600c6aae754008c014d55cf280118021aba200301413574200224464646666ae68cdc3a800a400046a00e600a6ae84d55cf280191999ab9a3370ea00490011280391931900919ab9c01501401000f135573aa00226ea800448488c00800c44880048c8c8cccd5cd19b875001480188c848888c010014c01cd5d09aab9e500323333573466e1d400920042321222230020053009357426aae7940108cccd5cd19b875003480088c848888c004014c01cd5d09aab9e500523333573466e1d40112000232122223003005375c6ae84d55cf280311931900819ab9c01301200e00d00c00b135573aa00226ea80048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931900619ab9c00f00e00a135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98c8028cd5ce00680600409baa001232323232323333573466e1d4005200c21222222200323333573466e1d4009200a21222222200423333573466e1d400d2008233221222222233001009008375c6ae854014dd69aba135744a00a46666ae68cdc3a8022400c4664424444444660040120106eb8d5d0a8039bae357426ae89401c8cccd5cd19b875005480108cc8848888888cc018024020c030d5d0a8049bae357426ae8940248cccd5cd19b875006480088c848888888c01c020c034d5d09aab9e500b23333573466e1d401d2000232122222223005008300e357426aae7940308c98c804ccd5ce00b00a80880800780700680600589aab9d5004135573ca00626aae7940084d55cf280089baa0012323232323333573466e1d400520022333222122333001005004003375a6ae854010dd69aba15003375a6ae84d5d1280191999ab9a3370ea0049000119091180100198041aba135573ca00c464c6401866ae7003c0380280244d55cea80189aba25001135573ca00226ea80048c8c8cccd5cd19b875001480088c8488c00400cdd71aba135573ca00646666ae68cdc3a8012400046424460040066eb8d5d09aab9e500423263200933573801801600e00c26aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6401466ae7003403002001c0184d55cea80089baa0012323333573466e1d40052002200623333573466e1d40092000200623263200633573801201000800626aae74dd5000a4c24400424400224002920103505431003200135500322112225335001135003220012213335005220023004002333553007120010050040011122002122122330010040031123230010012233003300200200101" -} -""" - , "check-datum-is-inline-unit" /\ - """ -{ - "type": "PlutusScriptV2", - "description": "", - "cborHex": "59089059088d010000332332232323233223232323232323232323322323232323232322223232533532325335001101b133573892011d556e657870656374656420646174756d206174206f776e20696e7075740001a323253335002153335001101c2101c2101c2153335002101c21333573466ebc00800407807484074854ccd400840708407484ccd5cd19b8f00200101e01d323500122220023235001220013553353500222350022222222222223333500d2501e2501e2501e233355302d12001321233001225335002210031001002501e2350012253355335333573466e3cd400888008d4010880080b40b04ccd5cd19b873500222001350042200102d02c102c1350220031502100d21123001002162001300a0053333573466e1cd55cea80124000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4054058d5d0a80619a80a80b1aba1500b33501501735742a014666aa034eb94064d5d0a804999aa80d3ae501935742a01066a02a0426ae85401cccd54068089d69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b1d69aba15002302d357426ae8940088c98c80bccd5ce01901881689aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a8163ad35742a004605a6ae84d5d1280111931901799ab9c03203102d135573ca00226ea8004d5d09aba2500223263202b33573805c05a05226aae7940044dd50009aba1500533501575c6ae854010ccd540680788004d5d0a801999aa80d3ae200135742a00460406ae84d5d1280111931901399ab9c02a029025135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00460206ae84d5d1280111931900c99ab9c01c01b017101a132632018335738921035054350001a135573ca00226ea800448c88c008dd6000990009aa80d111999aab9f0012501c233501b30043574200460066ae8800805c8c8c8cccd5cd19b8735573aa004900011991091980080180118069aba150023005357426ae8940088c98c8054cd5ce00c00b80989aab9e5001137540024646464646666ae68cdc39aab9d5004480008cccc888848cccc00401401000c008c8c8c8cccd5cd19b8735573aa0049000119910919800801801180b1aba1500233500e015357426ae8940088c98c8068cd5ce00e80e00c09aab9e5001137540026ae854010ccd54025d728041aba150033232323333573466e1d400520042300b357426aae79400c8cccd5cd19b875002480088c84888c004010dd71aba135573ca00846666ae68cdc3a801a400042444006464c6403866ae7007c0780680640604d55cea80089baa00135742a00466a014eb8d5d09aba2500223263201633573803203002826ae8940044d5d1280089aab9e500113754002424446004008266aa002eb9d6889119118011bab00132001355016223233335573e0044a032466a03066442466002006004600c6aae754008c014d55cf280118021aba200301413574200224464646666ae68cdc3a800a400046a00e600a6ae84d55cf280191999ab9a3370ea00490011280391931900919ab9c01501401000f135573aa00226ea800448488c00800c44880048c8c8cccd5cd19b875001480188c848888c010014c01cd5d09aab9e500323333573466e1d400920042321222230020053009357426aae7940108cccd5cd19b875003480088c848888c004014c01cd5d09aab9e500523333573466e1d40112000232122223003005375c6ae84d55cf280311931900819ab9c01301200e00d00c00b135573aa00226ea80048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931900619ab9c00f00e00a135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98c8028cd5ce00680600409baa001232323232323333573466e1d4005200c21222222200323333573466e1d4009200a21222222200423333573466e1d400d2008233221222222233001009008375c6ae854014dd69aba135744a00a46666ae68cdc3a8022400c4664424444444660040120106eb8d5d0a8039bae357426ae89401c8cccd5cd19b875005480108cc8848888888cc018024020c030d5d0a8049bae357426ae8940248cccd5cd19b875006480088c848888888c01c020c034d5d09aab9e500b23333573466e1d401d2000232122222223005008300e357426aae7940308c98c804ccd5ce00b00a80880800780700680600589aab9d5004135573ca00626aae7940084d55cf280089baa0012323232323333573466e1d400520022333222122333001005004003375a6ae854010dd69aba15003375a6ae84d5d1280191999ab9a3370ea0049000119091180100198041aba135573ca00c464c6401866ae7003c0380280244d55cea80189aba25001135573ca00226ea80048c8c8cccd5cd19b875001480088c8488c00400cdd71aba135573ca00646666ae68cdc3a8012400046424460040066eb8d5d09aab9e500423263200933573801801600e00c26aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6401466ae7003403002001c0184d55cea80089baa0012323333573466e1d40052002200623333573466e1d40092000200623263200633573801201000800626aae74dd5000a4c2440042440022400292010350543100320013550032211222533500113500322001221333500522002300400233355300712001005004001112200212212233001004003112323001001223300330020020014c0103d879800001" -} -""" - - , "one-shot-minting-v2" /\ - """ -{ - "type": "PlutusScriptV2", - "description": "one-shot-minting", - "cborHex": "59092c59092901000033233223322323232323232323232323232323232323232323222223232323232325335533533355300b12001323212330012233350052200200200100235001220011233001225335002102310010202325335333573466e3cd400488008d4014880080880844ccd5cd19b87350012200135005220010220211021350012200235500122222222222200c101f102013263201b335738921115574786f206e6f7420636f6e73756d65640001c1533553355335323301e5023001355001222222222222008101f22135002222533500415335333573466e3c00cd401c88cccd40048c98c808ccd5ce2481024c680002420012326320233357389201024c68000242326320233357389201024c680002402502415335333573466e3c0080240940904ccd5cd19b870014800809409040904090884098407c40804c98c806ccd5ce24811357726f6e6720616d6f756e74206d696e7465640001c101c135001220023333573466e1cd55cea80224000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4064068d5d0a80619a80c80d1aba1500b33501901b35742a014666aa03aeb94070d5d0a804999aa80ebae501c35742a01066a0320446ae85401cccd5407408dd69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b5d69aba15002302e357426ae8940088c98c80c0cd5ce01801881709aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a816bad35742a004605c6ae84d5d1280111931901819ab9c03003102e135573ca00226ea8004d5d09aba2500223263202c33573805805a05426aae7940044dd50009aba1500533501975c6ae854010ccd5407407c8004d5d0a801999aa80ebae200135742a00460426ae84d5d1280111931901419ab9c028029026135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00860226ae84d5d1280211931900d19ab9c01a01b0183010006375c00c26aae7940044dd5000990009aa80c1108911299a80089a80191000910999a802910011802001199aa9803890008028020008919118011bac001320013550182233335573e0024a034466a03260086ae84008c00cd5d1001009919191999ab9a3370e6aae7540092000233221233001003002300a35742a004600a6ae84d5d1280111931900919ab9c012013010135573ca00226ea80048c8c8c8c8cccd5cd19b8735573aa00890001199991110919998008028020018011919191999ab9a3370e6aae7540092000233221233001003002301335742a00466a01a0246ae84d5d1280111931900b99ab9c017018015135573ca00226ea8004d5d0a802199aa8043ae500735742a0066464646666ae68cdc3a800a4008464244460040086ae84d55cf280191999ab9a3370ea0049001119091118008021bae357426aae7940108cccd5cd19b875003480008488800c8c98c8064cd5ce00c80d00b80b00a89aab9d5001137540026ae854008cd4025d71aba135744a004464c6402666ae7004c0500444d5d1280089aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa02a44646666aae7c008940608cd405ccc8848cc00400c008c018d55cea80118029aab9e500230043574400602226ae84004488c8c8cccd5cd19b875001480008c8488c00800cc014d5d09aab9e500323333573466e1d40092002212200123263201033573802002201c01a26aae7540044dd5000919191999ab9a3370ea002900311909111180200298039aba135573ca00646666ae68cdc3a8012400846424444600400a60126ae84d55cf280211999ab9a3370ea006900111909111180080298039aba135573ca00a46666ae68cdc3a8022400046424444600600a6eb8d5d09aab9e500623263201033573802002201c01a01801626aae7540044dd5000919191999ab9a3370e6aae7540092000233221233001003002300535742a0046eb4d5d09aba2500223263200c33573801801a01426aae7940044dd50009191999ab9a3370e6aae75400520002375c6ae84d55cf280111931900519ab9c00a00b00813754002464646464646666ae68cdc3a800a401842444444400646666ae68cdc3a8012401442444444400846666ae68cdc3a801a40104664424444444660020120106eb8d5d0a8029bad357426ae8940148cccd5cd19b875004480188cc8848888888cc008024020dd71aba15007375c6ae84d5d1280391999ab9a3370ea00a900211991091111111980300480418061aba15009375c6ae84d5d1280491999ab9a3370ea00c900111909111111180380418069aba135573ca01646666ae68cdc3a803a400046424444444600a010601c6ae84d55cf280611931900999ab9c01301401101000f00e00d00c00b135573aa00826aae79400c4d55cf280109aab9e5001137540024646464646666ae68cdc3a800a4004466644424466600200a0080066eb4d5d0a8021bad35742a0066eb4d5d09aba2500323333573466e1d4009200023212230020033008357426aae7940188c98c8030cd5ce00600680500489aab9d5003135744a00226aae7940044dd5000919191999ab9a3370ea002900111909118008019bae357426aae79400c8cccd5cd19b875002480008c8488c00800cdd71aba135573ca008464c6401266ae7002402801c0184d55cea80089baa00112232323333573466e1d400520042122200123333573466e1d40092002232122230030043006357426aae7940108cccd5cd19b87500348000848880088c98c8028cd5ce00500580400380309aab9d5001137540024646666ae68cdc3a800a4004401446666ae68cdc3a801240004014464c6400c66ae7001801c01000c4d55ce9baa001499240103505431001200132001355006222533500110022213500222330073330080020060010033200135500522225335001100222135002225335333573466e1c005200000a0091333008007006003133300800733500b12333001008003002006003122002122001112200212212233001004003112323001001223300330020020014c01074643544c4e46540001" -} -""" - , "one-shot-minting-v2-big-arg" /\ - """ -{ - "type": "PlutusScriptV2", - "description": "", - "cborHex": "590a0d590a0a010000333333333233223322323232323232323232323232323232323232323222223232323232325335533533355300b12001323212330012233350052200200200100235001220011233001225335002102310010202325335333573466e3cd400488008d4014880080880844ccd5cd19b87350012200135005220010220211021350012200235500122222222222200c101f102013263201b3357389201115574786f206e6f7420636f6e73756d65640001c1533553355335323301e5023001355001222222222222008101f22135002222533500415335333573466e3c00cd401c88cccd40048c98c808ccd5ce2481024c680002420012326320233357389201024c68000242326320233357389201024c680002402502415335333573466e3c0080240940904ccd5cd19b870014800809409040904090884098407c40804c98c806ccd5ce24811357726f6e6720616d6f756e74206d696e7465640001c101c135001220023333573466e1cd55cea80224000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4064068d5d0a80619a80c80d1aba1500b33501901b35742a014666aa03aeb94070d5d0a804999aa80ebae501c35742a01066a0320446ae85401cccd5407408dd69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b5d69aba15002302e357426ae8940088c98c80c0cd5ce01801881709aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a816bad35742a004605c6ae84d5d1280111931901819ab9c03003102e135573ca00226ea8004d5d09aba2500223263202c33573805805a05426aae7940044dd50009aba1500533501975c6ae854010ccd5407407c8004d5d0a801999aa80ebae200135742a00460426ae84d5d1280111931901419ab9c028029026135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00860226ae84d5d1280211931900d19ab9c01a01b0183010006375c00c26aae7940044dd5000990009aa80c1108911299a80089a80191000910999a802910011802001199aa9803890008028020008919118011bac001320013550182233335573e0024a034466a03260086ae84008c00cd5d1001009919191999ab9a3370e6aae7540092000233221233001003002300a35742a004600a6ae84d5d1280111931900919ab9c012013010135573ca00226ea80048c8c8c8c8cccd5cd19b8735573aa00890001199991110919998008028020018011919191999ab9a3370e6aae7540092000233221233001003002301335742a00466a01a0246ae84d5d1280111931900b99ab9c017018015135573ca00226ea8004d5d0a802199aa8043ae500735742a0066464646666ae68cdc3a800a4008464244460040086ae84d55cf280191999ab9a3370ea0049001119091118008021bae357426aae7940108cccd5cd19b875003480008488800c8c98c8064cd5ce00c80d00b80b00a89aab9d5001137540026ae854008cd4025d71aba135744a004464c6402666ae7004c0500444d5d1280089aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa02a44646666aae7c008940608cd405ccc8848cc00400c008c018d55cea80118029aab9e500230043574400602226ae84004488c8c8cccd5cd19b875001480008c8488c00800cc014d5d09aab9e500323333573466e1d40092002212200123263201033573802002201c01a26aae7540044dd5000919191999ab9a3370ea002900311909111180200298039aba135573ca00646666ae68cdc3a8012400846424444600400a60126ae84d55cf280211999ab9a3370ea006900111909111180080298039aba135573ca00a46666ae68cdc3a8022400046424444600600a6eb8d5d09aab9e500623263201033573802002201c01a01801626aae7540044dd5000919191999ab9a3370e6aae7540092000233221233001003002300535742a0046eb4d5d09aba2500223263200c33573801801a01426aae7940044dd50009191999ab9a3370e6aae75400520002375c6ae84d55cf280111931900519ab9c00a00b00813754002464646464646666ae68cdc3a800a401842444444400646666ae68cdc3a8012401442444444400846666ae68cdc3a801a40104664424444444660020120106eb8d5d0a8029bad357426ae8940148cccd5cd19b875004480188cc8848888888cc008024020dd71aba15007375c6ae84d5d1280391999ab9a3370ea00a900211991091111111980300480418061aba15009375c6ae84d5d1280491999ab9a3370ea00c900111909111111180380418069aba135573ca01646666ae68cdc3a803a400046424444444600a010601c6ae84d55cf280611931900999ab9c01301401101000f00e00d00c00b135573aa00826aae79400c4d55cf280109aab9e5001137540024646464646666ae68cdc3a800a4004466644424466600200a0080066eb4d5d0a8021bad35742a0066eb4d5d09aba2500323333573466e1d4009200023212230020033008357426aae7940188c98c8030cd5ce00600680500489aab9d5003135744a00226aae7940044dd5000919191999ab9a3370ea002900111909118008019bae357426aae79400c8cccd5cd19b875002480008c8488c00800cdd71aba135573ca008464c6401266ae7002402801c0184d55cea80089baa00112232323333573466e1d400520042122200123333573466e1d40092002232122230030043006357426aae7940108cccd5cd19b87500348000848880088c98c8028cd5ce00500580400380309aab9d5001137540024646666ae68cdc3a800a4004401446666ae68cdc3a801240004014464c6400c66ae7001801c01000c4d55ce9baa001499240103505431001200132001355006222533500110022213500222330073330080020060010033200135500522225335001100222135002225335333573466e1c005200000a0091333008007006003133300800733500b12333001008003002006003122002122001112200212212233001004003112323001001223300330020020014c01074643544c4e4654004c010107004c0103d87980004c01089fd87980424d5fff004c01465f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dff004c0107a20507424d5f08004c0154d9055f9f079fd87980424d5f5f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dffffff004c0114d87e9f809f01ffa0a201d8798002d87b9f02ffff0001" -} -""" - , "one-shot-minting-v2-no-args" /\ - """ -{ - "type": "PlutusScriptV2", - "description": "", - "cborHex": "59092c59092901000033233223322323232323232323232323232323232323232323222223232323232325335533533355300b12001323212330012233350052200200200100235001220011233001225335002102310010202325335333573466e3cd400488008d4014880080880844ccd5cd19b87350012200135005220010220211021350012200235500122222222222200c101f102013263201b335738921115574786f206e6f7420636f6e73756d65640001c1533553355335323301e5023001355001222222222222008101f22135002222533500415335333573466e3c00cd401c88cccd40048c98c808ccd5ce2481024c680002420012326320233357389201024c68000242326320233357389201024c680002402502415335333573466e3c0080240940904ccd5cd19b870014800809409040904090884098407c40804c98c806ccd5ce24811357726f6e6720616d6f756e74206d696e7465640001c101c135001220023333573466e1cd55cea80224000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4064068d5d0a80619a80c80d1aba1500b33501901b35742a014666aa03aeb94070d5d0a804999aa80ebae501c35742a01066a0320446ae85401cccd5407408dd69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b5d69aba15002302e357426ae8940088c98c80c0cd5ce01801881709aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a816bad35742a004605c6ae84d5d1280111931901819ab9c03003102e135573ca00226ea8004d5d09aba2500223263202c33573805805a05426aae7940044dd50009aba1500533501975c6ae854010ccd5407407c8004d5d0a801999aa80ebae200135742a00460426ae84d5d1280111931901419ab9c028029026135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00860226ae84d5d1280211931900d19ab9c01a01b0183010006375c00c26aae7940044dd5000990009aa80c1108911299a80089a80191000910999a802910011802001199aa9803890008028020008919118011bac001320013550182233335573e0024a034466a03260086ae84008c00cd5d1001009919191999ab9a3370e6aae7540092000233221233001003002300a35742a004600a6ae84d5d1280111931900919ab9c012013010135573ca00226ea80048c8c8c8c8cccd5cd19b8735573aa00890001199991110919998008028020018011919191999ab9a3370e6aae7540092000233221233001003002301335742a00466a01a0246ae84d5d1280111931900b99ab9c017018015135573ca00226ea8004d5d0a802199aa8043ae500735742a0066464646666ae68cdc3a800a4008464244460040086ae84d55cf280191999ab9a3370ea0049001119091118008021bae357426aae7940108cccd5cd19b875003480008488800c8c98c8064cd5ce00c80d00b80b00a89aab9d5001137540026ae854008cd4025d71aba135744a004464c6402666ae7004c0500444d5d1280089aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa02a44646666aae7c008940608cd405ccc8848cc00400c008c018d55cea80118029aab9e500230043574400602226ae84004488c8c8cccd5cd19b875001480008c8488c00800cc014d5d09aab9e500323333573466e1d40092002212200123263201033573802002201c01a26aae7540044dd5000919191999ab9a3370ea002900311909111180200298039aba135573ca00646666ae68cdc3a8012400846424444600400a60126ae84d55cf280211999ab9a3370ea006900111909111180080298039aba135573ca00a46666ae68cdc3a8022400046424444600600a6eb8d5d09aab9e500623263201033573802002201c01a01801626aae7540044dd5000919191999ab9a3370e6aae7540092000233221233001003002300535742a0046eb4d5d09aba2500223263200c33573801801a01426aae7940044dd50009191999ab9a3370e6aae75400520002375c6ae84d55cf280111931900519ab9c00a00b00813754002464646464646666ae68cdc3a800a401842444444400646666ae68cdc3a8012401442444444400846666ae68cdc3a801a40104664424444444660020120106eb8d5d0a8029bad357426ae8940148cccd5cd19b875004480188cc8848888888cc008024020dd71aba15007375c6ae84d5d1280391999ab9a3370ea00a900211991091111111980300480418061aba15009375c6ae84d5d1280491999ab9a3370ea00c900111909111111180380418069aba135573ca01646666ae68cdc3a803a400046424444444600a010601c6ae84d55cf280611931900999ab9c01301401101000f00e00d00c00b135573aa00826aae79400c4d55cf280109aab9e5001137540024646464646666ae68cdc3a800a4004466644424466600200a0080066eb4d5d0a8021bad35742a0066eb4d5d09aba2500323333573466e1d4009200023212230020033008357426aae7940188c98c8030cd5ce00600680500489aab9d5003135744a00226aae7940044dd5000919191999ab9a3370ea002900111909118008019bae357426aae79400c8cccd5cd19b875002480008c8488c00800cdd71aba135573ca008464c6401266ae7002402801c0184d55cea80089baa00112232323333573466e1d400520042122200123333573466e1d40092002232122230030043006357426aae7940108cccd5cd19b87500348000848880088c98c8028cd5ce00500580400380309aab9d5001137540024646666ae68cdc3a800a4004401446666ae68cdc3a801240004014464c6400c66ae7001801c01000c4d55ce9baa001499240103505431001200132001355006222533500110022213500222330073330080020060010033200135500522225335001100222135002225335333573466e1c005200000a0091333008007006003133300800733500b12333001008003002006003122002122001112200212212233001004003112323001001223300330020020014c01074643544c4e46540001" -} -""" - , "one-shot-minting-v2-unit" /\ - """ -{ - "type": "PlutusScriptV2", - "description": "", - "cborHex": "590934590931010000333233223322323232323232323232323232323232323232323222223232323232325335533533355300b12001323212330012233350052200200200100235001220011233001225335002102310010202325335333573466e3cd400488008d4014880080880844ccd5cd19b87350012200135005220010220211021350012200235500122222222222200c101f102013263201b3357389201115574786f206e6f7420636f6e73756d65640001c1533553355335323301e5023001355001222222222222008101f22135002222533500415335333573466e3c00cd401c88cccd40048c98c808ccd5ce2481024c680002420012326320233357389201024c68000242326320233357389201024c680002402502415335333573466e3c0080240940904ccd5cd19b870014800809409040904090884098407c40804c98c806ccd5ce24811357726f6e6720616d6f756e74206d696e7465640001c101c135001220023333573466e1cd55cea80224000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4064068d5d0a80619a80c80d1aba1500b33501901b35742a014666aa03aeb94070d5d0a804999aa80ebae501c35742a01066a0320446ae85401cccd5407408dd69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b5d69aba15002302e357426ae8940088c98c80c0cd5ce01801881709aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a816bad35742a004605c6ae84d5d1280111931901819ab9c03003102e135573ca00226ea8004d5d09aba2500223263202c33573805805a05426aae7940044dd50009aba1500533501975c6ae854010ccd5407407c8004d5d0a801999aa80ebae200135742a00460426ae84d5d1280111931901419ab9c028029026135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00860226ae84d5d1280211931900d19ab9c01a01b0183010006375c00c26aae7940044dd5000990009aa80c1108911299a80089a80191000910999a802910011802001199aa9803890008028020008919118011bac001320013550182233335573e0024a034466a03260086ae84008c00cd5d1001009919191999ab9a3370e6aae7540092000233221233001003002300a35742a004600a6ae84d5d1280111931900919ab9c012013010135573ca00226ea80048c8c8c8c8cccd5cd19b8735573aa00890001199991110919998008028020018011919191999ab9a3370e6aae7540092000233221233001003002301335742a00466a01a0246ae84d5d1280111931900b99ab9c017018015135573ca00226ea8004d5d0a802199aa8043ae500735742a0066464646666ae68cdc3a800a4008464244460040086ae84d55cf280191999ab9a3370ea0049001119091118008021bae357426aae7940108cccd5cd19b875003480008488800c8c98c8064cd5ce00c80d00b80b00a89aab9d5001137540026ae854008cd4025d71aba135744a004464c6402666ae7004c0500444d5d1280089aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa02a44646666aae7c008940608cd405ccc8848cc00400c008c018d55cea80118029aab9e500230043574400602226ae84004488c8c8cccd5cd19b875001480008c8488c00800cc014d5d09aab9e500323333573466e1d40092002212200123263201033573802002201c01a26aae7540044dd5000919191999ab9a3370ea002900311909111180200298039aba135573ca00646666ae68cdc3a8012400846424444600400a60126ae84d55cf280211999ab9a3370ea006900111909111180080298039aba135573ca00a46666ae68cdc3a8022400046424444600600a6eb8d5d09aab9e500623263201033573802002201c01a01801626aae7540044dd5000919191999ab9a3370e6aae7540092000233221233001003002300535742a0046eb4d5d09aba2500223263200c33573801801a01426aae7940044dd50009191999ab9a3370e6aae75400520002375c6ae84d55cf280111931900519ab9c00a00b00813754002464646464646666ae68cdc3a800a401842444444400646666ae68cdc3a8012401442444444400846666ae68cdc3a801a40104664424444444660020120106eb8d5d0a8029bad357426ae8940148cccd5cd19b875004480188cc8848888888cc008024020dd71aba15007375c6ae84d5d1280391999ab9a3370ea00a900211991091111111980300480418061aba15009375c6ae84d5d1280491999ab9a3370ea00c900111909111111180380418069aba135573ca01646666ae68cdc3a803a400046424444444600a010601c6ae84d55cf280611931900999ab9c01301401101000f00e00d00c00b135573aa00826aae79400c4d55cf280109aab9e5001137540024646464646666ae68cdc3a800a4004466644424466600200a0080066eb4d5d0a8021bad35742a0066eb4d5d09aba2500323333573466e1d4009200023212230020033008357426aae7940188c98c8030cd5ce00600680500489aab9d5003135744a00226aae7940044dd5000919191999ab9a3370ea002900111909118008019bae357426aae79400c8cccd5cd19b875002480008c8488c00800cdd71aba135573ca008464c6401266ae7002402801c0184d55cea80089baa00112232323333573466e1d400520042122200123333573466e1d40092002232122230030043006357426aae7940108cccd5cd19b87500348000848880088c98c8028cd5ce00500580400380309aab9d5001137540024646666ae68cdc3a800a4004401446666ae68cdc3a801240004014464c6400c66ae7001801c01000c4d55ce9baa001499240103505431001200132001355006222533500110022213500222330073330080020060010033200135500522225335001100222135002225335333573466e1c005200000a0091333008007006003133300800733500b12333001008003002006003122002122001112200212212233001004003112323001001223300330020020014c01074643544c4e4654004c0103d879800001" -} -""" - - , "redeemer1-validator" /\ - """ -{ - "description": "validator that checks whether redeemer is 1", - "cborHex": "4e4d0100002223375e0046ea120021", - "type": "PlutusScriptV1" -} -""" - , "redeemer1-validator-big-arg" /\ - """ -{ - "type": "PlutusScriptV1", - "description": "", - "cborHex": "58f058ee01000033333332223375e0046ea120024c010107004c0103d87980004c01089fd87980424d5fff004c01465f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dff004c0107a20507424d5f08004c0154d9055f9f079fd87980424d5f5f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dffffff004c0114d87e9f809f01ffa0a201d8798002d87b9f02ffff0001" -} -""" - , "redeemer1-validator-no-args" /\ - """ -{ - "type": "PlutusScriptV1", - "description": "", - "cborHex": "4e4d0100002223375e0046ea120021" -} -""" - , "redeemer1-validator-unit" /\ - """ -{ - "type": "PlutusScriptV1", - "description": "", - "cborHex": "565501000032223375e0046ea120024c0103d879800001" -} -""" - ] - -main :: Effect Unit -main = launchAff_ $ interpret $ suite - -contract :: Contract Unit -contract = do - traverse_ (uncurry $ compareApplied (v1 scriptSources)) $ Tuple - <$> v1ScriptPaths - <*> params - traverse_ (uncurry $ compareApplied (v2 scriptSources)) $ Tuple - <$> v2ScriptPaths - <*> params - -suite :: TestPlanM (Aff Unit) Unit -suite = group "Applying params to scripts test" $ do - traverse_ (uncurry $ testCase $ v1 scriptSources) - $ Tuple - <$> v1ScriptPaths - <*> params - traverse_ (uncurry $ testCase $ v2 scriptSources) - $ Tuple - <$> v2ScriptPaths - <*> params - where - testCase lang scriptName (args /\ argsName) = - test - ("Apply " <> argsName <> " to " <> scriptName) - $ compareApplied lang scriptName (args /\ argsName) - -compareApplied - :: forall (m :: Type -> Type) - . Monad m - => MonadError Error m - => (String -> m PlutusScript) - -> String - -> Tuple (Array PlutusData) String - -> m Unit -compareApplied lang scriptName (args /\ argsName) = do - script <- lang scriptName - applied <- liftEither $ left (error <<< show) $ applyArgs script args - appliedShouldBe <- lang (scriptName <> "-" <> argsName) - applied `shouldEqual` appliedShouldBe - -v1ScriptPaths :: Array String -v1ScriptPaths = - [ "always-fails" - , "include-datum" - , "one-shot-minting" - , "redeemer1-validator" - ] - -v2ScriptPaths :: Array String -v2ScriptPaths = - [ "always-succeeds-v2" - , "one-shot-minting-v2" - , "check-datum-is-inline" - ] - -params :: Array (Tuple (Array PlutusData) String) -params = - [ ([] /\ "no-args") - , ([ un ] /\ "unit") - , ( [ i 7 - , un - , List [ un, bytes ] - , longBytes - , Map [ (i 5 /\ i 7), (bytes /\ i 8) ] - , Constr (BigNum.fromInt 102) [ i 7, List [ un, bytes, longBytes ] ] - , Constr (BigNum.fromInt 5) - [ List [] - , List [ i 1 ] - , Map [] - , Map [ (i 1 /\ un), (i 2 /\ Constr (BigNum.fromInt 2) [ i 2 ]) ] - ] - ] /\ "big-arg" - ) - ] - -i :: Int -> PlutusData -i k = toData (fromInt k) - -un :: PlutusData -un = toData unit - -bytes :: PlutusData -bytes = Bytes $ hexToByteArrayUnsafe "4d5f" - -longBytes :: PlutusData -longBytes = Bytes $ hexToByteArrayUnsafe $ foldl (\x y -> x <> y) "" $ - replicate 65 "4d" - -v1 - :: forall (m :: Type -> Type) - . MonadError Error m - => Object String - -> String - -> m PlutusScript -v1 scripts name = lookupAux plutusScriptFromEnvelope scripts name - -v2 - :: forall (m :: Type -> Type) - . MonadError Error m - => Object String - -> String - -> m PlutusScript -v2 scripts name = lookupAux plutusScriptFromEnvelope scripts name - -lookupAux - :: forall (m :: Type -> Type) - . MonadError Error m - => (TextEnvelope -> Maybe PlutusScript) - -> Object String - -> String - -> m PlutusScript -lookupAux decodeScript scripts name = - maybe (throwError $ error $ "Can't find the script with name " <> name) pure - $ do - txt <- Object.lookup name scripts - envelope <- decodeTextEnvelope txt - decodeScript envelope diff --git a/test/Plutip/Contract.purs b/test/Plutip/Contract.purs index ea91f84bd2..1bdeb80aad 100644 --- a/test/Plutip/Contract.purs +++ b/test/Plutip/Contract.purs @@ -5,6 +5,7 @@ module Test.Ctl.Plutip.Contract import Prelude import Cardano.AsCbor (decodeCbor) +import Cardano.Plutus.ApplyArgs (applyArgs) import Cardano.Serialization.Lib (fromBytes) import Cardano.Types ( Address @@ -59,7 +60,6 @@ import Contract.Prim.ByteArray import Contract.ScriptLookups as Lookups import Contract.Scripts ( ValidatorHash - , applyArgs , getScriptByHash , getScriptsByHashes , validatorHash diff --git a/test/Unit.purs b/test/Unit.purs index c7882764b2..ad0a36d3d8 100644 --- a/test/Unit.purs +++ b/test/Unit.purs @@ -11,7 +11,6 @@ import Effect (Effect) import Effect.Aff (Aff, cancelWith, effectCanceler, launchAff) import Effect.Class (liftEffect) import Mote.Monad (mapTest) -import Test.Ctl.ApplyArgs as ApplyArgs import Test.Ctl.Blockfrost.Aeson.Suite as Blockfrost.Aeson import Test.Ctl.Blockfrost.ProtocolParameters as Blockfrost.ProtocolParameters import Test.Ctl.CoinSelection as CoinSelection @@ -47,7 +46,6 @@ main = interruptOnSignal SIGINT =<< launchAff do testPlan :: TestPlanM (Aff Unit) Unit testPlan = do - ApplyArgs.suite Ipv6.suite NativeScript.suite Bip32.suite From 25bf6b79699598b2d18649c217ba69adbb984a03 Mon Sep 17 00:00:00 2001 From: Marcus Fernandes Date: Thu, 27 Jun 2024 11:06:56 -0300 Subject: [PATCH 18/52] Remove `applyArgs` E2E tests --- test/e2e-ci.env | 1 - test/e2e.env | 2 -- 2 files changed, 3 deletions(-) diff --git a/test/e2e-ci.env b/test/e2e-ci.env index 54a8bc2e86..e20d01d91a 100644 --- a/test/e2e-ci.env +++ b/test/e2e-ci.env @@ -10,5 +10,4 @@ plutip:http://localhost:4008/?plutip-nami-mock:SendsToken plutip:http://localhost:4008/?plutip-nami-mock:MintsMultipleTokens plutip:http://localhost:4008/?plutip-nami-mock:Schnorr plutip:http://localhost:4008/?plutip-nami-mock:ECDSA -plutip:http://localhost:4008/?plutip-nami-mock:ApplyArgs " diff --git a/test/e2e.env b/test/e2e.env index 8b0cc2d87f..7473508716 100755 --- a/test/e2e.env +++ b/test/e2e.env @@ -10,8 +10,6 @@ plutip:http://localhost:4008/?plutip-nami-mock:AlwaysMints plutip:http://localhost:4008/?plutip-nami-mock:Pkh2Pkh plutip:http://localhost:4008/?plutip-nami-mock:SendsToken plutip:http://localhost:4008/?plutip-nami-mock:MintsMultipleTokens -# This test does not depend on wallets, we only check that bundling is correct -plutip:http://localhost:4008/?plutip-nami-mock:ApplyArgs # If you add plutip tests above, please also add them to ./e2e-ci.env nami:http://localhost:4008/?nami:Schnorr From 7cd798fc8b022e2c66df0b9c3824e120052272d0 Mon Sep 17 00:00:00 2001 From: Marcus Fernandes Date: Thu, 27 Jun 2024 11:24:11 -0300 Subject: [PATCH 19/52] Fix typos --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e8bbf623b..ce57a34e29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -411,7 +411,7 @@ Then consult with [the template's build scripts](./templates/ctl-scaffold/esbuil - `startPlutipCluster` error message now includes cluster startup failure details. ([#1407](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1407)) - `PlutipTest` is now known as `Contract.Test.ContractTest`. It has been semantically untied from Plutip, because we now have another test runner for tests that rely on particular funds distributions - [Blockfrost](./doc/blockfrost.md). See `Contract.Test.Blockfrost.runContractTestsWithBlockfrost` ([#1260](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1260)) - `Contract.Staking.getPoolParameters` has been moved to `Contract.Backend.Ogmios.getPoolParameters`. This function only runs with Ogmios backend, because Blockfrost [does not provide](https://github.com/blockfrost/blockfrost-backend-ryo/issues/82) all the required values ([#1260](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1260)) -- Use of [CIP-40](https://chips.cardano.org/cip/CIP-0040/) collateral output is now enabled with CIP-30 wallets ([#1260](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1260)). +- Use of [CIP-40](https://cips.cardano.org/cip/CIP-0040/) collateral output is now enabled with CIP-30 wallets ([#1260](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1260)). - `reindexSpentScriptRedeemers` is no longer in Contract (it's pure) ([#1260](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1260)) ### Removed @@ -468,7 +468,7 @@ Then consult with [the template's build scripts](./templates/ctl-scaffold/esbuil ### Fixed -- Added missing `stakePoolTargetNum` ("`nOpt`") protocol parameter (see [CIP-9](https://chips.cardano.org/cip/CIP-0009)) ([#571](https://github.com/Plutonomicon/cardano-transaction-lib/issues/571)) +- Added missing `stakePoolTargetNum` ("`nOpt`") protocol parameter (see [CIP-9](https://cips.cardano.org/cip/CIP-0009)) ([#571](https://github.com/Plutonomicon/cardano-transaction-lib/issues/571)) - CIP-30 `signData` response handling ([#1289](https://github.com/Plutonomicon/cardano-transaction-lib/pull/1289)) ### Runtime Dependencies @@ -623,7 +623,7 @@ Then consult with [the template's build scripts](./templates/ctl-scaffold/esbuil - Constraint for attaching a reference input to a transaction: `mustReferenceOutput` ([#946](https://github.com/Plutonomicon/cardano-transaction-lib/pull/946)) - `DatumPresence` data type, which tags paying constraints that accept datum, to mark whether the datum should be inline or hashed in the transaction output. ([#931](https://github.com/Plutonomicon/cardano-transaction-lib/pull/931)) - Utility conversion functions `serializeData` and `deserializeData` between `PlutusData` and `CborBytes` to `Contract.PlutusData`. ([#1001](https://github.com/Plutonomicon/cardano-transaction-lib/issues/1001)) -- Added [CIP-30](https://chips.cardano.org/cip/CIP-0030) methods: `getNetworkId`, `getChangeAddress`, `getRewardAddresses`, `getUnusedAddresses`, `signData`, `isWalletAvailable`, `isEnabled`, `apiVersion`, `name` and `icon` to `Contract.Wallet` ([#974](https://github.com/Plutonomicon/cardano-transaction-lib/issues/974)) +- Added [CIP-30](https://cips.cardano.org/cip/CIP-0030) methods: `getNetworkId`, `getChangeAddress`, `getRewardAddresses`, `getUnusedAddresses`, `signData`, `isWalletAvailable`, `isEnabled`, `apiVersion`, `name` and `icon` to `Contract.Wallet` ([#974](https://github.com/Plutonomicon/cardano-transaction-lib/issues/974)) ### Changed @@ -676,7 +676,7 @@ Then consult with [the template's build scripts](./templates/ctl-scaffold/esbuil - We do not split strings in pieces when encoding to JSON - We require a `"version": 2` tag - `policy_id` must be 28 bytes - - `asset_name` is up to 32 bytes. See https://github.com/cardano-foundation/chips/issues/303 for motivation + - `asset_name` is up to 32 bytes. See https://github.com/cardano-foundation/CIPs/issues/303 for motivation - `ogmios-datum-cache` now works on `x86_64-darwin` - `TypedValidator` interface ([#808](https://github.com/Plutonomicon/cardano-transaction-lib/issues/808)) - `Contract.Address.getWalletCollateral` now works with `KeyWallet`. From baa9b8070b2d4558f6d6fc5cc2eae79daf712b66 Mon Sep 17 00:00:00 2001 From: Marcus Fernandes Date: Thu, 27 Jun 2024 11:24:38 -0300 Subject: [PATCH 20/52] Update references to `Cardano.Plutus.ApplyArgs` --- doc/plutus-comparison.md | 2 +- examples/OneShotMinting.purs | 3 ++- examples/PlutusV2/OneShotMinting.purs | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/plutus-comparison.md b/doc/plutus-comparison.md index 425727f6ee..603df9dc82 100644 --- a/doc/plutus-comparison.md +++ b/doc/plutus-comparison.md @@ -135,7 +135,7 @@ As noted above, all scripts and various script newtypes (`Validator`, `MintingPo #### Applying arguments to parameterized scripts -We support applying arguments to parameterized scripts with `Contract.Scripts.applyArgs`. It allows you to apply a list of `PlutusData` arguments to a `PlutusScript`. Using this allows you to dynamically apply arguments during contract execution, but also implies the following: +We support applying arguments to parameterized scripts with `Cardano.Plutus.ApplyArgs.applyArgs` (from [purescript-uplc-apply-args](https://github.com/mlabs-haskell/purescript-uplc-apply-args)). It allows you to apply a list of `PlutusData` arguments to a `PlutusScript`. Using this allows you to dynamically apply arguments during contract execution, but also implies the following: - All of your domain types must have `Contract.PlutusData.ToData` instances (or some other way of converting them to `PlutusData`) - You must employ a workaround, illustrated by the following examples, in your off-chain code to ensure that the applied scripts are valid for both on- and off-chain code. This essentially consists of creating an wrapper which accepts `Data` arguments for your parameterized scripts: diff --git a/examples/OneShotMinting.purs b/examples/OneShotMinting.purs index 3b8a83485a..c0162edd61 100644 --- a/examples/OneShotMinting.purs +++ b/examples/OneShotMinting.purs @@ -1,4 +1,5 @@ --- | This module demonstrates how `applyArgs` from `Contract.Scripts` can be +-- | This module demonstrates how `applyArgs` from `Cardano.Plutus.ApplyArgs` +-- | (from https://github.com/mlabs-haskell/purescript-uplc-apply-args) can be -- | used to build scripts with the provided arguments applied. It creates a -- | transaction that mints an NFT using the one-shot minting policy. module Ctl.Examples.OneShotMinting diff --git a/examples/PlutusV2/OneShotMinting.purs b/examples/PlutusV2/OneShotMinting.purs index c722a93664..41b3188e22 100644 --- a/examples/PlutusV2/OneShotMinting.purs +++ b/examples/PlutusV2/OneShotMinting.purs @@ -1,4 +1,5 @@ --- | This module demonstrates how `applyArgs` from `Contract.Scripts` can be +-- | This module demonstrates how `applyArgs` from `Cardano.Plutus.ApplyArgs` +-- | (from https://github.com/mlabs-haskell/purescript-uplc-apply-args) can be -- | used to build PlutusV2 scripts with the provided arguments applied. It -- | creates a transaction that mints an NFT using the one-shot minting policy. module Ctl.Examples.PlutusV2.OneShotMinting From 61e347a0b4c920a43f67bd9752a9ba58519722ad Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Thu, 27 Jun 2024 00:06:00 +0400 Subject: [PATCH 21/52] WIP: tie together the new constaints interface & balancer --- examples/AdditionalUtxos.purs | 13 +- examples/BalanceTxConstraints.purs | 6 +- examples/ChangeGeneration.purs | 5 +- examples/ContractTestUtils.purs | 3 +- examples/KeyWallet/SignMultiple.purs | 21 +- examples/OneShotMinting.purs | 36 +- examples/PlutusV2/ReferenceInputs.purs | 5 +- examples/SignMultiple.purs | 21 +- examples/TxChaining.purs | 7 +- packages.dhall | 2 +- spago.dhall | 1 + src/Contract/AuxiliaryData.purs | 54 +-- src/Contract/Constraints.purs | 20 +- src/Contract/PlutusData.purs | 6 +- src/Contract/ScriptLookups.purs | 1 - src/Contract/Transaction.purs | 199 ++++----- src/Contract/UnbalancedTx.purs | 35 +- src/Internal/BalanceTx/BalanceTx.purs | 118 +++--- src/Internal/BalanceTx/Error.purs | 31 +- src/Internal/BalanceTx/ExUnitsAndMinFee.purs | 74 ++-- src/Internal/BalanceTx/RedeemerIndex.purs | 175 -------- src/Internal/BalanceTx/Types.purs | 5 +- src/Internal/BalanceTx/UnattachedTx.purs | 54 --- src/Internal/Lens.purs | 4 + src/Internal/Plutip/Server.purs | 3 +- src/Internal/ProcessConstraints.purs | 94 ++--- src/Internal/ProcessConstraints/Error.purs | 6 + src/Internal/ProcessConstraints/State.purs | 6 +- .../ProcessConstraints/UnbalancedTx.purs | 30 -- src/Internal/Test/KeyDir.purs | 2 +- src/Internal/Test/UtxoDistribution.purs | 2 +- src/Internal/Types/RedeemerDatum.purs | 27 -- src/Internal/Types/TxConstraints.purs | 4 +- src/Internal/UseConstraints.purs | 379 ------------------ test/BalanceTx/Time.purs | 14 +- test/Fixtures.purs | 2 +- test/Plutip.purs | 5 +- test/Plutip/Common.purs | 2 +- test/Plutip/Contract.purs | 125 +++--- test/Plutip/Staking.purs | 49 ++- test/Utils/DrainWallets.purs | 2 +- 41 files changed, 453 insertions(+), 1195 deletions(-) delete mode 100644 src/Internal/BalanceTx/RedeemerIndex.purs delete mode 100644 src/Internal/BalanceTx/UnattachedTx.purs delete mode 100644 src/Internal/ProcessConstraints/UnbalancedTx.purs delete mode 100644 src/Internal/Types/RedeemerDatum.purs delete mode 100644 src/Internal/UseConstraints.purs diff --git a/examples/AdditionalUtxos.purs b/examples/AdditionalUtxos.purs index c3979ea619..9431ba1549 100644 --- a/examples/AdditionalUtxos.purs +++ b/examples/AdditionalUtxos.purs @@ -5,6 +5,7 @@ module Ctl.Examples.AdditionalUtxos import Contract.Prelude +import Cardano.Types (Transaction) import Cardano.Types.BigNum as BigNum import Cardano.Types.Credential (Credential(ScriptHashCredential)) import Cardano.Types.PlutusScript as PlutusScript @@ -15,7 +16,7 @@ import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) import Contract.PlutusData (Datum, PlutusData(Integer), unitRedeemer) -import Contract.ScriptLookups (ScriptLookups, UnbalancedTx) +import Contract.ScriptLookups (ScriptLookups) import Contract.ScriptLookups (datum, unspentOutputs, validator) as Lookups import Contract.Scripts (Validator, ValidatorHash, validatorHash) import Contract.Sync (withoutSync) @@ -23,7 +24,7 @@ import Contract.Transaction ( ScriptRef(NativeScriptRef) , TransactionInput , awaitTxConfirmed - , balanceTxWithConstraints + , balanceTx , createAdditionalUtxos , signTransaction , submit @@ -45,7 +46,7 @@ import Contract.Value (Value) import Contract.Value (lovelaceValueOf) as Value import Ctl.Examples.PlutusV2.Scripts.AlwaysSucceeds (alwaysSucceedsScriptV2) import Data.Array (fromFoldable) as Array -import Data.Map (difference, filter, keys) as Map +import Data.Map (difference, empty, filter, keys) as Map import JS.BigInt (fromInt) as BigInt import Test.QuickCheck (arbitrary) import Test.QuickCheck.Gen (randomSampleOne) @@ -63,7 +64,7 @@ contract testAdditionalUtxoOverlap = withoutSync do validator <- alwaysSucceedsScriptV2 let vhash = validatorHash validator { unbalancedTx, datum } <- payToValidator vhash - withBalancedTx unbalancedTx \balancedTx -> do + withBalancedTx unbalancedTx Map.empty mempty \balancedTx -> do balancedSignedTx <- signTransaction balancedTx txHash <- submit balancedSignedTx when testAdditionalUtxoOverlap $ awaitTxConfirmed txHash @@ -73,7 +74,7 @@ contract testAdditionalUtxoOverlap = withoutSync do spendFromValidator validator additionalUtxos datum payToValidator - :: ValidatorHash -> Contract { unbalancedTx :: UnbalancedTx, datum :: Datum } + :: ValidatorHash -> Contract { unbalancedTx :: Transaction, datum :: Datum } payToValidator vhash = do scriptRef <- liftEffect (NativeScriptRef <$> randomSampleOne arbitrary) let @@ -128,7 +129,7 @@ spendFromValidator validator additionalUtxos datum = do BalancerConstraints.mustUseAdditionalUtxos additionalUtxos unbalancedTx <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTxWithConstraints unbalancedTx balancerConstraints + balancedTx <- balanceTx unbalancedTx Map.empty balancerConstraints balancedSignedTx <- signTransaction balancedTx txHash <- submit balancedSignedTx diff --git a/examples/BalanceTxConstraints.purs b/examples/BalanceTxConstraints.purs index ec09ded576..5d597b47b1 100644 --- a/examples/BalanceTxConstraints.purs +++ b/examples/BalanceTxConstraints.purs @@ -35,7 +35,7 @@ import Contract.Transaction ( TransactionHash , TransactionInput , awaitTxConfirmed - , balanceTxWithConstraints + , balanceTx , signTransaction , submit ) @@ -56,7 +56,7 @@ import Ctl.Examples.AlwaysMints (alwaysMintsPolicy) import Ctl.Examples.Helpers (mkAssetName) as Helpers import Data.Array (head) import Data.Array (sort) as Array -import Data.Map (fromFoldable, keys, member) as Map +import Data.Map (empty, fromFoldable, keys, member) as Map import Data.Set (findMin) as Set import JS.BigInt as BigInt @@ -178,7 +178,7 @@ contract (ContractParams p) = do void $ runChecks checks $ lift do unbalancedTx <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTxWithConstraints unbalancedTx balanceTxConstraints + balancedTx <- balanceTx unbalancedTx Map.empty balanceTxConstraints balancedSignedTx <- (withKeyWallet p.bobKeyWallet <<< signTransaction) diff --git a/examples/ChangeGeneration.purs b/examples/ChangeGeneration.purs index 5942b72a18..5553352120 100644 --- a/examples/ChangeGeneration.purs +++ b/examples/ChangeGeneration.purs @@ -16,7 +16,7 @@ import Contract.Transaction ( _body , _outputs , awaitTxConfirmed - , balanceTxWithConstraints + , balanceTx , signTransaction , submit ) @@ -28,6 +28,7 @@ import Contract.Wallet (ownPaymentPubKeyHashes, ownStakePubKeyHashes) import Ctl.Examples.AlwaysSucceeds as AlwaysSucceeds import Data.Array (fold, length, replicate, take, zip) import Data.Lens ((^.)) +import Data.Map as Map import Data.Maybe (Maybe(Just, Nothing)) import Data.Tuple (Tuple(Tuple)) import JS.BigInt (fromInt) as BigInt @@ -64,7 +65,7 @@ checkChangeOutputsDistribution outputsToScript outputsToSelf expectedOutputs = lookups :: Lookups.ScriptLookups lookups = mempty unbalancedTx <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTxWithConstraints unbalancedTx + balancedTx <- balanceTx unbalancedTx Map.empty -- just to check that attaching datums works ( mustSendChangeWithDatum $ OutputDatum $ Integer $ BigInt.fromInt 1000 diff --git a/examples/ContractTestUtils.purs b/examples/ContractTestUtils.purs index 7760389535..aa8b09b520 100644 --- a/examples/ContractTestUtils.purs +++ b/examples/ContractTestUtils.purs @@ -63,6 +63,7 @@ import Contract.Wallet import Ctl.Examples.Helpers (mustPayToPubKeyStakeAddress) as Helpers import Data.Array (head) import Data.Lens (_1, _2, view, (%~)) +import Data.Map as Map import Effect.Exception (throw) type ContractParams = @@ -159,7 +160,7 @@ mkContract p = do lookups = Lookups.plutusMintingPolicy p.mintingPolicy unbalancedTx <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTx unbalancedTx + balancedTx <- balanceTx unbalancedTx Map.empty mempty balancedSignedTx <- signTransaction balancedTx txId <- submit balancedSignedTx diff --git a/examples/KeyWallet/SignMultiple.purs b/examples/KeyWallet/SignMultiple.purs index 6c944cbde3..73ed83292b 100644 --- a/examples/KeyWallet/SignMultiple.purs +++ b/examples/KeyWallet/SignMultiple.purs @@ -19,6 +19,7 @@ import Contract.Value (lovelaceValueOf) as Value import Control.Monad.Reader (asks) import Ctl.Examples.KeyWallet.Internal.Pkh2PkhContract (runKeyWalletContract_) import Data.Map (Map) +import Data.Map as Map import Data.Newtype (unwrap) import Data.Set (Set) import Data.UInt (UInt) @@ -45,11 +46,21 @@ main = runKeyWalletContract_ \pkh lovelace unlock -> do unbalancedTx0 <- mkUnbalancedTx lookups constraints unbalancedTx1 <- mkUnbalancedTx lookups constraints - txIds <- withBalancedTxs [ unbalancedTx0, unbalancedTx1 ] $ \balancedTxs -> do - locked <- getLockedInputs - logInfo' $ "Locked inputs inside bracket (should be nonempty): " - <> show locked - traverse (submitAndLog <=< signTransaction) balancedTxs + txIds <- + withBalancedTxs + [ { transaction: unbalancedTx0 + , extraUtxos: Map.empty + , balancerConstraints: mempty + } + , { transaction: unbalancedTx1 + , extraUtxos: Map.empty + , balancerConstraints: mempty + } + ] $ \balancedTxs -> do + locked <- getLockedInputs + logInfo' $ "Locked inputs inside bracket (should be nonempty): " + <> show locked + traverse (submitAndLog <=< signTransaction) balancedTxs locked <- getLockedInputs logInfo' $ "Locked inputs after bracket (should be empty): " <> show locked diff --git a/examples/OneShotMinting.purs b/examples/OneShotMinting.purs index 0ed28bc989..72af40ca7b 100644 --- a/examples/OneShotMinting.purs +++ b/examples/OneShotMinting.purs @@ -12,10 +12,12 @@ module Ctl.Examples.OneShotMinting import Contract.Prelude +import Cardano.Types (Coin, TransactionHash, UtxoMap, _body, _fee) import Cardano.Types.BigNum as BigNum import Cardano.Types.Int as Int import Cardano.Types.Mint as Mint import Cardano.Types.PlutusScript as PlutusScript +import Contract.BalanceTxConstraints (BalanceTxConstraintsBuilder) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad @@ -27,6 +29,7 @@ import Contract.Monad , runContract ) import Contract.PlutusData (PlutusData, toData) +import Contract.ScriptLookups (ScriptLookups) import Contract.ScriptLookups as Lookups import Contract.Scripts (PlutusScript, applyArgs) import Contract.Test.Assert @@ -35,23 +38,25 @@ import Contract.Test.Assert , checkTokenGainInWallet' , runChecks ) -import Contract.TextEnvelope - ( decodeTextEnvelope - , plutusScriptFromEnvelope - ) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( TransactionInput , awaitTxConfirmed - , submitTxFromConstraintsReturningFee + , balanceTx + , signTransaction + , submit ) +import Contract.TxConstraints (TxConstraints) import Contract.TxConstraints as Constraints +import Contract.UnbalancedTx (mkUnbalancedTx) import Contract.Value (AssetName, ScriptHash) import Contract.Wallet (getWalletUtxos) import Control.Monad.Error.Class (liftMaybe) import Control.Monad.Trans.Class (lift) import Ctl.Examples.Helpers (mkAssetName) as Helpers import Data.Array (head, singleton) as Array -import Data.Map (toUnfoldable) as Map +import Data.Lens (view) +import Data.Map (empty, toUnfoldable) as Map import Effect.Exception (error, throw) import JS.BigInt (BigInt) @@ -107,12 +112,29 @@ mkContractWithAssertions exampleName mkMintingPolicy = do let checks = mkChecks (cs /\ tn /\ one) void $ runChecks checks $ lift do { txHash, txFinalFee } <- - submitTxFromConstraintsReturningFee lookups constraints + submitTxFromConstraintsReturningFee lookups constraints Map.empty mempty logInfo' $ "Tx ID: " <> show txHash awaitTxConfirmed txHash logInfo' "Tx submitted successfully!" pure { txFinalFee: BigNum.toBigInt $ unwrap txFinalFee } +submitTxFromConstraintsReturningFee + :: ScriptLookups + -> TxConstraints + -> UtxoMap + -> BalanceTxConstraintsBuilder + -> Contract { txHash :: TransactionHash, txFinalFee :: Coin } +submitTxFromConstraintsReturningFee + lookups + constraints + extraUtxos + balancerConstraints = do + unbalancedTx <- mkUnbalancedTx lookups constraints + balancedTx <- balanceTx unbalancedTx extraUtxos balancerConstraints + balancedSignedTx <- signTransaction balancedTx + txHash <- submit balancedSignedTx + pure { txHash, txFinalFee: view (_body <<< _fee) balancedSignedTx } + oneShotMintingPolicyScript :: TransactionInput -> Contract PlutusScript oneShotMintingPolicyScript txInput = do script <- liftMaybe (error "Error decoding oneShotMinting") do diff --git a/examples/PlutusV2/ReferenceInputs.purs b/examples/PlutusV2/ReferenceInputs.purs index cf75d955b3..c01672101f 100644 --- a/examples/PlutusV2/ReferenceInputs.purs +++ b/examples/PlutusV2/ReferenceInputs.purs @@ -42,7 +42,7 @@ import Control.Monad.Trans.Class (lift) import Ctl.Examples.Helpers (mustPayToPubKeyStakeAddress) as Helpers import Data.Array (elem, head) as Array import Data.Lens.Getter ((^.)) -import Data.Map (member, toUnfoldable) as Map +import Data.Map (empty, member, toUnfoldable) as Map main :: Effect Unit main = example testnetNamiConfig @@ -76,7 +76,8 @@ contract = do void $ runChecks checks $ lift do unbalancedTx <- mkUnbalancedTx lookups constraints - balancedSignedTx <- signTransaction =<< balanceTx unbalancedTx + balancedSignedTx <- signTransaction =<< balanceTx unbalancedTx Map.empty + mempty txHash <- submit balancedSignedTx logInfo' $ "Tx ID: " <> show txHash awaitTxConfirmed txHash diff --git a/examples/SignMultiple.purs b/examples/SignMultiple.purs index 2d5ddc3de5..1f371a856b 100644 --- a/examples/SignMultiple.purs +++ b/examples/SignMultiple.purs @@ -38,6 +38,7 @@ import Contract.Wallet import Control.Monad.Reader (asks) import Data.Array (head) import Data.Map (Map, filter) +import Data.Map as Map import Data.Set (Set) import Data.UInt (UInt) import Effect.Ref as Ref @@ -75,11 +76,21 @@ contract = do unbalancedTx0 <- mkUnbalancedTx lookups constraints unbalancedTx1 <- mkUnbalancedTx lookups constraints - txIds <- withBalancedTxs [ unbalancedTx0, unbalancedTx1 ] $ \balancedTxs -> do - locked <- getLockedInputs - logInfo' $ "Locked inputs inside bracket (should be nonempty): " - <> show locked - traverse (submitAndLog <=< signTransaction) balancedTxs + txIds <- + withBalancedTxs + [ { transaction: unbalancedTx0 + , extraUtxos: Map.empty + , balancerConstraints: mempty + } + , { transaction: unbalancedTx1 + , extraUtxos: Map.empty + , balancerConstraints: mempty + } + ] $ \balancedTxs -> do + locked <- getLockedInputs + logInfo' $ "Locked inputs inside bracket (should be nonempty): " + <> show locked + traverse (submitAndLog <=< signTransaction) balancedTxs locked <- getLockedInputs logInfo' $ "Locked inputs after bracket (should be empty): " <> show locked diff --git a/examples/TxChaining.purs b/examples/TxChaining.purs index 7a4c53a0cf..f923869eac 100644 --- a/examples/TxChaining.purs +++ b/examples/TxChaining.purs @@ -21,7 +21,7 @@ import Contract.Monad (Contract, launchAff_, liftedM, runContract) import Contract.ScriptLookups as Lookups import Contract.Transaction ( awaitTxConfirmed - , balanceTxWithConstraints + , balanceTx , createAdditionalUtxos , signTransaction , submit @@ -33,6 +33,7 @@ import Contract.UnbalancedTx (mkUnbalancedTx) import Contract.Value as Value import Contract.Wallet (ownPaymentPubKeyHashes) import Data.Array (head) +import Data.Map as Map main :: Effect Unit main = example testnetNamiConfig @@ -55,7 +56,7 @@ contract = do unbalancedTx0 <- mkUnbalancedTx lookups0 constraints - withBalancedTx unbalancedTx0 \balancedTx0 -> do + withBalancedTx unbalancedTx0 Map.empty mempty \balancedTx0 -> do balancedSignedTx0 <- signTransaction balancedTx0 additionalUtxos <- createAdditionalUtxos balancedSignedTx0 @@ -70,7 +71,7 @@ contract = do BalanceTxConstraints.mustUseAdditionalUtxos additionalUtxos unbalancedTx1 <- mkUnbalancedTx lookups1 constraints - balancedTx1 <- balanceTxWithConstraints unbalancedTx1 balanceTxConstraints + balancedTx1 <- balanceTx unbalancedTx1 Map.empty balanceTxConstraints balancedSignedTx1 <- signTransaction balancedTx1 txId0 <- submit balancedSignedTx0 diff --git a/packages.dhall b/packages.dhall index 459932df51..a7021ff19d 100644 --- a/packages.dhall +++ b/packages.dhall @@ -362,7 +362,7 @@ let additions = , "unsafe-coerce" ] , repo = "https://github.com/mlabs-haskell/purescript-cardano-types" - , version = "v1.0.1" + , version = "40d9468a4712ad2bf57ebede19fae92208f082a0" } , cardano-message-signing = { dependencies = diff --git a/spago.dhall b/spago.dhall index 3fa172ac8a..c1d1836443 100644 --- a/spago.dhall +++ b/spago.dhall @@ -110,5 +110,6 @@ You can edit this file as you like. , "templates/ctl-scaffold/src/**/*.purs" , "templates/ctl-scaffold/test/**/*.purs" , "templates/ctl-scaffold/exe/**/*.purs" + , "../purescript-cardano-transaction-builder/src/**/*.purs" ] } diff --git a/src/Contract/AuxiliaryData.purs b/src/Contract/AuxiliaryData.purs index 9f98626b2b..3edf6ae83b 100644 --- a/src/Contract/AuxiliaryData.purs +++ b/src/Contract/AuxiliaryData.purs @@ -8,73 +8,51 @@ module Contract.AuxiliaryData import Prelude import Cardano.Types - ( AuxiliaryData(AuxiliaryData) - , AuxiliaryDataHash + ( AuxiliaryData , GeneralTransactionMetadata , Transaction + , _auxiliaryData + , _auxiliaryDataHash + , _body ) import Cardano.Types.AuxiliaryData (hashAuxiliaryData) -import Ctl.Internal.Lens (_auxiliaryData, _auxiliaryDataHash, _body) as Tx import Ctl.Internal.Metadata.MetadataType ( class MetadataType , toGeneralTxMetadata ) -import Ctl.Internal.ProcessConstraints.UnbalancedTx (UnbalancedTx) -import Data.Lens (lens', (.~), (?~)) +import Data.Lens ((.~), (?~)) import Data.Lens.Getter (view) import Data.Lens.Iso.Newtype (_Newtype) import Data.Lens.Record (prop) -import Data.Lens.Types (Lens') import Data.Maybe (Maybe(Just), fromMaybe) -import Data.Tuple (Tuple(Tuple)) import Type.Proxy (Proxy(Proxy)) setAuxiliaryData - :: UnbalancedTx + :: Transaction -> AuxiliaryData - -> UnbalancedTx + -> Transaction setAuxiliaryData tx auxData = - let - auxDataHash = hashAuxiliaryData auxData - in - tx # _auxiliaryData .~ Just auxData - # _auxiliaryDataHash ?~ auxDataHash + tx # _auxiliaryData .~ Just auxData + # _body <<< _auxiliaryDataHash ?~ hashAuxiliaryData auxData setGeneralTxMetadata - :: UnbalancedTx + :: Transaction -> GeneralTransactionMetadata - -> UnbalancedTx + -> Transaction setGeneralTxMetadata tx generalMetadata = let auxData = view _auxiliaryData tx in setAuxiliaryData tx - (fromMaybe mempty auxData # _metadata ?~ generalMetadata) + ( fromMaybe mempty auxData # + _Newtype <<< prop (Proxy :: Proxy "metadata") ?~ generalMetadata + ) setTxMetadata :: forall (m :: Type) . MetadataType m - => UnbalancedTx + => Transaction -> m - -> UnbalancedTx + -> Transaction setTxMetadata tx = setGeneralTxMetadata tx <<< toGeneralTxMetadata - --------------------------------------------------------------------------------- --- Lenses --------------------------------------------------------------------------------- - -_transaction :: Lens' UnbalancedTx Transaction -_transaction = _Newtype <<< prop (Proxy :: Proxy "transaction") - -_auxiliaryData :: Lens' UnbalancedTx (Maybe AuxiliaryData) -_auxiliaryData = - _Newtype <<< prop (Proxy :: Proxy "transaction") <<< Tx._auxiliaryData - -_auxiliaryDataHash :: Lens' UnbalancedTx (Maybe AuxiliaryDataHash) -_auxiliaryDataHash = - _transaction <<< Tx._body <<< Tx._auxiliaryDataHash - -_metadata :: Lens' AuxiliaryData (Maybe GeneralTransactionMetadata) -_metadata = lens' \(AuxiliaryData rec@{ metadata }) -> - Tuple metadata \md -> AuxiliaryData rec { metadata = md } diff --git a/src/Contract/Constraints.purs b/src/Contract/Constraints.purs index c7b2dbc3fc..d9c7cd73eb 100644 --- a/src/Contract/Constraints.purs +++ b/src/Contract/Constraints.purs @@ -3,21 +3,24 @@ module Contract.Constraints where import Prelude import Cardano.Types (Slot) +import Cardano.Types.AssetName (AssetName) import Cardano.Types.Certificate (Certificate) import Cardano.Types.Coin (Coin) import Cardano.Types.Epoch (Epoch) +import Cardano.Types.Int as Int import Cardano.Types.NativeScript (NativeScript) import Cardano.Types.PaymentPubKeyHash (PaymentPubKeyHash) import Cardano.Types.PlutusData (PlutusData) import Cardano.Types.PlutusScript (PlutusScript) import Cardano.Types.PoolParams (PoolParams) import Cardano.Types.PoolPubKeyHash (PoolPubKeyHash) +import Cardano.Types.RedeemerDatum (RedeemerDatum) +import Cardano.Types.ScriptHash (ScriptHash) import Cardano.Types.StakeCredential (StakeCredential) import Cardano.Types.StakePubKeyHash (StakePubKeyHash) import Cardano.Types.TransactionInput (TransactionInput) import Cardano.Types.TransactionOutput (TransactionOutput) import Cardano.Types.TransactionUnspentOutput (TransactionUnspentOutput) -import Ctl.Internal.Types.RedeemerDatum (RedeemerDatum) import Data.Generic.Rep (class Generic) import Data.Maybe (Maybe) import Data.Show.Generic (genericShow) @@ -26,11 +29,12 @@ type Constraints = Array Constraint -- TODO: consider using Maybe for witnesses data Constraint - = SpendOutput TransactionUnspentOutput OutputWitness - | PayTo TransactionOutput + = SpendOutput TransactionUnspentOutput (Maybe OutputWitness) + | Pay TransactionOutput + | MintAsset ScriptHash AssetName Int.Int CredentialWitness | RegisterStake StakeCredential - | IssueCertificate Certificate CredentialWitness - | WithdrawStake StakeCredential Coin CredentialWitness + | IssueCertificate Certificate (Maybe CredentialWitness) + | WithdrawStake StakeCredential Coin (Maybe CredentialWitness) | RequireSignature PaymentPubKeyHash | RegisterPool PoolParams | RetirePool PoolPubKeyHash Epoch @@ -47,8 +51,7 @@ instance Show Constraint where -- | output. It must correspond to a `TransactionUnspentOutput` address' -- | payment credential to unlock it. data OutputWitness - = PubKeyOutput - | NativeScriptOutput (ScriptWitness NativeScript) + = NativeScriptOutput (ScriptWitness NativeScript) | PlutusScriptOutput (ScriptWitness PlutusScript) RedeemerDatum (Maybe DatumWitness) @@ -66,8 +69,7 @@ instance Show OutputWitness where -- | Unlike `OutputWitness`, it does not include a `DatumWitness`, because -- | minting policies and stake scripts do not have a datum. data CredentialWitness - = PubKeyCredential - | NativeScriptCredential (ScriptWitness NativeScript) + = NativeScriptCredential (ScriptWitness NativeScript) | PlutusScriptCredential (ScriptWitness PlutusScript) RedeemerDatum derive instance Generic CredentialWitness _ diff --git a/src/Contract/PlutusData.purs b/src/Contract/PlutusData.purs index f94fb43950..3ba133791f 100644 --- a/src/Contract/PlutusData.purs +++ b/src/Contract/PlutusData.purs @@ -76,12 +76,12 @@ import Cardano.Types.OutputDatum ) as X import Cardano.Types.PlutusData (PlutusData) import Cardano.Types.PlutusData as Datum +import Cardano.Types.RedeemerDatum (RedeemerDatum) +import Cardano.Types.RedeemerDatum (RedeemerDatum(RedeemerDatum)) as X +import Cardano.Types.RedeemerDatum as Redeemer import Contract.Monad (Contract) import Control.Parallel (parTraverse) import Ctl.Internal.Contract.Monad (getQueryHandle) -import Ctl.Internal.Types.RedeemerDatum (RedeemerDatum) -import Ctl.Internal.Types.RedeemerDatum (RedeemerDatum(RedeemerDatum)) as X -import Ctl.Internal.Types.RedeemerDatum as Redeemer import Data.Either (Either(Left, Right), hush) import Data.Map (Map) import Data.Map as Map diff --git a/src/Contract/ScriptLookups.purs b/src/Contract/ScriptLookups.purs index 93fac750df..08a7ff7ccc 100644 --- a/src/Contract/ScriptLookups.purs +++ b/src/Contract/ScriptLookups.purs @@ -2,7 +2,6 @@ -- | transaction. module Contract.ScriptLookups (module X) where -import Ctl.Internal.ProcessConstraints.UnbalancedTx (UnbalancedTx(UnbalancedTx)) as X import Ctl.Internal.Types.ScriptLookups ( ScriptLookups(ScriptLookups) , datum diff --git a/src/Contract/Transaction.purs b/src/Contract/Transaction.purs index 9018e192ad..003097e677 100644 --- a/src/Contract/Transaction.purs +++ b/src/Contract/Transaction.purs @@ -3,10 +3,7 @@ module Contract.Transaction ( balanceTx , balanceTxE - , balanceTxWithConstraints - , balanceTxWithConstraintsE , balanceTxs - , balanceTxsWithConstraints , createAdditionalUtxos , getTxMetadata , module BalanceTxError @@ -14,18 +11,21 @@ module Contract.Transaction , submit , submitE , submitTxFromConstraints - , submitTxFromConstraintsReturningFee , withBalancedTx - , withBalancedTxWithConstraints , withBalancedTxs - , withBalancedTxsWithConstraints , lookupTxHash , mkPoolPubKeyHash , hashTransaction + , buildTx ) where import Prelude +import Cardano.Transaction.Builder + ( TransactionBuilderStep + , buildTransaction + , explainTxBuildError + ) import Cardano.Types ( Bech32String , Coin @@ -37,6 +37,9 @@ import Cardano.Types , TransactionOutput , TransactionUnspentOutput(TransactionUnspentOutput) , UtxoMap + , _body + , _fee + , _outputs ) import Cardano.Types ( DataHash(DataHash) @@ -86,7 +89,6 @@ import Ctl.Internal.BalanceTx.Error , Expected(Expected) , explainBalanceTxError ) as BalanceTxError -import Ctl.Internal.BalanceTx.UnattachedTx (UnindexedTx) import Ctl.Internal.Contract.AwaitTxConfirmed ( awaitTxConfirmed , awaitTxConfirmedWithTimeout @@ -139,8 +141,6 @@ import Ctl.Internal.Lens , _withdrawals , _witnessSet ) as X -import Ctl.Internal.Lens (_body, _fee, _outputs) -import Ctl.Internal.ProcessConstraints.UnbalancedTx (UnbalancedTx(UnbalancedTx)) import Ctl.Internal.Service.Error (ClientError) import Ctl.Internal.Types.ScriptLookups (ScriptLookups) import Ctl.Internal.Types.TxConstraints (TxConstraints) @@ -172,8 +172,21 @@ import Prim.Coerce (class Coercible) import Prim.TypeError (class Warn, Text) import Safe.Coerce (coerce) +buildTx + :: Array TransactionBuilderStep + -> Contract Transaction +buildTx steps = do + id <- asks _.networkId + let + eiRes = buildTransaction id steps + case eiRes of + Left err -> do + throwError (error $ explainTxBuildError err) + Right res -> pure res + hashTransaction - :: Warn (Text "Deprecated: Validator. Use Cardano.Types.PlutusData.hash") + :: Warn + (Text "Deprecated: hashTransaction. Use Cardano.Types.Transaction.hash") => Transaction -> TransactionHash hashTransaction = Transaction.hash @@ -251,19 +264,13 @@ withSingleTransaction prepare extract utx action = -- | in any other context. -- | After the function completes, the locks will be removed. -- | Errors will be thrown. -withBalancedTxsWithConstraints - :: forall (a :: Type) - . Array (UnbalancedTx /\ BalanceTxConstraintsBuilder) - -> (Array Transaction -> Contract a) - -> Contract a -withBalancedTxsWithConstraints = - withTransactions balanceTxsWithConstraints identity - --- | Same as `withBalancedTxsWithConstraints`, but uses the default balancer --- | constraints. withBalancedTxs :: forall (a :: Type) - . Array UnbalancedTx + . Array + { transaction :: Transaction + , extraUtxos :: UtxoMap + , balancerConstraints :: BalanceTxConstraintsBuilder + } -> (Array Transaction -> Contract a) -> Contract a withBalancedTxs = withTransactions balanceTxs identity @@ -274,78 +281,42 @@ withBalancedTxs = withTransactions balanceTxs identity -- | used in any other context. -- | After the function completes, the locks will be removed. -- | Errors will be thrown. -withBalancedTxWithConstraints - :: forall (a :: Type) - . UnbalancedTx - -> BalanceTxConstraintsBuilder - -> (Transaction -> Contract a) - -> Contract a -withBalancedTxWithConstraints unbalancedTx = - withSingleTransaction balanceAndLockWithConstraints identity - <<< Tuple unbalancedTx - --- | Same as `withBalancedTxWithConstraints`, but uses the default balancer --- | constraints. withBalancedTx :: forall (a :: Type) - . UnbalancedTx + . Transaction + -> UtxoMap + -> BalanceTxConstraintsBuilder -> (Transaction -> Contract a) -> Contract a -withBalancedTx = withSingleTransaction balanceAndLock identity +withBalancedTx tx extraUtxos balancerConstraints = + withSingleTransaction + ( \transaction -> balanceAndLock + { transaction, extraUtxos, balancerConstraints } + ) + identity + tx -unUnbalancedTx - :: UnbalancedTx -> UnindexedTx /\ Map TransactionInput TransactionOutput -unUnbalancedTx - ( UnbalancedTx - { transaction - , redeemers - , usedUtxos - } - ) = - { transaction, redeemers } /\ usedUtxos - --- | Attempts to balance an `UnbalancedTx` using the specified --- | balancer constraints. --- | --- | `balanceTxWithConstraints` is a throwing variant. -balanceTxWithConstraintsE - :: UnbalancedTx +-- | A variant of `balanceTx` that returns a balancer error value. +balanceTxE + :: Transaction + -> UtxoMap -> BalanceTxConstraintsBuilder -> Contract (Either BalanceTxError.BalanceTxError Transaction) -balanceTxWithConstraintsE tx = - let - tx' /\ ix = unUnbalancedTx tx - in - B.balanceTxWithConstraints tx' ix +balanceTxE tx utxos = B.balanceTxWithConstraints tx utxos --- | Attempts to balance an `UnbalancedTx` using the specified --- | balancer constraints. +-- | Balance a single transaction. +-- | +-- | `balanceTxE` is a non-throwing version of this function. -- | --- | 'Throwing' variant of `balanceTxWithConstraintsE`. -balanceTxWithConstraints - :: UnbalancedTx +-- | Use `balanceTxs` to balance multiple transactions and prevent them from +-- | using the same input UTxOs. +balanceTx + :: Transaction + -> UtxoMap -> BalanceTxConstraintsBuilder -> Contract Transaction -balanceTxWithConstraints tx bcb = do - result <- balanceTxWithConstraintsE tx bcb - case result of - Left err -> throwError $ error $ BalanceTxError.explainBalanceTxError err - Right ftx -> pure ftx - --- | Balance a transaction without providing balancer constraints. --- | --- | `balanceTx` is a throwing variant. -balanceTxE - :: UnbalancedTx - -> Contract (Either BalanceTxError.BalanceTxError Transaction) -balanceTxE = flip balanceTxWithConstraintsE mempty - --- | Balance a transaction without providing balancer constraints. --- | --- | `balanceTxE` is a non-throwing version of this function. -balanceTx :: UnbalancedTx -> Contract Transaction -balanceTx utx = do - result <- balanceTxE utx +balanceTx utx utxos constraints = do + result <- balanceTxE utx utxos constraints case result of Left err -> throwError $ error $ BalanceTxError.explainBalanceTxError err Right ftx -> pure ftx @@ -353,45 +324,33 @@ balanceTx utx = do -- | Balances each transaction using specified balancer constraint sets and -- | locks the used inputs so that they cannot be reused by subsequent -- | transactions. -balanceTxsWithConstraints - :: forall (t :: Type -> Type) - . Traversable t - => t (UnbalancedTx /\ BalanceTxConstraintsBuilder) - -> Contract (t Transaction) -balanceTxsWithConstraints unbalancedTxs = - unlockAllOnError $ traverse balanceAndLockWithConstraints unbalancedTxs +balanceTxs + :: Array + { transaction :: Transaction + , extraUtxos :: UtxoMap + , balancerConstraints :: BalanceTxConstraintsBuilder + } + -> Contract (Array Transaction) +balanceTxs unbalancedTxs = + unlockAllOnError $ traverse balanceAndLock unbalancedTxs where unlockAllOnError :: forall (a :: Type). Contract a -> Contract a unlockAllOnError f = catchError f $ \e -> do for_ unbalancedTxs $ - withUsedTxOuts <<< unlockTransactionInputs <<< uutxToTx <<< fst + withUsedTxOuts <<< unlockTransactionInputs <<< _.transaction throwError e - uutxToTx :: UnbalancedTx -> Transaction - uutxToTx = _.transaction <<< unwrap - --- | Same as `balanceTxsWithConstraints`, but uses the default balancer --- | constraints. -balanceTxs - :: forall (t :: Type -> Type) - . Traversable t - => t UnbalancedTx - -> Contract (t Transaction) -balanceTxs = balanceTxsWithConstraints <<< map (flip Tuple mempty) - -balanceAndLockWithConstraints - :: UnbalancedTx /\ BalanceTxConstraintsBuilder +balanceAndLock + :: { transaction :: Transaction + , extraUtxos :: UtxoMap + , balancerConstraints :: BalanceTxConstraintsBuilder + } -> Contract Transaction -balanceAndLockWithConstraints (unbalancedTx /\ constraints) = do - balancedTx <- balanceTxWithConstraints unbalancedTx constraints +balanceAndLock { transaction, extraUtxos, balancerConstraints } = do + balancedTx <- balanceTx transaction extraUtxos balancerConstraints void $ withUsedTxOuts $ lockTransactionInputs balancedTx pure balancedTx -balanceAndLock - :: UnbalancedTx - -> Contract Transaction -balanceAndLock = balanceAndLockWithConstraints <<< flip Tuple mempty - -- | Fetch transaction metadata. -- | Returns `Right` when the transaction exists and metadata was non-empty getTxMetadata @@ -423,23 +382,15 @@ createAdditionalUtxos tx = do pure $ txOutputs # foldl (\utxo txOut -> Map.insert (txIn $ length utxo) txOut utxo) Map.empty -submitTxFromConstraintsReturningFee - :: ScriptLookups - -> TxConstraints - -> Contract { txHash :: TransactionHash, txFinalFee :: Coin } -submitTxFromConstraintsReturningFee lookups constraints = do - unbalancedTx <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTx unbalancedTx - balancedSignedTx <- signTransaction balancedTx - txHash <- submit balancedSignedTx - pure { txHash, txFinalFee: view (_body <<< _fee) balancedSignedTx } - submitTxFromConstraints :: ScriptLookups -> TxConstraints -> Contract TransactionHash -submitTxFromConstraints lookups constraints = - _.txHash <$> submitTxFromConstraintsReturningFee lookups constraints +submitTxFromConstraints lookups constraints = do + unbalancedTx <- mkUnbalancedTx lookups constraints + balancedTx <- balanceTx unbalancedTx Map.empty mempty + balancedSignedTx <- signTransaction balancedTx + submit balancedSignedTx lookupTxHash :: TransactionHash -> UtxoMap -> Array TransactionUnspentOutput diff --git a/src/Contract/UnbalancedTx.purs b/src/Contract/UnbalancedTx.purs index 4d13f7fb46..fe88a4eb4a 100644 --- a/src/Contract/UnbalancedTx.purs +++ b/src/Contract/UnbalancedTx.purs @@ -3,11 +3,11 @@ module Contract.UnbalancedTx ( mkUnbalancedTx , mkUnbalancedTxE - , module X ) where import Prelude +import Cardano.Types (Transaction) import Contract.Monad (Contract) import Control.Monad.Error.Class (throwError) import Ctl.Internal.ProcessConstraints as PC @@ -15,35 +15,6 @@ import Ctl.Internal.ProcessConstraints.Error ( MkUnbalancedTxError , explainMkUnbalancedTxError ) -import Ctl.Internal.ProcessConstraints.Error - ( MkUnbalancedTxError - ( CannotFindDatum - , CannotQueryDatum - , CannotConvertPOSIXTimeRange - , CannotSolveTimeConstraints - , CannotGetMintingPolicyScriptIndex - , CannotGetValidatorHashFromAddress - , CannotMakeValue - , CannotWithdrawRewardsPubKey - , CannotWithdrawRewardsPlutusScript - , CannotWithdrawRewardsNativeScript - , DatumNotFound - , DatumWrongHash - , MintingPolicyHashNotCurrencySymbol - , MintingPolicyNotFound - , OwnPubKeyAndStakeKeyMissing - , TxOutRefNotFound - , TxOutRefWrongType - , WrongRefScriptHash - , ValidatorHashNotFound - , CannotSatisfyAny - , ExpectedPlutusScriptGotNativeScript - , CannotMintZero - ) - , explainMkUnbalancedTxError - ) as X -import Ctl.Internal.ProcessConstraints.UnbalancedTx (UnbalancedTx) -import Ctl.Internal.ProcessConstraints.UnbalancedTx (UnbalancedTx(UnbalancedTx)) as X import Ctl.Internal.Types.ScriptLookups (ScriptLookups) import Ctl.Internal.Types.TxConstraints (TxConstraints) import Data.Either (Either(Left, Right)) @@ -58,11 +29,11 @@ import Effect.Exception (error) mkUnbalancedTxE :: ScriptLookups -> TxConstraints - -> Contract (Either MkUnbalancedTxError UnbalancedTx) + -> Contract (Either MkUnbalancedTxError Transaction) mkUnbalancedTxE = PC.mkUnbalancedTxImpl -- | As `mkUnbalancedTxE`, but 'throwing'. -mkUnbalancedTx :: ScriptLookups -> TxConstraints -> Contract UnbalancedTx +mkUnbalancedTx :: ScriptLookups -> TxConstraints -> Contract Transaction mkUnbalancedTx lookups constraints = mkUnbalancedTxE lookups constraints >>= case _ of Left err -> throwError $ error $ explainMkUnbalancedTxError err diff --git a/src/Internal/BalanceTx/BalanceTx.purs b/src/Internal/BalanceTx/BalanceTx.purs index 81725d9767..0eaeb3aef7 100644 --- a/src/Internal/BalanceTx/BalanceTx.purs +++ b/src/Internal/BalanceTx/BalanceTx.purs @@ -4,6 +4,11 @@ module Ctl.Internal.BalanceTx import Prelude +import Cardano.Transaction.Edit + ( attachRedeemers + , editTransaction + , mkRedeemersContext + ) import Cardano.Types ( AssetClass(AssetClass) , Certificate(StakeDeregistration, StakeRegistration) @@ -22,10 +27,11 @@ import Cardano.Types.Coin as Coin import Cardano.Types.OutputDatum (OutputDatum(OutputDatum)) import Cardano.Types.TransactionInput (TransactionInput) import Cardano.Types.TransactionUnspentOutput as TransactionUnspentOutputs +import Cardano.Types.TransactionWitnessSet (_redeemers) import Cardano.Types.UtxoMap (pprintUtxoMap) import Cardano.Types.Value (getMultiAsset, mkValue, pprintValue) import Cardano.Types.Value as Value -import Contract.Log (logWarn') +import Contract.Log (logInfo', logWarn') import Control.Monad.Except (class MonadError) import Control.Monad.Except.Trans (except, runExceptT) import Control.Monad.Logger.Class (info) as Logger @@ -70,11 +76,6 @@ import Ctl.Internal.BalanceTx.ExUnitsAndMinFee ( evalExUnitsAndMinFee , finalizeTransaction ) -import Ctl.Internal.BalanceTx.RedeemerIndex - ( attachIndexedRedeemers - , indexRedeemers - , mkRedeemersContext - ) import Ctl.Internal.BalanceTx.Sync (isCip30Wallet, syncBackendWithWallet) import Ctl.Internal.BalanceTx.Types ( BalanceTxM @@ -85,12 +86,6 @@ import Ctl.Internal.BalanceTx.Types , liftEitherContract , withBalanceTxConstraints ) -import Ctl.Internal.BalanceTx.UnattachedTx - ( EvaluatedTx - , UnindexedTx - , _transaction - , indexTx - ) import Ctl.Internal.BalanceTx.UtxoMinAda (utxoMinAdaValue) import Ctl.Internal.CoinSelection.UtxoIndex (UtxoIndex, buildUtxoIndex) import Ctl.Internal.Contract (getProtocolParameters) @@ -173,7 +168,7 @@ import Partial.Unsafe (unsafePartial) -- | Balances an unbalanced transaction using the specified balancer -- | constraints. balanceTxWithConstraints - :: UnindexedTx + :: Transaction -> Map TransactionInput TransactionOutput -> BalanceTxConstraintsBuilder -> Contract (Either BalanceTxError Transaction) @@ -185,8 +180,7 @@ balanceTxWithConstraints transaction extraUtxos constraintsBuilder = do let depositValuePerCert = BigNum.toBigInt $ unwrap (unwrap pparams).stakeAddressDeposit - certsFee = getStakingBalance (transaction.transaction) - depositValuePerCert + certsFee = getStakingBalance transaction depositValuePerCert changeAddress <- getChangeAddress @@ -203,7 +197,10 @@ balanceTxWithConstraints transaction extraUtxos constraintsBuilder = do >>> _.syncBackendWithWallet >>> _.beforeBalancing ) - syncBackendWithWallet + do + logInfo' "balanceTxWithConstraints: syncBackendWithWallet" + syncBackendWithWallet + logInfo' "balanceTxWithConstraints: Wallet.getWalletUtxos" note CouldNotGetUtxos <$> do Wallet.getWalletUtxos -- Use UTxOs from source addresses @@ -220,7 +217,7 @@ balanceTxWithConstraints transaction extraUtxos constraintsBuilder = do >>> map (foldr Map.union Map.empty) -- merge all utxos into one map unbalancedCollTx <- transactionWithNetworkId >>= - if Array.null (transaction # _.redeemers) + if Array.null (transaction ^. _witnessSet <<< _redeemers) -- Don't set collateral if tx doesn't contain phase-2 scripts: then pure else setTransactionCollateral changeAddress @@ -239,19 +236,10 @@ balanceTxWithConstraints transaction extraUtxos constraintsBuilder = do selectionStrategy <- asksConstraints Constraints._selectionStrategy - -- Reindex redeemers and update transaction - reindexedRedeemers <- liftEither $ lmap ReindexRedeemersError $ - indexRedeemers (mkRedeemersContext unbalancedCollTx) transaction.redeemers - let - reindexedTransaction = transaction - { transaction = attachIndexedRedeemers reindexedRedeemers - unbalancedCollTx - } - -- Balance and finalize the transaction: runBalancer { strategy: selectionStrategy - , transaction: reindexedTransaction + , transaction: unbalancedCollTx , changeAddress , changeDatum: changeDatum' , allUtxos @@ -266,8 +254,8 @@ balanceTxWithConstraints transaction extraUtxos constraintsBuilder = do transactionWithNetworkId :: BalanceTxM Transaction transactionWithNetworkId = do networkId <- maybe askNetworkId pure - (transaction ^. _transaction <<< _body <<< _networkId) - pure (transaction.transaction # _body <<< _networkId ?~ networkId) + (transaction ^. _body <<< _networkId) + pure (transaction # _body <<< _networkId ?~ networkId) setTransactionCollateral :: Address -> Transaction -> BalanceTxM Transaction setTransactionCollateral changeAddr transaction = do @@ -309,7 +297,7 @@ setTransactionCollateral changeAddr transaction = do type BalancerParams = { strategy :: SelectionStrategy - , transaction :: UnindexedTx + , transaction :: Transaction , changeAddress :: Address , changeDatum :: Maybe OutputDatum , allUtxos :: UtxoMap @@ -317,6 +305,7 @@ type BalancerParams = , certsFee :: BigInt -- can be negative (deregistration) } +-- TODO: remove the parameter type BalancerState tx = { transaction :: tx , leftoverUtxos :: UtxoIndex @@ -325,16 +314,16 @@ type BalancerState tx = } initBalancerState - :: UnindexedTx + :: Transaction -> UtxoMap - -> BalancerState UnindexedTx + -> BalancerState Transaction initBalancerState transaction = buildUtxoIndex >>> { transaction, leftoverUtxos: _, changeOutputs: mempty, minFee: Coin.zero } data BalancerStep - = PrebalanceTx (BalancerState UnindexedTx) - | BalanceChangeAndMinFee (BalancerState UnindexedTx) + = PrebalanceTx (BalancerState Transaction) + | BalanceChangeAndMinFee (BalancerState Transaction) runBalancer :: BalancerParams -> BalanceTxM Transaction runBalancer p = do @@ -342,14 +331,14 @@ runBalancer p = do transaction <- addLovelacesToTransactionOutputs p.transaction mainLoop (initBalancerState transaction utxos.spendable) where - referenceInputSet = Set.fromFoldable $ p.transaction ^. _transaction <<< _body + referenceInputSet = Set.fromFoldable $ p.transaction ^. _body <<< _referenceInputs -- We check if the transaction uses a plutusv1 script, so that we can filter -- out utxos which use plutusv2 features if so. txHasPlutusV1 :: Boolean txHasPlutusV1 = - case p.transaction ^. _transaction <<< _witnessSet <<< _plutusScripts of + case p.transaction ^. _witnessSet <<< _plutusScripts of [] -> false scripts -> flip Array.any scripts case _ of PlutusScript (_ /\ PlutusV1) -> true @@ -402,7 +391,7 @@ runBalancer p = do } (Map.toUnfoldable p.utxos :: Array _) - mainLoop :: BalancerState UnindexedTx -> BalanceTxM Transaction + mainLoop :: BalancerState Transaction -> BalanceTxM Transaction mainLoop = worker <<< PrebalanceTx where worker :: BalancerStep -> BalanceTxM Transaction @@ -416,15 +405,15 @@ runBalancer p = do case newMinFee <= minFee of true -> do logTransaction "Balanced transaction (Done)" p.allUtxos - evaluatedTx.transaction - if Array.null $ evaluatedTx.transaction ^. _body <<< _inputs then + evaluatedTx + if Array.null $ evaluatedTx ^. _body <<< _inputs then do selectionState <- performMultiAssetSelection p.strategy leftoverUtxos (Val one Map.empty) runNextBalancerStep $ state - { transaction = transaction # - _transaction <<< _body <<< _inputs %~ appendInputs + { transaction = flip editTransaction transaction $ + _body <<< _inputs %~ appendInputs (Array.fromFoldable $ selectedInputs selectionState) , leftoverUtxos = selectionState ^. _leftoverUtxos @@ -434,7 +423,7 @@ runBalancer p = do false -> runNextBalancerStep $ state { transaction = transaction - # _transaction <<< _body <<< _fee .~ newMinFee + # _body <<< _fee .~ newMinFee , minFee = newMinFee } @@ -444,9 +433,9 @@ runBalancer p = do -- | after generation of change, the first balancing step `PrebalanceTx` -- | is performed, otherwise we proceed to `BalanceChangeAndMinFee`. runNextBalancerStep - :: BalancerState UnindexedTx -> BalanceTxM Transaction + :: BalancerState Transaction -> BalanceTxM Transaction runNextBalancerStep state@{ transaction } = do - let txBody = transaction ^. _transaction <<< _body + let txBody = transaction ^. _body inputValue <- except $ getInputVal p.allUtxos txBody ownWalletAddresses <- asks _.ownAddresses inputValue' <- liftValue inputValue @@ -458,8 +447,7 @@ runBalancer p = do requiredValue <- except $ getRequiredValue p.certsFee p.allUtxos - $ setTxChangeOutputs changeOutputs transaction ^. _transaction <<< - _body + $ setTxChangeOutputs changeOutputs transaction ^. _body worker $ if requiredValue == mempty then BalanceChangeAndMinFee $ state @@ -470,12 +458,12 @@ runBalancer p = do -- | utxo set so that the total input value is sufficient to cover all -- | transaction outputs, including generated change and min fee. prebalanceTx - :: BalancerState UnindexedTx -> BalanceTxM (BalancerState UnindexedTx) + :: BalancerState Transaction -> BalanceTxM (BalancerState Transaction) prebalanceTx state@{ transaction, changeOutputs, leftoverUtxos } = performCoinSelection <#> \selectionState -> state { transaction = - ( transaction # - _transaction <<< _body <<< _inputs %~ + ( flip editTransaction transaction $ + _body <<< _inputs %~ appendInputs (Array.fromFoldable $ selectedInputs selectionState) ) @@ -487,8 +475,7 @@ runBalancer p = do performCoinSelection = do let txBody :: TransactionBody - txBody = setTxChangeOutputs changeOutputs transaction ^. _transaction - <<< _body + txBody = setTxChangeOutputs changeOutputs transaction ^. _body except (getRequiredValue p.certsFee p.allUtxos txBody) >>= performMultiAssetSelection p.strategy leftoverUtxos @@ -499,27 +486,25 @@ runBalancer p = do -- | since this pre-condition is sometimes required for successfull script -- | execution during transaction evaluation. evaluateTx - :: BalancerState UnindexedTx -> BalanceTxM (BalancerState EvaluatedTx) + :: BalancerState Transaction -> BalanceTxM (BalancerState Transaction) evaluateTx state@{ transaction, changeOutputs } = do let - prebalancedTx :: UnindexedTx + prebalancedTx :: Transaction prebalancedTx = setTxChangeOutputs changeOutputs transaction - indexedTx <- liftEither $ lmap ReindexRedeemersError $ indexTx - prebalancedTx - evaluatedTx /\ minFee <- evalExUnitsAndMinFee indexedTx p.allUtxos + evaluatedTx /\ minFee <- evalExUnitsAndMinFee prebalancedTx p.allUtxos pure $ state { transaction = evaluatedTx, minFee = minFee } -- | For each transaction output, if necessary, adds some number of lovelaces -- | to cover the utxo min-ada-value requirement. addLovelacesToTransactionOutputs - :: UnindexedTx -> BalanceTxM UnindexedTx + :: Transaction -> BalanceTxM Transaction addLovelacesToTransactionOutputs transaction = map ( \txOutputs -> transaction # - _transaction <<< _body <<< _outputs .~ txOutputs + _body <<< _outputs .~ txOutputs ) $ traverse addLovelacesToTransactionOutput - (transaction ^. _transaction <<< _body <<< _outputs) + (transaction ^. _body <<< _outputs) addLovelacesToTransactionOutput :: TransactionOutput -> BalanceTxM TransactionOutput @@ -546,9 +531,9 @@ appendInputs appendInputs a b = Set.toUnfoldable (Set.fromFoldable a <> Set.fromFoldable b) setTxChangeOutputs - :: Array TransactionOutput -> UnindexedTx -> UnindexedTx + :: Array TransactionOutput -> Transaction -> Transaction setTxChangeOutputs outputs tx = - tx # _transaction <<< _body <<< _outputs %~ flip append outputs + tx # _body <<< _outputs %~ flip append outputs -------------------------------------------------------------------------------- -- Making change @@ -832,7 +817,7 @@ getInputVal :: UtxoMap -> TransactionBody -> Either BalanceTxError Val getInputVal utxos txBody = foldMap (view _amount >>> Val.fromValue) <$> for (Array.fromFoldable $ txBody ^. _inputs) \oref -> - note (UtxoLookupFailedFor oref) (Map.lookup oref utxos) + note (UtxoLookupFailedFor oref utxos) (Map.lookup oref utxos) outputValue :: TransactionBody -> Val outputValue txBody = foldMap (view _amount >>> Val.fromValue) @@ -879,9 +864,9 @@ logBalancerState :: forall rest . String -> UtxoMap - -> BalancerState { transaction :: Transaction | rest } + -> BalancerState Transaction -> BalanceTxM Unit -logBalancerState message utxos { transaction: { transaction }, changeOutputs } = +logBalancerState message utxos { transaction, changeOutputs } = logTransactionWithChange message utxos (Just changeOutputs) transaction logTransaction @@ -918,8 +903,9 @@ logTransactionWithChange message utxos mChangeOutputs tx = , "Fees" `tag` BigNum.toString (unwrap (txBody ^. _fee)) ] <> outputValuesTagSet mChangeOutputs in - except (getInputVal utxos txBody) - >>= (flip Logger.info (message <> ":") <<< transactionInfo) + do + except (getInputVal utxos txBody) + >>= (flip Logger.info (message <> ":") <<< transactionInfo) liftValue :: forall a. MonadError BalanceTxError a => Val -> a Value liftValue val = liftEither $ note (NumericOverflowError $ Just val) $ diff --git a/src/Internal/BalanceTx/Error.purs b/src/Internal/BalanceTx/Error.purs index a46cf69b9d..7b2195cf28 100644 --- a/src/Internal/BalanceTx/Error.purs +++ b/src/Internal/BalanceTx/Error.purs @@ -25,13 +25,14 @@ module Ctl.Internal.BalanceTx.Error import Prelude +import Cardano.AsCbor (encodeCbor) +import Cardano.Transaction.Edit (DetachedRedeemer) import Cardano.Types (Coin, Redeemer(Redeemer), Transaction) import Cardano.Types.BigNum as BigNum -import Cardano.Types.TransactionInput (TransactionInput) +import Cardano.Types.TransactionInput (TransactionInput(TransactionInput)) import Cardano.Types.TransactionOutput (TransactionOutput) import Cardano.Types.UtxoMap (UtxoMap, pprintUtxoMap) import Cardano.Types.Value (Value) -import Ctl.Internal.BalanceTx.RedeemerIndex (UnindexedRedeemer) import Ctl.Internal.Helpers (bugTrackerLink, pprintTagSet) import Ctl.Internal.Lens (_redeemers, _witnessSet) import Ctl.Internal.QueryM.Ogmios @@ -52,6 +53,7 @@ import Ctl.Internal.QueryM.Ogmios import Ctl.Internal.Types.Val (Val, pprintVal) import Data.Array (catMaybes, filter, uncons) as Array import Data.Bifunctor (bimap) +import Data.ByteArray (byteArrayToHex) import Data.Either (Either(Left, Right), either, isLeft) import Data.Foldable (find, fold, foldMap, foldl, length) import Data.FoldableWithIndex (foldMapWithIndex) @@ -59,8 +61,9 @@ import Data.Function (applyN) import Data.Generic.Rep (class Generic) import Data.Int (ceil, decimal, toNumber, toStringAs) import Data.Lens ((^.)) +import Data.Log.Tag (TagSet, tag) import Data.Maybe (Maybe(Just, Nothing)) -import Data.Newtype (class Newtype) +import Data.Newtype (class Newtype, unwrap) import Data.Show.Generic (genericShow) import Data.String (Pattern(Pattern)) import Data.String.CodePoints (length) as String @@ -80,8 +83,8 @@ data BalanceTxError | CollateralReturnMinAdaValueCalcError Coin TransactionOutput | ExUnitsEvaluationFailed Transaction Ogmios.TxEvaluationFailure | InsufficientUtxoBalanceToCoverAsset String - | ReindexRedeemersError UnindexedRedeemer - | UtxoLookupFailedFor TransactionInput + | ReindexRedeemersError DetachedRedeemer + | UtxoLookupFailedFor TransactionInput UtxoMap | UtxoMinAdaValueCalculationFailed | NumericOverflowError (Maybe Val) @@ -129,11 +132,12 @@ explainBalanceTxError = case _ of <> show uir <> "\nThis should be impossible: please report this as a bug to " <> bugTrackerLink - UtxoLookupFailedFor ti -> - "Could not look up UTxO for " - <> show ti - <> " from a given set of UTxOs.\n" - <> "This should be impossible: please report this as a bug to " + UtxoLookupFailedFor ti mp -> + "Could not look up UTxO " + <> pprintTagSet "for" (pprintTransactionInput ti) + <> " from a " + <> pprintTagSet "given set of UTxOs:" (pprintUtxoMap mp) + <> "\nThis should be impossible: please report this as a bug to " <> bugTrackerLink UtxoMinAdaValueCalculationFailed -> "Could not calculate min ADA for UTxO" @@ -144,6 +148,13 @@ explainBalanceTxError = case _ of prettyVal :: String -> Val -> String prettyVal str = pprintVal >>> pprintTagSet str + pprintTransactionInput :: TransactionInput -> TagSet + pprintTransactionInput (TransactionInput { transactionId, index }) = + "TransactionInput" `tag` + ( byteArrayToHex (unwrap (encodeCbor transactionId)) <> "#" <> + show (UInt.toInt index) + ) + newtype Actual = Actual Value derive instance Generic Actual _ diff --git a/src/Internal/BalanceTx/ExUnitsAndMinFee.purs b/src/Internal/BalanceTx/ExUnitsAndMinFee.purs index 625c43d4f3..f44cc80f2c 100644 --- a/src/Internal/BalanceTx/ExUnitsAndMinFee.purs +++ b/src/Internal/BalanceTx/ExUnitsAndMinFee.purs @@ -19,29 +19,26 @@ import Cardano.Types , TransactionWitnessSet , UtxoMap ) +import Cardano.Types.BigNum as BigNum import Cardano.Types.ScriptRef as ScriptRef import Cardano.Types.TransactionInput (TransactionInput) +import Cardano.Types.TransactionWitnessSet (_redeemers) import Control.Monad.Error.Class (throwError) import Control.Monad.Except.Trans (except) import Ctl.Internal.BalanceTx.Constraints (_additionalUtxos, _collateralUtxos) as Constraints import Ctl.Internal.BalanceTx.Error ( BalanceTxError(UtxoLookupFailedFor, ExUnitsEvaluationFailed) ) -import Ctl.Internal.BalanceTx.RedeemerIndex - ( IndexedRedeemer - , attachRedeemers - , indexedRedeemerToRedeemer - ) import Ctl.Internal.BalanceTx.Types ( BalanceTxM , askCostModelsForLanguages , asksConstraints , liftContract ) -import Ctl.Internal.BalanceTx.UnattachedTx (EvaluatedTx, IndexedTx) import Ctl.Internal.Contract.MinFee (calculateMinFee) as Contract.MinFee import Ctl.Internal.Contract.Monad (getQueryHandle) -import Ctl.Internal.Lens (_body, _isValid, _plutusData, _witnessSet) +import Ctl.Internal.Helpers (unsafeFromJust) +import Ctl.Internal.Lens (_body, _isValid, _witnessSet) import Ctl.Internal.QueryM.Ogmios ( AdditionalUtxoSet , TxEvaluationFailure(AdditionalUtxoOverlap) @@ -108,24 +105,19 @@ evalTxExecutionUnits tx = do -- and the minimum fee, including the script fees. -- Returns a tuple consisting of updated `UnbalancedTx` and the minimum fee. evalExUnitsAndMinFee - :: IndexedTx + :: Transaction -> UtxoMap - -> BalanceTxM (EvaluatedTx /\ Coin) -evalExUnitsAndMinFee unattachedTx allUtxos = do - -- Reattach datums and redeemers before evaluating ex units: - let attachedTx = reattachDatumsAndFakeRedeemers unattachedTx + -> BalanceTxM (Transaction /\ Coin) +evalExUnitsAndMinFee transaction allUtxos = do -- Evaluate transaction ex units: - exUnits <- evalTxExecutionUnits attachedTx + exUnits <- evalTxExecutionUnits transaction -- Set execution units received from the server: txWithExUnits <- - case updateTxExecutionUnits unattachedTx exUnits of + case updateTxExecutionUnits transaction exUnits of Just res -> pure res Nothing - | not (attachedTx ^. _isValid) -> pure $ - unattachedTx - { redeemers = indexedRedeemerToRedeemer <$> unattachedTx.redeemers - } - _ -> throwError $ ExUnitsEvaluationFailed attachedTx + | not (transaction ^. _isValid) -> pure transaction + _ -> throwError $ ExUnitsEvaluationFailed transaction (UnparsedError "Unable to extract ExUnits from Ogmios response") -- Attach datums and redeemers, set the script integrity hash: finalizedTx <- finalizeTransaction txWithExUnits allUtxos @@ -140,18 +132,14 @@ evalExUnitsAndMinFee unattachedTx allUtxos = do -- | Attaches datums and redeemers, sets the script integrity hash, -- | for use after reindexing. finalizeTransaction - :: EvaluatedTx -> UtxoMap -> BalanceTxM Transaction + :: Transaction -> UtxoMap -> BalanceTxM Transaction finalizeTransaction tx utxos = do let - attachedTxWithExUnits :: Transaction - attachedTxWithExUnits = - reattachDatumsAndRedeemers tx - txBody :: TransactionBody - txBody = attachedTxWithExUnits ^. _body + txBody = tx ^. _body ws :: TransactionWitnessSet - ws = attachedTxWithExUnits ^. _witnessSet + ws = tx ^. _witnessSet redeemers :: Array Redeemer redeemers = (_.redeemers $ unwrap ws) @@ -170,8 +158,7 @@ finalizeTransaction tx utxos = do (costModels :: Map Language CostModel) <- askCostModelsForLanguages languages - liftEffect $ setScriptDataHash costModels redeemers datums - attachedTxWithExUnits + liftEffect $ setScriptDataHash costModels redeemers datums tx where getRefPlutusScripts :: TransactionBody -> Either BalanceTxError (Array PlutusScript) @@ -183,42 +170,35 @@ finalizeTransaction tx utxos = do in catMaybes <<< map getPlutusScript <$> for spendAndRefInputs \oref -> - note (UtxoLookupFailedFor oref) (Map.lookup oref utxos) + note (UtxoLookupFailedFor oref utxos) (Map.lookup oref utxos) getPlutusScript :: TransactionOutput -> Maybe PlutusScript getPlutusScript (TransactionOutput { scriptRef }) = ScriptRef.getPlutusScript =<< scriptRef -reattachDatumsAndFakeRedeemers :: IndexedTx -> Transaction -reattachDatumsAndFakeRedeemers - { transaction, redeemers } = - reattachDatumsAndRedeemers - { transaction, redeemers: indexedRedeemerToRedeemer <$> redeemers } - -reattachDatumsAndRedeemers :: EvaluatedTx -> Transaction -reattachDatumsAndRedeemers - ({ transaction, redeemers }) = attachRedeemers redeemers transaction - updateTxExecutionUnits - :: IndexedTx + :: Transaction -> Ogmios.TxEvaluationResult - -> Maybe EvaluatedTx -updateTxExecutionUnits tx@{ redeemers } result = - getRedeemersExUnits result redeemers <#> \redeemers' -> tx - { redeemers = redeemers' } + -> Maybe Transaction +updateTxExecutionUnits tx result = + getRedeemersExUnits result (tx ^. _witnessSet <<< _redeemers) <#> + \redeemers' -> + tx # _witnessSet <<< _redeemers .~ redeemers' getRedeemersExUnits :: Ogmios.TxEvaluationResult - -> Array IndexedRedeemer + -> Array Redeemer -> Maybe (Array Redeemer) getRedeemersExUnits (Ogmios.TxEvaluationResult result) redeemers = do for redeemers \indexedRedeemer -> do { memory, steps } <- Map.lookup { redeemerTag: (unwrap indexedRedeemer).tag - , redeemerIndex: UInt.fromInt (unwrap indexedRedeemer).index + , redeemerIndex: UInt.fromInt $ unsafeFromJust "getRedeemersExUnits" + $ BigNum.toInt + $ (unwrap indexedRedeemer).index } result - pure $ Redeemer $ (unwrap $ indexedRedeemerToRedeemer indexedRedeemer) + pure $ Redeemer $ (unwrap indexedRedeemer) { exUnits = ExUnits { mem: memory , steps: steps diff --git a/src/Internal/BalanceTx/RedeemerIndex.purs b/src/Internal/BalanceTx/RedeemerIndex.purs deleted file mode 100644 index 7bcf257571..0000000000 --- a/src/Internal/BalanceTx/RedeemerIndex.purs +++ /dev/null @@ -1,175 +0,0 @@ --- | Redeemer indexing refers to the process of updating redeemer's `index` --- | value based on its `RedeemerPurpose` and context from the transaction. --- | Redeemer indexing is needed, because at the Tx construction stage we --- | don't know the exact indices redeemers will have after balancing. --- | For the algorithm, see `indexof` description in --- | "Combining Scripts with Their Inputs" chapter of "A Formal Specification --- | of the Cardano Ledger integrating Plutus Core" --- | https://github.com/input-output-hk/cardano-ledger/releases/latest/download/alonzo-ledger.pdf -module Ctl.Internal.BalanceTx.RedeemerIndex - ( IndexedRedeemer(IndexedRedeemer) - , RedeemerPurpose(ForReward, ForCert, ForMint, ForSpend) - , RedeemersContext - , UnindexedRedeemer(UnindexedRedeemer) - , attachIndexedRedeemers - , attachRedeemers - , indexRedeemers - , indexedRedeemerToRedeemer - , mkRedeemersContext - , unindexedRedeemerToRedeemer - ) where - -import Prelude - -import Aeson (class EncodeAeson, encodeAeson) -import Cardano.Types - ( Certificate - , Redeemer(Redeemer) - , RewardAddress - , ScriptHash - , Transaction(Transaction) - , TransactionBody(TransactionBody) - ) -import Cardano.Types.BigNum as BigNum -import Cardano.Types.ExUnits as ExUnits -import Cardano.Types.PlutusData (PlutusData) -import Cardano.Types.RedeemerTag (RedeemerTag(Spend, Mint, Cert, Reward)) -import Cardano.Types.TransactionInput (TransactionInput) -import Ctl.Internal.Lens (_redeemers, _witnessSet) -import Data.Array (findIndex) -import Data.Either (Either, note) -import Data.Generic.Rep (class Generic) -import Data.Lens ((.~)) -import Data.Map as Map -import Data.Maybe (Maybe, fromMaybe) -import Data.Newtype (class Newtype, unwrap, wrap) -import Data.Set as Set -import Data.Show.Generic (genericShow) -import Data.Traversable (for) - -attachRedeemers :: Array Redeemer -> Transaction -> Transaction -attachRedeemers redeemers = - _witnessSet <<< _redeemers .~ redeemers - -attachIndexedRedeemers :: Array IndexedRedeemer -> Transaction -> Transaction -attachIndexedRedeemers = attachRedeemers <<< map indexedRedeemerToRedeemer - --- | Redeemer that hasn't yet been indexed, that tracks its purpose info --- | that is enough to find its index given a `RedeemersContext`. -newtype UnindexedRedeemer = UnindexedRedeemer - { datum :: PlutusData - , purpose :: RedeemerPurpose - } - -derive instance Generic UnindexedRedeemer _ -derive instance Newtype UnindexedRedeemer _ -derive newtype instance Eq UnindexedRedeemer -derive newtype instance Ord UnindexedRedeemer -derive newtype instance EncodeAeson UnindexedRedeemer - -instance Show UnindexedRedeemer where - show = genericShow - --- | Ignore the value that the redeemer points to -redeemerPurposeToRedeemerTag :: RedeemerPurpose -> RedeemerTag -redeemerPurposeToRedeemerTag = case _ of - ForSpend _ -> Spend - ForMint _ -> Mint - ForReward _ -> Reward - ForCert _ -> Cert - -unindexedRedeemerToRedeemer :: UnindexedRedeemer -> Redeemer -unindexedRedeemerToRedeemer (UnindexedRedeemer { datum, purpose }) = - Redeemer - { tag: redeemerPurposeToRedeemerTag purpose - , "data": datum - , index: BigNum.zero - , exUnits: ExUnits.empty - } - --- | A redeemer with an index, but without `ExUnits` -newtype IndexedRedeemer = IndexedRedeemer - { tag :: RedeemerTag - , datum :: PlutusData - , index :: Prim.Int - } - -derive instance Generic IndexedRedeemer _ -derive instance Newtype IndexedRedeemer _ -derive newtype instance Eq IndexedRedeemer -derive newtype instance EncodeAeson IndexedRedeemer - -instance Show IndexedRedeemer where - show = genericShow - --- | Sets `ExUnits` to `zero` -indexedRedeemerToRedeemer :: IndexedRedeemer -> Redeemer -indexedRedeemerToRedeemer (IndexedRedeemer { tag, datum, index }) = - Redeemer - { tag - , index: BigNum.fromInt index - , data: datum - , exUnits: ExUnits.empty - } - --- | Contains a value redeemer corresponds to, different for each possible --- | `RedeemerTag`. --- | Allows to uniquely compute redeemer index, given a `RedeemersContext` that --- | is valid for the transaction. -data RedeemerPurpose - = ForSpend TransactionInput - | ForMint ScriptHash - | ForReward RewardAddress - | ForCert Certificate - -derive instance Generic RedeemerPurpose _ -derive instance Eq RedeemerPurpose -derive instance Ord RedeemerPurpose - -instance EncodeAeson RedeemerPurpose where - encodeAeson = case _ of - ForSpend txo -> encodeAeson { tag: "ForSpend", value: encodeAeson txo } - ForMint mps -> encodeAeson { tag: "ForMint", value: encodeAeson mps } - ForReward addr -> encodeAeson { tag: "ForReward", value: encodeAeson addr } - ForCert cert -> encodeAeson { tag: "ForCert", value: encodeAeson cert } - -instance Show RedeemerPurpose where - show = genericShow - --- | Contains parts of a transaction that are important when indexing redeemers -type RedeemersContext = - { inputs :: Array TransactionInput - , mintingPolicyHashes :: Array ScriptHash - , rewardAddresses :: Array RewardAddress - , certs :: Array Certificate - } - -mkRedeemersContext :: Transaction -> RedeemersContext -mkRedeemersContext - (Transaction { body: TransactionBody { inputs, mint, withdrawals, certs } }) = - { inputs: Set.toUnfoldable $ Set.fromFoldable inputs - , mintingPolicyHashes: - Set.toUnfoldable $ Map.keys $ unwrap $ fromMaybe - (wrap Map.empty) - mint - , rewardAddresses: Set.toUnfoldable $ Map.keys $ withdrawals - , certs - } - -indexRedeemers - :: RedeemersContext - -> Array UnindexedRedeemer - -> Either UnindexedRedeemer (Array IndexedRedeemer) -indexRedeemers ctx redeemers = do - for redeemers \redeemer -> note redeemer $ indexRedeemer ctx redeemer - -indexRedeemer :: RedeemersContext -> UnindexedRedeemer -> Maybe IndexedRedeemer -indexRedeemer ctx (UnindexedRedeemer { purpose, datum }) = case purpose of - ForSpend input -> findIndex (eq input) ctx.inputs <#> \index -> - IndexedRedeemer { tag: Spend, index, datum } - ForMint mps -> findIndex (eq mps) ctx.mintingPolicyHashes <#> \index -> - IndexedRedeemer { tag: Mint, index, datum } - ForReward addr -> findIndex (eq addr) ctx.rewardAddresses <#> \index -> - IndexedRedeemer { tag: Reward, index, datum } - ForCert cert -> findIndex (eq cert) ctx.certs <#> \index -> - IndexedRedeemer { tag: Cert, index, datum } diff --git a/src/Internal/BalanceTx/Types.purs b/src/Internal/BalanceTx/Types.purs index b73734ede9..42640cd0ce 100644 --- a/src/Internal/BalanceTx/Types.purs +++ b/src/Internal/BalanceTx/Types.purs @@ -12,8 +12,7 @@ module Ctl.Internal.BalanceTx.Types import Prelude -import Cardano.Types (Coin, CostModel, Language, NetworkId) -import Cardano.Types.Address as Csl +import Cardano.Types (Address, Coin, CostModel, Language, NetworkId) import Control.Monad.Except.Trans (ExceptT(ExceptT)) import Control.Monad.Reader.Class (asks) import Control.Monad.Reader.Trans (ReaderT, runReaderT) @@ -36,7 +35,7 @@ import Data.Set (Set) import Data.Set (fromFoldable, member) as Set type BalanceTxMContext = - { constraints :: BalanceTxConstraints, ownAddresses :: Set Csl.Address } + { constraints :: BalanceTxConstraints, ownAddresses :: Set Address } type BalanceTxM (a :: Type) = ExceptT BalanceTxError (ReaderT BalanceTxMContext Contract) a diff --git a/src/Internal/BalanceTx/UnattachedTx.purs b/src/Internal/BalanceTx/UnattachedTx.purs deleted file mode 100644 index f5439f5760..0000000000 --- a/src/Internal/BalanceTx/UnattachedTx.purs +++ /dev/null @@ -1,54 +0,0 @@ -module Ctl.Internal.BalanceTx.UnattachedTx - ( UnattachedTx - , UnindexedTx - , IndexedTx - , EvaluatedTx - , indexTx - , _transaction - , _redeemers - ) where - -import Prelude - -import Cardano.Types (PlutusData, Redeemer, Transaction) -import Ctl.Internal.BalanceTx.RedeemerIndex - ( IndexedRedeemer - , UnindexedRedeemer - , attachIndexedRedeemers - , indexRedeemers - , mkRedeemersContext - ) -import Data.Either (Either) -import Data.Lens (Lens') -import Data.Lens.Record (prop) -import Type.Proxy (Proxy(Proxy)) - -type UnattachedTx redeemer = - { transaction :: Transaction - , redeemers :: Array redeemer - } - --- | A Tx with unindexed redeemers -type UnindexedTx = UnattachedTx UnindexedRedeemer - --- | A Tx with indexed, but not yet evaluated redeemers -type IndexedTx = UnattachedTx IndexedRedeemer - --- | A Tx with fully indexed and evaluated redeemers -type EvaluatedTx = UnattachedTx Redeemer - -indexTx :: UnindexedTx -> Either UnindexedRedeemer IndexedTx -indexTx { transaction, redeemers } = do - redeemers' <- indexRedeemers (mkRedeemersContext transaction) redeemers - pure - { transaction: attachIndexedRedeemers redeemers' transaction - , redeemers: redeemers' - } - -_transaction - :: forall (redeemer :: Type). Lens' (UnattachedTx redeemer) Transaction -_transaction = prop (Proxy :: Proxy "transaction") - -_redeemers - :: forall (redeemer :: Type). Lens' (UnattachedTx redeemer) (Array redeemer) -_redeemers = prop (Proxy :: Proxy "redeemers") diff --git a/src/Internal/Lens.purs b/src/Internal/Lens.purs index bbfe9a8e73..461d88a86a 100644 --- a/src/Internal/Lens.purs +++ b/src/Internal/Lens.purs @@ -39,6 +39,7 @@ import Cardano.Types ( Address , AuxiliaryData , AuxiliaryDataHash + , BootstrapWitness , Certificate , Coin , Ed25519KeyHash @@ -176,3 +177,6 @@ _nativeScripts = _Newtype <<< prop (Proxy :: Proxy "nativeScripts") _vkeys :: Lens' TransactionWitnessSet (Array Vkeywitness) _vkeys = _Newtype <<< prop (Proxy :: Proxy "vkeys") + +_bootstraps :: Lens' TransactionWitnessSet (Array BootstrapWitness) +_bootstraps = _Newtype <<< prop (Proxy :: Proxy "bootstraps") diff --git a/src/Internal/Plutip/Server.purs b/src/Internal/Plutip/Server.purs index 7eea80025d..de2e51477c 100644 --- a/src/Internal/Plutip/Server.purs +++ b/src/Internal/Plutip/Server.purs @@ -376,7 +376,8 @@ startPlutipContractEnv plutipCfg distr cleanupRef = do -> Aff wallets mkWallets' env ourKey response = do runContractInEnv - env { customLogger = Just (\_ _ -> pure unit) } + -- TODO: uncomment me + env -- { customLogger = Just (\_ _ -> pure unit) } do wallets <- liftContractM diff --git a/src/Internal/ProcessConstraints.purs b/src/Internal/ProcessConstraints.purs index 0e12ded53b..a2cf08b0dd 100644 --- a/src/Internal/ProcessConstraints.purs +++ b/src/Internal/ProcessConstraints.purs @@ -4,6 +4,12 @@ module Ctl.Internal.ProcessConstraints import Prelude +import Cardano.Transaction.Edit + ( DetachedRedeemer + , RedeemerPurpose(ForSpend, ForMint, ForReward, ForCert) + , attachRedeemers + , mkRedeemersContext + ) import Cardano.Types ( Certificate ( StakeDelegation @@ -23,7 +29,7 @@ import Cardano.Types , TransactionInput , TransactionOutput(TransactionOutput) , TransactionUnspentOutput(TransactionUnspentOutput) - , TransactionWitnessSet(TransactionWitnessSet) + , UtxoMap , Value(Value) ) import Cardano.Types.Address @@ -49,11 +55,6 @@ import Control.Monad.Except.Trans (ExceptT(ExceptT), except, runExceptT) import Control.Monad.Reader.Class (asks) import Control.Monad.State.Trans (get, gets, put, runStateT) import Control.Monad.Trans.Class (lift) -import Ctl.Internal.BalanceTx.RedeemerIndex - ( RedeemerPurpose(ForReward, ForCert, ForMint, ForSpend) - , UnindexedRedeemer(UnindexedRedeemer) - , unindexedRedeemerToRedeemer - ) import Ctl.Internal.Contract (getProtocolParameters) import Ctl.Internal.Contract.Monad (Contract, getQueryHandle, wrapQueryM) import Ctl.Internal.Helpers (liftEither, liftM, unsafeFromJust) @@ -67,34 +68,9 @@ import Ctl.Internal.Lens , _outputs , _referenceInputs , _requiredSigners - , _scriptDataHash , _withdrawals - , _witnessSet - ) -import Ctl.Internal.ProcessConstraints.Error - ( MkUnbalancedTxError - ( CannotSatisfyAny - , CannotWithdrawRewardsNativeScript - , CannotWithdrawRewardsPlutusScript - , CannotWithdrawRewardsPubKey - , DatumWrongHash - , CannotMintZero - , ExpectedPlutusScriptGotNativeScript - , CannotFindDatum - , CannotQueryDatum - , CannotGetValidatorHashFromAddress - , TxOutRefWrongType - , CannotConvertPOSIXTimeRange - , NumericOverflow - , WrongRefScriptHash - , ValidatorHashNotFound - , MintingPolicyNotFound - , DatumNotFound - , TxOutRefNotFound - , CannotSolveTimeConstraints - , OwnPubKeyAndStakeKeyMissing - ) ) +import Ctl.Internal.ProcessConstraints.Error (MkUnbalancedTxError(..)) import Ctl.Internal.ProcessConstraints.State ( ConstraintProcessingState , ConstraintsM @@ -112,7 +88,6 @@ import Ctl.Internal.ProcessConstraints.State , requireValue , totalMissingValue ) -import Ctl.Internal.ProcessConstraints.UnbalancedTx (UnbalancedTx) import Ctl.Internal.QueryM.Pools ( getPubKeyHashDelegationsAndRewards , getValidatorHashDelegationsAndRewards @@ -175,14 +150,14 @@ import Data.Array (mapMaybe, singleton, (:)) as Array import Data.Bifunctor (lmap) import Data.Either (Either(Left, Right), either, hush, isRight, note) import Data.Foldable (foldM) -import Data.Lens ((%=), (%~), (.=), (.~), (<>=)) -import Data.Lens.Getter (to, use) +import Data.Lens ((%=), (.=), (<>=)) +import Data.Lens.Getter (use) import Data.Lens.Iso.Newtype (_Newtype) import Data.List (List(Nil, Cons)) import Data.Map (Map, empty, fromFoldable, lookup, union) import Data.Map as Map import Data.Maybe (Maybe(Nothing, Just), fromMaybe, maybe) -import Data.Newtype (over, unwrap, wrap) +import Data.Newtype (unwrap, wrap) import Data.Set as Set import Data.Traversable (for, traverse_) import Data.Tuple.Nested (type (/\), (/\)) @@ -287,8 +262,11 @@ addFakeScriptDataHash = runExceptT do dats <- use _datums costModels <- use _costModels -- Use both script and minting redeemers in the order they were appended. - reds <- use (_redeemers <<< to (map unindexedRedeemerToRedeemer)) tx <- use _cpsTransaction + let + ctx = mkRedeemersContext tx + reds <- ExceptT $ use _redeemers <#> attachRedeemers ctx >>> lmap + CannotAttachRedeemer tx' <- ExceptT $ liftEffect $ setScriptDataHash costModels reds dats tx <#> Right _cpsTransaction .= tx' @@ -560,11 +538,12 @@ processConstraint Nothing -> throwError CannotFindDatum _cpsTransaction <<< _body <<< _inputs %= appendInputs [ txo ] let - uiRedeemer = UnindexedRedeemer + dRedeemer :: DetachedRedeemer + dRedeemer = { purpose: ForSpend txo - , datum: unwrap red + , datum: red } - _redeemers <>= [ uiRedeemer ] + _redeemers <>= [ dRedeemer ] _valueSpentBalancesInputs <>= provideValue amount MustSpendNativeScriptOutput txo ns -> runExceptT do _cpsTransaction <<< _body <<< _inputs %= appendInputs [ txo ] @@ -605,7 +584,7 @@ processConstraint mkValue $ unsafeFromJust "processConstraints" $ Int.asPositive i _valueSpentBalancesOutputs <>= provideValue value _redeemers <>= - [ UnindexedRedeemer { purpose: ForMint scriptHash, datum: unwrap red } ] + [ { purpose: ForMint scriptHash, datum: red } ] -- Remove mint redeemers from array before reindexing. unsafePartial $ _cpsTransaction <<< _body <<< _mint <>= Just mint @@ -733,9 +712,7 @@ processConstraint ( PlutusScript.hash plutusScript ) _redeemers <>= - [ UnindexedRedeemer - { purpose: ForCert cert, datum: unwrap redeemerData } - ] + [ { purpose: ForCert cert, datum: redeemerData } ] void $ lift $ addCertificate cert lift $ attachToCps (map pure <<< attachPlutusScript) plutusScript MustDeregisterStakeNativeScript stakeValidator -> do @@ -765,9 +742,7 @@ processConstraint poolKeyHash lift $ addCertificate cert _redeemers <>= - [ UnindexedRedeemer - { purpose: ForCert cert, datum: unwrap redeemerData } - ] + [ { purpose: ForCert cert, datum: redeemerData } ] lift $ attachToCps (map pure <<< attachPlutusScript) stakeValidator MustDelegateStakeNativeScript stakeValidator poolKeyHash -> do void $ addCertificate $ StakeDelegation @@ -806,9 +781,7 @@ processConstraint _cpsTransaction <<< _body <<< _withdrawals %= Map.insert rewardAddress (fromMaybe Coin.zero rewards) _redeemers <>= - [ UnindexedRedeemer - { purpose: ForReward rewardAddress, datum: unwrap redeemerData } - ] + [ { purpose: ForReward rewardAddress, datum: redeemerData } ] lift $ attachToCps (map pure <<< attachPlutusScript) stakeValidator MustWithdrawStakeNativeScript stakeValidator -> runExceptT do let hash = NativeScript.hash stakeValidator @@ -899,24 +872,9 @@ getNetworkId = use (_cpsTransaction <<< _body <<< _networkId) >>= maybe (asks _.networkId) pure mkUnbalancedTxImpl - :: forall (validator :: Type) (datum :: Type) (redeemer :: Type) - . ScriptLookups + :: ScriptLookups -> TxConstraints - -> Contract (Either MkUnbalancedTxError UnbalancedTx) + -> Contract (Either MkUnbalancedTxError (Transaction /\ UtxoMap)) mkUnbalancedTxImpl scriptLookups txConstraints = runConstraintsM scriptLookups txConstraints <#> map - \{ transaction, redeemers, usedUtxos } -> - wrap - { transaction: stripRedeemers $ stripScriptDataHash transaction - , redeemers - , usedUtxos - } - where - stripScriptDataHash :: Transaction -> Transaction - stripScriptDataHash = - _body <<< _scriptDataHash .~ Nothing - - stripRedeemers :: Transaction -> Transaction - stripRedeemers = _witnessSet %~ - over TransactionWitnessSet - _ { redeemers = [] } + \({ transaction, usedUtxos }) -> transaction /\ usedUtxos diff --git a/src/Internal/ProcessConstraints/Error.purs b/src/Internal/ProcessConstraints/Error.purs index 5190256602..8b7d12d880 100644 --- a/src/Internal/ProcessConstraints/Error.purs +++ b/src/Internal/ProcessConstraints/Error.purs @@ -4,6 +4,7 @@ import Prelude import Cardano.AsCbor (encodeCbor) import Cardano.Serialization.Lib (toBytes) +import Cardano.Transaction.Edit (DetachedRedeemer) import Cardano.Types (DataHash, NativeScript) import Cardano.Types.Address (Address) import Cardano.Types.Address as Address @@ -59,6 +60,7 @@ data MkUnbalancedTxError | ExpectedPlutusScriptGotNativeScript ScriptHash | CannotMintZero ScriptHash AssetName | NumericOverflow + | CannotAttachRedeemer DetachedRedeemer derive instance Generic MkUnbalancedTxError _ derive instance Eq MkUnbalancedTxError @@ -155,6 +157,10 @@ explainMkUnbalancedTxError = case _ of <> " of currency " <> byteArrayToHex (unwrap $ encodeCbor cs) NumericOverflow -> "Numeric overflow" + CannotAttachRedeemer redeemer -> do + "Can't attach a redeemer: " <> show redeemer + <> "\nPlease report this as a bug here: " + <> bugTrackerLink where prettyAssetName :: AssetName -> String diff --git a/src/Internal/ProcessConstraints/State.purs b/src/Internal/ProcessConstraints/State.purs index 41d8f56de7..8f923d2fa0 100644 --- a/src/Internal/ProcessConstraints/State.purs +++ b/src/Internal/ProcessConstraints/State.purs @@ -20,10 +20,10 @@ module Ctl.Internal.ProcessConstraints.State import Prelude hiding (join) +import Cardano.Transaction.Edit (DetachedRedeemer) import Cardano.Types (CostModel, Language, PlutusData, Transaction, UtxoMap) import Cardano.Types.Value (Value) import Control.Monad.State.Trans (StateT) -import Ctl.Internal.BalanceTx.RedeemerIndex (UnindexedRedeemer) import Ctl.Internal.Contract.Monad (Contract) import Ctl.Internal.Types.ScriptLookups (ScriptLookups) import Ctl.Internal.Types.Val (Val, split) @@ -58,7 +58,7 @@ type ConstraintProcessingState = -- ^ Balance of the values produced and required for the transaction's outputs , datums :: Array PlutusData -- ^ Ordered accumulation of datums we can use to `setScriptDataHash` - , redeemers :: Array UnindexedRedeemer + , redeemers :: Array DetachedRedeemer -- ^ Unindexed redeemers that will be attached to the Tx later, on balancing -- stage. , lookups :: ScriptLookups @@ -94,7 +94,7 @@ _costModels _costModels = prop (Proxy :: Proxy "costModels") _redeemers - :: Lens' ConstraintProcessingState (Array UnindexedRedeemer) + :: Lens' ConstraintProcessingState (Array DetachedRedeemer) _redeemers = prop (Proxy :: Proxy "redeemers") _lookups diff --git a/src/Internal/ProcessConstraints/UnbalancedTx.purs b/src/Internal/ProcessConstraints/UnbalancedTx.purs deleted file mode 100644 index c90c3d626c..0000000000 --- a/src/Internal/ProcessConstraints/UnbalancedTx.purs +++ /dev/null @@ -1,30 +0,0 @@ -module Ctl.Internal.ProcessConstraints.UnbalancedTx - ( UnbalancedTx(UnbalancedTx) - ) where - -import Prelude hiding (join) - -import Cardano.Types.Transaction (Transaction) -import Cardano.Types.TransactionInput (TransactionInput) -import Cardano.Types.TransactionOutput (TransactionOutput) -import Ctl.Internal.BalanceTx.RedeemerIndex (UnindexedRedeemer) -import Data.Generic.Rep (class Generic) -import Data.Map (Map) -import Data.Newtype (class Newtype) -import Data.Show.Generic (genericShow) - --- | A newtype for the unbalanced transaction after creating one with datums --- | and redeemers not attached. -newtype UnbalancedTx = UnbalancedTx - { transaction :: Transaction -- the unbalanced tx created - , usedUtxos :: Map TransactionInput TransactionOutput - , redeemers :: Array UnindexedRedeemer - } - -derive instance Generic UnbalancedTx _ -derive instance Newtype UnbalancedTx _ -derive newtype instance Eq UnbalancedTx --- derive newtype instance EncodeAeson UnbalancedTx - -instance Show UnbalancedTx where - show = genericShow diff --git a/src/Internal/Test/KeyDir.purs b/src/Internal/Test/KeyDir.purs index a623be215a..8679ce208f 100644 --- a/src/Internal/Test/KeyDir.purs +++ b/src/Internal/Test/KeyDir.purs @@ -395,7 +395,7 @@ returnFunds backup env allWalletsArray mbFundTotal hasRun = lookups = unspentOutputs utxos unbalancedTx <- liftedE $ mkUnbalancedTxImpl lookups constraints - balancedTx <- balanceTx unbalancedTx + balancedTx <- balanceTx unbalancedTx Map.empty mempty balancedSignedTx <- Array.foldM (\tx wallet -> withKeyWallet wallet $ signTransaction tx) (wrap $ unwrap balancedTx) diff --git a/src/Internal/Test/UtxoDistribution.purs b/src/Internal/Test/UtxoDistribution.purs index ef04613156..35f1f16a81 100644 --- a/src/Internal/Test/UtxoDistribution.purs +++ b/src/Internal/Test/UtxoDistribution.purs @@ -219,7 +219,7 @@ transferFundsFromEnterpriseToBase ourKey wallets = do unbalancedTx <- mkUnbalancedTx lookups constraints signedTx <- withKeyWallet ourWallet $ - signTransaction =<< balanceTx unbalancedTx + signTransaction =<< balanceTx unbalancedTx Map.empty mempty signedTx' <- foldM (\tx { wallet } -> withKeyWallet wallet $ signTransaction tx) signedTx diff --git a/src/Internal/Types/RedeemerDatum.purs b/src/Internal/Types/RedeemerDatum.purs deleted file mode 100644 index c5ef2dc6a6..0000000000 --- a/src/Internal/Types/RedeemerDatum.purs +++ /dev/null @@ -1,27 +0,0 @@ -module Ctl.Internal.Types.RedeemerDatum where - -import Prelude - -import Cardano.FromData (class FromData) -import Cardano.ToData (class ToData, toData) -import Cardano.Types.PlutusData (PlutusData) -import Data.Generic.Rep (class Generic) -import Data.Newtype (class Newtype) -import Data.Show.Generic (genericShow) -import Prelude as Prelude - --- | Redeemer without ExUnits, tag or index - just a plain wrapper over `PlutusData` -newtype RedeemerDatum = RedeemerDatum PlutusData - -derive instance Generic RedeemerDatum _ -derive instance Newtype RedeemerDatum _ -derive newtype instance Eq RedeemerDatum -derive newtype instance FromData RedeemerDatum -derive newtype instance Ord RedeemerDatum -derive newtype instance ToData RedeemerDatum - -instance Show RedeemerDatum where - show = genericShow - -unit :: RedeemerDatum -unit = RedeemerDatum (toData Prelude.unit) diff --git a/src/Internal/Types/TxConstraints.purs b/src/Internal/Types/TxConstraints.purs index a6185715be..92b6afbc10 100644 --- a/src/Internal/Types/TxConstraints.purs +++ b/src/Internal/Types/TxConstraints.purs @@ -110,9 +110,9 @@ import Cardano.Types ) import Cardano.Types.Int as Int import Cardano.Types.Mint as Mint +import Cardano.Types.RedeemerDatum (RedeemerDatum) +import Cardano.Types.RedeemerDatum as RedeemerDatum import Ctl.Internal.Types.Interval (POSIXTimeRange) -import Ctl.Internal.Types.RedeemerDatum (RedeemerDatum) -import Ctl.Internal.Types.RedeemerDatum as RedeemerDatum import Data.Array (singleton) import Data.Array (singleton) as X import Data.Array as Array diff --git a/src/Internal/UseConstraints.purs b/src/Internal/UseConstraints.purs deleted file mode 100644 index 19144534d9..0000000000 --- a/src/Internal/UseConstraints.purs +++ /dev/null @@ -1,379 +0,0 @@ -module Ctl.Internal.UseConstraints where - -import Prelude - -import Cardano.AsCbor (encodeCbor) -import Cardano.Types - ( DataHash - , NetworkId - , PlutusData - , PlutusScript - , StakeCredential - , Transaction - , TransactionInput - , TransactionUnspentOutput - ) -import Cardano.Types.Address (getPaymentCredential) -import Cardano.Types.Certificate (Certificate(..)) -import Cardano.Types.Coin (Coin) -import Cardano.Types.CostModel (CostModel) -import Cardano.Types.Credential as Credential -import Cardano.Types.DataHash as PlutusData -import Cardano.Types.Language (Language) -import Cardano.Types.NativeScript (NativeScript) -import Cardano.Types.OutputDatum (OutputDatum(OutputDatumHash, OutputDatum)) -import Cardano.Types.TransactionBody (TransactionBody) -import Contract.Constraints - ( Constraint(..) - , Constraints - , CredentialWitness(..) - , DatumWitness(..) - , OutputWitness(..) - , RefInputAction(..) - , ScriptWitness(..) - ) -import Control.Monad.Error.Class (throwError) -import Control.Monad.Except (Except) -import Control.Monad.State (StateT) -import Control.Monad.State.Trans (gets) -import Ctl.Internal.BalanceTx.RedeemerIndex - ( RedeemerPurpose(ForSpend, ForCert) - , UnindexedRedeemer(UnindexedRedeemer) - ) -import Ctl.Internal.Lens - ( _address - , _body - , _certs - , _datum - , _inputs - , _isValid - , _nativeScripts - , _output - , _outputs - , _plutusData - , _plutusScripts - , _referenceInputs - , _requiredSigners - , _ttl - , _validityStartInterval - , _withdrawals - , _witnessSet - ) -import Data.Array (nub) -import Data.ByteArray (byteArrayToHex) -import Data.Lens (Lens', (%=), (.=), (<>=), (^.)) -import Data.Lens.Record (prop) -import Data.Map (Map) -import Data.Map as Map -import Data.Maybe (Maybe(Just, Nothing), isJust) -import Data.Newtype (unwrap, wrap) -import Data.Set as Set -import Data.Traversable (traverse_) -import Type.Proxy (Proxy(..)) - -type Context = - { transaction :: Transaction - , costModels :: Map Language CostModel - , redeemers :: Array UnindexedRedeemer - , datums :: Array PlutusData - , networkId :: NetworkId - } - -_transaction - :: Lens' Context Transaction -_transaction = prop (Proxy :: Proxy "transaction") - -_redeemers - :: Lens' Context (Array UnindexedRedeemer) -_redeemers = prop (Proxy :: Proxy "redeemers") - -_datums - :: Lens' Context (Array PlutusData) -_datums = prop (Proxy :: Proxy "datums") - -data ExpectedWitnessType = ScriptHashWitness | PubKeyHashWitness - -explainExpectedWitnessType :: ExpectedWitnessType -> String -explainExpectedWitnessType ScriptHashWitness = "ScriptHash" -explainExpectedWitnessType PubKeyHashWitness = "PubKeyHash" - -data CredentialAction = StakeCert | Withdrawal | Minting - -explainCredentialAction :: CredentialAction -> String -explainCredentialAction StakeCert = "This stake certificate" -explainCredentialAction Withdrawal = "This stake rewards withdrawal" -explainCredentialAction Minting = "This mint" - -data TxBuildError - = WrongSpendWitnessType TransactionUnspentOutput - | DatumHashLookupError DataHash - | IncorrectDatumHash TransactionUnspentOutput PlutusData DataHash - | WrongOutputType ExpectedWitnessType TransactionUnspentOutput - | WrongStakeCredentialType CredentialAction ExpectedWitnessType - StakeCredential - | DatumWitnessNotProvided TransactionUnspentOutput - | UnneededDatumWitness TransactionUnspentOutput DatumWitness - -explainTxBuildError :: TxBuildError -> String -explainTxBuildError (WrongSpendWitnessType utxo) = - "`OutputWitness` is incompatible with the given output. The output does not contain a datum: " - <> show utxo -explainTxBuildError (DatumHashLookupError dataHash) = - "The UTxO you are trying to spend contains a datum hash. You didn't provide a `DatumWitness` value corresponding to this hash, so CTL tried to look it up, using a database of datums observed on-chain. This lookup failed. Datum hash: " - <> show dataHash -explainTxBuildError (IncorrectDatumHash utxo datum datumHash) = - "You provided a `DatumWitness` with a datum that does not match the datum hash present in a transaction output.\n Datum: " - <> show datum - <> " (CBOR: " - <> byteArrayToHex (unwrap $ encodeCbor datum) - <> ")\n Datum hash: " - <> byteArrayToHex (unwrap $ encodeCbor datumHash) - <> "\n UTxO: " - <> show utxo -explainTxBuildError (WrongOutputType ScriptHashWitness utxo) = - "The UTxO you provided requires a Script witness to unlock. UTxO: " <> show - utxo -explainTxBuildError (WrongOutputType PubKeyHashWitness utxo) = - "The UTxO you provided requires a PubKeyHash witness to unlock. UTxO: " <> - show utxo -explainTxBuildError - (WrongStakeCredentialType operation expWitnessType stakeCredential) = - explainCredentialAction operation <> " requires a " - <> explainExpectedWitnessType expWitnessType - <> " witness: " - <> show stakeCredential -explainTxBuildError (DatumWitnessNotProvided utxo) = - "The UTxO you are trying to spend contains a datum hash. A matching `DatumWitness` is required. Use `getDatumByHash`. UTxO: " - <> show utxo -explainTxBuildError (UnneededDatumWitness utxo witness) = - "You've provided an optional `DatumWitness`, but the output you are spending already contains an inline datum (not just a datum hash). You should omit the provided datum witness. You provided: " - <> show witness - <> " for the UTxO: " - <> show utxo -explainTxBuildError _ = "TODO" - -type M a = StateT Context (Except TxBuildError) a - -processConstraints :: Constraints -> M Unit -processConstraints = traverse_ processConstraint - -processConstraint :: Constraint -> M Unit -processConstraint = case _ of - SpendOutput utxo spendWitness -> do - _transaction <<< _body <<< _inputs - %= pushUnique (unwrap utxo).input - useSpendWitness utxo spendWitness - PayTo utxo -> do - _transaction <<< _body <<< _outputs - -- intentionally not using pushUnique: we can - -- create multiple outputs of the same shape - %= flip append [ utxo ] - RegisterStake stakeCredential -> do - _transaction <<< _body <<< _certs %= pushUnique - (StakeRegistration stakeCredential) - IssueCertificate cert witness -> do - useCertificateWitness cert witness - WithdrawStake stakeCredential amount witness -> do - useWithdrawRewardsWitness stakeCredential amount witness - RequireSignature ppkh -> do - _transaction <<< _body <<< _requiredSigners <>= - [ wrap $ unwrap $ unwrap ppkh ] - RegisterPool poolParams -> do - _transaction <<< _body <<< _certs %= pushUnique - (PoolRegistration poolParams) - RetirePool poolKeyHash epoch -> do - _transaction <<< _body <<< _certs %= pushUnique - (PoolRetirement { poolKeyHash, epoch }) - IncludeDatum datum -> do - _datums %= pushUnique datum - _transaction <<< _witnessSet <<< _plutusData - %= pushUnique datum - SetTTL slot -> do - _transaction <<< _body <<< _ttl .= slot - SetValidityStartInterval slot -> do - _transaction <<< _body <<< _validityStartInterval .= slot - SetIsValid isValid -> do - _transaction <<< _isValid .= isValid - -assertOutputType :: ExpectedWitnessType -> TransactionUnspentOutput -> M Unit -assertOutputType outputType utxo = do - let - mbCredential = - (getPaymentCredential (utxo ^. _output <<< _address) <#> unwrap) - >>= case outputType of - ScriptHashWitness -> Credential.asScriptHash >>> void - PubKeyHashWitness -> Credential.asPubKeyHash >>> void - unless (isJust mbCredential) do - throwError $ WrongOutputType outputType utxo - -assertStakeCredentialType - :: CredentialAction -> ExpectedWitnessType -> StakeCredential -> M Unit -assertStakeCredentialType action expectedType credential = do - let - mbCredential = - case expectedType of - ScriptHashWitness -> - void $ Credential.asScriptHash $ unwrap credential - PubKeyHashWitness -> - void $ Credential.asPubKeyHash $ unwrap credential - unless (isJust mbCredential) do - throwError $ WrongStakeCredentialType action expectedType credential - -useCertificateWitness :: Certificate -> CredentialWitness -> M Unit -useCertificateWitness cert witness = do - _transaction <<< _body <<< _certs %= pushUnique cert - case cert of - StakeDeregistration stakeCredential -> do - useCertificateCredentialWitness cert witness - useCredentialWitness StakeCert stakeCredential witness - StakeDelegation stakeCredential _ -> do - useCertificateCredentialWitness cert witness - useCredentialWitness StakeCert stakeCredential witness - StakeRegistration _ -> pure unit - PoolRegistration _ -> pure unit - PoolRetirement _ -> pure unit - GenesisKeyDelegation _ -> pure unit - MoveInstantaneousRewardsCert _ -> pure unit - -useCertificateCredentialWitness :: Certificate -> CredentialWitness -> M Unit -useCertificateCredentialWitness cert witness = do - case witness of - PubKeyCredential -> pure unit - NativeScriptCredential _nsWitness -> pure unit - PlutusScriptCredential _plutusScriptWitness redeemerDatum -> do - -- attach the redeemer - let - uiRedeemer = UnindexedRedeemer - { purpose: ForCert cert - , datum: unwrap redeemerDatum - } - _redeemers %= pushUnique uiRedeemer - -useCredentialWitness - :: CredentialAction -> StakeCredential -> CredentialWitness -> M Unit -useCredentialWitness credentialAction stakeCredential witness = do - case witness of - PubKeyCredential -> do - assertStakeCredentialType credentialAction PubKeyHashWitness - stakeCredential - NativeScriptCredential nsWitness -> do - assertStakeCredentialType credentialAction ScriptHashWitness - stakeCredential - useNativeScriptWitness nsWitness - PlutusScriptCredential plutusScriptWitness _ -> do - assertStakeCredentialType credentialAction ScriptHashWitness - stakeCredential - usePlutusScriptWitness plutusScriptWitness - -useWithdrawRewardsWitness - :: StakeCredential -> Coin -> CredentialWitness -> M Unit -useWithdrawRewardsWitness stakeCredential amount witness = do - useCredentialWitness Withdrawal stakeCredential witness - networkId <- gets _.networkId - let - rewardAddress = - { networkId - , stakeCredential - } - _transaction <<< _body <<< _withdrawals %= - Map.insert rewardAddress amount - pure unit - --- | Tries to modify the transaction to make it consume a given output. --- | Uses a `SpendWitness` to try to satisfy spending requirements. -useSpendWitness :: TransactionUnspentOutput -> OutputWitness -> M Unit -useSpendWitness utxo = case _ of - PubKeyOutput -> do - assertOutputType PubKeyHashWitness utxo - NativeScriptOutput nsWitness -> do - assertOutputType ScriptHashWitness utxo - -- attach the script - useNativeScriptWitness nsWitness - PlutusScriptOutput plutusScriptWitness redeemerDatum mbDatumWitness -> do - assertOutputType ScriptHashWitness utxo - -- attach the script - usePlutusScriptWitness plutusScriptWitness - -- attach the datum - useDatumWitnessForUtxo utxo mbDatumWitness - -- attach the redeemer - let - uiRedeemer = UnindexedRedeemer - { purpose: ForSpend (unwrap utxo).input - , datum: unwrap redeemerDatum - } - _redeemers %= pushUnique uiRedeemer - -usePlutusScriptWitness :: ScriptWitness PlutusScript -> M Unit -usePlutusScriptWitness = - case _ of - ScriptValue ps -> do - _transaction <<< _witnessSet <<< _plutusScripts - %= pushUnique ps - ScriptReference input action -> do - _transaction <<< _body <<< refInputActionToLens action - %= pushUnique input - -useNativeScriptWitness :: ScriptWitness NativeScript -> M Unit -useNativeScriptWitness = - case _ of - ScriptValue ns -> do - _transaction <<< _witnessSet <<< _nativeScripts - %= pushUnique ns - ScriptReference refInput refInputAction -> do - _transaction <<< _body <<< refInputActionToLens refInputAction - %= pushUnique refInput - --- | Tries to modify the transaction state to make it consume a given script output. --- | Uses a `DatumWitness` if the UTxO datum is provided as a hash. -useDatumWitnessForUtxo - :: TransactionUnspentOutput -> Maybe DatumWitness -> M Unit -useDatumWitnessForUtxo utxo mbDatumWitness = do - case utxo ^. _output <<< _datum of - -- script outputs must have a datum - Nothing -> throwError $ WrongSpendWitnessType utxo - -- if the datum is inline, we don't need to attach it as witness - Just (OutputDatum _providedDatum) -> do - case mbDatumWitness of - Just datumWitness -> - throwError $ UnneededDatumWitness utxo datumWitness - Nothing -> pure unit - -- if the datum is provided as hash, - Just (OutputDatumHash datumHash) -> - case mbDatumWitness of - -- if the datum witness was not provided, look the datum up - Nothing -> do - throwError $ DatumWitnessNotProvided utxo - -- if the datum was provided, check it's hash. if it matches the one - -- specified in the output, use that datum. - Just (DatumValue providedDatum) - | datumHash == PlutusData.hashPlutusData providedDatum -> do - _datums %= pushUnique providedDatum - _transaction <<< _witnessSet <<< _plutusData - %= pushUnique providedDatum - -- otherwise, fail - Just (DatumValue providedDatum) -> do - throwError $ IncorrectDatumHash utxo providedDatum datumHash - -- if a reference input is provided, we just attach it. - -- TODO: consider querying for the inline datum to check if it matches. - Just (DatumReference datumWitnessRef refInputAction) -> do - _transaction <<< _body <<< refInputActionToLens refInputAction - %= pushUnique datumWitnessRef - --- | Depending on `RefInputAction` value, we either want to spend a reference --- | UTxO, or just reference it. -refInputActionToLens - :: RefInputAction - -> Lens' TransactionBody (Array TransactionInput) -refInputActionToLens = - case _ of - ReferenceInput -> _referenceInputs - SpendInput -> _inputs - --- | Ensures uniqueness of an element -pushUnique :: forall a. Ord a => a -> Array a -> Array a -pushUnique x xs = nub $ xs <> [ x ] - --- Ensures uniqueness -appendInput - :: TransactionInput -> Array TransactionInput -> Array TransactionInput -appendInput a b = Set.toUnfoldable (Set.singleton a <> Set.fromFoldable b) diff --git a/test/BalanceTx/Time.purs b/test/BalanceTx/Time.purs index c1f5487d50..739d120a7a 100644 --- a/test/BalanceTx/Time.purs +++ b/test/BalanceTx/Time.purs @@ -1,15 +1,13 @@ module Test.Ctl.BalanceTx.Time (suite) where import Contract.Prelude +import Data.Lens -import Cardano.Types.BigNum (BigNum) +import Cardano.Types (BigNum, Transaction, _body) import Cardano.Types.BigNum (fromInt, toInt) as BigNum import Contract.Config (testnetConfig) import Contract.Monad (Contract, runContract) -import Contract.ScriptLookups - ( ScriptLookups - , UnbalancedTx - ) +import Contract.ScriptLookups (ScriptLookups) import Contract.Time ( POSIXTime , Slot @@ -146,10 +144,8 @@ unsafeSubtractOne value = wrap <<< fromJust -------------------------------------------------------------------------------- getTimeFromUnbalanced - :: UnbalancedTx -> Contract (Interval POSIXTime) -getTimeFromUnbalanced utx = validityToPosixTime $ unwrap body - where - body = (unwrap utx) # _.transaction >>> unwrap >>> _.body + :: Transaction -> Contract (Interval POSIXTime) +getTimeFromUnbalanced tx = validityToPosixTime $ unwrap $ tx ^. _body toPosixTime :: Slot -> Contract POSIXTime toPosixTime time = do diff --git a/test/Fixtures.purs b/test/Fixtures.purs index e4a9f0783f..194d17dfd0 100644 --- a/test/Fixtures.purs +++ b/test/Fixtures.purs @@ -1351,7 +1351,7 @@ redeemerFixture1 :: Redeemer redeemerFixture1 = Redeemer { tag: Spend , index: BigNum.fromInt 0 - , data: plutusDataFixture7 + , data: wrap plutusDataFixture7 , exUnits: ExUnits { mem: BigNum.fromInt 1 , steps: BigNum.fromInt 1 diff --git a/test/Plutip.purs b/test/Plutip.purs index 2a582b2249..648bea2e43 100644 --- a/test/Plutip.purs +++ b/test/Plutip.purs @@ -20,6 +20,7 @@ import Ctl.Internal.Plutip.Server , stopPlutipCluster ) import Ctl.Internal.Plutip.Types (StopClusterResponse(StopClusterSuccess)) +import Data.Log.Level (LogLevel(..)) import Data.Maybe (Maybe(Just)) import Data.Posix.Signal (Signal(SIGINT)) import Effect (Effect) @@ -36,7 +37,7 @@ import Mote.Monad (mapTest) import Mote.TestPlanM (TestPlanM) import Mote.TestPlanM as Utils import Test.Ctl.BalanceTx.ChangeGeneration as ChangeGeneration -import Test.Ctl.Plutip.Common (config) +import Test.Ctl.Plutip.Common (config) as Config import Test.Ctl.Plutip.Contract as Contract import Test.Ctl.Plutip.Contract.Assert as Assert import Test.Ctl.Plutip.Contract.ClusterParameters as ClusterParameters @@ -50,6 +51,8 @@ import Test.Ctl.QueryM.AffInterface as QueryM.AffInterface import Test.Spec.Assertions (shouldSatisfy) import Test.Spec.Runner (defaultConfig) +config = Config.config { suppressLogs = false, logLevel = Trace } + -- Run with `npm run plutip-test` main :: Effect Unit main = interruptOnSignal SIGINT =<< launchAff do diff --git a/test/Plutip/Common.purs b/test/Plutip/Common.purs index 3cd0304fb4..0dc461e792 100644 --- a/test/Plutip/Common.purs +++ b/test/Plutip/Common.purs @@ -15,7 +15,7 @@ import Data.Newtype (wrap) import Partial.Unsafe (unsafePartial) config :: PlutipConfig -config = defaultPlutipConfig +config = defaultPlutipConfig { suppressLogs = false } privateStakeKey :: PrivateStakeKey privateStakeKey = wrap $ unsafePartial $ fromJust diff --git a/test/Plutip/Contract.purs b/test/Plutip/Contract.purs index ea91f84bd2..1123e06313 100644 --- a/test/Plutip/Contract.purs +++ b/test/Plutip/Contract.purs @@ -6,11 +6,18 @@ import Prelude import Cardano.AsCbor (decodeCbor) import Cardano.Serialization.Lib (fromBytes) +import Cardano.Transaction.Builder + ( TransactionBuilderStep(..) + , buildTransaction + ) import Cardano.Types ( Address + , Credential(..) , GeneralTransactionMetadata(GeneralTransactionMetadata) + , StakeCredential(..) , TransactionUnspentOutput(TransactionUnspentOutput) ) +import Cardano.Types.Address (mkPaymentAddress) import Cardano.Types.AssetName as AssetName import Cardano.Types.Coin as Coin import Cardano.Types.Credential @@ -18,11 +25,13 @@ import Cardano.Types.Credential ) import Cardano.Types.Int as Int import Cardano.Types.Mint as Mint +import Cardano.Types.PaymentCredential (PaymentCredential(..)) import Cardano.Types.PlutusScript as PlutusScript import Cardano.Types.Value (lovelaceValueOf) import Contract.Address ( PaymentPubKeyHash(PaymentPubKeyHash) , StakePubKeyHash + , getNetworkId , mkAddress ) import Contract.AuxiliaryData (setGeneralTxMetadata) @@ -86,9 +95,10 @@ import Contract.Transaction , _output , awaitTxConfirmed , balanceTx + , balanceTx + , balanceTxE , balanceTxE - , balanceTxWithConstraints - , balanceTxWithConstraintsE + , buildTx , createAdditionalUtxos , getTxMetadata , lookupTxHash @@ -169,7 +179,7 @@ import Data.UInt (UInt) import Effect.Class (liftEffect) import Effect.Exception (error, throw) import JS.BigInt as BigInt -import Mote (group, skip, test) +import Mote (group, only, skip, test) import Mote.TestPlanM (TestPlanM) import Partial.Unsafe (unsafePartial) import Safe.Coerce (coerce) @@ -238,7 +248,7 @@ suite = do lookups = mempty ubTx <- mkUnbalancedTx lookups constraints res <- - ( balanceTxWithConstraintsE ubTx + ( balanceTxE ubTx Map.empty (mustNotSpendUtxosWithOutRefs $ Map.keys utxos) ) res `shouldSatisfy` isLeft @@ -268,7 +278,7 @@ suite = do withWallets distribution \_ → pure unit - group "Contract interface" do + only $ group "Contract interface" do test "mustUseCollateralUtxos should not fail if enough UTxOs are provided" do @@ -312,10 +322,8 @@ suite = do Constraints.mustSpendScriptOutput txInput unitRedeemer ubTx <- mkUnbalancedTx lookups constraints - res <- - ( balanceTxWithConstraintsE ubTx - $ mustUseCollateralUtxos bobsCollateral - ) + res <- balanceTxE ubTx Map.empty + (mustUseCollateralUtxos bobsCollateral) res `shouldSatisfy` isRight test @@ -359,10 +367,7 @@ suite = do Constraints.mustSpendScriptOutput txInput unitRedeemer ubTx <- mkUnbalancedTx lookups constraints - res <- - ( balanceTxWithConstraintsE ubTx - $ mustUseCollateralUtxos Map.empty - ) + res <- balanceTxE ubTx Map.empty (mustUseCollateralUtxos Map.empty) res `shouldSatisfy` case _ of Left (InsufficientCollateralUtxos mp) -> Map.isEmpty mp _ -> false @@ -392,19 +397,23 @@ suite = do withKeyWallet bob do pure unit -- sign, balance, submit, etc. - test "Payment keyhash to payment keyhash transaction (Pkh2Pkh example)" do - let - distribution :: InitialUTxOs - distribution = - [ BigNum.fromInt 10_000_000 - , BigNum.fromInt 20_000_000 - ] - withWallets distribution \alice -> do - checkUtxoDistribution distribution alice - pkh <- liftedM "Failed to get PKH" $ head <$> withKeyWallet alice - ownPaymentPubKeyHashes - stakePkh <- join <<< head <$> withKeyWallet alice ownStakePubKeyHashes - withKeyWallet alice $ pkh2PkhContract pkh stakePkh + only $ test + "Payment keyhash to payment keyhash transaction (Pkh2Pkh example)" + do + let + distribution :: InitialUTxOs + distribution = + [ BigNum.fromInt 10_000_000 + , BigNum.fromInt 20_000_000 + , BigNum.fromInt 20_000_000 + ] + withWallets distribution \alice -> do + logInfo' "407 hi" + checkUtxoDistribution distribution alice + pkh <- liftedM "Failed to get PKH" $ head <$> withKeyWallet alice + ownPaymentPubKeyHashes + stakePkh <- join <<< head <$> withKeyWallet alice ownStakePubKeyHashes + withKeyWallet alice $ pkh2PkhContract pkh stakePkh test "Base Address to Base Address transaction (Pkh2Pkh example, but with stake keys)" do @@ -550,7 +559,7 @@ suite = do lookups = mempty ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx + bsTx <- signTransaction =<< balanceTx ubTx Map.empty mempty txId <- submit bsTx awaitTxConfirmed txId pure txId @@ -584,7 +593,7 @@ suite = do lookups = Lookups.unspentOutputs utxos ubTx <- mkUnbalancedTx lookups constraints - tx <- signTransaction =<< balanceTx ubTx + tx <- signTransaction =<< balanceTx ubTx Map.empty mempty let signWithWallet txToSign wallet = withKeyWallet wallet (signTransaction txToSign) @@ -643,7 +652,7 @@ suite = do lookups = mempty ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx + bsTx <- signTransaction =<< balanceTx ubTx Map.empty mempty txId <- submit bsTx awaitTxConfirmed txId pure txId @@ -668,7 +677,7 @@ suite = do ubTx <- mkUnbalancedTx lookups constraints -- Bob signs the tx - tx <- signTransaction =<< balanceTx ubTx + tx <- signTransaction =<< balanceTx ubTx Map.empty mempty let signWithWallet txToSign wallet = withKeyWallet wallet (signTransaction txToSign) @@ -701,7 +710,7 @@ suite = do lookups = Lookups.plutusMintingPolicy mp ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx + bsTx <- signTransaction =<< balanceTx ubTx Map.empty mempty submitAndLog bsTx test "mustProduceAtLeast spends native token" do @@ -786,7 +795,7 @@ suite = do lookups' = lookups <> Lookups.ownPaymentPubKeyHash pkh ubTx <- mkUnbalancedTx lookups' constraints' - result <- balanceTxE ubTx + result <- balanceTxE ubTx Map.empty mempty result `shouldSatisfy` isLeft test "mustSpendAtLeast succeeds to spend" do @@ -871,7 +880,7 @@ suite = do lookups' = lookups <> Lookups.ownPaymentPubKeyHash pkh ubTx <- mkUnbalancedTx lookups' constraints' - result <- balanceTxE ubTx + result <- balanceTxE ubTx Map.empty mempty result `shouldSatisfy` isLeft test "Minting using NativeScript (multisig) as a policy" do @@ -1028,7 +1037,7 @@ suite = do ubTx <- mkUnbalancedTx lookups constraints let ubTx' = setGeneralTxMetadata ubTx givenMetadata - bsTx <- signTransaction =<< balanceTx ubTx' + bsTx <- signTransaction =<< balanceTx ubTx' Map.empty mempty txId <- submit bsTx awaitTxConfirmed txId @@ -1110,7 +1119,7 @@ suite = do <> Lookups.plutusMintingPolicy mp3 ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx + bsTx <- signTransaction =<< balanceTx ubTx Map.empty mempty submitAndLog bsTx test "Multi-signature transaction" do @@ -1301,7 +1310,7 @@ suite = do BalanceTxConstraints.mustUseAdditionalUtxos additionalUtxos unbalancedTx <- mkUnbalancedTx lookups constraints - balanceTxWithConstraintsE unbalancedTx balanceTxConstraints + balanceTxE unbalancedTx Map.empty balanceTxConstraints let hasInsufficientBalance @@ -1525,7 +1534,7 @@ suite = do lookups = Lookups.plutusMintingPolicy mp ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx + bsTx <- signTransaction =<< balanceTx ubTx Map.empty mempty submit bsTx >>= awaitTxConfirmed logInfo' "Attempt to lock value" @@ -1718,7 +1727,7 @@ suite = do unbalancedTx0 <- mkUnbalancedTx lookups0 constraints0 - withBalancedTx unbalancedTx0 \balancedTx0 -> do + withBalancedTx unbalancedTx0 Map.empty mempty \balancedTx0 -> do balancedSignedTx0 <- signTransaction balancedTx0 additionalUtxos <- createAdditionalUtxos balancedSignedTx0 @@ -1741,7 +1750,7 @@ suite = do BalanceTxConstraints.mustUseAdditionalUtxos additionalUtxos unbalancedTx1 <- mkUnbalancedTx lookups1 constraints1 - balancedTx1 <- balanceTxWithConstraints unbalancedTx1 + balancedTx1 <- balanceTx unbalancedTx1 Map.empty balanceTxConstraints balancedSignedTx1 <- signTransaction balancedTx1 @@ -1832,7 +1841,7 @@ suite = do unbalancedTx0 <- mkUnbalancedTx lookups0 constraints0 - withBalancedTx unbalancedTx0 \balancedTx0 -> do + withBalancedTx unbalancedTx0 Map.empty mempty \balancedTx0 -> do balancedSignedTx0 <- signTransaction balancedTx0 additionalUtxos <- createAdditionalUtxos balancedSignedTx0 @@ -1856,7 +1865,7 @@ suite = do BalanceTxConstraints.mustUseAdditionalUtxos additionalUtxos unbalancedTx1 <- mkUnbalancedTx lookups1 constraints1 - balancedTx1 <- balanceTxWithConstraints unbalancedTx1 + balancedTx1 <- balanceTx unbalancedTx1 Map.empty balanceTxConstraints balancedSignedTx1 <- signTransaction balancedTx1 @@ -2081,7 +2090,16 @@ signMultipleContract = do ubTx1 <- mkUnbalancedTx lookups constraints ubTx2 <- mkUnbalancedTx lookups constraints - withBalancedTxs [ ubTx1, ubTx2 ] $ \txs -> do + withBalancedTxs + [ { transaction: ubTx1 + , extraUtxos: Map.empty + , balancerConstraints: mempty + } + , { transaction: ubTx2 + , extraUtxos: Map.empty + , balancerConstraints: mempty + } + ] $ \txs -> do locked <- getLockedInputs logInfo' $ "Locked inputs inside bracket (should be nonempty): " <> show locked @@ -2098,14 +2116,15 @@ pkh2PkhContract -> Maybe StakePubKeyHash -> Contract Unit pkh2PkhContract pkh stakePkh = do - let - constraints :: Constraints.TxConstraints - constraints = mustPayToPubKeyStakeAddress pkh stakePkh - $ Value.lovelaceValueOf - $ BigNum.fromInt 2_000_000 - - lookups :: Lookups.ScriptLookups - lookups = mempty - ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx - submitAndLog bsTx + address <- mkAddress + (PaymentCredential $ PubKeyHashCredential $ unwrap pkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> stakePkh) + transaction <- buildTx + [ Pay $ TransactionOutput + { address + , amount: Value.coinToValue $ wrap $ BigNum.fromInt 2_000_000 + , datum: Nothing + , scriptRef: Nothing + } + ] + submitAndLog =<< signTransaction =<< balanceTx transaction Map.empty mempty diff --git a/test/Plutip/Staking.purs b/test/Plutip/Staking.purs index 0a9882b2bf..a7b6f0bafd 100644 --- a/test/Plutip/Staking.purs +++ b/test/Plutip/Staking.purs @@ -74,6 +74,7 @@ import Data.Array (head, (!!)) import Data.Array as Array import Data.Either (hush) import Data.Foldable (for_) +import Data.Map as Map import Data.Maybe (Maybe(Just, Nothing)) import Data.Newtype (unwrap, wrap) import Data.Posix.Signal (Signal(SIGINT)) @@ -154,7 +155,7 @@ suite = do Lookups.ownStakePubKeyHash aliceStakePkh ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog -- Deregister stake key do @@ -167,7 +168,7 @@ suite = do Lookups.ownStakePubKeyHash aliceStakePkh ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog test "PlutusScript" do let @@ -203,7 +204,7 @@ suite = do Lookups.ownStakePubKeyHash aliceStakePkh ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog -- Deregister stake key do @@ -220,7 +221,7 @@ suite = do Lookups.ownStakePubKeyHash aliceStakePkh ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog test "NativeScript" do let @@ -251,7 +252,7 @@ suite = do Lookups.ownStakePubKeyHash aliceStakePkh ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog -- Deregister stake key do @@ -264,7 +265,7 @@ suite = do Lookups.ownStakePubKeyHash aliceStakePkh ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog test "Pool registration & retirement" do let @@ -289,7 +290,7 @@ suite = do Lookups.ownStakePubKeyHash aliceStakePkh ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog privateStakeKey <- liftM (error "Failed to get private stake key") $ keyWalletPrivateStakeKey alice @@ -338,7 +339,7 @@ suite = do Lookups.ownStakePubKeyHash aliceStakePkh ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog -- List pools: the pool must appear in the list do @@ -365,7 +366,7 @@ suite = do Lookups.ownStakePubKeyHash aliceStakePkh ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog let waitEpoch :: Epoch -> Contract Epoch @@ -416,7 +417,8 @@ suite = do lookups = mempty ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= + submitAndLog -- Register stake script do @@ -428,7 +430,8 @@ suite = do lookups = mempty ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= + submitAndLog -- Select a pool poolId <- selectPoolId @@ -444,7 +447,8 @@ suite = do Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= + submitAndLog -- Wait until rewards let @@ -475,7 +479,8 @@ suite = do Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= + submitAndLog -- Check rewards. -- Not going to deregister here, because the rewards are added too @@ -528,7 +533,8 @@ suite = do lookups = mempty ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= + submitAndLog -- Alice registers stake script (again, no need to validate it) do @@ -540,7 +546,8 @@ suite = do lookups = mempty ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= + submitAndLog -- Bob performs operations with the stake script that require his -- (and only his) signature. @@ -560,7 +567,8 @@ suite = do Lookups.ownPaymentPubKeyHash bobPkh <> Lookups.ownStakePubKeyHash bobStakePkh ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= + submitAndLog -- Wait until rewards let @@ -591,7 +599,8 @@ suite = do Lookups.ownPaymentPubKeyHash bobPkh <> Lookups.ownStakePubKeyHash bobStakePkh ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= + submitAndLog -- Check rewards. -- Not going to deregister here, because the rewards are added too @@ -627,7 +636,7 @@ suite = do Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog -- Select a pool ID poolId <- selectPoolId @@ -643,7 +652,7 @@ suite = do Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog -- Wait until rewards let @@ -677,7 +686,7 @@ suite = do Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx >>= signTransaction >>= submitAndLog + balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog -- Check rewards. -- Not going to deregister here, because the rewards are added too diff --git a/test/Utils/DrainWallets.purs b/test/Utils/DrainWallets.purs index 6e61639c4c..cd636c29b8 100644 --- a/test/Utils/DrainWallets.purs +++ b/test/Utils/DrainWallets.purs @@ -122,7 +122,7 @@ run privateKey walletsDir = runContract config do unbalancedTx <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTx unbalancedTx + balancedTx <- balanceTx unbalancedTx Map.empty mempty balancedSignedTx <- Array.foldM (\tx wallet -> withKeyWallet wallet $ signTransaction tx) (wrap $ unwrap balancedTx) From 0fef52ee27df5c93a0b52cf81a97cfff6d488006 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Fri, 28 Jun 2024 17:09:07 +0400 Subject: [PATCH 22/52] Fix the tests --- examples/AdditionalUtxos.purs | 21 ++++--- examples/BalanceTxConstraints.purs | 4 +- examples/ChangeGeneration.purs | 9 ++- examples/ContractTestUtils.purs | 4 +- examples/KeyWallet/SignMultiple.purs | 8 +-- examples/OneShotMinting.purs | 7 ++- examples/PlutusV2/ReferenceInputs.purs | 6 +- examples/SignMultiple.purs | 8 +-- examples/TxChaining.purs | 8 +-- src/Contract/Transaction.purs | 4 +- src/Contract/UnbalancedTx.purs | 10 ++- src/Internal/Plutip/Server.purs | 3 +- src/Internal/ProcessConstraints.purs | 6 +- src/Internal/Test/KeyDir.purs | 5 +- src/Internal/Test/UtxoDistribution.purs | 4 +- test/BalanceTx/Time.purs | 6 +- test/Plutip.purs | 5 +- test/Plutip/Common.purs | 2 +- test/Plutip/Contract.purs | 84 ++++++++++++------------- test/Plutip/Staking.purs | 80 +++++++++++------------ test/Utils/DrainWallets.purs | 5 +- 21 files changed, 147 insertions(+), 142 deletions(-) diff --git a/examples/AdditionalUtxos.purs b/examples/AdditionalUtxos.purs index 9431ba1549..b11109d6cf 100644 --- a/examples/AdditionalUtxos.purs +++ b/examples/AdditionalUtxos.purs @@ -46,7 +46,7 @@ import Contract.Value (Value) import Contract.Value (lovelaceValueOf) as Value import Ctl.Examples.PlutusV2.Scripts.AlwaysSucceeds (alwaysSucceedsScriptV2) import Data.Array (fromFoldable) as Array -import Data.Map (difference, empty, filter, keys) as Map +import Data.Map (difference, filter, keys) as Map import JS.BigInt (fromInt) as BigInt import Test.QuickCheck (arbitrary) import Test.QuickCheck.Gen (randomSampleOne) @@ -63,8 +63,8 @@ contract testAdditionalUtxoOverlap = withoutSync do logInfo' "Running Examples.AdditionalUtxos" validator <- alwaysSucceedsScriptV2 let vhash = validatorHash validator - { unbalancedTx, datum } <- payToValidator vhash - withBalancedTx unbalancedTx Map.empty mempty \balancedTx -> do + { unbalancedTx, usedUtxos, datum } <- payToValidator vhash + withBalancedTx unbalancedTx usedUtxos mempty \balancedTx -> do balancedSignedTx <- signTransaction balancedTx txHash <- submit balancedSignedTx when testAdditionalUtxoOverlap $ awaitTxConfirmed txHash @@ -74,7 +74,12 @@ contract testAdditionalUtxoOverlap = withoutSync do spendFromValidator validator additionalUtxos datum payToValidator - :: ValidatorHash -> Contract { unbalancedTx :: Transaction, datum :: Datum } + :: ValidatorHash + -> Contract + { unbalancedTx :: Transaction + , usedUtxos :: UtxoMap + , datum :: Datum + } payToValidator vhash = do scriptRef <- liftEffect (NativeScriptRef <$> randomSampleOne arbitrary) let @@ -93,8 +98,8 @@ payToValidator vhash = do lookups :: ScriptLookups lookups = Lookups.datum datum - unbalancedTx <- mkUnbalancedTx lookups constraints - pure { unbalancedTx, datum } + unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + pure { unbalancedTx, usedUtxos, datum } spendFromValidator :: Validator -> UtxoMap -> Datum -> Contract Unit spendFromValidator validator additionalUtxos datum = do @@ -128,8 +133,8 @@ spendFromValidator validator additionalUtxos datum = do balancerConstraints = BalancerConstraints.mustUseAdditionalUtxos additionalUtxos - unbalancedTx <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTx unbalancedTx Map.empty balancerConstraints + unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balancedTx <- balanceTx unbalancedTx usedUtxos balancerConstraints balancedSignedTx <- signTransaction balancedTx txHash <- submit balancedSignedTx diff --git a/examples/BalanceTxConstraints.purs b/examples/BalanceTxConstraints.purs index 5d597b47b1..937329e404 100644 --- a/examples/BalanceTxConstraints.purs +++ b/examples/BalanceTxConstraints.purs @@ -176,9 +176,9 @@ contract (ContractParams p) = do <> BalanceTxConstraints.mustUseCollateralUtxos bobsCollateral void $ runChecks checks $ lift do - unbalancedTx <- mkUnbalancedTx lookups constraints + unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTx unbalancedTx Map.empty balanceTxConstraints + balancedTx <- balanceTx unbalancedTx usedUtxos balanceTxConstraints balancedSignedTx <- (withKeyWallet p.bobKeyWallet <<< signTransaction) diff --git a/examples/ChangeGeneration.purs b/examples/ChangeGeneration.purs index 5553352120..d96ef33879 100644 --- a/examples/ChangeGeneration.purs +++ b/examples/ChangeGeneration.purs @@ -28,9 +28,8 @@ import Contract.Wallet (ownPaymentPubKeyHashes, ownStakePubKeyHashes) import Ctl.Examples.AlwaysSucceeds as AlwaysSucceeds import Data.Array (fold, length, replicate, take, zip) import Data.Lens ((^.)) -import Data.Map as Map import Data.Maybe (Maybe(Just, Nothing)) -import Data.Tuple (Tuple(Tuple)) +import Data.Tuple.Nested ((/\)) import JS.BigInt (fromInt) as BigInt import Test.Spec.Assertions (shouldEqual) @@ -50,7 +49,7 @@ checkChangeOutputsDistribution outputsToScript outputsToSelf expectedOutputs = constraintsToSelf :: TxConstraints constraintsToSelf = fold <<< take outputsToSelf <<< fold $ replicate outputsToSelf - $ zip pkhs skhs <#> \(Tuple pkh mbSkh) -> case mbSkh of + $ zip pkhs skhs <#> \(pkh /\ mbSkh) -> case mbSkh of Nothing -> Constraints.mustPayToPubKey pkh value Just skh -> Constraints.mustPayToPubKeyAddress pkh skh value @@ -64,8 +63,8 @@ checkChangeOutputsDistribution outputsToScript outputsToSelf expectedOutputs = lookups :: Lookups.ScriptLookups lookups = mempty - unbalancedTx <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTx unbalancedTx Map.empty + unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balancedTx <- balanceTx unbalancedTx usedUtxos -- just to check that attaching datums works ( mustSendChangeWithDatum $ OutputDatum $ Integer $ BigInt.fromInt 1000 diff --git a/examples/ContractTestUtils.purs b/examples/ContractTestUtils.purs index aa8b09b520..edc2ea175e 100644 --- a/examples/ContractTestUtils.purs +++ b/examples/ContractTestUtils.purs @@ -159,8 +159,8 @@ mkContract p = do lookups :: Lookups.ScriptLookups lookups = Lookups.plutusMintingPolicy p.mintingPolicy - unbalancedTx <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTx unbalancedTx Map.empty mempty + unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balancedTx <- balanceTx unbalancedTx usedUtxos mempty balancedSignedTx <- signTransaction balancedTx txId <- submit balancedSignedTx diff --git a/examples/KeyWallet/SignMultiple.purs b/examples/KeyWallet/SignMultiple.purs index 73ed83292b..3e4ee3c958 100644 --- a/examples/KeyWallet/SignMultiple.purs +++ b/examples/KeyWallet/SignMultiple.purs @@ -43,17 +43,17 @@ main = runKeyWalletContract_ \pkh lovelace unlock -> do lookups :: Lookups.ScriptLookups lookups = mempty - unbalancedTx0 <- mkUnbalancedTx lookups constraints - unbalancedTx1 <- mkUnbalancedTx lookups constraints + unbalancedTx0 /\ usedUtxos0 <- mkUnbalancedTx lookups constraints + unbalancedTx1 /\ usedUtxos1 <- mkUnbalancedTx lookups constraints txIds <- withBalancedTxs [ { transaction: unbalancedTx0 - , extraUtxos: Map.empty + , extraUtxos: usedUtxos0 , balancerConstraints: mempty } , { transaction: unbalancedTx1 - , extraUtxos: Map.empty + , extraUtxos: usedUtxos1 , balancerConstraints: mempty } ] $ \balancedTxs -> do diff --git a/examples/OneShotMinting.purs b/examples/OneShotMinting.purs index 72af40ca7b..8c0b1eb617 100644 --- a/examples/OneShotMinting.purs +++ b/examples/OneShotMinting.purs @@ -56,7 +56,7 @@ import Control.Monad.Trans.Class (lift) import Ctl.Examples.Helpers (mkAssetName) as Helpers import Data.Array (head, singleton) as Array import Data.Lens (view) -import Data.Map (empty, toUnfoldable) as Map +import Data.Map (empty, toUnfoldable, union) as Map import Effect.Exception (error, throw) import JS.BigInt (BigInt) @@ -129,8 +129,9 @@ submitTxFromConstraintsReturningFee constraints extraUtxos balancerConstraints = do - unbalancedTx <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTx unbalancedTx extraUtxos balancerConstraints + unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balancedTx <- balanceTx unbalancedTx (Map.union extraUtxos usedUtxos) + balancerConstraints balancedSignedTx <- signTransaction balancedTx txHash <- submit balancedSignedTx pure { txHash, txFinalFee: view (_body <<< _fee) balancedSignedTx } diff --git a/examples/PlutusV2/ReferenceInputs.purs b/examples/PlutusV2/ReferenceInputs.purs index c01672101f..8b47431023 100644 --- a/examples/PlutusV2/ReferenceInputs.purs +++ b/examples/PlutusV2/ReferenceInputs.purs @@ -75,9 +75,9 @@ contract = do lookups = mempty void $ runChecks checks $ lift do - unbalancedTx <- mkUnbalancedTx lookups constraints - balancedSignedTx <- signTransaction =<< balanceTx unbalancedTx Map.empty - mempty + unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balancedSignedTx <- signTransaction + =<< balanceTx unbalancedTx usedUtxos mempty txHash <- submit balancedSignedTx logInfo' $ "Tx ID: " <> show txHash awaitTxConfirmed txHash diff --git a/examples/SignMultiple.purs b/examples/SignMultiple.purs index 1f371a856b..137444f724 100644 --- a/examples/SignMultiple.purs +++ b/examples/SignMultiple.purs @@ -73,17 +73,17 @@ contract = do lookups :: Lookups.ScriptLookups lookups = mempty - unbalancedTx0 <- mkUnbalancedTx lookups constraints - unbalancedTx1 <- mkUnbalancedTx lookups constraints + unbalancedTx0 /\ usedUtxos0 <- mkUnbalancedTx lookups constraints + unbalancedTx1 /\ usedUtxos1 <- mkUnbalancedTx lookups constraints txIds <- withBalancedTxs [ { transaction: unbalancedTx0 - , extraUtxos: Map.empty + , extraUtxos: usedUtxos0 , balancerConstraints: mempty } , { transaction: unbalancedTx1 - , extraUtxos: Map.empty + , extraUtxos: usedUtxos1 , balancerConstraints: mempty } ] $ \balancedTxs -> do diff --git a/examples/TxChaining.purs b/examples/TxChaining.purs index f923869eac..80e995a3c6 100644 --- a/examples/TxChaining.purs +++ b/examples/TxChaining.purs @@ -54,9 +54,9 @@ contract = do lookups0 :: Lookups.ScriptLookups lookups0 = mempty - unbalancedTx0 <- mkUnbalancedTx lookups0 constraints + unbalancedTx0 /\ usedUtxos0 <- mkUnbalancedTx lookups0 constraints - withBalancedTx unbalancedTx0 Map.empty mempty \balancedTx0 -> do + withBalancedTx unbalancedTx0 usedUtxos0 mempty \balancedTx0 -> do balancedSignedTx0 <- signTransaction balancedTx0 additionalUtxos <- createAdditionalUtxos balancedSignedTx0 @@ -70,8 +70,8 @@ contract = do balanceTxConstraints = BalanceTxConstraints.mustUseAdditionalUtxos additionalUtxos - unbalancedTx1 <- mkUnbalancedTx lookups1 constraints - balancedTx1 <- balanceTx unbalancedTx1 Map.empty balanceTxConstraints + unbalancedTx1 /\ usedUtxos1 <- mkUnbalancedTx lookups1 constraints + balancedTx1 <- balanceTx unbalancedTx1 usedUtxos1 balanceTxConstraints balancedSignedTx1 <- signTransaction balancedTx1 txId0 <- submit balancedSignedTx0 diff --git a/src/Contract/Transaction.purs b/src/Contract/Transaction.purs index 003097e677..d7524907ae 100644 --- a/src/Contract/Transaction.purs +++ b/src/Contract/Transaction.purs @@ -387,8 +387,8 @@ submitTxFromConstraints -> TxConstraints -> Contract TransactionHash submitTxFromConstraints lookups constraints = do - unbalancedTx <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTx unbalancedTx Map.empty mempty + unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balancedTx <- balanceTx unbalancedTx usedUtxos mempty balancedSignedTx <- signTransaction balancedTx submit balancedSignedTx diff --git a/src/Contract/UnbalancedTx.purs b/src/Contract/UnbalancedTx.purs index fe88a4eb4a..e8f3491313 100644 --- a/src/Contract/UnbalancedTx.purs +++ b/src/Contract/UnbalancedTx.purs @@ -7,7 +7,7 @@ module Contract.UnbalancedTx import Prelude -import Cardano.Types (Transaction) +import Cardano.Types (Transaction, UtxoMap) import Contract.Monad (Contract) import Control.Monad.Error.Class (throwError) import Ctl.Internal.ProcessConstraints as PC @@ -18,6 +18,7 @@ import Ctl.Internal.ProcessConstraints.Error import Ctl.Internal.Types.ScriptLookups (ScriptLookups) import Ctl.Internal.Types.TxConstraints (TxConstraints) import Data.Either (Either(Left, Right)) +import Data.Tuple.Nested (type (/\)) import Effect.Exception (error) -- | Create an `UnbalancedTx` given `ScriptLookups` and @@ -29,11 +30,14 @@ import Effect.Exception (error) mkUnbalancedTxE :: ScriptLookups -> TxConstraints - -> Contract (Either MkUnbalancedTxError Transaction) + -> Contract (Either MkUnbalancedTxError (Transaction /\ UtxoMap)) mkUnbalancedTxE = PC.mkUnbalancedTxImpl -- | As `mkUnbalancedTxE`, but 'throwing'. -mkUnbalancedTx :: ScriptLookups -> TxConstraints -> Contract Transaction +mkUnbalancedTx + :: ScriptLookups + -> TxConstraints + -> Contract (Transaction /\ UtxoMap) mkUnbalancedTx lookups constraints = mkUnbalancedTxE lookups constraints >>= case _ of Left err -> throwError $ error $ explainMkUnbalancedTxError err diff --git a/src/Internal/Plutip/Server.purs b/src/Internal/Plutip/Server.purs index de2e51477c..7eea80025d 100644 --- a/src/Internal/Plutip/Server.purs +++ b/src/Internal/Plutip/Server.purs @@ -376,8 +376,7 @@ startPlutipContractEnv plutipCfg distr cleanupRef = do -> Aff wallets mkWallets' env ourKey response = do runContractInEnv - -- TODO: uncomment me - env -- { customLogger = Just (\_ _ -> pure unit) } + env { customLogger = Just (\_ _ -> pure unit) } do wallets <- liftContractM diff --git a/src/Internal/ProcessConstraints.purs b/src/Internal/ProcessConstraints.purs index a2cf08b0dd..ad69f9280a 100644 --- a/src/Internal/ProcessConstraints.purs +++ b/src/Internal/ProcessConstraints.purs @@ -31,7 +31,9 @@ import Cardano.Types , TransactionUnspentOutput(TransactionUnspentOutput) , UtxoMap , Value(Value) + , _witnessSet ) +import Cardano.Types as Cardano import Cardano.Types.Address ( Address(BaseAddress, EnterpriseAddress) , getPaymentCredential @@ -150,7 +152,7 @@ import Data.Array (mapMaybe, singleton, (:)) as Array import Data.Bifunctor (lmap) import Data.Either (Either(Left, Right), either, hush, isRight, note) import Data.Foldable (foldM) -import Data.Lens ((%=), (.=), (<>=)) +import Data.Lens ((%=), (.=), (.~), (<>=)) import Data.Lens.Getter (use) import Data.Lens.Iso.Newtype (_Newtype) import Data.List (List(Nil, Cons)) @@ -269,7 +271,7 @@ addFakeScriptDataHash = runExceptT do CannotAttachRedeemer tx' <- ExceptT $ liftEffect $ setScriptDataHash costModels reds dats tx <#> Right - _cpsTransaction .= tx' + _cpsTransaction .= (tx' # _witnessSet <<< Cardano._redeemers .~ reds) -- | Add the remaining balance of the total value that the tx must spend. -- | See note [Balance of value spent] diff --git a/src/Internal/Test/KeyDir.purs b/src/Internal/Test/KeyDir.purs index 8679ce208f..7c523f04ce 100644 --- a/src/Internal/Test/KeyDir.purs +++ b/src/Internal/Test/KeyDir.purs @@ -394,8 +394,9 @@ returnFunds backup env allWalletsArray mbFundTotal hasRun = <> foldMap mustBeSignedBy pkhs lookups = unspentOutputs utxos - unbalancedTx <- liftedE $ mkUnbalancedTxImpl lookups constraints - balancedTx <- balanceTx unbalancedTx Map.empty mempty + unbalancedTx /\ usedUtxos <- liftedE $ mkUnbalancedTxImpl lookups + constraints + balancedTx <- balanceTx unbalancedTx usedUtxos mempty balancedSignedTx <- Array.foldM (\tx wallet -> withKeyWallet wallet $ signTransaction tx) (wrap $ unwrap balancedTx) diff --git a/src/Internal/Test/UtxoDistribution.purs b/src/Internal/Test/UtxoDistribution.purs index 35f1f16a81..339864d80c 100644 --- a/src/Internal/Test/UtxoDistribution.purs +++ b/src/Internal/Test/UtxoDistribution.purs @@ -216,10 +216,10 @@ transferFundsFromEnterpriseToBase ourKey wallets = do constraints :: Constraints.TxConstraints constraints = Constraints.mustBeSignedBy ourPkh <> foldMap constraintsForWallet walletsInfo - unbalancedTx <- mkUnbalancedTx lookups constraints + unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints signedTx <- withKeyWallet ourWallet $ - signTransaction =<< balanceTx unbalancedTx Map.empty mempty + signTransaction =<< balanceTx unbalancedTx usedUtxos mempty signedTx' <- foldM (\tx { wallet } -> withKeyWallet wallet $ signTransaction tx) signedTx diff --git a/test/BalanceTx/Time.purs b/test/BalanceTx/Time.purs index 739d120a7a..4e436ce96c 100644 --- a/test/BalanceTx/Time.purs +++ b/test/BalanceTx/Time.purs @@ -1,7 +1,6 @@ module Test.Ctl.BalanceTx.Time (suite) where import Contract.Prelude -import Data.Lens import Cardano.Types (BigNum, Transaction, _body) import Cardano.Types.BigNum (fromInt, toInt) as BigNum @@ -26,6 +25,7 @@ import Contract.TxConstraints (mustValidateIn) import Contract.UnbalancedTx (mkUnbalancedTxE) import Control.Monad.Except (throwError) import Ctl.Internal.Types.Interval (Interval) +import Data.Lens ((^.)) import Effect.Aff (Aff) import Effect.Exception (error) import JS.BigInt (fromString) as BigInt @@ -83,7 +83,7 @@ mkTestFromSingleInterval interval = do mutx <- mkUnbalancedTxE emptyLookup constraint case mutx of Left e -> fail $ show e - Right utx -> + Right (utx /\ _) -> do returnedInterval <- getTimeFromUnbalanced utx returnedInterval `shouldEqual` interval @@ -118,7 +118,7 @@ mkTestMultipleInterval intervals expected = do mutx <- mkUnbalancedTxE emptyLookup constraint case mutx of Left e -> fail $ show e - Right utx -> + Right (utx /\ _) -> do returnedInterval <- getTimeFromUnbalanced utx returnedInterval `shouldEqual` expected diff --git a/test/Plutip.purs b/test/Plutip.purs index 648bea2e43..2a582b2249 100644 --- a/test/Plutip.purs +++ b/test/Plutip.purs @@ -20,7 +20,6 @@ import Ctl.Internal.Plutip.Server , stopPlutipCluster ) import Ctl.Internal.Plutip.Types (StopClusterResponse(StopClusterSuccess)) -import Data.Log.Level (LogLevel(..)) import Data.Maybe (Maybe(Just)) import Data.Posix.Signal (Signal(SIGINT)) import Effect (Effect) @@ -37,7 +36,7 @@ import Mote.Monad (mapTest) import Mote.TestPlanM (TestPlanM) import Mote.TestPlanM as Utils import Test.Ctl.BalanceTx.ChangeGeneration as ChangeGeneration -import Test.Ctl.Plutip.Common (config) as Config +import Test.Ctl.Plutip.Common (config) import Test.Ctl.Plutip.Contract as Contract import Test.Ctl.Plutip.Contract.Assert as Assert import Test.Ctl.Plutip.Contract.ClusterParameters as ClusterParameters @@ -51,8 +50,6 @@ import Test.Ctl.QueryM.AffInterface as QueryM.AffInterface import Test.Spec.Assertions (shouldSatisfy) import Test.Spec.Runner (defaultConfig) -config = Config.config { suppressLogs = false, logLevel = Trace } - -- Run with `npm run plutip-test` main :: Effect Unit main = interruptOnSignal SIGINT =<< launchAff do diff --git a/test/Plutip/Common.purs b/test/Plutip/Common.purs index 0dc461e792..3cd0304fb4 100644 --- a/test/Plutip/Common.purs +++ b/test/Plutip/Common.purs @@ -15,7 +15,7 @@ import Data.Newtype (wrap) import Partial.Unsafe (unsafePartial) config :: PlutipConfig -config = defaultPlutipConfig { suppressLogs = false } +config = defaultPlutipConfig privateStakeKey :: PrivateStakeKey privateStakeKey = wrap $ unsafePartial $ fromJust diff --git a/test/Plutip/Contract.purs b/test/Plutip/Contract.purs index 1123e06313..ecbe18e71b 100644 --- a/test/Plutip/Contract.purs +++ b/test/Plutip/Contract.purs @@ -12,12 +12,10 @@ import Cardano.Transaction.Builder ) import Cardano.Types ( Address - , Credential(..) , GeneralTransactionMetadata(GeneralTransactionMetadata) - , StakeCredential(..) + , StakeCredential(StakeCredential) , TransactionUnspentOutput(TransactionUnspentOutput) ) -import Cardano.Types.Address (mkPaymentAddress) import Cardano.Types.AssetName as AssetName import Cardano.Types.Coin as Coin import Cardano.Types.Credential @@ -31,7 +29,6 @@ import Cardano.Types.Value (lovelaceValueOf) import Contract.Address ( PaymentPubKeyHash(PaymentPubKeyHash) , StakePubKeyHash - , getNetworkId , mkAddress ) import Contract.AuxiliaryData (setGeneralTxMetadata) @@ -95,8 +92,6 @@ import Contract.Transaction , _output , awaitTxConfirmed , balanceTx - , balanceTx - , balanceTxE , balanceTxE , buildTx , createAdditionalUtxos @@ -246,7 +241,7 @@ suite = do lookups :: Lookups.ScriptLookups lookups = mempty - ubTx <- mkUnbalancedTx lookups constraints + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints res <- ( balanceTxE ubTx Map.empty (mustNotSpendUtxosWithOutRefs $ Map.keys utxos) @@ -278,7 +273,7 @@ suite = do withWallets distribution \_ → pure unit - only $ group "Contract interface" do + group "Contract interface" do test "mustUseCollateralUtxos should not fail if enough UTxOs are provided" do @@ -321,8 +316,8 @@ suite = do constraints = Constraints.mustSpendScriptOutput txInput unitRedeemer - ubTx <- mkUnbalancedTx lookups constraints - res <- balanceTxE ubTx Map.empty + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + res <- balanceTxE ubTx usedUtxos (mustUseCollateralUtxos bobsCollateral) res `shouldSatisfy` isRight @@ -366,7 +361,7 @@ suite = do constraints = Constraints.mustSpendScriptOutput txInput unitRedeemer - ubTx <- mkUnbalancedTx lookups constraints + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints res <- balanceTxE ubTx Map.empty (mustUseCollateralUtxos Map.empty) res `shouldSatisfy` case _ of Left (InsufficientCollateralUtxos mp) -> Map.isEmpty mp @@ -397,7 +392,7 @@ suite = do withKeyWallet bob do pure unit -- sign, balance, submit, etc. - only $ test + test "Payment keyhash to payment keyhash transaction (Pkh2Pkh example)" do let @@ -558,8 +553,8 @@ suite = do lookups :: Lookups.ScriptLookups lookups = mempty - ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx Map.empty mempty + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + bsTx <- signTransaction =<< balanceTx ubTx usedUtxos mempty txId <- submit bsTx awaitTxConfirmed txId pure txId @@ -592,8 +587,8 @@ suite = do lookups :: Lookups.ScriptLookups lookups = Lookups.unspentOutputs utxos - ubTx <- mkUnbalancedTx lookups constraints - tx <- signTransaction =<< balanceTx ubTx Map.empty mempty + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + tx <- signTransaction =<< balanceTx ubTx usedUtxos mempty let signWithWallet txToSign wallet = withKeyWallet wallet (signTransaction txToSign) @@ -651,8 +646,8 @@ suite = do lookups :: Lookups.ScriptLookups lookups = mempty - ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx Map.empty mempty + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + bsTx <- signTransaction =<< balanceTx ubTx usedUtxos mempty txId <- submit bsTx awaitTxConfirmed txId pure txId @@ -675,9 +670,9 @@ suite = do lookups :: Lookups.ScriptLookups lookups = Lookups.unspentOutputs utxos - ubTx <- mkUnbalancedTx lookups constraints + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints -- Bob signs the tx - tx <- signTransaction =<< balanceTx ubTx Map.empty mempty + tx <- signTransaction =<< balanceTx ubTx usedUtxos mempty let signWithWallet txToSign wallet = withKeyWallet wallet (signTransaction txToSign) @@ -709,8 +704,8 @@ suite = do lookups :: Lookups.ScriptLookups lookups = Lookups.plutusMintingPolicy mp - ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx Map.empty mempty + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + bsTx <- signTransaction =<< balanceTx ubTx usedUtxos mempty submitAndLog bsTx test "mustProduceAtLeast spends native token" do @@ -794,7 +789,7 @@ suite = do $ BigNum.fromInt 101 lookups' = lookups <> Lookups.ownPaymentPubKeyHash pkh - ubTx <- mkUnbalancedTx lookups' constraints' + ubTx /\ usedUtxos <- mkUnbalancedTx lookups' constraints' result <- balanceTxE ubTx Map.empty mempty result `shouldSatisfy` isLeft @@ -879,8 +874,8 @@ suite = do $ BigNum.fromInt 101 lookups' = lookups <> Lookups.ownPaymentPubKeyHash pkh - ubTx <- mkUnbalancedTx lookups' constraints' - result <- balanceTxE ubTx Map.empty mempty + ubTx /\ usedUtxos <- mkUnbalancedTx lookups' constraints' + result <- balanceTxE ubTx usedUtxos mempty result `shouldSatisfy` isLeft test "Minting using NativeScript (multisig) as a policy" do @@ -1035,7 +1030,7 @@ suite = do givenMetadata = GeneralTransactionMetadata $ Map.fromFoldable [ BigNum.fromInt 8 /\ Metadatum.Text "foo" ] - ubTx <- mkUnbalancedTx lookups constraints + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints let ubTx' = setGeneralTxMetadata ubTx givenMetadata bsTx <- signTransaction =<< balanceTx ubTx' Map.empty mempty txId <- submit bsTx @@ -1118,8 +1113,8 @@ suite = do <> Lookups.plutusMintingPolicy mp2 <> Lookups.plutusMintingPolicy mp3 - ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx Map.empty mempty + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + bsTx <- signTransaction =<< balanceTx ubTx usedUtxos mempty submitAndLog bsTx test "Multi-signature transaction" do @@ -1309,8 +1304,8 @@ suite = do balanceTxConstraints = BalanceTxConstraints.mustUseAdditionalUtxos additionalUtxos - unbalancedTx <- mkUnbalancedTx lookups constraints - balanceTxE unbalancedTx Map.empty balanceTxConstraints + unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTxE unbalancedTx usedUtxos balanceTxConstraints let hasInsufficientBalance @@ -1533,8 +1528,8 @@ suite = do lookups :: Lookups.ScriptLookups lookups = Lookups.plutusMintingPolicy mp - ubTx <- mkUnbalancedTx lookups constraints - bsTx <- signTransaction =<< balanceTx ubTx Map.empty mempty + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + bsTx <- signTransaction =<< balanceTx ubTx usedUtxos mempty submit bsTx >>= awaitTxConfirmed logInfo' "Attempt to lock value" @@ -1725,9 +1720,9 @@ suite = do lookups0 :: Lookups.ScriptLookups lookups0 = mempty - unbalancedTx0 <- mkUnbalancedTx lookups0 constraints0 + unbalancedTx0 /\ usedUtxos <- mkUnbalancedTx lookups0 constraints0 - withBalancedTx unbalancedTx0 Map.empty mempty \balancedTx0 -> do + withBalancedTx unbalancedTx0 usedUtxos mempty \balancedTx0 -> do balancedSignedTx0 <- signTransaction balancedTx0 additionalUtxos <- createAdditionalUtxos balancedSignedTx0 @@ -1749,8 +1744,8 @@ suite = do balanceTxConstraints = BalanceTxConstraints.mustUseAdditionalUtxos additionalUtxos - unbalancedTx1 <- mkUnbalancedTx lookups1 constraints1 - balancedTx1 <- balanceTx unbalancedTx1 Map.empty + unbalancedTx1 /\ usedUtxos <- mkUnbalancedTx lookups1 constraints1 + balancedTx1 <- balanceTx unbalancedTx1 usedUtxos balanceTxConstraints balancedSignedTx1 <- signTransaction balancedTx1 @@ -1839,9 +1834,9 @@ suite = do lookups0 :: Lookups.ScriptLookups lookups0 = Lookups.plutusMintingPolicy mp <> datumLookup - unbalancedTx0 <- mkUnbalancedTx lookups0 constraints0 + unbalancedTx0 /\ usedUtxos <- mkUnbalancedTx lookups0 constraints0 - withBalancedTx unbalancedTx0 Map.empty mempty \balancedTx0 -> do + withBalancedTx unbalancedTx0 usedUtxos mempty \balancedTx0 -> do balancedSignedTx0 <- signTransaction balancedTx0 additionalUtxos <- createAdditionalUtxos balancedSignedTx0 @@ -1864,8 +1859,9 @@ suite = do balanceTxConstraints = BalanceTxConstraints.mustUseAdditionalUtxos additionalUtxos - unbalancedTx1 <- mkUnbalancedTx lookups1 constraints1 - balancedTx1 <- balanceTx unbalancedTx1 Map.empty + unbalancedTx1 /\ usedUtxos1 <- mkUnbalancedTx lookups1 + constraints1 + balancedTx1 <- balanceTx unbalancedTx1 usedUtxos1 balanceTxConstraints balancedSignedTx1 <- signTransaction balancedTx1 @@ -2087,16 +2083,16 @@ signMultipleContract = do lookups :: Lookups.ScriptLookups lookups = mempty - ubTx1 <- mkUnbalancedTx lookups constraints - ubTx2 <- mkUnbalancedTx lookups constraints + ubTx1 /\ usedUtxos1 <- mkUnbalancedTx lookups constraints + ubTx2 /\ usedUtxos2 <- mkUnbalancedTx lookups constraints withBalancedTxs [ { transaction: ubTx1 - , extraUtxos: Map.empty + , extraUtxos: usedUtxos1 , balancerConstraints: mempty } , { transaction: ubTx2 - , extraUtxos: Map.empty + , extraUtxos: usedUtxos2 , balancerConstraints: mempty } ] $ \txs -> do diff --git a/test/Plutip/Staking.purs b/test/Plutip/Staking.purs index a7b6f0bafd..0161a2f0a0 100644 --- a/test/Plutip/Staking.purs +++ b/test/Plutip/Staking.purs @@ -154,8 +154,8 @@ suite = do Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog -- Deregister stake key do @@ -167,8 +167,8 @@ suite = do Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog test "PlutusScript" do let @@ -203,8 +203,8 @@ suite = do Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog -- Deregister stake key do @@ -220,8 +220,8 @@ suite = do Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog test "NativeScript" do let @@ -251,8 +251,8 @@ suite = do Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog -- Deregister stake key do @@ -264,8 +264,8 @@ suite = do Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog test "Pool registration & retirement" do let @@ -289,8 +289,8 @@ suite = do Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog privateStakeKey <- liftM (error "Failed to get private stake key") $ keyWalletPrivateStakeKey alice @@ -338,8 +338,8 @@ suite = do Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog -- List pools: the pool must appear in the list do @@ -365,8 +365,8 @@ suite = do Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog let waitEpoch :: Epoch -> Contract Epoch @@ -416,8 +416,8 @@ suite = do lookups :: Lookups.ScriptLookups lookups = mempty - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog -- Register stake script @@ -429,8 +429,8 @@ suite = do lookups :: Lookups.ScriptLookups lookups = mempty - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog -- Select a pool @@ -446,8 +446,8 @@ suite = do lookups = Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog -- Wait until rewards @@ -478,8 +478,8 @@ suite = do lookups = Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog -- Check rewards. @@ -532,8 +532,8 @@ suite = do lookups :: Lookups.ScriptLookups lookups = mempty - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog -- Alice registers stake script (again, no need to validate it) @@ -545,8 +545,8 @@ suite = do lookups :: Lookups.ScriptLookups lookups = mempty - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog -- Bob performs operations with the stake script that require his @@ -566,8 +566,8 @@ suite = do lookups = Lookups.ownPaymentPubKeyHash bobPkh <> Lookups.ownStakePubKeyHash bobStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog -- Wait until rewards @@ -598,8 +598,8 @@ suite = do lookups = Lookups.ownPaymentPubKeyHash bobPkh <> Lookups.ownStakePubKeyHash bobStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog -- Check rewards. @@ -635,8 +635,8 @@ suite = do lookups = Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog -- Select a pool ID poolId <- selectPoolId @@ -651,8 +651,8 @@ suite = do lookups = Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog -- Wait until rewards let @@ -685,8 +685,8 @@ suite = do lookups = Lookups.ownPaymentPubKeyHash alicePkh <> Lookups.ownStakePubKeyHash aliceStakePkh - ubTx <- mkUnbalancedTx lookups constraints - balanceTx ubTx Map.empty mempty >>= signTransaction >>= submitAndLog + ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog -- Check rewards. -- Not going to deregister here, because the rewards are added too diff --git a/test/Utils/DrainWallets.purs b/test/Utils/DrainWallets.purs index cd636c29b8..2ec20f9556 100644 --- a/test/Utils/DrainWallets.purs +++ b/test/Utils/DrainWallets.purs @@ -40,6 +40,7 @@ import Data.Maybe (Maybe(Nothing)) import Data.Newtype (unwrap, wrap) import Data.String (joinWith) import Data.Traversable (for) +import Data.Tuple.Nested ((/\)) import Data.UInt as UInt import Effect (Effect) import Effect.Aff (Aff, launchAff_) @@ -120,9 +121,9 @@ run privateKey walletsDir = runContract config do <> foldMap (_.pkh >>> mustBeSignedBy) usedWallets lookups = unspentOutputs utxos - unbalancedTx <- mkUnbalancedTx lookups constraints + unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTx unbalancedTx Map.empty mempty + balancedTx <- balanceTx unbalancedTx usedUtxos mempty balancedSignedTx <- Array.foldM (\tx wallet -> withKeyWallet wallet $ signTransaction tx) (wrap $ unwrap balancedTx) From b64d0ddbc825ae449dab612222b4c2b574eee105 Mon Sep 17 00:00:00 2001 From: Marcus Fernandes Date: Mon, 1 Jul 2024 12:22:46 -0300 Subject: [PATCH 23/52] Pin `purescript-uplc-apply-args` to v1.0.0 --- packages.dhall | 2 +- spago-packages.nix | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages.dhall b/packages.dhall index 7506c80e49..081878fc47 100644 --- a/packages.dhall +++ b/packages.dhall @@ -341,7 +341,7 @@ let additions = , "tuples" ] , repo = "https://github.com/mlabs-haskell/purescript-uplc-apply-args" - , version = "master" + , version = "v1.0.0" } , cardano-types = { dependencies = diff --git a/spago-packages.nix b/spago-packages.nix index ac4291c950..504b0f7fe4 100644 --- a/spago-packages.nix +++ b/spago-packages.nix @@ -1567,7 +1567,7 @@ let "uplc-apply-args" = pkgs.stdenv.mkDerivation { name = "uplc-apply-args"; - version = "master"; + version = "v1.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-uplc-apply-args.git"; rev = "aa528d5310cbfbd01b4d94557f404d95cfb6bb3c"; From 4870dac0713220e30e298286666668e34ed20b31 Mon Sep 17 00:00:00 2001 From: Marcus Fernandes Date: Mon, 1 Jul 2024 12:25:13 -0300 Subject: [PATCH 24/52] Fix `purescript-uplc-apply-args` dependency --- Makefile | 7 +++- flake.nix | 7 ++-- templates/ctl-scaffold/package-lock.json | 39 +++++++++++++++++++++++ templates/ctl-scaffold/package.json | 1 + templates/ctl-scaffold/packages.dhall | 25 +++++++++++++++ templates/ctl-scaffold/spago-packages.nix | 13 ++++++++ 6 files changed, 86 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index c84457f7ec..af4026a518 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ SHELL := bash .ONESHELL: -.PHONY: esbuild-bundle esbuild-serve webpack-bundle webpack-serve check-format format query-testnet-tip clean check-explicit-exports spago-build create-bundle-entrypoint create-html-entrypoint delete-bundle-entrypoint +.PHONY: esbuild-bundle esbuild-serve webpack-bundle webpack-serve check-format format query-testnet-tip clean check-explicit-exports spago-build create-bundle-entrypoint create-html-entrypoint delete-bundle-entrypoint run-template-checks .SHELLFLAGS := -eu -o pipefail -c ps-sources := $(shell fd --no-ignore-parent -epurs) @@ -108,6 +108,11 @@ run-ci-actions: nix build -L .#checks.x86_64-linux.ctl-staking-test nix build -L .#checks.x86_64-linux.examples-imports-check +run-template-checks: + nix build -L .#checks.x86_64-linux.template-deps-json + nix build -L .#checks.x86_64-linux.template-dhall-diff + nix build -L .#checks.x86_64-linux.template-version + clean: @ rm -r .psc-ide-port || true @ rm -rf .psci_modules || true diff --git a/flake.nix b/flake.nix index 2bae547d0a..c593fefad3 100644 --- a/flake.nix +++ b/flake.nix @@ -391,9 +391,8 @@ nativeBuildInputs = [ pkgs.jq ]; } '' cd ${self} - # We don't want to include `uplc-apply-args` in the template dependencies. diff \ - <(jq -S '.dependencies | del(."@mlabs-haskell/uplc-apply-args")' <<< $ctlPackageJson) \ + <(jq -S .dependencies <<< $ctlPackageJson) \ <(jq -S .dependencies <<< $ctlScaffoldPackageJson) # We don't want to include `doctoc` in the template dev dependencies. diff \ @@ -406,9 +405,7 @@ let ctlPkgsExp = import ./spago-packages.nix { inherit pkgs; }; ctlScaffoldPkgsExp = import ./templates/ctl-scaffold/spago-packages.nix { inherit pkgs; }; - # We don't include `uplc-apply-args` in the template dependencies. - ctlPs = filter (p: p.name != "uplc-apply-args") - (attrValues ctlPkgsExp.inputs); + ctlPs = (attrValues ctlPkgsExp.inputs); ctlScaffoldPs = filter (p: p.name != "cardano-transaction-lib") (attrValues ctlScaffoldPkgsExp.inputs); intersection = pkgs.lib.lists.intersectLists ctlPs ctlScaffoldPs; diff --git a/templates/ctl-scaffold/package-lock.json b/templates/ctl-scaffold/package-lock.json index bc61dd3b53..561dc93e3a 100644 --- a/templates/ctl-scaffold/package-lock.json +++ b/templates/ctl-scaffold/package-lock.json @@ -12,6 +12,7 @@ "@mlabs-haskell/cardano-message-signing": "^1.0.1", "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", "@mlabs-haskell/json-bigint": "2.0.0", + "@mlabs-haskell/uplc-apply-args": "2.0.1", "@noble/secp256k1": "^1.7.0", "base64-js": "^1.5.1", "bignumber.js": "^9.1.1", @@ -517,6 +518,25 @@ "resolved": "https://registry.npmjs.org/@mlabs-haskell/json-bigint/-/json-bigint-2.0.0.tgz", "integrity": "sha512-JX9TON+nZbt+1TJ5MNV1Gcpxp3/m56x1/glDwzGtydrzQzyZbKg4XFw9Frib6fh89YVqjSFJ9xmVeIyDJ5DxTQ==" }, + "node_modules/@mlabs-haskell/uplc-apply-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-2.0.1.tgz", + "integrity": "sha512-of0zlgBEk9vpTBFISDHADoYRzfbw84MQBMnGCXFhdSvdOIWsoGV4kvQJBdufYYh8BJNSyy0MLJ9uX7ARr7reig==", + "dependencies": { + "@mlabs-haskell/uplc-apply-args-browser": "^0.0.3", + "@mlabs-haskell/uplc-apply-args-nodejs": "^0.0.3" + } + }, + "node_modules/@mlabs-haskell/uplc-apply-args-browser": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-browser/-/uplc-apply-args-browser-0.0.3.tgz", + "integrity": "sha512-U2GFMN2Q2KLwTKjrwDXcOBznIvib3Jvdg79xmXDx3/L94PGoBfLN9bBByfVTwKP+ETRfJgRXwi5xxctwKXvT+g==" + }, + "node_modules/@mlabs-haskell/uplc-apply-args-nodejs": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-nodejs/-/uplc-apply-args-nodejs-0.0.3.tgz", + "integrity": "sha512-0uLz+67U1yiXvt3qu/7NBd0WK6LWXf9XteaInQk56RqRbxi4WKA/1Rm73VuciZzLWohXMDNbVNCiirmXi6k+9A==" + }, "node_modules/@noble/hashes": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", @@ -5751,6 +5771,25 @@ "resolved": "https://registry.npmjs.org/@mlabs-haskell/json-bigint/-/json-bigint-2.0.0.tgz", "integrity": "sha512-JX9TON+nZbt+1TJ5MNV1Gcpxp3/m56x1/glDwzGtydrzQzyZbKg4XFw9Frib6fh89YVqjSFJ9xmVeIyDJ5DxTQ==" }, + "@mlabs-haskell/uplc-apply-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args/-/uplc-apply-args-2.0.1.tgz", + "integrity": "sha512-of0zlgBEk9vpTBFISDHADoYRzfbw84MQBMnGCXFhdSvdOIWsoGV4kvQJBdufYYh8BJNSyy0MLJ9uX7ARr7reig==", + "requires": { + "@mlabs-haskell/uplc-apply-args-browser": "^0.0.3", + "@mlabs-haskell/uplc-apply-args-nodejs": "^0.0.3" + } + }, + "@mlabs-haskell/uplc-apply-args-browser": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-browser/-/uplc-apply-args-browser-0.0.3.tgz", + "integrity": "sha512-U2GFMN2Q2KLwTKjrwDXcOBznIvib3Jvdg79xmXDx3/L94PGoBfLN9bBByfVTwKP+ETRfJgRXwi5xxctwKXvT+g==" + }, + "@mlabs-haskell/uplc-apply-args-nodejs": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/uplc-apply-args-nodejs/-/uplc-apply-args-nodejs-0.0.3.tgz", + "integrity": "sha512-0uLz+67U1yiXvt3qu/7NBd0WK6LWXf9XteaInQk56RqRbxi4WKA/1Rm73VuciZzLWohXMDNbVNCiirmXi6k+9A==" + }, "@noble/hashes": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", diff --git a/templates/ctl-scaffold/package.json b/templates/ctl-scaffold/package.json index fccdce6b9f..f34f4d9e34 100644 --- a/templates/ctl-scaffold/package.json +++ b/templates/ctl-scaffold/package.json @@ -28,6 +28,7 @@ "@mlabs-haskell/cardano-message-signing": "^1.0.1", "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", "@mlabs-haskell/json-bigint": "2.0.0", + "@mlabs-haskell/uplc-apply-args": "2.0.1", "@noble/secp256k1": "^1.7.0", "base64-js": "^1.5.1", "bignumber.js": "^9.1.1", diff --git a/templates/ctl-scaffold/packages.dhall b/templates/ctl-scaffold/packages.dhall index 8513539b15..8be52f038c 100644 --- a/templates/ctl-scaffold/packages.dhall +++ b/templates/ctl-scaffold/packages.dhall @@ -318,6 +318,31 @@ let additions = , repo = "https://github.com/mlabs-haskell/purescript-plutus-types" , version = "v1.0.1" } + , uplc-apply-args = + { dependencies = + [ "aff" + , "bytearrays" + , "cardano-serialization-lib" + , "cardano-types" + , "effect" + , "either" + , "foldable-traversable" + , "foreign-object" + , "js-bigints" + , "lists" + , "maybe" + , "mote" + , "mote-testplan" + , "partial" + , "prelude" + , "profunctor" + , "spec" + , "transformers" + , "tuples" + ] + , repo = "https://github.com/mlabs-haskell/purescript-uplc-apply-args" + , version = "v1.0.0" + } , cardano-types = { dependencies = [ "aeson" diff --git a/templates/ctl-scaffold/spago-packages.nix b/templates/ctl-scaffold/spago-packages.nix index 4797c481b4..f8db4dae6d 100644 --- a/templates/ctl-scaffold/spago-packages.nix +++ b/templates/ctl-scaffold/spago-packages.nix @@ -1577,6 +1577,19 @@ let installPhase = "ln -s $src $out"; }; + "uplc-apply-args" = pkgs.stdenv.mkDerivation { + name = "uplc-apply-args"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-uplc-apply-args.git"; + rev = "aa528d5310cbfbd01b4d94557f404d95cfb6bb3c"; + sha256 = "1r064ca2m16hkbcswrvlng032ax1ygbpr2gxrlaqmjlf2gnin280"; + + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "variant" = pkgs.stdenv.mkDerivation { name = "variant"; version = "v8.0.0"; From 0a875da494fafa342dd4c637a66d78e83d910b3b Mon Sep 17 00:00:00 2001 From: Marcus Fernandes Date: Mon, 1 Jul 2024 12:25:38 -0300 Subject: [PATCH 25/52] Re-add tests related to `ApplyArgs` --- examples/ByUrl.purs | 2 + test/ApplyArgs.purs | 377 ++++++++++++++++++++++++++++++++++++++++++++ test/Unit.purs | 2 + test/e2e-ci.env | 1 + test/e2e.env | 2 + 5 files changed, 384 insertions(+) create mode 100644 test/ApplyArgs.purs diff --git a/examples/ByUrl.purs b/examples/ByUrl.purs index f13fcd5e52..3119dff8d5 100644 --- a/examples/ByUrl.purs +++ b/examples/ByUrl.purs @@ -67,6 +67,7 @@ import Data.Time.Duration (Seconds(Seconds)) import Data.Tuple.Nested (type (/\), (/\)) import Effect (Effect) import Effect.Console as Console +import Test.Ctl.ApplyArgs as ApplyArgs import Web.HTML (window) import Web.HTML.Window (localStorage) import Web.Storage.Storage (getItem) @@ -216,6 +217,7 @@ examples = addSuccessLog <$> Map.fromFoldable , "ReferenceInputs" /\ ReferenceInputsV2.contract , "ReferenceInputsAndScripts" /\ ReferenceInputsAndScriptsV2.contract , "Utxos" /\ Utxos.contract + , "ApplyArgs" /\ ApplyArgs.contract , "Schnorr" /\ Schnorr.contract , "ECDSA" /\ ECDSA.contract , "PaysWithDatum" /\ PaysWithDatum.contract diff --git a/test/ApplyArgs.purs b/test/ApplyArgs.purs new file mode 100644 index 0000000000..a1c24d4683 --- /dev/null +++ b/test/ApplyArgs.purs @@ -0,0 +1,377 @@ +module Test.Ctl.ApplyArgs (main, suite, contract) where + +import Contract.Prelude + +import Cardano.Plutus.ApplyArgs (applyArgs) +import Contract.Monad (Contract, launchAff_) +import Contract.Numeric.BigNum as BigNum +import Contract.PlutusData (PlutusData(List, Map, Bytes, Constr), toData) +import Contract.Prim.ByteArray (hexToByteArrayUnsafe) +import Contract.Scripts (PlutusScript) +import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) +import Control.Monad.Error.Class (class MonadError) +import Ctl.Internal.Cardano.TextEnvelope (TextEnvelope) +import Data.List.Lazy (replicate) +import Data.Profunctor.Choice (left) +import Effect.Aff (Error, error, throwError) +import Foreign.Object (Object) +import Foreign.Object as Object +import JS.BigInt (fromInt) +import Mote (group, test) +import Mote.TestPlanM (TestPlanM, interpret) +import Test.Spec.Assertions (shouldEqual) + +scriptSources :: Object String +scriptSources = + Object.fromFoldable + [ "always-fails" /\ + """ +{ + "type": "PlutusScriptV1", + "description": "", + "cborHex": "581e581c01000033223232222350040071235002353003001498498480048005" +} + """ + , "always-fails-big-arg" /\ + """ +{ + "type": "PlutusScriptV1", + "description": "", + "cborHex": "58ff58fd0100003333333332232322223500400712350023530030014984984800480053010107004c0103d87980004c01089fd87980424d5fff004c01465f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dff004c0107a20507424d5f08004c0154d9055f9f079fd87980424d5f5f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dffffff004c0114d87e9f809f01ffa0a201d8798002d87b9f02ffff0001" +} +""" + , "always-fails-no-args" /\ + """ +{ + "type": "PlutusScriptV1", + "description": "", + "cborHex": "581e581c01000033223232222350040071235002353003001498498480048005" +} +""" + , "always-fails-unit" /\ + """ +{ + "type": "PlutusScriptV1", + "description": "", + "cborHex": "5826582401000033322323222235004007123500235300300149849848004800530103d879800001" +} +""" + + , "include-datum" /\ + """ +{ + "type": "PlutusScriptV1", + "description": "include-datum", + "cborHex": "55540100002225333573466e1cdd6801a40a82930b01" +} +""" + , "include-datum-big-arg" /\ + """ +{ + "type": "PlutusScriptV1", + "description": "", + "cborHex": "58f658f401000033333332225333573466e1cdd6801a40a82930b2610107004c0103d87980004c01089fd87980424d5fff004c01465f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dff004c0107a20507424d5f08004c0154d9055f9f079fd87980424d5f5f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dffffff004c0114d87e9f809f01ffa0a201d8798002d87b9f02ffff0001" +} +""" + , "include-datum-no-args" /\ + """ +{ + "type": "PlutusScriptV1", + "description": "", + "cborHex": "55540100002225333573466e1cdd6801a40a82930b01" +} +""" + , "include-datum-unit" /\ + """ +{ + "type": "PlutusScriptV1", + "description": "", + "cborHex": "581d581b01000032225333573466e1cdd6801a40a82930b26103d879800001" +} +""" + + , "one-shot-minting" /\ + """ +{ + "type": "PlutusScriptV1", + "description": "one-shot-minting", + "cborHex": "5908d75908d401000033232332233223232323232323232323232323232323232323222223232323232325335533533355300b120013232123300122333500522002002001002350012200112330012253350021022100101f2325335333573466e3cd400488008d4014880080840804ccd5cd19b873500122001350052200102102010203500122002355001222222222200a101e101f1326353357389201115574786f206e6f7420636f6e73756d65640001b0191533553355335323301d50220013550012222222222007101e22135002222533500415335333573466e3c00cd401c88cccd40048c98d4cd5ce2481024c680002302120012326353357389201024c68000230212326353357389201024c680002302102402315335333573466e3c00802409008c4ccd5cd19b870014800809008c408c408c8840944078407c4c98d4cd5ce24811357726f6e6720616d6f756e74206d696e7465640001b019101b135001220023333573466e1cd55cea8022400046644246600200600464646464646464646464646666ae68cdc39aab9d500a480008cccccccccc888888888848cccccccccc00402c02802402001c01801401000c008cd40648c8c8cccd5cd19b8735573aa0049000119910919800801801180d9aba15002301e357426ae8940088c98d4cd5ce01481501401389aab9e5001137540026ae854028cd4064068d5d0a804999aa80e3ae501b35742a010666aa038eb9406cd5d0a80399a80c8101aba15006335019335502302175a6ae854014c8c8c8cccd5cd19b8735573aa00490001199109198008018011919191999ab9a3370e6aae754009200023322123300100300233502675a6ae854008c09cd5d09aba2500223263533573805a05c05805626aae7940044dd50009aba150023232323333573466e1cd55cea8012400046644246600200600466a04ceb4d5d0a80118139aba135744a004464c6a66ae700b40b80b00ac4d55cf280089baa001357426ae8940088c98d4cd5ce01481501401389aab9e5001137540026ae854010cd4065d71aba15003335019335502375c40026ae854008c060d5d09aba2500223263533573804a04c04804626ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226aae7940044dd50009aba150043232323333573466e1d400520062321222230040053018357426aae79400c8cccd5cd19b875002480108c848888c008014c068d5d09aab9e500423333573466e1d400d20022321222230010053011357426aae7940148cccd5cd19b875004480008c848888c00c014dd71aba135573ca00c464c6a66ae7008008407c07807407006c4d55cea80089baa001357426ae8940108c98d4cd5ce00c80d00c00b98048031bae006135573ca00226ea8004c8004d5406088448894cd40044d400c88004884ccd401488008c010008ccd54c01c480040140100048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931a99ab9c012013011010135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98d4cd5ce00800880780709baa0011232230023758002640026aa02c446666aae7c0049405c8cd4058c010d5d080118019aba200201023232323333573466e1cd55cea801a40004666444246660020080060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008c044d5d0a80119a8060081aba135744a004464c6a66ae7005005404c0484d55cf280089baa00135742a006666aa00eeb94018d5d0a80119a8043ae357426ae8940088c98d4cd5ce00800880780709aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa02844646666aae7c008940588cd4054cd5405cc018d55cea80118029aab9e500230043574400601e26ae84004488c8c8cccd5cd19b875001480008c8488c00800cc014d5d09aab9e500323333573466e1d40092002212200123263533573801c01e01a01801626aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6a66ae7003803c03403002c0284d55cea80089baa0012323333573466e1d40052002200e23333573466e1d40092000200e23263533573801401601201000e26aae74dd5000919191919191999ab9a3370ea002900610911111100191999ab9a3370ea004900510911111100211999ab9a3370ea00690041199109111111198008048041bae35742a00a6eb4d5d09aba2500523333573466e1d40112006233221222222233002009008375c6ae85401cdd71aba135744a00e46666ae68cdc3a802a400846644244444446600c01201060186ae854024dd71aba135744a01246666ae68cdc3a8032400446424444444600e010601a6ae84d55cf280591999ab9a3370ea00e900011909111111180280418071aba135573ca018464c6a66ae7004804c04404003c03803403002c0284d55cea80209aab9e5003135573ca00426aae7940044dd50009191919191999ab9a3370ea002900111999110911998008028020019bad35742a0086eb4d5d0a8019bad357426ae89400c8cccd5cd19b875002480008c8488c00800cc020d5d09aab9e500623263533573801601801401201026aae75400c4d5d1280089aab9e500113754002464646666ae68cdc3a800a400446424460020066eb8d5d09aab9e500323333573466e1d400920002321223002003375c6ae84d55cf280211931a99ab9c008009007006005135573aa00226ea800444888c8c8cccd5cd19b8735573aa0049000119aa80818031aba150023005357426ae8940088c98d4cd5ce00400480380309aab9e5001137540029324903505431001200132001355007222533500110022213500222330073330080020060010033200135500622225335001100222135002225335333573466e1c005200000a0091333008007006003133300800733500b1233300100800300200600312200212200111220021221223300100400311221233001003002112323001001223300330020020014c1074643544c4e46540001" +} +""" + , "one-shot-minting-big-arg" /\ + """ +{ + "type": "PlutusScriptV1", + "description": "", + "cborHex": "5909b75909b4010000333333333232332233223232323232323232323232323232323232323222223232323232325335533533355300b120013232123300122333500522002002001002350012200112330012253350021022100101f2325335333573466e3cd400488008d4014880080840804ccd5cd19b873500122001350052200102102010203500122002355001222222222200a101e101f132635335738921115574786f206e6f7420636f6e73756d65640001b0191533553355335323301d50220013550012222222222007101e22135002222533500415335333573466e3c00cd401c88cccd40048c98d4cd5ce2481024c680002302120012326353357389201024c68000230212326353357389201024c680002302102402315335333573466e3c00802409008c4ccd5cd19b870014800809008c408c408c8840944078407c4c98d4cd5ce24811357726f6e6720616d6f756e74206d696e7465640001b019101b135001220023333573466e1cd55cea8022400046644246600200600464646464646464646464646666ae68cdc39aab9d500a480008cccccccccc888888888848cccccccccc00402c02802402001c01801401000c008cd40648c8c8cccd5cd19b8735573aa0049000119910919800801801180d9aba15002301e357426ae8940088c98d4cd5ce01481501401389aab9e5001137540026ae854028cd4064068d5d0a804999aa80e3ae501b35742a010666aa038eb9406cd5d0a80399a80c8101aba15006335019335502302175a6ae854014c8c8c8cccd5cd19b8735573aa00490001199109198008018011919191999ab9a3370e6aae754009200023322123300100300233502675a6ae854008c09cd5d09aba2500223263533573805a05c05805626aae7940044dd50009aba150023232323333573466e1cd55cea8012400046644246600200600466a04ceb4d5d0a80118139aba135744a004464c6a66ae700b40b80b00ac4d55cf280089baa001357426ae8940088c98d4cd5ce01481501401389aab9e5001137540026ae854010cd4065d71aba15003335019335502375c40026ae854008c060d5d09aba2500223263533573804a04c04804626ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226aae7940044dd50009aba150043232323333573466e1d400520062321222230040053018357426aae79400c8cccd5cd19b875002480108c848888c008014c068d5d09aab9e500423333573466e1d400d20022321222230010053011357426aae7940148cccd5cd19b875004480008c848888c00c014dd71aba135573ca00c464c6a66ae7008008407c07807407006c4d55cea80089baa001357426ae8940108c98d4cd5ce00c80d00c00b98048031bae006135573ca00226ea8004c8004d5406088448894cd40044d400c88004884ccd401488008c010008ccd54c01c480040140100048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931a99ab9c012013011010135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98d4cd5ce00800880780709baa0011232230023758002640026aa02c446666aae7c0049405c8cd4058c010d5d080118019aba200201023232323333573466e1cd55cea801a40004666444246660020080060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008c044d5d0a80119a8060081aba135744a004464c6a66ae7005005404c0484d55cf280089baa00135742a006666aa00eeb94018d5d0a80119a8043ae357426ae8940088c98d4cd5ce00800880780709aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa02844646666aae7c008940588cd4054cd5405cc018d55cea80118029aab9e500230043574400601e26ae84004488c8c8cccd5cd19b875001480008c8488c00800cc014d5d09aab9e500323333573466e1d40092002212200123263533573801c01e01a01801626aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6a66ae7003803c03403002c0284d55cea80089baa0012323333573466e1d40052002200e23333573466e1d40092000200e23263533573801401601201000e26aae74dd5000919191919191999ab9a3370ea002900610911111100191999ab9a3370ea004900510911111100211999ab9a3370ea00690041199109111111198008048041bae35742a00a6eb4d5d09aba2500523333573466e1d40112006233221222222233002009008375c6ae85401cdd71aba135744a00e46666ae68cdc3a802a400846644244444446600c01201060186ae854024dd71aba135744a01246666ae68cdc3a8032400446424444444600e010601a6ae84d55cf280591999ab9a3370ea00e900011909111111180280418071aba135573ca018464c6a66ae7004804c04404003c03803403002c0284d55cea80209aab9e5003135573ca00426aae7940044dd50009191919191999ab9a3370ea002900111999110911998008028020019bad35742a0086eb4d5d0a8019bad357426ae89400c8cccd5cd19b875002480008c8488c00800cc020d5d09aab9e500623263533573801601801401201026aae75400c4d5d1280089aab9e500113754002464646666ae68cdc3a800a400446424460020066eb8d5d09aab9e500323333573466e1d400920002321223002003375c6ae84d55cf280211931a99ab9c008009007006005135573aa00226ea800444888c8c8cccd5cd19b8735573aa0049000119aa80818031aba150023005357426ae8940088c98d4cd5ce00400480380309aab9e5001137540029324903505431001200132001355007222533500110022213500222330073330080020060010033200135500622225335001100222135002225335333573466e1c005200000a0091333008007006003133300800733500b1233300100800300200600312200212200111220021221223300100400311221233001003002112323001001223300330020020014c1074643544c4e4654004c010107004c0103d87980004c01089fd87980424d5fff004c01465f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dff004c0107a20507424d5f08004c0154d9055f9f079fd87980424d5f5f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dffffff004c0114d87e9f809f01ffa0a201d8798002d87b9f02ffff0001" +} +""" + , "one-shot-minting-no-args" /\ + """ +{ + "type": "PlutusScriptV1", + "description": "", + "cborHex": "5908d75908d401000033232332233223232323232323232323232323232323232323222223232323232325335533533355300b120013232123300122333500522002002001002350012200112330012253350021022100101f2325335333573466e3cd400488008d4014880080840804ccd5cd19b873500122001350052200102102010203500122002355001222222222200a101e101f1326353357389201115574786f206e6f7420636f6e73756d65640001b0191533553355335323301d50220013550012222222222007101e22135002222533500415335333573466e3c00cd401c88cccd40048c98d4cd5ce2481024c680002302120012326353357389201024c68000230212326353357389201024c680002302102402315335333573466e3c00802409008c4ccd5cd19b870014800809008c408c408c8840944078407c4c98d4cd5ce24811357726f6e6720616d6f756e74206d696e7465640001b019101b135001220023333573466e1cd55cea8022400046644246600200600464646464646464646464646666ae68cdc39aab9d500a480008cccccccccc888888888848cccccccccc00402c02802402001c01801401000c008cd40648c8c8cccd5cd19b8735573aa0049000119910919800801801180d9aba15002301e357426ae8940088c98d4cd5ce01481501401389aab9e5001137540026ae854028cd4064068d5d0a804999aa80e3ae501b35742a010666aa038eb9406cd5d0a80399a80c8101aba15006335019335502302175a6ae854014c8c8c8cccd5cd19b8735573aa00490001199109198008018011919191999ab9a3370e6aae754009200023322123300100300233502675a6ae854008c09cd5d09aba2500223263533573805a05c05805626aae7940044dd50009aba150023232323333573466e1cd55cea8012400046644246600200600466a04ceb4d5d0a80118139aba135744a004464c6a66ae700b40b80b00ac4d55cf280089baa001357426ae8940088c98d4cd5ce01481501401389aab9e5001137540026ae854010cd4065d71aba15003335019335502375c40026ae854008c060d5d09aba2500223263533573804a04c04804626ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226aae7940044dd50009aba150043232323333573466e1d400520062321222230040053018357426aae79400c8cccd5cd19b875002480108c848888c008014c068d5d09aab9e500423333573466e1d400d20022321222230010053011357426aae7940148cccd5cd19b875004480008c848888c00c014dd71aba135573ca00c464c6a66ae7008008407c07807407006c4d55cea80089baa001357426ae8940108c98d4cd5ce00c80d00c00b98048031bae006135573ca00226ea8004c8004d5406088448894cd40044d400c88004884ccd401488008c010008ccd54c01c480040140100048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931a99ab9c012013011010135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98d4cd5ce00800880780709baa0011232230023758002640026aa02c446666aae7c0049405c8cd4058c010d5d080118019aba200201023232323333573466e1cd55cea801a40004666444246660020080060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008c044d5d0a80119a8060081aba135744a004464c6a66ae7005005404c0484d55cf280089baa00135742a006666aa00eeb94018d5d0a80119a8043ae357426ae8940088c98d4cd5ce00800880780709aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa02844646666aae7c008940588cd4054cd5405cc018d55cea80118029aab9e500230043574400601e26ae84004488c8c8cccd5cd19b875001480008c8488c00800cc014d5d09aab9e500323333573466e1d40092002212200123263533573801c01e01a01801626aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6a66ae7003803c03403002c0284d55cea80089baa0012323333573466e1d40052002200e23333573466e1d40092000200e23263533573801401601201000e26aae74dd5000919191919191999ab9a3370ea002900610911111100191999ab9a3370ea004900510911111100211999ab9a3370ea00690041199109111111198008048041bae35742a00a6eb4d5d09aba2500523333573466e1d40112006233221222222233002009008375c6ae85401cdd71aba135744a00e46666ae68cdc3a802a400846644244444446600c01201060186ae854024dd71aba135744a01246666ae68cdc3a8032400446424444444600e010601a6ae84d55cf280591999ab9a3370ea00e900011909111111180280418071aba135573ca018464c6a66ae7004804c04404003c03803403002c0284d55cea80209aab9e5003135573ca00426aae7940044dd50009191919191999ab9a3370ea002900111999110911998008028020019bad35742a0086eb4d5d0a8019bad357426ae89400c8cccd5cd19b875002480008c8488c00800cc020d5d09aab9e500623263533573801601801401201026aae75400c4d5d1280089aab9e500113754002464646666ae68cdc3a800a400446424460020066eb8d5d09aab9e500323333573466e1d400920002321223002003375c6ae84d55cf280211931a99ab9c008009007006005135573aa00226ea800444888c8c8cccd5cd19b8735573aa0049000119aa80818031aba150023005357426ae8940088c98d4cd5ce00400480380309aab9e5001137540029324903505431001200132001355007222533500110022213500222330073330080020060010033200135500622225335001100222135002225335333573466e1c005200000a0091333008007006003133300800733500b1233300100800300200600312200212200111220021221223300100400311221233001003002112323001001223300330020020014c1074643544c4e46540001" +} +""" + , "one-shot-minting-unit" /\ + """ +{ + "type": "PlutusScriptV1", + "description": "", + "cborHex": "5908de5908db010000333232332233223232323232323232323232323232323232323222223232323232325335533533355300b120013232123300122333500522002002001002350012200112330012253350021022100101f2325335333573466e3cd400488008d4014880080840804ccd5cd19b873500122001350052200102102010203500122002355001222222222200a101e101f132635335738921115574786f206e6f7420636f6e73756d65640001b0191533553355335323301d50220013550012222222222007101e22135002222533500415335333573466e3c00cd401c88cccd40048c98d4cd5ce2481024c680002302120012326353357389201024c68000230212326353357389201024c680002302102402315335333573466e3c00802409008c4ccd5cd19b870014800809008c408c408c8840944078407c4c98d4cd5ce24811357726f6e6720616d6f756e74206d696e7465640001b019101b135001220023333573466e1cd55cea8022400046644246600200600464646464646464646464646666ae68cdc39aab9d500a480008cccccccccc888888888848cccccccccc00402c02802402001c01801401000c008cd40648c8c8cccd5cd19b8735573aa0049000119910919800801801180d9aba15002301e357426ae8940088c98d4cd5ce01481501401389aab9e5001137540026ae854028cd4064068d5d0a804999aa80e3ae501b35742a010666aa038eb9406cd5d0a80399a80c8101aba15006335019335502302175a6ae854014c8c8c8cccd5cd19b8735573aa00490001199109198008018011919191999ab9a3370e6aae754009200023322123300100300233502675a6ae854008c09cd5d09aba2500223263533573805a05c05805626aae7940044dd50009aba150023232323333573466e1cd55cea8012400046644246600200600466a04ceb4d5d0a80118139aba135744a004464c6a66ae700b40b80b00ac4d55cf280089baa001357426ae8940088c98d4cd5ce01481501401389aab9e5001137540026ae854010cd4065d71aba15003335019335502375c40026ae854008c060d5d09aba2500223263533573804a04c04804626ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226aae7940044dd50009aba150043232323333573466e1d400520062321222230040053018357426aae79400c8cccd5cd19b875002480108c848888c008014c068d5d09aab9e500423333573466e1d400d20022321222230010053011357426aae7940148cccd5cd19b875004480008c848888c00c014dd71aba135573ca00c464c6a66ae7008008407c07807407006c4d55cea80089baa001357426ae8940108c98d4cd5ce00c80d00c00b98048031bae006135573ca00226ea8004c8004d5406088448894cd40044d400c88004884ccd401488008c010008ccd54c01c480040140100048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931a99ab9c012013011010135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98d4cd5ce00800880780709baa0011232230023758002640026aa02c446666aae7c0049405c8cd4058c010d5d080118019aba200201023232323333573466e1cd55cea801a40004666444246660020080060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008c044d5d0a80119a8060081aba135744a004464c6a66ae7005005404c0484d55cf280089baa00135742a006666aa00eeb94018d5d0a80119a8043ae357426ae8940088c98d4cd5ce00800880780709aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa02844646666aae7c008940588cd4054cd5405cc018d55cea80118029aab9e500230043574400601e26ae84004488c8c8cccd5cd19b875001480008c8488c00800cc014d5d09aab9e500323333573466e1d40092002212200123263533573801c01e01a01801626aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6a66ae7003803c03403002c0284d55cea80089baa0012323333573466e1d40052002200e23333573466e1d40092000200e23263533573801401601201000e26aae74dd5000919191919191999ab9a3370ea002900610911111100191999ab9a3370ea004900510911111100211999ab9a3370ea00690041199109111111198008048041bae35742a00a6eb4d5d09aba2500523333573466e1d40112006233221222222233002009008375c6ae85401cdd71aba135744a00e46666ae68cdc3a802a400846644244444446600c01201060186ae854024dd71aba135744a01246666ae68cdc3a8032400446424444444600e010601a6ae84d55cf280591999ab9a3370ea00e900011909111111180280418071aba135573ca018464c6a66ae7004804c04404003c03803403002c0284d55cea80209aab9e5003135573ca00426aae7940044dd50009191919191999ab9a3370ea002900111999110911998008028020019bad35742a0086eb4d5d0a8019bad357426ae89400c8cccd5cd19b875002480008c8488c00800cc020d5d09aab9e500623263533573801601801401201026aae75400c4d5d1280089aab9e500113754002464646666ae68cdc3a800a400446424460020066eb8d5d09aab9e500323333573466e1d400920002321223002003375c6ae84d55cf280211931a99ab9c008009007006005135573aa00226ea800444888c8c8cccd5cd19b8735573aa0049000119aa80818031aba150023005357426ae8940088c98d4cd5ce00400480380309aab9e5001137540029324903505431001200132001355007222533500110022213500222330073330080020060010033200135500622225335001100222135002225335333573466e1c005200000a0091333008007006003133300800733500b1233300100800300200600312200212200111220021221223300100400311221233001003002112323001001223300330020020014c1074643544c4e4654004c0103d879800001" +} +""" + + , "always-succeeds-v2" /\ + """ +{ + "cborHex": "4e4d01000033222220051200120011", + "description": "always-succeeds", + "type": "PlutusScriptV2" +} +""" + , "always-succeeds-v2-big-arg" /\ + """ +{ + "type": "PlutusScriptV2", + "description": "", + "cborHex": "58f058ee010000333333333222220051200120014c010107004c0103d87980004c01089fd87980424d5fff004c01465f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dff004c0107a20507424d5f08004c0154d9055f9f079fd87980424d5f5f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dffffff004c0114d87e9f809f01ffa0a201d8798002d87b9f02ffff0001" +} +""" + , "always-succeeds-v2-no-args" /\ + """ +{ + "type": "PlutusScriptV2", + "description": "", + "cborHex": "4e4d01000033222220051200120011" +} +""" + , "always-succeeds-v2-unit" /\ + """ +{ + "type": "PlutusScriptV2", + "description": "", + "cborHex": "5655010000333222220051200120014c0103d879800001" +} +""" + + , "check-datum-is-inline" /\ + """ +{ + "type": "PlutusScriptV2", + "description": "", + "cborHex": "59088859088501000032332232323233223232323232323232323322323232323232322223232533532325335001101b13357389211d556e657870656374656420646174756d206174206f776e20696e7075740001a323253335002153335001101c2101c2101c2153335002101c21333573466ebc00800407807484074854ccd400840708407484ccd5cd19b8f00200101e01d323500122220023235001220013553353500222350022222222222223333500d2501e2501e2501e233355302d12001321233001225335002210031001002501e2350012253355335333573466e3cd400888008d4010880080b40b04ccd5cd19b873500222001350042200102d02c102c1350220031502100d21123001002162001300a0053333573466e1cd55cea80124000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4054058d5d0a80619a80a80b1aba1500b33501501735742a014666aa034eb94064d5d0a804999aa80d3ae501935742a01066a02a0426ae85401cccd54068089d69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b1d69aba15002302d357426ae8940088c98c80bccd5ce01901881689aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a8163ad35742a004605a6ae84d5d1280111931901799ab9c03203102d135573ca00226ea8004d5d09aba2500223263202b33573805c05a05226aae7940044dd50009aba1500533501575c6ae854010ccd540680788004d5d0a801999aa80d3ae200135742a00460406ae84d5d1280111931901399ab9c02a029025135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00460206ae84d5d1280111931900c99ab9c01c01b017101a132632018335738921035054350001a135573ca00226ea800448c88c008dd6000990009aa80d111999aab9f0012501c233501b30043574200460066ae8800805c8c8c8cccd5cd19b8735573aa004900011991091980080180118069aba150023005357426ae8940088c98c8054cd5ce00c00b80989aab9e5001137540024646464646666ae68cdc39aab9d5004480008cccc888848cccc00401401000c008c8c8c8cccd5cd19b8735573aa0049000119910919800801801180b1aba1500233500e015357426ae8940088c98c8068cd5ce00e80e00c09aab9e5001137540026ae854010ccd54025d728041aba150033232323333573466e1d400520042300b357426aae79400c8cccd5cd19b875002480088c84888c004010dd71aba135573ca00846666ae68cdc3a801a400042444006464c6403866ae7007c0780680640604d55cea80089baa00135742a00466a014eb8d5d09aba2500223263201633573803203002826ae8940044d5d1280089aab9e500113754002424446004008266aa002eb9d6889119118011bab00132001355016223233335573e0044a032466a03066442466002006004600c6aae754008c014d55cf280118021aba200301413574200224464646666ae68cdc3a800a400046a00e600a6ae84d55cf280191999ab9a3370ea00490011280391931900919ab9c01501401000f135573aa00226ea800448488c00800c44880048c8c8cccd5cd19b875001480188c848888c010014c01cd5d09aab9e500323333573466e1d400920042321222230020053009357426aae7940108cccd5cd19b875003480088c848888c004014c01cd5d09aab9e500523333573466e1d40112000232122223003005375c6ae84d55cf280311931900819ab9c01301200e00d00c00b135573aa00226ea80048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931900619ab9c00f00e00a135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98c8028cd5ce00680600409baa001232323232323333573466e1d4005200c21222222200323333573466e1d4009200a21222222200423333573466e1d400d2008233221222222233001009008375c6ae854014dd69aba135744a00a46666ae68cdc3a8022400c4664424444444660040120106eb8d5d0a8039bae357426ae89401c8cccd5cd19b875005480108cc8848888888cc018024020c030d5d0a8049bae357426ae8940248cccd5cd19b875006480088c848888888c01c020c034d5d09aab9e500b23333573466e1d401d2000232122222223005008300e357426aae7940308c98c804ccd5ce00b00a80880800780700680600589aab9d5004135573ca00626aae7940084d55cf280089baa0012323232323333573466e1d400520022333222122333001005004003375a6ae854010dd69aba15003375a6ae84d5d1280191999ab9a3370ea0049000119091180100198041aba135573ca00c464c6401866ae7003c0380280244d55cea80189aba25001135573ca00226ea80048c8c8cccd5cd19b875001480088c8488c00400cdd71aba135573ca00646666ae68cdc3a8012400046424460040066eb8d5d09aab9e500423263200933573801801600e00c26aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6401466ae7003403002001c0184d55cea80089baa0012323333573466e1d40052002200623333573466e1d40092000200623263200633573801201000800626aae74dd5000a4c24400424400224002920103505431003200135500322112225335001135003220012213335005220023004002333553007120010050040011122002122122330010040031123230010012233003300200200101" +} +""" + , "check-datum-is-inline-big-arg" /\ + """ +{ + "type": "PlutusScriptV2", + "description": "", + "cborHex": "590969590966010000333333332332232323233223232323232323232323322323232323232322223232533532325335001101b133573892011d556e657870656374656420646174756d206174206f776e20696e7075740001a323253335002153335001101c2101c2101c2153335002101c21333573466ebc00800407807484074854ccd400840708407484ccd5cd19b8f00200101e01d323500122220023235001220013553353500222350022222222222223333500d2501e2501e2501e233355302d12001321233001225335002210031001002501e2350012253355335333573466e3cd400888008d4010880080b40b04ccd5cd19b873500222001350042200102d02c102c1350220031502100d21123001002162001300a0053333573466e1cd55cea80124000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4054058d5d0a80619a80a80b1aba1500b33501501735742a014666aa034eb94064d5d0a804999aa80d3ae501935742a01066a02a0426ae85401cccd54068089d69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b1d69aba15002302d357426ae8940088c98c80bccd5ce01901881689aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a8163ad35742a004605a6ae84d5d1280111931901799ab9c03203102d135573ca00226ea8004d5d09aba2500223263202b33573805c05a05226aae7940044dd50009aba1500533501575c6ae854010ccd540680788004d5d0a801999aa80d3ae200135742a00460406ae84d5d1280111931901399ab9c02a029025135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00460206ae84d5d1280111931900c99ab9c01c01b017101a132632018335738921035054350001a135573ca00226ea800448c88c008dd6000990009aa80d111999aab9f0012501c233501b30043574200460066ae8800805c8c8c8cccd5cd19b8735573aa004900011991091980080180118069aba150023005357426ae8940088c98c8054cd5ce00c00b80989aab9e5001137540024646464646666ae68cdc39aab9d5004480008cccc888848cccc00401401000c008c8c8c8cccd5cd19b8735573aa0049000119910919800801801180b1aba1500233500e015357426ae8940088c98c8068cd5ce00e80e00c09aab9e5001137540026ae854010ccd54025d728041aba150033232323333573466e1d400520042300b357426aae79400c8cccd5cd19b875002480088c84888c004010dd71aba135573ca00846666ae68cdc3a801a400042444006464c6403866ae7007c0780680640604d55cea80089baa00135742a00466a014eb8d5d09aba2500223263201633573803203002826ae8940044d5d1280089aab9e500113754002424446004008266aa002eb9d6889119118011bab00132001355016223233335573e0044a032466a03066442466002006004600c6aae754008c014d55cf280118021aba200301413574200224464646666ae68cdc3a800a400046a00e600a6ae84d55cf280191999ab9a3370ea00490011280391931900919ab9c01501401000f135573aa00226ea800448488c00800c44880048c8c8cccd5cd19b875001480188c848888c010014c01cd5d09aab9e500323333573466e1d400920042321222230020053009357426aae7940108cccd5cd19b875003480088c848888c004014c01cd5d09aab9e500523333573466e1d40112000232122223003005375c6ae84d55cf280311931900819ab9c01301200e00d00c00b135573aa00226ea80048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931900619ab9c00f00e00a135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98c8028cd5ce00680600409baa001232323232323333573466e1d4005200c21222222200323333573466e1d4009200a21222222200423333573466e1d400d2008233221222222233001009008375c6ae854014dd69aba135744a00a46666ae68cdc3a8022400c4664424444444660040120106eb8d5d0a8039bae357426ae89401c8cccd5cd19b875005480108cc8848888888cc018024020c030d5d0a8049bae357426ae8940248cccd5cd19b875006480088c848888888c01c020c034d5d09aab9e500b23333573466e1d401d2000232122222223005008300e357426aae7940308c98c804ccd5ce00b00a80880800780700680600589aab9d5004135573ca00626aae7940084d55cf280089baa0012323232323333573466e1d400520022333222122333001005004003375a6ae854010dd69aba15003375a6ae84d5d1280191999ab9a3370ea0049000119091180100198041aba135573ca00c464c6401866ae7003c0380280244d55cea80189aba25001135573ca00226ea80048c8c8cccd5cd19b875001480088c8488c00400cdd71aba135573ca00646666ae68cdc3a8012400046424460040066eb8d5d09aab9e500423263200933573801801600e00c26aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6401466ae7003403002001c0184d55cea80089baa0012323333573466e1d40052002200623333573466e1d40092000200623263200633573801201000800626aae74dd5000a4c2440042440022400292010350543100320013550032211222533500113500322001221333500522002300400233355300712001005004001112200212212233001004003112323001001223300330020020014c010107004c0103d87980004c01089fd87980424d5fff004c01465f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dff004c0107a20507424d5f08004c0154d9055f9f079fd87980424d5f5f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dffffff004c0114d87e9f809f01ffa0a201d8798002d87b9f02ffff0001" +} +""" + , "check-datum-is-inline-no-args" /\ + """ +{ + "type": "PlutusScriptV2", + "description": "", + "cborHex": "59088859088501000032332232323233223232323232323232323322323232323232322223232533532325335001101b13357389211d556e657870656374656420646174756d206174206f776e20696e7075740001a323253335002153335001101c2101c2101c2153335002101c21333573466ebc00800407807484074854ccd400840708407484ccd5cd19b8f00200101e01d323500122220023235001220013553353500222350022222222222223333500d2501e2501e2501e233355302d12001321233001225335002210031001002501e2350012253355335333573466e3cd400888008d4010880080b40b04ccd5cd19b873500222001350042200102d02c102c1350220031502100d21123001002162001300a0053333573466e1cd55cea80124000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4054058d5d0a80619a80a80b1aba1500b33501501735742a014666aa034eb94064d5d0a804999aa80d3ae501935742a01066a02a0426ae85401cccd54068089d69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b1d69aba15002302d357426ae8940088c98c80bccd5ce01901881689aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a8163ad35742a004605a6ae84d5d1280111931901799ab9c03203102d135573ca00226ea8004d5d09aba2500223263202b33573805c05a05226aae7940044dd50009aba1500533501575c6ae854010ccd540680788004d5d0a801999aa80d3ae200135742a00460406ae84d5d1280111931901399ab9c02a029025135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00460206ae84d5d1280111931900c99ab9c01c01b017101a132632018335738921035054350001a135573ca00226ea800448c88c008dd6000990009aa80d111999aab9f0012501c233501b30043574200460066ae8800805c8c8c8cccd5cd19b8735573aa004900011991091980080180118069aba150023005357426ae8940088c98c8054cd5ce00c00b80989aab9e5001137540024646464646666ae68cdc39aab9d5004480008cccc888848cccc00401401000c008c8c8c8cccd5cd19b8735573aa0049000119910919800801801180b1aba1500233500e015357426ae8940088c98c8068cd5ce00e80e00c09aab9e5001137540026ae854010ccd54025d728041aba150033232323333573466e1d400520042300b357426aae79400c8cccd5cd19b875002480088c84888c004010dd71aba135573ca00846666ae68cdc3a801a400042444006464c6403866ae7007c0780680640604d55cea80089baa00135742a00466a014eb8d5d09aba2500223263201633573803203002826ae8940044d5d1280089aab9e500113754002424446004008266aa002eb9d6889119118011bab00132001355016223233335573e0044a032466a03066442466002006004600c6aae754008c014d55cf280118021aba200301413574200224464646666ae68cdc3a800a400046a00e600a6ae84d55cf280191999ab9a3370ea00490011280391931900919ab9c01501401000f135573aa00226ea800448488c00800c44880048c8c8cccd5cd19b875001480188c848888c010014c01cd5d09aab9e500323333573466e1d400920042321222230020053009357426aae7940108cccd5cd19b875003480088c848888c004014c01cd5d09aab9e500523333573466e1d40112000232122223003005375c6ae84d55cf280311931900819ab9c01301200e00d00c00b135573aa00226ea80048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931900619ab9c00f00e00a135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98c8028cd5ce00680600409baa001232323232323333573466e1d4005200c21222222200323333573466e1d4009200a21222222200423333573466e1d400d2008233221222222233001009008375c6ae854014dd69aba135744a00a46666ae68cdc3a8022400c4664424444444660040120106eb8d5d0a8039bae357426ae89401c8cccd5cd19b875005480108cc8848888888cc018024020c030d5d0a8049bae357426ae8940248cccd5cd19b875006480088c848888888c01c020c034d5d09aab9e500b23333573466e1d401d2000232122222223005008300e357426aae7940308c98c804ccd5ce00b00a80880800780700680600589aab9d5004135573ca00626aae7940084d55cf280089baa0012323232323333573466e1d400520022333222122333001005004003375a6ae854010dd69aba15003375a6ae84d5d1280191999ab9a3370ea0049000119091180100198041aba135573ca00c464c6401866ae7003c0380280244d55cea80189aba25001135573ca00226ea80048c8c8cccd5cd19b875001480088c8488c00400cdd71aba135573ca00646666ae68cdc3a8012400046424460040066eb8d5d09aab9e500423263200933573801801600e00c26aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6401466ae7003403002001c0184d55cea80089baa0012323333573466e1d40052002200623333573466e1d40092000200623263200633573801201000800626aae74dd5000a4c24400424400224002920103505431003200135500322112225335001135003220012213335005220023004002333553007120010050040011122002122122330010040031123230010012233003300200200101" +} +""" + , "check-datum-is-inline-unit" /\ + """ +{ + "type": "PlutusScriptV2", + "description": "", + "cborHex": "59089059088d010000332332232323233223232323232323232323322323232323232322223232533532325335001101b133573892011d556e657870656374656420646174756d206174206f776e20696e7075740001a323253335002153335001101c2101c2101c2153335002101c21333573466ebc00800407807484074854ccd400840708407484ccd5cd19b8f00200101e01d323500122220023235001220013553353500222350022222222222223333500d2501e2501e2501e233355302d12001321233001225335002210031001002501e2350012253355335333573466e3cd400888008d4010880080b40b04ccd5cd19b873500222001350042200102d02c102c1350220031502100d21123001002162001300a0053333573466e1cd55cea80124000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4054058d5d0a80619a80a80b1aba1500b33501501735742a014666aa034eb94064d5d0a804999aa80d3ae501935742a01066a02a0426ae85401cccd54068089d69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b1d69aba15002302d357426ae8940088c98c80bccd5ce01901881689aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a8163ad35742a004605a6ae84d5d1280111931901799ab9c03203102d135573ca00226ea8004d5d09aba2500223263202b33573805c05a05226aae7940044dd50009aba1500533501575c6ae854010ccd540680788004d5d0a801999aa80d3ae200135742a00460406ae84d5d1280111931901399ab9c02a029025135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00460206ae84d5d1280111931900c99ab9c01c01b017101a132632018335738921035054350001a135573ca00226ea800448c88c008dd6000990009aa80d111999aab9f0012501c233501b30043574200460066ae8800805c8c8c8cccd5cd19b8735573aa004900011991091980080180118069aba150023005357426ae8940088c98c8054cd5ce00c00b80989aab9e5001137540024646464646666ae68cdc39aab9d5004480008cccc888848cccc00401401000c008c8c8c8cccd5cd19b8735573aa0049000119910919800801801180b1aba1500233500e015357426ae8940088c98c8068cd5ce00e80e00c09aab9e5001137540026ae854010ccd54025d728041aba150033232323333573466e1d400520042300b357426aae79400c8cccd5cd19b875002480088c84888c004010dd71aba135573ca00846666ae68cdc3a801a400042444006464c6403866ae7007c0780680640604d55cea80089baa00135742a00466a014eb8d5d09aba2500223263201633573803203002826ae8940044d5d1280089aab9e500113754002424446004008266aa002eb9d6889119118011bab00132001355016223233335573e0044a032466a03066442466002006004600c6aae754008c014d55cf280118021aba200301413574200224464646666ae68cdc3a800a400046a00e600a6ae84d55cf280191999ab9a3370ea00490011280391931900919ab9c01501401000f135573aa00226ea800448488c00800c44880048c8c8cccd5cd19b875001480188c848888c010014c01cd5d09aab9e500323333573466e1d400920042321222230020053009357426aae7940108cccd5cd19b875003480088c848888c004014c01cd5d09aab9e500523333573466e1d40112000232122223003005375c6ae84d55cf280311931900819ab9c01301200e00d00c00b135573aa00226ea80048c8c8cccd5cd19b8735573aa004900011991091980080180118029aba15002375a6ae84d5d1280111931900619ab9c00f00e00a135573ca00226ea80048c8cccd5cd19b8735573aa002900011bae357426aae7940088c98c8028cd5ce00680600409baa001232323232323333573466e1d4005200c21222222200323333573466e1d4009200a21222222200423333573466e1d400d2008233221222222233001009008375c6ae854014dd69aba135744a00a46666ae68cdc3a8022400c4664424444444660040120106eb8d5d0a8039bae357426ae89401c8cccd5cd19b875005480108cc8848888888cc018024020c030d5d0a8049bae357426ae8940248cccd5cd19b875006480088c848888888c01c020c034d5d09aab9e500b23333573466e1d401d2000232122222223005008300e357426aae7940308c98c804ccd5ce00b00a80880800780700680600589aab9d5004135573ca00626aae7940084d55cf280089baa0012323232323333573466e1d400520022333222122333001005004003375a6ae854010dd69aba15003375a6ae84d5d1280191999ab9a3370ea0049000119091180100198041aba135573ca00c464c6401866ae7003c0380280244d55cea80189aba25001135573ca00226ea80048c8c8cccd5cd19b875001480088c8488c00400cdd71aba135573ca00646666ae68cdc3a8012400046424460040066eb8d5d09aab9e500423263200933573801801600e00c26aae7540044dd500089119191999ab9a3370ea00290021091100091999ab9a3370ea00490011190911180180218031aba135573ca00846666ae68cdc3a801a400042444004464c6401466ae7003403002001c0184d55cea80089baa0012323333573466e1d40052002200623333573466e1d40092000200623263200633573801201000800626aae74dd5000a4c2440042440022400292010350543100320013550032211222533500113500322001221333500522002300400233355300712001005004001112200212212233001004003112323001001223300330020020014c0103d879800001" +} +""" + + , "one-shot-minting-v2" /\ + """ +{ + "type": "PlutusScriptV2", + "description": "one-shot-minting", + "cborHex": "59092c59092901000033233223322323232323232323232323232323232323232323222223232323232325335533533355300b12001323212330012233350052200200200100235001220011233001225335002102310010202325335333573466e3cd400488008d4014880080880844ccd5cd19b87350012200135005220010220211021350012200235500122222222222200c101f102013263201b335738921115574786f206e6f7420636f6e73756d65640001c1533553355335323301e5023001355001222222222222008101f22135002222533500415335333573466e3c00cd401c88cccd40048c98c808ccd5ce2481024c680002420012326320233357389201024c68000242326320233357389201024c680002402502415335333573466e3c0080240940904ccd5cd19b870014800809409040904090884098407c40804c98c806ccd5ce24811357726f6e6720616d6f756e74206d696e7465640001c101c135001220023333573466e1cd55cea80224000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4064068d5d0a80619a80c80d1aba1500b33501901b35742a014666aa03aeb94070d5d0a804999aa80ebae501c35742a01066a0320446ae85401cccd5407408dd69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b5d69aba15002302e357426ae8940088c98c80c0cd5ce01801881709aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a816bad35742a004605c6ae84d5d1280111931901819ab9c03003102e135573ca00226ea8004d5d09aba2500223263202c33573805805a05426aae7940044dd50009aba1500533501975c6ae854010ccd5407407c8004d5d0a801999aa80ebae200135742a00460426ae84d5d1280111931901419ab9c028029026135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00860226ae84d5d1280211931900d19ab9c01a01b0183010006375c00c26aae7940044dd5000990009aa80c1108911299a80089a80191000910999a802910011802001199aa9803890008028020008919118011bac001320013550182233335573e0024a034466a03260086ae84008c00cd5d1001009919191999ab9a3370e6aae7540092000233221233001003002300a35742a004600a6ae84d5d1280111931900919ab9c012013010135573ca00226ea80048c8c8c8c8cccd5cd19b8735573aa00890001199991110919998008028020018011919191999ab9a3370e6aae7540092000233221233001003002301335742a00466a01a0246ae84d5d1280111931900b99ab9c017018015135573ca00226ea8004d5d0a802199aa8043ae500735742a0066464646666ae68cdc3a800a4008464244460040086ae84d55cf280191999ab9a3370ea0049001119091118008021bae357426aae7940108cccd5cd19b875003480008488800c8c98c8064cd5ce00c80d00b80b00a89aab9d5001137540026ae854008cd4025d71aba135744a004464c6402666ae7004c0500444d5d1280089aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa02a44646666aae7c008940608cd405ccc8848cc00400c008c018d55cea80118029aab9e500230043574400602226ae84004488c8c8cccd5cd19b875001480008c8488c00800cc014d5d09aab9e500323333573466e1d40092002212200123263201033573802002201c01a26aae7540044dd5000919191999ab9a3370ea002900311909111180200298039aba135573ca00646666ae68cdc3a8012400846424444600400a60126ae84d55cf280211999ab9a3370ea006900111909111180080298039aba135573ca00a46666ae68cdc3a8022400046424444600600a6eb8d5d09aab9e500623263201033573802002201c01a01801626aae7540044dd5000919191999ab9a3370e6aae7540092000233221233001003002300535742a0046eb4d5d09aba2500223263200c33573801801a01426aae7940044dd50009191999ab9a3370e6aae75400520002375c6ae84d55cf280111931900519ab9c00a00b00813754002464646464646666ae68cdc3a800a401842444444400646666ae68cdc3a8012401442444444400846666ae68cdc3a801a40104664424444444660020120106eb8d5d0a8029bad357426ae8940148cccd5cd19b875004480188cc8848888888cc008024020dd71aba15007375c6ae84d5d1280391999ab9a3370ea00a900211991091111111980300480418061aba15009375c6ae84d5d1280491999ab9a3370ea00c900111909111111180380418069aba135573ca01646666ae68cdc3a803a400046424444444600a010601c6ae84d55cf280611931900999ab9c01301401101000f00e00d00c00b135573aa00826aae79400c4d55cf280109aab9e5001137540024646464646666ae68cdc3a800a4004466644424466600200a0080066eb4d5d0a8021bad35742a0066eb4d5d09aba2500323333573466e1d4009200023212230020033008357426aae7940188c98c8030cd5ce00600680500489aab9d5003135744a00226aae7940044dd5000919191999ab9a3370ea002900111909118008019bae357426aae79400c8cccd5cd19b875002480008c8488c00800cdd71aba135573ca008464c6401266ae7002402801c0184d55cea80089baa00112232323333573466e1d400520042122200123333573466e1d40092002232122230030043006357426aae7940108cccd5cd19b87500348000848880088c98c8028cd5ce00500580400380309aab9d5001137540024646666ae68cdc3a800a4004401446666ae68cdc3a801240004014464c6400c66ae7001801c01000c4d55ce9baa001499240103505431001200132001355006222533500110022213500222330073330080020060010033200135500522225335001100222135002225335333573466e1c005200000a0091333008007006003133300800733500b12333001008003002006003122002122001112200212212233001004003112323001001223300330020020014c01074643544c4e46540001" +} +""" + , "one-shot-minting-v2-big-arg" /\ + """ +{ + "type": "PlutusScriptV2", + "description": "", + "cborHex": "590a0d590a0a010000333333333233223322323232323232323232323232323232323232323222223232323232325335533533355300b12001323212330012233350052200200200100235001220011233001225335002102310010202325335333573466e3cd400488008d4014880080880844ccd5cd19b87350012200135005220010220211021350012200235500122222222222200c101f102013263201b3357389201115574786f206e6f7420636f6e73756d65640001c1533553355335323301e5023001355001222222222222008101f22135002222533500415335333573466e3c00cd401c88cccd40048c98c808ccd5ce2481024c680002420012326320233357389201024c68000242326320233357389201024c680002402502415335333573466e3c0080240940904ccd5cd19b870014800809409040904090884098407c40804c98c806ccd5ce24811357726f6e6720616d6f756e74206d696e7465640001c101c135001220023333573466e1cd55cea80224000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4064068d5d0a80619a80c80d1aba1500b33501901b35742a014666aa03aeb94070d5d0a804999aa80ebae501c35742a01066a0320446ae85401cccd5407408dd69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b5d69aba15002302e357426ae8940088c98c80c0cd5ce01801881709aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a816bad35742a004605c6ae84d5d1280111931901819ab9c03003102e135573ca00226ea8004d5d09aba2500223263202c33573805805a05426aae7940044dd50009aba1500533501975c6ae854010ccd5407407c8004d5d0a801999aa80ebae200135742a00460426ae84d5d1280111931901419ab9c028029026135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00860226ae84d5d1280211931900d19ab9c01a01b0183010006375c00c26aae7940044dd5000990009aa80c1108911299a80089a80191000910999a802910011802001199aa9803890008028020008919118011bac001320013550182233335573e0024a034466a03260086ae84008c00cd5d1001009919191999ab9a3370e6aae7540092000233221233001003002300a35742a004600a6ae84d5d1280111931900919ab9c012013010135573ca00226ea80048c8c8c8c8cccd5cd19b8735573aa00890001199991110919998008028020018011919191999ab9a3370e6aae7540092000233221233001003002301335742a00466a01a0246ae84d5d1280111931900b99ab9c017018015135573ca00226ea8004d5d0a802199aa8043ae500735742a0066464646666ae68cdc3a800a4008464244460040086ae84d55cf280191999ab9a3370ea0049001119091118008021bae357426aae7940108cccd5cd19b875003480008488800c8c98c8064cd5ce00c80d00b80b00a89aab9d5001137540026ae854008cd4025d71aba135744a004464c6402666ae7004c0500444d5d1280089aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa02a44646666aae7c008940608cd405ccc8848cc00400c008c018d55cea80118029aab9e500230043574400602226ae84004488c8c8cccd5cd19b875001480008c8488c00800cc014d5d09aab9e500323333573466e1d40092002212200123263201033573802002201c01a26aae7540044dd5000919191999ab9a3370ea002900311909111180200298039aba135573ca00646666ae68cdc3a8012400846424444600400a60126ae84d55cf280211999ab9a3370ea006900111909111180080298039aba135573ca00a46666ae68cdc3a8022400046424444600600a6eb8d5d09aab9e500623263201033573802002201c01a01801626aae7540044dd5000919191999ab9a3370e6aae7540092000233221233001003002300535742a0046eb4d5d09aba2500223263200c33573801801a01426aae7940044dd50009191999ab9a3370e6aae75400520002375c6ae84d55cf280111931900519ab9c00a00b00813754002464646464646666ae68cdc3a800a401842444444400646666ae68cdc3a8012401442444444400846666ae68cdc3a801a40104664424444444660020120106eb8d5d0a8029bad357426ae8940148cccd5cd19b875004480188cc8848888888cc008024020dd71aba15007375c6ae84d5d1280391999ab9a3370ea00a900211991091111111980300480418061aba15009375c6ae84d5d1280491999ab9a3370ea00c900111909111111180380418069aba135573ca01646666ae68cdc3a803a400046424444444600a010601c6ae84d55cf280611931900999ab9c01301401101000f00e00d00c00b135573aa00826aae79400c4d55cf280109aab9e5001137540024646464646666ae68cdc3a800a4004466644424466600200a0080066eb4d5d0a8021bad35742a0066eb4d5d09aba2500323333573466e1d4009200023212230020033008357426aae7940188c98c8030cd5ce00600680500489aab9d5003135744a00226aae7940044dd5000919191999ab9a3370ea002900111909118008019bae357426aae79400c8cccd5cd19b875002480008c8488c00800cdd71aba135573ca008464c6401266ae7002402801c0184d55cea80089baa00112232323333573466e1d400520042122200123333573466e1d40092002232122230030043006357426aae7940108cccd5cd19b87500348000848880088c98c8028cd5ce00500580400380309aab9d5001137540024646666ae68cdc3a800a4004401446666ae68cdc3a801240004014464c6400c66ae7001801c01000c4d55ce9baa001499240103505431001200132001355006222533500110022213500222330073330080020060010033200135500522225335001100222135002225335333573466e1c005200000a0091333008007006003133300800733500b12333001008003002006003122002122001112200212212233001004003112323001001223300330020020014c01074643544c4e4654004c010107004c0103d87980004c01089fd87980424d5fff004c01465f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dff004c0107a20507424d5f08004c0154d9055f9f079fd87980424d5f5f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dffffff004c0114d87e9f809f01ffa0a201d8798002d87b9f02ffff0001" +} +""" + , "one-shot-minting-v2-no-args" /\ + """ +{ + "type": "PlutusScriptV2", + "description": "", + "cborHex": "59092c59092901000033233223322323232323232323232323232323232323232323222223232323232325335533533355300b12001323212330012233350052200200200100235001220011233001225335002102310010202325335333573466e3cd400488008d4014880080880844ccd5cd19b87350012200135005220010220211021350012200235500122222222222200c101f102013263201b335738921115574786f206e6f7420636f6e73756d65640001c1533553355335323301e5023001355001222222222222008101f22135002222533500415335333573466e3c00cd401c88cccd40048c98c808ccd5ce2481024c680002420012326320233357389201024c68000242326320233357389201024c680002402502415335333573466e3c0080240940904ccd5cd19b870014800809409040904090884098407c40804c98c806ccd5ce24811357726f6e6720616d6f756e74206d696e7465640001c101c135001220023333573466e1cd55cea80224000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4064068d5d0a80619a80c80d1aba1500b33501901b35742a014666aa03aeb94070d5d0a804999aa80ebae501c35742a01066a0320446ae85401cccd5407408dd69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b5d69aba15002302e357426ae8940088c98c80c0cd5ce01801881709aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a816bad35742a004605c6ae84d5d1280111931901819ab9c03003102e135573ca00226ea8004d5d09aba2500223263202c33573805805a05426aae7940044dd50009aba1500533501975c6ae854010ccd5407407c8004d5d0a801999aa80ebae200135742a00460426ae84d5d1280111931901419ab9c028029026135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00860226ae84d5d1280211931900d19ab9c01a01b0183010006375c00c26aae7940044dd5000990009aa80c1108911299a80089a80191000910999a802910011802001199aa9803890008028020008919118011bac001320013550182233335573e0024a034466a03260086ae84008c00cd5d1001009919191999ab9a3370e6aae7540092000233221233001003002300a35742a004600a6ae84d5d1280111931900919ab9c012013010135573ca00226ea80048c8c8c8c8cccd5cd19b8735573aa00890001199991110919998008028020018011919191999ab9a3370e6aae7540092000233221233001003002301335742a00466a01a0246ae84d5d1280111931900b99ab9c017018015135573ca00226ea8004d5d0a802199aa8043ae500735742a0066464646666ae68cdc3a800a4008464244460040086ae84d55cf280191999ab9a3370ea0049001119091118008021bae357426aae7940108cccd5cd19b875003480008488800c8c98c8064cd5ce00c80d00b80b00a89aab9d5001137540026ae854008cd4025d71aba135744a004464c6402666ae7004c0500444d5d1280089aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa02a44646666aae7c008940608cd405ccc8848cc00400c008c018d55cea80118029aab9e500230043574400602226ae84004488c8c8cccd5cd19b875001480008c8488c00800cc014d5d09aab9e500323333573466e1d40092002212200123263201033573802002201c01a26aae7540044dd5000919191999ab9a3370ea002900311909111180200298039aba135573ca00646666ae68cdc3a8012400846424444600400a60126ae84d55cf280211999ab9a3370ea006900111909111180080298039aba135573ca00a46666ae68cdc3a8022400046424444600600a6eb8d5d09aab9e500623263201033573802002201c01a01801626aae7540044dd5000919191999ab9a3370e6aae7540092000233221233001003002300535742a0046eb4d5d09aba2500223263200c33573801801a01426aae7940044dd50009191999ab9a3370e6aae75400520002375c6ae84d55cf280111931900519ab9c00a00b00813754002464646464646666ae68cdc3a800a401842444444400646666ae68cdc3a8012401442444444400846666ae68cdc3a801a40104664424444444660020120106eb8d5d0a8029bad357426ae8940148cccd5cd19b875004480188cc8848888888cc008024020dd71aba15007375c6ae84d5d1280391999ab9a3370ea00a900211991091111111980300480418061aba15009375c6ae84d5d1280491999ab9a3370ea00c900111909111111180380418069aba135573ca01646666ae68cdc3a803a400046424444444600a010601c6ae84d55cf280611931900999ab9c01301401101000f00e00d00c00b135573aa00826aae79400c4d55cf280109aab9e5001137540024646464646666ae68cdc3a800a4004466644424466600200a0080066eb4d5d0a8021bad35742a0066eb4d5d09aba2500323333573466e1d4009200023212230020033008357426aae7940188c98c8030cd5ce00600680500489aab9d5003135744a00226aae7940044dd5000919191999ab9a3370ea002900111909118008019bae357426aae79400c8cccd5cd19b875002480008c8488c00800cdd71aba135573ca008464c6401266ae7002402801c0184d55cea80089baa00112232323333573466e1d400520042122200123333573466e1d40092002232122230030043006357426aae7940108cccd5cd19b87500348000848880088c98c8028cd5ce00500580400380309aab9d5001137540024646666ae68cdc3a800a4004401446666ae68cdc3a801240004014464c6400c66ae7001801c01000c4d55ce9baa001499240103505431001200132001355006222533500110022213500222330073330080020060010033200135500522225335001100222135002225335333573466e1c005200000a0091333008007006003133300800733500b12333001008003002006003122002122001112200212212233001004003112323001001223300330020020014c01074643544c4e46540001" +} +""" + , "one-shot-minting-v2-unit" /\ + """ +{ + "type": "PlutusScriptV2", + "description": "", + "cborHex": "590934590931010000333233223322323232323232323232323232323232323232323222223232323232325335533533355300b12001323212330012233350052200200200100235001220011233001225335002102310010202325335333573466e3cd400488008d4014880080880844ccd5cd19b87350012200135005220010220211021350012200235500122222222222200c101f102013263201b3357389201115574786f206e6f7420636f6e73756d65640001c1533553355335323301e5023001355001222222222222008101f22135002222533500415335333573466e3c00cd401c88cccd40048c98c808ccd5ce2481024c680002420012326320233357389201024c68000242326320233357389201024c680002402502415335333573466e3c0080240940904ccd5cd19b870014800809409040904090884098407c40804c98c806ccd5ce24811357726f6e6720616d6f756e74206d696e7465640001c101c135001220023333573466e1cd55cea80224000466442466002006004646464646464646464646464646666ae68cdc39aab9d500c480008cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cd4064068d5d0a80619a80c80d1aba1500b33501901b35742a014666aa03aeb94070d5d0a804999aa80ebae501c35742a01066a0320446ae85401cccd5407408dd69aba150063232323333573466e1cd55cea801240004664424660020060046464646666ae68cdc39aab9d5002480008cc8848cc00400c008cd40b5d69aba15002302e357426ae8940088c98c80c0cd5ce01801881709aab9e5001137540026ae854008c8c8c8cccd5cd19b8735573aa004900011991091980080180119a816bad35742a004605c6ae84d5d1280111931901819ab9c03003102e135573ca00226ea8004d5d09aba2500223263202c33573805805a05426aae7940044dd50009aba1500533501975c6ae854010ccd5407407c8004d5d0a801999aa80ebae200135742a00460426ae84d5d1280111931901419ab9c028029026135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d5d1280089aba25001135744a00226ae8940044d55cf280089baa00135742a00860226ae84d5d1280211931900d19ab9c01a01b0183010006375c00c26aae7940044dd5000990009aa80c1108911299a80089a80191000910999a802910011802001199aa9803890008028020008919118011bac001320013550182233335573e0024a034466a03260086ae84008c00cd5d1001009919191999ab9a3370e6aae7540092000233221233001003002300a35742a004600a6ae84d5d1280111931900919ab9c012013010135573ca00226ea80048c8c8c8c8cccd5cd19b8735573aa00890001199991110919998008028020018011919191999ab9a3370e6aae7540092000233221233001003002301335742a00466a01a0246ae84d5d1280111931900b99ab9c017018015135573ca00226ea8004d5d0a802199aa8043ae500735742a0066464646666ae68cdc3a800a4008464244460040086ae84d55cf280191999ab9a3370ea0049001119091118008021bae357426aae7940108cccd5cd19b875003480008488800c8c98c8064cd5ce00c80d00b80b00a89aab9d5001137540026ae854008cd4025d71aba135744a004464c6402666ae7004c0500444d5d1280089aba25001135573ca00226ea80044cd54005d73ad112232230023756002640026aa02a44646666aae7c008940608cd405ccc8848cc00400c008c018d55cea80118029aab9e500230043574400602226ae84004488c8c8cccd5cd19b875001480008c8488c00800cc014d5d09aab9e500323333573466e1d40092002212200123263201033573802002201c01a26aae7540044dd5000919191999ab9a3370ea002900311909111180200298039aba135573ca00646666ae68cdc3a8012400846424444600400a60126ae84d55cf280211999ab9a3370ea006900111909111180080298039aba135573ca00a46666ae68cdc3a8022400046424444600600a6eb8d5d09aab9e500623263201033573802002201c01a01801626aae7540044dd5000919191999ab9a3370e6aae7540092000233221233001003002300535742a0046eb4d5d09aba2500223263200c33573801801a01426aae7940044dd50009191999ab9a3370e6aae75400520002375c6ae84d55cf280111931900519ab9c00a00b00813754002464646464646666ae68cdc3a800a401842444444400646666ae68cdc3a8012401442444444400846666ae68cdc3a801a40104664424444444660020120106eb8d5d0a8029bad357426ae8940148cccd5cd19b875004480188cc8848888888cc008024020dd71aba15007375c6ae84d5d1280391999ab9a3370ea00a900211991091111111980300480418061aba15009375c6ae84d5d1280491999ab9a3370ea00c900111909111111180380418069aba135573ca01646666ae68cdc3a803a400046424444444600a010601c6ae84d55cf280611931900999ab9c01301401101000f00e00d00c00b135573aa00826aae79400c4d55cf280109aab9e5001137540024646464646666ae68cdc3a800a4004466644424466600200a0080066eb4d5d0a8021bad35742a0066eb4d5d09aba2500323333573466e1d4009200023212230020033008357426aae7940188c98c8030cd5ce00600680500489aab9d5003135744a00226aae7940044dd5000919191999ab9a3370ea002900111909118008019bae357426aae79400c8cccd5cd19b875002480008c8488c00800cdd71aba135573ca008464c6401266ae7002402801c0184d55cea80089baa00112232323333573466e1d400520042122200123333573466e1d40092002232122230030043006357426aae7940108cccd5cd19b87500348000848880088c98c8028cd5ce00500580400380309aab9d5001137540024646666ae68cdc3a800a4004401446666ae68cdc3a801240004014464c6400c66ae7001801c01000c4d55ce9baa001499240103505431001200132001355006222533500110022213500222330073330080020060010033200135500522225335001100222135002225335333573466e1c005200000a0091333008007006003133300800733500b12333001008003002006003122002122001112200212212233001004003112323001001223300330020020014c01074643544c4e4654004c0103d879800001" +} +""" + + , "redeemer1-validator" /\ + """ +{ + "description": "validator that checks whether redeemer is 1", + "cborHex": "4e4d0100002223375e0046ea120021", + "type": "PlutusScriptV1" +} +""" + , "redeemer1-validator-big-arg" /\ + """ +{ + "type": "PlutusScriptV1", + "description": "", + "cborHex": "58f058ee01000033333332223375e0046ea120024c010107004c0103d87980004c01089fd87980424d5fff004c01465f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dff004c0107a20507424d5f08004c0154d9055f9f079fd87980424d5f5f58404d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d4d414dffffff004c0114d87e9f809f01ffa0a201d8798002d87b9f02ffff0001" +} +""" + , "redeemer1-validator-no-args" /\ + """ +{ + "type": "PlutusScriptV1", + "description": "", + "cborHex": "4e4d0100002223375e0046ea120021" +} +""" + , "redeemer1-validator-unit" /\ + """ +{ + "type": "PlutusScriptV1", + "description": "", + "cborHex": "565501000032223375e0046ea120024c0103d879800001" +} +""" + ] + +main :: Effect Unit +main = launchAff_ $ interpret $ suite + +contract :: Contract Unit +contract = do + traverse_ (uncurry $ compareApplied (v1 scriptSources)) $ Tuple + <$> v1ScriptPaths + <*> params + traverse_ (uncurry $ compareApplied (v2 scriptSources)) $ Tuple + <$> v2ScriptPaths + <*> params + +suite :: TestPlanM (Aff Unit) Unit +suite = group "Applying params to scripts test" $ do + traverse_ (uncurry $ testCase $ v1 scriptSources) + $ Tuple + <$> v1ScriptPaths + <*> params + traverse_ (uncurry $ testCase $ v2 scriptSources) + $ Tuple + <$> v2ScriptPaths + <*> params + where + testCase lang scriptName (args /\ argsName) = + test + ("Apply " <> argsName <> " to " <> scriptName) + $ compareApplied lang scriptName (args /\ argsName) + +compareApplied + :: forall (m :: Type -> Type) + . Monad m + => MonadError Error m + => (String -> m PlutusScript) + -> String + -> Tuple (Array PlutusData) String + -> m Unit +compareApplied lang scriptName (args /\ argsName) = do + script <- lang scriptName + applied <- liftEither $ left (error <<< show) $ applyArgs script args + appliedShouldBe <- lang (scriptName <> "-" <> argsName) + applied `shouldEqual` appliedShouldBe + +v1ScriptPaths :: Array String +v1ScriptPaths = + [ "always-fails" + , "include-datum" + , "one-shot-minting" + , "redeemer1-validator" + ] + +v2ScriptPaths :: Array String +v2ScriptPaths = + [ "always-succeeds-v2" + , "one-shot-minting-v2" + , "check-datum-is-inline" + ] + +params :: Array (Tuple (Array PlutusData) String) +params = + [ ([] /\ "no-args") + , ([ un ] /\ "unit") + , ( [ i 7 + , un + , List [ un, bytes ] + , longBytes + , Map [ (i 5 /\ i 7), (bytes /\ i 8) ] + , Constr (BigNum.fromInt 102) [ i 7, List [ un, bytes, longBytes ] ] + , Constr (BigNum.fromInt 5) + [ List [] + , List [ i 1 ] + , Map [] + , Map [ (i 1 /\ un), (i 2 /\ Constr (BigNum.fromInt 2) [ i 2 ]) ] + ] + ] /\ "big-arg" + ) + ] + +i :: Int -> PlutusData +i k = toData (fromInt k) + +un :: PlutusData +un = toData unit + +bytes :: PlutusData +bytes = Bytes $ hexToByteArrayUnsafe "4d5f" + +longBytes :: PlutusData +longBytes = Bytes $ hexToByteArrayUnsafe $ foldl (\x y -> x <> y) "" $ + replicate 65 "4d" + +v1 + :: forall (m :: Type -> Type) + . MonadError Error m + => Object String + -> String + -> m PlutusScript +v1 scripts name = lookupAux plutusScriptFromEnvelope scripts name + +v2 + :: forall (m :: Type -> Type) + . MonadError Error m + => Object String + -> String + -> m PlutusScript +v2 scripts name = lookupAux plutusScriptFromEnvelope scripts name + +lookupAux + :: forall (m :: Type -> Type) + . MonadError Error m + => (TextEnvelope -> Maybe PlutusScript) + -> Object String + -> String + -> m PlutusScript +lookupAux decodeScript scripts name = + maybe (throwError $ error $ "Can't find the script with name " <> name) pure + $ do + txt <- Object.lookup name scripts + envelope <- decodeTextEnvelope txt + decodeScript envelope diff --git a/test/Unit.purs b/test/Unit.purs index ad0a36d3d8..c7882764b2 100644 --- a/test/Unit.purs +++ b/test/Unit.purs @@ -11,6 +11,7 @@ import Effect (Effect) import Effect.Aff (Aff, cancelWith, effectCanceler, launchAff) import Effect.Class (liftEffect) import Mote.Monad (mapTest) +import Test.Ctl.ApplyArgs as ApplyArgs import Test.Ctl.Blockfrost.Aeson.Suite as Blockfrost.Aeson import Test.Ctl.Blockfrost.ProtocolParameters as Blockfrost.ProtocolParameters import Test.Ctl.CoinSelection as CoinSelection @@ -46,6 +47,7 @@ main = interruptOnSignal SIGINT =<< launchAff do testPlan :: TestPlanM (Aff Unit) Unit testPlan = do + ApplyArgs.suite Ipv6.suite NativeScript.suite Bip32.suite diff --git a/test/e2e-ci.env b/test/e2e-ci.env index e20d01d91a..54a8bc2e86 100644 --- a/test/e2e-ci.env +++ b/test/e2e-ci.env @@ -10,4 +10,5 @@ plutip:http://localhost:4008/?plutip-nami-mock:SendsToken plutip:http://localhost:4008/?plutip-nami-mock:MintsMultipleTokens plutip:http://localhost:4008/?plutip-nami-mock:Schnorr plutip:http://localhost:4008/?plutip-nami-mock:ECDSA +plutip:http://localhost:4008/?plutip-nami-mock:ApplyArgs " diff --git a/test/e2e.env b/test/e2e.env index 7473508716..8b0cc2d87f 100755 --- a/test/e2e.env +++ b/test/e2e.env @@ -10,6 +10,8 @@ plutip:http://localhost:4008/?plutip-nami-mock:AlwaysMints plutip:http://localhost:4008/?plutip-nami-mock:Pkh2Pkh plutip:http://localhost:4008/?plutip-nami-mock:SendsToken plutip:http://localhost:4008/?plutip-nami-mock:MintsMultipleTokens +# This test does not depend on wallets, we only check that bundling is correct +plutip:http://localhost:4008/?plutip-nami-mock:ApplyArgs # If you add plutip tests above, please also add them to ./e2e-ci.env nami:http://localhost:4008/?nami:Schnorr From dcc99373dac1f82a570f6714d426d93db2914fbb Mon Sep 17 00:00:00 2001 From: Marcus Fernandes Date: Tue, 2 Jul 2024 17:42:08 -0300 Subject: [PATCH 26/52] Refactor Cip30Mock to use external packages --- examples/SignData.purs | 2 +- packages.dhall | 48 +++++ spago-packages.nix | 39 +++- spago.dhall | 3 +- src/Internal/Contract/Wallet.purs | 16 +- src/Internal/Test/KeyDir.purs | 5 +- src/Internal/Wallet/Cip30Mock.js | 45 ----- src/Internal/Wallet/Cip30Mock.purs | 47 ++--- src/Internal/Wallet/Key.purs | 179 +---------------- templates/ctl-scaffold/packages.dhall | 49 ++++- templates/ctl-scaffold/spago-packages.nix | 41 +++- templates/ctl-scaffold/spago.dhall | 1 - test/Unit.purs | 2 +- test/Wallet/Bip32.purs | 16 +- test/Wallet/Cip30/SignData.js | 135 ------------- test/Wallet/Cip30/SignData.purs | 230 ---------------------- 16 files changed, 219 insertions(+), 639 deletions(-) delete mode 100644 src/Internal/Wallet/Cip30Mock.js delete mode 100644 test/Wallet/Cip30/SignData.js delete mode 100644 test/Wallet/Cip30/SignData.purs diff --git a/examples/SignData.purs b/examples/SignData.purs index 5ac619d014..36804b2f2a 100644 --- a/examples/SignData.purs +++ b/examples/SignData.purs @@ -3,6 +3,7 @@ module Ctl.Examples.SignData (main, example, contract) where import Contract.Prelude import Cardano.Types (RawBytes) +import Cardano.Wallet.Cip30.SignData (checkCip30SignDataResponse) import Contract.Address (Address) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') @@ -12,7 +13,6 @@ import Data.Array (head) as Array import Data.ByteArray (byteArrayFromAscii) import Data.Maybe (fromJust) import Partial.Unsafe (unsafePartial) -import Test.Ctl.Wallet.Cip30.SignData (checkCip30SignDataResponse) main :: Effect Unit main = example testnetNamiConfig diff --git a/packages.dhall b/packages.dhall index 081878fc47..ab0b497fd7 100644 --- a/packages.dhall +++ b/packages.dhall @@ -318,6 +318,54 @@ let additions = , repo = "https://github.com/mlabs-haskell/purescript-plutus-types" , version = "v1.0.1" } + , cip30-mock = + { dependencies = + [ "aff-promise", "console", "effect", "functions", "prelude" ] + , repo = "https://github.com/mlabs-haskell/purescript-cip30-mock" + , version = "v1.0.0" + } + , cardano-collateral-select = + { dependencies = + [ "arrays" + , "cardano-types" + , "console" + , "effect" + , "exceptions" + , "foldable-traversable" + , "lists" + , "maybe" + , "newtype" + , "ordered-collections" + , "partial" + , "prelude" + , "tuples" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-collateral-select" + , version = "v1.0.0" + } + , cardano-key-wallet = + { dependencies = + [ "aeson" + , "aff" + , "arrays" + , "cardano-collateral-select" + , "cardano-message-signing" + , "cardano-types" + , "console" + , "effect" + , "either" + , "foldable-traversable" + , "maybe" + , "newtype" + , "prelude" + , "profunctor-lenses" + , "typelevel-prelude" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-key-wallet" + , version = "v1.0.0" + } , uplc-apply-args = { dependencies = [ "aff" diff --git a/spago-packages.nix b/spago-packages.nix index 504b0f7fe4..0c24697833 100644 --- a/spago-packages.nix +++ b/spago-packages.nix @@ -209,6 +209,18 @@ let installPhase = "ln -s $src $out"; }; + "cardano-collateral-select" = pkgs.stdenv.mkDerivation { + name = "cardano-collateral-select"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-collateral-select"; + rev = "296fe978a292f36d9fd2c18a2d173772301e71b9"; + sha256 = "09mcdjndalc9a91l0kx9s0p3bh5j58lji230b142yvgk8qmmayi9"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "cardano-hd-wallet" = pkgs.stdenv.mkDerivation { name = "cardano-hd-wallet"; version = "v1.0.0"; @@ -221,6 +233,18 @@ let installPhase = "ln -s $src $out"; }; + "cardano-key-wallet" = pkgs.stdenv.mkDerivation { + name = "cardano-key-wallet"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-key-wallet"; + rev = "f107d3dce0a0f1f866a4682783376ea9f476fd7d"; + sha256 = "0jxbzdjfvxvrf2nmay493x004d0y5jmnfqj06064nfihg5x0w2r8"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "cardano-message-signing" = pkgs.stdenv.mkDerivation { name = "cardano-message-signing"; version = "v1.0.0"; @@ -305,6 +329,18 @@ let installPhase = "ln -s $src $out"; }; + "cip30-mock" = pkgs.stdenv.mkDerivation { + name = "cip30-mock"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cip30-mock"; + rev = "7b4b7b2800f6d0ebd25554de63141cbd8c1e14a0"; + sha256 = "1b412s7p144h98csvy5w9z6vjhlpya9mqkxm2k8nxfdhq2znwfih"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "cip30-typesafe" = pkgs.stdenv.mkDerivation { name = "cip30-typesafe"; version = "d72e51fbc0255eb3246c9132d295de7f65e16a99"; @@ -1569,10 +1605,9 @@ let name = "uplc-apply-args"; version = "v1.0.0"; src = pkgs.fetchgit { - url = "https://github.com/mlabs-haskell/purescript-uplc-apply-args.git"; + url = "https://github.com/mlabs-haskell/purescript-uplc-apply-args"; rev = "aa528d5310cbfbd01b4d94557f404d95cfb6bb3c"; sha256 = "1r064ca2m16hkbcswrvlng032ax1ygbpr2gxrlaqmjlf2gnin280"; - }; phases = "installPhase"; installPhase = "ln -s $src $out"; diff --git a/spago.dhall b/spago.dhall index 957f2487e0..81cabcc47b 100644 --- a/spago.dhall +++ b/spago.dhall @@ -18,13 +18,14 @@ You can edit this file as you like. , "bignumber" , "bytearrays" , "cardano-hd-wallet" - , "cardano-message-signing" , "uplc-apply-args" , "cardano-plutus-data-schema" , "cardano-serialization-lib" + , "cardano-key-wallet" , "cardano-types" , "checked-exceptions" , "cip30" + , "cip30-mock" , "cip30-typesafe" , "console" , "control" diff --git a/src/Internal/Contract/Wallet.purs b/src/Internal/Contract/Wallet.purs index 08a351965b..851939cfbe 100644 --- a/src/Internal/Contract/Wallet.purs +++ b/src/Internal/Contract/Wallet.purs @@ -59,12 +59,16 @@ getChangeAddress = withWallet do actionBasedOnWallet _.getChangeAddress \kw -> do networkId <- asks _.networkId - pure $ (unwrap kw).address networkId + addr <- liftAff $ (unwrap kw).address networkId + pure addr getRewardAddresses :: Contract (Array Address) getRewardAddresses = withWallet $ actionBasedOnWallet _.getRewardAddresses - \kw -> asks _.networkId <#> Array.singleton <<< (unwrap kw).address + \kw -> do + networkId <- asks _.networkId + addr <- liftAff $ (unwrap kw).address networkId + pure $ Array.singleton addr -- | Get all `Address`es of the browser wallet. getWalletAddresses :: Contract (Array Address) @@ -72,7 +76,8 @@ getWalletAddresses = withWallet do actionBasedOnWallet _.getUsedAddresses ( \kw -> do networkId <- asks _.networkId - pure $ Array.singleton $ (unwrap kw).address networkId + addr <- liftAff $ (unwrap kw).address networkId + pure $ Array.singleton $ addr ) signData :: Address -> RawBytes -> Contract DataSignature @@ -127,13 +132,14 @@ getWalletCollateral = do actionBasedOnWallet _.getCollateral \kw -> do queryHandle <- getQueryHandle networkId <- asks _.networkId - let addr = (unwrap kw).address networkId + addr <- liftAff $ (unwrap kw).address networkId utxos <- (liftAff $ queryHandle.utxosAt addr) <#> hush >>> fromMaybe Map.empty >>= filterLockedUtxos - pure $ (unwrap kw).selectCollateral coinsPerUtxoByte + mColl <- liftAff $ (unwrap kw).selectCollateral coinsPerUtxoByte (UInt.toInt maxCollateralInputs) utxos + pure mColl let {- This is a workaround for the case where Eternl wallet, in addition to designated collateral UTxO, returns all UTxO's with diff --git a/src/Internal/Test/KeyDir.purs b/src/Internal/Test/KeyDir.purs index 12495fa548..366c40d483 100644 --- a/src/Internal/Test/KeyDir.purs +++ b/src/Internal/Test/KeyDir.purs @@ -235,8 +235,8 @@ markAsInactive :: FilePath -> Array KeyWallet -> Contract Unit markAsInactive backup wallets = do flip parTraverse_ wallets \wallet -> do networkId <- asks _.networkId + address <- liftAff $ Address.toBech32 <$> (unwrap wallet).address networkId let - address = Address.toBech32 $ (unwrap wallet).address networkId inactiveFlagFile = Path.concat [ backup, address, "inactive" ] liftAff $ writeTextFile UTF8 inactiveFlagFile $ "This address was marked as inactive. " @@ -285,8 +285,9 @@ backupWallets :: FilePath -> ContractEnv -> Array KeyWallet -> Aff Unit backupWallets backup env walletsArray = liftAff $ flip parTraverse_ walletsArray \wallet -> do + address <- liftAff $ Address.toBech32 <$> (unwrap wallet).address + env.networkId let - address = Address.toBech32 $ (unwrap wallet).address env.networkId payment = keyWalletPrivatePaymentKey wallet mbStake = keyWalletPrivateStakeKey wallet folder = Path.concat [ backup, address ] diff --git a/src/Internal/Wallet/Cip30Mock.js b/src/Internal/Wallet/Cip30Mock.js deleted file mode 100644 index 610baa03b4..0000000000 --- a/src/Internal/Wallet/Cip30Mock.js +++ /dev/null @@ -1,45 +0,0 @@ -/* eslint-disable no-global-assign */ - -export function injectCip30Mock(walletName) { - return mock => () => { - let window_ = typeof window != "undefined" ? window : (global.window = {}); - - if ( - typeof window_ == "object" && - typeof window_.cardano == "object" && - typeof window_.cardano[walletName] != "undefined" - ) { - throw ( - "injectCip30Mock: refusing to overwrite existing wallet (" + - walletName + - ")" - ); - } - - window_.cardano = {}; - window_.cardano[walletName] = { - enable: () => { - return new Promise((resolve, _reject) => - resolve({ - getNetworkId: mock.getNetworkId, - getUtxos: mock.getUtxos, - experimental: { - getCollateral: mock.getCollateral - }, - getBalance: mock.getBalance, - getUsedAddresses: mock.getUsedAddresses, - getUnusedAddresses: mock.getUnusedAddresses, - getChangeAddress: mock.getChangeAddress, - getRewardAddresses: mock.getRewardAddresses, - signTx: mock.signTx, - signData: mock.signData - }) - ); - } - }; - - return () => { - delete window_.cardano[walletName]; - }; - }; -} diff --git a/src/Internal/Wallet/Cip30Mock.purs b/src/Internal/Wallet/Cip30Mock.purs index a1a6b87c78..3a0d4079e5 100644 --- a/src/Internal/Wallet/Cip30Mock.purs +++ b/src/Internal/Wallet/Cip30Mock.purs @@ -22,11 +22,12 @@ import Cardano.Types.NetworkId (NetworkId(MainnetId, TestnetId)) import Cardano.Types.PrivateKey as PrivateKey import Cardano.Types.PublicKey as PublicKey import Cardano.Types.TransactionUnspentOutput as TransactionUnspentOutput +import Cardano.Wallet.Cip30Mock (Cip30Mock, injectCip30Mock) import Contract.Monad (Contract) import Control.Monad.Error.Class (liftMaybe, try) import Control.Monad.Reader (ask) import Control.Monad.Reader.Class (local) -import Control.Promise (Promise, fromAff) +import Control.Promise (fromAff) import Ctl.Internal.Contract.Monad (getQueryHandle) import Ctl.Internal.Helpers (liftEither) import Ctl.Internal.Wallet @@ -51,12 +52,11 @@ import Data.Array as Array import Data.ByteArray (byteArrayToHex, hexToByteArray) import Data.Either (hush) import Data.Foldable (fold, foldMap) -import Data.Function.Uncurried (Fn2, mkFn2) +import Data.Function.Uncurried (mkFn2) import Data.Map as Map import Data.Maybe (Maybe(Just), maybe) import Data.Newtype (unwrap, wrap) import Data.UInt as UInt -import Effect (Effect) import Effect.Aff (Aff) import Effect.Aff.Class (liftAff) import Effect.Class (liftEffect) @@ -118,24 +118,6 @@ withCip30Mock (KeyWallet keyWallet) mock contract = do MockNuFi -> "nufi" MockGenericCip30 name -> name -type Cip30Mock = - { getNetworkId :: Effect (Promise Int) - -- we ignore both the amount parameter and pagination: - , getUtxos :: Effect (Promise (Array String)) - -- we ignore the amount parameter: - , getCollateral :: Effect (Promise (Array String)) - , getBalance :: Effect (Promise String) - -- we ignore pagination parameter: - , getUsedAddresses :: Effect (Promise (Array String)) - , getUnusedAddresses :: Effect (Promise (Array String)) - , getChangeAddress :: Effect (Promise String) - , getRewardAddresses :: Effect (Promise (Array String)) - -- we ignore the 'isPartial' parameter - , signTx :: String -> Promise String - , signData :: - Fn2 String String (Promise { key :: String, signature :: String }) - } - mkCip30Mock :: PrivatePaymentKey -> Maybe PrivateStakeKey -> Contract Cip30Mock mkCip30Mock pKey mSKey = do @@ -148,22 +130,22 @@ mkCip30Mock pKey mSKey = do coinsPerUtxoByte = pparams.coinsPerUtxoByte maxCollateralInputs = UInt.toInt $ pparams.maxCollateralInputs - mbCollateral = fold $ - (unwrap keyWallet).selectCollateral coinsPerUtxoByte - maxCollateralInputs - utxos - pure mbCollateral + coll <- liftAff $ + (unwrap keyWallet).selectCollateral coinsPerUtxoByte + maxCollateralInputs + utxos + pure $ fold coll ownUtxos = do - let ownAddress = (unwrap keyWallet).address env.networkId + ownAddress <- liftAff $ (unwrap keyWallet).address env.networkId liftMaybe (error "No UTxOs at address") <<< hush =<< do queryHandle.utxosAt ownAddress keyWallet = privateKeysToKeyWallet pKey mSKey - addressHex = - byteArrayToHex $ unwrap $ encodeCbor - ((unwrap keyWallet).address env.networkId :: Address) - + addressHex <- liftAff $ + (byteArrayToHex <<< unwrap <<< encodeCbor) <$> + ((unwrap keyWallet).address env.networkId :: Aff Address) + let mbRewardAddressHex = mSKey <#> \stakeKey -> let stakePubKey = PrivateKey.toPublicKey (unwrap stakeKey) @@ -223,6 +205,3 @@ mkCip30Mock pKey mSKey = do , signature: byteArrayToHex $ unwrap signature } } - --- returns an action that removes the mock. -foreign import injectCip30Mock :: String -> Cip30Mock -> Effect (Effect Unit) diff --git a/src/Internal/Wallet/Key.purs b/src/Internal/Wallet/Key.purs index be85f52188..add12d9ccd 100644 --- a/src/Internal/Wallet/Key.purs +++ b/src/Internal/Wallet/Key.purs @@ -1,178 +1,13 @@ module Ctl.Internal.Wallet.Key + ( module KeyWallet + ) where + +import Cardano.Wallet.Key ( KeyWallet(KeyWallet) , PrivatePaymentKey(PrivatePaymentKey) , PrivateStakeKey(PrivateStakeKey) - , privateKeysToAddress - , privateKeysToKeyWallet , keyWalletPrivatePaymentKey , keyWalletPrivateStakeKey - ) where - -import Prelude - -import Aeson - ( class DecodeAeson - , class EncodeAeson - , JsonDecodeError(TypeMismatch) - , decodeAeson - , encodeAeson - ) -import Cardano.MessageSigning (DataSignature) -import Cardano.MessageSigning (signData) as MessageSigning -import Cardano.Types.Address (Address(BaseAddress, EnterpriseAddress)) -import Cardano.Types.Coin (Coin) -import Cardano.Types.Credential (Credential(PubKeyHashCredential)) -import Cardano.Types.NetworkId (NetworkId) -import Cardano.Types.PaymentCredential (PaymentCredential(PaymentCredential)) -import Cardano.Types.PrivateKey (PrivateKey(PrivateKey)) -import Cardano.Types.PrivateKey as PrivateKey -import Cardano.Types.PublicKey as PublicKey -import Cardano.Types.RawBytes (RawBytes) -import Cardano.Types.StakeCredential (StakeCredential(StakeCredential)) -import Cardano.Types.Transaction (Transaction, hash) -import Cardano.Types.TransactionUnspentOutput (TransactionUnspentOutput) -import Cardano.Types.TransactionWitnessSet (TransactionWitnessSet) -import Cardano.Types.UtxoMap (UtxoMap) -import Contract.Prelude (class Newtype) -import Ctl.Internal.BalanceTx.Collateral.Select as Collateral -import Ctl.Internal.Lens (_vkeys) -import Data.Array (fromFoldable) -import Data.Either (note) -import Data.Foldable (fold) -import Data.Lens (set) -import Data.Maybe (Maybe(Just, Nothing)) -import Data.Newtype (unwrap, wrap) -import Effect.Aff (Aff) -import Effect.Class (liftEffect) - -------------------------------------------------------------------------------- --- Key backend -------------------------------------------------------------------------------- - --- | A wrapper over `PrivateKey` that provides an interface for CTL -newtype KeyWallet = KeyWallet - { address :: NetworkId -> Address - , selectCollateral :: - Coin - -> Int - -> UtxoMap - -> Maybe (Array TransactionUnspentOutput) - , signTx :: Transaction -> Aff TransactionWitnessSet - , signData :: NetworkId -> RawBytes -> Aff DataSignature - , paymentKey :: PrivatePaymentKey - , stakeKey :: Maybe PrivateStakeKey - } - -derive instance Newtype KeyWallet _ - -newtype PrivatePaymentKey = PrivatePaymentKey PrivateKey - -derive instance Newtype PrivatePaymentKey _ - -instance Show PrivatePaymentKey where - show _ = "(PrivatePaymentKey )" - -instance EncodeAeson PrivatePaymentKey where - encodeAeson (PrivatePaymentKey pk) = encodeAeson - (PrivateKey.toBech32 pk) - -instance DecodeAeson PrivatePaymentKey where - decodeAeson aeson = - decodeAeson aeson >>= - note (TypeMismatch "PrivateKey") - <<< map PrivatePaymentKey - <<< PrivateKey.fromBech32 - -newtype PrivateStakeKey = PrivateStakeKey PrivateKey - -derive instance Newtype PrivateStakeKey _ - -instance Show PrivateStakeKey where - show _ = "(PrivateStakeKey )" - -instance EncodeAeson PrivateStakeKey where - encodeAeson (PrivateStakeKey pk) = encodeAeson - (PrivateKey.toBech32 pk) - -instance DecodeAeson PrivateStakeKey where - decodeAeson aeson = - decodeAeson aeson >>= - note (TypeMismatch "PrivateKey") - <<< map PrivateStakeKey - <<< PrivateKey.fromBech32 - -keyWalletPrivatePaymentKey :: KeyWallet -> PrivatePaymentKey -keyWalletPrivatePaymentKey = unwrap >>> _.paymentKey - -keyWalletPrivateStakeKey :: KeyWallet -> Maybe PrivateStakeKey -keyWalletPrivateStakeKey = unwrap >>> _.stakeKey - -privateKeysToAddress - :: PrivatePaymentKey -> Maybe PrivateStakeKey -> NetworkId -> Address -privateKeysToAddress payKey mbStakeKey networkId = do - let pubPayKey = PrivateKey.toPublicKey (unwrap payKey) - case mbStakeKey of - Just stakeKey -> - let - pubStakeKey = PrivateKey.toPublicKey (unwrap stakeKey) - in - BaseAddress - { networkId - , paymentCredential: - ( PaymentCredential $ PubKeyHashCredential $ PublicKey.hash $ - pubPayKey - ) - , stakeCredential: - ( StakeCredential $ PubKeyHashCredential $ PublicKey.hash $ - pubStakeKey - ) - } - - Nothing -> pubPayKey # PublicKey.hash - >>> PubKeyHashCredential - >>> wrap - >>> { networkId, paymentCredential: _ } - >>> EnterpriseAddress - -privateKeysToKeyWallet - :: PrivatePaymentKey -> Maybe PrivateStakeKey -> KeyWallet -privateKeysToKeyWallet payKey mbStakeKey = - KeyWallet - { address - , selectCollateral - , signTx - , signData - , paymentKey: payKey - , stakeKey: mbStakeKey - } - where - address :: NetworkId -> Address - address = privateKeysToAddress payKey mbStakeKey - - selectCollateral - :: Coin - -> Int - -> UtxoMap - -> Maybe (Array TransactionUnspentOutput) - selectCollateral coinsPerUtxoByte maxCollateralInputs utxos = fromFoldable - <$> Collateral.selectCollateral coinsPerUtxoByte maxCollateralInputs utxos - - signTx :: Transaction -> Aff TransactionWitnessSet - signTx tx = liftEffect do - let - txHash = hash tx - payWitness = PrivateKey.makeVkeyWitness txHash (unwrap payKey) - mbStakeWitness = - mbStakeKey <#> \stakeKey -> - PrivateKey.makeVkeyWitness txHash (unwrap stakeKey) - let - witnessSet' = set _vkeys - ([ payWitness ] <> fold (pure <$> mbStakeWitness)) - mempty - pure witnessSet' - - signData :: NetworkId -> RawBytes -> Aff DataSignature - signData networkId payload = do - liftEffect $ MessageSigning.signData (unwrap payKey) - (address networkId) - payload + , privateKeysToAddress + , privateKeysToKeyWallet + ) as KeyWallet diff --git a/templates/ctl-scaffold/packages.dhall b/templates/ctl-scaffold/packages.dhall index 8be52f038c..669048fce7 100644 --- a/templates/ctl-scaffold/packages.dhall +++ b/templates/ctl-scaffold/packages.dhall @@ -318,6 +318,54 @@ let additions = , repo = "https://github.com/mlabs-haskell/purescript-plutus-types" , version = "v1.0.1" } + , cip30-mock = + { dependencies = + [ "aff-promise", "console", "effect", "functions", "prelude" ] + , repo = "https://github.com/mlabs-haskell/purescript-cip30-mock" + , version = "v1.0.0" + } + , cardano-collateral-select = + { dependencies = + [ "arrays" + , "cardano-types" + , "console" + , "effect" + , "exceptions" + , "foldable-traversable" + , "lists" + , "maybe" + , "newtype" + , "ordered-collections" + , "partial" + , "prelude" + , "tuples" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-collateral-select" + , version = "v1.0.0" + } + , cardano-key-wallet = + { dependencies = + [ "aeson" + , "aff" + , "arrays" + , "cardano-collateral-select" + , "cardano-message-signing" + , "cardano-types" + , "console" + , "effect" + , "either" + , "foldable-traversable" + , "maybe" + , "newtype" + , "prelude" + , "profunctor-lenses" + , "typelevel-prelude" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-key-wallet" + , version = "v1.0.0" + } , uplc-apply-args = { dependencies = [ "aff" @@ -450,7 +498,6 @@ let additions = , "bignumber" , "bytearrays" , "cardano-hd-wallet" - , "cardano-message-signing" , "cardano-plutus-data-schema" , "cardano-serialization-lib" , "cardano-types" diff --git a/templates/ctl-scaffold/spago-packages.nix b/templates/ctl-scaffold/spago-packages.nix index f8db4dae6d..f2c859bbfc 100644 --- a/templates/ctl-scaffold/spago-packages.nix +++ b/templates/ctl-scaffold/spago-packages.nix @@ -209,6 +209,18 @@ let installPhase = "ln -s $src $out"; }; + "cardano-collateral-select" = pkgs.stdenv.mkDerivation { + name = "cardano-collateral-select"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-collateral-select"; + rev = "296fe978a292f36d9fd2c18a2d173772301e71b9"; + sha256 = "09mcdjndalc9a91l0kx9s0p3bh5j58lji230b142yvgk8qmmayi9"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "cardano-hd-wallet" = pkgs.stdenv.mkDerivation { name = "cardano-hd-wallet"; version = "v1.0.0"; @@ -221,6 +233,18 @@ let installPhase = "ln -s $src $out"; }; + "cardano-key-wallet" = pkgs.stdenv.mkDerivation { + name = "cardano-key-wallet"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-key-wallet"; + rev = "f107d3dce0a0f1f866a4682783376ea9f476fd7d"; + sha256 = "0jxbzdjfvxvrf2nmay493x004d0y5jmnfqj06064nfihg5x0w2r8"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "cardano-message-signing" = pkgs.stdenv.mkDerivation { name = "cardano-message-signing"; version = "v1.0.0"; @@ -257,7 +281,7 @@ let installPhase = "ln -s $src $out"; }; - "cardano-transaction-lib" = pkgs.stdenv.mkDerivation { + "cardano-transaction-lib" = pkgs.stdenv.mkDerivation { name = "cardano-transaction-lib"; version = "423e27b3f56b1a66db8d3126c22cea9bda7e50da"; src = pkgs.fetchgit { @@ -317,6 +341,18 @@ let installPhase = "ln -s $src $out"; }; + "cip30-mock" = pkgs.stdenv.mkDerivation { + name = "cip30-mock"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cip30-mock"; + rev = "7b4b7b2800f6d0ebd25554de63141cbd8c1e14a0"; + sha256 = "1b412s7p144h98csvy5w9z6vjhlpya9mqkxm2k8nxfdhq2znwfih"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "cip30-typesafe" = pkgs.stdenv.mkDerivation { name = "cip30-typesafe"; version = "d72e51fbc0255eb3246c9132d295de7f65e16a99"; @@ -1581,10 +1617,9 @@ let name = "uplc-apply-args"; version = "v1.0.0"; src = pkgs.fetchgit { - url = "https://github.com/mlabs-haskell/purescript-uplc-apply-args.git"; + url = "https://github.com/mlabs-haskell/purescript-uplc-apply-args"; rev = "aa528d5310cbfbd01b4d94557f404d95cfb6bb3c"; sha256 = "1r064ca2m16hkbcswrvlng032ax1ygbpr2gxrlaqmjlf2gnin280"; - }; phases = "installPhase"; installPhase = "ln -s $src $out"; diff --git a/templates/ctl-scaffold/spago.dhall b/templates/ctl-scaffold/spago.dhall index 40de0f604f..b25547240d 100644 --- a/templates/ctl-scaffold/spago.dhall +++ b/templates/ctl-scaffold/spago.dhall @@ -7,7 +7,6 @@ You can edit this file as you like. [ "aff" , "bytearrays" , "cardano-hd-wallet" - , "cardano-message-signing" , "cardano-plutus-data-schema" , "cardano-serialization-lib" , "cardano-transaction-lib" diff --git a/test/Unit.purs b/test/Unit.purs index c7882764b2..b2802bd5fa 100644 --- a/test/Unit.purs +++ b/test/Unit.purs @@ -2,6 +2,7 @@ module Test.Ctl.Unit (main, testPlan) where import Prelude +import Cardano.Wallet.Cip30.SignData as Cip30SignData import Contract.Test.Mote (TestPlanM, interpretWithConfig) import Contract.Test.Utils (exitCode, interruptOnSignal) import Data.Maybe (Maybe(Just)) @@ -34,7 +35,6 @@ import Test.Ctl.Types.TokenName as Types.TokenName import Test.Ctl.Types.Transaction as Types.Transaction import Test.Ctl.UsedTxOuts as UsedTxOuts import Test.Ctl.Wallet.Bip32 as Bip32 -import Test.Ctl.Wallet.Cip30.SignData as Cip30SignData import Test.Spec.Runner (defaultConfig) -- Run with `spago test --main Test.Ctl.Unit` diff --git a/test/Wallet/Bip32.purs b/test/Wallet/Bip32.purs index 7638934155..06f712ab7f 100644 --- a/test/Wallet/Bip32.purs +++ b/test/Wallet/Bip32.purs @@ -10,7 +10,7 @@ import Contract.Wallet.Key ( StakeKeyPresence(WithStakeKey) , mkKeyWalletFromMnemonic ) -import Ctl.Internal.Wallet.Key (KeyWallet(KeyWallet)) +import Ctl.Internal.Wallet.Key (KeyWallet) import Data.Lens (_Left, preview) import Data.UInt as UInt import Effect.Aff (Aff) @@ -31,15 +31,19 @@ suite = do <> ")" ) do - Address.fromBech32 addressStr `shouldEqual` - hush - ( mkKeyWalletFromMnemonic phrase1 + addr <- liftAff $ do + case + ( hush $ mkKeyWalletFromMnemonic phrase1 { accountIndex: UInt.fromInt accountIndex , addressIndex: UInt.fromInt addressIndex } - WithStakeKey <#> - \(KeyWallet wallet) -> wallet.address MainnetId + WithStakeKey ) + of + Nothing -> pure Nothing + Just (wlt :: KeyWallet) -> do + Just <$> (unwrap wlt).address MainnetId + Address.fromBech32 addressStr `shouldEqual` addr group "Invalid mnemonics" do test "handles errors for invalid phrases" do blush (mkKeyWalletFromMnemonic invalidPhrase zero WithStakeKey) diff --git a/test/Wallet/Cip30/SignData.js b/test/Wallet/Cip30/SignData.js deleted file mode 100644 index 353135d766..0000000000 --- a/test/Wallet/Cip30/SignData.js +++ /dev/null @@ -1,135 +0,0 @@ -import * as csl from "@mlabs-haskell/cardano-serialization-lib-gc"; -import * as lib from "@mlabs-haskell/cardano-message-signing"; - -function opt_chain(maybe, obj) { - const isNothing = x => x === null || x === undefined; - let result = obj; - for (let i = 2; i < arguments.length; i++) { - if (isNothing(result)) { - return maybe.nothing; - } else { - result = result[arguments[i]](); - } - } - return isNothing(result) ? maybe.nothing : maybe.just(result); -} - -const fromBytes = name => bytes => () => { - return lib[name].from_bytes(bytes); -}; - -// ----------------------------------------------------------------------------- -// PublicKey -// ----------------------------------------------------------------------------- - -// verifySignature :: COSESign1 -> PublicKey -> CborBytes -> Effect Boolean -export function verifySignature(coseSign1) { - return publicKey => sigStructBytes => () => { - const signature = csl.Ed25519Signature.from_bytes(coseSign1.signature()); - return publicKey.verify(sigStructBytes, signature); - }; -} - -// ----------------------------------------------------------------------------- -// COSESign1 -// ----------------------------------------------------------------------------- - -// _fromBytesCoseSign1 :: CborBytes -> Effect COSESign1 -export const fromBytesCoseSign1 = fromBytes("COSESign1"); - -// getSignedData :: COSESign1 -> Effect CborBytes -export function getSignedData(coseSign1) { - return () => { - return coseSign1.signed_data(null, null).to_bytes(); - }; -} - -// getCoseSign1ProtectedHeaders :: COSESign1 -> HeaderMap -const getCoseSign1ProtectedHeaders = coseSign1 => { - return coseSign1.headers().protected().deserialized_headers(); -}; - -// getCoseSign1ProtectedHeaderAlg :: MaybeFfiHelper -> COSESign1 -> Maybe Int -export function _getCoseSign1ProtectedHeaderAlg(maybe) { - return coseSign1 => { - const protectedHeaders = getCoseSign1ProtectedHeaders(coseSign1); - return opt_chain( - maybe, - protectedHeaders, - "algorithm_id", - "as_int", - "as_i32" - ); - }; -} - -// _getCoseSign1ProtectedHeaderAddress -// :: MaybeFfiHelper -> COSESign1 -> Maybe CborBytes -export function _getCoseSign1ProtectedHeaderAddress(maybe) { - return coseSign1 => { - const protectedHeaders = getCoseSign1ProtectedHeaders(coseSign1); - const cborValue = protectedHeaders.header(lib.Label.new_text("address")); - return opt_chain(maybe, cborValue, "as_bytes"); - }; -} - -// _getCoseSign1ProtectedHeaderKid -// :: MaybeFfiHelper -> COSESign1 -> Maybe RawBytes -export function _getCoseSign1ProtectedHeaderKid(maybe) { - return coseSign1 => { - const protectedHeaders = getCoseSign1ProtectedHeaders(coseSign1); - return opt_chain(maybe, protectedHeaders, "key_id"); - }; -} - -// ----------------------------------------------------------------------------- -// COSEKey -// ----------------------------------------------------------------------------- - -// _fromBytesCoseKey :: CborBytes -> Effect COSEKey -export const fromBytesCoseKey = fromBytes("COSEKey"); - -// _getCoseKeyHeaderKty :: MaybeFfiHelper -> COSEKey -> Maybe Int -export function _getCoseKeyHeaderKty(maybe) { - return coseKey => { - return opt_chain(maybe, coseKey.key_type(), "as_int", "as_i32"); - }; -} - -// _getCoseKeyHeaderAlg :: MaybeFfiHelper -> COSEKey -> Maybe Int -export function _getCoseKeyHeaderAlg(maybe) { - return coseKey => { - return opt_chain(maybe, coseKey, "algorithm_id", "as_int", "as_i32"); - }; -} - -// _getCoseKeyHeaderCrv :: MaybeFfiHelper -> COSEKey -> Maybe Int -export function _getCoseKeyHeaderCrv(maybe) { - return coseKey => { - const cborValue = coseKey.header( - lib.Label.new_int( - lib.Int.new_negative(lib.BigNum.from_str("1")) // crv (-1) - ) - ); - return opt_chain(maybe, cborValue, "as_int", "as_i32"); - }; -} - -// _getCoseKeyHeaderX :: MaybeFfiHelper -> COSEKey -> Maybe RawBytes -export function _getCoseKeyHeaderX(maybe) { - return coseKey => { - const cborValue = coseKey.header( - lib.Label.new_int( - lib.Int.new_negative(lib.BigNum.from_str("2")) // x (-2) - ) - ); - return opt_chain(maybe, cborValue, "as_bytes"); - }; -} - -// _getCoseKeyHeaderKid :: MaybeFfiHelper -> COSESign1 -> Maybe RawBytes -export function _getCoseKeyHeaderKid(maybe) { - return coseKey => { - return opt_chain(maybe, coseKey, "key_id"); - }; -} diff --git a/test/Wallet/Cip30/SignData.purs b/test/Wallet/Cip30/SignData.purs deleted file mode 100644 index 0d9e5abe0b..0000000000 --- a/test/Wallet/Cip30/SignData.purs +++ /dev/null @@ -1,230 +0,0 @@ -module Test.Ctl.Wallet.Cip30.SignData - ( suite - , COSEKey - , COSESign1 - , checkCip30SignDataResponse - ) where - -import Prelude - -import Cardano.AsCbor (encodeCbor) -import Cardano.MessageSigning (signData) -import Cardano.Types - ( Address - , CborBytes - , PrivateKey(PrivateKey) - , PublicKey - , RawBytes - ) -import Cardano.Types.NetworkId (NetworkId(MainnetId)) -import Cardano.Types.NetworkId as NetworkId -import Cardano.Types.PrivateKey as PrivateKey -import Cardano.Types.PublicKey as PublicKey -import Contract.Keys (publicKeyFromBytes) -import Ctl.Internal.FfiHelpers (MaybeFfiHelper, maybeFfiHelper) -import Ctl.Internal.Wallet.Cip30 (DataSignature) -import Ctl.Internal.Wallet.Key - ( PrivatePaymentKey - , PrivateStakeKey - , privateKeysToAddress - ) -import Data.ByteArray (byteArrayFromIntArrayUnsafe) -import Data.Maybe (Maybe(Just), fromJust, fromMaybe) -import Data.Newtype (class Newtype, unwrap, wrap) -import Data.Traversable (traverse_) -import Effect (Effect) -import Effect.Aff (Aff) -import Effect.Class (liftEffect) -import Mote (group, test) -import Mote.TestPlanM (TestPlanM) -import Partial.Unsafe (unsafePartial) -import Test.Ctl.Utils (assertTrue, errMaybe) -import Test.QuickCheck.Arbitrary (class Arbitrary, arbitrary) -import Test.QuickCheck.Gen (Gen, chooseInt, randomSample, vectorOf) - -suite :: TestPlanM (Aff Unit) Unit -suite = - group "signData (CIP-30)" do - test "generates a valid signature and key for a given payload" do - traverse_ testCip30SignData =<< liftEffect (randomSample arbitrary) - --------------------------------------------------------------------------------- --- Tests --------------------------------------------------------------------------------- - -type TestInput = - { privateKey :: ArbitraryPrivatePaymentKey - , privateStakeKey :: Maybe ArbitraryPrivateStakeKey - , payload :: RawBytes - , networkId :: ArbitraryNetworkId - } - -type DeserializedDataSignature = - { coseKey :: COSEKey - , coseSign1 :: COSESign1 - } - -testCip30SignData :: TestInput -> Aff Unit -testCip30SignData { privateKey, privateStakeKey, payload, networkId } = do - let - address = privateKeysToAddress (unwrap privateKey) - (unwrap <$> privateStakeKey) - (unwrap networkId) - - dataSignature <- liftEffect $ signData (privatePaymentKey) address - payload - { coseKey } <- checkCip30SignDataResponse address dataSignature - - assertTrue "COSE_Key's x (-2) header must be set to public key bytes" - (getCoseKeyHeaderX coseKey == Just (PublicKey.toRawBytes publicPaymentKey)) - where - privatePaymentKey :: PrivateKey - privatePaymentKey = unwrap $ unwrap privateKey - - publicPaymentKey :: PublicKey - publicPaymentKey = PrivateKey.toPublicKey privatePaymentKey - -checkCip30SignDataResponse - :: Address -> DataSignature -> Aff DeserializedDataSignature -checkCip30SignDataResponse address { key, signature } = do - coseSign1 <- liftEffect $ fromBytesCoseSign1 signature - coseKey <- liftEffect $ fromBytesCoseKey key - - checkCoseSign1ProtectedHeaders coseSign1 - checkCoseKeyHeaders coseKey - checkKidHeaders coseSign1 coseKey - liftEffect $ checkVerification coseSign1 coseKey - pure { coseKey, coseSign1 } - where - checkCoseSign1ProtectedHeaders :: COSESign1 -> Aff Unit - checkCoseSign1ProtectedHeaders coseSign1 = do - assertTrue "COSE_Sign1's alg (1) header must be set to EdDSA (-8)" - (getCoseSign1ProtectedHeaderAlg coseSign1 == Just (-8)) - - assertTrue "COSE_Sign1's \"address\" header must be set to address bytes" - ( getCoseSign1ProtectedHeaderAddress coseSign1 - == Just (encodeCbor address) - ) - - checkCoseKeyHeaders :: COSEKey -> Aff Unit - checkCoseKeyHeaders coseKey = do - assertTrue "COSE_Key's kty (1) header must be set to OKP (1)" - (getCoseKeyHeaderKty coseKey == Just 1) - - assertTrue "COSE_Key's alg (3) header must be set to EdDSA (-8)" - (getCoseKeyHeaderAlg coseKey == Just (-8)) - - assertTrue "COSE_Key's crv (-1) header must be set to Ed25519 (6)" - (getCoseKeyHeaderCrv coseKey == Just (6)) - - checkKidHeaders :: COSESign1 -> COSEKey -> Aff Unit - checkKidHeaders coseSign1 coseKey = - assertTrue - "COSE_Sign1's kid (4) and COSE_Key's kid (2) headers, if present, must \ - \be set to the same value" - (getCoseSign1ProtectedHeaderKid coseSign1 == getCoseKeyHeaderKid coseKey) - - checkVerification :: COSESign1 -> COSEKey -> Effect Unit - checkVerification coseSign1 coseKey = do - publicKey <- - errMaybe "COSE_Key's x (-2) header must be set to public key bytes" - $ getCoseKeyHeaderX coseKey >>= publicKeyFromBytes - sigStructBytes <- getSignedData coseSign1 - assertTrue "Signature verification failed" - =<< verifySignature coseSign1 publicKey sigStructBytes - --------------------------------------------------------------------------------- --- Arbitrary --------------------------------------------------------------------------------- - -newtype ArbitraryPrivatePaymentKey = - ArbitraryPrivatePaymentKey PrivatePaymentKey - -derive instance Newtype ArbitraryPrivatePaymentKey _ - -instance Arbitrary ArbitraryPrivatePaymentKey where - arbitrary = - wrap <<< wrap <<< unwrap <$> (arbitrary :: Gen ArbitraryPrivateKey) - -newtype ArbitraryPrivateStakeKey = ArbitraryPrivateStakeKey PrivateStakeKey - -derive instance Newtype ArbitraryPrivateStakeKey _ - -instance Arbitrary ArbitraryPrivateStakeKey where - arbitrary = - wrap <<< wrap <<< unwrap <$> (arbitrary :: Gen ArbitraryPrivateKey) - -newtype ArbitraryPrivateKey = ArbitraryPrivateKey PrivateKey - -derive instance Newtype ArbitraryPrivateKey _ - -instance Arbitrary ArbitraryPrivateKey where - arbitrary = - wrap <<< unsafePartial fromJust <$> - (PrivateKey.fromRawBytes <$> privateKeyBytes) - where - privateKeyBytes :: Gen RawBytes - privateKeyBytes = - wrap <<< byteArrayFromIntArrayUnsafe <$> vectorOf 32 (chooseInt 0 255) - -newtype ArbitraryNetworkId = ArbitraryNetworkId NetworkId - -derive instance Newtype ArbitraryNetworkId _ - -instance Arbitrary ArbitraryNetworkId where - arbitrary = - wrap <<< fromMaybe MainnetId <<< NetworkId.fromInt <$> chooseInt 0 1 - --------------------------------------------------------------------------------- --- FFI --------------------------------------------------------------------------------- - -foreign import data COSESign1 :: Type -foreign import _getCoseSign1ProtectedHeaderAlg - :: MaybeFfiHelper -> COSESign1 -> Maybe Int - -foreign import _getCoseSign1ProtectedHeaderAddress - :: MaybeFfiHelper -> COSESign1 -> Maybe CborBytes - -foreign import _getCoseSign1ProtectedHeaderKid - :: MaybeFfiHelper -> COSESign1 -> Maybe RawBytes - -foreign import data COSEKey :: Type -foreign import _getCoseKeyHeaderKty :: MaybeFfiHelper -> COSEKey -> Maybe Int -foreign import _getCoseKeyHeaderAlg :: MaybeFfiHelper -> COSEKey -> Maybe Int -foreign import _getCoseKeyHeaderCrv :: MaybeFfiHelper -> COSEKey -> Maybe Int -foreign import _getCoseKeyHeaderX :: MaybeFfiHelper -> COSEKey -> Maybe RawBytes -foreign import _getCoseKeyHeaderKid - :: MaybeFfiHelper -> COSEKey -> Maybe RawBytes - -foreign import fromBytesCoseSign1 :: CborBytes -> Effect COSESign1 -foreign import fromBytesCoseKey :: CborBytes -> Effect COSEKey - -foreign import getSignedData :: COSESign1 -> Effect CborBytes -foreign import verifySignature - :: COSESign1 -> PublicKey -> CborBytes -> Effect Boolean - -getCoseSign1ProtectedHeaderAlg :: COSESign1 -> Maybe Int -getCoseSign1ProtectedHeaderAlg = _getCoseSign1ProtectedHeaderAlg maybeFfiHelper - -getCoseSign1ProtectedHeaderAddress :: COSESign1 -> Maybe CborBytes -getCoseSign1ProtectedHeaderAddress = - _getCoseSign1ProtectedHeaderAddress maybeFfiHelper - -getCoseSign1ProtectedHeaderKid :: COSESign1 -> Maybe RawBytes -getCoseSign1ProtectedHeaderKid = _getCoseSign1ProtectedHeaderKid maybeFfiHelper - -getCoseKeyHeaderKty :: COSEKey -> Maybe Int -getCoseKeyHeaderKty = _getCoseKeyHeaderKty maybeFfiHelper - -getCoseKeyHeaderAlg :: COSEKey -> Maybe Int -getCoseKeyHeaderAlg = _getCoseKeyHeaderAlg maybeFfiHelper - -getCoseKeyHeaderCrv :: COSEKey -> Maybe Int -getCoseKeyHeaderCrv = _getCoseKeyHeaderCrv maybeFfiHelper - -getCoseKeyHeaderX :: COSEKey -> Maybe RawBytes -getCoseKeyHeaderX = _getCoseKeyHeaderX maybeFfiHelper - -getCoseKeyHeaderKid :: COSEKey -> Maybe RawBytes -getCoseKeyHeaderKid = _getCoseKeyHeaderKid maybeFfiHelper From 4627a2e88eab32610dcdf87a9bbe0f3167b5c753 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Wed, 3 Jul 2024 16:47:18 +0300 Subject: [PATCH 27/52] Nix formatting --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index c593fefad3..1db377fd0c 100644 --- a/flake.nix +++ b/flake.nix @@ -405,7 +405,7 @@ let ctlPkgsExp = import ./spago-packages.nix { inherit pkgs; }; ctlScaffoldPkgsExp = import ./templates/ctl-scaffold/spago-packages.nix { inherit pkgs; }; - ctlPs = (attrValues ctlPkgsExp.inputs); + ctlPs = attrValues ctlPkgsExp.inputs; ctlScaffoldPs = filter (p: p.name != "cardano-transaction-lib") (attrValues ctlScaffoldPkgsExp.inputs); intersection = pkgs.lib.lists.intersectLists ctlPs ctlScaffoldPs; From 999b8728dd6c86b2a155934165746649fc62bd27 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Wed, 3 Jul 2024 18:27:36 +0400 Subject: [PATCH 28/52] Fix CI --- examples/AlwaysSucceeds.purs | 4 +- examples/BalanceTxConstraints.purs | 2 +- examples/ChangeGeneration.purs | 8 +- examples/ContractTestUtils.purs | 16 +- examples/ExUnits.purs | 2 +- examples/IncludeDatum.purs | 6 +- examples/KeyWallet/SignMultiple.purs | 1 - examples/PlutusV2/ReferenceInputs.purs | 10 +- examples/SignMultiple.purs | 1 - examples/TxChaining.purs | 1 - packages.dhall | 55 ++++++ spago-packages.nix | 18 +- spago.dhall | 2 +- src/Contract/Constraints.purs | 1 + src/Contract/Test/Assert.purs | 6 +- src/Contract/Transaction.purs | 41 +---- src/Internal/BalanceTx/BalanceTx.purs | 37 ++-- src/Internal/BalanceTx/Collateral.purs | 10 +- src/Internal/BalanceTx/Error.purs | 9 +- src/Internal/BalanceTx/ExUnitsAndMinFee.purs | 4 +- src/Internal/Contract/MinFee.purs | 11 +- src/Internal/Contract/Sign.purs | 3 +- src/Internal/Lens.purs | 182 ------------------- src/Internal/ProcessConstraints.purs | 46 +++-- src/Internal/Serialization/MinFee.purs | 3 +- src/Internal/Test/KeyDir.purs | 3 +- src/Internal/Types/TxConstraints.purs | 3 +- src/Internal/Wallet/Key.purs | 2 +- templates/ctl-scaffold/packages.dhall | 58 +++++- templates/ctl-scaffold/spago-packages.nix | 18 +- test/Plutip/Contract.purs | 30 ++- test/Plutip/Staking.purs | 1 - test/PrivateKey.purs | 4 +- 33 files changed, 273 insertions(+), 325 deletions(-) delete mode 100644 src/Internal/Lens.purs diff --git a/examples/AlwaysSucceeds.purs b/examples/AlwaysSucceeds.purs index b449d74107..d227c52aa2 100644 --- a/examples/AlwaysSucceeds.purs +++ b/examples/AlwaysSucceeds.purs @@ -17,6 +17,7 @@ import Cardano.Types , PlutusScript , ScriptHash , TransactionHash + , _input ) import Cardano.Types.BigNum as BigNum import Cardano.Types.PlutusData as Datum @@ -30,8 +31,7 @@ import Contract.PlutusData (unitRedeemer) import Contract.ScriptLookups as Lookups import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction - ( _input - , awaitTxConfirmed + ( awaitTxConfirmed , lookupTxHash , submitTxFromConstraints ) diff --git a/examples/BalanceTxConstraints.purs b/examples/BalanceTxConstraints.purs index 937329e404..13b54824cd 100644 --- a/examples/BalanceTxConstraints.purs +++ b/examples/BalanceTxConstraints.purs @@ -56,7 +56,7 @@ import Ctl.Examples.AlwaysMints (alwaysMintsPolicy) import Ctl.Examples.Helpers (mkAssetName) as Helpers import Data.Array (head) import Data.Array (sort) as Array -import Data.Map (empty, fromFoldable, keys, member) as Map +import Data.Map (fromFoldable, keys, member) as Map import Data.Set (findMin) as Set import JS.BigInt as BigInt diff --git a/examples/ChangeGeneration.purs b/examples/ChangeGeneration.purs index d96ef33879..012b6362c6 100644 --- a/examples/ChangeGeneration.purs +++ b/examples/ChangeGeneration.purs @@ -2,6 +2,10 @@ module Ctl.Examples.ChangeGeneration (checkChangeOutputsDistribution) where import Prelude +import Cardano.Types + ( _body + , _outputs + ) import Cardano.Types.BigNum as BigNum import Contract.BalanceTxConstraints (mustSendChangeWithDatum) import Contract.Monad (Contract) @@ -13,9 +17,7 @@ import Contract.PlutusData import Contract.ScriptLookups as Lookups import Contract.Scripts (validatorHash) import Contract.Transaction - ( _body - , _outputs - , awaitTxConfirmed + ( awaitTxConfirmed , balanceTx , signTransaction , submit diff --git a/examples/ContractTestUtils.purs b/examples/ContractTestUtils.purs index edc2ea175e..b930bc44cf 100644 --- a/examples/ContractTestUtils.purs +++ b/examples/ContractTestUtils.purs @@ -11,7 +11,16 @@ module Ctl.Examples.ContractTestUtils import Contract.Prelude -import Cardano.Types (BigNum, Coin, ExUnits(ExUnits), TransactionOutput) +import Cardano.Types + ( BigNum + , Coin + , ExUnits(ExUnits) + , TransactionOutput + , _body + , _datum + , _fee + , _output + ) import Cardano.Types.BigNum as BigNum import Cardano.Types.Credential (Credential(PubKeyHashCredential)) import Cardano.Types.Int as Int @@ -39,10 +48,6 @@ import Contract.Test.Assert import Contract.Transaction ( TransactionHash , TransactionUnspentOutput - , _body - , _datum - , _fee - , _output , awaitTxConfirmed , balanceTx , lookupTxHash @@ -63,7 +68,6 @@ import Contract.Wallet import Ctl.Examples.Helpers (mustPayToPubKeyStakeAddress) as Helpers import Data.Array (head) import Data.Lens (_1, _2, view, (%~)) -import Data.Map as Map import Effect.Exception (throw) type ContractParams = diff --git a/examples/ExUnits.purs b/examples/ExUnits.purs index 434b27f330..9fc323912b 100644 --- a/examples/ExUnits.purs +++ b/examples/ExUnits.purs @@ -2,6 +2,7 @@ module Ctl.Examples.ExUnits where import Contract.Prelude +import Cardano.Types (_input) import Cardano.Types.BigNum as BigNum import Cardano.Types.Credential (Credential(ScriptHashCredential)) import Contract.Address (mkAddress) @@ -15,7 +16,6 @@ import Contract.Scripts (Validator, ValidatorHash, validatorHash) import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( TransactionHash - , _input , awaitTxConfirmed , lookupTxHash , submitTxFromConstraints diff --git a/examples/IncludeDatum.purs b/examples/IncludeDatum.purs index 4b5a979000..086e95250f 100644 --- a/examples/IncludeDatum.purs +++ b/examples/IncludeDatum.purs @@ -12,7 +12,10 @@ module Ctl.Examples.IncludeDatum import Contract.Prelude -import Cardano.Types (Credential(ScriptHashCredential)) +import Cardano.Types + ( Credential(ScriptHashCredential) + , _input + ) import Cardano.Types.BigNum as BigNum import Contract.Address (mkAddress) import Contract.Config (ContractParams, testnetNamiConfig) @@ -24,7 +27,6 @@ import Contract.Scripts (Validator, ValidatorHash, validatorHash) import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( TransactionHash - , _input , awaitTxConfirmed , lookupTxHash , submitTxFromConstraints diff --git a/examples/KeyWallet/SignMultiple.purs b/examples/KeyWallet/SignMultiple.purs index 3e4ee3c958..7e63e7a15d 100644 --- a/examples/KeyWallet/SignMultiple.purs +++ b/examples/KeyWallet/SignMultiple.purs @@ -19,7 +19,6 @@ import Contract.Value (lovelaceValueOf) as Value import Control.Monad.Reader (asks) import Ctl.Examples.KeyWallet.Internal.Pkh2PkhContract (runKeyWalletContract_) import Data.Map (Map) -import Data.Map as Map import Data.Newtype (unwrap) import Data.Set (Set) import Data.UInt (UInt) diff --git a/examples/PlutusV2/ReferenceInputs.purs b/examples/PlutusV2/ReferenceInputs.purs index 8b47431023..5651e90e5a 100644 --- a/examples/PlutusV2/ReferenceInputs.purs +++ b/examples/PlutusV2/ReferenceInputs.purs @@ -2,7 +2,11 @@ module Ctl.Examples.PlutusV2.ReferenceInputs (contract, example, main) where import Contract.Prelude -import Cardano.Types (Transaction) +import Cardano.Types + ( Transaction + , _body + , _referenceInputs + ) import Cardano.Types.BigNum as BigNum import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') @@ -23,8 +27,6 @@ import Contract.Test.Assert ) import Contract.Transaction ( TransactionInput - , _body - , _referenceInputs , awaitTxConfirmed , balanceTx , signTransaction @@ -42,7 +44,7 @@ import Control.Monad.Trans.Class (lift) import Ctl.Examples.Helpers (mustPayToPubKeyStakeAddress) as Helpers import Data.Array (elem, head) as Array import Data.Lens.Getter ((^.)) -import Data.Map (empty, member, toUnfoldable) as Map +import Data.Map (member, toUnfoldable) as Map main :: Effect Unit main = example testnetNamiConfig diff --git a/examples/SignMultiple.purs b/examples/SignMultiple.purs index 137444f724..2d644a907c 100644 --- a/examples/SignMultiple.purs +++ b/examples/SignMultiple.purs @@ -38,7 +38,6 @@ import Contract.Wallet import Control.Monad.Reader (asks) import Data.Array (head) import Data.Map (Map, filter) -import Data.Map as Map import Data.Set (Set) import Data.UInt (UInt) import Effect.Ref as Ref diff --git a/examples/TxChaining.purs b/examples/TxChaining.purs index 80e995a3c6..56c92096b2 100644 --- a/examples/TxChaining.purs +++ b/examples/TxChaining.purs @@ -33,7 +33,6 @@ import Contract.UnbalancedTx (mkUnbalancedTx) import Contract.Value as Value import Contract.Wallet (ownPaymentPubKeyHashes) import Data.Array (head) -import Data.Map as Map main :: Effect Unit main = example testnetNamiConfig diff --git a/packages.dhall b/packages.dhall index a7021ff19d..031e6285c0 100644 --- a/packages.dhall +++ b/packages.dhall @@ -390,6 +390,61 @@ let additions = , repo = "https://github.com/mlabs-haskell/purescript-cardano-hd-wallet" , version = "v1.0.0" } + , cardano-transaction-builder = + { dependencies = + [ "aeson" + , "aff" + , "arraybuffer-types" + , "arrays" + , "bifunctors" + , "bytearrays" + , "cardano-plutus-data-schema" + , "cardano-serialization-lib" + , "cardano-types" + , "console" + , "control" + , "datetime" + , "effect" + , "either" + , "encoding" + , "exceptions" + , "foldable-traversable" + , "foreign-object" + , "integers" + , "js-bigints" + , "lattice" + , "lists" + , "literals" + , "maybe" + , "monad-logger" + , "mote" + , "mote-testplan" + , "newtype" + , "nonempty" + , "nullable" + , "ordered-collections" + , "partial" + , "prelude" + , "profunctor" + , "profunctor-lenses" + , "quickcheck" + , "rationals" + , "record" + , "safe-coerce" + , "spec" + , "strings" + , "these" + , "transformers" + , "tuples" + , "typelevel-prelude" + , "uint" + , "unfoldable" + , "unsafe-coerce" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-transaction-builder" + , version = "c93cfaaa08643632021fb8c6dcc4d0b8130250d1" + } , mote-testplan = { dependencies = [ "aff" diff --git a/spago-packages.nix b/spago-packages.nix index 081d8d7895..3a41d7d07c 100644 --- a/spago-packages.nix +++ b/spago-packages.nix @@ -257,13 +257,25 @@ let installPhase = "ln -s $src $out"; }; + "cardano-transaction-builder" = pkgs.stdenv.mkDerivation { + name = "cardano-transaction-builder"; + version = "c93cfaaa08643632021fb8c6dcc4d0b8130250d1"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-transaction-builder"; + rev = "c93cfaaa08643632021fb8c6dcc4d0b8130250d1"; + sha256 = "14hflxhl5g8yv43k4i7xh6lx5cf3vc0vzhy76jw2b4nrp83ks6l3"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "cardano-types" = pkgs.stdenv.mkDerivation { name = "cardano-types"; - version = "v1.0.1"; + version = "40d9468a4712ad2bf57ebede19fae92208f082a0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-types"; - rev = "715d4b2dcf8b29cb45001209ee562f758a513261"; - sha256 = "1xcrdmpwd3qcdiyjfrj0z2dh56l4z1s97r25b6nhlqwmwz7qz19z"; + rev = "40d9468a4712ad2bf57ebede19fae92208f082a0"; + sha256 = "1iawinsrsipqgjrcgv650x3i2iad1z2vlwlhvlcx9880qmv0m9gc"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; diff --git a/spago.dhall b/spago.dhall index c1d1836443..cf65b5d00c 100644 --- a/spago.dhall +++ b/spago.dhall @@ -21,6 +21,7 @@ You can edit this file as you like. , "cardano-message-signing" , "cardano-plutus-data-schema" , "cardano-serialization-lib" + , "cardano-transaction-builder" , "cardano-types" , "checked-exceptions" , "cip30" @@ -110,6 +111,5 @@ You can edit this file as you like. , "templates/ctl-scaffold/src/**/*.purs" , "templates/ctl-scaffold/test/**/*.purs" , "templates/ctl-scaffold/exe/**/*.purs" - , "../purescript-cardano-transaction-builder/src/**/*.purs" ] } diff --git a/src/Contract/Constraints.purs b/src/Contract/Constraints.purs index d9c7cd73eb..1faa0c2443 100644 --- a/src/Contract/Constraints.purs +++ b/src/Contract/Constraints.purs @@ -1,6 +1,7 @@ module Contract.Constraints where import Prelude +import Prim hiding (Constraint) import Cardano.Types (Slot) import Cardano.Types.AssetName (AssetName) diff --git a/src/Contract/Test/Assert.purs b/src/Contract/Test/Assert.purs index 4d663947da..2ad6194b2d 100644 --- a/src/Contract/Test/Assert.purs +++ b/src/Contract/Test/Assert.purs @@ -79,6 +79,11 @@ import Cardano.Types , TransactionHash , TransactionOutput , Value + , _amount + , _datum + , _redeemers + , _scriptRef + , _witnessSet ) import Cardano.Types.BigNum as BigNum import Cardano.Types.Value as Value @@ -92,7 +97,6 @@ import Control.Monad.Error.Class as E import Control.Monad.Reader (ReaderT, ask, local, mapReaderT, runReaderT) import Control.Monad.Trans.Class (lift) import Ctl.Internal.Contract.Monad (ContractEnv) -import Ctl.Internal.Lens (_amount, _datum, _redeemers, _scriptRef, _witnessSet) import Ctl.Internal.Metadata.MetadataType (class MetadataType, metadataLabel) import Data.Array (foldr) import Data.Array (fromFoldable, length, mapWithIndex, partition) as Array diff --git a/src/Contract/Transaction.purs b/src/Contract/Transaction.purs index d7524907ae..4d66f38eb2 100644 --- a/src/Contract/Transaction.purs +++ b/src/Contract/Transaction.purs @@ -28,7 +28,6 @@ import Cardano.Transaction.Builder ) import Cardano.Types ( Bech32String - , Coin , GeneralTransactionMetadata , PoolPubKeyHash(PoolPubKeyHash) , Transaction(Transaction) @@ -38,7 +37,6 @@ import Cardano.Types , TransactionUnspentOutput(TransactionUnspentOutput) , UtxoMap , _body - , _fee , _outputs ) import Cardano.Types @@ -107,40 +105,6 @@ import Ctl.Internal.Contract.QueryHandle.Error ) as X import Ctl.Internal.Contract.Sign (signTransaction) import Ctl.Internal.Contract.Sign (signTransaction) as X -import Ctl.Internal.Lens - ( _address - , _amount - , _auxiliaryData - , _auxiliaryDataHash - , _body - , _certs - , _collateral - , _collateralReturn - , _datum - , _fee - , _input - , _inputs - , _isValid - , _mint - , _nativeScripts - , _networkId - , _output - , _outputs - , _plutusData - , _plutusScripts - , _redeemers - , _referenceInputs - , _requiredSigners - , _scriptDataHash - , _scriptRef - , _totalCollateral - , _ttl - , _update - , _validityStartInterval - , _vkeys - , _withdrawals - , _witnessSet - ) as X import Ctl.Internal.Service.Error (ClientError) import Ctl.Internal.Types.ScriptLookups (ScriptLookups) import Ctl.Internal.Types.TxConstraints (TxConstraints) @@ -155,14 +119,13 @@ import Data.Bifunctor (lmap) import Data.Either (Either(Left, Right)) import Data.Foldable (foldl, length) import Data.Lens.Getter (view) -import Data.Map (Map) import Data.Map (empty, insert, toUnfoldable) as Map import Data.Maybe (Maybe(Nothing)) import Data.Newtype (unwrap) import Data.String.Utils (startsWith) import Data.Traversable (class Traversable, for_, traverse) -import Data.Tuple (Tuple(Tuple), fst) -import Data.Tuple.Nested (type (/\), (/\)) +import Data.Tuple (fst) +import Data.Tuple.Nested ((/\)) import Data.UInt (UInt) import Effect.Aff (bracket, error) import Effect.Aff.Class (liftAff) diff --git a/src/Internal/BalanceTx/BalanceTx.purs b/src/Internal/BalanceTx/BalanceTx.purs index 0eaeb3aef7..6aa2ca9ed4 100644 --- a/src/Internal/BalanceTx/BalanceTx.purs +++ b/src/Internal/BalanceTx/BalanceTx.purs @@ -4,11 +4,7 @@ module Ctl.Internal.BalanceTx import Prelude -import Cardano.Transaction.Edit - ( attachRedeemers - , editTransaction - , mkRedeemersContext - ) +import Cardano.Transaction.Edit (editTransaction) import Cardano.Types ( AssetClass(AssetClass) , Certificate(StakeDeregistration, StakeRegistration) @@ -20,6 +16,18 @@ import Cardano.Types , TransactionOutput , UtxoMap , Value(Value) + , _amount + , _body + , _certs + , _fee + , _inputs + , _mint + , _networkId + , _outputs + , _plutusScripts + , _referenceInputs + , _withdrawals + , _witnessSet ) import Cardano.Types.Address (Address) import Cardano.Types.BigNum as BigNum @@ -65,7 +73,6 @@ import Ctl.Internal.BalanceTx.Constraints import Ctl.Internal.BalanceTx.Error ( BalanceTxError ( CouldNotGetUtxos - , ReindexRedeemersError , CouldNotGetCollateral , InsufficientCollateralUtxos , NumericOverflowError @@ -96,20 +103,6 @@ import Ctl.Internal.Contract.Wallet , getWalletUtxos ) as Wallet import Ctl.Internal.Helpers (liftEither, pprintTagSet, unsafeFromJust, (??)) -import Ctl.Internal.Lens - ( _amount - , _body - , _certs - , _fee - , _inputs - , _mint - , _networkId - , _outputs - , _plutusScripts - , _referenceInputs - , _withdrawals - , _witnessSet - ) import Ctl.Internal.Partition ( equipartition , equipartitionValueWithTokenQuantityUpperBound @@ -133,7 +126,6 @@ import Data.Array.NonEmpty , zipWith ) as NEArray import Data.Array.NonEmpty as NEA -import Data.Bifunctor (lmap) import Data.Bitraversable (ltraverse) import Data.Either (Either, hush, note) import Data.Foldable (fold, foldMap, foldr, length, null, sum) @@ -861,8 +853,7 @@ getStakingBalance tx depositLovelacesPerCert = -------------------------------------------------------------------------------- logBalancerState - :: forall rest - . String + :: String -> UtxoMap -> BalancerState Transaction -> BalanceTxM Unit diff --git a/src/Internal/BalanceTx/Collateral.purs b/src/Internal/BalanceTx/Collateral.purs index faef30a399..3a773ea3ed 100644 --- a/src/Internal/BalanceTx/Collateral.purs +++ b/src/Internal/BalanceTx/Collateral.purs @@ -13,6 +13,10 @@ import Cardano.Types , Transaction , TransactionOutput , TransactionUnspentOutput + , _body + , _collateral + , _collateralReturn + , _totalCollateral ) import Cardano.Types.Address (Address) import Cardano.Types.BigNum (add, max, maxValue, sub, zero) as BigNum @@ -27,12 +31,6 @@ import Ctl.Internal.BalanceTx.Error ) import Ctl.Internal.BalanceTx.Types (BalanceTxM, askCoinsPerUtxoUnit) import Ctl.Internal.BalanceTx.UtxoMinAda (utxoMinAdaValue) -import Ctl.Internal.Lens - ( _body - , _collateral - , _collateralReturn - , _totalCollateral - ) import Data.Either (Either(Left, Right)) import Data.Foldable (foldl) import Data.Lens ((.~)) diff --git a/src/Internal/BalanceTx/Error.purs b/src/Internal/BalanceTx/Error.purs index 7b2195cf28..3ed6911e5a 100644 --- a/src/Internal/BalanceTx/Error.purs +++ b/src/Internal/BalanceTx/Error.purs @@ -27,14 +27,19 @@ import Prelude import Cardano.AsCbor (encodeCbor) import Cardano.Transaction.Edit (DetachedRedeemer) -import Cardano.Types (Coin, Redeemer(Redeemer), Transaction) +import Cardano.Types + ( Coin + , Redeemer(Redeemer) + , Transaction + , _redeemers + , _witnessSet + ) import Cardano.Types.BigNum as BigNum import Cardano.Types.TransactionInput (TransactionInput(TransactionInput)) import Cardano.Types.TransactionOutput (TransactionOutput) import Cardano.Types.UtxoMap (UtxoMap, pprintUtxoMap) import Cardano.Types.Value (Value) import Ctl.Internal.Helpers (bugTrackerLink, pprintTagSet) -import Ctl.Internal.Lens (_redeemers, _witnessSet) import Ctl.Internal.QueryM.Ogmios ( RedeemerPointer , ScriptFailure diff --git a/src/Internal/BalanceTx/ExUnitsAndMinFee.purs b/src/Internal/BalanceTx/ExUnitsAndMinFee.purs index f44cc80f2c..f82298db86 100644 --- a/src/Internal/BalanceTx/ExUnitsAndMinFee.purs +++ b/src/Internal/BalanceTx/ExUnitsAndMinFee.purs @@ -18,6 +18,9 @@ import Cardano.Types , TransactionOutput(TransactionOutput) , TransactionWitnessSet , UtxoMap + , _body + , _isValid + , _witnessSet ) import Cardano.Types.BigNum as BigNum import Cardano.Types.ScriptRef as ScriptRef @@ -38,7 +41,6 @@ import Ctl.Internal.BalanceTx.Types import Ctl.Internal.Contract.MinFee (calculateMinFee) as Contract.MinFee import Ctl.Internal.Contract.Monad (getQueryHandle) import Ctl.Internal.Helpers (unsafeFromJust) -import Ctl.Internal.Lens (_body, _isValid, _witnessSet) import Ctl.Internal.QueryM.Ogmios ( AdditionalUtxoSet , TxEvaluationFailure(AdditionalUtxoOverlap) diff --git a/src/Internal/Contract/MinFee.purs b/src/Internal/Contract/MinFee.purs index 05fd89c54e..3543216825 100644 --- a/src/Internal/Contract/MinFee.purs +++ b/src/Internal/Contract/MinFee.purs @@ -2,7 +2,15 @@ module Ctl.Internal.Contract.MinFee (calculateMinFee) where import Prelude -import Cardano.Types (Coin, Ed25519KeyHash, Transaction, UtxoMap) +import Cardano.Types + ( Coin + , Ed25519KeyHash + , Transaction + , UtxoMap + , _body + , _collateral + , _inputs + ) import Cardano.Types.Address (Address, getPaymentCredential, getStakeCredential) import Cardano.Types.Credential (asPubKeyHash) import Cardano.Types.TransactionInput (TransactionInput) @@ -10,7 +18,6 @@ import Ctl.Internal.Contract (getProtocolParameters) import Ctl.Internal.Contract.Monad (Contract, getQueryHandle) import Ctl.Internal.Contract.Wallet (getWalletAddresses) import Ctl.Internal.Helpers (liftM, liftedM) -import Ctl.Internal.Lens (_body, _collateral, _inputs) import Ctl.Internal.Serialization.MinFee (calculateMinFeeCsl) import Data.Array (fromFoldable, mapMaybe) import Data.Array as Array diff --git a/src/Internal/Contract/Sign.purs b/src/Internal/Contract/Sign.purs index 6d269fc694..98c347a91b 100644 --- a/src/Internal/Contract/Sign.purs +++ b/src/Internal/Contract/Sign.purs @@ -4,12 +4,11 @@ module Ctl.Internal.Contract.Sign import Prelude -import Cardano.Types (Transaction) +import Cardano.Types (Transaction, _body, _inputs, _witnessSet) import Control.Monad.Reader (asks) import Ctl.Internal.BalanceTx.Sync (isCip30Wallet, syncWalletWithTxInputs) import Ctl.Internal.Contract.Monad (Contract) import Ctl.Internal.Contract.Wallet (withWallet) -import Ctl.Internal.Lens (_body, _inputs, _witnessSet) import Ctl.Internal.Wallet (Wallet(GenericCip30, KeyWallet)) import Data.Array (fromFoldable) import Data.Lens ((<>~)) diff --git a/src/Internal/Lens.purs b/src/Internal/Lens.purs deleted file mode 100644 index 461d88a86a..0000000000 --- a/src/Internal/Lens.purs +++ /dev/null @@ -1,182 +0,0 @@ -module Ctl.Internal.Lens - ( _address - , _amount - , _auxiliaryData - , _auxiliaryDataHash - , _body - , _certs - , _collateral - , _collateralReturn - , _datum - , _fee - , _input - , _inputs - , _isValid - , _mint - , _nativeScripts - , _networkId - , _output - , _outputs - , _plutusData - , _plutusScripts - , _redeemers - , _referenceInputs - , _requiredSigners - , _scriptDataHash - , _scriptRef - , _totalCollateral - , _ttl - , _update - , _validityStartInterval - , _vkeys - , _withdrawals - , _witnessSet - ) where - -import Prelude - -import Cardano.Types - ( Address - , AuxiliaryData - , AuxiliaryDataHash - , BootstrapWitness - , Certificate - , Coin - , Ed25519KeyHash - , Mint - , NativeScript - , NetworkId - , OutputDatum - , PlutusData - , PlutusScript - , Redeemer - , ScriptDataHash - , ScriptRef - , Slot - , Transaction - , TransactionBody - , TransactionInput - , TransactionOutput - , TransactionUnspentOutput - , TransactionWitnessSet - , Update - , Value - , Vkeywitness - ) -import Cardano.Types.RewardAddress (RewardAddress) -import Data.Lens (Lens') -import Data.Lens.Iso.Newtype (_Newtype) -import Data.Lens.Record (prop) -import Data.Map (Map) -import Data.Maybe (Maybe) -import Type.Proxy (Proxy(Proxy)) - --- Transaction - -_body :: Lens' Transaction TransactionBody -_body = _Newtype <<< prop (Proxy :: Proxy "body") - -_isValid :: Lens' Transaction Boolean -_isValid = _Newtype <<< prop (Proxy :: Proxy "isValid") - -_witnessSet :: Lens' Transaction TransactionWitnessSet -_witnessSet = _Newtype <<< prop (Proxy :: Proxy "witnessSet") - -_auxiliaryData :: Lens' Transaction (Maybe AuxiliaryData) -_auxiliaryData = _Newtype <<< prop (Proxy :: Proxy "auxiliaryData") - --- TransactionBody - -_inputs :: Lens' TransactionBody (Array TransactionInput) -_inputs = _Newtype <<< prop (Proxy :: Proxy "inputs") - -_fee :: Lens' TransactionBody Coin -_fee = _Newtype <<< prop (Proxy :: Proxy "fee") - -_outputs :: Lens' TransactionBody (Array TransactionOutput) -_outputs = _Newtype <<< prop (Proxy :: Proxy "outputs") - -_certs :: Lens' TransactionBody (Array Certificate) -_certs = _Newtype <<< prop (Proxy :: Proxy "certs") - -_networkId :: Lens' TransactionBody (Maybe NetworkId) -_networkId = _Newtype <<< prop (Proxy :: Proxy "networkId") - -_scriptDataHash :: Lens' TransactionBody (Maybe ScriptDataHash) -_scriptDataHash = _Newtype <<< prop (Proxy :: Proxy "scriptDataHash") - -_collateral :: Lens' TransactionBody (Array TransactionInput) -_collateral = _Newtype <<< prop (Proxy :: Proxy "collateral") - -_collateralReturn :: Lens' TransactionBody (Maybe TransactionOutput) -_collateralReturn = _Newtype <<< prop (Proxy :: Proxy "collateralReturn") - -_totalCollateral :: Lens' TransactionBody (Maybe Coin) -_totalCollateral = _Newtype <<< prop (Proxy :: Proxy "totalCollateral") - -_referenceInputs :: Lens' TransactionBody (Array TransactionInput) -_referenceInputs = _Newtype <<< prop (Proxy :: Proxy "referenceInputs") - -_requiredSigners :: Lens' TransactionBody (Array Ed25519KeyHash) -_requiredSigners = _Newtype <<< prop (Proxy :: Proxy "requiredSigners") - -_withdrawals :: Lens' TransactionBody (Map RewardAddress Coin) -_withdrawals = _Newtype <<< prop (Proxy :: Proxy "withdrawals") - -_mint :: Lens' TransactionBody (Maybe Mint) -_mint = _Newtype <<< prop (Proxy :: Proxy "mint") - -_auxiliaryDataHash :: Lens' TransactionBody (Maybe AuxiliaryDataHash) -_auxiliaryDataHash = _Newtype <<< prop (Proxy :: Proxy "auxiliaryDataHash") - -_ttl :: Lens' TransactionBody (Maybe Slot) -_ttl = _Newtype <<< prop (Proxy :: Proxy "ttl") - -_update :: Lens' TransactionBody (Maybe Update) -_update = _Newtype <<< prop (Proxy :: Proxy "update") - -_validityStartInterval :: Lens' TransactionBody (Maybe Slot) -_validityStartInterval = _Newtype <<< prop - (Proxy :: Proxy "validityStartInterval") - --- TransactionUnspentOutput - -_output :: Lens' TransactionUnspentOutput TransactionOutput -_output = _Newtype <<< prop (Proxy :: Proxy "output") - -_input :: Lens' TransactionUnspentOutput TransactionInput -_input = _Newtype <<< prop (Proxy :: Proxy "input") - --- TransactionOutput - -_amount :: Lens' TransactionOutput Value -_amount = _Newtype <<< prop (Proxy :: Proxy "amount") - -_scriptRef :: Lens' TransactionOutput (Maybe ScriptRef) -_scriptRef = _Newtype <<< prop (Proxy :: Proxy "scriptRef") - -_datum :: Lens' TransactionOutput (Maybe OutputDatum) -_datum = _Newtype <<< prop (Proxy :: Proxy "datum") - -_address :: Lens' TransactionOutput Address -_address = _Newtype <<< prop (Proxy :: Proxy "address") - --- TransactionWitnessSet - -_redeemers :: Lens' TransactionWitnessSet (Array Redeemer) -_redeemers = _Newtype <<< prop (Proxy :: Proxy "redeemers") - -_plutusData :: Lens' TransactionWitnessSet (Array PlutusData) -_plutusData = _Newtype <<< prop (Proxy :: Proxy "plutusData") - -_plutusScripts :: Lens' TransactionWitnessSet (Array PlutusScript) -_plutusScripts = _Newtype <<< prop (Proxy :: Proxy "plutusScripts") - -_nativeScripts :: Lens' TransactionWitnessSet (Array NativeScript) -_nativeScripts = _Newtype <<< prop (Proxy :: Proxy "nativeScripts") - -_vkeys :: Lens' TransactionWitnessSet (Array Vkeywitness) -_vkeys = _Newtype <<< prop (Proxy :: Proxy "vkeys") - -_bootstraps :: Lens' TransactionWitnessSet (Array BootstrapWitness) -_bootstraps = _Newtype <<< prop (Proxy :: Proxy "bootstraps") diff --git a/src/Internal/ProcessConstraints.purs b/src/Internal/ProcessConstraints.purs index ad69f9280a..c1cf2434f1 100644 --- a/src/Internal/ProcessConstraints.purs +++ b/src/Internal/ProcessConstraints.purs @@ -31,6 +31,16 @@ import Cardano.Types , TransactionUnspentOutput(TransactionUnspentOutput) , UtxoMap , Value(Value) + , _body + , _certs + , _inputs + , _isValid + , _mint + , _networkId + , _outputs + , _referenceInputs + , _requiredSigners + , _withdrawals , _witnessSet ) import Cardano.Types as Cardano @@ -60,19 +70,31 @@ import Control.Monad.Trans.Class (lift) import Ctl.Internal.Contract (getProtocolParameters) import Ctl.Internal.Contract.Monad (Contract, getQueryHandle, wrapQueryM) import Ctl.Internal.Helpers (liftEither, liftM, unsafeFromJust) -import Ctl.Internal.Lens - ( _body - , _certs - , _inputs - , _isValid - , _mint - , _networkId - , _outputs - , _referenceInputs - , _requiredSigners - , _withdrawals +import Ctl.Internal.ProcessConstraints.Error + ( MkUnbalancedTxError + ( CannotSatisfyAny + , CannotWithdrawRewardsNativeScript + , CannotWithdrawRewardsPlutusScript + , CannotWithdrawRewardsPubKey + , DatumWrongHash + , CannotMintZero + , ExpectedPlutusScriptGotNativeScript + , CannotFindDatum + , CannotQueryDatum + , CannotGetValidatorHashFromAddress + , TxOutRefWrongType + , CannotConvertPOSIXTimeRange + , WrongRefScriptHash + , ValidatorHashNotFound + , MintingPolicyNotFound + , DatumNotFound + , TxOutRefNotFound + , CannotSolveTimeConstraints + , NumericOverflow + , OwnPubKeyAndStakeKeyMissing + , CannotAttachRedeemer + ) ) -import Ctl.Internal.ProcessConstraints.Error (MkUnbalancedTxError(..)) import Ctl.Internal.ProcessConstraints.State ( ConstraintProcessingState , ConstraintsM diff --git a/src/Internal/Serialization/MinFee.purs b/src/Internal/Serialization/MinFee.purs index c6511ae68f..9a882efb02 100644 --- a/src/Internal/Serialization/MinFee.purs +++ b/src/Internal/Serialization/MinFee.purs @@ -10,6 +10,8 @@ import Cardano.Types , Transaction , Vkey(Vkey) , Vkeywitness(Vkeywitness) + , _vkeys + , _witnessSet ) import Cardano.Types.BigNum as BigNum import Cardano.Types.Ed25519Signature as Ed25519Signature @@ -19,7 +21,6 @@ import Cardano.Types.PublicKey as PublicKey import Cardano.Types.Transaction as Transaction import Control.Monad.Error.Class (class MonadThrow) import Ctl.Internal.Helpers (unsafeFromJust) -import Ctl.Internal.Lens (_vkeys, _witnessSet) import Ctl.Internal.NativeScripts (getMaximumSigners) import Ctl.Internal.Types.ProtocolParameters ( ProtocolParameters(ProtocolParameters) diff --git a/src/Internal/Test/KeyDir.purs b/src/Internal/Test/KeyDir.purs index 7c523f04ce..77f2314ebd 100644 --- a/src/Internal/Test/KeyDir.purs +++ b/src/Internal/Test/KeyDir.purs @@ -4,7 +4,7 @@ module Ctl.Internal.Test.KeyDir import Prelude -import Cardano.Types (BigNum, Value) +import Cardano.Types (BigNum, Value, _amount) import Cardano.Types.Address (toBech32) as Address import Cardano.Types.BigNum as BigNum import Cardano.Types.MultiAsset as MultiAsset @@ -52,7 +52,6 @@ import Control.Monad.Except (throwError) import Control.Monad.Reader (asks, local) import Control.Parallel (parTraverse, parTraverse_) import Ctl.Internal.Helpers (logWithLevel, unsafeFromJust) -import Ctl.Internal.Lens (_amount) import Ctl.Internal.ProcessConstraints (mkUnbalancedTxImpl) import Ctl.Internal.Test.ContractTest (ContractTest(ContractTest)) import Ctl.Internal.Test.UtxoDistribution diff --git a/src/Internal/Types/TxConstraints.purs b/src/Internal/Types/TxConstraints.purs index 92b6afbc10..3e1fb9a1f7 100644 --- a/src/Internal/Types/TxConstraints.purs +++ b/src/Internal/Types/TxConstraints.purs @@ -114,7 +114,6 @@ import Cardano.Types.RedeemerDatum (RedeemerDatum) import Cardano.Types.RedeemerDatum as RedeemerDatum import Ctl.Internal.Types.Interval (POSIXTimeRange) import Data.Array (singleton) -import Data.Array (singleton) as X import Data.Array as Array import Data.Foldable (class Foldable) import Data.Generic.Rep (class Generic) @@ -122,7 +121,7 @@ import Data.Map (Map) import Data.Map (singleton) as Map import Data.Maybe (Maybe(Just, Nothing)) import Data.Monoid (guard) -import Data.Newtype (class Newtype, over, unwrap) +import Data.Newtype (class Newtype) import Data.Show.Generic (genericShow) import Data.Tuple.Nested (type (/\), (/\)) import Prim.TypeError (class Warn, Text) diff --git a/src/Internal/Wallet/Key.purs b/src/Internal/Wallet/Key.purs index be85f52188..377d64b8a4 100644 --- a/src/Internal/Wallet/Key.purs +++ b/src/Internal/Wallet/Key.purs @@ -19,6 +19,7 @@ import Aeson ) import Cardano.MessageSigning (DataSignature) import Cardano.MessageSigning (signData) as MessageSigning +import Cardano.Types (_vkeys) import Cardano.Types.Address (Address(BaseAddress, EnterpriseAddress)) import Cardano.Types.Coin (Coin) import Cardano.Types.Credential (Credential(PubKeyHashCredential)) @@ -35,7 +36,6 @@ import Cardano.Types.TransactionWitnessSet (TransactionWitnessSet) import Cardano.Types.UtxoMap (UtxoMap) import Contract.Prelude (class Newtype) import Ctl.Internal.BalanceTx.Collateral.Select as Collateral -import Ctl.Internal.Lens (_vkeys) import Data.Array (fromFoldable) import Data.Either (note) import Data.Foldable (fold) diff --git a/templates/ctl-scaffold/packages.dhall b/templates/ctl-scaffold/packages.dhall index 8513539b15..0d4794c8d9 100644 --- a/templates/ctl-scaffold/packages.dhall +++ b/templates/ctl-scaffold/packages.dhall @@ -362,7 +362,7 @@ let additions = , "unsafe-coerce" ] , repo = "https://github.com/mlabs-haskell/purescript-cardano-types" - , version = "v1.0.1" + , version = "40d9468a4712ad2bf57ebede19fae92208f082a0" } , cardano-message-signing = { dependencies = @@ -409,6 +409,61 @@ let additions = , repo = "https://github.com/mlabs-haskell/purescript-mote-testplan" , version = "v1.0.0" } + , cardano-transaction-builder = + { dependencies = + [ "aeson" + , "aff" + , "arraybuffer-types" + , "arrays" + , "bifunctors" + , "bytearrays" + , "cardano-plutus-data-schema" + , "cardano-serialization-lib" + , "cardano-types" + , "console" + , "control" + , "datetime" + , "effect" + , "either" + , "encoding" + , "exceptions" + , "foldable-traversable" + , "foreign-object" + , "integers" + , "js-bigints" + , "lattice" + , "lists" + , "literals" + , "maybe" + , "monad-logger" + , "mote" + , "mote-testplan" + , "newtype" + , "nonempty" + , "nullable" + , "ordered-collections" + , "partial" + , "prelude" + , "profunctor" + , "profunctor-lenses" + , "quickcheck" + , "rationals" + , "record" + , "safe-coerce" + , "spec" + , "strings" + , "these" + , "transformers" + , "tuples" + , "typelevel-prelude" + , "uint" + , "unfoldable" + , "unsafe-coerce" + ] + , repo = + "https://github.com/mlabs-haskell/purescript-cardano-transaction-builder" + , version = "c93cfaaa08643632021fb8c6dcc4d0b8130250d1" + } , cardano-transaction-lib = { dependencies = [ "aeson" @@ -428,6 +483,7 @@ let additions = , "cardano-message-signing" , "cardano-plutus-data-schema" , "cardano-serialization-lib" + , "cardano-transaction-builder" , "cardano-types" , "checked-exceptions" , "cip30" diff --git a/templates/ctl-scaffold/spago-packages.nix b/templates/ctl-scaffold/spago-packages.nix index 4797c481b4..2b12f3f7e3 100644 --- a/templates/ctl-scaffold/spago-packages.nix +++ b/templates/ctl-scaffold/spago-packages.nix @@ -257,6 +257,18 @@ let installPhase = "ln -s $src $out"; }; + "cardano-transaction-builder" = pkgs.stdenv.mkDerivation { + name = "cardano-transaction-builder"; + version = "c93cfaaa08643632021fb8c6dcc4d0b8130250d1"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-transaction-builder"; + rev = "c93cfaaa08643632021fb8c6dcc4d0b8130250d1"; + sha256 = "14hflxhl5g8yv43k4i7xh6lx5cf3vc0vzhy76jw2b4nrp83ks6l3"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "cardano-transaction-lib" = pkgs.stdenv.mkDerivation { name = "cardano-transaction-lib"; version = "423e27b3f56b1a66db8d3126c22cea9bda7e50da"; @@ -271,11 +283,11 @@ let "cardano-types" = pkgs.stdenv.mkDerivation { name = "cardano-types"; - version = "v1.0.1"; + version = "40d9468a4712ad2bf57ebede19fae92208f082a0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-types"; - rev = "715d4b2dcf8b29cb45001209ee562f758a513261"; - sha256 = "1xcrdmpwd3qcdiyjfrj0z2dh56l4z1s97r25b6nhlqwmwz7qz19z"; + rev = "40d9468a4712ad2bf57ebede19fae92208f082a0"; + sha256 = "1iawinsrsipqgjrcgv650x3i2iad1z2vlwlhvlcx9880qmv0m9gc"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; diff --git a/test/Plutip/Contract.purs b/test/Plutip/Contract.purs index ecbe18e71b..eb5ccb90e7 100644 --- a/test/Plutip/Contract.purs +++ b/test/Plutip/Contract.purs @@ -6,15 +6,14 @@ import Prelude import Cardano.AsCbor (decodeCbor) import Cardano.Serialization.Lib (fromBytes) -import Cardano.Transaction.Builder - ( TransactionBuilderStep(..) - , buildTransaction - ) +import Cardano.Transaction.Builder (TransactionBuilderStep(Pay)) import Cardano.Types ( Address , GeneralTransactionMetadata(GeneralTransactionMetadata) , StakeCredential(StakeCredential) , TransactionUnspentOutput(TransactionUnspentOutput) + , _input + , _output ) import Cardano.Types.AssetName as AssetName import Cardano.Types.Coin as Coin @@ -23,7 +22,7 @@ import Cardano.Types.Credential ) import Cardano.Types.Int as Int import Cardano.Types.Mint as Mint -import Cardano.Types.PaymentCredential (PaymentCredential(..)) +import Cardano.Types.PaymentCredential (PaymentCredential(PaymentCredential)) import Cardano.Types.PlutusScript as PlutusScript import Cardano.Types.Value (lovelaceValueOf) import Contract.Address @@ -88,8 +87,6 @@ import Contract.Transaction , TransactionHash(TransactionHash) , TransactionInput(TransactionInput) , TransactionOutput(TransactionOutput) - , _input - , _output , awaitTxConfirmed , balanceTx , balanceTxE @@ -174,7 +171,7 @@ import Data.UInt (UInt) import Effect.Class (liftEffect) import Effect.Exception (error, throw) import JS.BigInt as BigInt -import Mote (group, only, skip, test) +import Mote (group, skip, test) import Mote.TestPlanM (TestPlanM) import Partial.Unsafe (unsafePartial) import Safe.Coerce (coerce) @@ -243,7 +240,7 @@ suite = do lookups = mempty ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints res <- - ( balanceTxE ubTx Map.empty + ( balanceTxE ubTx usedUtxos (mustNotSpendUtxosWithOutRefs $ Map.keys utxos) ) res `shouldSatisfy` isLeft @@ -362,7 +359,7 @@ suite = do Constraints.mustSpendScriptOutput txInput unitRedeemer ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - res <- balanceTxE ubTx Map.empty (mustUseCollateralUtxos Map.empty) + res <- balanceTxE ubTx usedUtxos (mustUseCollateralUtxos Map.empty) res `shouldSatisfy` case _ of Left (InsufficientCollateralUtxos mp) -> Map.isEmpty mp _ -> false @@ -790,7 +787,7 @@ suite = do lookups' = lookups <> Lookups.ownPaymentPubKeyHash pkh ubTx /\ usedUtxos <- mkUnbalancedTx lookups' constraints' - result <- balanceTxE ubTx Map.empty mempty + result <- balanceTxE ubTx usedUtxos mempty result `shouldSatisfy` isLeft test "mustSpendAtLeast succeeds to spend" do @@ -1032,7 +1029,7 @@ suite = do ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints let ubTx' = setGeneralTxMetadata ubTx givenMetadata - bsTx <- signTransaction =<< balanceTx ubTx' Map.empty mempty + bsTx <- signTransaction =<< balanceTx ubTx' usedUtxos mempty txId <- submit bsTx awaitTxConfirmed txId @@ -1720,9 +1717,9 @@ suite = do lookups0 :: Lookups.ScriptLookups lookups0 = mempty - unbalancedTx0 /\ usedUtxos <- mkUnbalancedTx lookups0 constraints0 + unbalancedTx0 /\ usedUtxos0 <- mkUnbalancedTx lookups0 constraints0 - withBalancedTx unbalancedTx0 usedUtxos mempty \balancedTx0 -> do + withBalancedTx unbalancedTx0 usedUtxos0 mempty \balancedTx0 -> do balancedSignedTx0 <- signTransaction balancedTx0 additionalUtxos <- createAdditionalUtxos balancedSignedTx0 @@ -1744,8 +1741,9 @@ suite = do balanceTxConstraints = BalanceTxConstraints.mustUseAdditionalUtxos additionalUtxos - unbalancedTx1 /\ usedUtxos <- mkUnbalancedTx lookups1 constraints1 - balancedTx1 <- balanceTx unbalancedTx1 usedUtxos + unbalancedTx1 /\ usedUtxos1 <- mkUnbalancedTx lookups1 + constraints1 + balancedTx1 <- balanceTx unbalancedTx1 usedUtxos1 balanceTxConstraints balancedSignedTx1 <- signTransaction balancedTx1 diff --git a/test/Plutip/Staking.purs b/test/Plutip/Staking.purs index 0161a2f0a0..5cd61a8c6f 100644 --- a/test/Plutip/Staking.purs +++ b/test/Plutip/Staking.purs @@ -74,7 +74,6 @@ import Data.Array (head, (!!)) import Data.Array as Array import Data.Either (hush) import Data.Foldable (for_) -import Data.Map as Map import Data.Maybe (Maybe(Just, Nothing)) import Data.Newtype (unwrap, wrap) import Data.Posix.Signal (Signal(SIGINT)) diff --git a/test/PrivateKey.purs b/test/PrivateKey.purs index ba463d1d63..46283a4ec8 100644 --- a/test/PrivateKey.purs +++ b/test/PrivateKey.purs @@ -6,14 +6,14 @@ import Cardano.Types ( Ed25519Signature , TransactionWitnessSet(TransactionWitnessSet) , Vkeywitness(Vkeywitness) + , _witnessSet ) import Cardano.Types.Ed25519Signature as Ed25519Signature import Contract.Config (testnetConfig) import Contract.Hashing (publicKeyHash) import Contract.Monad (runContract) import Contract.Transaction - ( _witnessSet - , signTransaction + ( signTransaction ) import Contract.Wallet.Key (publicKeyFromPrivateKey) import Ctl.Internal.Wallet.KeyFile From 8cdb6950a16828aaeb0fdf4e38ae7fe4b1db0dda Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Wed, 3 Jul 2024 16:47:18 +0300 Subject: [PATCH 29/52] Nix formatting --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index c593fefad3..1db377fd0c 100644 --- a/flake.nix +++ b/flake.nix @@ -405,7 +405,7 @@ let ctlPkgsExp = import ./spago-packages.nix { inherit pkgs; }; ctlScaffoldPkgsExp = import ./templates/ctl-scaffold/spago-packages.nix { inherit pkgs; }; - ctlPs = (attrValues ctlPkgsExp.inputs); + ctlPs = attrValues ctlPkgsExp.inputs; ctlScaffoldPs = filter (p: p.name != "cardano-transaction-lib") (attrValues ctlScaffoldPkgsExp.inputs); intersection = pkgs.lib.lists.intersectLists ctlPs ctlScaffoldPs; From 274673657c3fec262a21c66f4b4669db156df5da Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Thu, 4 Jul 2024 03:47:33 +0400 Subject: [PATCH 30/52] Rename extraUtxos -> usedUtxos --- examples/KeyWallet/SignMultiple.purs | 4 ++-- examples/SignMultiple.purs | 4 ++-- src/Contract/Transaction.purs | 14 +++++++------- test/Plutip/Contract.purs | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/KeyWallet/SignMultiple.purs b/examples/KeyWallet/SignMultiple.purs index 7e63e7a15d..8d9c68db6d 100644 --- a/examples/KeyWallet/SignMultiple.purs +++ b/examples/KeyWallet/SignMultiple.purs @@ -48,11 +48,11 @@ main = runKeyWalletContract_ \pkh lovelace unlock -> do txIds <- withBalancedTxs [ { transaction: unbalancedTx0 - , extraUtxos: usedUtxos0 + , usedUtxos: usedUtxos0 , balancerConstraints: mempty } , { transaction: unbalancedTx1 - , extraUtxos: usedUtxos1 + , usedUtxos: usedUtxos1 , balancerConstraints: mempty } ] $ \balancedTxs -> do diff --git a/examples/SignMultiple.purs b/examples/SignMultiple.purs index 2d644a907c..6622c55a0d 100644 --- a/examples/SignMultiple.purs +++ b/examples/SignMultiple.purs @@ -78,11 +78,11 @@ contract = do txIds <- withBalancedTxs [ { transaction: unbalancedTx0 - , extraUtxos: usedUtxos0 + , usedUtxos: usedUtxos0 , balancerConstraints: mempty } , { transaction: unbalancedTx1 - , extraUtxos: usedUtxos1 + , usedUtxos: usedUtxos1 , balancerConstraints: mempty } ] $ \balancedTxs -> do diff --git a/src/Contract/Transaction.purs b/src/Contract/Transaction.purs index 4d66f38eb2..c8a61f9a6d 100644 --- a/src/Contract/Transaction.purs +++ b/src/Contract/Transaction.purs @@ -231,7 +231,7 @@ withBalancedTxs :: forall (a :: Type) . Array { transaction :: Transaction - , extraUtxos :: UtxoMap + , usedUtxos :: UtxoMap , balancerConstraints :: BalanceTxConstraintsBuilder } -> (Array Transaction -> Contract a) @@ -251,10 +251,10 @@ withBalancedTx -> BalanceTxConstraintsBuilder -> (Transaction -> Contract a) -> Contract a -withBalancedTx tx extraUtxos balancerConstraints = +withBalancedTx tx usedUtxos balancerConstraints = withSingleTransaction ( \transaction -> balanceAndLock - { transaction, extraUtxos, balancerConstraints } + { transaction, usedUtxos, balancerConstraints } ) identity tx @@ -290,7 +290,7 @@ balanceTx utx utxos constraints = do balanceTxs :: Array { transaction :: Transaction - , extraUtxos :: UtxoMap + , usedUtxos :: UtxoMap , balancerConstraints :: BalanceTxConstraintsBuilder } -> Contract (Array Transaction) @@ -305,12 +305,12 @@ balanceTxs unbalancedTxs = balanceAndLock :: { transaction :: Transaction - , extraUtxos :: UtxoMap + , usedUtxos :: UtxoMap , balancerConstraints :: BalanceTxConstraintsBuilder } -> Contract Transaction -balanceAndLock { transaction, extraUtxos, balancerConstraints } = do - balancedTx <- balanceTx transaction extraUtxos balancerConstraints +balanceAndLock { transaction, usedUtxos, balancerConstraints } = do + balancedTx <- balanceTx transaction usedUtxos balancerConstraints void $ withUsedTxOuts $ lockTransactionInputs balancedTx pure balancedTx diff --git a/test/Plutip/Contract.purs b/test/Plutip/Contract.purs index eb5ccb90e7..65259e6ee6 100644 --- a/test/Plutip/Contract.purs +++ b/test/Plutip/Contract.purs @@ -2086,11 +2086,11 @@ signMultipleContract = do withBalancedTxs [ { transaction: ubTx1 - , extraUtxos: usedUtxos1 + , usedUtxos: usedUtxos1 , balancerConstraints: mempty } , { transaction: ubTx2 - , extraUtxos: usedUtxos2 + , usedUtxos: usedUtxos2 , balancerConstraints: mempty } ] $ \txs -> do From bfa1b51d4f6647dafa5d4b12fe79f4e47b24b525 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Tue, 9 Jul 2024 00:26:43 +0400 Subject: [PATCH 31/52] Add retry logic for port checks --- src/Internal/Plutip/Server.purs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/Internal/Plutip/Server.purs b/src/Internal/Plutip/Server.purs index 104314d085..dbe4d522f1 100644 --- a/src/Internal/Plutip/Server.purs +++ b/src/Internal/Plutip/Server.purs @@ -23,6 +23,7 @@ import Cardano.Types.PrivateKey (PrivateKey(PrivateKey)) import Contract.Chain (waitNSlots) import Contract.Config (defaultSynchronizationParams, defaultTimeParams) import Contract.Monad (Contract, ContractEnv, liftContractM, runContractInEnv) +import Control.Alternative (guard) import Control.Monad.Error.Class (liftEither, throwError) import Control.Monad.State (State, execState, modify_) import Control.Monad.Trans.Class (lift) @@ -102,6 +103,7 @@ import Effect.Aff.Class (liftAff) import Effect.Aff.Retry ( RetryPolicy , constantDelay + , exponentialBackoff , limitRetriesByCumulativeDelay , recovering ) @@ -438,16 +440,22 @@ configCheck cfg = do , cfg.ogmiosConfig.port /\ "ogmios" , cfg.kupoConfig.port /\ "kupo" ] - occupiedServices <- Array.catMaybes <$> for services \(port /\ service) -> do - isPortAvailable port <#> if _ then Nothing else Just (port /\ service) - unless (Array.null occupiedServices) do - liftEffect $ throw $ - "Unable to run the following services, because the ports are occupied:\ - \\n" <> foldMap printServiceEntry occupiedServices + totalDelay = 10000.00 + retryPolicy = limitRetriesByCumulativeDelay (Milliseconds totalDelay) $ + exponentialBackoff (Milliseconds 100.0) + recovering retryPolicy [ \_ _ -> pure true ] \_ -> do + occupiedServices <- Array.catMaybes <$> for services \service@(port /\ _) -> + do + isPortAvailable port <#> \isAvailable -> Just service <* guard + (not isAvailable) + unless (Array.null occupiedServices) do + liftEffect $ throw $ + "Unable to run the following services, because the ports are occupied:\ + \\n" <> foldMap printServiceEntry occupiedServices where printServiceEntry :: UInt /\ String -> String - printServiceEntry (port /\ service) = - "- " <> service <> " (port: " <> show (UInt.toInt port) <> ")\n" + printServiceEntry (port /\ name) = + "- " <> name <> " (port: " <> show (UInt.toInt port) <> ")\n" -- | Start the plutip cluster, initializing the state with the given -- | UTxO distribution. Also initializes an extra payment key (aka From 29994bffcc26c801d32c5d1030188acf33cff6c0 Mon Sep 17 00:00:00 2001 From: Marcus Fernandes Date: Tue, 9 Jul 2024 15:05:14 -0300 Subject: [PATCH 32/52] Update package versions --- examples/SignData.js | 105 ++++++++++++++++ examples/SignData.purs | 144 +++++++++++++++++++++- package-lock.json | 48 ++++---- package.json | 4 +- packages.dhall | 4 +- spago-packages.nix | 20 +-- src/Contract/Transaction.purs | 1 - src/Contract/Wallet/Key.purs | 4 +- src/Internal/BalanceTx/RedeemerIndex.purs | 4 +- src/Internal/Contract/Wallet.purs | 4 +- src/Internal/Lens.purs | 5 - src/Internal/QueryM/Ogmios.purs | 7 +- src/Internal/Test/E2E/Runner.purs | 10 +- src/Internal/Test/KeyDir.purs | 48 ++++---- src/Internal/Wallet/Cip30Mock.purs | 9 +- src/Internal/Wallet/Key.purs | 4 +- templates/ctl-scaffold/package-lock.json | 48 ++++---- templates/ctl-scaffold/package.json | 4 +- templates/ctl-scaffold/packages.dhall | 4 +- templates/ctl-scaffold/spago-packages.nix | 22 ++-- test/Fixtures.purs | 128 +++++-------------- test/Plutip/Staking.purs | 7 +- test/Unit.purs | 6 - 23 files changed, 417 insertions(+), 223 deletions(-) create mode 100644 examples/SignData.js diff --git a/examples/SignData.js b/examples/SignData.js new file mode 100644 index 0000000000..f681dc76a9 --- /dev/null +++ b/examples/SignData.js @@ -0,0 +1,105 @@ +"use strict"; + +// eslint-disable-next-line no-unused-vars +import * as lib from "@mlabs-haskell/cardano-message-signing"; +import * as CSL from "@mlabs-haskell/cardano-serialization-lib-gc"; + +function opt_chain(maybe, obj) { + const isNothing = x => x === null || x === undefined; + let result = obj; + for (let i = 2; i < arguments.length; i++) { + if (isNothing(result)) { + return maybe.nothing; + } else { + result = result[arguments[i]](); + } + } + return isNothing(result) ? maybe.nothing : maybe.just(result); +} + +const getCoseSign1ProtectedHeaders = coseSign1 => { + return coseSign1.headers().protected().deserialized_headers(); +}; + +export function _getCoseSign1ProtectedHeaderAlg(maybe) { + return coseSign1 => { + const protectedHeaders = getCoseSign1ProtectedHeaders(coseSign1); + return opt_chain( + maybe, + protectedHeaders, + "algorithm_id", + "as_int", + "as_i32" + ); + }; +} + +export function _getCoseSign1ProtectedHeaderAddress(maybe) { + return coseSign1 => { + const protectedHeaders = getCoseSign1ProtectedHeaders(coseSign1); + const cborValue = protectedHeaders.header(lib.Label.new_text("address")); + return opt_chain(maybe, cborValue, "as_bytes"); + }; +} + +export function _getCoseKeyHeaderKty(maybe) { + return coseKey => { + return opt_chain(maybe, coseKey.key_type(), "as_int", "as_i32"); + }; +} + +export function _getCoseKeyHeaderAlg(maybe) { + return coseKey => { + return opt_chain(maybe, coseKey, "algorithm_id", "as_int", "as_i32"); + }; +} + +export function _getCoseKeyHeaderCrv(maybe) { + return coseKey => { + const cborValue = coseKey.header( + lib.Label.new_int( + lib.Int.new_negative(lib.BigNum.from_str("1")) // crv (-1) + ) + ); + return opt_chain(maybe, cborValue, "as_int", "as_i32"); + }; +} + +export function _getCoseSign1ProtectedHeaderKid(maybe) { + return coseSign1 => { + const protectedHeaders = getCoseSign1ProtectedHeaders(coseSign1); + return opt_chain(maybe, protectedHeaders, "key_id"); + }; +} + +export function _getCoseKeyHeaderKid(maybe) { + return coseKey => { + return opt_chain(maybe, coseKey, "key_id"); + }; +} +export function _getCoseKeyHeaderX(maybe) { + return coseKey => { + const cborValue = coseKey.header( + lib.Label.new_int( + lib.Int.new_negative(lib.BigNum.from_str("2")) // x (-2) + ) + ); + return opt_chain(maybe, cborValue, "as_bytes"); + }; +} +export function getSignedData(coseSign1) { + return () => { + return coseSign1.signed_data(null, null).to_bytes(); + }; +} +export function verifySignature(coseSign1) { + return publicKey => sigStructBytes => () => { + const signature = CSL.Ed25519Signature.from_bytes(coseSign1.signature()); + return publicKey.verify(sigStructBytes, signature); + }; +} +const fromBytes = name => bytes => () => { + return lib[name].from_bytes(bytes); +}; +export const fromBytesCoseKey = fromBytes("COSEKey"); +export const fromBytesCoseSign1 = fromBytes("COSESign1"); diff --git a/examples/SignData.purs b/examples/SignData.purs index 36804b2f2a..e777a4a1b2 100644 --- a/examples/SignData.purs +++ b/examples/SignData.purs @@ -2,8 +2,11 @@ module Ctl.Examples.SignData (main, example, contract) where import Contract.Prelude -import Cardano.Types (RawBytes) -import Cardano.Wallet.Cip30.SignData (checkCip30SignDataResponse) +import Cardano.AsCbor (encodeCbor) +import Cardano.MessageSigning (DataSignature) +import Cardano.Types (CborBytes, PublicKey, RawBytes) +import Cardano.Types.PublicKey as PublicKey +import Cardano.Wallet.Cip30.SignData (COSEKey, COSESign1) import Contract.Address (Address) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') @@ -12,6 +15,9 @@ import Contract.Wallet (getChangeAddress, getRewardAddresses, signData) import Data.Array (head) as Array import Data.ByteArray (byteArrayFromAscii) import Data.Maybe (fromJust) +import Effect.Aff (error) +import Effect.Class (class MonadEffect) +import Effect.Exception (throw, throwException) import Partial.Unsafe (unsafePartial) main :: Effect Unit @@ -41,3 +47,137 @@ contract = do dataSignature <- signData address payload logInfo' $ "signData " <> addressLabel <> ": " <> show dataSignature void $ liftAff $ checkCip30SignDataResponse address dataSignature + +type DeserializedDataSignature = + { coseKey :: COSEKey + , coseSign1 :: COSESign1 + } + +checkCip30SignDataResponse + :: Address -> DataSignature -> Aff DeserializedDataSignature +checkCip30SignDataResponse address { key, signature } = do + coseSign1 <- liftEffect $ fromBytesCoseSign1 signature + coseKey <- liftEffect $ fromBytesCoseKey key + + checkCoseSign1ProtectedHeaders coseSign1 + checkCoseKeyHeaders coseKey + checkKidHeaders coseSign1 coseKey + liftEffect $ checkVerification coseSign1 coseKey + pure { coseKey, coseSign1 } + where + checkCoseSign1ProtectedHeaders :: COSESign1 -> Aff Unit + checkCoseSign1ProtectedHeaders coseSign1 = do + assertTrue "COSE_Sign1's alg (1) header must be set to EdDSA (-8)" + (getCoseSign1ProtectedHeaderAlg coseSign1 == Just (-8)) + + assertTrue "COSE_Sign1's \"address\" header must be set to address bytes" + ( getCoseSign1ProtectedHeaderAddress coseSign1 + == Just (encodeCbor address) + ) + + checkCoseKeyHeaders :: COSEKey -> Aff Unit + checkCoseKeyHeaders coseKey = do + assertTrue "COSE_Key's kty (1) header must be set to OKP (1)" + (getCoseKeyHeaderKty coseKey == Just 1) + + assertTrue "COSE_Key's alg (3) header must be set to EdDSA (-8)" + (getCoseKeyHeaderAlg coseKey == Just (-8)) + + assertTrue "COSE_Key's crv (-1) header must be set to Ed25519 (6)" + (getCoseKeyHeaderCrv coseKey == Just (6)) + + checkKidHeaders :: COSESign1 -> COSEKey -> Aff Unit + checkKidHeaders coseSign1 coseKey = + assertTrue + "COSE_Sign1's kid (4) and COSE_Key's kid (2) headers, if present, must \ + \be set to the same value" + (getCoseSign1ProtectedHeaderKid coseSign1 == getCoseKeyHeaderKid coseKey) + + checkVerification :: COSESign1 -> COSEKey -> Effect Unit + checkVerification coseSign1 coseKey = do + publicKey <- + errMaybe "COSE_Key's x (-2) header must be set to public key bytes" + $ getCoseKeyHeaderX coseKey + >>= PublicKey.fromRawBytes + sigStructBytes <- getSignedData coseSign1 + assertTrue "Signature verification failed" + =<< verifySignature coseSign1 publicKey sigStructBytes + +getCoseSign1ProtectedHeaderAlg :: COSESign1 -> Maybe Int +getCoseSign1ProtectedHeaderAlg = _getCoseSign1ProtectedHeaderAlg maybeFfiHelper + +getCoseSign1ProtectedHeaderAddress :: COSESign1 -> Maybe CborBytes +getCoseSign1ProtectedHeaderAddress = + _getCoseSign1ProtectedHeaderAddress maybeFfiHelper + +type MaybeFfiHelper = + { nothing :: forall (x :: Type). Maybe x + , just :: forall (x :: Type). x -> Maybe x + , from :: forall (x :: Type). x -> Maybe x -> x + } + +maybeFfiHelper :: MaybeFfiHelper +maybeFfiHelper = { nothing: Nothing, just: Just, from: fromMaybe } + +getCoseKeyHeaderKty :: COSEKey -> Maybe Int +getCoseKeyHeaderKty = _getCoseKeyHeaderKty maybeFfiHelper + +getCoseKeyHeaderAlg :: COSEKey -> Maybe Int +getCoseKeyHeaderAlg = _getCoseKeyHeaderAlg maybeFfiHelper + +getCoseKeyHeaderCrv :: COSEKey -> Maybe Int +getCoseKeyHeaderCrv = _getCoseKeyHeaderCrv maybeFfiHelper + +getCoseSign1ProtectedHeaderKid :: COSESign1 -> Maybe RawBytes +getCoseSign1ProtectedHeaderKid = _getCoseSign1ProtectedHeaderKid maybeFfiHelper + +getCoseKeyHeaderKid :: COSEKey -> Maybe RawBytes +getCoseKeyHeaderKid = _getCoseKeyHeaderKid maybeFfiHelper + +assertTrue + :: forall (m :: Type -> Type) + . Applicative m + => MonadEffect m + => String + -> Boolean + -> m Unit +assertTrue msg b = unless b $ liftEffect $ throwException $ error msg + +errMaybe + :: forall (m :: Type -> Type) (a :: Type) + . MonadEffect m + => String + -> Maybe a + -> m a +errMaybe msg = maybe (liftEffect $ throw msg) pure + +getCoseKeyHeaderX :: COSEKey -> Maybe RawBytes +getCoseKeyHeaderX = _getCoseKeyHeaderX maybeFfiHelper + +-------------------------------------------------------------------------------- +-- Foreign functions +-------------------------------------------------------------------------------- + +foreign import _getCoseSign1ProtectedHeaderAlg + :: MaybeFfiHelper -> COSESign1 -> Maybe Int + +foreign import _getCoseSign1ProtectedHeaderAddress + :: MaybeFfiHelper -> COSESign1 -> Maybe CborBytes + +foreign import _getCoseKeyHeaderX :: MaybeFfiHelper -> COSEKey -> Maybe RawBytes +foreign import _getCoseKeyHeaderKty :: MaybeFfiHelper -> COSEKey -> Maybe Int +foreign import _getCoseKeyHeaderAlg :: MaybeFfiHelper -> COSEKey -> Maybe Int +foreign import _getCoseKeyHeaderCrv :: MaybeFfiHelper -> COSEKey -> Maybe Int +foreign import _getCoseSign1ProtectedHeaderKid + :: MaybeFfiHelper -> COSESign1 -> Maybe RawBytes + +foreign import _getCoseKeyHeaderKid + :: MaybeFfiHelper -> COSEKey -> Maybe RawBytes + +foreign import getSignedData :: COSESign1 -> Effect CborBytes + +foreign import verifySignature + :: COSESign1 -> PublicKey -> CborBytes -> Effect Boolean + +foreign import fromBytesCoseSign1 :: CborBytes -> Effect COSESign1 +foreign import fromBytesCoseKey :: CborBytes -> Effect COSEKey diff --git a/package-lock.json b/package-lock.json index a9845f2b0e..ab2b617850 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,8 +8,10 @@ "name": "cardano-transaction-lib", "license": "MIT", "dependencies": { + "@emurgo/cardano-serialization-lib-browser": "v12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-nodejs": "v12.0.0-alpha.31", "@mlabs-haskell/cardano-message-signing": "^1.0.1", - "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", + "@mlabs-haskell/cardano-serialization-lib-gc": "v12.0.0-alpha.31", "@mlabs-haskell/json-bigint": "2.0.0", "@mlabs-haskell/uplc-apply-args": "2.0.1", "@noble/secp256k1": "^1.7.0", @@ -60,14 +62,14 @@ "integrity": "sha512-PoKh1tQnJX18f8iEr8Jk1KXxKCn9eqaSslMI1pyOJvYRJhQVDLCh0+9YReufjp0oFJIY1ShcrR+4/WnECVZUKQ==" }, "node_modules/@emurgo/cardano-serialization-lib-browser": { - "version": "11.5.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-11.5.0.tgz", - "integrity": "sha512-qchOJ9NYDUz10tzs5r5QhP9hK0p+ZOlRiBwPdTAxqAYLw/8emYBkQQLaS8T1DF6EkeudyrgS00ym5Trw1fo4iA==" + "version": "12.0.0-alpha.31", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-12.0.0-alpha.31.tgz", + "integrity": "sha512-LEMiaui1ByuVuesWGUQ4CzksZJW9FeL/KL8HN2smSTjuCA3IaAp2VXZPxPjxP/0VbF+EM1aLkPn6DD02U/qy5Q==" }, "node_modules/@emurgo/cardano-serialization-lib-nodejs": { - "version": "11.5.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-11.5.0.tgz", - "integrity": "sha512-IlVABlRgo9XaTR1NunwZpWcxnfEv04ba2l1vkUz4S1W7Jt36F4CtffP+jPeqBZGnAe+fnUwo0XjIJC3ZTNToNQ==" + "version": "12.0.0-alpha.31", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-12.0.0-alpha.31.tgz", + "integrity": "sha512-YvE4JmTwQTM+8Blbmfa7qv44vWr3qWRn5RsfjxmyptyJwAk0Z/AfGQjYyWO/LmFsj8YCIZD2lS80LhrzzkN+Kw==" }, "node_modules/@esbuild/android-arm": { "version": "0.18.11", @@ -501,12 +503,12 @@ } }, "node_modules/@mlabs-haskell/cardano-serialization-lib-gc": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-1.0.10.tgz", - "integrity": "sha512-7XFxxMvZH6oogWVP/teveVRUTRboWfY5fT0bkRDu68u9yb2HBjoMxkCkmF7MvJBVs2i0unt4UnzcrNm0dmHriQ==", + "version": "12.0.0-alpha.31", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-12.0.0-alpha.31.tgz", + "integrity": "sha512-QQBzl7rNRy7wk37uxzWJXCZfZRt3aTlfQb3kmb10ulY/janlUNETmS09OtiJbK/BdV5Fu7Gv+Mdda3ggMIL/bg==", "dependencies": { - "@emurgo/cardano-serialization-lib-browser": "^11.2.1", - "@emurgo/cardano-serialization-lib-nodejs": "^11.2.1", + "@emurgo/cardano-serialization-lib-browser": "^12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-nodejs": "^12.0.0-alpha.31", "@mlabs-haskell/csl-gc-wrapper": "^1.0.2" } }, @@ -6391,14 +6393,14 @@ "integrity": "sha512-PoKh1tQnJX18f8iEr8Jk1KXxKCn9eqaSslMI1pyOJvYRJhQVDLCh0+9YReufjp0oFJIY1ShcrR+4/WnECVZUKQ==" }, "@emurgo/cardano-serialization-lib-browser": { - "version": "11.5.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-11.5.0.tgz", - "integrity": "sha512-qchOJ9NYDUz10tzs5r5QhP9hK0p+ZOlRiBwPdTAxqAYLw/8emYBkQQLaS8T1DF6EkeudyrgS00ym5Trw1fo4iA==" + "version": "12.0.0-alpha.31", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-12.0.0-alpha.31.tgz", + "integrity": "sha512-LEMiaui1ByuVuesWGUQ4CzksZJW9FeL/KL8HN2smSTjuCA3IaAp2VXZPxPjxP/0VbF+EM1aLkPn6DD02U/qy5Q==" }, "@emurgo/cardano-serialization-lib-nodejs": { - "version": "11.5.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-11.5.0.tgz", - "integrity": "sha512-IlVABlRgo9XaTR1NunwZpWcxnfEv04ba2l1vkUz4S1W7Jt36F4CtffP+jPeqBZGnAe+fnUwo0XjIJC3ZTNToNQ==" + "version": "12.0.0-alpha.31", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-12.0.0-alpha.31.tgz", + "integrity": "sha512-YvE4JmTwQTM+8Blbmfa7qv44vWr3qWRn5RsfjxmyptyJwAk0Z/AfGQjYyWO/LmFsj8YCIZD2lS80LhrzzkN+Kw==" }, "@esbuild/android-arm": { "version": "0.18.11", @@ -6625,12 +6627,12 @@ } }, "@mlabs-haskell/cardano-serialization-lib-gc": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-1.0.10.tgz", - "integrity": "sha512-7XFxxMvZH6oogWVP/teveVRUTRboWfY5fT0bkRDu68u9yb2HBjoMxkCkmF7MvJBVs2i0unt4UnzcrNm0dmHriQ==", + "version": "12.0.0-alpha.31", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-12.0.0-alpha.31.tgz", + "integrity": "sha512-QQBzl7rNRy7wk37uxzWJXCZfZRt3aTlfQb3kmb10ulY/janlUNETmS09OtiJbK/BdV5Fu7Gv+Mdda3ggMIL/bg==", "requires": { - "@emurgo/cardano-serialization-lib-browser": "^11.2.1", - "@emurgo/cardano-serialization-lib-nodejs": "^11.2.1", + "@emurgo/cardano-serialization-lib-browser": "^12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-nodejs": "^12.0.0-alpha.31", "@mlabs-haskell/csl-gc-wrapper": "^1.0.2" } }, diff --git a/package.json b/package.json index 4cb9d98924..d47e7be018 100755 --- a/package.json +++ b/package.json @@ -32,7 +32,9 @@ "license": "MIT", "dependencies": { "@mlabs-haskell/cardano-message-signing": "^1.0.1", - "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", + "@mlabs-haskell/cardano-serialization-lib-gc": "v12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-nodejs": "v12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-browser": "v12.0.0-alpha.31", "@mlabs-haskell/json-bigint": "2.0.0", "@mlabs-haskell/uplc-apply-args": "2.0.1", "@noble/secp256k1": "^1.7.0", diff --git a/packages.dhall b/packages.dhall index ab0b497fd7..e85d9abb73 100644 --- a/packages.dhall +++ b/packages.dhall @@ -280,7 +280,7 @@ let additions = ] , repo = "https://github.com/mlabs-haskell/purescript-cardano-serialization-lib" - , version = "26d437c3f398172c839b93b57c30eb43a7fa7ca0" + , version = "v1.0.0" } , cardano-plutus-data-schema = { dependencies = [ "prelude" ] @@ -435,7 +435,7 @@ let additions = , "unsafe-coerce" ] , repo = "https://github.com/mlabs-haskell/purescript-cardano-types" - , version = "v1.0.1" + , version = "v2.0.0" } , cardano-message-signing = { dependencies = diff --git a/spago-packages.nix b/spago-packages.nix index 0c24697833..48997ba7f8 100644 --- a/spago-packages.nix +++ b/spago-packages.nix @@ -214,8 +214,8 @@ let version = "v1.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-collateral-select"; - rev = "296fe978a292f36d9fd2c18a2d173772301e71b9"; - sha256 = "09mcdjndalc9a91l0kx9s0p3bh5j58lji230b142yvgk8qmmayi9"; + rev = "193bf49be979b42aa1f0f9cb3d7582d6bc98e3b9"; + sha256 = "1jbl6k779brbqzf7jf80is63b23k3mqzf2mzr222qswd3wg8s5b0"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; @@ -238,8 +238,8 @@ let version = "v1.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-key-wallet"; - rev = "f107d3dce0a0f1f866a4682783376ea9f476fd7d"; - sha256 = "0jxbzdjfvxvrf2nmay493x004d0y5jmnfqj06064nfihg5x0w2r8"; + rev = "fd50834bad329b3064b602e6487e9471ea102341"; + sha256 = "0bgizyhrpmj51lz24cnr6wvxwgvm41z24c66kk3lzhwq798n5q50"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; @@ -271,11 +271,11 @@ let "cardano-serialization-lib" = pkgs.stdenv.mkDerivation { name = "cardano-serialization-lib"; - version = "26d437c3f398172c839b93b57c30eb43a7fa7ca0"; + version = "v1.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-serialization-lib"; - rev = "26d437c3f398172c839b93b57c30eb43a7fa7ca0"; - sha256 = "1ikz6j3jvls3cvl6znrw55f59abzdaf7ggd2x7j3f81m5cvkxggr"; + rev = "903bf0adeefedc4d065ad6523ad079433bdd8e32"; + sha256 = "0jlfxrx037hyd4v0j7l2b16yxlm6nw6qlnr992hj9nzip36vbpfg"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; @@ -283,11 +283,11 @@ let "cardano-types" = pkgs.stdenv.mkDerivation { name = "cardano-types"; - version = "v1.0.1"; + version = "v2.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-types"; - rev = "715d4b2dcf8b29cb45001209ee562f758a513261"; - sha256 = "1xcrdmpwd3qcdiyjfrj0z2dh56l4z1s97r25b6nhlqwmwz7qz19z"; + rev = "780c28ee27d0ba7e76884a565ad60dea0a414842"; + sha256 = "1my7fgk218h6yllw09zf1m55hpn787mjq79whxxm9lqgarrdp66z"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; diff --git a/src/Contract/Transaction.purs b/src/Contract/Transaction.purs index 1c038632f9..1ed8e59f25 100644 --- a/src/Contract/Transaction.purs +++ b/src/Contract/Transaction.purs @@ -132,7 +132,6 @@ import Ctl.Internal.Lens , _scriptRef , _totalCollateral , _ttl - , _update , _validityStartInterval , _vkeys , _withdrawals diff --git a/src/Contract/Wallet/Key.purs b/src/Contract/Wallet/Key.purs index 0849396a62..ddbb9e63c0 100644 --- a/src/Contract/Wallet/Key.purs +++ b/src/Contract/Wallet/Key.purs @@ -8,8 +8,8 @@ import Cardano.Types (PrivateKey, PublicKey) import Cardano.Types.PrivateKey as PrivateKey import Ctl.Internal.Wallet.Key ( KeyWallet(KeyWallet) - , keyWalletPrivatePaymentKey - , keyWalletPrivateStakeKey + , getPrivatePaymentKey + , getPrivateStakeKey , privateKeysToKeyWallet ) as X import Ctl.Internal.Wallet.Spec diff --git a/src/Internal/BalanceTx/RedeemerIndex.purs b/src/Internal/BalanceTx/RedeemerIndex.purs index 1b4182808b..47a9388101 100644 --- a/src/Internal/BalanceTx/RedeemerIndex.purs +++ b/src/Internal/BalanceTx/RedeemerIndex.purs @@ -81,7 +81,7 @@ unindexedRedeemerToRedeemer :: UnindexedRedeemer -> Redeemer unindexedRedeemerToRedeemer (UnindexedRedeemer { datum, purpose }) = Redeemer { tag: redeemerPurposeToRedeemerTag purpose - , "data": datum + , "data": wrap datum , index: BigNum.zero , exUnits: ExUnits.empty } @@ -107,7 +107,7 @@ indexedRedeemerToRedeemer (IndexedRedeemer { tag, datum, index }) = Redeemer { tag , index: BigNum.fromInt index - , data: datum + , data: wrap datum , exUnits: ExUnits.empty } diff --git a/src/Internal/Contract/Wallet.purs b/src/Internal/Contract/Wallet.purs index 851939cfbe..a2808b2875 100644 --- a/src/Internal/Contract/Wallet.purs +++ b/src/Internal/Contract/Wallet.purs @@ -28,6 +28,7 @@ import Cardano.Types.Value (Value, valueToCoin) import Cardano.Types.Value (geq, lovelaceValueOf, sum) as Value import Control.Monad.Reader.Trans (asks) import Control.Parallel (parTraverse) +import Ctl.Internal.BalanceTx.Collateral.Select (minRequiredCollateral) import Ctl.Internal.Contract (getProtocolParameters) import Ctl.Internal.Contract.Monad (Contract, filterLockedUtxos, getQueryHandle) import Ctl.Internal.Helpers (bugTrackerLink, liftM, liftedM) @@ -136,7 +137,8 @@ getWalletCollateral = do utxos <- (liftAff $ queryHandle.utxosAt addr) <#> hush >>> fromMaybe Map.empty >>= filterLockedUtxos - mColl <- liftAff $ (unwrap kw).selectCollateral coinsPerUtxoByte + mColl <- liftAff $ (unwrap kw).selectCollateral minRequiredCollateral + coinsPerUtxoByte (UInt.toInt maxCollateralInputs) utxos pure mColl diff --git a/src/Internal/Lens.purs b/src/Internal/Lens.purs index 94a9bf7866..4be16aa3e4 100644 --- a/src/Internal/Lens.purs +++ b/src/Internal/Lens.purs @@ -25,7 +25,6 @@ module Ctl.Internal.Lens , _scriptRef , _totalCollateral , _ttl - , _update , _validityStartInterval , _vkeys , _withdrawals @@ -56,7 +55,6 @@ import Cardano.Types , TransactionOutput , TransactionUnspentOutput , TransactionWitnessSet - , Update , Value , Vkeywitness ) @@ -129,9 +127,6 @@ _auxiliaryDataHash = _Newtype <<< prop (Proxy :: Proxy "auxiliaryDataHash") _ttl :: Lens' TransactionBody (Maybe Slot) _ttl = _Newtype <<< prop (Proxy :: Proxy "ttl") -_update :: Lens' TransactionBody (Maybe Update) -_update = _Newtype <<< prop (Proxy :: Proxy "update") - _validityStartInterval :: Lens' TransactionBody (Maybe Slot) _validityStartInterval = _Newtype <<< prop (Proxy :: Proxy "validityStartInterval") diff --git a/src/Internal/QueryM/Ogmios.purs b/src/Internal/QueryM/Ogmios.purs index 8d1cb2eb82..2cdbd39c02 100644 --- a/src/Internal/QueryM/Ogmios.purs +++ b/src/Internal/QueryM/Ogmios.purs @@ -99,7 +99,7 @@ import Cardano.Serialization.Lib (fromBytes, ipv4_new) import Cardano.Types ( Bech32String , BigNum(BigNum) - , Language(PlutusV1, PlutusV2) + , Language(PlutusV1, PlutusV2, PlutusV3) , RedeemerTag , VRFKeyHash(VRFKeyHash) ) @@ -1220,6 +1220,11 @@ instance EncodeAeson AdditionalUtxoSet where { "language": "plutus:v2" , "cbor": byteArrayToHex $ unwrap $ PlutusScript.getBytes ps } + encodeScriptRef (PlutusScriptRef (ps@(PlutusScript (_ /\ PlutusV3)))) = + encodeAeson + { "language": "plutus:v2" + , "cbor": byteArrayToHex $ unwrap $ PlutusScript.getBytes ps + } encodeValue :: Value -> Aeson encodeValue value = encodeMap $ map encodeMap $ Map.union adaPart nonAdaPart diff --git a/src/Internal/Test/E2E/Runner.purs b/src/Internal/Test/E2E/Runner.purs index debdd06738..76ec5618ae 100644 --- a/src/Internal/Test/E2E/Runner.purs +++ b/src/Internal/Test/E2E/Runner.purs @@ -75,8 +75,8 @@ import Ctl.Internal.Test.E2E.Wallets import Ctl.Internal.Test.UtxoDistribution (withStakeKey) import Ctl.Internal.Wallet.Key ( PrivateStakeKey - , keyWalletPrivatePaymentKey - , keyWalletPrivateStakeKey + , getPrivatePaymentKey + , getPrivateStakeKey ) import Data.Array (catMaybes, mapMaybe, nub) import Data.Array as Array @@ -263,13 +263,15 @@ testPlan opts@{ tests } rt@{ wallets } = -- https://github.com/Plutonomicon/cardano-transaction-lib/issues/1197 liftAff $ withPlutipContractEnv (buildPlutipConfig opts) distr \env wallet -> do + kwPaymentKey <- liftAff $ getPrivatePaymentKey wallet + kwMStakeKey <- liftAff $ getPrivateStakeKey wallet (clusterSetup :: ClusterSetup) <- case env.backend of CtlBackend backend _ -> pure { ogmiosConfig: backend.ogmios.config , kupoConfig: backend.kupoConfig , keys: - { payment: keyWalletPrivatePaymentKey wallet - , stake: keyWalletPrivateStakeKey wallet + { payment: kwPaymentKey + , stake: kwMStakeKey } } _ -> liftEffect $ throw "Unsupported backend" diff --git a/src/Internal/Test/KeyDir.purs b/src/Internal/Test/KeyDir.purs index 366c40d483..3738df2f72 100644 --- a/src/Internal/Test/KeyDir.purs +++ b/src/Internal/Test/KeyDir.purs @@ -38,8 +38,8 @@ import Contract.Wallet , withKeyWallet ) import Contract.Wallet.Key - ( keyWalletPrivatePaymentKey - , keyWalletPrivateStakeKey + ( getPrivatePaymentKey + , getPrivateStakeKey ) import Contract.Wallet.KeyFile ( privatePaymentKeyFromTextEnvelope @@ -287,9 +287,9 @@ backupWallets backup env walletsArray = do address <- liftAff $ Address.toBech32 <$> (unwrap wallet).address env.networkId + payment <- getPrivatePaymentKey wallet + mbStake <- getPrivateStakeKey wallet let - payment = keyWalletPrivatePaymentKey wallet - mbStake = keyWalletPrivateStakeKey wallet folder = Path.concat [ backup, address ] mkdir folder @@ -303,13 +303,12 @@ fundWallets :: ContractEnv -> Array KeyWallet -> Array (Array UtxoAmount) -> Aff BigNum fundWallets env walletsArray distrArray = runContractInEnv env $ noLogs do logTrace' "Funding wallets" - let - constraints = flip foldMap (Array.zip walletsArray distrArray) - \(wallet /\ walletDistr) -> flip foldMap walletDistr - \value -> mustPayToKeyWallet wallet $ - Value.mkValue - (wrap value) - MultiAsset.empty + constraints <- liftAff $ flip foldMap (Array.zip walletsArray distrArray) + \(wallet /\ walletDistr) -> flip foldMap walletDistr + \value -> mustPayToKeyWallet wallet $ + Value.mkValue + (wrap value) + MultiAsset.empty txHash <- submitTxFromConstraints mempty constraints awaitTxConfirmed txHash @@ -446,18 +445,19 @@ mustPayToKeyWallet :: forall (i :: Type) (o :: Type) . KeyWallet -> Value - -> TxConstraints -mustPayToKeyWallet wallet value = + -> Aff TxConstraints +mustPayToKeyWallet wallet value = do + kwPaymentKey <- getPrivatePaymentKey wallet + kwMStakeKey <- getPrivateStakeKey wallet let convert = PublicKey.hash <<< PrivateKey.toPublicKey - payment = over wrap convert $ keyWalletPrivatePaymentKey wallet - mbStake = over wrap convert <$> keyWalletPrivateStakeKey wallet - in - maybe - -- We don't use `mustPayToPubKey payment` to avoid the compile-time - -- warning that is tied to it (it should not be propagated to - -- `runContractTestWithKeyDir`) - (singleton <<< MustPayToPubKeyAddress payment Nothing Nothing Nothing) - (mustPayToPubKeyAddress payment) - mbStake - value + payment = over wrap convert $ kwPaymentKey + mbStake = over wrap convert <$> kwMStakeKey + pure $ maybe + -- We don't use `mustPayToPubKey payment` to avoid the compile-time + -- warning that is tied to it (it should not be propagated to + -- `runContractTestWithKeyDir`) + (singleton <<< MustPayToPubKeyAddress payment Nothing Nothing Nothing) + (mustPayToPubKeyAddress payment) + mbStake + value diff --git a/src/Internal/Wallet/Cip30Mock.purs b/src/Internal/Wallet/Cip30Mock.purs index 3a0d4079e5..e585d8efd3 100644 --- a/src/Internal/Wallet/Cip30Mock.purs +++ b/src/Internal/Wallet/Cip30Mock.purs @@ -28,6 +28,7 @@ import Control.Monad.Error.Class (liftMaybe, try) import Control.Monad.Reader (ask) import Control.Monad.Reader.Class (local) import Control.Promise (fromAff) +import Ctl.Internal.BalanceTx.Collateral.Select (minRequiredCollateral) import Ctl.Internal.Contract.Monad (getQueryHandle) import Ctl.Internal.Helpers (liftEither) import Ctl.Internal.Wallet @@ -92,8 +93,9 @@ withCip30Mock -> Contract a -> Contract a withCip30Mock (KeyWallet keyWallet) mock contract = do - cip30Mock <- mkCip30Mock keyWallet.paymentKey - keyWallet.stakeKey + kwPaymentKey <- liftAff keyWallet.paymentKey + kwMStakeKey <- liftAff keyWallet.stakeKey + cip30Mock <- mkCip30Mock kwPaymentKey kwMStakeKey deleteMock <- liftEffect $ injectCip30Mock mockString cip30Mock wallet <- liftAff mkWalletAff' res <- try $ local _ { wallet = Just wallet } contract @@ -131,7 +133,8 @@ mkCip30Mock pKey mSKey = do maxCollateralInputs = UInt.toInt $ pparams.maxCollateralInputs coll <- liftAff $ - (unwrap keyWallet).selectCollateral coinsPerUtxoByte + (unwrap keyWallet).selectCollateral minRequiredCollateral + coinsPerUtxoByte maxCollateralInputs utxos pure $ fold coll diff --git a/src/Internal/Wallet/Key.purs b/src/Internal/Wallet/Key.purs index add12d9ccd..641d4df359 100644 --- a/src/Internal/Wallet/Key.purs +++ b/src/Internal/Wallet/Key.purs @@ -6,8 +6,8 @@ import Cardano.Wallet.Key ( KeyWallet(KeyWallet) , PrivatePaymentKey(PrivatePaymentKey) , PrivateStakeKey(PrivateStakeKey) - , keyWalletPrivatePaymentKey - , keyWalletPrivateStakeKey + , getPrivatePaymentKey + , getPrivateStakeKey , privateKeysToAddress , privateKeysToKeyWallet ) as KeyWallet diff --git a/templates/ctl-scaffold/package-lock.json b/templates/ctl-scaffold/package-lock.json index 561dc93e3a..6d800dbebf 100644 --- a/templates/ctl-scaffold/package-lock.json +++ b/templates/ctl-scaffold/package-lock.json @@ -9,8 +9,10 @@ "version": "0.1.0", "license": "MIT", "dependencies": { + "@emurgo/cardano-serialization-lib-browser": "v12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-nodejs": "v12.0.0-alpha.31", "@mlabs-haskell/cardano-message-signing": "^1.0.1", - "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", + "@mlabs-haskell/cardano-serialization-lib-gc": "v12.0.0-alpha.31", "@mlabs-haskell/json-bigint": "2.0.0", "@mlabs-haskell/uplc-apply-args": "2.0.1", "@noble/secp256k1": "^1.7.0", @@ -58,14 +60,14 @@ "integrity": "sha512-PoKh1tQnJX18f8iEr8Jk1KXxKCn9eqaSslMI1pyOJvYRJhQVDLCh0+9YReufjp0oFJIY1ShcrR+4/WnECVZUKQ==" }, "node_modules/@emurgo/cardano-serialization-lib-browser": { - "version": "11.5.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-11.5.0.tgz", - "integrity": "sha512-qchOJ9NYDUz10tzs5r5QhP9hK0p+ZOlRiBwPdTAxqAYLw/8emYBkQQLaS8T1DF6EkeudyrgS00ym5Trw1fo4iA==" + "version": "12.0.0-alpha.31", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-12.0.0-alpha.31.tgz", + "integrity": "sha512-LEMiaui1ByuVuesWGUQ4CzksZJW9FeL/KL8HN2smSTjuCA3IaAp2VXZPxPjxP/0VbF+EM1aLkPn6DD02U/qy5Q==" }, "node_modules/@emurgo/cardano-serialization-lib-nodejs": { - "version": "11.5.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-11.5.0.tgz", - "integrity": "sha512-IlVABlRgo9XaTR1NunwZpWcxnfEv04ba2l1vkUz4S1W7Jt36F4CtffP+jPeqBZGnAe+fnUwo0XjIJC3ZTNToNQ==" + "version": "12.0.0-alpha.31", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-12.0.0-alpha.31.tgz", + "integrity": "sha512-YvE4JmTwQTM+8Blbmfa7qv44vWr3qWRn5RsfjxmyptyJwAk0Z/AfGQjYyWO/LmFsj8YCIZD2lS80LhrzzkN+Kw==" }, "node_modules/@esbuild/android-arm": { "version": "0.18.11", @@ -499,12 +501,12 @@ } }, "node_modules/@mlabs-haskell/cardano-serialization-lib-gc": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-1.0.10.tgz", - "integrity": "sha512-7XFxxMvZH6oogWVP/teveVRUTRboWfY5fT0bkRDu68u9yb2HBjoMxkCkmF7MvJBVs2i0unt4UnzcrNm0dmHriQ==", + "version": "12.0.0-alpha.31", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-12.0.0-alpha.31.tgz", + "integrity": "sha512-QQBzl7rNRy7wk37uxzWJXCZfZRt3aTlfQb3kmb10ulY/janlUNETmS09OtiJbK/BdV5Fu7Gv+Mdda3ggMIL/bg==", "dependencies": { - "@emurgo/cardano-serialization-lib-browser": "^11.2.1", - "@emurgo/cardano-serialization-lib-nodejs": "^11.2.1", + "@emurgo/cardano-serialization-lib-browser": "^12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-nodejs": "^12.0.0-alpha.31", "@mlabs-haskell/csl-gc-wrapper": "^1.0.2" } }, @@ -5518,14 +5520,14 @@ "integrity": "sha512-PoKh1tQnJX18f8iEr8Jk1KXxKCn9eqaSslMI1pyOJvYRJhQVDLCh0+9YReufjp0oFJIY1ShcrR+4/WnECVZUKQ==" }, "@emurgo/cardano-serialization-lib-browser": { - "version": "11.5.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-11.5.0.tgz", - "integrity": "sha512-qchOJ9NYDUz10tzs5r5QhP9hK0p+ZOlRiBwPdTAxqAYLw/8emYBkQQLaS8T1DF6EkeudyrgS00ym5Trw1fo4iA==" + "version": "12.0.0-alpha.31", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-12.0.0-alpha.31.tgz", + "integrity": "sha512-LEMiaui1ByuVuesWGUQ4CzksZJW9FeL/KL8HN2smSTjuCA3IaAp2VXZPxPjxP/0VbF+EM1aLkPn6DD02U/qy5Q==" }, "@emurgo/cardano-serialization-lib-nodejs": { - "version": "11.5.0", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-11.5.0.tgz", - "integrity": "sha512-IlVABlRgo9XaTR1NunwZpWcxnfEv04ba2l1vkUz4S1W7Jt36F4CtffP+jPeqBZGnAe+fnUwo0XjIJC3ZTNToNQ==" + "version": "12.0.0-alpha.31", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-12.0.0-alpha.31.tgz", + "integrity": "sha512-YvE4JmTwQTM+8Blbmfa7qv44vWr3qWRn5RsfjxmyptyJwAk0Z/AfGQjYyWO/LmFsj8YCIZD2lS80LhrzzkN+Kw==" }, "@esbuild/android-arm": { "version": "0.18.11", @@ -5752,12 +5754,12 @@ } }, "@mlabs-haskell/cardano-serialization-lib-gc": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-1.0.10.tgz", - "integrity": "sha512-7XFxxMvZH6oogWVP/teveVRUTRboWfY5fT0bkRDu68u9yb2HBjoMxkCkmF7MvJBVs2i0unt4UnzcrNm0dmHriQ==", + "version": "12.0.0-alpha.31", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-12.0.0-alpha.31.tgz", + "integrity": "sha512-QQBzl7rNRy7wk37uxzWJXCZfZRt3aTlfQb3kmb10ulY/janlUNETmS09OtiJbK/BdV5Fu7Gv+Mdda3ggMIL/bg==", "requires": { - "@emurgo/cardano-serialization-lib-browser": "^11.2.1", - "@emurgo/cardano-serialization-lib-nodejs": "^11.2.1", + "@emurgo/cardano-serialization-lib-browser": "^12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-nodejs": "^12.0.0-alpha.31", "@mlabs-haskell/csl-gc-wrapper": "^1.0.2" } }, diff --git a/templates/ctl-scaffold/package.json b/templates/ctl-scaffold/package.json index f34f4d9e34..b746c3ce7d 100644 --- a/templates/ctl-scaffold/package.json +++ b/templates/ctl-scaffold/package.json @@ -26,7 +26,9 @@ "license": "MIT", "dependencies": { "@mlabs-haskell/cardano-message-signing": "^1.0.1", - "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", + "@mlabs-haskell/cardano-serialization-lib-gc": "v12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-nodejs": "v12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-browser": "v12.0.0-alpha.31", "@mlabs-haskell/json-bigint": "2.0.0", "@mlabs-haskell/uplc-apply-args": "2.0.1", "@noble/secp256k1": "^1.7.0", diff --git a/templates/ctl-scaffold/packages.dhall b/templates/ctl-scaffold/packages.dhall index 669048fce7..3427369803 100644 --- a/templates/ctl-scaffold/packages.dhall +++ b/templates/ctl-scaffold/packages.dhall @@ -280,7 +280,7 @@ let additions = ] , repo = "https://github.com/mlabs-haskell/purescript-cardano-serialization-lib" - , version = "26d437c3f398172c839b93b57c30eb43a7fa7ca0" + , version = "v1.0.0" } , cardano-plutus-data-schema = { dependencies = [ "prelude" ] @@ -435,7 +435,7 @@ let additions = , "unsafe-coerce" ] , repo = "https://github.com/mlabs-haskell/purescript-cardano-types" - , version = "v1.0.1" + , version = "v2.0.0" } , cardano-message-signing = { dependencies = diff --git a/templates/ctl-scaffold/spago-packages.nix b/templates/ctl-scaffold/spago-packages.nix index f2c859bbfc..6d317917f3 100644 --- a/templates/ctl-scaffold/spago-packages.nix +++ b/templates/ctl-scaffold/spago-packages.nix @@ -214,8 +214,8 @@ let version = "v1.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-collateral-select"; - rev = "296fe978a292f36d9fd2c18a2d173772301e71b9"; - sha256 = "09mcdjndalc9a91l0kx9s0p3bh5j58lji230b142yvgk8qmmayi9"; + rev = "193bf49be979b42aa1f0f9cb3d7582d6bc98e3b9"; + sha256 = "1jbl6k779brbqzf7jf80is63b23k3mqzf2mzr222qswd3wg8s5b0"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; @@ -238,8 +238,8 @@ let version = "v1.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-key-wallet"; - rev = "f107d3dce0a0f1f866a4682783376ea9f476fd7d"; - sha256 = "0jxbzdjfvxvrf2nmay493x004d0y5jmnfqj06064nfihg5x0w2r8"; + rev = "fd50834bad329b3064b602e6487e9471ea102341"; + sha256 = "0bgizyhrpmj51lz24cnr6wvxwgvm41z24c66kk3lzhwq798n5q50"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; @@ -271,17 +271,17 @@ let "cardano-serialization-lib" = pkgs.stdenv.mkDerivation { name = "cardano-serialization-lib"; - version = "26d437c3f398172c839b93b57c30eb43a7fa7ca0"; + version = "v1.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-serialization-lib"; - rev = "26d437c3f398172c839b93b57c30eb43a7fa7ca0"; - sha256 = "1ikz6j3jvls3cvl6znrw55f59abzdaf7ggd2x7j3f81m5cvkxggr"; + rev = "903bf0adeefedc4d065ad6523ad079433bdd8e32"; + sha256 = "0jlfxrx037hyd4v0j7l2b16yxlm6nw6qlnr992hj9nzip36vbpfg"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; }; - "cardano-transaction-lib" = pkgs.stdenv.mkDerivation { + "cardano-transaction-lib" = pkgs.stdenv.mkDerivation { name = "cardano-transaction-lib"; version = "423e27b3f56b1a66db8d3126c22cea9bda7e50da"; src = pkgs.fetchgit { @@ -295,11 +295,11 @@ let "cardano-types" = pkgs.stdenv.mkDerivation { name = "cardano-types"; - version = "v1.0.1"; + version = "v2.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-types"; - rev = "715d4b2dcf8b29cb45001209ee562f758a513261"; - sha256 = "1xcrdmpwd3qcdiyjfrj0z2dh56l4z1s97r25b6nhlqwmwz7qz19z"; + rev = "780c28ee27d0ba7e76884a565ad60dea0a414842"; + sha256 = "1my7fgk218h6yllw09zf1m55hpn787mjq79whxxm9lqgarrdp66z"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; diff --git a/test/Fixtures.purs b/test/Fixtures.purs index e4a9f0783f..25e6f80b5a 100644 --- a/test/Fixtures.purs +++ b/test/Fixtures.purs @@ -86,25 +86,19 @@ import Cardano.Types ( AuxiliaryData(AuxiliaryData) , Bech32String , Certificate - ( StakeRegistration - , StakeDeregistration - , StakeDelegation + ( PoolRetirement , PoolRegistration - , PoolRetirement - , GenesisKeyDelegation - , MoveInstantaneousRewardsCert + , StakeDelegation + , StakeDeregistration + , StakeRegistration ) , Coin(Coin) , Credential(PubKeyHashCredential) , Ed25519KeyHash , Epoch(Epoch) - , ExUnitPrices(ExUnitPrices) , ExUnits(ExUnits) , GeneralTransactionMetadata(GeneralTransactionMetadata) , Language(PlutusV2) - , MIRPot(Reserves, Treasury) - , MIRToStakeCredentials(MIRToStakeCredentials) - , MoveInstantaneousReward(ToOtherPot, ToStakeCreds) , NativeScript ( TimelockExpiry , TimelockStart @@ -121,12 +115,9 @@ import Cardano.Types , PoolMetadata(PoolMetadata) , PoolParams(PoolParams) , PoolPubKeyHash(PoolPubKeyHash) - , ProposedProtocolParameterUpdates(ProposedProtocolParameterUpdates) - , ProtocolParamUpdate(ProtocolParamUpdate) - , ProtocolVersion(ProtocolVersion) , Redeemer(Redeemer) , RedeemerTag(Spend) - , Relay(SingleHostAddr, SingleHostName, MultiHostName) + , Relay(MultiHostName, SingleHostName, SingleHostAddr) , RewardAddress , ScriptHash , ScriptRef(NativeScriptRef) @@ -139,7 +130,6 @@ import Cardano.Types , TransactionWitnessSet(TransactionWitnessSet) , URL(URL) , UnitInterval(UnitInterval) - , Update(Update) , UtxoMap , Value(Value) , Vkey(Vkey) @@ -177,7 +167,6 @@ import JS.BigInt as BigInt import Node.Encoding (Encoding(UTF8)) import Node.FS.Sync (readTextFile) import Partial.Unsafe (unsafePartial) -import Test.Ctl.Fixtures.CostModels (costModelsFixture1) txOutputFixture1 :: TransactionOutput txOutputFixture1 = @@ -254,49 +243,6 @@ bigNumOne = BigNum.fromInt 1 rewardAddress1 :: RewardAddress rewardAddress1 = { networkId: TestnetId, stakeCredential: wrap stake1 } -proposedProtocolParameterUpdates1 :: ProposedProtocolParameterUpdates -proposedProtocolParameterUpdates1 = ProposedProtocolParameterUpdates $ - Map.fromFoldable - [ ( unsafePartial $ fromJust $ decodeCbor $ wrap $ hexToByteArrayUnsafe - "5d677265fa5bb21ce6d8c7502aca70b9316d10e958611f3c6b758f65" - ) /\ - ProtocolParamUpdate - { minfeeA: Just $ Coin $ BigNum.fromInt 1 - , minfeeB: Just $ Coin $ BigNum.fromInt 1 - , maxBlockBodySize: Just $ UInt.fromInt 10000 - , maxTxSize: Just $ UInt.fromInt 10000 - , maxBlockHeaderSize: Just $ UInt.fromInt 1000 - , keyDeposit: Just $ Coin $ BigNum.fromInt 1 - , poolDeposit: Just $ Coin $ BigNum.fromInt 1 - , maxEpoch: Just $ Epoch one - , nOpt: Just $ UInt.fromInt 1 - , poolPledgeInfluence: Just $ UnitInterval - { numerator: bigNumOne, denominator: bigNumOne } - , expansionRate: Just $ UnitInterval - { numerator: bigNumOne, denominator: bigNumOne } - , treasuryGrowthRate: Just $ UnitInterval - { numerator: bigNumOne, denominator: bigNumOne } - , protocolVersion: Just $ ProtocolVersion - { major: 1, minor: 1 } - , minPoolCost: Just $ wrap bigNumOne - , adaPerUtxoByte: Just $ wrap bigNumOne - , costModels: Just costModelsFixture1 - , executionCosts: Just $ ExUnitPrices - { memPrice: UnitInterval - { numerator: bigNumOne, denominator: bigNumOne } - , stepPrice: UnitInterval - { numerator: bigNumOne, denominator: bigNumOne } - } - , maxTxExUnits: Just $ ExUnits - { mem: BigNum.fromInt 1, steps: BigNum.fromInt 1 } - , maxBlockExUnits: Just $ ExUnits - { mem: BigNum.fromInt 1, steps: BigNum.fromInt 1 } - , maxValueSize: Just $ UInt.fromInt 1 - , collateralPercentage: Just $ UInt.fromInt 140 - , maxCollateralInputs: Just $ UInt.fromInt 10 - } - ] - -- | Extend this for your needs. type SampleTxConfig = { inputs :: Array TransactionInput } @@ -325,7 +271,6 @@ mkSampleTx startTx changes = , ttl , certs , withdrawals - , update , auxiliaryDataHash , validityStartInterval , mint @@ -351,7 +296,6 @@ mkSampleTx startTx changes = , ttl , certs , withdrawals - , update , auxiliaryDataHash , validityStartInterval , mint @@ -362,6 +306,10 @@ mkSampleTx startTx changes = , networkId , collateralReturn , totalCollateral + , votingProposals: [] + , votingProcedures: wrap Map.empty + , currentTreasuryValue: Nothing + , donation: Nothing } , witnessSet , isValid @@ -404,7 +352,6 @@ txFixture1 = , ttl: Nothing , certs: [] , withdrawals: Map.empty - , update: Nothing , auxiliaryDataHash: Nothing , validityStartInterval: Nothing , mint: Nothing @@ -415,6 +362,10 @@ txFixture1 = , networkId: Just MainnetId , collateralReturn: Nothing , totalCollateral: Nothing + , votingProposals: [] + , votingProcedures: wrap Map.empty + , currentTreasuryValue: Nothing + , donation: Nothing } , witnessSet: TransactionWitnessSet { vkeys: [] @@ -438,7 +389,6 @@ txFixture2 = , ttl: Nothing , certs: [] , withdrawals: Map.empty - , update: Nothing , auxiliaryDataHash: Nothing , validityStartInterval: Nothing , mint: Nothing @@ -449,6 +399,10 @@ txFixture2 = , networkId: Just MainnetId , collateralReturn: Nothing , totalCollateral: Nothing + , votingProposals: [] + , votingProcedures: wrap Map.empty + , currentTreasuryValue: Nothing + , donation: Nothing } , witnessSet: witnessSetFixture3Value , isValid: true @@ -490,7 +444,6 @@ txFixture3 = , ttl: Nothing , certs: [] , withdrawals: Map.empty - , update: Nothing , referenceInputs: [ txInputFixture1 ] , auxiliaryDataHash: Nothing , validityStartInterval: Nothing @@ -501,6 +454,10 @@ txFixture3 = , networkId: Just MainnetId , collateralReturn: Nothing , totalCollateral: Nothing + , votingProposals: [] + , votingProcedures: wrap Map.empty + , currentTreasuryValue: Nothing + , donation: Nothing } , witnessSet: TransactionWitnessSet { vkeys: [] @@ -607,36 +564,9 @@ txFixture4 = { poolKeyHash: PoolPubKeyHash ed25519KeyHash1 , epoch: Epoch one } - , GenesisKeyDelegation - { genesisHash: unsafePartial $ fromJust $ decodeCbor $ wrap $ - hexToByteArrayUnsafe - "5d677265fa5bb21ce6d8c7502aca70b9316d10e958611f3c6b758f65" - , genesisDelegateHash: unsafePartial $ fromJust $ decodeCbor - $ wrap - $ - hexToByteArrayUnsafe - "5d677265fa5bb21ce6d8c7502aca70b9316d10e958611f3c6b758f65" - , vrfKeyhash: unsafePartial $ fromJust $ decodeCbor $ wrap $ - hexToByteArrayUnsafe - "fbf6d41985670b9041c5bf362b5262cf34add5d265975de176d613ca05f37096" - } - , MoveInstantaneousRewardsCert $ ToOtherPot - { pot: Reserves - , amount: wrap bigNumOne - } - , MoveInstantaneousRewardsCert $ ToStakeCreds - { pot: Treasury - , amounts: MIRToStakeCredentials $ Map.fromFoldable - [ wrap stake1 /\ Int.newPositive bigNumOne ] - } ] , withdrawals: Map.fromFoldable [ rewardAddress1 /\ Coin BigNum.one ] - , update: Just $ Update - { proposedProtocolParameterUpdates: - proposedProtocolParameterUpdates1 - , epoch: Epoch zero - } , auxiliaryDataHash: decodeCbor $ wrap $ byteArrayFromIntArrayUnsafe $ Array.replicate 32 0 @@ -653,6 +583,10 @@ txFixture4 = , networkId: Just MainnetId , collateralReturn: Just txOutputFixture1 , totalCollateral: Just $ Coin $ BigNum.fromInt 5_000_000 + , votingProposals: [] + , votingProcedures: wrap Map.empty + , currentTreasuryValue: Nothing + , donation: Nothing } , witnessSet: TransactionWitnessSet { vkeys: [] @@ -690,7 +624,6 @@ txFixture5 = , ttl: Nothing , certs: [] , withdrawals: Map.empty - , update: Nothing , auxiliaryDataHash: Nothing , validityStartInterval: Nothing , mint: Nothing @@ -701,6 +634,10 @@ txFixture5 = , networkId: Just MainnetId , collateralReturn: Nothing , totalCollateral: Nothing + , votingProposals: [] + , votingProcedures: wrap Map.empty + , currentTreasuryValue: Nothing + , donation: Nothing } , witnessSet: TransactionWitnessSet { vkeys: [] @@ -724,7 +661,6 @@ txFixture6 = , ttl: Nothing , certs: [] , withdrawals: Map.empty - , update: Nothing , auxiliaryDataHash: Nothing , validityStartInterval: Nothing , mint: Nothing @@ -735,6 +671,10 @@ txFixture6 = , networkId: Just MainnetId , collateralReturn: Nothing , totalCollateral: Nothing + , votingProposals: [] + , votingProcedures: wrap Map.empty + , currentTreasuryValue: Nothing + , donation: Nothing } , witnessSet: TransactionWitnessSet { vkeys: [] @@ -1351,7 +1291,7 @@ redeemerFixture1 :: Redeemer redeemerFixture1 = Redeemer { tag: Spend , index: BigNum.fromInt 0 - , data: plutusDataFixture7 + , data: wrap plutusDataFixture7 , exUnits: ExUnits { mem: BigNum.fromInt 1 , steps: BigNum.fromInt 1 diff --git a/test/Plutip/Staking.purs b/test/Plutip/Staking.purs index 630a407d17..076db91dac 100644 --- a/test/Plutip/Staking.purs +++ b/test/Plutip/Staking.purs @@ -64,7 +64,7 @@ import Contract.Wallet , ownStakePubKeyHashes , withKeyWallet ) -import Contract.Wallet.Key (keyWalletPrivateStakeKey, publicKeyFromPrivateKey) +import Contract.Wallet.Key (getPrivateStakeKey, publicKeyFromPrivateKey) import Ctl.Examples.AlwaysSucceeds (alwaysSucceedsScript) import Ctl.Examples.Helpers (submitAndLog) import Ctl.Examples.IncludeDatum (only42Script) @@ -285,8 +285,9 @@ suite = do ubTx <- mkUnbalancedTx lookups constraints balanceTx ubTx >>= signTransaction >>= submitAndLog - privateStakeKey <- liftM (error "Failed to get private stake key") $ - keyWalletPrivateStakeKey alice + kwMStakeKey <- liftAff $ getPrivateStakeKey alice + privateStakeKey <- liftM (error "Failed to get private stake key") + kwMStakeKey networkId <- getNetworkId let poolOperator = PoolPubKeyHash $ publicKeyHash $ diff --git a/test/Unit.purs b/test/Unit.purs index b2802bd5fa..9bd4da80eb 100644 --- a/test/Unit.purs +++ b/test/Unit.purs @@ -2,7 +2,6 @@ module Test.Ctl.Unit (main, testPlan) where import Prelude -import Cardano.Wallet.Cip30.SignData as Cip30SignData import Contract.Test.Mote (TestPlanM, interpretWithConfig) import Contract.Test.Utils (exitCode, interruptOnSignal) import Data.Maybe (Maybe(Just)) @@ -16,8 +15,6 @@ import Test.Ctl.ApplyArgs as ApplyArgs import Test.Ctl.Blockfrost.Aeson.Suite as Blockfrost.Aeson import Test.Ctl.Blockfrost.ProtocolParameters as Blockfrost.ProtocolParameters import Test.Ctl.CoinSelection as CoinSelection -import Test.Ctl.CslGc as CslGc -import Test.Ctl.Data as Data import Test.Ctl.Data.Interval as Ctl.Data.Interval import Test.Ctl.E2E.Route as E2E.Route import Test.Ctl.Hashing as Hashing @@ -51,9 +48,6 @@ testPlan = do Ipv6.suite NativeScript.suite Bip32.suite - Cip30SignData.suite - CslGc.suite - Data.suite Hashing.suite Partition.suite Plutus.Time.suite From a75de33cb96e9790d41fc2b65cf3560896bc68ec Mon Sep 17 00:00:00 2001 From: Marcus Fernandes Date: Tue, 9 Jul 2024 15:13:50 -0300 Subject: [PATCH 33/52] Remove `Ctl.Internal.Wallet.Key` module Use `Cardano.Wallet.Key` instead. --- src/Contract/Config.purs | 10 +++++----- src/Contract/Wallet.purs | 12 ++++++------ src/Contract/Wallet/Key.purs | 2 +- src/Contract/Wallet/KeyFile.purs | 2 +- src/Internal/Plutip/Server.purs | 2 +- src/Internal/QueryM.purs | 2 +- src/Internal/Test/E2E/Runner.purs | 10 +++++----- src/Internal/Test/KeyDir.purs | 2 +- src/Internal/Test/UtxoDistribution.purs | 12 ++++++------ src/Internal/Wallet.purs | 6 +++--- src/Internal/Wallet/Cip30Mock.purs | 2 +- src/Internal/Wallet/Key.purs | 13 ------------- src/Internal/Wallet/KeyFile.purs | 2 +- src/Internal/Wallet/Spec.purs | 12 ++++++------ test/Plutip/Common.purs | 2 +- test/Wallet/Bip32.purs | 2 +- 16 files changed, 40 insertions(+), 53 deletions(-) delete mode 100644 src/Internal/Wallet/Key.purs diff --git a/src/Contract/Config.purs b/src/Contract/Config.purs index 57d523e14a..b7b8fa5605 100644 --- a/src/Contract/Config.purs +++ b/src/Contract/Config.purs @@ -23,11 +23,15 @@ module Contract.Config , module Data.Log.Message , module Ctl.Internal.ServerConfig , module Ctl.Internal.Wallet.Spec - , module Ctl.Internal.Wallet.Key + , module Cardano.Wallet.Key , module X ) where import Cardano.Types (NetworkId(MainnetId, TestnetId)) +import Cardano.Wallet.Key + ( PrivatePaymentKey(PrivatePaymentKey) + , PrivateStakeKey(PrivateStakeKey) + ) import Ctl.Internal.BalanceTx.Sync ( disabledSynchronizationParams ) as X @@ -67,10 +71,6 @@ import Ctl.Internal.ServerConfig , defaultKupoServerConfig , defaultOgmiosWsConfig ) -import Ctl.Internal.Wallet.Key - ( PrivatePaymentKey(PrivatePaymentKey) - , PrivateStakeKey(PrivateStakeKey) - ) import Ctl.Internal.Wallet.Spec ( Cip1852DerivationPath , MnemonicSource(MnemonicString, MnemonicFile) diff --git a/src/Contract/Wallet.purs b/src/Contract/Wallet.purs index 391ea46933..4ad52a1bab 100644 --- a/src/Contract/Wallet.purs +++ b/src/Contract/Wallet.purs @@ -18,6 +18,12 @@ import Cardano.Types (Address, StakePubKeyHash, UtxoMap, Value) import Cardano.Types.PaymentPubKeyHash (PaymentPubKeyHash) import Cardano.Types.TransactionUnspentOutput (TransactionUnspentOutput) import Cardano.Types.Value as Value +import Cardano.Wallet.Key + ( KeyWallet + , PrivatePaymentKey(PrivatePaymentKey) + , PrivateStakeKey(PrivateStakeKey) + , privateKeysToKeyWallet + ) as X import Contract.Config (PrivatePaymentKey, PrivateStakeKey) import Contract.Log (logTrace') import Contract.Monad (Contract) @@ -58,12 +64,6 @@ import Ctl.Internal.Wallet ) , isWalletAvailable ) as X -import Ctl.Internal.Wallet.Key - ( KeyWallet - , PrivatePaymentKey(PrivatePaymentKey) - , PrivateStakeKey(PrivateStakeKey) - , privateKeysToKeyWallet - ) as X import Ctl.Internal.Wallet.KeyFile (formatPaymentKey, formatStakeKey) as X import Ctl.Internal.Wallet.Spec ( Cip1852DerivationPath diff --git a/src/Contract/Wallet/Key.purs b/src/Contract/Wallet/Key.purs index ddbb9e63c0..3b962f04c5 100644 --- a/src/Contract/Wallet/Key.purs +++ b/src/Contract/Wallet/Key.purs @@ -6,7 +6,7 @@ module Contract.Wallet.Key import Cardano.Types (PrivateKey, PublicKey) import Cardano.Types.PrivateKey as PrivateKey -import Ctl.Internal.Wallet.Key +import Cardano.Wallet.Key ( KeyWallet(KeyWallet) , getPrivatePaymentKey , getPrivateStakeKey diff --git a/src/Contract/Wallet/KeyFile.purs b/src/Contract/Wallet/KeyFile.purs index eeec865eb4..cb139e0047 100644 --- a/src/Contract/Wallet/KeyFile.purs +++ b/src/Contract/Wallet/KeyFile.purs @@ -6,7 +6,7 @@ module Contract.Wallet.KeyFile import Prelude -import Ctl.Internal.Wallet.Key (KeyWallet, privateKeysToKeyWallet) +import Cardano.Wallet.Key (KeyWallet, privateKeysToKeyWallet) import Ctl.Internal.Wallet.KeyFile ( privatePaymentKeyFromFile , privatePaymentKeyFromTextEnvelope diff --git a/src/Internal/Plutip/Server.purs b/src/Internal/Plutip/Server.purs index 104314d085..e717749c32 100644 --- a/src/Internal/Plutip/Server.purs +++ b/src/Internal/Plutip/Server.purs @@ -20,6 +20,7 @@ import Affjax.ResponseFormat as Affjax.ResponseFormat import Cardano.Types (NetworkId(MainnetId)) import Cardano.Types.BigNum as BigNum import Cardano.Types.PrivateKey (PrivateKey(PrivateKey)) +import Cardano.Wallet.Key (PrivatePaymentKey(PrivatePaymentKey)) import Contract.Chain (waitNSlots) import Contract.Config (defaultSynchronizationParams, defaultTimeParams) import Contract.Monad (Contract, ContractEnv, liftContractM, runContractInEnv) @@ -78,7 +79,6 @@ import Ctl.Internal.Test.UtxoDistribution , transferFundsFromEnterpriseToBase ) import Ctl.Internal.Types.UsedTxOuts (newUsedTxOuts) -import Ctl.Internal.Wallet.Key (PrivatePaymentKey(PrivatePaymentKey)) import Data.Array as Array import Data.Bifunctor (lmap) import Data.Either (Either(Left, Right), either, isLeft) diff --git a/src/Internal/QueryM.purs b/src/Internal/QueryM.purs index 6fd3fa2989..052c5447bc 100644 --- a/src/Internal/QueryM.purs +++ b/src/Internal/QueryM.purs @@ -154,7 +154,7 @@ import Ctl.Internal.Service.Error ) import Ctl.Internal.Types.Chain as Chain import Ctl.Internal.Types.SystemStart (SystemStart) -import Ctl.Internal.Wallet.Key (PrivatePaymentKey, PrivateStakeKey) +import Cardano.Wallet.Key (PrivatePaymentKey, PrivateStakeKey) import Data.Bifunctor (lmap) import Data.ByteArray (byteArrayToHex) import Data.Either (Either(Left, Right), either, isRight) diff --git a/src/Internal/Test/E2E/Runner.purs b/src/Internal/Test/E2E/Runner.purs index 76ec5618ae..383fef8d18 100644 --- a/src/Internal/Test/E2E/Runner.purs +++ b/src/Internal/Test/E2E/Runner.purs @@ -12,6 +12,11 @@ import Affjax (printError) import Affjax.ResponseFormat as Affjax.ResponseFormat import Cardano.Types.BigNum as BigNum import Cardano.Types.PrivateKey as PrivateKey +import Cardano.Wallet.Key + ( PrivateStakeKey + , getPrivatePaymentKey + , getPrivateStakeKey + ) import Control.Alt ((<|>)) import Control.Monad.Error.Class (liftMaybe) import Control.Promise (Promise, toAffE) @@ -73,11 +78,6 @@ import Ctl.Internal.Test.E2E.Wallets , namiSign ) import Ctl.Internal.Test.UtxoDistribution (withStakeKey) -import Ctl.Internal.Wallet.Key - ( PrivateStakeKey - , getPrivatePaymentKey - , getPrivateStakeKey - ) import Data.Array (catMaybes, mapMaybe, nub) import Data.Array as Array import Data.ByteArray (hexToByteArray) diff --git a/src/Internal/Test/KeyDir.purs b/src/Internal/Test/KeyDir.purs index 3738df2f72..e36ed22439 100644 --- a/src/Internal/Test/KeyDir.purs +++ b/src/Internal/Test/KeyDir.purs @@ -70,7 +70,7 @@ import Ctl.Internal.Types.TxConstraints , mustSpendPubKeyOutput , singleton ) -import Ctl.Internal.Wallet.Key (KeyWallet) +import Cardano.Wallet.Key (KeyWallet) import Data.Array (catMaybes) import Data.Array as Array import Data.Either (Either(Right, Left), hush) diff --git a/src/Internal/Test/UtxoDistribution.purs b/src/Internal/Test/UtxoDistribution.purs index ef04613156..b6644938ea 100644 --- a/src/Internal/Test/UtxoDistribution.purs +++ b/src/Internal/Test/UtxoDistribution.purs @@ -25,6 +25,12 @@ import Cardano.Types import Cardano.Types.Address (Address(EnterpriseAddress)) import Cardano.Types.PrivateKey (PrivateKey) import Cardano.Types.UtxoMap (UtxoMap) +import Cardano.Wallet.Key + ( KeyWallet + , PrivatePaymentKey(PrivatePaymentKey) + , PrivateStakeKey + , privateKeysToKeyWallet + ) import Contract.Address (getNetworkId) import Contract.Monad (Contract, liftedM) import Contract.Prelude (foldM, foldMap, null) @@ -48,12 +54,6 @@ import Contract.Wallet import Control.Alternative (guard) import Control.Monad.Reader (asks) import Control.Monad.State.Trans (StateT(StateT), runStateT) -import Ctl.Internal.Wallet.Key - ( KeyWallet - , PrivatePaymentKey(PrivatePaymentKey) - , PrivateStakeKey - , privateKeysToKeyWallet - ) import Data.Array (head) import Data.Array as Array import Data.FoldableWithIndex (foldMapWithIndex) diff --git a/src/Internal/Wallet.purs b/src/Internal/Wallet.purs index 16d43bb315..8a6ba2180e 100644 --- a/src/Internal/Wallet.purs +++ b/src/Internal/Wallet.purs @@ -19,14 +19,14 @@ module Ctl.Internal.Wallet import Prelude import Cardano.Wallet.Cip30 as Cip30 -import Control.Monad.Error.Class (catchError, throwError) -import Ctl.Internal.Wallet.Cip30 (Cip30Wallet, mkCip30WalletAff) -import Ctl.Internal.Wallet.Key +import Cardano.Wallet.Key ( KeyWallet , PrivatePaymentKey , PrivateStakeKey , privateKeysToKeyWallet ) +import Control.Monad.Error.Class (catchError, throwError) +import Ctl.Internal.Wallet.Cip30 (Cip30Wallet, mkCip30WalletAff) import Data.Int (toNumber) import Data.Maybe (Maybe) import Data.Newtype (wrap) diff --git a/src/Internal/Wallet/Cip30Mock.purs b/src/Internal/Wallet/Cip30Mock.purs index e585d8efd3..3a3a949c43 100644 --- a/src/Internal/Wallet/Cip30Mock.purs +++ b/src/Internal/Wallet/Cip30Mock.purs @@ -43,7 +43,7 @@ import Ctl.Internal.Wallet ) , mkWalletAff ) -import Ctl.Internal.Wallet.Key +import Cardano.Wallet.Key ( KeyWallet(KeyWallet) , PrivatePaymentKey , PrivateStakeKey diff --git a/src/Internal/Wallet/Key.purs b/src/Internal/Wallet/Key.purs deleted file mode 100644 index 641d4df359..0000000000 --- a/src/Internal/Wallet/Key.purs +++ /dev/null @@ -1,13 +0,0 @@ -module Ctl.Internal.Wallet.Key - ( module KeyWallet - ) where - -import Cardano.Wallet.Key - ( KeyWallet(KeyWallet) - , PrivatePaymentKey(PrivatePaymentKey) - , PrivateStakeKey(PrivateStakeKey) - , getPrivatePaymentKey - , getPrivateStakeKey - , privateKeysToAddress - , privateKeysToKeyWallet - ) as KeyWallet diff --git a/src/Internal/Wallet/KeyFile.purs b/src/Internal/Wallet/KeyFile.purs index 3238cb04fc..c18d7046b2 100644 --- a/src/Internal/Wallet/KeyFile.purs +++ b/src/Internal/Wallet/KeyFile.purs @@ -27,7 +27,7 @@ import Ctl.Internal.Cardano.TextEnvelope , decodeTextEnvelope ) import Ctl.Internal.Helpers (liftM) -import Ctl.Internal.Wallet.Key +import Cardano.Wallet.Key ( PrivatePaymentKey(PrivatePaymentKey) , PrivateStakeKey(PrivateStakeKey) ) diff --git a/src/Internal/Wallet/Spec.purs b/src/Internal/Wallet/Spec.purs index 29bd687802..21f2b5bdd1 100644 --- a/src/Internal/Wallet/Spec.purs +++ b/src/Internal/Wallet/Spec.purs @@ -28,6 +28,12 @@ import Cardano.Wallet.HD , derivePaymentKey , deriveStakeKey ) +import Cardano.Wallet.Key + ( KeyWallet + , PrivatePaymentKey(PrivatePaymentKey) + , PrivateStakeKey(PrivateStakeKey) + , privateKeysToKeyWallet + ) import Control.Monad.Error.Class (liftEither) import Ctl.Internal.Wallet ( Wallet(KeyWallet) @@ -44,12 +50,6 @@ import Ctl.Internal.Wallet , mkKeyWallet , mkWalletAff ) -import Ctl.Internal.Wallet.Key - ( KeyWallet - , PrivatePaymentKey(PrivatePaymentKey) - , PrivateStakeKey(PrivateStakeKey) - , privateKeysToKeyWallet - ) import Ctl.Internal.Wallet.KeyFile ( privatePaymentKeyFromFile , privateStakeKeyFromFile diff --git a/test/Plutip/Common.purs b/test/Plutip/Common.purs index 3cd0304fb4..604bc9a703 100644 --- a/test/Plutip/Common.purs +++ b/test/Plutip/Common.purs @@ -8,7 +8,7 @@ import Prelude import Contract.Keys (privateKeyFromBytes) import Contract.Test.Plutip (defaultPlutipConfig) import Ctl.Internal.Plutip.Types (PlutipConfig) -import Ctl.Internal.Wallet.Key (PrivateStakeKey) +import Cardano.Wallet.Key (PrivateStakeKey) import Data.ByteArray (hexToByteArray) import Data.Maybe (fromJust) import Data.Newtype (wrap) diff --git a/test/Wallet/Bip32.purs b/test/Wallet/Bip32.purs index 06f712ab7f..074f841254 100644 --- a/test/Wallet/Bip32.purs +++ b/test/Wallet/Bip32.purs @@ -6,11 +6,11 @@ import Contract.Prelude import Cardano.Types.Address as Address import Cardano.Types.NetworkId (NetworkId(MainnetId)) +import Cardano.Wallet.Key (KeyWallet) import Contract.Wallet.Key ( StakeKeyPresence(WithStakeKey) , mkKeyWalletFromMnemonic ) -import Ctl.Internal.Wallet.Key (KeyWallet) import Data.Lens (_Left, preview) import Data.UInt as UInt import Effect.Aff (Aff) From cbcdf7d3b08ca563308a87e263bb7ea5fba60bd4 Mon Sep 17 00:00:00 2001 From: Marcus Fernandes Date: Tue, 9 Jul 2024 15:23:24 -0300 Subject: [PATCH 34/52] Fix formatting --- src/Internal/QueryM.purs | 2 +- src/Internal/Test/KeyDir.purs | 2 +- src/Internal/Wallet/Cip30Mock.purs | 12 ++++++------ src/Internal/Wallet/KeyFile.purs | 8 ++++---- test/Plutip/Common.purs | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Internal/QueryM.purs b/src/Internal/QueryM.purs index 052c5447bc..5dece7cc83 100644 --- a/src/Internal/QueryM.purs +++ b/src/Internal/QueryM.purs @@ -67,6 +67,7 @@ import Cardano.Types (PlutusScript) import Cardano.Types.CborBytes (CborBytes) import Cardano.Types.PlutusScript as PlutusScript import Cardano.Types.TransactionHash (TransactionHash) +import Cardano.Wallet.Key (PrivatePaymentKey, PrivateStakeKey) import Control.Alt (class Alt) import Control.Alternative (class Alternative) import Control.Monad.Error.Class @@ -154,7 +155,6 @@ import Ctl.Internal.Service.Error ) import Ctl.Internal.Types.Chain as Chain import Ctl.Internal.Types.SystemStart (SystemStart) -import Cardano.Wallet.Key (PrivatePaymentKey, PrivateStakeKey) import Data.Bifunctor (lmap) import Data.ByteArray (byteArrayToHex) import Data.Either (Either(Left, Right), either, isRight) diff --git a/src/Internal/Test/KeyDir.purs b/src/Internal/Test/KeyDir.purs index e36ed22439..075046de79 100644 --- a/src/Internal/Test/KeyDir.purs +++ b/src/Internal/Test/KeyDir.purs @@ -11,6 +11,7 @@ import Cardano.Types.MultiAsset as MultiAsset import Cardano.Types.PrivateKey as PrivateKey import Cardano.Types.PublicKey as PublicKey import Cardano.Types.Value as Value +import Cardano.Wallet.Key (KeyWallet) import Contract.Config (ContractParams) import Contract.Log (logError', logTrace') import Contract.Monad @@ -70,7 +71,6 @@ import Ctl.Internal.Types.TxConstraints , mustSpendPubKeyOutput , singleton ) -import Cardano.Wallet.Key (KeyWallet) import Data.Array (catMaybes) import Data.Array as Array import Data.Either (Either(Right, Left), hush) diff --git a/src/Internal/Wallet/Cip30Mock.purs b/src/Internal/Wallet/Cip30Mock.purs index 3a3a949c43..17a6117b44 100644 --- a/src/Internal/Wallet/Cip30Mock.purs +++ b/src/Internal/Wallet/Cip30Mock.purs @@ -23,6 +23,12 @@ import Cardano.Types.PrivateKey as PrivateKey import Cardano.Types.PublicKey as PublicKey import Cardano.Types.TransactionUnspentOutput as TransactionUnspentOutput import Cardano.Wallet.Cip30Mock (Cip30Mock, injectCip30Mock) +import Cardano.Wallet.Key + ( KeyWallet(KeyWallet) + , PrivatePaymentKey + , PrivateStakeKey + , privateKeysToKeyWallet + ) import Contract.Monad (Contract) import Control.Monad.Error.Class (liftMaybe, try) import Control.Monad.Reader (ask) @@ -43,12 +49,6 @@ import Ctl.Internal.Wallet ) , mkWalletAff ) -import Cardano.Wallet.Key - ( KeyWallet(KeyWallet) - , PrivatePaymentKey - , PrivateStakeKey - , privateKeysToKeyWallet - ) import Data.Array as Array import Data.ByteArray (byteArrayToHex, hexToByteArray) import Data.Either (hush) diff --git a/src/Internal/Wallet/KeyFile.purs b/src/Internal/Wallet/KeyFile.purs index c18d7046b2..80b0a7d946 100644 --- a/src/Internal/Wallet/KeyFile.purs +++ b/src/Internal/Wallet/KeyFile.purs @@ -16,6 +16,10 @@ import Prelude import Aeson (encodeAeson) import Cardano.Types.PrivateKey (PrivateKey) import Cardano.Types.PrivateKey as PrivateKey +import Cardano.Wallet.Key + ( PrivatePaymentKey(PrivatePaymentKey) + , PrivateStakeKey(PrivateStakeKey) + ) import Control.Monad.Error.Class (liftMaybe) import Control.Monad.Except (catchError) import Ctl.Internal.Cardano.TextEnvelope @@ -27,10 +31,6 @@ import Ctl.Internal.Cardano.TextEnvelope , decodeTextEnvelope ) import Ctl.Internal.Helpers (liftM) -import Cardano.Wallet.Key - ( PrivatePaymentKey(PrivatePaymentKey) - , PrivateStakeKey(PrivateStakeKey) - ) import Data.ByteArray (ByteArray, byteArrayToHex) import Data.Maybe (Maybe(Nothing)) import Data.Newtype (unwrap, wrap) diff --git a/test/Plutip/Common.purs b/test/Plutip/Common.purs index 604bc9a703..fbca65804a 100644 --- a/test/Plutip/Common.purs +++ b/test/Plutip/Common.purs @@ -5,10 +5,10 @@ module Test.Ctl.Plutip.Common import Prelude +import Cardano.Wallet.Key (PrivateStakeKey) import Contract.Keys (privateKeyFromBytes) import Contract.Test.Plutip (defaultPlutipConfig) import Ctl.Internal.Plutip.Types (PlutipConfig) -import Cardano.Wallet.Key (PrivateStakeKey) import Data.ByteArray (hexToByteArray) import Data.Maybe (fromJust) import Data.Newtype (wrap) From ecc2308eb77c0dc816fcfc5d0974eb6628325ea5 Mon Sep 17 00:00:00 2001 From: Marcus Fernandes Date: Tue, 9 Jul 2024 19:22:42 -0300 Subject: [PATCH 35/52] Revert dependencies version update --- package-lock.json | 48 ++++---- package.json | 4 +- packages.dhall | 4 +- spago-packages.nix | 16 +-- src/Contract/Transaction.purs | 1 + src/Internal/BalanceTx/RedeemerIndex.purs | 4 +- src/Internal/Contract/Wallet.purs | 3 +- src/Internal/Lens.purs | 5 + src/Internal/QueryM/Ogmios.purs | 7 +- src/Internal/Test/KeyDir.purs | 7 +- src/Internal/Wallet/Cip30Mock.purs | 3 +- templates/ctl-scaffold/package-lock.json | 48 ++++---- templates/ctl-scaffold/package.json | 4 +- templates/ctl-scaffold/packages.dhall | 4 +- templates/ctl-scaffold/spago-packages.nix | 18 +-- test/Fixtures.purs | 128 ++++++++++++++++------ test/Unit.purs | 4 + 17 files changed, 183 insertions(+), 125 deletions(-) diff --git a/package-lock.json b/package-lock.json index ab2b617850..a9845f2b0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,10 +8,8 @@ "name": "cardano-transaction-lib", "license": "MIT", "dependencies": { - "@emurgo/cardano-serialization-lib-browser": "v12.0.0-alpha.31", - "@emurgo/cardano-serialization-lib-nodejs": "v12.0.0-alpha.31", "@mlabs-haskell/cardano-message-signing": "^1.0.1", - "@mlabs-haskell/cardano-serialization-lib-gc": "v12.0.0-alpha.31", + "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", "@mlabs-haskell/json-bigint": "2.0.0", "@mlabs-haskell/uplc-apply-args": "2.0.1", "@noble/secp256k1": "^1.7.0", @@ -62,14 +60,14 @@ "integrity": "sha512-PoKh1tQnJX18f8iEr8Jk1KXxKCn9eqaSslMI1pyOJvYRJhQVDLCh0+9YReufjp0oFJIY1ShcrR+4/WnECVZUKQ==" }, "node_modules/@emurgo/cardano-serialization-lib-browser": { - "version": "12.0.0-alpha.31", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-12.0.0-alpha.31.tgz", - "integrity": "sha512-LEMiaui1ByuVuesWGUQ4CzksZJW9FeL/KL8HN2smSTjuCA3IaAp2VXZPxPjxP/0VbF+EM1aLkPn6DD02U/qy5Q==" + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-11.5.0.tgz", + "integrity": "sha512-qchOJ9NYDUz10tzs5r5QhP9hK0p+ZOlRiBwPdTAxqAYLw/8emYBkQQLaS8T1DF6EkeudyrgS00ym5Trw1fo4iA==" }, "node_modules/@emurgo/cardano-serialization-lib-nodejs": { - "version": "12.0.0-alpha.31", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-12.0.0-alpha.31.tgz", - "integrity": "sha512-YvE4JmTwQTM+8Blbmfa7qv44vWr3qWRn5RsfjxmyptyJwAk0Z/AfGQjYyWO/LmFsj8YCIZD2lS80LhrzzkN+Kw==" + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-11.5.0.tgz", + "integrity": "sha512-IlVABlRgo9XaTR1NunwZpWcxnfEv04ba2l1vkUz4S1W7Jt36F4CtffP+jPeqBZGnAe+fnUwo0XjIJC3ZTNToNQ==" }, "node_modules/@esbuild/android-arm": { "version": "0.18.11", @@ -503,12 +501,12 @@ } }, "node_modules/@mlabs-haskell/cardano-serialization-lib-gc": { - "version": "12.0.0-alpha.31", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-12.0.0-alpha.31.tgz", - "integrity": "sha512-QQBzl7rNRy7wk37uxzWJXCZfZRt3aTlfQb3kmb10ulY/janlUNETmS09OtiJbK/BdV5Fu7Gv+Mdda3ggMIL/bg==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-1.0.10.tgz", + "integrity": "sha512-7XFxxMvZH6oogWVP/teveVRUTRboWfY5fT0bkRDu68u9yb2HBjoMxkCkmF7MvJBVs2i0unt4UnzcrNm0dmHriQ==", "dependencies": { - "@emurgo/cardano-serialization-lib-browser": "^12.0.0-alpha.31", - "@emurgo/cardano-serialization-lib-nodejs": "^12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-browser": "^11.2.1", + "@emurgo/cardano-serialization-lib-nodejs": "^11.2.1", "@mlabs-haskell/csl-gc-wrapper": "^1.0.2" } }, @@ -6393,14 +6391,14 @@ "integrity": "sha512-PoKh1tQnJX18f8iEr8Jk1KXxKCn9eqaSslMI1pyOJvYRJhQVDLCh0+9YReufjp0oFJIY1ShcrR+4/WnECVZUKQ==" }, "@emurgo/cardano-serialization-lib-browser": { - "version": "12.0.0-alpha.31", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-12.0.0-alpha.31.tgz", - "integrity": "sha512-LEMiaui1ByuVuesWGUQ4CzksZJW9FeL/KL8HN2smSTjuCA3IaAp2VXZPxPjxP/0VbF+EM1aLkPn6DD02U/qy5Q==" + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-11.5.0.tgz", + "integrity": "sha512-qchOJ9NYDUz10tzs5r5QhP9hK0p+ZOlRiBwPdTAxqAYLw/8emYBkQQLaS8T1DF6EkeudyrgS00ym5Trw1fo4iA==" }, "@emurgo/cardano-serialization-lib-nodejs": { - "version": "12.0.0-alpha.31", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-12.0.0-alpha.31.tgz", - "integrity": "sha512-YvE4JmTwQTM+8Blbmfa7qv44vWr3qWRn5RsfjxmyptyJwAk0Z/AfGQjYyWO/LmFsj8YCIZD2lS80LhrzzkN+Kw==" + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-11.5.0.tgz", + "integrity": "sha512-IlVABlRgo9XaTR1NunwZpWcxnfEv04ba2l1vkUz4S1W7Jt36F4CtffP+jPeqBZGnAe+fnUwo0XjIJC3ZTNToNQ==" }, "@esbuild/android-arm": { "version": "0.18.11", @@ -6627,12 +6625,12 @@ } }, "@mlabs-haskell/cardano-serialization-lib-gc": { - "version": "12.0.0-alpha.31", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-12.0.0-alpha.31.tgz", - "integrity": "sha512-QQBzl7rNRy7wk37uxzWJXCZfZRt3aTlfQb3kmb10ulY/janlUNETmS09OtiJbK/BdV5Fu7Gv+Mdda3ggMIL/bg==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-1.0.10.tgz", + "integrity": "sha512-7XFxxMvZH6oogWVP/teveVRUTRboWfY5fT0bkRDu68u9yb2HBjoMxkCkmF7MvJBVs2i0unt4UnzcrNm0dmHriQ==", "requires": { - "@emurgo/cardano-serialization-lib-browser": "^12.0.0-alpha.31", - "@emurgo/cardano-serialization-lib-nodejs": "^12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-browser": "^11.2.1", + "@emurgo/cardano-serialization-lib-nodejs": "^11.2.1", "@mlabs-haskell/csl-gc-wrapper": "^1.0.2" } }, diff --git a/package.json b/package.json index d47e7be018..4cb9d98924 100755 --- a/package.json +++ b/package.json @@ -32,9 +32,7 @@ "license": "MIT", "dependencies": { "@mlabs-haskell/cardano-message-signing": "^1.0.1", - "@mlabs-haskell/cardano-serialization-lib-gc": "v12.0.0-alpha.31", - "@emurgo/cardano-serialization-lib-nodejs": "v12.0.0-alpha.31", - "@emurgo/cardano-serialization-lib-browser": "v12.0.0-alpha.31", + "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", "@mlabs-haskell/json-bigint": "2.0.0", "@mlabs-haskell/uplc-apply-args": "2.0.1", "@noble/secp256k1": "^1.7.0", diff --git a/packages.dhall b/packages.dhall index e85d9abb73..ab0b497fd7 100644 --- a/packages.dhall +++ b/packages.dhall @@ -280,7 +280,7 @@ let additions = ] , repo = "https://github.com/mlabs-haskell/purescript-cardano-serialization-lib" - , version = "v1.0.0" + , version = "26d437c3f398172c839b93b57c30eb43a7fa7ca0" } , cardano-plutus-data-schema = { dependencies = [ "prelude" ] @@ -435,7 +435,7 @@ let additions = , "unsafe-coerce" ] , repo = "https://github.com/mlabs-haskell/purescript-cardano-types" - , version = "v2.0.0" + , version = "v1.0.1" } , cardano-message-signing = { dependencies = diff --git a/spago-packages.nix b/spago-packages.nix index 48997ba7f8..ecec85db80 100644 --- a/spago-packages.nix +++ b/spago-packages.nix @@ -238,8 +238,8 @@ let version = "v1.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-key-wallet"; - rev = "fd50834bad329b3064b602e6487e9471ea102341"; - sha256 = "0bgizyhrpmj51lz24cnr6wvxwgvm41z24c66kk3lzhwq798n5q50"; + rev = "55f176dbedddbd37297a3d1f90c756420159454e"; + sha256 = "1fr77kvgdvxqi0jhg98balrwpf7rlhwiyrf1v8z2112yyln2myj9"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; @@ -271,11 +271,11 @@ let "cardano-serialization-lib" = pkgs.stdenv.mkDerivation { name = "cardano-serialization-lib"; - version = "v1.0.0"; + version = "26d437c3f398172c839b93b57c30eb43a7fa7ca0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-serialization-lib"; - rev = "903bf0adeefedc4d065ad6523ad079433bdd8e32"; - sha256 = "0jlfxrx037hyd4v0j7l2b16yxlm6nw6qlnr992hj9nzip36vbpfg"; + rev = "26d437c3f398172c839b93b57c30eb43a7fa7ca0"; + sha256 = "1ikz6j3jvls3cvl6znrw55f59abzdaf7ggd2x7j3f81m5cvkxggr"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; @@ -283,11 +283,11 @@ let "cardano-types" = pkgs.stdenv.mkDerivation { name = "cardano-types"; - version = "v2.0.0"; + version = "v1.0.1"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-types"; - rev = "780c28ee27d0ba7e76884a565ad60dea0a414842"; - sha256 = "1my7fgk218h6yllw09zf1m55hpn787mjq79whxxm9lqgarrdp66z"; + rev = "715d4b2dcf8b29cb45001209ee562f758a513261"; + sha256 = "1xcrdmpwd3qcdiyjfrj0z2dh56l4z1s97r25b6nhlqwmwz7qz19z"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; diff --git a/src/Contract/Transaction.purs b/src/Contract/Transaction.purs index 1ed8e59f25..1c038632f9 100644 --- a/src/Contract/Transaction.purs +++ b/src/Contract/Transaction.purs @@ -132,6 +132,7 @@ import Ctl.Internal.Lens , _scriptRef , _totalCollateral , _ttl + , _update , _validityStartInterval , _vkeys , _withdrawals diff --git a/src/Internal/BalanceTx/RedeemerIndex.purs b/src/Internal/BalanceTx/RedeemerIndex.purs index 47a9388101..1b4182808b 100644 --- a/src/Internal/BalanceTx/RedeemerIndex.purs +++ b/src/Internal/BalanceTx/RedeemerIndex.purs @@ -81,7 +81,7 @@ unindexedRedeemerToRedeemer :: UnindexedRedeemer -> Redeemer unindexedRedeemerToRedeemer (UnindexedRedeemer { datum, purpose }) = Redeemer { tag: redeemerPurposeToRedeemerTag purpose - , "data": wrap datum + , "data": datum , index: BigNum.zero , exUnits: ExUnits.empty } @@ -107,7 +107,7 @@ indexedRedeemerToRedeemer (IndexedRedeemer { tag, datum, index }) = Redeemer { tag , index: BigNum.fromInt index - , data: wrap datum + , data: datum , exUnits: ExUnits.empty } diff --git a/src/Internal/Contract/Wallet.purs b/src/Internal/Contract/Wallet.purs index a2808b2875..c0262a8c0e 100644 --- a/src/Internal/Contract/Wallet.purs +++ b/src/Internal/Contract/Wallet.purs @@ -137,7 +137,8 @@ getWalletCollateral = do utxos <- (liftAff $ queryHandle.utxosAt addr) <#> hush >>> fromMaybe Map.empty >>= filterLockedUtxos - mColl <- liftAff $ (unwrap kw).selectCollateral minRequiredCollateral + mColl <- liftAff $ (unwrap kw).selectCollateral + minRequiredCollateral coinsPerUtxoByte (UInt.toInt maxCollateralInputs) utxos diff --git a/src/Internal/Lens.purs b/src/Internal/Lens.purs index 4be16aa3e4..94a9bf7866 100644 --- a/src/Internal/Lens.purs +++ b/src/Internal/Lens.purs @@ -25,6 +25,7 @@ module Ctl.Internal.Lens , _scriptRef , _totalCollateral , _ttl + , _update , _validityStartInterval , _vkeys , _withdrawals @@ -55,6 +56,7 @@ import Cardano.Types , TransactionOutput , TransactionUnspentOutput , TransactionWitnessSet + , Update , Value , Vkeywitness ) @@ -127,6 +129,9 @@ _auxiliaryDataHash = _Newtype <<< prop (Proxy :: Proxy "auxiliaryDataHash") _ttl :: Lens' TransactionBody (Maybe Slot) _ttl = _Newtype <<< prop (Proxy :: Proxy "ttl") +_update :: Lens' TransactionBody (Maybe Update) +_update = _Newtype <<< prop (Proxy :: Proxy "update") + _validityStartInterval :: Lens' TransactionBody (Maybe Slot) _validityStartInterval = _Newtype <<< prop (Proxy :: Proxy "validityStartInterval") diff --git a/src/Internal/QueryM/Ogmios.purs b/src/Internal/QueryM/Ogmios.purs index 2cdbd39c02..8d1cb2eb82 100644 --- a/src/Internal/QueryM/Ogmios.purs +++ b/src/Internal/QueryM/Ogmios.purs @@ -99,7 +99,7 @@ import Cardano.Serialization.Lib (fromBytes, ipv4_new) import Cardano.Types ( Bech32String , BigNum(BigNum) - , Language(PlutusV1, PlutusV2, PlutusV3) + , Language(PlutusV1, PlutusV2) , RedeemerTag , VRFKeyHash(VRFKeyHash) ) @@ -1220,11 +1220,6 @@ instance EncodeAeson AdditionalUtxoSet where { "language": "plutus:v2" , "cbor": byteArrayToHex $ unwrap $ PlutusScript.getBytes ps } - encodeScriptRef (PlutusScriptRef (ps@(PlutusScript (_ /\ PlutusV3)))) = - encodeAeson - { "language": "plutus:v2" - , "cbor": byteArrayToHex $ unwrap $ PlutusScript.getBytes ps - } encodeValue :: Value -> Aeson encodeValue value = encodeMap $ map encodeMap $ Map.union adaPart nonAdaPart diff --git a/src/Internal/Test/KeyDir.purs b/src/Internal/Test/KeyDir.purs index 075046de79..42ff140a88 100644 --- a/src/Internal/Test/KeyDir.purs +++ b/src/Internal/Test/KeyDir.purs @@ -285,13 +285,12 @@ backupWallets :: FilePath -> ContractEnv -> Array KeyWallet -> Aff Unit backupWallets backup env walletsArray = liftAff $ flip parTraverse_ walletsArray \wallet -> do - address <- liftAff $ Address.toBech32 <$> (unwrap wallet).address - env.networkId payment <- getPrivatePaymentKey wallet mbStake <- getPrivateStakeKey wallet + address <- liftAff $ Address.toBech32 <$> (unwrap wallet).address + env.networkId let folder = Path.concat [ backup, address ] - mkdir folder privatePaymentKeyToFile (Path.concat [ folder, "payment_signing_key" ]) payment @@ -309,7 +308,6 @@ fundWallets env walletsArray distrArray = runContractInEnv env $ noLogs do Value.mkValue (wrap value) MultiAsset.empty - txHash <- submitTxFromConstraints mempty constraints awaitTxConfirmed txHash let @@ -449,6 +447,7 @@ mustPayToKeyWallet mustPayToKeyWallet wallet value = do kwPaymentKey <- getPrivatePaymentKey wallet kwMStakeKey <- getPrivateStakeKey wallet + let convert = PublicKey.hash <<< PrivateKey.toPublicKey payment = over wrap convert $ kwPaymentKey diff --git a/src/Internal/Wallet/Cip30Mock.purs b/src/Internal/Wallet/Cip30Mock.purs index 17a6117b44..95d5b9d50d 100644 --- a/src/Internal/Wallet/Cip30Mock.purs +++ b/src/Internal/Wallet/Cip30Mock.purs @@ -133,7 +133,8 @@ mkCip30Mock pKey mSKey = do maxCollateralInputs = UInt.toInt $ pparams.maxCollateralInputs coll <- liftAff $ - (unwrap keyWallet).selectCollateral minRequiredCollateral + (unwrap keyWallet).selectCollateral + minRequiredCollateral coinsPerUtxoByte maxCollateralInputs utxos diff --git a/templates/ctl-scaffold/package-lock.json b/templates/ctl-scaffold/package-lock.json index 6d800dbebf..561dc93e3a 100644 --- a/templates/ctl-scaffold/package-lock.json +++ b/templates/ctl-scaffold/package-lock.json @@ -9,10 +9,8 @@ "version": "0.1.0", "license": "MIT", "dependencies": { - "@emurgo/cardano-serialization-lib-browser": "v12.0.0-alpha.31", - "@emurgo/cardano-serialization-lib-nodejs": "v12.0.0-alpha.31", "@mlabs-haskell/cardano-message-signing": "^1.0.1", - "@mlabs-haskell/cardano-serialization-lib-gc": "v12.0.0-alpha.31", + "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", "@mlabs-haskell/json-bigint": "2.0.0", "@mlabs-haskell/uplc-apply-args": "2.0.1", "@noble/secp256k1": "^1.7.0", @@ -60,14 +58,14 @@ "integrity": "sha512-PoKh1tQnJX18f8iEr8Jk1KXxKCn9eqaSslMI1pyOJvYRJhQVDLCh0+9YReufjp0oFJIY1ShcrR+4/WnECVZUKQ==" }, "node_modules/@emurgo/cardano-serialization-lib-browser": { - "version": "12.0.0-alpha.31", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-12.0.0-alpha.31.tgz", - "integrity": "sha512-LEMiaui1ByuVuesWGUQ4CzksZJW9FeL/KL8HN2smSTjuCA3IaAp2VXZPxPjxP/0VbF+EM1aLkPn6DD02U/qy5Q==" + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-11.5.0.tgz", + "integrity": "sha512-qchOJ9NYDUz10tzs5r5QhP9hK0p+ZOlRiBwPdTAxqAYLw/8emYBkQQLaS8T1DF6EkeudyrgS00ym5Trw1fo4iA==" }, "node_modules/@emurgo/cardano-serialization-lib-nodejs": { - "version": "12.0.0-alpha.31", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-12.0.0-alpha.31.tgz", - "integrity": "sha512-YvE4JmTwQTM+8Blbmfa7qv44vWr3qWRn5RsfjxmyptyJwAk0Z/AfGQjYyWO/LmFsj8YCIZD2lS80LhrzzkN+Kw==" + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-11.5.0.tgz", + "integrity": "sha512-IlVABlRgo9XaTR1NunwZpWcxnfEv04ba2l1vkUz4S1W7Jt36F4CtffP+jPeqBZGnAe+fnUwo0XjIJC3ZTNToNQ==" }, "node_modules/@esbuild/android-arm": { "version": "0.18.11", @@ -501,12 +499,12 @@ } }, "node_modules/@mlabs-haskell/cardano-serialization-lib-gc": { - "version": "12.0.0-alpha.31", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-12.0.0-alpha.31.tgz", - "integrity": "sha512-QQBzl7rNRy7wk37uxzWJXCZfZRt3aTlfQb3kmb10ulY/janlUNETmS09OtiJbK/BdV5Fu7Gv+Mdda3ggMIL/bg==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-1.0.10.tgz", + "integrity": "sha512-7XFxxMvZH6oogWVP/teveVRUTRboWfY5fT0bkRDu68u9yb2HBjoMxkCkmF7MvJBVs2i0unt4UnzcrNm0dmHriQ==", "dependencies": { - "@emurgo/cardano-serialization-lib-browser": "^12.0.0-alpha.31", - "@emurgo/cardano-serialization-lib-nodejs": "^12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-browser": "^11.2.1", + "@emurgo/cardano-serialization-lib-nodejs": "^11.2.1", "@mlabs-haskell/csl-gc-wrapper": "^1.0.2" } }, @@ -5520,14 +5518,14 @@ "integrity": "sha512-PoKh1tQnJX18f8iEr8Jk1KXxKCn9eqaSslMI1pyOJvYRJhQVDLCh0+9YReufjp0oFJIY1ShcrR+4/WnECVZUKQ==" }, "@emurgo/cardano-serialization-lib-browser": { - "version": "12.0.0-alpha.31", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-12.0.0-alpha.31.tgz", - "integrity": "sha512-LEMiaui1ByuVuesWGUQ4CzksZJW9FeL/KL8HN2smSTjuCA3IaAp2VXZPxPjxP/0VbF+EM1aLkPn6DD02U/qy5Q==" + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-browser/-/cardano-serialization-lib-browser-11.5.0.tgz", + "integrity": "sha512-qchOJ9NYDUz10tzs5r5QhP9hK0p+ZOlRiBwPdTAxqAYLw/8emYBkQQLaS8T1DF6EkeudyrgS00ym5Trw1fo4iA==" }, "@emurgo/cardano-serialization-lib-nodejs": { - "version": "12.0.0-alpha.31", - "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-12.0.0-alpha.31.tgz", - "integrity": "sha512-YvE4JmTwQTM+8Blbmfa7qv44vWr3qWRn5RsfjxmyptyJwAk0Z/AfGQjYyWO/LmFsj8YCIZD2lS80LhrzzkN+Kw==" + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/@emurgo/cardano-serialization-lib-nodejs/-/cardano-serialization-lib-nodejs-11.5.0.tgz", + "integrity": "sha512-IlVABlRgo9XaTR1NunwZpWcxnfEv04ba2l1vkUz4S1W7Jt36F4CtffP+jPeqBZGnAe+fnUwo0XjIJC3ZTNToNQ==" }, "@esbuild/android-arm": { "version": "0.18.11", @@ -5754,12 +5752,12 @@ } }, "@mlabs-haskell/cardano-serialization-lib-gc": { - "version": "12.0.0-alpha.31", - "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-12.0.0-alpha.31.tgz", - "integrity": "sha512-QQBzl7rNRy7wk37uxzWJXCZfZRt3aTlfQb3kmb10ulY/janlUNETmS09OtiJbK/BdV5Fu7Gv+Mdda3ggMIL/bg==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mlabs-haskell/cardano-serialization-lib-gc/-/cardano-serialization-lib-gc-1.0.10.tgz", + "integrity": "sha512-7XFxxMvZH6oogWVP/teveVRUTRboWfY5fT0bkRDu68u9yb2HBjoMxkCkmF7MvJBVs2i0unt4UnzcrNm0dmHriQ==", "requires": { - "@emurgo/cardano-serialization-lib-browser": "^12.0.0-alpha.31", - "@emurgo/cardano-serialization-lib-nodejs": "^12.0.0-alpha.31", + "@emurgo/cardano-serialization-lib-browser": "^11.2.1", + "@emurgo/cardano-serialization-lib-nodejs": "^11.2.1", "@mlabs-haskell/csl-gc-wrapper": "^1.0.2" } }, diff --git a/templates/ctl-scaffold/package.json b/templates/ctl-scaffold/package.json index b746c3ce7d..f34f4d9e34 100644 --- a/templates/ctl-scaffold/package.json +++ b/templates/ctl-scaffold/package.json @@ -26,9 +26,7 @@ "license": "MIT", "dependencies": { "@mlabs-haskell/cardano-message-signing": "^1.0.1", - "@mlabs-haskell/cardano-serialization-lib-gc": "v12.0.0-alpha.31", - "@emurgo/cardano-serialization-lib-nodejs": "v12.0.0-alpha.31", - "@emurgo/cardano-serialization-lib-browser": "v12.0.0-alpha.31", + "@mlabs-haskell/cardano-serialization-lib-gc": "^1.0.10", "@mlabs-haskell/json-bigint": "2.0.0", "@mlabs-haskell/uplc-apply-args": "2.0.1", "@noble/secp256k1": "^1.7.0", diff --git a/templates/ctl-scaffold/packages.dhall b/templates/ctl-scaffold/packages.dhall index 3427369803..669048fce7 100644 --- a/templates/ctl-scaffold/packages.dhall +++ b/templates/ctl-scaffold/packages.dhall @@ -280,7 +280,7 @@ let additions = ] , repo = "https://github.com/mlabs-haskell/purescript-cardano-serialization-lib" - , version = "v1.0.0" + , version = "26d437c3f398172c839b93b57c30eb43a7fa7ca0" } , cardano-plutus-data-schema = { dependencies = [ "prelude" ] @@ -435,7 +435,7 @@ let additions = , "unsafe-coerce" ] , repo = "https://github.com/mlabs-haskell/purescript-cardano-types" - , version = "v2.0.0" + , version = "v1.0.1" } , cardano-message-signing = { dependencies = diff --git a/templates/ctl-scaffold/spago-packages.nix b/templates/ctl-scaffold/spago-packages.nix index 6d317917f3..e80b0fecbf 100644 --- a/templates/ctl-scaffold/spago-packages.nix +++ b/templates/ctl-scaffold/spago-packages.nix @@ -238,8 +238,8 @@ let version = "v1.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-key-wallet"; - rev = "fd50834bad329b3064b602e6487e9471ea102341"; - sha256 = "0bgizyhrpmj51lz24cnr6wvxwgvm41z24c66kk3lzhwq798n5q50"; + rev = "55f176dbedddbd37297a3d1f90c756420159454e"; + sha256 = "1fr77kvgdvxqi0jhg98balrwpf7rlhwiyrf1v8z2112yyln2myj9"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; @@ -271,17 +271,17 @@ let "cardano-serialization-lib" = pkgs.stdenv.mkDerivation { name = "cardano-serialization-lib"; - version = "v1.0.0"; + version = "26d437c3f398172c839b93b57c30eb43a7fa7ca0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-serialization-lib"; - rev = "903bf0adeefedc4d065ad6523ad079433bdd8e32"; - sha256 = "0jlfxrx037hyd4v0j7l2b16yxlm6nw6qlnr992hj9nzip36vbpfg"; + rev = "26d437c3f398172c839b93b57c30eb43a7fa7ca0"; + sha256 = "1ikz6j3jvls3cvl6znrw55f59abzdaf7ggd2x7j3f81m5cvkxggr"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; }; - "cardano-transaction-lib" = pkgs.stdenv.mkDerivation { + "cardano-transaction-lib" = pkgs.stdenv.mkDerivation { name = "cardano-transaction-lib"; version = "423e27b3f56b1a66db8d3126c22cea9bda7e50da"; src = pkgs.fetchgit { @@ -295,11 +295,11 @@ let "cardano-types" = pkgs.stdenv.mkDerivation { name = "cardano-types"; - version = "v2.0.0"; + version = "v1.0.1"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-types"; - rev = "780c28ee27d0ba7e76884a565ad60dea0a414842"; - sha256 = "1my7fgk218h6yllw09zf1m55hpn787mjq79whxxm9lqgarrdp66z"; + rev = "715d4b2dcf8b29cb45001209ee562f758a513261"; + sha256 = "1xcrdmpwd3qcdiyjfrj0z2dh56l4z1s97r25b6nhlqwmwz7qz19z"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; diff --git a/test/Fixtures.purs b/test/Fixtures.purs index 25e6f80b5a..e4a9f0783f 100644 --- a/test/Fixtures.purs +++ b/test/Fixtures.purs @@ -86,19 +86,25 @@ import Cardano.Types ( AuxiliaryData(AuxiliaryData) , Bech32String , Certificate - ( PoolRetirement - , PoolRegistration - , StakeDelegation + ( StakeRegistration , StakeDeregistration - , StakeRegistration + , StakeDelegation + , PoolRegistration + , PoolRetirement + , GenesisKeyDelegation + , MoveInstantaneousRewardsCert ) , Coin(Coin) , Credential(PubKeyHashCredential) , Ed25519KeyHash , Epoch(Epoch) + , ExUnitPrices(ExUnitPrices) , ExUnits(ExUnits) , GeneralTransactionMetadata(GeneralTransactionMetadata) , Language(PlutusV2) + , MIRPot(Reserves, Treasury) + , MIRToStakeCredentials(MIRToStakeCredentials) + , MoveInstantaneousReward(ToOtherPot, ToStakeCreds) , NativeScript ( TimelockExpiry , TimelockStart @@ -115,9 +121,12 @@ import Cardano.Types , PoolMetadata(PoolMetadata) , PoolParams(PoolParams) , PoolPubKeyHash(PoolPubKeyHash) + , ProposedProtocolParameterUpdates(ProposedProtocolParameterUpdates) + , ProtocolParamUpdate(ProtocolParamUpdate) + , ProtocolVersion(ProtocolVersion) , Redeemer(Redeemer) , RedeemerTag(Spend) - , Relay(MultiHostName, SingleHostName, SingleHostAddr) + , Relay(SingleHostAddr, SingleHostName, MultiHostName) , RewardAddress , ScriptHash , ScriptRef(NativeScriptRef) @@ -130,6 +139,7 @@ import Cardano.Types , TransactionWitnessSet(TransactionWitnessSet) , URL(URL) , UnitInterval(UnitInterval) + , Update(Update) , UtxoMap , Value(Value) , Vkey(Vkey) @@ -167,6 +177,7 @@ import JS.BigInt as BigInt import Node.Encoding (Encoding(UTF8)) import Node.FS.Sync (readTextFile) import Partial.Unsafe (unsafePartial) +import Test.Ctl.Fixtures.CostModels (costModelsFixture1) txOutputFixture1 :: TransactionOutput txOutputFixture1 = @@ -243,6 +254,49 @@ bigNumOne = BigNum.fromInt 1 rewardAddress1 :: RewardAddress rewardAddress1 = { networkId: TestnetId, stakeCredential: wrap stake1 } +proposedProtocolParameterUpdates1 :: ProposedProtocolParameterUpdates +proposedProtocolParameterUpdates1 = ProposedProtocolParameterUpdates $ + Map.fromFoldable + [ ( unsafePartial $ fromJust $ decodeCbor $ wrap $ hexToByteArrayUnsafe + "5d677265fa5bb21ce6d8c7502aca70b9316d10e958611f3c6b758f65" + ) /\ + ProtocolParamUpdate + { minfeeA: Just $ Coin $ BigNum.fromInt 1 + , minfeeB: Just $ Coin $ BigNum.fromInt 1 + , maxBlockBodySize: Just $ UInt.fromInt 10000 + , maxTxSize: Just $ UInt.fromInt 10000 + , maxBlockHeaderSize: Just $ UInt.fromInt 1000 + , keyDeposit: Just $ Coin $ BigNum.fromInt 1 + , poolDeposit: Just $ Coin $ BigNum.fromInt 1 + , maxEpoch: Just $ Epoch one + , nOpt: Just $ UInt.fromInt 1 + , poolPledgeInfluence: Just $ UnitInterval + { numerator: bigNumOne, denominator: bigNumOne } + , expansionRate: Just $ UnitInterval + { numerator: bigNumOne, denominator: bigNumOne } + , treasuryGrowthRate: Just $ UnitInterval + { numerator: bigNumOne, denominator: bigNumOne } + , protocolVersion: Just $ ProtocolVersion + { major: 1, minor: 1 } + , minPoolCost: Just $ wrap bigNumOne + , adaPerUtxoByte: Just $ wrap bigNumOne + , costModels: Just costModelsFixture1 + , executionCosts: Just $ ExUnitPrices + { memPrice: UnitInterval + { numerator: bigNumOne, denominator: bigNumOne } + , stepPrice: UnitInterval + { numerator: bigNumOne, denominator: bigNumOne } + } + , maxTxExUnits: Just $ ExUnits + { mem: BigNum.fromInt 1, steps: BigNum.fromInt 1 } + , maxBlockExUnits: Just $ ExUnits + { mem: BigNum.fromInt 1, steps: BigNum.fromInt 1 } + , maxValueSize: Just $ UInt.fromInt 1 + , collateralPercentage: Just $ UInt.fromInt 140 + , maxCollateralInputs: Just $ UInt.fromInt 10 + } + ] + -- | Extend this for your needs. type SampleTxConfig = { inputs :: Array TransactionInput } @@ -271,6 +325,7 @@ mkSampleTx startTx changes = , ttl , certs , withdrawals + , update , auxiliaryDataHash , validityStartInterval , mint @@ -296,6 +351,7 @@ mkSampleTx startTx changes = , ttl , certs , withdrawals + , update , auxiliaryDataHash , validityStartInterval , mint @@ -306,10 +362,6 @@ mkSampleTx startTx changes = , networkId , collateralReturn , totalCollateral - , votingProposals: [] - , votingProcedures: wrap Map.empty - , currentTreasuryValue: Nothing - , donation: Nothing } , witnessSet , isValid @@ -352,6 +404,7 @@ txFixture1 = , ttl: Nothing , certs: [] , withdrawals: Map.empty + , update: Nothing , auxiliaryDataHash: Nothing , validityStartInterval: Nothing , mint: Nothing @@ -362,10 +415,6 @@ txFixture1 = , networkId: Just MainnetId , collateralReturn: Nothing , totalCollateral: Nothing - , votingProposals: [] - , votingProcedures: wrap Map.empty - , currentTreasuryValue: Nothing - , donation: Nothing } , witnessSet: TransactionWitnessSet { vkeys: [] @@ -389,6 +438,7 @@ txFixture2 = , ttl: Nothing , certs: [] , withdrawals: Map.empty + , update: Nothing , auxiliaryDataHash: Nothing , validityStartInterval: Nothing , mint: Nothing @@ -399,10 +449,6 @@ txFixture2 = , networkId: Just MainnetId , collateralReturn: Nothing , totalCollateral: Nothing - , votingProposals: [] - , votingProcedures: wrap Map.empty - , currentTreasuryValue: Nothing - , donation: Nothing } , witnessSet: witnessSetFixture3Value , isValid: true @@ -444,6 +490,7 @@ txFixture3 = , ttl: Nothing , certs: [] , withdrawals: Map.empty + , update: Nothing , referenceInputs: [ txInputFixture1 ] , auxiliaryDataHash: Nothing , validityStartInterval: Nothing @@ -454,10 +501,6 @@ txFixture3 = , networkId: Just MainnetId , collateralReturn: Nothing , totalCollateral: Nothing - , votingProposals: [] - , votingProcedures: wrap Map.empty - , currentTreasuryValue: Nothing - , donation: Nothing } , witnessSet: TransactionWitnessSet { vkeys: [] @@ -564,9 +607,36 @@ txFixture4 = { poolKeyHash: PoolPubKeyHash ed25519KeyHash1 , epoch: Epoch one } + , GenesisKeyDelegation + { genesisHash: unsafePartial $ fromJust $ decodeCbor $ wrap $ + hexToByteArrayUnsafe + "5d677265fa5bb21ce6d8c7502aca70b9316d10e958611f3c6b758f65" + , genesisDelegateHash: unsafePartial $ fromJust $ decodeCbor + $ wrap + $ + hexToByteArrayUnsafe + "5d677265fa5bb21ce6d8c7502aca70b9316d10e958611f3c6b758f65" + , vrfKeyhash: unsafePartial $ fromJust $ decodeCbor $ wrap $ + hexToByteArrayUnsafe + "fbf6d41985670b9041c5bf362b5262cf34add5d265975de176d613ca05f37096" + } + , MoveInstantaneousRewardsCert $ ToOtherPot + { pot: Reserves + , amount: wrap bigNumOne + } + , MoveInstantaneousRewardsCert $ ToStakeCreds + { pot: Treasury + , amounts: MIRToStakeCredentials $ Map.fromFoldable + [ wrap stake1 /\ Int.newPositive bigNumOne ] + } ] , withdrawals: Map.fromFoldable [ rewardAddress1 /\ Coin BigNum.one ] + , update: Just $ Update + { proposedProtocolParameterUpdates: + proposedProtocolParameterUpdates1 + , epoch: Epoch zero + } , auxiliaryDataHash: decodeCbor $ wrap $ byteArrayFromIntArrayUnsafe $ Array.replicate 32 0 @@ -583,10 +653,6 @@ txFixture4 = , networkId: Just MainnetId , collateralReturn: Just txOutputFixture1 , totalCollateral: Just $ Coin $ BigNum.fromInt 5_000_000 - , votingProposals: [] - , votingProcedures: wrap Map.empty - , currentTreasuryValue: Nothing - , donation: Nothing } , witnessSet: TransactionWitnessSet { vkeys: [] @@ -624,6 +690,7 @@ txFixture5 = , ttl: Nothing , certs: [] , withdrawals: Map.empty + , update: Nothing , auxiliaryDataHash: Nothing , validityStartInterval: Nothing , mint: Nothing @@ -634,10 +701,6 @@ txFixture5 = , networkId: Just MainnetId , collateralReturn: Nothing , totalCollateral: Nothing - , votingProposals: [] - , votingProcedures: wrap Map.empty - , currentTreasuryValue: Nothing - , donation: Nothing } , witnessSet: TransactionWitnessSet { vkeys: [] @@ -661,6 +724,7 @@ txFixture6 = , ttl: Nothing , certs: [] , withdrawals: Map.empty + , update: Nothing , auxiliaryDataHash: Nothing , validityStartInterval: Nothing , mint: Nothing @@ -671,10 +735,6 @@ txFixture6 = , networkId: Just MainnetId , collateralReturn: Nothing , totalCollateral: Nothing - , votingProposals: [] - , votingProcedures: wrap Map.empty - , currentTreasuryValue: Nothing - , donation: Nothing } , witnessSet: TransactionWitnessSet { vkeys: [] @@ -1291,7 +1351,7 @@ redeemerFixture1 :: Redeemer redeemerFixture1 = Redeemer { tag: Spend , index: BigNum.fromInt 0 - , data: wrap plutusDataFixture7 + , data: plutusDataFixture7 , exUnits: ExUnits { mem: BigNum.fromInt 1 , steps: BigNum.fromInt 1 diff --git a/test/Unit.purs b/test/Unit.purs index 9bd4da80eb..da961ca05e 100644 --- a/test/Unit.purs +++ b/test/Unit.purs @@ -15,6 +15,8 @@ import Test.Ctl.ApplyArgs as ApplyArgs import Test.Ctl.Blockfrost.Aeson.Suite as Blockfrost.Aeson import Test.Ctl.Blockfrost.ProtocolParameters as Blockfrost.ProtocolParameters import Test.Ctl.CoinSelection as CoinSelection +import Test.Ctl.CslGc as CslGc +import Test.Ctl.Data as Data import Test.Ctl.Data.Interval as Ctl.Data.Interval import Test.Ctl.E2E.Route as E2E.Route import Test.Ctl.Hashing as Hashing @@ -48,6 +50,8 @@ testPlan = do Ipv6.suite NativeScript.suite Bip32.suite + CslGc.suite + Data.suite Hashing.suite Partition.suite Plutus.Time.suite From fbd6723310ab1efd0e615c7585131ea0235c6a6d Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Thu, 11 Jul 2024 17:04:05 +0400 Subject: [PATCH 36/52] WIP: rewrite examples --- CHANGELOG.md | 5 +++ examples/AlwaysMints.purs | 53 +++++++++++++++-------- examples/AlwaysSucceeds.purs | 79 +++++++++++++++++----------------- examples/ECDSA.purs | 76 ++++++++++++++++++-------------- examples/Schnorr.purs | 81 ++++++++++++++++++++--------------- scripts/import-fixer.sh | 7 +++ src/Contract/Transaction.purs | 13 ++++++ 7 files changed, 190 insertions(+), 124 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b5ae290e8..4b9d74416a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,8 +71,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Added +- Ability to spend native script outputs using a reference input that contains an inline native script. + ### Removed +- `Contract.Transaction.submitTxFromConstraintsReturningFee` +- `Contract.Transaction` lens values + ### Changed ### Fixed diff --git a/examples/AlwaysMints.purs b/examples/AlwaysMints.purs index 85553e9918..ab56202064 100644 --- a/examples/AlwaysMints.purs +++ b/examples/AlwaysMints.purs @@ -11,18 +11,37 @@ module Ctl.Examples.AlwaysMints import Contract.Prelude +import Cardano.Transaction.Builder + ( CredentialWitness(NativeScriptCredential, PlutusScriptCredential) + , ScriptWitness(ScriptValue, ScriptReference) + , TransactionBuilderStep + ( SpendOutput + , Pay + , MintAsset + , RegisterStake + , IssueCertificate + , WithdrawStake + , RequireSignature + , RegisterPool + , RetirePool + , IncludeDatum + , SetTTL + , SetValidityStartInterval + , SetIsValid + ) + ) import Cardano.Types (PlutusScript) import Cardano.Types.Int as Int -import Cardano.Types.Mint as Mint import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.Transaction as Transaction import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftContractM, runContract) -import Contract.ScriptLookups as Lookups +import Contract.PlutusData (unitRedeemer) import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) -import Contract.Transaction (awaitTxConfirmed, submitTxFromConstraints) -import Contract.TxConstraints as Constraints +import Contract.Transaction (awaitTxConfirmed, submitTxFromBuildPlan) import Ctl.Examples.Helpers (mkAssetName) as Helpers +import Data.Map as Map main :: Effect Unit main = example testnetNamiConfig @@ -30,21 +49,17 @@ main = example testnetNamiConfig contract :: Contract Unit contract = do logInfo' "Running Examples.AlwaysMints" - mp <- alwaysMintsPolicy - let cs = PlutusScript.hash mp - tn <- Helpers.mkAssetName "TheToken" - let - constraints :: Constraints.TxConstraints - constraints = Constraints.mustMintValue - $ Mint.singleton cs tn - $ Int.fromInt 100 - - lookups :: Lookups.ScriptLookups - lookups = Lookups.plutusMintingPolicy mp - - txId <- submitTxFromConstraints lookups constraints - - awaitTxConfirmed txId + mintingPolicy <- alwaysMintsPolicy + let scriptHash = PlutusScript.hash mintingPolicy + tokenName <- Helpers.mkAssetName "TheToken" + awaitTxConfirmed <<< Transaction.hash =<< + submitTxFromBuildPlan Map.empty mempty + [ MintAsset + scriptHash + tokenName + (Int.fromInt 100) + (PlutusScriptCredential (ScriptValue mintingPolicy) unitRedeemer) + ] logInfo' "Tx submitted successfully!" example :: ContractParams -> Effect Unit diff --git a/examples/AlwaysSucceeds.purs b/examples/AlwaysSucceeds.purs index d227c52aa2..4652c08c47 100644 --- a/examples/AlwaysSucceeds.purs +++ b/examples/AlwaysSucceeds.purs @@ -12,37 +12,47 @@ module Ctl.Examples.AlwaysSucceeds import Contract.Prelude +import Cardano.Transaction.Builder + ( DatumWitness(DatumValue, DatumReference) + , OutputWitness(NativeScriptOutput, PlutusScriptOutput) + , ScriptWitness(ScriptValue, ScriptReference) + , TransactionBuilderStep(SpendOutput, Pay) + ) import Cardano.Types ( Credential(PubKeyHashCredential, ScriptHashCredential) + , OutputDatum(OutputDatum) + , PaymentCredential(PaymentCredential) , PlutusScript , ScriptHash + , StakeCredential(StakeCredential) , TransactionHash - , _input + , TransactionOutput(TransactionOutput) ) import Cardano.Types.BigNum as BigNum -import Cardano.Types.PlutusData as Datum +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.DataHash as PlutusData +import Cardano.Types.OutputDatum (OutputDatum(OutputDatumHash, OutputDatum)) import Cardano.Types.PlutusData as PlutusData import Cardano.Types.PlutusScript as Script +import Cardano.Types.Transaction as Transaction +import Cardano.Types.TransactionUnspentOutput (toUtxoMap) import Contract.Address (mkAddress) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) import Contract.PlutusData (unitRedeemer) -import Contract.ScriptLookups as Lookups import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( awaitTxConfirmed , lookupTxHash - , submitTxFromConstraints + , submitTxFromBuildPlan ) -import Contract.TxConstraints (TxConstraints) -import Contract.TxConstraints as Constraints import Contract.Utxos (utxosAt) import Contract.Value as Value import Contract.Wallet (ownStakePubKeyHashes) import Control.Monad.Error.Class (liftMaybe) import Data.Array (head) -import Data.Lens (view) +import Data.Map as Map import Effect.Exception (error) main :: Effect Unit @@ -67,27 +77,16 @@ payToAlwaysSucceeds :: ScriptHash -> Contract TransactionHash payToAlwaysSucceeds vhash = do -- Send to own stake credential. This is used to test mustPayToScriptAddress. mbStakeKeyHash <- join <<< head <$> ownStakePubKeyHashes - let - value = Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 - - constraints :: TxConstraints - constraints = - case mbStakeKeyHash of - Nothing -> - Constraints.mustPayToScript vhash PlutusData.unit - Constraints.DatumWitness - value - Just stakeKeyHash -> - Constraints.mustPayToScriptAddress vhash - (PubKeyHashCredential $ unwrap stakeKeyHash) - Datum.unit - Constraints.DatumWitness - value - - lookups :: Lookups.ScriptLookups - lookups = mempty - - submitTxFromConstraints lookups constraints + scriptAddress <- mkAddress (PaymentCredential $ ScriptHashCredential vhash) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> mbStakeKeyHash) + Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address: scriptAddress + , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ] spendFromAlwaysSucceeds :: ScriptHash @@ -101,7 +100,7 @@ spendFromAlwaysSucceeds vhash validator txId = do (wrap $ ScriptHashCredential vhash) (wrap <<< PubKeyHashCredential <<< unwrap <$> mbStakeKeyHash) utxos <- utxosAt scriptAddress - txInput <- + utxo <- liftM ( error ( "The id " @@ -110,17 +109,17 @@ spendFromAlwaysSucceeds vhash validator txId = do <> show scriptAddress ) ) - (view _input <$> head (lookupTxHash txId utxos)) - let - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - <> Lookups.unspentOutputs utxos - - constraints :: TxConstraints - constraints = - Constraints.mustSpendScriptOutput txInput unitRedeemer - spendTxId <- submitTxFromConstraints lookups constraints - awaitTxConfirmed spendTxId + $ head (lookupTxHash txId utxos) + spendTx <- submitTxFromBuildPlan (Map.union utxos $ toUtxoMap [ utxo ]) + mempty + [ SpendOutput + utxo + ( Just $ PlutusScriptOutput (ScriptValue validator) unitRedeemer $ Just + $ DatumValue + $ PlutusData.unit + ) + ] + awaitTxConfirmed $ Transaction.hash spendTx logInfo' "Successfully spent locked values." alwaysSucceedsScript :: Contract PlutusScript diff --git a/examples/ECDSA.purs b/examples/ECDSA.purs index 7aeaaa6f76..1a99d2de5c 100644 --- a/examples/ECDSA.purs +++ b/examples/ECDSA.purs @@ -2,7 +2,21 @@ module Ctl.Examples.ECDSA (contract) where import Contract.Prelude +import Cardano.Transaction.Builder + ( DatumWitness(DatumValue) + , OutputWitness(PlutusScriptOutput) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(SpendOutput, Pay) + ) +import Cardano.Types + ( OutputDatum(OutputDatumHash) + , TransactionOutput(TransactionOutput) + ) import Cardano.Types.Credential (Credential(ScriptHashCredential)) +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.Transaction as Transaction +import Cardano.Types.TransactionUnspentOutput (_input, fromUtxoMap, toUtxoMap) import Contract.Address (mkAddress) import Contract.Crypto.Secp256k1.ECDSA ( ECDSAPublicKey @@ -25,22 +39,20 @@ import Contract.PlutusData , PlutusData(Constr) , RedeemerDatum(RedeemerDatum) , toData - , unitDatum ) import Contract.Prim.ByteArray (byteArrayFromIntArrayUnsafe) -import Contract.ScriptLookups as Lookups import Contract.Scripts (Validator, validatorHash) import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( TransactionHash , awaitTxConfirmed - , submitTxFromConstraints + , submitTxFromBuildPlan ) -import Contract.TxConstraints as Constraints import Contract.Utxos (utxosAt) import Contract.Value as Value +import Data.Array as Array +import Data.Lens (view) import Data.Map as Map -import Data.Set as Set import Noble.Secp256k1.ECDSA (unECDSASignature) newtype ECDSARedemeer = ECDSARedemeer @@ -69,28 +81,29 @@ prepTest = do validator <- liftContractM "Caonnot get validator" getValidator let valHash = validatorHash validator - val = Value.lovelaceValueOf BigNum.one - - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - - constraints :: Constraints.TxConstraints - constraints = Constraints.mustPayToScript valHash unitDatum - Constraints.DatumInline - val - txId <- submitTxFromConstraints lookups constraints + scriptAddress <- mkAddress + (wrap $ ScriptHashCredential valHash) + Nothing + tx <- submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address: scriptAddress + , amount: val + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ] + let txId = Transaction.hash tx logInfo' $ "Submitted ECDSA test preparation tx: " <> show txId awaitTxConfirmed txId logInfo' $ "Transaction confirmed: " <> show txId - pure txId -- | Attempt to unlock one utxo using an ECDSA signature testVerification :: TransactionHash -> ECDSARedemeer -> Contract TransactionHash testVerification txId ecdsaRed = do - let red = RedeemerDatum $ toData ecdsaRed + let redeemer = RedeemerDatum $ toData ecdsaRed validator <- liftContractM "Can't get validator" getValidator let valHash = validatorHash validator @@ -98,20 +111,21 @@ testVerification txId ecdsaRed = do valAddr <- mkAddress (wrap $ ScriptHashCredential valHash) Nothing scriptUtxos <- utxosAt valAddr - txIn <- liftContractM "No UTxOs found at validator address" - $ Set.toUnfoldable - $ Set.filter (unwrap >>> _.transactionId >>> eq txId) - $ Map.keys scriptUtxos - - let - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - <> Lookups.unspentOutputs - (Map.filterKeys ((unwrap >>> _.transactionId >>> eq txId)) scriptUtxos) - - constraints :: Constraints.TxConstraints - constraints = Constraints.mustSpendScriptOutput txIn red - txId' <- submitTxFromConstraints lookups constraints + utxo <- liftContractM "No UTxOs found at validator address" + $ Array.head + $ Array.filter (view _input >>> unwrap >>> _.transactionId >>> eq txId) + $ fromUtxoMap scriptUtxos + + tx <- submitTxFromBuildPlan (toUtxoMap [ utxo ]) mempty + [ SpendOutput utxo $ Just + $ PlutusScriptOutput + (ScriptValue validator) + redeemer + $ Just + $ DatumValue + $ PlutusData.unit + ] + let txId' = Transaction.hash tx logInfo' $ "Submitted ECDSA test verification tx: " <> show txId' awaitTxConfirmed txId' logInfo' $ "Transaction confirmed: " <> show txId' diff --git a/examples/Schnorr.purs b/examples/Schnorr.purs index ea1f526156..f0228128e8 100644 --- a/examples/Schnorr.purs +++ b/examples/Schnorr.purs @@ -2,9 +2,21 @@ module Ctl.Examples.Schnorr (contract) where import Contract.Prelude +import Cardano.Transaction.Builder + ( DatumWitness(DatumValue) + , OutputWitness(PlutusScriptOutput) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(SpendOutput, Pay) + ) import Cardano.Types (Credential(ScriptHashCredential)) import Cardano.Types.Address (Address(EnterpriseAddress)) -import Contract.Address (getNetworkId) +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.OutputDatum (OutputDatum(OutputDatumHash)) +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.Transaction as Transaction +import Cardano.Types.TransactionOutput (TransactionOutput(TransactionOutput)) +import Cardano.Types.TransactionUnspentOutput (_input, fromUtxoMap, toUtxoMap) +import Contract.Address (getNetworkId, mkAddress) import Contract.Crypto.Secp256k1.Schnorr ( deriveSchnorrSecp256k1PublicKey , signSchnorrSecp256k1 @@ -18,23 +30,21 @@ import Contract.PlutusData , PlutusData(Constr) , RedeemerDatum(RedeemerDatum) , toData - , unitDatum ) import Contract.Prim.ByteArray (ByteArray, byteArrayFromIntArrayUnsafe) -import Contract.ScriptLookups as Lookups import Contract.Scripts (Validator, validatorHash) import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( TransactionHash , awaitTxConfirmed - , submitTxFromConstraints + , submitTxFromBuildPlan ) -import Contract.TxConstraints as Constraints import Contract.Utxos (utxosAt) import Contract.Value as Value +import Data.Array as Array +import Data.Lens (view) import Data.Map as Map import Data.Newtype (unwrap) -import Data.Set as Set import Noble.Secp256k1.Schnorr ( SchnorrPublicKey , SchnorrSignature @@ -68,27 +78,29 @@ prepTest = do validator <- liftContractM "Caonnot get validator" getValidator let valHash = validatorHash validator - val = Value.lovelaceValueOf $ BigNum.one - - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - - constraints :: Constraints.TxConstraints - constraints = Constraints.mustPayToScript valHash unitDatum - Constraints.DatumInline - val - txId <- submitTxFromConstraints lookups constraints - logInfo' $ "Submitted Schnorr test preparation tx: " <> show txId + val = Value.lovelaceValueOf BigNum.one + scriptAddress <- mkAddress + (wrap $ ScriptHashCredential valHash) + Nothing + tx <- submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address: scriptAddress + , amount: val + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ] + let txId = Transaction.hash tx + logInfo' $ "Submitted ECDSA test preparation tx: " <> show txId awaitTxConfirmed txId logInfo' $ "Transaction confirmed: " <> show txId - pure txId -- | Attempt to unlock one utxo using an ECDSA signature testVerification :: TransactionHash -> SchnorrRedeemer -> Contract TransactionHash testVerification txId ecdsaRed = do - let red = RedeemerDatum $ toData ecdsaRed + let redeemer = RedeemerDatum $ toData ecdsaRed validator <- liftContractM "Can't get validator" getValidator let valHash = validatorHash validator @@ -99,21 +111,22 @@ testVerification txId ecdsaRed = do { networkId, paymentCredential: wrap $ ScriptHashCredential valHash } scriptUtxos <- utxosAt valAddr - txIn <- liftContractM "No UTxOs found at validator address" - $ Set.toUnfoldable - $ Set.filter (unwrap >>> _.transactionId >>> eq txId) - $ Map.keys scriptUtxos - - let - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - <> Lookups.unspentOutputs - (Map.filterKeys ((unwrap >>> _.transactionId >>> eq txId)) scriptUtxos) - - constraints :: Constraints.TxConstraints - constraints = Constraints.mustSpendScriptOutput txIn red - txId' <- submitTxFromConstraints lookups constraints - logInfo' $ "Submitted Schnorr test verification tx: " <> show txId' + utxo <- liftContractM "No UTxOs found at validator address" + $ Array.head + $ Array.filter (view _input >>> unwrap >>> _.transactionId >>> eq txId) + $ fromUtxoMap scriptUtxos + + tx <- submitTxFromBuildPlan (toUtxoMap [ utxo ]) mempty + [ SpendOutput utxo $ Just + $ PlutusScriptOutput + (ScriptValue validator) + redeemer + $ Just + $ DatumValue + $ PlutusData.unit + ] + let txId' = Transaction.hash tx + logInfo' $ "Submitted ECDSA test verification tx: " <> show txId' awaitTxConfirmed txId' logInfo' $ "Transaction confirmed: " <> show txId' pure txId' diff --git a/scripts/import-fixer.sh b/scripts/import-fixer.sh index ee0770fc2a..27714ad940 100755 --- a/scripts/import-fixer.sh +++ b/scripts/import-fixer.sh @@ -41,6 +41,13 @@ constrs["NetworkId"]="MainnetId, TestnetId" constrs["ScriptRef"]="NativeScriptRef, PlutusScriptRef" constrs["RedeemerTag"]="Spend, Mint, Cert, Reward" constrs["Maybe"]="Just, Nothing" +constrs["PaymentCredential"]="PaymentCredential" +constrs["TransactionBuilderStep"]="SpendOutput, Pay, MintAsset, RegisterStake, IssueCertificate, WithdrawStake, RequireSignature, RegisterPool, RetirePool, IncludeDatum, SetTTL, SetValidityStartInterval, SetIsValid" +constrs["OutputWitness"]="NativeScriptOutput, PlutusScriptOutput" +constrs["CredentialWitness"]="NativeScriptCredential, PlutusScriptCredential" +constrs["ScriptWitness"]="ScriptValue, ScriptReference" +constrs["DatumWitness"]="DatumValue, DatumReference" +constrs["RefInputAction"]="ReferenceInput, SpendInput" for d in "src" "test" "examples"; do echo "processing $d" diff --git a/src/Contract/Transaction.purs b/src/Contract/Transaction.purs index c8a61f9a6d..7f25e1ba26 100644 --- a/src/Contract/Transaction.purs +++ b/src/Contract/Transaction.purs @@ -17,6 +17,7 @@ module Contract.Transaction , mkPoolPubKeyHash , hashTransaction , buildTx + , submitTxFromBuildPlan ) where import Prelude @@ -355,6 +356,18 @@ submitTxFromConstraints lookups constraints = do balancedSignedTx <- signTransaction balancedTx submit balancedSignedTx +submitTxFromBuildPlan + :: UtxoMap + -> BalanceTxConstraintsBuilder + -> Array TransactionBuilderStep + -> Contract Transaction +submitTxFromBuildPlan usedUtxos balancerConstraints plan = do + unbalancedTx <- buildTx plan + balancedTx <- balanceTx unbalancedTx usedUtxos balancerConstraints + balancedSignedTx <- signTransaction balancedTx + void $ submit balancedSignedTx + pure balancedSignedTx + lookupTxHash :: TransactionHash -> UtxoMap -> Array TransactionUnspentOutput lookupTxHash txHash utxos = From 16845ca8efe0a9a04562a6de27c4a375041ba87c Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Sun, 14 Jul 2024 23:14:20 +0400 Subject: [PATCH 37/52] WIP: refactoring the examples. Found, supposedly, an ogmios bug --- examples/AdditionalUtxos.purs | 96 +++++++++++++++----------------- examples/AlwaysMints.purs | 26 +++------ examples/Helpers.purs | 7 ++- examples/Lose7Ada.purs | 99 ++++++++++++++++++--------------- examples/NativeScriptMints.purs | 76 ++++++++++++++----------- examples/OneShotMinting.purs | 70 +++++++++-------------- examples/Pkh2Pkh.purs | 47 +++++++++------- examples/SendsToken.purs | 72 +++++++++++++++--------- examples/SignMultiple.purs | 97 +++++++++++++++++++------------- examples/TxChaining.purs | 50 ++++++++++------- examples/Utxos.purs | 85 ++++++++++++++-------------- scripts/import-fixer.sh | 7 ++- src/Contract/Scripts.purs | 2 +- src/Contract/Transaction.purs | 6 +- test/Plutip/Contract.purs | 8 +-- 15 files changed, 394 insertions(+), 354 deletions(-) diff --git a/examples/AdditionalUtxos.purs b/examples/AdditionalUtxos.purs index b11109d6cf..a7681cff67 100644 --- a/examples/AdditionalUtxos.purs +++ b/examples/AdditionalUtxos.purs @@ -5,48 +5,46 @@ module Ctl.Examples.AdditionalUtxos import Contract.Prelude -import Cardano.Types (Transaction) +import Cardano.Transaction.Builder + ( OutputWitness(PlutusScriptOutput) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(SpendOutput, Pay) + ) +import Cardano.Types + ( OutputDatum(OutputDatum) + , PaymentCredential(PaymentCredential) + , Transaction + ) import Cardano.Types.BigNum as BigNum import Cardano.Types.Credential (Credential(ScriptHashCredential)) import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.TransactionOutput (TransactionOutput(TransactionOutput)) +import Cardano.Types.TransactionUnspentOutput (fromUtxoMap) import Contract.Address (mkAddress) import Contract.BalanceTxConstraints (BalanceTxConstraintsBuilder) import Contract.BalanceTxConstraints (mustUseAdditionalUtxos) as BalancerConstraints import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) -import Contract.PlutusData (Datum, PlutusData(Integer), unitRedeemer) -import Contract.ScriptLookups (ScriptLookups) -import Contract.ScriptLookups (datum, unspentOutputs, validator) as Lookups +import Contract.PlutusData (Datum, PlutusData(Integer)) import Contract.Scripts (Validator, ValidatorHash, validatorHash) import Contract.Sync (withoutSync) import Contract.Transaction ( ScriptRef(NativeScriptRef) - , TransactionInput , awaitTxConfirmed , balanceTx + , buildTx , createAdditionalUtxos , signTransaction , submit , withBalancedTx ) -import Contract.TxConstraints - ( DatumPresence(DatumInline, DatumWitness) - , TxConstraints - ) -import Contract.TxConstraints - ( mustPayToScript - , mustPayToScriptWithScriptRef - , mustSpendPubKeyOutput - , mustSpendScriptOutput - ) as Constraints -import Contract.UnbalancedTx (mkUnbalancedTx) import Contract.Utxos (UtxoMap) import Contract.Value (Value) import Contract.Value (lovelaceValueOf) as Value import Ctl.Examples.PlutusV2.Scripts.AlwaysSucceeds (alwaysSucceedsScriptV2) -import Data.Array (fromFoldable) as Array -import Data.Map (difference, filter, keys) as Map +import Data.Map (difference, empty, filter) as Map import JS.BigInt (fromInt) as BigInt import Test.QuickCheck (arbitrary) import Test.QuickCheck.Gen (randomSampleOne) @@ -63,8 +61,8 @@ contract testAdditionalUtxoOverlap = withoutSync do logInfo' "Running Examples.AdditionalUtxos" validator <- alwaysSucceedsScriptV2 let vhash = validatorHash validator - { unbalancedTx, usedUtxos, datum } <- payToValidator vhash - withBalancedTx unbalancedTx usedUtxos mempty \balancedTx -> do + { unbalancedTx, datum } <- payToValidator vhash + withBalancedTx unbalancedTx Map.empty mempty \balancedTx -> do balancedSignedTx <- signTransaction balancedTx txHash <- submit balancedSignedTx when testAdditionalUtxoOverlap $ awaitTxConfirmed txHash @@ -77,7 +75,6 @@ payToValidator :: ValidatorHash -> Contract { unbalancedTx :: Transaction - , usedUtxos :: UtxoMap , datum :: Datum } payToValidator vhash = do @@ -87,19 +84,25 @@ payToValidator vhash = do value = Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 datum = Integer $ BigInt.fromInt 42 + scriptAddress <- mkAddress (PaymentCredential $ ScriptHashCredential vhash) + Nothing - constraints :: TxConstraints - constraints = - Constraints.mustPayToScript vhash datum DatumWitness value - <> Constraints.mustPayToScriptWithScriptRef vhash datum DatumInline - scriptRef - value - - lookups :: ScriptLookups - lookups = Lookups.datum datum - - unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - pure { unbalancedTx, usedUtxos, datum } + tx <- buildTx + [ Pay $ TransactionOutput + { address: scriptAddress + , amount: value + , datum: Just $ OutputDatum $ datum + , scriptRef: Nothing + } + , Pay $ TransactionOutput + { address: scriptAddress + , amount: value + , datum: Just $ OutputDatum $ datum + , scriptRef: Just scriptRef + } + ] + + pure { unbalancedTx: tx, datum } spendFromValidator :: Validator -> UtxoMap -> Datum -> Contract Unit spendFromValidator validator additionalUtxos datum = do @@ -111,30 +114,23 @@ spendFromValidator validator additionalUtxos datum = do additionalUtxos # Map.filter \out -> (unwrap out).address == addr - scriptOrefs :: Array TransactionInput - scriptOrefs = Array.fromFoldable $ Map.keys scriptUtxos - - pubKeyOrefs :: Array TransactionInput - pubKeyOrefs = - Array.fromFoldable $ Map.keys $ Map.difference additionalUtxos scriptUtxos + spendScriptOutputs = fromUtxoMap scriptUtxos <#> \output -> + SpendOutput output $ Just $ PlutusScriptOutput (ScriptValue validator) + RedeemerDatum.unit + Nothing - constraints :: TxConstraints - constraints = - foldMap (flip Constraints.mustSpendScriptOutput unitRedeemer) scriptOrefs - <> foldMap Constraints.mustSpendPubKeyOutput pubKeyOrefs + spendPubkeyOutputs = + fromUtxoMap (Map.difference additionalUtxos scriptUtxos) <#> \output -> + SpendOutput output Nothing - lookups :: ScriptLookups - lookups = - Lookups.validator validator - <> Lookups.unspentOutputs additionalUtxos - <> Lookups.datum datum + plan = spendScriptOutputs <> spendPubkeyOutputs balancerConstraints :: BalanceTxConstraintsBuilder balancerConstraints = BalancerConstraints.mustUseAdditionalUtxos additionalUtxos - unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTx unbalancedTx usedUtxos balancerConstraints + unbalancedTx <- buildTx plan + balancedTx <- balanceTx unbalancedTx additionalUtxos balancerConstraints balancedSignedTx <- signTransaction balancedTx txHash <- submit balancedSignedTx diff --git a/examples/AlwaysMints.purs b/examples/AlwaysMints.purs index ab56202064..6269acc36b 100644 --- a/examples/AlwaysMints.purs +++ b/examples/AlwaysMints.purs @@ -12,32 +12,18 @@ module Ctl.Examples.AlwaysMints import Contract.Prelude import Cardano.Transaction.Builder - ( CredentialWitness(NativeScriptCredential, PlutusScriptCredential) - , ScriptWitness(ScriptValue, ScriptReference) - , TransactionBuilderStep - ( SpendOutput - , Pay - , MintAsset - , RegisterStake - , IssueCertificate - , WithdrawStake - , RequireSignature - , RegisterPool - , RetirePool - , IncludeDatum - , SetTTL - , SetValidityStartInterval - , SetIsValid - ) + ( CredentialWitness(PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(MintAsset) ) import Cardano.Types (PlutusScript) import Cardano.Types.Int as Int import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.RedeemerDatum as RedeemerDatum import Cardano.Types.Transaction as Transaction import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftContractM, runContract) -import Contract.PlutusData (unitRedeemer) import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction (awaitTxConfirmed, submitTxFromBuildPlan) import Ctl.Examples.Helpers (mkAssetName) as Helpers @@ -58,7 +44,9 @@ contract = do scriptHash tokenName (Int.fromInt 100) - (PlutusScriptCredential (ScriptValue mintingPolicy) unitRedeemer) + ( PlutusScriptCredential (ScriptValue mintingPolicy) + RedeemerDatum.unit + ) ] logInfo' "Tx submitted successfully!" diff --git a/examples/Helpers.purs b/examples/Helpers.purs index bd79deec18..c52cfdb6a0 100644 --- a/examples/Helpers.purs +++ b/examples/Helpers.purs @@ -26,9 +26,10 @@ import Contract.TxConstraints (DatumPresence) import Contract.TxConstraints as Constraints mkAssetName :: String -> Contract AssetName -mkAssetName = - liftContractM "Cannot make token name" - <<< (AssetName.mkAssetName <=< byteArrayFromAscii) +mkAssetName str = + liftContractM ("Cannot make token name from: " <> str) + $ AssetName.mkAssetName + =<< byteArrayFromAscii str mustPayToPubKeyStakeAddress :: forall (i :: Type) (o :: Type) diff --git a/examples/Lose7Ada.purs b/examples/Lose7Ada.purs index 5a0f04f62b..732ad0af6a 100644 --- a/examples/Lose7Ada.purs +++ b/examples/Lose7Ada.purs @@ -13,30 +13,47 @@ module Ctl.Examples.Lose7Ada import Contract.Prelude +import Cardano.Transaction.Builder + ( OutputWitness(PlutusScriptOutput) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(SpendOutput, Pay) + ) +import Cardano.Types + ( Credential(ScriptHashCredential) + , OutputDatum(OutputDatum) + , PaymentCredential(PaymentCredential) + , TransactionOutput(TransactionOutput) + , _isValid + ) import Cardano.Types.BigNum as BigNum -import Cardano.Types.Credential (Credential(ScriptHashCredential)) +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.Transaction as Transaction +import Cardano.Types.TransactionUnspentOutput (toUtxoMap) import Contract.Address (mkAddress) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) -import Contract.PlutusData (unitDatum, unitRedeemer) -import Contract.ScriptLookups as Lookups +import Contract.PlutusData (unitRedeemer) import Contract.Scripts (Validator, ValidatorHash, validatorHash) import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( TransactionHash - , TransactionInput(TransactionInput) , awaitTxConfirmed - , submitTxFromConstraints + , balanceTx + , buildTx + , lookupTxHash + , signTransaction + , submit + , submitTxFromBuildPlan ) -import Contract.TxConstraints (TxConstraints) -import Contract.TxConstraints as Constraints import Contract.Utxos (utxosAt) import Contract.Value (lovelaceValueOf, minus) as Value import Contract.Wallet (getWalletBalance) import Control.Monad.Error.Class (liftMaybe) +import Data.Array (head) import Data.Foldable (fold) import Data.Functor ((<$>)) +import Data.Lens ((.~)) import Data.Map as Map import Effect.Exception (error) import Partial.Unsafe (unsafePartial) @@ -59,18 +76,16 @@ example cfg = launchAff_ do payToAlwaysFails :: ValidatorHash -> Contract TransactionHash payToAlwaysFails vhash = do - let - constraints :: TxConstraints - constraints = - Constraints.mustPayToScript vhash unitDatum - Constraints.DatumWitness - $ Value.lovelaceValueOf - $ BigNum.fromInt 2_000_000 - - lookups :: Lookups.ScriptLookups - lookups = mempty - - submitTxFromConstraints lookups constraints + scriptAddress <- + mkAddress (PaymentCredential $ ScriptHashCredential vhash) Nothing + Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address: scriptAddress + , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + , datum: Just $ OutputDatum PlutusData.unit + , scriptRef: Nothing + } + ] spendFromAlwaysFails :: ValidatorHash @@ -81,39 +96,33 @@ spendFromAlwaysFails vhash validator txId = do balanceBefore <- unsafePartial $ fold <$> getWalletBalance scriptAddress <- mkAddress (wrap $ ScriptHashCredential vhash) Nothing utxos <- utxosAt scriptAddress - txInput <- liftM - ( error - ( "The id " - <> show txId - <> " does not have output locked at: " - <> show scriptAddress - ) - ) - (fst <$> find hasTransactionId (Map.toUnfoldable utxos :: Array _)) - let - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - <> Lookups.unspentOutputs utxos - - constraints :: TxConstraints - constraints = - Constraints.mustSpendScriptOutput txInput unitRedeemer - <> Constraints.mustNotBeValid - - spendTxId <- submitTxFromConstraints lookups constraints + utxo <- + liftM + ( error + ( "The id " + <> show txId + <> " does not have output locked at: " + <> show scriptAddress + ) + ) + $ head (lookupTxHash txId utxos) + unbalancedTx <- + buildTx + [ SpendOutput + utxo + $ Just + $ PlutusScriptOutput (ScriptValue validator) unitRedeemer Nothing + ] <#> _isValid .~ false + balancedTx <- balanceTx unbalancedTx (toUtxoMap [ utxo ]) mempty + balancedSignedTx <- signTransaction $ balancedTx # _isValid .~ true + spendTxId <- submit balancedSignedTx logInfo' $ "Tx ID: " <> show spendTxId awaitTxConfirmed spendTxId logInfo' "Successfully spent locked values." - balance <- unsafePartial $ fold <$> getWalletBalance let collateralLoss = Value.lovelaceValueOf $ BigNum.fromInt (5_000_000) Just balance `shouldEqual` (Value.minus balanceBefore collateralLoss) - where - hasTransactionId :: TransactionInput /\ _ -> Boolean - hasTransactionId (TransactionInput tx /\ _) = - tx.transactionId == txId - alwaysFailsScript :: Contract Validator alwaysFailsScript = do liftMaybe (error "Error decoding alwaysFails") do diff --git a/examples/NativeScriptMints.purs b/examples/NativeScriptMints.purs index e83c1abd2b..2808fce87b 100644 --- a/examples/NativeScriptMints.purs +++ b/examples/NativeScriptMints.purs @@ -4,23 +4,34 @@ module Ctl.Examples.NativeScriptMints (main, example, contract, pkhPolicy) where import Contract.Prelude -import Cardano.Types (BigNum) +import Cardano.Transaction.Builder + ( CredentialWitness(NativeScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(Pay, MintAsset) + ) +import Cardano.Types + ( BigNum + , Credential(PubKeyHashCredential) + , PaymentCredential(PaymentCredential) + , StakeCredential(StakeCredential) + , TransactionOutput(TransactionOutput) + ) import Cardano.Types.BigNum as BigNum import Cardano.Types.Int as Int import Cardano.Types.NativeScript as NativeScript -import Contract.Address (PaymentPubKeyHash) +import Cardano.Types.Transaction as Transaction +import Contract.Address (PaymentPubKeyHash, mkAddress) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftedM, runContract) -import Contract.ScriptLookups as Lookups import Contract.Scripts (NativeScript(ScriptPubkey)) -import Contract.Transaction (awaitTxConfirmed, submitTxFromConstraints) -import Contract.TxConstraints as Constraints +import Contract.Transaction (awaitTxConfirmed, submitTxFromBuildPlan) import Contract.Value (CurrencySymbol, TokenName) import Contract.Value as Value import Contract.Wallet (ownPaymentPubKeyHashes, ownStakePubKeyHashes) -import Ctl.Examples.Helpers (mkAssetName, mustPayToPubKeyStakeAddress) as Helpers +import Ctl.Examples.Helpers (mkAssetName) as Helpers import Data.Array (head) +import Data.Map as Map import JS.BigInt as BigInt main :: Effect Unit @@ -32,44 +43,43 @@ contract = do pkh <- liftedM "Couldn't get own pkh" $ head <$> ownPaymentPubKeyHashes - let mp = pkhPolicy pkh - let cs = NativeScript.hash mp - tn <- Helpers.mkAssetName "NSToken" + let mintingPolicy = pkhPolicy pkh + let scriptHash = NativeScript.hash mintingPolicy + assetName <- Helpers.mkAssetName "NSToken" - let - constraints :: Constraints.TxConstraints - constraints = - Constraints.mustMintCurrencyUsingNativeScript - (pkhPolicy pkh) - tn $ Int.fromInt 100 - - lookups :: Lookups.ScriptLookups - lookups = Lookups.nativeMintingPolicy mp - - txId <- submitTxFromConstraints lookups constraints + txId <- Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty + [ MintAsset + scriptHash + assetName + (Int.fromInt 100) + (NativeScriptCredential (ScriptValue mintingPolicy)) + ] awaitTxConfirmed txId logInfo' "Minted successfully" - toSelfContract cs tn $ BigNum.fromInt 50 + toSelfContract scriptHash assetName $ BigNum.fromInt 50 toSelfContract :: CurrencySymbol -> TokenName -> BigNum -> Contract Unit toSelfContract cs tn amount = do pkh <- liftedM "Failed to get own PKH" $ head <$> ownPaymentPubKeyHashes skh <- join <<< head <$> ownStakePubKeyHashes - + address <- mkAddress + (PaymentCredential $ PubKeyHashCredential $ unwrap pkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> skh) let - constraints :: Constraints.TxConstraints - constraints = Helpers.mustPayToPubKeyStakeAddress pkh skh - $ Value.singleton cs tn - $ amount - - lookups :: Lookups.ScriptLookups - lookups = mempty - - txId <- submitTxFromConstraints lookups constraints - - awaitTxConfirmed txId + plan = + [ Pay $ TransactionOutput + { address + , amount: Value.singleton cs tn amount + , datum: Nothing + , scriptRef: Nothing + } + ] + + tx <- submitTxFromBuildPlan Map.empty mempty plan + + awaitTxConfirmed $ Transaction.hash tx logInfo' $ "Moved " <> show (BigInt.fromInt 50) <> " to self successfully" example :: ContractParams -> Effect Unit diff --git a/examples/OneShotMinting.purs b/examples/OneShotMinting.purs index 8c0b1eb617..4370e749a8 100644 --- a/examples/OneShotMinting.purs +++ b/examples/OneShotMinting.purs @@ -12,12 +12,18 @@ module Ctl.Examples.OneShotMinting import Contract.Prelude -import Cardano.Types (Coin, TransactionHash, UtxoMap, _body, _fee) +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(SpendOutput, MintAsset) + ) +import Cardano.Types (_body, _fee, _input) import Cardano.Types.BigNum as BigNum import Cardano.Types.Int as Int -import Cardano.Types.Mint as Mint import Cardano.Types.PlutusScript as PlutusScript -import Contract.BalanceTxConstraints (BalanceTxConstraintsBuilder) +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction +import Cardano.Types.TransactionUnspentOutput (fromUtxoMap) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad @@ -29,8 +35,6 @@ import Contract.Monad , runContract ) import Contract.PlutusData (PlutusData, toData) -import Contract.ScriptLookups (ScriptLookups) -import Contract.ScriptLookups as Lookups import Contract.Scripts (PlutusScript, applyArgs) import Contract.Test.Assert ( ContractCheck @@ -42,21 +46,16 @@ import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( TransactionInput , awaitTxConfirmed - , balanceTx - , signTransaction - , submit + , submitTxFromBuildPlan ) -import Contract.TxConstraints (TxConstraints) -import Contract.TxConstraints as Constraints -import Contract.UnbalancedTx (mkUnbalancedTx) import Contract.Value (AssetName, ScriptHash) import Contract.Wallet (getWalletUtxos) import Control.Monad.Error.Class (liftMaybe) import Control.Monad.Trans.Class (lift) import Ctl.Examples.Helpers (mkAssetName) as Helpers import Data.Array (head, singleton) as Array -import Data.Lens (view) -import Data.Map (empty, toUnfoldable, union) as Map +import Data.Lens ((^.)) +import Data.Map (empty) as Map import Effect.Exception (error, throw) import JS.BigInt (BigInt) @@ -89,53 +88,34 @@ mkContractWithAssertions -> Contract Unit mkContractWithAssertions exampleName mkMintingPolicy = do logInfo' ("Running " <> exampleName) - utxos <- liftedM "Failed to get UTxOs from wallet" getWalletUtxos + utxos <- liftedM "Failed to get UTxOs from wallet" $ getWalletUtxos <#> map + fromUtxoMap oref <- liftContractM "Utxo set is empty" - (fst <$> Array.head (Map.toUnfoldable utxos :: Array _)) + (Array.head utxos) - ps <- mkMintingPolicy oref + ps <- mkMintingPolicy (oref ^. _input) let cs = PlutusScript.hash ps tn <- Helpers.mkAssetName "CTLNFT" let - constraints :: Constraints.TxConstraints - constraints = - Constraints.mustMintValue (Mint.singleton cs tn $ Int.fromInt one) - <> Constraints.mustSpendPubKeyOutput oref - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.plutusMintingPolicy ps - <> Lookups.unspentOutputs utxos + plan = + [ MintAsset cs tn (Int.fromInt one) + (PlutusScriptCredential (ScriptValue ps) RedeemerDatum.unit) + , SpendOutput (oref) Nothing + ] let checks = mkChecks (cs /\ tn /\ one) void $ runChecks checks $ lift do - { txHash, txFinalFee } <- - submitTxFromConstraintsReturningFee lookups constraints Map.empty mempty + tx <- submitTxFromBuildPlan Map.empty mempty plan + let + txHash = Transaction.hash tx + txFinalFee = tx ^. _body <<< _fee logInfo' $ "Tx ID: " <> show txHash awaitTxConfirmed txHash logInfo' "Tx submitted successfully!" pure { txFinalFee: BigNum.toBigInt $ unwrap txFinalFee } -submitTxFromConstraintsReturningFee - :: ScriptLookups - -> TxConstraints - -> UtxoMap - -> BalanceTxConstraintsBuilder - -> Contract { txHash :: TransactionHash, txFinalFee :: Coin } -submitTxFromConstraintsReturningFee - lookups - constraints - extraUtxos - balancerConstraints = do - unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTx unbalancedTx (Map.union extraUtxos usedUtxos) - balancerConstraints - balancedSignedTx <- signTransaction balancedTx - txHash <- submit balancedSignedTx - pure { txHash, txFinalFee: view (_body <<< _fee) balancedSignedTx } - oneShotMintingPolicyScript :: TransactionInput -> Contract PlutusScript oneShotMintingPolicyScript txInput = do script <- liftMaybe (error "Error decoding oneShotMinting") do diff --git a/examples/Pkh2Pkh.purs b/examples/Pkh2Pkh.purs index 88b37a4cd1..0a3d5be28b 100644 --- a/examples/Pkh2Pkh.purs +++ b/examples/Pkh2Pkh.purs @@ -5,19 +5,29 @@ module Ctl.Examples.Pkh2Pkh (main, contract, example) where import Contract.Prelude +import Cardano.Transaction.Builder + ( TransactionBuilderStep(Pay) + ) +import Cardano.Types + ( Credential(PubKeyHashCredential) + , OutputDatum(OutputDatumHash) + , PaymentCredential(PaymentCredential) + , StakeCredential(StakeCredential) + , TransactionOutput(TransactionOutput) + ) import Cardano.Types.BigNum as BigNum +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.Transaction as Transaction +import Contract.Address (mkAddress) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftedM, runContract) -import Contract.ScriptLookups as Lookups -import Contract.Transaction - ( awaitTxConfirmedWithTimeout - , submitTxFromConstraints - ) -import Contract.TxConstraints as Constraints +import Contract.Transaction (awaitTxConfirmedWithTimeout, submitTxFromBuildPlan) import Contract.Value as Value import Contract.Wallet (ownPaymentPubKeyHashes, ownStakePubKeyHashes) import Data.Array (head) +import Data.Map as Map main :: Effect Unit main = example testnetNamiConfig @@ -26,20 +36,19 @@ contract :: Contract Unit contract = do logInfo' "Running Examples.Pkh2Pkh" pkh <- liftedM "Failed to get own PKH" $ head <$> ownPaymentPubKeyHashes - skh <- liftedM "Failed to get own SKH" $ join <<< head <$> + skh <- liftedM "Failed to get own SKH" $ head <$> ownStakePubKeyHashes - - let - constraints :: Constraints.TxConstraints - constraints = Constraints.mustPayToPubKeyAddress pkh skh - $ Value.lovelaceValueOf - $ BigNum.fromInt 2_000_000 - - lookups :: Lookups.ScriptLookups - lookups = mempty - - txId <- submitTxFromConstraints lookups constraints - + address <- mkAddress + (PaymentCredential $ PubKeyHashCredential $ unwrap pkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> skh) + txId <- Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address + , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ] awaitTxConfirmedWithTimeout (wrap 100.0) txId logInfo' $ "Tx submitted successfully!" diff --git a/examples/SendsToken.purs b/examples/SendsToken.purs index ee9211f84d..2415500768 100644 --- a/examples/SendsToken.purs +++ b/examples/SendsToken.purs @@ -6,28 +6,41 @@ module Ctl.Examples.SendsToken (main, example, contract) where import Contract.Prelude -import Cardano.Types (PlutusScript) +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(Pay, MintAsset) + ) +import Cardano.Types + ( AssetName + , Credential(PubKeyHashCredential) + , PaymentCredential(PaymentCredential) + , PlutusScript + , ScriptHash + , StakeCredential(StakeCredential) + , TransactionOutput(TransactionOutput) + ) import Cardano.Types.BigNum as BigNum import Cardano.Types.Int as Int -import Cardano.Types.Mint (Mint) -import Cardano.Types.Mint as Mint import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction +import Contract.Address (mkAddress) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftedM, runContract) -import Contract.ScriptLookups as Lookups import Contract.Transaction ( TransactionHash , awaitTxConfirmed - , submitTxFromConstraints + , submitTxFromBuildPlan ) -import Contract.TxConstraints as Constraints import Contract.Value (Value) import Contract.Value as Value import Contract.Wallet (ownPaymentPubKeyHashes, ownStakePubKeyHashes) import Ctl.Examples.AlwaysMints (alwaysMintsPolicy) -import Ctl.Examples.Helpers (mkAssetName, mustPayToPubKeyStakeAddress) as Helpers +import Ctl.Examples.Helpers (mkAssetName) as Helpers import Data.Array (head) +import Data.Map as Map main :: Effect Unit main = example testnetNamiConfig @@ -48,34 +61,39 @@ contract = do mintToken :: Contract TransactionHash mintToken = do - mp /\ mint /\ _value <- tokenValue - let - constraints :: Constraints.TxConstraints - constraints = Constraints.mustMintValue mint - - lookups :: Lookups.ScriptLookups - lookups = Lookups.plutusMintingPolicy mp + mp /\ sh /\ an /\ amount /\ _value <- tokenValue - submitTxFromConstraints lookups constraints + tx <- submitTxFromBuildPlan Map.empty mempty + [ MintAsset + sh + an + amount + (PlutusScriptCredential (ScriptValue mp) RedeemerDatum.unit) + ] + pure $ Transaction.hash tx sendToken :: Contract TransactionHash sendToken = do pkh <- liftedM "Failed to get own PKH" $ head <$> ownPaymentPubKeyHashes skh <- join <<< head <$> ownStakePubKeyHashes - _ /\ _mint /\ value <- tokenValue - let - constraints :: Constraints.TxConstraints - constraints = Helpers.mustPayToPubKeyStakeAddress pkh skh value - - lookups :: Lookups.ScriptLookups - lookups = mempty - - submitTxFromConstraints lookups constraints + _ /\ _ /\ _ /\ _ /\ value <- tokenValue + address <- mkAddress (PaymentCredential $ PubKeyHashCredential $ unwrap pkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> skh) + tx <- submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address + , amount: value + , datum: Nothing + , scriptRef: Nothing + } + ] + pure $ Transaction.hash tx -tokenValue :: Contract (PlutusScript /\ Mint /\ Value) +tokenValue + :: Contract (PlutusScript /\ ScriptHash /\ AssetName /\ Int.Int /\ Value) tokenValue = do mp <- alwaysMintsPolicy let cs = PlutusScript.hash mp - tn <- Helpers.mkAssetName "TheToken" - pure $ mp /\ Mint.singleton cs tn (Int.fromInt 1) /\ Value.singleton cs tn + an <- Helpers.mkAssetName "TheToken" + pure $ mp /\ cs /\ an /\ Int.fromInt 1 /\ Value.singleton cs an (BigNum.fromInt 1) diff --git a/examples/SignMultiple.purs b/examples/SignMultiple.purs index 6622c55a0d..e9d1cfe49d 100644 --- a/examples/SignMultiple.purs +++ b/examples/SignMultiple.purs @@ -5,7 +5,21 @@ module Ctl.Examples.SignMultiple (example, contract, main) where import Contract.Prelude -import Cardano.Types (Transaction) +import Cardano.Transaction.Builder + ( TransactionBuilderStep(Pay) + ) +import Cardano.Types + ( Credential(PubKeyHashCredential) + , OutputDatum(OutputDatumHash) + , PaymentCredential(PaymentCredential) + , StakeCredential(StakeCredential) + , Transaction + , TransactionOutput(TransactionOutput) + ) +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.Transaction as Transaction +import Contract.Address (mkAddress) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo', logWarn') import Contract.Monad @@ -16,18 +30,16 @@ import Contract.Monad , throwContractError ) import Contract.Numeric.BigNum as BigNum -import Contract.ScriptLookups as Lookups import Contract.Transaction ( TransactionHash , awaitTxConfirmed , awaitTxConfirmedWithTimeout + , buildTx , signTransaction , submit - , submitTxFromConstraints + , submitTxFromBuildPlan , withBalancedTxs ) -import Contract.TxConstraints as Constraints -import Contract.UnbalancedTx (mkUnbalancedTx) import Contract.Value (leq) import Contract.Value as Value import Contract.Wallet @@ -38,6 +50,7 @@ import Contract.Wallet import Control.Monad.Reader (asks) import Data.Array (head) import Data.Map (Map, filter) +import Data.Map as Map import Data.Set (Set) import Data.UInt (UInt) import Effect.Ref as Ref @@ -55,34 +68,36 @@ contract :: Contract Unit contract = do logInfo' "Running Examples.SignMultiple" pkh <- liftedM "Failed to get own PKH" $ head <$> ownPaymentPubKeyHashes - skh <- liftedM "Failed to get own SKH" $ join <<< head <$> - ownStakePubKeyHashes + skh <- liftedM "Failed to get own SKH" $ head <$> ownStakePubKeyHashes -- Early fail if not enough utxos present for 2 transactions unlessM hasSufficientUtxos do logWarn' "Insufficient Utxos for 2 transactions" createAdditionalUtxos - + address <- mkAddress + (PaymentCredential $ PubKeyHashCredential $ unwrap pkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> skh) let - constraints :: Constraints.TxConstraints - constraints = Constraints.mustPayToPubKeyAddress pkh skh - $ Value.lovelaceValueOf - $ BigNum.fromInt 2_000_000 - - lookups :: Lookups.ScriptLookups - lookups = mempty - - unbalancedTx0 /\ usedUtxos0 <- mkUnbalancedTx lookups constraints - unbalancedTx1 /\ usedUtxos1 <- mkUnbalancedTx lookups constraints + plan = + [ Pay $ TransactionOutput + { address + , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ] + + unbalancedTx0 <- buildTx plan + unbalancedTx1 <- buildTx plan txIds <- withBalancedTxs [ { transaction: unbalancedTx0 - , usedUtxos: usedUtxos0 + , usedUtxos: Map.empty , balancerConstraints: mempty } , { transaction: unbalancedTx1 - , usedUtxos: usedUtxos1 + , usedUtxos: Map.empty , balancerConstraints: mempty } ] $ \balancedTxs -> do @@ -128,27 +143,29 @@ createAdditionalUtxos :: Contract Unit createAdditionalUtxos = do logInfo' "Creating additional UTxOs for SignMultiple example" pkh <- liftedM "Failed to get own PKH" $ head <$> ownPaymentPubKeyHashes - skh <- liftedM "Failed to get own SKH" $ join <<< head <$> - ownStakePubKeyHashes - + skh <- liftedM "Failed to get own SKH" $ head <$> ownStakePubKeyHashes + address <- mkAddress + (PaymentCredential $ PubKeyHashCredential $ unwrap pkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> skh) let - constraints :: Constraints.TxConstraints - constraints = - Constraints.mustPayToPubKeyAddress pkh skh - ( Value.lovelaceValueOf - $ BigNum.fromInt 2_000_000 - ) <> - Constraints.mustPayToPubKeyAddress pkh skh - ( Value.lovelaceValueOf - $ BigNum.fromInt 2_000_000 - ) - - lookups :: Lookups.ScriptLookups - lookups = mempty - - txId <- submitTxFromConstraints lookups constraints - - awaitTxConfirmedWithTimeout (wrap 100.0) txId + plan = + [ Pay $ TransactionOutput + { address + , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + , Pay $ TransactionOutput + { address + , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ] + + tx <- submitTxFromBuildPlan Map.empty mempty plan + + awaitTxConfirmedWithTimeout (wrap 100.0) $ Transaction.hash tx logInfo' $ "Tx submitted successfully!" example :: ContractParams -> Effect Unit diff --git a/examples/TxChaining.purs b/examples/TxChaining.purs index 56c92096b2..a9dec95547 100644 --- a/examples/TxChaining.purs +++ b/examples/TxChaining.purs @@ -10,7 +10,17 @@ module Ctl.Examples.TxChaining import Contract.Prelude +import Cardano.Transaction.Builder (TransactionBuilderStep(Pay)) +import Cardano.Types + ( Credential(PubKeyHashCredential) + , OutputDatum(OutputDatumHash) + , PaymentCredential(PaymentCredential) + , TransactionOutput(TransactionOutput) + ) import Cardano.Types.BigNum as BigNum +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.PlutusData as PlutusData +import Contract.Address (mkAddress) import Contract.BalanceTxConstraints ( BalanceTxConstraintsBuilder , mustUseAdditionalUtxos @@ -18,21 +28,20 @@ import Contract.BalanceTxConstraints import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftedM, runContract) -import Contract.ScriptLookups as Lookups import Contract.Transaction ( awaitTxConfirmed , balanceTx + , buildTx , createAdditionalUtxos , signTransaction , submit , withBalancedTx ) -import Contract.TxConstraints (TxConstraints) -import Contract.TxConstraints as Constraints -import Contract.UnbalancedTx (mkUnbalancedTx) import Contract.Value as Value import Contract.Wallet (ownPaymentPubKeyHashes) import Data.Array (head) +import Data.Map as Map +import Effect.Exception (throw) main :: Effect Unit main = example testnetNamiConfig @@ -44,33 +53,34 @@ example cfg = launchAff_ do contract :: Contract Unit contract = do pkh <- liftedM "Failed to get PKH" $ head <$> ownPaymentPubKeyHashes + address <- mkAddress (PaymentCredential $ PubKeyHashCredential $ unwrap pkh) + Nothing let - constraints :: TxConstraints - constraints = - Constraints.mustPayToPubKey pkh - (Value.lovelaceValueOf $ BigNum.fromInt 1_000_000) - - lookups0 :: Lookups.ScriptLookups - lookups0 = mempty + plan = + [ Pay $ TransactionOutput + { address: address + , amount: Value.lovelaceValueOf $ BigNum.fromInt 1_000_000 + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ] - unbalancedTx0 /\ usedUtxos0 <- mkUnbalancedTx lookups0 constraints + unbalancedTx0 <- buildTx plan - withBalancedTx unbalancedTx0 usedUtxos0 mempty \balancedTx0 -> do + withBalancedTx unbalancedTx0 Map.empty mempty \balancedTx0 -> do + logInfo' $ "balanced" balancedSignedTx0 <- signTransaction balancedTx0 additionalUtxos <- createAdditionalUtxos balancedSignedTx0 logInfo' $ "Additional utxos: " <> show additionalUtxos - + when (Map.isEmpty additionalUtxos) do + liftEffect $ throw "empty utxos" let - lookups1 :: Lookups.ScriptLookups - lookups1 = Lookups.unspentOutputs additionalUtxos - balanceTxConstraints :: BalanceTxConstraints.BalanceTxConstraintsBuilder balanceTxConstraints = BalanceTxConstraints.mustUseAdditionalUtxos additionalUtxos - - unbalancedTx1 /\ usedUtxos1 <- mkUnbalancedTx lookups1 constraints - balancedTx1 <- balanceTx unbalancedTx1 usedUtxos1 balanceTxConstraints + unbalancedTx1 <- buildTx plan + balancedTx1 <- balanceTx unbalancedTx1 additionalUtxos balanceTxConstraints balancedSignedTx1 <- signTransaction balancedTx1 txId0 <- submit balancedSignedTx0 diff --git a/examples/Utxos.purs b/examples/Utxos.purs index 23cc6eaa5b..4cf0754ed7 100644 --- a/examples/Utxos.purs +++ b/examples/Utxos.purs @@ -2,12 +2,25 @@ module Ctl.Examples.Utxos (main, example, contract) where import Contract.Prelude +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(Pay, MintAsset) + ) +import Cardano.Types + ( Credential(PubKeyHashCredential) + , OutputDatum(OutputDatum, OutputDatumHash) + , PaymentCredential(PaymentCredential) + , StakeCredential(StakeCredential) + , TransactionOutput(TransactionOutput) + ) import Cardano.Types.BigNum as BigNum +import Cardano.Types.DataHash (hashPlutusData) import Cardano.Types.Int as Int -import Cardano.Types.Mint (Mint) -import Cardano.Types.Mint as Mint import Cardano.Types.PlutusScript as PlutusScript -import Contract.Address (PaymentPubKeyHash, StakePubKeyHash) +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction +import Contract.Address (mkAddress) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo, logInfo') import Contract.Monad @@ -18,14 +31,11 @@ import Contract.Monad , runContract ) import Contract.PlutusData (PlutusData(Integer)) -import Contract.ScriptLookups as Lookups import Contract.Transaction ( ScriptRef(NativeScriptRef, PlutusScriptRef) , awaitTxConfirmed - , submitTxFromConstraints + , submitTxFromBuildPlan ) -import Contract.TxConstraints (DatumPresence(DatumInline, DatumWitness)) -import Contract.TxConstraints as Constraints import Contract.Value (Value) import Contract.Value (lovelaceValueOf, singleton) as Value import Contract.Wallet @@ -37,7 +47,7 @@ import Ctl.Examples.Helpers (mkAssetName) as Helpers import Ctl.Examples.PlutusV2.OneShotMinting (oneShotMintingPolicyScriptV2) import Data.Array (head) as Array import Data.Log.Tag (tag) -import Data.Map (toUnfoldable) as Map +import Data.Map (empty, toUnfoldable) as Map import JS.BigInt (fromInt) as BigInt import Partial.Unsafe (unsafePartial) import Test.QuickCheck.Arbitrary (arbitrary) @@ -54,6 +64,9 @@ contract = do logInfo' "Running Examples.Utxos" pkh <- liftedM "Failed to get own PKH" ownPaymentPubKeyHash skh <- ownStakePubKeyHash + address <- mkAddress + (PaymentCredential $ PubKeyHashCredential $ unwrap pkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> skh) datum <- liftEffect $ Integer @@ -77,45 +90,33 @@ contract = do adaValue :: Value adaValue = Value.lovelaceValueOf (BigNum.fromInt 2_000_000) - mintValue :: Mint - mintValue = Mint.singleton cs0 tn0 (Int.fromInt one) - tokenValue = Value.singleton cs0 tn0 BigNum.one - constraints :: Constraints.TxConstraints - constraints = mconcat - [ Constraints.mustMintValue mintValue - , mustPayWithDatumAndScriptRef pkh skh datum DatumWitness plutusScriptRef - (unsafePartial $ tokenValue <> adaValue) - , mustPayWithDatumAndScriptRef pkh skh datum DatumInline nativeScriptRef - adaValue + plan = + [ MintAsset + cs0 + tn0 + (Int.fromInt one) + ( PlutusScriptCredential (ScriptValue oneShotMintingPolicy) + RedeemerDatum.unit + ) + , Pay $ TransactionOutput + { address + , amount: unsafePartial $ tokenValue <> adaValue + , datum: Just $ OutputDatumHash $ hashPlutusData datum + , scriptRef: Just plutusScriptRef + } + , Pay $ TransactionOutput + { address + , amount: adaValue + , datum: Just $ OutputDatum datum + , scriptRef: Just nativeScriptRef + } ] - lookups :: Lookups.ScriptLookups - lookups = Lookups.plutusMintingPolicy oneShotMintingPolicy <> - Lookups.unspentOutputs utxos - - txHash <- submitTxFromConstraints lookups constraints - awaitTxConfirmed txHash + tx <- submitTxFromBuildPlan Map.empty mempty plan + awaitTxConfirmed $ Transaction.hash tx logInfo' "Tx submitted successfully!" utxos' <- liftedM "Failed to get UTxOs from wallet" getWalletUtxos logInfo (tag "utxos" $ show utxos') "Utxos after transaction confirmation:" - --------------------------------------------------------------------------------- --- Helpers --------------------------------------------------------------------------------- - -mustPayWithDatumAndScriptRef - :: forall (i :: Type) (o :: Type) - . PaymentPubKeyHash - -> Maybe StakePubKeyHash - -> PlutusData - -> DatumPresence - -> ScriptRef - -> Value - -> Constraints.TxConstraints -mustPayWithDatumAndScriptRef pkh Nothing = - Constraints.mustPayToPubKeyWithDatumAndScriptRef pkh -mustPayWithDatumAndScriptRef pkh (Just skh) = - Constraints.mustPayToPubKeyAddressWithDatumAndScriptRef pkh skh diff --git a/scripts/import-fixer.sh b/scripts/import-fixer.sh index 27714ad940..66e90ff440 100755 --- a/scripts/import-fixer.sh +++ b/scripts/import-fixer.sh @@ -42,6 +42,7 @@ constrs["ScriptRef"]="NativeScriptRef, PlutusScriptRef" constrs["RedeemerTag"]="Spend, Mint, Cert, Reward" constrs["Maybe"]="Just, Nothing" constrs["PaymentCredential"]="PaymentCredential" +constrs["StakeCredential"]="StakeCredential" constrs["TransactionBuilderStep"]="SpendOutput, Pay, MintAsset, RegisterStake, IssueCertificate, WithdrawStake, RequireSignature, RegisterPool, RetirePool, IncludeDatum, SetTTL, SetValidityStartInterval, SetIsValid" constrs["OutputWitness"]="NativeScriptOutput, PlutusScriptOutput" constrs["CredentialWitness"]="NativeScriptCredential, PlutusScriptCredential" @@ -52,9 +53,11 @@ constrs["RefInputAction"]="ReferenceInput, SpendInput" for d in "src" "test" "examples"; do echo "processing $d" pushd "./$d" + command='' for key in "${!constrs[@]}"; do - echo -n "$key," - find -type f | grep '\.purs$' --color=never | xargs -I'{}' -exec sed -i 's/'"$key"'(..)/'"$key(${constrs[$key]})"'/g;' '{}' + command="$command"'s/\b'"$key"'(..)/'"$key(${constrs[$key]})"'/g;' done + find -type f | grep '\.purs$' --color=never | xargs -I'{}' -exec sed -i -e "$command" '{}' + echo "$command" popd done; diff --git a/src/Contract/Scripts.purs b/src/Contract/Scripts.purs index 8133e8fece..c23c326bf6 100644 --- a/src/Contract/Scripts.purs +++ b/src/Contract/Scripts.purs @@ -65,7 +65,7 @@ type Validator = PlutusScript type ValidatorHash = ScriptHash validatorHash - :: Warn (Text "Deprecated: Validator. Use Cardano.Types.PlutusData.hash") + :: Warn (Text "Deprecated: validatorHash. Use Cardano.Types.PlutusData.hash") => PlutusScript -> ScriptHash validatorHash = PlutusScript.hash diff --git a/src/Contract/Transaction.purs b/src/Contract/Transaction.purs index 7f25e1ba26..52bbd851e7 100644 --- a/src/Contract/Transaction.purs +++ b/src/Contract/Transaction.purs @@ -140,10 +140,8 @@ buildTx :: Array TransactionBuilderStep -> Contract Transaction buildTx steps = do - id <- asks _.networkId - let - eiRes = buildTransaction id steps - case eiRes of + networkId <- asks _.networkId + case buildTransaction networkId steps of Left err -> do throwError (error $ explainTxBuildError err) Right res -> pure res diff --git a/test/Plutip/Contract.purs b/test/Plutip/Contract.purs index 65259e6ee6..f88ceaf364 100644 --- a/test/Plutip/Contract.purs +++ b/test/Plutip/Contract.purs @@ -171,7 +171,7 @@ import Data.UInt (UInt) import Effect.Class (liftEffect) import Effect.Exception (error, throw) import JS.BigInt as BigInt -import Mote (group, skip, test) +import Mote (group, only, skip, test) import Mote.TestPlanM (TestPlanM) import Partial.Unsafe (unsafePartial) import Safe.Coerce (coerce) @@ -270,7 +270,7 @@ suite = do withWallets distribution \_ → pure unit - group "Contract interface" do + only $ group "Contract interface" do test "mustUseCollateralUtxos should not fail if enough UTxOs are provided" do @@ -1452,8 +1452,8 @@ suite = do logInfo' "Try to spend locked values" AlwaysSucceeds.spendFromAlwaysSucceeds vhash validator txId - group "CIP-40 Collateral Output" do - test "Always failing script triggers Collateral Return (ADA-only)" do + only $ group "CIP-40 Collateral Output" do + only $ test "Always failing script triggers Collateral Return (ADA-only)" do let distribution :: InitialUTxOs /\ InitialUTxOs distribution = From 9431f6a0597287b9b0bd6ce887a7e654d0c6a3c0 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Wed, 17 Jul 2024 13:42:39 +0400 Subject: [PATCH 38/52] WIP: more examples. Make the tests more stable by fixing the seed --- examples/AdditionalUtxos.purs | 12 +-- examples/AlwaysSucceeds.purs | 15 ++-- examples/ContractTestUtils.purs | 71 ++++++++-------- examples/Lose7Ada.purs | 11 +-- examples/ManyAssets.purs | 46 ++++------ src/Contract/Scripts.purs | 3 +- src/Internal/BalanceTx/Error.purs | 2 - test/Plutip/Contract.purs | 135 +++++++++++++++++------------- test/Plutip/UtxoDistribution.purs | 9 +- 9 files changed, 155 insertions(+), 149 deletions(-) diff --git a/examples/AdditionalUtxos.purs b/examples/AdditionalUtxos.purs index a7681cff67..4436d47182 100644 --- a/examples/AdditionalUtxos.purs +++ b/examples/AdditionalUtxos.purs @@ -6,13 +6,16 @@ module Ctl.Examples.AdditionalUtxos import Contract.Prelude import Cardano.Transaction.Builder - ( OutputWitness(PlutusScriptOutput) + ( DatumWitness(DatumValue) + , OutputWitness(PlutusScriptOutput) , ScriptWitness(ScriptValue) , TransactionBuilderStep(SpendOutput, Pay) ) import Cardano.Types ( OutputDatum(OutputDatum) , PaymentCredential(PaymentCredential) + , PlutusScript + , ScriptHash , Transaction ) import Cardano.Types.BigNum as BigNum @@ -28,7 +31,6 @@ import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) import Contract.PlutusData (Datum, PlutusData(Integer)) -import Contract.Scripts (Validator, ValidatorHash, validatorHash) import Contract.Sync (withoutSync) import Contract.Transaction ( ScriptRef(NativeScriptRef) @@ -60,7 +62,7 @@ contract :: Boolean -> Contract Unit contract testAdditionalUtxoOverlap = withoutSync do logInfo' "Running Examples.AdditionalUtxos" validator <- alwaysSucceedsScriptV2 - let vhash = validatorHash validator + let vhash = PlutusScript.hash validator { unbalancedTx, datum } <- payToValidator vhash withBalancedTx unbalancedTx Map.empty mempty \balancedTx -> do balancedSignedTx <- signTransaction balancedTx @@ -72,7 +74,7 @@ contract testAdditionalUtxoOverlap = withoutSync do spendFromValidator validator additionalUtxos datum payToValidator - :: ValidatorHash + :: ScriptHash -> Contract { unbalancedTx :: Transaction , datum :: Datum @@ -104,7 +106,7 @@ payToValidator vhash = do pure { unbalancedTx: tx, datum } -spendFromValidator :: Validator -> UtxoMap -> Datum -> Contract Unit +spendFromValidator :: PlutusScript -> UtxoMap -> Datum -> Contract Unit spendFromValidator validator additionalUtxos datum = do addr <- mkAddress (wrap $ ScriptHashCredential $ PlutusScript.hash validator) Nothing diff --git a/examples/AlwaysSucceeds.purs b/examples/AlwaysSucceeds.purs index 4652c08c47..7225f0d8f2 100644 --- a/examples/AlwaysSucceeds.purs +++ b/examples/AlwaysSucceeds.purs @@ -13,14 +13,13 @@ module Ctl.Examples.AlwaysSucceeds import Contract.Prelude import Cardano.Transaction.Builder - ( DatumWitness(DatumValue, DatumReference) - , OutputWitness(NativeScriptOutput, PlutusScriptOutput) - , ScriptWitness(ScriptValue, ScriptReference) + ( DatumWitness(DatumValue) + , OutputWitness(PlutusScriptOutput) + , ScriptWitness(ScriptValue) , TransactionBuilderStep(SpendOutput, Pay) ) import Cardano.Types ( Credential(PubKeyHashCredential, ScriptHashCredential) - , OutputDatum(OutputDatum) , PaymentCredential(PaymentCredential) , PlutusScript , ScriptHash @@ -30,17 +29,16 @@ import Cardano.Types ) import Cardano.Types.BigNum as BigNum import Cardano.Types.DataHash (hashPlutusData) -import Cardano.Types.DataHash as PlutusData -import Cardano.Types.OutputDatum (OutputDatum(OutputDatumHash, OutputDatum)) +import Cardano.Types.OutputDatum (OutputDatum(OutputDatumHash)) import Cardano.Types.PlutusData as PlutusData import Cardano.Types.PlutusScript as Script +import Cardano.Types.RedeemerDatum as RedeemerDatum import Cardano.Types.Transaction as Transaction import Cardano.Types.TransactionUnspentOutput (toUtxoMap) import Contract.Address (mkAddress) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) -import Contract.PlutusData (unitRedeemer) import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( awaitTxConfirmed @@ -114,7 +112,8 @@ spendFromAlwaysSucceeds vhash validator txId = do mempty [ SpendOutput utxo - ( Just $ PlutusScriptOutput (ScriptValue validator) unitRedeemer $ Just + ( Just $ PlutusScriptOutput (ScriptValue validator) RedeemerDatum.unit + $ Just $ DatumValue $ PlutusData.unit ) diff --git a/examples/ContractTestUtils.purs b/examples/ContractTestUtils.purs index b930bc44cf..570776223b 100644 --- a/examples/ContractTestUtils.purs +++ b/examples/ContractTestUtils.purs @@ -11,11 +11,18 @@ module Ctl.Examples.ContractTestUtils import Contract.Prelude +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(Pay, MintAsset) + ) import Cardano.Types ( BigNum , Coin , ExUnits(ExUnits) - , TransactionOutput + , PaymentCredential(PaymentCredential) + , StakeCredential(StakeCredential) + , TransactionOutput(TransactionOutput) , _body , _datum , _fee @@ -23,17 +30,16 @@ import Cardano.Types ) import Cardano.Types.BigNum as BigNum import Cardano.Types.Credential (Credential(PubKeyHashCredential)) +import Cardano.Types.DataHash (hashPlutusData) import Cardano.Types.Int as Int -import Cardano.Types.Mint (Mint) -import Cardano.Types.Mint as Mint import Cardano.Types.PlutusScript (PlutusScript) +import Cardano.Types.RedeemerDatum as RedeemerDatum import Cardano.Types.ScriptRef (ScriptRef(PlutusScriptRef)) import Contract.Address (Address, PaymentPubKeyHash, StakePubKeyHash, mkAddress) import Contract.Hashing (datumHash) import Contract.Log (logInfo') import Contract.Monad (Contract, liftContractM, liftedM) import Contract.PlutusData (Datum, OutputDatum(OutputDatumHash)) -import Contract.ScriptLookups as Lookups import Contract.Test.Assert ( ContractCheck , assertOutputHasDatum @@ -50,13 +56,11 @@ import Contract.Transaction , TransactionUnspentOutput , awaitTxConfirmed , balanceTx + , buildTx , lookupTxHash , signTransaction , submit ) -import Contract.TxConstraints (DatumPresence(DatumWitness)) -import Contract.TxConstraints as Constraints -import Contract.UnbalancedTx (mkUnbalancedTx) import Contract.Utxos (utxosAt) import Contract.Value (CurrencySymbol, TokenName, Value) import Contract.Value (lovelaceValueOf, singleton) as Value @@ -65,9 +69,9 @@ import Contract.Wallet , ownPaymentPubKeyHashes , ownStakePubKeyHashes ) -import Ctl.Examples.Helpers (mustPayToPubKeyStakeAddress) as Helpers import Data.Array (head) -import Data.Lens (_1, _2, view, (%~)) +import Data.Lens (view) +import Data.Map as Map import Effect.Exception (throw) type ContractParams = @@ -132,39 +136,40 @@ mkContract p = do logInfo' "Running Examples.ContractTestUtils" ownPkh <- liftedM "Failed to get own PKH" $ head <$> ownPaymentPubKeyHashes ownSkh <- join <<< head <$> ownStakePubKeyHashes + receiverAddress <- mkAddress + (PaymentCredential $ PubKeyHashCredential $ unwrap p.receiverPkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> p.receiverSkh) + ownAddress <- mkAddress + (PaymentCredential $ PubKeyHashCredential $ unwrap ownPkh) + (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> ownSkh) let - mustPayToPubKeyStakeAddressWithDatumAndScriptRef = - ownSkh # maybe Constraints.mustPayToPubKeyWithDatumAndScriptRef - \skh pkh -> - Constraints.mustPayToPubKeyAddressWithDatumAndScriptRef pkh skh - adaValue :: Value adaValue = Value.lovelaceValueOf (unwrap p.adaToSend) - nonAdaMint :: Mint - nonAdaMint = uncurry3 Mint.singleton - (p.tokensToMint <#> _2 <<< _1 %~ Int.newPositive) - nonAdaValue :: Value nonAdaValue = uncurry3 Value.singleton p.tokensToMint - constraints :: Constraints.TxConstraints - constraints = mconcat - [ Helpers.mustPayToPubKeyStakeAddress p.receiverPkh p.receiverSkh adaValue - - , Constraints.mustMintValue nonAdaMint - - , mustPayToPubKeyStakeAddressWithDatumAndScriptRef ownPkh p.datumToAttach - DatumWitness - (PlutusScriptRef p.mintingPolicy) - nonAdaValue + scriptHash /\ assetName /\ mintAmount /\ _ = p.tokensToMint + plan = + [ Pay $ TransactionOutput + { address: receiverAddress + , amount: adaValue + , datum: Nothing + , scriptRef: Nothing + } + , MintAsset scriptHash assetName (Int.newPositive mintAmount) + $ PlutusScriptCredential (ScriptValue p.mintingPolicy) + RedeemerDatum.unit + , Pay $ TransactionOutput + { address: ownAddress + , amount: nonAdaValue + , datum: Just $ OutputDatumHash $ hashPlutusData p.datumToAttach + , scriptRef: Just $ PlutusScriptRef p.mintingPolicy + } ] - lookups :: Lookups.ScriptLookups - lookups = Lookups.plutusMintingPolicy p.mintingPolicy - - unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTx unbalancedTx usedUtxos mempty + unbalancedTx <- buildTx plan + balancedTx <- balanceTx unbalancedTx Map.empty mempty balancedSignedTx <- signTransaction balancedTx txId <- submit balancedSignedTx diff --git a/examples/Lose7Ada.purs b/examples/Lose7Ada.purs index 732ad0af6a..54a8326a37 100644 --- a/examples/Lose7Ada.purs +++ b/examples/Lose7Ada.purs @@ -27,13 +27,13 @@ import Cardano.Types ) import Cardano.Types.BigNum as BigNum import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.RedeemerDatum as RedeemerDatum import Cardano.Types.Transaction as Transaction import Cardano.Types.TransactionUnspentOutput (toUtxoMap) import Contract.Address (mkAddress) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) -import Contract.PlutusData (unitRedeemer) import Contract.Scripts (Validator, ValidatorHash, validatorHash) import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction @@ -111,11 +111,12 @@ spendFromAlwaysFails vhash validator txId = do [ SpendOutput utxo $ Just - $ PlutusScriptOutput (ScriptValue validator) unitRedeemer Nothing + $ PlutusScriptOutput (ScriptValue validator) RedeemerDatum.unit + Nothing ] <#> _isValid .~ false - balancedTx <- balanceTx unbalancedTx (toUtxoMap [ utxo ]) mempty - balancedSignedTx <- signTransaction $ balancedTx # _isValid .~ true - spendTxId <- submit balancedSignedTx + spendTx <- balanceTx unbalancedTx (toUtxoMap [ utxo ]) mempty + signedTx <- signTransaction (spendTx # _isValid .~ true) + spendTxId <- submit signedTx logInfo' $ "Tx ID: " <> show spendTxId awaitTxConfirmed spendTxId logInfo' "Successfully spent locked values." diff --git a/examples/ManyAssets.purs b/examples/ManyAssets.purs index 3d2a8f1e3b..32ee45a4f4 100644 --- a/examples/ManyAssets.purs +++ b/examples/ManyAssets.purs @@ -8,26 +8,23 @@ module Ctl.Examples.ManyAssets import Contract.Prelude +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(MintAsset) + ) import Cardano.Types.Int as Int -import Cardano.Types.Mint as Mint import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') -import Contract.Monad - ( Contract - , launchAff_ - , liftContractM - , liftedM - , runContract - ) -import Contract.ScriptLookups as Lookups -import Contract.Transaction (awaitTxConfirmed, submitTxFromConstraints) -import Contract.TxConstraints as Constraints -import Contract.Wallet (getWalletUtxos) +import Contract.Monad (Contract, launchAff_, runContract) +import Contract.Transaction (awaitTxConfirmed, submitTxFromBuildPlan) import Ctl.Examples.Helpers (mkAssetName) as Helpers import Ctl.Examples.PlutusV2.Scripts.AlwaysMints (alwaysMintsPolicyScriptV2) -import Data.Array (head, range) as Array -import Data.Map (toUnfoldable) as Map +import Data.Array (range) as Array +import Data.Map as Map main :: Effect Unit main = example testnetNamiConfig @@ -45,29 +42,16 @@ mkContractWithAssertions -> Contract Unit mkContractWithAssertions exampleName = do logInfo' ("Running " <> exampleName) - utxos <- liftedM "Failed to get UTxOs from wallet" getWalletUtxos - oref <- - liftContractM "Utxo set is empty" - (fst <$> Array.head (Map.toUnfoldable utxos :: Array _)) - mp <- alwaysMintsPolicyScriptV2 let cs = PlutusScript.hash mp tns <- for (Array.range 0 600) \i -> Helpers.mkAssetName $ "CTLNFT" <> show i let - constraints :: Constraints.TxConstraints - constraints = - fold - ( tns <#> \tn -> Constraints.mustMintValue - (Mint.singleton cs tn $ Int.fromInt one) - ) - <> Constraints.mustSpendPubKeyOutput oref - - lookups :: Lookups.ScriptLookups - lookups = Lookups.plutusMintingPolicy mp - <> Lookups.unspentOutputs utxos + plan = + tns <#> \tn -> MintAsset cs tn (Int.fromInt one) + (PlutusScriptCredential (ScriptValue mp) RedeemerDatum.unit) - txHash <- submitTxFromConstraints lookups constraints + txHash <- Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty plan logInfo' $ "Tx ID: " <> show txHash awaitTxConfirmed txHash logInfo' "Tx submitted successfully!" diff --git a/src/Contract/Scripts.purs b/src/Contract/Scripts.purs index c23c326bf6..d9e76f4d63 100644 --- a/src/Contract/Scripts.purs +++ b/src/Contract/Scripts.purs @@ -65,7 +65,8 @@ type Validator = PlutusScript type ValidatorHash = ScriptHash validatorHash - :: Warn (Text "Deprecated: validatorHash. Use Cardano.Types.PlutusData.hash") + :: Warn + (Text "Deprecated: validatorHash. Use Cardano.Types.PlutusScript.hash") => PlutusScript -> ScriptHash validatorHash = PlutusScript.hash diff --git a/src/Internal/BalanceTx/Error.purs b/src/Internal/BalanceTx/Error.purs index 3ed6911e5a..a644f57f8a 100644 --- a/src/Internal/BalanceTx/Error.purs +++ b/src/Internal/BalanceTx/Error.purs @@ -142,8 +142,6 @@ explainBalanceTxError = case _ of <> pprintTagSet "for" (pprintTransactionInput ti) <> " from a " <> pprintTagSet "given set of UTxOs:" (pprintUtxoMap mp) - <> "\nThis should be impossible: please report this as a bug to " - <> bugTrackerLink UtxoMinAdaValueCalculationFailed -> "Could not calculate min ADA for UTxO" NumericOverflowError mbVal -> diff --git a/test/Plutip/Contract.purs b/test/Plutip/Contract.purs index f88ceaf364..32ac37db77 100644 --- a/test/Plutip/Contract.purs +++ b/test/Plutip/Contract.purs @@ -6,10 +6,17 @@ import Prelude import Cardano.AsCbor (decodeCbor) import Cardano.Serialization.Lib (fromBytes) -import Cardano.Transaction.Builder (TransactionBuilderStep(Pay)) +import Cardano.Transaction.Builder + ( DatumWitness(DatumValue) + , OutputWitness(PlutusScriptOutput) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(Pay, SpendOutput) + ) import Cardano.Types ( Address + , Credential(PubKeyHashCredential, ScriptHashCredential) , GeneralTransactionMetadata(GeneralTransactionMetadata) + , PaymentCredential(PaymentCredential) , StakeCredential(StakeCredential) , TransactionUnspentOutput(TransactionUnspentOutput) , _input @@ -17,13 +24,12 @@ import Cardano.Types ) import Cardano.Types.AssetName as AssetName import Cardano.Types.Coin as Coin -import Cardano.Types.Credential - ( Credential(PubKeyHashCredential, ScriptHashCredential) - ) import Cardano.Types.Int as Int import Cardano.Types.Mint as Mint -import Cardano.Types.PaymentCredential (PaymentCredential(PaymentCredential)) +import Cardano.Types.PlutusData as PlutusData import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.TransactionUnspentOutput (toUtxoMap) import Cardano.Types.Value (lovelaceValueOf) import Contract.Address ( PaymentPubKeyHash(PaymentPubKeyHash) @@ -82,7 +88,7 @@ import Contract.Transaction ( BalanceTxError(BalanceInsufficientError, InsufficientCollateralUtxos) , DataHash , NativeScript(ScriptPubkey, ScriptNOfK, ScriptAll) - , OutputDatum(OutputDatumHash, OutputDatum) + , OutputDatum(OutputDatum, OutputDatumHash) , ScriptRef(PlutusScriptRef, NativeScriptRef) , TransactionHash(TransactionHash) , TransactionInput(TransactionInput) @@ -142,7 +148,9 @@ import Ctl.Examples.PaysWithDatum (contract) as PaysWithDatum import Ctl.Examples.PlutusV2.InlineDatum as InlineDatum import Ctl.Examples.PlutusV2.OneShotMinting (contract) as OneShotMintingV2 import Ctl.Examples.PlutusV2.ReferenceInputs (contract) as ReferenceInputs -import Ctl.Examples.PlutusV2.ReferenceInputsAndScripts (contract) as ReferenceInputsAndScripts +import Ctl.Examples.PlutusV2.ReferenceInputsAndScripts + ( contract + ) as ReferenceInputsAndScripts import Ctl.Examples.PlutusV2.ReferenceScripts (contract) as ReferenceScripts import Ctl.Examples.PlutusV2.Scripts.AlwaysMints (alwaysMintsPolicyScriptV2) import Ctl.Examples.PlutusV2.Scripts.AlwaysSucceeds (alwaysSucceedsScriptV2) @@ -171,7 +179,7 @@ import Data.UInt (UInt) import Effect.Class (liftEffect) import Effect.Exception (error, throw) import JS.BigInt as BigInt -import Mote (group, only, skip, test) +import Mote (group, skip, test) import Mote.TestPlanM (TestPlanM) import Partial.Unsafe (unsafePartial) import Safe.Coerce (coerce) @@ -201,7 +209,6 @@ suite = do void $ waitUntilSlot $ Slot $ BigNum.fromInt 10 void $ waitUntilSlot $ Slot $ BigNum.fromInt 160 void $ waitUntilSlot $ Slot $ BigNum.fromInt 161 - void $ waitUntilSlot $ Slot $ BigNum.fromInt 241 group "Regressions" do skip $ test "#1441 - Mint many assets at once - fails with TooManyAssetsInOutput" @@ -270,7 +277,7 @@ suite = do withWallets distribution \_ → pure unit - only $ group "Contract interface" do + group "Contract interface" do test "mustUseCollateralUtxos should not fail if enough UTxOs are provided" do @@ -294,7 +301,7 @@ suite = do scriptAddress <- mkAddress (wrap $ ScriptHashCredential vhash) Nothing utxos <- utxosAt scriptAddress - txInput <- + utxo <- liftM ( error ( "The id " @@ -303,17 +310,21 @@ suite = do <> show scriptAddress ) ) - (view _input <$> head (lookupTxHash txId utxos)) + $ head (lookupTxHash txId utxos) let - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - <> Lookups.unspentOutputs utxos - - constraints :: TxConstraints - constraints = - Constraints.mustSpendScriptOutput txInput unitRedeemer + usedUtxos = Map.union utxos $ toUtxoMap [ utxo ] + ubTx <- buildTx + [ SpendOutput + utxo + ( Just + $ PlutusScriptOutput (ScriptValue validator) + RedeemerDatum.unit + $ Just + $ DatumValue + $ PlutusData.unit + ) + ] - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints res <- balanceTxE ubTx usedUtxos (mustUseCollateralUtxos bobsCollateral) res `shouldSatisfy` isRight @@ -339,7 +350,7 @@ suite = do scriptAddress <- mkAddress (wrap $ ScriptHashCredential vhash) Nothing utxos <- utxosAt scriptAddress - txInput <- + utxo <- liftM ( error ( "The id " @@ -348,17 +359,20 @@ suite = do <> show scriptAddress ) ) - (view _input <$> head (lookupTxHash txId utxos)) + $ head (lookupTxHash txId utxos) let - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - <> Lookups.unspentOutputs utxos - - constraints :: TxConstraints - constraints = - Constraints.mustSpendScriptOutput txInput unitRedeemer - - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints + usedUtxos = Map.union utxos $ toUtxoMap [ utxo ] + ubTx <- buildTx + [ SpendOutput + utxo + ( Just + $ PlutusScriptOutput (ScriptValue validator) + RedeemerDatum.unit + $ Just + $ DatumValue + $ PlutusData.unit + ) + ] res <- balanceTxE ubTx usedUtxos (mustUseCollateralUtxos Map.empty) res `shouldSatisfy` case _ of Left (InsufficientCollateralUtxos mp) -> Map.isEmpty mp @@ -1452,36 +1466,37 @@ suite = do logInfo' "Try to spend locked values" AlwaysSucceeds.spendFromAlwaysSucceeds vhash validator txId - only $ group "CIP-40 Collateral Output" do - only $ test "Always failing script triggers Collateral Return (ADA-only)" do - let - distribution :: InitialUTxOs /\ InitialUTxOs - distribution = - [ BigNum.fromInt 10_000_000 - , BigNum.fromInt 50_000_000 - ] /\ [ BigNum.fromInt 50_000_000 ] - withWallets distribution \(alice /\ seed) -> do - validator <- AlwaysFails.alwaysFailsScript - let vhash = validatorHash validator - txId <- withKeyWallet seed do - logInfo' "Attempt to lock value" - txId <- AlwaysFails.payToAlwaysFails vhash - awaitTxConfirmed txId - pure txId + group "CIP-40 Collateral Output" do + test "Always failing script triggers Collateral Return (ADA-only)" + do + let + distribution :: InitialUTxOs /\ InitialUTxOs + distribution = + [ BigNum.fromInt 10_000_000 + , BigNum.fromInt 50_000_000 + ] /\ [ BigNum.fromInt 50_000_000 ] + withWallets distribution \(alice /\ seed) -> do + validator <- AlwaysFails.alwaysFailsScript + let vhash = validatorHash validator + txId <- withKeyWallet seed do + logInfo' "Attempt to lock value" + txId <- AlwaysFails.payToAlwaysFails vhash + awaitTxConfirmed txId + pure txId - withKeyWallet alice do - awaitTxConfirmed txId - logInfo' "Try to spend locked values" - balanceBefore <- unsafePartial $ fold <$> getWalletBalance - AlwaysFails.spendFromAlwaysFails vhash validator txId - balance <- unsafePartial $ fold <$> getWalletBalance - let - collateralLoss = Value.lovelaceValueOf $ BigNum.fromInt $ - 5_000_000 - balance `shouldEqual` - ( unsafePartial $ fromJust $ balanceBefore `Value.minus` - collateralLoss - ) + withKeyWallet alice do + awaitTxConfirmed txId + logInfo' "Try to spend locked values" + balanceBefore <- unsafePartial $ fold <$> getWalletBalance + AlwaysFails.spendFromAlwaysFails vhash validator txId + balance <- unsafePartial $ fold <$> getWalletBalance + let + collateralLoss = Value.lovelaceValueOf $ BigNum.fromInt $ + 5_000_000 + balance `shouldEqual` + ( unsafePartial $ fromJust $ balanceBefore `Value.minus` + collateralLoss + ) test "AlwaysFails script triggers Native Asset Collateral Return (tokens)" do diff --git a/test/Plutip/UtxoDistribution.purs b/test/Plutip/UtxoDistribution.purs index fd7afd7369..a6bd33cdc7 100644 --- a/test/Plutip/UtxoDistribution.purs +++ b/test/Plutip/UtxoDistribution.purs @@ -60,14 +60,14 @@ import Mote (group, test) import Mote.TestPlanM (TestPlanM) import Partial.Unsafe (unsafePartial) import Test.Ctl.Plutip.Common (config, privateStakeKey) -import Test.QuickCheck (class Arbitrary, arbitrary) +import Test.QuickCheck (class Arbitrary, arbitrary, mkSeed) import Test.QuickCheck.Gen ( Gen , arrayOf , chooseInt , frequency - , randomSample' , resize + , sample , sized ) import Type.Prelude (Proxy(Proxy)) @@ -102,8 +102,9 @@ suite = group "UtxoDistribution" do (withStakeKey privateStakeKey <$> distribution1) runPlutipContract config distribution $ checkUtxoDistribution distribution - distrs <- liftEffect $ randomSample' 5 arbitrary - for_ distrs $ \distr -> + -- set seed to 5 and size to 10 to fail + let distrs = sample (mkSeed 2) 5 arbitrary + for_ distrs $ \distr -> do test ( "stake key transfers with random distribution: " <> ppArbitraryUtxoDistr distr From 2e72416a4a7f4eb677267afb2c0b73e77df20455 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Wed, 17 Jul 2024 13:43:30 +0400 Subject: [PATCH 39/52] Deprecate Contract.TxConstraints --- src/Internal/Types/TxConstraints.purs | 122 ++++++++++++++++---------- 1 file changed, 78 insertions(+), 44 deletions(-) diff --git a/src/Internal/Types/TxConstraints.purs b/src/Internal/Types/TxConstraints.purs index 3e1fb9a1f7..4ca42ce6a9 100644 --- a/src/Internal/Types/TxConstraints.purs +++ b/src/Internal/Types/TxConstraints.purs @@ -249,6 +249,9 @@ instance Show OutputConstraint where -- | Restrictions placed on the allocation of funds to outputs of transactions. type TxConstraints = Array TxConstraint +type TxConstraintsDeprecated = Text + "Contract.TxConstraints is deprecated. Use `purescript-cardano-transaction-builder`" + -------------------------------------------------------------------------------- -- Helpers -------------------------------------------------------------------------------- @@ -256,27 +259,28 @@ type TxConstraints = Array TxConstraint -- | `mustValidateIn r` requires the transaction's time range to be contained -- | in `r`. mustValidateIn - :: POSIXTimeRange -> TxConstraints + :: Warn TxConstraintsDeprecated => POSIXTimeRange -> TxConstraints mustValidateIn = singleton <<< MustValidateIn -- | Require the transaction to be signed by the public key. mustBeSignedBy - :: PaymentPubKeyHash -> TxConstraints + :: Warn TxConstraintsDeprecated => PaymentPubKeyHash -> TxConstraints mustBeSignedBy = singleton <<< MustBeSignedBy -- | Require the transaction to include a datum. -mustIncludeDatum :: PlutusData -> TxConstraints +mustIncludeDatum :: Warn TxConstraintsDeprecated => PlutusData -> TxConstraints mustIncludeDatum = singleton <<< MustIncludeDatum -- | Require the transaction to reference (not spend!) the given unspent -- | transaction output. mustReferenceOutput - :: TransactionInput -> TxConstraints + :: Warn TxConstraintsDeprecated => TransactionInput -> TxConstraints mustReferenceOutput = singleton <<< MustReferenceOutput -- | Lock the value with a public key address. (Base Address) mustPayToPubKeyAddress - :: PaymentPubKeyHash + :: Warn TxConstraintsDeprecated + => PaymentPubKeyHash -> StakePubKeyHash -> Value -> TxConstraints @@ -285,7 +289,8 @@ mustPayToPubKeyAddress pkh skh = -- | Lock the value and datum with a public key address. mustPayToPubKeyAddressWithDatum - :: PaymentPubKeyHash + :: Warn TxConstraintsDeprecated + => PaymentPubKeyHash -> StakePubKeyHash -> PlutusData -> DatumPresence @@ -297,7 +302,8 @@ mustPayToPubKeyAddressWithDatum pkh skh datum dtp = -- | Lock the value and reference script with a public key address. mustPayToPubKeyAddressWithScriptRef - :: PaymentPubKeyHash + :: Warn TxConstraintsDeprecated + => PaymentPubKeyHash -> StakePubKeyHash -> ScriptRef -> Value @@ -307,7 +313,8 @@ mustPayToPubKeyAddressWithScriptRef pkh skh scriptRef = -- | Lock the value, datum and reference script with a public key address. mustPayToPubKeyAddressWithDatumAndScriptRef - :: PaymentPubKeyHash + :: Warn TxConstraintsDeprecated + => PaymentPubKeyHash -> StakePubKeyHash -> PlutusData -> DatumPresence @@ -324,6 +331,7 @@ mustPayToPubKey ( Text "Some wallets may not recognize addresses without a staking key component. Consider using mustPayToPubKeyAddress" ) + => Warn TxConstraintsDeprecated => PaymentPubKeyHash -> Value -> TxConstraints @@ -332,7 +340,8 @@ mustPayToPubKey pkh = -- | Lock the value and datum with a payment public key hash. mustPayToPubKeyWithDatum - :: PaymentPubKeyHash + :: Warn TxConstraintsDeprecated + => PaymentPubKeyHash -> PlutusData -> DatumPresence -> Value @@ -342,7 +351,8 @@ mustPayToPubKeyWithDatum pkh datum dtp = -- | Lock the value and reference script with a payment public key hash. mustPayToPubKeyWithScriptRef - :: PaymentPubKeyHash + :: Warn TxConstraintsDeprecated + => PaymentPubKeyHash -> ScriptRef -> Value -> TxConstraints @@ -367,7 +377,8 @@ mustPayToPubKeyWithDatumAndScriptRef pkh datum dtp scriptRef = -- | `mustPayToScript`, and all scripts must be explicitly provided to build -- | the transaction. mustPayToScript - :: ScriptHash + :: Warn TxConstraintsDeprecated + => ScriptHash -> PlutusData -> DatumPresence -> Value @@ -377,7 +388,8 @@ mustPayToScript vh dt dtp vl = <> guard (dtp == DatumWitness) (singleton $ MustIncludeDatum dt) mustPayToScriptAddress - :: ScriptHash + :: Warn TxConstraintsDeprecated + => ScriptHash -> Credential -> PlutusData -> DatumPresence @@ -391,7 +403,8 @@ mustPayToScriptAddress vh credential dt dtp vl = -- | Note that the provided reference script does *not* necessarily need to -- | control the spending of the output, i.e. both scripts can be different. mustPayToScriptWithScriptRef - :: ScriptHash + :: Warn TxConstraintsDeprecated + => ScriptHash -> PlutusData -> DatumPresence -> ScriptRef @@ -405,7 +418,8 @@ mustPayToScriptWithScriptRef vh dt dtp scriptRef vl = -- | Note that the provided reference script does *not* necessarily need to -- | control the spending of the output, i.e. both scripts can be different. mustPayToScriptAddressWithScriptRef - :: ScriptHash + :: Warn TxConstraintsDeprecated + => ScriptHash -> Credential -> PlutusData -> DatumPresence @@ -417,14 +431,16 @@ mustPayToScriptAddressWithScriptRef vh credential dt dtp scriptRef vl = <> guard (dtp == DatumWitness) (singleton $ MustIncludeDatum dt) mustPayToNativeScript - :: ScriptHash + :: Warn TxConstraintsDeprecated + => ScriptHash -> Value -> TxConstraints mustPayToNativeScript nsHash vl = singleton (MustPayToNativeScript nsHash Nothing vl) mustPayToNativeScriptAddress - :: ScriptHash + :: Warn TxConstraintsDeprecated + => ScriptHash -> Credential -> Value -> TxConstraints @@ -433,13 +449,14 @@ mustPayToNativeScriptAddress nsHash credential vl = -- | Mint the given `Value` -- | The amount to mint must not be zero. -mustMintValue :: Mint -> TxConstraints +mustMintValue :: Warn TxConstraintsDeprecated => Mint -> TxConstraints mustMintValue = mustMintValueWithRedeemer RedeemerDatum.unit -- | Mint the given `Value` by accessing non-Ada assets. -- | The amount to mint must not be zero. mustMintValueWithRedeemer - :: RedeemerDatum + :: Warn TxConstraintsDeprecated + => RedeemerDatum -> Mint -> TxConstraints mustMintValueWithRedeemer redeemer = @@ -453,7 +470,8 @@ mustMintValueWithRedeemer redeemer = -- | Create the given amount of the currency. -- | The amount to mint must not be zero. mustMintCurrency - :: ScriptHash + :: Warn TxConstraintsDeprecated + => ScriptHash -> AssetName -> Int.Int -> TxConstraints @@ -461,7 +479,8 @@ mustMintCurrency mph = mustMintCurrencyWithRedeemer mph RedeemerDatum.unit mustMintCurrencyUsingNativeScript - :: NativeScript + :: Warn TxConstraintsDeprecated + => NativeScript -> AssetName -> Int.Int -> TxConstraints @@ -471,7 +490,8 @@ mustMintCurrencyUsingNativeScript ns tk i = singleton -- | Create the given amount of the currency using a reference minting policy. -- | The amount to mint must not be zero. mustMintCurrencyUsingScriptRef - :: ScriptHash + :: Warn TxConstraintsDeprecated + => ScriptHash -> AssetName -> Int.Int -> InputWithScriptRef @@ -482,7 +502,8 @@ mustMintCurrencyUsingScriptRef mph = -- | Create the given amount of the currency. -- | The amount to mint must not be zero. mustMintCurrencyWithRedeemer - :: ScriptHash + :: Warn TxConstraintsDeprecated + => ScriptHash -> RedeemerDatum -> AssetName -> Int.Int @@ -493,7 +514,8 @@ mustMintCurrencyWithRedeemer mph red tn amount = -- | Create the given amount of the currency using a reference minting policy. -- | The amount to mint must not be zero. mustMintCurrencyWithRedeemerUsingScriptRef - :: ScriptHash + :: Warn TxConstraintsDeprecated + => ScriptHash -> RedeemerDatum -> AssetName -> Int.Int @@ -503,21 +525,22 @@ mustMintCurrencyWithRedeemerUsingScriptRef mph red tn amount = singleton <<< MustMintValue mph red tn amount <<< Just -- | Requirement to spend inputs with at least the given value -mustSpendAtLeast :: Value -> TxConstraints +mustSpendAtLeast :: Warn TxConstraintsDeprecated => Value -> TxConstraints mustSpendAtLeast = singleton <<< MustSpendAtLeast -- | Requirement to produce outputs with at least the given value -mustProduceAtLeast :: Value -> TxConstraints +mustProduceAtLeast :: Warn TxConstraintsDeprecated => Value -> TxConstraints mustProduceAtLeast = singleton <<< MustProduceAtLeast -- | Spend the given unspent transaction public key output. mustSpendPubKeyOutput - :: TransactionInput -> TxConstraints + :: Warn TxConstraintsDeprecated => TransactionInput -> TxConstraints mustSpendPubKeyOutput = singleton <<< MustSpendPubKeyOutput -- | Spend the given unspent transaction script output. mustSpendScriptOutput - :: TransactionInput + :: Warn TxConstraintsDeprecated + => TransactionInput -> RedeemerDatum -> TxConstraints mustSpendScriptOutput txOutRef red = @@ -526,7 +549,8 @@ mustSpendScriptOutput txOutRef red = -- | Spend the given unspent transaction script output, using a reference script -- | to satisfy the script witnessing requirement. mustSpendScriptOutputUsingScriptRef - :: TransactionInput + :: Warn TxConstraintsDeprecated + => TransactionInput -> RedeemerDatum -> InputWithScriptRef -> TxConstraints @@ -534,59 +558,65 @@ mustSpendScriptOutputUsingScriptRef txOutRef red = singleton <<< MustSpendScriptOutput txOutRef red <<< Just mustSpendNativeScriptOutput - :: TransactionInput + :: Warn TxConstraintsDeprecated + => TransactionInput -> NativeScript -> TxConstraints mustSpendNativeScriptOutput txOutRef = singleton <<< MustSpendNativeScriptOutput txOutRef mustHashDatum - :: DataHash -> PlutusData -> TxConstraints + :: Warn TxConstraintsDeprecated => DataHash -> PlutusData -> TxConstraints mustHashDatum dhsh = singleton <<< MustHashDatum dhsh mustRegisterStakePubKey - :: StakePubKeyHash -> TxConstraints + :: Warn TxConstraintsDeprecated => StakePubKeyHash -> TxConstraints mustRegisterStakePubKey = singleton <<< MustRegisterStakePubKey mustDeregisterStakePubKey - :: StakePubKeyHash -> TxConstraints + :: Warn TxConstraintsDeprecated => StakePubKeyHash -> TxConstraints mustDeregisterStakePubKey = singleton <<< MustDeregisterStakePubKey mustRegisterStakeScript - :: ScriptHash -> TxConstraints + :: Warn TxConstraintsDeprecated => ScriptHash -> TxConstraints mustRegisterStakeScript = singleton <<< MustRegisterStakeScript mustDeregisterStakePlutusScript - :: PlutusScript + :: Warn TxConstraintsDeprecated + => PlutusScript -> RedeemerDatum -> TxConstraints mustDeregisterStakePlutusScript sv = singleton <<< MustDeregisterStakePlutusScript sv mustDeregisterStakeNativeScript - :: NativeScript + :: Warn TxConstraintsDeprecated + => NativeScript -> TxConstraints mustDeregisterStakeNativeScript = singleton <<< MustDeregisterStakeNativeScript mustRegisterPool - :: PoolParams -> TxConstraints + :: Warn TxConstraintsDeprecated => PoolParams -> TxConstraints mustRegisterPool = singleton <<< MustRegisterPool mustRetirePool - :: PoolPubKeyHash + :: Warn TxConstraintsDeprecated + => PoolPubKeyHash -> Epoch -> TxConstraints mustRetirePool poolPubKeyHash = singleton <<< MustRetirePool poolPubKeyHash mustDelegateStakePubKey - :: StakePubKeyHash + :: Warn TxConstraintsDeprecated + => StakePubKeyHash -> PoolPubKeyHash -> TxConstraints mustDelegateStakePubKey spkh ppkh = singleton $ MustDelegateStakePubKey spkh ppkh mustDelegateStakePlutusScript - :: PlutusScript + :: Warn TxConstraintsDeprecated + => PlutusScript -> RedeemerDatum -> PoolPubKeyHash -> TxConstraints @@ -594,25 +624,28 @@ mustDelegateStakePlutusScript sv redeemer ppkh = singleton $ MustDelegateStakePlutusScript sv redeemer ppkh mustDelegateStakeNativeScript - :: NativeScript + :: Warn TxConstraintsDeprecated + => NativeScript -> PoolPubKeyHash -> TxConstraints mustDelegateStakeNativeScript sv ppkh = singleton $ MustDelegateStakeNativeScript sv ppkh mustWithdrawStakePubKey - :: StakePubKeyHash -> TxConstraints + :: Warn TxConstraintsDeprecated => StakePubKeyHash -> TxConstraints mustWithdrawStakePubKey spkh = singleton $ MustWithdrawStakePubKey spkh mustWithdrawStakePlutusScript - :: PlutusScript + :: Warn TxConstraintsDeprecated + => PlutusScript -> RedeemerDatum -> TxConstraints mustWithdrawStakePlutusScript validator redeemer = singleton $ MustWithdrawStakePlutusScript validator redeemer mustWithdrawStakeNativeScript - :: NativeScript + :: Warn TxConstraintsDeprecated + => NativeScript -> TxConstraints mustWithdrawStakeNativeScript = singleton <<< MustWithdrawStakeNativeScript @@ -624,6 +657,7 @@ mustWithdrawStakeNativeScript = mustSatisfyAnyOf :: forall (f :: Type -> Type) . Foldable f + => Warn TxConstraintsDeprecated => f (TxConstraints) -> TxConstraints mustSatisfyAnyOf = @@ -634,5 +668,5 @@ mustSatisfyAnyOf = -- | Marks the transaction as invalid, requiring at least one script execution -- | to fail. Despite failure, the transaction can still be submitted into the -- | chain and collateral will be lost. -mustNotBeValid :: TxConstraints +mustNotBeValid :: Warn TxConstraintsDeprecated => TxConstraints mustNotBeValid = singleton $ MustNotBeValid From 50a30863f08f3ee0cf6135f60d213df6c2649976 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Wed, 17 Jul 2024 18:14:10 +0400 Subject: [PATCH 40/52] WIP: rewrite more examples --- examples/ChangeGeneration.purs | 73 ++++++++++++++------------- examples/ExUnits.purs | 83 +++++++++++++++---------------- examples/IncludeDatum.purs | 67 ++++++++++++------------- examples/MintsMultipleTokens.purs | 48 +++++++++--------- examples/Pkh2Pkh.purs | 19 ++----- src/Contract/Wallet.purs | 2 +- 6 files changed, 140 insertions(+), 152 deletions(-) diff --git a/examples/ChangeGeneration.purs b/examples/ChangeGeneration.purs index 012b6362c6..1c15e1bb57 100644 --- a/examples/ChangeGeneration.purs +++ b/examples/ChangeGeneration.purs @@ -2,36 +2,37 @@ module Ctl.Examples.ChangeGeneration (checkChangeOutputsDistribution) where import Prelude +import Cardano.Transaction.Builder (TransactionBuilderStep(Pay)) import Cardano.Types - ( _body + ( Credential(ScriptHashCredential) + , OutputDatum(OutputDatumHash) + , PaymentCredential(PaymentCredential) + , TransactionOutput(TransactionOutput) + , _body , _outputs ) import Cardano.Types.BigNum as BigNum +import Cardano.Types.DataHash (hashPlutusData) +import Cardano.Types.PlutusData as PlutusData +import Contract.Address (mkAddress) import Contract.BalanceTxConstraints (mustSendChangeWithDatum) -import Contract.Monad (Contract) -import Contract.PlutusData - ( OutputDatum(OutputDatum) - , PlutusData(Integer) - , unitDatum - ) -import Contract.ScriptLookups as Lookups +import Contract.Monad (Contract, liftedM) +import Contract.PlutusData (OutputDatum(OutputDatum), PlutusData(Integer)) import Contract.Scripts (validatorHash) import Contract.Transaction ( awaitTxConfirmed , balanceTx + , buildTx , signTransaction , submit ) -import Contract.TxConstraints (TxConstraints) -import Contract.TxConstraints as Constraints -import Contract.UnbalancedTx (mkUnbalancedTx) import Contract.Value as Value -import Contract.Wallet (ownPaymentPubKeyHashes, ownStakePubKeyHashes) +import Contract.Wallet (getWalletAddress) import Ctl.Examples.AlwaysSucceeds as AlwaysSucceeds -import Data.Array (fold, length, replicate, take, zip) +import Data.Array (length, replicate) import Data.Lens ((^.)) +import Data.Map as Map import Data.Maybe (Maybe(Just, Nothing)) -import Data.Tuple.Nested ((/\)) import JS.BigInt (fromInt) as BigInt import Test.Spec.Assertions (shouldEqual) @@ -41,32 +42,36 @@ import Test.Spec.Assertions (shouldEqual) checkChangeOutputsDistribution :: Int -> Int -> Int -> Contract Unit checkChangeOutputsDistribution outputsToScript outputsToSelf expectedOutputs = do - pkhs <- ownPaymentPubKeyHashes - skhs <- ownStakePubKeyHashes validator <- AlwaysSucceeds.alwaysSucceedsScript + address <- liftedM "Failed to get own address" $ getWalletAddress let vhash = validatorHash validator + scriptAddress <- mkAddress + (PaymentCredential $ ScriptHashCredential $ vhash) + Nothing + let value = Value.lovelaceValueOf $ BigNum.fromInt 1000001 - constraintsToSelf :: TxConstraints - constraintsToSelf = fold <<< take outputsToSelf <<< fold - $ replicate outputsToSelf - $ zip pkhs skhs <#> \(pkh /\ mbSkh) -> case mbSkh of - Nothing -> Constraints.mustPayToPubKey pkh value - Just skh -> Constraints.mustPayToPubKeyAddress pkh skh value - - constraintsToScripts :: TxConstraints - constraintsToScripts = fold $ replicate outputsToScript - $ Constraints.mustPayToScript vhash unitDatum - Constraints.DatumWitness - value - - constraints = constraintsToSelf <> constraintsToScripts + plan = + replicate outputsToSelf + ( Pay $ TransactionOutput + { address: address + , amount: value + , datum: Nothing + , scriptRef: Nothing + } + ) <> + replicate outputsToScript + ( Pay $ TransactionOutput + { address: scriptAddress + , amount: value + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ) - lookups :: Lookups.ScriptLookups - lookups = mempty - unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balancedTx <- balanceTx unbalancedTx usedUtxos + unbalancedTx <- buildTx plan + balancedTx <- balanceTx unbalancedTx Map.empty -- just to check that attaching datums works ( mustSendChangeWithDatum $ OutputDatum $ Integer $ BigInt.fromInt 1000 diff --git a/examples/ExUnits.purs b/examples/ExUnits.purs index 9fc323912b..54ff6abf7f 100644 --- a/examples/ExUnits.purs +++ b/examples/ExUnits.purs @@ -2,32 +2,41 @@ module Ctl.Examples.ExUnits where import Contract.Prelude -import Cardano.Types (_input) +import Cardano.Transaction.Builder + ( OutputWitness(PlutusScriptOutput) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(Pay, SpendOutput) + ) +import Cardano.Types + ( Credential(ScriptHashCredential) + , OutputDatum(OutputDatum) + , PaymentCredential(PaymentCredential) + , TransactionOutput(TransactionOutput) + ) import Cardano.Types.BigNum as BigNum -import Cardano.Types.Credential (Credential(ScriptHashCredential)) +import Cardano.Types.PlutusData as PlutusData +import Cardano.Types.Transaction as Transaction +import Cardano.Types.TransactionUnspentOutput (toUtxoMap) import Contract.Address (mkAddress) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Credential (Credential(PubKeyHashCredential)) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) -import Contract.PlutusData (RedeemerDatum(RedeemerDatum), toData, unitDatum) -import Contract.ScriptLookups as Lookups +import Contract.PlutusData (RedeemerDatum(RedeemerDatum), toData) import Contract.Scripts (Validator, ValidatorHash, validatorHash) import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( TransactionHash , awaitTxConfirmed , lookupTxHash - , submitTxFromConstraints + , submitTxFromBuildPlan ) -import Contract.TxConstraints (TxConstraints) -import Contract.TxConstraints as Constraints import Contract.Utxos (utxosAt) import Contract.Value as Value import Contract.Wallet (ownStakePubKeyHashes) import Control.Monad.Error.Class (liftMaybe) import Data.Array (head) -import Data.Lens (view) +import Data.Map as Map import Effect.Exception (error) import JS.BigInt (BigInt) import JS.BigInt as BigInt @@ -52,29 +61,17 @@ example cfg = launchAff_ do payToExUnits :: ValidatorHash -> Contract TransactionHash payToExUnits vhash = do - -- Send to own stake credential. This is used to test mustPayToScriptAddress. - mbStakeKeyHash <- join <<< head <$> ownStakePubKeyHashes - let - constraints :: TxConstraints - constraints = - case mbStakeKeyHash of - Nothing -> - Constraints.mustPayToScript vhash unitDatum - Constraints.DatumWitness - $ Value.lovelaceValueOf - $ BigNum.fromInt 2_000_000 - Just stakeKeyHash -> - Constraints.mustPayToScriptAddress vhash - (PubKeyHashCredential $ unwrap stakeKeyHash) - unitDatum - Constraints.DatumWitness - $ Value.lovelaceValueOf - $ BigNum.fromInt 2_000_000 - - lookups :: Lookups.ScriptLookups - lookups = mempty - - submitTxFromConstraints lookups constraints + address <- mkAddress + (PaymentCredential $ ScriptHashCredential vhash) + Nothing + Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address: address + , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + , datum: Just $ OutputDatum PlutusData.unit + , scriptRef: Nothing + } + ] -- | ExUnits script loops a given number of iterations provided as redeemer. spendFromExUnits @@ -90,7 +87,7 @@ spendFromExUnits iters vhash validator txId = do mkAddress (wrap $ ScriptHashCredential vhash) (wrap <<< PubKeyHashCredential <<< unwrap <$> mbStakeKeyHash) utxos <- utxosAt scriptAddress - txInput <- + utxo <- liftM ( error ( "The id " @@ -99,18 +96,18 @@ spendFromExUnits iters vhash validator txId = do <> show scriptAddress ) ) - (view _input <$> head (lookupTxHash txId utxos)) - let - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - <> Lookups.unspentOutputs utxos - - constraints :: TxConstraints - constraints = - Constraints.mustSpendScriptOutput txInput (RedeemerDatum $ toData iters) + (head (lookupTxHash txId utxos)) - spendTxId <- submitTxFromConstraints lookups constraints - awaitTxConfirmed spendTxId + spendTx <- submitTxFromBuildPlan (toUtxoMap [ utxo ]) + mempty + [ SpendOutput + utxo + $ Just + $ PlutusScriptOutput (ScriptValue validator) + (RedeemerDatum $ toData iters) + Nothing + ] + awaitTxConfirmed $ Transaction.hash spendTx logInfo' "Successfully spent locked values." exUnitsScript :: Contract Validator diff --git a/examples/IncludeDatum.purs b/examples/IncludeDatum.purs index 086e95250f..c17aed717f 100644 --- a/examples/IncludeDatum.purs +++ b/examples/IncludeDatum.purs @@ -12,32 +12,38 @@ module Ctl.Examples.IncludeDatum import Contract.Prelude +import Cardano.Transaction.Builder + ( OutputWitness(PlutusScriptOutput) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(SpendOutput, Pay) + ) import Cardano.Types ( Credential(ScriptHashCredential) - , _input + , OutputDatum(OutputDatum) + , TransactionOutput(TransactionOutput) ) import Cardano.Types.BigNum as BigNum +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction +import Cardano.Types.TransactionUnspentOutput (toUtxoMap) import Contract.Address (mkAddress) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftContractM, runContract) -import Contract.PlutusData (PlutusData(Integer), unitRedeemer) -import Contract.ScriptLookups as Lookups +import Contract.PlutusData (PlutusData(Integer)) import Contract.Scripts (Validator, ValidatorHash, validatorHash) import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) import Contract.Transaction ( TransactionHash , awaitTxConfirmed , lookupTxHash - , submitTxFromConstraints + , submitTxFromBuildPlan ) -import Contract.TxConstraints (TxConstraints) -import Contract.TxConstraints as Constraints import Contract.Utxos (utxosAt) import Contract.Value as Value import Control.Monad.Error.Class (liftMaybe) import Data.Array (head) -import Data.Lens (view) +import Data.Map as Map import Effect.Exception (error) import JS.BigInt as BigInt @@ -60,20 +66,16 @@ datum :: PlutusData datum = Integer $ BigInt.fromInt 42 payToIncludeDatum :: ValidatorHash -> Contract TransactionHash -payToIncludeDatum vhash = - let - constraints :: TxConstraints - constraints = - ( Constraints.mustPayToScript vhash datum Constraints.DatumWitness - $ Value.lovelaceValueOf - $ BigNum.fromInt 2_000_000 - ) - <> Constraints.mustIncludeDatum datum - - lookups :: Lookups.ScriptLookups - lookups = mempty - in - submitTxFromConstraints lookups constraints +payToIncludeDatum vhash = do + address <- mkAddress (wrap $ ScriptHashCredential vhash) Nothing + Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address + , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 + , datum: Just $ OutputDatum datum + , scriptRef: Nothing + } + ] spendFromIncludeDatum :: ValidatorHash @@ -83,19 +85,16 @@ spendFromIncludeDatum spendFromIncludeDatum vhash validator txId = do scriptAddress <- mkAddress (wrap $ ScriptHashCredential vhash) Nothing utxos <- utxosAt scriptAddress - txInput <- liftContractM "no locked output at address" - (view _input <$> head (lookupTxHash txId utxos)) - let - lookups :: Lookups.ScriptLookups - lookups = Lookups.validator validator - <> Lookups.unspentOutputs utxos - - constraints :: TxConstraints - constraints = - Constraints.mustSpendScriptOutput txInput unitRedeemer - <> Constraints.mustIncludeDatum datum - spendTxId <- submitTxFromConstraints lookups constraints - awaitTxConfirmed spendTxId + utxo <- liftContractM "no locked output at address" + (head (lookupTxHash txId utxos)) + spendTx <- submitTxFromBuildPlan (toUtxoMap [ utxo ]) + mempty + [ SpendOutput + utxo + ( Just $ PlutusScriptOutput (ScriptValue validator) RedeemerDatum.unit Nothing + ) + ] + awaitTxConfirmed $ Transaction.hash spendTx logInfo' "Successfully spent locked values." -- | checks if the datum equals 42 diff --git a/examples/MintsMultipleTokens.purs b/examples/MintsMultipleTokens.purs index 141692ad72..fc87338354 100644 --- a/examples/MintsMultipleTokens.purs +++ b/examples/MintsMultipleTokens.purs @@ -12,23 +12,26 @@ module Ctl.Examples.MintsMultipleTokens import Contract.Prelude +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(MintAsset) + ) import Cardano.Types.Int as Int -import Cardano.Types.Mint as Mint import Cardano.Types.PlutusScript (PlutusScript) import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.Transaction as Transaction import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) import Contract.PlutusData (PlutusData(Integer), RedeemerDatum(RedeemerDatum)) -import Contract.ScriptLookups as Lookups import Contract.TextEnvelope (decodeTextEnvelope, plutusScriptFromEnvelope) -import Contract.Transaction (awaitTxConfirmed, submitTxFromConstraints) -import Contract.TxConstraints as Constraints +import Contract.Transaction (awaitTxConfirmed, submitTxFromBuildPlan) import Control.Monad.Error.Class (liftMaybe) import Ctl.Examples.Helpers (mkAssetName) as Helpers +import Data.Map as Map import Effect.Exception (error) import JS.BigInt (fromInt) as BigInt -import Partial.Unsafe (unsafePartial) main :: Effect Unit main = example testnetNamiConfig @@ -47,28 +50,23 @@ contract = do cs3 = PlutusScript.hash mp3 let - constraints :: Constraints.TxConstraints - constraints = unsafePartial $ mconcat - [ Constraints.mustMintValueWithRedeemer - (RedeemerDatum $ Integer (BigInt.fromInt 1)) - (Mint.singleton cs1 tn1 Int.one <> Mint.singleton cs1 tn2 Int.one) - , Constraints.mustMintValueWithRedeemer - (RedeemerDatum $ Integer (BigInt.fromInt 2)) - (Mint.singleton cs2 tn1 Int.one <> Mint.singleton cs2 tn2 Int.one) - , Constraints.mustMintValueWithRedeemer - (RedeemerDatum $ Integer (BigInt.fromInt 3)) - (Mint.singleton cs3 tn1 Int.one <> Mint.singleton cs3 tn2 Int.one) + plan = + [ MintAsset cs1 tn1 Int.one + ( PlutusScriptCredential (ScriptValue mp1) $ RedeemerDatum $ Integer + (BigInt.fromInt 1) + ) + , MintAsset cs2 tn2 Int.one + ( PlutusScriptCredential (ScriptValue mp2) $ RedeemerDatum $ Integer + (BigInt.fromInt 2) + ) + , MintAsset cs3 tn2 Int.one + ( PlutusScriptCredential (ScriptValue mp3) $ RedeemerDatum $ Integer + (BigInt.fromInt 3) + ) ] - lookups :: Lookups.ScriptLookups - lookups = - Lookups.plutusMintingPolicy mp1 - <> Lookups.plutusMintingPolicy mp2 - <> Lookups.plutusMintingPolicy mp3 - - txId <- submitTxFromConstraints lookups constraints - - awaitTxConfirmed txId + tx <- submitTxFromBuildPlan Map.empty mempty plan + awaitTxConfirmed $ Transaction.hash tx logInfo' $ "Tx submitted successfully!" example :: ContractParams -> Effect Unit diff --git a/examples/Pkh2Pkh.purs b/examples/Pkh2Pkh.purs index 0a3d5be28b..237971e614 100644 --- a/examples/Pkh2Pkh.purs +++ b/examples/Pkh2Pkh.purs @@ -5,27 +5,21 @@ module Ctl.Examples.Pkh2Pkh (main, contract, example) where import Contract.Prelude -import Cardano.Transaction.Builder - ( TransactionBuilderStep(Pay) - ) +import Cardano.Transaction.Builder (TransactionBuilderStep(Pay)) import Cardano.Types - ( Credential(PubKeyHashCredential) - , OutputDatum(OutputDatumHash) - , PaymentCredential(PaymentCredential) - , StakeCredential(StakeCredential) + ( OutputDatum(OutputDatumHash) , TransactionOutput(TransactionOutput) ) import Cardano.Types.BigNum as BigNum import Cardano.Types.DataHash (hashPlutusData) import Cardano.Types.PlutusData as PlutusData import Cardano.Types.Transaction as Transaction -import Contract.Address (mkAddress) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftedM, runContract) import Contract.Transaction (awaitTxConfirmedWithTimeout, submitTxFromBuildPlan) import Contract.Value as Value -import Contract.Wallet (ownPaymentPubKeyHashes, ownStakePubKeyHashes) +import Contract.Wallet (getWalletAddresses) import Data.Array (head) import Data.Map as Map @@ -35,12 +29,7 @@ main = example testnetNamiConfig contract :: Contract Unit contract = do logInfo' "Running Examples.Pkh2Pkh" - pkh <- liftedM "Failed to get own PKH" $ head <$> ownPaymentPubKeyHashes - skh <- liftedM "Failed to get own SKH" $ head <$> - ownStakePubKeyHashes - address <- mkAddress - (PaymentCredential $ PubKeyHashCredential $ unwrap pkh) - (StakeCredential <<< PubKeyHashCredential <<< unwrap <$> skh) + address <- liftedM "Failed to get own address" $ head <$> getWalletAddresses txId <- Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty [ Pay $ TransactionOutput { address diff --git a/src/Contract/Wallet.purs b/src/Contract/Wallet.purs index 4ad52a1bab..a80d125acb 100644 --- a/src/Contract/Wallet.purs +++ b/src/Contract/Wallet.purs @@ -129,7 +129,7 @@ mkKeyWalletFromPrivateKeys payment mbStake = privateKeysToKeyWallet payment getWalletAddress :: Warn ( Text - "This function returns only one `Adress` even in case multiple `Adress`es are available. Use `getWalletAdresses` instead" + "This function returns only one `Address` even in case multiple `Address`es are available. Use `getWalletAddresses` instead" ) => Contract (Maybe Address) getWalletAddress = head <$> getWalletAddresses From 80bc5a0954cc2501140fd3daf70f8c1692598d49 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Wed, 17 Jul 2024 21:20:31 +0400 Subject: [PATCH 41/52] WIP: updating the examples. Remove overlapping tests. --- examples/ByUrl.purs | 2 - examples/IncludeDatum.purs | 12 +- examples/MultipleRedeemers.purs | 34 ++- examples/PlutusV2/ReferenceInputs.purs | 121 ----------- .../PlutusV2/ReferenceInputsAndScripts.purs | 205 +++++++----------- examples/PlutusV2/ReferenceScripts.purs | 125 ----------- test/Plutip/Contract.purs | 44 +--- 7 files changed, 123 insertions(+), 420 deletions(-) delete mode 100644 examples/PlutusV2/ReferenceInputs.purs delete mode 100644 examples/PlutusV2/ReferenceScripts.purs diff --git a/examples/ByUrl.purs b/examples/ByUrl.purs index 3119dff8d5..8d027d1715 100644 --- a/examples/ByUrl.purs +++ b/examples/ByUrl.purs @@ -48,7 +48,6 @@ import Ctl.Examples.PaysWithDatum as PaysWithDatum import Ctl.Examples.Pkh2Pkh as Pkh2Pkh import Ctl.Examples.PlutusV2.AlwaysSucceeds as AlwaysSucceedsV2 import Ctl.Examples.PlutusV2.OneShotMinting as OneShotMintingV2 -import Ctl.Examples.PlutusV2.ReferenceInputs as ReferenceInputsV2 import Ctl.Examples.PlutusV2.ReferenceInputsAndScripts as ReferenceInputsAndScriptsV2 import Ctl.Examples.Schnorr as Schnorr import Ctl.Examples.SendsToken as SendsToken @@ -214,7 +213,6 @@ examples = addSuccessLog <$> Map.fromFoldable , "OneShotMinting" /\ OneShotMinting.contract , "OneShotMintingV2" /\ OneShotMintingV2.contract , "Cip30" /\ Cip30.contract - , "ReferenceInputs" /\ ReferenceInputsV2.contract , "ReferenceInputsAndScripts" /\ ReferenceInputsAndScriptsV2.contract , "Utxos" /\ Utxos.contract , "ApplyArgs" /\ ApplyArgs.contract diff --git a/examples/IncludeDatum.purs b/examples/IncludeDatum.purs index c17aed717f..42135a565d 100644 --- a/examples/IncludeDatum.purs +++ b/examples/IncludeDatum.purs @@ -13,16 +13,18 @@ module Ctl.Examples.IncludeDatum import Contract.Prelude import Cardano.Transaction.Builder - ( OutputWitness(PlutusScriptOutput) + ( DatumWitness(DatumValue) + , OutputWitness(PlutusScriptOutput) , ScriptWitness(ScriptValue) , TransactionBuilderStep(SpendOutput, Pay) ) import Cardano.Types ( Credential(ScriptHashCredential) - , OutputDatum(OutputDatum) + , OutputDatum(OutputDatumHash) , TransactionOutput(TransactionOutput) ) import Cardano.Types.BigNum as BigNum +import Cardano.Types.DataHash (hashPlutusData) import Cardano.Types.RedeemerDatum as RedeemerDatum import Cardano.Types.Transaction as Transaction import Cardano.Types.TransactionUnspentOutput (toUtxoMap) @@ -72,7 +74,7 @@ payToIncludeDatum vhash = do [ Pay $ TransactionOutput { address , amount: Value.lovelaceValueOf $ BigNum.fromInt 2_000_000 - , datum: Just $ OutputDatum datum + , datum: Just $ OutputDatumHash $ hashPlutusData datum , scriptRef: Nothing } ] @@ -91,7 +93,9 @@ spendFromIncludeDatum vhash validator txId = do mempty [ SpendOutput utxo - ( Just $ PlutusScriptOutput (ScriptValue validator) RedeemerDatum.unit Nothing + ( Just $ PlutusScriptOutput (ScriptValue validator) RedeemerDatum.unit + $ Just + $ DatumValue datum ) ] awaitTxConfirmed $ Transaction.hash spendTx diff --git a/examples/MultipleRedeemers.purs b/examples/MultipleRedeemers.purs index a27e33e126..2e7c6a4300 100644 --- a/examples/MultipleRedeemers.purs +++ b/examples/MultipleRedeemers.purs @@ -8,10 +8,13 @@ module Ctl.Examples.MultipleRedeemers import Contract.Prelude -import Cardano.Types.Credential (Credential(ScriptHashCredential)) +import Cardano.Types (AssetName, Credential(ScriptHashCredential)) +import Cardano.Types.BigNum as BigNum import Cardano.Types.Int as Int import Cardano.Types.Mint as Mint +import Cardano.Types.PlutusData as PlutusData import Cardano.Types.PlutusScript as PlutusScript +import Cardano.Types.Value as Value import Contract.Address (mkAddress) import Contract.Monad (Contract) import Contract.PlutusData @@ -27,9 +30,6 @@ import Contract.TxConstraints as Constraints import Contract.Utxos (utxosAt) import Control.Monad.Error.Class (liftMaybe) import Ctl.Examples.Helpers (mkAssetName) -import Ctl.Examples.PlutusV2.ReferenceInputsAndScripts - ( mintAlwaysMintsV2ToTheScript - ) import Ctl.Examples.PlutusV2.Scripts.AlwaysMints (alwaysMintsPolicyScriptV2) import Data.List as List import Data.Map as Map @@ -137,3 +137,29 @@ redeemerIs3Validator = do liftMaybe (error "Error decoding redeemerIs3Script") do envelope <- decodeTextEnvelope redeemerIs3Script plutusScriptFromEnvelope envelope + +mintAlwaysMintsV2ToTheScript + :: AssetName -> Validator -> Int -> Contract Unit +mintAlwaysMintsV2ToTheScript tokenName validator sum = do + mp <- alwaysMintsPolicyScriptV2 + let cs = PlutusScript.hash mp + + let + vhash = PlutusScript.hash validator + + constraints :: Constraints.TxConstraints + constraints = mconcat + [ Constraints.mustMintValue + $ Mint.singleton cs tokenName + $ Int.fromInt sum + , Constraints.mustPayToScript vhash PlutusData.unit + Constraints.DatumWitness + $ Value.singleton cs tokenName + $ BigNum.fromInt sum + ] + + lookups :: Lookups.ScriptLookups + lookups = Lookups.plutusMintingPolicy mp + + txHash <- submitTxFromConstraints lookups constraints + void $ awaitTxConfirmed txHash diff --git a/examples/PlutusV2/ReferenceInputs.purs b/examples/PlutusV2/ReferenceInputs.purs deleted file mode 100644 index 5651e90e5a..0000000000 --- a/examples/PlutusV2/ReferenceInputs.purs +++ /dev/null @@ -1,121 +0,0 @@ -module Ctl.Examples.PlutusV2.ReferenceInputs (contract, example, main) where - -import Contract.Prelude - -import Cardano.Types - ( Transaction - , _body - , _referenceInputs - ) -import Cardano.Types.BigNum as BigNum -import Contract.Config (ContractParams, testnetNamiConfig) -import Contract.Log (logInfo') -import Contract.Monad - ( Contract - , launchAff_ - , liftContractM - , liftedM - , runContract - ) -import Contract.ScriptLookups as Lookups -import Contract.Test.Assert - ( ContractAssertionFailure(CustomFailure) - , ContractCheck - , assertContract - , assertionToCheck - , runChecks - ) -import Contract.Transaction - ( TransactionInput - , awaitTxConfirmed - , balanceTx - , signTransaction - , submit - ) -import Contract.TxConstraints as Constraints -import Contract.UnbalancedTx (mkUnbalancedTx) -import Contract.Value (lovelaceValueOf) as Value -import Contract.Wallet - ( getWalletUtxos - , ownPaymentPubKeyHashes - , ownStakePubKeyHashes - ) -import Control.Monad.Trans.Class (lift) -import Ctl.Examples.Helpers (mustPayToPubKeyStakeAddress) as Helpers -import Data.Array (elem, head) as Array -import Data.Lens.Getter ((^.)) -import Data.Map (member, toUnfoldable) as Map - -main :: Effect Unit -main = example testnetNamiConfig - -example :: ContractParams -> Effect Unit -example = launchAff_ <<< flip runContract contract - -contract :: Contract Unit -contract = do - logInfo' "Running Examples.PlutusV2.ReferenceInputs" - - pkh <- liftedM "Failed to get own PKH" - (Array.head <$> ownPaymentPubKeyHashes) - skh <- join <<< Array.head <$> ownStakePubKeyHashes - - utxos <- liftedM "Failed to get UTxOs from wallet" getWalletUtxos - oref <- - liftContractM "Utxo set is empty" - (fst <$> Array.head (Map.toUnfoldable utxos :: Array _)) - - let - constraints :: Constraints.TxConstraints - constraints = mconcat - [ Constraints.mustReferenceOutput oref - , Helpers.mustPayToPubKeyStakeAddress pkh skh - (Value.lovelaceValueOf $ BigNum.fromInt 2_000_000) - ] - - lookups :: Lookups.ScriptLookups - lookups = mempty - - void $ runChecks checks $ lift do - unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balancedSignedTx <- signTransaction - =<< balanceTx unbalancedTx usedUtxos mempty - txHash <- submit balancedSignedTx - logInfo' $ "Tx ID: " <> show txHash - awaitTxConfirmed txHash - logInfo' "Tx submitted successfully!" - - pure { referenceInput: oref, balancedSignedTx } - -type ContractResult = - { referenceInput :: TransactionInput - , balancedSignedTx :: Transaction - } - -assertTxContainsReferenceInput :: ContractCheck ContractResult -assertTxContainsReferenceInput = - assertionToCheck "Tx contains a reference input" - \{ balancedSignedTx, referenceInput } -> do - let - assertionFailure :: ContractAssertionFailure - assertionFailure = CustomFailure - "Could not find given input in `referenceInputs`" - assertContract assertionFailure do - Array.elem referenceInput - (balancedSignedTx ^. _body <<< _referenceInputs) - -assertReferenceInputNotSpent :: ContractCheck ContractResult -assertReferenceInputNotSpent = assertionToCheck "A reference input UTxO" - \{ referenceInput } -> do - let - assertionFailure :: ContractAssertionFailure - assertionFailure = CustomFailure "Reference input has been spent" - utxos <- lift $ liftedM "Failed to get UTxOs from wallet" getWalletUtxos - assertContract assertionFailure do - Map.member referenceInput utxos - -checks :: Array (ContractCheck ContractResult) -checks = - [ assertTxContainsReferenceInput - , assertReferenceInputNotSpent - ] diff --git a/examples/PlutusV2/ReferenceInputsAndScripts.purs b/examples/PlutusV2/ReferenceInputsAndScripts.purs index 21bab6eff3..6c55b4b041 100644 --- a/examples/PlutusV2/ReferenceInputsAndScripts.purs +++ b/examples/PlutusV2/ReferenceInputsAndScripts.purs @@ -2,61 +2,51 @@ module Ctl.Examples.PlutusV2.ReferenceInputsAndScripts ( contract , example , main - , mintAlwaysMintsV2ToTheScript ) where import Contract.Prelude +import Cardano.Transaction.Builder + ( CredentialWitness(PlutusScriptCredential) + , OutputWitness(PlutusScriptOutput) + , RefInputAction(ReferenceInput) + , ScriptWitness(ScriptReference) + , TransactionBuilderStep(MintAsset, SpendOutput, Pay) + ) +import Cardano.Types + ( Credential(ScriptHashCredential) + , OutputDatum(OutputDatum) + , ScriptHash + , TransactionOutput(TransactionOutput) + ) import Cardano.Types.BigNum as BigNum -import Cardano.Types.Credential (Credential(ScriptHashCredential)) import Cardano.Types.Int as Int -import Cardano.Types.Mint as Mint +import Cardano.Types.PlutusData as PlutusData import Cardano.Types.PlutusScript as PlutusScript -import Cardano.Types.TransactionUnspentOutput - ( TransactionUnspentOutput(TransactionUnspentOutput) - ) -import Contract.Address (PaymentPubKeyHash, StakePubKeyHash, mkAddress) +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction +import Contract.Address (mkAddress) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') -import Contract.Monad - ( Contract - , launchAff_ - , liftContractM - , liftedM - , runContract - ) -import Contract.PlutusData (unitDatum, unitRedeemer) -import Contract.ScriptLookups as Lookups -import Contract.Scripts (PlutusScript, Validator, ValidatorHash) +import Contract.Monad (Contract, launchAff_, liftContractM, runContract) +import Contract.Scripts (PlutusScript) import Contract.Transaction ( ScriptRef(PlutusScriptRef) , TransactionHash - , TransactionInput(TransactionInput) , TransactionOutput , awaitTxConfirmed - , submitTxFromConstraints + , lookupTxHash + , submitTxFromBuildPlan ) -import Contract.TxConstraints - ( DatumPresence(DatumWitness) - , InputWithScriptRef(RefInput) - , TxConstraints - ) -import Contract.TxConstraints as Constraints import Contract.Utxos (utxosAt) import Contract.Value (TokenName, Value) import Contract.Value as Value -import Contract.Wallet - ( getWalletAddresses - , ownPaymentPubKeyHashes - , ownStakePubKeyHashes - ) import Ctl.Examples.Helpers (mkAssetName) as Helpers -import Ctl.Examples.PlutusV2.Scripts.AlwaysMints - ( alwaysMintsPolicyScriptV2 - ) +import Ctl.Examples.PlutusV2.Scripts.AlwaysMints (alwaysMintsPolicyScriptV2) import Ctl.Examples.PlutusV2.Scripts.AlwaysSucceeds (alwaysSucceedsScriptV2) -import Data.Array (head) -import Data.Map (toUnfoldable) as Map +import Data.Array (find, head) as Array +import Data.Map (empty, toUnfoldable) as Map +import Effect.Exception (error) main :: Effect Unit main = example testnetNamiConfig @@ -72,7 +62,7 @@ contract = do mintsScript <- alwaysMintsPolicyScriptV2 tokenName <- Helpers.mkAssetName "TheToken" let - vhash :: ValidatorHash + vhash :: ScriptHash vhash = PlutusScript.hash validator validatorRef :: ScriptRef @@ -89,31 +79,35 @@ contract = do tokenName payToAlwaysSucceedsAndCreateScriptRefOutput - :: ValidatorHash -> ScriptRef -> ScriptRef -> Contract TransactionHash + :: ScriptHash -> ScriptRef -> ScriptRef -> Contract TransactionHash payToAlwaysSucceedsAndCreateScriptRefOutput vhash validatorRef mpRef = do - pkh <- liftedM "Failed to get own PKH" $ head <$> ownPaymentPubKeyHashes - skh <- join <<< head <$> ownStakePubKeyHashes + scriptAddress <- mkAddress (wrap $ ScriptHashCredential vhash) Nothing let value :: Value value = Value.lovelaceValueOf (BigNum.fromInt 2_000_000) - - createOutputWithScriptRef :: ScriptRef -> TxConstraints - createOutputWithScriptRef scriptRef = - mustPayToPubKeyStakeAddressWithScriptRef pkh skh scriptRef value - - constraints :: TxConstraints - constraints = - Constraints.mustPayToScript vhash unitDatum DatumWitness value - <> createOutputWithScriptRef validatorRef - <> createOutputWithScriptRef mpRef - - lookups :: Lookups.ScriptLookups - lookups = mempty - - submitTxFromConstraints lookups constraints + Transaction.hash <$> submitTxFromBuildPlan Map.empty mempty + [ Pay $ TransactionOutput + { address: scriptAddress + , amount: value + , datum: Just $ OutputDatum PlutusData.unit + , scriptRef: Just validatorRef + } + , Pay $ TransactionOutput + { address: scriptAddress + , amount: value + , datum: Just $ OutputDatum PlutusData.unit + , scriptRef: Just mpRef + } + , Pay $ TransactionOutput + { address: scriptAddress + , amount: value + , datum: Just $ OutputDatum PlutusData.unit + , scriptRef: Nothing + } + ] spendFromAlwaysSucceeds - :: ValidatorHash + :: ScriptHash -> TransactionHash -> PlutusScript -> PlutusScript @@ -121,88 +115,49 @@ spendFromAlwaysSucceeds -> Contract Unit spendFromAlwaysSucceeds vhash txId validator mp tokenName = do scriptAddress <- mkAddress (wrap $ ScriptHashCredential vhash) Nothing - ownAddress <- liftedM "Failed to get own address" $ head <$> - getWalletAddresses - (utxos :: Array _) <- Map.toUnfoldable <$> utxosAt ownAddress scriptAddressUtxos <- utxosAt scriptAddress + utxos <- utxosAt scriptAddress + utxo <- + liftM + ( error + ( "The id " + <> show txId + <> " does not have output locked at: " + <> show scriptAddress + ) + ) + $ Array.head (lookupTxHash txId utxos) - txInput /\ _ <- - liftContractM "Could not find unspent output locked at script address" - $ find hasTransactionId (Map.toUnfoldable scriptAddressUtxos :: Array _) - - refValidatorInput /\ refValidatorOutput <- + refValidatorInput /\ _ <- liftContractM "Could not find unspent output containing ref validator" - $ find (hasRefPlutusScript validator) utxos + $ Array.find (hasRefPlutusScript validator) + $ Map.toUnfoldable utxos - refMpInput /\ refMpOutput <- + refMpInput /\ _ <- liftContractM "Could not find unspent output containing ref minting policy" - $ find (hasRefPlutusScript mp) utxos + $ Array.find (hasRefPlutusScript mp) + $ Map.toUnfoldable utxos let mph = PlutusScript.hash mp - - constraints :: TxConstraints - constraints = mconcat - [ Constraints.mustSpendScriptOutputUsingScriptRef txInput unitRedeemer - ( RefInput $ TransactionUnspentOutput - { input: refValidatorInput, output: refValidatorOutput } - ) - - , Constraints.mustMintCurrencyUsingScriptRef mph tokenName (Int.fromInt 1) - ( RefInput $ TransactionUnspentOutput - { input: refMpInput, output: refMpOutput } - ) - ] - - lookups :: Lookups.ScriptLookups - lookups = Lookups.unspentOutputs scriptAddressUtxos - - spendTxId <- submitTxFromConstraints lookups constraints - awaitTxConfirmed spendTxId + spendTx <- submitTxFromBuildPlan scriptAddressUtxos mempty + [ SpendOutput + utxo + ( Just + $ PlutusScriptOutput + (ScriptReference refValidatorInput ReferenceInput) + RedeemerDatum.unit + Nothing + ) + , MintAsset mph tokenName (Int.fromInt 1) + $ PlutusScriptCredential (ScriptReference refMpInput ReferenceInput) + RedeemerDatum.unit + ] + awaitTxConfirmed $ Transaction.hash spendTx logInfo' "Successfully spent locked values and minted tokens." where - hasTransactionId :: TransactionInput /\ _ -> Boolean - hasTransactionId (TransactionInput txInput /\ _) = - txInput.transactionId == txId hasRefPlutusScript :: PlutusScript -> _ /\ TransactionOutput -> Boolean hasRefPlutusScript plutusScript (_ /\ txOutput) = (unwrap txOutput).scriptRef == Just (PlutusScriptRef plutusScript) - -mustPayToPubKeyStakeAddressWithScriptRef - :: forall (i :: Type) (o :: Type) - . PaymentPubKeyHash - -> Maybe StakePubKeyHash - -> ScriptRef - -> Value - -> TxConstraints -mustPayToPubKeyStakeAddressWithScriptRef pkh Nothing = - Constraints.mustPayToPubKeyWithScriptRef pkh -mustPayToPubKeyStakeAddressWithScriptRef pkh (Just skh) = - Constraints.mustPayToPubKeyAddressWithScriptRef pkh skh - -mintAlwaysMintsV2ToTheScript - :: TokenName -> Validator -> Int -> Contract Unit -mintAlwaysMintsV2ToTheScript tokenName validator sum = do - mp <- alwaysMintsPolicyScriptV2 - let cs = PlutusScript.hash mp - - let - vhash = PlutusScript.hash validator - - constraints :: Constraints.TxConstraints - constraints = mconcat - [ Constraints.mustMintValue - $ Mint.singleton cs tokenName - $ Int.fromInt sum - , Constraints.mustPayToScript vhash unitDatum Constraints.DatumWitness - $ Value.singleton cs tokenName - $ BigNum.fromInt sum - ] - - lookups :: Lookups.ScriptLookups - lookups = Lookups.plutusMintingPolicy mp - - txHash <- submitTxFromConstraints lookups constraints - void $ awaitTxConfirmed txHash diff --git a/examples/PlutusV2/ReferenceScripts.purs b/examples/PlutusV2/ReferenceScripts.purs deleted file mode 100644 index e854092304..0000000000 --- a/examples/PlutusV2/ReferenceScripts.purs +++ /dev/null @@ -1,125 +0,0 @@ -module Ctl.Examples.PlutusV2.ReferenceScripts - ( main - , example - , contract - ) where - -import Contract.Prelude - -import Cardano.Types - ( Credential(ScriptHashCredential) - , TransactionUnspentOutput(TransactionUnspentOutput) - ) -import Cardano.Types.BigNum as BigNum -import Contract.Address (mkAddress) -import Contract.Config (ContractParams, testnetNamiConfig) -import Contract.Credential (Credential(PubKeyHashCredential)) -import Contract.Log (logInfo') -import Contract.Monad (Contract, launchAff_, liftContractM, runContract) -import Contract.PlutusData (unitDatum, unitRedeemer) -import Contract.ScriptLookups as Lookups -import Contract.Scripts (ValidatorHash, validatorHash) -import Contract.Transaction - ( ScriptRef(PlutusScriptRef) - , TransactionHash - , TransactionInput(TransactionInput) - , awaitTxConfirmed - , submitTxFromConstraints - ) -import Contract.TxConstraints - ( DatumPresence(DatumWitness) - , InputWithScriptRef(SpendInput) - , TxConstraints - ) -import Contract.TxConstraints as Constraints -import Contract.Utxos (utxosAt) -import Contract.Value (lovelaceValueOf) as Value -import Contract.Wallet (ownStakePubKeyHashes) -import Ctl.Examples.PlutusV2.Scripts.AlwaysSucceeds (alwaysSucceedsScriptV2) -import Data.Array (head) -import Data.Map (toUnfoldable) as Map - -main :: Effect Unit -main = example testnetNamiConfig - -example :: ContractParams -> Effect Unit -example cfg = launchAff_ do - runContract cfg contract - --- NOTE: If you are looking for an example of the most common case of --- using reference scripts by referencing an output and not spending it, --- you likely need to look at the example in `ReferenceInputsAndScripts.purs`. -contract :: Contract Unit -contract = do - logInfo' "Running Examples.PlutusV2.ReferenceScripts" - validator <- alwaysSucceedsScriptV2 - let - vhash :: ValidatorHash - vhash = validatorHash validator - - scriptRef :: ScriptRef - scriptRef = PlutusScriptRef validator - - logInfo' "Attempt to lock value" - txId <- payWithScriptRefToAlwaysSucceeds vhash scriptRef - awaitTxConfirmed txId - logInfo' "Tx submitted successfully, Try to spend locked values" - spendFromAlwaysSucceeds vhash txId - -payWithScriptRefToAlwaysSucceeds - :: ValidatorHash -> ScriptRef -> Contract TransactionHash -payWithScriptRefToAlwaysSucceeds vhash scriptRef = do - -- Send to own stake credential. This is used to test - -- `mustPayToScriptAddressWithScriptRef` - mbStakeKeyHash <- join <<< head <$> ownStakePubKeyHashes - let - constraints :: TxConstraints - constraints = - case mbStakeKeyHash of - Nothing -> - Constraints.mustPayToScriptWithScriptRef vhash unitDatum DatumWitness - scriptRef - (Value.lovelaceValueOf $ BigNum.fromInt 2_000_000) - Just stakeKeyHash -> - Constraints.mustPayToScriptAddressWithScriptRef - vhash - (PubKeyHashCredential $ unwrap stakeKeyHash) - unitDatum - DatumWitness - scriptRef - (Value.lovelaceValueOf $ BigNum.fromInt 2_000_000) - - lookups :: Lookups.ScriptLookups - lookups = mempty - - submitTxFromConstraints lookups constraints - -spendFromAlwaysSucceeds :: ValidatorHash -> TransactionHash -> Contract Unit -spendFromAlwaysSucceeds vhash txId = do - -- Send to own stake credential. This is used to test - -- `mustPayToScriptAddressWithScriptRef` - mbStakeKeyHash <- join <<< head <$> ownStakePubKeyHashes - scriptAddress <- mkAddress (wrap $ ScriptHashCredential $ vhash) - (wrap <<< PubKeyHashCredential <<< unwrap <$> mbStakeKeyHash) - utxos <- utxosAt scriptAddress - - input /\ output <- - liftContractM "Could not find unspent output locked at script address" - $ find hasTransactionId (Map.toUnfoldable utxos :: Array _) - - let - constraints :: TxConstraints - constraints = - Constraints.mustSpendScriptOutputUsingScriptRef input unitRedeemer - (SpendInput $ TransactionUnspentOutput { input, output }) - - lookups :: Lookups.ScriptLookups - lookups = mempty - - spendTxId <- submitTxFromConstraints lookups constraints - awaitTxConfirmed spendTxId - logInfo' "Successfully spent locked values." - where - hasTransactionId :: TransactionInput /\ _ -> Boolean - hasTransactionId (TransactionInput tx /\ _) = - tx.transactionId == txId diff --git a/test/Plutip/Contract.purs b/test/Plutip/Contract.purs index 0a5552258b..26a197d986 100644 --- a/test/Plutip/Contract.purs +++ b/test/Plutip/Contract.purs @@ -147,11 +147,9 @@ import Ctl.Examples.OneShotMinting (contract) as OneShotMinting import Ctl.Examples.PaysWithDatum (contract) as PaysWithDatum import Ctl.Examples.PlutusV2.InlineDatum as InlineDatum import Ctl.Examples.PlutusV2.OneShotMinting (contract) as OneShotMintingV2 -import Ctl.Examples.PlutusV2.ReferenceInputs (contract) as ReferenceInputs import Ctl.Examples.PlutusV2.ReferenceInputsAndScripts ( contract ) as ReferenceInputsAndScripts -import Ctl.Examples.PlutusV2.ReferenceScripts (contract) as ReferenceScripts import Ctl.Examples.PlutusV2.Scripts.AlwaysMints (alwaysMintsPolicyScriptV2) import Ctl.Examples.PlutusV2.Scripts.AlwaysSucceeds (alwaysSucceedsScriptV2) import Ctl.Examples.Schnorr as Schnorr @@ -1556,49 +1554,17 @@ suite = do logInfo' "Try to spend locked values" AlwaysFails.spendFromAlwaysFails vhash validator txId - group "CIP-33 Reference Scripts" do - test "Use reference scripts for spending" do - let - distribution :: InitialUTxOs - distribution = - [ BigNum.fromInt 5_000_000 - , BigNum.fromInt 50_000_000 - ] - withWallets distribution \alice -> - withKeyWallet alice ReferenceScripts.contract - - test - "Use reference scripts for spending (with Base Address, testing `mustPayToScriptAddressWithScriptRef`)" + group "CIP-33 Reference Scripts + CIP-31 Reference Inputs" do + test "Use reference inputs and reference scripts at the same time" do let - distribution :: InitialUTxOsWithStakeKey - distribution = withStakeKey privateStakeKey + distribution :: InitialUTxOs + distribution = [ BigNum.fromInt 5_000_000 , BigNum.fromInt 50_000_000 ] withWallets distribution \alice -> - withKeyWallet alice ReferenceScripts.contract - - group "CIP-31 Reference Inputs" do - test "Use reference inputs" do - let - distribution :: InitialUTxOs - distribution = - [ BigNum.fromInt 5_000_000 - , BigNum.fromInt 50_000_000 - ] - withWallets distribution \alice -> - withKeyWallet alice ReferenceInputs.contract - - test "Use reference inputs and reference scripts at the same time" do - let - distribution :: InitialUTxOs - distribution = - [ BigNum.fromInt 5_000_000 - , BigNum.fromInt 50_000_000 - ] - withWallets distribution \alice -> - withKeyWallet alice ReferenceInputsAndScripts.contract + withKeyWallet alice ReferenceInputsAndScripts.contract test "One-Shot Minting example" do let From 877b2c3ce45fbec881ba042072357fb2aa784b82 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Thu, 18 Jul 2024 21:35:22 +0400 Subject: [PATCH 42/52] Update the docs --- CHANGELOG.md | 22 +- doc/babbage-features.md | 31 +-- doc/balancing.md | 6 +- doc/development.md | 10 + doc/getting-started.md | 53 +++-- doc/plutus-comparison.md | 50 ++--- doc/side-by-side-ctl-plutus-comparison.md | 209 +------------------ doc/test-plan.md | 243 ---------------------- src/Contract/Config.purs | 16 +- src/Contract/Constraints.purs | 176 ---------------- 10 files changed, 92 insertions(+), 724 deletions(-) delete mode 100644 doc/test-plan.md delete mode 100644 src/Contract/Constraints.purs diff --git a/CHANGELOG.md b/CHANGELOG.md index d4fa8c2f66..b5de6bcc96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - [[Unreleased]](#unreleased) + - [Deprecated](#deprecated) - [Added](#added) - [Removed](#removed) - [Changed](#changed) @@ -69,18 +70,31 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## [Unreleased] +### Deprecated + +- **IMPORTANT** Constraints interface (`Contract.TxConstraints`) has been deprecated and will be removed in a future version. Please use [`purescript-cardano-transaction-builder`](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder) for any new contracts. + ### Added -- Ability to spend native script outputs using a reference input that contains an inline native script. +- `Contract.Transaction.buildTx :: Array TransactionBuilderStep -> Contract Transaction` that provides a `Contract`-based interface for the [new transaction builder](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder). +- `submitTxFromBuildPlan :: UtxoMap -> BalanceTxConstraintsBuilder -> Array TransactionBuilderStep -> Contract Transaction` - a convenience function that executes the whole transaction creation pipeline starting from a build plan for [the new transaction builder](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder). +- `Contract.ClientError.pprintClientError` to provide readable error reports. +- ### Removed -- `Contract.Transaction.submitTxFromConstraintsReturningFee` -- `Contract.Transaction` lens values -- `Contract.Scripts.applyArgs` - use `Cardano.Plutus.ApplyArgs.applyArgs` from [purescript-uplc-apply-args](https://github.com/mlabs-haskell/purescript-uplc-apply-args) +- **IMPORTANT** `UnbalancedTx` type has been removed. This change was motivated by the fact that `UnbalancedTx` existed simply to tie together transaction building and balancing by keeping extra context. Now that transaction builder is placed in [its own package](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder), there is no more need in `UnbalancedTx`, that is not used with the new builder. +- **IMPORTANT** `Contract.Scripts.applyArgs` - use `Cardano.Plutus.ApplyArgs.applyArgs` from [purescript-uplc-apply-args](https://github.com/mlabs-haskell/purescript-uplc-apply-args) +- **IMPORTANT** `balanceTxWithConstraints` - use `balanceTx` +- `Contract.Transaction.submitTxFromConstraintsReturningFee` - too niche case to be allowed in the public API. +- `Contract.Transaction` lens values. ### Changed +- `Contract.Transaction.mkUnbalancedTx` now returns a tuple: a transaction and its used UTxOs. +- `Contract.Transaction.balanceTx` accepts two extra argument: a list of used UTxOs (set to `Data.Map.empty` if none of them are coming from the outside of the wallet) and balancer constraints (set to `mempty` if not needed) +- Default synchronization parameters: all [wallet <-> query layer synchronization primitives](./doc/query-layer.md) are now off by default. The reason is that the runtime overhead made the users unhappy and it was not worth it for most of the users. If your dApp sends transactions in quick succession, consider enabling the synchronization again. + ### Fixed ## [v8.0.0] diff --git a/doc/babbage-features.md b/doc/babbage-features.md index 02a32211a5..1cfac81e77 100644 --- a/doc/babbage-features.md +++ b/doc/babbage-features.md @@ -6,48 +6,29 @@ This document is a reference/explainer for the new CTL APIs introduced for Babba -- [Reference Inputs](#reference-inputs) -- [Reference Scripts](#reference-scripts) +- [Reference Inputs & Reference Scripts](#reference-inputs--reference-scripts) - [Inline Data](#inline-data) - [Collateral Output](#collateral-output) -## Reference Inputs +## Reference Inputs & Reference Scripts [Reference inputs](https://cips.cardano.org/cip/CIP-0031#reference-inputs) allow looking at an output without spending it in Plutus scripts. -There are two ways to use an input as a reference in the constraints API: - -1. via `mustReferenceOutput`, which allows Plutus scripts to access the information (e.g. datum, locked value) contained in the output. - -[Usage example](../examples/PlutusV2/ReferenceInputs.purs) - -2. by providing constraints which accept a value of the type `InputWithScriptRef` with the `RefInput` constructor. These allow scripts (validating or minting) to be reused by reference between multiple transactions without including them in those transactions, explained further in [Reference Scripts](#reference-scripts). - -[Usage example](../examples/PlutusV2/ReferenceInputsAndScripts.purs) - -## Reference Scripts - [Reference Scripts](https://cips.cardano.org/cip/CIP-0033) allows the use of scripts without attaching them to the transaction (and using a reference instead). -Reference scripts can be utilized in CTL by first creating a reference point for the script to be used later via `mustPayToScriptWithScriptRef` (or its variants). +Reference scripts can be utilized in CTL by first creating a UTxO containing the script to be used later. -This constraint utilises a new `ScriptRef` type that includes either a native script or a Plutus script. - -Then, `mustSpendScriptOutputUsingScriptRef` (or its variants) can be used to use a reference script. It accepts a value of type `InputWithScriptRef` that specifies whether the UTxO with the reference script should be spent or referenced. - -[Usage example](../examples/PlutusV2/ReferenceScripts.purs) +[Usage example](../examples/PlutusV2/ReferenceInputsAndScripts.purs) ## Inline Data [CIP-32](https://cips.cardano.org/cip/CIP-0032) introduces the inline data feature that allows storing datum values directly in transaction outputs, instead of just the hashes. -In CTL, alternating between datum storage options can be achieved by specifying a `DatumPresence` value with constraints that accept it, like `mustPayToPubKeyWithDatum`. - -[Usage example](../examples/PlutusV2/InlineDatum.purs) - ## Collateral Output [CIP-40](https://cips.cardano.org/cip/CIP-0040) introduces explicit collateral output. On validation failure, previously the entire collateral was consumed. Now, if excess collateral is supplied, even with native assets, the surplus can be returned on validation failure. Collateral output is automatically added to transactions in CTL. To trigger a collateral return, the `mustNotBeValid` constraint should be explicitly specified, otherwise a script error would be detected earlier and the transaction will not be sent. + +[Usage example](../examples/Lose7Ada.purs) diff --git a/doc/balancing.md b/doc/balancing.md index 961e357a4a..f3681101ee 100644 --- a/doc/balancing.md +++ b/doc/balancing.md @@ -1,7 +1,7 @@ -- [Configuring balancing process](#configuring-balancing-process) +- [Configuring the balancing process](#configuring-the-balancing-process) - [Balancer constraints](#balancer-constraints) - [Concurrent spending](#concurrent-spending) - [Balancing a Tx for other wallet](#balancing-a-tx-for-other-wallet) @@ -10,7 +10,7 @@ -# Configuring balancing process +# Configuring the balancing process Transaction balancing in Cardano is the process of finding a set of inputs and outputs that that sum up to zero, covering all the required fees for the transaction to be valid. @@ -37,7 +37,7 @@ Setting `mustUseUtxosAtAddress`, `mustSendChangeToAddress` and `mustUseCollatera ## Synchronization -Before balancing, CTL tries to synchronize the wallet state with the query layer, i.e. waits until all UTxOs that the wallet returns are visible in the query layer. Thus the situation when the query layer refuses to validate a Tx (either during ex-units evaluation or on Tx submission) is only possible due to a rollback or a synchronization timeout. Please see [our docs for query layer synchronization](./query-layers.md). +It's possible to make CTL try to synchronize the wallet state with the query layer, i.e. wait until all UTxOs that the wallet returns are visible in the query layer. Thus the situation when the query layer refuses to validate a Tx (either during ex-units evaluation or on Tx submission) is only possible due to a rollback or a synchronization timeout. Please see [our docs for query layer synchronization](./query-layers.md). ## Balancing process limitations diff --git a/doc/development.md b/doc/development.md index 6ffc51091b..ef2af05759 100644 --- a/doc/development.md +++ b/doc/development.md @@ -22,6 +22,7 @@ This document outlines development workflows for CTL itself. You may also wish t - [JS](#js) - [Switching development networks](#switching-development-networks) - [Maintaining the template](#maintaining-the-template) +- [Updating the template](#updating-the-template) @@ -148,4 +149,13 @@ Set new `network.name` and `network.magic` in `runtime.nix`. Also see [Changing [The template](../templates/ctl-scaffold/) must be kept up-to-date with the repo. Although there are some checks for common problems in CI, it's still possible to forget to update the `package-lock.json` file. +## Updating the template + +1. Update the revision of CTL in the template's `flake.nix` +2. Update the npm packages in the `package.json` (if needed) +3. Run `npm i` to update the lockfile (if there are NPM dependency version changes) +4. Update the revisions in the template's `packages.dhall` (CTL version must match the one in `flake.nix`) +5. Run `spago2nix generate` +6. Run `nix develop` + [This helper script](../scripts/template-check.sh) can be used to make sure the template can be initialized properly from a given revision. diff --git a/doc/getting-started.md b/doc/getting-started.md index f758fa8472..41b1de8099 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -16,11 +16,6 @@ This guide will help you get started writing contracts with CTL. Please also see - [Executing contracts and the `ContractEnv`](#executing-contracts-and-the-contractenv) - [Making the `ContractEnv`](#making-the-contractenv) - [Building and submitting transactions](#building-and-submitting-transactions) - - [Using compiled scripts](#using-compiled-scripts) -- [Testing](#testing) - - [Without a light wallet](#without-a-light-wallet) - - [With a light wallet](#with-a-light-wallet) - - [Plutip integration](#plutip-integration) @@ -140,9 +135,13 @@ main = Contract.Monad.launchAff_ do -- we re-export this for you , kupoConfig: defaultKupoServerConfig } , networkId: TestnetId - , logLevel: Trace , walletSpec: Just ConnectToNami + , logLevel: Trace , customLogger: Nothing + , suppressLogs: false + , hooks: emptyHooks + , timeParams: defaultTimeParams + , synchronizationParams: defaultSynchronizationParams } runContract config someContract @@ -167,49 +166,49 @@ customOgmiosWsConfig = Unlike PAB, CTL obscures less of the build-balance-sign-submit pipeline for transactions and most of the steps are called individually. The general workflow in CTL is similar to the following: -- Build a transaction using `Contract.ScriptLookups`, `Contract.TxConstraints` and `Contract.BalanceTxConstraints` (it is also possible to directly build a `Transaction` if you require even greater low-level control over the process, although we recommend the constraints/lookups approach for most users): +- Build a transaction using [`cardano-transaction-builder`](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder): ```purescript contract = do let - constraints :: TxConstraints Unit Unit - constraints = - TxConstraints.mustPayToScript vhash unitDatum - (Value.lovelaceValueOf $ BigInt.fromInt 2_000_000) - - lookups :: ScriptLookups PlutusData - lookups = ScriptLookups.validator validator - - balanceTxConstraints :: BalanceTxConstraints.BalanceTxConstraintsBuilder - balanceTxConstraints = - BalanceTxConstraints.mustUseUtxosAtAddress address - <> BalanceTxConstraints.mustSendChangeToAddress address - <> BalanceTxConstraints.mustNotSpendUtxoWithOutRef nonSpendableOref - - -- `liftedE` will throw a runtime exception on `Left`s - unbalancedTx <- liftedE $ Lookups.mkUnbalancedTx lookups constraints + plan = + [ Pay $ TransactionOutput + { address: address + , amount: Value.lovelaceValueOf $ BigNum.fromInt 1_000_000 + , datum: Just $ OutputDatumHash $ hashPlutusData PlutusData.unit + , scriptRef: Nothing + } + ] + unbalancedTx <- buildTx plan ... ``` -- Balance it using `Contract.Transaction.balanceTx` (or `Contract.Transaction.balanceTxWithConstraints` if you need to adjust the balancer behaviour) and then sign it using `signTransaction`: +- Balance it using `Contract.Transaction.balanceTx`, and then sign it using `signTransaction`: ```purescript contract = do ... + let + balanceTxConstraints :: BalanceTxConstraints.BalanceTxConstraintsBuilder + balanceTxConstraints = + BalanceTxConstraints.mustUseUtxosAtAddress address + <> BalanceTxConstraints.mustSendChangeToAddress address + <> BalanceTxConstraints.mustNotSpendUtxoWithOutRef nonSpendableOref -- `liftedE` will throw a runtime exception on `Left`s balancedTx <- - liftedE $ balanceTxWithConstraints unbalancedTx balanceTxConstraints + balanceTx unbalancedTx usedUtxos balanceTxConstraints balancedSignedTx <- signTransaction balancedTx ... ``` -- Submit using `Contract.Transaction.submit`: +- Submit using `Contract.Transaction.submit` and await for confirmation using `awaitTxConfirmed`: ```purescript contract = do ... txId <- submit balancedSignedTx + awaitTxConfirmed txId logInfo' $ "Tx ID: " <> show txId - ``` +``` ### Using compiled scripts diff --git a/doc/plutus-comparison.md b/doc/plutus-comparison.md index 603df9dc82..65fa249b4c 100644 --- a/doc/plutus-comparison.md +++ b/doc/plutus-comparison.md @@ -10,10 +10,10 @@ This document outlines the core differences between CTL and Plutus Application B - [Library vs. process](#library-vs-process) - [The `Contract` type](#the-contract-type) - [API differences](#api-differences) - - [Transaction manipulation API](#transaction-manipulation-api) - - [Constraints and lookups](#constraints-and-lookups) - - [Babbage-era constraints](#babbage-era-constraints) - - [Typed scripts](#typed-scripts) + - [DEPRECATION WARNING](#deprecation-warning) + - [**DEPRECATED** Transaction manipulation API](#deprecated-transaction-manipulation-api) + - [**DEPRECATED** Constraints and lookups](#deprecated-constraints-and-lookups) + - [**DEPRECATED** Babbage-era constraints](#deprecated-babbage-era-constraints) - [Working with scripts](#working-with-scripts) - [Using scripts from the frontend](#using-scripts-from-the-frontend) - [Applying arguments to parameterized scripts](#applying-arguments-to-parameterized-scripts) @@ -25,7 +25,7 @@ This document outlines the core differences between CTL and Plutus Application B Unlike contracts written for PAB, which are compiled to a single process, CTL is a library. CTL itself can be [imported as a Purescript library](./ctl-as-dependency.md) and offchain contracts written in CTL compile to Javascript that can be run in the browser or NodeJS. Accordingly, there is no need to activate endpoints in CTL -- contracts are executed by calling effectful functions written using the library. This distinction has influenced our adaption of Plutus' `Contract` type, as outlined [below](#the-contract-type). -Note, however, that CTL still requires a number of runtime dependencies. In some respects, this is similar to PAB, which also needs to communicate with plutus-chain-index and a running node. Please see the [documentation](./runtime.md) for more details on CTL's runtime. +Note, however, that CTL still requires a number of runtime dependencies. In some respects, this is similar to PAB, which also needs to communicate with plutus-chain-index and a running node. Please see the [runtime documentation](./runtime.md) for more details. ### The `Contract` type @@ -66,13 +66,17 @@ Finally, CTL's `Contract` is not parameterized by an error type as in Plutus. `C ## API differences -### Transaction manipulation API +### DEPRECATION WARNING + +The original constraints interface has been deprecated and will be removed. Use [`cardano-transaction-builder`](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder) for any new code. + +### **DEPRECATED** Transaction manipulation API | Plutus | CTL | | --------------------------- | ----------------------------- | | `submitTxConstraintsWith` | `submitTxFromConstraints` | -### Constraints and lookups +### **DEPRECATED** Constraints and lookups CTL has adapted Plutus' Alonzo-era constraints/lookups interface fairly closely and it functions largely the same. One key difference is that CTL does not, and cannot, have the notion of a "current" script. All scripts must be explicitly provided to CTL (serialized as CBOR, see below). This has led us to depart from Plutus' naming conventions for certain constraints/lookups: @@ -87,7 +91,7 @@ CTL has adapted Plutus' Alonzo-era constraints/lookups interface fairly closely Additionally, we implement `NativeScript` (multi-signature phase-1 script) support, which is not covered by Plutus. -#### Babbage-era constraints +#### **DEPRECATED** Babbage-era constraints CIPs 0031-0033 brought several improvements to Plutus and are supported from the Babbage era onwards: @@ -97,36 +101,6 @@ CIPs 0031-0033 brought several improvements to Plutus and are supported from the CTL has upgraded its constraints interface to work with these new features. At the time of writing, however, `plutus-apps` has not yet upgraded their constraints/lookups interface to support these new features. This means a direct comparison between `plutus-apps` and CTL regarding Babbage-era features is not currently possible. It also implies that, moving forward, CTL's constraints implementation will increasingly no longer match that of `plutus-apps`' to the same degree. -### Typed scripts - -Another difference between Plutus and CTL is our implementation of typed scripts. Recall that Plutus' `ValidatorTypes` class: - -```haskell -class ValidatorTypes (a :: Type) where - type RedeemerType a :: Type - type DatumType a :: Type - - type instance RedeemerType a = () - type instance DatumType a = () -``` - -Purescript lacks most of Haskell's more advanced type-level faculties, including type/data families. Purescript does, however, support functional dependencies, allowing us to encode `ValidatorTypes` as follows: - -```purescript -class ValidatorTypes :: Type -> Type -> Type -> Constraint -class - ( DatumType validator datum - , RedeemerType validator redeemer - ) <= - ValidatorTypes validator datum redeemer - -class DatumType :: Type -> Type -> Constraint -class DatumType validator datum | validator -> datum - -class RedeemerType :: Type -> Type -> Constraint -class RedeemerType validator redeemer | validator -> redeemer -``` - ### Working with scripts #### Using scripts from the frontend diff --git a/doc/side-by-side-ctl-plutus-comparison.md b/doc/side-by-side-ctl-plutus-comparison.md index 61fea0b9ad..5bf75b70a2 100644 --- a/doc/side-by-side-ctl-plutus-comparison.md +++ b/doc/side-by-side-ctl-plutus-comparison.md @@ -11,10 +11,7 @@ both of them. - [About `Contract` in CTL and Plutus](#about-contract-in-ctl-and-plutus) -- [Contract comparison](#contract-comparison) - - [MustPayTo functions](#mustpayto-functions) - - [The `give` contract](#the-give-contract) - - [The `grab` contract](#the-grab-contract) +- [Contract code comparison](#contract-code-comparison) @@ -62,206 +59,6 @@ effectful actions are defined directly in terms of those provided by `Aff`, logging is provided by a configurable logger stored in `ContractEnv`. -## Contract comparison - -We can now begin to compare contracts. - -The most famous contracts are those contained as part of -the [Plutus pioneer program](https://plutus-pioneer-program.readthedocs.io/en/latest/pioneer/week2.html) in week2. -Both of them use the same on-chain contract that allows an arbitrary -datum and arbitrary redeemer. - -### MustPayTo functions - - -In the case of Plutus `Contract`, we use the function -`mustPayToOtherScript`, according to Plutus ledger, is defined as: - -```Haskell -{-# INLINABLE mustPayToOtherScript #-} --- | @mustPayToOtherScript vh d v@ locks the value @v@ with the given script --- hash @vh@ alonside a datum @d@. --- --- If used in 'Ledger.Constraints.OffChain', this constraint creates a script --- output with @vh@, @d@ and @v@ and adds @d@ in the transaction's datum --- witness set. --- --- If used in 'Ledger.Constraints.OnChain', this constraint verifies that @d@ is --- part of the datum witness set and that the script transaction output with --- @vh@, @d@ and @v@ is part of the transaction's outputs. -mustPayToOtherScript - :: forall i o. ValidatorHash -> Datum -> Value -> TxConstraints i o -``` - -While in the case of CTL we would use `mustPayToScript`: - -```PureScript --- | Note that CTL does not have explicit equivalents of Plutus' --- | `mustPayToTheScript` or `mustPayToOtherScript`, as we have no notion --- | of a "current" script. Thus, we have the single constraint --- | `mustPayToScript`, and all scripts must be explicitly provided to build --- | the transaction. -mustPayToScript - :: forall (i :: Type) (o :: Type) - . ValidatorHash - -> Datum - -> Value - -> TxConstraints i o -``` - -### The `give` contract - -Now we can write and compare the `give` contract. -This contract takes and amount of Ada from our wallet -an lock it to the script that validates any -transactions. - -```Haskell --- Haskell -give :: - forall (w :: Type) (s :: Type) (e :: Type). - AsContractError e => - Integer -> Contract w s e () -give amount = do - let tx = mustPayToOtherScript vHash (Datum $ Constr 0 []) - $ Ada.lovelaceValueOf amount - ledgerTx <- submitTx tx - void $ awaitTxConfirmed $ txId ledgerTx - logInfo @String $ printf "made a gift of %d lovelace" amount -``` - -We include some of the imports for the PureScript -contract. - -```PureScript --- PureScript -import Contract.PlutusData (PlutusData, unitDatum) -import Contract.ScriptLookups as Lookups -import Contract.TxConstraints as Constraints -import Contract.Prelude -import Data.BigInt as BigInt - -give :: ValidatorHash -> Contract TransactionHash -give vhash = do - let - constraints :: Constraints.TxConstraints Unit Unit - constraints = Constraints.mustPayToScript vhash unitDatum - $ Value.lovelaceValueOf - $ BigInt.fromInt 2_000_000 - - lookups :: Lookups.ScriptLookups PlutusData - lookups = mempty - - submitTxFromConstraints lookups constraints -``` - - -### The `grab` contract - -The Plutus `grab` example takes all the UTxOs locked by -the on-chain contract that always validates a transaction, and spends -them to get all in the wallet of the user running the example. -This isn't a problem as the example is intended to run inside a -Plutus `EmulatorTrace` in a local toy environment. - -```Haskell --- Haskell -grab :: forall w s e. AsContractError e => Contract w s e () -grab = do - utxos <- utxoAt scrAddress - let orefs = fst <$> Map.toList utxos - lookups = Constraints.unspentOutputs utxos <> - Constraints.otherScript validator - tx :: TxConstraints Void Void - tx = - mconcat [mustSpendScriptOutput oref $ Redeemer $ I 17 | oref <- orefs] - ledgerTx <- submitTxFromConstraints @Void lookups tx - void $ awaitTxConfirmed $ txId ledgerTx - logInfo @String $ "collected gifts" -``` - -To talk about the grab contract in CTL we need to talk about some -functions and types of CTL first. - -```PureScript -module Ctl.Internal.Plutus.Types.Transaction ... -. -. -. -type UtxoMap = Map TransactionInput TransactionOutputWithRefScript -``` - -```PureScript -module Contract.Utxos ... -. -. -. --- | Queries for utxos at the given Plutus `Address`. -utxosAt - :: forall (address :: Type) - . PlutusAddress address - => address - -> Contract UtxoMap -``` - - -In the case of the CTL version of `grab`, we cannot use all the UTxOs locked by -the validator that always validates, since the example is -intended to run in the `testnet` and other people could have some -values locked by the script. -This is the reason we assume we have already run the `give` contract to -pay some `testAda` to the validator first, and then We got a `TransactionHash`. -We would use the `TransactionHash` to locate the right UTxO to spend. - -```PureScript --- PureScript -grab - :: ValidatorHash - -> Validator - -> TransactionHash - -> Contract Unit -grab vhash validator txId = do - let scriptAddress = scriptHashAddress vhash Nothing - utxos <- fromMaybe Map.empty <$> utxosAt scriptAddress - case fst <$> find hasTransactionId (Map.toUnfoldable utxos :: Array _) of - Just txInput -> - let - lookups :: Lookups.ScriptLookups PlutusData - lookups = Lookups.validator validator - <> Lookups.unspentOutputs utxos - - constraints :: TxConstraints Unit Unit - constraints = - Constraints.mustSpendScriptOutput txInput unitRedeemer - in - void $ submitTxFromConstraints lookups constraints - _ -> - logInfo' $ "The id " - <> show txId - <> " does not have output locked at: " - <> show scriptAddress - where - hasTransactionId :: TransactionInput /\ _ -> Boolean - hasTransactionId (TransactionInput tx /\ _) = - tx.transactionId == txId -``` - -Notice the explicit signature in: - -```PureScript - fst <$> find hasTransactionId (Map.toUnfoldable utxos :: Array _) -``` - -Since PureScript has JS as the backend, `Array` is the most used container -(instead of `List` as in Haskell), so, we prefer the use of `Array` over `List` -whenever it's adequate. -A downside of this is the lack of pattern matching over arbitrary arrays. - - -Both versions of the contract use the same kind of constraints. -Both need to add the validator and the UTxOs to the `lookups` -and both need the `SpendScriptOutput` constraint. -In the case of Plutus, this is done by a special function -that accept lookups, while in CTL this is done by the explicit -construction of an unbalanced transaction. +## Contract code comparison +Compare the contracts defined in week2 of the [Plutus pioneer program](https://plutus-pioneer-program.readthedocs.io/en/latest/pioneer/week2.html) with the [`AlwaysSucceeds`](../examples/AlwaysSucceeds.purs) example in CTL. diff --git a/doc/test-plan.md b/doc/test-plan.md deleted file mode 100644 index 27c312d7fa..0000000000 --- a/doc/test-plan.md +++ /dev/null @@ -1,243 +0,0 @@ -# CTL Test Plan - -This document outlines CTL's test plan, i.e. a formalized description of testing CTL itself. - -**Table of Contents** - - - - -- [User interactions](#user-interactions) - - [Constraints/lookups](#constraintslookups) - - [Stake operations](#stake-operations) - - [Stake pools](#stake-pools) - - [Stake credential registration](#stake-credential-registration) - - [Delegation](#delegation) - - [Rewards withdrawal](#rewards-withdrawal) - - [Stake credential deregistration](#stake-credential-deregistration) - - [Other functionality](#other-functionality) -- [Acceptance criteria](#acceptance-criteria) - - [Example contracts as tests](#example-contracts-as-tests) - - [Test environments](#test-environments) - - [Unit and integration testing](#unit-and-integration-testing) - - [Required parsing tests](#required-parsing-tests) - - - -## User interactions - -This section outlines the parts of CTL's interface that we aim to guarantee function as expected. Each of the following functionality **must** be covered by an example contract (see our [Acceptance criteria](#acceptance-criteria) below for more details about coverage). - -### Constraints/lookups - -CTL's primary user interface is its constraints and lookups API, modeled after that of Plutus. We must ensure then that **all** of this interface is covered by complete examples (see [Acceptance criteria](#acceptance-criteria) below for a definition of an "example"). Each of the following constraints should be covered, along with the lookup that it implies (indicated in parentheses where applicable): - -- [x] `mustMintValue` (`mintingPolicy`). Also implies - - `mustMintCurrency` -- [x] `mustPayToScript` (`validator`) -- [x] `mustPayToScriptAddress` -- [x] `mustPayToPubKey` - - **Note**: This invokes the same code as `mustPayToPubKeyAddress`, but does not include a stake key component -- [x] `mustPayToPubKeyAddress` -- [x] `mustMintValueWithRedeemer` (`mintingPolicy`). Also implies - - `mustMintCurrencyWithRedeemer` -- [x] `mustSpendScriptOutput` -- [x] `mustSpendPubKeyOutput` -- [x] `mustBeSignedBy` -- [x] `mustHashDatum` -- [x] `mustIncludeDatum` -- [x] `mustPayToPubKeyWithDatum` -- [x] `mustPayToPubKeyAddressWithDatum` -- [x] `mustSatisfyAnyOf` -- [x] `mustSpendAtLeastTotal`. Also implies - - [x] `mustSpendAtLeast` -- [x] `mustValidateIn` - -The following constraints were added for `PlutusV2` features as part of our `v2.0.0` release. They do not have direct correspondances in `plutus-apps`: - -- [x] `mustMintCurrencyUsingScriptRef` -- [x] `mustMintCurrencyWithRedeemerUsingScriptRef` -- [x] `mustPayToScriptWithScriptRef` -- [x] `mustPayToScriptAddressWithScriptRef` -- [x] `mustPayToPubKeyAddressWithDatumAndScriptRef` -- [x] `mustPayToPubKeyAddressWithScriptRef` -- [x] `mustPayToPubKeyWithDatumAndScriptRef` -- [x] `mustPayToPubKeyWithScriptRef` -- [x] `mustReferenceOutput` -- [x] `mustSpendScriptOutputUsingScriptRef` - -That release also included the following constraints for working with native scripts, which also have no `plutus-apps` analogue: - -- [x] `mustPayToNativeScript` -- [x] `mustPayToNativeScriptAddress` -- [x] `mustSpendNativeScriptOutput` - -In addition, several redeemer combinations in a **single transaction** must be covered by tests or examples as well, namely - -- [x] Two or more `Mint` redeemers -- [x] Two or more `Spend` redeemers -- [x] (At least) One each of a `Spend` and `Mint` redeemer - -#### Stake operations - -New constraints for operations with stake will be added in `v3`. - -##### Stake pools - -- [x] mustRegisterPool -- [x] mustRetirePool - -##### Stake credential registration - -- [x] mustRegisterStakePubKey -- [x] mustRegisterStakeScript - -##### Delegation - -- [x] mustDelegateStakePubKey -- [x] mustDelegateStakePlutusScript -- [x] mustDelegateStakeNativeScript - -##### Rewards withdrawal - -- [x] mustWithdrawStakePubKey -- [x] mustWithdrawStakePlutusScript -- [x] mustWithdrawStakeNativeScript - -##### Stake credential deregistration - -- [x] mustDeregisterStakePubKey -- [x] mustDeregisterStakePlutusScript -- [x] mustDeregisterStakeNativeScript - -### Other functionality - -In addition to the constraints/lookups listed above, there are several other critical pieces of functionality that CTL must guarantee. This functionality is subject to the same criteria as our constraints/lookups. - -- `Contract.Transaction.*` - - [x] `balanceTx` - - [x] `signTransaction` - - [x] `submit` - - [x] `awaitTxConfirmed` (implies `awaitTxConfirmedWithTimeout`) - - [x] `getTxMetadata` -- `Contract.Scripts.*` - - [x] `validatorHash` - - [x] `mintingPolicy` - - [x] `applyArgs` - - [x] `getScriptByHash` - - [x] `getScriptsByHashes` -- `Contract.Hashing.*` - - [x] `datumHash` - - [x] `plutusScriptHash` -- `Contract.PlutusData.*` - - [x] `getDatumByHash` - - [x] `getDatumsByHashes` -- `Contract.Utxos.*` - - [x] `utxosAt` - -## Acceptance criteria - -Coverage of particular functionality is measured by the inclusion of the **public** interface in full example contracts and tests. CTL's public API is defined in its `Contract.*` modules. - -Most user interactions defined [above](#user-interactions) also call various parsers and serialization/deserialization code defined in CTL's private/internal modules. Acceptance criteria for these aspects of CTL are defined in [Unit testing](#unit-and-integration-testing) below. - -### Example contracts as tests - -In the case of CTL's constraints/lookups API, in order to be qualified as "covered", the relevant part of the API **must** be included in a **complete example** (such examples are currently contained in our [`examples/`](../examples) directory). Such examples must successfully - -- build an unbalanced transaction specified using the constraints/lookups interface - - **Note**: For implemented transaction features _not_ supported by our current constraints/lookups implementation, such as the features introduced by CIPs 31-33 (inline datums, etc...), modifying the transaction directly is also acceptable -- balance the transaction while calculating sufficient fees/execution units -- sign the transaction using the attached wallet (either a browser-based light wallet or our own `KeyWallet`) -- submit the transaction to the node - -The functionality to achieve the above **must** be taken from our public API. That is, we must consume the public interface directly in all example contracts rather than importing internal CTL modules (anything outside of `Contract.*`). - -#### Test environments - -Furthermore, **all** example contracts must be able to execute in both of the environments that CTL supports. The following sections will refer to two different approachs for testing CTL: - -- **Plutip** testing - - This represents CTL's support for running in a Node.js environment (for `KeyWallet` examples), without a browser or light wallet - - These examples must use our Plutip integrations (`Contract.Test.Plutip` and `purescriptProject.runPlutipTest` from our Nix infrastructure) - - As these do not require network access, they can be executed in an entirely pure environment - - These must be run on CI on each pull request against the CTL repository using `runPlutipTest` by adding the contract to `Test.Plutip` -- **e2e** (end-to-end) testing - - This represents our browser integration and uses real light wallets and a public testnet - - **All** currently supported wallets must be tested against each example contract - - In the future, all e2e tests using real light wallets and a headless Chromium instance might also be run on CI - - See [issue #929](https://github.com/Plutonomicon/cardano-transaction-lib/issues/929) for more details - -Example contracts should be implemented such that the same contract can be reused in both environments. An example module might look like: - -```purescript - -module Examples.MintsToken - ( example - ) where - -import Contract.Prelude - -import Contract.Config (ContractParams) -import Contract.Log (logInfo') -import Contract.Monad (launchAff_) - -example :: ContractParams -> Effect Unit -example cfg = launchAff_ do - runContract cfg do - logInfo' "Running Examples.MintsToken" - -- rest of the contract -``` - -Then, the exported `example` must be added to `Examples.ByUrl` to be run with `make e2e-test`. In some cases, it can be reused directly in a Plutip test (contained in the module `Test.Plutip`); in other cases, an indentical contract can be reimplemented inline in the Plutip test suite. - -The **only** exception to the above rule is when the particulars of a contract preclude running it in one of the environments. For example, a contract that requires interaction between two or more wallets cannot currently be adapted to our e2e testing (as it assumes one connected wallet with one account). - -### Unit and integration testing - -CTL relies heavily on various runtime components to provide the necessary information to perform chain queries and construct transactions. We depend on a large amount of parsers, including serialization/deserialization code (i.e. to and from CTL's own domain type to `cardano-serialization-lib` FFI types), to consume the responses to websocket and HTTP requests made against CTL's runtime. - -Although such parsers are included implicitly in the example contracts defined above, we must also ensure good coverage of edge cases that may arise when making runtime requests. Our approach to such testing can be formalized as: - -- **Unit tests** - - These tests rely on fixtures generated from runtime responses (see [`fixtures/`](../fixtures/test) for examples), stored in the same format as they are received in genuine responses - - The corresponding tests can be largely pure functions which read the fixture and parse it - - Success is defined as a parse returning a `Just` or `Right` value, depending on the parser - - Due to the large number and semi-random nature of our test fixtures, we do not require comparing parsed values to an expected result - - If possible, we should validate a parser against a component's _own_ test fixtures - - See `Test.Ogmios.GenerateFixtures` for an example of this approach, which uses Ogmios' generated test vectors for our own testing -- **Integration tests** - - These tests are run against a full runtime and make real requests to different components - - These are intended to augment the unit tests described above and are a step below our full example contracts - - These can be effects from the `Contract` interface and the underlying backends - -#### Required parsing tests - -Currently, we require parsing tests for the following data structures, organized by dependency (including runtime dependencies): - -- Ogmios - - [x] `ChainTipQR` - - [x] `CurrentEpoch` - - [x] `SystemStart` - - [x] `EraSummaries` - - [x] `ProtocolParameters` - - [x] `TxEvaluationR` - - [x] `SubmitTxR` -- `cardano-serialization-lib` - - `Transaction` - - [x] Serialization - - [x] Deserialization - - `TxBody` - - [x] Serialization - - [x] Deserialization - - `TransactionWitnessSet` - - [x] Serialization - - [x] Deserialization -- Kupo - - [ ] `KupoUtxoMap` - - [ ] `KupoDatum` - - [ ] `KupoScriptRef` - - [ ] `KupoUtxoSlot` - - [ ] `KupoMetadata` -- Blockfrost - - TODO diff --git a/src/Contract/Config.purs b/src/Contract/Config.purs index b7b8fa5605..991a8ddc29 100644 --- a/src/Contract/Config.purs +++ b/src/Contract/Config.purs @@ -18,6 +18,7 @@ module Contract.Config , mainnetLaceConfig , defaultSynchronizationParams , strictSynchronizationParams + , softSynchronizationParams , defaultTimeParams , module Data.Log.Level , module Data.Log.Message @@ -136,11 +137,22 @@ defaultTimeParams = , waitUntilSlot: { delay: Milliseconds 1_000.0 } } --- | Default synchronization parameters with all synchronization primitives --- | enabled. `errorOnTimeout` options are all set to `false`. +-- | Default synchronization parameters with all synchronizations +-- | disabled. -- | See `doc/query-layers.md` for more info. defaultSynchronizationParams :: ContractSynchronizationParams defaultSynchronizationParams = + { syncBackendWithWallet: + { errorOnTimeout: false, beforeCip30Methods: false, beforeBalancing: false } + , syncWalletWithTxInputs: { errorOnTimeout: false, beforeCip30Sign: false } + , syncWalletWithTransaction: + { errorOnTimeout: false, beforeTxConfirmed: false } + } + +-- | Attempt to synchronize, but do not throw an exception on failure. Used to be the default option in CTL up to and including v8. +-- | See `doc/query-layers.md` for more info. +softSynchronizationParams :: ContractSynchronizationParams +softSynchronizationParams = { syncBackendWithWallet: { errorOnTimeout: false, beforeCip30Methods: true, beforeBalancing: true } , syncWalletWithTxInputs: { errorOnTimeout: false, beforeCip30Sign: true } diff --git a/src/Contract/Constraints.purs b/src/Contract/Constraints.purs deleted file mode 100644 index 1faa0c2443..0000000000 --- a/src/Contract/Constraints.purs +++ /dev/null @@ -1,176 +0,0 @@ -module Contract.Constraints where - -import Prelude -import Prim hiding (Constraint) - -import Cardano.Types (Slot) -import Cardano.Types.AssetName (AssetName) -import Cardano.Types.Certificate (Certificate) -import Cardano.Types.Coin (Coin) -import Cardano.Types.Epoch (Epoch) -import Cardano.Types.Int as Int -import Cardano.Types.NativeScript (NativeScript) -import Cardano.Types.PaymentPubKeyHash (PaymentPubKeyHash) -import Cardano.Types.PlutusData (PlutusData) -import Cardano.Types.PlutusScript (PlutusScript) -import Cardano.Types.PoolParams (PoolParams) -import Cardano.Types.PoolPubKeyHash (PoolPubKeyHash) -import Cardano.Types.RedeemerDatum (RedeemerDatum) -import Cardano.Types.ScriptHash (ScriptHash) -import Cardano.Types.StakeCredential (StakeCredential) -import Cardano.Types.StakePubKeyHash (StakePubKeyHash) -import Cardano.Types.TransactionInput (TransactionInput) -import Cardano.Types.TransactionOutput (TransactionOutput) -import Cardano.Types.TransactionUnspentOutput (TransactionUnspentOutput) -import Data.Generic.Rep (class Generic) -import Data.Maybe (Maybe) -import Data.Show.Generic (genericShow) - -type Constraints = Array Constraint - --- TODO: consider using Maybe for witnesses -data Constraint - = SpendOutput TransactionUnspentOutput (Maybe OutputWitness) - | Pay TransactionOutput - | MintAsset ScriptHash AssetName Int.Int CredentialWitness - | RegisterStake StakeCredential - | IssueCertificate Certificate (Maybe CredentialWitness) - | WithdrawStake StakeCredential Coin (Maybe CredentialWitness) - | RequireSignature PaymentPubKeyHash - | RegisterPool PoolParams - | RetirePool PoolPubKeyHash Epoch - | IncludeDatum PlutusData - | SetTTL (Maybe Slot) - | SetValidityStartInterval (Maybe Slot) - | SetIsValid Boolean - -derive instance Generic Constraint _ -instance Show Constraint where - show = genericShow - --- | `OutputWitness` is used to provide the evidence needed to consume an --- | output. It must correspond to a `TransactionUnspentOutput` address' --- | payment credential to unlock it. -data OutputWitness - = NativeScriptOutput (ScriptWitness NativeScript) - | PlutusScriptOutput (ScriptWitness PlutusScript) RedeemerDatum - (Maybe DatumWitness) - -derive instance Generic OutputWitness _ -instance Show OutputWitness where - show = genericShow - --- | `CredentialWitness` is used to provide the evidence needed to perform --- | operations on behalf of a credential, which include: --- | --- | - Minting --- | - Certificate witnessing --- | - Rewards withdrawal --- | --- | Unlike `OutputWitness`, it does not include a `DatumWitness`, because --- | minting policies and stake scripts do not have a datum. -data CredentialWitness - = NativeScriptCredential (ScriptWitness NativeScript) - | PlutusScriptCredential (ScriptWitness PlutusScript) RedeemerDatum - -derive instance Generic CredentialWitness _ -instance Show CredentialWitness where - show = genericShow - --- | Gives the user options for specifying everything needed to spend an UTxO --- | located at an address with a ScriptHash payment credential. --- | --- | - `ScriptValue` contains a script for the witness set. --- | --- | - `ScriptReference` contains a CIP-31 reference input where the inline script should be available at, and a flag to either spend the referenced input or just reference it. -data ScriptWitness a - = ScriptValue a - | ScriptReference TransactionInput RefInputAction - -derive instance Show a => Generic (ScriptWitness a) _ -instance Show a => Show (ScriptWitness a) where - show = genericShow - --- | Inputs can be referenced or spent in a transaction (See CIP-31). --- | Inline datums (CIP-32) and reference scripts (CIP-33) contained within --- | transaction outputs become visible to the script context of the --- | transaction, regardless of whether the output is spent or just --- | referenced. This data type lets the developer to specify, which --- | action to perform with a referenced input. -data RefInputAction - = ReferenceInput - | SpendInput - -derive instance Generic RefInputAction _ -instance Show RefInputAction where - show = genericShow - --- | Datums in UTxOs can be stored in two forms: inline datums or datum hashes. --- | When there's a hash, we need to provide a datum corresponding to this hash, --- | which can be done by either providing the value literally, or using a --- | reference input where it is stored inline. -data DatumWitness - = DatumValue PlutusData - | DatumReference TransactionInput RefInputAction - -derive instance Generic DatumWitness _ -instance Show DatumWitness where - show = genericShow - -data StakeWitness - = PubKeyHashStakeWitness StakePubKeyHash - | PlutusScriptStakeWitness (ScriptWitness PlutusScript) - | NativeScriptStakeWitness (ScriptWitness NativeScript) - -derive instance Generic StakeWitness _ -instance Show StakeWitness where - show = genericShow - --- Stake operations - --- registerStake :: StakeRegistration -> TxConstraints --- registerStake = singleton <<< case _ of --- StakePubKeyRegistration spkh -> MustRegisterStakePubKey spkh --- StakeScriptRegistration ssh -> MustRegisterStakeScript ssh - --- delegateStake :: PoolPubKeyHash -> StakeDelegation -> TxConstraints --- delegateStake ppkh = singleton <<< case _ of --- DelegatePubKeyHashStake spkh -> --- MustDelegateStakePubKey spkh ppkh --- DelegateNativeScriptStake ns -> --- MustDelegateStakeNativeScript ns ppkh --- DelegatePlutusScriptStake ps redeemer -> --- MustDelegateStakePlutusScript ps redeemer ppkh - --- withdrawStake :: StakeWithdrawal -> TxConstraints --- withdrawStake = singleton <<< case _ of --- WithdrawNativeScriptStake ns -> --- MustWithdrawStakeNativeScript ns --- WithdrawPlutusScriptStake ps redeemer -> --- MustWithdrawStakePlutusScript ps redeemer --- WithdrawPubKeyStake spkh -> --- MustWithdrawStakePubKey spkh - --- data StakeDelegation --- = DelegatePubKeyHashStake StakePubKeyHash --- | DelegateNativeScriptStake NativeScriptWitness --- | DelegatePlutusScriptStake PlutusScriptWitness - --- data StakeWithdrawal --- = WithdrawNativeScriptStake NativeScriptWitness --- | WithdrawPlutusScriptStake PlutusScriptWitness --- | WithdrawPubKeyStake StakePubKeyHash - --- data DeregisterStake --- = DeregisterNativeScriptStake NativeScriptWitness --- | DeregisterPlutusScriptStake PlutusScriptWitness --- | DeregisterPubKeyStake StakePubKeyHash - --- deregisterStake :: DeregisterStake -> TxConstraints --- deregisterStake = singleton <<< case _ of --- DeregisterNativeScriptStake ns -> --- MustDeregisterStakeNativeScript ns --- DeregisterPlutusScriptStake ps redeemer -> --- MustDeregisterStakePlutusScript ps redeemer --- DeregisterPubKeyStake spkh -> --- MustDeregisterStakePubKey spkh From dbc4608610b1e0d53e583b1402bf1f2765f7056f Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Thu, 18 Jul 2024 21:43:00 +0400 Subject: [PATCH 43/52] Rename BalanceTxConstraintsBuilder to BalancerConstraints (backward-compatible change) --- CHANGELOG.md | 1 + examples/AdditionalUtxos.purs | 10 ++-- examples/BalanceTxConstraints.purs | 16 +++--- examples/TxChaining.purs | 8 +-- src/Contract/BalanceTxConstraints.purs | 2 + src/Contract/Config.purs | 5 +- src/Internal/BalanceTx/BalanceTx.purs | 4 +- src/Internal/BalanceTx/Constraints.purs | 67 +++++++++++++------------ src/Internal/BalanceTx/Types.purs | 22 ++++---- 9 files changed, 73 insertions(+), 62 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5de6bcc96..98ebffd7db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -94,6 +94,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - `Contract.Transaction.mkUnbalancedTx` now returns a tuple: a transaction and its used UTxOs. - `Contract.Transaction.balanceTx` accepts two extra argument: a list of used UTxOs (set to `Data.Map.empty` if none of them are coming from the outside of the wallet) and balancer constraints (set to `mempty` if not needed) - Default synchronization parameters: all [wallet <-> query layer synchronization primitives](./doc/query-layer.md) are now off by default. The reason is that the runtime overhead made the users unhappy and it was not worth it for most of the users. If your dApp sends transactions in quick succession, consider enabling the synchronization again. +- `BalanceTxConstraintsBuilder` has been renamed to `BalancerConstraints`. It is still available under the old name as a type synonym. ### Fixed diff --git a/examples/AdditionalUtxos.purs b/examples/AdditionalUtxos.purs index 7aa80ded9d..4184ed772d 100644 --- a/examples/AdditionalUtxos.purs +++ b/examples/AdditionalUtxos.purs @@ -24,8 +24,10 @@ import Cardano.Types.RedeemerDatum as RedeemerDatum import Cardano.Types.TransactionOutput (TransactionOutput(TransactionOutput)) import Cardano.Types.TransactionUnspentOutput (fromUtxoMap) import Contract.Address (mkAddress) -import Contract.BalanceTxConstraints (BalanceTxConstraintsBuilder) -import Contract.BalanceTxConstraints (mustUseAdditionalUtxos) as BalancerConstraints +import Contract.BalanceTxConstraints + ( BalancerConstraints + , mustUseAdditionalUtxos + ) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, runContract) @@ -126,9 +128,9 @@ spendFromValidator validator additionalUtxos _datum = do plan = spendScriptOutputs <> spendPubkeyOutputs - balancerConstraints :: BalanceTxConstraintsBuilder + balancerConstraints :: BalancerConstraints balancerConstraints = - BalancerConstraints.mustUseAdditionalUtxos additionalUtxos + mustUseAdditionalUtxos additionalUtxos unbalancedTx <- buildTx plan balancedTx <- balanceTx unbalancedTx additionalUtxos balancerConstraints diff --git a/examples/BalanceTxConstraints.purs b/examples/BalanceTxConstraints.purs index 13b54824cd..048013dcba 100644 --- a/examples/BalanceTxConstraints.purs +++ b/examples/BalanceTxConstraints.purs @@ -12,13 +12,13 @@ import Cardano.Types.Mint as Mint import Cardano.Types.PlutusScript as PlutusScript import Contract.Address (Address) import Contract.BalanceTxConstraints - ( BalanceTxConstraintsBuilder + ( BalancerConstraints , mustGenChangeOutsWithMaxTokenQuantity , mustNotSpendUtxoWithOutRef , mustSendChangeToAddress , mustUseCollateralUtxos , mustUseUtxosAtAddress - ) as BalanceTxConstraints + ) import Contract.Log (logInfo') import Contract.Monad (Contract, liftedM) import Contract.ScriptLookups as Lookups @@ -166,14 +166,14 @@ contract (ContractParams p) = do lookups :: Lookups.ScriptLookups lookups = Lookups.plutusMintingPolicy mp - balanceTxConstraints :: BalanceTxConstraints.BalanceTxConstraintsBuilder + balanceTxConstraints :: BalancerConstraints balanceTxConstraints = - BalanceTxConstraints.mustGenChangeOutsWithMaxTokenQuantity + mustGenChangeOutsWithMaxTokenQuantity (BigInt.fromInt 4) - <> BalanceTxConstraints.mustUseUtxosAtAddress bobAddress - <> BalanceTxConstraints.mustSendChangeToAddress bobAddress - <> BalanceTxConstraints.mustNotSpendUtxoWithOutRef nonSpendableOref - <> BalanceTxConstraints.mustUseCollateralUtxos bobsCollateral + <> mustUseUtxosAtAddress bobAddress + <> mustSendChangeToAddress bobAddress + <> mustNotSpendUtxoWithOutRef nonSpendableOref + <> mustUseCollateralUtxos bobsCollateral void $ runChecks checks $ lift do unbalancedTx /\ usedUtxos <- mkUnbalancedTx lookups constraints diff --git a/examples/TxChaining.purs b/examples/TxChaining.purs index a9dec95547..4ca765ff9e 100644 --- a/examples/TxChaining.purs +++ b/examples/TxChaining.purs @@ -22,9 +22,9 @@ import Cardano.Types.DataHash (hashPlutusData) import Cardano.Types.PlutusData as PlutusData import Contract.Address (mkAddress) import Contract.BalanceTxConstraints - ( BalanceTxConstraintsBuilder + ( BalancerConstraints , mustUseAdditionalUtxos - ) as BalanceTxConstraints + ) import Contract.Config (ContractParams, testnetNamiConfig) import Contract.Log (logInfo') import Contract.Monad (Contract, launchAff_, liftedM, runContract) @@ -76,9 +76,9 @@ contract = do when (Map.isEmpty additionalUtxos) do liftEffect $ throw "empty utxos" let - balanceTxConstraints :: BalanceTxConstraints.BalanceTxConstraintsBuilder + balanceTxConstraints :: BalancerConstraints balanceTxConstraints = - BalanceTxConstraints.mustUseAdditionalUtxos additionalUtxos + mustUseAdditionalUtxos additionalUtxos unbalancedTx1 <- buildTx plan balancedTx1 <- balanceTx unbalancedTx1 additionalUtxos balanceTxConstraints balancedSignedTx1 <- signTransaction balancedTx1 diff --git a/src/Contract/BalanceTxConstraints.purs b/src/Contract/BalanceTxConstraints.purs index 531e16c63b..67d95706dd 100644 --- a/src/Contract/BalanceTxConstraints.purs +++ b/src/Contract/BalanceTxConstraints.purs @@ -4,6 +4,8 @@ module Contract.BalanceTxConstraints (module BalanceTxConstraints) where import Ctl.Internal.BalanceTx.Constraints ( BalanceTxConstraintsBuilder + , BalancerConfig(BalancerConfig) + , BalancerConstraints(BalancerConstraints) , mustGenChangeOutsWithMaxTokenQuantity , mustNotSpendUtxoWithOutRef , mustNotSpendUtxosWithOutRefs diff --git a/src/Contract/Config.purs b/src/Contract/Config.purs index 991a8ddc29..55660a150f 100644 --- a/src/Contract/Config.purs +++ b/src/Contract/Config.purs @@ -143,7 +143,10 @@ defaultTimeParams = defaultSynchronizationParams :: ContractSynchronizationParams defaultSynchronizationParams = { syncBackendWithWallet: - { errorOnTimeout: false, beforeCip30Methods: false, beforeBalancing: false } + { errorOnTimeout: false + , beforeCip30Methods: false + , beforeBalancing: false + } , syncWalletWithTxInputs: { errorOnTimeout: false, beforeCip30Sign: false } , syncWalletWithTransaction: { errorOnTimeout: false, beforeTxConfirmed: false } diff --git a/src/Internal/BalanceTx/BalanceTx.purs b/src/Internal/BalanceTx/BalanceTx.purs index 6aa2ca9ed4..d3128a083c 100644 --- a/src/Internal/BalanceTx/BalanceTx.purs +++ b/src/Internal/BalanceTx/BalanceTx.purs @@ -91,7 +91,7 @@ import Ctl.Internal.BalanceTx.Types , asksConstraints , liftContract , liftEitherContract - , withBalanceTxConstraints + , withBalancerConstraints ) import Ctl.Internal.BalanceTx.UtxoMinAda (utxoMinAdaValue) import Ctl.Internal.CoinSelection.UtxoIndex (UtxoIndex, buildUtxoIndex) @@ -168,7 +168,7 @@ balanceTxWithConstraints transaction extraUtxos constraintsBuilder = do pparams <- getProtocolParameters - withBalanceTxConstraints constraintsBuilder $ runExceptT do + withBalancerConstraints constraintsBuilder $ runExceptT do let depositValuePerCert = BigNum.toBigInt $ unwrap (unwrap pparams).stakeAddressDeposit diff --git a/src/Internal/BalanceTx/Constraints.purs b/src/Internal/BalanceTx/Constraints.purs index 8fd509df9d..edc89414b0 100644 --- a/src/Internal/BalanceTx/Constraints.purs +++ b/src/Internal/BalanceTx/Constraints.purs @@ -1,7 +1,8 @@ module Ctl.Internal.BalanceTx.Constraints - ( BalanceTxConstraints(BalanceTxConstraints) - , BalanceTxConstraintsBuilder(BalanceTxConstraintsBuilder) - , buildBalanceTxConstraints + ( BalanceTxConstraintsBuilder + , BalancerConstraints(BalancerConstraints) + , buildBalancerConfig + , BalancerConfig(BalancerConfig) , mustGenChangeOutsWithMaxTokenQuantity , mustNotSpendUtxosWithOutRefs , mustNotSpendUtxoWithOutRef @@ -43,7 +44,7 @@ import Data.Set (singleton) as Set import JS.BigInt (BigInt) import Type.Proxy (Proxy(Proxy)) -newtype BalanceTxConstraints = BalanceTxConstraints +newtype BalancerConfig = BalancerConfig { additionalUtxos :: UtxoMap , collateralUtxos :: Maybe UtxoMap , maxChangeOutputTokenQuantity :: Maybe BigInt @@ -54,48 +55,50 @@ newtype BalanceTxConstraints = BalanceTxConstraints , selectionStrategy :: SelectionStrategy } -derive instance Newtype BalanceTxConstraints _ +derive instance Newtype BalancerConfig _ -_additionalUtxos :: Lens' BalanceTxConstraints UtxoMap +_additionalUtxos :: Lens' BalancerConfig UtxoMap _additionalUtxos = _Newtype <<< prop (Proxy :: Proxy "additionalUtxos") -_collateralUtxos :: Lens' BalanceTxConstraints (Maybe UtxoMap) +_collateralUtxos :: Lens' BalancerConfig (Maybe UtxoMap) _collateralUtxos = _Newtype <<< prop (Proxy :: Proxy "collateralUtxos") -_maxChangeOutputTokenQuantity :: Lens' BalanceTxConstraints (Maybe BigInt) +_maxChangeOutputTokenQuantity :: Lens' BalancerConfig (Maybe BigInt) _maxChangeOutputTokenQuantity = _Newtype <<< prop (Proxy :: Proxy "maxChangeOutputTokenQuantity") -_nonSpendableInputs :: Lens' BalanceTxConstraints (Set TransactionInput) +_nonSpendableInputs :: Lens' BalancerConfig (Set TransactionInput) _nonSpendableInputs = _Newtype <<< prop (Proxy :: Proxy "nonSpendableInputs") -_srcAddresses :: Lens' BalanceTxConstraints (Maybe (Array Address)) +_srcAddresses :: Lens' BalancerConfig (Maybe (Array Address)) _srcAddresses = _Newtype <<< prop (Proxy :: Proxy "srcAddresses") -_changeAddress :: Lens' BalanceTxConstraints (Maybe Address) +_changeAddress :: Lens' BalancerConfig (Maybe Address) _changeAddress = _Newtype <<< prop (Proxy :: Proxy "changeAddress") -_changeDatum :: Lens' BalanceTxConstraints (Maybe OutputDatum) +_changeDatum :: Lens' BalancerConfig (Maybe OutputDatum) _changeDatum = _Newtype <<< prop (Proxy :: Proxy "changeDatum") -_selectionStrategy :: Lens' BalanceTxConstraints SelectionStrategy +_selectionStrategy :: Lens' BalancerConfig SelectionStrategy _selectionStrategy = _Newtype <<< prop (Proxy :: Proxy "selectionStrategy") -newtype BalanceTxConstraintsBuilder = - BalanceTxConstraintsBuilder (BalanceTxConstraints -> BalanceTxConstraints) +type BalanceTxConstraintsBuilder = BalancerConstraints -derive instance Newtype BalanceTxConstraintsBuilder _ +newtype BalancerConstraints = + BalancerConstraints (BalancerConfig -> BalancerConfig) -instance Semigroup BalanceTxConstraintsBuilder where - append = over2 BalanceTxConstraintsBuilder (>>>) +derive instance Newtype BalancerConstraints _ -instance Monoid BalanceTxConstraintsBuilder where +instance Semigroup BalancerConstraints where + append = over2 BalancerConstraints (>>>) + +instance Monoid BalancerConstraints where mempty = wrap identity -buildBalanceTxConstraints :: BalanceTxConstraintsBuilder -> BalanceTxConstraints -buildBalanceTxConstraints = applyFlipped defaultConstraints <<< unwrap +buildBalancerConfig :: BalancerConstraints -> BalancerConfig +buildBalancerConfig = applyFlipped defaultConstraints <<< unwrap where - defaultConstraints :: BalanceTxConstraints + defaultConstraints :: BalancerConfig defaultConstraints = wrap { additionalUtxos: Map.empty , collateralUtxos: Nothing @@ -114,13 +117,13 @@ buildBalanceTxConstraints = applyFlipped defaultConstraints <<< unwrap -- | NOTE: Setting `mustUseUtxosAtAddresses` or `mustUseUtxosAtAddress` -- | does NOT have any effect on which address will be used as a change address. mustSendChangeToAddress - :: Address -> BalanceTxConstraintsBuilder + :: Address -> BalancerConstraints mustSendChangeToAddress = wrap <<< setJust _changeAddress -- | Tells the balancer to include the datum in each change UTxO. Useful when -- | balancing a transactions for script owned UTxOs. -mustSendChangeWithDatum :: OutputDatum -> BalanceTxConstraintsBuilder +mustSendChangeWithDatum :: OutputDatum -> BalancerConstraints mustSendChangeWithDatum = wrap <<< setJust _changeDatum @@ -131,7 +134,7 @@ mustSendChangeWithDatum = -- | NOTE: Setting `mustUseUtxosAtAddresses` or `mustUseUtxosAtAddress` -- | does NOT have any effect on which address will be used as a change address. mustUseUtxosAtAddresses - :: Array Address -> BalanceTxConstraintsBuilder + :: Array Address -> BalancerConstraints mustUseUtxosAtAddresses = wrap <<< setJust _srcAddresses @@ -142,7 +145,7 @@ mustUseUtxosAtAddresses = -- | NOTE: Setting `mustUseUtxosAtAddresses` or `mustUseUtxosAtAddress` -- | does NOT have any effect on which address will be used as a change address. mustUseUtxosAtAddress - :: Address -> BalanceTxConstraintsBuilder + :: Address -> BalancerConstraints mustUseUtxosAtAddress address = mustUseUtxosAtAddresses (Array.singleton address) @@ -150,31 +153,31 @@ mustUseUtxosAtAddress address = -- | between them if the total change `Value` contains token quantities -- | exceeding the specified upper bound. -- | (See `Cardano.Types.Value.equipartitionValueWithTokenQuantityUpperBound`) -mustGenChangeOutsWithMaxTokenQuantity :: BigInt -> BalanceTxConstraintsBuilder +mustGenChangeOutsWithMaxTokenQuantity :: BigInt -> BalancerConstraints mustGenChangeOutsWithMaxTokenQuantity = wrap <<< setJust _maxChangeOutputTokenQuantity <<< max one -- | Tells the balancer not to spend UTxO's with the specified output references. mustNotSpendUtxosWithOutRefs - :: Set TransactionInput -> BalanceTxConstraintsBuilder + :: Set TransactionInput -> BalancerConstraints mustNotSpendUtxosWithOutRefs = wrap <<< appendOver _nonSpendableInputs -- | Tells the balancer not to spend a UTxO with the specified output reference. -mustNotSpendUtxoWithOutRef :: TransactionInput -> BalanceTxConstraintsBuilder +mustNotSpendUtxoWithOutRef :: TransactionInput -> BalancerConstraints mustNotSpendUtxoWithOutRef = mustNotSpendUtxosWithOutRefs <<< Set.singleton -- | Tells the balancer to use the provided UTxO set when evaluating script -- | execution units (sets `additionalUtxoSet` of Ogmios `EvaluateTx`). -- | Note that you need to use `unspentOutputs` lookup to make these UTxO's -- | spendable by the transaction (see `Examples.TxChaining` for reference). -mustUseAdditionalUtxos :: UtxoMap -> BalanceTxConstraintsBuilder +mustUseAdditionalUtxos :: UtxoMap -> BalancerConstraints mustUseAdditionalUtxos = wrap <<< set _additionalUtxos -- | Tells the balancer to select from the provided UTxO set when choosing -- | collateral UTxOs, instead of UTxOs provided by the browser wallet. -mustUseCollateralUtxos :: UtxoMap -> BalanceTxConstraintsBuilder +mustUseCollateralUtxos :: UtxoMap -> BalancerConstraints mustUseCollateralUtxos = wrap <<< set _collateralUtxos <<< Just -- | Tells the balancer to use the given strategy for coin selection. -mustUseCoinSelectionStrategy :: SelectionStrategy -> BalanceTxConstraintsBuilder +mustUseCoinSelectionStrategy :: SelectionStrategy -> BalancerConstraints mustUseCoinSelectionStrategy = wrap <<< set _selectionStrategy diff --git a/src/Internal/BalanceTx/Types.purs b/src/Internal/BalanceTx/Types.purs index 42640cd0ce..2ce82ab871 100644 --- a/src/Internal/BalanceTx/Types.purs +++ b/src/Internal/BalanceTx/Types.purs @@ -7,7 +7,7 @@ module Ctl.Internal.BalanceTx.Types , asksConstraints , liftEitherContract , liftContract - , withBalanceTxConstraints + , withBalancerConstraints ) where import Prelude @@ -18,9 +18,9 @@ import Control.Monad.Reader.Class (asks) import Control.Monad.Reader.Trans (ReaderT, runReaderT) import Control.Monad.Trans.Class (lift) import Ctl.Internal.BalanceTx.Constraints - ( BalanceTxConstraints - , BalanceTxConstraintsBuilder - , buildBalanceTxConstraints + ( BalancerConfig + , BalancerConstraints + , buildBalancerConfig ) import Ctl.Internal.BalanceTx.Error (BalanceTxError) import Ctl.Internal.Contract.Monad (Contract, ContractEnv) @@ -35,7 +35,7 @@ import Data.Set (Set) import Data.Set (fromFoldable, member) as Set type BalanceTxMContext = - { constraints :: BalanceTxConstraints, ownAddresses :: Set Address } + { constraints :: BalancerConfig, ownAddresses :: Set Address } type BalanceTxM (a :: Type) = ExceptT BalanceTxError (ReaderT BalanceTxMContext Contract) a @@ -48,7 +48,7 @@ liftEitherContract liftEitherContract = ExceptT <<< lift asksConstraints - :: forall (a :: Type). Lens' BalanceTxConstraints a -> BalanceTxM a + :: forall (a :: Type). Lens' BalancerConfig a -> BalanceTxM a asksConstraints l = asks (view l <<< _.constraints) asksContractEnv :: forall (a :: Type). (ContractEnv -> a) -> BalanceTxM a @@ -62,19 +62,19 @@ askCoinsPerUtxoUnit = askNetworkId :: BalanceTxM NetworkId askNetworkId = asksContractEnv _.networkId -withBalanceTxConstraints +withBalancerConstraints :: forall (a :: Type) - . BalanceTxConstraintsBuilder + . BalancerConstraints -> ReaderT BalanceTxMContext Contract a -> Contract a -withBalanceTxConstraints constraintsBuilder m = do +withBalancerConstraints constraintsBuilder m = do -- we can ignore failures due to reward addresses because reward addresses -- do not receive transaction outputs from dApps ownAddresses <- Set.fromFoldable <$> getWalletAddresses flip runReaderT { constraints, ownAddresses } m where - constraints :: BalanceTxConstraints - constraints = buildBalanceTxConstraints constraintsBuilder + constraints :: BalancerConfig + constraints = buildBalancerConfig constraintsBuilder askCostModelsForLanguages :: Set Language -> BalanceTxM (Map Language CostModel) askCostModelsForLanguages languages = From 34b6b92a6c8d27da102460e484f94ed725c128bf Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Fri, 19 Jul 2024 19:39:43 +0400 Subject: [PATCH 44/52] Update the template dependencies --- templates/ctl-scaffold/packages.dhall | 7 ++- templates/ctl-scaffold/spago-packages.nix | 60 +++++++++++++++++++++++ templates/ctl-scaffold/spago.dhall | 5 ++ 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/templates/ctl-scaffold/packages.dhall b/templates/ctl-scaffold/packages.dhall index adfe30ae0d..8694c67083 100644 --- a/templates/ctl-scaffold/packages.dhall +++ b/templates/ctl-scaffold/packages.dhall @@ -553,12 +553,15 @@ let additions = , "bignumber" , "bytearrays" , "cardano-hd-wallet" + , "cardano-key-wallet" + , "cardano-message-signing" , "cardano-plutus-data-schema" , "cardano-serialization-lib" , "cardano-transaction-builder" , "cardano-types" , "checked-exceptions" , "cip30" + , "cip30-mock" , "cip30-typesafe" , "console" , "control" @@ -614,7 +617,6 @@ let additions = , "profunctor-lenses" , "quickcheck" , "quickcheck-combinators" - , "quickcheck-laws" , "random" , "rationals" , "record" @@ -634,12 +636,13 @@ let additions = , "unfoldable" , "unsafe-coerce" , "untagged-union" + , "uplc-apply-args" , "variant" , "web-html" , "web-storage" ] , repo = "https://github.com/Plutonomicon/cardano-transaction-lib.git" - , version = "423e27b3f56b1a66db8d3126c22cea9bda7e50da" + , version = "dbc4608610b1e0d53e583b1402bf1f2765f7056f" } } diff --git a/templates/ctl-scaffold/spago-packages.nix b/templates/ctl-scaffold/spago-packages.nix index cd0e4d5dc7..369921ee0e 100644 --- a/templates/ctl-scaffold/spago-packages.nix +++ b/templates/ctl-scaffold/spago-packages.nix @@ -209,6 +209,18 @@ let installPhase = "ln -s $src $out"; }; + "cardano-collateral-select" = pkgs.stdenv.mkDerivation { + name = "cardano-collateral-select"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-collateral-select"; + rev = "193bf49be979b42aa1f0f9cb3d7582d6bc98e3b9"; + sha256 = "1jbl6k779brbqzf7jf80is63b23k3mqzf2mzr222qswd3wg8s5b0"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "cardano-hd-wallet" = pkgs.stdenv.mkDerivation { name = "cardano-hd-wallet"; version = "v1.0.0"; @@ -221,6 +233,30 @@ let installPhase = "ln -s $src $out"; }; + "cardano-key-wallet" = pkgs.stdenv.mkDerivation { + name = "cardano-key-wallet"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-key-wallet"; + rev = "55f176dbedddbd37297a3d1f90c756420159454e"; + sha256 = "1fr77kvgdvxqi0jhg98balrwpf7rlhwiyrf1v8z2112yyln2myj9"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + + "cardano-message-signing" = pkgs.stdenv.mkDerivation { + name = "cardano-message-signing"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cardano-message-signing"; + rev = "97f6f97a258ae3490df0be6b39fa6769677aa04f"; + sha256 = "1ns7m9awn4w5amvf9ffldxk7acm73fg8clw4hja4nnl61mskqr5w"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "cardano-plutus-data-schema" = pkgs.stdenv.mkDerivation { name = "cardano-plutus-data-schema"; version = "v1.0.0"; @@ -317,6 +353,18 @@ let installPhase = "ln -s $src $out"; }; + "cip30-mock" = pkgs.stdenv.mkDerivation { + name = "cip30-mock"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-cip30-mock"; + rev = "7b4b7b2800f6d0ebd25554de63141cbd8c1e14a0"; + sha256 = "1b412s7p144h98csvy5w9z6vjhlpya9mqkxm2k8nxfdhq2znwfih"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "cip30-typesafe" = pkgs.stdenv.mkDerivation { name = "cip30-typesafe"; version = "d72e51fbc0255eb3246c9132d295de7f65e16a99"; @@ -1577,6 +1625,18 @@ let installPhase = "ln -s $src $out"; }; + "uplc-apply-args" = pkgs.stdenv.mkDerivation { + name = "uplc-apply-args"; + version = "v1.0.0"; + src = pkgs.fetchgit { + url = "https://github.com/mlabs-haskell/purescript-uplc-apply-args"; + rev = "aa528d5310cbfbd01b4d94557f404d95cfb6bb3c"; + sha256 = "1r064ca2m16hkbcswrvlng032ax1ygbpr2gxrlaqmjlf2gnin280"; + }; + phases = "installPhase"; + installPhase = "ln -s $src $out"; + }; + "variant" = pkgs.stdenv.mkDerivation { name = "variant"; version = "v8.0.0"; diff --git a/templates/ctl-scaffold/spago.dhall b/templates/ctl-scaffold/spago.dhall index b25547240d..3d2677eb46 100644 --- a/templates/ctl-scaffold/spago.dhall +++ b/templates/ctl-scaffold/spago.dhall @@ -8,6 +8,11 @@ You can edit this file as you like. , "bytearrays" , "cardano-hd-wallet" , "cardano-plutus-data-schema" + , "cardano-collateral-select" + , "cardano-key-wallet" + , "cardano-message-signing" + , "cip30-mock" + , "uplc-apply-args" , "cardano-serialization-lib" , "cardano-transaction-lib" , "cardano-types" From d17bbb30b49287018d8d00b9cfd9aa6ee07cce0c Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Fri, 19 Jul 2024 19:51:16 +0400 Subject: [PATCH 45/52] Fix broken link --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98ebffd7db..bb4f221af9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -93,7 +93,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - `Contract.Transaction.mkUnbalancedTx` now returns a tuple: a transaction and its used UTxOs. - `Contract.Transaction.balanceTx` accepts two extra argument: a list of used UTxOs (set to `Data.Map.empty` if none of them are coming from the outside of the wallet) and balancer constraints (set to `mempty` if not needed) -- Default synchronization parameters: all [wallet <-> query layer synchronization primitives](./doc/query-layer.md) are now off by default. The reason is that the runtime overhead made the users unhappy and it was not worth it for most of the users. If your dApp sends transactions in quick succession, consider enabling the synchronization again. +- Default synchronization parameters: all [wallet <-> query layer synchronization primitives](./doc/query-layers.md) are now off by default. The reason is that the runtime overhead made the users unhappy and it was not worth it for most of the users. If your dApp sends transactions in quick succession, consider enabling the synchronization again. - `BalanceTxConstraintsBuilder` has been renamed to `BalancerConstraints`. It is still available under the old name as a type synonym. ### Fixed From 3bf59a2760b6db2799d89e74211c29fb75b48fbc Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Tue, 23 Jul 2024 21:26:05 +0400 Subject: [PATCH 46/52] Add getStakeCredentialDelegationsAndRewards --- CHANGELOG.md | 2 +- src/Contract/Staking.purs | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb4f221af9..484bf7de67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -79,7 +79,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - `Contract.Transaction.buildTx :: Array TransactionBuilderStep -> Contract Transaction` that provides a `Contract`-based interface for the [new transaction builder](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder). - `submitTxFromBuildPlan :: UtxoMap -> BalanceTxConstraintsBuilder -> Array TransactionBuilderStep -> Contract Transaction` - a convenience function that executes the whole transaction creation pipeline starting from a build plan for [the new transaction builder](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder). - `Contract.ClientError.pprintClientError` to provide readable error reports. -- +- `Contract.Staking.getStakeCredentialDelegationsAndRewards` utility function ### Removed diff --git a/src/Contract/Staking.purs b/src/Contract/Staking.purs index 2be33a901d..067a75525e 100644 --- a/src/Contract/Staking.purs +++ b/src/Contract/Staking.purs @@ -2,12 +2,19 @@ module Contract.Staking ( getPoolIds , getPubKeyHashDelegationsAndRewards , getValidatorHashDelegationsAndRewards + , getStakeCredentialDelegationsAndRewards , module X ) where import Prelude -import Cardano.Types (Ed25519KeyHash, PoolPubKeyHash, ScriptHash) +import Cardano.Types + ( Credential(PubKeyHashCredential, ScriptHashCredential) + , Ed25519KeyHash + , PoolPubKeyHash + , ScriptHash + , StakeCredential(StakeCredential) + ) import Contract.Monad (Contract) import Control.Monad.Reader (asks) import Ctl.Internal.Contract.Monad (getQueryHandle) @@ -27,6 +34,15 @@ getPoolIds = do queryHandle.getPoolIds >>= either (liftEffect <<< throw <<< show) pure +getStakeCredentialDelegationsAndRewards + :: StakeCredential + -> Contract (Maybe DelegationsAndRewards) +getStakeCredentialDelegationsAndRewards = case _ of + StakeCredential (PubKeyHashCredential pkh) -> + getPubKeyHashDelegationsAndRewards pkh + StakeCredential (ScriptHashCredential sh) -> + getValidatorHashDelegationsAndRewards sh + getPubKeyHashDelegationsAndRewards :: Ed25519KeyHash -> Contract (Maybe DelegationsAndRewards) From 2b5c3ea04e134eaa73ae0667ec22e12efe234111 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Tue, 23 Jul 2024 21:26:26 +0400 Subject: [PATCH 47/52] Fix all Staking examples --- packages.dhall | 2 +- scripts/import-fixer.sh | 10 +- spago-packages.nix | 6 +- src/Contract/Transaction.purs | 23 +- src/Contract/Wallet/Key.purs | 5 +- templates/ctl-scaffold/packages.dhall | 2 +- templates/ctl-scaffold/spago-packages.nix | 12 +- test/Plutip/Staking.purs | 494 +++++++++++----------- 8 files changed, 277 insertions(+), 277 deletions(-) diff --git a/packages.dhall b/packages.dhall index 32f5a10b78..23decc6196 100644 --- a/packages.dhall +++ b/packages.dhall @@ -516,7 +516,7 @@ let additions = ] , repo = "https://github.com/mlabs-haskell/purescript-cardano-transaction-builder" - , version = "c93cfaaa08643632021fb8c6dcc4d0b8130250d1" + , version = "70d219d6463466458fd381b55d84f458dcaee94a" } , mote-testplan = { dependencies = diff --git a/scripts/import-fixer.sh b/scripts/import-fixer.sh index 66e90ff440..368ab577a5 100755 --- a/scripts/import-fixer.sh +++ b/scripts/import-fixer.sh @@ -9,8 +9,8 @@ if [[ "${TRACE-0}" == "1" ]]; then fi if [[ "${1-}" =~ ^-*h(elp)?$ ]]; then - echo 'Usage: ./scripts/import-fixer.sh [REVISION] -This script attempts to fix imports from implicit for (Something(..)) to explicit (Something(SomeConstructor, OtherConstructor)) + echo 'Usage: ./scripts/import-fixer.sh +This script attempts to fix imports from implicit (Something(..)) to explicit (Something(SomeConstructor, OtherConstructor)) based on a set of hardcoded types ' exit fi @@ -43,12 +43,16 @@ constrs["RedeemerTag"]="Spend, Mint, Cert, Reward" constrs["Maybe"]="Just, Nothing" constrs["PaymentCredential"]="PaymentCredential" constrs["StakeCredential"]="StakeCredential" -constrs["TransactionBuilderStep"]="SpendOutput, Pay, MintAsset, RegisterStake, IssueCertificate, WithdrawStake, RequireSignature, RegisterPool, RetirePool, IncludeDatum, SetTTL, SetValidityStartInterval, SetIsValid" +constrs["TransactionBuilderStep"]="SpendOutput, Pay, MintAsset, IssueCertificate, WithdrawStake" constrs["OutputWitness"]="NativeScriptOutput, PlutusScriptOutput" constrs["CredentialWitness"]="NativeScriptCredential, PlutusScriptCredential" constrs["ScriptWitness"]="ScriptValue, ScriptReference" constrs["DatumWitness"]="DatumValue, DatumReference" constrs["RefInputAction"]="ReferenceInput, SpendInput" +constrs["ExpectedWitnessType"]="ScriptHashWitness, PubKeyHashWitness" +constrs["TxBuildError"]="WrongSpendWitnessType, IncorrectDatumHash, IncorrectScriptHash, WrongOutputType, WrongStakeCredentialType, DatumWitnessNotProvided, UnneededDatumWitness, UnneededDeregisterWitness, UnableToAddMints, RedeemerIndexingError, RedeemerIndexingInternalError, WrongNetworkId, ScriptHashAddressAndNoDatum, NoTransactionNetworkId" +constrs["Certificate"]="StakeRegistration, StakeDeregistration, StakeDelegation, PoolRegistration, PoolRetirement, GenesisKeyDelegation, MoveInstantaneousRewardsCert" +constrs["PlutusData"]="Constr, Map, List, Integer, Bytes" for d in "src" "test" "examples"; do echo "processing $d" diff --git a/spago-packages.nix b/spago-packages.nix index 25962cf811..9ecb540127 100644 --- a/spago-packages.nix +++ b/spago-packages.nix @@ -283,11 +283,11 @@ let "cardano-transaction-builder" = pkgs.stdenv.mkDerivation { name = "cardano-transaction-builder"; - version = "c93cfaaa08643632021fb8c6dcc4d0b8130250d1"; + version = "70d219d6463466458fd381b55d84f458dcaee94a"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-transaction-builder"; - rev = "c93cfaaa08643632021fb8c6dcc4d0b8130250d1"; - sha256 = "14hflxhl5g8yv43k4i7xh6lx5cf3vc0vzhy76jw2b4nrp83ks6l3"; + rev = "70d219d6463466458fd381b55d84f458dcaee94a"; + sha256 = "1148x79lxq2rr897cfspkrjspwyjgw5xm9b9188wvgf568703r3w"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; diff --git a/src/Contract/Transaction.purs b/src/Contract/Transaction.purs index 52bbd851e7..2974c376ec 100644 --- a/src/Contract/Transaction.purs +++ b/src/Contract/Transaction.purs @@ -62,13 +62,14 @@ import Cardano.Types.PoolPubKeyHash (PoolPubKeyHash(PoolPubKeyHash)) as X import Cardano.Types.ScriptRef (ScriptRef(NativeScriptRef, PlutusScriptRef)) as X import Cardano.Types.Transaction (Transaction(Transaction), empty) as X import Cardano.Types.Transaction as Transaction +import Contract.Log (logTrace') import Contract.Monad (Contract, runContractInEnv) import Contract.UnbalancedTx (mkUnbalancedTx) import Control.Monad.Error.Class (catchError, liftEither, throwError) import Control.Monad.Reader (ReaderT, asks, runReaderT) import Control.Monad.Reader.Class (ask) import Ctl.Internal.BalanceTx as B -import Ctl.Internal.BalanceTx.Constraints (BalanceTxConstraintsBuilder) +import Ctl.Internal.BalanceTx.Constraints (BalancerConstraints) import Ctl.Internal.BalanceTx.Error ( Actual(Actual) , BalanceTxError @@ -140,8 +141,7 @@ buildTx :: Array TransactionBuilderStep -> Contract Transaction buildTx steps = do - networkId <- asks _.networkId - case buildTransaction networkId steps of + case buildTransaction steps of Left err -> do throwError (error $ explainTxBuildError err) Right res -> pure res @@ -159,6 +159,7 @@ submit :: Transaction -> Contract TransactionHash submit tx = do + logTrace' $ "Submitting transaction: " <> show tx eiTxHash <- submitE tx liftEither $ flip lmap eiTxHash \err -> error $ "Failed to submit tx:\n" <> show err @@ -231,7 +232,7 @@ withBalancedTxs . Array { transaction :: Transaction , usedUtxos :: UtxoMap - , balancerConstraints :: BalanceTxConstraintsBuilder + , balancerConstraints :: BalancerConstraints } -> (Array Transaction -> Contract a) -> Contract a @@ -247,7 +248,7 @@ withBalancedTx :: forall (a :: Type) . Transaction -> UtxoMap - -> BalanceTxConstraintsBuilder + -> BalancerConstraints -> (Transaction -> Contract a) -> Contract a withBalancedTx tx usedUtxos balancerConstraints = @@ -262,12 +263,14 @@ withBalancedTx tx usedUtxos balancerConstraints = balanceTxE :: Transaction -> UtxoMap - -> BalanceTxConstraintsBuilder + -> BalancerConstraints -> Contract (Either BalanceTxError.BalanceTxError Transaction) balanceTxE tx utxos = B.balanceTxWithConstraints tx utxos -- | Balance a single transaction. -- | +-- | `UtxoMap` is a collection of UTxOs used as inputs that are coming from outside of the user wallet. +-- | -- | `balanceTxE` is a non-throwing version of this function. -- | -- | Use `balanceTxs` to balance multiple transactions and prevent them from @@ -275,7 +278,7 @@ balanceTxE tx utxos = B.balanceTxWithConstraints tx utxos balanceTx :: Transaction -> UtxoMap - -> BalanceTxConstraintsBuilder + -> BalancerConstraints -> Contract Transaction balanceTx utx utxos constraints = do result <- balanceTxE utx utxos constraints @@ -290,7 +293,7 @@ balanceTxs :: Array { transaction :: Transaction , usedUtxos :: UtxoMap - , balancerConstraints :: BalanceTxConstraintsBuilder + , balancerConstraints :: BalancerConstraints } -> Contract (Array Transaction) balanceTxs unbalancedTxs = @@ -305,7 +308,7 @@ balanceTxs unbalancedTxs = balanceAndLock :: { transaction :: Transaction , usedUtxos :: UtxoMap - , balancerConstraints :: BalanceTxConstraintsBuilder + , balancerConstraints :: BalancerConstraints } -> Contract Transaction balanceAndLock { transaction, usedUtxos, balancerConstraints } = do @@ -356,7 +359,7 @@ submitTxFromConstraints lookups constraints = do submitTxFromBuildPlan :: UtxoMap - -> BalanceTxConstraintsBuilder + -> BalancerConstraints -> Array TransactionBuilderStep -> Contract Transaction submitTxFromBuildPlan usedUtxos balancerConstraints plan = do diff --git a/src/Contract/Wallet/Key.purs b/src/Contract/Wallet/Key.purs index 3b962f04c5..d461402134 100644 --- a/src/Contract/Wallet/Key.purs +++ b/src/Contract/Wallet/Key.purs @@ -20,7 +20,10 @@ import Ctl.Internal.Wallet.Spec import Prim.TypeError (class Warn, Text) publicKeyFromPrivateKey - :: Warn (Text "Deprecated: use Cardano.Types.PrivateKey.toPublicKey") + :: Warn + ( Text + "Deprecated: publicKeyFromPrivateKey. Use Cardano.Types.PrivateKey.toPublicKey" + ) => PrivateKey -> PublicKey publicKeyFromPrivateKey = PrivateKey.toPublicKey diff --git a/templates/ctl-scaffold/packages.dhall b/templates/ctl-scaffold/packages.dhall index 8694c67083..38173545b8 100644 --- a/templates/ctl-scaffold/packages.dhall +++ b/templates/ctl-scaffold/packages.dhall @@ -535,7 +535,7 @@ let additions = ] , repo = "https://github.com/mlabs-haskell/purescript-cardano-transaction-builder" - , version = "c93cfaaa08643632021fb8c6dcc4d0b8130250d1" + , version = "70d219d6463466458fd381b55d84f458dcaee94a" } , cardano-transaction-lib = { dependencies = diff --git a/templates/ctl-scaffold/spago-packages.nix b/templates/ctl-scaffold/spago-packages.nix index 369921ee0e..bf447e8860 100644 --- a/templates/ctl-scaffold/spago-packages.nix +++ b/templates/ctl-scaffold/spago-packages.nix @@ -283,11 +283,11 @@ let "cardano-transaction-builder" = pkgs.stdenv.mkDerivation { name = "cardano-transaction-builder"; - version = "c93cfaaa08643632021fb8c6dcc4d0b8130250d1"; + version = "70d219d6463466458fd381b55d84f458dcaee94a"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-transaction-builder"; - rev = "c93cfaaa08643632021fb8c6dcc4d0b8130250d1"; - sha256 = "14hflxhl5g8yv43k4i7xh6lx5cf3vc0vzhy76jw2b4nrp83ks6l3"; + rev = "70d219d6463466458fd381b55d84f458dcaee94a"; + sha256 = "1148x79lxq2rr897cfspkrjspwyjgw5xm9b9188wvgf568703r3w"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; @@ -295,11 +295,11 @@ let "cardano-transaction-lib" = pkgs.stdenv.mkDerivation { name = "cardano-transaction-lib"; - version = "423e27b3f56b1a66db8d3126c22cea9bda7e50da"; + version = "dbc4608610b1e0d53e583b1402bf1f2765f7056f"; src = pkgs.fetchgit { url = "https://github.com/Plutonomicon/cardano-transaction-lib.git"; - rev = "423e27b3f56b1a66db8d3126c22cea9bda7e50da"; - sha256 = "0s3j719mvwl1r149xgig4zs8y775v0zx31p15k2rxfi4df6xyw2r"; + rev = "dbc4608610b1e0d53e583b1402bf1f2765f7056f"; + sha256 = "0j0318hibrpsivgl62nbgkkf1kd70fnqfd39ganf8amlc8sm82s2"; }; phases = "installPhase"; installPhase = "ln -s $src $out"; diff --git a/test/Plutip/Staking.purs b/test/Plutip/Staking.purs index d2b44f6b41..5c5093be87 100644 --- a/test/Plutip/Staking.purs +++ b/test/Plutip/Staking.purs @@ -7,28 +7,48 @@ import Prelude import Cardano.AsCbor (decodeCbor) import Cardano.Plutus.ApplyArgs (applyArgs) -import Cardano.Types (PoolParams(PoolParams), UnitInterval(UnitInterval)) -import Cardano.Types.BigInt as BigInt -import Cardano.Types.Credential - ( Credential(ScriptHashCredential, PubKeyHashCredential) +import Cardano.Transaction.Builder + ( CredentialWitness(NativeScriptCredential, PlutusScriptCredential) + , ScriptWitness(ScriptValue) + , TransactionBuilderStep(WithdrawRewards, IssueCertificate, Pay) + ) +import Cardano.Types + ( Certificate + ( StakeDelegation + , StakeRegistration + , StakeDeregistration + , PoolRetirement + , PoolRegistration + ) + , Credential(ScriptHashCredential, PubKeyHashCredential) + , OutputDatum(OutputDatum) + , PlutusData(Integer) + , PoolParams(PoolParams) + , TransactionOutput(TransactionOutput) + , UnitInterval(UnitInterval) + , _body + , _certs ) +import Cardano.Types.BigInt as BigInt import Cardano.Types.NativeScript as NativeScript -import Cardano.Types.PlutusData (PlutusData(Integer)) +import Cardano.Types.PlutusData as PlutusData import Cardano.Types.PlutusScript as PlutusScript -import Contract.Address (getNetworkId) +import Cardano.Types.PrivateKey as PrivateKey +import Cardano.Types.PublicKey as PublicKey +import Cardano.Types.RedeemerDatum as RedeemerDatum +import Cardano.Types.Transaction as Transaction +import Contract.Address (getNetworkId, mkAddress) import Contract.Backend.Ogmios (getPoolParameters) -import Contract.Hashing (publicKeyHash) import Contract.Log (logInfo') import Contract.Monad (Contract, liftedM) import Contract.Numeric.BigNum (fromInt, toBigInt) as BigNum -import Contract.PlutusData (unitDatum, unitRedeemer) import Contract.Prelude (liftM) import Contract.Prim.ByteArray (hexToByteArray) -import Contract.ScriptLookups as Lookups import Contract.Scripts (NativeScript(ScriptPubkey, ScriptAny)) import Contract.Staking ( getPoolIds , getPubKeyHashDelegationsAndRewards + , getStakeCredentialDelegationsAndRewards , getValidatorHashDelegationsAndRewards ) import Contract.Test.Mote (TestPlanM, interpretWithConfig) @@ -39,35 +59,18 @@ import Contract.Transaction ( Epoch(Epoch) , PoolPubKeyHash(PoolPubKeyHash) , balanceTx + , buildTx , mkPoolPubKeyHash , signTransaction ) -import Contract.TxConstraints - ( DatumPresence(DatumWitness) - , mustDelegateStakeNativeScript - , mustDelegateStakePlutusScript - , mustDelegateStakePubKey - , mustDeregisterStakeNativeScript - , mustDeregisterStakePlutusScript - , mustDeregisterStakePubKey - , mustPayToNativeScriptAddress - , mustPayToScriptAddress - , mustRegisterPool - , mustRegisterStakePubKey - , mustRegisterStakeScript - , mustRetirePool - , mustWithdrawStakeNativeScript - , mustWithdrawStakePlutusScript - , mustWithdrawStakePubKey - ) -import Contract.UnbalancedTx (mkUnbalancedTx) import Contract.Value (lovelaceValueOf) import Contract.Wallet ( ownPaymentPubKeyHashes , ownStakePubKeyHashes , withKeyWallet ) -import Contract.Wallet.Key (getPrivateStakeKey, publicKeyFromPrivateKey) +import Contract.Wallet.Key (getPrivateStakeKey) +import Control.Bind (bindFlipped) import Ctl.Examples.AlwaysSucceeds (alwaysSucceedsScript) import Ctl.Examples.Helpers (submitAndLog) import Ctl.Examples.IncludeDatum (only42Script) @@ -75,11 +78,12 @@ import Data.Array (head, (!!)) import Data.Array as Array import Data.Either (hush) import Data.Foldable (for_) +import Data.Lens ((.~)) +import Data.Map as Map import Data.Maybe (Maybe(Just, Nothing)) import Data.Newtype (unwrap, wrap) import Data.Posix.Signal (Signal(SIGINT)) import Data.Time.Duration (Seconds(Seconds)) -import Data.Tuple (Tuple(Tuple)) import Data.Tuple.Nested ((/\)) import Data.UInt as UInt import Effect (Effect) @@ -104,7 +108,7 @@ main :: Effect Unit main = interruptOnSignal SIGINT =<< launchAff do flip cancelWith (effectCanceler (exitCode 1)) do interpretWithConfig - defaultConfig { timeout = Just $ Milliseconds 450_000.0, exit = true } + defaultConfig { timeout = Just $ Milliseconds 90_000.0, exit = true } suite suite :: TestPlanM (Aff Unit) Unit @@ -137,38 +141,32 @@ suite = do , BigNum.fromInt 2_000_000_000 ] runPlutipContract config distribution $ flip withKeyWallet do - alicePkh /\ aliceStakePkh <- do - Tuple - <$> liftedM "Failed to get PKH" (head <$> ownPaymentPubKeyHashes) - <*> - liftedM "Failed to get Stake PKH" - (join <<< head <$> ownStakePubKeyHashes) + aliceStakePkh <- liftedM "Failed to get Stake PKH" + (join <<< head <$> ownStakePubKeyHashes) -- Register do let - constraints = mustRegisterStakePubKey aliceStakePkh - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh + transaction = Transaction.empty + # _body <<< _certs .~ + [ StakeRegistration $ wrap $ PubKeyHashCredential $ unwrap + aliceStakePkh + ] - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog + balanceTx transaction Map.empty mempty >>= signTransaction >>= + submitAndLog -- Deregister stake key do - let - constraints = mustDeregisterStakePubKey aliceStakePkh - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh + tx <- buildTx + [ IssueCertificate + ( StakeDeregistration $ wrap $ PubKeyHashCredential $ unwrap + aliceStakePkh + ) + Nothing + ] - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog test "PlutusScript" do let @@ -177,12 +175,6 @@ suite = do , BigNum.fromInt 2_000_000_000 ] runPlutipContract config distribution $ flip withKeyWallet do - alicePkh /\ aliceStakePkh <- do - Tuple - <$> liftedM "Failed to get PKH" (head <$> ownPaymentPubKeyHashes) - <*> - liftedM "Failed to get Stake PKH" - (join <<< head <$> ownStakePubKeyHashes) validator1 <- alwaysSucceedsScript validator2 <- do only42 <- only42Script @@ -195,33 +187,39 @@ suite = do -- Register do let - constraints = mustRegisterStakeScript validatorHash1 - <> mustRegisterStakeScript validatorHash2 - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh + tx = + Transaction.empty + # _body <<< _certs .~ + [ StakeRegistration $ wrap $ ScriptHashCredential + validatorHash1 + , StakeRegistration $ wrap $ ScriptHashCredential + validatorHash2 + ] - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog -- Deregister stake key do let - constraints = - mustDeregisterStakePlutusScript validator1 - unitRedeemer - <> mustDeregisterStakePlutusScript validator2 - unitRedeemer - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh + plan = + [ IssueCertificate + ( StakeDeregistration $ wrap $ ScriptHashCredential $ + PlutusScript.hash validator1 + ) + $ Just + $ PlutusScriptCredential (ScriptValue validator1) + RedeemerDatum.unit + , IssueCertificate + ( StakeDeregistration $ wrap $ ScriptHashCredential $ + PlutusScript.hash validator2 + ) + $ Just + $ PlutusScriptCredential (ScriptValue validator2) + RedeemerDatum.unit + ] - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog test "NativeScript" do let @@ -230,12 +228,8 @@ suite = do , BigNum.fromInt 2_000_000_000 ] runPlutipContract config distribution $ flip withKeyWallet do - alicePkh /\ aliceStakePkh <- do - Tuple - <$> liftedM "Failed to get PKH" (head <$> ownPaymentPubKeyHashes) - <*> - liftedM "Failed to get Stake PKH" - (join <<< head <$> ownStakePubKeyHashes) + alicePkh <- liftedM "Failed to get PKH" + (head <$> ownPaymentPubKeyHashes) let nativeScript = ScriptAny [ ScriptPubkey $ unwrap alicePkh ] @@ -244,28 +238,29 @@ suite = do -- Register do let - constraints = mustRegisterStakeScript stakeValidatorHash + tx = + Transaction.empty + # _body <<< _certs .~ + [ StakeRegistration $ wrap $ ScriptHashCredential + stakeValidatorHash + ] - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog -- Deregister stake key do let - constraints = mustDeregisterStakeNativeScript nativeScript - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh + credential = wrap $ ScriptHashCredential $ NativeScript.hash + nativeScript + plan = + [ IssueCertificate (StakeDeregistration credential) + $ Just + $ NativeScriptCredential + $ ScriptValue nativeScript + ] - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog test "Pool registration & retirement" do let @@ -274,31 +269,26 @@ suite = do , BigNum.fromInt 2_000_000_000 ] runPlutipContract config distribution \alice -> withKeyWallet alice do - alicePkh /\ aliceStakePkh <- Tuple - <$> liftedM "Failed to get PKH" (head <$> ownPaymentPubKeyHashes) - <*> liftedM "Failed to get Stake PKH" - (join <<< head <$> ownStakePubKeyHashes) + aliceStakePkh <- liftedM "Failed to get Stake PKH" + (join <<< head <$> ownStakePubKeyHashes) -- Register stake key do let - constraints = mustRegisterStakePubKey aliceStakePkh - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh + credential = wrap $ PubKeyHashCredential $ unwrap aliceStakePkh - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog + plan = + [ IssueCertificate (StakeRegistration credential) Nothing ] + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog kwMStakeKey <- liftAff $ getPrivateStakeKey alice privateStakeKey <- liftM (error "Failed to get private stake key") kwMStakeKey networkId <- getNetworkId let - poolOperator = PoolPubKeyHash $ publicKeyHash $ - publicKeyFromPrivateKey (unwrap privateStakeKey) + poolOperator = PoolPubKeyHash $ PublicKey.hash $ + PrivateKey.toPublicKey (unwrap privateStakeKey) -- Register pool do @@ -324,23 +314,19 @@ suite = do } , rewardAccount , poolOwners: - [ publicKeyHash $ - publicKeyFromPrivateKey + [ PublicKey.hash $ + PrivateKey.toPublicKey (unwrap privateStakeKey) ] , relays: [] , poolMetadata: Nothing } - constraints = mustRegisterPool poolParams + tx = + Transaction.empty # _body <<< _certs .~ + [ PoolRegistration poolParams ] - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog -- List pools: the pool must appear in the list do @@ -359,15 +345,12 @@ suite = do -- Retire pool do let - constraints = mustRetirePool poolOperator retirementEpoch - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog + tx = + Transaction.empty # _body <<< _certs .~ + [ PoolRetirement + { poolKeyHash: poolOperator, epoch: retirementEpoch } + ] + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog let waitEpoch :: Epoch -> Contract Epoch @@ -395,43 +378,40 @@ suite = do ] runPlutipContract config distribution \alice -> withKeyWallet alice do - alicePkh /\ aliceStakePkh <- Tuple - <$> liftedM "Failed to get PKH" (head <$> ownPaymentPubKeyHashes) - <*> liftedM "Failed to get Stake PKH" - (join <<< head <$> ownStakePubKeyHashes) validator <- alwaysSucceedsScript let validatorHash = PlutusScript.hash validator -- Lock funds on the stake script do + address <- mkAddress (wrap $ ScriptHashCredential validatorHash) + (Just $ wrap $ ScriptHashCredential $ validatorHash) let - constraints = - mustPayToScriptAddress validatorHash - (ScriptHashCredential validatorHash) - unitDatum - DatumWitness - $ lovelaceValueOf - $ BigNum.fromInt 1_000_000_000 - - lookups :: Lookups.ScriptLookups - lookups = mempty - - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= + plan = + [ Pay $ TransactionOutput + { address + , datum: Just $ OutputDatum PlutusData.unit + , amount: lovelaceValueOf + $ BigNum.fromInt 1_000_000_000 + , scriptRef: Nothing + } + ] + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog -- Register stake script do let - constraints = - mustRegisterStakeScript validatorHash - - lookups :: Lookups.ScriptLookups - lookups = mempty - - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= + credential = wrap $ ScriptHashCredential validatorHash + tx <- buildTx + [ IssueCertificate (StakeRegistration credential) + $ Just + $ PlutusScriptCredential + (ScriptValue validator) + RedeemerDatum.unit + ] + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog -- Select a pool @@ -440,15 +420,17 @@ suite = do -- Delegate do let - constraints = - mustDelegateStakePlutusScript validator unitRedeemer poolId - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= + credential = wrap $ ScriptHashCredential $ PlutusScript.hash + validator + plan = + [ IssueCertificate (StakeDeregistration credential) + $ Just + $ PlutusScriptCredential + (ScriptValue validator) + RedeemerDatum.unit + ] + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog -- Wait until rewards @@ -472,15 +454,22 @@ suite = do -- Withdraw do let - constraints = - mustWithdrawStakePlutusScript validator unitRedeemer - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= + credential = wrap $ ScriptHashCredential $ PlutusScript.hash + validator + + rewardsAmount <- liftedM "Unable to get rewards" $ + getStakeCredentialDelegationsAndRewards credential <#> + bindFlipped _.rewards + let + plan = + [ WithdrawRewards credential rewardsAmount + $ Just + ( PlutusScriptCredential (ScriptValue validator) + RedeemerDatum.unit + ) + ] + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog -- Check rewards. @@ -507,47 +496,46 @@ suite = do , BigNum.fromInt 2_000_000_000 ] runPlutipContract config distribution \(alice /\ bob) -> do - bobPkh /\ bobStakePkh <- withKeyWallet bob do - Tuple - <$> liftedM "Failed to get PKH" (head <$> ownPaymentPubKeyHashes) - <*> liftedM "Failed to get Stake PKH" - (join <<< head <$> ownStakePubKeyHashes) + bobStakePkh <- withKeyWallet bob do + liftedM "Failed to get Stake PKH" + (join <<< head <$> ownStakePubKeyHashes) let nativeScript = ScriptAny [ ScriptPubkey $ unwrap bobStakePkh ] scriptHash = NativeScript.hash nativeScript + credential = wrap $ ScriptHashCredential $ NativeScript.hash + nativeScript -- Alice withKeyWallet alice do -- She locks funds on the stake script (no need for her to validate -- the script in order to do that) do + address <- mkAddress (wrap $ ScriptHashCredential scriptHash) + (Just $ wrap $ ScriptHashCredential scriptHash) let - constraints = - mustPayToNativeScriptAddress - scriptHash - (ScriptHashCredential scriptHash) - $ lovelaceValueOf - $ BigNum.fromInt 1_000_000_000 - - lookups :: Lookups.ScriptLookups - lookups = mempty - - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= + plan = + [ Pay $ TransactionOutput + { address + , datum: Just $ OutputDatum PlutusData.unit + , amount: lovelaceValueOf + $ BigNum.fromInt 1_000_000_000 + , scriptRef: Nothing + } + ] + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog -- Alice registers stake script (again, no need to validate it) do - let - constraints = - mustRegisterStakeScript scriptHash - - lookups :: Lookups.ScriptLookups - lookups = mempty - - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= + tx <- buildTx + [ IssueCertificate (StakeRegistration credential) + $ Just + $ NativeScriptCredential + $ ScriptValue nativeScript + ] + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog -- Bob performs operations with the stake script that require his @@ -559,16 +547,19 @@ suite = do -- Delegate do - let - constraints = - mustDelegateStakeNativeScript nativeScript poolId - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash bobPkh <> - Lookups.ownStakePubKeyHash bobStakePkh - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= + tx <- buildTx + [ IssueCertificate + ( StakeDelegation + ( wrap $ ScriptHashCredential $ NativeScript.hash + nativeScript + ) + poolId + ) + $ Just + $ NativeScriptCredential + $ ScriptValue nativeScript + ] + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog -- Wait until rewards @@ -591,16 +582,16 @@ suite = do -- Withdraw do + rewardsAmount <- liftedM "Unable to get rewards" $ + getStakeCredentialDelegationsAndRewards credential <#> + bindFlipped _.rewards let - constraints = - mustWithdrawStakeNativeScript nativeScript - - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash bobPkh <> - Lookups.ownStakePubKeyHash bobStakePkh - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= + plan = + [ WithdrawRewards credential rewardsAmount + $ Just (NativeScriptCredential (ScriptValue nativeScript)) + ] + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog -- Check rewards. @@ -622,38 +613,35 @@ suite = do ] runPlutipContract config distribution \alice -> withKeyWallet alice do - alicePkh /\ aliceStakePkh <- Tuple - <$> liftedM "Failed to get PKH" (head <$> ownPaymentPubKeyHashes) - <*> liftedM "Failed to get Stake PKH" - (join <<< head <$> ownStakePubKeyHashes) + aliceStakePkh <- liftedM "Failed to get Stake PKH" + (join <<< head <$> ownStakePubKeyHashes) -- Register stake key do let - constraints = mustRegisterStakePubKey aliceStakePkh + tx = Transaction.empty + # _body <<< _certs .~ + [ StakeRegistration $ wrap $ PubKeyHashCredential $ unwrap $ + aliceStakePkh + ] - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog -- Select a pool ID poolId <- selectPoolId -- Delegate do - let - constraints = - mustDelegateStakePubKey aliceStakePkh poolId + tx <- buildTx + [ IssueCertificate + ( StakeDelegation + (wrap $ PubKeyHashCredential $ unwrap aliceStakePkh) + poolId + ) + Nothing + ] - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog -- Wait until rewards let @@ -679,15 +667,16 @@ suite = do -- Withdraw do let - constraints = - mustWithdrawStakePubKey aliceStakePkh + credential = wrap $ PubKeyHashCredential $ unwrap aliceStakePkh - lookups :: Lookups.ScriptLookups - lookups = - Lookups.ownPaymentPubKeyHash alicePkh <> - Lookups.ownStakePubKeyHash aliceStakePkh - ubTx /\ usedUtxos <- mkUnbalancedTx lookups constraints - balanceTx ubTx usedUtxos mempty >>= signTransaction >>= submitAndLog + rewardsAmount <- liftedM "Unable to get rewards" $ + getStakeCredentialDelegationsAndRewards credential <#> + bindFlipped _.rewards + let + plan = + [ WithdrawRewards credential rewardsAmount Nothing ] + tx <- buildTx plan + balanceTx tx Map.empty mempty >>= signTransaction >>= submitAndLog -- Check rewards. -- Not going to deregister here, because the rewards are added too @@ -711,4 +700,5 @@ suite = do { slotLength = Seconds 0.05 , epochSize = Just $ UInt.fromInt 80 } + -- , suppressLogs = false } From 7bd7a323107d55b66fe2116b75419b43351e13ad Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Tue, 23 Jul 2024 21:41:46 +0400 Subject: [PATCH 48/52] Update CHANGELOG --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 484bf7de67..dee2bb3dce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,7 +72,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Deprecated -- **IMPORTANT** Constraints interface (`Contract.TxConstraints`) has been deprecated and will be removed in a future version. Please use [`purescript-cardano-transaction-builder`](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder) for any new contracts. +> [!WARNING] +> **IMPORTANT** Constraints interface (`Contract.TxConstraints` & `Contract.ScriptLookups`) has been deprecated and will be removed in a future version. Please use [`purescript-cardano-transaction-builder`](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder) (via `Contract.Transaction.buildTx`) for new contracts. The motivation for deprecation is that it was unnecessarily complex, not flexible enough, and existed only because of the desire to provide code-level compatibility with PAB. See [this Catalyst proposal](https://cardano.ideascale.com/c/idea/101478) for more info. ### Added @@ -86,8 +87,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - **IMPORTANT** `UnbalancedTx` type has been removed. This change was motivated by the fact that `UnbalancedTx` existed simply to tie together transaction building and balancing by keeping extra context. Now that transaction builder is placed in [its own package](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder), there is no more need in `UnbalancedTx`, that is not used with the new builder. - **IMPORTANT** `Contract.Scripts.applyArgs` - use `Cardano.Plutus.ApplyArgs.applyArgs` from [purescript-uplc-apply-args](https://github.com/mlabs-haskell/purescript-uplc-apply-args) - **IMPORTANT** `balanceTxWithConstraints` - use `balanceTx` -- `Contract.Transaction.submitTxFromConstraintsReturningFee` - too niche case to be allowed in the public API. -- `Contract.Transaction` lens values. +- `Contract.Transaction.submitTxFromConstraintsReturningFee` - too niche use case to be allowed in the public API. +- `Contract.Transaction` lens values. Use lenses from `Cardano.Types.Transaction` ### Changed From 25a27030a513813817462dccbb0adc02d7cc3c3f Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Tue, 23 Jul 2024 21:46:34 +0400 Subject: [PATCH 49/52] Fix CI --- templates/ctl-scaffold/flake.lock | 8 ++++---- templates/ctl-scaffold/flake.nix | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/ctl-scaffold/flake.lock b/templates/ctl-scaffold/flake.lock index 8a0100234f..f4003614da 100644 --- a/templates/ctl-scaffold/flake.lock +++ b/templates/ctl-scaffold/flake.lock @@ -1686,17 +1686,17 @@ "plutip": "plutip" }, "locked": { - "lastModified": 1713303538, - "narHash": "sha256-WXDfjWskup7FLOGG0T/Y5RyP9Ccvvp5IyIHyXVM4cmg=", + "lastModified": 1721324763, + "narHash": "sha256-QgtUNWK0KuSsemk0h60Dp83g5nzLCkPfjvrmFSEKA0g=", "owner": "Plutonomicon", "repo": "cardano-transaction-lib", - "rev": "423e27b3f56b1a66db8d3126c22cea9bda7e50da", + "rev": "dbc4608610b1e0d53e583b1402bf1f2765f7056f", "type": "github" }, "original": { "owner": "Plutonomicon", "repo": "cardano-transaction-lib", - "rev": "423e27b3f56b1a66db8d3126c22cea9bda7e50da", + "rev": "dbc4608610b1e0d53e583b1402bf1f2765f7056f", "type": "github" } }, diff --git a/templates/ctl-scaffold/flake.nix b/templates/ctl-scaffold/flake.nix index 6b29765ca9..93b1b84880 100644 --- a/templates/ctl-scaffold/flake.nix +++ b/templates/ctl-scaffold/flake.nix @@ -16,7 +16,7 @@ type = "github"; owner = "Plutonomicon"; repo = "cardano-transaction-lib"; - rev = "423e27b3f56b1a66db8d3126c22cea9bda7e50da"; + rev = "dbc4608610b1e0d53e583b1402bf1f2765f7056f"; }; # To use the same version of `nixpkgs` as we do nixpkgs.follows = "ctl/nixpkgs"; From ddbd601e882276958fe260b8c492b5c7f489f174 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Wed, 24 Jul 2024 00:10:40 +0400 Subject: [PATCH 50/52] Update dependency versions --- doc/getting-started.md | 2 +- packages.dhall | 4 ++-- spago-packages.nix | 4 ++-- templates/ctl-scaffold/packages.dhall | 4 ++-- templates/ctl-scaffold/spago-packages.nix | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/getting-started.md b/doc/getting-started.md index 41b1de8099..280e5a724b 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -51,7 +51,7 @@ You can learn more about using CTL as a dependency [here](./ctl-as-dependency.md ### Other prerequisites -You will also need to become familiar with [CTL's runtime](./runtime.md) as its runtime services are required for executing virtually all contracts. +You will also need to become familiar with [CTL's runtime](./runtime.md) as its runtime services are required for executing virtually all contracts. If you want to avoid manual backend setup, use [blockfrost.io](./blockfrost.md). ## Importing CTL modules diff --git a/packages.dhall b/packages.dhall index 23decc6196..cd898c6efe 100644 --- a/packages.dhall +++ b/packages.dhall @@ -435,7 +435,7 @@ let additions = , "unsafe-coerce" ] , repo = "https://github.com/mlabs-haskell/purescript-cardano-types" - , version = "40d9468a4712ad2bf57ebede19fae92208f082a0" + , version = "v1.0.2" } , cardano-message-signing = { dependencies = @@ -516,7 +516,7 @@ let additions = ] , repo = "https://github.com/mlabs-haskell/purescript-cardano-transaction-builder" - , version = "70d219d6463466458fd381b55d84f458dcaee94a" + , version = "v1.0.0" } , mote-testplan = { dependencies = diff --git a/spago-packages.nix b/spago-packages.nix index 9ecb540127..28853d177c 100644 --- a/spago-packages.nix +++ b/spago-packages.nix @@ -283,7 +283,7 @@ let "cardano-transaction-builder" = pkgs.stdenv.mkDerivation { name = "cardano-transaction-builder"; - version = "70d219d6463466458fd381b55d84f458dcaee94a"; + version = "v1.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-transaction-builder"; rev = "70d219d6463466458fd381b55d84f458dcaee94a"; @@ -295,7 +295,7 @@ let "cardano-types" = pkgs.stdenv.mkDerivation { name = "cardano-types"; - version = "40d9468a4712ad2bf57ebede19fae92208f082a0"; + version = "v1.0.2"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-types"; rev = "40d9468a4712ad2bf57ebede19fae92208f082a0"; diff --git a/templates/ctl-scaffold/packages.dhall b/templates/ctl-scaffold/packages.dhall index 38173545b8..195b841513 100644 --- a/templates/ctl-scaffold/packages.dhall +++ b/templates/ctl-scaffold/packages.dhall @@ -435,7 +435,7 @@ let additions = , "unsafe-coerce" ] , repo = "https://github.com/mlabs-haskell/purescript-cardano-types" - , version = "40d9468a4712ad2bf57ebede19fae92208f082a0" + , version = "v1.0.2" } , cardano-message-signing = { dependencies = @@ -535,7 +535,7 @@ let additions = ] , repo = "https://github.com/mlabs-haskell/purescript-cardano-transaction-builder" - , version = "70d219d6463466458fd381b55d84f458dcaee94a" + , version = "v1.0.0" } , cardano-transaction-lib = { dependencies = diff --git a/templates/ctl-scaffold/spago-packages.nix b/templates/ctl-scaffold/spago-packages.nix index bf447e8860..6a363d2f3d 100644 --- a/templates/ctl-scaffold/spago-packages.nix +++ b/templates/ctl-scaffold/spago-packages.nix @@ -283,7 +283,7 @@ let "cardano-transaction-builder" = pkgs.stdenv.mkDerivation { name = "cardano-transaction-builder"; - version = "70d219d6463466458fd381b55d84f458dcaee94a"; + version = "v1.0.0"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-transaction-builder"; rev = "70d219d6463466458fd381b55d84f458dcaee94a"; @@ -307,7 +307,7 @@ let "cardano-types" = pkgs.stdenv.mkDerivation { name = "cardano-types"; - version = "40d9468a4712ad2bf57ebede19fae92208f082a0"; + version = "v1.0.2"; src = pkgs.fetchgit { url = "https://github.com/mlabs-haskell/purescript-cardano-types"; rev = "40d9468a4712ad2bf57ebede19fae92208f082a0"; From 372a3c774ac811a4e344ac5a5a8f014b250d0874 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Wed, 24 Jul 2024 14:56:55 +0400 Subject: [PATCH 51/52] Prepare v9.0.0 --- CHANGELOG.md | 16 +++++++++------- templates/ctl-scaffold/flake.lock | 8 ++++---- templates/ctl-scaffold/flake.nix | 2 +- templates/ctl-scaffold/packages.dhall | 2 +- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dee2bb3dce..de51e725b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) -- [[Unreleased]](#unreleased) +- [[v9.0.0]](#v900) - [Deprecated](#deprecated) - [Added](#added) - [Removed](#removed) @@ -68,7 +68,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) -## [Unreleased] +## [v9.0.0] ### Deprecated @@ -78,23 +78,25 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Added - `Contract.Transaction.buildTx :: Array TransactionBuilderStep -> Contract Transaction` that provides a `Contract`-based interface for the [new transaction builder](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder). -- `submitTxFromBuildPlan :: UtxoMap -> BalanceTxConstraintsBuilder -> Array TransactionBuilderStep -> Contract Transaction` - a convenience function that executes the whole transaction creation pipeline starting from a build plan for [the new transaction builder](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder). +- `Contract.Transaction.submitTxFromBuildPlan :: UtxoMap -> BalanceTxConstraintsBuilder -> Array TransactionBuilderStep -> Contract Transaction` - a convenience function that executes the whole transaction creation pipeline starting from a build plan for [the new transaction builder](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder). - `Contract.ClientError.pprintClientError` to provide readable error reports. - `Contract.Staking.getStakeCredentialDelegationsAndRewards` utility function ### Removed - **IMPORTANT** `UnbalancedTx` type has been removed. This change was motivated by the fact that `UnbalancedTx` existed simply to tie together transaction building and balancing by keeping extra context. Now that transaction builder is placed in [its own package](https://github.com/mlabs-haskell/purescript-cardano-transaction-builder), there is no more need in `UnbalancedTx`, that is not used with the new builder. -- **IMPORTANT** `Contract.Scripts.applyArgs` - use `Cardano.Plutus.ApplyArgs.applyArgs` from [purescript-uplc-apply-args](https://github.com/mlabs-haskell/purescript-uplc-apply-args) -- **IMPORTANT** `balanceTxWithConstraints` - use `balanceTx` +- **IMPORTANT** `balanceTxWithConstraints`, `balanceTxWithConstraintsE` - use `balanceTx` +- **IMPORTANT** `balanceTxsWithConstraints` - use `balanceTxs` +- **IMPORTANT** `withBalancedTxWithConstraints`, `withBalancedTxWithConstraints` - use `withBalancedTxs` +- **IMPORTANT** `Contract.Scripts.applyArgs` - use `Cardano.Plutus.ApplyArgs.applyArgs` from [purescript-uplc-apply-args](https://github.com/mlabs-haskell/purescript-uplc-apply-args). - `Contract.Transaction.submitTxFromConstraintsReturningFee` - too niche use case to be allowed in the public API. - `Contract.Transaction` lens values. Use lenses from `Cardano.Types.Transaction` ### Changed -- `Contract.Transaction.mkUnbalancedTx` now returns a tuple: a transaction and its used UTxOs. +- `Contract.Transaction.mkUnbalancedTx` now returns a tuple: a transaction and the UTxOs it used. - `Contract.Transaction.balanceTx` accepts two extra argument: a list of used UTxOs (set to `Data.Map.empty` if none of them are coming from the outside of the wallet) and balancer constraints (set to `mempty` if not needed) -- Default synchronization parameters: all [wallet <-> query layer synchronization primitives](./doc/query-layers.md) are now off by default. The reason is that the runtime overhead made the users unhappy and it was not worth it for most of the users. If your dApp sends transactions in quick succession, consider enabling the synchronization again. +- Default synchronization parameters: all [wallet <-> query layer synchronization primitives](./doc/query-layers.md) are now off by default. The reason is that the runtime overhead made the users unhappy and it was not worth it for most of the users. If your dApp sends transactions in quick succession, consider enabling the synchronization again by using `softSynchronizationParams` (old behavior) or `strictSynchronizationParams`. - `BalanceTxConstraintsBuilder` has been renamed to `BalancerConstraints`. It is still available under the old name as a type synonym. ### Fixed diff --git a/templates/ctl-scaffold/flake.lock b/templates/ctl-scaffold/flake.lock index f4003614da..64625f7621 100644 --- a/templates/ctl-scaffold/flake.lock +++ b/templates/ctl-scaffold/flake.lock @@ -1686,17 +1686,17 @@ "plutip": "plutip" }, "locked": { - "lastModified": 1721324763, - "narHash": "sha256-QgtUNWK0KuSsemk0h60Dp83g5nzLCkPfjvrmFSEKA0g=", + "lastModified": 1721765440, + "narHash": "sha256-H54m6RQRxb83z1IEp1y3krmQk7+SspymnSNaCKQm8LU=", "owner": "Plutonomicon", "repo": "cardano-transaction-lib", - "rev": "dbc4608610b1e0d53e583b1402bf1f2765f7056f", + "rev": "ddbd601e882276958fe260b8c492b5c7f489f174", "type": "github" }, "original": { "owner": "Plutonomicon", "repo": "cardano-transaction-lib", - "rev": "dbc4608610b1e0d53e583b1402bf1f2765f7056f", + "rev": "ddbd601e882276958fe260b8c492b5c7f489f174", "type": "github" } }, diff --git a/templates/ctl-scaffold/flake.nix b/templates/ctl-scaffold/flake.nix index 93b1b84880..e9b27874be 100644 --- a/templates/ctl-scaffold/flake.nix +++ b/templates/ctl-scaffold/flake.nix @@ -16,7 +16,7 @@ type = "github"; owner = "Plutonomicon"; repo = "cardano-transaction-lib"; - rev = "dbc4608610b1e0d53e583b1402bf1f2765f7056f"; + rev = "ddbd601e882276958fe260b8c492b5c7f489f174"; }; # To use the same version of `nixpkgs` as we do nixpkgs.follows = "ctl/nixpkgs"; diff --git a/templates/ctl-scaffold/packages.dhall b/templates/ctl-scaffold/packages.dhall index 195b841513..06e2d6e6da 100644 --- a/templates/ctl-scaffold/packages.dhall +++ b/templates/ctl-scaffold/packages.dhall @@ -642,7 +642,7 @@ let additions = , "web-storage" ] , repo = "https://github.com/Plutonomicon/cardano-transaction-lib.git" - , version = "dbc4608610b1e0d53e583b1402bf1f2765f7056f" + , version = "ddbd601e882276958fe260b8c492b5c7f489f174" } } From c02737564866f4f5a1d82ddf0e59eea6241c91a1 Mon Sep 17 00:00:00 2001 From: Vladimir Kalnitsky Date: Wed, 24 Jul 2024 14:59:01 +0400 Subject: [PATCH 52/52] Fix CI --- templates/ctl-scaffold/spago-packages.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/ctl-scaffold/spago-packages.nix b/templates/ctl-scaffold/spago-packages.nix index 6a363d2f3d..7d7a8b3d1d 100644 --- a/templates/ctl-scaffold/spago-packages.nix +++ b/templates/ctl-scaffold/spago-packages.nix @@ -295,11 +295,11 @@ let "cardano-transaction-lib" = pkgs.stdenv.mkDerivation { name = "cardano-transaction-lib"; - version = "dbc4608610b1e0d53e583b1402bf1f2765f7056f"; + version = "ddbd601e882276958fe260b8c492b5c7f489f174"; src = pkgs.fetchgit { url = "https://github.com/Plutonomicon/cardano-transaction-lib.git"; - rev = "dbc4608610b1e0d53e583b1402bf1f2765f7056f"; - sha256 = "0j0318hibrpsivgl62nbgkkf1kd70fnqfd39ganf8amlc8sm82s2"; + rev = "ddbd601e882276958fe260b8c492b5c7f489f174"; + sha256 = "1dgh4sj0hni3knk9rcljpy9r1fcjnxfaf12jrwvvzi8i2kljd7hz"; }; phases = "installPhase"; installPhase = "ln -s $src $out";