11{-# LANGUAGE FlexibleInstances #-}
2+ {-# LANGUAGE GADTs #-}
23{-# LANGUAGE MultiParamTypeClasses #-}
34{-# LANGUAGE OverloadedLabels #-}
5+ {-# LANGUAGE ScopedTypeVariables #-}
6+ {-# LANGUAGE TypeApplications #-}
47{-# OPTIONS_GHC -Wno-orphans #-}
58
69module Cardano.Rpc.Server.Internal.Orphans () where
710
8- import Cardano.Api.Block (ChainPoint (.. ), Hash (.. ), SlotNo (.. ))
9- import Cardano.Api.Era (Inject (.. ))
11+ import Cardano.Api.Address
12+ import Cardano.Api.Era
13+ import Cardano.Api.Error
14+ import Cardano.Api.Ledger qualified as L
15+ import Cardano.Api.Plutus
16+ import Cardano.Api.Pretty
17+ import Cardano.Api.Serialise.Cbor
18+ import Cardano.Api.Serialise.Raw
19+ import Cardano.Api.Tx
20+ import Cardano.Api.Value
1021import Cardano.Rpc.Proto.Api.UtxoRpc.Query qualified as UtxoRpc
1122
12- import Cardano.Ledger.Plutus qualified as L
23+ import RIO hiding ( toList )
1324
14- import RIO
15-
16- import Data.ByteString.Short qualified as SBS
1725import Data.ProtoLens (defMessage )
1826import Data.Ratio (Ratio , denominator , numerator , (%) )
27+ import Data.Text.Encoding qualified as T
28+ import GHC.IsList
1929import Network.GRPC.Spec
2030
31+ ---------------
32+ -- Conversion
33+ ---------------
34+
35+ -- It's easier to use 'Proto a' wrappers for RPC types, because it makes lens automatically available.
36+
37+ -- TODO: write property tests for bijections
38+
2139instance Inject (Proto UtxoRpc. RationalNumber ) (Ratio Integer ) where
2240 inject r = r ^. # numerator . to fromIntegral % r ^. # denominator . to fromIntegral
2341
@@ -40,12 +58,74 @@ instance Inject L.ExUnits (Proto UtxoRpc.ExUnits) where
4058 & # memory .~ fromIntegral mem
4159 & # steps .~ fromIntegral steps
4260
43- instance Inject ChainPoint (Proto UtxoRpc. ChainPoint ) where
44- inject chainPoint = do
45- let (slotNo, blockHash) =
46- case chainPoint of
47- ChainPointAtGenesis -> (0 , mempty )
48- ChainPoint (SlotNo slot) (HeaderHash hash) -> (slot, SBS. fromShort hash)
61+ -- | Note that conversion is not total in the other direction
62+ instance Inject TxIn (Proto UtxoRpc. TxoRef ) where
63+ inject (TxIn txId' (TxIx txIx)) =
4964 defMessage
50- & # slot .~ slotNo
51- & # hash .~ blockHash
65+ & # hash .~ serialiseToRawBytes txId'
66+ & # index .~ fromIntegral txIx
67+
68+ instance Inject (ReferenceScript era ) (Proto UtxoRpc. Script ) where
69+ inject ReferenceScriptNone = defMessage
70+ inject (ReferenceScript _ (ScriptInAnyLang _ script)) =
71+ case script of
72+ SimpleScript _ ->
73+ defMessage & # native .~ serialiseToCBOR script
74+ PlutusScript PlutusScriptV1 ps ->
75+ defMessage & # plutusV1 .~ serialiseToRawBytes ps
76+ PlutusScript PlutusScriptV2 ps ->
77+ defMessage & # plutusV2 .~ serialiseToRawBytes ps
78+ PlutusScript PlutusScriptV3 ps ->
79+ defMessage & # plutusV3 .~ serialiseToRawBytes ps
80+
81+ instance IsCardanoEra era => Inject (UTxO era ) [Proto UtxoRpc. AnyUtxoData ] where
82+ inject utxo =
83+ toList utxo <&> \ (txIn, TxOut addressInEra txOutValue datum script) -> do
84+ let multiAsset =
85+ fromList $
86+ toList (valueToPolicyAssets $ txOutValueToValue txOutValue) <&> \ (pId, policyAssets) -> do
87+ let assets =
88+ toList policyAssets <&> \ (assetName, Quantity qty) -> do
89+ defMessage
90+ & # name .~ serialiseToRawBytes assetName
91+ -- we don't have access to info it the coin was minted in the transaction,
92+ -- maybe we should add it later
93+ & # maybe'mintCoin .~ Nothing
94+ & # outputCoin .~ fromIntegral qty
95+ defMessage
96+ & # policyId .~ serialiseToRawBytes pId
97+ & # assets .~ assets
98+ datumRpc = case datum of
99+ TxOutDatumNone ->
100+ defMessage
101+ TxOutDatumHash _ scriptDataHash ->
102+ defMessage
103+ & # hash .~ serialiseToRawBytes scriptDataHash
104+ & # originalCbor .~ mempty -- we don't have it
105+ TxOutDatumInline _ hashableScriptData ->
106+ defMessage
107+ & # hash .~ serialiseToRawBytes (hashScriptDataBytes hashableScriptData)
108+ & # originalCbor .~ getOriginalScriptDataBytes hashableScriptData
109+
110+ protoTxOut =
111+ defMessage
112+ -- TODO we don't have serialiseToRawBytes for AddressInEra, so perhaps this is wrong, because 'address'
113+ -- has type bytes, but we're putting text there
114+ & # address .~ T. encodeUtf8 (cardanoEraConstraints (cardanoEra @ era ) $ serialiseAddress addressInEra)
115+ & # coin .~ fromIntegral (L. unCoin (txOutValueToLovelace txOutValue))
116+ & # assets .~ multiAsset
117+ & # datum .~ datumRpc
118+ & # script .~ inject script
119+ defMessage
120+ & # nativeBytes .~ " " -- TODO where to get that from? run cbor serialisation of utxos list?
121+ & # txoRef .~ inject txIn
122+ & # cardano .~ protoTxOut
123+
124+ -----------
125+ -- Errors
126+ -----------
127+
128+ -- TODO add RIO to cardano-api and move this instance there
129+
130+ instance Error StringException where
131+ prettyError = pshow
0 commit comments