uniswap-pab and reading of Uniswap and cid's in client

This commit is contained in:
Lars Brünjes 2021-06-08 00:16:05 +02:00
parent f82ad343b9
commit 4e4b7dc900
No known key found for this signature in database
GPG key ID: B488B9045DC1A087
7 changed files with 55 additions and 169 deletions

View file

@ -1,6 +1,6 @@
dist-newstyle/ dist-newstyle/
oracle.cid uniswap.json
W1.cid
W2.cid W2.cid
W3.cid W3.cid
W4.cid W4.cid
W5.cid

View file

@ -41,3 +41,6 @@ wallets = [Wallet i | i <- [1 .. 4]]
tokenNames :: [TokenName] tokenNames :: [TokenName]
tokenNames = ["A", "B", "C", "D"] tokenNames = ["A", "B", "C", "D"]
cidFile :: Wallet -> FilePath
cidFile w = "W" ++ show (getWallet w) ++ ".cid"

View file

@ -1,123 +0,0 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NumericUnderscores #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Main
( main
) where
import Control.Monad (forM_, void, when)
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 (..), fromJSON)
import Data.Monoid (Last (..))
import Data.Text (Text, pack)
import Ledger
import Ledger.Constraints
import qualified Ledger.Value as Value
import Plutus.Contract hiding (when)
import Plutus.PAB.Effects.Contract (ContractEffect (..))
import Plutus.PAB.Effects.Contract.Builtin (Builtin, SomeBuiltin (..), type (.\\), endpointsToSchemas, handleBuiltin)
import Plutus.PAB.Monitoring.PABLogMsg (PABMultiAgentMsg)
import Plutus.PAB.Simulator (SimulatorEffectHandlers)
import qualified Plutus.PAB.Simulator as Simulator
import Plutus.PAB.Types (PABError (..))
import qualified Plutus.PAB.Webserver.Server as PAB.Server
import qualified Plutus.Contracts.Currency as Currency
import Wallet.Emulator.Types (Wallet (..), walletPubKey)
import Wallet.Types (ContractInstanceId (..))
import qualified Week06.Oracle.Core as Oracle
import Week06.Oracle.PAB (OracleContracts (..))
import qualified Week06.Oracle.Swap as Oracle
main :: IO ()
main = void $ Simulator.runSimulationWith handlers $ do
Simulator.logString @(Builtin OracleContracts) "Starting Oracle PAB webserver. Press enter to exit."
shutdown <- PAB.Server.startServerDebug
cidInit <- Simulator.activateContract (Wallet 1) Init
cs <- waitForLast cidInit
_ <- Simulator.waitUntilFinished cidInit
cidOracle <- Simulator.activateContract (Wallet 1) $ Oracle cs
liftIO $ writeFile "oracle.cid" $ show $ unContractInstanceId cidOracle
oracle <- waitForLast cidOracle
forM_ wallets $ \w ->
when (w /= Wallet 1) $ do
cid <- Simulator.activateContract w $ Swap oracle
liftIO $ writeFile ('W' : show (getWallet w) ++ ".cid") $ show $ unContractInstanceId cid
void $ liftIO getLine
shutdown
waitForLast :: FromJSON a => ContractInstanceId -> Simulator.Simulation t a
waitForLast cid =
flip Simulator.waitForState cid $ \json -> case fromJSON json of
Success (Last (Just x)) -> Just x
_ -> Nothing
wallets :: [Wallet]
wallets = [Wallet i | i <- [1 .. 5]]
usdt :: TokenName
usdt = "USDT"
oracleParams :: CurrencySymbol -> Oracle.OracleParams
oracleParams cs = Oracle.OracleParams
{ Oracle.opFees = 1_000_000
, Oracle.opSymbol = cs
, Oracle.opToken = usdt
}
handleOracleContracts ::
( Member (Error PABError) effs
, Member (LogMsg (PABMultiAgentMsg (Builtin OracleContracts))) effs
)
=> ContractEffect (Builtin OracleContracts)
~> Eff effs
handleOracleContracts = handleBuiltin getSchema getContract where
getSchema = \case
Init -> endpointsToSchemas @Empty
Oracle _ -> endpointsToSchemas @(Oracle.OracleSchema .\\ BlockchainActions)
Swap _ -> endpointsToSchemas @(Oracle.SwapSchema .\\ BlockchainActions)
getContract = \case
Init -> SomeBuiltin initContract
Oracle cs -> SomeBuiltin $ Oracle.runOracle $ oracleParams cs
Swap oracle -> SomeBuiltin $ Oracle.swap oracle
handlers :: SimulatorEffectHandlers (Builtin OracleContracts)
handlers =
Simulator.mkSimulatorHandlers @(Builtin OracleContracts) []
$ interpret handleOracleContracts
initContract :: Contract (Last CurrencySymbol) BlockchainActions Text ()
initContract = do
ownPK <- pubKeyHash <$> ownPubKey
cur <-
mapError (pack . show)
(Currency.forgeContract ownPK [(usdt, fromIntegral (length wallets) * amount)]
:: Contract (Last CurrencySymbol) BlockchainActions Currency.CurrencyError Currency.OneShotCurrency)
let cs = Currency.currencySymbol cur
v = Value.singleton cs usdt amount
forM_ wallets $ \w -> do
let pkh = pubKeyHash $ walletPubKey w
when (pkh /= ownPK) $ do
tx <- submitTx $ mustPayToPubKey pkh v
awaitTxConfirmed $ txId tx
tell $ Last $ Just cs
where
amount :: Integer
amount = 100_000_000

View file

@ -6,25 +6,38 @@ module Main
( main ( main
) where ) where
import Control.Concurrent import Control.Concurrent
import Control.Exception import Control.Exception
import Control.Monad.IO.Class (MonadIO (..)) import Control.Monad.IO.Class (MonadIO (..))
import Data.Aeson (Result (..), fromJSON) import Data.Aeson (Result (..), decode, fromJSON)
import Data.Monoid (Last (..)) import qualified Data.ByteString.Lazy as LB
import Data.Proxy (Proxy (..)) import Data.Monoid (Last (..))
import Data.Text (pack) import Data.Proxy (Proxy (..))
import Data.UUID import Data.Text (pack)
import Ledger.Value (flattenValue) import Data.UUID
import Network.HTTP.Req import Ledger.Value (flattenValue)
import Plutus.PAB.Events.ContractInstanceState (PartiallyDecodedResponse (..)) import Network.HTTP.Req
import Plutus.PAB.Webserver.Types import Plutus.Contracts.Uniswap (Uniswap)
import System.Environment (getArgs) import Plutus.PAB.Events.ContractInstanceState (PartiallyDecodedResponse (..))
import System.IO import Plutus.PAB.Webserver.Types
import Text.Read (readMaybe) import System.Environment (getArgs)
import System.Exit (exitFailure)
import System.IO
import Text.Read (readMaybe)
import Wallet.Emulator.Types (Wallet (..))
import Uniswap (cidFile)
main :: IO () main :: IO ()
main = do main = do
putStrLn "Uniswap Client" w <- Wallet . read . head <$> getArgs
cid <- read <$> readFile (cidFile w)
mus <- decode <$> LB.readFile "uniswap.json"
case mus of
Nothing -> putStrLn "invalid uniswap.json" >> exitFailure
Just us -> do
putStrLn $ "cid: " ++ show (cid :: UUID)
putStrLn $ "uniswap: " ++ show (us :: Uniswap)
{- {-
[i :: Int] <- map read <$> getArgs [i :: Int] <- map read <$> getArgs
uuid <- read <$> readFile ('W' : show i ++ ".cid") uuid <- read <$> readFile ('W' : show i ++ ".cid")

View file

@ -13,19 +13,18 @@ module Main
( main ( main
) where ) where
import Control.Monad (forM, void) import Control.Monad (forM_, void)
import Control.Monad.Freer (Eff, Member, interpret, type (~>)) import Control.Monad.Freer (Eff, Member, interpret, type (~>))
import Control.Monad.Freer.Error (Error) import Control.Monad.Freer.Error (Error)
import Control.Monad.Freer.Extras.Log (LogMsg) import Control.Monad.Freer.Extras.Log (LogMsg)
import Control.Monad.IO.Class (MonadIO (..)) import Control.Monad.IO.Class (MonadIO (..))
import Data.Aeson (FromJSON, Result (..), ToJSON, encode, fromJSON) import Data.Aeson (FromJSON, Result (..), ToJSON, encode, fromJSON)
import qualified Data.Map.Strict as Map import qualified Data.ByteString.Lazy as LB
import qualified Data.Monoid as Monoid import qualified Data.Monoid as Monoid
import qualified Data.Semigroup as Semigroup import qualified Data.Semigroup as Semigroup
import Data.Text (Text) import Data.Text (Text)
import Data.Text.Prettyprint.Doc (Pretty (..), viaShow) import Data.Text.Prettyprint.Doc (Pretty (..), viaShow)
import GHC.Generics (Generic) import GHC.Generics (Generic)
import Ledger.Ada (adaSymbol, adaToken)
import Plutus.Contract import Plutus.Contract
import qualified Plutus.Contracts.Currency as Currency import qualified Plutus.Contracts.Currency as Currency
import qualified Plutus.Contracts.Uniswap as Uniswap import qualified Plutus.Contracts.Uniswap as Uniswap
@ -40,6 +39,7 @@ import qualified Plutus.PAB.Webserver.Server as PAB.Server
import Prelude hiding (init) import Prelude hiding (init)
import Uniswap as US import Uniswap as US
import Wallet.Emulator.Types (Wallet (..)) import Wallet.Emulator.Types (Wallet (..))
import Wallet.Types (ContractInstanceId (..))
main :: IO () main :: IO ()
main = void $ Simulator.runSimulationWith handlers $ do main = void $ Simulator.runSimulationWith handlers $ do
@ -54,37 +54,20 @@ main = void $ Simulator.runSimulationWith handlers $ do
logString @(Builtin UniswapContracts) $ "Initialization finished. Minted: " ++ show cs 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 cidStart <- Simulator.activateContract (Wallet 1) UniswapStart
us <- flip Simulator.waitForState cidStart $ \json -> case (fromJSON json :: Result (Monoid.Last (Either Text Uniswap.Uniswap))) of 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 Success (Monoid.Last (Just (Right us))) -> Just us
_ -> Nothing _ -> Nothing
liftIO $ LB.writeFile "uniswap.json" $ encode us
logString @(Builtin UniswapContracts) $ "Uniswap instance created: " ++ show us logString @(Builtin UniswapContracts) $ "Uniswap instance created: " ++ show us
cids <- fmap Map.fromList $ forM wallets $ \w -> do forM_ wallets $ \w -> do
cid <- Simulator.activateContract w $ UniswapUser us cid <- Simulator.activateContract w $ UniswapUser us
liftIO $ writeFile (cidFile w) $ show $ unContractInstanceId cid
logString @(Builtin UniswapContracts) $ "Uniswap user contract started for " ++ show w 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 void $ liftIO getLine
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 shutdown
data UniswapContracts = data UniswapContracts =
@ -115,5 +98,5 @@ handleUniswapContract = Builtin.handleBuiltin getSchema getContract where
handlers :: SimulatorEffectHandlers (Builtin UniswapContracts) handlers :: SimulatorEffectHandlers (Builtin UniswapContracts)
handlers = handlers =
Simulator.mkSimulatorHandlers @(Builtin UniswapContracts) [] -- [Init, UniswapStart, UniswapUser ???] Simulator.mkSimulatorHandlers @(Builtin UniswapContracts) []
$ interpret handleUniswapContract $ interpret handleUniswapContract

View file

@ -25,7 +25,8 @@ source-repository-package
plutus-use-cases plutus-use-cases
prettyprinter-configurable prettyprinter-configurable
quickcheck-dynamic quickcheck-dynamic
tag: 74cb849b6580d937a97aff42636d4ddc6a140ed6 word-array
tag: 26449c6e6e1c14d335683e5a4f40e2662b9b7e7
-- The following sections are copied from the 'plutus' repository cabal.project at the revision -- The following sections are copied from the 'plutus' repository cabal.project at the revision
-- given above. -- given above.
@ -61,6 +62,11 @@ constraints:
-- (NOTE this will change to ieee754 in newer versions of nixpkgs). -- (NOTE this will change to ieee754 in newer versions of nixpkgs).
extra-packages: ieee, filemanip extra-packages: ieee, filemanip
-- Drops an instance breaking our code. Should be released to Hackage eventually.
source-repository-package
type: git
location: https://github.com/Quid2/flat.git
tag: 95e5d7488451e43062ca84d5376b3adcc465f1cd
-- Needs some patches, but upstream seems to be fairly dead (no activity in > 1 year) -- Needs some patches, but upstream seems to be fairly dead (no activity in > 1 year)
source-repository-package source-repository-package

View file

@ -42,8 +42,8 @@ executable uniswap-pab
-Wno-missing-import-lists -Wredundant-constraints -O0 -Wno-missing-import-lists -Wredundant-constraints -O0
build-depends: build-depends:
base >=4.9 && <5, base >=4.9 && <5,
bytestring,
aeson -any, aeson -any,
bytestring -any,
containers -any, containers -any,
freer-extras -any, freer-extras -any,
freer-simple -any, freer-simple -any,
@ -55,13 +55,17 @@ executable uniswap-pab
text -any text -any
executable uniswap-client executable uniswap-client
main-is: uniswap-client.hs main-is: uniswap-client.hs
other-modules: Uniswap
hs-source-dirs: app hs-source-dirs: app
ghc-options: -Wall ghc-options: -Wall
build-depends: aeson build-depends: aeson
, base ^>= 4.14.1.0 , base ^>= 4.14.1.0
, bytestring
, plutus-contract
, plutus-ledger , plutus-ledger
, plutus-pab , plutus-pab
, plutus-use-cases
, req ^>= 3.9.0 , req ^>= 3.9.0
, text , text
, uuid , uuid