/
Types.hs
150 lines (131 loc) · 5.42 KB
/
Types.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
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE StrictData #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
module Cardano.Wallet.Mock.Types (
-- * effect type for the mock wallet
WalletEffects
, Wallets
, MultiWalletEffect (..)
, createWallet
, multiWallet
, getWalletInfo
-- * wallet configuration
, WalletConfig (..)
, defaultWalletConfig
-- * wallet log messages
, WalletMsg (..)
-- * newtypes for convenience
, Port (..)
, NodeClient (..)
, ChainClient (..)
, WalletUrl (..)
, ChainIndexUrl
-- * Wallet info
, WalletInfo(..)
, fromWalletState
) where
import Cardano.BM.Data.Tracer (ToObject (..))
import Cardano.BM.Data.Tracer.Extras (Tagged (..), mkObjectStr)
import Cardano.ChainIndex.Types (ChainIndexUrl)
import qualified Cardano.Crypto.Wallet as Crypto
import Control.Monad.Freer (Eff)
import Control.Monad.Freer.Error (Error)
import Control.Monad.Freer.Extras.Log (LogMsg)
import Control.Monad.Freer.State (State)
import Control.Monad.Freer.TH (makeEffect)
import Data.Aeson (FromJSON, ToJSON)
import Data.Default (Default, def)
import Data.Map.Strict (Map)
import Data.Text (Text)
import Data.Text.Prettyprint.Doc (Pretty (..), (<+>))
import GHC.Generics (Generic)
import Ledger (PubKey, PubKeyHash)
import qualified Ledger.Crypto as Crypto
import Plutus.ChainIndex (ChainIndexQueryEffect)
import Plutus.PAB.Arbitrary ()
import Servant (ServerError (..))
import Servant.Client (BaseUrl (..), ClientError, Scheme (..))
import Servant.Client.Internal.HttpClient (ClientEnv)
import Wallet.Effects (NodeClientEffect, WalletEffect)
import Wallet.Emulator.Error (WalletAPIError)
import Wallet.Emulator.LogMessages (TxBalanceMsg)
import Wallet.Emulator.Wallet (Wallet (..), WalletId (..), WalletState (..))
-- | Information about an emulated wallet.
data WalletInfo =
WalletInfo
{ wiWallet :: Wallet
, wiPubKey :: Maybe PubKey -- ^ Public key of the wallet (if known)
, wiPubKeyHash :: PubKeyHash
}
deriving stock (Show, Generic)
deriving anyclass (ToJSON, FromJSON)
type Wallets = Map Wallet WalletState
fromWalletState :: WalletState -> WalletInfo
fromWalletState WalletState{_ownPrivateKey} =
let xpub = Crypto.toXPub _ownPrivateKey
pk = Crypto.xPubToPublicKey xpub
in WalletInfo
{ wiWallet = Wallet (XPubWallet xpub)
, wiPubKey = Just pk
, wiPubKeyHash = Crypto.pubKeyHash pk
}
data MultiWalletEffect r where
CreateWallet :: MultiWalletEffect WalletInfo
MultiWallet :: Wallet -> Eff '[WalletEffect] a -> MultiWalletEffect a
GetWalletInfo :: WalletId -> MultiWalletEffect (Maybe WalletInfo)
makeEffect ''MultiWalletEffect
type WalletEffects m = '[ MultiWalletEffect
, NodeClientEffect
, ChainIndexQueryEffect
, State Wallets
, LogMsg Text
, Error WalletAPIError
, Error ClientError
, Error ServerError
, m]
newtype NodeClient = NodeClient ClientEnv
newtype ChainClient = ChainClient ClientEnv
newtype WalletUrl = WalletUrl BaseUrl
deriving (Eq, Show, ToJSON, FromJSON) via BaseUrl
newtype Port = Port Int
deriving (Show)
deriving (Eq, Num, ToJSON, FromJSON, Pretty) via Int
newtype WalletConfig =
WalletConfig
{ baseUrl :: WalletUrl
}
deriving (Show, Eq, Generic)
deriving anyclass (FromJSON, ToJSON)
defaultWalletConfig :: WalletConfig
defaultWalletConfig =
WalletConfig
-- See Note [pab-ports] in "test/full/Plutus/PAB/CliSpec.hs".
{ baseUrl = WalletUrl $ BaseUrl Http "localhost" 9081 ""
}
instance Default WalletConfig where
def = defaultWalletConfig
data WalletMsg = StartingWallet Port
| ChainClientMsg Text
| Balancing TxBalanceMsg
deriving stock (Show, Generic)
deriving anyclass (ToJSON, FromJSON)
instance Pretty WalletMsg where
pretty = \case
StartingWallet port -> "Starting wallet server on port " <+> pretty port
ChainClientMsg m -> "Chain Client: " <+> pretty m
Balancing m -> pretty m
instance ToObject WalletMsg where
toObject _ = \case
StartingWallet port -> mkObjectStr "Starting wallet server" (Tagged @"port" port)
ChainClientMsg m -> mkObjectStr "Chain Client: " (Tagged @"msg" m)
Balancing m -> mkObjectStr "Balancing" (Tagged @"msg" m)