<p>In order to collect and filter by datum in offchain code you can use <strong>collectFromScriptFilter</strong> from <strong>Plutus.Contract</strong>. I've implemented a simple example showing the use case.</p>
<pre><code>{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE DerivingStrategies  #-}
{-# LANGUAGE DeriveAnyClass      #-}
{-# LANGUAGE DeriveGeneric       #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE NoImplicitPrelude   #-}
{-# LANGUAGE NumericUnderscores  #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell     #-}
{-# LANGUAGE TypeApplications    #-}
{-# LANGUAGE TypeFamilies        #-}
{-# LANGUAGE TypeOperators       #-}
{-# LANGUAGE RecordWildCards     #-}

module Week05.OffchainFilterByDatumAndCollect where

import           Control.Monad        hiding (fmap)
import           Data.Aeson           (FromJSON, ToJSON)
import           Data.Text            (Text)
import           GHC.Generics         (Generic)
import           Plutus.Contract
import           Ledger               hiding (singleton)
import           Ledger.Ada           as Ada
import           Ledger.Constraints   as Constraints
import qualified Ledger.Typed.Scripts as Scripts
import           Plutus.Trace.Emulator  as Emulator
import qualified PlutusTx
import           PlutusTx.Prelude     hiding (Semigroup(..), unless)
import           Prelude              (IO, Semigroup (..), String, Show(..))
import qualified Prelude              as Haskell
import           Text.Printf          (printf)
import qualified Ledger.Tx            as Tx
import           Wallet.Emulator.Wallet ( knownWallet )

type Field1 = Integer
type Field2 = Integer

data MyParams = MyParams 
    { mpField1 :: Field1
    , mpField2 :: Field2
    } deriving stock (Haskell.Eq, Haskell.Show, Generic)
      deriving anyclass (ToJSON, FromJSON)

data MyDatum = MyDatum 
    { mdField1 :: Field1
    , myField2 :: Field2
    } deriving Show

PlutusTx.unstableMakeIsData ''MyDatum 

{-# INLINABLE mkValidator #-}
mkValidator :: MyDatum -&gt; () -&gt; ScriptContext -&gt; Bool
mkValidator _ _ _ = True

data Typed
instance Scripts.ValidatorTypes Typed where
    type instance DatumType Typed = MyDatum
    type instance RedeemerType Typed = ()

typedValidator :: Scripts.TypedValidator Typed
typedValidator = Scripts.mkTypedValidator @Typed
    $$(PlutusTx.compile [|| mkValidator ||])
    $$(PlutusTx.compile [|| wrap ||])
  where
    wrap = Scripts.wrapValidator @MyDatum @()

validator :: Validator
validator = Scripts.validatorScript typedValidator

valHash :: Ledger.ValidatorHash
valHash = Scripts.validatorHash typedValidator

scrAddress :: Ledger.Address
scrAddress = scriptAddress validator

type GiftSchema =
            Endpoint &quot;give&quot; (Integer, MyParams)
        .\/ Endpoint &quot;grab&quot; MyParams

give :: AsContractError e =&gt; (Integer, MyParams) -&gt; Contract w s e ()
give (amount, MyParams{..}) = do
    let dat = MyDatum mpField1 mpField2
        lookups = Constraints.typedValidatorLookups typedValidator
        tx      = mustPayToTheScript dat $ Ada.lovelaceValueOf amount
    utx  &lt;- mkTxConstraints lookups tx
    txid &lt;- getCardanoTxId &lt;$&gt; submitUnbalancedTx (Constraints.adjustUnbalancedTx utx) 
    void $ awaitTxConfirmed txid
    logInfo @String $ printf &quot;made a gift of %d lovelace&quot; amount
    
grab :: forall w s e. AsContractError e =&gt; MyParams -&gt; Contract w s e ()
grab MyParams{..} = do
    utxos &lt;- utxosAt scrAddress
    let dat     = MyDatum mpField1 mpField2
        flt _ ciTxOut = either id Ledger.datumHash (Tx._ciTxOutDatum ciTxOut) == Ledger.datumHash (Datum (PlutusTx.toBuiltinData dat))
        lookups = Constraints.unspentOutputs utxos &lt;&gt;
                  Constraints.typedValidatorLookups typedValidator
        tx      = collectFromScriptFilter flt utxos ()
    utx  &lt;- mkTxConstraints lookups tx
    txid &lt;- getCardanoTxId &lt;$&gt; submitUnbalancedTx (Constraints.adjustUnbalancedTx utx) 
    void $ awaitTxConfirmed txid
    logInfo @String $ &quot;collected gifts&quot;

endpoints :: Contract () GiftSchema Text ()
endpoints = awaitPromise (give' `select` grab') &gt;&gt; endpoints
  where
    give' = endpoint @&quot;give&quot; give
    grab' = endpoint @&quot;grab&quot; grab

-- w1 gives 10 (datum1) + 20 (datum2)
-- w2 grab  10 (datum1)
-- script locks 20 (datum2)
test :: IO ()
test = runEmulatorTraceIO $ do
    let params1 = MyParams 1 1
        params2 = MyParams 2 2
    h1 &lt;- activateContractWallet (knownWallet 1) endpoints
    h2 &lt;- activateContractWallet (knownWallet 2) endpoints
    callEndpoint @&quot;give&quot; h1 (10_000_000, params1)
    void $ Emulator.waitNSlots 1
    callEndpoint @&quot;give&quot; h1 (20_000_000, params2)
    void $ Emulator.waitNSlots 1
    callEndpoint @&quot;grab&quot; h2 params1
    void $ Emulator.waitNSlots 1

</code></pre>
<p>In <strong>plutus-use-cases</strong> repo you can find more interesting examples:</p>
<ul>
<li><p><a href="https://github.com/input-output-hk/plutus-apps/blob/main/plutus-use-cases/src/Plutus/Contracts/Crowdfunding.hs" rel="nofollow noreferrer">https://github.com/input-output-hk/plutus-apps/blob/main/plutus-use-cases/src/Plutus/Contracts/Crowdfunding.hs</a></p>
</li>
<li><p><a href="https://github.com/input-output-hk/plutus-apps/blob/main/plutus-use-cases/src/Plutus/Contracts/Escrow.hs" rel="nofollow noreferrer">https://github.com/input-output-hk/plutus-apps/blob/main/plutus-use-cases/src/Plutus/Contracts/Escrow.hs</a></p>
</li>
</ul>

CC BY-SA 4.0
2022-02-13T15:34:55.847Z
2022-02-13T16:16:37.473Z
2022-02-13T16:16:37.473Z
kindofdev
<p>I Have 1000 utxo's sitting at a script address with unique datums is there documentation for a validator so that when collectFromScript is called it only pulls 1 utxo based on the user input matching with the datum of one of the utxo's sitting at the script?</p>

CC BY-SA 4.0
2022-02-12T20:06:25.277Z
Do you want to filter by datum in offchain code?
kindofdev
CC BY-SA 4.0
2022-02-13T01:58:48.397Z
I want to filter by off-chain code preferably
Floof99
CC BY-SA 4.0
2022-02-14T09:53:11.000Z
Did my answer solve your doubt?
kindofdev
CC BY-SA 4.0
2022-02-14T13:30:41.343Z
yes for sure thank you so much could another way to do this also be mustSpendScriptOutput
Floof99
CC BY-SA 4.0
2022-02-14T15:07:19.897Z
You can achieve the same thing in 2 steps: filter the map and then use mustSpendScriptOutput like in the following code snippet I've created for you: https://gist.github.com/kindofdev/47cf9e650fbd6a651e471a5e67462a9a
Don't forget up vote the answer ;)
kindofdev
<plutus><datum><offchain>
Documentation for filtering through the inputs of a Plutus Script
# Documentation for filtering through the inputs of a Plutus Script

(Asked by: username_0 on 2022-02-12)

I Have 1000 utxo's sitting at a script address with unique datums is there documentation for a validator so that when collectFromScript is called it only pulls 1 utxo based on the user input matching with the datum of one of the utxo's sitting at the script?

**Tags:** plutus, datum, offchain
> **Comments:**
> **username_1**: Do you want to filter by datum in offchain code?  
> **username_0**: I want to filter by off-chain code preferably  
> **username_1**: Did my answer solve your doubt?  
> **username_0**: yes for sure thank you so much could another way to do this also be mustSpendScriptOutput  
> **username_1**: You can achieve the same thing in 2 steps: filter the map and then use mustSpendScriptOutput like in the following code snippet I've created for you: https://gist.github.com/kindofdev/47cf9e650fbd6a651e471a5e67462a9a Don't forget up vote the answer ;)  

---

## 1 answers

### Answer by username_1 on 2022-02-13. Score: 0 | Accepted answer

In order to collect and filter by datum in offchain code you can use collectFromScriptFilter from Plutus.Contract. I've implemented a simple example showing the use case.
{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE DerivingStrategies  #-}
{-# LANGUAGE DeriveAnyClass      #-}
{-# LANGUAGE DeriveGeneric       #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE NoImplicitPrelude   #-}
{-# LANGUAGE NumericUnderscores  #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell     #-}
{-# LANGUAGE TypeApplications    #-}
{-# LANGUAGE TypeFamilies        #-}
{-# LANGUAGE TypeOperators       #-}
{-# LANGUAGE RecordWildCards     #-}

module Week05.OffchainFilterByDatumAndCollect where

import           Control.Monad        hiding (fmap)
import           Data.Aeson           (FromJSON, ToJSON)
import           Data.Text            (Text)
import           GHC.Generics         (Generic)
import           Plutus.Contract
import           Ledger               hiding (singleton)
import           Ledger.Ada           as Ada
import           Ledger.Constraints   as Constraints
import qualified Ledger.Typed.Scripts as Scripts
import           Plutus.Trace.Emulator  as Emulator
import qualified PlutusTx
import           PlutusTx.Prelude     hiding (Semigroup(..), unless)
import           Prelude              (IO, Semigroup (..), String, Show(..))
import qualified Prelude              as Haskell
import           Text.Printf          (printf)
import qualified Ledger.Tx            as Tx
import           Wallet.Emulator.Wallet ( knownWallet )

type Field1 = Integer
type Field2 = Integer

data MyParams = MyParams 
    { mpField1 :: Field1
    , mpField2 :: Field2
    } deriving stock (Haskell.Eq, Haskell.Show, Generic)
      deriving anyclass (ToJSON, FromJSON)

data MyDatum = MyDatum 
    { mdField1 :: Field1
    , myField2 :: Field2
    } deriving Show

PlutusTx.unstableMakeIsData ''MyDatum 

{-# INLINABLE mkValidator #-}
mkValidator :: MyDatum -> () -> ScriptContext -> Bool
mkValidator _ _ _ = True

data Typed
instance Scripts.ValidatorTypes Typed where
    type instance DatumType Typed = MyDatum
    type instance RedeemerType Typed = ()

typedValidator :: Scripts.TypedValidator Typed
typedValidator = Scripts.mkTypedValidator @Typed
    $$(PlutusTx.compile [|| mkValidator ||])
    $$(PlutusTx.compile [|| wrap ||])
  where
    wrap = Scripts.wrapValidator @MyDatum @()

validator :: Validator
validator = Scripts.validatorScript typedValidator

valHash :: Ledger.ValidatorHash
valHash = Scripts.validatorHash typedValidator

scrAddress :: Ledger.Address
scrAddress = scriptAddress validator

type GiftSchema =
            Endpoint "give" (Integer, MyParams)
        .\/ Endpoint "grab" MyParams

give :: AsContractError e => (Integer, MyParams) -> Contract w s e ()
give (amount, MyParams{..}) = do
    let dat = MyDatum mpField1 mpField2
        lookups = Constraints.typedValidatorLookups typedValidator
        tx      = mustPayToTheScript dat $ Ada.lovelaceValueOf amount
    utx  <- mkTxConstraints lookups tx
    txid <- getCardanoTxId <$> submitUnbalancedTx (Constraints.adjustUnbalancedTx utx) 
    void $ awaitTxConfirmed txid
    logInfo @String $ printf "made a gift of %d lovelace" amount
    
grab :: forall w s e. AsContractError e => MyParams -> Contract w s e ()
grab MyParams{..} = do
    utxos <- utxosAt scrAddress
    let dat     = MyDatum mpField1 mpField2
        flt _ ciTxOut = either id Ledger.datumHash (Tx._ciTxOutDatum ciTxOut) == Ledger.datumHash (Datum (PlutusTx.toBuiltinData dat))
        lookups = Constraints.unspentOutputs utxos <>
                  Constraints.typedValidatorLookups typedValidator
        tx      = collectFromScriptFilter flt utxos ()
    utx  <- mkTxConstraints lookups tx
    txid <- getCardanoTxId <$> submitUnbalancedTx (Constraints.adjustUnbalancedTx utx) 
    void $ awaitTxConfirmed txid
    logInfo @String $ "collected gifts"

endpoints :: Contract () GiftSchema Text ()
endpoints = awaitPromise (give' `select` grab') >> endpoints
  where
    give' = endpoint @"give" give
    grab' = endpoint @"grab" grab

-- w1 gives 10 (datum1) + 20 (datum2)
-- w2 grab  10 (datum1)
-- script locks 20 (datum2)
test :: IO ()
test = runEmulatorTraceIO $ do
    let params1 = MyParams 1 1
        params2 = MyParams 2 2
    h1 <- activateContractWallet (knownWallet 1) endpoints
    h2 <- activateContractWallet (knownWallet 2) endpoints
    callEndpoint @"give" h1 (10_000_000, params1)
    void $ Emulator.waitNSlots 1
    callEndpoint @"give" h1 (20_000_000, params2)
    void $ Emulator.waitNSlots 1
    callEndpoint @"grab" h2 params1
    void $ Emulator.waitNSlots 1


In plutus-use-cases repo you can find more interesting examples:

https://github.com/input-output-hk/plutus-apps/blob/main/plutus-use-cases/src/Plutus/Contracts/Crowdfunding.hs

https://github.com/input-output-hk/plutus-apps/blob/main/plutus-use-cases/src/Plutus/Contracts/Escrow.hs


---

