Enhances memo decoding

This commit is contained in:
Rene Vergara 2022-06-27 09:25:36 -05:00
parent 9cc1950d94
commit 462c72c882
Signed by: pitmutt
GPG key ID: 65122AD495A7F5B2
7 changed files with 35 additions and 14 deletions

View file

@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## [0.3.0.0]
### Changed
- Changed decoding of memos to support Unicode (emojis!)
### Fixed
- Displaying transactions for view-only addresses
## [0.2.0.0] ## [0.2.0.0]
### Added ### Added

View file

@ -58,6 +58,9 @@ Zenith will attempt to connect to the node and check compatibility. Connections
- `send`: Prompts the user to prepare an outgoing transaction, selecting the source address, validating the destination address, the amount and the memo. - `send`: Prompts the user to prepare an outgoing transaction, selecting the source address, validating the destination address, the amount and the memo.
- If the source is a transparent address, the privacy policy is set to `AllowRevealedSenders`, favoring the shielding of funds when sent to a UA. - If the source is a transparent address, the privacy policy is set to `AllowRevealedSenders`, favoring the shielding of funds when sent to a UA.
- If the source is a shielded address, the privacy policy is set to `AllowRevealedAmounts`, favoring the move of funds from legacy shielded pools to Orchard. - If the source is a shielded address, the privacy policy is set to `AllowRevealedAmounts`, favoring the move of funds from legacy shielded pools to Orchard.
- `uri`: Prompts the user to select the source account and to enter a [ZIP-321](https://zips.z.cash/zip-0321) compliant URI to generate and send a transaction.
- `exit`: Ends the session. - `exit`: Ends the session.
### Support
If you would like to support the development of Zenith, please visit our [Free2Z](https://free2z.com/zenith-full-node-cli) page.

View file

@ -9,6 +9,7 @@ import Data.Configurator
import Data.Default (def) import Data.Default (def)
import Data.Sort import Data.Sort
import qualified Data.Text as T import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import Data.Time.Clock.POSIX import Data.Time.Clock.POSIX
import System.Console.StructuredCLI import System.Console.StructuredCLI
import System.Exit import System.Exit
@ -155,7 +156,7 @@ displayTx t = do
putStr "Zats: " putStr "Zats: "
print $ zamountZat t print $ zamountZat t
putStr "Memo: " putStr "Memo: "
putStrLn $ T.unpack $ zmemo t TIO.putStrLn $ zmemo t
putStrLn "-----" putStrLn "-----"
processUri :: B.ByteString -> B.ByteString -> Commands () processUri :: B.ByteString -> B.ByteString -> Commands ()

View file

@ -50,6 +50,7 @@ executables:
- -rtsopts - -rtsopts
- -with-rtsopts=-N - -with-rtsopts=-N
- -Wall - -Wall
- -Wunused-imports
dependencies: dependencies:
- zenith - zenith
- configurator - configurator

View file

@ -19,7 +19,10 @@ import Data.Functor (void)
import Data.Maybe import Data.Maybe
import qualified Data.Scientific as Scientific import qualified Data.Scientific as Scientific
import qualified Data.Text as T import qualified Data.Text as T
import qualified Data.Text.Encoding as E
import Data.Text.Encoding.Error (lenientDecode)
import qualified Data.Vector as V import qualified Data.Vector as V
import Data.Word
import GHC.Generics import GHC.Generics
import Haskoin.Address.Bech32 import Haskoin.Address.Bech32
import Network.HTTP.Simple import Network.HTTP.Simple
@ -199,7 +202,7 @@ instance FromJSON ZcashTx where
aZ <- obj .: "amountZat" aZ <- obj .: "amountZat"
bh <- obj .: "blockheight" bh <- obj .: "blockheight"
bt <- obj .: "blocktime" bt <- obj .: "blocktime"
c <- obj .: "change" c <- obj .:? "change"
conf <- obj .: "confirmations" conf <- obj .: "confirmations"
m <- obj .:? "memo" m <- obj .:? "memo"
pure $ pure $
@ -209,11 +212,11 @@ instance FromJSON ZcashTx where
aZ aZ
bh bh
bt bt
c (fromMaybe False c)
conf conf
(case m of (case m of
Nothing -> "" Nothing -> ""
Just m' -> T.pack (filter (/= '\NUL') $ decodeHexText m')) Just m' -> T.filter (/= '\NUL') $ decodeHexText m')
instance ToJSON ZcashTx where instance ToJSON ZcashTx where
toJSON (ZcashTx t a aZ bh bt c conf m) = toJSON (ZcashTx t a aZ bh bt c conf m) =
@ -288,12 +291,15 @@ instance FromJSON OpResult where
pure $ OpResult s m t pure $ OpResult s m t
-- | Helper function to turn a hex-encoded memo strings to readable text -- | Helper function to turn a hex-encoded memo strings to readable text
decodeHexText :: String -> String decodeHexText :: String -> T.Text
decodeHexText hexText decodeHexText h = E.decodeUtf8With lenientDecode $ B.pack $ hexRead h
| null chunk = ""
| otherwise = chr (read ("0x" <> chunk)) : decodeHexText (drop 2 hexText)
where where
chunk = take 2 hexText hexRead hexText
| null chunk = []
| otherwise =
fromIntegral (read ("0x" <> chunk)) : hexRead (drop 2 hexText)
where
chunk = take 2 hexText
-- | Helper function to turn a string into a hex-encoded string -- | Helper function to turn a string into a hex-encoded string
encodeHexText :: String -> String encodeHexText :: String -> String
@ -375,7 +381,7 @@ listTxs user pwd zaddy = do
makeZcashCall user pwd "z_listreceivedbyaddress" [String $ addy zaddy] makeZcashCall user pwd "z_listreceivedbyaddress" [String $ addy zaddy]
let rpcResp = decode response :: Maybe (RpcResponse [ZcashTx]) let rpcResp = decode response :: Maybe (RpcResponse [ZcashTx])
case rpcResp of case rpcResp of
Nothing -> fail "Couldn't parse node response" Nothing -> fail "listTxs: Couldn't parse node response"
Just res -> do Just res -> do
return $ result res return $ result res
@ -578,13 +584,13 @@ sendWithUri user pwd fromAddy uri = do
Just amt -> do Just amt -> do
putStrLn $ " Valid ZEC amount: " ++ show amt putStrLn $ " Valid ZEC amount: " ++ show amt
let decodedMemo = B64.decodeLenient $ C.pack parsedEncodedMemo let decodedMemo = B64.decodeLenient $ C.pack parsedEncodedMemo
putStrLn $ " Memo: " ++ show decodedMemo putStrLn $ " Memo: " ++ C.unpack decodedMemo
sendTx sendTx
user user
pwd pwd
fromAddy fromAddy
(T.pack parsedAddress) (T.pack parsedAddress)
amt amt
(show decodedMemo) (C.unpack decodedMemo)
else putStrLn " Invalid address" else putStrLn " Invalid address"
else putStrLn "URI is not compliant with ZIP-321" else putStrLn "URI is not compliant with ZIP-321"

View file

@ -42,7 +42,7 @@ packages:
# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a # commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
# #
# extra-deps: [] # extra-deps: []
#
# Override default flag values for local packages and extra-deps # Override default flag values for local packages and extra-deps
# flags: {} # flags: {}

View file

@ -55,7 +55,7 @@ executable zenith
Paths_zenith Paths_zenith
hs-source-dirs: hs-source-dirs:
app app
ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall -Wunused-imports
build-depends: build-depends:
base >=4.7 && <5 base >=4.7 && <5
, bytestring , bytestring