implement basic login in the wui

This commit is contained in:
didier amyot committed 2018-10-13 16:35:19 -04:00
1 parent d4bc2490ff
commit addff66470
20 files changed
+217 -83

No files matched your search

+4 -4
View File
@@ -1,5 +1,5 @@
(ns skirmish.bookkeeper.bookkeeper
(:require [skirmish.exchange.exchange :refer [empty-book create-exchange-for-security]]
(:require [skirmish.exchange.exchange :refer [empty-book]]
[org.httpkit.server :refer [run-server with-channel send! close on-close]]
[compojure.route :refer [not-found]]
[compojure.handler :refer [api]]
@@ -73,14 +73,14 @@
(fn [{{sec-id-str :sec-id} :route-params :as request}]
(with-channel request ws-chan
(let [status-to-listen-on (get-status-to-listen-on request)
order-channel (get-new-order-channel exchange-apis (keyword sec-id-str) status-to-listen-on)]
order-channel (get-new-order-channel @exchange-apis (keyword sec-id-str) status-to-listen-on)]
(chan-to-websocket request order-channel ws-chan)))))
(defn listen-to-trades [exchange-apis]
(fn [{{sec-id-str :sec-id} :route-params :as request}]
(with-channel request ws-chan
(let [order-channel (get-new-trades-channel exchange-apis (keyword sec-id-str))]
(let [order-channel (get-new-trades-channel @exchange-apis (keyword sec-id-str))]
(chan-to-websocket request order-channel ws-chan)))))
@@ -108,7 +108,7 @@
(defn create-routes-for-bookkeeper [exchange-apis config]
(let [books (map-values #(create-book %) exchange-apis)]
(let [books (map-values #(create-book %) @exchange-apis)]
(routes
(context "/api/1" []
(GET "/" [] api-description)
+3 -1
View File
@@ -2,11 +2,13 @@
(:require [org.httpkit.server :refer [run-server]]
[compojure.handler :refer [api]]
[skirmish.util :refer [block-thread]]
[skirmish.middleware.core :refer [create-map-exchange-apis]]
[skirmish.bookkeeper.bookkeeper :refer [create-routes-for-bookkeeper]]
[ring.middleware.cors :refer [wrap-cors]]))
(defn -main [config exchange-apis]
(defn -main [config securities-api exchange-apis-mult-chan]
(let [bookkeeper-config (:api-bookkeeper config)
exchange-apis (create-map-exchange-apis exchange-apis-mult-chan)
api-routes (create-routes-for-bookkeeper exchange-apis config)]
(println "Running skirmish.bookkeeper.core server with bellow config\n" bookkeeper-config)
(println bookkeeper-config)
+12 -7
View File
@@ -1,9 +1,14 @@
(ns skirmish.broker.core)
(ns skirmish.broker.core
(:require [org.httpkit.server :refer [run-server]]
[compojure.handler :refer [api]]
[skirmish.util :refer [block-thread]]
[skirmish.exchange-gateway.exchange-gateway :refer [create-routes-for-exchange]]
[skirmish.middleware.core :refer [create-map-exchange-apis]]
[ring.middleware.cors :refer [wrap-cors]]))
(def portfolio {:dapm {:amount 10}
:foo {:amount 5 :long-exposure 10 :short-exposure 7}
:bar {:amount 100 :long-exposure 10 :short-exposure 7}})
(defn -main [config exchange-apis])
(defn -main [config securities-api exchange-apis]
(let [webserver-config (:api-broker config)
api-routes (-> exchange-apis create-map-exchange-apis create-routes-for-exchange)]
(println "Running skirmish.exchange-gateway.core server with bellow config\n" webserver-config)
(run-server (api api-routes) webserver-config)))
+8 -7
View File
@@ -6,7 +6,8 @@
[skirmish.bookkeeper.core]
[skirmish.exchange-gateway.core]
[skirmish.ledger.core]
[skirmish.middleware.core :refer [create-exchange-apis-for]]
[skirmish.middleware.core :refer [create-exchange-apis-for
create-securities-api-for]]
[aero.core :refer (read-config)]
[orchestra.spec.test :as st]
[clojure.core.async :as async])
@@ -20,21 +21,21 @@
:ledger skirmish.ledger.core/-main
:wui skirmish.wui.server/-main})
(defn run-all-targets-in-separate-threads [target-fns config exchange-apis]
(defn run-all-targets-in-separate-threads [target-fns config securities-api exchange-apis]
(println "running multiple targets. This is okay in dev but horrible in production")
(println (clojure.string/join "\n" target-fns))
(let [threads (map #(async/thread (% config exchange-apis)) target-fns)
(let [threads (map #(async/thread (% config securities-api exchange-apis)) target-fns)
finished-threads (async/merge threads)]
(loop [finished-thread (async/<!! finished-threads)]
(when (some? finished-thread)
(recur (async/<!! finished-threads))))))
(defn run-all-targets [target-fns config]
(let [exchange-apis (create-exchange-apis-for config)]
(let [securities-api (create-securities-api-for config)
exchange-apis (create-exchange-apis-for config securities-api)]
(if (= (count target-fns) 1)
((first target-fns) config exchange-apis)
(run-all-targets-in-separate-threads target-fns config exchange-apis))))
((first target-fns) config securities-api exchange-apis)
(run-all-targets-in-separate-threads target-fns config securities-api exchange-apis))))
(defn -main [& argv]
(let [config (-> "config.edn" clojure.java.io/resource read-config)
+6 -3
View File
@@ -1,5 +1,6 @@
(ns skirmish.exchange.core
(:require [skirmish.util :refer [block-thread]]
[clojure.core.async :as async]
[skirmish.middleware.core :refer [create-exchange-apis-for]]
[skirmish.exchange.exchange :refer [create-exchange-for-security empty-book]]))
@@ -15,7 +16,9 @@
trades-submitter
orders-submitter)))
(defn -main [config exchange-apis]
(doseq [{sec-id :sec-id} (:securities config)]
(create-exchange-for (get exchange-apis sec-id)))
(defn -main [config securities-api exchange-apis-mult-chan]
(let [ch (async/chan)]
(async/tap exchange-apis-mult-chan ch)
(async/go-loop [exchange-api (async/<! ch)]
(create-exchange-for exchange-api)))
(block-thread))
+3 -2
View File
@@ -3,12 +3,13 @@
[compojure.handler :refer [api]]
[skirmish.util :refer [block-thread]]
[skirmish.exchange-gateway.exchange-gateway :refer [create-routes-for-exchange]]
[skirmish.middleware.core :refer [create-map-exchange-apis]]
[ring.middleware.cors :refer [wrap-cors]]))
(defn -main [config exchange-apis]
(defn -main [config securities-api exchange-apis]
(let [webserver-config (:api-server config)
api-routes (create-routes-for-exchange exchange-apis)]
api-routes (-> exchange-apis create-map-exchange-apis create-routes-for-exchange)]
(println "Running skirmish.exchange-gateway.core server with bellow config\n" webserver-config)
(run-server (api api-routes) webserver-config)))
@@ -1,15 +1,12 @@
(ns skirmish.exchange-gateway.exchange-gateway
(:require [skirmish.exchange.exchange :refer [empty-book create-exchange-for-security]]
[org.httpkit.server :refer [run-server with-channel send! close on-close]]
[compojure.route :refer [not-found]]
[compojure.handler :refer [api]]
(:require [compojure.route :refer [not-found]]
[compojure.core :refer :all]
[skirmish.order] ;; for spec side effect
[skirmish.rest.util :refer [build-response build-response-body get-body]]
[skirmish.rest.util :refer [build-response get-body]]
[clojure.spec.alpha :as s]
[kinsky.client]
[slingshot.slingshot :refer [try+ throw+]]
[clojure.core.async :refer [chan go go-loop close! <! >!! sub]]))
[clojure.core.async :refer [>!!]]))
(def order-id (atom -1))
@@ -37,7 +34,7 @@
(fn [{{sec-id-str :sec-id} :route-params body :body :as request}]
(try+
(let [asked-order (get-body body)
exchange-api (get-exchange-api (keyword sec-id-str) exchange-apis)
exchange-api (get-exchange-api (keyword sec-id-str) @exchange-apis)
incoming-order-channel (:new-order-submitter exchange-api)
order (validate-order asked-order (:sec-id exchange-api))]
(>!! incoming-order-channel order)
+2 -4
View File
@@ -80,9 +80,7 @@
(build-response request {:body {:success true}
:headers {"location" (str "/api/1" "/ledger/securities/" (name sec-id))}}))
(catch [:error-type :4XX] e (build-response request e))
(catch [:error-type :5XX] e (build-response request e))
(catch Object _
(println (:throwable &throw-context) "unexpected error")))))
(catch [:error-type :5XX] e (build-response request e)))))
(defn get-security [conn]
"Returns the security."
@@ -169,7 +167,7 @@
(not-found "not found")))
(defn -main [config exchange-apis]
(defn -main [config securities-api exchange-apis]
(let [ledger-config (:ledger-server config)
conn (skirmish.ledger.accounts/create-connection (-> config :datomic :transactor-url))
api-routes (create-routes-for-ledger (:securities config) conn)]
+42 -8
View File
@@ -1,6 +1,7 @@
(ns skirmish.middleware.core
(:require [clojure.core.async :as async]
[kinsky.async]
[clojure.core.async :refer [go-loop <! sub chan]]
[kinsky.client]))
(defn create-chan-based-exchange-api-for [sec-id]
@@ -8,6 +9,7 @@
trades (async/chan)
orders (async/chan)]
{:sec-id sec-id
:disabled false
:new-order-publisher new-order ;; anything published here will be processed as
:new-order-submitter new-order
:trades-publisher (async/pub trades :book.order/type)
@@ -15,12 +17,44 @@
:orders-publisher (async/pub orders :book.order/status)
:orders-submitter orders}))
(def api-creators {})
(defn create-exchange-apis-for [config]
;; todo: spec this function
(let [security-definitions (map :sec-id (:securities config))
create-exchange-api-for (get api-creators (:middleware config) create-chan-based-exchange-api-for)
f (fn [sec] [sec (create-exchange-api-for sec)])
ret (into {} (map f security-definitions))]
ret))
(defn create-chan-based-security-api [config]
(let [securities (async/chan)]
{:securities-publisher (async/mult securities)
:securities-submitter securities}))
(def security-api-creators {})
(defn create-securities-api-for [config]
(let [creator (get security-api-creators (:middleware config) create-chan-based-security-api)]
(creator config)))
(defn update-exchange-apis [create-exchange-api-for sec]
(let [sec-id (:sec-id sec)
disabled? (get sec :disabled false)]
(if disabled?
{:sec-id sec-id :disabled true}
(create-exchange-api-for sec-id))))
(def exchange-api-creators {})
(defn create-exchange-apis-for [config securities-api]
(let [ret (async/chan)
securities-ch (async/chan)
securities-publisher (:securities-publisher securities-api)
create-exchange-api-for (get exchange-api-creators (:middleware config) create-chan-based-exchange-api-for)]
(async/tap securities-publisher securities-ch)
(go-loop [sec (<! securities-ch)]
(async/>! ret (update-exchange-apis create-exchange-api-for sec))
(recur (<! securities-ch)))
(async/mult ret)))
(defn create-map-exchange-apis [exchange-apis-mult-chan]
(let [c (async/chan)
ret (atom {})]
(async/tap exchange-apis-mult-chan chan)
(async/go-loop [exchange-api (async/<! c)]
(if (:disabled? exchange-api)
(swap! ret #(dissoc % (:sec-id exchange-api)))
(swap! ret #(assoc % (:sec-id exchange-api) exchange-api))))
ret))
-1
View File
@@ -16,7 +16,6 @@
(let [event-end (:calendar.event/end event)]
(take-while #(< (:calendar.event/start %) event-end) sorted-events)))
(defn get-overlapping-events [events]
(let [sorted-events (sort-by :calendar.event/start events)]
(loop [events sorted-events ret []]
+1 -1
View File
@@ -3,6 +3,6 @@
[ring.adapter.jetty :refer [run-jetty]])
(:gen-class))
(defn -main [config exchange-apis]
(defn -main [config securities-api exchange-apis]
(let [port 3000]
(run-jetty app {:port port :join? false})))
@@ -7,10 +7,24 @@
"Gentrify palo santo enamel pin, tumeric jianbing thundercats shaman green juice chambray yr. Kale chips synth meditation chambray thundercats helvetica, cornhole whatever kickstarter ennui pop-up lo-fi godard. Austin unicorn brunch woke hammock. Coloring book kombucha occupy tofu wayfarers."])
(defn login [state]
(let [login-field (atom (get state :user ""))
on-change #(reset! login-field (-> % .-target .-value))]
(fn []
[:div.field
[:div.control
[:label.label "Username"]
[:div.field.is-grouped
[:input.input.is-success {:type "text" :value @login-field :on-change on-change :style {:margin-right "1em"}}]
[:div.control
[:a.button.is-link.has-background-primary {:href (str "/home/" @login-field)} "login"]]]]])))
(defn page [state]
[:div
[:section.section
[:div.container
[:h1.title "lorem ipsum"]
[login state]
(for [sentence lorem-ipsum]
[:p sentence])]]])
+18 -23
View File
@@ -8,26 +8,21 @@
(defn page []
[:div.content
[:ul
[:li "General"
[:ul
[:li "write trivial mock strategy framework."]
[:li "write mock strategies."]
[:li "think of a solution where to store data."]]]
[:li "Web user interface"
[:ul
[:li done "Add simple pages for every section"]
[:li "Securities"
[:ul
[:li "display all the available securities"]
[:li "display the book for selected securities"]]]]]
[:li "Exchange"
[:ul
[:li done "make an exchange that kind of work"]
[:li "spec the exchange"]]]
[:li "Book keeper"
[:ul
[:li "Find a place to store information about securities"]]]
[:li "Brooker"
[:ul
[:li "Write a small broker"]]]]])
[:ol
[:li "Broker"
[:p "the brooker should use the exchange-gateway and ledge as apis. Nothing else."]
[:ol
[:li done "implement basic login in the wui"]
[:li on-it "implement basic web server"]
[:li "implement stupid login."]
[:li "implement account notion. Use ledger for that."]
[:li "implement buy/sell securities."]]]
[:li "Implement Ledger"
[:ol
[:li "Use ledger as source of through in each sub server."]
[:li "Update web ui for integrating securities with ledger."]
[:li "Create a basic broker that supports..."]
[:li "Ledger should compute interest rate."]
[:li "implement transactions in ledger."]
[:li "implement escrow."]]]]])
+22 -1
View File
@@ -10,6 +10,26 @@
"is-active"))
(defn- user-dropdown [state]
(when (:user @state)
(let [icon [:i.fa.fa-sign-out {:aria-hidden true}]]
[:div.navbar-item.has-dropdown.is-hoverable
[:a.navbar-link {} (str "[ " (:user @state) " ]")]
[:div.navbar-dropdown
[:a.navbar-item {:href "/home/"} icon " logout"]]])))
(defn- login [state]
(let [icon [:i.fa.fa-sign-out {:aria-hidden true}]]
[:a.navbar-item.is-tab {:href "/"} icon " login"]))
(defn user-placeholder [state]
(if (:user @state)
[user-dropdown state]
[login state]))
(defn top-bar [state]
[:nav.navbar.is-dark.is-boxed {:style {:margin-bottom "1em"}}
[:div.container
@@ -20,4 +40,5 @@
[:a.navbar-item.is-tab {:href "/portfolio" :class (top-bar-class state :view-portfolio)} "View Portfolio"]
[:a.navbar-item.is-tab {:href "/todo" :class (top-bar-class state :todo)} "Todo"]]
[:div.navbar-end
[:a.navbar-item.is-tab {} "Skirmish Shitty Exchange"]]]])
[:a.navbar-item.is-tab {} "Skirmish Shitty Exchange"]
[user-placeholder state]]]])
+9
View File
@@ -26,6 +26,15 @@
(session/put! :current-page #'pages/home-page)
(swap! state #(into % {:page :home})))
(secretary/defroute "/home/:username" [username]
(session/put! :current-page #'pages/home-page)
(swap! state #(into % {:page :home :user username})))
(secretary/defroute "/home/" []
(session/put! :current-page #'pages/home-page)
(swap! state #(into % {:page :home :user nil})))
(secretary/defroute "/securities" []
(session/put! :current-page #'pages/securities-page)
(swap! state #(into % {:page :securities})))
+8
View File
@@ -8,11 +8,19 @@
@import "../../node_modules/bulma/sass/utilities/_all";
// main color changes
$background: $black;
$body-background-color: $black;
$text: $white-ter;
$link: $turquoise;
// navbar color change
$navbar-dropdown-background-color: $grey-darker;
$navbar-dropdown-border-top: 1px solid $turquoise !default;
$navbar-dropdown-item-hover-color: none;
$navbar-dropdown-item-hover-background-color: $grey-darker;
// table color changes
$table-background-color: $grey-dark;
$table-cell-heading-color: $grey-darker;
$table-row-hover-background-color: $black-ter;