This repository has been archived by the owner on Nov 7, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Controller.hs
153 lines (137 loc) · 5.65 KB
/
Controller.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
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
-----------------------------------------------------------------------------
--
-- Module : $Headers
-- Copyright : (c) 2021 Brian W Bush
-- License : MIT
--
-- Maintainer : Brian W Bush <code@functionally.io>
-- Stability : Experimental
-- Portability : Portable
--
-- | Controlling the general-purpose oracle.
--
-----------------------------------------------------------------------------
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Mantra.Oracle.Controller (
-- * Schema
OracleSchema
-- * Endpoints
, deleteOracle
, writeOracle
-- * Utilities
, runOracleController
) where
import PlutusTx.Prelude hiding ((<>))
import Data.Monoid (Last (..))
import Data.Text (Text)
import Data.Void (Void)
import Ledger (Redeemer(..), pubKeyHash, txId)
import Ledger.Constraints (mustPayToPubKey, mustPayToTheScript, mustSpendScriptOutput, otherScript, typedValidatorLookups, unspentOutputs)
import Ledger.Value (assetClassValue)
import Mantra.Oracle (OracleScript, oracleInstance, oracleValidator)
import Mantra.Oracle.Client (findOracle, readOracle)
import Mantra.Oracle.Types (Action(..), Oracle(..))
import Plutus.Contract (Contract, Endpoint, Promise, type (.\/), awaitTxConfirmed, handleEndpoint, logError, logInfo, ownPubKey, runError, select, submitTxConstraints, submitTxConstraintsWith, tell)
import PlutusTx (Data, ToData(..), dataToBuiltinData)
import Prelude (String, (<>), show)
import qualified Data.Map as M (singleton)
-- | Schema for controlling the oracle.
type OracleSchema =
Endpoint "read" ()
.\/ Endpoint "write" Data
.\/ Endpoint "delete" ()
-- | Endpoint for writing datum to the oracle.
writeOracle :: Oracle -- ^ The oracle.
-> Data -- ^ The datum to be written.
-> Contract w s Text () -- ^ Action for writing the datum to the oracle.
writeOracle oracle@Oracle{..} datum =
do
owner <- pubKeyHash <$> ownPubKey
let
mustControl = mustPayToPubKey owner $ assetClassValue controlToken 1
mustUseDatum = mustPayToTheScript (dataToBuiltinData datum) $ assetClassValue datumToken 1
notFound =
do
ledgerTx <-
submitTxConstraints (oracleInstance oracle)
$ mustControl <> mustUseDatum
awaitTxConfirmed $ txId ledgerTx
logInfo $ "Set oracle datum: " ++ show datum ++ "."
found (outputRef, output, _) =
do
let
lookups = otherScript (oracleValidator oracle)
<> unspentOutputs (M.singleton outputRef output)
<> typedValidatorLookups (oracleInstance oracle)
tx = mustControl
<> mustUseDatum
<> mustSpendScriptOutput outputRef (Redeemer $ toBuiltinData Write)
ledgerTx <- submitTxConstraintsWith @OracleScript lookups tx
awaitTxConfirmed $ txId ledgerTx
logInfo $ "Updated oracle datum: " ++ show datum ++ "."
maybe notFound found
=<< findOracle oracle
-- | Endpoint for deleting (closing) the oracle.
deleteOracle :: Oracle -- ^ The oracle.
-> Contract w s Text () -- ^ Action to close the oracle.
deleteOracle oracle@Oracle{..} =
do
owner <- pubKeyHash <$> ownPubKey
let
mustControl = mustPayToPubKey owner $ assetClassValue controlToken 1
notFound = logError @String $ "Oracle not found."
found (outputRef, output, _) =
do
let
lookups = otherScript (oracleValidator oracle)
<> unspentOutputs (M.singleton outputRef output)
<> typedValidatorLookups (oracleInstance oracle)
tx = mustControl
<> mustSpendScriptOutput outputRef (Redeemer $ toBuiltinData Delete)
ledgerTx <- submitTxConstraintsWith @OracleScript lookups tx
awaitTxConfirmed $ txId ledgerTx
logInfo @String $ "Deleted oracle datum."
maybe notFound found
=<< findOracle oracle
-- | Create the oracle and run its control endpoints.
runOracleController :: Oracle -- ^ The oracle.
-> Promise (Last (Either Text Oracle)) OracleSchema Void () -- ^ Action for creating and running the oracle.
runOracleController oracle =
do
let
write' =
handleEndpoint @"write"
$ \input ->
(tell . Last . Just) =<<
case input of
Right datum -> fmap (either Left (const $ Right oracle))
. runError
$ writeOracle oracle datum
Left e -> return $ Left e
read' =
handleEndpoint @"read"
$ \input ->
(tell . Last . Just) =<<
case input of
Right () -> fmap (either Left (const $ Right oracle))
. runError
$ readOracle oracle
Left e -> return $ Left e
delete' =
handleEndpoint @"delete"
$ \input ->
(tell . Last . Just) =<<
case input of
Right () -> fmap (either Left (const $ Right oracle))
. runError
$ deleteOracle oracle
Left e -> return $ Left e
let
operate = (read' `select` write' `select` delete') <> operate
operate