plutus-pioneer-program/code/week10/app/uniswap-pab.hs

120 lines
6 KiB
Haskell
Raw Normal View History

2021-06-07 22:49:01 +02:00
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Main
( main
) where
import Control.Monad (forM, void)
import Control.Monad.Freer (Eff, Member, interpret, type (~>))
import Control.Monad.Freer.Error (Error)
import Control.Monad.Freer.Extras.Log (LogMsg)
import Control.Monad.IO.Class (MonadIO (..))
import Data.Aeson (FromJSON, Result (..), ToJSON, encode, fromJSON)
import qualified Data.Map.Strict as Map
import qualified Data.Monoid as Monoid
import qualified Data.Semigroup as Semigroup
import Data.Text (Text)
import Data.Text.Prettyprint.Doc (Pretty (..), viaShow)
import GHC.Generics (Generic)
import Ledger.Ada (adaSymbol, adaToken)
import Plutus.Contract
import qualified Plutus.Contracts.Currency as Currency
import qualified Plutus.Contracts.Uniswap as Uniswap
import Plutus.PAB.Effects.Contract (ContractEffect (..))
import Plutus.PAB.Effects.Contract.Builtin (Builtin, SomeBuiltin (..), type (.\\))
import qualified Plutus.PAB.Effects.Contract.Builtin as Builtin
import Plutus.PAB.Monitoring.PABLogMsg (PABMultiAgentMsg)
import Plutus.PAB.Simulator (SimulatorEffectHandlers, logString)
import qualified Plutus.PAB.Simulator as Simulator
import Plutus.PAB.Types (PABError (..))
import qualified Plutus.PAB.Webserver.Server as PAB.Server
import Prelude hiding (init)
import Uniswap as US
import Wallet.Emulator.Types (Wallet (..))
main :: IO ()
main = void $ Simulator.runSimulationWith handlers $ do
logString @(Builtin UniswapContracts) "Starting Uniswap PAB webserver on port 8080. Press enter to exit."
shutdown <- PAB.Server.startServerDebug
cidInit <- Simulator.activateContract (Wallet 1) Init
cs <- flip Simulator.waitForState cidInit $ \json -> case fromJSON json of
Success (Just (Semigroup.Last cur)) -> Just $ Currency.currencySymbol cur
_ -> Nothing
_ <- Simulator.waitUntilFinished cidInit
logString @(Builtin UniswapContracts) $ "Initialization finished. Minted: " ++ show cs
let coins = Map.fromList [(tn, Uniswap.mkCoin cs tn) | tn <- tokenNames]
ada = Uniswap.mkCoin adaSymbol adaToken
cidStart <- Simulator.activateContract (Wallet 1) UniswapStart
us <- flip Simulator.waitForState cidStart $ \json -> case (fromJSON json :: Result (Monoid.Last (Either Text Uniswap.Uniswap))) of
Success (Monoid.Last (Just (Right us))) -> Just us
_ -> Nothing
logString @(Builtin UniswapContracts) $ "Uniswap instance created: " ++ show us
cids <- fmap Map.fromList $ forM wallets $ \w -> do
cid <- Simulator.activateContract w $ UniswapUser us
logString @(Builtin UniswapContracts) $ "Uniswap user contract started for " ++ show w
Simulator.waitForEndpoint cid "funds"
_ <- Simulator.callEndpointOnInstance cid "funds" ()
v <- flip Simulator.waitForState cid $ \json -> case (fromJSON json :: Result (Monoid.Last (Either Text Uniswap.UserContractState))) of
Success (Monoid.Last (Just (Right (Uniswap.Funds v)))) -> Just v
_ -> Nothing
logString @(Builtin UniswapContracts) $ "initial funds in wallet " ++ show w ++ ": " ++ show v
return (w, cid)
let cp = Uniswap.CreateParams ada (coins Map.! "A") 100000 500000
logString @(Builtin UniswapContracts) $ "creating liquidity pool: " ++ show (encode cp)
let cid2 = cids Map.! Wallet 2
Simulator.waitForEndpoint cid2 "create"
_ <- Simulator.callEndpointOnInstance cid2 "create" cp
flip Simulator.waitForState (cids Map.! Wallet 2) $ \json -> case (fromJSON json :: Result (Monoid.Last (Either Text Uniswap.UserContractState))) of
Success (Monoid.Last (Just (Right Uniswap.Created))) -> Just ()
_ -> Nothing
logString @(Builtin UniswapContracts) "liquidity pool created"
_ <- liftIO getLine
shutdown
data UniswapContracts =
Init
| UniswapStart
| UniswapUser Uniswap.Uniswap
deriving (Eq, Ord, Show, Generic)
deriving anyclass (FromJSON, ToJSON)
instance Pretty UniswapContracts where
pretty = viaShow
handleUniswapContract ::
( Member (Error PABError) effs
, Member (LogMsg (PABMultiAgentMsg (Builtin UniswapContracts))) effs
)
=> ContractEffect (Builtin UniswapContracts)
~> Eff effs
handleUniswapContract = Builtin.handleBuiltin getSchema getContract where
getSchema = \case
UniswapUser _ -> Builtin.endpointsToSchemas @(Uniswap.UniswapUserSchema .\\ BlockchainActions)
UniswapStart -> Builtin.endpointsToSchemas @(Uniswap.UniswapOwnerSchema .\\ BlockchainActions)
Init -> Builtin.endpointsToSchemas @Empty
getContract = \case
UniswapUser us -> SomeBuiltin $ Uniswap.userEndpoints us
UniswapStart -> SomeBuiltin Uniswap.ownerEndpoint
Init -> SomeBuiltin US.initContract
handlers :: SimulatorEffectHandlers (Builtin UniswapContracts)
handlers =
Simulator.mkSimulatorHandlers @(Builtin UniswapContracts) [] -- [Init, UniswapStart, UniswapUser ???]
$ interpret handleUniswapContract