-
Notifications
You must be signed in to change notification settings - Fork 214
/
Tx.hs
421 lines (360 loc) · 18.9 KB
/
Tx.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE NumericUnderscores #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# OPTIONS_GHC -Wno-redundant-constraints #-}
module Ledger.Tx
( module Export
, C.TxId(..)
, C.TxIn(..)
, C.TxIx(..)
-- * DecoratedTxOut
, DecoratedTxOut(..)
, toTxOut
, toTxInfoTxOut
, toDecoratedTxOut
-- ** Lenses and Prisms
, decoratedTxOutPubKeyHash
, decoratedTxOutAddress
, decoratedTxOutDatum
, decoratedTxOutValue
, decoratedTxOutPubKeyDatum
, decoratedTxOutScriptDatum
, decoratedTxOutStakingCredential
, decoratedTxOutReferenceScript
, decoratedTxOutValidatorHash
, decoratedTxOutValidator
, _PublicKeyDecoratedTxOut
, _ScriptDecoratedTxOut
, _decoratedTxOutAddress
-- ** smart Constructors
, mkDecoratedTxOut
, mkPubkeyDecoratedTxOut
, mkScriptDecoratedTxOut
-- * DatumFromQuery
, DatumFromQuery(..)
, datumInDatumFromQuery
-- * Transactions
, getCardanoTxId
, getCardanoTxInputs
, getCardanoTxCollateralInputs
, getCardanoTxOutRefs
, getCardanoTxOutputs
, getCardanoTxRedeemers
, getCardanoTxSpentOutputs
, getCardanoTxProducedOutputs
, getCardanoTxReturnCollateral
, getCardanoTxProducedReturnCollateral
, getCardanoTxTotalCollateral
, getCardanoTxFee
, getCardanoTxMint
, getCardanoTxValidityRange
, getCardanoTxData
, CardanoTx(.., CardanoEmulatorEraTx)
, ToCardanoError(..)
, addCardanoTxSignature
-- * TxBodyContent functions
, getTxBodyContentInputs
, getTxBodyContentCollateralInputs
, getTxBodyContentReturnCollateral
, getTxBodyContentMint
, txBodyContentIns
, txBodyContentCollateralIns
, txBodyContentOuts
-- * Utility
, decoratedTxOutPlutusValue
, fromDecoratedIndex
) where
import Cardano.Api qualified as C
import Cardano.Api.Shelley qualified as C.Api
import Cardano.Crypto.Wallet qualified as Crypto
import Cardano.Ledger.Alonzo.Tx (ValidatedTx (..))
import Cardano.Ledger.Alonzo.TxWitness (txwitsVKey)
import Codec.Serialise (Serialise)
import Control.Lens (Getter, Lens', Traversal', lens, makeLenses, makePrisms, to, view, views, (^.), (^?))
import Data.Aeson (FromJSON, ToJSON)
import Data.Coerce (coerce)
import Data.Map (Map)
import Data.Map qualified as Map
import Data.Set (Set)
import Data.Set qualified as Set
import Data.Tuple (swap)
import GHC.Generics (Generic)
import Ledger.Address (Address, CardanoAddress, cardanoAddressCredential, cardanoStakingCredential)
import Ledger.Orphans ()
import Ledger.Slot (SlotRange)
import Ledger.Tx.CardanoAPI (CardanoTx (CardanoTx), ToCardanoError (..), pattern CardanoEmulatorEraTx)
import Ledger.Tx.CardanoAPI qualified as CardanoAPI
import Plutus.Script.Utils.Scripts (scriptHash)
import Plutus.V1.Ledger.Api qualified as V1
import Plutus.V2.Ledger.Api qualified as V2
import Plutus.V2.Ledger.Tx qualified as V2.Tx hiding (TxId (..), TxIn (..), TxInType (..))
import Prettyprinter (Pretty (pretty), colon, hang, nest, viaShow, vsep, (<+>))
-- for re-export
import Ledger.Index.Internal (UtxoIndex)
import Ledger.Tx.Internal as Export
import Plutus.V1.Ledger.Tx as Export hiding (TxId (..), TxIn (..), TxInType (..), TxOut (..), inRef, inType, outAddress,
outValue, pubKeyTxIn, scriptTxIn, txOutDatum, txOutPubKey)
import Plutus.V1.Ledger.Value (Value)
-- | A datum in a transaction output that comes from a chain index query.
data DatumFromQuery
= DatumUnknown
| DatumInline V2.Datum
| DatumInBody V2.Datum
deriving (Show, Eq, Serialise, Generic, ToJSON, FromJSON)
makePrisms ''DatumFromQuery
datumInDatumFromQuery :: Traversal' DatumFromQuery V2.Datum
datumInDatumFromQuery _ DatumUnknown = pure DatumUnknown
datumInDatumFromQuery f (DatumInline d) = DatumInline <$> f d
datumInDatumFromQuery f (DatumInBody d) = DatumInBody <$> f d
-- | Offchain view of a transaction output.
data DecoratedTxOut =
PublicKeyDecoratedTxOut {
-- | The pubKey hash that protects the transaction address
_decoratedTxOutPubKeyHash :: V1.PubKeyHash,
-- | The staking credential of the transaction address, if any
_decoratedTxOutStakingCredential :: Maybe V1.StakingCredential,
-- | Value of the transaction output.
_decoratedTxOutValue :: C.Value,
-- | Optional datum (inline datum or datum in transaction body) attached to the transaction output.
_decoratedTxOutPubKeyDatum :: Maybe (V2.DatumHash, DatumFromQuery),
-- | Value of the transaction output.
_decoratedTxOutReferenceScript :: Maybe (Versioned V1.Script)
}
| ScriptDecoratedTxOut {
-- | The hash of the script that protects the transaction address
_decoratedTxOutValidatorHash :: V1.ValidatorHash,
-- | The staking credential of the transaction address, if any
_decoratedTxOutStakingCredential :: Maybe V1.StakingCredential,
-- | Value of the transaction output.
_decoratedTxOutValue :: C.Value,
-- | Datum attached to the transaction output, either in full (inline datum or datum in transaction body) or as a
-- hash reference. A transaction output protected by a Plutus script
-- is guardateed to have an associated datum.
_decoratedTxOutScriptDatum :: (V2.DatumHash, DatumFromQuery),
-- The reference script is, in genereal, unrelated to the validator
-- script althought it could also be the same.
_decoratedTxOutReferenceScript :: Maybe (Versioned V1.Script),
-- | Full version of the validator protecting the transaction output
_decoratedTxOutValidator :: Maybe (Versioned V1.Validator)
}
deriving (Show, Eq, Serialise, Generic, ToJSON, FromJSON)
makeLenses ''DecoratedTxOut
makePrisms ''DecoratedTxOut
mkDecoratedTxOut
:: CardanoAddress -> C.Value -> Maybe (V2.DatumHash, DatumFromQuery) -> Maybe (Versioned V1.Script)
-> Maybe DecoratedTxOut
mkDecoratedTxOut a v md rs = let
sc = cardanoStakingCredential a
in case cardanoAddressCredential a of
(V2.PubKeyCredential c) -> Just (PublicKeyDecoratedTxOut c sc v md rs)
(V2.ScriptCredential c) -> (\dt -> ScriptDecoratedTxOut c sc v dt rs Nothing) <$> md
mkPubkeyDecoratedTxOut
:: CardanoAddress -> C.Value -> Maybe (V2.DatumHash, DatumFromQuery) -> Maybe (Versioned V1.Script)
-> Maybe DecoratedTxOut
mkPubkeyDecoratedTxOut a v dat rs = let
sc = cardanoStakingCredential a
in case cardanoAddressCredential a of
(V2.PubKeyCredential c) -> Just $ PublicKeyDecoratedTxOut c sc v dat rs
_ -> Nothing
mkScriptDecoratedTxOut
:: CardanoAddress
-> C.Value
-> (V2.DatumHash, DatumFromQuery)
-> Maybe (Versioned V1.Script)
-> Maybe (Versioned V1.Validator)
-> Maybe DecoratedTxOut
mkScriptDecoratedTxOut a v dat rs val = let
sc = cardanoStakingCredential a
in case cardanoAddressCredential a of
(V2.ScriptCredential c) -> pure $ ScriptDecoratedTxOut c sc v dat rs val
_ -> Nothing
_decoratedTxOutAddress :: DecoratedTxOut -> Address
_decoratedTxOutAddress PublicKeyDecoratedTxOut{_decoratedTxOutPubKeyHash, _decoratedTxOutStakingCredential} =
V1.Address (V1.PubKeyCredential _decoratedTxOutPubKeyHash) _decoratedTxOutStakingCredential
_decoratedTxOutAddress ScriptDecoratedTxOut{_decoratedTxOutValidatorHash, _decoratedTxOutStakingCredential} =
V1.Address (V1.ScriptCredential _decoratedTxOutValidatorHash) _decoratedTxOutStakingCredential
decoratedTxOutAddress :: Getter DecoratedTxOut Address
decoratedTxOutAddress = to _decoratedTxOutAddress
decoratedTxOutDatum :: Traversal' DecoratedTxOut (V2.DatumHash, DatumFromQuery)
decoratedTxOutDatum f p@(PublicKeyDecoratedTxOut pkh sc v dat rs) =
maybe (pure p) (fmap (\ dat' -> PublicKeyDecoratedTxOut pkh sc v (Just dat') rs) . f) dat
decoratedTxOutDatum f (ScriptDecoratedTxOut vh sc v dat rs val) =
(\dat' -> ScriptDecoratedTxOut vh sc v dat' rs val) <$> f dat
toDecoratedTxOut :: TxOut -> Maybe DecoratedTxOut
toDecoratedTxOut (TxOut (C.TxOut addr' val dt rs)) =
mkDecoratedTxOut addr' (C.txOutValueToValue val) (toDecoratedDatum dt) (CardanoAPI.fromCardanoReferenceScript rs)
where
toDecoratedDatum :: C.TxOutDatum C.CtxTx C.BabbageEra -> Maybe (V2.DatumHash, DatumFromQuery)
toDecoratedDatum C.TxOutDatumNone =
Nothing
toDecoratedDatum (C.TxOutDatumHash _ h) =
Just (V2.DatumHash $ V2.toBuiltin (C.serialiseToRawBytes h), DatumUnknown)
toDecoratedDatum (C.TxOutDatumInTx _ d) =
Just (V2.DatumHash $ V2.toBuiltin (C.serialiseToRawBytes (C.hashScriptData d)), DatumInBody $ V2.Datum $ CardanoAPI.fromCardanoScriptData d)
toDecoratedDatum (C.TxOutDatumInline _ d) =
Just (V2.DatumHash $ V2.toBuiltin (C.serialiseToRawBytes (C.hashScriptData d)), DatumInline $ V2.Datum $ CardanoAPI.fromCardanoScriptData d)
toTxOut :: C.NetworkId -> DecoratedTxOut -> Either ToCardanoError TxOut
toTxOut networkId p =
TxOut <$> (C.TxOut
<$> CardanoAPI.toCardanoAddressInEra networkId (p ^. decoratedTxOutAddress)
<*> pure (CardanoAPI.toCardanoTxOutValue (p ^. decoratedTxOutValue))
<*> (toTxOutDatum $ p ^? decoratedTxOutDatum)
<*> CardanoAPI.toCardanoReferenceScript (p ^. decoratedTxOutReferenceScript))
toTxOutDatum :: Maybe (V2.DatumHash, DatumFromQuery) -> Either ToCardanoError (C.TxOutDatum C.CtxTx C.BabbageEra)
toTxOutDatum = CardanoAPI.toCardanoTxOutDatum . toPlutusOutputDatum
-- | Converts a transaction output from the chain index to the plutus-ledger-api
-- transaction output.
--
-- Note that 'DecoratedTxOut' supports features such inline datums and
-- reference scripts which are not supported by V1 TxOut. Converting from
-- 'DecoratedTxOut' to 'TxOut' and back is therefore lossy.
toTxInfoTxOut :: DecoratedTxOut -> V2.Tx.TxOut
toTxInfoTxOut p =
V2.Tx.TxOut (p ^. decoratedTxOutAddress) (CardanoAPI.fromCardanoValue $ p ^. decoratedTxOutValue)
(toPlutusOutputDatum $ p ^? decoratedTxOutDatum)
(views decoratedTxOutReferenceScript (fmap scriptHash) p)
toPlutusOutputDatum :: Maybe (V2.DatumHash, DatumFromQuery) -> V2.Tx.OutputDatum
toPlutusOutputDatum Nothing = V2.Tx.NoOutputDatum
toPlutusOutputDatum (Just (_, DatumInline d)) = V2.Tx.OutputDatum d
toPlutusOutputDatum (Just (dh, _)) = V2.Tx.OutputDatumHash dh
fromDecoratedIndex :: C.Api.NetworkId -> Map TxOutRef DecoratedTxOut -> Either ToCardanoError UtxoIndex
fromDecoratedIndex networkId m = C.UTxO . Map.fromList <$> traverse toCardanoUtxo (Map.toList m)
where
toCardanoUtxo (outRef, txOut) = do
txOut' <- toCtxUTxOTxOut <$> toTxOut networkId txOut
txIn <- CardanoAPI.toCardanoTxIn outRef
pure (txIn, txOut')
instance Pretty DecoratedTxOut where
pretty p =
hang 2 $ vsep [ "-" <+> pretty (p ^. decoratedTxOutValue) <+> "addressed to"
, pretty (p ^. decoratedTxOutAddress)]
instance Pretty CardanoTx where
pretty tx =
let
renderScriptWitnesses (CardanoEmulatorEraTx (C.Api.Tx (C.Api.ShelleyTxBody _ _ scripts _ _ _) _)) =
[ hang 2 (vsep ("attached scripts:": fmap viaShow scripts)) | not (null scripts) ]
lines' =
[ hang 2 (vsep ("inputs:" : fmap (("-" <+>) . pretty) (getCardanoTxInputs tx)))
, hang 2 (vsep ("reference inputs:" : fmap (("-" <+>) . pretty) (getCardanoTxReferenceInputs tx)))
, hang 2 (vsep ("collateral inputs:" : fmap (("-" <+>) . pretty) (getCardanoTxCollateralInputs tx)))
, hang 2 (vsep ("outputs:" : fmap pretty (getCardanoTxOutputs tx)))
]
<> maybe [] (\out -> [hang 2 (vsep ["return collateral:", pretty out])]) (getCardanoTxReturnCollateral tx)
<> maybe [] (\val -> ["total collateral:" <+> pretty val]) (getCardanoTxTotalCollateral tx)
++ [ "mint:" <+> pretty (getCardanoTxMint tx)
, "fee:" <+> pretty (getCardanoTxFee tx)
, "validity range:" <+> viaShow (getCardanoTxValidityRange tx)
, hang 2 (vsep ("data:": fmap pretty (Map.toList (getCardanoTxData tx))))
, hang 2 (vsep ("redeemers:": fmap (\(k, V2.Redeemer red) -> viaShow k <+> ":" <+> viaShow red) (Map.toList $ getCardanoTxRedeemers tx)))
] ++
[ hang 2 (vsep ("required signatures:": (viaShow <$> wits))) | let wits = getCardanoTxExtraKeyWitnesses tx, not (null wits)
] ++ renderScriptWitnesses tx
in nest 2 $ vsep ["Tx" <+> pretty (getCardanoTxId tx) <> colon, vsep lines']
instance Pretty CardanoAPI.CardanoBuildTx where
pretty txBodyContent = case C.makeSignedTransaction [] <$> CardanoAPI.makeTransactionBody Nothing mempty txBodyContent of
Right tx -> pretty $ CardanoEmulatorEraTx tx
_ -> viaShow txBodyContent
getTxBodyContent :: CardanoTx -> C.TxBodyContent C.ViewTx C.BabbageEra
getTxBodyContent (CardanoEmulatorEraTx (C.Tx (C.TxBody bodyContent) _)) = bodyContent
getCardanoTxId :: CardanoTx -> C.TxId
getCardanoTxId = getCardanoApiTxId
getCardanoApiTxId :: CardanoTx -> C.TxId
getCardanoApiTxId (CardanoTx (C.Tx body _) _) = C.getTxId body
getCardanoTxInputs :: CardanoTx -> [C.TxIn]
getCardanoTxInputs = getTxBodyContentInputs . getTxBodyContent
getTxBodyContentInputs :: C.TxBodyContent ctx era -> [C.TxIn]
getTxBodyContentInputs C.TxBodyContent {..} =
fmap fst txIns
getCardanoTxCollateralInputs :: CardanoTx -> [C.TxIn]
getCardanoTxCollateralInputs = getTxBodyContentCollateralInputs . getTxBodyContent
getTxBodyContentCollateralInputs :: C.TxBodyContent ctx era -> [C.TxIn]
getTxBodyContentCollateralInputs C.TxBodyContent {..} = CardanoAPI.fromCardanoTxInsCollateral txInsCollateral
getCardanoTxReferenceInputs :: CardanoTx -> [C.TxIn]
getCardanoTxReferenceInputs (CardanoTx (C.Tx (C.TxBody C.TxBodyContent {..}) _) _) =
txInsReferenceToTxIns txInsReference
where
txInsReferenceToTxIns C.TxInsReferenceNone = []
txInsReferenceToTxIns (C.TxInsReference _ txIns') = txIns'
getCardanoTxOutRefs :: CardanoTx -> [(TxOut, C.TxIn)]
getCardanoTxOutRefs (CardanoEmulatorEraTx (C.Tx txBody@(C.TxBody C.TxBodyContent{..}) _)) =
mkOut <$> zip [0..] (coerce txOuts)
where
mkOut (i, o) = (o, C.TxIn (C.getTxId txBody) (C.TxIx i))
getCardanoTxOutputs :: CardanoTx -> [TxOut]
getCardanoTxOutputs = fmap fst . getCardanoTxOutRefs
getCardanoTxProducedOutputs :: CardanoTx -> Map C.TxIn TxOut
getCardanoTxProducedOutputs = Map.fromList . fmap swap . getCardanoTxOutRefs
getCardanoTxSpentOutputs :: CardanoTx -> Set C.TxIn
getCardanoTxSpentOutputs = Set.fromList . getCardanoTxInputs
getCardanoTxReturnCollateral :: CardanoTx -> Maybe TxOut
getCardanoTxReturnCollateral = getTxBodyContentReturnCollateral . getTxBodyContent
getTxBodyContentReturnCollateral :: C.TxBodyContent ctx C.Api.BabbageEra -> Maybe TxOut
getTxBodyContentReturnCollateral C.TxBodyContent {..} =
case txReturnCollateral of
C.TxReturnCollateralNone -> Nothing
C.TxReturnCollateral _ txOut -> Just $ TxOut txOut
getCardanoTxProducedReturnCollateral :: CardanoTx -> Map C.TxIn TxOut
getCardanoTxProducedReturnCollateral tx = maybe Map.empty (Map.singleton (C.TxIn (getCardanoTxId tx) (C.TxIx 0))) $
getCardanoTxReturnCollateral tx
getCardanoTxTotalCollateral :: CardanoTx -> Maybe C.Lovelace
getCardanoTxTotalCollateral (CardanoEmulatorEraTx (C.Tx (C.TxBody C.TxBodyContent {..}) _)) =
CardanoAPI.fromCardanoTotalCollateral txTotalCollateral
getCardanoTxFee :: CardanoTx -> C.Lovelace
getCardanoTxFee (CardanoTx (C.Tx (C.TxBody C.TxBodyContent {..}) _) _) = CardanoAPI.fromCardanoFee txFee
getCardanoTxMint :: CardanoTx -> C.Value
getCardanoTxMint = getTxBodyContentMint . getTxBodyContent
getTxBodyContentMint :: C.TxBodyContent ctx era -> C.Value
getTxBodyContentMint C.TxBodyContent {..} = CardanoAPI.fromCardanoMintValue txMintValue
getCardanoTxValidityRange :: CardanoTx -> SlotRange
getCardanoTxValidityRange (CardanoTx (C.Tx (C.TxBody C.TxBodyContent {..}) _) _) = CardanoAPI.fromCardanoValidityRange txValidityRange
getCardanoTxData :: CardanoTx -> Map V1.DatumHash V1.Datum
getCardanoTxData (CardanoTx (C.Tx txBody _) _) = fst $ CardanoAPI.scriptDataFromCardanoTxBody txBody
-- TODO: add txMetaData
txBodyContentIns :: Lens' (C.TxBodyContent C.BuildTx C.BabbageEra) [(C.TxIn, C.BuildTxWith C.BuildTx (C.Witness C.WitCtxTxIn C.BabbageEra))]
txBodyContentIns = lens C.txIns (\bodyContent ins -> bodyContent { C.txIns = ins })
txBodyContentCollateralIns :: Lens' (C.TxBodyContent C.BuildTx C.BabbageEra) [C.TxIn]
txBodyContentCollateralIns = lens
(\bodyContent -> case C.txInsCollateral bodyContent of C.TxInsCollateralNone -> []; C.TxInsCollateral _ txIns -> txIns)
(\bodyContent ins -> bodyContent { C.txInsCollateral = case ins of [] -> C.TxInsCollateralNone; _ -> C.TxInsCollateral C.CollateralInBabbageEra ins })
txBodyContentOuts :: Lens' (C.TxBodyContent ctx C.BabbageEra) [TxOut]
txBodyContentOuts = lens (map TxOut . C.txOuts) (\bodyContent outs -> bodyContent { C.txOuts = map getTxOut outs })
getCardanoTxRedeemers :: CardanoTx -> V2.Tx.Redeemers
getCardanoTxRedeemers (CardanoTx (C.Tx txBody _) _) = snd $ CardanoAPI.scriptDataFromCardanoTxBody txBody
getCardanoTxExtraKeyWitnesses :: CardanoTx -> [C.Hash C.PaymentKey]
getCardanoTxExtraKeyWitnesses (CardanoEmulatorEraTx (C.Tx (C.TxBody C.TxBodyContent {..}) _)) = case txExtraKeyWits of
C.Api.TxExtraKeyWitnessesNone -> mempty
C.Api.TxExtraKeyWitnesses _ txwits -> txwits
type PrivateKey = Crypto.XPrv
addCardanoTxSignature :: PrivateKey -> CardanoTx -> CardanoTx
addCardanoTxSignature privKey = addSignatureCardano
where
addSignatureCardano :: CardanoTx -> CardanoTx
addSignatureCardano (CardanoEmulatorEraTx ctx)
= CardanoEmulatorEraTx (addSignatureCardano' ctx)
addSignatureCardano' (C.Api.ShelleyTx shelleyBasedEra (ValidatedTx body wits isValid aux))
= C.Api.ShelleyTx shelleyBasedEra (ValidatedTx body wits' isValid aux)
where
wits' = wits <> mempty { txwitsVKey = newWits }
newWits = case fromPaymentPrivateKey privKey body of
C.Api.ShelleyKeyWitness _ wit -> Set.singleton wit
_ -> Set.empty
fromPaymentPrivateKey xprv txBody
= C.Api.makeShelleyKeyWitness
(C.Api.ShelleyTxBody C.Api.ShelleyBasedEraBabbage txBody notUsed notUsed notUsed notUsed)
(C.Api.WitnessPaymentExtendedKey (C.Api.PaymentExtendedSigningKey xprv))
where
notUsed = undefined -- hack so we can reuse code from cardano-api
decoratedTxOutPlutusValue :: DecoratedTxOut -> Value
decoratedTxOutPlutusValue = CardanoAPI.fromCardanoValue . view decoratedTxOutValue