         ss-api             (atom {})
         ;; ???: Do the perf implications of anonymous functions mean these
         ;; shouldn't be in a tight loop?
-        fn-desc->rpc       (fn fn-desc->rpc [remote-name desc]
-                             (let [f (fn [& all-args]
-                                       ;; TODO: Check if last argument is a channel, an
-                                       (let [cb-or-ch (last all-args)
-                                             cb       (cond
-                                                        (fn? cb-or-ch)   cb-or-ch
-                                                        (chan? cb-or-ch) #(put! cb-or-ch %)
-                                                        :else            false)
-                                             args     (if cb
-                                                        (drop-last 1 all-args)
-                                                        all-args)
-                                             uuid     (d/squuid)]
-                                         (when (fn? cb)
-                                           (swap! pending-rpc assoc uuid cb-or-ch))
-                                         (dato-send! remote-name {:args   args
-                                                                  :rpc/id uuid})
-                                         (if (chan? cb-or-ch)
-                                           cb-or-ch
-                                           uuid)))]
-                               f))]
+        fn-desc->rpc       (fn [remote-name desc]
+                             (fn [& all-args]
+                               ;; TODO: Check if last argument is a channel, an
+                               (let [cb-or-ch (last all-args)
+                                     cb       (cond
+                                                (fn? cb-or-ch)   cb-or-ch
+                                                (chan? cb-or-ch) #(put! cb-or-ch %)
+                                                :else            false)
+                                     args     (if cb
+                                                (drop-last 1 all-args)
+                                                all-args)]
+                                 (when (fn? cb)
+                                   (swap! pending-rpc assoc uuid cb-or-ch))
+                                 (tal/queue-msg! tal-state
+                                                 {:op remote-name
+                                                  :data {:args args}}
+                                                 30000
+                                                 (fn [reply]
+                                                   (if (fn? cb)
+                                                     (cb reply)
+                                                     (when (:event reply)
+                                                       (put! dato-ch reply)))))
+                                 (if (chan? cb-or-ch)
+                                   cb-or-ch
+                                   uuid))))]
     {:comms    comms
      ;; Just for debugging to simulate messages coming in from the
      ;; server
      :ss-cast! ss-cast!
-     :ws       {:ch    ws-ch
-                :host  dato-host
-                :path  dato-path
-                :send! dato-send!
-                :ws    ws}
      :conn     app-db
      :db       (fn
                  ([] @(app-db))

(defn bootstrapped? [db]
  (dsu/qe-by db :dato.meta/bootrapped? true))

(defn new-dato [dato-host dato-path app-db cs-schema]
  (let [cast-bootstrapped? (atom false)
        ws-ch              (async/chan)
        dato-ch            (async/chan)
        ss-cast!           #(put! ws-ch %)
        pending-rpc        (atom {})
        ws                 (ws/build dato-host dato-path {:on-open    (fn [event] (js/console.log ":on-open :" event))
                                                          :on-close   (fn [event] (js/console.log ":on-close :" event))
                                                          :on-message (fn [event]
                                                                        (let [fr (js/FileReader. (.-data event))]
                                                                          (aset fr "onloadend" (fn [e]
                                                                                                 (let [data (transit/read transit-reader (.. e -target -result))]
                                                                                                   (if-let [cb-id (:server/rpc-id data)]
                                                                                                     (let [cb-or-ch (get @pending-rpc cb-id)]
                                                                                                       (swap! pending-rpc dissoc cb-id)
                                                                                                       ;; Should we just pass the whole payload through, or just the data/results?
                                                                                                       (cond
                                                                                                         (chan? cb-or-ch) (put! cb-or-ch (:data data))
                                                                                                         (fn? cb-or-ch)   (cb-or-ch (:data data))
                                                                                                         :else            (ss-cast! (:data data))))
                                                                                                     (ss-cast! data)))))
                                                                          (.readAsText fr (.-data event))))
                                                          :on-error   (fn [event] (js/console.log ":on-error :" event))})
        dato-send!         (fn [event data]
                             (.send ws (transit/write transit-writer [event data])))
        controls-ch        (async/chan)
        comms              {:controls controls-ch
                            :stop     (async/chan)

     key
     update-history!)
    (go
      (try
        (loop []
          (alt!
            dato-ch ([{:keys [sender event data] :as payload}]
                     (js/console.log "payload" (clj->js payload))
                     (cond
                       ;; Special-case waiting on https://github.com/tonsky/datascript/issues/76
                       ;; Can eliminate this branch afterwards
                       (= :server/database-transacted event)
                       (let [previous-state @conn]
                         (def f-tx data)
                         ;; This is the abstraction not yet supported
                         ;; (two-phase commit, plus intermediate
                         ;; processing)
                         (db/consume-foreign-tx! conn data)
                         (con/effect! context previous-state @conn payload))
                       :else
                       (let [previous-state @conn
                             tx-data        (con/transition @conn payload)
                             tx-meta        (meta tx-data)
                             full-tx-meta   (-> (if tx-meta
                                                  tx-meta
                                                  {:tx/transient? true})
                                                (update-in [:tx/intent] (fn [intent]
                                                                          (or intent event))))]
                         (when-not (:tx/transient? full-tx-meta)
                           (js/console.log "\tevent: " (pr-str event))
                           (js/console.log "\ttx-data: " (pr-str tx-data))
                           (js/console.log "\ttx-meta: " (pr-str full-tx-meta)))
                         (if tx-data
                           (d/transact! conn tx-data full-tx-meta)
                           (update-history! {:tx-meta full-tx-meta}))
                         (con/effect! context previous-state @conn payload)))
                     (recur))))
        (catch js/Error e
          (js/console.error "Error in go loop" e))))))

;; Component stuff

