Safe Haskell | Safe-Inferred |
---|---|
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
- deriveRPCWithOptions :: String -> DeriveRPCOptions -> Q [Dec]
- data DeriveRPCOptions = DeriveRPCOptions {}
- 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
deriveRPCWithOptions :: String -> DeriveRPCOptions -> Q [Dec] Source #
Derive an RPC representation for a type, as well as instances for
Generic
, IsoValue
, HasRPCRepr
and optionally HasAnnotation
.
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 ...
When droHasAnnotation
is True
, it will also generate a HasAnnotation
(from
Lorentz
) instance like:
instance With [HasAnnotation, HasRPCRepr] ExampleStorage => HasAnnotation ExampleStorageRPC where getAnnotation = notesAsRPC . getAnnotation @ExampleStorage annOptions = annOptions @ExampleStorage
Note that if the type doesn't contain type variables or only contains phantom
type variables, HasRPCRepr
constraint is omitted, as it would be redundant.
HasAnnotation
and its methods must be in scope.
When droRecursive
is True
, recursively enumerate data
, newtype
and
type
declarations, and derive 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 droRecursiveSkipTypes
.
In this example, this 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 deriveRPCWithOptions "A" def{droRecursive=True, droRecursiveSkipTypes=["C"]}
data DeriveRPCOptions Source #
Options for deriveRPCWithOptions
.
DeriveRPCOptions | |
|
Instances
Default DeriveRPCOptions Source # | |
Defined in Morley.AsRPC def :: DeriveRPCOptions # |
deriveRPC :: String -> Q [Dec] Source #
deriveRPCWithOptions
using default DeriveRPCOptions
.
deriveRPCWithStrategy :: String -> GenericStrategy -> Q [Dec] Source #
deriveManyRPC :: String -> [String] -> Q [Dec] Source #
Deprecated: Use deriveRPCWithOptions instead
Same as deriveRPCWithOptions
with droRecursive
set to True
and
droHasAnnotation
set to False
. Accepts droRecursiveSkipTypes
as second
argument.
deriveManyRPCWithStrategy :: String -> [String] -> GenericStrategy -> Q [Dec] Source #
Deprecated: Use deriveRPCWithOptions instead
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
.