{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE DeriveAnyClass      #-}
{-# LANGUAGE DeriveGeneric       #-}
{-# LANGUAGE DerivingStrategies  #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE NamedFieldPuns      #-}
{-# LANGUAGE NoImplicitPrelude   #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE RecordWildCards     #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell     #-}
{-# LANGUAGE TypeApplications    #-}
{-# LANGUAGE TypeFamilies        #-}
{-# LANGUAGE TypeOperators       #-}
{-# OPTIONS_GHC -fno-ignore-interface-pragmas #-}
-- | Implements an n-out-of-m multisig contract.
module Plutus.Contracts.MultiSig
    ( MultiSig(..)
    , MultiSigSchema
    , contract
    , lock
    , typedValidator
    , validate
    ) where

import Cardano.Node.Emulator.Internal.Node (pNetworkId)
import Control.Monad (void)
import Data.Aeson (FromJSON, ToJSON)
import GHC.Generics (Generic)
import Ledger
import Ledger.Tx.Constraints qualified as Constraints
import Ledger.Typed.Scripts qualified as Scripts
import Plutus.Contract
import Plutus.Script.Utils.V2.Typed.Scripts qualified as V2
import Plutus.V2.Ledger.Api as Plutus (Value)
import Plutus.V2.Ledger.Contexts as V2
import PlutusTx qualified
import PlutusTx.Prelude hiding (Semigroup (..), foldMap)

import Prelude as Haskell (Semigroup (..), Show, foldMap)

type MultiSigSchema =
        Endpoint "lock" (MultiSig, Plutus.Value)
        .\/ Endpoint "unlock" (MultiSig, [PaymentPubKeyHash])

data MultiSig =
        MultiSig
                { MultiSig -> [PaymentPubKeyHash]
signatories      :: [Ledger.PaymentPubKeyHash]
                -- ^ List of public keys of people who may sign the transaction
                , MultiSig -> Integer
minNumSignatures :: Integer
                -- ^ Minimum number of signatures required to unlock
                --   the output (should not exceed @length signatories@)
                } deriving stock (Int -> MultiSig -> ShowS
[MultiSig] -> ShowS
MultiSig -> String
(Int -> MultiSig -> ShowS)
-> (MultiSig -> String) -> ([MultiSig] -> ShowS) -> Show MultiSig
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MultiSig] -> ShowS
$cshowList :: [MultiSig] -> ShowS
show :: MultiSig -> String
$cshow :: MultiSig -> String
showsPrec :: Int -> MultiSig -> ShowS
$cshowsPrec :: Int -> MultiSig -> ShowS
Show, (forall x. MultiSig -> Rep MultiSig x)
-> (forall x. Rep MultiSig x -> MultiSig) -> Generic MultiSig
forall x. Rep MultiSig x -> MultiSig
forall x. MultiSig -> Rep MultiSig x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep MultiSig x -> MultiSig
$cfrom :: forall x. MultiSig -> Rep MultiSig x
Generic)
                  deriving anyclass ([MultiSig] -> Encoding
[MultiSig] -> Value
MultiSig -> Encoding
MultiSig -> Value
(MultiSig -> Value)
-> (MultiSig -> Encoding)
-> ([MultiSig] -> Value)
-> ([MultiSig] -> Encoding)
-> ToJSON MultiSig
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [MultiSig] -> Encoding
$ctoEncodingList :: [MultiSig] -> Encoding
toJSONList :: [MultiSig] -> Value
$ctoJSONList :: [MultiSig] -> Value
toEncoding :: MultiSig -> Encoding
$ctoEncoding :: MultiSig -> Encoding
toJSON :: MultiSig -> Value
$ctoJSON :: MultiSig -> Value
ToJSON, Value -> Parser [MultiSig]
Value -> Parser MultiSig
(Value -> Parser MultiSig)
-> (Value -> Parser [MultiSig]) -> FromJSON MultiSig
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [MultiSig]
$cparseJSONList :: Value -> Parser [MultiSig]
parseJSON :: Value -> Parser MultiSig
$cparseJSON :: Value -> Parser MultiSig
FromJSON)

PlutusTx.makeLift ''MultiSig

contract :: AsContractError e => Contract () MultiSigSchema e ()
contract :: Contract () MultiSigSchema e ()
contract = [Promise
   ()
   ('R
      '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
         "unlock"
         ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
               ActiveEndpoint)])
   e
   ()]
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     ()
forall w (s :: Row *) e a. [Promise w s e a] -> Contract w s e a
selectList [Promise
  ()
  ('R
     '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
        "unlock"
        ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
              ActiveEndpoint)])
  e
  ()
forall e. AsContractError e => Promise () MultiSigSchema e ()
lock, Promise
  ()
  ('R
     '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
        "unlock"
        ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
              ActiveEndpoint)])
  e
  ()
forall e. AsContractError e => Promise () MultiSigSchema e ()
unlock] Contract
  ()
  ('R
     '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
        "unlock"
        ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
              ActiveEndpoint)])
  e
  ()
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     ()
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Contract
  ()
  ('R
     '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
        "unlock"
        ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
              ActiveEndpoint)])
  e
  ()
forall e. AsContractError e => Contract () MultiSigSchema e ()
contract

{-# INLINABLE validate #-}
validate :: MultiSig -> () -> () -> V2.ScriptContext -> Bool
validate :: MultiSig -> () -> () -> ScriptContext -> Bool
validate MultiSig{[PaymentPubKeyHash]
signatories :: [PaymentPubKeyHash]
signatories :: MultiSig -> [PaymentPubKeyHash]
signatories, Integer
minNumSignatures :: Integer
minNumSignatures :: MultiSig -> Integer
minNumSignatures} ()
_ ()
_ ScriptContext
p =
    let present :: Integer
present = [PaymentPubKeyHash] -> Integer
forall (t :: * -> *) a. Foldable t => t a -> Integer
length ((PaymentPubKeyHash -> Bool)
-> [PaymentPubKeyHash] -> [PaymentPubKeyHash]
forall a. (a -> Bool) -> [a] -> [a]
filter (TxInfo -> PubKeyHash -> Bool
V2.txSignedBy (ScriptContext -> TxInfo
V2.scriptContextTxInfo ScriptContext
p) (PubKeyHash -> Bool)
-> (PaymentPubKeyHash -> PubKeyHash) -> PaymentPubKeyHash -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PaymentPubKeyHash -> PubKeyHash
unPaymentPubKeyHash) [PaymentPubKeyHash]
signatories)
    in BuiltinString -> Bool -> Bool
traceIfFalse BuiltinString
"not enough signatures" (Integer
present Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
>= Integer
minNumSignatures)

instance Scripts.ValidatorTypes MultiSig where
    type instance RedeemerType MultiSig = ()
    type instance DatumType MultiSig = ()

typedValidator :: MultiSig -> V2.TypedValidator MultiSig
typedValidator :: MultiSig -> TypedValidator MultiSig
typedValidator = CompiledCode (MultiSig -> ValidatorType MultiSig)
-> CompiledCode (ValidatorType MultiSig -> UntypedValidator)
-> MultiSig
-> TypedValidator MultiSig
forall a param.
Lift DefaultUni param =>
CompiledCode (param -> ValidatorType a)
-> CompiledCode (ValidatorType a -> UntypedValidator)
-> param
-> TypedValidator a
V2.mkTypedValidatorParam @MultiSig
    $$(PlutusTx.compile [|| validate ||])
    $$(PlutusTx.compile [|| wrap ||])
    where
        wrap :: (() -> () -> ScriptContext -> Bool) -> UntypedValidator
wrap = (() -> () -> ScriptContext -> Bool) -> UntypedValidator
forall sc d r.
(IsScriptContext sc, UnsafeFromData d, UnsafeFromData r) =>
(d -> r -> sc -> Bool) -> UntypedValidator
Scripts.mkUntypedValidator


-- | Lock some funds in a 'MultiSig' contract.
lock :: AsContractError e => Promise () MultiSigSchema e ()
lock :: Promise () MultiSigSchema e ()
lock = forall a w (s :: Row *) e b.
(HasEndpoint "lock" a s, AsContractError e, FromJSON a) =>
(a -> Contract w s e b) -> Promise w s e b
forall (l :: Symbol) a w (s :: Row *) e b.
(HasEndpoint l a s, AsContractError e, FromJSON a) =>
(a -> Contract w s e b) -> Promise w s e b
endpoint @"lock" (((MultiSig, Value)
  -> Contract
       ()
       ('R
          '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
             "unlock"
             ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                   ActiveEndpoint)])
       e
       ())
 -> Promise
      ()
      ('R
         '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
            "unlock"
            ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                  ActiveEndpoint)])
      e
      ())
-> ((MultiSig, Value)
    -> Contract
         ()
         ('R
            '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
               "unlock"
               ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                     ActiveEndpoint)])
         e
         ())
-> Promise
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     ()
forall a b. (a -> b) -> a -> b
$ \(MultiSig
ms, Value
vl) -> do
    let inst :: TypedValidator MultiSig
inst = MultiSig -> TypedValidator MultiSig
typedValidator MultiSig
ms
    let tx :: TxConstraints () ()
tx = () -> Value -> TxConstraints () ()
forall o i. o -> Value -> TxConstraints i o
Constraints.mustPayToTheScriptWithDatumInTx () Value
vl
        lookups :: ScriptLookups MultiSig
lookups = TypedValidator MultiSig -> ScriptLookups MultiSig
forall a. TypedValidator a -> ScriptLookups a
Constraints.typedValidatorLookups TypedValidator MultiSig
inst
    ScriptLookups MultiSig
-> TxConstraints (RedeemerType MultiSig) (DatumType MultiSig)
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     UnbalancedTx
forall a w (s :: Row *) e.
(ToData (RedeemerType a), FromData (DatumType a),
 ToData (DatumType a), AsContractError e) =>
ScriptLookups a
-> TxConstraints (RedeemerType a) (DatumType a)
-> Contract w s e UnbalancedTx
mkTxConstraints ScriptLookups MultiSig
lookups TxConstraints () ()
TxConstraints (RedeemerType MultiSig) (DatumType MultiSig)
tx
        Contract
  ()
  ('R
     '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
        "unlock"
        ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
              ActiveEndpoint)])
  e
  UnbalancedTx
-> (UnbalancedTx
    -> Contract
         ()
         ('R
            '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
               "unlock"
               ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                     ActiveEndpoint)])
         e
         UnbalancedTx)
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     UnbalancedTx
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= UnbalancedTx
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     UnbalancedTx
forall w (s :: Row *) e.
AsContractError e =>
UnbalancedTx -> Contract w s e UnbalancedTx
adjustUnbalancedTx Contract
  ()
  ('R
     '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
        "unlock"
        ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
              ActiveEndpoint)])
  e
  UnbalancedTx
-> (UnbalancedTx
    -> Contract
         ()
         ('R
            '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
               "unlock"
               ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                     ActiveEndpoint)])
         e
         ())
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Contract
  ()
  ('R
     '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
        "unlock"
        ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
              ActiveEndpoint)])
  e
  CardanoTx
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Contract
   ()
   ('R
      '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
         "unlock"
         ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
               ActiveEndpoint)])
   e
   CardanoTx
 -> Contract
      ()
      ('R
         '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
            "unlock"
            ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                  ActiveEndpoint)])
      e
      ())
-> (UnbalancedTx
    -> Contract
         ()
         ('R
            '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
               "unlock"
               ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                     ActiveEndpoint)])
         e
         CardanoTx)
-> UnbalancedTx
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnbalancedTx
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     CardanoTx
forall w (s :: Row *) e.
AsContractError e =>
UnbalancedTx -> Contract w s e CardanoTx
submitUnbalancedTx

-- | The @"unlock"@ endpoint, unlocking some funds with a list
--   of signatures.
unlock :: AsContractError e => Promise () MultiSigSchema e ()
unlock :: Promise () MultiSigSchema e ()
unlock = forall a w (s :: Row *) e b.
(HasEndpoint "unlock" a s, AsContractError e, FromJSON a) =>
(a -> Contract w s e b) -> Promise w s e b
forall (l :: Symbol) a w (s :: Row *) e b.
(HasEndpoint l a s, AsContractError e, FromJSON a) =>
(a -> Contract w s e b) -> Promise w s e b
endpoint @"unlock" (((MultiSig, [PaymentPubKeyHash])
  -> Contract
       ()
       ('R
          '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
             "unlock"
             ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                   ActiveEndpoint)])
       e
       ())
 -> Promise
      ()
      ('R
         '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
            "unlock"
            ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                  ActiveEndpoint)])
      e
      ())
-> ((MultiSig, [PaymentPubKeyHash])
    -> Contract
         ()
         ('R
            '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
               "unlock"
               ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                     ActiveEndpoint)])
         e
         ())
-> Promise
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     ()
forall a b. (a -> b) -> a -> b
$ \(MultiSig
ms, [PaymentPubKeyHash]
pks) -> do
    NetworkId
networkId <- Params -> NetworkId
pNetworkId (Params -> NetworkId)
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     Params
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     NetworkId
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Contract
  ()
  ('R
     '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
        "unlock"
        ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
              ActiveEndpoint)])
  e
  Params
forall w (s :: Row *) e. AsContractError e => Contract w s e Params
getParams
    let inst :: TypedValidator MultiSig
inst = MultiSig -> TypedValidator MultiSig
typedValidator MultiSig
ms
    Map TxOutRef DecoratedTxOut
utx <- CardanoAddress
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     (Map TxOutRef DecoratedTxOut)
forall w (s :: Row *) e.
AsContractError e =>
CardanoAddress -> Contract w s e (Map TxOutRef DecoratedTxOut)
utxosAt (NetworkId -> TypedValidator MultiSig -> CardanoAddress
forall a. NetworkId -> TypedValidator a -> CardanoAddress
Scripts.validatorCardanoAddress NetworkId
networkId TypedValidator MultiSig
inst)
    let tx :: TxConstraints () ()
tx = Map TxOutRef DecoratedTxOut -> () -> TxConstraints () ()
forall i o. Map TxOutRef DecoratedTxOut -> i -> TxConstraints i o
Constraints.spendUtxosFromTheScript Map TxOutRef DecoratedTxOut
utx ()
                TxConstraints () () -> TxConstraints () () -> TxConstraints () ()
forall a. Semigroup a => a -> a -> a
<> (PaymentPubKeyHash -> TxConstraints () ())
-> [PaymentPubKeyHash] -> TxConstraints () ()
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap PaymentPubKeyHash -> TxConstraints () ()
forall i o. PaymentPubKeyHash -> TxConstraints i o
Constraints.mustBeSignedBy [PaymentPubKeyHash]
pks
        lookups :: ScriptLookups MultiSig
lookups = TypedValidator MultiSig -> ScriptLookups MultiSig
forall a. TypedValidator a -> ScriptLookups a
Constraints.typedValidatorLookups TypedValidator MultiSig
inst
                ScriptLookups MultiSig
-> ScriptLookups MultiSig -> ScriptLookups MultiSig
forall a. Semigroup a => a -> a -> a
<> Map TxOutRef DecoratedTxOut -> ScriptLookups MultiSig
forall a. Map TxOutRef DecoratedTxOut -> ScriptLookups a
Constraints.unspentOutputs Map TxOutRef DecoratedTxOut
utx
    ScriptLookups MultiSig
-> TxConstraints (RedeemerType MultiSig) (DatumType MultiSig)
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     UnbalancedTx
forall a w (s :: Row *) e.
(ToData (RedeemerType a), FromData (DatumType a),
 ToData (DatumType a), AsContractError e) =>
ScriptLookups a
-> TxConstraints (RedeemerType a) (DatumType a)
-> Contract w s e UnbalancedTx
mkTxConstraints ScriptLookups MultiSig
lookups TxConstraints () ()
TxConstraints (RedeemerType MultiSig) (DatumType MultiSig)
tx
        Contract
  ()
  ('R
     '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
        "unlock"
        ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
              ActiveEndpoint)])
  e
  UnbalancedTx
-> (UnbalancedTx
    -> Contract
         ()
         ('R
            '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
               "unlock"
               ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                     ActiveEndpoint)])
         e
         UnbalancedTx)
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     UnbalancedTx
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= UnbalancedTx
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     UnbalancedTx
forall w (s :: Row *) e.
AsContractError e =>
UnbalancedTx -> Contract w s e UnbalancedTx
adjustUnbalancedTx Contract
  ()
  ('R
     '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
        "unlock"
        ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
              ActiveEndpoint)])
  e
  UnbalancedTx
-> (UnbalancedTx
    -> Contract
         ()
         ('R
            '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
               "unlock"
               ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                     ActiveEndpoint)])
         e
         ())
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Contract
  ()
  ('R
     '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
        "unlock"
        ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
              ActiveEndpoint)])
  e
  CardanoTx
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Contract
   ()
   ('R
      '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
         "unlock"
         ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
               ActiveEndpoint)])
   e
   CardanoTx
 -> Contract
      ()
      ('R
         '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
            "unlock"
            ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                  ActiveEndpoint)])
      e
      ())
-> (UnbalancedTx
    -> Contract
         ()
         ('R
            '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
               "unlock"
               ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                     ActiveEndpoint)])
         e
         CardanoTx)
-> UnbalancedTx
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnbalancedTx
-> Contract
     ()
     ('R
        '[ "lock" ':-> (EndpointValue (MultiSig, Value), ActiveEndpoint),
           "unlock"
           ':-> (EndpointValue (MultiSig, [PaymentPubKeyHash]),
                 ActiveEndpoint)])
     e
     CardanoTx
forall w (s :: Row *) e.
AsContractError e =>
UnbalancedTx -> Contract w s e CardanoTx
submitUnbalancedTx