Skip to content

Commit 62c1011

Browse files
UnisayPhilip DiSarro
andcommitted
Replace redundant helpers with existing API functions
- Replace local isPubKeyAddress/isScriptAddress with toPubKeyHash/toScriptHash from PlutusLedgerApi.V1.Address - Replace negateValue with PlutusTx.negate (Value has AdditiveGroup) - Export and relocate currencySymbolFromHex and singleCurrencySymbol to a dedicated Helpers section at the bottom of Builder.hs Co-authored-by: Philip DiSarro <philip-disarro@users.noreply.github.com>
1 parent 7c88f80 commit 62c1011

1 file changed

Lines changed: 67 additions & 60 deletions

File tree

  • plutus-ledger-api/testlib/PlutusLedgerApi/Test/ScriptContextBuilder

plutus-ledger-api/testlib/PlutusLedgerApi/Test/ScriptContextBuilder/Builder.hs

Lines changed: 67 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ module PlutusLedgerApi.Test.ScriptContextBuilder.Builder
3636
, mkMintingScriptWithPurpose
3737
, addChangeOutput
3838
, signAndAddChangeOutput
39-
, negateValue
4039
, mkAdaValue
4140
, mkTxOut
4241
, withTxOutReferenceScript
@@ -48,6 +47,10 @@ module PlutusLedgerApi.Test.ScriptContextBuilder.Builder
4847
, buildBalancedScriptContext
4948
, balanceWithChangeOutput
5049
, builderPlaceHolderTxOutRef
50+
51+
-- * Helpers
52+
, currencySymbolFromHex
53+
, singleCurrencySymbol
5154
)
5255
where
5356

@@ -56,6 +59,7 @@ import Data.ByteString.Base16 qualified as Base16
5659
import Data.ByteString.Char8 qualified as BS8
5760
import Data.Function (on)
5861
import Data.List qualified as List
62+
import Data.Maybe (isJust)
5963
import Data.Ord (comparing)
6064
import GHC.Generics (Generic)
6165
import PlutusLedgerApi.Test.ScriptContextBuilder.Lenses
@@ -68,10 +72,11 @@ import PlutusLedgerApi.Test.ScriptContextBuilder.Lenses
6872
, txInfoReferenceInputsL
6973
, txInfoSignatoriesL
7074
)
75+
import PlutusLedgerApi.V1.Address (toPubKeyHash, toScriptHash)
7176
import PlutusLedgerApi.V3
7277
( Address (Address)
7378
, BuiltinData
74-
, Credential (PubKeyCredential, ScriptCredential)
79+
, Credential (PubKeyCredential)
7580
, CurrencySymbol (CurrencySymbol)
7681
, Datum (Datum)
7782
, Lovelace (getLovelace)
@@ -100,27 +105,11 @@ import PlutusTx qualified
100105
import PlutusTx.AssocMap qualified as Map
101106
import PlutusTx.Builtins.Internal (BuiltinByteString (..))
102107
import PlutusTx.Eq qualified
108+
import PlutusTx.Numeric qualified as PlutusTx
103109

104110
instance PlutusTx.Eq.Eq ScriptPurpose where
105111
a == b = PlutusTx.toBuiltinData a == PlutusTx.toBuiltinData b
106112

107-
-- | Convert a hex encoded Haskell 'String' to a 'CurrencySymbol'.
108-
currencySymbolFromHex :: String -> CurrencySymbol
109-
currencySymbolFromHex hexStr =
110-
case Base16.decode (BS8.pack hexStr) of
111-
Left err -> error $ "currencySymbolFromHex: invalid hex: " <> err
112-
Right bs -> CurrencySymbol (BuiltinByteString bs)
113-
114-
{-| Extract the single currency symbol from a 'Value'. Errors if the value
115-
contains zero or more than one currency symbol. -}
116-
singleCurrencySymbol :: Value -> CurrencySymbol
117-
singleCurrencySymbol val = case Map.keys (getValue val) of
118-
[cs] -> cs
119-
keys ->
120-
error $
121-
"singleCurrencySymbol: expected exactly 1 currency symbol, got "
122-
<> show (length keys)
123-
124113
-- | Arguments for a unit test: a script context and additional parameters.
125114
data UnitTestArgs = UnitTestArgs
126115
{ utaScriptContext :: ScriptContext
@@ -332,42 +321,50 @@ mkMintingScriptWithPurpose mintValue redeemer =
332321
, txInfoTreasuryDonation = Nothing
333322
}
334323

335-
-- | Negate all token quantities in a 'Value'.
336-
negateValue :: Value -> Value
337-
negateValue (Value val) = Value $ Map.mapWithKey (\_ -> Map.mapWithKey (\_ x -> negate x)) val
338-
339324
-- | Compute and add a change output to the given public key hash.
340325
addChangeOutput :: PubKeyHash -> ScriptContext -> ScriptContext
341326
addChangeOutput signerPkh ctx =
342-
let ti = ctx ^. scriptContextTxInfoL
343-
totalInputValue = foldMap (txOutValue . txInInfoResolved) (ti ^. txInfoInputsL)
344-
totalOutputValue = foldMap txOutValue (ti ^. txInfoOutputsL)
345-
feeValue = mkAdaValue (ti ^. txInfoFeeL)
346-
mintedValue = Value $ mintValueToMap (ti ^. txInfoMintL)
347-
changeValue = mintedValue <> totalInputValue <> negateValue feeValue <> negateValue totalOutputValue
348-
changeOutput = TxOut (Address (PubKeyCredential signerPkh) Nothing) changeValue NoOutputDatum Nothing
327+
let info = ctx ^. scriptContextTxInfoL
328+
totalInputValue = foldMap (txOutValue . txInInfoResolved) (info ^. txInfoInputsL)
329+
totalOutputValue = foldMap txOutValue (info ^. txInfoOutputsL)
330+
feeValue = mkAdaValue (info ^. txInfoFeeL)
331+
mintedValue = Value (mintValueToMap (info ^. txInfoMintL))
332+
changeOutput =
333+
TxOut
334+
(Address (PubKeyCredential signerPkh) Nothing)
335+
( mintedValue
336+
<> totalInputValue
337+
<> PlutusTx.negate feeValue
338+
<> PlutusTx.negate totalOutputValue
339+
)
340+
NoOutputDatum
341+
Nothing
349342
in ctx & scriptContextTxInfoL . txInfoOutputsL %~ (changeOutput :)
350343

351344
-- | Balance the transaction by adding a change output to the first public key input.
352345
balanceWithChangeOutput :: ScriptContext -> ScriptContext
353346
balanceWithChangeOutput ctx =
354-
let ti = ctx ^. scriptContextTxInfoL
355-
resolvedInputs = map txInInfoResolved (ti ^. txInfoInputsL)
356-
signerPkh = case filter (isPubKeyAddress . txOutAddress) resolvedInputs of
357-
(TxOut (Address (PubKeyCredential pkh) _) _ _ _ : _) -> pkh
347+
let info = ctx ^. scriptContextTxInfoL
348+
resolvedInputs = map txInInfoResolved (info ^. txInfoInputsL)
349+
signerPkh = case filter (isJust . toPubKeyHash . txOutAddress) resolvedInputs of
350+
TxOut (Address (PubKeyCredential pkh) _) _ _ _ : _ -> pkh
358351
_ -> PubKeyHash "deadbeef"
359352
-- \^ Fallback to default if no public key input is found
360-
totalInputValue = foldMap (txOutValue . txInInfoResolved) (ti ^. txInfoInputsL)
361-
totalOutputValue = foldMap txOutValue (ti ^. txInfoOutputsL)
362-
feeValue = mkAdaValue (ti ^. txInfoFeeL)
363-
mintedValue = Value $ mintValueToMap (ti ^. txInfoMintL)
364-
changeValue = mintedValue <> totalInputValue <> negateValue feeValue <> negateValue totalOutputValue
365-
changeOutput = TxOut (Address (PubKeyCredential signerPkh) Nothing) changeValue NoOutputDatum Nothing
353+
totalInputValue = foldMap (txOutValue . txInInfoResolved) (info ^. txInfoInputsL)
354+
totalOutputValue = foldMap txOutValue (info ^. txInfoOutputsL)
355+
feeValue = mkAdaValue (info ^. txInfoFeeL)
356+
mintedValue = Value $ mintValueToMap (info ^. txInfoMintL)
357+
changeOutput =
358+
TxOut
359+
(Address (PubKeyCredential signerPkh) Nothing)
360+
( mintedValue
361+
<> totalInputValue
362+
<> PlutusTx.negate feeValue
363+
<> PlutusTx.negate totalOutputValue
364+
)
365+
NoOutputDatum
366+
Nothing
366367
in ctx & scriptContextTxInfoL . txInfoOutputsL %~ (<> [changeOutput])
367-
where
368-
isPubKeyAddress :: Address -> Bool
369-
isPubKeyAddress (Address (PubKeyCredential _) _) = True
370-
isPubKeyAddress _ = False
371368

372369
-- | Add a signatory to an existing 'ScriptContext'.
373370
addSigner :: PubKeyHash -> ScriptContext -> ScriptContext
@@ -457,36 +454,27 @@ withOutput modify = ScriptContextBuilder \scb ->
457454

458455
-- | Add a public-key input. Errors if the address is a script address.
459456
withInput :: InputBuilder -> ScriptContextBuilder
460-
withInput modify = ScriptContextBuilder \scb ->
461-
let newInput = mkInput modify
462-
newInputAddress = txOutAddress $ txInInfoResolved newInput
463-
in if isPubKeyAddress newInputAddress
464-
then
465-
scb {scbInputs = List.insertBy (comparing txInInfoOutRef) newInput (scbInputs scb)}
466-
else
467-
error "withInput: Input address is not a public key address"
457+
withInput inputBuilder = ScriptContextBuilder \scb ->
458+
if isJust (toPubKeyHash (txOutAddress (txInInfoResolved newInput)))
459+
then scb {scbInputs = List.insertBy (comparing txInInfoOutRef) newInput (scbInputs scb)}
460+
else error "withInput: Input address is not a public key address"
468461
where
469-
isPubKeyAddress :: Address -> Bool
470-
isPubKeyAddress (Address (PubKeyCredential _) _) = True
471-
isPubKeyAddress _ = False
462+
newInput :: TxInInfo
463+
newInput = mkInput inputBuilder
472464

473465
-- | Add a script input with a redeemer. Errors if the address is not a script address.
474466
withScriptInput :: BuiltinData -> InputBuilder -> ScriptContextBuilder
475467
withScriptInput redeemer modify = ScriptContextBuilder \scb ->
476468
let newInput = mkInput modify
477469
inputOutRef = txInInfoOutRef newInput
478470
newRedeemers = Map.insert (Spending inputOutRef) (Redeemer redeemer) (scbRedeemers scb)
479-
in if isScriptAddress (txOutAddress $ txInInfoResolved newInput)
471+
in if isJust (toScriptHash (txOutAddress $ txInInfoResolved newInput))
480472
then
481473
scb
482474
{ scbInputs = List.insertBy (comparing txInInfoOutRef) newInput (scbInputs scb)
483475
, scbRedeemers = newRedeemers
484476
}
485477
else error "withScriptInput: Input address is not a script address"
486-
where
487-
isScriptAddress :: Address -> Bool
488-
isScriptAddress (Address (ScriptCredential _) _) = True
489-
isScriptAddress _ = False
490478

491479
-- | Add a reference input (read-only, not spent).
492480
withReferenceInput :: InputBuilder -> ScriptContextBuilder
@@ -630,3 +618,22 @@ buildBalancedScriptContext modify =
630618
}
631619
where
632620
finalState = runBuilder modify defaultScriptContextBuilderState
621+
622+
-- * Helpers
623+
624+
-- | Convert a hex encoded Haskell 'String' to a 'CurrencySymbol'.
625+
currencySymbolFromHex :: String -> CurrencySymbol
626+
currencySymbolFromHex hexStr =
627+
case Base16.decode (BS8.pack hexStr) of
628+
Left err -> error $ "currencySymbolFromHex: invalid hex: " <> err
629+
Right bs -> CurrencySymbol (BuiltinByteString bs)
630+
631+
{-| Extract the single currency symbol from a 'Value'. Errors if the value
632+
contains zero or more than one currency symbol. -}
633+
singleCurrencySymbol :: Value -> CurrencySymbol
634+
singleCurrencySymbol val = case Map.keys (getValue val) of
635+
[cs] -> cs
636+
keys ->
637+
error $
638+
"singleCurrencySymbol: expected exactly 1 currency symbol, got "
639+
<> show (length keys)

0 commit comments

Comments
 (0)