- This cheastsheet is quick reminder, not a tutorial about
cooked-validators
. - Minimum prior knowledge (Cardano, general idea of what
cooked-validators
is about) is expected. - It reminds how to use or help discover
cooked-validators
features. - Code snippets are not usable as is, they give intuition and direction. Adapt them to your use case.
- In a test
Tasty.testCase "foo" $ C.testSucceeds foo
Tasty.testCase "foo" $ C.testFails foo
- In the REPL
printCooked $ interpretAndRun foo
for all tracesprintCooked $ runMockChain foo
forMonadBlockChain
traces only
- With values only
initDist :: InitialDistribution initDist = distributionFromList $ [ (wallet 1 , [ ada 42 , ada 2 <> quickValue "TOK" 1 ] , (wallet 2 , [ ada 10 ]) , (wallet 3 , [ ada 10 <> permanentValue "XYZ" 10]) ]
- With arbitrary payments
initDist :: InitialDistribution initDist = InitialDistribution [ wallet 3 `receives` (Value $ ada 6) , fooTypedValidator `receives` (Value (myToken 6) <&&> InlineDatum fooTypedDatum) , wallet 2 `receives` (Value (ada 2) <&&> VisibleHashedDatum fooDatum) , wallet 1 `receives` (Value (ada 10) <&&> ReferenceScript fooValidator <&&> StakingCredential cred) ]
- In a test
Tasty.testCase "foo" $ testSucceedsFrom def initDist foo
- In the REPL
printCooked $ interpretAndRunWith (runMockChainTFrom initDist) foo
pcOpts :: C.PrettyCookedOpts
pcOpts =
def
{ C.pcOptHashes =
def
{ C.pcOptHashNames =
C.hashNamesFromList
[ (alice, "Alice"),
(bob, "Bob"),
(carrie, "Carie")
]
<> C.hashNamesFromList
[ (nftCurrencySymbol, "NFT"),
(customCoinsCurrencySymbol, "Custom Coins")
]
<> C.hashNamesFromList
[ (fooValidator, "Foo")
]
<> C.defaultHashNames -- IMPORTANT: must be the last element
}
}
foo :: MonadBlockChain m => m ()
foo = do
transactionOrEndpoint1
transactionOrEndpoint2
transactionOrEndpoint3
foo :: MonadBlockChain m => m ()
foo = do
...
(firstMsOfCurrentSlot, lastMsOfCurrentSlot) <- currentTime
...
foo :: MonadBlockChain m => m ()
foo = do
...
(firstMsOfCurrentSlot, lastMsOfCurrentSlot) <- currentTime
targetSlot <- getEnclosingSlot $ lastMsOfCurrentSlot + 3_600_000 -- 1 hour
awaitSlot targetSlot
...
- ... get the validated Cardano transaction
foo :: MonadBlockChain m => m () foo = do ... cardanoTx <- validateTxSkel $ txSkelTemplate { txSkelIns = ..., txSkelOuts = ..., txSkelMints = ..., txSkelSigners = ... } ...
- ... get the generated
TxOutRef
sfoo :: MonadBlockChain m => m () foo = do ... txOutRefs <- validateTxSkel' $ txSkelTemplate { txSkelIns = ..., txSkelOuts = ..., txSkelMints = ..., txSkelSigners = ... } ...
- 10 wallets:
wallet 1
towallet 10
walletAddress (wallet 3)
walletPKHash (wallet 2)
txSkelTemplate
{ ...
txSkelSigners = [wallet 1]
...
}
- A simple value to a wallet:
wallet 3 `receives` Value (ada 3)
- A value and an inline datum to a script:
fooTypedValidator `receives` (InlineDatum FooTypedDatum <&&> Value (myToken 4 <> lovelace 160_000))
- Hashed datums (visible to the transaction or hidden from it):
... <&&> (VisibleHashedDatum dat)
or... <&&> (HiddenHashedDatum dat)
- A reference script:
(... <&&> ReferenceScript dat)
- A staking credential:
(... <&&> StakingCredential dat)
txSkelTemplate
{ ...
txSkelOuts = [party1 `receives` payment1, party2 `receives` payment2, ...]
...
}
- No redeemer:
txSkelEmptyRedeemer
- With a given redeemer:
txSkelSomeRedeemer
- A redeemer and a reference script:
txSkelSomeRedeemerAndReferenceScript
- No redeemer but a reference script:
txSkelEmptyRedeemerAndReferenceScript
txSkelTemplate
{ ...
txSkelIns = Map.fromList [(txOutRef1, myRedeemer1), (txOutRef2, myRedeemer2]
...
}
- ... the Cardano transaction
endpointFoo :: MonadBlockChain m => m (Api.TxOutRef, Api.TxOutRef) endpointFoo = do cTx <- validateTxSkel $ txSkelTemplate { ..., ... } let (txOutRef1, _) : (txOutRef2, _) : _ = utxosFromCardanoTx cTx return (txOutRef1, txOutRef2)
- ... the returns
TxOutRef
sendpointFoo :: MonadBlockChain m => m (Api.TxOutRef, Api.TxOutRef) endpointFoo = do txOutRef1 : txOutRef2 : _ <- validateTxSkel' $ txSkelTemplate { ..., ... } return (txOutRef1, txOutRef2)
foo :: MonadBlockChain m => Api.TxOutRef -> m ()
foo txOutRef = do
Just txOut <- txOutByRef txOutRef
foo :: MonadBlockChain m => Api.TxOutRef -> m ()
foo txOutRef = do
Just address <- outputAddress <$> txOutByRef txOutRef
Just value <- valueFromTxOutRef txOutRef
Just datum <- typedDatumFromTxOutRef @typeOfDatum txOutRef
-
Mint tokens: positive amount
-
Burn tokens: negative amount
-
No redeemer:
(Script.Versioned fooPolicy Script.PlutusV3, txSkelEmptyRedeemer, "fooName", 3)
-
With redeemer:
(Script.Versioned barPolicy Script.PlutusV3, txSkelSomeRedeemer typedRedeemer, "barName", -3)
-
With a redeemer and reference script:
(Script.Versioned barPolicy Script.PlutusV3, txSkelSomeRedeemerAndReferenceScript txOutRef typedRedeemer, "barName", 12)
-
With no redeemer but a reference script:
(Script.Versioned barPolicy Script.PlutusV3, txSkelEmptyRedeemerAndReferenceScript txOutRef, "fooName", -6)
txSkelTemplate
{ ...
txSkelMints = txSkelMintsFromList
[ (Script.Versioned fooPolicy Script.PlutusV3, ..., ..., ...),
(Script.Versioned barPolicy Script.PlutusV3, ..., ..., ...)
]
...
}
- allow min ADA adjustment, by providing a value:
party `receives` (Value (myToken 5))
- allow min ADA adjustment, by providing no value:
party `receives` (Datum myDatum)
- forbid min ADA adjustment:
party `receives` (FixedValue $ ada 10)
distributionFromList [..., (... <> permanentValue "customToken" 1000), ...]
party `receives` ... (permanentValue "customToken" 7)
txSkelTemplate
{ ...
txSkelInsReference = Set.fromList [txOutRef1, txOutRef2, ...]
...
}
txSkelTemplate
{ ...
txSkelIns = Map.fromList [(scriptTxOutRefToSpend, txSkelSomeRedeemerForReferencedScript txOutRefCarryingReferenceScript redeemer), ...],
...
}
First signer (default):
txSkelTemplate
{ ...
txSkelSigners = [wallet 1, wallet 2]
...
}
Another signer:
txSkelTemplate
{ ...
txSkelSigners = [wallet 1, wallet 2],
txOpts = def {txOptBalancingPolicy = BalanceWith (wallet 2)}
...
}
txSkelTemplate
{ ...
txSkelSigners = [wallet 1, wallet 2],
txOpts = def {txOptBalancingPolicy = DoNotBalance}
...
}
From first signer (default):
txSkelTemplate
{ ...
txSkelSigners = [wallet 1, wallet 2]
...
}
From another wallet:
txSkelTemplate
{ ...
txSkelSigners = [wallet 1],
txSkelCollateralUtxos = CollateralUtxosFromWallet (wallet 2)
...
}
From a direct Utxo list:
txSkelTemplate
{ ...
txSkelSigners = [wallet 1],
txSkelCollateralUtxos = CollateralUtxosFromSet (Set.fromList [txOutRef1, txOutRef2])
...
}
foo :: MonadBlockChain m => m ()
foo = do
...
-- searchResults :: [(Api.TxOutRef, Api.TxOut)]
searchResults <- runUtxoSearch $ allUtxos
...
foo :: MonadBlockChain m => m ()
foo = do
...
-- searchResults :: [(Api.TxOutRef, Api.TxOut)]
searchResults <- runUtxoSearch $ utxosAtSearch (walletAddress (wallet 2))
...
foo :: MonadBlockChain m => m ()
foo = do
...
searchResults <-
runUtxoSearch $
allUtxos `filterWithPred` ((== ada 10) . outputValue)
...
foo :: MonadBlockChain m => m ()
foo = do
...
searchResults <- runUtxoSearch $ allUtxos `filterWithPure` isOutputWithoutDatum
...
foo :: MonadBlockChain m => m ()
foo = do
...
searchResults <-
runUtxoSearch $
utxosAtSearch (walletAddress (wallet 2))
`filterWithPure` isOutputWithoutDatum
`filterWithPred` ((== ada 10) . outputValue)
...
foo :: MonadBlockChain m => m ()
foo = do
bar `withTweak` modification
foo :: MonadBlockChain m => m ()
foo = do
bar `withTweak` ( do
addOutputTweak $ bazValidator `receives` bazPayment
removeOutputTweak (\(Pays out) -> somePredicate out)
addInputTweak somePkTxOutRef txSkelEmptyRedeemer
removeInputTweak (\txOutRef redeemer -> somePredicate txOutRef redeemer)
)
foo :: MonadBlockChain m => m ()
foo = do
bar `withTweak` ( do
addSignersTweak [alice, bob]
replaceFirstSigner carol
removeSigners [eve]
)
foo :: MonadBlockChain m => m ()
foo = do
bar `withTweak` ( do
C.overTweak
(txSkelOutsL % _head % txSkelOutValueL) -- Value of first output
(<> assetClassValue bazAssetClass 10) -- Add 10 baz tokens
)
- Using the builtin constructor for proposals.
txSkelTemplate
{ ...
txSkelProposals =
[ TxSkelProposal
{ txSkelProposalAddress = walletAddress (wallet 1),
txSkelProposalAction =
TxGovActionTreasuryWithdrawals $
Map.fromList
[ (toCredential $ wallet 1, Api.Lovelace 100),
(toCredential $ wallet 2, Api.Lovelace 10_000)
],
txSkelProposalWitness = (toScript myScript, myRedeemer),
txSkelProposalAnchor = Nothing
}
]
...
}
- Using smart constructors and (optional) helpers.
txSkelTemplate
{ ...
txSkelProposals =
[ simpleTxSkelProposal
(wallet 1)
(TxGovActionParameterChange [FeePerByte 100, FeeFixed 1_000])
`withWitness` (myScript, myRedeemer)
`withAnchor` "https://www.tweag.io/"
]
...
}
- Auto resolution using a given map with resolved page content as bytestrings (default behavior)
txSkelOpts = def
{ txOptAnchorResolution = AnchorResolutionLocal $ Map.singleton "https://www.tweag.io/" someByteString
}
- Auto resolution using web requests (very unsafe, prevents reproducibility)
txSkelOpts = def
{ txOptAnchorResolution = AnchorResolutionHttp
}