Milestone 3: RPC server, ZIP-320 #104

Merged
pitmutt merged 152 commits from milestone3 into master 2024-11-21 15:39:19 +00:00
7 changed files with 167 additions and 8 deletions
Showing only changes of commit 94bfca95ca - Show all commits

View file

@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- RPC module
## [0.6.0.0-beta] ## [0.6.0.0-beta]
### Added ### Added

8
app/Server.hs Normal file
View file

@ -0,0 +1,8 @@
module Server where
import Network.Wai.Handler.Warp (run)
import Servant
import Zenith.RPC (ZenithRPC(..), zenithServer)
main :: IO ()
main = run 8081 (serve (Proxy :: Proxy ZenithRPC) zenithServer)

View file

@ -41,8 +41,8 @@ constraints: any.Cabal ==3.10.3.0,
any.authenticate-oauth ==1.7, any.authenticate-oauth ==1.7,
any.auto-update ==0.2.1, any.auto-update ==0.2.1,
any.base ==4.18.2.1, any.base ==4.18.2.1,
any.base-compat ==0.14.0, any.base-compat ==0.13.1,
any.base-compat-batteries ==0.14.0, any.base-compat-batteries ==0.13.1,
any.base-orphans ==0.9.2, any.base-orphans ==0.9.2,
any.base16 ==1.0, any.base16 ==1.0,
any.base16-bytestring ==1.0.2.0, any.base16-bytestring ==1.0.2.0,
@ -59,9 +59,12 @@ constraints: any.Cabal ==3.10.3.0,
any.blaze-builder ==0.4.2.3, any.blaze-builder ==0.4.2.3,
any.blaze-html ==0.9.2.0, any.blaze-html ==0.9.2.0,
any.blaze-markup ==0.8.3.0, any.blaze-markup ==0.8.3.0,
any.boring ==0.2.2,
boring +tagged,
any.borsh ==0.3.0, any.borsh ==0.3.0,
any.brick ==2.4, any.brick ==2.4,
brick -demos, brick -demos,
any.bsb-http-chunked ==0.0.0.4,
any.byteorder ==1.0.4, any.byteorder ==1.0.4,
any.bytes ==0.17.3, any.bytes ==0.17.3,
any.bytestring ==0.11.5.3, any.bytestring ==0.11.5.3,
@ -90,6 +93,7 @@ constraints: any.Cabal ==3.10.3.0,
config-ini -enable-doctests, config-ini -enable-doctests,
any.configurator ==0.3.0.0, any.configurator ==0.3.0.0,
configurator -developer, configurator -developer,
any.constraints ==0.14.2,
any.containers ==0.6.7, any.containers ==0.6.7,
any.contravariant ==1.5.5, any.contravariant ==1.5.5,
contravariant +semigroups +statevar +tagged, contravariant +semigroups +statevar +tagged,
@ -113,6 +117,7 @@ constraints: any.Cabal ==3.10.3.0,
any.data-default-instances-dlist ==0.0.1, any.data-default-instances-dlist ==0.0.1,
any.data-default-instances-old-locale ==0.0.1, any.data-default-instances-old-locale ==0.0.1,
any.data-fix ==0.3.4, any.data-fix ==0.3.4,
any.dec ==0.0.6,
any.deepseq ==1.4.8.1, any.deepseq ==1.4.8.1,
any.directory ==1.3.8.4, any.directory ==1.3.8.4,
any.distributive ==0.6.2.1, any.distributive ==0.6.2.1,
@ -129,6 +134,7 @@ constraints: any.Cabal ==3.10.3.0,
any.exceptions ==0.10.7, any.exceptions ==0.10.7,
any.extra ==1.7.16, any.extra ==1.7.16,
any.fast-logger ==3.2.3, any.fast-logger ==3.2.3,
any.file-embed ==0.0.16.0,
any.filepath ==1.4.300.1, any.filepath ==1.4.300.1,
any.fixed ==0.3, any.fixed ==0.3,
any.foreign-rust ==0.1.0, any.foreign-rust ==0.1.0,
@ -169,7 +175,12 @@ constraints: any.Cabal ==3.10.3.0,
any.http-client-tls ==0.3.6.3, any.http-client-tls ==0.3.6.3,
any.http-conduit ==2.3.8.3, any.http-conduit ==2.3.8.3,
http-conduit +aeson, http-conduit +aeson,
any.http-date ==0.0.11,
any.http-media ==0.8.1.1,
any.http-semantics ==0.1.2,
any.http-types ==0.12.4, any.http-types ==0.12.4,
any.http2 ==5.2.6,
http2 -devel -h2spec,
any.indexed-traversable ==0.1.4, any.indexed-traversable ==0.1.4,
any.indexed-traversable-instances ==0.1.2, any.indexed-traversable-instances ==0.1.2,
any.integer-conversion ==0.1.1, any.integer-conversion ==0.1.1,
@ -196,6 +207,7 @@ constraints: any.Cabal ==3.10.3.0,
any.microlens-mtl ==0.2.0.3, any.microlens-mtl ==0.2.0.3,
any.microlens-th ==0.4.3.15, any.microlens-th ==0.4.3.15,
any.mime-types ==0.1.2.0, any.mime-types ==0.1.2.0,
any.mmorph ==1.2.0,
any.monad-control ==1.0.3.1, any.monad-control ==1.0.3.1,
any.monad-logger ==0.3.40, any.monad-logger ==0.3.40,
monad-logger +template_haskell, monad-logger +template_haskell,
@ -210,9 +222,13 @@ constraints: any.Cabal ==3.10.3.0,
nanovg -examples -gl2 -gles3 -stb_truetype, nanovg -examples -gl2 -gles3 -stb_truetype,
any.network ==3.2.1.0, any.network ==3.2.1.0,
network -devel, network -devel,
any.network-byte-order ==0.1.7,
any.network-control ==0.1.1,
any.network-uri ==2.6.4.2, any.network-uri ==2.6.4.2,
any.old-locale ==1.0.0.7, any.old-locale ==1.0.0.7,
any.old-time ==1.1.0.4, any.old-time ==1.1.0.4,
any.optparse-applicative ==0.18.1.0,
optparse-applicative +process,
any.os-string ==2.0.6, any.os-string ==2.0.6,
any.parallel ==3.2.2.0, any.parallel ==3.2.2.0,
any.parsec ==3.1.16.1, any.parsec ==3.1.16.1,
@ -225,6 +241,9 @@ constraints: any.Cabal ==3.10.3.0,
persistent-sqlite -build-sanity-exe +full-text-search +have-usleep +json1 -systemlib +uri-filenames -use-pkgconfig -use-stat3 +use-stat4, persistent-sqlite -build-sanity-exe +full-text-search +have-usleep +json1 -systemlib +uri-filenames -use-pkgconfig -use-stat3 +use-stat4,
any.persistent-template ==2.12.0.0, any.persistent-template ==2.12.0.0,
any.pretty ==1.1.3.6, any.pretty ==1.1.3.6,
any.prettyprinter ==1.7.1,
prettyprinter -buildreadme +text,
any.prettyprinter-ansi-terminal ==1.1.3,
any.primitive ==0.9.0.0, any.primitive ==0.9.0.0,
any.process ==1.6.19.0, any.process ==1.6.19.0,
any.profunctors ==5.6.2, any.profunctors ==5.6.2,
@ -236,6 +255,7 @@ constraints: any.Cabal ==3.10.3.0,
any.quickcheck-io ==0.2.0, any.quickcheck-io ==0.2.0,
any.quickcheck-transformer ==0.3.1.2, any.quickcheck-transformer ==0.3.1.2,
any.random ==1.2.1.2, any.random ==1.2.1.2,
any.recv ==0.1.0,
any.reflection ==2.1.8, any.reflection ==2.1.8,
reflection -slow +template-haskell, reflection -slow +template-haskell,
any.regex-base ==0.94.0.2, any.regex-base ==0.94.0.2,
@ -260,8 +280,15 @@ constraints: any.Cabal ==3.10.3.0,
semigroups +binary +bytestring -bytestring-builder +containers +deepseq +hashable +tagged +template-haskell +text +transformers +unordered-containers, semigroups +binary +bytestring -bytestring-builder +containers +deepseq +hashable +tagged +template-haskell +text +transformers +unordered-containers,
any.serialise ==0.2.6.1, any.serialise ==0.2.6.1,
serialise +newtime15, serialise +newtime15,
any.servant ==0.20.1,
any.servant-server ==0.20,
any.silently ==1.2.5.3, any.silently ==1.2.5.3,
any.simple-sendfile ==0.2.32,
simple-sendfile +allow-bsd -fallback,
any.singleton-bool ==0.1.8,
any.socks ==0.6.1, any.socks ==0.6.1,
any.some ==1.0.6,
some +newtype-unsafe,
any.sop-core ==0.5.0.2, any.sop-core ==0.5.0.2,
any.sort ==1.0.0.0, any.sort ==1.0.0.0,
any.split ==0.2.5, any.split ==0.2.5,
@ -296,6 +323,7 @@ constraints: any.Cabal ==3.10.3.0,
any.time-compat ==1.9.7, any.time-compat ==1.9.7,
any.time-locale-compat ==0.1.1.5, any.time-locale-compat ==0.1.1.5,
time-locale-compat -old-locale, time-locale-compat -old-locale,
any.time-manager ==0.1.0,
any.tls ==2.1.0, any.tls ==2.1.0,
tls -devel, tls -devel,
any.transformers ==0.6.1.0, any.transformers ==0.6.1.0,
@ -326,9 +354,18 @@ constraints: any.Cabal ==3.10.3.0,
any.vty-crossplatform ==0.4.0.0, any.vty-crossplatform ==0.4.0.0,
vty-crossplatform -demos, vty-crossplatform -demos,
any.vty-unix ==0.2.0.0, any.vty-unix ==0.2.0.0,
any.wai ==3.2.4,
any.wai-app-static ==3.1.9,
wai-app-static +crypton -print,
any.wai-extra ==3.1.15,
wai-extra -build-example,
any.wai-logger ==2.4.0,
any.warp ==3.4.1,
warp +allow-sendfilefd -network-bytestring -warp-debug +x509,
any.wide-word ==0.1.6.0, any.wide-word ==0.1.6.0,
any.witherable ==0.5, any.witherable ==0.5,
any.word-wrap ==0.5, any.word-wrap ==0.5,
any.word8 ==0.1.3,
any.wreq ==0.5.4.3, any.wreq ==0.5.4.3,
wreq -aws -developer +doctest -httpbin, wreq -aws -developer +doctest -httpbin,
any.zlib ==0.7.1.0, any.zlib ==0.7.1.0,

View file

@ -1040,10 +1040,9 @@ handleEvent wenv node model evt =
Nothing -> return $ ShowError "No wallet available" Nothing -> return $ ShowError "No wallet available"
Just cW -> do Just cW -> do
syncWallet (model ^. configuration) cW syncWallet (model ^. configuration) cW
return $ SwitchAddr (model ^. selAddr)
, Task $ do
pool <- pool <-
runNoLoggingT $ initPool $ c_dbPath $ model ^. configuration runNoLoggingT $
initPool $ c_dbPath $ model ^. configuration
wL <- getWallets pool (model ^. network) wL <- getWallets pool (model ^. network)
return $ LoadWallets wL return $ LoadWallets wL
] ]

55
src/Zenith/RPC.hs Normal file
View file

@ -0,0 +1,55 @@
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
module Zenith.RPC where
import Data.Aeson
import qualified Data.Text as T
import Servant
import ZcashHaskell.Types (RpcError(..), RpcResponse(..))
import Zenith.Types (RpcCall(..), ZenithMethod(..), ZenithParams(..))
type ZenithRPC
= "getinfo" :> Get '[ JSON] Value :<|> ReqBody '[ JSON] RpcCall :> Post
'[ JSON]
(RpcResponse Value)
zenithServer :: Server ZenithRPC
zenithServer = getinfo :<|> handleRPC
where
getinfo :: Handler Value
getinfo =
return $
object
[ "version" .= ("0.7.0.0-beta" :: String)
, "network" .= ("testnet" :: String)
]
handleRPC :: RpcCall -> Handler (RpcResponse Value)
handleRPC req =
case method req of
GetInfo ->
case parameters req of
GetInfoParams ->
return $
MakeRpcResponse
Nothing
(callId req)
(Just $ object ["data" .= ("Here's your info" :: String)])
_anyOtherParams ->
return $
MakeRpcResponse
(Just $ RpcError (-32602) "Invalid params")
(callId req)
Nothing
Test ->
case parameters req of
TestParams x ->
return $
MakeRpcResponse Nothing (callId req) (Just $ object ["data" .= x])
_anyOtherParams ->
return $
MakeRpcResponse
(Just $ RpcError (-32602) "Invalid params")
(callId req)
Nothing

View file

@ -94,6 +94,44 @@ data Config = Config
, c_zebraPort :: !Int , c_zebraPort :: !Int
} deriving (Eq, Prelude.Show) } deriving (Eq, Prelude.Show)
-- ** Zenith methods
data ZenithMethod
= GetInfo
| Test
deriving (Eq, Prelude.Show)
instance FromJSON ZenithMethod where
parseJSON =
withText "ZenithMethod" $ \case
"getinfo" -> pure GetInfo
"test" -> pure Test
_ -> fail "Invalid method"
data ZenithParams
= GetInfoParams
| TestParams !T.Text
deriving (Eq, Prelude.Show)
-- | A type to model Zenith RPC calls
data RpcCall = RpcCall
{ jsonrpc :: !T.Text
, callId :: !T.Text
, method :: !ZenithMethod
, parameters :: !ZenithParams
} deriving (Eq, Prelude.Show)
instance FromJSON RpcCall where
parseJSON =
withObject "RpcCall" $ \obj -> do
v <- obj .: "jsonrpc"
i <- obj .: "id"
m <- obj .: "method"
case m of
GetInfo -> pure $ RpcCall v i GetInfo GetInfoParams
Test -> do
p <- obj .: "params"
pure $ RpcCall v i Test (TestParams $ head p)
-- ** `zebrad` -- ** `zebrad`
-- | Type for modeling the tree state response -- | Type for modeling the tree state response
data ZebraTreeInfo = ZebraTreeInfo data ZebraTreeInfo = ZebraTreeInfo

View file

@ -35,6 +35,7 @@ library
Zenith.Utils Zenith.Utils
Zenith.Zcashd Zenith.Zcashd
Zenith.Scanner Zenith.Scanner
Zenith.RPC
hs-source-dirs: hs-source-dirs:
src src
build-depends: build-depends:
@ -80,6 +81,7 @@ library
, regex-compat , regex-compat
, regex-posix , regex-posix
, scientific , scientific
, servant-server
, text , text
, text-show , text-show
, time , time
@ -123,6 +125,20 @@ executable zenscan
pkgconfig-depends: rustzcash_wrapper pkgconfig-depends: rustzcash_wrapper
default-language: Haskell2010 default-language: Haskell2010
executable zenithserver
ghc-options: -main-is Server -threaded -rtsopts -with-rtsopts=-N
main-is: Server.hs
hs-source-dirs:
app
build-depends:
base >=4.12 && <5
, wai-extra
, warp
, servant-server
, zenith
pkgconfig-depends: rustzcash_wrapper
default-language: Haskell2010
test-suite zenith-tests test-suite zenith-tests
type: exitcode-stdio-1.0 type: exitcode-stdio-1.0
ghc-options: -threaded -rtsopts -with-rtsopts=-N ghc-options: -threaded -rtsopts -with-rtsopts=-N