Skip to content

Commit

Permalink
Merge pull request #474 from input-output-hk/j-mueller/tutorial
Browse files Browse the repository at this point in the history
wallet-api: Improve tutorial
  • Loading branch information
michaelpj committed Jan 17, 2019
2 parents 2805297 + 4228882 commit a6d7600
Show file tree
Hide file tree
Showing 26 changed files with 416 additions and 280 deletions.
2 changes: 1 addition & 1 deletion docs/model/UTxO.hsproj/Ledger.hs
Expand Up @@ -94,7 +94,7 @@ txIn :: TxId -> Int -> Witness -> TxIn
txIn txId idx wit = TxIn (TxOutRef txId idx) wit

---- Equality of transaction inputs is only predicated on the output that the input
---- refers to, *not* on the witness. This is curcial so that two 'TxIn' values
---- refers to, *not* on the witness. This is crucial so that two 'TxIn values
---- spending the same input are considered the same.
----
--instance Eq TxIn where
Expand Down
8 changes: 4 additions & 4 deletions plutus-playground/plutus-playground-client/src/Chain.purs
Expand Up @@ -26,7 +26,7 @@ import Halogen.ECharts (EChartsEffects, echarts)
import Halogen.HTML (ClassName(ClassName), br_, div, div_, h2_, h3_, slot', text)
import Halogen.HTML.Events (input)
import Halogen.HTML.Properties (class_)
import Ledger.Types (Slot(..), TxId(..), Value)
import Ledger.Types (Slot(..), TxIdOf(..), Value)
import Playground.API (EvaluationResult(EvaluationResult))
import Prelude (class Monad, Unit, discard, map, show, unit, ($), (<$>), (<>), (>>>))
import Types (BalancesChartSlot(BalancesChartSlot), ChildQuery, ChildSlot, MockchainChartSlot(MockchainChartSlot), Query(HandleBalancesChartMessage, HandleMockchainChartMessage), cpBalancesChart, cpMockchainChart)
Expand Down Expand Up @@ -69,15 +69,15 @@ evaluationPane (EvaluationResult {emulatorLog}) =
]

emulatorEventPane :: forall i p. EmulatorEvent -> HTML p i
emulatorEventPane (TxnSubmit (TxId txId)) =
emulatorEventPane (TxnSubmit (TxIdOf txId)) =
div_
[ text $ "Submitting transaction: " <> txId.getTxId ]

emulatorEventPane (TxnValidate (TxId txId)) =
emulatorEventPane (TxnValidate (TxIdOf txId)) =
div_
[ text $ "Validating transaction: " <> txId.getTxId ]

emulatorEventPane (TxnValidationFail (TxId txId) error) =
emulatorEventPane (TxnValidationFail (TxIdOf txId) error) =
div [ class_ $ ClassName "error" ]
[ text $ "Validation failed for transaction: " <> txId.getTxId
, br_
Expand Down
Expand Up @@ -11,7 +11,7 @@ import qualified Data.Map as Map
import Data.Monoid (Sum (Sum), getSum)
import qualified Data.Set as Set
import qualified Data.Typeable as T
import Ledger.Types (Blockchain, PubKey (PubKey), Tx, TxOut (txOutValue), Value (Value))
import Ledger.Types (Blockchain, PubKey (PubKey), Tx, TxOutOf (txOutValue), Value (Value))
import Playground.API (PlaygroundError (OtherError))
import Wallet.Emulator.Types (EmulatorEvent, EmulatorState (_chainNewestFirst, _emulatorLog), MockWallet,
Trace, Wallet (Wallet), ownFunds, processPending, runTraceTxPool,
Expand Down
16 changes: 8 additions & 8 deletions plutus-playground/plutus-playground-server/app/PSGenerator.hs
Expand Up @@ -29,9 +29,9 @@ import Language.PureScript.Bridge (BridgeData, BridgePa
import Language.PureScript.Bridge.PSTypes (psArray, psInt, psString)
import Language.PureScript.Bridge.TypeParameters (A)
import Ledger.Index (ValidationError)
import Ledger.Types (Address, DataScript, PubKey, RedeemerScript, Signature,
Slot, Tx, TxId, TxIn, TxInType, TxOut, TxOutRef, TxOutType,
ValidatorScript, Value)
import Ledger.Types (AddressOf, DataScript, PubKey, RedeemerScript, Signature,
Slot, Tx, TxIdOf, TxInOf, TxInType, TxOutOf, TxOutRefOf,
TxOutType, ValidatorScript, Value)
import Playground.API (CompilationError, Evaluation, EvaluationResult, Expression,
Fn, FunctionSchema, SimpleArgumentSchema, SourceCode)
import qualified Playground.API as API
Expand Down Expand Up @@ -154,16 +154,16 @@ myTypes =
, mkSumType (Proxy @Slot)
, mkSumType (Proxy @WalletAPIError)
, mkSumType (Proxy @Tx)
, mkSumType (Proxy @(TxIn A))
, mkSumType (Proxy @(TxOutRef A))
, mkSumType (Proxy @(TxInOf A))
, mkSumType (Proxy @(TxOutRefOf A))
, mkSumType (Proxy @TxOutType)
, mkSumType (Proxy @(TxOut A))
, mkSumType (Proxy @(TxId A))
, mkSumType (Proxy @(TxOutOf A))
, mkSumType (Proxy @(TxIdOf A))
, mkSumType (Proxy @TxInType)
, mkSumType (Proxy @Signature)
, mkSumType (Proxy @Value)
, mkSumType (Proxy @PubKey)
, mkSumType (Proxy @(Address A))
, mkSumType (Proxy @(AddressOf A))
, mkSumType (Proxy @FlowLink)
, mkSumType (Proxy @TxRef)
, mkSumType (Proxy @UtxOwner)
Expand Down
Expand Up @@ -128,7 +128,7 @@ contributionScript cmp = ValidatorScript val where
if isValid then () else $$(P.error) () ||])

-- | The address of a [[Campaign]]
campaignAddress :: Campaign -> Ledger.Address'
campaignAddress :: Campaign -> Ledger.Address
campaignAddress = Ledger.scriptAddress . contributionScript

-- | Contribute funds to the campaign (contributor)
Expand Down Expand Up @@ -185,7 +185,7 @@ collectFundsTrigger c = andT
(slotRangeT (Interval (campaignDeadline c) (campaignCollectionDeadline c)))

-- | Claim a refund of our campaign contribution
refundHandler :: TxId' -> Signature -> Campaign -> EventHandler MockWallet
refundHandler :: TxId -> Signature -> Campaign -> EventHandler MockWallet
refundHandler txid signature cmp = EventHandler (\_ -> do
logMsg "Claiming refund"
let validatorScript = contributionScript cmp
Expand Down
Expand Up @@ -51,7 +51,7 @@ gameValidator = ValidatorScript (Ledger.fromCompiledCode $$(PlutusTx.compile [||
||]))

-- | The address of the game (the hash of its validator script)
gameAddress :: Address'
gameAddress :: Address
gameAddress = Ledger.scriptAddress gameValidator

-- | The "lock" contract endpoint. See note [Contract endpoints]
Expand Down
Expand Up @@ -34,7 +34,7 @@ import GHC.Generics (Generic)

import qualified Language.PlutusTx as PlutusTx
import Ledger (DataScript (..), Signature(..), PubKey (..),
TxId', ValidatorScript (..), Value (..), scriptTxIn, Slot(..))
TxId, ValidatorScript (..), Value (..), scriptTxIn, Slot(..))
import qualified Ledger as Ledger
import Ledger.Validation (PendingTx (..), PendingTxIn (..), PendingTxOut)
import qualified Ledger.Validation as Validation
Expand Down Expand Up @@ -98,7 +98,7 @@ collect cmp = register (collectFundsTrigger cmp) $ EventHandler $ \_ -> do


-- | The address of a [[Campaign]]
campaignAddress :: Campaign -> Ledger.Address'
campaignAddress :: Campaign -> Ledger.Address
campaignAddress = Ledger.scriptAddress . contributionScript

-- | The validator script that determines whether the campaign owner can
Expand Down Expand Up @@ -192,7 +192,7 @@ collectFundsTrigger c = andT
(slotRangeT $ Interval (campaignDeadline c) (campaignCollectionDeadline c))

-- | Claim a refund of our campaign contribution
refund :: (WalletAPI m, WalletDiagnostics m) => TxId' -> Campaign -> EventHandler m
refund :: (WalletAPI m, WalletDiagnostics m) => TxId -> Campaign -> EventHandler m
refund txid cmp = EventHandler $ \_ -> do
logMsg "Claiming refund"
am <- watchedAddresses
Expand Down
Expand Up @@ -29,7 +29,7 @@ import Data.Maybe (maybeToList)
import qualified Data.Set as Set
import GHC.Generics (Generic)
import qualified Language.PlutusTx as PlutusTx
import Ledger (DataScript (..), Slot(..), PubKey, TxOutRef', Value (..), ValidatorScript (..), scriptTxIn, scriptTxOut)
import Ledger (DataScript (..), Slot(..), PubKey, TxOutRef, Value (..), ValidatorScript (..), scriptTxIn, scriptTxOut)
import qualified Ledger as Ledger
import Ledger.Validation (OracleValue (..), PendingTx (..), PendingTxIn(..), PendingTxOut (..),
PendingTxOutType (..))
Expand Down Expand Up @@ -92,7 +92,7 @@ initialise long short f = do
settle :: (
MonadError WalletAPIError m,
WalletAPI m)
=> [TxOutRef']
=> [TxOutRef]
-> Future
-> FutureData
-> OracleValue Value
Expand All @@ -116,7 +116,7 @@ settle refs ft fd ov = do
settleEarly :: (
MonadError WalletAPIError m,
WalletAPI m)
=> [TxOutRef']
=> [TxOutRef]
-> Future
-> FutureData
-> OracleValue Value
Expand All @@ -131,7 +131,7 @@ settleEarly refs ft fd ov = do
adjustMargin :: (
MonadError WalletAPIError m,
WalletAPI m)
=> [TxOutRef']
=> [TxOutRef]
-> Future
-> FutureData
-> Ledger.Value
Expand Down
Expand Up @@ -34,7 +34,7 @@ gameValidator = ValidatorScript (Ledger.fromCompiledCode $$(PlutusTx.compile [||

||]))

gameAddress :: Address'
gameAddress :: Address
gameAddress = Ledger.scriptAddress gameValidator

lock :: (WalletAPI m, WalletDiagnostics m) => String -> Value -> m ()
Expand Down
Expand Up @@ -23,7 +23,7 @@ import GHC.Generics (Generic)
import Ledger.Validation (PendingTx (..), PendingTxOut (..), PendingTxOutType (..),
ValidatorHash)
import qualified Language.PlutusTx as PlutusTx
import Ledger (DataScript (..), Slot(..), PubKey (..), TxOutRef', ValidatorScript (..), Value (..), scriptTxIn, scriptTxOut)
import Ledger (DataScript (..), Slot(..), PubKey (..), TxOutRef, ValidatorScript (..), Value (..), scriptTxIn, scriptTxOut)
import qualified Ledger as Ledger
import qualified Ledger.Validation as Validation
import Prelude hiding ((&&))
Expand Down Expand Up @@ -83,7 +83,7 @@ retrieveFunds :: (
WalletAPI m)
=> Vesting
-> VestingData -- ^ Value that has already been taken out
-> TxOutRef' -- ^ Transaction output locked by the vesting validator script
-> TxOutRef -- ^ Transaction output locked by the vesting validator script
-> Ledger.Value -- ^ Value we want to take out now
-> m VestingData
retrieveFunds vs vd r vnow = do
Expand Down
6 changes: 3 additions & 3 deletions plutus-use-cases/test/Spec/Future.hs
Expand Up @@ -29,19 +29,19 @@ tests = testGroup "futures" [
testProperty "increase the margin" increaseMargin
]

init :: Wallet -> Trace MockWallet Ledger.TxOutRef'
init :: Wallet -> Trace MockWallet Ledger.TxOutRef
init w = outp <$> walletAction w (F.initialise (PubKey 1) (PubKey 2) contract) where
outp = snd . head . filter (Ledger.isPayToScriptOut . fst) . Ledger.txOutRefs . head

adjustMargin :: Wallet -> [Ledger.TxOutRef'] -> FutureData -> Ledger.Value -> Trace MockWallet Ledger.TxOutRef'
adjustMargin :: Wallet -> [Ledger.TxOutRef] -> FutureData -> Ledger.Value -> Trace MockWallet Ledger.TxOutRef
adjustMargin w refs fd vl =
outp <$> walletAction w (F.adjustMargin refs contract fd vl) where
outp = snd . head . filter (Ledger.isPayToScriptOut . fst) . Ledger.txOutRefs . head

-- | Initialise the futures contract with contributions from wallets 1 and 2,
-- and update all wallets. Running `initBoth` will increase the slot number
-- by 2.
initBoth :: Trace MockWallet [Ledger.TxOutRef']
initBoth :: Trace MockWallet [Ledger.TxOutRef]
initBoth = do
updateAll
ins <- traverse init [w1, w2]
Expand Down
2 changes: 1 addition & 1 deletion plutus-use-cases/test/Spec/Vesting.hs
Expand Up @@ -50,7 +50,7 @@ scen1 = VestingScenario{..} where
-- | Commit some funds from a wallet to a vesting scheme. Returns the reference
-- to the transaction output that is locked by the schemes's validator
-- script (and can be collected by the scheme's owner)
commit :: Wallet -> Vesting -> Ledger.Value -> Trace MockWallet Ledger.TxOutRef'
commit :: Wallet -> Vesting -> Ledger.Value -> Trace MockWallet Ledger.TxOutRef
commit w vv vl = exScriptOut <$> walletAction w (void $ vestFunds vv vl) where
exScriptOut = snd . head . filter (Ledger.isPayToScriptOut . fst) . Ledger.txOutRefs . head

Expand Down
32 changes: 16 additions & 16 deletions wallet-api/src/Ledger/Index.hs
Expand Up @@ -32,8 +32,8 @@ import qualified Data.Map as Map
import Data.Semigroup (Semigroup, Sum (..))
import qualified Data.Set as Set
import GHC.Generics (Generic)
import Ledger.Types (Blockchain, DataScript, PubKey, Signature, Slot (..), Tx (..), TxIn (..), TxIn',
TxOut (..), TxOut', TxOutRef', ValidationData (..), Value, lifted, updateUtxo,
import Ledger.Types (Blockchain, DataScript, PubKey, Signature, Slot (..), Tx (..), TxIn, TxInOf (..),
TxOut, TxOutOf (..), TxOutRef, ValidationData (..), Value, lifted, updateUtxo,
validValuesTx)
import qualified Ledger.Types as Ledger
import Ledger.Validation (PendingTx (..))
Expand All @@ -45,7 +45,7 @@ import Prelude hiding (lookup)
type ValidationMonad m = (MonadReader UtxoIndex m, MonadError ValidationError m)

-- | The transactions of a blockchain indexed by hash
newtype UtxoIndex = UtxoIndex { getIndex :: Map.Map TxOutRef' TxOut' }
newtype UtxoIndex = UtxoIndex { getIndex :: Map.Map TxOutRef TxOut }
deriving (Eq, Ord, Show, Semigroup)

-- | An empty [[UtxoIndex]]
Expand All @@ -65,15 +65,15 @@ insertBlock :: [Tx] -> UtxoIndex -> UtxoIndex
insertBlock blck i = foldl' (flip insert) i blck

-- | Find an unspent transaction output by the `TxOutRef'` that spends it.
lookup :: TxOutRef' -> UtxoIndex -> Either ValidationError TxOut'
lookup :: TxOutRef -> UtxoIndex -> Either ValidationError TxOut
lookup i =
maybe (Left $ TxOutRefNotFound i) Right . Map.lookup i . getIndex

-- | Reason why a transaction is invalid
data ValidationError =
InOutTypeMismatch TxIn' TxOut'
InOutTypeMismatch TxIn TxOut
-- ^ A pay-to-pubkey output was consumed by a pay-to-script input or vice versa
| TxOutRefNotFound TxOutRef'
| TxOutRefNotFound TxOutRef
-- ^ The unspent transaction output consumed by a transaction input could not be found (either because it was already spent, or because there was no transaction with the given hash on the blockchain)
| InvalidScriptHash DataScript
-- ^ (for pay-to-script outputs) The validator script provided in the transaction input does not match the hash specified in the transaction output
Expand All @@ -97,15 +97,15 @@ newtype Validation a = Validation { _runValidation :: (ReaderT UtxoIndex (Either
runValidation :: Validation a -> UtxoIndex -> Either ValidationError a
runValidation l = runReaderT (_runValidation l)

-- | Determine the unspent value that a [[TxOutRef']] refers to
lkpValue :: ValidationMonad m => TxOutRef' -> m Value
-- | Determine the unspent value that a [[TxOutRef]] refers to
lkpValue :: ValidationMonad m => TxOutRef -> m Value
lkpValue = fmap txOutValue . lkpTxOut

-- | Find an unspent transaction output by its reference. Assumes that the
-- output for this reference exists. If you want to handle the lookup error
-- you can use `runLookup`.
-- Determine the transaction output that a [[TxOutRef']] refers to
lkpTxOut :: ValidationMonad m => TxOutRef' -> m TxOut'
lkpTxOut :: ValidationMonad m => TxOutRef -> m TxOut
lkpTxOut t = liftEither . lookup t =<< ask

-- | Validate a transaction in a `ValidationMonad` context.
Expand All @@ -130,23 +130,23 @@ checkValidInputs h tx = do
traverse_ (checkMatch vld) matches

-- | Match each input of the transaction with its output
lkpOutputs :: ValidationMonad m => Tx -> m [(TxIn', TxOut')]
lkpOutputs :: ValidationMonad m => Tx -> m [(TxIn, TxOut)]
lkpOutputs = traverse (\t -> traverse (lkpTxOut . txInRef) (t, t)) . Set.toList . txInputs

-- | Matching pair of transaction input and transaction output.
data InOutMatch =
ScriptMatch
TxIn'
TxIn
Ledger.ValidatorScript
Ledger.RedeemerScript
DataScript
(Ledger.Address (Digest SHA256))
(Ledger.AddressOf (Digest SHA256))
| PubKeyMatch PubKey Signature
deriving (Eq, Ord, Show)

-- | Match a transaction input with the output that it consumes, ensuring that
-- both are of the same type (pubkey or pay-to-script)
matchInputOutput :: ValidationMonad m => TxIn' -> TxOut' -> m InOutMatch
matchInputOutput :: ValidationMonad m => TxIn -> TxOut -> m InOutMatch
matchInputOutput i txo = case (txInType i, txOutType txo) of
(Ledger.ConsumeScriptAddress v r, Ledger.PayToScript d) ->
pure $ ScriptMatch i v r d (txOutAddress txo)
Expand Down Expand Up @@ -211,7 +211,7 @@ validationData h tx = rump <$> ins where
-- this is changed accordingly in `checkMatch` during validation
}

mkOut :: TxOut' -> Validation.PendingTxOut
mkOut :: TxOut -> Validation.PendingTxOut
mkOut t = Validation.PendingTxOut (txOutValue t) d tp where
(d, tp) = case txOutType t of
Ledger.PayToScript scrpt ->
Expand All @@ -222,7 +222,7 @@ mkOut t = Validation.PendingTxOut (txOutValue t) d tp where
(Just (validatorHash, dataScriptHash), Validation.DataTxOut)
Ledger.PayToPubKey pk -> (Nothing, Validation.PubKeyTxOut pk)

mkIn :: ValidationMonad m => TxIn' -> m Validation.PendingTxIn
mkIn :: ValidationMonad m => TxIn -> m Validation.PendingTxIn
mkIn i = Validation.PendingTxIn <$> pure ref <*> pure red <*> vl where
ref =
let hash = Validation.plcTxHash . Ledger.txOutRefId $ txInRef i
Expand All @@ -237,5 +237,5 @@ mkIn i = Validation.PendingTxIn <$> pure ref <*> pure red <*> vl where
Right sig
vl = valueOf i

valueOf :: ValidationMonad m => Ledger.TxIn' -> m Value
valueOf :: ValidationMonad m => Ledger.TxIn -> m Value
valueOf = lkpValue . txInRef

0 comments on commit a6d7600

Please sign in to comment.