something
This commit is contained in:
1 parent
440206e924
commit
b972e6e69f
15 files changed
+230
-141
No files matched your search
@@ -50,7 +50,7 @@
|
||||
:where [_ :skirmish.broker.user/email ?email]] db)
|
||||
xf (comp cat (map #(hash-map :email % :url (str "/api/1/users/" %))))]
|
||||
(build-response request
|
||||
(doall ((sequence xf emails)))))
|
||||
{:users (doall (sequence xf emails))}))
|
||||
(catch [:error-type :4XX] e (build-response request e))
|
||||
(catch [:error-type :5XX] e (build-response request e)))))
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
:db/fn (d/function {:lang "clojure"
|
||||
:requires ['[slingshot.slingshot]]
|
||||
:params '[db email]
|
||||
:code '(let [existing-user (d/pull db '[:db/id] [:skirmish.broker.user/email email
|
||||
:skirmish.broker.user/accounts []])]
|
||||
:code '(let [existing-user (d/pull db '[:db/id] [:skirmish.broker.user/email email])]
|
||||
;:skirmish.broker.user/accounts []])]
|
||||
(when (-> existing-user :db/id some?)
|
||||
(slingshot.slingshot/throw+ {:error-type :4XX :status 400 :body {:error "A user with this email already exists."}}))
|
||||
[#:skirmish.broker.user{:email email}])})}])
|
||||
@@ -27,7 +27,7 @@
|
||||
:db/ident :skirmish.broker.account/sec-id
|
||||
:db/valueType :db.type/keyword
|
||||
:db/cardinality :db.cardinality/one
|
||||
:db/doc "The security if of the account."}
|
||||
:db/doc "The security id of the account."}
|
||||
{
|
||||
:db/ident :skirmish.broker.account/private-key
|
||||
:db/valueType :db.type/string
|
||||
@@ -44,10 +44,9 @@
|
||||
:db/doc "The email of the user; used as id."}
|
||||
{
|
||||
:db/ident :skirmish.broker.user/accounts
|
||||
:db/unique :db.unique/identity
|
||||
:db/valueType :db.type/ref
|
||||
:db/cardinality :db.cardinality/many
|
||||
:db/doc "The email of the user; used as id."}])
|
||||
:db/doc "The list of the accounts own by the user."}])
|
||||
|
||||
|
||||
(def schema (-> []
|
||||
|
||||
@@ -111,10 +111,56 @@
|
||||
(concat create-securities)
|
||||
(concat print-securities)))
|
||||
|
||||
(defn create-connection [uri]
|
||||
(let [new-db? (d/create-database uri)
|
||||
conn (d/connect uri)]
|
||||
;(when new-db?
|
||||
@(d/transact conn schema)
|
||||
conn))
|
||||
|
||||
(defn add-default-currencies [conn]
|
||||
(let [dapm #:skirmish.security{:sec-id :dapm
|
||||
:name "didier amyot paper money"
|
||||
:type :currency
|
||||
:description "The official currency of the 'Skirmish Shitty Exchange'."
|
||||
:emitter "dapm private key"
|
||||
:number-of-decimal 2
|
||||
:symbol "რ"
|
||||
:interest-rate 10}
|
||||
apbm #:skirmish.security{:sec-id :apbm
|
||||
:name "apache beam"
|
||||
:type :equity
|
||||
:description "Unified programming model to define and execute data processing pipelines, including ETL, batch and stream (continuous) processing."
|
||||
:emitter "apbm private key"
|
||||
:number-of-decimal 0}
|
||||
apac #:skirmish.security{:sec-id :apac
|
||||
:name "apache accumulo"
|
||||
:type :equity
|
||||
:description "A sorted, distributed key/value store that provides robust, scalable data storage and retrieval."
|
||||
:emitter "apac private key"
|
||||
:number-of-decimal 0}
|
||||
apax #:skirmish.security{:sec-id :apax
|
||||
:name "apache apex"
|
||||
:type :equity
|
||||
:description "Enterprise-grade unified stream and batch processing engine."
|
||||
:emitter ":apax private key"
|
||||
:number-of-decimal 0}
|
||||
apdr #:skirmish.security{:sec-id :apdr
|
||||
:name "apache drill"
|
||||
:type :equity
|
||||
:description "Schema-free SQL Query Engine for Hadoop, NoSQL and Cloud Storage."
|
||||
:emitter ":apdr private key"
|
||||
:number-of-decimal 0}
|
||||
apmh #:skirmish.security{:sec-id :apmh
|
||||
:name "apache mahout"
|
||||
:type :equity
|
||||
:description "For Creating Scalable Performant Machine Learning Applications."
|
||||
:emitter ":apmh private key"
|
||||
:number-of-decimal 0}]
|
||||
@(d/transact conn [dapm apbm apac apax apdr apmh])))
|
||||
|
||||
(defn create-connection
|
||||
([uri init-when-new?]
|
||||
(let [new-db? (d/create-database uri)
|
||||
conn (d/connect uri)]
|
||||
@(d/transact conn schema)
|
||||
(if (and init-when-new? new-db?)
|
||||
(add-default-currencies conn))
|
||||
conn))
|
||||
([uri]
|
||||
(create-connection uri true)))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(ns skirmish.ledger.core
|
||||
(:require [org.httpkit.server :refer [run-server]]
|
||||
[skirmish.routes.core :as routes]
|
||||
[compojure.handler :refer [api]]
|
||||
[skirmish.util :refer [block-thread]]
|
||||
[slingshot.slingshot :refer [try+ throw+]]
|
||||
@@ -9,7 +10,7 @@
|
||||
[skirmish.ledger.accounts]
|
||||
[datomic.api :as d]
|
||||
[taoensso.timbre :as timbre]
|
||||
[compojure.core :refer :all]
|
||||
[compojure.core :as compojure]
|
||||
[clojure.spec.alpha :as s]
|
||||
[ring.middleware.cors :refer [wrap-cors]]))
|
||||
|
||||
@@ -88,10 +89,10 @@
|
||||
:type type_
|
||||
:description description}))
|
||||
|
||||
|
||||
(defn get-security-from-db [conn sec-id]
|
||||
(let [db (d/db conn)
|
||||
e (d/pull db '[*] [:skirmish.security/sec-id sec-id])]
|
||||
(println (str e))
|
||||
(if (-> e :db/id nil?)
|
||||
(throw+ {:error-type :4XX :status 404 :body {:error "Security not found."}})
|
||||
(prettify-security e db))))
|
||||
@@ -100,13 +101,14 @@
|
||||
"Create a fresh new security."
|
||||
(fn [{body :body :as request}]
|
||||
(try+
|
||||
(let [[sec-id interest-rate] (-> body get-body get-new-security)]
|
||||
@(d/transact conn [[:skirmish.ledger/create-security sec-id interest-rate]])
|
||||
(let [[sec-id interest-rate] (-> body get-body get-new-security)
|
||||
new-sec @(d/transact conn [[:skirmish.ledger/create-security sec-id interest-rate]])]
|
||||
(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)))))
|
||||
|
||||
|
||||
(defn get-security [conn]
|
||||
"Returns the security."
|
||||
(fn [{{sec-id-str :sec-id} :route-params :as request}]
|
||||
@@ -126,7 +128,7 @@
|
||||
|
||||
|
||||
(defn get-available-securities-body [securities]
|
||||
(let [sec-id->url #(str "/api/1/ledger/securities/" (name %))
|
||||
(let [sec-id->url #(routes/get-path-for :ledger/security {:sec-id (name %)})
|
||||
to-security-description #(hash-map :sec-id % :url (sec-id->url %))
|
||||
xf (comp cat (map to-security-description))
|
||||
securities-info (sequence xf securities)];;
|
||||
@@ -161,7 +163,7 @@
|
||||
|
||||
|
||||
(defn get-available-accounts-body [accounts]
|
||||
(let [sec-id->url #(str "/api/1/ledger/accounts/" (name %))
|
||||
(let [sec-id->url #(routes/get-path-for :ledger/account {:account-id (name %)})
|
||||
to-security-description #(hash-map :account-public-key % :url (sec-id->url %))
|
||||
xf (comp cat (map to-security-description))
|
||||
securities-info (sequence xf accounts)];;
|
||||
@@ -180,25 +182,25 @@
|
||||
(build-response request body)))
|
||||
|
||||
|
||||
(defn create-routes-for-ledger [securities conn]
|
||||
(routes
|
||||
(context "/api/1/ledger" []
|
||||
(GET "/" get-api-description)
|
||||
(GET "/accounts" [] (get-available-accounts conn))
|
||||
(GET "/accounts/:account-id" [] (get-account conn))
|
||||
(GET "/securities" [] (get-available-securities conn)) ;; done
|
||||
(POST "/securities" [] (create-security conn)) ;; done
|
||||
(GET "/securities/:sec-id" [] (get-security conn)) ;; done
|
||||
(PUT "/securities/:sec-id" [] (update-security conn)) ;; not done
|
||||
(POST "/securities/:sec-id" [] (emit-securities conn))) ;; done
|
||||
(defn create-routes-for-ledger [conn]
|
||||
(compojure/routes
|
||||
;; (routes/get-context :ledger)
|
||||
(routes/context :ledger []
|
||||
(routes/GET :ledger/home [] get-api-description)
|
||||
(routes/GET :ledger/accounts [] (get-available-accounts conn))
|
||||
(routes/GET :ledger/account [] (get-account conn))
|
||||
(routes/GET :ledger/securities [] (get-available-securities conn)) ;; done
|
||||
(routes/POST :ledger/securities [] (create-security conn)) ;; done
|
||||
(routes/GET :ledger/security [] (get-security conn)) ;; done
|
||||
(routes/PUT :ledger/security [] (update-security conn)) ;; not done
|
||||
(routes/POST :ledger/security [] (emit-securities conn))) ;; done
|
||||
(not-found "not found")))
|
||||
|
||||
|
||||
(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)]
|
||||
|
||||
api-routes (create-routes-for-ledger conn)]
|
||||
(timbre/info "Running skirmish.ledger.core server with config: " ledger-config)
|
||||
(run-server
|
||||
(-> api-routes api cors-middleware)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(ns skirmish.routes)
|
||||
(ns skirmish.routes.api)
|
||||
|
||||
(defn get-app-for [all-routes k]
|
||||
"An app consists on a name, a prefix and some routes."
|
||||
@@ -16,16 +16,15 @@
|
||||
"Returns what compojure expects to have."
|
||||
(->> k (get-route-for all-routes) :path))
|
||||
|
||||
(defn replace-part [part params]
|
||||
(defn- replace-part [part params]
|
||||
(if (clojure.string/starts-with? part ":")
|
||||
(-> part (subs 1) keyword params)
|
||||
part))
|
||||
|
||||
(defn path-for [p params]
|
||||
(defn- path-for [p params]
|
||||
(let [parts (clojure.string/split p #"/")]
|
||||
(clojure.string/join "/" (map #(replace-part % params) parts))))
|
||||
|
||||
|
||||
(defn get-context [all-routes c]
|
||||
(let [get-app #(get-app-for all-routes %)]
|
||||
(-> c
|
||||
@@ -34,7 +33,6 @@
|
||||
get-app
|
||||
:path)))
|
||||
|
||||
|
||||
(defn get-path-for
|
||||
"Returns a link to a location by name."
|
||||
([all-routes k]
|
||||
@@ -42,6 +40,7 @@
|
||||
([all-routes k params]
|
||||
(let [app (get-app-for all-routes k)
|
||||
route (get-route-for all-routes k)
|
||||
p (str (:path app) (:path route))]
|
||||
(path-for p params))))
|
||||
p (str (:path app) (:path route))
|
||||
domain (get app :domain "")]
|
||||
(str domain (path-for p params)))))
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
(ns skirmish.routes.core
|
||||
(:require [skirmish.routes.api :as routes-api]
|
||||
[compojure.core :as compojure]))
|
||||
|
||||
|
||||
(def ledger-routes {
|
||||
:name :ledger
|
||||
:domain "http://localhost:1604" ;; should somehow be in some config
|
||||
:path "/api/1/ledger"
|
||||
:routes [{:name :home :path "/"}
|
||||
{:name :accounts :path "/accounts"}
|
||||
{:name :account :path "/accounts/:account-id"}
|
||||
{:name :securities :path "/securities"}
|
||||
{:name :security :path "/securities/:sec-id"}]})
|
||||
|
||||
(def all-routes [ledger-routes])
|
||||
|
||||
(def get-context (partial routes-api/get-context all-routes))
|
||||
|
||||
(def get-compojure-path (partial routes-api/get-compojure-path all-routes))
|
||||
|
||||
(def get-path-for (partial routes-api/get-path-for all-routes))
|
||||
|
||||
(defmacro GET [path args & body]
|
||||
(compojure/compile-route :get
|
||||
(get-compojure-path path)
|
||||
args
|
||||
body))
|
||||
|
||||
(defmacro POST [path args & body]
|
||||
(compojure/compile-route :post
|
||||
(get-compojure-path path)
|
||||
args
|
||||
body))
|
||||
|
||||
(defmacro PUT [path args & body]
|
||||
(compojure/compile-route :put
|
||||
(get-compojure-path path)
|
||||
args
|
||||
body))
|
||||
|
||||
(defmacro context [path args & routes]
|
||||
(let [resolved-path (get-context path)]
|
||||
(concat `(compojure/context ~resolved-path ~args) routes)))
|
||||
@@ -11,19 +11,3 @@
|
||||
(defn block-thread []
|
||||
"Block the current thread until chuck norris gets weaker."
|
||||
(async/<!! (async/chan)))
|
||||
|
||||
(defn- get-overlapping-for-specific-event [event sorted-events]
|
||||
(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 []]
|
||||
(if (seq events)
|
||||
(let [first-event (first events)
|
||||
rest-events (rest events)
|
||||
overlapping-events (get-overlapping-for-specific-event first-event rest-events)
|
||||
overlapping-pairs (map vector (repeat first-event) overlapping-events)
|
||||
new-ret (if (seq overlapping-pairs) (into ret overlapping-pairs) ret)]
|
||||
(recur rest-events new-ret))
|
||||
ret))))
|
||||
@@ -1,6 +1,6 @@
|
||||
(ns skirmish.wui.components.securities-page
|
||||
(:require [cljs-http.client :as http]
|
||||
[cljs.core.async :refer [<!]]
|
||||
[cljs.core.async :refer [<!] :as async]
|
||||
[reagent.core :refer [atom]])
|
||||
(:require-macros [cljs.core.async.macros :refer [go]]))
|
||||
|
||||
@@ -18,21 +18,62 @@
|
||||
[:td (:name sec)]
|
||||
[:td (:description sec)]]))
|
||||
|
||||
(defn get-securities [securities]
|
||||
(go (let [url "http://localhost:1603/api/1/securities"
|
||||
response (<! (http/get url {:with-credentials? false}))]
|
||||
(reset! securities (get-in response [:body :securities])))))
|
||||
(defn get-all-securities-urls []
|
||||
(let [ret (async/chan)]
|
||||
(go (let [url "http://localhost:1604/api/1/ledger/securities"
|
||||
response (<! (http/get url {:with-credentials? false}))
|
||||
urls (map :url (get-in response [:body :securities]))]
|
||||
(async/onto-chan ret urls)))
|
||||
ret))
|
||||
|
||||
(defn create-security-table [securities]
|
||||
[:table.table.is-hoverable.is-fullwidth
|
||||
table-head
|
||||
[:tbody
|
||||
(for [sec securities] (create-row sec))]])
|
||||
(defn get-all-securities []
|
||||
(let [ret (async/chan)
|
||||
urls (get-all-securities-urls)]
|
||||
(async/go-loop [url (async/<! urls)]
|
||||
(when-let [url (async/<! urls)]
|
||||
(async/go
|
||||
(let [sec (:body (<! (http/get url {:with-credentials? false})))]
|
||||
(println sec)
|
||||
(async/>! ret sec)))
|
||||
(recur url)))
|
||||
ret))
|
||||
|
||||
(defn get-securities [a-securities]
|
||||
(let [securities (get-all-securities)]
|
||||
(async/go-loop [security (async/<! securities)]
|
||||
(when (some? security)
|
||||
(swap! a-securities #(conj % security))
|
||||
(recur (async/<! securities))))))
|
||||
|
||||
|
||||
(defn create-currencies-table [securities]
|
||||
[:div
|
||||
[:div.content
|
||||
[:h3 "Currencies"]]
|
||||
[:table.table.is-hoverable.is-fullwidth
|
||||
table-head
|
||||
[:tbody
|
||||
(for [sec securities :when (= (:type sec) "currency")] (create-row sec))]]])
|
||||
|
||||
(defn create-equities-table [securities]
|
||||
[:div
|
||||
[:div.content
|
||||
[:h3 "Equities"]]
|
||||
[:table.table.is-hoverable.is-fullwidth
|
||||
table-head
|
||||
[:tbody
|
||||
(for [sec securities :when (= (:type sec) "equity")] (create-row sec))]]])
|
||||
|
||||
(defn create-securities-table [securities]
|
||||
[:div
|
||||
[create-currencies-table securities]
|
||||
[:br]
|
||||
[create-equities-table securities]])
|
||||
|
||||
(defn security-table []
|
||||
(let [securities (atom [])]
|
||||
(get-securities securities)
|
||||
#(create-security-table @securities)))
|
||||
#(create-securities-table @securities)))
|
||||
|
||||
(defn page [state]
|
||||
(security-table))
|
||||
@@ -30,17 +30,8 @@
|
||||
[:li "Make sure the ledger can have accounts"]
|
||||
[:li "when a new user signs in, he should receive some sort of money"]
|
||||
[:li "\u22EE"]
|
||||
[:li "implement buy/sell securities."]]]
|
||||
|
||||
[:li "Cleaning up..."
|
||||
[:ul
|
||||
[:li "All the urls on the client should be at the same place."]
|
||||
[:li "We should have a nice way to handle routes on the server."]]]
|
||||
|
||||
[:li "Implement Ledger"
|
||||
[:ol
|
||||
[:li "implement buy/sell securities."]
|
||||
[:li "Use ledger as source of through in each sub server."]
|
||||
[:li "Update web ui for integrating securities with ledger."]
|
||||
[:li "Ledger should compute interest rate."]
|
||||
[:li "implement transactions in ledger."]
|
||||
[:li "implement escrow."]]]]])
|
||||
Reference in new issue
Block a user