Skip to content

Commit 3aa659c

Browse files
committed
Basic implementation of stake certificate API
1 parent 0ca3d5d commit 3aa659c

File tree

2 files changed

+158
-0
lines changed

2 files changed

+158
-0
lines changed

cardano-wasm/cardano-wasm.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ library cardano-wasi-lib
3030
src-lib
3131

3232
exposed-modules:
33+
Cardano.Wasm.Api.Certificate.StakeCertificate
3334
Cardano.Wasm.Api.GRPC
3435
Cardano.Wasm.Api.Info
3536
Cardano.Wasm.Api.InfoToTypeScript
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
{-# LANGUAGE ExistentialQuantification #-}
2+
{-# LANGUAGE GADTs #-}
3+
{-# LANGUAGE NamedFieldPuns #-}
4+
{-# LANGUAGE RankNTypes #-}
5+
{-# LANGUAGE ScopedTypeVariables #-}
6+
{-# LANGUAGE StandaloneDeriving #-}
7+
8+
module Cardano.Wasm.Api.Certificate.StakeCertificate
9+
( StakeCertificateObject (..)
10+
, createStakeKeyCertificate
11+
, asStakeRegistration
12+
, asStakeUnregistration
13+
, asDelegateOnly
14+
, withDeposit
15+
, withoutDeposit
16+
, withDelegation
17+
, withoutDelegation
18+
)
19+
where
20+
21+
import Cardano.Api (Coin, Hash, PoolId, StakeKey, ToJSON (..))
22+
import Cardano.Api.Experimental (Era (..), obtainCommonConstraints)
23+
import Cardano.Api.Experimental qualified as Exp
24+
import Cardano.Api.Serialise.Raw qualified as Api
25+
26+
import Cardano.Wasm.ExceptionHandling (rightOrError, throwError, toMonadFail)
27+
28+
import Data.Aeson (FromJSON, (.:), (.=))
29+
import Data.Aeson qualified as Aeson
30+
import Data.Text (Text)
31+
import Data.Text.Encoding qualified as Text
32+
33+
data StakeCertificateAction
34+
= RegisterStake
35+
| UnregisterStake
36+
| DelegateOnly
37+
deriving (Show, Eq)
38+
39+
data Delegation
40+
= NoDelegation
41+
| DelegateToPool PoolId
42+
-- ToDo: Add DRep delegation
43+
deriving (Show, Eq)
44+
45+
data StakeCertificateObject
46+
= forall era. StakeCertificateObject
47+
{ era :: !(Era era)
48+
, stakeCredential :: !(Hash StakeKey) -- ToDo: Generalize to support scripts as well
49+
, deposit :: !(Maybe Coin)
50+
, action :: !StakeCertificateAction
51+
, delegation :: Delegation
52+
}
53+
54+
deriving instance Show StakeCertificateObject
55+
56+
instance ToJSON StakeCertificateObject where
57+
toJSON (StakeCertificateObject{era, stakeCredential, deposit, action, delegation}) =
58+
obtainCommonConstraints era $
59+
Aeson.object
60+
[ "era" .= Exp.Some era
61+
, "stakeCredential" .= Text.decodeUtf8 (Api.serialiseToRawBytesHex stakeCredential)
62+
, "deposit" .= deposit
63+
, "action" .= case action of
64+
RegisterStake -> Aeson.String "RegisterStake"
65+
UnregisterStake -> Aeson.String "UnregisterStake"
66+
DelegateOnly -> Aeson.String "DelegateOnly"
67+
, "delegation" .= case delegation of
68+
NoDelegation -> Aeson.String "NoDelegation"
69+
DelegateToPool pid -> Aeson.object ["DelegateToPool" .= show pid]
70+
]
71+
72+
instance FromJSON StakeCertificateObject where
73+
parseJSON = Aeson.withObject "StakeCertificateObject" $ \o -> do
74+
Exp.Some era <- o .: "era"
75+
skHashText :: Text <- o .: "stakeCredential"
76+
stakeCredential :: Hash StakeKey <-
77+
toMonadFail $
78+
rightOrError $
79+
Api.deserialiseFromRawBytesHex (Text.encodeUtf8 skHashText)
80+
deposit :: Maybe Coin <- o .: "deposit"
81+
actionStr :: Text <- o .: "action"
82+
action <-
83+
case actionStr of
84+
"RegisterStake" -> return RegisterStake
85+
"UnregisterStake" -> return UnregisterStake
86+
"DelegateOnly" -> return DelegateOnly
87+
_ -> toMonadFail $ throwError ("Invalid action for StakeCertificateObject: " ++ show actionStr)
88+
delegationVal <- o .: "delegation"
89+
delegation <-
90+
case delegationVal of
91+
Aeson.String "NoDelegation" -> return NoDelegation
92+
Aeson.Object obj -> do
93+
pidStr :: Text <- obj .: "DelegateToPool"
94+
DelegateToPool
95+
<$> toMonadFail (rightOrError $ Api.deserialiseFromRawBytesHex $ Text.encodeUtf8 pidStr)
96+
_ ->
97+
toMonadFail $ throwError ("Invalid delegation for StakeCertificateObject: " ++ show delegationVal)
98+
obtainCommonConstraints era $
99+
return $
100+
StakeCertificateObject
101+
{ era
102+
, stakeCredential
103+
, deposit
104+
, action
105+
, delegation
106+
}
107+
108+
-- | Creates an empty stake certificate object for the given stake key hash.
109+
-- For the certificate to be valid must be either a registration, an unregistration or
110+
-- a delegation certificate. But it can be both registration and delegation.
111+
createStakeKeyCertificate :: Hash StakeKey -> StakeCertificateObject
112+
createStakeKeyCertificate skHash =
113+
StakeCertificateObject
114+
{ era = ConwayEra
115+
, stakeCredential = skHash
116+
, deposit = Nothing
117+
, action = DelegateOnly
118+
, delegation = NoDelegation
119+
}
120+
121+
-- | Marks the certificate as a stake registration certificate.
122+
asStakeRegistration :: StakeCertificateObject -> StakeCertificateObject
123+
asStakeRegistration certObj =
124+
certObj{action = RegisterStake}
125+
126+
-- | Marks the certificate as a stake un-registration certificate.
127+
asStakeUnregistration :: StakeCertificateObject -> StakeCertificateObject
128+
asStakeUnregistration certObj =
129+
certObj{action = UnregisterStake}
130+
131+
-- | Marks the certificate as a delegation-only certificate (not registration nor un-registration).
132+
asDelegateOnly :: StakeCertificateObject -> StakeCertificateObject
133+
asDelegateOnly certObj =
134+
certObj{action = DelegateOnly}
135+
136+
-- | Sets the deposit for the stake certificate. This only has effect for stake registration
137+
-- and unregistration certificates. The amount must match the expected deposit amount specified by
138+
-- 'ppKeyDepositL' in the protocol parameters for registration certificates and the amount
139+
-- depositted for unregistration certificates.
140+
withDeposit :: Coin -> StakeCertificateObject -> StakeCertificateObject
141+
withDeposit dep certObj =
142+
certObj{deposit = Just dep}
143+
144+
-- | Resets the deposit for the stake certificate.
145+
withoutDeposit :: StakeCertificateObject -> StakeCertificateObject
146+
withoutDeposit certObj =
147+
certObj{deposit = Nothing}
148+
149+
-- | Sets the pool to which the stake key will be delegated.
150+
withDelegation :: PoolId -> StakeCertificateObject -> StakeCertificateObject
151+
withDelegation poolId certObj =
152+
certObj{delegation = DelegateToPool poolId}
153+
154+
-- | Resets the delegation for the stake certificate.
155+
withoutDelegation :: StakeCertificateObject -> StakeCertificateObject
156+
withoutDelegation certObj =
157+
certObj{delegation = NoDelegation}

0 commit comments

Comments
 (0)