- 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 [ paysPK (wallet 3) (ada 6) , paysScript fooTypedValidator FooTypedDatum (ada 6) , paysPK (wallet 2) (ada 2) `withDatum` fooDatum , paysPK (wallet 1) (ada 2) `withReferenceScript` fooValidator ]
- Ensure each initial distribution payment has min ada
initDist :: InitialDistribution initDist = unsafeToInitDistWithMinAda $ InitialDistribution ...
- 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]
...
}
paysPK (wallet 3) (ada 6)
paysScript fooTypedValidator FooTypedDatum (ada 6)
txSkelTemplate
{ ...
txSkelOuts = [paysPK ..., paysScript ...]
...
}
- 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 scrip:
(Script.Versioned barPolicy Script.PlutusV3, txSkelEmptyRedeemerAndReferenceScript txOutRef, "fooName", -6)
txSkelTemplate
{ ...
txSkelMints = txSkelMintsFromList
[ (Script.Versioned fooPolicy Script.PlutusV3, ..., ..., ...),
(Script.Versioned barPolicy Script.PlutusV3, ..., ..., ...)
]
...
}
txSkelTemplate
{ ...
txOpts = def {txOptEnsureMinAda = True}
...
}
distributionFromList [..., (... <> permanentValue "customToken" 1000), ...]
paysPK ... (permanentValue "customToken" 7)
paysPK ... `withDatum` FooTypedDatum
paysPK ... `withInlineDatum` FooTypedDatum
paysScriptInlineDatum fooTypedValidator FooTypedDatum (ada 6)
paysPK ... `withDatumHash` FooTypedDatum
paysScriptDatumHash fooTypedValidator FooTypedDatum (ada 6)
paysScriptNoDatum fooTypedValidator (ada 6) `withDatum` FooTypedDatum
paysScriptNoDatum fooTypedValidator (ada 6) `withInlineDatum` FooTypedDatum
paysScriptNoDatum fooTypedValidator (ada 6) `withDatumHash` FooTypedDatum
txSkelTemplate
{ ...
txSkelInsReference = Set.fromList [txOutRef1, txOutRef2, ...]
...
}
paysPK ... `withReferenceScript` fooTypedValidator
paysScript... ... `withReferenceScript` fooTypedValidator
paysPK ... `withStakingCredential` ...
paysScript... ... `withStakingCredential` ...
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 $ paysScript bazValidator bazDatum bazValue
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
}