|
| 1 | +{-# LANGUAGE NamedFieldPuns #-} |
| 2 | + |
| 3 | +-- | |
| 4 | +-- Copyright: © 2024 Cardano Foundation |
| 5 | +-- License: Apache-2.0 |
| 6 | +-- |
| 7 | +module Cardano.Wallet.Deposit.IO.Address.Store |
| 8 | + ( mkStoreAddressState |
| 9 | + ) |
| 10 | + where |
| 11 | + |
| 12 | +import Prelude |
| 13 | + |
| 14 | +import Cardano.Wallet.Deposit.Pure |
| 15 | + ( Customer |
| 16 | + ) |
| 17 | +import Cardano.Wallet.Deposit.Pure.Address |
| 18 | + ( AddressState (..) |
| 19 | + ) |
| 20 | +import Control.Exception |
| 21 | + ( Exception |
| 22 | + , SomeException (SomeException) |
| 23 | + ) |
| 24 | +import Data.Delta |
| 25 | + ( Delta (..) |
| 26 | + ) |
| 27 | +import Data.Store |
| 28 | + ( UpdateStore |
| 29 | + , mkUpdateStore |
| 30 | + , updateLoad |
| 31 | + ) |
| 32 | +import Database.Table |
| 33 | + ( Col (..) |
| 34 | + , Row |
| 35 | + , Table |
| 36 | + , (:.) |
| 37 | + ) |
| 38 | + |
| 39 | +import qualified Cardano.Wallet.Deposit.Read as Read |
| 40 | +import qualified Data.Map.Strict as Map |
| 41 | +import qualified Database.SQLite.Simple as Sqlite |
| 42 | +import qualified Database.Table.SQLite.Simple as Sql |
| 43 | + |
| 44 | +{----------------------------------------------------------------------------- |
| 45 | + Delta type |
| 46 | + TODO: move out |
| 47 | +------------------------------------------------------------------------------} |
| 48 | + |
| 49 | +data DeltaAddressState |
| 50 | + = InsertAddressCustomer Read.Address Customer |
| 51 | + |
| 52 | +instance Delta DeltaAddressState where |
| 53 | + type Base DeltaAddressState = AddressState |
| 54 | + apply (DeltaAddressState addr c) s@AddressStateC{addresses} |
| 55 | + = s {addresses = Map.insert addr c addresses} |
| 56 | + |
| 57 | +{----------------------------------------------------------------------------- |
| 58 | + Database schema |
| 59 | +------------------------------------------------------------------------------} |
| 60 | + |
| 61 | +type TableAddressesMap = |
| 62 | + Table "deposit_addresses" |
| 63 | + :. Col "address" Address |
| 64 | + :. Col "customer" Customer |
| 65 | + |
| 66 | +tableAddressesMap :: Proxy TableAddressesMap |
| 67 | +tableAddressesMap = Proxy |
| 68 | + |
| 69 | +type TableAddressState = |
| 70 | + Table "deposit_xpub_change" |
| 71 | + :. Col "xpub" XPub |
| 72 | + :. Col "change" Address |
| 73 | + |
| 74 | +tableAddressState :: Proxy TableAddressState |
| 75 | +tableAddressState = Proxy |
| 76 | + |
| 77 | +{----------------------------------------------------------------------------- |
| 78 | + Store |
| 79 | +------------------------------------------------------------------------------} |
| 80 | + |
| 81 | +mkStoreAddressState :: UpdateStore Sql.SqlM DeltaAddressState |
| 82 | +mkStoreAddressState = mkUpdateStore loadS' writeS' updateS' |
| 83 | + |
| 84 | +data ErrStoreAddressState |
| 85 | + = ErrTableAddressState |
| 86 | + deriving Show |
| 87 | + |
| 88 | +instance Exception ErrStoreAddressState |
| 89 | + |
| 90 | +loadS' :: Sql.SqlM (Either SomeException AddressState) |
| 91 | +loadS' = do |
| 92 | + -- TODO: use `catch` or some form of wrapping the exception |
| 93 | + addresses <- Map.fromList $ Sql.selectAll tableAddressesMap |
| 94 | + [(stateXPub, change)] <- Sql.selectAll tableAddressState |
| 95 | + pure $ AddressStateC{addresses, stateXPub, change} |
| 96 | + |
| 97 | +writeS' :: AddressState -> Sql.SqlM () |
| 98 | +writeS' AddressStateC{addresses,stateXPub,change} = do |
| 99 | + Sql.deleteAll tableAddressesMap |
| 100 | + Sql.insertMany (Map.toList addresses) tableAddressesMap |
| 101 | + Sql.deleteAll tableAddressState |
| 102 | + Sql.insertOne (stateXPub, change) tableAddressState |
| 103 | + |
| 104 | +updateS' |
| 105 | + :: Maybe AddressState |
| 106 | + -> DeltaAddressState |
| 107 | + -> Sql.SqlM () |
| 108 | +updateS' _ (InsertAddressCustomer addr customer) = |
| 109 | + Sql.insertOne (addr, customer) tableAddressesMap |
0 commit comments