-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHomework2.hs
94 lines (82 loc) · 3.81 KB
/
Homework2.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Week05.Homework2 where
import Control.Monad hiding (fmap)
import qualified Data.Map as Map
import Data.Text (Text)
import Data.Void (Void)
import Plutus.Contract as Contract
import Plutus.Trace.Emulator as Emulator
import qualified PlutusTx
import PlutusTx.Prelude hiding (Semigroup(..), unless)
import Ledger hiding (mint, singleton)
import Ledger.Constraints as Constraints
import qualified Ledger.Typed.Scripts as Scripts
import Ledger.Value as Value
import Prelude (IO, Semigroup (..), Show (..), String, undefined)
import Text.Printf (printf)
import Wallet.Emulator.Wallet
import Plutus.V1.Ledger.Ada
{-# INLINABLE mkPolicy #-}
-- Minting policy for an NFT, where the minting transaction must consume the given UTxO as input
-- and where the TokenName will be the empty ByteString.
mkPolicy :: TxOutRef -> () -> ScriptContext -> Bool
mkPolicy oref () ctx = traceIfFalse "UTxO not consumed" hasUTxO &&
traceIfFalse "wrong amount minted" checkMintedAmount
where
info :: TxInfo
info = scriptContextTxInfo ctx
-- check if the TxOutRef compiled into the script is the same one
-- as one of the inputs of the transaction.
-- see http://localhost:8002/haddock/plutus-ledger-api/html/Plutus-V1-Ledger-Api.html#t:TxInInfo
hasUTxO :: Bool
hasUTxO = any (\i -> txInInfoOutRef i == oref) $ txInfoInputs info
-- `any even [2 :: Int, 3, 5 ]` ==> true as at least 2 is even
checkMintedAmount :: Bool
-- see http://localhost:8002/haddock/plutus-ledger-api/html/Plutus-V1-Ledger-Api.html#t:TxInfo
checkMintedAmount = case flattenValue (txInfoMint info) of
[(_, tn', amt)] -> tn' == adaToken && amt == 1
_ -> False
policy :: TxOutRef -> Scripts.MintingPolicy
policy oref = mkMintingPolicyScript $
$$(PlutusTx.compile [|| Scripts.wrapMintingPolicy . mkPolicy ||])
`PlutusTx.applyCode`
PlutusTx.liftCode oref
curSymbol :: TxOutRef -> CurrencySymbol
curSymbol = scriptCurrencySymbol . policy
type NFTSchema = Endpoint "mint" Address
mint :: Address -> Contract w NFTSchema Text ()
mint npAddress = do
utxos <- utxosAt $ npAddress
-- `Map.keys utxos` returns the `txOutRefs`
case Map.keys utxos of
[] -> Contract.logError @String "no utxo found"
oref : _ -> do
let val = Value.singleton (curSymbol oref) adaToken 1
lookups = Constraints.mintingPolicy (policy oref) <> Constraints.unspentOutputs utxos
tx = Constraints.mustMintValue val <> Constraints.mustSpendPubKeyOutput oref
ledgerTx <- submitTxConstraintsWith @Void lookups tx
void $ awaitTxConfirmed $ getCardanoTxId ledgerTx
Contract.logInfo @String $ printf "forged %s" (show val)
endpoints :: Contract () NFTSchema Text ()
endpoints = mint' >> endpoints
where
mint' = awaitPromise $ endpoint @"mint" mint
test :: IO ()
test = runEmulatorTraceIO $ do
let w1 = knownWallet 1
w2 = knownWallet 2
h1 <- activateContractWallet w1 endpoints
h2 <- activateContractWallet w2 endpoints
callEndpoint @"mint" h1 $ mockWalletAddress w1
callEndpoint @"mint" h2 $ mockWalletAddress w2
void $ Emulator.waitNSlots 1