Initial, still broken, checkin
This commit is contained in:
commit
21d07b383c
|
@ -0,0 +1,8 @@
|
||||||
|
.DS_Store
|
||||||
|
.idea
|
||||||
|
*.log
|
||||||
|
tmp/
|
||||||
|
|
||||||
|
.cpcache/
|
||||||
|
.nrepl-port
|
||||||
|
target/
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
:paths ["src"]
|
||||||
|
:deps {
|
||||||
|
org.clojure/clojure { :mvn/version "1.10.3" }
|
||||||
|
org.clojure/core.async { :mvn/version "1.5.640" }
|
||||||
|
org.clojure/data.json { :mvn/version "2.4.0" }
|
||||||
|
|
||||||
|
clj-http/clj-http { :mvn/version "3.12.3" }
|
||||||
|
|
||||||
|
org.fudo/fudo-clojure {
|
||||||
|
:git/url "https://git.fudo.org/fudo-public/fudo-clojure.git"
|
||||||
|
:sha "047f5d531c8d1493880313d13bbff6da88b0a4b8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,397 @@
|
||||||
|
# generated by clj2nix-1.1.0-rc
|
||||||
|
{ fetchMavenArtifact, fetchgit, lib }:
|
||||||
|
|
||||||
|
let repos = [
|
||||||
|
"https://repo1.maven.org/maven2/"
|
||||||
|
"https://repo.clojars.org/" ];
|
||||||
|
|
||||||
|
in rec {
|
||||||
|
makePaths = {extraClasspaths ? []}:
|
||||||
|
if (builtins.typeOf extraClasspaths != "list")
|
||||||
|
then builtins.throw "extraClasspaths must be of type 'list'!"
|
||||||
|
else (lib.concatMap (dep:
|
||||||
|
builtins.map (path:
|
||||||
|
if builtins.isString path then
|
||||||
|
path
|
||||||
|
else if builtins.hasAttr "jar" path then
|
||||||
|
path.jar
|
||||||
|
else if builtins.hasAttr "outPath" path then
|
||||||
|
path.outPath
|
||||||
|
else
|
||||||
|
path
|
||||||
|
)
|
||||||
|
dep.paths)
|
||||||
|
packages) ++ extraClasspaths;
|
||||||
|
makeClasspaths = {extraClasspaths ? []}:
|
||||||
|
if (builtins.typeOf extraClasspaths != "list")
|
||||||
|
then builtins.throw "extraClasspaths must be of type 'list'!"
|
||||||
|
else builtins.concatStringsSep ":" (makePaths {inherit extraClasspaths;});
|
||||||
|
packageSources = builtins.map (dep: dep.src) packages;
|
||||||
|
packages = [
|
||||||
|
rec {
|
||||||
|
name = "data.json/org.clojure";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "data.json";
|
||||||
|
groupId = "org.clojure";
|
||||||
|
sha512 = "04b7c0c90cb26d643a0b3e7e1ffa2d2d423e977c1454ee5ea7c2e75547ecbc113838df17b797902a975f5ea2184a81a45b605a4d82970805e2bbb02feebc578d";
|
||||||
|
version = "2.4.0";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "clojure/org.clojure";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "clojure";
|
||||||
|
groupId = "org.clojure";
|
||||||
|
sha512 = "4bb567b9262d998f554f44e677a8628b96e919bc8bcfb28ab2e80d9810f8adf8f13a8898142425d92f3515e58c57b16782cff12ba1b5ffb38b7d0ccd13d99bbc";
|
||||||
|
version = "1.10.3";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "commons-codec/commons-codec";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "commons-codec";
|
||||||
|
groupId = "commons-codec";
|
||||||
|
sha512 = "da30a716770795fce390e4dd340a8b728f220c6572383ffef55bd5839655d5611fcc06128b2144f6cdcb36f53072a12ec80b04afee787665e7ad0b6e888a6787";
|
||||||
|
version = "1.15";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "tools.analyzer/org.clojure";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "tools.analyzer";
|
||||||
|
groupId = "org.clojure";
|
||||||
|
sha512 = "c51752a714848247b05c6f98b54276b4fe8fd44b3d970070b0f30cd755ac6656030fd8943a1ffd08279af8eeff160365be47791e48f05ac9cc2488b6e2dfe504";
|
||||||
|
version = "1.1.0";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "core.specs.alpha/org.clojure";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "core.specs.alpha";
|
||||||
|
groupId = "org.clojure";
|
||||||
|
sha512 = "c1d2a740963896d97cd6b9a8c3dcdcc84459ea66b44170c05b8923e5fbb731b4b292b217ed3447bbc9e744c9a496552f77a6c38aea232e5e69f8faa627dea4b5";
|
||||||
|
version = "0.2.56";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "spec.alpha/org.clojure";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "spec.alpha";
|
||||||
|
groupId = "org.clojure";
|
||||||
|
sha512 = "0740dc3a755530f52e32d27139a9ebfd7cbdb8d4351c820de8d510fe2d52a98acd6e4dfc004566ede3d426e52ec98accdca1156965218f269e60dd1cd4242a73";
|
||||||
|
version = "0.2.194";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "httpasyncclient/org.apache.httpcomponents";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "httpasyncclient";
|
||||||
|
groupId = "org.apache.httpcomponents";
|
||||||
|
sha512 = "0a80db5dbf772f02d02ba6c7c163e8da9517dd7195714b495acb845c429580c1fc926d3e71c115e75be8c145651dce2fdfa0dc380132f7809c14b3ad95492aee";
|
||||||
|
version = "4.1.4";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "tools.analyzer.jvm/org.clojure";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "tools.analyzer.jvm";
|
||||||
|
groupId = "org.clojure";
|
||||||
|
sha512 = "6764305bd18a5b7bddd7e50b037cbcdb4f5cf61606faa92353bfb4fdb89dc9055530c665e102cd7e17b808f3461255bcc8c88a7b46d5af9bec8d6eaf7000ae7d";
|
||||||
|
version = "1.2.0";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "slingshot/slingshot";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "slingshot";
|
||||||
|
groupId = "slingshot";
|
||||||
|
sha512 = "ff2b2a27b441d230261c7f3ec8c38aa551865e05ab6438a74bd12bfcbc5f6bdc88199d42aaf5932b47df84f3d2700c8f514b9f4e9b5da28d29da7ff6b09a7fb5";
|
||||||
|
version = "0.12.2";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "httpcore-nio/org.apache.httpcomponents";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "httpcore-nio";
|
||||||
|
groupId = "org.apache.httpcomponents";
|
||||||
|
sha512 = "002af5f72b68a4ff1b1ff46b788013283d195e1d62ee1d7b102aa930b30f77f7e215a6d18edbea0fccd18fb1fa3a66cc4aef6070d72d6d1886f0044dfe0e16c7";
|
||||||
|
version = "4.4.10";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "commons-io/commons-io";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "commons-io";
|
||||||
|
groupId = "commons-io";
|
||||||
|
sha512 = "72040ed293a083f979c3f23b00c359195cf0e4c227a9cb962d99804cbe07d86e24d2864aa8c533bb79e4ad1f83d3d17f290c8c24630410eb80734d6d1266e7ec";
|
||||||
|
version = "2.8.0";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "clj-http/clj-http";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "clj-http";
|
||||||
|
groupId = "clj-http";
|
||||||
|
sha512 = "9884557d4f38068cb3234aec80acc0de8f9716645529693ffd9bd6db8221f5d1cf9e2d1b8bf7c7df4215d71372b02d83043ebf8fc27dc422552b32c9bdba1602";
|
||||||
|
version = "3.12.3";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "asm/org.ow2.asm";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "asm";
|
||||||
|
groupId = "org.ow2.asm";
|
||||||
|
sha512 = "40614e658138f2eb95bc26999545f996794c622c4d68efb9e10093743504c4b58bf22590767bc6bd93b77cdfb202c507144ba867bbc8b54d74fe7621cbc55e3a";
|
||||||
|
version = "5.2";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "httpcore/org.apache.httpcomponents";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "httpcore";
|
||||||
|
groupId = "org.apache.httpcomponents";
|
||||||
|
sha512 = "f16a652f4a7b87dbf7cb16f8590d54a3f719c4c7b2f8883ce59db2d73be4701b64f2ca8a2c45aca6a5dbeaddeedff0c280a03722f70c076e239b645faa54eff9";
|
||||||
|
version = "4.4.14";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "httpclient-cache/org.apache.httpcomponents";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "httpclient-cache";
|
||||||
|
groupId = "org.apache.httpcomponents";
|
||||||
|
sha512 = "e150e8dc49c8c9972d8b324b56bb292b15e2f0e686f1292c4edac975615dfb16e5edb8ab325e614732a7d43a03061ca4fe93fe1e1f7487851a4d4d3af50a61f9";
|
||||||
|
version = "4.5.13";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "clj-tuple/clj-tuple";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "clj-tuple";
|
||||||
|
groupId = "clj-tuple";
|
||||||
|
sha512 = "dd626944d0aba679a21b164ed0c77ea84449359361496cba810f83b9fdeab751e5889963888098ce4bf8afa112dbda0a46ed60348a9c01ad36a2e255deb7ab6d";
|
||||||
|
version = "0.2.2";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "riddley/riddley";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "riddley";
|
||||||
|
groupId = "riddley";
|
||||||
|
sha512 = "b478ecba9d1ab9d38c84a42354586fcece763000907b40c97bc43c0f16dc560b0860144efe410193cb3b7cb0149fbc1724fdd737cc3ba53de23618f5b30e6f9f";
|
||||||
|
version = "0.1.12";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "commons-logging/commons-logging";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "commons-logging";
|
||||||
|
groupId = "commons-logging";
|
||||||
|
sha512 = "ed00dbfabd9ae00efa26dd400983601d076fe36408b7d6520084b447e5d1fa527ce65bd6afdcb58506c3a808323d28e88f26cb99c6f5db9ff64f6525ecdfa557";
|
||||||
|
version = "1.2";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "httpclient/org.apache.httpcomponents";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "httpclient";
|
||||||
|
groupId = "org.apache.httpcomponents";
|
||||||
|
sha512 = "3567739186e551f84cad3e4b6b270c5b8b19aba297675a96bcdff3663ff7d20d188611d21f675fe5ff1bfd7d8ca31362070910d7b92ab1b699872a120aa6f089";
|
||||||
|
version = "4.5.13";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
(rec {
|
||||||
|
name = "org.fudo/fudo-clojure";
|
||||||
|
src = fetchgit {
|
||||||
|
name = "fudo-clojure";
|
||||||
|
url = "https://git.fudo.org/fudo-public/fudo-clojure.git";
|
||||||
|
rev = "047f5d531c8d1493880313d13bbff6da88b0a4b8";
|
||||||
|
sha256 = "1lbc7nf0qdb97znn6nl46q0489caxlsiki2apw4isfx8m14d095m";
|
||||||
|
};
|
||||||
|
paths = map (path: src + path) [
|
||||||
|
"/src"
|
||||||
|
];
|
||||||
|
})
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "tools.reader/org.clojure";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "tools.reader";
|
||||||
|
groupId = "org.clojure";
|
||||||
|
sha512 = "290a2d98b2eec08a8affc2952006f43c0459c7e5467dc454f5fb5670ea7934fa974e6be19f7e7c91dadcfed62082d0fbcc7788455b7446a2c9c5af02f7fc52b6";
|
||||||
|
version = "1.3.2";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "potemkin/potemkin";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "potemkin";
|
||||||
|
groupId = "potemkin";
|
||||||
|
sha512 = "5abc050bf7ff0b27d8c45aaa5e378201980815b711b2db99735db73304576c17e285026ea48a714bf0b0df7ad7a008de38b7d182cdc0e8989f4be1e6b3afa8aa";
|
||||||
|
version = "0.4.5";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "core.memoize/org.clojure";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "core.memoize";
|
||||||
|
groupId = "org.clojure";
|
||||||
|
sha512 = "37308fcbbe64d0a2802917ef5a589075f81086d63e08c71a9a1b648b73dd362e5bdc8f756084fde1f4b1964ba82a6dc06b2119460281b7949a271d82e6a47a7e";
|
||||||
|
version = "1.0.236";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "camel-snake-kebab/camel-snake-kebab";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "camel-snake-kebab";
|
||||||
|
groupId = "camel-snake-kebab";
|
||||||
|
sha512 = "589d34b500560b7113760a16bfb6f0ccd8f162a1ce8c9bc829495432159ba9c95aebf6bc43aa126237a0525806a205a05f9910122074902b659e7fd151d176b1";
|
||||||
|
version = "0.4.2";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "data.priority-map/org.clojure";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "data.priority-map";
|
||||||
|
groupId = "org.clojure";
|
||||||
|
sha512 = "fb2d703468fb6d5f28c38f25e8e7acdaf02d2fa1ac23c14a9ff065873e88c9b74e155e73e5069436d674d7ef8547f01bc9777b7ae3b9dcde67cbd327d4a20c06";
|
||||||
|
version = "1.0.0";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "httpmime/org.apache.httpcomponents";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "httpmime";
|
||||||
|
groupId = "org.apache.httpcomponents";
|
||||||
|
sha512 = "e1b0ee84bce78576074dc1b6836a69d8f5518eade38562e6890e3ddaa72b7f54bf735c8e2286142c58cddf45f745da31261e5d73b7d8092eb6ecfb20946eb36c";
|
||||||
|
version = "4.5.13";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "core.cache/org.clojure";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "core.cache";
|
||||||
|
groupId = "org.clojure";
|
||||||
|
sha512 = "6e4e126f23b20120c50a4dbefbe1b3b9bd98f0a7b8fa83affa267ff7f0de09542d2727243859a1ea346bda5b782d4ae0110f6c2b169c298261707a1fdadaedb0";
|
||||||
|
version = "1.0.207";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
rec {
|
||||||
|
name = "core.async/org.clojure";
|
||||||
|
src = fetchMavenArtifact {
|
||||||
|
inherit repos;
|
||||||
|
artifactId = "core.async";
|
||||||
|
groupId = "org.clojure";
|
||||||
|
sha512 = "11de341de544951f1c944fca67610d024f562a87127bb9a7095aaa8b5ae0e7c4e7ddaebbe2567ade7ff988beda804835d8f5eb6b2b0a0c0d6766e697fe817523";
|
||||||
|
version = "1.5.640";
|
||||||
|
|
||||||
|
};
|
||||||
|
paths = [ src ];
|
||||||
|
}
|
||||||
|
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
description = "Coinbase Pro Client.";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "nixpkgs/nixos-22.05";
|
||||||
|
utils.url = "github:numtide/flake-utils";
|
||||||
|
clj-nix = {
|
||||||
|
url = "github:jlesquembre/clj-nix";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, utils, clj-nix, ... }:
|
||||||
|
utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
pkgs = nixpkgs.legacyPackages."${system}";
|
||||||
|
cljpkgs = clj-nix.packages."${system}";
|
||||||
|
update-deps = pkgs.writeShellScriptBin "update-deps.sh" ''
|
||||||
|
${clj-nix.packages."${system}".deps-lock}/bin/deps-lock
|
||||||
|
'';
|
||||||
|
in {
|
||||||
|
packages = {
|
||||||
|
coinbase-pro-client = cljpkgs.mkCljBin {
|
||||||
|
projectSrc = ./.;
|
||||||
|
name = "org.fudo/coinbase-pro.client";
|
||||||
|
main-ns = "coinbase-pro.client.core";
|
||||||
|
jdkRunner = pkgs.jdk17_headless;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
defaultPackage = self.packages."${system}".coinbase-pro-client;
|
||||||
|
|
||||||
|
devShell =
|
||||||
|
pkgs.mkShell { buildInputs = with pkgs; [ clojure update-deps ]; };
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,293 @@
|
||||||
|
(ns coinbase-pro.client
|
||||||
|
(:require [clojure.set :as set]
|
||||||
|
[clojure.spec.alpha :as s]
|
||||||
|
[clojure.string :as str]
|
||||||
|
|
||||||
|
[exchange.account :as acct]
|
||||||
|
[exchange.client :as client]
|
||||||
|
[exchange.common :as common]
|
||||||
|
[exchange.order :as order]
|
||||||
|
[exchange.ticker :as ticker]
|
||||||
|
|
||||||
|
[coinbase-pro.order :as order-req]
|
||||||
|
|
||||||
|
[fudo-clojure.common :refer [base64-decode base64-encode-string ensure-conform instant-to-epoch-timestamp to-uuid parse-timestamp]]
|
||||||
|
[fudo-clojure.http.client :as http]
|
||||||
|
[fudo-clojure.http.request :as req]
|
||||||
|
[fudo-clojure.logging :as log]
|
||||||
|
[fudo-clojure.result :refer [map-success bind success exception-failure]]))
|
||||||
|
|
||||||
|
(def signature-algo "HmacSHA256")
|
||||||
|
|
||||||
|
(defn- build-path [& path-elems]
|
||||||
|
(str "/" (str/join "/" (map to-path-elem path-elems))))
|
||||||
|
|
||||||
|
(defn- to-path-elem [el]
|
||||||
|
(cond (keyword? el) (name el)
|
||||||
|
(uuid? el) (.toString el)
|
||||||
|
(string? el) el
|
||||||
|
:else (throw (ex-info (str "Bad path element: " el) {}))))
|
||||||
|
|
||||||
|
(defn- make-signature-generator [key]
|
||||||
|
(let [hmac (doto (javax.crypto.Mac/getInstance signature-algo)
|
||||||
|
(.init (javax.crypto.spec.SecretKeySpec. key signature-algo)))]
|
||||||
|
(fn [msg]
|
||||||
|
(-> (.doFinal hmac (.getBytes msg))
|
||||||
|
(base64-encode-string)))))
|
||||||
|
|
||||||
|
(s/def ::secret string?)
|
||||||
|
|
||||||
|
(s/def ::passphrase string?)
|
||||||
|
(s/def ::key string?)
|
||||||
|
|
||||||
|
(s/def ::profile-id uuid?)
|
||||||
|
(s/def ::trade-id uuid?)
|
||||||
|
(s/def ::order-id uuid?)
|
||||||
|
|
||||||
|
(s/def ::credentials
|
||||||
|
(s/keys :req [::authenticator
|
||||||
|
::key
|
||||||
|
::passphrase]))
|
||||||
|
|
||||||
|
(s/def ::hostname string?)
|
||||||
|
|
||||||
|
(s/def ::connection
|
||||||
|
(s/keys :req [::hostname ::http/client]
|
||||||
|
:opt [::log/logger]))
|
||||||
|
|
||||||
|
(s/def ::authenticated-connection
|
||||||
|
(s/and ::connection
|
||||||
|
(s/keys :req [::credentials])))
|
||||||
|
|
||||||
|
(defn- make-request-authenticator
|
||||||
|
[{key ::key secret ::secret passphrase ::passphrase}]
|
||||||
|
(let [sign (make-signature-generator (base64-decode secret))]
|
||||||
|
(fn [req]
|
||||||
|
(let [epoch-timestamp (-> req req/timestamp instant-to-epoch-timestamp str)
|
||||||
|
req-str (str epoch-timestamp
|
||||||
|
(-> req req/method name)
|
||||||
|
(-> req req/request-path)
|
||||||
|
(-> req req/body (or "")))
|
||||||
|
signature (sign req-str)]
|
||||||
|
(req/with-headers req
|
||||||
|
{::cb-access-timestamp epoch-timestamp
|
||||||
|
::cb-access-key key
|
||||||
|
::cb-access-passphrase passphrase
|
||||||
|
::cb-access-sign signature})))))
|
||||||
|
|
||||||
|
(def lower-case-keyword (comp keyword str/lower-case))
|
||||||
|
|
||||||
|
(defn- currency-product [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}))))
|
||||||
|
|
||||||
|
(defn- accounts-request []
|
||||||
|
(-> (req/base-request)
|
||||||
|
(req/as-get)
|
||||||
|
(req/with-path (build-path :accounts))))
|
||||||
|
|
||||||
|
(defn- reify-account [acct]
|
||||||
|
(reify acct/CurrencyAccount
|
||||||
|
(currency [_] (-> acct :currency lower-case-keyword))
|
||||||
|
(balance [_] (-> acct :balance bigdec))
|
||||||
|
(hold [_] (-> acct :hold bigdec))
|
||||||
|
(available [_] (-> acct :available bigdec))))
|
||||||
|
|
||||||
|
(defn- order-request [order-id]
|
||||||
|
(-> (req/base-request)
|
||||||
|
(req/as-get)
|
||||||
|
(req/with-path (build-path :orders order-id))))
|
||||||
|
|
||||||
|
(defn- cancel-order-request [order-id]
|
||||||
|
(-> (req/base-request)
|
||||||
|
(req/as-delete)
|
||||||
|
(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) })))))
|
||||||
|
|
||||||
|
(defn- create-order-request [order]
|
||||||
|
(-> (req/base-request)
|
||||||
|
(req/as-post)
|
||||||
|
(req/with-path (build-path :orders))
|
||||||
|
(req/with-body-params (ensure-conform ::order-req/order order))))
|
||||||
|
(s/fdef create-order-request
|
||||||
|
:args (s/cat :params ::order-req/order)
|
||||||
|
:ret ::req/request)
|
||||||
|
|
||||||
|
(defn- ticker-request [currency]
|
||||||
|
(-> (req/base-request)
|
||||||
|
(req/as-get)
|
||||||
|
(req/with-path (build-path :products
|
||||||
|
(currency-product currency)
|
||||||
|
:ticker))))
|
||||||
|
|
||||||
|
(defn- ensure-keys [ks m]
|
||||||
|
(let [diff (set/difference ks (set (keys m)))]
|
||||||
|
(when (not (empty? diff))
|
||||||
|
(throw (ex-info (str "missing keys: "
|
||||||
|
(str/join "," diff))
|
||||||
|
{:missing-keys diff
|
||||||
|
:map m})))))
|
||||||
|
|
||||||
|
(defn- reify-order [order]
|
||||||
|
(let [required-keys #{:id
|
||||||
|
:product_id
|
||||||
|
:type
|
||||||
|
:side
|
||||||
|
:price
|
||||||
|
:size
|
||||||
|
:settled
|
||||||
|
:created_at}]
|
||||||
|
(do (ensure-keys required-keys order)
|
||||||
|
(reify order/Order
|
||||||
|
(id [_] (-> order :id to-uuid))
|
||||||
|
(currency [_] (-> order :product_id product-currency))
|
||||||
|
(limit? [_] (-> order :type keyword (= :limit)))
|
||||||
|
(market? [_] (-> order :type keyword (= :market)))
|
||||||
|
(stop? [_] (-> order :stop nil? not))
|
||||||
|
(sell? [_] (-> order :side keyword (= :sell)))
|
||||||
|
(buy? [_] (-> order :side keyword (= :buy)))
|
||||||
|
(stop-loss? [_] (-> order :stop keyword (= :loss)))
|
||||||
|
(stop-gain? [_] (-> order :stop keyword (= :entry)))
|
||||||
|
(filled? [_] (-> order :done_reason keyword (= :filled)))
|
||||||
|
(price [_] (-> order :price bigdec))
|
||||||
|
(stop-price [_] (some-> order :stop_price bigdec))
|
||||||
|
(size [_] (-> order :size bigdec))
|
||||||
|
(settled? [_] (-> order :settled))
|
||||||
|
(done? [_] (-> order :status keyword (= :done)))
|
||||||
|
(cancelled? [_] (-> order :done_reason keyword (= :canceled)))
|
||||||
|
(fees [_] (some-> order :fill_fees bigdec))
|
||||||
|
(created [_] (-> order :created_at parse-timestamp))
|
||||||
|
(completed [_] (some-> order :done_at parse-timestamp))
|
||||||
|
(get-raw [_] order)))))
|
||||||
|
|
||||||
|
(defn- reify-ticker [currency ticker]
|
||||||
|
(reify ticker/Ticker
|
||||||
|
(currency [_] currency)
|
||||||
|
(price [_] (-> ticker :price bigdec))
|
||||||
|
(tick-time [_] (-> ticker :time parse-timestamp))
|
||||||
|
(bid [_] (-> ticker :bid bigdec))
|
||||||
|
(ask [_] (-> ticker :ask bigdec))
|
||||||
|
(volume [_] (-> ticker :volume bigdec))))
|
||||||
|
|
||||||
|
(defn- reify-exchange-client [{client ::http/client
|
||||||
|
hostname ::common/hostname
|
||||||
|
logger ::log/logger}]
|
||||||
|
(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))
|
||||||
|
(partial reify-ticker currency)))
|
||||||
|
(get-market-price! [self currency]
|
||||||
|
(map-success (client/get-ticker! self currency)
|
||||||
|
ticker/price)))))
|
||||||
|
|
||||||
|
(defn- reify-exchange-account-client [{:keys [http/client common/hostname] :as opts}]
|
||||||
|
(let [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-orders (comp (partial sort-by order/created before)
|
||||||
|
(partial map reify-order))
|
||||||
|
accounts-map (fn [accts] (into {} (map (juxt acct/currency identity) accts)))]
|
||||||
|
(reify
|
||||||
|
client/ExchangeClient
|
||||||
|
(get-ticker! [_ currency] (client/get-ticker! public-client currency))
|
||||||
|
|
||||||
|
(get-market-price! [_ currency] (client/get-market-price! public-client currency))
|
||||||
|
|
||||||
|
client/ExchangeAccountClient
|
||||||
|
(get-accounts! [_]
|
||||||
|
(map-success (request! (accounts-request))
|
||||||
|
(comp accounts-map (partial map reify-account))))
|
||||||
|
|
||||||
|
(get-account! [this currency]
|
||||||
|
(bind (client/get-accounts! this)
|
||||||
|
(fn [accts]
|
||||||
|
(if-let [acct (get accts currency)]
|
||||||
|
(success acct)
|
||||||
|
(exception-failure (ex-info (str "no account for currency: " currency)
|
||||||
|
{:currency currency
|
||||||
|
:existing-accounts accts}))))))
|
||||||
|
|
||||||
|
(get-order! [_ order-id]
|
||||||
|
(map-success (request! (order-request order-id))
|
||||||
|
reify-order))
|
||||||
|
|
||||||
|
(get-orders! [_ currency]
|
||||||
|
(map-success (request! (currency-orders-request currency))
|
||||||
|
reify-orders))
|
||||||
|
|
||||||
|
(get-incomplete-orders! [_ currency]
|
||||||
|
(map-success (request! (currency-orders-request currency { ::order/status [:open :pending] }))
|
||||||
|
reify-orders))
|
||||||
|
|
||||||
|
(get-completed-orders! [_ currency]
|
||||||
|
(map-success (request! (currency-orders-request currency { ::order/status [:done] }))
|
||||||
|
reify-orders))
|
||||||
|
|
||||||
|
(get-completed-limit-orders! [self currency]
|
||||||
|
(map-success (client/get-completed-orders! self currency)
|
||||||
|
(comp reify-orders (partial filter order/limit?))))
|
||||||
|
|
||||||
|
(get-completed-limit-buy-orders! [self currency]
|
||||||
|
(map-success (client/get-completed-limit-orders! self currency)
|
||||||
|
(comp reify-orders (partial filter order/buy?))))
|
||||||
|
|
||||||
|
(get-completed-limit-sell-orders! [self currency]
|
||||||
|
(map-success (client/get-completed-limit-orders! self currency)
|
||||||
|
(comp reify-orders (partial filter order/sell?))))
|
||||||
|
|
||||||
|
(cancel-order! [_ order-id]
|
||||||
|
(map-success (request! (cancel-order-request order-id))
|
||||||
|
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))
|
||||||
|
(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))
|
||||||
|
(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))
|
||||||
|
(order-req/as-limit)
|
||||||
|
(order-req/as-sell)
|
||||||
|
(order-req/with-price (bigdec sell-price))
|
||||||
|
(order-req/with-size (bigdec size)))))
|
||||||
|
(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))
|
||||||
|
(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
|
||||||
|
([client] ()))
|
||||||
|
|
||||||
|
(defn connect [& args]
|
||||||
|
(reify-client (apply build-connection args)))
|
||||||
|
(s/fdef connect :ret ::client/client)
|
|
@ -0,0 +1,5 @@
|
||||||
|
(ns coinbase-pro.client.core)
|
||||||
|
|
||||||
|
(defn -main [_]
|
||||||
|
(println "Not Implemented!")
|
||||||
|
(System/exit 1))
|
|
@ -0,0 +1,89 @@
|
||||||
|
(ns coinbase-pro.order
|
||||||
|
(:require [clojure.spec.alpha :as s]
|
||||||
|
[fudo-clojure.common :refer [*->]]))
|
||||||
|
|
||||||
|
;; Anything other than USD is an error for now
|
||||||
|
(defn- product-id? [product]
|
||||||
|
(and (string? product)
|
||||||
|
(not (nil? (re-matches #"^[A-Z]{2,5}-USD$" product)))))
|
||||||
|
|
||||||
|
(defn- must-be [k v]
|
||||||
|
(fn [o] (= (k o) v)))
|
||||||
|
|
||||||
|
(defn- ensure-relationship [pred k0 k1]
|
||||||
|
(fn [o] (pred (k0 o) (k1 o))))
|
||||||
|
|
||||||
|
;; Order details are going to be exchange-specific, I'll put them here for now.
|
||||||
|
(s/def ::product-id product-id?)
|
||||||
|
(s/def ::type #{:limit :market})
|
||||||
|
(s/def ::side #{:buy :sell})
|
||||||
|
(s/def ::stop #{:entry :loss})
|
||||||
|
(s/def ::stop-price decimal?)
|
||||||
|
(s/def ::price decimal?)
|
||||||
|
(s/def ::size decimal?)
|
||||||
|
|
||||||
|
(s/def ::base-order
|
||||||
|
(s/keys :req [::product-id
|
||||||
|
::type
|
||||||
|
::side
|
||||||
|
::price
|
||||||
|
::size]))
|
||||||
|
|
||||||
|
(s/def ::buy-order
|
||||||
|
(s/and ::base-order (must-be ::side :buy)))
|
||||||
|
|
||||||
|
(s/def ::sell-order
|
||||||
|
(s/and ::base-order (must-be ::side :sell)))
|
||||||
|
|
||||||
|
(s/def ::limit-buy-order
|
||||||
|
(s/and ::buy-order (must-be ::type :limit)))
|
||||||
|
|
||||||
|
(s/def ::limit-sell-order
|
||||||
|
(s/and ::sell-order (must-be ::type :limit)))
|
||||||
|
|
||||||
|
(s/def ::stop-gain-order
|
||||||
|
(s/and ::limit-buy-order
|
||||||
|
(s/keys :req [::stop ::stop-price])
|
||||||
|
(must-be ::stop :entry)
|
||||||
|
(ensure-relationship < ::stop-price ::price)))
|
||||||
|
|
||||||
|
(s/def ::stop-loss-order
|
||||||
|
(s/and ::limit-sell-order
|
||||||
|
(s/keys :req [::stop ::stop-price])
|
||||||
|
(must-be ::stop :loss)
|
||||||
|
(ensure-relationship > ::stop-price ::price)))
|
||||||
|
|
||||||
|
(s/def ::order
|
||||||
|
(s/or :buy ::buy-order
|
||||||
|
:sell ::sell-order
|
||||||
|
:limit-buy ::limit-buy-order
|
||||||
|
:limit-sell ::limit-sell-order
|
||||||
|
:stop-gain ::stop-gain-order
|
||||||
|
:stop-loss ::stop-loss-order))
|
||||||
|
|
||||||
|
(defn base-order [product]
|
||||||
|
{ ::product-id product })
|
||||||
|
|
||||||
|
(def as-limit (*-> (assoc ::type :limit)))
|
||||||
|
(def as-market (*-> (assoc ::type :market)))
|
||||||
|
(def as-buy (*-> (assoc ::side :buy)))
|
||||||
|
(def as-sell (*-> (assoc ::side :sell)))
|
||||||
|
|
||||||
|
(defn with-price [o price]
|
||||||
|
(assoc o ::price price))
|
||||||
|
(defn with-size [o size]
|
||||||
|
(assoc o ::size size))
|
||||||
|
|
||||||
|
(defn as-stop-loss [o stop-price]
|
||||||
|
(-> o
|
||||||
|
(as-limit)
|
||||||
|
(as-sell)
|
||||||
|
(assoc ::stop-price stop-price)
|
||||||
|
(assoc ::stop :loss)))
|
||||||
|
|
||||||
|
(defn as-stop-gain [o stop-price]
|
||||||
|
(-> o
|
||||||
|
(as-limit)
|
||||||
|
(as-buy)
|
||||||
|
(assoc ::stop-price stop-price)
|
||||||
|
(assoc ::stop :entry)))
|
|
@ -0,0 +1,39 @@
|
||||||
|
(ns exchange.account
|
||||||
|
(:require [clojure.spec.alpha :as s]
|
||||||
|
[exchange.common :as common]))
|
||||||
|
|
||||||
|
(s/def ::balance decimal?)
|
||||||
|
(s/def ::hold decimal?)
|
||||||
|
(s/def ::available decimal?)
|
||||||
|
|
||||||
|
(defprotocol CurrencyAccount
|
||||||
|
(currency [self])
|
||||||
|
(balance [self])
|
||||||
|
(hold [self])
|
||||||
|
(available [self]))
|
||||||
|
|
||||||
|
(def account? (partial satisfies? CurrencyAccount))
|
||||||
|
|
||||||
|
(defn currency-account? [curr acct]
|
||||||
|
(= curr (currency acct)))
|
||||||
|
|
||||||
|
(defn account-balance [accts curr]
|
||||||
|
(balance (get accts curr)))
|
||||||
|
|
||||||
|
(s/def ::acct account?)
|
||||||
|
|
||||||
|
(s/fdef currency
|
||||||
|
:args (s/cat :acct ::acct)
|
||||||
|
:ret ::common/currency)
|
||||||
|
|
||||||
|
(s/fdef balance
|
||||||
|
:args (s/cat :acct ::acct)
|
||||||
|
:ret decimal?)
|
||||||
|
|
||||||
|
(s/fdef hold
|
||||||
|
:args (s/cat :acct ::acct)
|
||||||
|
:ret decimal?)
|
||||||
|
|
||||||
|
(s/fdef available
|
||||||
|
:args (s/cat :acct ::acct)
|
||||||
|
:ret decimal?)
|
|
@ -0,0 +1,28 @@
|
||||||
|
(ns exchange.client
|
||||||
|
(:require [clojure.spec.alpha :as s]))
|
||||||
|
|
||||||
|
(defprotocol ExchangeClient
|
||||||
|
(get-ticker! [client currency])
|
||||||
|
(get-market-price! [client currency]))
|
||||||
|
|
||||||
|
(defprotocol ExchangeAccountClient
|
||||||
|
(get-order! [client order-id])
|
||||||
|
(get-orders! [client currency])
|
||||||
|
(get-incomplete-orders! [client currency])
|
||||||
|
(get-completed-orders! [client currency])
|
||||||
|
(get-completed-limit-orders! [client currency])
|
||||||
|
(get-completed-limit-buy-orders! [client currency])
|
||||||
|
(get-completed-limit-sell-orders! [client currency])
|
||||||
|
(cancel-order! [client order-id])
|
||||||
|
(get-accounts! [client])
|
||||||
|
(get-account! [client currency])
|
||||||
|
(create-stop-loss-order! [client currency stop-price sell-price size])
|
||||||
|
(create-stop-gain-order! [client currency stop-price buy-price size])
|
||||||
|
(create-limit-sell-order! [client currency sell-price size])
|
||||||
|
(create-limit-buy-order! [client currency buy-price size]))
|
||||||
|
|
||||||
|
(def client? (partial satisfies? ExchangeClient))
|
||||||
|
(def account-client? (partial satisfies? ExchangeAccountClient))
|
||||||
|
|
||||||
|
(s/def ::client client?)
|
||||||
|
(s/def ::account-client account-client?)
|
|
@ -0,0 +1,8 @@
|
||||||
|
(ns exchange.common
|
||||||
|
(:require [clojure.spec.alpha :as s]))
|
||||||
|
|
||||||
|
(s/def ::amount decimal?)
|
||||||
|
(s/def ::balance decimal?)
|
||||||
|
(s/def ::currency keyword?)
|
||||||
|
(s/def ::timestamp (partial instance? java.time.Instant))
|
||||||
|
(s/def ::hostname string?)
|
|
@ -0,0 +1,57 @@
|
||||||
|
(ns exchange.order
|
||||||
|
(:refer-clojure :exclude [type])
|
||||||
|
(:require [clojure.spec.alpha :as s]
|
||||||
|
[exchange.common :as common]))
|
||||||
|
|
||||||
|
(defprotocol Order
|
||||||
|
(id [order])
|
||||||
|
(currency [order])
|
||||||
|
(limit? [order])
|
||||||
|
(market? [order])
|
||||||
|
(stop? [order])
|
||||||
|
(sell? [order])
|
||||||
|
(buy? [order])
|
||||||
|
(stop-loss? [order])
|
||||||
|
(stop-gain? [order])
|
||||||
|
(filled? [order])
|
||||||
|
(price [order])
|
||||||
|
(stop-price [order])
|
||||||
|
(size [order])
|
||||||
|
(settled? [order])
|
||||||
|
(fees [order])
|
||||||
|
(created [order])
|
||||||
|
(completed [order])
|
||||||
|
(done? [order])
|
||||||
|
(cancelled? [order])
|
||||||
|
(get-raw [order]))
|
||||||
|
|
||||||
|
(def order? (partial satisfies? Order))
|
||||||
|
|
||||||
|
(s/def ::order order?)
|
||||||
|
|
||||||
|
(s/def ::order-id uuid?)
|
||||||
|
|
||||||
|
(defn- fn-order-to [type]
|
||||||
|
(s/fspec :args (s/cat :order ::order)
|
||||||
|
:ret type))
|
||||||
|
|
||||||
|
(s/def id (fn-order-to ::order-id))
|
||||||
|
(s/def currency (fn-order-to ::common/currency))
|
||||||
|
(s/def limit? (fn-order-to boolean?))
|
||||||
|
(s/def market? (fn-order-to boolean?))
|
||||||
|
(s/def stop? (fn-order-to boolean?))
|
||||||
|
(s/def sell? (fn-order-to boolean?))
|
||||||
|
(s/def buy? (fn-order-to boolean?))
|
||||||
|
(s/def stop-loss? (fn-order-to boolean?))
|
||||||
|
(s/def stop-gain? (fn-order-to boolean?))
|
||||||
|
(s/def filled? (fn-order-to boolean?))
|
||||||
|
(s/def price (fn-order-to ::common/amount))
|
||||||
|
(s/def stop-price (fn-order-to (s/nilable ::common/amount)))
|
||||||
|
(s/def size (fn-order-to ::common/amount))
|
||||||
|
(s/def cancelled? (fn-order-to boolean?))
|
||||||
|
(s/def settled? (fn-order-to boolean?))
|
||||||
|
(s/def fees (fn-order-to ::common/amount))
|
||||||
|
(s/def created (fn-order-to ::common/timestamp))
|
||||||
|
(s/def completed (fn-order-to ::common/timestamp))
|
||||||
|
(s/def done? (fn-order-to boolean?))
|
||||||
|
(s/def cancelled? (fn-order-to boolean?))
|
|
@ -0,0 +1,9 @@
|
||||||
|
(ns exchange.ticker)
|
||||||
|
|
||||||
|
(defprotocol Ticker
|
||||||
|
(currency [self])
|
||||||
|
(price [self])
|
||||||
|
(tick-time [self])
|
||||||
|
(bid [self])
|
||||||
|
(ask [self])
|
||||||
|
(volume [self]))
|
Loading…
Reference in New Issue