going somewhere.

This commit is contained in:
didier amyot committed 2020-09-11 07:25:08 -04:00
1 parent 30d732f708
commit 75a91f7f7b
2 files changed
+84 -28

No files matched your search

+29 -3
View File
@@ -1,6 +1,7 @@
(ns skirmish.ledger.data-layer
(:require [datomic.api :as d]
[infix.macros :refer [infix]]))
[infix.macros :refer [infix]]
[slingshot.slingshot :refer [throw+]]))
(defn get-all-account-public-key [db]
(d/q '[:find ?pk :where [?e :skirmish.ledger/owner-public-key ?pk]] db))
@@ -123,6 +124,31 @@
res (assoc res (:to-account-id transaction) to-account)]
res))
(defn validate-transactions [transactions]
(loop [transactions transactions]
(when (seq transactions)
(let [transaction (first transactions)]
(when (not= (-> transaction :from-account :skirmish.ledger/sec)
(-> transaction :to-account :skirmish.ledger/sec))
(throw+ {:error-type :4XX
:status 400
:body {:error "Part of the transaction includes a transaction between two wallets of different underlying securities."}}))
(recur (rest transactions)))))
transactions)
(defn validate-resulting-transactions [transactions]
(loop [transactions transactions]
(when (seq transactions)
(let [transaction (first transactions)]
(when (neg? (get transaction 3))
(throw+ {:error-type :4XX
:status 400
:body {:error "Transaction would result in a negative amount in a wallet."}})))
(recur (rest transactions))))
transactions)
(defn create-transactions [db transactions]
(let [transactions (map #(assoc-accounts db %) transactions)]
(into #{} (vals (reduce compute-transactions {} transactions)))))
(let [transactions (map #(assoc-accounts db %) transactions)
transactions (validate-transactions transactions)
ret (vals (reduce compute-transactions {} transactions))]
(validate-resulting-transactions ret)))
+55 -25
View File
@@ -57,21 +57,22 @@
(->> create-security-4 cs (s/assert ::ok))
conn))
(defn create-some-accounts [conn]
(let [es (controllers/emit-securities conn)
emit-sec-req-1 {:body (edn->stream [100 "1-sec-1"]) :route-params {:sec-id "sec-1"}}
emit-sec-req-2 {:body (edn->stream [200 "2-sec-1"]) :route-params {:sec-id "sec-1"}}
emit-sec-req-3 {:body (edn->stream [1000 "1-sec-2"]) :route-params {:sec-id "sec-2"}}
emit-sec-req-4 {:body (edn->stream [2000 "2-sec-2"]) :route-params {:sec-id "sec-2"}}]
(->> emit-sec-req-1 es (s/assert ::ok))
(->> emit-sec-req-2 es (s/assert ::ok))
(->> emit-sec-req-3 es (s/assert ::ok))
(->> emit-sec-req-4 es (s/assert ::ok))
(defn create-some-accounts [conn n]
(let [create-emit-req (fn [amount account-id sec-id] {:body (edn->stream [amount account-id]) :route-params {:sec-id sec-id}})
sec-1-reqs (for [i (range 1 (inc n))] (create-emit-req (* i 100) (str i "-sec-1") "sec-1"))
sec-2-reqs (for [i (range 1 (inc n))] (create-emit-req (* i 100) (str i "-sec-2") "sec-2"))
reqs (concat sec-1-reqs sec-2-reqs)]
(loop [reqs reqs]
(when (seq reqs)
(let [es (controllers/emit-securities conn)
req (first reqs)]
(->> req es (s/assert ::ok))
(recur (rest reqs)))))
conn))
(def create-some-securities-and-accounts (comp create-some-accounts create-some-securities))
(defn create-some-securities-and-accounts [conn n-accounts-by-currency]
(-> conn create-some-securities (create-some-accounts n-accounts-by-currency)))
(facts "about the securities"
@@ -173,24 +174,24 @@
(facts "about accounts"
(fact "we should be able to get list of all accounts"
(let [conn (create-some-securities-and-accounts (create-conn))
(let [conn (create-some-securities-and-accounts (create-conn) 2)
req {:route-params {} :headers {"accept" "application/edn"}}
expt [{:account-public-key "1-sec-1" :url "http://localhost:1604/api/1/ledger/accounts/1-sec-1"}
{:account-public-key "1-sec-2" :url "http://localhost:1604/api/1/ledger/accounts/1-sec-2"}
{:account-public-key "2-sec-1" :url "http://localhost:1604/api/1/ledger/accounts/2-sec-1"}
{:account-public-key "2-sec-2" :url "http://localhost:1604/api/1/ledger/accounts/2-sec-2"}]]
expt #{{:account-public-key "1-sec-1" :url "http://localhost:1604/api/1/ledger/accounts/1-sec-1"}
{:account-public-key "1-sec-2" :url "http://localhost:1604/api/1/ledger/accounts/1-sec-2"}
{:account-public-key "2-sec-1" :url "http://localhost:1604/api/1/ledger/accounts/2-sec-1"}
{:account-public-key "2-sec-2" :url "http://localhost:1604/api/1/ledger/accounts/2-sec-2"}}]
((controllers/get-available-accounts conn) req) => (spec-check ::ok)
(-> ((controllers/get-available-accounts conn) req) body :accounts sec->hash-set) => (sec->hash-set expt)))
(-> ((controllers/get-available-accounts conn) req) body :accounts) => (just expt)))
(fact "we should be able to get account"
(let [conn (create-some-securities-and-accounts (create-conn))
(let [conn (create-some-securities-and-accounts (create-conn) 10)
req {:route-params {:account-id "2-sec-1"} :headers {"accept" "application/edn"}}]
((controllers/get-account conn) req) => (spec-check ::ok)
(body ((controllers/get-account conn) req)) => {:account {:account-public-key "2-sec-1" :amount 200 :sec-id :sec-1}
:sec-url "/api/1/ledger/securities/sec-1"}))
(fact "the interest should be payed when getting the account"
(let [conn (create-some-securities-and-accounts (create-conn))
(let [conn (create-some-securities-and-accounts (create-conn) 10)
req {:route-params {:account-id "2-sec-1"} :headers {"accept" "application/edn"}}]
((controllers/get-account conn) req) => (spec-check ::ok)
(body ((controllers/get-account conn) req)) => {:account {:account-public-key "2-sec-1" :amount 200 :sec-id :sec-1}
@@ -198,7 +199,7 @@
(fact "we should not get an account if it does not exists"
(let [conn (create-some-securities-and-accounts (create-conn))
(let [conn (create-some-securities-and-accounts (create-conn) 10)
req {:route-params {:account-id "2-sec-10"} :headers {"accept" "application/edn"}}]
((controllers/get-account conn) req) => (spec-check ::status-404))))
@@ -266,7 +267,7 @@
(facts "about transactions"
(fact "about transferring an amount from one wallet to another"
(let [conn (create-some-securities-and-accounts (create-conn))
(let [conn (create-some-securities-and-accounts (create-conn) 10)
transaction {:from-account-id "1-sec-1"
:to-account-id "2-sec-1"
:amount 50}
@@ -274,13 +275,42 @@
[eid1 eid2] (get-account-eids db "1-sec-1" "2-sec-1")
expt #{[:db/add eid1 :skirmish.ledger/amount 50]
[:db/add eid2 :skirmish.ledger/amount 250]}]
(data-layer/create-transactions db [transaction]) => expt)) ;expt))
(data-layer/create-transactions db [transaction]) => (just expt)))
(fact "about transferring an amount from one wallet to another"
(let [conn (create-some-securities-and-accounts (create-conn))
(let [conn (create-some-securities-and-accounts (create-conn) 10)
transaction {:from-account-id "1-sec-1"
:to-account-id "1-sec-1"
:amount 45}
db (d/db conn)
[eid1] (get-account-eids db "1-sec-1")
expt #{[:db/add eid1 :skirmish.ledger/amount 100]}]
(data-layer/create-transactions db [transaction]) => expt)))
(data-layer/create-transactions db [transaction]) => (just expt)))
(fact "about transferring amounts between three wallets"
(let [conn (create-some-securities-and-accounts (create-conn) 10)
transaction-1 {:from-account-id "1-sec-1"
:to-account-id "2-sec-1"
:amount 50}
transaction-2 {:from-account-id "2-sec-1"
:to-account-id "3-sec-1"
:amount 250}
db (d/db conn)
[eid1 eid2 eid3] (get-account-eids db "1-sec-1" "2-sec-1" "3-sec-1")
expt #{[:db/add eid1 :skirmish.ledger/amount 50]
[:db/add eid2 :skirmish.ledger/amount 0]
[:db/add eid3 :skirmish.ledger/amount 550]}]
(data-layer/create-transactions db [transaction-1 transaction-2]) => (just expt)))
(fact "about transaction between different assets types"
(let [conn (create-some-securities-and-accounts (create-conn) 10)
transaction {:from-account-id "1-sec-1"
:to-account-id "1-sec-2"
:amount 50}
db (d/db conn)]
(data-layer/create-transactions db [transaction]) => (throws #"different underlying securities")))
(fact "about transaction with negative results"
(let [conn (create-some-securities-and-accounts (create-conn) 10)
transaction {:from-account-id "1-sec-1"
:to-account-id "2-sec-1"
:amount 500}
db (d/db conn)]
(data-layer/create-transactions db [transaction]) => (throws #"negative amount in a wallet"))))