|
| 1 | +{-# LANGUAGE DeriveGeneric #-} |
| 2 | +{-# LANGUAGE OverloadedStrings #-} |
| 3 | +{-# LANGUAGE TypeFamilies #-} |
| 4 | + |
| 5 | +module Cardano.Db.Schema.Core.StakeDelegation where |
| 6 | + |
| 7 | +import Contravariant.Extras (contrazip4, contrazip5) |
| 8 | +import Data.ByteString.Char8 (ByteString) |
| 9 | +import Data.Functor.Contravariant |
| 10 | +import Data.Text (Text) |
| 11 | +import Data.Word (Word16, Word64) |
| 12 | +import GHC.Generics (Generic) |
| 13 | +import Hasql.Decoders as D |
| 14 | +import Hasql.Encoders as E |
| 15 | + |
| 16 | +import Cardano.Db.Schema.Ids |
| 17 | +import Cardano.Db.Schema.Types (textDecoder) |
| 18 | +import Cardano.Db.Statement.Function.Core (bulkEncoder) |
| 19 | +import Cardano.Db.Statement.Types (DbInfo (..), Key) |
| 20 | +import Cardano.Db.Types ( |
| 21 | + DbLovelace (..), |
| 22 | + RewardSource, |
| 23 | + maybeDbLovelaceEncoder, |
| 24 | + rewardSourceEncoder, |
| 25 | + ) |
| 26 | + |
| 27 | +----------------------------------------------------------------------------------------------------------------------------------- |
| 28 | + |
| 29 | +-- | STAKE DELEGATION |
| 30 | +-- | These tables handle stake addresses, delegation, and reward |
| 31 | + |
| 32 | +----------------------------------------------------------------------------------------------------------------------------------- |
| 33 | + |
| 34 | +-- | |
| 35 | +-- Table Name: stake_address |
| 36 | +-- Description: Contains information about stakeholder addresses. |
| 37 | +data StakeAddress = StakeAddress -- Can be an address of a script hash |
| 38 | + { stakeAddressHashRaw :: !ByteString -- sqltype=addr29type |
| 39 | + , stakeAddressView :: !Text |
| 40 | + , stakeAddressScriptHash :: !(Maybe ByteString) -- sqltype=hash28type |
| 41 | + } |
| 42 | + deriving (Show, Eq, Generic) |
| 43 | + |
| 44 | +type instance Key StakeAddress = StakeAddressId |
| 45 | +instance DbInfo StakeAddress where |
| 46 | + uniqueFields _ = ["hash_raw"] |
| 47 | + |
| 48 | +stakeAddressDecoder :: D.Row StakeAddress |
| 49 | +stakeAddressDecoder = |
| 50 | + StakeAddress |
| 51 | + <$> D.column (D.nonNullable D.bytea) -- stakeAddressHashRaw |
| 52 | + <*> D.column (D.nonNullable textDecoder) -- stakeAddressView |
| 53 | + <*> D.column (D.nullable D.bytea) -- stakeAddressScriptHash |
| 54 | + |
| 55 | +stakeAddressEncoder :: E.Params StakeAddress |
| 56 | +stakeAddressEncoder = |
| 57 | + mconcat |
| 58 | + [ stakeAddressHashRaw >$< E.param (E.nonNullable E.bytea) |
| 59 | + , stakeAddressView >$< E.param (E.nonNullable E.text) |
| 60 | + , stakeAddressScriptHash >$< E.param (E.nullable E.bytea) |
| 61 | + ] |
| 62 | + |
| 63 | +----------------------------------------------------------------------------------------------------------------------------------- |
| 64 | + |
| 65 | +-- | |
| 66 | +-- Table Name: stake_registration |
| 67 | +-- Description: Contains information about stakeholder registrations. |
| 68 | +data StakeRegistration = StakeRegistration |
| 69 | + { stakeRegistrationAddrId :: !StakeAddressId -- noreference |
| 70 | + , stakeRegistrationCertIndex :: !Word16 |
| 71 | + , stakeRegistrationEpochNo :: !Word64 -- sqltype=word31type |
| 72 | + , stakeRegistrationTxId :: !TxId -- noreference |
| 73 | + , stakeRegistrationDeposit :: !(Maybe DbLovelace) -- sqltype=lovelace |
| 74 | + } |
| 75 | + deriving (Eq, Show, Generic) |
| 76 | + |
| 77 | +type instance Key StakeRegistration = StakeRegistrationId |
| 78 | +instance DbInfo StakeRegistration |
| 79 | + |
| 80 | +stakeRegistrationEncoder :: E.Params StakeRegistration |
| 81 | +stakeRegistrationEncoder = |
| 82 | + mconcat |
| 83 | + [ stakeRegistrationAddrId >$< idEncoder getStakeAddressId |
| 84 | + , stakeRegistrationCertIndex >$< E.param (E.nonNullable $ fromIntegral >$< E.int2) |
| 85 | + , stakeRegistrationEpochNo >$< E.param (E.nonNullable $ fromIntegral >$< E.int8) |
| 86 | + , stakeRegistrationTxId >$< idEncoder getTxId |
| 87 | + , stakeRegistrationDeposit >$< maybeDbLovelaceEncoder |
| 88 | + ] |
| 89 | + |
| 90 | +----------------------------------------------------------------------------------------------------------------------------------- |
| 91 | + |
| 92 | +-- | |
| 93 | +-- Table Name: stake_deregistration |
| 94 | +-- Description: Contains information about stakeholder deregistrations. |
| 95 | +data StakeDeregistration = StakeDeregistration |
| 96 | + { stakeDeregistrationAddrId :: !StakeAddressId -- noreference |
| 97 | + , stakeDeregistrationCertIndex :: !Word16 |
| 98 | + , stakeDeregistrationEpochNo :: !Word64 -- sqltype=word31type |
| 99 | + , stakeDeregistrationTxId :: !TxId -- noreference |
| 100 | + , stakeDeregistrationRedeemerId :: !(Maybe RedeemerId) -- noreference |
| 101 | + } |
| 102 | + deriving (Eq, Show, Generic) |
| 103 | + |
| 104 | +type instance Key StakeDeregistration = StakeDeregistrationId |
| 105 | +instance DbInfo StakeDeregistration |
| 106 | + |
| 107 | +stakeDeregistrationDecoder :: D.Row StakeDeregistration |
| 108 | +stakeDeregistrationDecoder = |
| 109 | + StakeDeregistration |
| 110 | + <$> idDecoder StakeAddressId -- stakeDeregistrationAddrId |
| 111 | + <*> D.column (D.nonNullable $ fromIntegral <$> D.int2) -- stakeDeregistrationCertIndex |
| 112 | + <*> D.column (D.nonNullable $ fromIntegral <$> D.int8) -- stakeDeregistrationEpochNo |
| 113 | + <*> idDecoder TxId -- stakeDeregistrationTxId |
| 114 | + <*> maybeIdDecoder RedeemerId -- stakeDeregistrationRedeemerId |
| 115 | + |
| 116 | +stakeDeregistrationEncoder :: E.Params StakeDeregistration |
| 117 | +stakeDeregistrationEncoder = |
| 118 | + mconcat |
| 119 | + [ stakeDeregistrationAddrId >$< idEncoder getStakeAddressId |
| 120 | + , stakeDeregistrationCertIndex >$< E.param (E.nonNullable $ fromIntegral >$< E.int2) |
| 121 | + , stakeDeregistrationEpochNo >$< E.param (E.nonNullable $ fromIntegral >$< E.int8) |
| 122 | + , stakeDeregistrationTxId >$< idEncoder getTxId |
| 123 | + , stakeDeregistrationRedeemerId >$< maybeIdEncoder getRedeemerId |
| 124 | + ] |
| 125 | + |
| 126 | +----------------------------------------------------------------------------------------------------------------------------------- |
| 127 | + |
| 128 | +-- | |
| 129 | +-- Table Name: delegation |
| 130 | +-- Description:Contains information about stakeholder delegations, including the stakeholder's address and the pool to which they are delegating. |
| 131 | +data Delegation = Delegation |
| 132 | + { delegationAddrId :: !StakeAddressId -- noreference |
| 133 | + , delegationCertIndex :: !Word16 |
| 134 | + , delegationPoolHashId :: !PoolHashId -- noreference |
| 135 | + , delegationActiveEpochNo :: !Word64 |
| 136 | + , delegationTxId :: !TxId -- noreference |
| 137 | + , delegationSlotNo :: !Word64 -- sqltype=word63type |
| 138 | + , delegationRedeemerId :: !(Maybe RedeemerId) -- noreference |
| 139 | + } |
| 140 | + deriving (Eq, Show, Generic) |
| 141 | + |
| 142 | +type instance Key Delegation = DelegationId |
| 143 | +instance DbInfo Delegation |
| 144 | + |
| 145 | +delegationDecoder :: D.Row Delegation |
| 146 | +delegationDecoder = |
| 147 | + Delegation |
| 148 | + <$> idDecoder StakeAddressId -- delegationAddrId |
| 149 | + <*> D.column (D.nonNullable $ fromIntegral <$> D.int2) -- delegationCertIndex |
| 150 | + <*> idDecoder PoolHashId -- delegationPoolHashId |
| 151 | + <*> D.column (D.nonNullable $ fromIntegral <$> D.int8) -- delegationActiveEpochNo |
| 152 | + <*> idDecoder TxId -- delegationTxId |
| 153 | + <*> D.column (D.nonNullable $ fromIntegral <$> D.int8) -- delegationSlotNo |
| 154 | + <*> maybeIdDecoder RedeemerId -- delegationRedeemerId |
| 155 | + |
| 156 | +delegationEncoder :: E.Params Delegation |
| 157 | +delegationEncoder = |
| 158 | + mconcat |
| 159 | + [ delegationAddrId >$< idEncoder getStakeAddressId |
| 160 | + , delegationCertIndex >$< E.param (E.nonNullable $ fromIntegral >$< E.int2) |
| 161 | + , delegationPoolHashId >$< idEncoder getPoolHashId |
| 162 | + , delegationActiveEpochNo >$< E.param (E.nonNullable $ fromIntegral >$< E.int8) |
| 163 | + , delegationTxId >$< idEncoder getTxId |
| 164 | + , delegationSlotNo >$< E.param (E.nonNullable $ fromIntegral >$< E.int8) |
| 165 | + , delegationRedeemerId >$< maybeIdEncoder getRedeemerId |
| 166 | + ] |
| 167 | + |
| 168 | +----------------------------------------------------------------------------------------------------------------------------------- |
| 169 | + |
| 170 | +-- | |
| 171 | +-- Table Name: reward |
| 172 | +-- Description: Reward, Stake and Treasury need to be obtained from the ledger state. |
| 173 | +-- The reward for each stake address and. This is not a balance, but a reward amount and the |
| 174 | +-- epoch in which the reward was earned. |
| 175 | +-- This table should never get rolled back. |
| 176 | +data Reward = Reward |
| 177 | + { rewardAddrId :: !StakeAddressId -- noreference |
| 178 | + , rewardType :: !RewardSource -- sqltype=rewardtype |
| 179 | + , rewardAmount :: !DbLovelace -- sqltype=lovelace |
| 180 | + , rewardSpendableEpoch :: !Word64 |
| 181 | + , rewardPoolId :: !PoolHashId -- noreference |
| 182 | + , rewardEarnedEpoch :: !Word64 -- generated="((CASE WHEN (type='refund') then spendable_epoch else (CASE WHEN spendable_epoch >= 2 then spendable_epoch-2 else 0 end) end) STORED)" |
| 183 | + } |
| 184 | + deriving (Show, Eq, Generic) |
| 185 | + |
| 186 | +type instance Key Reward = RewardId |
| 187 | + |
| 188 | +instance DbInfo Reward where |
| 189 | + enumFields _ = [("type", "rewardtype"), ("amount", "lovelace")] |
| 190 | + generatedFields _ = ["earned_epoch"] |
| 191 | + unnestParamTypes _ = [("addr_id", "bigint[]"), ("type", "text[]"), ("amount", "bigint[]"), ("spendable_epoch", "bigint[]"), ("pool_id", "bigint[]")] |
| 192 | + |
| 193 | +rewardBulkEncoder :: E.Params ([StakeAddressId], [RewardSource], [DbLovelace], [Word64], [PoolHashId]) |
| 194 | +rewardBulkEncoder = |
| 195 | + contrazip5 |
| 196 | + (bulkEncoder $ idBulkEncoder getStakeAddressId) |
| 197 | + (bulkEncoder $ E.nonNullable rewardSourceEncoder) |
| 198 | + (bulkEncoder $ E.nonNullable $ fromIntegral . unDbLovelace >$< E.int8) |
| 199 | + (bulkEncoder $ E.nonNullable $ fromIntegral >$< E.int8) |
| 200 | + (bulkEncoder $ idBulkEncoder getPoolHashId) |
| 201 | + |
| 202 | +----------------------------------------------------------------------------------------------------------------------------------- |
| 203 | + |
| 204 | +-- | |
| 205 | +-- Table Name: reward_rest |
| 206 | +-- Description: Contains information about the remaining reward for each stakeholder. |
| 207 | +data RewardRest = RewardRest |
| 208 | + { rewardRestAddrId :: !StakeAddressId -- noreference |
| 209 | + , rewardRestType :: !RewardSource -- sqltype=rewardtype |
| 210 | + , rewardRestAmount :: !DbLovelace -- sqltype=lovelace |
| 211 | + , rewardRestSpendableEpoch :: !Word64 |
| 212 | + , rewardRestEarnedEpoch :: !Word64 -- generated="(CASE WHEN spendable_epoch >= 1 then spendable_epoch-1 else 0 end)" |
| 213 | + } |
| 214 | + deriving (Show, Eq, Generic) |
| 215 | + |
| 216 | +type instance Key RewardRest = RewardRestId |
| 217 | + |
| 218 | +instance DbInfo RewardRest where |
| 219 | + enumFields _ = [("type", "rewardtype"), ("amount", "lovelace")] |
| 220 | + generatedFields _ = ["earned_epoch"] |
| 221 | + unnestParamTypes _ = |
| 222 | + [ ("addr_id", "bigint[]") |
| 223 | + , ("type", "text[]") |
| 224 | + , ("amount", "bigint[]") |
| 225 | + , ("spendable_epoch", "bigint[]") |
| 226 | + ] |
| 227 | + |
| 228 | +rewardRestBulkEncoder :: E.Params ([StakeAddressId], [RewardSource], [DbLovelace], [Word64]) |
| 229 | +rewardRestBulkEncoder = |
| 230 | + contrazip4 |
| 231 | + (bulkEncoder $ idBulkEncoder getStakeAddressId) |
| 232 | + (bulkEncoder $ E.nonNullable rewardSourceEncoder) |
| 233 | + (bulkEncoder $ E.nonNullable $ fromIntegral . unDbLovelace >$< E.int8) |
| 234 | + (bulkEncoder $ E.nonNullable $ fromIntegral >$< E.int8) |
| 235 | + |
| 236 | +----------------------------------------------------------------------------------------------------------------------------------- |
| 237 | + |
| 238 | +-- | |
| 239 | +-- Table Name: epoch_stake |
| 240 | +-- Description: Contains information about the stake of each stakeholder in each epoch. |
| 241 | +-- This table should never get rolled back |
| 242 | +data EpochStake = EpochStake |
| 243 | + { epochStakeAddrId :: !StakeAddressId -- noreference |
| 244 | + , epochStakePoolId :: !PoolHashId -- noreference |
| 245 | + , epochStakeAmount :: !DbLovelace -- sqltype=lovelace |
| 246 | + , epochStakeEpochNo :: !Word64 -- sqltype=word31type |
| 247 | + } |
| 248 | + deriving (Show, Eq, Generic) |
| 249 | + |
| 250 | +-- similar scenario as in Reward the constraint that was here is now set manually in |
| 251 | +-- `applyAndInsertBlockMaybe` at a more optimal time. |
| 252 | + |
| 253 | +type instance Key EpochStake = EpochStakeId |
| 254 | + |
| 255 | +instance DbInfo EpochStake where |
| 256 | + uniqueFields _ = ["addr_id", "pool_id", "epoch_no"] |
| 257 | + unnestParamTypes _ = |
| 258 | + [ ("addr_id", "bigint[]") |
| 259 | + , ("pool_id", "bigint[]") |
| 260 | + , ("amount", "bigint[]") |
| 261 | + , ("epoch_no", "bigint[]") |
| 262 | + ] |
| 263 | + |
| 264 | +epochStakeBulkEncoder :: E.Params ([StakeAddressId], [PoolHashId], [DbLovelace], [Word64]) |
| 265 | +epochStakeBulkEncoder = |
| 266 | + contrazip4 |
| 267 | + (bulkEncoder $ idBulkEncoder getStakeAddressId) |
| 268 | + (bulkEncoder $ idBulkEncoder getPoolHashId) |
| 269 | + (bulkEncoder $ E.nonNullable $ fromIntegral . unDbLovelace >$< E.int8) |
| 270 | + (bulkEncoder $ E.nonNullable $ fromIntegral >$< E.int8) |
| 271 | + |
| 272 | +----------------------------------------------------------------------------------------------------------------------------------- |
| 273 | + |
| 274 | +-- | |
| 275 | +-- Table Name: epoch_stake_progress |
| 276 | +-- Description: Contains information about the progress of the epoch stake calculation. |
| 277 | +data EpochStakeProgress = EpochStakeProgress |
| 278 | + { epochStakeProgressEpochNo :: !Word64 -- sqltype=word31type |
| 279 | + , epochStakeProgressCompleted :: !Bool |
| 280 | + } |
| 281 | + deriving (Show, Eq, Generic) |
| 282 | + |
| 283 | +type instance Key EpochStakeProgress = EpochStakeProgressId |
| 284 | + |
| 285 | +instance DbInfo EpochStakeProgress where |
| 286 | + uniqueFields _ = ["epoch_no"] |
| 287 | + unnestParamTypes _ = |
| 288 | + [ ("epoch_no", "bigint[]") |
| 289 | + , ("completed", "boolean[]") |
| 290 | + ] |
0 commit comments