|
|
@ -77,17 +77,19 @@ |
|
|
|
|
|
|
|
(def lower-case-keyword (comp keyword str/lower-case)) |
|
|
|
|
|
|
|
(defn- currency-product [currency] |
|
|
|
(defn- currency-product [base currency] |
|
|
|
(str (-> currency name str/upper-case) |
|
|
|
"-USD")) |
|
|
|
|
|
|
|
(defn- product-currency [product] |
|
|
|
(if-let [currency (some-> (re-matches #"^([A-Z]{2,5})-USD$" product) |
|
|
|
(get 1) |
|
|
|
(lower-case-keyword))] |
|
|
|
currency |
|
|
|
(throw (ex-info (str "not a valid product_id: " product) |
|
|
|
{:product product})))) |
|
|
|
"-" |
|
|
|
base)) |
|
|
|
|
|
|
|
(defn- product-currency [base product] |
|
|
|
(let [product-rx (re-pattern (format "^([A-Z]{2,5})-%s$" base))] |
|
|
|
(if-let [currency (some-> (re-matches product-rx product) |
|
|
|
(get 1) |
|
|
|
(lower-case-keyword))] |
|
|
|
currency |
|
|
|
(throw (ex-info (str "not a valid product_id: " product) |
|
|
|
{:product product}))))) |
|
|
|
|
|
|
|
(defn- accounts-request [] |
|
|
|
(-> (req/base-request) |
|
|
@ -112,12 +114,12 @@ |
|
|
|
(req/with-path (build-path :orders order-id)))) |
|
|
|
|
|
|
|
(defn- currency-orders-request |
|
|
|
([currency] (currency-orders-request currency {})) |
|
|
|
([currency query] (-> (req/base-request) |
|
|
|
(req/as-get); |
|
|
|
(req/with-path (build-path :orders)) |
|
|
|
(req/with-query-params |
|
|
|
(merge query { :product_id (currency-product currency) }))))) |
|
|
|
([base currency] (currency-orders-request currency {})) |
|
|
|
([base currency query] (-> (req/base-request) |
|
|
|
(req/as-get); |
|
|
|
(req/with-path (build-path :orders)) |
|
|
|
(req/with-query-params |
|
|
|
(merge query { :product_id (currency-product base currency) }))))) |
|
|
|
|
|
|
|
(defn- create-order-request [order] |
|
|
|
(-> (req/base-request) |
|
|
@ -128,11 +130,11 @@ |
|
|
|
:args (s/cat :params ::order-req/order) |
|
|
|
:ret ::req/request) |
|
|
|
|
|
|
|
(defn- ticker-request [currency] |
|
|
|
(defn- ticker-request [base currency] |
|
|
|
(-> (req/base-request) |
|
|
|
(req/as-get) |
|
|
|
(req/with-path (build-path :products |
|
|
|
(currency-product currency) |
|
|
|
(currency-product base currency) |
|
|
|
:ticker)))) |
|
|
|
|
|
|
|
(defn- ensure-keys [ks m] |
|
|
@ -186,11 +188,12 @@ |
|
|
|
|
|
|
|
(defn- reify-exchange-client [{client ::http/client |
|
|
|
hostname ::hostname |
|
|
|
logger ::log/logger}] |
|
|
|
logger ::log/logger |
|
|
|
base ::base-currency}] |
|
|
|
(let [request! (fn [req] (http/execute-request! client (req/with-host req hostname)))] |
|
|
|
(reify client/ExchangeClient |
|
|
|
(get-ticker! [_ currency] |
|
|
|
(map-success (request! (ticker-request currency)) |
|
|
|
(map-success (request! (ticker-request base currency)) |
|
|
|
(partial reify-ticker currency))) |
|
|
|
(get-market-price! [self currency] |
|
|
|
(map-success (client/get-ticker! self currency) |
|
|
@ -199,10 +202,12 @@ |
|
|
|
(defn- reify-exchange-account-client [opts] |
|
|
|
(let [{client ::http/client |
|
|
|
hostname ::hostname |
|
|
|
logger ::log/logger} opts |
|
|
|
logger ::log/logger |
|
|
|
base ::base-currency} opts |
|
|
|
public-client (reify-exchange-client opts) |
|
|
|
request! (fn [req] (http/execute-request! client (req/with-host req hostname))) |
|
|
|
before (fn [a b] (.isBefore a b)) |
|
|
|
reify-order (partial reify-order base) |
|
|
|
reify-orders (comp (partial sort-by order/created before) |
|
|
|
(partial map reify-order)) |
|
|
|
accounts-map (fn [accts] (into {} (map (juxt acct/currency identity) accts)))] |
|
|
@ -231,15 +236,17 @@ |
|
|
|
reify-order)) |
|
|
|
|
|
|
|
(get-orders! [_ currency] |
|
|
|
(map-success (request! (currency-orders-request currency)) |
|
|
|
(map-success (request! (currency-orders-request base currency)) |
|
|
|
reify-orders)) |
|
|
|
|
|
|
|
(get-incomplete-orders! [_ currency] |
|
|
|
(map-success (request! (currency-orders-request currency { ::order/status [:open :pending] })) |
|
|
|
(map-success (request! (currency-orders-request base currency |
|
|
|
{ ::order/status [:open :pending] })) |
|
|
|
reify-orders)) |
|
|
|
|
|
|
|
(get-completed-orders! [_ currency] |
|
|
|
(map-success (request! (currency-orders-request currency { ::order/status [:done] })) |
|
|
|
(map-success (request! (currency-orders-request base currency |
|
|
|
{ ::order/status [:done] })) |
|
|
|
reify-orders)) |
|
|
|
|
|
|
|
(get-completed-limit-orders! [self currency] |
|
|
@ -259,21 +266,21 @@ |
|
|
|
to-uuid)) |
|
|
|
|
|
|
|
(create-stop-loss-order! [_ currency stop-price sell-price size] |
|
|
|
(map-success (request! (create-order-request (-> (order-req/base-order (currency-product currency)) |
|
|
|
(map-success (request! (create-order-request (-> (order-req/base-order (currency-product base currency)) |
|
|
|
(order-req/as-stop-loss (bigdec stop-price)) |
|
|
|
(order-req/with-price (bigdec sell-price)) |
|
|
|
(order-req/with-size (bigdec size))))) |
|
|
|
(comp to-uuid :id))) |
|
|
|
|
|
|
|
(create-stop-gain-order! [_ currency stop-price buy-price size] |
|
|
|
(map-success (request! (create-order-request (-> (order-req/base-order (currency-product currency)) |
|
|
|
(map-success (request! (create-order-request (-> (order-req/base-order (currency-product base currency)) |
|
|
|
(order-req/as-stop-gain (bigdec stop-price)) |
|
|
|
(order-req/with-price (bigdec buy-price)) |
|
|
|
(order-req/with-size (bigdec size))))) |
|
|
|
(comp to-uuid :id))) |
|
|
|
|
|
|
|
(create-limit-sell-order! [_ currency sell-price size] |
|
|
|
(map-success (request! (create-order-request (-> (order-req/base-order (currency-product currency)) |
|
|
|
(map-success (request! (create-order-request (-> (order-req/base-order (currency-product base currency)) |
|
|
|
(order-req/as-limit) |
|
|
|
(order-req/as-sell) |
|
|
|
(order-req/with-price (bigdec sell-price)) |
|
|
@ -281,15 +288,16 @@ |
|
|
|
(comp to-uuid :id))) |
|
|
|
|
|
|
|
(create-limit-buy-order! [_ currency buy-price size] |
|
|
|
(map-success (request! (create-order-request (-> (order-req/base-order (currency-product currency)) |
|
|
|
(map-success (request! (create-order-request (-> (order-req/base-order (currency-product base currency)) |
|
|
|
(order-req/as-limit) |
|
|
|
(order-req/as-buy) |
|
|
|
(order-req/with-price (bigdec buy-price)) |
|
|
|
(order-req/with-size (bigdec size))))) |
|
|
|
(comp to-uuid :id)))))) |
|
|
|
|
|
|
|
(defn connect [& {:keys [hostname logger credentials] |
|
|
|
:or { logger (log/print-logger :error :notify) }}] |
|
|
|
(defn connect [& {:keys [hostname logger credentials base-currency] |
|
|
|
:or { logger (log/print-logger :error :notify) |
|
|
|
base-currency "USD"}}] |
|
|
|
(if credentials |
|
|
|
(let [authenticator (make-request-authenticator credentials)] |
|
|
|
(reify-exchange-account-client {::http/client (http/json-client :authenticator authenticator |
|
|
|