 (defn get-or-make-channel [client channel-id]
   (or (client/get-channel client channel-id) (client/new-channel client channel-id)))
 
-;; (defn add-orderer
-;;   ([client channel-id orderer-opts-map]
-;;    ;; Add an orderer if there is no orderer
-;;    (add-orderer channel-id orderer-opts-map false))
-;;   ([client channel-id orderer-opts-map force?]
-;;    (let [channel (get-or-make-channel client channel-id)]
-;;      (if-let [existing-orderers (and (not force?) (client/get))])
-         
-;;      )
-;;    )
-;;   )
+(defprotocol ChannelEndOpts
+  (new-channel-end [channel-end client])
+  (get-channel-ends [channel-end client]))
+
+;; Channel ends are: Peers(Endorsers,...), Orderers
+(defrecord OrdererOpts [name grpc-url properties]
+  ChannelEndOpts
+    (new-channel-end [{:keys [name grpc-url properties]} client]
+    (client/new-orderer client name grpc-url properties))
+  (get-channel-ends [this channel]
+    (channel/get-orderers channel)))
+
+(defrecord PeerOpts [name grpc-url properties]
+  ChannelEndOpts
+  (new-channel-end [{:keys [name grpc-url properties]} client]
+    (client/new-orderer client name grpc-url properties))
+  (get-channel-ends [this channel]
+    (channel/get-peers channel)))
+
+(defprotocol ChannelEnd
+  (add-channel-end-to-channel [channel-end channel]))
+  
+(extend-protocol ChannelEnd
+  Orderer
+  (add-channel-end-to-channel [this channel]
+    (channel/add-orderer channel this)))
+
+(extend-protocol ChannelEnd
+  Peer
+  (add-channel-end-to-channel [this channel]
+    (channel/add-peer channel this)))
+
+(defn add-channel-end
+  ([client channel-id channel-end-opts]
+   ;; Add a {orderer peer} if there is no {orderer peer}
+   (add-channel-end client channel-id channel-end-opts false))
+  ([client channel-id channel-end-opts force?]
+   ;; To add an additional {orderer peer} set 'force?' true
+   (let [channel (get-or-make-channel client channel-id)]
+     (when (or force?
+               (empty? (get-channel-ends channel-end-opts (get-or-make-channel client channel-id))))
+       (add-channel-end-to-channel (new-channel-end channel-end-opts client) channel)))))
+
+
 ;;;
 ;;; Peers
 ;;;     Endorser


;;;;;;;;;;; Ex
#_
(make-client "Org1Msp"
             "PeerAdmin"
             (-> (slurp "resources/creds/cd96d5260ad4757551ed4a5a991e62130f8008a0bf996e4e4b84cd097a747fec-priv")
                 (keys/str->private-key))
             "-----BEGIN CERTIFICATE-----\nMIICGDCCAb+gAwIBAgIQFSxnLAGsu04zrFkAEwzn6zAKBggqhkjOPQQDAjBzMQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu\nb3JnMS5leGFtcGxlLmNvbTAeFw0xNzA4MzEwOTE0MzJaFw0yNzA4MjkwOTE0MzJa\nMFsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T\nYW4gRnJhbmNpc2NvMR8wHQYDVQQDDBZBZG1pbkBvcmcxLmV4YW1wbGUuY29tMFkw\nEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEV1dfmKxsFKWo7o6DNBIaIVebCCPAM9C/\nsLBt4pJRre9pWE987DjXZoZ3glc4+DoPMtTmBRqbPVwYcUvpbYY8p6NNMEswDgYD\nVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwKwYDVR0jBCQwIoAgQjmqDc122u64\nugzacBhR0UUE0xqtGy3d26xqVzZeSXwwCgYIKoZIzj0EAwIDRwAwRAIgXMy26AEU\n/GUMPfCMs/nQjQME1ZxBHAYZtKEuRR361JsCIEg9BOZdIoioRivJC+ZUzvJUnkXu\no2HkWiuxLsibGxtE\n-----END CERTIFICATE-----\n")
#_
(comment
  ;; Copy from fabcar example

            [clojure-fabric.request :as request]
            [clojure-fabric.response :as response]
            [clojure.core.cache :as cache])
  (:import [org.hyperledger.fabric.sdk User Enrollment Peer Orderer]
           [org.bouncycastle.jcajce.provider.asymmetric.ec BCECPrivateKey]))

(defprotocol Marshall
  (marshall [obj]))

;;; FIXME: call marshal from generated code when return type matches
(extend-protocol Marshall
  java.util.Collection
  (marshall [obj]
    (if (instance? clojure.lang.IPersistentSet obj)
      obj
      (seq obj))))

(defonce client-lru-cache
  ;; FIXME: magic number
  (atom (cache/lru-cache-factory {} :threshold 64)))

(defn make-client [msp-id name priv-key cert {:keys [roles account affiliation]}]
  (let [new-client (client/create-new-instance)]
    (client/set-crypto-suite new-client (crypto/get-crypto-suite))
    (client/set-user-context new-client 
