Compare commits
1 commit
master
...
milestone4
Author | SHA1 | Date | |
---|---|---|---|
83fa73bc0a |
15 changed files with 568 additions and 187 deletions
|
@ -67,7 +67,7 @@ main = do
|
||||||
zebraPort
|
zebraPort
|
||||||
(zgb_net chainInfo)
|
(zgb_net chainInfo)
|
||||||
threadDelay 90000000
|
threadDelay 90000000
|
||||||
putStrLn "Zenith RPC Server 0.7.0.0-beta"
|
putStrLn "Zenith RPC Server 0.8.0.0-beta"
|
||||||
putStrLn "------------------------------"
|
putStrLn "------------------------------"
|
||||||
putStrLn $
|
putStrLn $
|
||||||
"Connected to " ++
|
"Connected to " ++
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -79,6 +79,7 @@ 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 Data.Time.Clock.POSIX (posixSecondsToUTCTime)
|
import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
|
||||||
|
import qualified Data.UUID as U
|
||||||
import qualified Data.Vector as Vec
|
import qualified Data.Vector as Vec
|
||||||
import Database.Persist
|
import Database.Persist
|
||||||
import Database.Persist.Sqlite
|
import Database.Persist.Sqlite
|
||||||
|
@ -116,6 +117,7 @@ import Zenith.Types
|
||||||
, ValidAddressAPI(..)
|
, ValidAddressAPI(..)
|
||||||
, ZcashNetDB(..)
|
, ZcashNetDB(..)
|
||||||
, ZenithStatus(..)
|
, ZenithStatus(..)
|
||||||
|
, ZenithUuid(..)
|
||||||
)
|
)
|
||||||
import Zenith.Utils
|
import Zenith.Utils
|
||||||
( displayTaz
|
( displayTaz
|
||||||
|
@ -778,8 +780,8 @@ listDrawTx znet sel tx =
|
||||||
else displayTaz amt
|
else displayTaz amt
|
||||||
fmtAmt =
|
fmtAmt =
|
||||||
if amt > 0
|
if amt > 0
|
||||||
then "↘" <> dispAmount <> " "
|
then "↘ " <> dispAmount <> " "
|
||||||
else " " <> dispAmount <> "↗"
|
else " " <> dispAmount <> "↗ "
|
||||||
selStr s =
|
selStr s =
|
||||||
if sel
|
if sel
|
||||||
then withAttr customAttr (txt $ "> " <> s)
|
then withAttr customAttr (txt $ "> " <> s)
|
||||||
|
@ -1283,45 +1285,23 @@ appEvent (BT.VtyEvent e) = do
|
||||||
Just (_j, w1) -> return w1
|
Just (_j, w1) -> return w1
|
||||||
Just (_k, w) -> return w
|
Just (_k, w) -> return w
|
||||||
fs1 <- BT.zoom deshieldForm $ BT.gets formState
|
fs1 <- BT.zoom deshieldForm $ BT.gets formState
|
||||||
let tAddrMaybe =
|
|
||||||
Transparent <$>
|
|
||||||
((decodeTransparentAddress .
|
|
||||||
E.encodeUtf8 .
|
|
||||||
encodeTransparentReceiver (s ^. network)) =<<
|
|
||||||
(t_rec =<<
|
|
||||||
(isValidUnifiedAddress .
|
|
||||||
E.encodeUtf8 .
|
|
||||||
getUA . walletAddressUAddress)
|
|
||||||
(entityVal selAddr)))
|
|
||||||
bl <-
|
bl <-
|
||||||
liftIO $
|
liftIO $
|
||||||
getChainTip (s ^. zebraHost) (s ^. zebraPort)
|
getChainTip (s ^. zebraHost) (s ^. zebraPort)
|
||||||
case tAddrMaybe of
|
_ <-
|
||||||
Nothing -> do
|
liftIO $
|
||||||
BT.modify $
|
forkIO $
|
||||||
set
|
deshieldTransaction
|
||||||
msg
|
pool
|
||||||
"Failed to obtain transparent address"
|
(s ^. eventDispatch)
|
||||||
BT.modify $ set displayBox MsgDisplay
|
(s ^. zebraHost)
|
||||||
BT.modify $ set dialogBox Blank
|
(s ^. zebraPort)
|
||||||
Just tAddr -> do
|
(s ^. network)
|
||||||
_ <-
|
(entityKey selAcc)
|
||||||
liftIO $
|
bl
|
||||||
forkIO $
|
(fs1 ^. shAmt)
|
||||||
deshieldTransaction
|
BT.modify $ set displayBox SendDisplay
|
||||||
pool
|
BT.modify $ set dialogBox Blank
|
||||||
(s ^. eventDispatch)
|
|
||||||
(s ^. zebraHost)
|
|
||||||
(s ^. zebraPort)
|
|
||||||
(s ^. network)
|
|
||||||
(entityKey selAcc)
|
|
||||||
bl
|
|
||||||
(ProposedNote
|
|
||||||
(ValidAddressAPI tAddr)
|
|
||||||
(fs1 ^. shAmt)
|
|
||||||
Nothing)
|
|
||||||
BT.modify $ set displayBox SendDisplay
|
|
||||||
BT.modify $ set dialogBox Blank
|
|
||||||
else do
|
else do
|
||||||
BT.modify $ set msg "Invalid inputs"
|
BT.modify $ set msg "Invalid inputs"
|
||||||
BT.modify $ set displayBox MsgDisplay
|
BT.modify $ set displayBox MsgDisplay
|
||||||
|
@ -2050,19 +2030,20 @@ shieldTransaction ::
|
||||||
shieldTransaction pool chan zHost zPort znet accId bl = do
|
shieldTransaction pool chan zHost zPort znet accId bl = do
|
||||||
BC.writeBChan chan $ TickMsg "Preparing shielding transaction..."
|
BC.writeBChan chan $ TickMsg "Preparing shielding transaction..."
|
||||||
res <- runNoLoggingT $ shieldTransparentNotes pool zHost zPort znet accId bl
|
res <- runNoLoggingT $ shieldTransparentNotes pool zHost zPort znet accId bl
|
||||||
forM_ res $ \case
|
ops <-
|
||||||
Left e -> BC.writeBChan chan $ TickMsg $ show e
|
mapM
|
||||||
Right rawTx -> do
|
(\case
|
||||||
BC.writeBChan chan $ TickMsg "Transaction ready, sending to Zebra..."
|
Left e -> return $ T.pack $ show e
|
||||||
resp <-
|
Right x -> do
|
||||||
makeZebraCall
|
thisOp <- getOperation pool x
|
||||||
zHost
|
case thisOp of
|
||||||
zPort
|
Nothing -> return ""
|
||||||
"sendrawtransaction"
|
Just o ->
|
||||||
[Data.Aeson.String $ toText rawTx]
|
return $
|
||||||
case resp of
|
(U.toText . getUuid . operationUuid $ entityVal o) <>
|
||||||
Left e1 -> BC.writeBChan chan $ TickMsg $ "Zebra error: " ++ show e1
|
": " <> (T.pack . show . operationStatus $ entityVal o))
|
||||||
Right txId -> BC.writeBChan chan $ TickTx txId
|
res
|
||||||
|
BC.writeBChan chan $ TickMsg $ T.unpack $ T.intercalate "\n" ops
|
||||||
|
|
||||||
deshieldTransaction ::
|
deshieldTransaction ::
|
||||||
ConnectionPool
|
ConnectionPool
|
||||||
|
@ -2072,7 +2053,7 @@ deshieldTransaction ::
|
||||||
-> ZcashNet
|
-> ZcashNet
|
||||||
-> ZcashAccountId
|
-> ZcashAccountId
|
||||||
-> Int
|
-> Int
|
||||||
-> ProposedNote
|
-> Scientific
|
||||||
-> IO ()
|
-> IO ()
|
||||||
deshieldTransaction pool chan zHost zPort znet accId bl pnote = do
|
deshieldTransaction pool chan zHost zPort znet accId bl pnote = do
|
||||||
BC.writeBChan chan $ TickMsg "Deshielding funds..."
|
BC.writeBChan chan $ TickMsg "Deshielding funds..."
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
-- | Core wallet functionality for Zenith
|
-- | Core wallet functionality for Zenith
|
||||||
module Zenith.Core where
|
module Zenith.Core where
|
||||||
|
|
||||||
|
import Control.Concurrent (forkIO)
|
||||||
import Control.Exception (throwIO, try)
|
import Control.Exception (throwIO, try)
|
||||||
import Control.Monad (forM, unless, when)
|
import Control.Monad (forM, unless, when)
|
||||||
import Control.Monad.IO.Class (liftIO)
|
import Control.Monad.IO.Class (liftIO)
|
||||||
|
@ -25,6 +26,8 @@ import Data.Scientific (Scientific, scientific, toBoundedInteger)
|
||||||
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
|
import Data.Time
|
||||||
|
import qualified Data.UUID as U
|
||||||
|
import Data.UUID.V4 (nextRandom)
|
||||||
import qualified Database.Esqueleto.Experimental as ESQ
|
import qualified Database.Esqueleto.Experimental as ESQ
|
||||||
import Database.Persist
|
import Database.Persist
|
||||||
import Database.Persist.Sqlite
|
import Database.Persist.Sqlite
|
||||||
|
@ -41,6 +44,7 @@ import ZcashHaskell.Orchard
|
||||||
, getOrchardTreeParts
|
, getOrchardTreeParts
|
||||||
, getOrchardWitness
|
, getOrchardWitness
|
||||||
, isValidUnifiedAddress
|
, isValidUnifiedAddress
|
||||||
|
, parseAddress
|
||||||
, updateOrchardCommitmentTree
|
, updateOrchardCommitmentTree
|
||||||
, updateOrchardWitness
|
, updateOrchardWitness
|
||||||
)
|
)
|
||||||
|
@ -80,7 +84,10 @@ import Zenith.Types
|
||||||
, ValidAddressAPI(..)
|
, ValidAddressAPI(..)
|
||||||
, ZcashNetDB(..)
|
, ZcashNetDB(..)
|
||||||
, ZebraTreeInfo(..)
|
, ZebraTreeInfo(..)
|
||||||
|
, ZenithStatus(..)
|
||||||
|
, ZenithUuid(..)
|
||||||
)
|
)
|
||||||
|
import Zenith.Utils (getTransparentFromUA)
|
||||||
|
|
||||||
-- * Zebra Node interaction
|
-- * Zebra Node interaction
|
||||||
-- | Checks the status of the `zebrad` node
|
-- | Checks the status of the `zebrad` node
|
||||||
|
@ -746,14 +753,37 @@ deshieldNotes ::
|
||||||
-> ZcashNet
|
-> ZcashNet
|
||||||
-> ZcashAccountId
|
-> ZcashAccountId
|
||||||
-> Int
|
-> Int
|
||||||
-> ProposedNote
|
-> Scientific
|
||||||
-> NoLoggingT IO (Either TxError HexString)
|
-> NoLoggingT IO (Either TxError HexString)
|
||||||
deshieldNotes pool zebraHost zebraPort znet za bh pnote = do
|
deshieldNotes pool zebraHost zebraPort znet za bh pnote = do
|
||||||
bal <- liftIO $ getShieldedBalance pool za
|
bal <- liftIO $ getShieldedBalance pool za
|
||||||
let zats = pn_amt pnote * scientific 1 8
|
addrs <- getAddresses pool za
|
||||||
if fromInteger bal > (scientific 2 4 + zats)
|
let defAddr =
|
||||||
then prepareTxV2 pool zebraHost zebraPort znet za bh [pnote] Low
|
parseAddress $
|
||||||
else return $ Left InsufficientFunds
|
E.encodeUtf8 $ getUA $ walletAddressUAddress $ entityVal $ head addrs
|
||||||
|
case defAddr of
|
||||||
|
Nothing -> return $ Left ZHError
|
||||||
|
Just (Unified x) -> do
|
||||||
|
case getTransparentFromUA x of
|
||||||
|
Nothing -> return $ Left ZHError
|
||||||
|
Just ta -> do
|
||||||
|
let zats = pnote * scientific 1 8
|
||||||
|
if fromInteger bal > (scientific 2 4 + zats)
|
||||||
|
then prepareTxV2
|
||||||
|
pool
|
||||||
|
zebraHost
|
||||||
|
zebraPort
|
||||||
|
znet
|
||||||
|
za
|
||||||
|
bh
|
||||||
|
[ ProposedNote
|
||||||
|
(ValidAddressAPI $ Transparent ta)
|
||||||
|
pnote
|
||||||
|
Nothing
|
||||||
|
]
|
||||||
|
Low
|
||||||
|
else return $ Left InsufficientFunds
|
||||||
|
_anyOther -> return $ Left ZHError
|
||||||
|
|
||||||
shieldTransparentNotes ::
|
shieldTransparentNotes ::
|
||||||
ConnectionPool
|
ConnectionPool
|
||||||
|
@ -762,8 +792,8 @@ shieldTransparentNotes ::
|
||||||
-> ZcashNet
|
-> ZcashNet
|
||||||
-> ZcashAccountId
|
-> ZcashAccountId
|
||||||
-> Int
|
-> Int
|
||||||
-> NoLoggingT IO [Either TxError HexString]
|
-> NoLoggingT IO [Either TxError U.UUID]
|
||||||
shieldTransparentNotes pool zebraHost zebraPort znet za bh = do
|
shieldTransparentNotes pool zHost zPort znet za bh = do
|
||||||
accRead <- liftIO $ getAccountById pool za
|
accRead <- liftIO $ getAccountById pool za
|
||||||
logDebugN $ T.pack $ "Target block: " ++ show bh
|
logDebugN $ T.pack $ "Target block: " ++ show bh
|
||||||
case accRead of
|
case accRead of
|
||||||
|
@ -772,58 +802,94 @@ shieldTransparentNotes pool zebraHost zebraPort znet za bh = do
|
||||||
return [Left ZHError]
|
return [Left ZHError]
|
||||||
Just acc -> do
|
Just acc -> do
|
||||||
trNotes' <- liftIO $ getWalletUnspentTrNotes pool za
|
trNotes' <- liftIO $ getWalletUnspentTrNotes pool za
|
||||||
dRecvs <- liftIO $ getReceivers pool trNotes'
|
if null trNotes'
|
||||||
let fNotes =
|
then return [Left InsufficientFunds]
|
||||||
map
|
else do
|
||||||
(\x ->
|
dRecvs <- liftIO $ getReceivers pool trNotes'
|
||||||
filter (\y -> walletTrNoteAddress (entityVal y) == x) trNotes')
|
let fNotes =
|
||||||
dRecvs
|
map
|
||||||
sTree <- liftIO $ getSaplingTree pool
|
(\x ->
|
||||||
oTree <- liftIO $ getOrchardTree pool
|
filter
|
||||||
forM fNotes $ \trNotes -> do
|
(\y -> walletTrNoteAddress (entityVal y) == x)
|
||||||
let noteTotal = getTotalAmount (trNotes, [], [])
|
trNotes')
|
||||||
tSpends <-
|
dRecvs
|
||||||
liftIO $
|
sTree <- liftIO $ getSaplingTree pool
|
||||||
prepTSpends
|
oTree <- liftIO $ getOrchardTree pool
|
||||||
(getTranSK $ zcashAccountTPrivateKey $ entityVal acc)
|
forM fNotes $ \trNotes -> do
|
||||||
trNotes
|
opid <- liftIO nextRandom
|
||||||
chgAddr <- getInternalAddresses pool $ entityKey acc
|
startTime <- liftIO getCurrentTime
|
||||||
let internalUA =
|
opkey <-
|
||||||
getUA $ walletAddressUAddress $ entityVal $ head chgAddr
|
liftIO $
|
||||||
let oRcvr =
|
saveOperation pool $
|
||||||
fromJust $
|
Operation (ZenithUuid opid) startTime Nothing Processing Nothing
|
||||||
o_rec =<< isValidUnifiedAddress (E.encodeUtf8 internalUA)
|
case opkey of
|
||||||
let dummy =
|
Nothing -> return $ Left ZHError
|
||||||
OutgoingNote
|
Just opkey' -> do
|
||||||
4
|
let noteTotal = getTotalAmount (trNotes, [], [])
|
||||||
(getBytes $ getOrchSK $ zcashAccountOrchSpendKey $ entityVal acc)
|
tSpends <-
|
||||||
(getBytes oRcvr)
|
liftIO $
|
||||||
(fromIntegral $ noteTotal - 500)
|
prepTSpends
|
||||||
""
|
(getTranSK $ zcashAccountTPrivateKey $ entityVal acc)
|
||||||
True
|
trNotes
|
||||||
let feeAmt = calculateTxFee (trNotes, [], []) [dummy]
|
chgAddr <- getInternalAddresses pool $ entityKey acc
|
||||||
let snote =
|
let internalUA =
|
||||||
OutgoingNote
|
getUA $ walletAddressUAddress $ entityVal $ head chgAddr
|
||||||
4
|
let oRcvr =
|
||||||
(getBytes $ getOrchSK $ zcashAccountOrchSpendKey $ entityVal acc)
|
fromJust $
|
||||||
(getBytes oRcvr)
|
o_rec =<< isValidUnifiedAddress (E.encodeUtf8 internalUA)
|
||||||
(fromIntegral $ noteTotal - fromIntegral feeAmt)
|
let dummy =
|
||||||
""
|
OutgoingNote
|
||||||
True
|
4
|
||||||
tx <-
|
(getBytes $
|
||||||
liftIO $
|
getOrchSK $ zcashAccountOrchSpendKey $ entityVal acc)
|
||||||
createTransaction
|
(getBytes oRcvr)
|
||||||
(maybe (hexString "00") (getHash . value . fst) sTree)
|
(fromIntegral $ noteTotal - 500)
|
||||||
(maybe (hexString "00") (getHash . value . fst) oTree)
|
""
|
||||||
tSpends
|
True
|
||||||
[]
|
let feeAmt = calculateTxFee (trNotes, [], []) [dummy]
|
||||||
[]
|
let snote =
|
||||||
[snote]
|
OutgoingNote
|
||||||
znet
|
4
|
||||||
(bh + 3)
|
(getBytes $
|
||||||
True
|
getOrchSK $ zcashAccountOrchSpendKey $ entityVal acc)
|
||||||
logDebugN $ T.pack $ show tx
|
(getBytes oRcvr)
|
||||||
return tx
|
(fromIntegral $ noteTotal - fromIntegral feeAmt)
|
||||||
|
""
|
||||||
|
True
|
||||||
|
_ <-
|
||||||
|
liftIO $
|
||||||
|
forkIO $ do
|
||||||
|
tx <-
|
||||||
|
liftIO $
|
||||||
|
createTransaction
|
||||||
|
(maybe (hexString "00") (getHash . value . fst) sTree)
|
||||||
|
(maybe (hexString "00") (getHash . value . fst) oTree)
|
||||||
|
tSpends
|
||||||
|
[]
|
||||||
|
[]
|
||||||
|
[snote]
|
||||||
|
znet
|
||||||
|
(bh + 3)
|
||||||
|
True
|
||||||
|
case tx of
|
||||||
|
Left e ->
|
||||||
|
finalizeOperation pool opkey' Failed $ T.pack $ show e
|
||||||
|
Right rawTx -> do
|
||||||
|
zebraRes <-
|
||||||
|
makeZebraCall
|
||||||
|
zHost
|
||||||
|
zPort
|
||||||
|
"sendrawtransaction"
|
||||||
|
[Data.Aeson.String $ toText rawTx]
|
||||||
|
case zebraRes of
|
||||||
|
Left e1 ->
|
||||||
|
finalizeOperation pool opkey' Failed $
|
||||||
|
T.pack $ show e1
|
||||||
|
Right txId ->
|
||||||
|
finalizeOperation pool opkey' Successful $
|
||||||
|
"Tx ID: " <> toText txId
|
||||||
|
logDebugN $ T.pack $ show opid
|
||||||
|
return $ Right opid
|
||||||
where
|
where
|
||||||
getTotalAmount ::
|
getTotalAmount ::
|
||||||
( [Entity WalletTrNote]
|
( [Entity WalletTrNote]
|
||||||
|
|
|
@ -630,6 +630,7 @@ 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 ::
|
||||||
|
|
|
@ -28,6 +28,7 @@ import Data.Scientific (Scientific, fromFloatDigits)
|
||||||
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.POSIX (posixSecondsToUTCTime)
|
import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
|
||||||
|
import qualified Data.UUID as U
|
||||||
import Database.Esqueleto.Experimental (ConnectionPool, fromSqlKey)
|
import Database.Esqueleto.Experimental (ConnectionPool, fromSqlKey)
|
||||||
import Database.Persist
|
import Database.Persist
|
||||||
import Lens.Micro ((&), (+~), (.~), (?~), (^.), set)
|
import Lens.Micro ((&), (+~), (.~), (?~), (^.), set)
|
||||||
|
@ -1750,19 +1751,20 @@ shieldTransaction config znet accId sendMsg = do
|
||||||
pool <- runNoLoggingT $ initPool dbPath
|
pool <- runNoLoggingT $ initPool dbPath
|
||||||
bl <- getChainTip zHost zPort
|
bl <- getChainTip zHost zPort
|
||||||
res <- runNoLoggingT $ shieldTransparentNotes pool zHost zPort znet accId bl
|
res <- runNoLoggingT $ shieldTransparentNotes pool zHost zPort znet accId bl
|
||||||
forM_ res $ \case
|
ops <-
|
||||||
Left e -> sendMsg $ ShowError $ T.pack (show e)
|
mapM
|
||||||
Right rawTx -> do
|
(\case
|
||||||
sendMsg $ ShowMsg "Transaction ready, sending to Zebra..."
|
Left e -> return $ T.pack $ show e
|
||||||
resp <-
|
Right x -> do
|
||||||
makeZebraCall
|
thisOp <- getOperation pool x
|
||||||
zHost
|
case thisOp of
|
||||||
zPort
|
Nothing -> return ""
|
||||||
"sendrawtransaction"
|
Just o ->
|
||||||
[Data.Aeson.String $ toText rawTx]
|
return $
|
||||||
case resp of
|
(U.toText . getUuid . operationUuid $ entityVal o) <>
|
||||||
Left e1 -> sendMsg $ ShowError $ "Zebra error: " <> T.pack (show e1)
|
": " <> (T.pack . show . operationStatus $ entityVal o))
|
||||||
Right txId -> sendMsg $ ShowTxId txId
|
res
|
||||||
|
sendMsg $ ShowMsg $ T.intercalate "\n" ops
|
||||||
|
|
||||||
deshieldTransaction ::
|
deshieldTransaction ::
|
||||||
Config
|
Config
|
||||||
|
@ -1782,40 +1784,20 @@ deshieldTransaction config znet accId addR pnote sendMsg = do
|
||||||
let zPort = c_zebraPort config
|
let zPort = c_zebraPort config
|
||||||
pool <- runNoLoggingT $ initPool dbPath
|
pool <- runNoLoggingT $ initPool dbPath
|
||||||
bl <- getChainTip zHost zPort
|
bl <- getChainTip zHost zPort
|
||||||
let tAddrMaybe =
|
res <- runNoLoggingT $ deshieldNotes pool zHost zPort znet accId bl pnote
|
||||||
Transparent <$>
|
case res of
|
||||||
((decodeTransparentAddress .
|
Left e -> sendMsg $ ShowError $ T.pack (show e)
|
||||||
E.encodeUtf8 . encodeTransparentReceiver znet) =<<
|
Right rawTx -> do
|
||||||
(t_rec =<<
|
sendMsg $ ShowModal "Transaction ready, sending to Zebra..."
|
||||||
(isValidUnifiedAddress .
|
resp <-
|
||||||
E.encodeUtf8 . getUA . walletAddressUAddress)
|
makeZebraCall
|
||||||
(entityVal addr)))
|
|
||||||
case tAddrMaybe of
|
|
||||||
Nothing -> sendMsg $ ShowError "No transparent address available"
|
|
||||||
Just tAddr -> do
|
|
||||||
res <-
|
|
||||||
runNoLoggingT $
|
|
||||||
deshieldNotes
|
|
||||||
pool
|
|
||||||
zHost
|
zHost
|
||||||
zPort
|
zPort
|
||||||
znet
|
"sendrawtransaction"
|
||||||
accId
|
[Data.Aeson.String $ toText rawTx]
|
||||||
bl
|
case resp of
|
||||||
(ProposedNote (ValidAddressAPI tAddr) pnote Nothing)
|
Left e1 -> sendMsg $ ShowError $ "Zebra error: " <> showt e1
|
||||||
case res of
|
Right txId -> sendMsg $ ShowTxId txId
|
||||||
Left e -> sendMsg $ ShowError $ T.pack (show e)
|
|
||||||
Right rawTx -> do
|
|
||||||
sendMsg $ ShowModal "Transaction ready, sending to Zebra..."
|
|
||||||
resp <-
|
|
||||||
makeZebraCall
|
|
||||||
zHost
|
|
||||||
zPort
|
|
||||||
"sendrawtransaction"
|
|
||||||
[Data.Aeson.String $ toText rawTx]
|
|
||||||
case resp of
|
|
||||||
Left e1 -> sendMsg $ ShowError $ "Zebra error: " <> showt e1
|
|
||||||
Right txId -> sendMsg $ ShowTxId txId
|
|
||||||
|
|
||||||
sendTransaction ::
|
sendTransaction ::
|
||||||
Config
|
Config
|
||||||
|
|
|
@ -20,7 +20,7 @@ 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 (floatingOrInteger)
|
import Data.Scientific (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)
|
||||||
|
@ -50,7 +50,9 @@ import Zenith.Core
|
||||||
( checkBlockChain
|
( checkBlockChain
|
||||||
, createCustomWalletAddress
|
, createCustomWalletAddress
|
||||||
, createZcashAccount
|
, createZcashAccount
|
||||||
|
, deshieldNotes
|
||||||
, prepareTxV2
|
, prepareTxV2
|
||||||
|
, shieldTransparentNotes
|
||||||
, syncWallet
|
, syncWallet
|
||||||
, updateCommitmentTrees
|
, updateCommitmentTrees
|
||||||
)
|
)
|
||||||
|
@ -121,6 +123,8 @@ data ZenithMethod
|
||||||
| GetNewAddress
|
| GetNewAddress
|
||||||
| GetOperationStatus
|
| GetOperationStatus
|
||||||
| SendMany
|
| SendMany
|
||||||
|
| ShieldNotes
|
||||||
|
| DeshieldFunds
|
||||||
| UnknownMethod
|
| UnknownMethod
|
||||||
deriving (Eq, Prelude.Show)
|
deriving (Eq, Prelude.Show)
|
||||||
|
|
||||||
|
@ -136,6 +140,8 @@ 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 UnknownMethod = Data.Aeson.Null
|
toJSON UnknownMethod = Data.Aeson.Null
|
||||||
|
|
||||||
instance FromJSON ZenithMethod where
|
instance FromJSON ZenithMethod where
|
||||||
|
@ -152,6 +158,8 @@ 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
|
||||||
_ -> pure UnknownMethod
|
_ -> pure UnknownMethod
|
||||||
|
|
||||||
data ZenithParams
|
data ZenithParams
|
||||||
|
@ -167,6 +175,8 @@ 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
|
||||||
deriving (Eq, Prelude.Show)
|
deriving (Eq, Prelude.Show)
|
||||||
|
|
||||||
instance ToJSON ZenithParams where
|
instance ToJSON ZenithParams where
|
||||||
|
@ -191,6 +201,9 @@ 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]
|
||||||
|
|
||||||
data ZenithResponse
|
data ZenithResponse
|
||||||
= InfoResponse !T.Text !ZenithInfo
|
= InfoResponse !T.Text !ZenithInfo
|
||||||
|
@ -203,6 +216,7 @@ 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]
|
||||||
| ErrorResponse !T.Text !Double !T.Text
|
| ErrorResponse !T.Text !Double !T.Text
|
||||||
deriving (Eq, Prelude.Show)
|
deriving (Eq, Prelude.Show)
|
||||||
|
|
||||||
|
@ -224,6 +238,7 @@ 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
|
||||||
|
|
||||||
instance FromJSON ZenithResponse where
|
instance FromJSON ZenithResponse where
|
||||||
parseJSON =
|
parseJSON =
|
||||||
|
@ -298,6 +313,9 @@ 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
|
||||||
|
@ -489,6 +507,27 @@ 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
|
||||||
|
|
||||||
type ZenithRPC
|
type ZenithRPC
|
||||||
= "status" :> Get '[ JSON] Value :<|> BasicAuth "zenith-realm" Bool :> ReqBody
|
= "status" :> Get '[ JSON] Value :<|> BasicAuth "zenith-realm" Bool :> ReqBody
|
||||||
|
@ -511,7 +550,7 @@ zenithServer state = getinfo :<|> handleRPC
|
||||||
getinfo =
|
getinfo =
|
||||||
return $
|
return $
|
||||||
object
|
object
|
||||||
[ "version" .= ("0.7.0.0-beta" :: String)
|
[ "version" .= ("0.8.0.0-beta" :: String)
|
||||||
, "network" .= ("testnet" :: String)
|
, "network" .= ("testnet" :: String)
|
||||||
]
|
]
|
||||||
handleRPC :: Bool -> RpcCall -> Handler ZenithResponse
|
handleRPC :: Bool -> RpcCall -> Handler ZenithResponse
|
||||||
|
@ -587,7 +626,7 @@ zenithServer state = getinfo :<|> handleRPC
|
||||||
return $
|
return $
|
||||||
InfoResponse
|
InfoResponse
|
||||||
(callId req)
|
(callId req)
|
||||||
(ZenithInfo "0.7.0.0-beta" (w_network state) (w_build state))
|
(ZenithInfo "0.8.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 ->
|
||||||
|
@ -871,6 +910,137 @@ 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"
|
||||||
|
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
|
||||||
|
Just acc' -> do
|
||||||
|
bl <-
|
||||||
|
liftIO $
|
||||||
|
getLastSyncBlock
|
||||||
|
pool
|
||||||
|
(zcashAccountWalletId $ entityVal acc')
|
||||||
|
_ <-
|
||||||
|
liftIO $
|
||||||
|
forkIO $ do
|
||||||
|
res <-
|
||||||
|
runNoLoggingT $
|
||||||
|
deshieldNotes
|
||||||
|
pool
|
||||||
|
zHost
|
||||||
|
zPort
|
||||||
|
net
|
||||||
|
(entityKey acc')
|
||||||
|
bl
|
||||||
|
k
|
||||||
|
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
|
||||||
|
Nothing ->
|
||||||
|
return $
|
||||||
|
ErrorResponse
|
||||||
|
(callId req)
|
||||||
|
(-32006)
|
||||||
|
"Account does not exist."
|
||||||
|
_anyOtherParams ->
|
||||||
|
return $ ErrorResponse (callId req) (-32602) "Invalid params"
|
||||||
|
|
||||||
authenticate :: Config -> BasicAuthCheck Bool
|
authenticate :: Config -> BasicAuthCheck Bool
|
||||||
authenticate config = BasicAuthCheck check
|
authenticate config = BasicAuthCheck check
|
||||||
|
|
|
@ -235,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
|
||||||
|
@ -248,3 +248,6 @@ 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
|
||||||
|
|
||||||
|
getTransparentFromUA :: UnifiedAddress -> Maybe TransparentAddress
|
||||||
|
getTransparentFromUA ua = TransparentAddress (ua_net ua) <$> t_rec ua
|
||||||
|
|
|
@ -86,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.7.0.0-beta" TestNet "v1.9.0")
|
InfoResponse "zh" (ZenithInfo "0.8.0.0-beta" TestNet "v2.1.0")
|
||||||
describe "Wallets" $ do
|
describe "Wallets" $ do
|
||||||
describe "listwallet" $ do
|
describe "listwallet" $ do
|
||||||
it "bad credentials" $ do
|
it "bad credentials" $ do
|
||||||
|
@ -676,6 +676,54 @@ 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` []
|
||||||
|
|
||||||
startAPI :: Config -> IO ()
|
startAPI :: Config -> IO ()
|
||||||
startAPI config = do
|
startAPI config = do
|
||||||
|
|
31
test/Spec.hs
31
test/Spec.hs
|
@ -643,8 +643,7 @@ 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 <-
|
updatedTree <- runNoLoggingT $ truncateTree oTree i
|
||||||
runFileLoggingT "test.log" $ truncateTree oTree i
|
|
||||||
let finalAnchor =
|
let finalAnchor =
|
||||||
getOrchardTreeAnchor $
|
getOrchardTreeAnchor $
|
||||||
OrchardCommitmentTree $ ztiOrchard zebraTreesIn
|
OrchardCommitmentTree $ ztiOrchard zebraTreesIn
|
||||||
|
@ -737,7 +736,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 <-
|
||||||
runFileLoggingT "zenith.log" $
|
runNoLoggingT $
|
||||||
prepareTxV2
|
prepareTxV2
|
||||||
pool
|
pool
|
||||||
"localhost"
|
"localhost"
|
||||||
|
@ -763,7 +762,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 <-
|
||||||
runFileLoggingT "zenith.log" $
|
runNoLoggingT $
|
||||||
prepareTxV2
|
prepareTxV2
|
||||||
pool
|
pool
|
||||||
"localhost"
|
"localhost"
|
||||||
|
@ -787,7 +786,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 <-
|
||||||
runFileLoggingT "zenith.log" $
|
runNoLoggingT $
|
||||||
prepareTxV2
|
prepareTxV2
|
||||||
pool
|
pool
|
||||||
"localhost"
|
"localhost"
|
||||||
|
@ -815,7 +814,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 <-
|
||||||
runFileLoggingT "zenith.log" $
|
runNoLoggingT $
|
||||||
prepareTxV2
|
prepareTxV2
|
||||||
pool
|
pool
|
||||||
"localhost"
|
"localhost"
|
||||||
|
@ -847,7 +846,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 <-
|
||||||
runFileLoggingT "zenith.log" $
|
runNoLoggingT $
|
||||||
prepareTxV2
|
prepareTxV2
|
||||||
pool
|
pool
|
||||||
"localhost"
|
"localhost"
|
||||||
|
@ -873,7 +872,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 <-
|
||||||
runFileLoggingT "zenith.log" $
|
runNoLoggingT $
|
||||||
prepareTxV2
|
prepareTxV2
|
||||||
pool
|
pool
|
||||||
"localhost"
|
"localhost"
|
||||||
|
@ -897,7 +896,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 <-
|
||||||
runFileLoggingT "zenith.log" $
|
runNoLoggingT $
|
||||||
prepareTxV2
|
prepareTxV2
|
||||||
pool
|
pool
|
||||||
"localhost"
|
"localhost"
|
||||||
|
@ -926,7 +925,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 <-
|
||||||
runFileLoggingT "zenith.log" $
|
runNoLoggingT $
|
||||||
prepareTxV2
|
prepareTxV2
|
||||||
pool
|
pool
|
||||||
"localhost"
|
"localhost"
|
||||||
|
@ -957,7 +956,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 <-
|
||||||
runFileLoggingT "zenith.log" $
|
runNoLoggingT $
|
||||||
prepareTxV2
|
prepareTxV2
|
||||||
pool
|
pool
|
||||||
"localhost"
|
"localhost"
|
||||||
|
@ -983,7 +982,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 <-
|
||||||
runFileLoggingT "zenith.log" $
|
runNoLoggingT $
|
||||||
prepareTxV2
|
prepareTxV2
|
||||||
pool
|
pool
|
||||||
"localhost"
|
"localhost"
|
||||||
|
@ -1007,7 +1006,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 <-
|
||||||
runFileLoggingT "zenith.log" $
|
runNoLoggingT $
|
||||||
prepareTxV2
|
prepareTxV2
|
||||||
pool
|
pool
|
||||||
"localhost"
|
"localhost"
|
||||||
|
@ -1034,7 +1033,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 <-
|
||||||
runFileLoggingT "zenith.log" $
|
runNoLoggingT $
|
||||||
prepareTxV2
|
prepareTxV2
|
||||||
pool
|
pool
|
||||||
"localhost"
|
"localhost"
|
||||||
|
@ -1061,7 +1060,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 <-
|
||||||
runFileLoggingT "zenith.log" $
|
runNoLoggingT $
|
||||||
prepareTxV2
|
prepareTxV2
|
||||||
pool
|
pool
|
||||||
"localhost"
|
"localhost"
|
||||||
|
@ -1086,7 +1085,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 <-
|
||||||
runFileLoggingT "zenith.log" $
|
runNoLoggingT $
|
||||||
prepareTxV2
|
prepareTxV2
|
||||||
pool
|
pool
|
||||||
"localhost"
|
"localhost"
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 4289a9ded67ef2ca432abc412934fb5b8b59a9cf
|
Subproject commit 7d3ae36d2b48b8ed91a70e40a77fb7efe57765a0
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"openrpc": "1.0.0-rc1",
|
"openrpc": "1.0.0-rc1",
|
||||||
"info": {
|
"info": {
|
||||||
"version": "0.7.0.0-beta",
|
"version": "0.8.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": {
|
||||||
|
@ -605,10 +605,9 @@
|
||||||
],
|
],
|
||||||
"paramStructure": "by-position",
|
"paramStructure": "by-position",
|
||||||
"result": {
|
"result": {
|
||||||
"name": "Operation ID(s)",
|
"name": "Operation ID",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "array",
|
"$ref": "#/components/contentDescriptors/OperationId"
|
||||||
"items": { "$ref": "#/components/contentDescriptors/OperationId"}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"examples": [
|
"examples": [
|
||||||
|
@ -620,7 +619,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",
|
||||||
|
@ -641,9 +640,8 @@
|
||||||
],
|
],
|
||||||
"result": {
|
"result": {
|
||||||
"name": "SendMany result",
|
"name": "SendMany result",
|
||||||
"value": [
|
"value": "3cc31c07-07cf-4a6e-9190-156c4b8c4088"
|
||||||
"3cc31c07-07cf-4a6e-9190-156c4b8c4088"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -669,6 +667,130 @@
|
||||||
"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" }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"components": {
|
"components": {
|
||||||
|
@ -700,6 +822,15 @@
|
||||||
"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",
|
||||||
|
|
BIN
zenith_er.bmp
BIN
zenith_er.bmp
Binary file not shown.
Before Width: | Height: | Size: 7.7 MiB |
BIN
zenith_er.png
BIN
zenith_er.png
Binary file not shown.
Before Width: | Height: | Size: 329 KiB |
Loading…
Reference in a new issue