| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Morley.AsRPC
Contents
Description
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_maps 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_maps 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 bcan 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 vcannot be big_maps, but the values can, so its RPC representation ismap k (TAsRPC v). - Values of type
set acannot contain big_maps, so its RPC representation is justset a. - Values of type
contract acannot 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 aandlambda a b.
Equations
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 BigMaps will be replaced
by BigMapIds.
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)
Constructors
| 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 Methods 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.
Arguments
| :: 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.