RPC Server #103
2 changed files with 104 additions and 39 deletions
|
@ -54,6 +54,8 @@ import Zenith.Utils
|
||||||
, getZenithPath
|
, getZenithPath
|
||||||
, isEmpty
|
, isEmpty
|
||||||
, isRecipientValid
|
, isRecipientValid
|
||||||
|
, isRecipientValidGUI
|
||||||
|
, isZecAddressValid
|
||||||
, isValidString
|
, isValidString
|
||||||
, jsonNumber
|
, jsonNumber
|
||||||
, padWithZero
|
, padWithZero
|
||||||
|
@ -125,6 +127,7 @@ data AppEvent
|
||||||
| CopyABAdress !T.Text
|
| CopyABAdress !T.Text
|
||||||
| DeleteABEntry !T.Text
|
| DeleteABEntry !T.Text
|
||||||
| UpdateABDescrip !T.Text !T.Text
|
| UpdateABDescrip !T.Text !T.Text
|
||||||
|
| ResetRecipientValid
|
||||||
deriving (Eq, Show)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
data AppModel = AppModel
|
data AppModel = AppModel
|
||||||
|
@ -605,8 +608,29 @@ buildUI wenv model = widgetTree
|
||||||
[textFont "Bold", textSize 12])
|
[textFont "Bold", textSize 12])
|
||||||
, separatorLine `styleBasic` [fgColor btnColor]
|
, separatorLine `styleBasic` [fgColor btnColor]
|
||||||
, spacer
|
, spacer
|
||||||
|
, hstack
|
||||||
|
[
|
||||||
|
label "Privacy Level:" `styleBasic` [width 70, textFont "Bold"]
|
||||||
|
, spacer
|
||||||
|
, label "Full " `styleBasic` [width 40]
|
||||||
|
, radio Full privacyChoice
|
||||||
|
, spacer
|
||||||
|
, label "Medium " `styleBasic` [width 40]
|
||||||
|
, radio Medium privacyChoice
|
||||||
|
]
|
||||||
|
, hstack
|
||||||
|
[
|
||||||
|
label " " `styleBasic` [width 70, textFont "Bold"]
|
||||||
|
, spacer
|
||||||
|
, label "Low " `styleBasic` [width 40]
|
||||||
|
, radio Low privacyChoice
|
||||||
|
, spacer
|
||||||
|
, label "None " `styleBasic` [width 40]
|
||||||
|
, radio None privacyChoice
|
||||||
|
]
|
||||||
|
, spacer
|
||||||
, hstack
|
, hstack
|
||||||
[ label "To:" `styleBasic` [width 50]
|
[ label "To:" `styleBasic` [width 50, textFont "Bold"]
|
||||||
, spacer
|
, spacer
|
||||||
, textField_ sendRecipient [onChange CheckRecipient] `styleBasic`
|
, textField_ sendRecipient [onChange CheckRecipient] `styleBasic`
|
||||||
[ width 150
|
[ width 150
|
||||||
|
@ -616,7 +640,7 @@ buildUI wenv model = widgetTree
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
, hstack
|
, hstack
|
||||||
[ label "Amount:" `styleBasic` [width 50]
|
[ label "Amount:" `styleBasic` [width 50, textFont "Bold"]
|
||||||
, spacer
|
, spacer
|
||||||
, numericField_
|
, numericField_
|
||||||
sendAmount
|
sendAmount
|
||||||
|
@ -634,35 +658,13 @@ buildUI wenv model = widgetTree
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
, hstack
|
, hstack
|
||||||
[ label "Memo:" `styleBasic` [width 50]
|
[ label "Memo:" `styleBasic` [width 50, textFont "Bold"]
|
||||||
, spacer
|
, spacer
|
||||||
, textArea sendMemo `styleBasic`
|
, textArea sendMemo `styleBasic`
|
||||||
[width 150, height 40]
|
[width 150, height 40]
|
||||||
]
|
]
|
||||||
, spacer
|
, spacer
|
||||||
-- Radio button group for privacy level
|
-- Radio button group for privacy level
|
||||||
, hstack
|
|
||||||
[
|
|
||||||
label "Privacy Level:" `styleBasic` [width 70]
|
|
||||||
, spacer
|
|
||||||
, label "None " `styleBasic` [width 40]
|
|
||||||
, radio None privacyChoice
|
|
||||||
, spacer
|
|
||||||
, label "Low " `styleBasic` [width 40]
|
|
||||||
, radio Low privacyChoice
|
|
||||||
|
|
||||||
]
|
|
||||||
, hstack
|
|
||||||
[
|
|
||||||
label " " `styleBasic` [width 70]
|
|
||||||
, spacer
|
|
||||||
, label "Medium " `styleBasic` [width 40]
|
|
||||||
, radio Medium privacyChoice
|
|
||||||
, spacer
|
|
||||||
, label "Full " `styleBasic` [width 40]
|
|
||||||
, radio Full privacyChoice
|
|
||||||
]
|
|
||||||
, spacer
|
|
||||||
, box_
|
, box_
|
||||||
[alignMiddle]
|
[alignMiddle]
|
||||||
(hstack
|
(hstack
|
||||||
|
@ -1080,7 +1082,7 @@ handleEvent wenv node model evt =
|
||||||
]
|
]
|
||||||
ConfirmCancel -> [Model $ model & confirmTitle .~ Nothing & mainInput .~ ""]
|
ConfirmCancel -> [Model $ model & confirmTitle .~ Nothing & mainInput .~ ""]
|
||||||
ShowSeed -> [Model $ model & showSeed .~ True & menuPopup .~ False]
|
ShowSeed -> [Model $ model & showSeed .~ True & menuPopup .~ False]
|
||||||
ShowSend -> [Model $ model & openSend .~ True]
|
ShowSend -> [Model $ model & openSend .~ True & privacyChoice .~ Full & recipientValid .~ False]
|
||||||
SendTx ->
|
SendTx ->
|
||||||
case currentAccount of
|
case currentAccount of
|
||||||
Nothing -> [Event $ ShowError "No account available", Event CancelSend]
|
Nothing -> [Event $ ShowError "No account available", Event CancelSend]
|
||||||
|
@ -1261,7 +1263,10 @@ handleEvent wenv node model evt =
|
||||||
("Wallet Sync: " <>
|
("Wallet Sync: " <>
|
||||||
T.pack (printf "%.2f%%" (model ^. barValue * 100)))
|
T.pack (printf "%.2f%%" (model ^. barValue * 100)))
|
||||||
]
|
]
|
||||||
CheckRecipient a -> [Model $ model & recipientValid .~ isRecipientValid a]
|
ResetRecipientValid -> [Model $ model & recipientValid .~ False]
|
||||||
|
CheckRecipient a -> [Model $
|
||||||
|
model & recipientValid .~ isRecipientValidGUI (model ^.privacyChoice) a ]
|
||||||
|
-- model & recipientValid .~ ((model ^. privacyChoice) == Low) ]
|
||||||
CheckAmount i ->
|
CheckAmount i ->
|
||||||
[ Model $
|
[ Model $
|
||||||
model & amountValid .~
|
model & amountValid .~
|
||||||
|
@ -1272,7 +1277,7 @@ handleEvent wenv node model evt =
|
||||||
-- | Address Book Events
|
-- | Address Book Events
|
||||||
-- |
|
-- |
|
||||||
CheckValidAddress a ->
|
CheckValidAddress a ->
|
||||||
[Model $ model & abAddressValid .~ isRecipientValid a]
|
[Model $ model & abAddressValid .~ isZecAddressValid a]
|
||||||
CheckValidDescrip a -> [Model $ model & abDescripValid .~ isValidString a]
|
CheckValidDescrip a -> [Model $ model & abDescripValid .~ isValidString a]
|
||||||
ShowAdrBook ->
|
ShowAdrBook ->
|
||||||
if null (model ^. abaddressList)
|
if null (model ^. abaddressList)
|
||||||
|
@ -1673,7 +1678,7 @@ runZenithGUI config = do
|
||||||
Nothing
|
Nothing
|
||||||
False
|
False
|
||||||
False
|
False
|
||||||
None
|
Full
|
||||||
startApp model handleEvent buildUI (params hD)
|
startApp model handleEvent buildUI (params hD)
|
||||||
Left _e -> print "Zebra not available"
|
Left _e -> print "Zebra not available"
|
||||||
where
|
where
|
||||||
|
|
|
@ -24,12 +24,15 @@ import ZcashHaskell.Types
|
||||||
, TransparentAddress(..)
|
, TransparentAddress(..)
|
||||||
, UnifiedAddress(..)
|
, UnifiedAddress(..)
|
||||||
, ZcashNet(..)
|
, ZcashNet(..)
|
||||||
|
, ValidAddress(..)
|
||||||
|
, ExchangeAddress(..)
|
||||||
)
|
)
|
||||||
import Zenith.Types
|
import Zenith.Types
|
||||||
( AddressGroup(..)
|
( AddressGroup(..)
|
||||||
, UnifiedAddressDB(..)
|
, UnifiedAddressDB(..)
|
||||||
, ZcashAddress(..)
|
, ZcashAddress(..)
|
||||||
, ZcashPool(..)
|
, ZcashPool(..)
|
||||||
|
, PrivacyPolicy(..)
|
||||||
)
|
)
|
||||||
|
|
||||||
-- | Helper function to convert numbers into JSON
|
-- | Helper function to convert numbers into JSON
|
||||||
|
@ -71,8 +74,8 @@ getAddresses ag = agtransparent ag <> agsapling ag <> agunified ag
|
||||||
-- | Helper function to validate potential Zcash addresses
|
-- | Helper function to validate potential Zcash addresses
|
||||||
validateAddress :: T.Text -> Maybe ZcashPool
|
validateAddress :: T.Text -> Maybe ZcashPool
|
||||||
validateAddress txt --(tReg || sReg && isJust chk) || (uReg && isJust chk)
|
validateAddress txt --(tReg || sReg && isJust chk) || (uReg && isJust chk)
|
||||||
| tReg = Just Transparent
|
| tReg = Just Zenith.Types.Transparent
|
||||||
| sReg && chkS = Just Sapling
|
| sReg && chkS = Just Zenith.Types.Sapling
|
||||||
| uReg && chk = Just Orchard
|
| uReg && chk = Just Orchard
|
||||||
| otherwise = Nothing
|
| otherwise = Nothing
|
||||||
where
|
where
|
||||||
|
@ -110,7 +113,64 @@ validBarValue :: Float -> Float
|
||||||
validBarValue = clamp (0, 1)
|
validBarValue = clamp (0, 1)
|
||||||
|
|
||||||
isRecipientValid :: T.Text -> Bool
|
isRecipientValid :: T.Text -> Bool
|
||||||
isRecipientValid a =
|
isRecipientValid a = do
|
||||||
|
case isValidUnifiedAddress (E.encodeUtf8 a) of
|
||||||
|
Just _a1 -> True
|
||||||
|
Nothing ->
|
||||||
|
isValidShieldedAddress (E.encodeUtf8 a) ||
|
||||||
|
(case decodeTransparentAddress (E.encodeUtf8 a) of
|
||||||
|
Just _a3 -> True
|
||||||
|
Nothing ->
|
||||||
|
case decodeExchangeAddress (E.encodeUtf8 a) of
|
||||||
|
Just _a4 -> True
|
||||||
|
Nothing -> False)
|
||||||
|
|
||||||
|
isUnifiedAddressValid :: T.Text -> Bool
|
||||||
|
isUnifiedAddressValid ua =
|
||||||
|
case isValidUnifiedAddress (E.encodeUtf8 ua) of
|
||||||
|
Just _a1 -> True
|
||||||
|
Nothing -> False
|
||||||
|
|
||||||
|
isSaplingAddressValid :: T.Text -> Bool
|
||||||
|
isSaplingAddressValid sa = isValidShieldedAddress (E.encodeUtf8 sa)
|
||||||
|
|
||||||
|
isTransparentAddressValid :: T.Text -> Bool
|
||||||
|
isTransparentAddressValid ta =
|
||||||
|
case decodeTransparentAddress (E.encodeUtf8 ta) of
|
||||||
|
Just _a3 -> True
|
||||||
|
Nothing -> False
|
||||||
|
|
||||||
|
isExchangeAddressValid :: T.Text -> Bool
|
||||||
|
isExchangeAddressValid xa =
|
||||||
|
case decodeExchangeAddress (E.encodeUtf8 xa) of
|
||||||
|
Just _a4 -> True
|
||||||
|
Nothing -> False
|
||||||
|
|
||||||
|
isRecipientValidGUI :: PrivacyPolicy -> T.Text -> Bool
|
||||||
|
isRecipientValidGUI p a = do
|
||||||
|
case (parseAddress a) of
|
||||||
|
Just a1 ->
|
||||||
|
case p of
|
||||||
|
Full -> case a1 of
|
||||||
|
Unified ua -> True
|
||||||
|
ZcashHaskell.Types.Sapling sa -> True
|
||||||
|
_ -> False
|
||||||
|
Medium -> case a1 of
|
||||||
|
Unified ua -> True
|
||||||
|
ZcashHaskell.Types.Sapling sa -> True
|
||||||
|
_ -> False
|
||||||
|
Low -> case a1 of
|
||||||
|
Unified ua -> True
|
||||||
|
ZcashHaskell.Types.Sapling sa -> True
|
||||||
|
ZcashHaskell.Types.Transparent ta -> True
|
||||||
|
Exchange ea -> True
|
||||||
|
None -> case a1 of
|
||||||
|
ZcashHaskell.Types.Transparent ta -> True
|
||||||
|
Exchange ea -> True
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
isZecAddressValid :: T.Text -> Bool
|
||||||
|
isZecAddressValid a = do
|
||||||
case isValidUnifiedAddress (E.encodeUtf8 a) of
|
case isValidUnifiedAddress (E.encodeUtf8 a) of
|
||||||
Just _a1 -> True
|
Just _a1 -> True
|
||||||
Nothing ->
|
Nothing ->
|
||||||
|
@ -138,27 +198,27 @@ parseAddress a znet =
|
||||||
|
|
||||||
isValidContent :: String -> Bool
|
isValidContent :: String -> Bool
|
||||||
isValidContent [] = False -- an empty string is invalid
|
isValidContent [] = False -- an empty string is invalid
|
||||||
isValidContent (x:xs)
|
isValidContent (x:xs)
|
||||||
| not (isAlphaNum x ) = False -- string must start with an alphanumeric character
|
| not (isAlphaNum x ) = False -- string must start with an alphanumeric character
|
||||||
| otherwise = allValidChars xs -- process the rest of the string
|
| otherwise = allValidChars xs -- process the rest of the string
|
||||||
where
|
where
|
||||||
allValidChars :: String -> Bool
|
allValidChars :: String -> Bool
|
||||||
allValidChars [] = True -- if we got here, string is valid
|
allValidChars [] = True -- if we got here, string is valid
|
||||||
allValidChars (y:ys)
|
allValidChars (y:ys)
|
||||||
| isAlphaNum y || isSpace y = allValidChars ys -- char is valid, continue
|
| isAlphaNum y || isSpace y = allValidChars ys -- char is valid, continue
|
||||||
| otherwise = False -- found an invalid character, return false
|
| otherwise = False -- found an invalid character, return false
|
||||||
|
|
||||||
isValidString :: T.Text -> Bool
|
isValidString :: T.Text -> Bool
|
||||||
isValidString c = do
|
isValidString c = do
|
||||||
let a = T.unpack c
|
let a = T.unpack c
|
||||||
isValidContent a
|
isValidContent a
|
||||||
|
|
||||||
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
|
||||||
isEmpty [] = True
|
isEmpty [] = True
|
||||||
isEmpty _ = False
|
isEmpty _ = False
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue