         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))

     key
     update-history!)
    (go
      (loop []
        (alt!
          dato-ch ([{:keys [sender event data] :as 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)))))))

;; Component stuff


                               (dato-send! event payload)
                               true))
                :bootstrap! (fn []
                              (js/console.log "1. Bootstrap")
                              (tal/queue-msg! tal-state {:op :ss/bootstrap}
                                              30000
                                              (fn [reply]
                                                (let [{:keys [session-id schema] :as data} (:data reply)]
                                                  (swap! ss-data merge (:ss data))
                                                  (reset! ss-api (->> (:ss data)
                                                                      (map (fn [[k v]]
                                                                             {(keyword (name k)) (fn-desc->rpc k v)}))
                                                                      (reduce merge {})))
                                                  (let [db (let [bootstrapped? (bootstrapped? @app-db)
                                                                 conn          (if bootstrapped?
                                                                                 app-db
                                                                                 (d/create-conn (merge schema db/cs-schema cs-schema)))]
                                                             (def --fconn conn)
                                                             ;; Check if we're reloading
                                                             ;; with a pre-existing db
                                                             (when-not bootstrapped?
                                                               (remove-watch app-db :global-listener)
                                                               (reset! app-db @conn)
                                                               (doto app-db
                                                                 (db/setup-listener! :global-listener))
                                                               (let [request-transaction! (get-in @ss-api [:tx-requested])]
                                                                 (d/listen! app-db :server-tx-report
                                                                            (fn [tx-report]
                                                                              (let [datoms (tx-report->transaction tx-report)]
                                                                                (when (or (get-in tx-report [:tx-meta :tx/broadcast?])
                                                                                          (get-in tx-report [:tx-meta :tx/persist?]))
                                                                                  (let [prepped (db/prep-broadcastable-tx-report tx-report)]
                                                                                    (when @network-enabled?
                                                                                      (request-transaction! prepped))))))))
                                                               (let [local-session-id (d/tempid :db.part/user)
                                                                     local-session-tx [{:db/id                 (d/tempid :db.part/user)
                                                                                        :dato.meta/bootrapped? true}
                                                                                       ;; TODO: This can likely be moved out to a user-land handler
                                                                                       (assoc (:session data) :db/id local-session-id)
                                                                                       {:local/current-session {:db/id local-session-id}}]]
                                                                 (d/transact! app-db (vals schema))
                                                                 (d/transact! app-db local-session-tx))
                                                               (reset! cast-bootstrapped? true))
                                                             conn)]
                                                    (put! dato-ch [:dato/bootstrap-succeeded session-id])
                                                    (js/console.log "Finished bootstrap"))))))}}))

;; TODO: Probably convert to cljs Record to reify this stuff + avoid the apply shortcut
(defn bootstrap! [dato & args]
