Compare commits

..

No commits in common. "master" and "0.7.0.0-beta" have entirely different histories.

26 changed files with 782 additions and 4228 deletions

4
.gitignore vendored
View file

@ -5,7 +5,3 @@ zenith.db
zenith.log zenith.log
zenith.db-shm zenith.db-shm
zenith.db-wal zenith.db-wal
test.db
test.db-shm
test.db-wal

2
.gitmodules vendored
View file

@ -1,4 +1,4 @@
[submodule "zcash-haskell"] [submodule "zcash-haskell"]
path = zcash-haskell path = zcash-haskell
url = https://code.vergara.tech/Vergara_Tech/zcash-haskell url = https://git.vergara.tech/Vergara_Tech/zcash-haskell.git
branch = master branch = master

View file

@ -5,66 +5,6 @@ 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).
## [0.9.1.0-beta]
### Fixed
- RPC imports
## [0.9.0.0-beta]
### Added
- RPC
- `importvk`
- TUI
- Import viewing keys
- Import seed phrase
- GUI
- Import viewing keys
- Import seed phrase
### Changed
- Database schema for wallets and accounts
- RPC:
- New field in wallet schema
- New field in account schema
## [0.8.0.0-beta]
### Added
- TUI:
- Generate payment URI
- Read a payment URI
- Generate a Full Viewing Key
- Generate an Incoming Viewing Key
- GUI:
- Generate payment URI and QR code
- Read a payment URI and QR code
- Generate a Full Viewing Key
- Generate an Incoming Viewing Key
- RPC methods:
- `shieldnotes`
- `deshieldfunds`
- `getfullvk`
- `getincomingvk`
## [0.7.2.0-beta]
### Fixed
- Creation of change addresses during account creation in GUI ([#111](https://code.vergara.tech/Vergara_Tech/zenith/issues/111))
## [0.7.1.0-beta]
### Changed
- Removed workaround to obtain block time
## [0.7.0.0-beta] ## [0.7.0.0-beta]
### Added ### Added

View file

@ -210,18 +210,9 @@ main = do
zebraPort <- require config "zebraPort" zebraPort <- require config "zebraPort"
zebraHost <- require config "zebraHost" zebraHost <- require config "zebraHost"
nodePort <- require config "nodePort" nodePort <- require config "nodePort"
currencyCode <- require config "currencyCode"
dbFP <- getZenithPath dbFP <- getZenithPath
let dbFilePath = T.pack $ dbFP ++ dbFileName let dbFilePath = T.pack $ dbFP ++ dbFileName
let myConfig = let myConfig = Config dbFilePath zebraHost zebraPort nodeUser nodePwd nodePort
Config
dbFilePath
zebraHost
zebraPort
nodeUser
nodePwd
nodePort
currencyCode
if not (null args) if not (null args)
then do then do
case head args case head args

View file

@ -5,7 +5,7 @@ module Server where
import Control.Concurrent (forkIO, threadDelay) import Control.Concurrent (forkIO, threadDelay)
import Control.Exception (throwIO, throwTo, try) import Control.Exception (throwIO, throwTo, try)
import Control.Monad (forever, when) import Control.Monad (forever, when)
import Control.Monad.Logger (runNoLoggingT, runStderrLoggingT) import Control.Monad.Logger (runNoLoggingT)
import Data.Configurator import Data.Configurator
import qualified Data.Text as T import qualified Data.Text as T
import Network.Wai.Handler.Warp (run) import Network.Wai.Handler.Warp (run)
@ -14,7 +14,7 @@ import System.Exit
import System.Posix.Signals import System.Posix.Signals
import ZcashHaskell.Types (ZebraGetBlockChainInfo(..), ZebraGetInfo(..)) import ZcashHaskell.Types (ZebraGetBlockChainInfo(..), ZebraGetInfo(..))
import Zenith.Core (checkBlockChain, checkZebra) import Zenith.Core (checkBlockChain, checkZebra)
import Zenith.DB (getWallets, initDb, initPool, upgradeAccountTable) import Zenith.DB (getWallets, initDb, initPool)
import Zenith.RPC import Zenith.RPC
( State(..) ( State(..)
, ZenithRPC(..) , ZenithRPC(..)
@ -35,18 +35,9 @@ main = do
zebraPort <- require config "zebraPort" zebraPort <- require config "zebraPort"
zebraHost <- require config "zebraHost" zebraHost <- require config "zebraHost"
nodePort <- require config "nodePort" nodePort <- require config "nodePort"
currencyCode <- require config "currencyCode"
dbFP <- getZenithPath dbFP <- getZenithPath
let dbFilePath = T.pack $ dbFP ++ dbFileName let dbFilePath = T.pack $ dbFP ++ dbFileName
let myConfig = let myConfig = Config dbFilePath zebraHost zebraPort nodeUser nodePwd nodePort
Config
dbFilePath
zebraHost
zebraPort
nodeUser
nodePwd
nodePort
currencyCode
let ctx = authenticate myConfig :. EmptyContext let ctx = authenticate myConfig :. EmptyContext
w <- try $ checkZebra zebraHost zebraPort :: IO (Either IOError ZebraGetInfo) w <- try $ checkZebra zebraHost zebraPort :: IO (Either IOError ZebraGetInfo)
case w of case w of
@ -57,13 +48,12 @@ main = do
case bc of case bc of
Left e1 -> throwIO e1 Left e1 -> throwIO e1
Right chainInfo -> do Right chainInfo -> do
x <- runNoLoggingT $ initDb dbFilePath x <- initDb dbFilePath
case x of case x of
Left e2 -> throwIO $ userError e2 Left e2 -> throwIO $ userError e2
Right x' -> do Right x' -> do
when x' $ rescanZebra zebraHost zebraPort dbFilePath when x' $ rescanZebra zebraHost zebraPort dbFilePath
pool <- runNoLoggingT $ initPool dbFilePath pool <- runNoLoggingT $ initPool dbFilePath
_ <- runNoLoggingT $ upgradeAccountTable pool
walList <- getWallets pool $ zgb_net chainInfo walList <- getWallets pool $ zgb_net chainInfo
if not (null walList) if not (null walList)
then do then do
@ -77,7 +67,7 @@ main = do
zebraPort zebraPort
(zgb_net chainInfo) (zgb_net chainInfo)
threadDelay 90000000 threadDelay 90000000
putStrLn "Zenith RPC Server 0.9.1.0-beta" putStrLn "Zenith RPC Server 0.7.0.0-beta"
putStrLn "------------------------------" putStrLn "------------------------------"
putStrLn $ putStrLn $
"Connected to " ++ "Connected to " ++

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

View file

@ -6,15 +6,10 @@ with-compiler: ghc-9.6.5
source-repository-package source-repository-package
type: git type: git
location: https://code.vergara.tech/Vergara_Tech/haskell-hexstring.git location: https://git.vergara.tech/Vergara_Tech/haskell-hexstring.git
tag: 39d8da7b11a80269454c2f134a5c834e0f3cb9a7 tag: 39d8da7b11a80269454c2f134a5c834e0f3cb9a7
source-repository-package source-repository-package
type: git type: git
location: https://code.vergara.tech/Vergara_Tech/haskell-foreign-rust.git location: https://git.vergara.tech/Vergara_Tech/haskell-foreign-rust.git
tag: 335e804454cd30da2c526457be37e477f71e4665 tag: 335e804454cd30da2c526457be37e477f71e4665
source-repository-package
type: git
location: https://code.vergara.tech/Vergara_Tech/persistent-sqlite.git
tag: 85093ef51cb2bd245ac9a85925770fdb55afce9e

View file

@ -9,18 +9,19 @@ constraints: any.Cabal ==3.10.3.0,
any.OneTuple ==0.4.2, any.OneTuple ==0.4.2,
any.OpenGLRaw ==3.3.4.1, any.OpenGLRaw ==3.3.4.1,
OpenGLRaw -osandroid +usegles2 +useglxgetprocaddress +usenativewindowslibraries, OpenGLRaw -osandroid +usegles2 +useglxgetprocaddress +usenativewindowslibraries,
any.QuickCheck ==2.15.0.1, any.QuickCheck ==2.14.3,
QuickCheck -old-random +templatehaskell, QuickCheck -old-random +templatehaskell,
any.RSA ==2.4.1, any.RSA ==2.4.1,
any.SHA ==1.6.4.4, any.SHA ==1.6.4.4,
SHA -exe, SHA -exe,
any.StateVar ==1.2.2, any.StateVar ==1.2.2,
any.X11 ==1.9.2, any.X11 ==1.10.3,
X11 -pedantic,
any.adjunctions ==4.4.2, any.adjunctions ==4.4.2,
any.aeson ==2.2.3.0, any.aeson ==2.2.3.0,
aeson +ordered-keymap, aeson +ordered-keymap,
any.alex ==3.5.1.0, any.alex ==3.5.1.0,
any.ansi-terminal ==1.1.2, any.ansi-terminal ==1.1.1,
ansi-terminal -example, ansi-terminal -example,
any.ansi-terminal-types ==1.1, any.ansi-terminal-types ==1.1,
any.appar ==0.1.8, any.appar ==0.1.8,
@ -38,11 +39,11 @@ constraints: any.Cabal ==3.10.3.0,
attoparsec -developer, attoparsec -developer,
any.attoparsec-aeson ==2.2.2.0, any.attoparsec-aeson ==2.2.2.0,
any.authenticate-oauth ==1.7, any.authenticate-oauth ==1.7,
any.auto-update ==0.2.4, any.auto-update ==0.2.1,
any.base ==4.18.2.1, any.base ==4.18.2.1,
any.base-compat ==0.14.1, any.base-compat ==0.13.1,
any.base-compat-batteries ==0.14.1, any.base-compat-batteries ==0.13.1,
any.base-orphans ==0.9.3, 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,
any.base58-bytestring ==0.1.0, any.base58-bytestring ==0.1.0,
@ -61,16 +62,18 @@ constraints: any.Cabal ==3.10.3.0,
any.boring ==0.2.2, any.boring ==0.2.2,
boring +tagged, boring +tagged,
any.borsh ==0.3.0, any.borsh ==0.3.0,
any.brick ==2.6, any.brick ==2.4,
brick -demos, brick -demos,
any.bsb-http-chunked ==0.0.0.4, any.bsb-http-chunked ==0.0.0.4,
any.byteorder ==1.0.4, any.byteorder ==1.0.4,
any.bytes ==0.17.4, any.bytes ==0.17.3,
any.bytestring ==0.11.5.3, any.bytestring ==0.11.5.3,
any.bytestring-builder ==0.10.8.2.0,
bytestring-builder +bytestring_has_builder,
any.bytestring-to-vector ==0.3.0.1, any.bytestring-to-vector ==0.3.0.1,
any.c2hs ==0.28.8, any.c2hs ==0.28.8,
c2hs +base3 -regression, c2hs +base3 -regression,
any.cabal-doctest ==1.0.11, any.cabal-doctest ==1.0.10,
any.call-stack ==0.4.0, any.call-stack ==0.4.0,
any.case-insensitive ==1.2.1.0, any.case-insensitive ==1.2.1.0,
any.cborg ==0.2.10.0, any.cborg ==0.2.10.0,
@ -81,10 +84,10 @@ constraints: any.Cabal ==3.10.3.0,
any.clock ==0.8.4, any.clock ==0.8.4,
clock -llvm, clock -llvm,
any.colour ==2.3.6, any.colour ==2.3.6,
any.comonad ==5.0.9, any.comonad ==5.0.8,
comonad +containers +distributive +indexed-traversable, comonad +containers +distributive +indexed-traversable,
any.concurrent-output ==1.10.21, any.concurrent-output ==1.10.21,
any.conduit ==1.3.6, any.conduit ==1.3.5,
any.conduit-extra ==1.3.6, any.conduit-extra ==1.3.6,
any.config-ini ==0.2.7.0, any.config-ini ==0.2.7.0,
config-ini -enable-doctests, config-ini -enable-doctests,
@ -98,20 +101,21 @@ constraints: any.Cabal ==3.10.3.0,
any.crypto-api ==0.13.3, any.crypto-api ==0.13.3,
crypto-api -all_cpolys, crypto-api -all_cpolys,
any.crypto-pubkey-types ==0.4.3, any.crypto-pubkey-types ==0.4.3,
any.cryptohash-md5 ==0.11.101.0, any.crypton ==1.0.0,
any.cryptohash-sha1 ==0.11.101.0,
any.crypton ==1.0.1,
crypton -check_alignment +integer-gmp -old_toolchain_inliner +support_aesni +support_deepseq +support_pclmuldq +support_rdrand -support_sse +use_target_attributes, crypton -check_alignment +integer-gmp -old_toolchain_inliner +support_aesni +support_deepseq +support_pclmuldq +support_rdrand -support_sse +use_target_attributes,
any.crypton-connection ==0.4.3, any.crypton-connection ==0.4.1,
any.crypton-x509 ==1.7.7, any.crypton-x509 ==1.7.7,
any.crypton-x509-store ==1.6.9, any.crypton-x509-store ==1.6.9,
any.crypton-x509-system ==1.6.7, any.crypton-x509-system ==1.6.7,
any.crypton-x509-validation ==1.6.13, any.crypton-x509-validation ==1.6.12,
any.cryptonite ==0.30, any.cryptonite ==0.30,
cryptonite -check_alignment +integer-gmp -old_toolchain_inliner +support_aesni +support_deepseq -support_pclmuldq +support_rdrand -support_sse +use_target_attributes, cryptonite -check_alignment +integer-gmp -old_toolchain_inliner +support_aesni +support_deepseq -support_pclmuldq +support_rdrand -support_sse +use_target_attributes,
any.data-clist ==0.2, any.data-clist ==0.2,
any.data-default ==0.8.0.0, any.data-default ==0.7.1.1,
any.data-default-class ==0.2.0.0, any.data-default-class ==0.1.2.0,
any.data-default-instances-containers ==0.0.1,
any.data-default-instances-dlist ==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.dec ==0.0.6,
any.deepseq ==1.4.8.1, any.deepseq ==1.4.8.1,
@ -125,11 +129,11 @@ constraints: any.Cabal ==3.10.3.0,
any.easy-file ==0.2.5, any.easy-file ==0.2.5,
any.entropy ==0.4.1.10, any.entropy ==0.4.1.10,
entropy -donotgetentropy, entropy -donotgetentropy,
any.envy ==2.1.4.0, any.envy ==2.1.3.0,
any.esqueleto ==3.5.13.1, any.esqueleto ==3.5.11.2,
any.exceptions ==0.10.7, any.exceptions ==0.10.7,
any.extra ==1.8, any.extra ==1.7.16,
any.fast-logger ==3.2.5, any.fast-logger ==3.2.3,
any.file-embed ==0.0.16.0, 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,
@ -138,6 +142,8 @@ constraints: any.Cabal ==3.10.3.0,
any.formatting ==7.2.0, any.formatting ==7.2.0,
formatting -no-double-conversion, formatting -no-double-conversion,
any.free ==5.2, any.free ==5.2,
any.generic-deriving ==1.14.5,
generic-deriving +base-4-9,
any.generically ==0.1.1, any.generically ==0.1.1,
any.generics-sop ==0.5.1.4, any.generics-sop ==0.5.1.4,
any.ghc ==9.6.5, any.ghc ==9.6.5,
@ -147,34 +153,33 @@ constraints: any.Cabal ==3.10.3.0,
any.ghc-heap ==9.6.5, any.ghc-heap ==9.6.5,
any.ghc-prim ==0.10.0, any.ghc-prim ==0.10.0,
any.ghci ==9.6.5, any.ghci ==9.6.5,
any.half ==0.3.2, any.half ==0.3.1,
any.happy ==2.1.3, any.happy ==1.20.1.1,
any.happy-lib ==2.1.3,
any.hashable ==1.4.7.0, any.hashable ==1.4.7.0,
hashable -arch-native +integer-gmp -random-initial-seed, hashable -arch-native +integer-gmp -random-initial-seed,
any.haskell-lexer ==1.1.2, any.haskell-lexer ==1.1.1,
any.haskoin-core ==1.1.0, any.haskoin-core ==1.1.0,
any.hexstring ==0.12.1.0, any.hexstring ==0.12.1.0,
any.hourglass ==0.2.12, any.hourglass ==0.2.12,
any.hpc ==0.6.2.0, any.hpc ==0.6.2.0,
any.hsc2hs ==0.68.10, any.hsc2hs ==0.68.10,
hsc2hs -in-ghc-tree, hsc2hs -in-ghc-tree,
any.hspec ==2.11.10, any.hspec ==2.11.9,
any.hspec-core ==2.11.10, any.hspec-core ==2.11.9,
any.hspec-discover ==2.11.10, any.hspec-discover ==2.11.9,
any.hspec-expectations ==0.8.4, any.hspec-expectations ==0.8.4,
any.http-api-data ==0.6.1, any.http-api-data ==0.6.1,
http-api-data -use-text-show, http-api-data -use-text-show,
any.http-client ==0.7.17, any.http-client ==0.7.17,
http-client +network-uri, http-client +network-uri,
any.http-client-tls ==0.3.6.4, any.http-client-tls ==0.3.6.3,
any.http-conduit ==2.3.9.1, any.http-conduit ==2.3.8.3,
http-conduit +aeson, http-conduit +aeson,
any.http-date ==0.0.11, any.http-date ==0.0.11,
any.http-media ==0.8.1.1, any.http-media ==0.8.1.1,
any.http-semantics ==0.3.0, any.http-semantics ==0.1.2,
any.http-types ==0.12.4, any.http-types ==0.12.4,
any.http2 ==5.3.9, any.http2 ==5.2.6,
http2 -devel -h2spec, 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,
@ -182,19 +187,19 @@ constraints: any.Cabal ==3.10.3.0,
any.integer-gmp ==1.1, any.integer-gmp ==1.1,
any.integer-logarithms ==1.0.3.1, any.integer-logarithms ==1.0.3.1,
integer-logarithms -check-bounds +integer-gmp, integer-logarithms -check-bounds +integer-gmp,
any.invariant ==0.6.4, any.invariant ==0.6.3,
any.iproute ==1.7.15, any.iproute ==1.7.12,
any.kan-extensions ==5.2.6, any.kan-extensions ==5.2.6,
any.language-c ==0.10.0, any.language-c ==0.9.3,
language-c +iecfpextension +usebytestrings, language-c -allwarnings +iecfpextension +usebytestrings,
any.lens ==5.3.2, any.lens ==5.3.2,
lens -benchmark-uniplate -dump-splices +inlining -j +test-hunit +test-properties +test-templates +trustworthy, lens -benchmark-uniplate -dump-splices +inlining -j +test-hunit +test-properties +test-templates +trustworthy,
any.lens-aeson ==1.2.3, any.lens-aeson ==1.2.3,
any.lift-type ==0.1.2.0, any.lift-type ==0.1.1.1,
any.lifted-base ==0.2.3.12, any.lifted-base ==0.2.3.12,
any.linear ==1.22, any.linear ==1.22,
linear -herbie +template-haskell, linear -herbie +template-haskell,
any.megaparsec ==9.7.0, any.megaparsec ==9.6.1,
megaparsec -dev, megaparsec -dev,
any.memory ==0.18.0, any.memory ==0.18.0,
memory +support_bytestring +support_deepseq, memory +support_bytestring +support_deepseq,
@ -208,31 +213,30 @@ constraints: any.Cabal ==3.10.3.0,
monad-logger +template_haskell, monad-logger +template_haskell,
any.monad-loops ==0.4.3, any.monad-loops ==0.4.3,
monad-loops +base4, monad-loops +base4,
any.mono-traversable ==1.0.21.0, any.mono-traversable ==1.0.17.0,
any.monomer ==1.6.0.1, any.monomer ==1.6.0.1,
monomer -examples, monomer -examples,
any.mtl ==2.3.1, any.mtl ==2.3.1,
any.murmur3 ==1.0.5, any.murmur3 ==1.0.5,
any.nanovg ==0.8.1.0, any.nanovg ==0.8.1.0,
nanovg -examples -gl2 -gles3 -stb_truetype, nanovg -examples -gl2 -gles3 -stb_truetype,
any.network ==3.2.7.0, any.network ==3.2.1.0,
network -devel, network -devel,
any.network-byte-order ==0.1.7, any.network-byte-order ==0.1.7,
any.network-control ==0.1.3, any.network-control ==0.1.1,
any.network-info ==0.2.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, any.optparse-applicative ==0.18.1.0,
optparse-applicative +process, optparse-applicative +process,
any.os-string ==2.0.7, 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,
any.parser-combinators ==1.3.0, any.parser-combinators ==1.3.0,
parser-combinators -dev, parser-combinators -dev,
any.path-pieces ==0.2.1, any.path-pieces ==0.2.1,
any.pem ==0.2.4, any.pem ==0.2.4,
any.persistent ==2.14.6.3, any.persistent ==2.14.6.1,
any.persistent-sqlite ==2.13.3.0, any.persistent-sqlite ==2.13.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,
@ -246,13 +250,13 @@ constraints: any.Cabal ==3.10.3.0,
any.psqueues ==0.2.8.0, any.psqueues ==0.2.8.0,
any.pureMD5 ==2.1.4, any.pureMD5 ==2.1.4,
pureMD5 -test, pureMD5 -test,
any.qrcode-core ==0.9.10, any.qrcode-core ==0.9.9,
any.qrcode-juicypixels ==0.8.6, any.qrcode-juicypixels ==0.8.5,
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.recv ==0.1.0,
any.reflection ==2.1.9, 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,
any.regex-compat ==0.95.2.1, any.regex-compat ==0.95.2.1,
@ -267,7 +271,7 @@ constraints: any.Cabal ==3.10.3.0,
scientific -integer-simple, scientific -integer-simple,
any.sdl2 ==2.5.5.0, any.sdl2 ==2.5.5.0,
sdl2 -examples -no-linear -opengl-example +pkgconfig +recent-ish, sdl2 -examples -no-linear -opengl-example +pkgconfig +recent-ish,
any.secp256k1-haskell ==1.4.2, any.secp256k1-haskell ==1.2.0,
any.semialign ==1.3.1, any.semialign ==1.3.1,
semialign +semigroupoids, semialign +semigroupoids,
any.semigroupoids ==6.0.1, any.semigroupoids ==6.0.1,
@ -276,9 +280,9 @@ 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.2, any.servant ==0.20.1,
any.servant-server ==0.20.2, any.servant-server ==0.20,
any.silently ==1.2.5.4, any.silently ==1.2.5.3,
any.simple-sendfile ==0.2.32, any.simple-sendfile ==0.2.32,
simple-sendfile +allow-bsd -fallback, simple-sendfile +allow-bsd -fallback,
any.singleton-bool ==0.1.8, any.singleton-bool ==0.1.8,
@ -297,10 +301,8 @@ constraints: any.Cabal ==3.10.3.0,
any.strict ==0.5.1, any.strict ==0.5.1,
any.string-conversions ==0.4.0.1, any.string-conversions ==0.4.0.1,
any.system-cxx-std-lib ==1.0, any.system-cxx-std-lib ==1.0,
any.tagged ==0.8.9, any.tagged ==0.8.8,
tagged +deepseq +transformers, tagged +deepseq +transformers,
any.tasty ==1.5.2,
tasty +unix,
any.template-haskell ==2.20.0.0, any.template-haskell ==2.20.0.0,
any.terminal-size ==0.3.4, any.terminal-size ==0.3.4,
any.terminfo ==0.4.1.6, any.terminfo ==0.4.1.6,
@ -308,43 +310,42 @@ constraints: any.Cabal ==3.10.3.0,
any.text-iso8601 ==0.1.1, any.text-iso8601 ==0.1.1,
any.text-short ==0.1.6, any.text-short ==0.1.6,
text-short -asserts, text-short -asserts,
any.text-show ==3.11, any.text-show ==3.10.5,
text-show +integer-gmp, text-show +base-4-9 +integer-gmp +new-functor-classes +template-haskell-2-11,
any.text-zipper ==0.13, any.text-zipper ==0.13,
any.tf-random ==0.5, any.tf-random ==0.5,
any.th-abstraction ==0.7.1.0, any.th-abstraction ==0.7.0.0,
any.th-compat ==0.1.6, any.th-compat ==0.1.5,
any.th-lift ==0.8.6, any.th-lift ==0.8.4,
any.th-lift-instances ==0.1.20, any.th-lift-instances ==0.1.20,
any.these ==1.2.1, any.these ==1.2.1,
any.time ==1.12.2, any.time ==1.12.2,
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.2.1, any.time-manager ==0.1.0,
any.tls ==2.1.5, any.tls ==2.1.0,
tls -devel, tls -devel,
any.transformers ==0.6.1.0, any.transformers ==0.6.1.0,
any.transformers-base ==0.4.6, any.transformers-base ==0.4.6,
transformers-base +orphaninstances, transformers-base +orphaninstances,
any.transformers-compat ==0.7.2, any.transformers-compat ==0.7.2,
transformers-compat -five +five-three -four +generic-deriving +mtl -three -two, transformers-compat -five +five-three -four +generic-deriving +mtl -three -two,
any.typed-process ==0.2.12.0, any.typed-process ==0.2.11.1,
any.unix ==2.8.4.0, any.unix ==2.8.4.0,
any.unix-compat ==0.7.3, any.unix-compat ==0.7.2,
any.unix-time ==0.4.16, any.unix-time ==0.4.15,
any.unliftio ==0.2.25.0, any.unliftio ==0.2.25.0,
any.unliftio-core ==0.2.1.0, any.unliftio-core ==0.2.1.0,
any.unordered-containers ==0.2.20, any.unordered-containers ==0.2.20,
unordered-containers -debug, unordered-containers -debug,
any.utf8-string ==1.0.2, any.utf8-string ==1.0.2,
any.uuid ==1.3.16,
any.uuid-types ==1.0.6, any.uuid-types ==1.0.6,
any.vault ==0.3.1.5, any.vault ==0.3.1.5,
vault +useghc, vault +useghc,
any.vector ==0.13.2.0, any.vector ==0.13.1.0,
vector +boundschecks -internalchecks -unsafechecks -wall, vector +boundschecks -internalchecks -unsafechecks -wall,
any.vector-algorithms ==0.9.0.3, any.vector-algorithms ==0.9.0.2,
vector-algorithms +bench +boundschecks -internalchecks -llvm +properties -unsafechecks, vector-algorithms +bench +boundschecks -internalchecks -llvm +properties -unsafechecks,
any.vector-stream ==0.1.0.1, any.vector-stream ==0.1.0.1,
any.void ==0.7.3, any.void ==0.7.3,
@ -356,10 +357,10 @@ constraints: any.Cabal ==3.10.3.0,
any.wai ==3.2.4, any.wai ==3.2.4,
any.wai-app-static ==3.1.9, any.wai-app-static ==3.1.9,
wai-app-static +crypton -print, wai-app-static +crypton -print,
any.wai-extra ==3.1.17, any.wai-extra ==3.1.15,
wai-extra -build-example, wai-extra -build-example,
any.wai-logger ==2.5.0, any.wai-logger ==2.4.0,
any.warp ==3.4.7, any.warp ==3.4.1,
warp +allow-sendfilefd -network-bytestring -warp-debug +x509, 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,
@ -369,4 +370,4 @@ constraints: any.Cabal ==3.10.3.0,
wreq -aws -developer +doctest -httpbin, wreq -aws -developer +doctest -httpbin,
any.zlib ==0.7.1.0, any.zlib ==0.7.1.0,
zlib -bundled-c-zlib +non-blocking-ffi +pkg-config zlib -bundled-c-zlib +non-blocking-ffi +pkg-config
index-state: hackage.haskell.org 2024-12-14T09:52:48Z index-state: hackage.haskell.org 2024-07-10T18:40:26Z

BIN
sapling-output.params Normal file

Binary file not shown.

BIN
sapling-spend.params Normal file

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -20,14 +20,13 @@ module Zenith.DB where
import Codec.Borsh import Codec.Borsh
import Control.Exception (SomeException(..), throw, throwIO, try) import Control.Exception (SomeException(..), throw, throwIO, try)
import Control.Monad (forM_, unless, when) import Control.Monad (unless, when)
import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Monad.Logger import Control.Monad.Logger
( LoggingT ( LoggingT
, NoLoggingT , NoLoggingT
, logDebugN , logDebugN
, logErrorN , logErrorN
, logInfoN
, runNoLoggingT , runNoLoggingT
, runStderrLoggingT , runStderrLoggingT
) )
@ -53,7 +52,6 @@ import Haskoin.Transaction.Common
) )
import System.Directory (doesFileExist, getHomeDirectory, removeFile) import System.Directory (doesFileExist, getHomeDirectory, removeFile)
import System.FilePath ((</>)) import System.FilePath ((</>))
import ZcashHaskell.Keys (deriveUfvk, deriveUivk)
import ZcashHaskell.Orchard import ZcashHaskell.Orchard
( compareAddress ( compareAddress
, getSaplingFromUA , getSaplingFromUA
@ -67,7 +65,6 @@ import ZcashHaskell.Types
, OrchardBundle(..) , OrchardBundle(..)
, OrchardReceiver(..) , OrchardReceiver(..)
, OrchardWitness(..) , OrchardWitness(..)
, Phrase(..)
, SaplingAddress(..) , SaplingAddress(..)
, SaplingBundle(..) , SaplingBundle(..)
, SaplingReceiver(..) , SaplingReceiver(..)
@ -83,13 +80,11 @@ import ZcashHaskell.Types
, TxError(..) , TxError(..)
, UnifiedAddress(..) , UnifiedAddress(..)
, ValidAddress(..) , ValidAddress(..)
, ValidVk(..)
, ZcashNet(..) , ZcashNet(..)
) )
import Zenith.Tree (OrchardNode(..), SaplingNode(..), Tree(..), truncateTree) import Zenith.Tree (OrchardNode(..), SaplingNode(..), Tree(..), truncateTree)
import Zenith.Types import Zenith.Types
( AccountBalance(..) ( AccountBalance(..)
, AccountType(..)
, HexStringDB(..) , HexStringDB(..)
, OrchardSpendingKeyDB(..) , OrchardSpendingKeyDB(..)
, PhraseDB(..) , PhraseDB(..)
@ -97,10 +92,8 @@ import Zenith.Types
, RseedDB(..) , RseedDB(..)
, SaplingSpendingKeyDB(..) , SaplingSpendingKeyDB(..)
, ScopeDB(..) , ScopeDB(..)
, TransparentSpendingKeyDB(..) , TransparentSpendingKeyDB
, UnifiedAddressDB(..) , UnifiedAddressDB(..)
, UnifiedFvkDB(..)
, UnifiedIvkDB(..)
, ZcashAccountAPI(..) , ZcashAccountAPI(..)
, ZcashAddressAPI(..) , ZcashAddressAPI(..)
, ZcashNetDB(..) , ZcashNetDB(..)
@ -111,16 +104,6 @@ import Zenith.Types
, ZenithUuid(..) , ZenithUuid(..)
) )
share
[mkPersist sqlSettings, mkMigrate "schemaMigration"]
[persistLowerCase|
ZenithSchema
version Int
action T.Text
UniqueAction version action
deriving Show Eq
|]
share share
[mkPersist sqlSettings, mkMigrate "migrateAll"] [mkPersist sqlSettings, mkMigrate "migrateAll"]
[persistLowerCase| [persistLowerCase|
@ -130,19 +113,15 @@ share
seedPhrase PhraseDB seedPhrase PhraseDB
birthdayHeight Int birthdayHeight Int
lastSync Int default=0 lastSync Int default=0
local Bool default=TRUE
UniqueWallet name network UniqueWallet name network
deriving Show Eq deriving Show Eq
ZcashAccount ZcashAccount
index Int index Int
walletId ZcashWalletId walletId ZcashWalletId
name T.Text name T.Text
orchSpendKey OrchardSpendingKeyDB Maybe default=NULL orchSpendKey OrchardSpendingKeyDB
sapSpendKey SaplingSpendingKeyDB Maybe default=NULL sapSpendKey SaplingSpendingKeyDB
tPrivateKey TransparentSpendingKeyDB Maybe default=NULL tPrivateKey TransparentSpendingKeyDB
fvk UnifiedFvkDB Maybe default=NULL
ivk UnifiedIvkDB Maybe default=NULL
type AccountType default='Local'
UniqueAccount index walletId UniqueAccount index walletId
UniqueAccName walletId name UniqueAccName walletId name
deriving Show Eq deriving Show Eq
@ -346,7 +325,6 @@ toZcashWalletAPI w =
(getNet $ zcashWalletNetwork $ entityVal w) (getNet $ zcashWalletNetwork $ entityVal w)
(zcashWalletBirthdayHeight $ entityVal w) (zcashWalletBirthdayHeight $ entityVal w)
(zcashWalletLastSync $ entityVal w) (zcashWalletLastSync $ entityVal w)
(zcashWalletLocal $ entityVal w)
-- | @ZcashAccount@ -- | @ZcashAccount@
toZcashAccountAPI :: Entity ZcashAccount -> ZcashAccountAPI toZcashAccountAPI :: Entity ZcashAccount -> ZcashAccountAPI
@ -355,7 +333,6 @@ toZcashAccountAPI a =
(fromIntegral $ fromSqlKey $ entityKey a) (fromIntegral $ fromSqlKey $ entityKey a)
(fromIntegral $ fromSqlKey $ zcashAccountWalletId $ entityVal a) (fromIntegral $ fromSqlKey $ zcashAccountWalletId $ entityVal a)
(zcashAccountName $ entityVal a) (zcashAccountName $ entityVal a)
(zcashAccountType $ entityVal a)
-- | @WalletAddress@ -- | @WalletAddress@
toZcashAddressAPI :: Entity WalletAddress -> ZcashAddressAPI toZcashAddressAPI :: Entity WalletAddress -> ZcashAddressAPI
@ -448,159 +425,61 @@ orchToZcashNoteAPI pool n = do
-- | Initializes the database -- | Initializes the database
initDb :: initDb ::
T.Text -- ^ The database path to check T.Text -- ^ The database path to check
-> NoLoggingT IO (Either String Bool) -> IO (Either String Bool)
initDb dbName = do initDb dbName = do
x <- j <-
liftIO try $ PS.runSqlite dbName $ runMigrationQuiet migrateAll :: IO
(try $ PS.runSqlite dbName $ runMigrationUnsafeQuiet schemaMigration :: IO (Either SomeException [T.Text])
(Either SomeException [T.Text])) case j of
case x of Left _e1 -> do
Left _ -> do pool <- runNoLoggingT $ initPool dbName
logErrorN "Failed to initiate schema table" wallets <-
return $ Left "Failed to initiate schema table" runNoLoggingT $
Right _ -> do PS.retryOnBusy $
pool <- liftIO $ runNoLoggingT $ initPool dbName flip PS.runSqlPool pool $ do select . from $ table @ZcashWallet
j <- accounts <-
liftIO runNoLoggingT $
(try $ PS.runSqlite dbName $ runMigrationQuiet migrateAll :: IO PS.retryOnBusy $
(Either SomeException [T.Text])) flip PS.runSqlPool pool $ do select . from $ table @ZcashAccount
case j of abook <-
Left e1 -> do runNoLoggingT $
logDebugN "Automatic migration failed, starting manual" PS.retryOnBusy $
versions <- liftIO $ getVersions pool flip PS.runSqlPool pool $ do select . from $ table @AddressBook
migrateTables pool versions hDir <- getHomeDirectory
PS.runSqlite dbName $ printMigration migrateAll let backupDb = hDir </> "Zenith/.backup.db"
m <- checkDbFile <- doesFileExist backupDb
liftIO when checkDbFile $ removeFile backupDb
(try $ PS.runSqlite dbName $ runMigration migrateAll :: IO _ <- PS.runSqlite (T.pack backupDb) $ runMigrationQuiet migrateAll
(Either SomeException ())) backupPool <- runNoLoggingT $ initPool $ T.pack backupDb
case m of _ <-
Left e2 -> do runNoLoggingT $
logErrorN $ "Failed to migrate data tables " <> T.pack (show e2) PS.retryOnBusy $
return $ Left $ "Failed to migrate data tables" ++ show e2 flip PS.runSqlPool backupPool $ insertMany_ $ entityVal <$> wallets
Right _ -> do _ <-
logInfoN "Migration of tables successful" runNoLoggingT $
return $ Right False PS.retryOnBusy $
flip PS.runSqlPool backupPool $ insertMany_ $ entityVal <$> accounts
_ <-
runNoLoggingT $
PS.retryOnBusy $
flip PS.runSqlPool backupPool $ insertMany_ $ entityVal <$> abook
clearWalletTransactions pool
clearWalletData pool
m <-
try $ PS.runSqlite dbName $ runMigrationUnsafeQuiet migrateAll :: IO
(Either SomeException [T.Text])
case m of
Left e2 -> return $ Left $ "Failed to migrate data tables" ++ show e2
Right _ -> do Right _ -> do
_ <- return $ Right True
runNoLoggingT $ Right _ -> do
PS.retryOnBusy $ return $ Right False
flip PS.runSqlPool pool $ do
upsert (ZenithSchema 1 "Viewing Keys") []
wallets <-
runNoLoggingT $
PS.retryOnBusy $
flip PS.runSqlPool pool $ do select . from $ table @ZcashWallet
accounts <-
runNoLoggingT $
PS.retryOnBusy $
flip PS.runSqlPool pool $ do select . from $ table @ZcashAccount
addresses <-
runNoLoggingT $
PS.retryOnBusy $
flip PS.runSqlPool pool $ do select . from $ table @WalletAddress
abook <-
runNoLoggingT $
PS.retryOnBusy $
flip PS.runSqlPool pool $ do select . from $ table @AddressBook
hDir <- liftIO getHomeDirectory
let backupDb = hDir </> "Zenith/.backup.db"
checkDbFile <- liftIO $ doesFileExist backupDb
when checkDbFile $ liftIO $ removeFile backupDb
_ <- PS.runSqlite (T.pack backupDb) $ runMigrationQuiet migrateAll
backupPool <- liftIO $ runNoLoggingT $ initPool $ T.pack backupDb
_ <-
runNoLoggingT $
PS.retryOnBusy $
flip PS.runSqlPool backupPool $ insertMany_ $ entityVal <$> wallets
_ <-
runNoLoggingT $
PS.retryOnBusy $
flip PS.runSqlPool backupPool $ insertMany_ $ entityVal <$> accounts
_ <-
runNoLoggingT $
PS.retryOnBusy $
flip PS.runSqlPool backupPool $ insertMany_ $ entityVal <$> abook
_ <-
runNoLoggingT $
PS.retryOnBusy $
flip PS.runSqlPool backupPool $
insertMany_ $ entityVal <$> addresses
return $ Right False
migrateTables :: ConnectionPool -> [Int] -> NoLoggingT IO ()
migrateTables pool versions = do
unless (1 `elem` versions) $ do
logDebugN "Making version 1 changes"
_ <-
runNoLoggingT $
PS.retryOnBusy $
flip PS.runSqlPool pool $ do
rawExecute
"ALTER TABLE \"zcash_wallet\" ADD COLUMN \"local\" BOOLEAN NOT NULL DEFAULT TRUE;"
[]
rawExecute
"ALTER TABLE \"zcash_account\" RENAME COLUMN \"orch_spend_key\" TO \"orch_spend_key_old\";"
[]
rawExecute
"ALTER TABLE \"zcash_account\" RENAME COLUMN \"sap_spend_key\" TO \"sap_spend_key_old\";"
[]
rawExecute
"ALTER TABLE \"zcash_account\" RENAME COLUMN \"t_private_key\" TO \"t_private_key_old\";"
[]
rawExecute
"ALTER TABLE \"zcash_account\" ADD COLUMN \"orch_spend_key\" VARCHAR NULL DEFAULT NULL;"
[]
rawExecute
"ALTER TABLE \"zcash_account\" ADD COLUMN \"sap_spend_key\" VARCHAR NULL DEFAULT NULL;"
[]
rawExecute
"ALTER TABLE \"zcash_account\" ADD COLUMN \"t_private_key\" VARCHAR NULL DEFAULT NULL;"
[]
rawExecute
"UPDATE \"zcash_account\" SET \"orch_spend_key\" = \"orch_spend_key_old\", \"sap_spend_key\" = \"sap_spend_key_old\", \"t_private_key\" = \"t_private_key_old\" WHERE 1=1;"
[]
rawExecute
"ALTER TABLE \"zcash_account\" DROP COLUMN \"orch_spend_key_old\";"
[]
rawExecute
"ALTER TABLE \"zcash_account\" DROP COLUMN \"sap_spend_key_old\";"
[]
rawExecute
"ALTER TABLE \"zcash_account\" DROP COLUMN \"t_private_key_old\";"
[]
rawExecute
"ALTER TABLE \"zcash_account\" ADD COLUMN \"fvk\" VARCHAR NULL DEFAULT NULL;"
[]
rawExecute
"ALTER TABLE \"zcash_account\" ADD COLUMN \"ivk\" VARCHAR NULL DEFAULT NULL;"
[]
rawExecute
"ALTER TABLE \"zcash_account\" ADD COLUMN \"type\" VARCHAR NOT NULL DEFAULT 'Local';"
[]
_ <-
runNoLoggingT $
PS.retryOnBusy $
flip PS.runSqlPool pool $ do upsert (ZenithSchema 1 "Viewing Keys") []
logDebugN "Version 1 changes complete"
initPool :: T.Text -> NoLoggingT IO ConnectionPool initPool :: T.Text -> NoLoggingT IO ConnectionPool
initPool dbPath = do initPool dbPath = do
let dbInfo = PS.mkSqliteConnectionInfo dbPath let dbInfo = PS.mkSqliteConnectionInfo dbPath
PS.createSqlitePoolFromInfo dbInfo 5 PS.createSqlitePoolFromInfo dbInfo 5
getVersions :: ConnectionPool -> IO [Int]
getVersions pool = do
versions <-
runNoLoggingT $
PS.retryOnBusy $
flip PS.runSqlPool pool $ do
select $ do
v <- from $ table @ZenithSchema
orderBy [asc $ v ^. ZenithSchemaVersion]
pure (v ^. ZenithSchemaVersion)
return $ map (\(Value x) -> x) versions
-- | Upgrade the database -- | Upgrade the database
upgradeDb :: upgradeDb ::
T.Text -- ^ database path T.Text -- ^ database path
@ -629,32 +508,6 @@ walletExists pool n =
where_ (wallets ^. ZcashWalletId ==. val (toSqlKey $ fromIntegral n)) where_ (wallets ^. ZcashWalletId ==. val (toSqlKey $ fromIntegral n))
pure wallets pure wallets
getVkWallet :: ConnectionPool -> IO (Maybe (Entity ZcashWallet))
getVkWallet pool = do
runNoLoggingT $
PS.retryOnBusy $
flip PS.runSqlPool pool $ do
selectOne $ do
wal <- from $ table @ZcashWallet
where_ (wal ^. ZcashWalletName ==. val "Viewing Keys")
where_ (wal ^. ZcashWalletLocal ==. val False)
pure wal
saveVkWallet ::
ConnectionPool -> ZcashNet -> Int -> IO (Maybe (Entity ZcashWallet))
saveVkWallet pool znet bh = do
runNoLoggingT $
PS.retryOnBusy $
flip PS.runSqlPool pool $
insertUniqueEntity $
ZcashWallet
"Viewing Keys"
(ZcashNetDB znet)
(PhraseDB $ Phrase "")
bh
0
False
getNetwork :: ConnectionPool -> WalletAddressId -> IO ZcashNet getNetwork :: ConnectionPool -> WalletAddressId -> IO ZcashNet
getNetwork pool a = do getNetwork pool a = do
n <- n <-
@ -707,23 +560,6 @@ getAccounts pool w =
where_ (accs ^. ZcashAccountWalletId ==. val w) where_ (accs ^. ZcashAccountWalletId ==. val w)
pure accs pure accs
-- | Returns a list of accounts with no viewing keys. For database migration purposes
getAccountsNoVKs ::
ConnectionPool -- ^ The database path
-> NoLoggingT IO [(Value ZcashNetDB, Entity ZcashAccount)]
getAccountsNoVKs pool =
PS.retryOnBusy $
flip PS.runSqlPool pool $ do
select $ do
(wallet :& acc) <-
from $ table @ZcashWallet `innerJoin` table @ZcashAccount `on`
(\(wallet :& acc) ->
wallet ^. ZcashWalletId ==. acc ^. ZcashAccountWalletId)
where_
(acc ^. ZcashAccountType ==. val Local &&.
isNothing (acc ^. ZcashAccountFvk))
pure (wallet ^. ZcashWalletNetwork, acc)
getAccountById :: getAccountById ::
ConnectionPool -> ZcashAccountId -> IO (Maybe (Entity ZcashAccount)) ConnectionPool -> ZcashAccountId -> IO (Maybe (Entity ZcashAccount))
getAccountById pool za = do getAccountById pool za = do
@ -794,7 +630,6 @@ getAddresses pool a =
addrs <- from $ table @WalletAddress addrs <- from $ table @WalletAddress
where_ (addrs ^. WalletAddressAccId ==. val a) where_ (addrs ^. WalletAddressAccId ==. val a)
where_ (addrs ^. WalletAddressScope ==. val (ScopeDB External)) where_ (addrs ^. WalletAddressScope ==. val (ScopeDB External))
orderBy [asc $ addrs ^. WalletAddressId]
pure addrs pure addrs
getAddressById :: getAddressById ::
@ -812,9 +647,8 @@ getAddressById pool a = do
getInternalAddresses :: getInternalAddresses ::
ConnectionPool -- ^ The database path ConnectionPool -- ^ The database path
-> ZcashAccountId -- ^ The account ID to check -> ZcashAccountId -- ^ The account ID to check
-> IO [Entity WalletAddress] -> NoLoggingT IO [Entity WalletAddress]
getInternalAddresses pool a = getInternalAddresses pool a =
runNoLoggingT $
PS.retryOnBusy $ PS.retryOnBusy $
flip PS.runSqlPool pool $ do flip PS.runSqlPool pool $ do
select $ do select $ do
@ -1075,36 +909,6 @@ upgradeQrTable pool = do
[PersistText "TransparentPool", PersistText "Transparent"] [PersistText "TransparentPool", PersistText "Transparent"]
return () return ()
upgradeAccountTable :: ConnectionPool -> NoLoggingT IO ()
upgradeAccountTable pool = do
accs <- liftIO $ runNoLoggingT $ getAccountsNoVKs pool
logDebugN $ T.pack $ show $ length accs
forM_ accs $ \(Value znet, a) -> do
FullVk b <-
liftIO $
deriveUfvk
(getNet znet)
(getOrchSK <$> zcashAccountOrchSpendKey (entityVal a))
(getSapSK <$> zcashAccountSapSpendKey (entityVal a))
(getTranSK <$> zcashAccountTPrivateKey (entityVal a))
IncomingVk c <-
liftIO $
deriveUivk
(getNet znet)
(getOrchSK <$> zcashAccountOrchSpendKey (entityVal a))
(getSapSK <$> zcashAccountSapSpendKey (entityVal a))
(getTranSK <$> zcashAccountTPrivateKey (entityVal a))
runNoLoggingT $
PS.retryOnBusy $
flip PS.runSqlPool pool $ do
update $ \w -> do
set
w
[ ZcashAccountFvk =. just (val $ UnifiedFvkDB b)
, ZcashAccountIvk =. just (val $ UnifiedIvkDB c)
]
where_ $ w ^. ZcashAccountId ==. val (entityKey a)
-- * Wallet -- * Wallet
-- | Get the block of the last transaction known to the wallet -- | Get the block of the last transaction known to the wallet
getMaxWalletBlock :: getMaxWalletBlock ::
@ -1632,8 +1436,7 @@ getWalletTransactions ::
-> NoLoggingT IO () -> NoLoggingT IO ()
getWalletTransactions pool w = do getWalletTransactions pool w = do
let w' = entityVal w let w' = entityVal w
chgAddr <- chgAddr <- getInternalAddresses pool $ walletAddressAccId $ entityVal w
liftIO $ getInternalAddresses pool $ walletAddressAccId $ entityVal w
let ctReceiver = t_rec =<< readUnifiedAddressDB (entityVal $ head chgAddr) let ctReceiver = t_rec =<< readUnifiedAddressDB (entityVal $ head chgAddr)
let csReceiver = s_rec =<< readUnifiedAddressDB (entityVal $ head chgAddr) let csReceiver = s_rec =<< readUnifiedAddressDB (entityVal $ head chgAddr)
let coReceiver = o_rec =<< readUnifiedAddressDB (entityVal $ head chgAddr) let coReceiver = o_rec =<< readUnifiedAddressDB (entityVal $ head chgAddr)

File diff suppressed because it is too large Load diff

View file

@ -13,14 +13,14 @@
module Zenith.RPC where module Zenith.RPC where
import Control.Concurrent (forkIO) import Control.Concurrent (forkIO)
import Control.Exception (SomeException(..), try) import Control.Exception (try)
import Control.Monad (unless) import Control.Monad (unless, when)
import Control.Monad.IO.Class (liftIO) import Control.Monad.IO.Class (liftIO)
import Control.Monad.Logger (runNoLoggingT, runStderrLoggingT) import Control.Monad.Logger (runFileLoggingT, runNoLoggingT, runStderrLoggingT)
import Data.Aeson import Data.Aeson
import qualified Data.HexString as H import qualified Data.HexString as H
import Data.Int import Data.Int
import Data.Scientific (Scientific(..), floatingOrInteger) import Data.Scientific (floatingOrInteger)
import qualified Data.Text as T import qualified Data.Text as T
import qualified Data.Text.Encoding as E import qualified Data.Text.Encoding as E
import Data.Time.Clock (getCurrentTime) import Data.Time.Clock (getCurrentTime)
@ -36,18 +36,12 @@ import Database.Esqueleto.Experimental
) )
import Servant import Servant
import Text.Read (readMaybe) import Text.Read (readMaybe)
import ZcashHaskell.Keys import ZcashHaskell.Keys (generateWalletSeedPhrase)
( deriveUfvk
, deriveUivk
, encodeVK
, generateWalletSeedPhrase
)
import ZcashHaskell.Orchard (parseAddress) import ZcashHaskell.Orchard (parseAddress)
import ZcashHaskell.Types import ZcashHaskell.Types
( BlockResponse(..) ( BlockResponse(..)
, RpcError(..) , RpcError(..)
, Scope(..) , Scope(..)
, ValidVk(..)
, ZcashNet(..) , ZcashNet(..)
, ZebraGetBlockChainInfo(..) , ZebraGetBlockChainInfo(..)
) )
@ -56,11 +50,7 @@ import Zenith.Core
( checkBlockChain ( checkBlockChain
, createCustomWalletAddress , createCustomWalletAddress
, createZcashAccount , createZcashAccount
, deshieldNotes
, importViewingKey
, parseVK
, prepareTxV2 , prepareTxV2
, shieldTransparentNotes
, syncWallet , syncWallet
, updateCommitmentTrees , updateCommitmentTrees
) )
@ -104,15 +94,11 @@ import Zenith.DB
import Zenith.Scanner (checkIntegrity, processTx, updateConfs) import Zenith.Scanner (checkIntegrity, processTx, updateConfs)
import Zenith.Types import Zenith.Types
( AccountBalance(..) ( AccountBalance(..)
, AccountType(..)
, Config(..) , Config(..)
, HexStringDB(..) , HexStringDB(..)
, OrchardSpendingKeyDB(..)
, PhraseDB(..) , PhraseDB(..)
, PrivacyPolicy(..) , PrivacyPolicy(..)
, ProposedNote(..) , ProposedNote(..)
, UnifiedFvkDB(..)
, UnifiedIvkDB(..)
, ZcashAccountAPI(..) , ZcashAccountAPI(..)
, ZcashAddressAPI(..) , ZcashAddressAPI(..)
, ZcashNetDB(..) , ZcashNetDB(..)
@ -135,11 +121,6 @@ data ZenithMethod
| GetNewAddress | GetNewAddress
| GetOperationStatus | GetOperationStatus
| SendMany | SendMany
| ShieldNotes
| DeshieldFunds
| GetFVK
| GetIVK
| ImportVK
| UnknownMethod | UnknownMethod
deriving (Eq, Prelude.Show) deriving (Eq, Prelude.Show)
@ -155,11 +136,6 @@ instance ToJSON ZenithMethod where
toJSON GetNewAddress = Data.Aeson.String "getnewaddress" toJSON GetNewAddress = Data.Aeson.String "getnewaddress"
toJSON GetOperationStatus = Data.Aeson.String "getoperationstatus" toJSON GetOperationStatus = Data.Aeson.String "getoperationstatus"
toJSON SendMany = Data.Aeson.String "sendmany" toJSON SendMany = Data.Aeson.String "sendmany"
toJSON ShieldNotes = Data.Aeson.String "shieldnotes"
toJSON DeshieldFunds = Data.Aeson.String "deshieldfunds"
toJSON GetFVK = Data.Aeson.String "getfullvk"
toJSON GetIVK = Data.Aeson.String "getincomingvk"
toJSON ImportVK = Data.Aeson.String "importvk"
toJSON UnknownMethod = Data.Aeson.Null toJSON UnknownMethod = Data.Aeson.Null
instance FromJSON ZenithMethod where instance FromJSON ZenithMethod where
@ -176,11 +152,6 @@ instance FromJSON ZenithMethod where
"getnewaddress" -> pure GetNewAddress "getnewaddress" -> pure GetNewAddress
"getoperationstatus" -> pure GetOperationStatus "getoperationstatus" -> pure GetOperationStatus
"sendmany" -> pure SendMany "sendmany" -> pure SendMany
"shieldnotes" -> pure ShieldNotes
"deshieldfunds" -> pure DeshieldFunds
"getfullvk" -> pure GetFVK
"getincomingvk" -> pure GetIVK
"importvk" -> pure ImportVK
_ -> pure UnknownMethod _ -> pure UnknownMethod
data ZenithParams data ZenithParams
@ -196,10 +167,6 @@ data ZenithParams
| OpParams !ZenithUuid | OpParams !ZenithUuid
| SendParams !Int ![ProposedNote] !PrivacyPolicy | SendParams !Int ![ProposedNote] !PrivacyPolicy
| TestParams !T.Text | TestParams !T.Text
| ShieldNotesParams !Int
| DeshieldParams !Int !Scientific
| ViewingKeyParams !Int
| ImportVkParams !T.Text !T.Text !Int
deriving (Eq, Prelude.Show) deriving (Eq, Prelude.Show)
instance ToJSON ZenithParams where instance ToJSON ZenithParams where
@ -224,13 +191,6 @@ instance ToJSON ZenithParams where
Data.Aeson.Array $ V.fromList [Data.Aeson.String $ U.toText $ getUuid i] Data.Aeson.Array $ V.fromList [Data.Aeson.String $ U.toText $ getUuid i]
toJSON (SendParams i ns p) = toJSON (SendParams i ns p) =
Data.Aeson.Array $ V.fromList [jsonNumber i, toJSON ns, toJSON p] Data.Aeson.Array $ V.fromList [jsonNumber i, toJSON ns, toJSON p]
toJSON (ShieldNotesParams i) = Data.Aeson.Array $ V.fromList [jsonNumber i]
toJSON (DeshieldParams i s) =
Data.Aeson.Array $ V.fromList [jsonNumber i, Data.Aeson.Number s]
toJSON (ViewingKeyParams i) = Data.Aeson.Array $ V.fromList [jsonNumber i]
toJSON (ImportVkParams n k b) =
Data.Aeson.Array $
V.fromList [Data.Aeson.String n, Data.Aeson.String k, jsonNumber b]
data ZenithResponse data ZenithResponse
= InfoResponse !T.Text !ZenithInfo = InfoResponse !T.Text !ZenithInfo
@ -243,8 +203,6 @@ data ZenithResponse
| NewAddrResponse !T.Text !ZcashAddressAPI | NewAddrResponse !T.Text !ZcashAddressAPI
| OpResponse !T.Text !Operation | OpResponse !T.Text !Operation
| SendResponse !T.Text !U.UUID | SendResponse !T.Text !U.UUID
| MultiOpResponse !T.Text ![T.Text]
| ViewingKeyResponse !T.Text !T.Text
| ErrorResponse !T.Text !Double !T.Text | ErrorResponse !T.Text !Double !T.Text
deriving (Eq, Prelude.Show) deriving (Eq, Prelude.Show)
@ -266,8 +224,6 @@ instance ToJSON ZenithResponse where
toJSON (NewAddrResponse i a) = packRpcResponse i a toJSON (NewAddrResponse i a) = packRpcResponse i a
toJSON (OpResponse i u) = packRpcResponse i u toJSON (OpResponse i u) = packRpcResponse i u
toJSON (SendResponse i o) = packRpcResponse i o toJSON (SendResponse i o) = packRpcResponse i o
toJSON (MultiOpResponse i o) = packRpcResponse i o
toJSON (ViewingKeyResponse i k) = packRpcResponse i k
instance FromJSON ZenithResponse where instance FromJSON ZenithResponse where
parseJSON = parseJSON =
@ -342,9 +298,6 @@ instance FromJSON ZenithResponse where
k5 <- parseJSON r1 k5 <- parseJSON r1
pure $ NoteListResponse i k5 pure $ NoteListResponse i k5
Nothing -> fail "Unknown object" Nothing -> fail "Unknown object"
String s -> do
k7 <- parseJSON r1
pure $ MultiOpResponse i k7
_anyOther -> fail "Malformed JSON" _anyOther -> fail "Malformed JSON"
Number k -> do Number k -> do
case floatingOrInteger k of case floatingOrInteger k of
@ -352,7 +305,7 @@ instance FromJSON ZenithResponse where
Right k' -> pure $ NewItemResponse i k' Right k' -> pure $ NewItemResponse i k'
String s -> do String s -> do
case U.fromText s of case U.fromText s of
Nothing -> pure $ ViewingKeyResponse i s Nothing -> fail "Unknown value"
Just u -> pure $ SendResponse i u Just u -> pure $ SendResponse i u
_anyOther -> fail "Malformed JSON" _anyOther -> fail "Malformed JSON"
Just e1 -> pure $ ErrorResponse i (ecode e1) (emessage e1) Just e1 -> pure $ ErrorResponse i (ecode e1) (emessage e1)
@ -536,59 +489,6 @@ instance FromJSON RpcCall where
_anyOther -> pure $ RpcCall v i SendMany BadParams _anyOther -> pure $ RpcCall v i SendMany BadParams
else pure $ RpcCall v i SendMany BadParams else pure $ RpcCall v i SendMany BadParams
_anyOther -> pure $ RpcCall v i SendMany BadParams _anyOther -> pure $ RpcCall v i SendMany BadParams
ShieldNotes -> do
p <- obj .: "params"
case p of
Array a ->
if V.length a == 1
then do
x <- parseJSON $ a V.! 0
pure $ RpcCall v i ShieldNotes (ShieldNotesParams x)
else pure $ RpcCall v i ShieldNotes BadParams
_anyOther -> pure $ RpcCall v i ShieldNotes BadParams
DeshieldFunds -> do
p <- obj .: "params"
case p of
Array a ->
if V.length a == 2
then do
x <- parseJSON $ a V.! 0
y <- parseJSON $ a V.! 1
pure $ RpcCall v i DeshieldFunds (DeshieldParams x y)
else pure $ RpcCall v i DeshieldFunds BadParams
_anyOther -> pure $ RpcCall v i DeshieldFunds BadParams
GetFVK -> do
p <- obj .: "params"
case p of
Array a ->
if V.length a == 1
then do
x <- parseJSON $ a V.! 0
pure $ RpcCall v i GetFVK (ViewingKeyParams x)
else pure $ RpcCall v i GetFVK BadParams
_anyOther -> pure $ RpcCall v i GetFVK BadParams
GetIVK -> do
p <- obj .: "params"
case p of
Array a ->
if V.length a == 1
then do
x <- parseJSON $ a V.! 0
pure $ RpcCall v i GetIVK (ViewingKeyParams x)
else pure $ RpcCall v i GetIVK BadParams
_anyOther -> pure $ RpcCall v i GetIVK BadParams
ImportVK -> do
p <- obj .: "params"
case p of
Array a ->
if V.length a == 3
then do
x <- parseJSON $ a V.! 0
y <- parseJSON $ a V.! 1
z <- parseJSON $ a V.! 2
pure $ RpcCall v i ImportVK (ImportVkParams x y z)
else pure $ RpcCall v i ImportVK BadParams
_anyOther -> pure $ RpcCall v i ImportVK BadParams
type ZenithRPC type ZenithRPC
= "status" :> Get '[ JSON] Value :<|> BasicAuth "zenith-realm" Bool :> ReqBody = "status" :> Get '[ JSON] Value :<|> BasicAuth "zenith-realm" Bool :> ReqBody
@ -611,7 +511,7 @@ zenithServer state = getinfo :<|> handleRPC
getinfo = getinfo =
return $ return $
object object
[ "version" .= ("0.9.1.0-beta" :: String) [ "version" .= ("0.7.0.0-beta" :: String)
, "network" .= ("testnet" :: String) , "network" .= ("testnet" :: String)
] ]
handleRPC :: Bool -> RpcCall -> Handler ZenithResponse handleRPC :: Bool -> RpcCall -> Handler ZenithResponse
@ -687,7 +587,7 @@ zenithServer state = getinfo :<|> handleRPC
return $ return $
InfoResponse InfoResponse
(callId req) (callId req)
(ZenithInfo "0.9.1.0-beta" (w_network state) (w_build state)) (ZenithInfo "0.7.0.0-beta" (w_network state) (w_build state))
_anyOtherParams -> _anyOtherParams ->
return $ ErrorResponse (callId req) (-32602) "Invalid params" return $ ErrorResponse (callId req) (-32602) "Invalid params"
ListReceived -> ListReceived ->
@ -734,12 +634,9 @@ zenithServer state = getinfo :<|> handleRPC
acc <- liftIO $ getAccountById pool $ toSqlKey i acc <- liftIO $ getAccountById pool $ toSqlKey i
case acc of case acc of
Just acc' -> do Just acc' -> do
if zcashAccountType (entityVal acc') /= IncomingViewKey c <- liftIO $ getPoolBalance pool $ entityKey acc'
then do u <- liftIO $ getUnconfPoolBalance pool $ entityKey acc'
c <- liftIO $ getPoolBalance pool $ entityKey acc' return $ BalanceResponse (callId req) c u
u <- liftIO $ getUnconfPoolBalance pool $ entityKey acc'
return $ BalanceResponse (callId req) c u
else return $ readOnlyError $ callId req
Nothing -> Nothing ->
return $ return $
ErrorResponse (callId req) (-32006) "Account does not exist." ErrorResponse (callId req) (-32006) "Account does not exist."
@ -768,7 +665,6 @@ zenithServer state = getinfo :<|> handleRPC
(PhraseDB sP) (PhraseDB sP)
(w_startBlock state) (w_startBlock state)
0 0
True
case r of case r of
Nothing -> Nothing ->
return $ return $
@ -798,35 +694,27 @@ zenithServer state = getinfo :<|> handleRPC
case w of case w of
Just w' -> do Just w' -> do
aIdx <- liftIO $ getMaxAccount pool $ entityKey w' aIdx <- liftIO $ getMaxAccount pool $ entityKey w'
if zcashWalletLocal $ entityVal w' nAcc <-
then do liftIO
nAcc <- (try $ createZcashAccount t (aIdx + 1) w' :: IO
liftIO (Either IOError ZcashAccount))
(try $ case nAcc of
createZcashAccount Left e ->
t return $
(aIdx + 1) ErrorResponse (callId req) (-32010) $ T.pack $ show e
(getNet $ zcashWalletNetwork $ entityVal w') Right nAcc' -> do
w' :: IO (Either IOError ZcashAccount)) r <- liftIO $ saveAccount pool nAcc'
case nAcc of case r of
Left e -> Nothing ->
return $ return $
ErrorResponse (callId req) (-32010) $ ErrorResponse
T.pack $ show e (callId req)
Right nAcc' -> do (-32007)
r <- liftIO $ saveAccount pool nAcc' "Entity with that name already exists."
case r of Just x ->
Nothing -> return $
return $ NewItemResponse (callId req) $
ErrorResponse fromSqlKey $ entityKey x
(callId req)
(-32007)
"Entity with that name already exists."
Just x ->
return $
NewItemResponse (callId req) $
fromSqlKey $ entityKey x
else return $ notLocalError $ callId req
Nothing -> Nothing ->
return $ return $
ErrorResponse ErrorResponse
@ -934,145 +822,6 @@ zenithServer state = getinfo :<|> handleRPC
Just opkey' -> do Just opkey' -> do
acc <- acc <-
liftIO $ getAccountById pool $ toSqlKey $ fromIntegral a liftIO $ getAccountById pool $ toSqlKey $ fromIntegral a
case acc of
Just acc' -> do
if zcashAccountType (entityVal acc') == Local
then do
bl <-
liftIO $
getLastSyncBlock
pool
(zcashAccountWalletId $ entityVal acc')
_ <-
liftIO $
forkIO $ do
res <-
liftIO $
runNoLoggingT $
prepareTxV2
pool
zHost
zPort
znet
(entityKey acc')
bl
ns
p
case res of
Left e ->
finalizeOperation pool opkey' Failed $
T.pack $ show e
Right rawTx -> do
zebraRes <-
makeZebraCall
zHost
zPort
"sendrawtransaction"
[Data.Aeson.String $ H.toText rawTx]
case zebraRes of
Left e1 ->
finalizeOperation pool opkey' Failed $
T.pack $ show e1
Right txId ->
finalizeOperation
pool
opkey'
Successful $
"Tx ID: " <> H.toText txId
return $ SendResponse (callId req) opid
else return $ readOnlyError $ callId req
Nothing ->
return $
ErrorResponse
(callId req)
(-32006)
"Account does not exist."
_anyOtherParams ->
return $ ErrorResponse (callId req) (-32602) "Invalid params"
ShieldNotes -> do
case parameters req of
ShieldNotesParams i -> do
let dbPath = w_dbPath state
let net = w_network state
let zHost = w_host state
let zPort = w_port state
pool <- liftIO $ runNoLoggingT $ initPool dbPath
syncChk <- liftIO $ isSyncing pool
if syncChk
then return $
ErrorResponse
(callId req)
(-32012)
"The Zenith server is syncing, please try again later."
else do
acc <-
liftIO $ getAccountById pool $ toSqlKey $ fromIntegral i
case acc of
Just acc' -> do
bl <-
liftIO $
getLastSyncBlock
pool
(zcashAccountWalletId $ entityVal acc')
opids <-
liftIO $
runNoLoggingT $
shieldTransparentNotes
pool
zHost
zPort
net
(entityKey acc')
bl
let ops =
map
(\case
Left e -> T.pack $ show e
Right op -> U.toText op)
opids
return $ MultiOpResponse (callId req) ops
Nothing ->
return $
ErrorResponse
(callId req)
(-32006)
"Account does not exist."
_anyOtherParams ->
return $ ErrorResponse (callId req) (-32602) "Invalid params"
DeshieldFunds -> do
case parameters req of
DeshieldParams i k -> do
let dbPath = w_dbPath state
let net = w_network state
let zHost = w_host state
let zPort = w_port state
pool <- liftIO $ runNoLoggingT $ initPool dbPath
syncChk <- liftIO $ isSyncing pool
if syncChk
then return $
ErrorResponse
(callId req)
(-32012)
"The Zenith server is syncing, please try again later."
else do
opid <- liftIO nextRandom
startTime <- liftIO getCurrentTime
opkey <-
liftIO $
saveOperation pool $
Operation
(ZenithUuid opid)
startTime
Nothing
Processing
Nothing
case opkey of
Nothing ->
return $
ErrorResponse (callId req) (-32010) "Internal Error"
Just opkey' -> do
acc <-
liftIO $ getAccountById pool $ toSqlKey $ fromIntegral i
case acc of case acc of
Just acc' -> do Just acc' -> do
bl <- bl <-
@ -1084,15 +833,17 @@ zenithServer state = getinfo :<|> handleRPC
liftIO $ liftIO $
forkIO $ do forkIO $ do
res <- res <-
liftIO $
runNoLoggingT $ runNoLoggingT $
deshieldNotes prepareTxV2
pool pool
zHost zHost
zPort zPort
net znet
(entityKey acc') (entityKey acc')
bl bl
k ns
p
case res of case res of
Left e -> Left e ->
finalizeOperation pool opkey' Failed $ finalizeOperation pool opkey' Failed $
@ -1120,65 +871,6 @@ zenithServer state = getinfo :<|> handleRPC
"Account does not exist." "Account does not exist."
_anyOtherParams -> _anyOtherParams ->
return $ ErrorResponse (callId req) (-32602) "Invalid params" return $ ErrorResponse (callId req) (-32602) "Invalid params"
GetFVK -> do
case parameters req of
ViewingKeyParams aid -> do
let dbPath = w_dbPath state
pool <- liftIO $ runNoLoggingT $ initPool dbPath
acc <- liftIO $ getAccountById pool $ toSqlKey $ fromIntegral aid
case acc of
Just acc' -> do
case zcashAccountFvk (entityVal acc') of
Nothing ->
return $
ErrorResponse (callId req) (-32010) "Internal Error"
Just fvk ->
return $
ViewingKeyResponse
(callId req)
(encodeVK (FullVk $ getFvk fvk))
Nothing ->
return $
ErrorResponse (callId req) (-32006) "Account does not exist."
_anyOtherParams ->
return $ ErrorResponse (callId req) (-32602) "Invalid params"
GetIVK -> do
case parameters req of
ViewingKeyParams aid -> do
let dbPath = w_dbPath state
pool <- liftIO $ runNoLoggingT $ initPool dbPath
acc <- liftIO $ getAccountById pool $ toSqlKey $ fromIntegral aid
case acc of
Just acc' -> do
case zcashAccountIvk (entityVal acc') of
Nothing ->
return $
ErrorResponse (callId req) (-32010) "Internal Error"
Just ivk ->
return $
ViewingKeyResponse
(callId req)
(encodeVK $ IncomingVk $ getIvk ivk)
Nothing ->
return $
ErrorResponse (callId req) (-32006) "Account does not exist."
_anyOtherParams ->
return $ ErrorResponse (callId req) (-32602) "Invalid params"
ImportVK -> do
case parameters req of
ImportVkParams n k b -> do
let dbPath = w_dbPath state
let znet = w_network state
pool <- liftIO $ runNoLoggingT $ initPool dbPath
case parseVK k of
Nothing -> return $ invalidVkError $ callId req
Just vk -> do
res <- liftIO $ importViewingKey pool n znet vk b
case res of
Left e -> return $ ErrorResponse (callId req) (-32010) e
Right x -> return $ NewItemResponse (callId req) x
_anyOtherParams ->
return $ ErrorResponse (callId req) (-32602) "Invalid params"
authenticate :: Config -> BasicAuthCheck Bool authenticate :: Config -> BasicAuthCheck Bool
authenticate config = BasicAuthCheck check authenticate config = BasicAuthCheck check
@ -1224,7 +916,7 @@ scanZebra dbPath zHost zPort net = do
updateCommitmentTrees pool zHost zPort $ ZcashNetDB net updateCommitmentTrees pool zHost zPort $ ZcashNetDB net
runNoLoggingT $ runNoLoggingT $
mapM_ mapM_
(syncWallet (Config dbPath zHost zPort "user" "pwd" 8080 "usd")) (syncWallet (Config dbPath zHost zPort "user" "pwd" 8080))
wals wals
_ <- completeSync pool Successful _ <- completeSync pool Successful
return () return ()
@ -1240,28 +932,22 @@ scanZebra dbPath zHost zPort net = do
case r of case r of
Left _ -> completeSync pool Failed Left _ -> completeSync pool Failed
Right blk -> do Right blk -> do
bi <- r2 <-
saveBlock pool $ makeZebraCall
ZcashBlock zHost
(fromIntegral $ bl_height blk) zPort
(HexStringDB $ bl_hash blk) "getblock"
(fromIntegral $ bl_confirmations blk) [Data.Aeson.String $ T.pack (show bl), jsonNumber 0]
(fromIntegral $ bl_time blk) case r2 of
(ZcashNetDB net) Left _ -> completeSync pool Failed
mapM_ (processTx zHost zPort bi pool) $ bl_txs blk Right hb -> do
let blockTime = getBlockTime hb
-- * Errors bi <-
invalidVkError :: T.Text -> ZenithResponse saveBlock pool $
invalidVkError i = ZcashBlock
ErrorResponse i (-32013) "The viewing key provided is not valid." (fromIntegral $ bl_height blk)
(HexStringDB $ bl_hash blk)
readOnlyError :: T.Text -> ZenithResponse (fromIntegral $ bl_confirmations blk)
readOnlyError i = blockTime
ErrorResponse i (-32014) "Read-only account, operation is not valid." (ZcashNetDB net)
mapM_ (processTx zHost zPort bi pool) $ bl_txs blk
notLocalError :: T.Text -> ZenithResponse
notLocalError i =
ErrorResponse
i
(-32015)
"The wallet is not local, cannot create new accounts."

View file

@ -50,7 +50,6 @@ import Zenith.DB
, saveTransaction , saveTransaction
, startSync , startSync
, updateWalletSync , updateWalletSync
, upgradeAccountTable
, upgradeQrTable , upgradeQrTable
) )
import Zenith.Types import Zenith.Types
@ -78,7 +77,7 @@ rescanZebra host port dbFilePath = do
pool1 <- runNoLoggingT $ initPool dbFilePath pool1 <- runNoLoggingT $ initPool dbFilePath
{-pool2 <- runNoLoggingT $ initPool dbFilePath-} {-pool2 <- runNoLoggingT $ initPool dbFilePath-}
{-pool3 <- runNoLoggingT $ initPool dbFilePath-} {-pool3 <- runNoLoggingT $ initPool dbFilePath-}
_ <- runNoLoggingT $ initDb dbFilePath _ <- initDb dbFilePath
upgradeQrTable pool1 upgradeQrTable pool1
clearWalletTransactions pool1 clearWalletTransactions pool1
clearWalletData pool1 clearWalletData pool1
@ -134,16 +133,29 @@ processBlock host port pool pg net b = do
_ <- completeSync pool Failed _ <- completeSync pool Failed
liftIO $ throwIO $ userError e liftIO $ throwIO $ userError e
Right blk -> do Right blk -> do
bi <- r2 <-
saveBlock pool $ liftIO $
ZcashBlock makeZebraCall
(fromIntegral $ bl_height blk) host
(HexStringDB $ bl_hash blk) port
(fromIntegral $ bl_confirmations blk) "getblock"
(fromIntegral $ bl_time blk) [Data.Aeson.String $ T.pack $ show b, jsonNumber 0]
net case r2 of
mapM_ (processTx host port bi pool) $ bl_txs blk Left e2 -> do
liftIO $ tick pg _ <- completeSync pool Failed
liftIO $ throwIO $ userError e2
Right hb -> do
let blockTime = getBlockTime hb
bi <-
saveBlock pool $
ZcashBlock
(fromIntegral $ bl_height blk)
(HexStringDB $ bl_hash blk)
(fromIntegral $ bl_confirmations blk)
blockTime
net
mapM_ (processTx host port bi pool) $ bl_txs blk
liftIO $ tick pg
-- | Function to process a raw transaction -- | Function to process a raw transaction
processTx :: processTx ::
@ -217,9 +229,8 @@ clearSync config = do
case bc of case bc of
Left e1 -> throwIO e1 Left e1 -> throwIO e1
Right chainInfo -> do Right chainInfo -> do
x <- runNoLoggingT $ initDb dbPath x <- initDb dbPath
_ <- upgradeQrTable pool _ <- upgradeQrTable pool
_ <- runNoLoggingT $ upgradeAccountTable pool
case x of case x of
Left e2 -> throwIO $ userError e2 Left e2 -> throwIO $ userError e2
Right x' -> do Right x' -> do

View file

@ -40,8 +40,6 @@ import ZcashHaskell.Types
, Scope(..) , Scope(..)
, TransparentAddress(..) , TransparentAddress(..)
, TransparentSpendingKey , TransparentSpendingKey
, UnifiedFullViewingKey(..)
, UnifiedIncomingViewingKey(..)
, ValidAddress(..) , ValidAddress(..)
, ZcashNet(..) , ZcashNet(..)
) )
@ -105,41 +103,6 @@ newtype RseedDB = RseedDB
derivePersistField "RseedDB" derivePersistField "RseedDB"
newtype UnifiedFvkDB = UnifiedFvkDB
{ getFvk :: UnifiedFullViewingKey
} deriving newtype (Eq, Show, Read)
derivePersistField "UnifiedFvkDB"
newtype UnifiedIvkDB = UnifiedIvkDB
{ getIvk :: UnifiedIncomingViewingKey
} deriving newtype (Eq, Show, Read)
derivePersistField "UnifiedIvkDB"
data AccountType
= Local
| FullViewKey
| IncomingViewKey
deriving (Eq, Show, Read)
derivePersistField "AccountType"
instance ToJSON AccountType where
toJSON at =
case at of
Local -> Data.Aeson.String "Local"
FullViewKey -> Data.Aeson.String "FullViewKey"
IncomingViewKey -> Data.Aeson.String "IncomingViewKey"
instance FromJSON AccountType where
parseJSON =
withText "AccountType" $ \case
"Local" -> return Local
"FullViewKey" -> return FullViewKey
"IncomingViewKey" -> return IncomingViewKey
_ -> fail "Not a valid Account type"
-- * RPC -- * RPC
-- | Type for Configuration parameters -- | Type for Configuration parameters
data Config = Config data Config = Config
@ -149,7 +112,6 @@ data Config = Config
, c_zenithUser :: !BS.ByteString , c_zenithUser :: !BS.ByteString
, c_zenithPwd :: !BS.ByteString , c_zenithPwd :: !BS.ByteString
, c_zenithPort :: !Int , c_zenithPort :: !Int
, c_currencyCode :: !T.Text
} deriving (Eq, Prelude.Show) } deriving (Eq, Prelude.Show)
data ZcashPool data ZcashPool
@ -191,7 +153,6 @@ data ZcashWalletAPI = ZcashWalletAPI
, zw_network :: !ZcashNet , zw_network :: !ZcashNet
, zw_birthday :: !Int , zw_birthday :: !Int
, zw_lastSync :: !Int , zw_lastSync :: !Int
, zw_local :: !Bool
} deriving (Eq, Prelude.Show) } deriving (Eq, Prelude.Show)
$(deriveJSON defaultOptions {fieldLabelModifier = drop 3} ''ZcashWalletAPI) $(deriveJSON defaultOptions {fieldLabelModifier = drop 3} ''ZcashWalletAPI)
@ -200,7 +161,6 @@ data ZcashAccountAPI = ZcashAccountAPI
{ za_index :: !Int { za_index :: !Int
, za_wallet :: !Int , za_wallet :: !Int
, za_name :: !T.Text , za_name :: !T.Text
, za_type :: !AccountType
} deriving (Eq, Prelude.Show) } deriving (Eq, Prelude.Show)
$(deriveJSON defaultOptions {fieldLabelModifier = drop 3} ''ZcashAccountAPI) $(deriveJSON defaultOptions {fieldLabelModifier = drop 3} ''ZcashAccountAPI)
@ -547,19 +507,3 @@ encodeHexText' t =
if T.length t > 0 if T.length t > 0
then C.unpack . B64.encode $ E.encodeUtf8 t then C.unpack . B64.encode $ E.encodeUtf8 t
else C.unpack . B64.encode $ E.encodeUtf8 "Sent from Zenith" else C.unpack . B64.encode $ E.encodeUtf8 "Sent from Zenith"
-- | Define a data structure for the parsed components
data ZcashPaymentURI = ZcashPaymentURI
{ uriAddress :: String
, uriAmount :: Maybe Double
, uriMemo :: T.Text
, uriLabel :: Maybe String
, uriMessage :: Maybe String
} deriving (Show, Eq)
-- | Define a data structure for the URI QR image
data URIQrCode = URIQrCode
{ uriBytes :: BS.ByteString -- Image as ByteString
, uriWidth :: Double -- Number of columns in QR Image
, uriHeight :: Double -- Number of rows in a QR Image
} deriving (Show, Eq)

View file

@ -2,32 +2,16 @@
module Zenith.Utils where module Zenith.Utils where
import Control.Exception (SomeException, try)
import Control.Monad (when)
import Data.Aeson import Data.Aeson
import qualified Data.Aeson.Key as K
import qualified Data.Aeson.KeyMap as KM
import Data.Aeson.Types (parseMaybe)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Base64 as B64
import qualified Data.ByteString.Char8 as BC
import qualified Data.ByteString.Lazy as B
import qualified Data.ByteString.Lazy.Char8 as BL
import Data.Char (isAlphaNum, isSpace) import Data.Char (isAlphaNum, isSpace)
import Data.Functor (void) import Data.Functor (void)
import Data.Maybe import Data.Maybe
import Data.Ord (clamp) import Data.Ord (clamp)
import Data.Scientific (Scientific(..), Scientific, scientific, toRealFloat) import Data.Scientific (Scientific(..), scientific)
import qualified Data.Text as T import qualified Data.Text as T
import qualified Data.Text.Encoding as E import qualified Data.Text.Encoding as E
--import qualified Data.Text.Encoding as TE
import Network.HTTP.Simple
import Network.URI (escapeURIString, isUnreserved)
import System.Directory import System.Directory
import System.Process (createProcess_, shell) import System.Process (createProcess_, shell)
import Text.Printf (printf)
import Text.Read (readMaybe)
import Text.Regex.Posix import Text.Regex.Posix
import ZcashHaskell.Orchard import ZcashHaskell.Orchard
( encodeUnifiedAddress ( encodeUnifiedAddress
@ -41,13 +25,10 @@ import ZcashHaskell.Transparent
) )
import ZcashHaskell.Types import ZcashHaskell.Types
( ExchangeAddress(..) ( ExchangeAddress(..)
, ExchangeAddress(..)
, Phrase(..)
, SaplingAddress(..) , SaplingAddress(..)
, TransparentAddress(..) , TransparentAddress(..)
, UnifiedAddress(..) , UnifiedAddress(..)
, ValidAddress(..) , ValidAddress(..)
, ValidAddress(..)
, ZcashNet(..) , ZcashNet(..)
) )
import ZcashHaskell.Utils (makeZebraCall) import ZcashHaskell.Utils (makeZebraCall)
@ -56,7 +37,6 @@ import Zenith.Types
, PrivacyPolicy(..) , PrivacyPolicy(..)
, UnifiedAddressDB(..) , UnifiedAddressDB(..)
, ZcashAddress(..) , ZcashAddress(..)
, ZcashPaymentURI(..)
, ZcashPool(..) , ZcashPool(..)
) )
@ -72,7 +52,7 @@ displayZec s
| abs s < 100000000 = show (fromIntegral s / 100000) ++ " mZEC" | abs s < 100000000 = show (fromIntegral s / 100000) ++ " mZEC"
| otherwise = show (fromIntegral s / 100000000) ++ " ZEC " | otherwise = show (fromIntegral s / 100000000) ++ " ZEC "
-- | Helper function to display small amounts of TAZ -- | Helper function to display small amounts of ZEC
displayTaz :: Integer -> String displayTaz :: Integer -> String
displayTaz s displayTaz s
| abs s < 100 = show s ++ " tazs" | abs s < 100 = show s ++ " tazs"
@ -255,7 +235,7 @@ isValidString c = do
padWithZero :: Int -> String -> String padWithZero :: Int -> String -> String
padWithZero n s padWithZero n s
| length s >= n = s | (length s) >= n = s
| otherwise = padWithZero n ("0" ++ s) | otherwise = padWithZero n ("0" ++ s)
isEmpty :: [a] -> Bool isEmpty :: [a] -> Bool
@ -268,119 +248,3 @@ getChainTip zHost zPort = do
case r of case r of
Left e1 -> pure 0 Left e1 -> pure 0
Right i -> pure i Right i -> pure i
-- Function to fetch Zcash price from CoinGecko
getZcashPrice :: T.Text -> IO (Maybe Double)
getZcashPrice currency = do
let url =
"https://api.coingecko.com/api/v3/simple/price?ids=zcash&vs_currencies=" <>
T.unpack currency
response <- httpJSONEither (parseRequest_ url)
case getResponseBody response of
Right (Object obj)
-- Extract "zcash" object
-> do
case KM.lookup "zcash" obj of
Just (Object zcashObj)
-- Extract the currency price
->
case KM.lookup (K.fromText (T.toLower currency)) zcashObj of
Just (Number price) -> return (Just (toRealFloat price))
_ -> return Nothing
_ -> return Nothing
_ -> return Nothing
-- Parse memo result to convert it to a ByteString
processEither :: Either String BC.ByteString -> BC.ByteString
processEither (Right bs) = bs
processEither (Left e) = BC.pack e -- Returns the error message
-- Parse the query string into key-value pairs
parseQuery :: String -> [(String, String)]
parseQuery query = map (breakOn '=') (splitOn '&' query)
where
splitOn :: Char -> String -> [String]
splitOn _ [] = [""]
splitOn delim (c:cs)
| c == delim = "" : rest
| otherwise = (c : head rest) : tail rest
where
rest = splitOn delim cs
breakOn :: Char -> String -> (String, String)
breakOn delim str = (key, drop 1 value)
where
(key, value) = span (/= delim) str
-- Parse a ZIP-321 encoded string into a ZcashPayment structure
parseZcashPayment :: String -> Either String ZcashPaymentURI
parseZcashPayment input
| not (T.isPrefixOf "zcash:" (T.pack input)) =
Left "Invalid scheme: must start with 'zcash:'"
| otherwise =
let (addrPart, queryPart) = break (== '?') (drop 6 input)
queryParams = parseQuery (drop 1 queryPart)
in Right
ZcashPaymentURI
{ uriAddress = addrPart
, uriAmount = lookup "amount" queryParams >>= readMaybe
, uriMemo =
case lookup "memo" queryParams of
Just m ->
T.pack
(BC.unpack
(processEither $ decodeBase64Unpadded (BC.pack m)))
_ -> ""
, uriLabel = lookup "label" queryParams
, uriMessage = lookup "message" queryParams
}
-- Function to pad a base64 string if it's not a multiple of 4
padBase64 :: BC.ByteString -> BC.ByteString
padBase64 bs = bs <> BC.replicate paddingLength '='
where
paddingLength = (4 - BC.length bs `mod` 4) `mod` 4
-- Function to decode a base64 un-padded string
decodeBase64Unpadded :: BC.ByteString -> Either String BC.ByteString
decodeBase64Unpadded = B64.decode . padBase64
-- Function to encode memo as un-padded Base64
encodeBase64Memo :: String -> String
encodeBase64Memo = BC.unpack . BC.takeWhile (/= '=') . B64.encode . BC.pack
-- Function to drop trailing zeros
dropTrailingZeros :: String -> String
dropTrailingZeros str =
let withoutZeros = reverse (dropWhile (== '0') (reverse str))
in if last withoutZeros == '.'
then withoutZeros ++ "0" -- Ensure at least one decimal place
else withoutZeros
-- Function to create a ZIP-321 URI
createZip321 :: String -> Maybe Double -> Maybe String -> String
createZip321 address mAmount mMemo =
"zcash:" ++
address ++
maybe
""
(\amount -> "?amount=" ++ dropTrailingZeros (printf "%.8f" amount))
mAmount ++
maybe
""
(\memo -> "&memo=" ++ escapeURIString isUnreserved (encodeBase64Memo memo))
mMemo
getTransparentFromUA :: UnifiedAddress -> Maybe TransparentAddress
getTransparentFromUA ua = TransparentAddress (ua_net ua) <$> t_rec ua
-- Function to check if Text is non-empty after trimming leading spaces
isNotEmptyAfterTrim :: T.Text -> Bool
isNotEmptyAfterTrim txt = not (T.null (T.stripStart txt))
-- Function to convert a Scientific number to Int
scientificToInt :: Scientific -> Int
scientificToInt sc = fromIntegral $ round $ toRealFloat sc
-- Convert a ByteString to Phrase
toPhrase :: BS.ByteString -> Phrase
toPhrase = Phrase

View file

@ -38,8 +38,7 @@ import Zenith.RPC
, zenithServer , zenithServer
) )
import Zenith.Types import Zenith.Types
( AccountType(..) ( Config(..)
, Config(..)
, PrivacyPolicy(..) , PrivacyPolicy(..)
, ProposedNote(..) , ProposedNote(..)
, ValidAddressAPI(..) , ValidAddressAPI(..)
@ -59,16 +58,7 @@ main = do
zebraPort <- require config "zebraPort" zebraPort <- require config "zebraPort"
zebraHost <- require config "zebraHost" zebraHost <- require config "zebraHost"
nodePort <- require config "nodePort" nodePort <- require config "nodePort"
currencyCode <- require config "currencyCode" let myConfig = Config dbFilePath zebraHost zebraPort nodeUser nodePwd nodePort
let myConfig =
Config
dbFilePath
zebraHost
zebraPort
nodeUser
nodePwd
nodePort
currencyCode
hspec $ do hspec $ do
describe "RPC methods" $ do describe "RPC methods" $ do
beforeAll_ (startAPI myConfig) $ do beforeAll_ (startAPI myConfig) $ do
@ -96,7 +86,7 @@ main = do
Left e -> assertFailure e Left e -> assertFailure e
Right r -> Right r ->
r `shouldBe` r `shouldBe`
InfoResponse "zh" (ZenithInfo "0.8.0.0-beta" TestNet "v2.1.0") InfoResponse "zh" (ZenithInfo "0.7.0.0-beta" TestNet "v1.9.0")
describe "Wallets" $ do describe "Wallets" $ do
describe "listwallet" $ do describe "listwallet" $ do
it "bad credentials" $ do it "bad credentials" $ do
@ -308,9 +298,7 @@ main = do
Left e -> assertFailure e Left e -> assertFailure e
Right r -> Right r ->
r `shouldBe` r `shouldBe`
AccountListResponse AccountListResponse "zh" [ZcashAccountAPI 1 1 "Personal"]
"zh"
[ZcashAccountAPI 1 1 "Personal" Local]
describe "Addresses" $ do describe "Addresses" $ do
describe "listaddresses" $ do describe "listaddresses" $ do
it "bad credentials" $ do it "bad credentials" $ do
@ -688,204 +676,6 @@ main = do
case res of case res of
Left e -> assertFailure e Left e -> assertFailure e
Right (SendResponse i o) -> o `shouldNotBe` U.nil Right (SendResponse i o) -> o `shouldNotBe` U.nil
describe "Shield notes" $ do
it "bad credentials" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
"baduser"
"idontknow"
ShieldNotes
BlankParams
res `shouldBe` Left "Invalid credentials"
describe "correct credentials" $ do
it "no parameters" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
nodeUser
nodePwd
ShieldNotes
BlankParams
case res of
Left e -> assertFailure e
Right (ErrorResponse i c m) -> c `shouldBe` (-32602)
it "invalid account" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
nodeUser
nodePwd
ShieldNotes
(ShieldNotesParams 27)
case res of
Left e -> assertFailure e
Right (ErrorResponse i c m) -> c `shouldBe` (-32006)
it "valid account" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
nodeUser
nodePwd
ShieldNotes
(ShieldNotesParams 1)
case res of
Left e -> assertFailure e
Right (MultiOpResponse i c) -> c `shouldNotBe` []
describe "Viewing Keys" $ do
describe "Full" $ do
it "bad credentials" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
"baduser"
"idontknow"
GetFVK
BlankParams
res `shouldBe` Left "Invalid credentials"
describe "correct credentials" $ do
it "no parameters" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
nodeUser
nodePwd
GetFVK
BlankParams
case res of
Left e -> assertFailure e
Right (ErrorResponse i c m) -> c `shouldBe` (-32602)
it "invalid account" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
nodeUser
nodePwd
GetFVK
(ViewingKeyParams 27)
case res of
Left e -> assertFailure e
Right (ErrorResponse i c m) -> c `shouldBe` (-32006)
it "valid account" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
nodeUser
nodePwd
GetFVK
(ViewingKeyParams 1)
case res of
Left e -> assertFailure e
Right (ViewingKeyResponse i c) -> c `shouldNotBe` ""
Right x -> assertFailure $ show x
describe "Incoming" $ do
it "bad credentials" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
"baduser"
"idontknow"
GetIVK
BlankParams
res `shouldBe` Left "Invalid credentials"
describe "correct credentials" $ do
it "no parameters" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
nodeUser
nodePwd
GetIVK
BlankParams
case res of
Left e -> assertFailure e
Right (ErrorResponse i c m) -> c `shouldBe` (-32602)
it "invalid account" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
nodeUser
nodePwd
GetIVK
(ViewingKeyParams 27)
case res of
Left e -> assertFailure e
Right (ErrorResponse i c m) -> c `shouldBe` (-32006)
it "valid account" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
nodeUser
nodePwd
GetIVK
(ViewingKeyParams 1)
case res of
Left e -> assertFailure e
Right (ViewingKeyResponse i c) -> c `shouldNotBe` ""
Right x -> assertFailure $ show x
describe "Importing" $ do
it "bad credentials" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
"baduser"
"idontknow"
ImportVK
BlankParams
res `shouldBe` Left "Invalid credentials"
describe "correct credentials" $ do
it "no parameters" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
nodeUser
nodePwd
ImportVK
BlankParams
case res of
Left e -> assertFailure e
Right (ErrorResponse i c m) -> c `shouldBe` (-32602)
it "correct params" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
nodeUser
nodePwd
ImportVK
(ImportVkParams
"OldWallet"
"uviewtest1jna46ql5qns5rlg99jgs6mhf0j9tk8zxvqsm472scgvmj0vs0rqv2kvdf626gftx7dgn2tltyf0s200gvjlsdvz5celpue9wxxw78txswqmayxc3pfrt5fs5frvr3ep0jrjg8euahqzc63yx9sy4z8lql4ev6q3asptl9rhsfzzrup2g5slwnlvy3dgft44jw3l08xtzypjmsrwxskgnp5s03xlc2kg5520a25pa6fdjxhzutam4wkwr6mh4zeq3qndpks8dk0y90y7gucgsp0j5k2xnhh90m3krk5glz4794dj93pf59h85dqms6337f85ccvpxhays94kvsj2hyjsltf52tygqs8y0vp2yf39drxl687the6xkp8nxkfffc3kqlkhw53t5plplde0vk9rwv340ys04gg48fs0pxfp35rvt2f2pvxjmgmln6lp5k2yzkm0r87k89p6xqv68a6uyfpsauswh9fsckfqey02pjedz5gs934qa"
3249286)
case res of
Left e -> assertFailure e
Right (NewItemResponse i k) -> k `shouldSatisfy` (> 0)
it "list wallets" $ do
res <-
makeZenithCall
"127.0.0.1"
nodePort
nodeUser
nodePwd
ListWallets
BlankParams
case res of
Left e -> assertFailure e
Right (WalletListResponse i k) -> length k `shouldBe` 2
startAPI :: Config -> IO () startAPI :: Config -> IO ()
startAPI config = do startAPI config = do
@ -904,7 +694,7 @@ startAPI config = do
case bc of case bc of
Left e1 -> throwIO e1 Left e1 -> throwIO e1
Right chainInfo -> do Right chainInfo -> do
x <- runNoLoggingT $ initDb "test.db" x <- initDb "test.db"
case x of case x of
Left e2 -> throwIO $ userError e2 Left e2 -> throwIO $ userError e2
Right x' -> do Right x' -> do

View file

@ -9,7 +9,6 @@ import qualified Data.ByteString.Lazy as LBS
import Data.HexString import Data.HexString
import Data.List (foldl') import Data.List (foldl')
import Data.Maybe (fromJust) import Data.Maybe (fromJust)
import qualified Data.Text as T
import qualified Data.Text.Encoding as E import qualified Data.Text.Encoding as E
import Database.Persist import Database.Persist
import Database.Persist.Sqlite import Database.Persist.Sqlite
@ -70,7 +69,6 @@ import Zenith.Core
import Zenith.DB import Zenith.DB
import Zenith.Tree import Zenith.Tree
import Zenith.Types import Zenith.Types
import Zenith.Utils
main :: IO () main :: IO ()
main = do main = do
@ -645,7 +643,8 @@ main = do
case ix of case ix of
Nothing -> assertFailure "couldn't find index at block" Nothing -> assertFailure "couldn't find index at block"
Just i -> do Just i -> do
updatedTree <- runNoLoggingT $ truncateTree oTree i updatedTree <-
runFileLoggingT "test.log" $ truncateTree oTree i
let finalAnchor = let finalAnchor =
getOrchardTreeAnchor $ getOrchardTreeAnchor $
OrchardCommitmentTree $ ztiOrchard zebraTreesIn OrchardCommitmentTree $ ztiOrchard zebraTreesIn
@ -738,7 +737,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runNoLoggingT $ runFileLoggingT "zenith.log" $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -764,7 +763,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runNoLoggingT $ runFileLoggingT "zenith.log" $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -788,7 +787,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runNoLoggingT $ runFileLoggingT "zenith.log" $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -816,7 +815,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runNoLoggingT $ runFileLoggingT "zenith.log" $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -848,7 +847,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runNoLoggingT $ runFileLoggingT "zenith.log" $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -874,7 +873,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runNoLoggingT $ runFileLoggingT "zenith.log" $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -898,7 +897,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runNoLoggingT $ runFileLoggingT "zenith.log" $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -927,7 +926,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runNoLoggingT $ runFileLoggingT "zenith.log" $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -958,7 +957,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runNoLoggingT $ runFileLoggingT "zenith.log" $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -984,7 +983,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runNoLoggingT $ runFileLoggingT "zenith.log" $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -1008,7 +1007,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runNoLoggingT $ runFileLoggingT "zenith.log" $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -1035,7 +1034,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runNoLoggingT $ runFileLoggingT "zenith.log" $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -1062,7 +1061,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runNoLoggingT $ runFileLoggingT "zenith.log" $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -1087,7 +1086,7 @@ main = do
Just ua -> do Just ua -> do
pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db" pool <- runNoLoggingT $ initPool "/home/rav/Zenith/zenith.db"
tx <- tx <-
runNoLoggingT $ runFileLoggingT "zenith.log" $
prepareTxV2 prepareTxV2
pool pool
"localhost" "localhost"
@ -1104,47 +1103,3 @@ main = do
case tx of case tx of
Left e -> assertFailure $ show e Left e -> assertFailure $ show e
Right h -> h `shouldNotBe` hexString "deadbeef" Right h -> h `shouldNotBe` hexString "deadbeef"
describe "Call CoinGecko to get ZEC price" $ do
it "Testing for USD " $ do
price <- getZcashPrice $ T.pack "usd"
case price of
Just p -> p `shouldNotBe` 0.0
Nothing -> assertFailure "Failed to get ZEC price"
describe "Parse an URI payment string (all fields filled) " $ do
it ("Parsing URI -> " ++ "zcash:ztestsapling10yy2ex5....") $ do
let zcashURI2 =
"zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=100&memo=SGVsbG8sIFdvcmxkIQ==&message=Test"
case parseZcashPayment zcashURI2 of
Right p -> do
print p
(uriAmount p) `shouldBe` Just 100.0
Left e -> assertFailure $ "Error: " ++ e
describe
"Parse an URI payment string (just address and amount fields provided) " $ do
it ("Parsing URI -> " ++ "zcash:ztestsapling10yy2ex5....") $ do
let zcashURI3 =
"zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=100"
case parseZcashPayment zcashURI3 of
Right p -> do
print p
(uriAmount p) `shouldBe` Just 100.0
Left e -> assertFailure $ "Error: " ++ e
describe "Parse an URI payment string (invalid URI provided) " $ do
it ("Parsing URI -> " ++ "zcash:ztestsapling10yy2ex5....") $ do
let zcashURI3 =
"z:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=100"
case parseZcashPayment zcashURI3 of
Right p -> do
print p
(uriAmount p) `shouldBe` Just 100.0
Left e -> assertFailure $ "Error: " ++ e
describe "Create a ZIP-321 URI payment string " $ do
it "Creating an URI using a valid Zcash address, an amount, and a memo " $ do
let address =
"ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez"
let amount = Just 1.2345
let memo = Just "This is a simple memo."
let uriString = createZip321 address amount memo
print uriString
uriString `shouldBe`
"zcash:ztestsapling10yy2ex5dcqkclhc7z7yrnjq2z6feyjad56ptwlfgmy77dmaqqrl9gyhprdx59qgmsnyfska2kez?amount=1.2345&memo=VGhpcyBpcyBhIHNpbXBsZSBtZW1vLg"

@ -1 +1 @@
Subproject commit 0d042d639d471af14ebe94707f64b5ff5c2cb5eb Subproject commit d45bd7dcf3c3cf4e893900a1774d24b14bf56591

View file

@ -1,7 +1,7 @@
{ {
"openrpc": "1.0.0-rc1", "openrpc": "1.0.0-rc1",
"info": { "info": {
"version": "0.9.0.0-beta", "version": "0.7.0.0-beta",
"title": "Zenith RPC", "title": "Zenith RPC",
"description": "The RPC methods to interact with the Zenith Zcash wallet", "description": "The RPC methods to interact with the Zenith Zcash wallet",
"license": { "license": {
@ -230,8 +230,7 @@
{ "$ref": "#/components/errors/ZebraNotAvailable" }, { "$ref": "#/components/errors/ZebraNotAvailable" },
{ "$ref": "#/components/errors/DuplicateName" }, { "$ref": "#/components/errors/DuplicateName" },
{ "$ref": "#/components/errors/ZenithBusy" }, { "$ref": "#/components/errors/ZenithBusy" },
{ "$ref": "#/components/errors/InvalidWallet" }, { "$ref": "#/components/errors/InvalidWallet" }
{ "$ref": "#/components/errors/NotLocal" }
] ]
}, },
{ {
@ -497,8 +496,7 @@
} }
], ],
"errors": [ "errors": [
{ "$ref": "#/components/errors/InvalidAccount" }, { "$ref": "#/components/errors/InvalidAccount" }
{ "$ref": "#/components/errors/ReadOnly" }
] ]
}, },
{ {
@ -607,9 +605,10 @@
], ],
"paramStructure": "by-position", "paramStructure": "by-position",
"result": { "result": {
"name": "Operation ID", "name": "Operation ID(s)",
"schema": { "schema": {
"$ref": "#/components/contentDescriptors/OperationId" "type": "array",
"items": { "$ref": "#/components/contentDescriptors/OperationId"}
} }
}, },
"examples": [ "examples": [
@ -621,7 +620,7 @@
{ {
"name": "Account index", "name": "Account index",
"summary": "The index for the account to use", "summary": "The index for the account to use",
"value": 1 "value": "1"
}, },
{ {
"name": "Privacy Policy", "name": "Privacy Policy",
@ -642,16 +641,16 @@
], ],
"result": { "result": {
"name": "SendMany result", "name": "SendMany result",
"value": "3cc31c07-07cf-4a6e-9190-156c4b8c4088" "value": [
"3cc31c07-07cf-4a6e-9190-156c4b8c4088"
]
} }
} }
], ],
"errors": [ "errors": [
{ "$ref": "#/components/errors/ZebraNotAvailable" }, { "$ref": "#/components/errors/ZebraNotAvailable" },
{ "$ref": "#/components/errors/ZenithBusy" }, { "$ref": "#/components/errors/ZenithBusy" },
{ "$ref": "#/components/errors/InvalidAccount" }, { "$ref": "#/components/errors/InvalidAccount" }
{ "$ref": "#/components/errors/ReadOnly" }
] ]
}, },
{ {
@ -670,226 +669,6 @@
"errors": [ "errors": [
{ "$ref": "#/components/errors/OpNotFound" } { "$ref": "#/components/errors/OpNotFound" }
] ]
},
{
"name": "shieldnotes",
"summary": "Shield all transparent notes into the Orchard pool for the given account",
"description": "Creates one or more transactions, grouping all the unspent transparent notes for the given account by their transparent address to avoid associating different transparent addresses. These notes are sent to the given account's internal change address as shielded Orchard notes.",
"tags": [],
"params": [
{ "$ref": "#/components/contentDescriptors/AccountId"}
],
"paramStructure": "by-position",
"result": {
"name": "Operation ID(s)",
"schema": {
"type": "array",
"items": { "$ref": "#/components/contentDescriptors/OperationId"}
}
},
"examples": [
{
"name": "Shield transparent notes",
"summary": "Shield transparent notes",
"description": "Shield the transparent notes in a given account",
"params": [
{
"name": "Account index",
"summary": "The index for the account to use",
"value": "3"
}
],
"result": {
"name": "ShieldNotes result",
"value": [
"ab350df0-9f57-44c0-9e0d-f7b8af1f4231",
"8c6f2656-22ef-4f9d-b465-80ddd13fc485"
]
}
},
{
"name": "No transparent funds",
"summary": "Shield transparent notes with no transparent funds",
"description": "Attempt to shield the transparent notes in a given account, when account has none",
"params": [
{
"name": "Account index",
"summary": "The index for the account to use",
"value": "3"
}
],
"result": {
"name": "ShieldNotes result",
"value": [
"InsufficientFunds"
]
}
}
],
"errors": [
{ "$ref": "#/components/errors/ZebraNotAvailable" },
{ "$ref": "#/components/errors/ZenithBusy" },
{ "$ref": "#/components/errors/InvalidAccount" }
]
},
{
"name": "deshieldfunds",
"summary": "De-shield the given amount of ZEC from the given account",
"description": "Creates a new internal transaction with the requested amount of ZEC to the transparent pool. The fee is not included in the given amount.",
"tags": [],
"params": [
{ "$ref": "#/components/contentDescriptors/AccountId"},
{ "$ref": "#/components/contentDescriptors/Amount"}
],
"paramStructure": "by-position",
"result": {
"name": "Operation ID",
"schema": {
"$ref": "#/components/contentDescriptors/OperationId"
}
},
"examples": [
{
"name": "De-Shield funds",
"summary": "De-shield funds",
"description": "Move the given amount of ZEC for the given acount from the shielded pool to the transparent pool",
"params": [
{
"name": "Account index",
"summary": "The index for the account to use",
"value": "3"
},
{
"name": "Amount",
"summary": "The amount of ZEC to use",
"value": 1.23
}
],
"result": {
"name": "Deshield funds result",
"value": "ab350df0-9f57-44c0-9e0d-f7b8af1f4231"
}
},
{
"name": "No transparent funds",
"summary": "Shield transparent notes with no transparent funds",
"description": "Attempt to shield the transparent notes in a given account, when account has none",
"params": [
{
"name": "Account index",
"summary": "The index for the account to use",
"value": "3"
}
],
"result": {
"name": "ShieldNotes result",
"value": [
"InsufficientFunds"
]
}
}
],
"errors": [
{ "$ref": "#/components/errors/ZebraNotAvailable" },
{ "$ref": "#/components/errors/ZenithBusy" },
{ "$ref": "#/components/errors/InvalidAccount" }
]
},
{
"name": "getfullvk",
"summary": "Derive the full viewing key for the given account.",
"description": "Derive the full viewing key for the given account, encoded per ZIP-316.",
"tags": [],
"params": [
{ "$ref": "#/components/contentDescriptors/AccountId"}
],
"paramStructure": "by-position",
"result": {
"name": "Full viewing key",
"schema": {
"$ref": "#/components/schemas/ViewingKey"
}
},
"examples": [
{
"name": "Get full viewing key",
"summary": "Get the full viewing key",
"description": "Get the full viewing key for the give account, encoded per ZIP-316",
"params": [
{
"name": "Account index",
"summary": "The index for the account to use",
"value": 1
}
],
"result": {
"name": "Full Viewing key",
"value": "uview16qdhd9e283s4y53gmw72ag7adzdrj9f9v96dw89ggv9el0yrf7vkappau69j8luq7uf540sr78ncslnqk6kwpc4qeqgfg5vn4xcmllynyfr32cgq6nx5ptku44kfxtsj99px2g9yp7kyc32quun0elakgltqmqflprwmryuelcfwwt58vqap065as7qwljg02l6mkutsh2y9aefd284dsrj0246fd2n4hra3r03uftsh4njh3w590z78tpnfqhjvvwhgus476zrw3fd69qekru709ghr0zr7h8majy9aclwg7uhakt24lmuec8dd7t270kamcs99rz8jasj3jl6m9y77dvkdn23e2kwuc6kyagpstzrdjnlzdldmgsu4k056v80ucajcjvl99pcf2znjg37vztdp4zr5qrphxs4y7wppxmankmdwwgjxhlmyrjd68z80q0n0t2cyqge6mlc7pd5wre4392pjtdaqvtyeg0denh4ekynnjxnm"
}
}
],
"errors": [
{ "$ref": "#/components/errors/InvalidAccount" }
]
},
{
"name": "getincomingvk",
"summary": "Get the incoming viewing key for the given account.",
"description": "Derives the incoming viewing key for the given account per ZIP-316.",
"tags": [],
"params": [
{ "$ref": "#/components/contentDescriptors/AccountId"}
],
"paramStructure": "by-position",
"result": {
"name": "Incoming viewing key",
"schema": {
"$ref": "#/components/schemas/ViewingKey"
}
},
"examples": [
{
"name": "Get incoming viewing key",
"summary": "Get the incoming viewing key",
"description": "Get the incoming viewing key for the give account, encoded per ZIP-316",
"params": [
{
"name": "Account index",
"summary": "The index for the account to use",
"value": 1
}
],
"result": {
"name": "Incoming Viewing key",
"value": "uivk199qcjxrj73n7fapg79a2ltah6f3j83haljcux5t5kvn5unn7rpfmvglttdt9g6na3llkefnd3pn0x9ky6lh8s42trj0vfg5wtv0nrerq0wsq5v4q7lt5j4l9svppspr6h7407ztgsuvkfk977c3tj408nx5phxap8fn3ecdmdrah9spp76md9tel89tuqz6m0xplqp83wj33qf7s3hwfe79t04rq49g24nr3emlpm298wpqla2dvh4rr584kwdtxc9ahse5x0drcjr95tt4k0hxr32l6yturje7dptlgjnr4cm6uk29ysu9l5xwgz40p6alyedzzqltqf5nswy48ekru4ahapw"
}
}
],
"errors": [
{ "$ref": "#/components/errors/InvalidAccount" }
]
},
{
"name": "importvk",
"summary": "Import the given Unified Viewing Key",
"description": "Imports the given Unified Viewing Key, autodetecting if it is Full or Incoming. Caution: If the given birthday height is lower than the lowest birthday height in the wallet, this will trigger a full re-scan of the wallet.",
"tags": [
],
"params": [
{ "$ref": "#/components/contentDescriptors/Name"},
{ "$ref": "#/components/contentDescriptors/ViewingKey"},
{ "$ref": "#/components/contentDescriptors/BirthdayHeight"}
],
"paramStructure": "by-position",
"result": {
"name": "Account Identifier",
"schema": { "$ref": "#/components/contentDescriptors/AccountId"}
},
"errors": [
{ "$ref": "#/components/errors/ZebraNotAvailable" },
{ "$ref": "#/components/errors/DuplicateName" },
{ "$ref": "#/components/errors/ZenithBusy" }
]
} }
], ],
"components": { "components": {
@ -921,15 +700,6 @@
"type": "string" "type": "string"
} }
}, },
"Amount": {
"name": "A numeric amount",
"summary": "A numeric amount",
"description": "A number that represents an amount to be used by a function as an input",
"required": true,
"schema": {
"type": "number"
}
},
"Name": { "Name": {
"name": "Name", "name": "Name",
"summary": "A user-friendly name", "summary": "A user-friendly name",
@ -985,24 +755,6 @@
"type": "string", "type": "string",
"enum": ["None", "Low", "Medium", "Full"] "enum": ["None", "Low", "Medium", "Full"]
} }
},
"BirthdayHeight": {
"name": "Birthday Height",
"summary": "The block height at which a wallet was created.",
"description": "The block height where a wallet was created. The wallet will not scan blocks at a lower block height than this, assuming there are no transactions on-chain before this point.",
"required": true,
"schema": {
"type": "integer"
}
},
"ViewingKey": {
"name": "Viewing Key",
"summary": "A Unified viewing key.",
"description": "A Unified viewing key encoded per [ZIP-316](https://zips.z.cash/zip-0316). Zenith supports both full and incoming viewing keys.",
"required": true,
"schema": {
"type": "string"
}
} }
}, },
"schemas": { "schemas": {
@ -1021,8 +773,7 @@
"name": { "type": "string", "description": "User-friendly name of the wallet" }, "name": { "type": "string", "description": "User-friendly name of the wallet" },
"network": { "type": "string", "description": "Network the wallet is for. Testnet or MainNet" }, "network": { "type": "string", "description": "Network the wallet is for. Testnet or MainNet" },
"birthday": { "type": "integer", "description": "Wallet's birthday height" }, "birthday": { "type": "integer", "description": "Wallet's birthday height" },
"lastSync": { "type": "integer", "description": "Last block the wallet is synced to" }, "lastSync": { "type": "integer", "description": "Last block the wallet is synced to" }
"local": { "type": "boolean", "description": "True for wallets belonging to this Zenith instance, False for wallets created to manage viewing keys"}
} }
}, },
"ZcashAccount": { "ZcashAccount": {
@ -1030,8 +781,7 @@
"properties": { "properties": {
"index": { "type": "integer", "description": "Internal index for account"}, "index": { "type": "integer", "description": "Internal index for account"},
"wallet": { "type": "integer", "description": "ID of the wallet this account belongs to"}, "wallet": { "type": "integer", "description": "ID of the wallet this account belongs to"},
"name": { "type": "string", "description": "User-friendly name of the account"}, "name": { "type": "string", "description": "User-friendly name of the account"}
"type": { "type": "string", "description": "Local for accounts belonging to the wallet, FullViewKey for full viewing keys, IncomingViewKey for incoming"}
} }
}, },
"ZcashAddress": { "ZcashAddress": {
@ -1085,10 +835,6 @@
"amount": { "type": "number", "description": "The amount to send in ZEC"}, "amount": { "type": "number", "description": "The amount to send in ZEC"},
"memo": { "type": "string", "description": "The shielded memo to include, if applicable"} "memo": { "type": "string", "description": "The shielded memo to include, if applicable"}
} }
},
"ViewingKey": {
"type": "string",
"description": "The viewing key, encoded per ZIP-316"
} }
}, },
"examples": {}, "examples": {},
@ -1148,18 +894,6 @@
"ZenithBusy": { "ZenithBusy": {
"code": -32012, "code": -32012,
"message": "The Zenith server is syncing, please try again later." "message": "The Zenith server is syncing, please try again later."
},
"InvalidVK": {
"code": -32013,
"message": "The viewing key provided is not valid."
},
"ReadOnly": {
"code": -32014,
"message": "Read-only account, operation is not valid."
},
"NotLocal": {
"code": -32015,
"message": "The wallet is not local, cannot create new accounts."
} }
} }
} }

View file

@ -1,6 +1,6 @@
cabal-version: 3.0 cabal-version: 3.0
name: zenith name: zenith
version: 0.9.1.0-beta version: 0.7.0.0-beta
license: MIT license: MIT
license-file: LICENSE license-file: LICENSE
author: Rene Vergara author: Rene Vergara
@ -96,8 +96,6 @@ library
, vty-crossplatform , vty-crossplatform
, word-wrap , word-wrap
, zcash-haskell , zcash-haskell
, unordered-containers
, network-uri
--pkgconfig-depends: rustzcash_wrapper --pkgconfig-depends: rustzcash_wrapper
default-language: Haskell2010 default-language: Haskell2010

View file

@ -1,42 +1,5 @@
#
# Zenith Configuration File
#
# -------------------------------------------------------------
# nodeUser -
# -------------------------------------------------------------
nodeUser = "user" nodeUser = "user"
# -------------------------------------------------------------
# nodePwd -
nodePwd = "superSecret" nodePwd = "superSecret"
# ------------------------------------------------------------- dbFilePath = "zenith.db"
# nodePort -
nodePort = 8234
# -------------------------------------------------------------
# nodePwd -
# dbFileName - contains the SQLite database name used for
# keeping all Zenith's data
# default = zenith.db
#
dbFileName = "zenith.db"
# -------------------------------------------------------------
# zebraHost - Zebra IP
# Default - "127.0.0.1"
zebraHost = "127.0.0.1" zebraHost = "127.0.0.1"
# ------------------------------------------------------------- zebraPort = 18232
# zebraPort - Port used for access Zebra API endpoints
# must be the same port configured for your
# Zebra node
zebraPort = 8232
# -------------------------------------------------------------
# currencyCode - ISO 4217 currency code
#
# Example of currency codes are:
#
# United States -> currencyCode = "usd"
# Canada -> currencyCode = "cnd"
# Australia -> currencyCode = "aud"
# Euro Region -> currencyCode = "eur"
# Great Britain -> currencyCode = "gbp"
# Japan -> currencyCode = "jpy"
#
currencyCode = "usd"

BIN
zenith_er.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 MiB

BIN
zenith_er.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 KiB