Created
July 11, 2021 17:09
-
-
Save franleplant/eb3ae7e715edf98ad2857c8f2b0e828a to your computer and use it in GitHub Desktop.
Plutus Pioneer program: lecture 2, homework 2 annotated
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE DataKinds #-} | |
{-# LANGUAGE DeriveAnyClass #-} | |
{-# LANGUAGE DeriveGeneric #-} | |
{-# LANGUAGE FlexibleContexts #-} | |
{-# LANGUAGE NoImplicitPrelude #-} | |
{-# LANGUAGE OverloadedStrings #-} | |
{-# LANGUAGE ScopedTypeVariables #-} | |
{-# LANGUAGE TemplateHaskell #-} | |
{-# LANGUAGE TypeApplications #-} | |
{-# LANGUAGE TypeFamilies #-} | |
{-# LANGUAGE TypeOperators #-} | |
{-# OPTIONS_GHC -fno-warn-unused-imports #-} | |
module Week02.Homework2 where | |
import Control.Monad hiding (fmap) | |
import Data.Aeson (FromJSON, ToJSON) | |
import Data.Map as Map | |
import Data.Text (Text) | |
import Data.Void (Void) | |
import GHC.Generics (Generic) | |
import Plutus.Contract | |
import qualified PlutusTx | |
import PlutusTx.Prelude hiding (Semigroup(..), unless) | |
import Ledger hiding (singleton) | |
import Ledger.Constraints as Constraints | |
import qualified Ledger.Typed.Scripts as Scripts | |
import Ledger.Ada as Ada | |
import Playground.Contract (printJson, printSchemas, ensureKnownCurrencies, stage, ToSchema) | |
import Playground.TH (mkKnownCurrencies, mkSchemaDefinitions) | |
import Playground.Types (KnownCurrency (..)) | |
import Prelude (IO, Semigroup (..), String, undefined) | |
import Text.Printf (printf) | |
-- Custom redeemer type | |
data CustomRedeemer = CustomRedeemer { | |
flag1 :: Bool, | |
flag2 :: Bool | |
} deriving (Generic, FromJSON, ToJSON, ToSchema) | |
PlutusTx.unstableMakeIsData ''CustomRedeemer | |
-- define your own validation logic | |
{-# INLINABLE validator #-} | |
validator :: () -> CustomRedeemer -> ScriptContext -> Bool | |
validator _ (CustomRedeemer f1 f2) _ = traceIfFalse "wrong redemeer" f1 == f2 | |
-- define a type to represent your validator | |
data ValidatorType | |
instance Scripts.ValidatorTypes ValidatorType where | |
type instance DatumType ValidatorType = () | |
type instance RedeemerType ValidatorType = CustomRedeemer | |
-- compile your validator with the proper type information | |
typedValidator :: Scripts.TypedValidator ValidatorType | |
typedValidator = Scripts.mkTypedValidator @ValidatorType | |
$$(PlutusTx.compile [|| validator ||]) | |
$$(PlutusTx.compile [|| wrap ||]) | |
where | |
wrap = Scripts.wrapValidator @() @CustomRedeemer | |
-- calc the validator hash | |
validatorHash :: Ledger.ValidatorHash | |
validatorHash = Scripts.validatorHash typedValidator | |
-- make a validator script | |
validatorScript :: Validator | |
validatorScript = Scripts.validatorScript typedValidator | |
-- calc the validator address (which is a wrapper around the hash) | |
validatorScriptAddress :: Ledger.Address | |
validatorScriptAddress = scriptAddress validatorScript | |
give :: forall w s e. AsContractError e => Integer -> Contract w s e () | |
give amount = do | |
-- build a transaction that pays "amount" of lovelace to the contract | |
let tx = mustPayToTheScript () $ Ada.lovelaceValueOf amount | |
-- submit transaction and validate | |
ledgerTx <- submitTxConstraints typedValidator tx | |
-- await for the transaction to be confirmed (what does confirmation | |
-- in cardano really mean? x blocks after this transaction was processed?) | |
-- void tells haskell that we don't care about the return value of the following | |
-- functions in the context of a monad (functor to be correct) | |
void $ awaitTxConfirmed $ txId ledgerTx | |
-- logs! | |
logInfo @String $ printf "made a gift of %d lovelace" amount | |
grab :: forall w s e. AsContractError e => CustomRedeemer -> Contract w s e () | |
grab r = do | |
-- get all the utxos of our contract (in our case | |
-- the amount of lovelace people have "give" to it | |
utxos <- utxoAt validatorScriptAddress | |
-- get a list of "references" for the utxos | |
let orefs = fst <$> Map.toList utxos | |
-- ??? | |
lookups = Constraints.unspentOutputs utxos <> | |
Constraints.otherScript validatorScript | |
-- build the transaction | |
-- it loos like we are building a list of utxos (refs) that are going to be grabbed by | |
-- the address (person) that called this endpoint. | |
-- TLDR: sum all utox available at the contract and let them be taken by the grabber | |
tx :: TxConstraints Void Void | |
tx = mconcat [mustSpendScriptOutput oref $ Redeemer $ PlutusTx.toData r | oref <- orefs] | |
-- submit the transaction, it looks like `lookups` is | |
-- extra information we provide to the "built transaction" | |
ledgerTx <- submitTxConstraintsWith @Void lookups tx | |
-- await for the transaction to be done! | |
void $ awaitTxConfirmed $ txId ledgerTx | |
-- logs! | |
logInfo @String $ "collected gifts" | |
-- lets define the contract interface | |
-- in our case we will be interacting with these "actions" | |
-- from the playground, and the playground itself acts like a | |
-- front end for the smart contract we are building | |
type GiftSchema = | |
Endpoint "give" Integer | |
.\/ Endpoint "grab" CustomRedeemer | |
mkSchemaDefinitions ''GiftSchema | |
-- hook up the endpoints | |
endpoints :: Contract () GiftSchema Text () | |
endpoints = (give' `select` grab') >> endpoints | |
where | |
give' = endpoint @"give" >>= give | |
grab' = endpoint @"grab" >>= grab | |
mkKnownCurrencies [] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment