Skip to content

Commit

Permalink
Add functions for converting between Lovelace and Value (#5682)
Browse files Browse the repository at this point in the history
  • Loading branch information
zliu41 authored Dec 14, 2023
1 parent b03488d commit ef082e1
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 16 deletions.
4 changes: 2 additions & 2 deletions doc/read-the-docs-site/simple-example.rst
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ The ``refundsPreviousHighestBid`` condition checks that the transaction pays the

It uses ``PlutusTx.find`` to find the transaction output (a UTXO) that pays to the previous bidder the amount equivalent to the previous highest bid, and verifies that there is at least one such output.

``singleton adaSymbol adaToken amt`` constructs a ``Value`` with ``amt`` Lovelaces (the subunit of the Ada currency).
``lovelaceValue amt`` constructs a ``Value`` with ``amt`` Lovelaces (the subunit of the Ada currency).
``Value`` is a multi-asset type that represents a collection of assets, including Ada.
An asset is identified by a (symbol, token) pair, where the symbol represents the policy that controls the minting and burning of tokens, and the token represents a particular kind of token manipulated by the policy.
``(adaSymbol, adaToken)`` is the special identifier for Ada/Lovelace.
Expand Down Expand Up @@ -284,7 +284,7 @@ Libraries for writing Plutus Tx scripts
This auction example shows a relatively low-level way of writing scripts using Plutus Tx.
In practice, you may consider using a higher-level library that abstracts away some of the details.
For example, `plutus-apps <https://github.com/input-output-hk/plutus-apps>`_ provides a constraint library for writing Plutus Tx.
Using these libraries, writing a validator in Plutus Tx becomes a matter of defining state transactions and the corresponding constraints, e.g., the condition ``refundsPreviousHighestBid`` can simply be written as ``Constraints.mustPayToPubKey bidder (singleton adaSymbol adaToken amt)``.
Using these libraries, writing a validator in Plutus Tx becomes a matter of defining state transactions and the corresponding constraints, e.g., the condition ``refundsPreviousHighestBid`` can simply be written as ``Constraints.mustPayToPubKey bidder (lovelaceValue amt)``.

Alternatives to Plutus Tx
-----------------------------
Expand Down
13 changes: 7 additions & 6 deletions doc/read-the-docs-site/tutorials/AuctionValidator.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
module AuctionValidator where

import PlutusCore.Version (plcVersion100)
import PlutusLedgerApi.V1 (POSIXTime, PubKeyHash, Value, adaSymbol, adaToken, singleton)
import PlutusLedgerApi.V1 (Lovelace, POSIXTime, PubKeyHash, Value)
import PlutusLedgerApi.V1.Address (pubKeyHashAddress)
import PlutusLedgerApi.V1.Interval (contains)
import PlutusLedgerApi.V1.Value (lovelaceValue)
import PlutusLedgerApi.V2 (Datum (..), OutputDatum (..), ScriptContext (..), TxInfo (..),
TxOut (..), from, to)
import PlutusLedgerApi.V2.Contexts (getContinuingOutputs)
Expand All @@ -39,7 +40,7 @@ data AuctionParams = AuctionParams
-- ^ The asset being auctioned. It can be a single token, multiple tokens of the same
-- kind, or tokens of different kinds, and the token(s) can be fungible or non-fungible.
-- These can all be encoded as a `Value`.
apMinBid :: Integer,
apMinBid :: Lovelace,
-- ^ The minimum bid in Lovelace.
apEndTime :: POSIXTime
-- ^ The deadline for placing a bid. This is the earliest time the auction can be closed.
Expand All @@ -50,8 +51,8 @@ PlutusTx.makeLift ''AuctionParams
data Bid = Bid
{ bBidder :: PubKeyHash,
-- ^ Bidder's wallet address.
bAmount :: Integer
-- ^ Bid amount.
bAmount :: Lovelace
-- ^ Bid amount in Lovelace.
}

PlutusTx.deriveShow ''Bid
Expand Down Expand Up @@ -126,7 +127,7 @@ auctionTypedValidator params (AuctionDatum highestBid) redeemer ctx@(ScriptConte
Just (Bid bidder amt) ->
case PlutusTx.find
(\o -> txOutAddress o PlutusTx.== pubKeyHashAddress bidder
PlutusTx.&& txOutValue o PlutusTx.== singleton adaSymbol adaToken amt)
PlutusTx.&& txOutValue o PlutusTx.== lovelaceValue amt)
(txInfoOutputs txInfo) of
Just _ -> True
Nothing -> PlutusTx.traceError ("Not found: refund output")
Expand Down Expand Up @@ -168,7 +169,7 @@ auctionTypedValidator params (AuctionDatum highestBid) redeemer ctx@(ScriptConte
case PlutusTx.find
( \o ->
txOutAddress o PlutusTx.== pubKeyHashAddress (apSeller params)
PlutusTx.&& txOutValue o PlutusTx.== singleton adaSymbol adaToken amt
PlutusTx.&& txOutValue o PlutusTx.== lovelaceValue amt
)
(txInfoOutputs txInfo) of
Just _ -> True
Expand Down
3 changes: 2 additions & 1 deletion doc/read-the-docs-site/tutorials/BasicValidators.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE NumericUnderscores #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
Expand Down Expand Up @@ -80,7 +81,7 @@ validatePayment _ _ ctx =
values = pubKeyOutputsAt myKeyHash txinfo
-- 'fold' sums up all the values, we assert that there must be more
-- than 1 Ada (more stuff is fine!)
in check $ valueOf (fold values) adaSymbol adaToken >= 1
in check $ lovelaceValueOf (fold values) >= 1_000_000
--- BLOCK5
-- We can serialize a 'Validator' directly to CBOR
serialisedDateValidator :: SerialisedScript
Expand Down
2 changes: 0 additions & 2 deletions plutus-benchmark/marlowe/exe/PlutusBenchmark/Marlowe/Util.hs
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,3 @@ makeBuiltinData =
. LBS.fromStrict
. fromBuiltin
. getLedgerBytes


Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

### Added

- Added functions for converting between `Lovelace` and `Value`: `lovelaceValue`
and `lovelaceValueOf`.
19 changes: 14 additions & 5 deletions plutus-ledger-api/src/PlutusLedgerApi/V1/Value.hs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ module PlutusLedgerApi.V1.Value (
, Value(..)
, singleton
, valueOf
, lovelaceValue
, lovelaceValueOf
, scale
, symbols
-- * Partial order operations
Expand Down Expand Up @@ -69,6 +71,7 @@ import PlutusTx.AssocMap qualified as Map
import PlutusTx.Lift (makeLift)
import PlutusTx.Ord qualified as Ord
import PlutusTx.Prelude as PlutusTx hiding (sort)
import PlutusTx.Show qualified as PlutusTx
import PlutusTx.These (These (..))
import Prettyprinter (Pretty, (<>))
import Prettyprinter.Extras (PrettyShow (PrettyShow))
Expand Down Expand Up @@ -176,10 +179,6 @@ quotes and we write the latter with a lower case "v" and without the quotes, i.e
-- See Note [Value vs value].
{- | The 'Value' type represents a collection of amounts of different currencies.
We can think of 'Value' as a vector space whose dimensions are currencies.
To create a value of 'Value', we need to specify a currency. This can be done
using 'Ledger.Ada.adaValueOf'. To get the ada dimension of 'Value' we use
'Ledger.Ada.fromValue'. Plutus contract authors will be able to define modules
similar to 'Ledger.Ada' for their own currencies.
Operations on currencies are usually implemented /pointwise/. That is,
we apply the operation to the quantities for each currency in turn. So
Expand Down Expand Up @@ -262,6 +261,15 @@ symbols (Value mp) = Map.keys mp
singleton :: CurrencySymbol -> TokenName -> Integer -> Value
singleton c tn i = Value (Map.singleton c (Map.singleton tn i))

lovelaceValue :: Lovelace -> Value
-- | A 'Value' containing the given quantity of Lovelace.
lovelaceValue = singleton adaSymbol adaToken . getLovelace

{-# INLINABLE lovelaceValueOf #-}
-- | Get the quantity of Lovelace in the 'Value'.
lovelaceValueOf :: Value -> Lovelace
lovelaceValueOf v = Lovelace (valueOf v adaSymbol adaToken)

{-# INLINABLE assetClassValue #-}
-- | A 'Value' containing the given amount of the asset class.
assetClassValue :: AssetClass -> Integer -> Value
Expand Down Expand Up @@ -443,7 +451,7 @@ eqMapWith is0 eqV (Map.toList -> xs1) (Map.toList -> xs2) = unordEqWith is0 eqV
eq :: Value -> Value -> Bool
eq (Value currs1) (Value currs2) = eqMapWith (Map.all (0 ==)) (eqMapWith (0 ==) (==)) currs1 currs2

newtype Lovelace = Lovelace Integer
newtype Lovelace = Lovelace { getLovelace :: Integer }
deriving stock (Generic)
deriving (Pretty) via (PrettyShow Lovelace)
deriving newtype
Expand All @@ -461,6 +469,7 @@ newtype Lovelace = Lovelace Integer
, PlutusTx.AdditiveSemigroup
, PlutusTx.AdditiveMonoid
, PlutusTx.AdditiveGroup
, PlutusTx.Show
)

makeLift ''CurrencySymbol
Expand Down

0 comments on commit ef082e1

Please sign in to comment.