mkTx :: forall h a m. (GenHash m, CoinSelDom (DSL h a))
     => a -> [CoinSelResult (DSL h a)] -> m (DSL.Transaction h a)
mkTx changeAddr css = do
    h <- genHash
    return DSL.Transaction {
          DSL.trFresh = 0
        , DSL.trIns   = Set.unions $ map coinSelInputSet css
        , DSL.trOuts  = concatMap mkOutputs css
        , DSL.trFee   = 0 -- TODO: deal with fees
        , DSL.trHash  = h
        , DSL.trExtra = []
        }
  where
    mkOutputs :: CoinSelResult (DSL h a) -> [DSL.Output h a]
    mkOutputs cs = coinSelOutput cs : map mkChangeOutput (coinSelChange cs)

    mkChangeOutput :: Value (DSL h a) -> DSL.Output h a
    mkChangeOutput (Value change) = DSL.Output changeAddr change

{-------------------------------------------------------------------------------
  Wrap the generic coin selection algorithms
-------------------------------------------------------------------------------}
mkTx :: forall h a m. (GenHash m, CoinSelDom (DSL h a))
     => a -> [CoinSelResult (DSL h a)] -> m (DSL.Transaction h a)
mkTx changeAddr css = do
    h <- genHash
    return DSL.Transaction {
          DSL.trFresh = 0
        , DSL.trIns   = Set.unions $ map coinSelInputSet css
        , DSL.trOuts  = concatMap mkOutputs css
        , DSL.trFee   = 0 -- TODO: deal with fees
        , DSL.trHash  = h
        , DSL.trExtra = []
        }
  where
    mkOutputs :: CoinSelResult (DSL h a) -> [DSL.Output h a]
    mkOutputs cs = coinSelOutput cs : map mkChangeOutput (coinSelChange cs)

    mkChangeOutput :: Value (DSL h a) -> DSL.Output h a
    mkChangeOutput (Value change) = DSL.Output changeAddr change

{-------------------------------------------------------------------------------
  Wrap the generic coin selection algorithms
-------------------------------------------------------------------------------}
mkTx changeAddr css = do
    h <- genHash
    return DSL.Transaction {
          DSL.trFresh = 0
        , DSL.trIns   = Set.unions $ map coinSelInputSet css
        , DSL.trOuts  = concatMap mkOutputs css
        , DSL.trFee   = 0 -- TODO: deal with fees
        , DSL.trHash  = h
        , DSL.trExtra = []
        }
  where
    mkOutputs :: CoinSelResult (DSL h a) -> [DSL.Output h a]
    mkOutputs cs = coinSelOutput cs : map mkChangeOutput (coinSelChange cs)

    mkChangeOutput :: Value (DSL h a) -> DSL.Output h a
    mkChangeOutput (Value change) = DSL.Output changeAddr change

{-------------------------------------------------------------------------------
  Wrap the generic coin selection algorithms
-------------------------------------------------------------------------------}