Compare commits
No commits in common. "5ce822e52f9bf2f32193db6815eb258b1ca4fe2d" and "865f7241b1fcff64ba26b44a931385bde79685a4" have entirely different histories.
5ce822e52f
...
865f7241b1
5 changed files with 53 additions and 233 deletions
|
@ -163,10 +163,5 @@ createWalletAddress n i zNet scope za = do
|
||||||
syncWallet ::
|
syncWallet ::
|
||||||
T.Text -- ^ The database path
|
T.Text -- ^ The database path
|
||||||
-> Entity ZcashWallet
|
-> Entity ZcashWallet
|
||||||
-> IO String
|
-> IO ()
|
||||||
syncWallet walletDb w = do
|
syncWallet walletDb w = undefined
|
||||||
accs <- getAccounts walletDb $ entityKey w
|
|
||||||
addrs <- concat <$> mapM (getAddresses walletDb . entityKey) accs
|
|
||||||
lastBlock <- getMaxWalletBlock walletDb
|
|
||||||
trNotes <- mapM (findTransparentNotes walletDb lastBlock . entityVal) addrs
|
|
||||||
return $ show trNotes
|
|
||||||
|
|
258
src/Zenith/DB.hs
258
src/Zenith/DB.hs
|
@ -14,27 +14,19 @@
|
||||||
{-# LANGUAGE DataKinds #-}
|
{-# LANGUAGE DataKinds #-}
|
||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
{-# LANGUAGE TypeOperators #-}
|
{-# LANGUAGE TypeOperators #-}
|
||||||
{-# LANGUAGE TypeApplications #-}
|
|
||||||
|
|
||||||
module Zenith.DB where
|
module Zenith.DB where
|
||||||
|
|
||||||
import Control.Monad (when)
|
import Control.Monad (when)
|
||||||
|
import Control.Monad.IO.Class (liftIO)
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
import Data.HexString
|
import Data.HexString
|
||||||
import Data.Maybe (fromJust, isJust)
|
import Data.Maybe (fromJust, isJust)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Data.Text.Encoding as TE
|
import Database.Persist
|
||||||
import Database.Esqueleto.Experimental
|
import Database.Persist.Sqlite
|
||||||
import qualified Database.Persist as P
|
|
||||||
import qualified Database.Persist.Sqlite as PS
|
|
||||||
import Database.Persist.TH
|
import Database.Persist.TH
|
||||||
import Haskoin.Transaction.Common
|
import Haskoin.Transaction.Common (TxOut(..))
|
||||||
( OutPoint(..)
|
|
||||||
, TxIn(..)
|
|
||||||
, TxOut(..)
|
|
||||||
, txHashToHex
|
|
||||||
)
|
|
||||||
import ZcashHaskell.Orchard (isValidUnifiedAddress)
|
|
||||||
import ZcashHaskell.Types
|
import ZcashHaskell.Types
|
||||||
( OrchardAction(..)
|
( OrchardAction(..)
|
||||||
, OrchardBundle(..)
|
, OrchardBundle(..)
|
||||||
|
@ -43,9 +35,7 @@ import ZcashHaskell.Types
|
||||||
, ShieldedOutput(..)
|
, ShieldedOutput(..)
|
||||||
, ShieldedSpend(..)
|
, ShieldedSpend(..)
|
||||||
, Transaction(..)
|
, Transaction(..)
|
||||||
, TransparentAddress(..)
|
|
||||||
, TransparentBundle(..)
|
, TransparentBundle(..)
|
||||||
, UnifiedAddress(..)
|
|
||||||
, ZcashNet
|
, ZcashNet
|
||||||
)
|
)
|
||||||
import Zenith.Types
|
import Zenith.Types
|
||||||
|
@ -93,7 +83,6 @@ share
|
||||||
block Int
|
block Int
|
||||||
conf Int
|
conf Int
|
||||||
time Int
|
time Int
|
||||||
UniqueWTx txId
|
|
||||||
deriving Show Eq
|
deriving Show Eq
|
||||||
WalletTrNote
|
WalletTrNote
|
||||||
tx WalletTransactionId
|
tx WalletTransactionId
|
||||||
|
@ -110,7 +99,6 @@ share
|
||||||
memo T.Text
|
memo T.Text
|
||||||
rawId ShieldOutputId
|
rawId ShieldOutputId
|
||||||
spent Bool
|
spent Bool
|
||||||
nullifier HexStringDB
|
|
||||||
deriving Show Eq
|
deriving Show Eq
|
||||||
WalletOrchNote
|
WalletOrchNote
|
||||||
tx WalletTransactionId
|
tx WalletTransactionId
|
||||||
|
@ -120,7 +108,6 @@ share
|
||||||
memo T.Text
|
memo T.Text
|
||||||
rawId OrchActionId
|
rawId OrchActionId
|
||||||
spent Bool
|
spent Bool
|
||||||
nullifier HexStringDB
|
|
||||||
deriving Show Eq
|
deriving Show Eq
|
||||||
ZcashTransaction
|
ZcashTransaction
|
||||||
block Int
|
block Int
|
||||||
|
@ -132,18 +119,6 @@ share
|
||||||
tx ZcashTransactionId
|
tx ZcashTransactionId
|
||||||
value Int
|
value Int
|
||||||
script BS.ByteString
|
script BS.ByteString
|
||||||
position Int
|
|
||||||
UniqueTNPos tx position
|
|
||||||
deriving Show Eq
|
|
||||||
TransparentSpend
|
|
||||||
tx ZcashTransactionId
|
|
||||||
outPointHash HexStringDB
|
|
||||||
outPointIndex Int
|
|
||||||
script BS.ByteString
|
|
||||||
seq Int
|
|
||||||
position Int
|
|
||||||
UniqueTSPos tx position
|
|
||||||
deriving Show Eq
|
|
||||||
OrchAction
|
OrchAction
|
||||||
tx ZcashTransactionId
|
tx ZcashTransactionId
|
||||||
nf HexStringDB
|
nf HexStringDB
|
||||||
|
@ -154,8 +129,6 @@ share
|
||||||
outCipher HexStringDB
|
outCipher HexStringDB
|
||||||
cv HexStringDB
|
cv HexStringDB
|
||||||
auth HexStringDB
|
auth HexStringDB
|
||||||
position Int
|
|
||||||
UniqueOAPos tx position
|
|
||||||
deriving Show Eq
|
deriving Show Eq
|
||||||
ShieldOutput
|
ShieldOutput
|
||||||
tx ZcashTransactionId
|
tx ZcashTransactionId
|
||||||
|
@ -165,8 +138,6 @@ share
|
||||||
encCipher HexStringDB
|
encCipher HexStringDB
|
||||||
outCipher HexStringDB
|
outCipher HexStringDB
|
||||||
proof HexStringDB
|
proof HexStringDB
|
||||||
position Int
|
|
||||||
UniqueSOPos tx position
|
|
||||||
deriving Show Eq
|
deriving Show Eq
|
||||||
ShieldSpend
|
ShieldSpend
|
||||||
tx ZcashTransactionId
|
tx ZcashTransactionId
|
||||||
|
@ -176,8 +147,6 @@ share
|
||||||
rk HexStringDB
|
rk HexStringDB
|
||||||
proof HexStringDB
|
proof HexStringDB
|
||||||
authSig HexStringDB
|
authSig HexStringDB
|
||||||
position Int
|
|
||||||
UniqueSSPos tx position
|
|
||||||
deriving Show Eq
|
deriving Show Eq
|
||||||
|]
|
|]
|
||||||
|
|
||||||
|
@ -187,35 +156,26 @@ initDb ::
|
||||||
T.Text -- ^ The database path to check
|
T.Text -- ^ The database path to check
|
||||||
-> IO ()
|
-> IO ()
|
||||||
initDb dbName = do
|
initDb dbName = do
|
||||||
PS.runSqlite dbName $ do runMigration migrateAll
|
runSqlite dbName $ do runMigration migrateAll
|
||||||
|
|
||||||
-- | Get existing wallets from database
|
-- | Get existing wallets from database
|
||||||
getWallets :: T.Text -> ZcashNet -> IO [Entity ZcashWallet]
|
getWallets :: T.Text -> ZcashNet -> IO [Entity ZcashWallet]
|
||||||
getWallets dbFp n =
|
getWallets dbFp n =
|
||||||
PS.runSqlite dbFp $
|
runSqlite dbFp $ selectList [ZcashWalletNetwork ==. ZcashNetDB n] []
|
||||||
select $ do
|
|
||||||
wallets <- from $ table @ZcashWallet
|
|
||||||
where_ (wallets ^. ZcashWalletNetwork ==. val (ZcashNetDB n))
|
|
||||||
pure wallets
|
|
||||||
|
|
||||||
-- | Save a new wallet to the database
|
-- | Save a new wallet to the database
|
||||||
saveWallet ::
|
saveWallet ::
|
||||||
T.Text -- ^ The database path to use
|
T.Text -- ^ The database path to use
|
||||||
-> ZcashWallet -- ^ The wallet to add to the database
|
-> ZcashWallet -- ^ The wallet to add to the database
|
||||||
-> IO (Maybe (Entity ZcashWallet))
|
-> IO (Maybe (Entity ZcashWallet))
|
||||||
saveWallet dbFp w = PS.runSqlite dbFp $ insertUniqueEntity w
|
saveWallet dbFp w = runSqlite dbFp $ insertUniqueEntity w
|
||||||
|
|
||||||
-- | Returns a list of accounts associated with the given wallet
|
-- | Returns a list of accounts associated with the given wallet
|
||||||
getAccounts ::
|
getAccounts ::
|
||||||
T.Text -- ^ The database path
|
T.Text -- ^ The database path
|
||||||
-> ZcashWalletId -- ^ The wallet ID to check
|
-> ZcashWalletId -- ^ The wallet ID to check
|
||||||
-> IO [Entity ZcashAccount]
|
-> IO [Entity ZcashAccount]
|
||||||
getAccounts dbFp w =
|
getAccounts dbFp w = runSqlite dbFp $ selectList [ZcashAccountWalletId ==. w] []
|
||||||
PS.runSqlite dbFp $
|
|
||||||
select $ do
|
|
||||||
accs <- from $ table @ZcashAccount
|
|
||||||
where_ (accs ^. ZcashAccountWalletId ==. val w)
|
|
||||||
pure accs
|
|
||||||
|
|
||||||
-- | Returns the largest account index for the given wallet
|
-- | Returns the largest account index for the given wallet
|
||||||
getMaxAccount ::
|
getMaxAccount ::
|
||||||
|
@ -224,12 +184,8 @@ getMaxAccount ::
|
||||||
-> IO Int
|
-> IO Int
|
||||||
getMaxAccount dbFp w = do
|
getMaxAccount dbFp w = do
|
||||||
a <-
|
a <-
|
||||||
PS.runSqlite dbFp $
|
runSqlite dbFp $
|
||||||
selectOne $ do
|
selectFirst [ZcashAccountWalletId ==. w] [Desc ZcashAccountIndex]
|
||||||
accs <- from $ table @ZcashAccount
|
|
||||||
where_ (accs ^. ZcashAccountWalletId ==. val w)
|
|
||||||
orderBy [desc $ accs ^. ZcashAccountIndex]
|
|
||||||
pure accs
|
|
||||||
case a of
|
case a of
|
||||||
Nothing -> return $ -1
|
Nothing -> return $ -1
|
||||||
Just x -> return $ zcashAccountIndex $ entityVal x
|
Just x -> return $ zcashAccountIndex $ entityVal x
|
||||||
|
@ -239,7 +195,7 @@ saveAccount ::
|
||||||
T.Text -- ^ The database path
|
T.Text -- ^ The database path
|
||||||
-> ZcashAccount -- ^ The account to add to the database
|
-> ZcashAccount -- ^ The account to add to the database
|
||||||
-> IO (Maybe (Entity ZcashAccount))
|
-> IO (Maybe (Entity ZcashAccount))
|
||||||
saveAccount dbFp a = PS.runSqlite dbFp $ insertUniqueEntity a
|
saveAccount dbFp a = runSqlite dbFp $ insertUniqueEntity a
|
||||||
|
|
||||||
-- | Returns the largest block in storage
|
-- | Returns the largest block in storage
|
||||||
getMaxBlock ::
|
getMaxBlock ::
|
||||||
|
@ -247,38 +203,34 @@ getMaxBlock ::
|
||||||
-> IO Int
|
-> IO Int
|
||||||
getMaxBlock dbPath = do
|
getMaxBlock dbPath = do
|
||||||
b <-
|
b <-
|
||||||
PS.runSqlite dbPath $
|
runSqlite dbPath $
|
||||||
selectOne $ do
|
selectFirst [ZcashTransactionBlock >. 0] [Desc ZcashTransactionBlock]
|
||||||
txs <- from $ table @ZcashTransaction
|
|
||||||
where_ (txs ^. ZcashTransactionBlock >. val 0)
|
|
||||||
orderBy [desc $ txs ^. ZcashTransactionBlock]
|
|
||||||
pure txs
|
|
||||||
case b of
|
case b of
|
||||||
Nothing -> return $ -1
|
Nothing -> return $ -1
|
||||||
Just x -> return $ zcashTransactionBlock $ entityVal x
|
Just x -> return $ zcashTransactionBlock $ entityVal x
|
||||||
|
|
||||||
|
-- | Returns the largest block in the wallet
|
||||||
|
getMaxWalletBlock ::
|
||||||
|
T.Text -- ^ The database path
|
||||||
|
-> IO Int
|
||||||
|
getMaxWalletBlock dbPath = do
|
||||||
|
b <-
|
||||||
|
runSqlite dbPath $
|
||||||
|
selectFirst [WalletTransactionBlock >. 0] [Desc WalletTransactionBlock]
|
||||||
|
case b of
|
||||||
|
Nothing -> return $ -1
|
||||||
|
Just x -> return $ walletTransactionBlock $ entityVal x
|
||||||
|
|
||||||
-- | Returns a list of addresses associated with the given account
|
-- | Returns a list of addresses associated with the given account
|
||||||
getAddresses ::
|
getAddresses ::
|
||||||
T.Text -- ^ The database path
|
T.Text -- ^ The database path
|
||||||
-> ZcashAccountId -- ^ The account ID to check
|
-> ZcashAccountId -- ^ The account ID to check
|
||||||
-> IO [Entity WalletAddress]
|
-> IO [Entity WalletAddress]
|
||||||
getAddresses dbFp a =
|
getAddresses dbFp a =
|
||||||
PS.runSqlite dbFp $
|
runSqlite dbFp $
|
||||||
select $ do
|
selectList
|
||||||
addrs <- from $ table @WalletAddress
|
[WalletAddressAccId ==. a, WalletAddressScope ==. ScopeDB External]
|
||||||
where_ (addrs ^. WalletAddressAccId ==. val a)
|
[]
|
||||||
where_ (addrs ^. WalletAddressScope ==. val (ScopeDB External))
|
|
||||||
pure addrs
|
|
||||||
|
|
||||||
-- | Returns a list of addressess associated with the given wallet
|
|
||||||
getWalletAddresses ::
|
|
||||||
T.Text -- ^ The database path
|
|
||||||
-> ZcashWalletId -- ^ the wallet to search
|
|
||||||
-> IO [Entity WalletAddress]
|
|
||||||
getWalletAddresses dbFp w = do
|
|
||||||
accs <- getAccounts dbFp w
|
|
||||||
addrs <- mapM (getAddresses dbFp . entityKey) accs
|
|
||||||
return $ concat addrs
|
|
||||||
|
|
||||||
-- | Returns the largest address index for the given account
|
-- | Returns the largest address index for the given account
|
||||||
getMaxAddress ::
|
getMaxAddress ::
|
||||||
|
@ -288,13 +240,10 @@ getMaxAddress ::
|
||||||
-> IO Int
|
-> IO Int
|
||||||
getMaxAddress dbFp aw s = do
|
getMaxAddress dbFp aw s = do
|
||||||
a <-
|
a <-
|
||||||
PS.runSqlite dbFp $
|
runSqlite dbFp $
|
||||||
selectOne $ do
|
selectFirst
|
||||||
addrs <- from $ table @WalletAddress
|
[WalletAddressAccId ==. aw, WalletAddressScope ==. ScopeDB s]
|
||||||
where_ $ addrs ^. WalletAddressAccId ==. val aw
|
[Desc WalletAddressIndex]
|
||||||
where_ $ addrs ^. WalletAddressScope ==. val (ScopeDB s)
|
|
||||||
orderBy [desc $ addrs ^. WalletAddressIndex]
|
|
||||||
pure addrs
|
|
||||||
case a of
|
case a of
|
||||||
Nothing -> return $ -1
|
Nothing -> return $ -1
|
||||||
Just x -> return $ walletAddressIndex $ entityVal x
|
Just x -> return $ walletAddressIndex $ entityVal x
|
||||||
|
@ -304,7 +253,7 @@ saveAddress ::
|
||||||
T.Text -- ^ the database path
|
T.Text -- ^ the database path
|
||||||
-> WalletAddress -- ^ The wallet to add to the database
|
-> WalletAddress -- ^ The wallet to add to the database
|
||||||
-> IO (Maybe (Entity WalletAddress))
|
-> IO (Maybe (Entity WalletAddress))
|
||||||
saveAddress dbFp w = PS.runSqlite dbFp $ insertUniqueEntity w
|
saveAddress dbFp w = runSqlite dbFp $ insertUniqueEntity w
|
||||||
|
|
||||||
-- | Save a transaction to the data model
|
-- | Save a transaction to the data model
|
||||||
saveTransaction ::
|
saveTransaction ::
|
||||||
|
@ -313,50 +262,30 @@ saveTransaction ::
|
||||||
-> Transaction -- ^ The transaction to save
|
-> Transaction -- ^ The transaction to save
|
||||||
-> IO (Key ZcashTransaction)
|
-> IO (Key ZcashTransaction)
|
||||||
saveTransaction dbFp t wt =
|
saveTransaction dbFp t wt =
|
||||||
PS.runSqlite dbFp $ do
|
runSqlite dbFp $ do
|
||||||
let ix = [0 ..]
|
|
||||||
w <-
|
w <-
|
||||||
insert $
|
insert $
|
||||||
ZcashTransaction (tx_height wt) (HexStringDB $ tx_id wt) (tx_conf wt) t
|
ZcashTransaction (tx_height wt) (HexStringDB $ tx_id wt) (tx_conf wt) t
|
||||||
when (isJust $ tx_transpBundle wt) $ do
|
when (isJust $ tx_transpBundle wt) $
|
||||||
_ <-
|
|
||||||
insertMany_ $
|
insertMany_ $
|
||||||
zipWith (curry (storeTxOut w)) ix $
|
map (storeTxOut w) $ (tb_vout . fromJust . tx_transpBundle) wt
|
||||||
(tb_vout . fromJust . tx_transpBundle) wt
|
|
||||||
_ <-
|
|
||||||
insertMany_ $
|
|
||||||
zipWith (curry (storeTxIn w)) ix $
|
|
||||||
(tb_vin . fromJust . tx_transpBundle) wt
|
|
||||||
return ()
|
|
||||||
when (isJust $ tx_saplingBundle wt) $ do
|
when (isJust $ tx_saplingBundle wt) $ do
|
||||||
_ <-
|
_ <-
|
||||||
insertMany_ $
|
insertMany_ $
|
||||||
zipWith (curry (storeSapSpend w)) ix $
|
map (storeSapSpend w) $ (sbSpends . fromJust . tx_saplingBundle) wt
|
||||||
(sbSpends . fromJust . tx_saplingBundle) wt
|
|
||||||
_ <-
|
_ <-
|
||||||
insertMany_ $
|
insertMany_ $
|
||||||
zipWith (curry (storeSapOutput w)) ix $
|
map (storeSapOutput w) $ (sbOutputs . fromJust . tx_saplingBundle) wt
|
||||||
(sbOutputs . fromJust . tx_saplingBundle) wt
|
|
||||||
return ()
|
return ()
|
||||||
when (isJust $ tx_orchardBundle wt) $
|
when (isJust $ tx_orchardBundle wt) $
|
||||||
insertMany_ $
|
insertMany_ $
|
||||||
zipWith (curry (storeOrchAction w)) ix $
|
map (storeOrchAction w) $ (obActions . fromJust . tx_orchardBundle) wt
|
||||||
(obActions . fromJust . tx_orchardBundle) wt
|
|
||||||
return w
|
return w
|
||||||
where
|
where
|
||||||
storeTxOut :: ZcashTransactionId -> (Int, TxOut) -> TransparentNote
|
storeTxOut :: ZcashTransactionId -> TxOut -> TransparentNote
|
||||||
storeTxOut wid (i, TxOut v s) = TransparentNote wid (fromIntegral v) s i
|
storeTxOut wid (TxOut v s) = TransparentNote wid (fromIntegral v) s
|
||||||
storeTxIn :: ZcashTransactionId -> (Int, TxIn) -> TransparentSpend
|
storeSapSpend :: ZcashTransactionId -> ShieldedSpend -> ShieldSpend
|
||||||
storeTxIn wid (i, TxIn (OutPoint h k) s sq) =
|
storeSapSpend wid sp =
|
||||||
TransparentSpend
|
|
||||||
wid
|
|
||||||
(HexStringDB . fromText $ txHashToHex h)
|
|
||||||
(fromIntegral k)
|
|
||||||
s
|
|
||||||
(fromIntegral sq)
|
|
||||||
i
|
|
||||||
storeSapSpend :: ZcashTransactionId -> (Int, ShieldedSpend) -> ShieldSpend
|
|
||||||
storeSapSpend wid (i, sp) =
|
|
||||||
ShieldSpend
|
ShieldSpend
|
||||||
wid
|
wid
|
||||||
(HexStringDB $ sp_cv sp)
|
(HexStringDB $ sp_cv sp)
|
||||||
|
@ -365,10 +294,8 @@ saveTransaction dbFp t wt =
|
||||||
(HexStringDB $ sp_rk sp)
|
(HexStringDB $ sp_rk sp)
|
||||||
(HexStringDB $ sp_proof sp)
|
(HexStringDB $ sp_proof sp)
|
||||||
(HexStringDB $ sp_auth sp)
|
(HexStringDB $ sp_auth sp)
|
||||||
i
|
storeSapOutput :: ZcashTransactionId -> ShieldedOutput -> ShieldOutput
|
||||||
storeSapOutput ::
|
storeSapOutput wid so =
|
||||||
ZcashTransactionId -> (Int, ShieldedOutput) -> ShieldOutput
|
|
||||||
storeSapOutput wid (i, so) =
|
|
||||||
ShieldOutput
|
ShieldOutput
|
||||||
wid
|
wid
|
||||||
(HexStringDB $ s_cv so)
|
(HexStringDB $ s_cv so)
|
||||||
|
@ -377,9 +304,8 @@ saveTransaction dbFp t wt =
|
||||||
(HexStringDB $ s_encCipherText so)
|
(HexStringDB $ s_encCipherText so)
|
||||||
(HexStringDB $ s_outCipherText so)
|
(HexStringDB $ s_outCipherText so)
|
||||||
(HexStringDB $ s_proof so)
|
(HexStringDB $ s_proof so)
|
||||||
i
|
storeOrchAction :: ZcashTransactionId -> OrchardAction -> OrchAction
|
||||||
storeOrchAction :: ZcashTransactionId -> (Int, OrchardAction) -> OrchAction
|
storeOrchAction wid oa =
|
||||||
storeOrchAction wid (i, oa) =
|
|
||||||
OrchAction
|
OrchAction
|
||||||
wid
|
wid
|
||||||
(HexStringDB $ nf oa)
|
(HexStringDB $ nf oa)
|
||||||
|
@ -390,91 +316,3 @@ saveTransaction dbFp t wt =
|
||||||
(HexStringDB $ out_ciphertext oa)
|
(HexStringDB $ out_ciphertext oa)
|
||||||
(HexStringDB $ cv oa)
|
(HexStringDB $ cv oa)
|
||||||
(HexStringDB $ auth oa)
|
(HexStringDB $ auth oa)
|
||||||
i
|
|
||||||
|
|
||||||
-- | Get the transactions from a particular block forward
|
|
||||||
getZcashTransactions ::
|
|
||||||
T.Text -- ^ The database path
|
|
||||||
-> Int -- ^ Block
|
|
||||||
-> IO [Entity ZcashTransaction]
|
|
||||||
getZcashTransactions dbFp b =
|
|
||||||
PS.runSqlite dbFp $
|
|
||||||
select $ do
|
|
||||||
txs <- from $ table @ZcashTransaction
|
|
||||||
where_ $ txs ^. ZcashTransactionBlock >. val b
|
|
||||||
orderBy [asc $ txs ^. ZcashTransactionBlock]
|
|
||||||
return txs
|
|
||||||
|
|
||||||
-- * Wallet
|
|
||||||
-- | Get the block of the last transaction known to the wallet
|
|
||||||
getMaxWalletBlock ::
|
|
||||||
T.Text -- ^ The database path
|
|
||||||
-> IO Int
|
|
||||||
getMaxWalletBlock dbPath = do
|
|
||||||
b <-
|
|
||||||
PS.runSqlite dbPath $
|
|
||||||
selectOne $ do
|
|
||||||
txs <- from $ table @WalletTransaction
|
|
||||||
where_ $ txs ^. WalletTransactionBlock >. val 0
|
|
||||||
orderBy [desc $ txs ^. WalletTransactionBlock]
|
|
||||||
return txs
|
|
||||||
case b of
|
|
||||||
Nothing -> return $ -1
|
|
||||||
Just x -> return $ walletTransactionBlock $ entityVal x
|
|
||||||
|
|
||||||
-- | Find the Transparent Notes that match the given transparent receiver
|
|
||||||
findTransparentNotes ::
|
|
||||||
T.Text -- ^ The database path
|
|
||||||
-> Int -- ^ Starting block
|
|
||||||
-> WalletAddress
|
|
||||||
-> IO [(Entity ZcashTransaction, Entity TransparentNote)]
|
|
||||||
findTransparentNotes dbPath b t = do
|
|
||||||
let tReceiver = t_rec =<< readUnifiedAddressDB t
|
|
||||||
case tReceiver of
|
|
||||||
Just tR -> do
|
|
||||||
let s =
|
|
||||||
BS.concat
|
|
||||||
[ BS.pack [0x76, 0xA9, 0x14]
|
|
||||||
, (toBytes . ta_bytes) tR
|
|
||||||
, BS.pack [0x88, 0xAC]
|
|
||||||
]
|
|
||||||
PS.runSqlite dbPath $
|
|
||||||
select $ do
|
|
||||||
(txs :& tNotes) <-
|
|
||||||
from $ table @ZcashTransaction `innerJoin` table @TransparentNote `on`
|
|
||||||
(\(txs :& tNotes) ->
|
|
||||||
txs ^. ZcashTransactionId ==. tNotes ^. TransparentNoteTx)
|
|
||||||
where_ (txs ^. ZcashTransactionBlock >. val b)
|
|
||||||
where_ (tNotes ^. TransparentNoteScript ==. val s)
|
|
||||||
pure (txs, tNotes)
|
|
||||||
Nothing -> return []
|
|
||||||
|
|
||||||
-- | Add the transparent notes to the wallet
|
|
||||||
saveWalletTrNote ::
|
|
||||||
T.Text -- ^ the database path
|
|
||||||
-> (Entity ZcashTransaction, Entity TransparentNote)
|
|
||||||
-> WalletAddressId
|
|
||||||
-> IO ()
|
|
||||||
saveWalletTrNote dbPath (zt, tn) wa = do
|
|
||||||
let zT' = entityVal zt
|
|
||||||
PS.runSqlite dbPath $ do
|
|
||||||
t <-
|
|
||||||
upsert
|
|
||||||
(WalletTransaction
|
|
||||||
(zcashTransactionTxId zT')
|
|
||||||
(zcashTransactionBlock zT')
|
|
||||||
(zcashTransactionConf zT')
|
|
||||||
(zcashTransactionTime zT'))
|
|
||||||
[]
|
|
||||||
insert_ $
|
|
||||||
WalletTrNote
|
|
||||||
(entityKey t)
|
|
||||||
wa
|
|
||||||
(transparentNoteValue $ entityVal tn)
|
|
||||||
(entityKey tn)
|
|
||||||
False
|
|
||||||
|
|
||||||
-- | Helper function to extract a Unified Address from the database
|
|
||||||
readUnifiedAddressDB :: WalletAddress -> Maybe UnifiedAddress
|
|
||||||
readUnifiedAddressDB =
|
|
||||||
isValidUnifiedAddress . TE.encodeUtf8 . getUA . walletAddressUAddress
|
|
||||||
|
|
11
test/Spec.hs
11
test/Spec.hs
|
@ -4,7 +4,6 @@ import Control.Monad (when)
|
||||||
import Database.Persist
|
import Database.Persist
|
||||||
import Database.Persist.Sqlite
|
import Database.Persist.Sqlite
|
||||||
import System.Directory
|
import System.Directory
|
||||||
import Test.HUnit
|
|
||||||
import Test.Hspec
|
import Test.Hspec
|
||||||
import ZcashHaskell.Orchard (isValidUnifiedAddress)
|
import ZcashHaskell.Orchard (isValidUnifiedAddress)
|
||||||
import ZcashHaskell.Types
|
import ZcashHaskell.Types
|
||||||
|
@ -99,13 +98,3 @@ main = do
|
||||||
let ua =
|
let ua =
|
||||||
"utest1mvlny48qd4x94w8vz5u2lrxx0enuquajt72yekgq24p6pjaky3czk6m7x358h7g900ex6gzvdehaekl96qnakjzw8yaasp8y0u3j5jnlfd33trduznh6k3fcn5ek9qc857fgz8ehm37etx94sj58nrkc0k5hurxnuxpcpms3j8uy2t8kt2vy6vetvsfxxdhtjq0yqulqprvh7mf2u3x"
|
"utest1mvlny48qd4x94w8vz5u2lrxx0enuquajt72yekgq24p6pjaky3czk6m7x358h7g900ex6gzvdehaekl96qnakjzw8yaasp8y0u3j5jnlfd33trduznh6k3fcn5ek9qc857fgz8ehm37etx94sj58nrkc0k5hurxnuxpcpms3j8uy2t8kt2vy6vetvsfxxdhtjq0yqulqprvh7mf2u3x"
|
||||||
isValidUnifiedAddress ua `shouldNotBe` Nothing
|
isValidUnifiedAddress ua `shouldNotBe` Nothing
|
||||||
describe "Function tests" $ do
|
|
||||||
it "Wallet sync" $ do
|
|
||||||
w <-
|
|
||||||
runSqlite "zenith.db" $
|
|
||||||
selectFirst [ZcashWalletBirthdayHeight >. 0] []
|
|
||||||
case w of
|
|
||||||
Nothing -> assertFailure "No wallet in DB"
|
|
||||||
Just w' -> do
|
|
||||||
r <- syncWallet "zenith.db" w'
|
|
||||||
r `shouldBe` "Done"
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 2709d422667080527ccc180e97352693a4c6c2c7
|
Subproject commit 938ccb4b9730fd8615513eb27bdbffacd62e29cc
|
|
@ -39,12 +39,10 @@ library
|
||||||
Clipboard
|
Clipboard
|
||||||
, aeson
|
, aeson
|
||||||
, array
|
, array
|
||||||
, ascii-progress
|
|
||||||
, base >=4.12 && <5
|
, base >=4.12 && <5
|
||||||
, base64-bytestring
|
, base64-bytestring
|
||||||
, brick
|
, brick
|
||||||
, bytestring
|
, bytestring
|
||||||
, esqueleto
|
|
||||||
, ghc
|
, ghc
|
||||||
, haskoin-core
|
, haskoin-core
|
||||||
, hexstring
|
, hexstring
|
||||||
|
@ -67,6 +65,7 @@ library
|
||||||
, vector
|
, vector
|
||||||
, vty
|
, vty
|
||||||
, word-wrap
|
, word-wrap
|
||||||
|
, ascii-progress
|
||||||
, zcash-haskell
|
, zcash-haskell
|
||||||
--pkgconfig-depends: rustzcash_wrapper
|
--pkgconfig-depends: rustzcash_wrapper
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
@ -120,7 +119,6 @@ test-suite zenith-tests
|
||||||
, persistent
|
, persistent
|
||||||
, persistent-sqlite
|
, persistent-sqlite
|
||||||
, hspec
|
, hspec
|
||||||
, HUnit
|
|
||||||
, directory
|
, directory
|
||||||
, zcash-haskell
|
, zcash-haskell
|
||||||
, zenith
|
, zenith
|
||||||
|
|
Loading…
Reference in a new issue