-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy path05 - ParametrizedContract.hs
More file actions
138 lines (118 loc) · 5.96 KB
/
Copy path05 - ParametrizedContract.hs
File metadata and controls
138 lines (118 loc) · 5.96 KB
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-} -- Not seen before extension (Nsb e):
{-# LANGUAGE DeriveGeneric #-} -- Nseb e:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module OurVesting where
import Control.Monad hiding (fmap)
import Data.Aeson (ToJSON, FromJSON) --Nsb import
import Data.Map as Map
import Data.Text (Text)
import Data.Void (Void)
import GHC.Generics (Generic)
import Plutus.Contract
import PlutusTx (Data (..))
import qualified PlutusTx
import PlutusTx.Prelude hiding (Semigroup(..), unless)
import Ledger hiding (singleton)
import Ledger.Constraints (TxConstraints)
import qualified 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 (..), Show (..), String)
import Text.Printf (printf)
data VestingParams = VestingParams -- Custom Data Type for Datum
{ beneficiary :: PaymentPubKeyHash -- includes beneficiary
, deadline :: POSIXTime -- and deadline (in POSIX format)
} deriving Show
PlutusTx.makeLift ''VestingParams
{-# INLINABLE paramsValidator #-}
paramsValidator :: VestingParams -> () -> () -> ScriptContext -> Bool
paramsValidator params () () ctx = traceIfFalse "beneficiary's signature missing" signedByBeneficiary &&
traceIfFalse "deadline not reached" deadlineReached
where
info :: TxInfo
info = scriptContextTxInfo ctx
signedByBeneficiary :: Bool
signedByBeneficiary = txSignedBy info $ unPaymentPubKeyHash $ beneficiary params -- Beneficiary from dat (Datum), PaymentPubKeyHash unwrapping to PubKeyHash
deadlineReached :: Bool
deadlineReached = contains (from $ deadline params) $ txInfoValidRange info -- Auxiliary TxInfo and POSIX time functions
data Vesting -- Enconding the type of the datum and the redeemer
instance Scripts.ValidatorTypes Vesting where
type instance DatumType Vesting = () -- Instance for the Datum
type instance RedeemerType Vesting = () -- Instance for the Reederm, unit since its not been used
typedValidator :: VestingParams -> Scripts.TypedValidator Vesting
typedValidator params = Scripts.mkTypedValidator @Vesting
($$(PlutusTx.compile [|| paramsValidator ||]) `PlutusTx.applyCode` PlutusTx.liftCode params)
$$(PlutusTx.compile [|| wrap ||])
where
wrap = Scripts.wrapValidator @() @()
validator :: VestingParams -> Validator
validator = Scripts.validatorScript . typedValidator
valHash :: VestingParams -> Ledger.ValidatorHash
valHash = Scripts.validatorHash . typedValidator
scrAddress :: VestingParams -> Ledger.Address
scrAddress = scriptAddress . validator
-- OFF-CHAIN
data GiveParams = GiveParams --We can use Custom Data types
{ gpBeneficiary :: !PaymentPubKeyHash
, gpDeadline :: !POSIXTime
, gpAmount :: !Integer
} deriving (Generic, ToJSON, FromJSON, ToSchema)
type VestingSchema =
Endpoint "give" GiveParams
.\/ Endpoint "grab" POSIXTime
give :: AsContractError e => GiveParams -> Contract w s e ()
give gp = do
let dat = VestingParams
{ beneficiary = gpBeneficiary gp
, deadline = gpDeadline gp
}
tx = Constraints.mustPayToTheScript () $ Ada.lovelaceValueOf $ gpAmount gp
ledgerTx <- submitTxConstraints (typedValidator dat) tx
void $ awaitTxConfirmed $ getCardanoTxId ledgerTx
logInfo @String $ printf "made a gift of %d lovelace to %s with deadline %s"
(gpAmount gp)
(show $ gpBeneficiary gp)
(show $ gpDeadline gp)
grab :: forall w s e. AsContractError e => POSIXTime -> Contract w s e ()
grab dln = do
now <- currentTime
pkh <- ownPaymentPubKeyHash
if now < dln
then logInfo @String $ "too early!"
else do
let params = VestingParams
{ beneficiary = pkh
, deadline = dln
}
utxos <- utxosAt $ scrAddress params
if Map.null utxos
then logInfo @String $ "no gifts available"
else do
let orefs = fst <$> Map.toList utxos
lookups = Constraints.unspentOutputs utxos <>
Constraints.otherScript (validator params)
tx :: TxConstraints Void Void
tx = mconcat [Constraints.mustSpendScriptOutput oref unitRedeemer | oref <- orefs] <>
Constraints.mustValidateIn (from now)
ledgerTx <- submitTxConstraintsWith @Void lookups tx
void $ awaitTxConfirmed $ getCardanoTxId ledgerTx
logInfo @String $ "collected gifts"
endpoints :: Contract () VestingSchema Text ()
endpoints = awaitPromise (give' `select` grab') >> endpoints
where
give' = endpoint @"give" give
grab' = endpoint @"grab" grab
mkSchemaDefinitions ''VestingSchema
mkKnownCurrencies []