implemented so many things...
This commit is contained in:
1 parent
fd843a5425
commit
bce64fc8f6
24 files changed
+734
-59
No files matched your search
@@ -9,7 +9,7 @@
|
||||
(defn -main [config exchange-apis]
|
||||
(let [bookkeeper-config (:api-bookkeeper config)
|
||||
api-routes (create-routes-for-bookkeeper exchange-apis config)]
|
||||
(println "Running server with bellow config")
|
||||
(println "Running skirmish.bookkeeper.core server with bellow config\n" bookkeeper-config)
|
||||
(println bookkeeper-config)
|
||||
(run-server
|
||||
(-> api-routes api (wrap-cors :access-control-allow-origin #"http://localhost:3449"
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
(ns skirmish.broker.core)
|
||||
|
||||
|
||||
(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])
|
||||
@@ -5,6 +5,7 @@
|
||||
[skirmish.wui.server]
|
||||
[skirmish.bookkeeper.core]
|
||||
[skirmish.exchange-gateway.core]
|
||||
[skirmish.ledger.core]
|
||||
[skirmish.middleware.core :refer [create-exchange-apis-for]]
|
||||
[aero.core :refer (read-config)]
|
||||
[orchestra.spec.test :as st]
|
||||
@@ -16,11 +17,12 @@
|
||||
{:api-server skirmish.exchange-gateway.core/-main
|
||||
:exchange-core skirmish.exchange.core/-main ;; should be skirmish.exchange.core/api-main
|
||||
:api-bookkeeper skirmish.bookkeeper.core/-main
|
||||
:ledger skirmish.ledger.core/-main
|
||||
:wui skirmish.wui.server/-main})
|
||||
|
||||
(defn run-all-targets-in-separate-threads [target-fns config exchange-apis]
|
||||
(println "running multiple targets. This is okay in dev but horrible in production")
|
||||
(println target-fns)
|
||||
(println (clojure.string/join "\n" target-fns))
|
||||
(let [threads (map #(async/thread (% config exchange-apis)) target-fns)
|
||||
finished-threads (async/merge threads)]
|
||||
(loop [finished-thread (async/<!! finished-threads)]
|
||||
|
||||
@@ -10,8 +10,7 @@
|
||||
(defn -main [config exchange-apis]
|
||||
(let [webserver-config (:api-server config)
|
||||
api-routes (create-routes-for-exchange exchange-apis)]
|
||||
(println "Running server with bellow config")
|
||||
(println webserver-config)
|
||||
(println "Running skirmish.exchange-gateway.core server with bellow config\n" webserver-config)
|
||||
(run-server (api api-routes) webserver-config)))
|
||||
|
||||
|
||||
@@ -5,12 +5,11 @@
|
||||
[compojure.handler :refer [api]]
|
||||
[compojure.core :refer :all]
|
||||
[skirmish.order] ;; for spec side effect
|
||||
[skirmish.rest.util :refer [build-response build-response-body]]
|
||||
[skirmish.rest.util :refer [build-response build-response-body 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.edn :as edn]))
|
||||
[clojure.core.async :refer [chan go go-loop close! <! >!! sub]]))
|
||||
|
||||
|
||||
(def order-id (atom -1))
|
||||
@@ -28,13 +27,6 @@
|
||||
:book.order/entry-timestamp now})))
|
||||
|
||||
|
||||
(defn get-body [body]
|
||||
(try+
|
||||
(-> body clojure.java.io/reader slurp edn/read-string)
|
||||
(catch Exception e
|
||||
(throw+ {:error-type :4XX :status 400 :body {:error "Invalid body format. Body must be edn format."}}))))
|
||||
|
||||
|
||||
(defn get-exchange-api [sec-id exchange-apis]
|
||||
(if (contains? exchange-apis sec-id)
|
||||
(get exchange-apis sec-id)
|
||||
|
||||
@@ -1 +1,93 @@
|
||||
(ns skirmish.ledger.accounts)
|
||||
(ns skirmish.ledger.accounts
|
||||
(:require [datomic.api :as d]
|
||||
[slingshot.slingshot :refer [throw+]]))
|
||||
|
||||
(def db-uri "datomic:free://localhost:4334/skirmish")
|
||||
|
||||
(def create-securities
|
||||
[
|
||||
{:db/ident :skirmish.ledger/create-security
|
||||
:db/doc "Create a security in the system."
|
||||
:db/fn (d/function {:lang "clojure"
|
||||
:requires ['[slingshot.slingshot]]
|
||||
:params '[db sec-id interest-rate]
|
||||
:code '(let [security (d/pull db '[:db/id] [:skirmish.security/sec-id sec-id])]
|
||||
(when (-> security :db/id some?)
|
||||
(slingshot.slingshot/throw+ {:error-type :4XX :status 400 :body {:error "The security already exists."}}))
|
||||
[#:skirmish.security{:sec-id sec-id :interest-rate interest-rate}])})}])
|
||||
|
||||
(def print-securities
|
||||
[
|
||||
{:db/ident :skirmish.ledger/emit-securities
|
||||
:db/doc "Print securities fresh from the press."
|
||||
:db/fn (d/function {:lang "clojure"
|
||||
:requires ['[slingshot.slingshot]]
|
||||
:params '[db sec-id amount account-public-key]
|
||||
:code '(let [security (d/pull db '[:db/id] [:skirmish.security/sec-id sec-id])
|
||||
account (d/pull db '[:skirmish.ledger/amount :skirmish.security/sec] [:skirmish.ledger/owner-public-key account-public-key])
|
||||
base-amount (get account :skirmish.ledger/amount 0)
|
||||
entity (:db/id account "new-account")]
|
||||
(when (-> security :db/id nil?)
|
||||
(slingshot.slingshot/throw+ {:error-type :4XX :status 404 :body {:error "No security with such id."}}))
|
||||
(when (and (not= (:skirmish.security/sec account) (:db/id security)) (some? (:db/id account)))
|
||||
(slingshot.slingshot/throw+ {:error-type :4XX :status 400 :body {:error "The security emitted does not match the account security."}}))
|
||||
[[:db/add entity :skirmish.ledger/amount (+ base-amount amount)]
|
||||
[:db/add entity :skirmish.ledger/owner-public-key account-public-key]
|
||||
[:db/add entity :skirmish.ledger/sec (:db/id security)]])})}])
|
||||
|
||||
;; there are different types of securities...
|
||||
;; 1. currencies, which pays interest rates in their one sec-id.
|
||||
;; 2. equities, which do not pay interest rates.
|
||||
;; 3. bonds, which pays interest rates in another currency.
|
||||
|
||||
(def schema-securities
|
||||
[
|
||||
{
|
||||
:db/ident :skirmish.security/sec-id
|
||||
:db/valueType :db.type/keyword
|
||||
:db/cardinality :db.cardinality/one
|
||||
:db/unique :db.unique/identity
|
||||
:db/doc "The sec id."}
|
||||
{
|
||||
:db/ident :skirmish.security/interest-rate
|
||||
:db/valueType :db.type/long
|
||||
:db/cardinality :db.cardinality/one
|
||||
:db/doc "The interest-rate payed by the security as a multiple of 0.01% (100 is 1% interest rate)."}])
|
||||
|
||||
(def ledger-schema
|
||||
[
|
||||
|
||||
{
|
||||
:db/ident :skirmish.ledger/owner-public-key
|
||||
:db/unique :db.unique/identity
|
||||
:db/valueType :db.type/string
|
||||
:db/cardinality :db.cardinality/one
|
||||
:db/doc "The public key of the owner"}
|
||||
{
|
||||
:db/ident :skirmish.ledger/amount
|
||||
:db/index false
|
||||
:db/valueType :db.type/long
|
||||
:db/cardinality :db.cardinality/one
|
||||
:db/doc "The quantity of currency owned by this account."}
|
||||
{
|
||||
:db/ident :skirmish.ledger/sec
|
||||
:db/index false
|
||||
:db/valueType :db.type/ref
|
||||
:db/cardinality :db.cardinality/one
|
||||
:db/doc "The sec kept in this account."}])
|
||||
|
||||
|
||||
(def schema (-> []
|
||||
(concat schema-securities)
|
||||
(concat ledger-schema)
|
||||
(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))
|
||||
|
||||
@@ -1 +1,174 @@
|
||||
(ns skirmish.ledger.core)
|
||||
(ns skirmish.ledger.core
|
||||
(:require [org.httpkit.server :refer [run-server]]
|
||||
[compojure.handler :refer [api]]
|
||||
[skirmish.util :refer [block-thread]]
|
||||
[slingshot.slingshot :refer [try+ throw+]]
|
||||
[compojure.route :refer [not-found]]
|
||||
[skirmish.middleware.core :refer [create-exchange-apis-for]]
|
||||
[skirmish.exchange-gateway.exchange-gateway :refer [create-routes-for-exchange]]
|
||||
[skirmish.rest.util :refer [build-response get-body]]
|
||||
[skirmish.ledger.accounts]
|
||||
[datomic.api :as d]
|
||||
[compojure.core :refer :all]
|
||||
[clojure.spec.alpha :as s]
|
||||
[ring.middleware.cors :refer [wrap-cors]]))
|
||||
|
||||
;; the ledger is the central
|
||||
|
||||
;; an :account-id is the public key of a
|
||||
;; an :account-secret is an :acount-id private key
|
||||
|
||||
(defn get-account-body [request account sec]
|
||||
(if (nil? sec)
|
||||
(build-response request {:status 404})
|
||||
(let [sec-url (str "/api/1/securities/" (-> sec :skirmish.security/sec-id name))
|
||||
beautify-account { :amount (:skirmish.ledger/amount account)
|
||||
:sec-id (:skirmish.security/sec-id sec)
|
||||
:account-public-key (:skirmish.ledger/owner-public-key account)}
|
||||
ret {:account beautify-account :sec-url sec-url}]
|
||||
(build-response request ret))))
|
||||
|
||||
|
||||
(defn get-account [conn]
|
||||
"Returns the value of an account."
|
||||
(fn [{{account-id :account-id} :route-params :as request}]
|
||||
(let [db (d/db conn)
|
||||
account (d/pull db '[*] [:skirmish.ledger/owner-public-key account-id])
|
||||
sec-eid (-> account :skirmish.ledger/sec :db/id)
|
||||
sec (d/entity db sec-eid)]
|
||||
(get-account-body request account sec))))
|
||||
|
||||
|
||||
(s/def ::transaction (s/cat :type #{:create}
|
||||
:sec-id keyword?
|
||||
:amount int?
|
||||
:account-id string?))
|
||||
|
||||
|
||||
(defn get-transaction [raw-transact]
|
||||
(if (s/valid? ::transaction raw-transact)
|
||||
(s/conform ::transaction raw-transact)
|
||||
(throw+ {:error-type :4XX :status 400 :body {:error "Invalid transaction format."}})))
|
||||
|
||||
|
||||
(s/def ::security (s/cat :sec-id keyword?
|
||||
:interest-rate nat-int?))
|
||||
|
||||
(defn get-new-security [raw-securities]
|
||||
(if (s/valid? ::security raw-securities)
|
||||
raw-securities
|
||||
(throw+ {:error-type :4XX :status 400 :body {:error "Invalid security format."}})))
|
||||
|
||||
(defn get-security-from-db [conn sec-id]
|
||||
(let [e (d/pull (d/db conn) '[*] [:skirmish.security/sec-id sec-id])
|
||||
{interest-rate :skirmish.security/interest-rate id :db/id} e
|
||||
ret {:sec-id sec-id :interest-rate interest-rate}]
|
||||
(if (nil? id)
|
||||
(throw+ {:error-type :4XX :status 404 :body {:error "Security not found."}})
|
||||
ret)))
|
||||
|
||||
(defn create-security [conn]
|
||||
"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]])
|
||||
(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")))))
|
||||
|
||||
(defn get-security [conn]
|
||||
"Returns the security."
|
||||
(fn [{{sec-id-str :sec-id} :route-params :as request}]
|
||||
(try+
|
||||
(let [sec-id (keyword sec-id-str)]
|
||||
(build-response request (get-security-from-db conn sec-id)))
|
||||
(catch [:error-type :4XX] e (build-response request e))
|
||||
(catch [:error-type :5XX] e (build-response request e)))))
|
||||
|
||||
|
||||
(defn update-security [conn]
|
||||
"Update a security with new features."
|
||||
(fn [request]
|
||||
(try+
|
||||
(catch [:error-type :4XX] e (build-response request e))
|
||||
(catch [:error-type :5XX] e (build-response request e)))))
|
||||
|
||||
|
||||
(defn get-available-securities-body [securities]
|
||||
(let [sec-id->url #(str "/api/1/ledger/securities/" (name %))
|
||||
to-security-description #(hash-map :sec-id % :url (sec-id->url %))
|
||||
xf (comp cat (map to-security-description))
|
||||
securities-info (sequence xf securities)];;
|
||||
{:securities securities-info}))
|
||||
|
||||
|
||||
(defn get-available-securities [conn]
|
||||
(fn [request]
|
||||
(let [securities (d/q '[:find ?s :where [?e :skirmish.security/sec-id ?s]] (d/db conn))]
|
||||
(build-response request (get-available-securities-body securities)))))
|
||||
|
||||
|
||||
(s/def ::emit-securities (s/cat :sec-id keyword?
|
||||
:amount nat-int?
|
||||
:account string?))
|
||||
|
||||
|
||||
(defn get-emit-securities-request [[amount account] sec-id]
|
||||
(if (s/valid? ::emit-securities [sec-id amount account])
|
||||
[:skirmish.ledger/emit-securities sec-id amount account]
|
||||
(throw+ {:error-type :4XX :status 400 :body {:error "Invalid emit request."}})))
|
||||
|
||||
|
||||
(defn emit-securities [conn]
|
||||
(fn [{{sec-id-str :sec-id} :route-params body :body :as request}]
|
||||
(try+
|
||||
(let [emit-request (-> body get-body (get-emit-securities-request (keyword sec-id-str)))]
|
||||
@(d/transact conn [emit-request])
|
||||
(build-response request {}))
|
||||
(catch [:error-type :4XX] e (build-response request e))
|
||||
(catch [:error-type :5XX] e (build-response request e)))))
|
||||
|
||||
|
||||
(defn get-available-accounts-body [accounts]
|
||||
(let [sec-id->url #(str "/api/1/ledger/accounts/" (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)];;
|
||||
{:accounts securities-info}))
|
||||
|
||||
|
||||
(defn get-available-accounts [conn]
|
||||
(fn [request]
|
||||
(let [securities (d/q '[:find ?pk :where [?e :skirmish.ledger/owner-public-key ?pk]] (d/db conn))]
|
||||
(build-response request (get-available-accounts-body securities)))))
|
||||
|
||||
(defn get-api-description [request]
|
||||
(let [body [{:url "ledger/accounts" :name "accounts"}
|
||||
{:url "ledger/securities" :name "securities"}]]
|
||||
(build-response request body)))
|
||||
|
||||
(defn create-routes-for-ledger [securities conn]
|
||||
(routes
|
||||
(context "/api/1" []
|
||||
(GET "/" get-api-description)
|
||||
(GET "/ledger/accounts" [] (get-available-accounts conn))
|
||||
(GET "/ledger/accounts/:account-id" [] (get-account conn))
|
||||
(GET "/ledger/securities" [] (get-available-securities conn)) ;; done
|
||||
(POST "/ledger/securities" [] (create-security conn)) ;; done
|
||||
(GET "/ledger/securities/:sec-id" [] (get-security conn)) ;; done
|
||||
(PUT "/ledger/securities/:sec-id" [] (update-security conn)) ;; not done
|
||||
(POST "/ledger/securities/:sec-id" [] (emit-securities conn))) ;; done
|
||||
(not-found "not found")))
|
||||
|
||||
|
||||
(defn -main [config 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)]
|
||||
|
||||
(println "Running skirmish.ledger.core server with bellow config\n" ledger-config)
|
||||
(run-server (api api-routes) ledger-config)))
|
||||
@@ -1,5 +1,7 @@
|
||||
(ns skirmish.rest.util
|
||||
(:require [cheshire.core :refer [generate-string]]
|
||||
[slingshot.slingshot :refer [try+ throw+]]
|
||||
[clojure.edn :as edn]
|
||||
[clojure.string :refer [split starts-with? ends-with?]]))
|
||||
|
||||
;; Access-Control-Allow-Origin
|
||||
@@ -40,8 +42,24 @@
|
||||
(let [[_ serializer] (get-best-serializer request)]
|
||||
(serializer body)))
|
||||
|
||||
(defn build-response [request {status :status body :body :as response}]
|
||||
(let [[content-type serializer] (get-best-serializer request)]
|
||||
(defn build-response [request {status :status body :body headers :headers :as response}]
|
||||
(let [[content-type serializer] (get-best-serializer request)
|
||||
ret-headers (if (some? headers) headers {})]
|
||||
{:body (serializer (if (nil? body) response body))
|
||||
:headers {"Content-Type" content-type}
|
||||
:status (get-status status request)}))
|
||||
:headers (into {"Content-Type" content-type} ret-headers)
|
||||
:status (get-status status request)}))
|
||||
|
||||
(defn get-body [body]
|
||||
(try+
|
||||
(-> body clojure.java.io/reader slurp edn/read-string)
|
||||
(catch Exception e
|
||||
(throw+ {:error-type :4XX :status 400 :body {:error "Invalid body format. Body must be edn format."}}))))
|
||||
|
||||
(defn string->stream
|
||||
([s] (string->stream s "UTF-8"))
|
||||
([s encoding]
|
||||
(-> s
|
||||
(.getBytes encoding)
|
||||
(java.io.ByteArrayInputStream.))))
|
||||
|
||||
(def edn->stream (comp string->stream str))
|
||||
@@ -10,4 +10,21 @@
|
||||
|
||||
(defn block-thread []
|
||||
"Block the current thread until chuck norris gets weaker."
|
||||
(async/<!! (async/chan)))
|
||||
(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,4 +1,50 @@
|
||||
(ns skirmish.wui.components.create-order-page)
|
||||
(ns skirmish.wui.components.create-order-page
|
||||
(:require [reagent.core :refer [atom]]))
|
||||
|
||||
(defn set-value-in-atom [atm key evt]
|
||||
(swap! atm #(assoc % key (-> evt .-target .-value))))
|
||||
|
||||
|
||||
|
||||
(defn select-type [order]
|
||||
[:div.control
|
||||
[:div.select
|
||||
[:select {:on-change (partial set-value-in-atom order :type)}
|
||||
[:option {:value :buy} "Buy"]
|
||||
[:option {:value :sell} "Sell"]]]])
|
||||
|
||||
(defn select-securities [order]
|
||||
[:div.control
|
||||
[:div.select
|
||||
[:select {:on-change (partial set-value-in-atom order :sec-id)}
|
||||
[:option {:value :nype} ":nype"]
|
||||
[:option {:value :osko} ":osko"]
|
||||
[:option {:value :oops} ":oops"]]]])
|
||||
|
||||
(defn select-quantities [order]
|
||||
[:div.control
|
||||
[:input.input {:type "number"
|
||||
:on-change (partial set-value-in-atom order :quantity)}]])
|
||||
|
||||
(def action-button
|
||||
[:div.control
|
||||
[:button.button.is-primary "Submit"]])
|
||||
|
||||
|
||||
(defn page []
|
||||
[:h1 "create order page"])
|
||||
(let [order (atom {})]
|
||||
(fn []
|
||||
[:div
|
||||
[:div.columns
|
||||
[:div.column.content
|
||||
[:div.columns.is-centered
|
||||
[:column
|
||||
[:div.field.has-addons
|
||||
(select-type order)
|
||||
(select-securities order)
|
||||
(select-quantities order)
|
||||
action-button]]]]]
|
||||
[:div.columns
|
||||
[:div.column.content
|
||||
[:pre (str @order)]]]])))
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
(ns skirmish.wui.components.home-page)
|
||||
(ns skirmish.wui.components.home-page
|
||||
(:require [reagent.core :refer [atom]]))
|
||||
|
||||
|
||||
(def lorem-ipsum ["Lorem ipsum dolor amet pickled bushwick next level adaptogen ugh franzen salvia hoodie man bun organic kinfolk. Hammock pickled banjo, artisan single-origin coffee brunch 90's occupy taxidermy. Put a bird on it gentrify offal tilde. Authentic put a bird on it prism semiotics, roof party banh mi typewriter. XOXO schlitz sriracha godard."
|
||||
"Succulents shoreditch twee, VHS hammock hot chicken distillery. Edison bulb aesthetic pork belly meggings. 3 wolf moon artisan keytar blue bottle. Actually pok pok asymmetrical, banh mi before they sold out PBR&B portland tumblr."
|
||||
"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 page [state]
|
||||
[:h1 "Hello world sdjjksd dsklsd"])
|
||||
[:div
|
||||
[:section.section
|
||||
[:div.container
|
||||
[:h1.title "lorem ipsum"]
|
||||
(for [sentence lorem-ipsum]
|
||||
[:p sentence])]]])
|
||||
@@ -1,4 +1,21 @@
|
||||
(ns skirmish.wui.components.portfolio-page)
|
||||
(ns skirmish.wui.components.portfolio-page
|
||||
(:require [reagent.core :refer [atom]]
|
||||
[skirmish.wui.components.secunit :refer [secunit]]))
|
||||
|
||||
(defn make-portfolio-summary-table [portfolio]
|
||||
[:table
|
||||
[:thead
|
||||
[:tr [:th "Security"] [:th "Amount"] [:th "Face Value"]]]
|
||||
[:tbody
|
||||
(for [sec-summary portfolio]
|
||||
[:tr
|
||||
[:td (:sec-id sec-summary)]
|
||||
[:td [secunit (:sec-id sec-summary) (:amount sec-summary)]]
|
||||
[:td [secunit :dapm (:face-value sec-summary)]]])]])
|
||||
|
||||
(defn page []
|
||||
[:h1 "portfolio page"])
|
||||
(let [porfolio [{:sec-id :foo :amount 100 :face-value 1265}
|
||||
{:sec-id :toto :amount 100 :face-value 1265}
|
||||
{:sec-id :foo :amount 100 :face-value 1265}]]
|
||||
[:div.content
|
||||
(make-portfolio-summary-table porfolio)]))
|
||||
@@ -0,0 +1,5 @@
|
||||
(ns skirmish.wui.components.secunit)
|
||||
|
||||
(defn secunit [sec-id amount]
|
||||
(let [href (str "/securities/" sec-id)]
|
||||
[:a {:href href} (str amount)]))
|
||||
Reference in new issue
Block a user