Safe Haskell | None |
---|---|
Language | Haskell2010 |
This module contains a type family for converting a type to its RPC representation, and TemplateHaskell functions for deriving RPC representations for custom types.
Synopsis
- type family TAsRPC t where ...
- class TAsRPC (ToT t) ~ ToT (AsRPC t) => HasRPCRepr (t :: Type) where
- data MaybeRPC v where
- deriveRPC :: String -> Q [Dec]
- deriveRPCWithStrategy :: String -> GenericStrategy -> Q [Dec]
- deriveManyRPC :: String -> [String] -> Q [Dec]
- deriveManyRPCWithStrategy :: String -> [String] -> GenericStrategy -> Q [Dec]
- valueAsRPC :: HasCallStack => Value t -> Value (TAsRPC t)
- replaceBigMapIds :: forall t m. Monad m => (forall k v. (SingI k, SingI v) => Natural -> m (Value ('TBigMap k v))) -> Sing t -> Value (TAsRPC t) -> m (Value t)
- notesAsRPC :: Notes t -> Notes (TAsRPC t)
- rpcSingIEvi :: forall (t :: T). SingI t :- SingI (TAsRPC t)
- rpcHasNoOpEvi :: forall (t :: T). (SingI t, HasNoOp t) => HasNoOp t :- HasNoOp (TAsRPC t)
- rpcHasNoBigMapEvi :: forall (t :: T). SingI t => Dict (HasNoBigMap (TAsRPC t))
- rpcHasNoNestedBigMapsEvi :: forall (t :: T). SingI t => Dict (HasNoNestedBigMaps (TAsRPC t))
- rpcHasNoContractEvi :: forall (t :: T). (SingI t, HasNoContract t) => HasNoContract t :- HasNoContract (TAsRPC t)
- rpcStorageScopeEvi :: forall (t :: T). StorageScope t :- StorageScope (TAsRPC t)
Documentation
type family TAsRPC t where ... Source #
A type-level function that maps a Michelson type to its Tezos RPC representation.
For example, when we retrieve a contract's storage using the Tezos RPC,
all its big_map
s will be replaced by nat
, representing a big_map ID.
>>>
:k! TAsRPC ('TBigMap 'TInt 'TString)
... = 'TNat
>>>
:k! TAsRPC ('TList ('TBigMap 'TInt 'TString))
... = 'TList 'TNat
>>>
:k! TAsRPC ('TPair 'TString ('TPair 'TAddress ('TBigMap 'TInt 'TString)))
... = 'TPair 'TString ('TPair 'TAddress 'TNat)
NB: As far as we are aware, details of RPC representation of Michelson
types are not documented. We know empirically that big_map
s are
represented as their ids, and are the only type with an explicitly
different representation.
Whether TAsRPC
needs to propagate into type parameters then depends on
whether a value can hold big_map values.
- Values of type
option a
,list a
,pair a b
, andor a b
can contain big_map values, so their RPC representations areoption (TAsRPC a)
,list (TAsRPC a)
,pair (TAsRPC a) (TAsRPC b)
andor (TAsRPC a) (TAsRPC b)
. - The keys of a
map k v
cannot be big_maps, but the values can, so its RPC representation ismap k (TAsRPC v)
. - Values of type
set a
cannot contain big_maps, so its RPC representation is justset a
. - Values of type
contract a
cannot contain big_maps either, because it's just a wrapper for an address and an entrypoint name, so its RPC representation is justcontract a
. The same reasoning applies toticket a
andlambda a b
.
class TAsRPC (ToT t) ~ ToT (AsRPC t) => HasRPCRepr (t :: Type) Source #
A type-level function that maps a type to its Tezos RPC representation.
For example, when we retrieve a contract's storage using the Tezos RPC, all its BigMap
s will be replaced
by BigMapId
s.
So if a contract has a storage of type T
, when we call the Tezos RPC
to retrieve it, we must deserialize the micheline expression to the type AsRPC T
.
AsRPC (BigMap Integer MText) ~ BigMapId Integer MText AsRPC [BigMap Integer MText] ~ [BigMapId Integer MText] AsRPC (MText, (Address, BigMap Integer MText)) ~ (MText, (Address, BigMapId Integer MText))
The following law must hold:
TAsRPC (ToT t) ~ ToT (AsRPC t)
In other words, ToT
and AsRPC
/TAsRPC
must be commutative.
Storage ----------(applying ToT)-------------> ToT Storage | | | | | | (applying AsRPC) (applying TAsRPC) | | | | | | | V | TAsRPC (ToT Storage) V ~ AsRPC Storage ------(applying ToT)-----------> ToT (AsRPC Storage)
This law ensures that we can go from some type Storage
to AsRPC Storage
by
composing fromVal . valueAsRPC . toVal
.
Storage ------------(toVal)--------------> Value (ToT Storage) | | | | | | (fromVal . valueAsRPC . toVal) (valueAsRPC) | | | | | | | V | Value (TAsRPC (ToT Storage)) V ~ AsRPC Storage <--------(fromVal)--------- Value (ToT (AsRPC Storage))
Instances
data MaybeRPC v where Source #
Represents a value that may or may not be in its RPC representation.
>>>
:t NotRPC @(BigMap Integer MText) (mkBigMap @[(Integer, MText)] [])
... :: MaybeRPC (BigMap Integer MText)
>>>
:t IsRPC @(BigMap Integer MText) (BigMapId 1)
... :: MaybeRPC (BigMap Integer MText)
NotRPC :: IsoValue v => v -> MaybeRPC v | |
IsRPC :: (SingI (ToT v), IsoValue (AsRPC v), HasRPCRepr v) => AsRPC v -> MaybeRPC v |
Instances
HasNoOp (ToT v) => ToExpression (MaybeRPC v) Source # | |
Defined in Morley.AsRPC toExpression :: MaybeRPC v -> Expression Source # |
deriveRPC :: String -> Q [Dec] Source #
Derive an RPC representation for a type, as well as instances for Generic
, IsoValue
and HasRPCRepr
.
data ExampleStorage a b = ExampleStorage { esField1 :: Integer , esField2 :: [BigMap Integer MText] , esField3 :: a } deriving stock Generic deriving anyclass IsoValue deriveRPC "ExampleStorage"
Will generate:
data ExampleStorageRPC a b = ExampleStorageRPC { esField1RPC :: AsRPC Integer , esField2RPC :: AsRPC [BigMap Integer MText] , esField3RPC :: AsRPC a } instance HasRPCRepr a => HasRPCRepr (ExampleStorage a b) where type AsRPC (ExampleStorage a b) = ExampleStorageRPC a b deriving anyclass instance (IsoValue (AsRPC a), IsoValue (AsRPC b)) => IsoValue (ExampleStorageRPC a b) instance Generic (ExampleStorageRPC a b) where ...
deriveRPCWithStrategy :: String -> GenericStrategy -> Q [Dec] Source #
deriveManyRPC :: String -> [String] -> Q [Dec] Source #
Recursively enumerate data
, newtype
and type
declarations,
and derives an RPC representation for each type that doesn't yet have one.
You can also pass in a list of types for which you _don't_ want an RPC representation to be derived.
In this example, deriveManyRPC
will generate an RPC
representation for A
and B
,
but not for C
(because we explicitly said we don't want one)
or D
(because it already has one).
data B = B data C = C data D = D deriveRPC "D" data A = A B C D deriveManyRPC "A" ["C"]
deriveManyRPCWithStrategy :: String -> [String] -> GenericStrategy -> Q [Dec] Source #
Same as deriveManyRPC
, but uses a custom strategy for deriving a Generic
instance.
Conversions
valueAsRPC :: HasCallStack => Value t -> Value (TAsRPC t) Source #
Replace all big_maps in a value with the respective big_map IDs.
Throws an error if it finds a big_map without an ID.
:: forall t m. Monad m | |
=> (forall k v. (SingI k, SingI v) => Natural -> m (Value ('TBigMap k v))) | A function for looking up a bigmap using its ID. |
-> Sing t | |
-> Value (TAsRPC t) | |
-> m (Value t) |
Replaces all bigmap IDs with their corresponding bigmap values.
This is the inverse of valueAsRPC
.
notesAsRPC :: Notes t -> Notes (TAsRPC t) Source #
Replace all big_map
annotations in a value with nat
annotations.
Entailments
rpcSingIEvi :: forall (t :: T). SingI t :- SingI (TAsRPC t) Source #
A proof that if a singleton exists for t
,
then so it does for TAsRPC t
.
rpcHasNoOpEvi :: forall (t :: T). (SingI t, HasNoOp t) => HasNoOp t :- HasNoOp (TAsRPC t) Source #
A proof that if t
does not contain any operations, then neither does TAsRPC t
.
rpcHasNoBigMapEvi :: forall (t :: T). SingI t => Dict (HasNoBigMap (TAsRPC t)) Source #
A proof that AsRPC (Value t)
does not contain big_maps.
rpcHasNoNestedBigMapsEvi :: forall (t :: T). SingI t => Dict (HasNoNestedBigMaps (TAsRPC t)) Source #
A proof that AsRPC (Value t)
does not contain big_maps.
rpcHasNoContractEvi :: forall (t :: T). (SingI t, HasNoContract t) => HasNoContract t :- HasNoContract (TAsRPC t) Source #
A proof that if t
does not contain any contract values, then neither does TAsRPC t
.
rpcStorageScopeEvi :: forall (t :: T). StorageScope t :- StorageScope (TAsRPC t) Source #
A proof that if t
is a valid storage type, then so is TAsRPC t
.