├── julia ├── README.md └── Bitwyre │ └── Project.toml ├── rust ├── .gitignore ├── src │ ├── lib.rs │ └── public │ │ └── config.rs ├── .cargo │ └── config.toml ├── README.md ├── Cargo.toml └── tests │ └── private.rs ├── cpp ├── doc │ ├── .gitignore │ ├── design.md │ ├── doxygen │ │ ├── footer.html │ │ ├── header.html │ │ └── Doxyfile.in │ ├── directoryStructure.md │ ├── CMakeLists.txt │ └── start_working.md ├── source │ ├── version.cpp.in │ ├── unittest │ │ ├── testmain.cpp │ │ ├── utils.test.cpp.hpp │ │ ├── CMakeLists.txt │ │ ├── MockAsyncDispatcher.hpp │ │ └── MockDispatcher.hpp │ ├── rest │ │ ├── public │ │ │ ├── Announcements.hpp │ │ │ ├── Market.hpp │ │ │ ├── Product.hpp │ │ │ ├── Time.hpp │ │ │ ├── OrderTypes.hpp │ │ │ ├── SupportedLanguages.hpp │ │ │ ├── Asset.hpp │ │ │ ├── FiatAsset.hpp │ │ │ ├── CryptoAsset.hpp │ │ │ ├── Instrument.hpp │ │ │ ├── Depth.hpp │ │ │ ├── Trades.hpp │ │ │ ├── Contract.hpp │ │ │ └── Ticker.hpp │ │ └── private │ │ │ ├── AccountBalance.hpp │ │ │ ├── TradesHistory.hpp │ │ │ ├── NewOrder.hpp │ │ │ ├── TransactionHistory.hpp │ │ │ ├── CancelOrder.hpp │ │ │ ├── OrderInfo.hpp │ │ │ ├── AccountStatement.hpp │ │ │ ├── OpenOrders.hpp │ │ │ └── ClosedOrders.hpp │ ├── details │ │ ├── Response.hpp │ │ ├── Config.hpp │ │ ├── ConstexprMap.hpp │ │ └── Utils.hpp │ ├── version.h │ └── CMakeLists.txt ├── .gitignore ├── data │ └── CMakeLists.txt ├── cmake │ ├── bitwyresdk.pc.in │ ├── useGoldLinker.cmake │ ├── sanitizers.cmake │ └── cleanCppExtensions.cmake ├── .clang-format ├── license.md ├── .clang-tidy ├── test │ └── CMakeLists.txt ├── conanfile.py ├── cleanCppProject.sublime-project ├── CMakeLists.txt └── README.md ├── java ├── .gitignore ├── README.md ├── src │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── bitwyre │ │ │ └── sdk │ │ │ └── AppTest.java │ └── main │ │ └── java │ │ └── com │ │ └── bitwyre │ │ └── sdk │ │ ├── App.java │ │ └── config.java ├── .project ├── .classpath └── pom.xml ├── swift └── README.md ├── kotlin ├── README.md ├── gradle.properties ├── settings.gradle.kts ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── build.gradle.kts ├── src │ └── main │ │ └── kotlin │ │ ├── test.kt │ │ └── com │ │ └── bitwyre │ │ └── kotlin_sdk │ │ └── Config.kt └── gradlew.bat ├── objc └── README.md ├── scala ├── project │ ├── build.properties │ ├── target │ │ ├── streams │ │ │ ├── _global │ │ │ │ ├── ivySbt │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ └── out │ │ │ │ ├── _global │ │ │ │ │ ├── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ │ └── out │ │ │ │ │ └── csrLogger │ │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ └── out │ │ │ │ ├── csrProject │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ └── out │ │ │ │ ├── csrConfiguration │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ └── out │ │ │ │ ├── ivyConfiguration │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ └── out │ │ │ │ ├── moduleSettings │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ └── out │ │ │ │ ├── projectDescriptors │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ └── out │ │ │ │ ├── scalaCompilerBridgeScope │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ └── out │ │ │ │ ├── dependencyPositions │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ └── update_cache_2.12 │ │ │ │ │ │ ├── input_dsp │ │ │ │ │ │ └── output_dsp │ │ │ │ └── update │ │ │ │ │ └── _global │ │ │ │ │ └── streams │ │ │ │ │ └── out │ │ │ ├── compile │ │ │ │ ├── bspReporter │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ └── out │ │ │ │ ├── compile │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ └── out │ │ │ │ ├── scalacOptions │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ └── out │ │ │ │ ├── compileIncremental │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ ├── export │ │ │ │ │ │ └── out │ │ │ │ ├── unmanagedClasspath │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ ├── out │ │ │ │ │ │ └── export │ │ │ │ ├── unmanagedJars │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ └── export │ │ │ │ ├── _global │ │ │ │ │ └── _global │ │ │ │ │ │ ├── discoveredMainClasses │ │ │ │ │ │ └── data │ │ │ │ │ │ └── compileOutputs │ │ │ │ │ │ └── previous │ │ │ │ ├── internalDependencyClasspath │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ ├── out │ │ │ │ │ │ └── export │ │ │ │ ├── copyResources │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ ├── copy-resources │ │ │ │ │ │ └── out │ │ │ │ ├── exportedProducts │ │ │ │ │ └── _global │ │ │ │ │ │ └── streams │ │ │ │ │ │ └── export │ │ │ │ └── incOptions │ │ │ │ │ └── _global │ │ │ │ │ └── streams │ │ │ │ │ └── out │ │ │ └── runtime │ │ │ │ ├── unmanagedClasspath │ │ │ │ └── _global │ │ │ │ │ └── streams │ │ │ │ │ ├── out │ │ │ │ │ └── export │ │ │ │ ├── unmanagedJars │ │ │ │ └── _global │ │ │ │ │ └── streams │ │ │ │ │ └── export │ │ │ │ ├── internalDependencyClasspath │ │ │ │ └── _global │ │ │ │ │ └── streams │ │ │ │ │ ├── out │ │ │ │ │ └── export │ │ │ │ └── exportedProducts │ │ │ │ └── _global │ │ │ │ └── streams │ │ │ │ └── export │ │ ├── config-classes │ │ │ ├── $2efa8683f29609a5ace9.cache │ │ │ ├── $2efa8683f29609a5ace9.class │ │ │ └── $2efa8683f29609a5ace9$.class │ │ └── scala-2.12 │ │ │ └── sbt-1.0 │ │ │ └── update │ │ │ └── update_cache_2.12 │ │ │ └── inputs │ └── project │ │ └── target │ │ └── config-classes │ │ ├── $ad6c7f301aa480b814ab.cache │ │ ├── $ad6c7f301aa480b814ab$.class │ │ └── $ad6c7f301aa480b814ab.class ├── src │ ├── test │ │ └── scala │ │ │ └── Test1.scala │ └── main │ │ └── scala │ │ ├── Demo.scala │ │ └── com │ │ └── bitwyre │ │ └── scala_sdk │ │ └── Config.scala ├── README.md └── build.sbt ├── python ├── requirements.txt ├── requirements-dev.txt ├── Manifest.in ├── pyproject.toml ├── README.md ├── setup.cfg ├── bitwyre_sdk │ ├── config.py │ └── utils.py └── setup.py ├── js ├── packages │ ├── private │ │ ├── .env.example │ │ ├── babel.config.js │ │ ├── tslint.json │ │ ├── .prettierrc │ │ ├── test │ │ │ ├── jest.json │ │ │ └── index.spec.ts │ │ ├── tsconfig.json │ │ ├── src │ │ │ ├── types.ts │ │ │ └── authentication.ts │ │ ├── examples │ │ │ └── main.ts │ │ └── package.json │ └── public │ │ ├── .env.example │ │ ├── babel.config.js │ │ ├── tslint.json │ │ ├── .prettierrc │ │ ├── examples │ │ └── main.ts │ │ ├── test │ │ ├── jest.json │ │ └── index.spec.ts │ │ ├── tsconfig.json │ │ ├── package.json │ │ └── src │ │ └── index.ts ├── README.md ├── lerna.json ├── .gitignore └── package.json ├── websocket_python ├── requirements.txt ├── Manifest.in ├── requirements-dev.txt ├── pyproject.toml ├── README.md ├── setup.cfg ├── setup.py └── websocket_python_sdk │ ├── utils.py │ ├── public.py │ └── private.py ├── .gitignore ├── LICENSE └── README.md /julia/README.md: -------------------------------------------------------------------------------- 1 | # Julia -------------------------------------------------------------------------------- /rust/.gitignore: -------------------------------------------------------------------------------- 1 | target/ -------------------------------------------------------------------------------- /cpp/doc/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | -------------------------------------------------------------------------------- /cpp/source/version.cpp.in: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /java/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /java/README.md: -------------------------------------------------------------------------------- 1 | # Java 2 | -------------------------------------------------------------------------------- /swift/README.md: -------------------------------------------------------------------------------- 1 | # Swift 2 | -------------------------------------------------------------------------------- /kotlin/README.md: -------------------------------------------------------------------------------- 1 | # Kotlin 2 | -------------------------------------------------------------------------------- /objc/README.md: -------------------------------------------------------------------------------- 1 | # Objective-C 2 | -------------------------------------------------------------------------------- /cpp/doc/design.md: -------------------------------------------------------------------------------- 1 | # Design Document -------------------------------------------------------------------------------- /rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod public; 2 | pub mod private; -------------------------------------------------------------------------------- /scala/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.5.5 2 | -------------------------------------------------------------------------------- /kotlin/gradle.properties: -------------------------------------------------------------------------------- 1 | kotlin.code.style=official 2 | -------------------------------------------------------------------------------- /scala/project/target/streams/_global/ivySbt/_global/streams/out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scala/project/target/streams/_global/_global/_global/streams/out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scala/project/target/streams/_global/csrProject/_global/streams/out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scala/project/target/streams/compile/bspReporter/_global/streams/out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scala/project/target/streams/compile/compile/_global/streams/out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kotlin/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | 2 | rootProject.name = "KotlinSDK" 3 | 4 | -------------------------------------------------------------------------------- /python/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | hmac 3 | hashlib 4 | logging 5 | -------------------------------------------------------------------------------- /scala/project/target/config-classes/$2efa8683f29609a5ace9.cache: -------------------------------------------------------------------------------- 1 | root 2 | -------------------------------------------------------------------------------- /scala/project/target/streams/_global/csrConfiguration/_global/streams/out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scala/project/target/streams/_global/ivyConfiguration/_global/streams/out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scala/project/target/streams/_global/moduleSettings/_global/streams/out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scala/project/target/streams/compile/scalacOptions/_global/streams/out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scala/project/target/streams/_global/_global/csrLogger/_global/streams/out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scala/project/target/streams/_global/projectDescriptors/_global/streams/out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scala/project/target/streams/compile/compileIncremental/_global/streams/export: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scala/project/target/streams/compile/unmanagedClasspath/_global/streams/out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scala/project/target/streams/compile/unmanagedJars/_global/streams/export: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /scala/project/target/streams/runtime/unmanagedClasspath/_global/streams/out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scala/project/target/streams/runtime/unmanagedJars/_global/streams/export: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /scala/project/target/scala-2.12/sbt-1.0/update/update_cache_2.12/inputs: -------------------------------------------------------------------------------- 1 | 1547390021 -------------------------------------------------------------------------------- /scala/project/target/streams/_global/scalaCompilerBridgeScope/_global/streams/out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scala/project/target/streams/compile/_global/_global/discoveredMainClasses/data: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /scala/project/target/streams/compile/unmanagedClasspath/_global/streams/export: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /scala/project/target/streams/runtime/unmanagedClasspath/_global/streams/export: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /scala/project/target/streams/compile/internalDependencyClasspath/_global/streams/out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scala/project/target/streams/runtime/internalDependencyClasspath/_global/streams/out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /js/packages/private/.env.example: -------------------------------------------------------------------------------- 1 | BASE_URL=https://api.bitwyre.com 2 | API_KEY= 3 | SECRET_KEY= -------------------------------------------------------------------------------- /js/packages/public/.env.example: -------------------------------------------------------------------------------- 1 | BASE_URL=https://api.bitwyre.com 2 | API_KEY= 3 | SECRET_KEY= -------------------------------------------------------------------------------- /scala/project/project/target/config-classes/$ad6c7f301aa480b814ab.cache: -------------------------------------------------------------------------------- 1 | sbt.internal.DslEntry -------------------------------------------------------------------------------- /scala/project/target/streams/compile/copyResources/_global/streams/copy-resources: -------------------------------------------------------------------------------- 1 | [[{},{}],{}] -------------------------------------------------------------------------------- /scala/project/target/streams/compile/internalDependencyClasspath/_global/streams/export: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /js/packages/private/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['@babel/preset-env'] 3 | } -------------------------------------------------------------------------------- /js/packages/public/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['@babel/preset-env'] 3 | } -------------------------------------------------------------------------------- /js/packages/public/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["tslint:recommended", "tslint-config-prettier"] 3 | } -------------------------------------------------------------------------------- /js/README.md: -------------------------------------------------------------------------------- 1 | # Javascript 2 | 3 | # Copyright 4 | 5 | 2021, Bitwyre Technologies Holdings Incorporated 6 | -------------------------------------------------------------------------------- /js/packages/private/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["tslint:recommended", "tslint-config-prettier"] 3 | } -------------------------------------------------------------------------------- /python/requirements-dev.txt: -------------------------------------------------------------------------------- 1 | coverage 2 | mypy 3 | pre-commit 4 | pycodestyle 5 | pytest 6 | pytest-mock 7 | -------------------------------------------------------------------------------- /scala/project/target/streams/_global/dependencyPositions/_global/streams/update_cache_2.12/input_dsp: -------------------------------------------------------------------------------- 1 | -1193090271 -------------------------------------------------------------------------------- /js/packages/public/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "trailingComma": "all", 4 | "singleQuote": true 5 | } -------------------------------------------------------------------------------- /python/Manifest.in: -------------------------------------------------------------------------------- 1 | # Include the README 2 | include *.md 3 | 4 | # Include the license file 5 | include LICENSE 6 | -------------------------------------------------------------------------------- /websocket_python/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | json 3 | hmac 4 | hashlib 5 | logging 6 | websocket-client 7 | logging -------------------------------------------------------------------------------- /js/packages/private/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "trailingComma": "all", 4 | "singleQuote": true 5 | } -------------------------------------------------------------------------------- /rust/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [env] 2 | SECRET_KEY = "SECRET_KEY" 3 | API_KEY = "API_KEY" 4 | API_URL = "https://api.bitwyre.net" -------------------------------------------------------------------------------- /kotlin/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwyre/sdk/HEAD/kotlin/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /websocket_python/Manifest.in: -------------------------------------------------------------------------------- 1 | # Include the README 2 | include *.md 3 | 4 | # Include the license file 5 | include LICENSE 6 | -------------------------------------------------------------------------------- /rust/README.md: -------------------------------------------------------------------------------- 1 | # Rust 2 | 3 | To test run the project, go to this directory and type 4 | 5 | ```shell 6 | cargo run 7 | ``` 8 | -------------------------------------------------------------------------------- /js/lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "packages/*" 4 | ], 5 | "npmClient": "yarn", 6 | "useWorkspaces": true, 7 | "version": "1.0.0" 8 | } -------------------------------------------------------------------------------- /websocket_python/requirements-dev.txt: -------------------------------------------------------------------------------- 1 | coverage 2 | mypy 3 | pre-commit 4 | pycodestyle 5 | pytest 6 | pytest-mock 7 | websocket-client 8 | json 9 | logging -------------------------------------------------------------------------------- /scala/project/target/streams/compile/exportedProducts/_global/streams/export: -------------------------------------------------------------------------------- 1 | /Users/thomsoe/Documents/mysdkproject/project/target/scala-2.12/sbt-1.0/classes 2 | -------------------------------------------------------------------------------- /scala/project/target/streams/runtime/exportedProducts/_global/streams/export: -------------------------------------------------------------------------------- 1 | /Users/thomsoe/Documents/mysdkproject/project/target/scala-2.12/sbt-1.0/classes 2 | -------------------------------------------------------------------------------- /julia/Bitwyre/Project.toml: -------------------------------------------------------------------------------- 1 | name = "Bitwyre" 2 | uuid = "b899f29a-51cb-47de-bd4a-0a13f814388d" 3 | authors = ["Bitwyre "] 4 | version = "0.1.0" 5 | -------------------------------------------------------------------------------- /scala/project/target/config-classes/$2efa8683f29609a5ace9.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwyre/sdk/HEAD/scala/project/target/config-classes/$2efa8683f29609a5ace9.class -------------------------------------------------------------------------------- /scala/project/target/streams/runtime/internalDependencyClasspath/_global/streams/export: -------------------------------------------------------------------------------- 1 | /Users/thomsoe/Documents/mysdkproject/project/target/scala-2.12/sbt-1.0/classes 2 | -------------------------------------------------------------------------------- /scala/project/target/config-classes/$2efa8683f29609a5ace9$.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwyre/sdk/HEAD/scala/project/target/config-classes/$2efa8683f29609a5ace9$.class -------------------------------------------------------------------------------- /scala/project/target/streams/compile/copyResources/_global/streams/out: -------------------------------------------------------------------------------- 1 | [debug] Copy resource mappings:  2 | [debug]   3 | -------------------------------------------------------------------------------- /scala/project/project/target/config-classes/$ad6c7f301aa480b814ab$.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwyre/sdk/HEAD/scala/project/project/target/config-classes/$ad6c7f301aa480b814ab$.class -------------------------------------------------------------------------------- /scala/project/project/target/config-classes/$ad6c7f301aa480b814ab.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwyre/sdk/HEAD/scala/project/project/target/config-classes/$ad6c7f301aa480b814ab.class -------------------------------------------------------------------------------- /cpp/source/unittest/testmain.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do 2 | // this in one cpp file 3 | #include "catch2/catch.hpp" 4 | -------------------------------------------------------------------------------- /scala/src/test/scala/Test1.scala: -------------------------------------------------------------------------------- 1 | import org.junit.Test 2 | import org.junit.Assert.* 3 | 4 | class Test1: 5 | @Test def t1(): Unit = 6 | assertEquals("I was compiled by Scala 3. :)", msg) 7 | -------------------------------------------------------------------------------- /cpp/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | build*/ 3 | external/* 4 | !external/CMakeLists.txt 5 | *.sublime-workspace 6 | .tags 7 | tags 8 | *.pyc 9 | *.swp 10 | *.swo 11 | *.idea 12 | cmake-build-debug 13 | cmake-build-release -------------------------------------------------------------------------------- /cpp/data/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # copy all from data to install dir /share 2 | # here can be images, models 3 | 4 | # install(DIRECTORY ${PROJECT_SOURCE_DIR}/data/images 5 | # DESTINATION ./share/images 6 | # ) 7 | 8 | -------------------------------------------------------------------------------- /scala/project/target/streams/compile/_global/_global/compileOutputs/previous: -------------------------------------------------------------------------------- 1 | ["sbt.Task[scala.collection.Seq[java.nio.file.Path]]",["/Users/thomsoe/Documents/mysdkproject/project/target/scala-2.12/sbt-1.0/zinc/inc_compile_2.12.zip"]] -------------------------------------------------------------------------------- /kotlin/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /python/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | line-length = 120 3 | include = '\.pyi?$' 4 | exclude = ''' 5 | /( 6 | \.git 7 | | \.hg 8 | | \.mypy_cache 9 | | \.tox 10 | | \.venv 11 | | _build 12 | | buck-out 13 | | build 14 | | dist 15 | )/ 16 | ''' 17 | -------------------------------------------------------------------------------- /websocket_python/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | line-length = 120 3 | include = '\.pyi?$' 4 | exclude = ''' 5 | /( 6 | \.git 7 | | \.hg 8 | | \.mypy_cache 9 | | \.tox 10 | | \.venv 11 | | _build 12 | | buck-out 13 | | build 14 | | dist 15 | )/ 16 | ''' 17 | -------------------------------------------------------------------------------- /js/packages/public/examples/main.ts: -------------------------------------------------------------------------------- 1 | import { getServerTime } from '../src'; 2 | 3 | async function main() { 4 | const res = await getServerTime(`https://api.bitwyre.com`); 5 | return res.data; 6 | } 7 | 8 | main() 9 | .then(console.log) 10 | .catch((e) => console.log(e.response.data)); 11 | -------------------------------------------------------------------------------- /js/packages/private/test/jest.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | }, 9 | "collectCoverageFrom": ["**/*.(t|j)s"], 10 | "coverageDirectory": "../coverage" 11 | } -------------------------------------------------------------------------------- /js/packages/public/test/jest.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | }, 9 | "collectCoverageFrom": ["**/*.(t|j)s"], 10 | "coverageDirectory": "../coverage" 11 | } -------------------------------------------------------------------------------- /scala/README.md: -------------------------------------------------------------------------------- 1 | ## sbt project compiled with Scala 3 2 | 3 | ### Usage 4 | 5 | This is a normal sbt project. You can compile code with `sbt compile`, run it with `sbt run`, and `sbt console` will start a Scala 3 REPL. 6 | 7 | For more information on the sbt-dotty plugin, see the 8 | [scala3-example-project](https://github.com/scala/scala3-example-project/blob/main/README.md). 9 | -------------------------------------------------------------------------------- /js/packages/public/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "target": "es6", 5 | "module": "commonjs", 6 | "declaration": true, 7 | "outDir": "./lib", 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true, 10 | "strict": false 11 | }, 12 | "include": ["src"], 13 | "exclude": ["node_modules", "**/__tests__/*"] 14 | } -------------------------------------------------------------------------------- /js/packages/private/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "target": "es6", 5 | "module": "commonjs", 6 | "declaration": true, 7 | "outDir": "./lib", 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true, 10 | "strict": false 11 | }, 12 | "include": ["src", "authentication.ts"], 13 | "exclude": ["node_modules", "**/__tests__/*"] 14 | } -------------------------------------------------------------------------------- /cpp/cmake/bitwyresdk.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=${prefix} 3 | includedir=${prefix}/include 4 | libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ 5 | 6 | Name: lib@PROJECT_NAME@ 7 | Description: Official C++ SDK for accessing Bitwyre APIs. 8 | URL: https://github.com/bitwyre/sdk 9 | CFlags: -I${includedir} @PKG_CONFIG_DEFINES@ 10 | Libs: -L${libdir} -lbitwyresdk -pthread 11 | Requires: @PKG_CONFIG_REQUIRES@ -------------------------------------------------------------------------------- /java/src/test/java/com/bitwyre/sdk/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.bitwyre.sdk; 2 | 3 | import static org.junit.Assert.assertTrue; 4 | 5 | import org.junit.Test; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | { 12 | /** 13 | * Rigorous Test :-) 14 | */ 15 | @Test 16 | public void shouldAnswerWithTrue() 17 | { 18 | assertTrue( true ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /js/packages/private/src/types.ts: -------------------------------------------------------------------------------- 1 | export interface SignData { 2 | nonce: number; 3 | checksum: string; 4 | signature: string; 5 | } 6 | 7 | export type Instruments = 8 | | 'btc_usdt_spot' 9 | | 'eth_usdt_spot' 10 | | 'usdt_idr_spot' 11 | | 'usdc_idr_spot' 12 | | 'usdc_usd_spot' 13 | | 'usdt_usd_spot' 14 | | 'btcusdtx_usdt_200607F1000000'; 15 | 16 | export const currentDateNs = +new Date() * 1000; 17 | -------------------------------------------------------------------------------- /scala/project/target/streams/compile/incOptions/_global/streams/out: -------------------------------------------------------------------------------- 1 | [debug] Created transactional ClassFileManager with tempDir = /Users/thomsoe/Documents/mysdkproject/project/target/scala-2.12/sbt-1.0/classes.bak 2 | [debug] Removing the temporary directory used for backing up class files: /Users/thomsoe/Documents/mysdkproject/project/target/scala-2.12/sbt-1.0/classes.bak 3 | -------------------------------------------------------------------------------- /scala/project/target/streams/_global/update/_global/streams/out: -------------------------------------------------------------------------------- 1 | [debug] not up to date. inChanged = true, force = false 2 | [debug] Updating ProjectRef(uri("file:/Users/thomsoe/Documents/mysdkproject/project/"), "mysdkproject-build")... 3 | [debug] Done updating ProjectRef(uri("file:/Users/thomsoe/Documents/mysdkproject/project/"), "mysdkproject-build") 4 | -------------------------------------------------------------------------------- /scala/build.sbt: -------------------------------------------------------------------------------- 1 | val scala3Version = "3.1.0" 2 | 3 | lazy val root = project 4 | .in(file(".")) 5 | .settings( 6 | name := "MySDKProject", 7 | version := "0.1.0-SNAPSHOT", 8 | scalaVersion := scala3Version, 9 | 10 | libraryDependencies ++= Seq( 11 | "com.novocode" % "junit-interface" % "0.11" % "test", 12 | "com.softwaremill.sttp.client3" %% "core" % "3.3.16" 13 | ) 14 | ) 15 | -------------------------------------------------------------------------------- /kotlin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 2 | 3 | plugins { 4 | kotlin("jvm") version "1.5.10" 5 | } 6 | 7 | group = "me.thomsoe" 8 | version = "1.0-SNAPSHOT" 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | testImplementation(kotlin("test")) 16 | } 17 | 18 | tasks.test { 19 | useJUnit() 20 | } 21 | 22 | tasks.withType() { 23 | kotlinOptions.jvmTarget = "1.8" 24 | } -------------------------------------------------------------------------------- /js/packages/private/examples/main.ts: -------------------------------------------------------------------------------- 1 | import { getAccountBalance } from '../src'; 2 | import * as dotenv from 'dotenv'; 3 | 4 | dotenv.config({ path: `${__dirname}/../.env` }); 5 | 6 | async function main() { 7 | const res = await getAccountBalance( 8 | process.env.BASE_URL ?? '', 9 | process.env.API_KEY ?? '', 10 | process.env.SECRET_KEY ?? '', 11 | ); 12 | return res.data; 13 | } 14 | 15 | main() 16 | .then(console.log) 17 | .catch((e) => console.log(e.response.data)); 18 | -------------------------------------------------------------------------------- /python/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Logo 4 | 5 |

6 | 7 | # Bitwyre - API Connectors 8 | 9 | This is the API Connectors for Bitwyre REST and WS endpoints. 10 | 11 | # Authors 12 | 13 | [Bitwyre](https://github.com/bitwyre) 14 | 15 | ## Contributors 16 | 17 | [Bitwyre](https://github.com/bitwyre) 18 | 19 | # Copyright 20 | 21 | © 2020 Bitwyre Technologies LLC 22 | -------------------------------------------------------------------------------- /scala/project/target/streams/_global/dependencyPositions/_global/streams/update_cache_2.12/output_dsp: -------------------------------------------------------------------------------- 1 | {"{\"organization\":\"org.scala-lang\",\"name\":\"scala-library\",\"revision\":\"2.12.14\",\"configurations\":\"provided\",\"isChanging\":false,\"isTransitive\":true,\"isForce\":false,\"explicitArtifacts\":[],\"inclusions\":[],\"exclusions\":[],\"extraAttributes\":{},\"crossVersion\":{\"type\":\"Disabled\"}}":{"value":{"$fields":["path","startLine"],"path":"(sbt.Classpaths.jvmBaseSettings) Defaults.scala","startLine":3242},"type":"LinePosition"}} -------------------------------------------------------------------------------- /websocket_python/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Logo 4 | 5 |

6 | 7 | # Bitwyre - API Connectors 8 | 9 | This is the API Connectors for Bitwyre REST and WS endpoints. 10 | 11 | # Authors 12 | 13 | [Bitwyre](https://github.com/bitwyre) 14 | 15 | ## Contributors 16 | 17 | [Bitwyre](https://github.com/bitwyre) 18 | 19 | # Copyright 20 | 21 | © 2020 Bitwyre Technologies LLC 22 | -------------------------------------------------------------------------------- /js/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | *.log 4 | .vscode/** 5 | !.vscode/extensions.json 6 | .idea 7 | coverage 8 | .DS_Store 9 | *.tsbuildinfo 10 | .cache 11 | fiddle/build/ 12 | packages/core/mitosis-build 13 | .history 14 | .pnp.* 15 | .yarn 16 | **/.yarn/* 17 | !**/.yarn/patches 18 | !**/.yarn/plugins 19 | !**/.yarn/releases 20 | !**/.yarn/sdks 21 | !**/.yarn/versions 22 | 23 | examples/**/output 24 | e2e/**/output 25 | packages/e2e-*/** 26 | **/test-results/ 27 | **/playwright-report/ 28 | 29 | packages/**/dist/ 30 | packages/**/lib/ 31 | 32 | .env -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # IDE 35 | *.idea 36 | *.prefs 37 | *.version 38 | *.index 39 | *.tree 40 | *.xmi 41 | *.dat 42 | *.ser 43 | *.log 44 | *.setup 45 | *.ini 46 | *.resources 47 | *.xml 48 | java/* -------------------------------------------------------------------------------- /cpp/.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | DerivePointerAlignment: false 3 | PointerAlignment: Left 4 | BinPackArguments: false 5 | AlwaysBreakTemplateDeclarations: Yes 6 | AllowShortLoopsOnASingleLine: false 7 | AllowAllParametersOfDeclarationOnNextLine: true 8 | AllowShortBlocksOnASingleLine: Never 9 | AllowShortCaseLabelsOnASingleLine: false 10 | AllowShortFunctionsOnASingleLine: Empty 11 | AllowShortIfStatementsOnASingleLine: false 12 | MaxEmptyLinesToKeep: 1 13 | ReflowComments: true 14 | SortIncludes: true 15 | SortUsingDeclarations: false 16 | NamespaceIndentation: All 17 | SpaceAfterTemplateKeyword: false 18 | Standard: c++20 19 | -------------------------------------------------------------------------------- /java/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | java_sdk 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /scala/project/target/streams/compile/compileIncremental/_global/streams/out: -------------------------------------------------------------------------------- 1 | [debug] [zinc] IncrementalCompile ----------- 2 | [debug] IncrementalCompile.incrementalCompile 3 | [debug] previous = Stamps for: 0 products, 0 sources, 0 libraries 4 | [debug] current source = Set() 5 | [debug] > initialChanges = InitialChanges(Changes(added = Set(), removed = Set(), changed = Set(), unmodified = ...),Set(),Set(),API Changes: Set()) 6 | [debug] Full compilation, no sources in previous analysis. 7 | -------------------------------------------------------------------------------- /rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust_sdk" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | reqwest = { version = "0.11.8", features = ["blocking","cookies","json"] } 10 | tokio = { version = "1.15.0", features = ["full"] } 11 | string-builder = "0.2.0" 12 | hmac = "0.12.0" 13 | sha2 = "0.10.1" 14 | hex-literal = "0.3.4" 15 | rust-crypto = "0.2.36" 16 | rustc-serialize = "0.3.24" 17 | hex = "0.4.3" 18 | ring = "0.16.20" 19 | async-trait = "0.1.52" 20 | 21 | [dev-dependencies] 22 | serde = "1.0.119" 23 | serde_json = "1.0.59" 24 | mockito = "0.30.0" -------------------------------------------------------------------------------- /cpp/cmake/useGoldLinker.cmake: -------------------------------------------------------------------------------- 1 | if (UNIX AND NOT APPLE) 2 | execute_process(COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE ld_version) 3 | if ("${ld_version}" MATCHES "GNU gold") 4 | option(USE_GOLD_LINKER "Wheather the gold linker should be used" OFF) 5 | message(STATUS "USE_GOLD_LINKER ${USE_GOLD_LINKER}") 6 | if(USE_GOLD_LINKER) 7 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold -Wl,--disable-new-dtags") 8 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=gold -Wl,--disable-new-dtags") 9 | endif() 10 | endif() 11 | endif() 12 | -------------------------------------------------------------------------------- /cpp/source/rest/public/Announcements.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "../../details/Dispatcher.hpp" 5 | 6 | using namespace Bitwyre::Details; 7 | 8 | namespace Bitwyre::Rest::Public { 9 | 10 | struct Announcements { 11 | 12 | [[nodiscard]] std::string uri() const noexcept { 13 | return "/public/announcements"; 14 | } 15 | [[nodiscard]] Response getAsync() const noexcept { 16 | return std::async(std::launch::async, [](){return get();}); 17 | } 18 | [[nodiscard]] Response get() const noexcept { 19 | return Request::sendGet(uri()); 20 | } 21 | }; 22 | } // namespace Bitwyre::Rest::Public 23 | -------------------------------------------------------------------------------- /python/setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | license_files = LICENSE 3 | 4 | [bdist_wheel] 5 | universal=1 6 | 7 | [pycodestyle] 8 | ignore = E501, F401, W503, E701 9 | max-line-length = 120 10 | max-complexity = 10 11 | select = C,E,F,W,B,B950 12 | 13 | [pep8] 14 | ignore = E501, F401, W503, E701 15 | max-line-length = 120 16 | max-complexity = 10 17 | select = C,E,F,W,B,B950 18 | 19 | [tool:isort] 20 | force_grid_wrap=0 21 | include_trailing_comma=True 22 | line_length=120 23 | multi_line_output=3 24 | use_parentheses=True 25 | 26 | [flake8] 27 | ignore = E501, F401, W503, E701 28 | max-line-length = 120 29 | max-complexity = 10 30 | select = C,E,F,W,B,B950 31 | exclude = 32 | .git, 33 | __pycache__, 34 | .venv, 35 | venv, 36 | -------------------------------------------------------------------------------- /websocket_python/setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | license_files = LICENSE 3 | 4 | [bdist_wheel] 5 | universal=1 6 | 7 | [pycodestyle] 8 | ignore = E501, F401, W503, E701 9 | max-line-length = 120 10 | max-complexity = 10 11 | select = C,E,F,W,B,B950 12 | 13 | [pep8] 14 | ignore = E501, F401, W503, E701 15 | max-line-length = 120 16 | max-complexity = 10 17 | select = C,E,F,W,B,B950 18 | 19 | [tool:isort] 20 | force_grid_wrap=0 21 | include_trailing_comma=True 22 | line_length=120 23 | multi_line_output=3 24 | use_parentheses=True 25 | 26 | [flake8] 27 | ignore = E501, F401, W503, E701 28 | max-line-length = 120 29 | max-complexity = 10 30 | select = C,E,F,W,B,B950 31 | exclude = 32 | .git, 33 | __pycache__, 34 | .venv, 35 | venv, 36 | -------------------------------------------------------------------------------- /cpp/source/unittest/utils.test.cpp.hpp: -------------------------------------------------------------------------------- 1 | #include "catch2/catch.hpp" 2 | 3 | TEST_CASE("Sha256 of a payload", "[rest][private][sign]") { 4 | json payload; 5 | payload["instrument"] = "btc_usdt_spot"; 6 | payload["side"] = 1; 7 | payload["price"] = 10000; 8 | payload["ordtype"] = 2; 9 | payload["orderqty"] = 1; 10 | 11 | std::cout << nlohmann::json(payload.dump()).dump() << "\n"; 12 | std::cout << Bitwyre::Utils::SHA256( 13 | nlohmann::json(payload.dump()).dump()); 14 | } 15 | 16 | TEST_CASE("HMAC", "[rest][private][hmac]") { 17 | auto r = Bitwyre::Utils::HMAC("qwerty"); 18 | auto expectedHmac = 19 | "BABA40E43388359970C18593159EEA9881E24F00304412848B4EF53EB264531E4D17920D" 20 | "BB8FAD7B30EF9D6F5E5F1E0AD124B24109410BE53FE158BAC6BB041E"; 21 | REQUIRE(expectedHmac == r); 22 | } -------------------------------------------------------------------------------- /cpp/doc/doxygen/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /cpp/source/details/Response.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "nlohmann/json.hpp" 3 | #include 4 | 5 | namespace Bitwyre::Details { 6 | using json = nlohmann::json; 7 | using ErrorsT = std::vector; 8 | 9 | struct Response { 10 | int statusCode_; 11 | ErrorsT errors_; 12 | bool next_{false}; 13 | 14 | [[nodiscard]] auto getErrors() const& noexcept -> const ErrorsT& { 15 | return errors_; 16 | } 17 | 18 | [[nodiscard]] auto getErrors() && noexcept -> ErrorsT { 19 | return std::move(errors_); 20 | } 21 | 22 | [[nodiscard]] auto getStatusCode() const noexcept -> long { 23 | return statusCode_; 24 | } 25 | 26 | auto hasNext() const -> bool { 27 | return next_; 28 | } 29 | 30 | auto showErrors() -> void { 31 | for (const auto& e : errors_) { 32 | std::cout << e << "\n"; 33 | } 34 | } 35 | }; 36 | } // namespace Bitwyre::Details -------------------------------------------------------------------------------- /python/bitwyre_sdk/config.py: -------------------------------------------------------------------------------- 1 | TIMEOUT = 5 2 | 3 | 4 | URL_API_BITWYRE = "https://api.bitwyre.id" 5 | 6 | URI_PUBLIC_API_BITWYRE = { 7 | "SERVERTIME": "/public/time", 8 | "TRADES": "/public/trades", 9 | "TICKER": "/public/ticker", 10 | "INSTRUMENT": "/public/pairs", 11 | "DEPTH": "/public/depth", 12 | "ANNOUNCEMENTS": "/public/announcements", 13 | "PRODUCTS": "/public/products", 14 | "MARKETS": "/public/markets", 15 | "ASSETS": "/public/assets", 16 | } 17 | URI_PRIVATE_API_BITWYRE = { 18 | "ACCOUNT_BALANCE": "/private/account/spotbalance", 19 | "ACCOUNT_STATEMENT": "/private/account/statement", 20 | "TRANSACTION_HISTORIES": "/private/account/transactions", 21 | "ORDER": "/private/orders", 22 | "CANCEL_ORDER": "/private/orders/cancel", 23 | "OPEN_ORDERS": "/private/orders/open", 24 | "CLOSED_ORDERS": "/private/orders/closed", 25 | "ORDER_INFO": "/private/orders/info", 26 | "TRADE_HISTORY": "/private/trades", 27 | } 28 | -------------------------------------------------------------------------------- /cpp/source/details/Config.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ConstexprMap.hpp" 4 | #include 5 | 6 | namespace Bitwyre::Details { 7 | 8 | [[nodiscard]] static auto getEnvOr(std::string_view envName, 9 | std::string_view defValue) noexcept 10 | -> std::string { 11 | 12 | if (auto* envVal = std::getenv(envName.data())) { 13 | return envVal; 14 | } 15 | return std::string{defValue}; 16 | } 17 | 18 | struct Config { 19 | using ConfMapT = ConstexprMap; 20 | 21 | private: 22 | const inline static auto API_URL = 23 | getEnvOr("URL_API_BITWYRE", "https://api.bitwyre.id"); 24 | const inline static std::map confMap_ = { 25 | {"URL_API_BITWYRE", API_URL}, 26 | {"TIMEOUT", "5"}, 27 | }; 28 | 29 | public: 30 | static auto getConfig() { 31 | return confMap_; 32 | } 33 | }; 34 | 35 | } // namespace Bitwyre::Details 36 | -------------------------------------------------------------------------------- /java/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /cpp/license.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Kracejic 2 | Copyright (c) 2021 Bitwyre LLC 3 | 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "root", 3 | "version": "1.0.0", 4 | "description": "Bitwyre's Software Development Kit - Algorithmic Trading", 5 | "private": true, 6 | "scripts": { 7 | "lerna": "lerna", 8 | "bootstrap": "yarn --ignore-scripts --silent && lerna bootstrap -- --ignore-scripts && yarn build && lerna bootstrap -- --ignore-scripts", 9 | "build": "lerna run build", 10 | "lint": "lerna run lint", 11 | "test": "lerna run test", 12 | "format": "lerna run format", 13 | "check:all": "yarn test && yarn format && yarn lint && yarn bootstrap" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/bitwyre/sdk.git" 18 | }, 19 | "keywords": [ 20 | "sdk", 21 | "algorithmic", 22 | "trading", 23 | "cryptocurrency" 24 | ], 25 | "author": "Agustinus Theodorus", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/bitwyre/sdk/issues" 29 | }, 30 | "workspaces": [ 31 | "packages/*" 32 | ], 33 | "homepage": "https://github.com/bitwyre/sdk#readme", 34 | "dependencies": { 35 | "lerna": "^5.5.4" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Bitwyre 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /cpp/source/unittest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Unit tests via Catch framework 3 | # 4 | # For testing on the function/class level. 5 | 6 | add_executable(unittests 7 | testmain.cpp 8 | publicApi.test.cpp 9 | privateApi.test.cpp 10 | utils.test.cpp.hpp 11 | MockDispatcher.hpp) 12 | 13 | target_compile_definitions(unittests PRIVATE UNIT_TESTS) # add -DUNIT_TESTS define 14 | target_include_directories(unittests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/..) 15 | target_link_libraries(unittests PRIVATE ${CONAN_LIBS} -fsanitize=address -fsanitize=undefined) 16 | 17 | # convenience target for running only the unit tests 18 | add_custom_target(unit 19 | #this way we can use faux data from /test dir (if we have any): 20 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/test 21 | COMMAND $ 22 | DEPENDS unittests) 23 | # Verbose printing of results 24 | add_custom_target(unitall 25 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/test 26 | COMMAND $ -s -a -r=compact 27 | DEPENDS unittests) 28 | -------------------------------------------------------------------------------- /scala/src/main/scala/Demo.scala: -------------------------------------------------------------------------------- 1 | import com.bitwyre.scala_sdk.{PrivateAPI, PublicAPI} 2 | 3 | object Demo extends App { 4 | /* 5 | val public = new PublicAPI() 6 | public.get_server_time() 7 | public.get_asset_pairs("crypto","spot","US") 8 | public.get_ticker("btc_idr_spot") 9 | public.get_trades(2, "btc_usd_spot") 10 | public.get_depth("btc_usd_spot", 20) 11 | public.get_assets() 12 | public.get_markets() 13 | public.get_products() 14 | public.get_announcements() 15 | */ 16 | val p = new PrivateAPI(System.getenv("SECRET_KEY"), System.getenv("API_KEY")) 17 | //p.get_account_balance() 18 | //p.get_account_statement() 19 | //p.get_transaction_histories() 20 | //p.get_open_orders("btc_usdt_spot", 0, 0); 21 | //p.get_closed_orders("btc_usdt_spot", 0, 0); 22 | //p.get_trade_history("btc_usdt_spot", 2, 0, 0); 23 | //p.get_order_info("d16489da-6899-4200-8ed1-4ff8cfb423e0"); 24 | //p.opening_new_order("btc_usdt_spot", 2, "69000", 2, "0.00001"); 25 | //p.cancelling_open_order_per_instrument("btc_usdt_spot"); 26 | p.cancelling_open_order(Array("3eb90ccd-ce4c-4174-ab40-f54956d164a7"),Array(1)); 27 | } 28 | -------------------------------------------------------------------------------- /cpp/source/details/ConstexprMap.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using std::literals::string_view_literals::operator""sv; 12 | namespace Bitwyre::Details { 13 | 14 | template 15 | struct ConstexprMap { 16 | using key_type = K; 17 | using value_type = V; 18 | using const_key_type = std::add_const_t; 19 | using pair_type = std::pair; 20 | 21 | std::array map_; 22 | 23 | [[nodiscard]] constexpr auto at(const_key_type& lookedForKey) const 24 | -> value_type { 25 | auto it = std::find_if( 26 | map_.begin(), map_.end(), [&lookedForKey](const pair_type& e) { 27 | return e.first == lookedForKey; 28 | }); 29 | if (it != map_.end()) { 30 | return it->second; 31 | } 32 | throw std::runtime_error("Element with the specified key not found"); 33 | } 34 | 35 | constexpr auto operator[](const_key_type& k) const -> value_type { 36 | return at(k); 37 | } 38 | }; 39 | } // namespace Bitwyre::Details -------------------------------------------------------------------------------- /kotlin/src/main/kotlin/test.kt: -------------------------------------------------------------------------------- 1 | import com.bitwyre.kotlin_sdk.PrivateAPI 2 | import com.bitwyre.kotlin_sdk.PublicAPI 3 | 4 | fun main() { 5 | val app = PublicAPI() 6 | //app.getServerTime() 7 | app.getAssetPairs("crypto","spot", "ID") 8 | //app.getTicker("btc_idr_spot") 9 | //app.getTrades(2, "btc_usdt_spot") 10 | //app.getDepth("btc_usdt_spot", 2) 11 | //app.getAssets() 12 | //app.getMarkets() 13 | //app.getProducts() 14 | //app.getAnnouncements() 15 | 16 | val secretkey = System.getenv("SECRET_KEY") 17 | val apikey = System.getenv("API_KEY") 18 | val p = PrivateAPI(secretkey, apikey) 19 | //p.get_account_balance() 20 | //p.get_account_statement() 21 | //p.get_transaction_histories() 22 | //p.get_open_orders("btc_usdt_spot", 0, 0) 23 | //p.get_closed_orders("btc_usdt_spot", 0, 0) 24 | //p.get_trade_history("btc_usdt_spot", 2, 0, 0) 25 | //p.opening_new_order("btc_usdt_spot", 1, "30000", 2, "0.0125") 26 | //p.opening_new_order("btc_usdt_spot", 1, "35000", 2, "0.001") 27 | p.get_order_info("bd9edbda-69eb-4874-8f3f-d004e4fac9bd") 28 | //p.get_order_info("0d4b33e9-6b41-49eb-b8c0-21d0112f9724") 29 | //p.cancelling_open_order_per_instrument("btc_usdt_spot") 30 | //p.cancelling_open_order(arrayOf("e7ee03fe-f5bc-47dc-a1a1-5736e5147ca7","c98090d5-3ec0-4e9a-a2e0-2fb904d7580a"), arrayOf(1,1)) 31 | } 32 | -------------------------------------------------------------------------------- /cpp/source/version.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace Version { 5 | 6 | struct Version { 7 | /// Creates empty Version object 8 | Version(); 9 | 10 | Version(long long int version); 11 | 12 | int major{0}; 13 | int minor{0}; 14 | int patch{0}; 15 | 16 | /// Type of build 17 | std::string type{""}; 18 | 19 | /// Get time of build in format like: Feb 20 2016 14:38:27 20 | std::string datetime{""}; 21 | 22 | /// Machine where it was built 23 | std::string machine{""}; 24 | 25 | /** 26 | * Returns version string with version in format: 27 | * * Major.Minor.Patch VersionType 28 | * * 1.2.3 beta 29 | */ 30 | std::string asShortStr() const; 31 | 32 | /** 33 | * Returns Version + Date + Build machine 34 | * 35 | * Will produce result similar to: 36 | * 1.2.6 beta / Feb 20 2016 14:42:41 / buildMachine 37 | */ 38 | std::string asLongStr() const; 39 | 40 | long long asNumber() const; 41 | 42 | // Operators 43 | bool operator<(const Version& other); 44 | bool operator>(const Version& other); 45 | bool operator<=(const Version& other); 46 | bool operator>=(const Version& other); 47 | bool operator==(const Version& other); 48 | bool operator!=(const Version& other); 49 | }; 50 | 51 | /// Get current version 52 | const Version& current(); 53 | 54 | } // namespace Version 55 | -------------------------------------------------------------------------------- /cpp/source/unittest/MockAsyncDispatcher.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "details/Types.hpp" 3 | #include "nlohmann/json.hpp" 4 | #include "gmock/gmock.h" 5 | #include 6 | 7 | using ::testing::AtLeast; 8 | using json = nlohmann::json; 9 | using namespace Bitwyre::Types::Public; 10 | using namespace Bitwyre::Types::Private; 11 | using Callback = std::function; 12 | 13 | class MockAsyncDispatcher { 14 | public: 15 | MOCK_METHOD(void, getAsync, (Callback cb)); 16 | MOCK_METHOD(json, getAsync, ()); 17 | MOCK_METHOD(json, getAsync, (DepthRequest request)); 18 | MOCK_METHOD(json, getAsync, (InstrumentRequest request)); 19 | MOCK_METHOD(json, getAsync, (ContractRequest request)); 20 | MOCK_METHOD(json, getAsync, (TickerRequest request)); 21 | MOCK_METHOD(json, getAsync, (TradesRequest request)); 22 | MOCK_METHOD(json, getAsync, (AccountBalanceRequest request)); 23 | MOCK_METHOD(json, getAsync, (AccountStatementRequest request)); 24 | MOCK_METHOD(json, delAsync, (CancelOrderRequest request)); 25 | MOCK_METHOD(json, getAsync, (OpenOrdersRequest request)); 26 | MOCK_METHOD(json, getAsync, (ClosedOrdersRequest request)); 27 | MOCK_METHOD(json, postAsync, (NewOrderRequest request)); 28 | MOCK_METHOD(json, getAsync, (OrderInfoRequest request)); 29 | MOCK_METHOD(json, getAsync, (TradesHistoryRequest request)); 30 | MOCK_METHOD(json, getAsync, (TransactionHistoryRequest request)); 31 | 32 | }; 33 | -------------------------------------------------------------------------------- /python/setup.py: -------------------------------------------------------------------------------- 1 | from io import open 2 | from os import path 3 | 4 | from setuptools import find_packages, setup 5 | 6 | here = path.abspath(path.dirname(__file__)) 7 | 8 | with open(path.join(here, "README.md"), encoding="utf-8") as f: 9 | long_description = f.read() 10 | 11 | setup( 12 | name="bitwyre_sdk", 13 | version="0.0.1", 14 | description="Bitwyre API SDK", 15 | long_description=long_description, 16 | long_description_content_type="text/markdown", 17 | url="https://github.com/bitwyre/sdk", 18 | author="Bitwyre Technologies LLC", 19 | author_email="dev@bitwyre.com", 20 | classifiers=[ 21 | "Development Status :: 3 - Alpha", 22 | "Intended Audience :: Developers", 23 | "Topic :: Software Development :: Build Tools", 24 | "License :: OSI Approved :: GNU GPLv3 License", 25 | "Programming Language :: Python :: 3.7", 26 | ], 27 | keywords="financial exchange cryptocurrency", 28 | packages=find_packages(exclude=["contrib", "docs", "tests"]), # Required 29 | python_requires=">=3.7.*, <4", 30 | install_requires=[], # Optional 31 | extras_require={"dev": ["check-manifest", "pycodestyle", "mypy", "pre-commit"], "test": ["coverage", "pytest"]}, 32 | project_urls={ 33 | "Bug Reports": "https://github.com/bitwyre/sdk/issues", 34 | "Funding": "https://bitwyre.com", 35 | "Say Thanks!": "http://bitwyre.gives", 36 | "Source": "https://github.com/bitwyre/sdk", 37 | }, 38 | ) 39 | -------------------------------------------------------------------------------- /websocket_python/setup.py: -------------------------------------------------------------------------------- 1 | from io import open 2 | from os import path 3 | 4 | from setuptools import find_packages, setup 5 | 6 | here = path.abspath(path.dirname(__file__)) 7 | 8 | with open(path.join(here, "README.md"), encoding="utf-8") as f: 9 | long_description = f.read() 10 | 11 | setup( 12 | name="bitwyre_websocket_sdk", 13 | version="0.0.1", 14 | description="Bitwyre Websocket API SDK", 15 | long_description=long_description, 16 | long_description_content_type="text/markdown", 17 | url="https://github.com/bitwyre/sdk", 18 | author="Bitwyre Technologies LLC", 19 | author_email="dev@bitwyre.com", 20 | classifiers=[ 21 | "Development Status :: 3 - Alpha", 22 | "Intended Audience :: Developers", 23 | "Topic :: Software Development :: Build Tools", 24 | "License :: OSI Approved :: GNU GPLv3 License", 25 | "Programming Language :: Python :: 3.7", 26 | ], 27 | keywords="financial exchange cryptocurrency", 28 | packages=find_packages(exclude=["contrib", "docs", "tests"]), # Required 29 | python_requires=">=3.7.*, <4", 30 | install_requires=[], # Optional 31 | extras_require={"dev": ["check-manifest", "pycodestyle", "mypy", "pre-commit"], "test": ["coverage", "pytest"]}, 32 | project_urls={ 33 | "Bug Reports": "https://github.com/bitwyre/sdk/issues", 34 | "Funding": "https://bitwyre.com", 35 | "Say Thanks!": "http://bitwyre.gives", 36 | "Source": "https://github.com/bitwyre/sdk", 37 | }, 38 | ) 39 | -------------------------------------------------------------------------------- /cpp/doc/directoryStructure.md: -------------------------------------------------------------------------------- 1 | # Directory structure 2 | 3 | * mainProjectFolder 4 | - **build** - user created, build takes place here 5 | + **dist** - here builded application is copied (by deafult, see CMAKE_INSTALL_PREFIX in main CMakeLists.txt) 6 | * **bin** 7 | * **share** 8 | - **data** - here folder data is copied 9 | * **doc** 10 | - doxygen lives here documentation 11 | - **cmake** - contains cmake scripts that can be included with include() 12 | + cleanCppExtensions.cmake - reusable helpers for source/CMakeLists.txt 13 | + sanitizers.cmake - adds sanitizers options 14 | + useGoldLinker.cmake - enables simple use of gold linker for faster linkage 15 | - **data** - contain data 16 | - **doc** - contains documentation 17 | + CMakeLists.txt - doc building 18 | + **doxygen** 19 | * doxygen settings, and modern style config 20 | - **source** - contain source files 21 | + CMakeLists.txt - source building 22 | + **unittest* contains unittest build 23 | + CMakeLists.txt - unittest building 24 | + testmain.cpp - main unit tests function 25 | - **test** - integration tests, CTest, data sets for tests and unit tests 26 | + CMakeLists.txt - tests specification 27 | - README.md - main readme file 28 | - CMakeLists.md - Main CMake configuration 29 | - .clang-format - clang format config file 30 | - .clang-tidy - clang tidy config file 31 | 32 | 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Logo 4 | 5 |

6 | 7 | # Bitwyre's Software Development Kit 8 | 9 | Algorithmic trading development on Bitwyre's crypto spot and derivative exchange. 10 | 11 | # Getting Started 12 | 13 | ## What is SDK? 14 | 15 | A software development kit (aka `SDK`) refers to a set of tools, guidelines 16 | and programs used to develop application for our algorithmic trading platform. 17 | Our SDK includes APIs to a variety of programming languages, documentation, libraries, code samples 18 | and other utilities. Our SDK boast a set of robust features and functionalities by wrapping 19 | all the complexity calling an API directly into specific programming languages users consider. 20 | 21 | ## What is a REST API? 22 | Roughly speaking, a REST API is about getting request and processing response. 23 | 24 | ## Gateways 25 | 26 | Bitwyre electronic trading team developed several interfaces to trade on our exchange 27 | 28 | - REST (HTTP + JSON) gateway 29 | - Websocket gateway 30 | - Financial Information Exchange (FIX) gateway 31 | 32 | ## Programming Languages 33 | 34 | We also have included basic trading bots in several popular programming languages 35 | 36 | - Python 37 | - C++ 38 | - Rust 39 | - Objective-C 40 | - Kotlin 41 | - Java 42 | - Scala 43 | - Swift 44 | - Javascript 45 | 46 | # Copyright 47 | 48 | 2021, Bitwyre Technologies Holdings Incorporated 49 | -------------------------------------------------------------------------------- /cpp/.clang-tidy: -------------------------------------------------------------------------------- 1 | --- 2 | Checks: '*,-google*,-*UnreachableCode,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-readability-braces-around-statements,-readability-redundant-string-init,-readability-else-after-return,-modernize-raw-string-literal,-clang-analyzer-alpha.cplusplus.VirtualCall,-readability-simplify-boolean-expri,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-clang-analyzer-alpha.core.CastToStruct, -llvmlibc*' 3 | HeaderFilterRegex: '' 4 | AnalyzeTemporaryDtors: false 5 | User: xohnheis 6 | CheckOptions: 7 | - key: google-readability-braces-around-statements.ShortStatementLines 8 | value: '1' 9 | - key: google-readability-function-size.StatementThreshold 10 | value: '800' 11 | - key: google-readability-namespace-comments.ShortNamespaceLines 12 | value: '10' 13 | - key: google-readability-namespace-comments.SpacesBeforeComments 14 | value: '2' 15 | - key: modernize-loop-convert.MaxCopySize 16 | value: '16' 17 | - key: modernize-loop-convert.MinConfidence 18 | value: reasonable 19 | - key: modernize-loop-convert.NamingStyle 20 | value: CamelCase 21 | - key: modernize-pass-by-value.IncludeStyle 22 | value: llvm 23 | - key: modernize-replace-auto-ptr.IncludeStyle 24 | value: llvm 25 | - key: modernize-use-nullptr.NullMacros 26 | value: 'NULL' 27 | ... 28 | 29 | -------------------------------------------------------------------------------- /js/packages/public/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@bitwyre/internal-public", 3 | "version": "1.0.0", 4 | "description": "Bitwyre's Software Development Kit - Algorithmic Trading", 5 | "main": "lib/index.js", 6 | "types": "lib/index.d.ts", 7 | "files": [ 8 | "lib/**/*" 9 | ], 10 | "scripts": { 11 | "build": "tsc", 12 | "format": "prettier --write \"**/*.ts\"", 13 | "lint": "tslint -p tsconfig.json", 14 | "prepare": "yarn build", 15 | "prepublishOnly": "npm test && yarn lint && yarn build", 16 | "preversion": "yarn lint", 17 | "version": "yarn format && git add -A src", 18 | "postversion": "git push && git push --tags", 19 | "test": "jest --config ./test/jest.json --runInBand" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "git+https://github.com/bitwyre/sdk.git" 24 | }, 25 | "keywords": [ 26 | "sdk", 27 | "algorithmic", 28 | "trading", 29 | "cryptocurrency" 30 | ], 31 | "author": "Agustinus Theodorus", 32 | "license": "MIT", 33 | "bugs": { 34 | "url": "https://github.com/bitwyre/sdk/issues" 35 | }, 36 | "homepage": "https://github.com/bitwyre/sdk#readme", 37 | "dependencies": { 38 | "axios": "^1.0.0" 39 | }, 40 | "devDependencies": { 41 | "@types/jest": "^29.1.2", 42 | "@types/node": "^18.8.2", 43 | "babel-jest": "^29.1.2", 44 | "jest": "^29.1.2", 45 | "prettier": "^2.7.1", 46 | "ts-jest": "^29.0.3", 47 | "tslint": "^6.1.3", 48 | "tslint-config-prettier": "^1.18.0", 49 | "typescript": "^4.8.4" 50 | }, 51 | "directories": { 52 | "test": "test" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /cpp/cmake/sanitizers.cmake: -------------------------------------------------------------------------------- 1 | 2 | #------------------------------------------------------------------------------ 3 | # Clang and gcc sanitizers 4 | if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") 5 | message(STATUS "Sanitizers:") 6 | 7 | option(ADDRESS_SANITIZER "description" OFF) 8 | message(STATUS " + ADDRESS_SANITIZER ${ADDRESS_SANITIZER}") 9 | if(ADDRESS_SANITIZER) 10 | add_compile_options(-fsanitize=address -fno-omit-frame-pointer) 11 | link_libraries(-fsanitize=address -fno-omit-frame-pointer) 12 | endif() 13 | 14 | option(UB_SANITIZER "description" OFF) 15 | message(STATUS " + UB_SANITIZER ${UB_SANITIZER}") 16 | if(UB_SANITIZER) 17 | add_compile_options(-fsanitize=undefined) 18 | link_libraries(-fsanitize=undefined) 19 | endif() 20 | 21 | option(THREAD_SANITIZER "description" OFF) 22 | message(STATUS " + THREAD_SANITIZER ${THREAD_SANITIZER}") 23 | if(THREAD_SANITIZER) 24 | add_compile_options(-fsanitize=thread) 25 | link_libraries(-fsanitize=thread) 26 | endif() 27 | 28 | # Clang only 29 | if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") 30 | option(MEMORY_SANITIZER "description" OFF) 31 | message(STATUS " + MEMORY_SANITIZER ${MEMORY_SANITIZER}") 32 | if(MEMORY_SANITIZER) 33 | add_compile_options(-fsanitize=memory -fno-omit-frame-pointer) 34 | link_libraries(-fsanitize=memory -fno-omit-frame-pointer) 35 | endif() 36 | endif() 37 | endif() 38 | 39 | -------------------------------------------------------------------------------- /cpp/source/rest/public/Market.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Details; 5 | using AsyncMarketResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Public { 8 | 9 | struct Market { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/public/markets"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto getAsync(Callback cb) noexcept -> void { 19 | static_assert( std::is_invocable_v ); 20 | auto result = getAsync(); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto getAsync() noexcept -> AsyncMarketResponse { 26 | return std::async(std::launch::async, [](){return get();}); 27 | } 28 | 29 | template 30 | [[nodiscard]] static auto get() noexcept -> MarketResponse { 31 | auto response = Dispatcher()(uri(), CommonPublicRequest{}); 32 | return processResponse(std::move(response)); 33 | } 34 | 35 | static auto processResponse(json&& response) -> MarketResponse { 36 | MarketResponse marketResponse; 37 | marketResponse.statusCode_ = response["statusCode"].get(); 38 | marketResponse.errors_ = response["error"].get(); 39 | marketResponse.markets = 40 | response["result"].get>(); 41 | return marketResponse; 42 | } 43 | }; 44 | } // namespace Bitwyre::Rest::Public -------------------------------------------------------------------------------- /cpp/source/rest/public/Product.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Details; 5 | using AsyncProductResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Public { 8 | 9 | struct Product { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/public/products"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto getAsync(Callback cb) noexcept -> void { 19 | static_assert( std::is_invocable_v ); 20 | auto result = getAsync(); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto getAsync() noexcept -> AsyncProductResponse { 26 | return std::async(std::launch::async, [](){return get();}); 27 | } 28 | 29 | template 30 | [[nodiscard]] static auto get() noexcept -> ProductResponse { 31 | auto rawResponse = Dispatcher()(uri(), CommonPublicRequest{}); 32 | return processResponse(std::move(rawResponse)); 33 | } 34 | 35 | static auto processResponse(json&& response) -> ProductResponse { 36 | ProductResponse productResponse; 37 | productResponse.statusCode_ = response["statusCode"]; 38 | productResponse.errors_ = response["error"].get(); 39 | productResponse.products = 40 | response["result"].get>(); 41 | return productResponse; 42 | } 43 | }; 44 | } // namespace Bitwyre::Rest::Public 45 | -------------------------------------------------------------------------------- /python/bitwyre_sdk/utils.py: -------------------------------------------------------------------------------- 1 | import hmac 2 | import json 3 | import time 4 | from hashlib import sha256, sha512 5 | import logging 6 | 7 | 8 | logging.basicConfig(level=logging.DEBUG, format="%(asctime)s:%(levelname)s:%(message)s") 9 | 10 | 11 | class Logger(): 12 | 13 | def __init__(self): 14 | pass 15 | 16 | def debug(self, text: str): 17 | logging.debug(f"{text}") 18 | 19 | def info(self, text: str): 20 | logging.info(f"{text}") 21 | 22 | def warning(self, text: str): 23 | logging.warning(f"{text}") 24 | 25 | 26 | def return_timeout(): 27 | status_code = 408 28 | results = {} 29 | results["error"] = ["Timeout"] 30 | results["result"] = {} 31 | return (status_code, results) 32 | 33 | 34 | def return_not_ok(response): 35 | results = {} 36 | try: 37 | results = response.json() 38 | status_code = response.status_code 39 | except Exception: 40 | results["error"] = [response.reason] 41 | results["result"] = {} 42 | status_code = response.status_code 43 | return (status_code, results) 44 | 45 | return (status_code, results) 46 | 47 | 48 | def sign(secret_key: str, uri_path: str, payload: str) -> (int, str, str): 49 | nonce = time.time_ns() 50 | payload = json.dumps(payload) 51 | payload = json.dumps(payload) 52 | checksum = sha256(str(payload).encode("utf-8")).hexdigest() 53 | nonce_checksum = sha256(str(nonce).encode("utf-8") + str(checksum).encode("utf-8")).hexdigest() 54 | signature = hmac.new( 55 | secret_key.encode("utf-8"), uri_path.encode("utf-8") + nonce_checksum.encode("utf-8"), sha512 56 | ).hexdigest() 57 | return (nonce, checksum, signature) 58 | -------------------------------------------------------------------------------- /scala/src/main/scala/com/bitwyre/scala_sdk/Config.scala: -------------------------------------------------------------------------------- 1 | package com.bitwyre.scala_sdk 2 | 3 | import scala.collection.mutable.HashMap 4 | 5 | class Config { 6 | object baseURL { 7 | val URL_API_BITWYRE: String = "https://api.bitwyre.com" 8 | val TIMEOUT: Int = 5 9 | def getPublicAPIEndpoint(key: String): String = { 10 | val URI_PUBLIC_API_BITWYRE = HashMap( 11 | "SERVERTIME" -> "/public/time", 12 | "TRADES" -> "/public/trades", 13 | "TICKER" -> "/public/ticker", 14 | "INSTRUMENT" -> "/public/pairs", 15 | "DEPTH" -> "/public/depth", 16 | "ANNOUNCEMENTS" -> "/public/announcements", 17 | "PRODUCTS" -> "/public/products", 18 | "MARKETS" -> "/public/markets", 19 | "ASSETS" -> "/public/assets" 20 | ) 21 | URI_PUBLIC_API_BITWYRE(key) 22 | } 23 | def getPrivateAPIEndPoint(key: String): String = { 24 | val URI_PRIVATE_API_BITWYRE = HashMap( 25 | "ACCOUNT_BALANCE" -> "/private/account/spotbalance", 26 | "ACCOUNT_STATEMENT" -> "/private/account/statement", 27 | "TRANSACTION_HISTORIES" -> "/private/account/transactions", 28 | "ORDER" -> "/private/orders", 29 | "CANCEL_ORDER" -> "/private/orders/cancel", 30 | "OPEN_ORDERS" -> "/private/orders/open", 31 | "CLOSED_ORDERS" -> "/private/orders/closed", 32 | "ORDER_INFO" -> "/private/orders/info", 33 | "TRADE_HISTORY" -> "/private/trades" 34 | ) 35 | URI_PRIVATE_API_BITWYRE(key) 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /js/packages/private/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@bitwyre/sdk", 3 | "version": "1.0.0", 4 | "description": "Bitwyre's Software Development Kit - Algorithmic Trading", 5 | "main": "lib/index.js", 6 | "types": "lib/index.d.ts", 7 | "files": [ 8 | "lib/**/*" 9 | ], 10 | "scripts": { 11 | "build": "tsc", 12 | "format": "prettier --write \"**/*.ts\"", 13 | "lint": "tslint -p tsconfig.json", 14 | "prepare": "yarn build", 15 | "prepublishOnly": "npm test && yarn lint && yarn build", 16 | "preversion": "yarn lint", 17 | "version": "yarn format && git add -A src", 18 | "postversion": "git push && git push --tags", 19 | "test": "jest --config ./test/jest.json --runInBand" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "git+https://github.com/bitwyre/sdk.git" 24 | }, 25 | "keywords": [ 26 | "sdk", 27 | "algorithmic", 28 | "trading", 29 | "cryptocurrency" 30 | ], 31 | "author": "Agustinus Theodorus", 32 | "license": "MIT", 33 | "bugs": { 34 | "url": "https://github.com/bitwyre/sdk/issues" 35 | }, 36 | "homepage": "https://github.com/bitwyre/sdk#readme", 37 | "dependencies": { 38 | "@bitwyre/internal-public": "1.0.0", 39 | "@types/sha256": "^0.2.0", 40 | "axios": "^1.0.0", 41 | "crypto": "^1.0.1" 42 | }, 43 | "devDependencies": { 44 | "@types/jest": "^29.1.2", 45 | "@types/node": "^18.8.2", 46 | "babel-jest": "^29.1.2", 47 | "dotenv": "^16.0.3", 48 | "jest": "^29.1.2", 49 | "prettier": "^2.7.1", 50 | "ts-jest": "^29.0.3", 51 | "tslint": "^6.1.3", 52 | "tslint-config-prettier": "^1.18.0", 53 | "typescript": "^4.8.4" 54 | }, 55 | "directories": { 56 | "test": "test" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /cpp/source/rest/public/Time.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Details; 5 | using AsyncTimeResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Public { 8 | using TimeT = std::chrono::nanoseconds; 9 | 10 | struct Time { 11 | 12 | using Callback = std::function; 13 | 14 | [[nodiscard]] static auto uri() noexcept -> std::string { 15 | return "/public/time"; 16 | } 17 | 18 | template 19 | [[nodiscard]] static auto getAsync(Callback cb) noexcept -> void { 20 | static_assert( std::is_invocable_v ); 21 | auto result = getAsync(); 22 | return cb(result.get()); 23 | } 24 | 25 | template 26 | [[nodiscard]] static auto getAsync() noexcept -> AsyncTimeResponse { 27 | return std::async(std::launch::async, [](){return get();}); 28 | } 29 | 30 | template 31 | [[nodiscard]] static auto get() noexcept -> TimeResponse { //from Types.hpp 32 | auto response = Dispatcher()(uri(), CommonPublicRequest{}); 33 | return processResponse(std::move(response)); 34 | } 35 | 36 | static auto processResponse(json&& rawResponse) -> TimeResponse { 37 | TimeResponse timeResponse; 38 | timeResponse.statusCode_ = rawResponse["statusCode"].get(); 39 | timeResponse.errors_ = rawResponse["error"].get(); 40 | timeResponse.unixtime = 41 | static_cast(rawResponse["result"]["unixtime"].get()); 42 | return timeResponse; 43 | } 44 | }; 45 | } // namespace Bitwyre::Rest::Public 46 | -------------------------------------------------------------------------------- /cpp/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # https://cmake.org/cmake/help/latest/manual/ctest.1.html 2 | # https://cmake.org/Wiki/CMake/Testing_With_CTest 3 | # https://cmake.org/cmake/help/latest/command/add_test.html? 4 | 5 | include(CTest) 6 | 7 | # Convenience targets for fast testing, they depends on binaries (so the build 8 | # is triggered, when sources were changed). 9 | add_custom_target(check 10 | COMMAND echo [----] Running tests 11 | USES_TERMINAL 12 | COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C Debug 13 | DEPENDS bitwyresdk unittests) 14 | 15 | add_custom_target(checkVerbose 16 | COMMAND echo [----] Running tests 17 | USES_TERMINAL 18 | COMMAND ${CMAKE_CTEST_COMMAND} -V --output-on-failure -C Debug 19 | DEPENDS bitwyresdk unittests) 20 | 21 | #------------------------------------------------------------------------------ 22 | # CTest test suite 23 | # 24 | # Test suite is defined here, when executed test fails (returns not 0), test 25 | # failed. There are more options, check CMake documentation. 26 | # 27 | # Good to use to integration test, run whole program with parameters, 28 | # check if it will crash, produce correct results, etc. 29 | 30 | 31 | # Basic runable tests (will not crash) 32 | add_test(NAME "Is_Runable " 33 | COMMAND $) 34 | 35 | add_test(NAME "Is_Runable-v" 36 | COMMAND $ -v) 37 | 38 | add_test(NAME "Is_Runable-h" 39 | COMMAND $ -h) 40 | 41 | 42 | 43 | 44 | 45 | # Add unit test to CTest suite as one of the tests 46 | # unit test build is located in source/unittest/CMakeLists.txt 47 | add_test(NAME "catch_unit_tests" 48 | COMMAND $ 49 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 50 | 51 | -------------------------------------------------------------------------------- /cpp/source/rest/public/OrderTypes.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Details; 5 | using AsyncOrderTypesResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Public { 8 | 9 | struct OrderTypes { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/public/ordertypes"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto getAsync(Callback cb) noexcept -> void { 19 | static_assert( std::is_invocable_v ); 20 | auto result = getAsync(); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto getAsync() noexcept -> AsyncOrderTypesResponse { 26 | return std::async(std::launch::async, [](){return get();}); 27 | } 28 | 29 | template 30 | [[nodiscard]] static auto get() noexcept -> OrderTypesResponse { 31 | auto rawResponse = Dispatcher()(uri(), CommonPublicRequest{}); 32 | return processResponse(std::move(rawResponse)); 33 | } 34 | 35 | static auto processResponse(json&& rawResponse) -> OrderTypesResponse { 36 | OrderTypesResponse orderTypesResponse; 37 | orderTypesResponse.statusCode_ = rawResponse["statusCode"].get(); 38 | orderTypesResponse.errors_ = rawResponse["error"].get(); 39 | 40 | for (const auto& orderType : rawResponse["result"]) { 41 | orderTypesResponse.orderTypes.push_back(orderType); 42 | } 43 | return orderTypesResponse; 44 | } 45 | }; 46 | } // namespace Bitwyre::Rest::Public -------------------------------------------------------------------------------- /java/src/main/java/com/bitwyre/sdk/App.java: -------------------------------------------------------------------------------- 1 | package com.bitwyre.sdk; 2 | 3 | import java.io.IOException; 4 | import java.io.UnsupportedEncodingException; 5 | import java.security.InvalidKeyException; 6 | import java.security.NoSuchAlgorithmException; 7 | /** 8 | * For testing only! 9 | * 10 | */ 11 | public class App 12 | { 13 | public static void main( String[] args ) throws IOException, InterruptedException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException 14 | { 15 | /* 16 | PublicAPI.get_server_time(); 17 | PublicAPI.get_asset_pairs("crypto", "spot", "US"); 18 | PublicAPI.get_ticker("btc_idr_spot"); 19 | PublicAPI.get_trades(2, "btc_usd_spot"); 20 | PublicAPI.get_depth("btc_usd_spot", 20); 21 | PublicAPI.get_assets(); 22 | PublicAPI.get_markets(); 23 | PublicAPI.get_products(); 24 | PublicAPI.get_announcements(); 25 | */ 26 | 27 | PrivateAPI p = new PrivateAPI(System.getenv("SECRET_KEY"), System.getenv("API_KEY")); 28 | p.get_account_balance(); 29 | //p.get_account_statement(); 30 | //p.get_transaction_histories(); 31 | //p.get_open_orders("btc_usdt_spot", 0, 0); 32 | //p.get_closed_orders("btc_usdt_spot", 0, 0); 33 | //p.get_trade_history("btc_usdt_spot", 2, 0, 0); 34 | //p.opening_new_order("btc_usdt_spot", 1, "30000", 2, "0.0125"); 35 | //p.opening_new_order("btc_usdt_spot", 1, "35000", 2, "0.001"); 36 | //p.get_order_info("e7ee03fe-f5bc-47dc-a1a1-5736e5147ca7"); 37 | //p.cancelling_open_order_per_instrument("btc_usdt_spot"); 38 | //p.cancelling_open_order(new String[]{"e7ee03fe-f5bc-47dc-a1a1-5736e5147ca7","c98090d5-3ec0-4e9a-a2e0-2fb904d7580a"},new Integer[]{1,1}); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /cpp/source/rest/public/SupportedLanguages.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Details; 5 | using AsyncSupportedLanguagesResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Public { 8 | 9 | struct SupportedLanguages { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/public/languages"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto getAsyncLanguage(Callback cb) noexcept -> void { 19 | static_assert( std::is_invocable_v ); 20 | auto result = getAsyncLanguage(); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto getAsyncLanguage() noexcept -> AsyncSupportedLanguagesResponse { 26 | return std::async(std::launch::async, [](){return get();}); 27 | } 28 | 29 | template 30 | [[nodiscard]] static auto get() noexcept -> SupportedLanguagesResponse { 31 | auto rawResponse = Dispatcher()(uri(), CommonPublicRequest{}); 32 | return processResponse(std::move(rawResponse)); 33 | } 34 | 35 | static auto processResponse(json&& rawResponse) 36 | -> SupportedLanguagesResponse { 37 | SupportedLanguagesResponse supportedLanguagesResponse; 38 | supportedLanguagesResponse.statusCode_ = 39 | rawResponse["statusCode"].get(); 40 | supportedLanguagesResponse.errors_ = rawResponse["error"].get(); 41 | return supportedLanguagesResponse; 42 | } 43 | }; 44 | } // namespace Bitwyre::Rest::Public -------------------------------------------------------------------------------- /cpp/source/rest/public/Asset.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Details; 5 | using AsyncAssetResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Public { 8 | 9 | struct Asset { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/public/assets"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto getAsync(Callback cb) noexcept -> void { 19 | static_assert( std::is_invocable_v ); 20 | auto result = getAsync(); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto getAsync() noexcept -> AsyncAssetResponse { 26 | return std::async(std::launch::async, [](){return get();}); 27 | } 28 | 29 | template 30 | [[nodiscard]] static auto get() noexcept -> AssetResponse { 31 | auto response = Dispatcher()(uri(), CommonPublicRequest{}); 32 | return processResponse(std::move(response)); 33 | } 34 | 35 | static auto processResponse(json&& rawResponse) -> AssetResponse { 36 | AssetResponse assetResponse; 37 | assetResponse.statusCode_ = rawResponse["statusCode"].get(); 38 | assetResponse.errors_ = rawResponse["error"].get(); 39 | 40 | for (const auto& asset : rawResponse["result"]) { 41 | AssetElement parsedAsset; 42 | parsedAsset.name = asset["name"].get(); 43 | assetResponse.assets.push_back(std::move(parsedAsset)); 44 | } 45 | return assetResponse; 46 | } 47 | }; 48 | } // namespace Bitwyre::Rest::Public 49 | -------------------------------------------------------------------------------- /cpp/source/rest/public/FiatAsset.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Details; 5 | using AsyncFiatAssetResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Public { 8 | 9 | struct FiatAsset { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/public/assets/fiat"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto getAsync(Callback cb) noexcept -> void { 19 | static_assert( std::is_invocable_v ); 20 | auto result = getAsync(); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto getAsync() noexcept -> AsyncFiatAssetResponse { 26 | return std::async(std::launch::async, [](){return get();}); 27 | } 28 | 29 | template 30 | [[nodiscard]] static auto get() noexcept -> FiatAssetResponse { 31 | auto rawResponse = Dispatcher()(uri(), CommonPublicRequest{}); 32 | return processResponse(std::move(rawResponse)); 33 | } 34 | 35 | static auto processResponse(json&& rawResponse) -> FiatAssetResponse { 36 | FiatAssetResponse assetResponse; 37 | assetResponse.statusCode_ = rawResponse["statusCode"].get(); 38 | assetResponse.errors_ = rawResponse["error"].get(); 39 | 40 | for (const auto& asset : rawResponse["result"]) { 41 | AssetElement parsedAsset; 42 | parsedAsset.name = asset["name"].get(); 43 | assetResponse.assets.push_back(std::move(parsedAsset)); 44 | } 45 | return assetResponse; 46 | } 47 | }; 48 | } // namespace Bitwyre::Rest::Public 49 | -------------------------------------------------------------------------------- /cpp/source/rest/public/CryptoAsset.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Details; 5 | using AsyncCrytoAssetResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Public { 8 | 9 | struct CryptoAsset { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/public/assets/crypto"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto getAsync(Callback cb) noexcept -> void { 19 | static_assert( std::is_invocable_v ); 20 | auto result = getAsync(); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto getAsync() noexcept -> AsyncCrytoAssetResponse { 26 | return std::async(std::launch::async, [](){return get();}); 27 | 28 | } 29 | 30 | template 31 | [[nodiscard]] static auto get() noexcept -> CryptoAssetResponse { 32 | auto rawResponse = Dispatcher()(uri(), CommonPublicRequest{}); 33 | return processResponse(std::move(rawResponse)); 34 | } 35 | 36 | static auto processResponse(json&& rawResponse) -> CryptoAssetResponse { 37 | CryptoAssetResponse assetResponse; 38 | assetResponse.statusCode_ = rawResponse["statusCode"].get(); 39 | assetResponse.errors_ = rawResponse["error"].get(); 40 | 41 | for (const auto& asset : rawResponse["result"]) { 42 | AssetElement parsedAsset; 43 | parsedAsset.name = asset["name"].get(); 44 | assetResponse.assets.push_back(std::move(parsedAsset)); 45 | } 46 | return assetResponse; 47 | } 48 | }; 49 | } // namespace Bitwyre::Rest::Public 50 | -------------------------------------------------------------------------------- /websocket_python/websocket_python_sdk/utils.py: -------------------------------------------------------------------------------- 1 | import logging 2 | logging.basicConfig( 3 | format='%(asctime)s %(message)s', 4 | filemode='w' 5 | ) 6 | logger = logging.getLogger() 7 | logger.setLevel(logging.DEBUG) 8 | 9 | BASE_URL = "wss://api.bitwyre.com" 10 | PRINT_DEBUGS = False 11 | 12 | def exit_message(response, error_code, error_msg): 13 | logging.debug("") 14 | logging.debug(" ================ ") 15 | logging.debug(" ================ CONNECT FAILED ================ ") 16 | logging.debug(f"Host response {response}") 17 | logging.debug(f"Host error codes {error_code}") 18 | logging.debug(f"Host error message {error_msg}") 19 | logging.debug(f"Exiting") 20 | 21 | def parse_codes(status_code, response, error_code, error_msg): 22 | """ 23 | Websocket STATUS OPERATION CODE 24 | 0: Continue next packet 25 | 1: returned text message 26 | 2: returned binary message 27 | 3, 4, 5, 6, 7: Unsupported RSV 28 | 8: Connection is closed by host 29 | 9: Ping request 30 | a: Pong answer 31 | 32 | returns: 33 | success: bool 34 | response: string 35 | connection status: string 36 | backend message: string 37 | """ 38 | 39 | if status_code in [0, 1, 2]: 40 | # all good 41 | return (True, response, {"code": status_code, "msg": "all good, connection alive"}, error_msg) 42 | elif status_code in [3, 4, 5, 6, 7]: 43 | return (False, response, {"code": status_code, "msg": "rsv is not supported, connection still open"}, error_msg) 44 | elif status_code == 8: 45 | return (False, response, {"code": status_code, "msg": "Connection is terminated by host"}, error_msg) 46 | elif status_code == 9: 47 | return (True, response, {"code": status_code, "msg": "Counterparty ask for ping"}, error_msg) 48 | elif status_code in ['a', 'A']: 49 | return (True, response, {"code": status_code, "msg": "Counterparty pong answer"}, error_msg) -------------------------------------------------------------------------------- /js/packages/private/src/authentication.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import crypto from "crypto"; 3 | 4 | export const currentDateNs = +new Date() * 1000; 5 | 6 | export async function getServerTime(baseUrl: string) { 7 | const uriPath: string = "/public/time"; 8 | 9 | return await axios.get(uriPath, { 10 | baseURL: baseUrl, 11 | }); 12 | } 13 | 14 | export interface SignData { 15 | nonce: number; 16 | checksum: string; 17 | signature: string; 18 | } 19 | 20 | export async function getNonce(baseUrl: string): Promise { 21 | const res = await getServerTime(baseUrl); 22 | return res.data.result.unixtime; 23 | } 24 | 25 | export function getChecksum(payload: string): string { 26 | const temp = JSON.stringify(payload); 27 | const temp2 = JSON.stringify(temp); 28 | const temp3 = JSON.stringify(temp2); 29 | return crypto.createHash("sha256").update(temp3).digest("hex"); 30 | } 31 | 32 | export function getNonceChecksum(nonce: string, checksum: string): string { 33 | const noncechecksum = crypto 34 | .createHash("sha256") 35 | .update(nonce.concat(checksum)) 36 | .digest("hex"); 37 | return noncechecksum; 38 | } 39 | 40 | export async function sign( 41 | baseUrl: string, 42 | secretKey: string, 43 | uriPath: string, 44 | payload: string 45 | ): Promise { 46 | //const nonce: number = await getNonce(baseUrl); 47 | const nonce: number = Date.now(); 48 | console.log(`Nonce used to compute checksum ${nonce}`); 49 | const checksum: string = getChecksum(payload); 50 | const nonceChecksum = getNonceChecksum(nonce.toString(), checksum); 51 | console.log(`Nonce checksum ${nonceChecksum}`); 52 | const data = uriPath.concat(nonceChecksum); 53 | console.log(`data ${data}`); 54 | const signature = crypto 55 | .createHmac("sha512", secretKey) 56 | .update(data) 57 | .digest("hex"); 58 | console.log(`signature ${signature}`); 59 | 60 | return { 61 | nonce, 62 | checksum, 63 | signature, 64 | }; 65 | } 66 | -------------------------------------------------------------------------------- /cpp/conanfile.py: -------------------------------------------------------------------------------- 1 | from conans import ConanFile, CMake, tools 2 | import os 3 | 4 | class bitwyresdkCpp(ConanFile): 5 | name = "bitwyresdk" 6 | version = "1.0.0" 7 | url = "https://github.com/bitwyre/bitwyre_sdk_cpp" 8 | description = "The official C++ SDK to connect with Bitwyre's REST, WS and FIX API" 9 | settings = "os", "compiler", "build_type", "arch" 10 | options = {"shared": [True, False], "build_doc": [True, False]} 11 | default_options = {"shared": False, "build_doc": False} 12 | generators = "cmake" 13 | exports_sources = ("source/details/*", "source/rest/*", "source/CMakeLists.txt", 14 | "source/version.h", "source/version.cpp.in", "CMakeLists.txt", "cmake/*") 15 | 16 | requires = [ 17 | "fmt/6.2.0@bitwyre/stable", 18 | "nlohmann_json/3.9.1@bitwyre/stable", 19 | "cpr/1.6.2@bitwyre/stable", 20 | "cryptopp/8.5.0@bitwyre/stable", 21 | "namedtype/20190324@bitwyre/stable", 22 | ] 23 | 24 | @property 25 | def _source_subfolder(self): 26 | return "source_subfolder" 27 | 28 | def requirements(self): 29 | if tools.get_env("CONAN_RUN_TESTS"): 30 | self.requires("catch2/2.13.6@bitwyre/stable") 31 | self.requires("gtest/cci.20210126@bitwyre/stable") 32 | 33 | def config_options(self): 34 | if self.settings.os == "Windows": 35 | del self.options.fPIC 36 | 37 | def _configure_cmake(self): 38 | cmake = CMake(self) 39 | cmake.definitions["BITWYRE_INSTALL_DOCS"] = self.options.build_doc 40 | cmake.configure() 41 | return cmake 42 | 43 | def build(self): 44 | cmake = self._configure_cmake() 45 | cmake.build() 46 | 47 | def package(self): 48 | self.copy("LICENSE.md", dst="licenses", src=self._source_subfolder) 49 | cmake = self._configure_cmake() 50 | cmake.install() 51 | 52 | def package_info(self): 53 | self.cpp_info.libs = ["bitwyresdk"] 54 | -------------------------------------------------------------------------------- /cpp/cleanCppProject.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "file_exclude_patterns":[ 6 | "*swp" 7 | ], 8 | "folder_exclude_patterns": 9 | [ 10 | "build*" 11 | ], 12 | "path": "." 13 | } 14 | ], 15 | "build_systems": 16 | [ 17 | { 18 | "name": "build", 19 | "working_dir": "${project_path}/build", 20 | "file_regex": "^([\\/\\.^\\s^\\[]..*?):([0-9]+):([0-9]+):(.*)", 21 | "shell": true, 22 | "cmd":["cmake --build ."], 23 | // "syntax": "Packages/cppinabox/C++build.sublime-syntax", 24 | "windows":{"shell_cmd":"c:/runLinux32.bat cmake --build ."}, 25 | "variants": [ 26 | { 27 | "name":"install", 28 | "cmd":["cmake --build . --target install"], 29 | "windows":{"shell_cmd":"c:/runLinux32.bat cmake --build . --target install"}, 30 | }, 31 | { 32 | "name":"doc", 33 | "cmd":["cmake --build . --target doc"], 34 | "windows":{"shell_cmd":"c:/runLinux32.bat cmake --build . --target doc"}, 35 | }, 36 | { 37 | "name":"check", 38 | "cmd":["cmake --build . --target check"], 39 | "windows":{"shell_cmd":"c:/runLinux32.bat cmake --build . --target check"}, 40 | }, 41 | { 42 | "name":"clean", 43 | "cmd":["cmake --build . --target clean"], 44 | "windows":{"shell_cmd":"c:/runLinux32.bat cmake --build . --target clean"}, 45 | }, 46 | { 47 | "name":"run", 48 | "cmd":["cmake --build . --target run"], 49 | "windows":{"shell_cmd":"c:/runLinux32.bat cmake --build . --target run"}, 50 | }, 51 | 52 | ] 53 | }, 54 | 55 | ] 56 | } -------------------------------------------------------------------------------- /java/src/main/java/com/bitwyre/sdk/config.java: -------------------------------------------------------------------------------- 1 | package com.bitwyre.sdk; 2 | 3 | import java.util.HashMap; 4 | 5 | public class config { 6 | final static int TIMEOUT = 5; 7 | final static String URL_API_BITWYRE = "https://api.bitwyre.com"; 8 | public static String getPublicAPIEndPoint(String key) { 9 | HashMap URI_PUBLIC_API_BITWYRE = new HashMap<>(); 10 | URI_PUBLIC_API_BITWYRE.put("SERVERTIME", "/public/time"); 11 | URI_PUBLIC_API_BITWYRE.put("TRADES", "/public/trades"); 12 | URI_PUBLIC_API_BITWYRE.put("TICKER", "/public/ticker"); 13 | URI_PUBLIC_API_BITWYRE.put("INSTRUMENT", "/public/pairs"); 14 | URI_PUBLIC_API_BITWYRE.put("DEPTH", "/public/depth"); 15 | URI_PUBLIC_API_BITWYRE.put("ANNOUNCEMENTS", "/public/announcements"); 16 | URI_PUBLIC_API_BITWYRE.put("PRODUCTS", "/public/products"); 17 | URI_PUBLIC_API_BITWYRE.put("MARKETS", "/public/markets"); 18 | URI_PUBLIC_API_BITWYRE.put("ASSETS", "/public/assets"); 19 | String value = URI_PUBLIC_API_BITWYRE.get(key); 20 | return value; 21 | } 22 | public static String getPrivateAPIEndPoint(String key) { 23 | HashMap URI_PRIVATE_API_BITWYRE = new HashMap<>(); 24 | URI_PRIVATE_API_BITWYRE.put("ACCOUNT_BALANCE", "/private/account/spotbalance"); 25 | URI_PRIVATE_API_BITWYRE.put("ACCOUNT_STATEMENT", "/private/account/statement"); 26 | URI_PRIVATE_API_BITWYRE.put("TRANSACTION_HISTORIES", "/private/account/transactions"); 27 | URI_PRIVATE_API_BITWYRE.put("ORDER", "/private/orders"); 28 | URI_PRIVATE_API_BITWYRE.put("CANCEL_ORDER", "/private/orders/cancel"); 29 | URI_PRIVATE_API_BITWYRE.put("OPEN_ORDERS", "/private/orders/open"); 30 | URI_PRIVATE_API_BITWYRE.put("CLOSED_ORDERS", "/private/orders/closed"); 31 | URI_PRIVATE_API_BITWYRE.put("ORDER_INFO", "/private/orders/info"); 32 | URI_PRIVATE_API_BITWYRE.put("TRADE_HISTORY", "/private/trades"); 33 | String value = URI_PRIVATE_API_BITWYRE.get(key); 34 | return value; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /kotlin/src/main/kotlin/com/bitwyre/kotlin_sdk/Config.kt: -------------------------------------------------------------------------------- 1 | package com.bitwyre.kotlin_sdk 2 | 3 | class Config { 4 | object baseURL { 5 | val URL_API_BITWYRE = "https://api.bitwyre.com/" 6 | val TIMEOUT = 5 7 | fun getPublicAPIEndpoint(key: String): String? { 8 | val URI_PUBLIC_API_BITWYRE = HashMap () 9 | URI_PUBLIC_API_BITWYRE.put("SERVERTIME", "/public/time") 10 | URI_PUBLIC_API_BITWYRE.put("TRADES", "/public/trades") 11 | URI_PUBLIC_API_BITWYRE.put("TICKER", "/public/ticker") 12 | URI_PUBLIC_API_BITWYRE.put("INSTRUMENT", "/public/pairs") 13 | URI_PUBLIC_API_BITWYRE.put("DEPTH", "/public/depth") 14 | URI_PUBLIC_API_BITWYRE.put("ANNOUNCEMENTS", "/public/announcements") 15 | URI_PUBLIC_API_BITWYRE.put("PRODUCTS", "/public/products") 16 | URI_PUBLIC_API_BITWYRE.put("MARKETS", "/public/markets") 17 | URI_PUBLIC_API_BITWYRE.put("ASSETS", "/public/assets") 18 | val value = URI_PUBLIC_API_BITWYRE.get(key) 19 | return value 20 | } 21 | fun getPrivateAPIEndPoint(key: String): String? { 22 | val URI_PRIVATE_API_BITWYRE = HashMap () 23 | URI_PRIVATE_API_BITWYRE.put("ACCOUNT_BALANCE", "/private/account/spotbalance") 24 | URI_PRIVATE_API_BITWYRE.put("ACCOUNT_STATEMENT", "/private/account/statement") 25 | URI_PRIVATE_API_BITWYRE.put("TRANSACTION_HISTORIES", "/private/account/transactions") 26 | URI_PRIVATE_API_BITWYRE.put("ORDER", "/private/orders") 27 | URI_PRIVATE_API_BITWYRE.put("CANCEL_ORDER", "/private/orders/cancel") 28 | URI_PRIVATE_API_BITWYRE.put("OPEN_ORDERS", "/private/orders/open") 29 | URI_PRIVATE_API_BITWYRE.put("CLOSED_ORDERS", "/private/orders/closed") 30 | URI_PRIVATE_API_BITWYRE.put("ORDER_INFO", "/private/orders/info") 31 | URI_PRIVATE_API_BITWYRE.put("TRADE_HISTORY", "/private/trades") 32 | val value = URI_PRIVATE_API_BITWYRE.get(key) 33 | return value 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /cpp/source/rest/public/Instrument.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Details; 5 | using namespace Bitwyre::Types::Public; 6 | using AsyncInstrumentResponse = std::future; 7 | 8 | namespace Bitwyre::Rest::Public { 9 | 10 | struct Instrument { 11 | 12 | using Callback = std::function; 13 | 14 | [[nodiscard]] static auto uri() noexcept -> std::string { 15 | return "/public/pairs"; 16 | } 17 | 18 | template 19 | [[nodiscard]] static auto getAsync(Callback cb, const InstrumentRequest& request) noexcept -> void { 20 | static_assert( std::is_invocable_v ); 21 | auto result = getAsync(request); 22 | return cb(result.get()); 23 | } 24 | 25 | template 26 | [[nodiscard]] static auto getAsync(const InstrumentRequest& request) noexcept -> AsyncInstrumentResponse { 27 | return std::async(std::launch::async, [&request](){return get(request);}); 28 | } 29 | 30 | template 31 | [[nodiscard]] static auto get(const InstrumentRequest& request) noexcept 32 | -> InstrumentResponse { 33 | auto rawResponse = Dispatcher()(uri(), request); 34 | return processResponse(std::move(rawResponse)); 35 | } 36 | 37 | static auto processResponse(json&& rawResponse) noexcept 38 | -> InstrumentResponse { 39 | InstrumentResponse instrumentResponse; 40 | instrumentResponse.statusCode_ = rawResponse["statusCode"].get(); 41 | instrumentResponse.errors_ = rawResponse["error"].get(); 42 | 43 | for (const auto& rawInstrument : rawResponse["result"]) { 44 | InstrumentElement instrumentElement; 45 | instrumentElement.instrument = 46 | rawInstrument["instrument"].get(); 47 | instrumentElement.symbol = rawInstrument["symbol"].get(); 48 | instrumentResponse.instruments.push_back(std::move(instrumentElement)); 49 | } 50 | return instrumentResponse; 51 | } 52 | }; 53 | } // namespace Bitwyre::Rest::Public -------------------------------------------------------------------------------- /cpp/source/rest/public/Depth.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Details; 5 | using AsyncDepthResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Public { 8 | 9 | struct Depth { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/public/depth"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto getAsync(Callback cb, const DepthRequest& request) noexcept -> void { 19 | static_assert( std::is_invocable_v ); 20 | auto result = getAsync(request); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto getAsync(const DepthRequest& request) noexcept -> AsyncDepthResponse { 26 | return std::async(std::launch::async, [&request](){return get(request);}); 27 | } 28 | 29 | template 30 | [[nodiscard]] static auto get(const DepthRequest& request) noexcept 31 | -> DepthResponse { 32 | auto rawResponse = Dispatcher()(uri(), request); 33 | return processResponse(std::move(rawResponse)); 34 | } 35 | 36 | static auto processResponse(json&& rawResponse) -> DepthResponse { 37 | DepthResponse depthResponse; 38 | depthResponse.statusCode_ = rawResponse["statusCode"].get(); 39 | depthResponse.errors_ = rawResponse["error"].get(); 40 | 41 | for (const auto& depth : rawResponse["result"]["bids"]) { 42 | auto p = std::make_pair(std::stold(depth[0].get()), 43 | std::stold(depth[1].get())); 44 | depthResponse.bids.push_back(std::move(p)); 45 | } 46 | 47 | for (const auto& depth : rawResponse["result"]["asks"]) { 48 | auto p = std::make_pair(std::stold(depth[0].get()), 49 | std::stold(depth[1].get())); 50 | depthResponse.asks.push_back(std::move(p)); 51 | } 52 | return depthResponse; 53 | } 54 | }; 55 | } // namespace Bitwyre::Rest::Public 56 | -------------------------------------------------------------------------------- /js/packages/public/src/index.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export async function getServerTime(baseUrl: string) { 4 | const uriPath: string = '/public/time'; 5 | 6 | return await axios.get(uriPath, { 7 | baseURL: baseUrl, 8 | }); 9 | } 10 | 11 | export async function getAssetPairs(baseUrl: string, market: string, product: string, country: string) { 12 | const uriPath: string = '/public/pairs'; 13 | 14 | return await axios.get(uriPath, { 15 | baseURL: baseUrl, 16 | params: { 17 | market, 18 | product, 19 | country, 20 | }, 21 | }); 22 | } 23 | 24 | export async function getTicker(baseUrl: string, instrument: string) { 25 | const uriPath: string = '/public/ticker'; 26 | 27 | return await axios.get(uriPath, { 28 | baseURL: baseUrl, 29 | params: { 30 | instrument, 31 | }, 32 | }); 33 | } 34 | 35 | export async function getTrades(baseUrl: string, tradeNum: number, instrument: string) { 36 | const uriPath: string = '/public/trades'; 37 | 38 | return await axios.get(uriPath, { 39 | baseURL: baseUrl, 40 | params: { 41 | instrument, 42 | trade_num: tradeNum, 43 | }, 44 | }); 45 | } 46 | 47 | export async function getDepth(baseUrl: string, instrument: string, depthNum: number) { 48 | const uriPath: string = '/public/depth'; 49 | 50 | return await axios.get(uriPath, { 51 | baseURL: baseUrl, 52 | params: { 53 | instrument, 54 | depth_num: depthNum, 55 | }, 56 | }); 57 | } 58 | 59 | export async function getAssets(baseUrl: string) { 60 | const uriPath: string = '/public/assets'; 61 | 62 | return await axios.get(uriPath, { 63 | baseURL: baseUrl, 64 | }); 65 | } 66 | 67 | export async function getMarkets(baseUrl: string) { 68 | const uriPath: string = '/public/markets'; 69 | 70 | return await axios.get(uriPath, { 71 | baseURL: baseUrl, 72 | }); 73 | } 74 | 75 | export async function getProducts(baseUrl: string) { 76 | const uriPath: string = '/public/products'; 77 | 78 | return await axios.get(uriPath, { 79 | baseURL: baseUrl, 80 | }); 81 | } 82 | 83 | export async function getAnnouncements(baseUrl: string) { 84 | const uriPath: string = '/public/announcements'; 85 | 86 | return await axios.get(uriPath, { 87 | baseURL: baseUrl, 88 | }); 89 | } 90 | -------------------------------------------------------------------------------- /js/packages/private/test/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | cancellingOpenOrderPerInstrument, 3 | getAccountBalance, 4 | getClosedOrders, 5 | getOpenOrders, 6 | getOrderInfo, 7 | getTradeHistory, 8 | getTransactionHistories, 9 | openingNewOrder, 10 | } from '../src'; 11 | import * as dotenv from 'dotenv'; 12 | 13 | dotenv.config({ path: `${__dirname}/../.env` }); 14 | 15 | describe('Private API Tests', () => { 16 | global.console = { 17 | ...console, 18 | log: jest.fn(), 19 | debug: jest.fn(), 20 | info: jest.fn(), 21 | warn: jest.fn(), 22 | error: jest.fn(), 23 | }; 24 | 25 | const BASE_URL = process.env.BASE_URL ?? ''; 26 | const API_KEY = process.env.API_KEY ?? ''; 27 | const SECRET_KEY = process.env.SECRET_KEY ?? ''; 28 | 29 | it('get account balance should return', async () => { 30 | // Arrange 31 | 32 | // Act 33 | const res = await getAccountBalance(BASE_URL, API_KEY, SECRET_KEY); 34 | 35 | // Assert 36 | expect(res.status).toEqual(200); 37 | expect(res.data.error.length).toEqual(0); 38 | }, 6000); 39 | 40 | it('get transaction histories should return', async () => { 41 | // Arrange 42 | 43 | // Act 44 | const res = await getTransactionHistories(BASE_URL, API_KEY, SECRET_KEY); 45 | 46 | // Assert 47 | expect(res.status).toEqual(200); 48 | expect(res.data.error.length).toEqual(0); 49 | }, 6000); 50 | 51 | it('get open orders should return', async () => { 52 | // Arrange 53 | 54 | // Act 55 | const res = await getOpenOrders(BASE_URL, API_KEY, SECRET_KEY); 56 | 57 | // Assert 58 | expect(res.status).toEqual(200); 59 | expect(res.data.error.length).toEqual(0); 60 | }, 6000); 61 | 62 | it('get closed orders should return', async () => { 63 | // Arrange 64 | 65 | // Act 66 | const res = await getClosedOrders(BASE_URL, API_KEY, SECRET_KEY); 67 | 68 | // Assert 69 | expect(res.status).toEqual(200); 70 | expect(res.data.error.length).toEqual(0); 71 | }, 6000); 72 | 73 | it('get trade history should return', async () => { 74 | // Arrange 75 | 76 | // Act 77 | const res = await getTradeHistory(BASE_URL, API_KEY, SECRET_KEY); 78 | 79 | // Assert 80 | expect(res.status).toEqual(200); 81 | expect(res.data.error.length).toEqual(0); 82 | }, 6000); 83 | }); 84 | -------------------------------------------------------------------------------- /rust/src/public/config.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | use mockito; 3 | 4 | pub fn url_api_bitwyre() -> String { 5 | #[cfg(test)] 6 | let url = mockito::server_url(); 7 | 8 | #[cfg(not(test))] 9 | let url = env!("API_URL").to_string(); 10 | 11 | return url; 12 | } 13 | 14 | pub fn timeout() -> u64 { 15 | return 5; 16 | } 17 | pub fn get_public_api_endpoint(key: &str) -> &str { 18 | match key { 19 | "SERVERTIME" => "/public/time", 20 | "TRADES" => "/public/trades", 21 | "TICKER" => "/public/ticker", 22 | "INSTRUMENT" => "/public/pairs", 23 | "DEPTH" => "/public/depth", 24 | "ANNOUNCEMENTS" => "/public/announcements", 25 | "PRODUCTS" => "/public/products", 26 | "MARKETS" => "/public/markets", 27 | "ASSETS" => "/public/assets", 28 | "ASSETS_CRYPTO" => "/public/assets/crypto", 29 | "ASSETS_FIAT" => "/public/assets/fiat", 30 | "CONTRACT" => "/public/contract", 31 | "INSIDER_PROFILES" => "/public/insider", 32 | "INSIDER_TRADES" => "/public/insider/trades", 33 | "ORDER_TYPES" => "/public/ordertypes", 34 | "LANGUAGES" => "/public/languages", 35 | "SEARCH" => "/public/search", 36 | "PRICE_INDEX" => "/public/index", 37 | "ORDER_LAG" => "/public/orderlag", 38 | "THROUGHPUT" => "/public/throughput", 39 | _ => "" 40 | } 41 | } 42 | pub fn get_private_api_endpoint(key: &str) -> &str { 43 | match key { 44 | "ACCOUNT_BALANCE" => "/private/account/spotbalance", 45 | "ACCOUNT_STATEMENT" => "/private/account/statement", 46 | "TRANSACTION_HISTORIES" => "/private/account/transactions", 47 | "ORDER" => "/private/orders", 48 | "CANCEL_ORDER" => "/private/orders/cancel", 49 | "OPEN_ORDERS" => "/private/orders/open", 50 | "CLOSED_ORDERS" => "/private/orders/closed", 51 | "ORDER_INFO" => "/private/orders/info", 52 | "TRADE_HISTORY" => "/private/trades", 53 | _ => "" 54 | } 55 | } 56 | pub fn bitwyre_instrument(key: &str) -> &str { 57 | match key { 58 | "1" => "btc_usdt_spot", 59 | "2" => "eth_usdt_spot", 60 | "3" => "usdt_idr_spot", 61 | "4" => "usdc_idr_spot", 62 | "5" => "usdc_usd_spot", 63 | "6" => "usdt_usd_spot", 64 | "7" => "btcusdtx_usdt_200607F1000000", 65 | _ => "" 66 | } 67 | } -------------------------------------------------------------------------------- /cpp/source/rest/public/Trades.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Details; 5 | using AsyncTradesResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Public { 8 | 9 | struct Trades { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/public/trades"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto getAsync(Callback cb, const TradesRequest& request) noexcept -> void { 19 | static_assert( std::is_invocable_v ); 20 | auto result = getAsync(request); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto getAsync(const TradesRequest& request) noexcept -> AsyncTradesResponse { 26 | return std::async(std::launch::async, [&request](){return get(request);}); 27 | } 28 | 29 | template 30 | [[nodiscard]] static auto get(const TradesRequest& tradesRequest) noexcept 31 | -> TradesResponse { 32 | auto rawResponse = Dispatcher()(uri(), tradesRequest); 33 | return processResponse(std::move(rawResponse)); 34 | } 35 | 36 | static auto processResponse(json&& rawResponse) -> TradesResponse { 37 | TradesResponse tradesResponse; 38 | tradesResponse.statusCode_ = rawResponse["statusCode"].get(); 39 | tradesResponse.errors_ = rawResponse["error"].get(); 40 | 41 | for (const auto& trade : rawResponse["result"]) { 42 | TradeElement tradeElement{}; 43 | tradeElement.instrument = trade["instrument"].get(); 44 | tradeElement.tradeUuid = trade["trade_uuid"].get(); 45 | tradeElement.price = std::stold(trade["price"].get()); 46 | tradeElement.value = std::stold(trade["price"].get()); 47 | tradeElement.volume = std::stold(trade["volume"].get()); 48 | tradeElement.timestamp = 49 | static_cast(trade["timestamp"].get()); 50 | tradesResponse.trades.push_back(std::move(tradeElement)); 51 | } 52 | return tradesResponse; 53 | } 54 | }; 55 | } // namespace Bitwyre::Rest::Public 56 | -------------------------------------------------------------------------------- /cpp/doc/doxygen/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | $projectname: $title 9 | $title 10 | 11 | 12 | 13 | 14 | 15 | 16 | $treeview 17 | $search 18 | $mathjax 19 | 20 | $extrastylesheet 21 | 22 | 23 |
24 |
25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 41 | 42 | 43 | 44 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 |
36 |
$projectname 37 |  $projectnumber 38 |
39 |
$projectbrief
40 |
45 |
$projectbrief
46 |
$searchbox
57 |
58 | 59 | 60 | -------------------------------------------------------------------------------- /cpp/source/details/Utils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "cryptopp/filters.h" 3 | #include "cryptopp/hex.h" 4 | #include "cryptopp/hmac.h" 5 | #include "cryptopp/sha.h" 6 | 7 | namespace Bitwyre { 8 | namespace Utils { 9 | 10 | inline static std::string lowercase(const std::string& data) { 11 | std::string res{}; 12 | for (auto& e : data) { 13 | if (!std::isdigit(e)) { 14 | res += std::tolower(e); 15 | } else { 16 | res += e; 17 | } 18 | } 19 | return res; 20 | } 21 | 22 | inline static std::string SHA256(const std::string& data) { 23 | CryptoPP::SHA256 hash{}; 24 | std::string digest; 25 | 26 | CryptoPP::StringSource stringSource{ 27 | data, 28 | /*dumpAll=*/true, 29 | new CryptoPP::HashFilter( 30 | hash, 31 | new CryptoPP::HexEncoder(new CryptoPP::StringSink(digest)))}; 32 | return digest; 33 | } 34 | 35 | inline static std::string HMAC(const std::string& data) { 36 | assert(std::getenv("BITWYRE_API_SECRET") != nullptr && "BITWYRE_API_SECRET NOT SET"); 37 | std::string encoded; 38 | std::string key = std::getenv("BITWYRE_API_SECRET"); 39 | std::string mac; 40 | try { 41 | CryptoPP::HMAC hmac((CryptoPP::byte*)key.c_str(), 42 | key.size()); 43 | CryptoPP::StringSource stringSource( 44 | data, 45 | true, 46 | new CryptoPP::HashFilter( 47 | hmac, 48 | new CryptoPP::StringSink(mac)) // HashFilter 49 | ); // StringSource 50 | } catch (const CryptoPP::Exception& e) { 51 | std::cerr << e.what() << "\n"; 52 | exit(1); 53 | } 54 | encoded.clear(); 55 | CryptoPP::StringSource stringSource( 56 | mac, 57 | true, 58 | new CryptoPP::HexEncoder( 59 | new CryptoPP::StringSink(encoded)) // HexEncoder 60 | ); // StringSource 61 | return encoded; 62 | } 63 | 64 | static auto getTimestamp() { 65 | return std::chrono::duration_cast( 66 | std::chrono::system_clock::now().time_since_epoch()) 67 | .count(); 68 | } 69 | 70 | static auto sign(std::string_view uri, std::uint64_t nonce, 71 | std::string checksum) -> std::string { 72 | auto nonceChecksum = SHA256(std::to_string(nonce) + checksum); 73 | auto dataToSign = std::string(uri.data()) + lowercase(nonceChecksum); 74 | return HMAC(dataToSign); 75 | } 76 | 77 | } // namespace Utils 78 | 79 | } // namespace Bitwyre -------------------------------------------------------------------------------- /cpp/source/rest/private/AccountBalance.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | using namespace Bitwyre::Types::Private; 4 | using namespace Bitwyre::Details; 5 | using AsyncAccountBalanceResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Private { 8 | using json = nlohmann::json; 9 | 10 | struct AccountBalance { 11 | 12 | using Callback = std::function; 13 | 14 | [[nodiscard]] static auto uri() noexcept -> std::string { 15 | return "/private/account/spotbalance"; 16 | } 17 | 18 | template 19 | [[nodiscard]] static auto getAsync(Callback cb, const AccountBalanceRequest& request) noexcept -> void { 20 | static_assert( std::is_invocable_v); 21 | auto result = getAsync(request); 22 | return cb(result.get()); 23 | } 24 | 25 | template 26 | [[nodiscard]] static auto getAsync(const AccountBalanceRequest& request) noexcept 27 | -> AsyncAccountBalanceResponse { 28 | return std::async(std::launch::async, [&request](){return get(request);}); 29 | } 30 | 31 | template 32 | [[nodiscard]] static auto get(const AccountBalanceRequest& request) noexcept 33 | -> AccountBalanceResponse { 34 | auto rawResponse = Dispatcher()(uri().data(), request); 35 | return processResponse(std::move(rawResponse)); 36 | } 37 | 38 | static auto processResponse(json&& rawResponse) -> AccountBalanceResponse { 39 | AccountBalanceResponse accountBalanceResponse; 40 | accountBalanceResponse.statusCode_ = rawResponse["statusCode"].get(); 41 | accountBalanceResponse.errors_ = rawResponse["error"].get(); 42 | 43 | for (const auto& rawBalance : rawResponse["result"]) { 44 | AccountBalanceElement balanceElement; 45 | balanceElement.asset = rawBalance["asset"].get(); 46 | balanceElement.localReference = 47 | rawBalance["local_reference"].get(); 48 | balanceElement.availableBalance = 49 | rawBalance["available_balance"].get(); 50 | balanceElement.btcEquivalent = 51 | rawBalance["btc_equivalent"].get(); 52 | balanceElement.localEquivalent = 53 | rawBalance["local_equivalent"].get(); 54 | balanceElement.lockedBalance = 55 | rawBalance["locked_balance"].get(); 56 | balanceElement.totalBalance = 57 | rawBalance["total_balance"].get(); 58 | accountBalanceResponse.balances.push_back(std::move(balanceElement)); 59 | } 60 | return accountBalanceResponse; 61 | } 62 | }; 63 | } // namespace Bitwyre::Rest::Private -------------------------------------------------------------------------------- /java/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 4.0.0 6 | 7 | com.bitwyre.sdk 8 | java_sdk 9 | 1.0-SNAPSHOT 10 | 11 | java_sdk 12 | 13 | http://www.example.com 14 | 15 | 16 | UTF-8 17 | 1.7 18 | 1.7 19 | 20 | 21 | 22 | 23 | junit 24 | junit 25 | 4.13.1 26 | test 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | maven-clean-plugin 36 | 3.1.0 37 | 38 | 39 | 40 | maven-resources-plugin 41 | 3.0.2 42 | 43 | 44 | maven-compiler-plugin 45 | 3.8.0 46 | 47 | 48 | maven-surefire-plugin 49 | 2.22.1 50 | 51 | 52 | maven-jar-plugin 53 | 3.0.2 54 | 55 | 56 | maven-install-plugin 57 | 2.5.2 58 | 59 | 60 | maven-deploy-plugin 61 | 2.8.2 62 | 63 | 64 | 65 | maven-site-plugin 66 | 3.7.1 67 | 68 | 69 | maven-project-info-reports-plugin 70 | 3.0.0 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /cpp/doc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This CMake file will add doc target for convenient documentation generation. 2 | # 3 | # Additional features are supported: 4 | # * dot = for automatically generated UML diagrams (class, include, caller, call, collaboration) 5 | # * PlantUML = for easy generation of custom diagrams 6 | 7 | # Helper functions 8 | macro(path_linux_to_win MsysPath ResultingPath) 9 | string(REGEX REPLACE "^/([a-zA-Z])/" "\\1:/" ${ResultingPath} "${MsysPath}") 10 | endmacro() 11 | macro(path_win_to_linux MsysPath ResultingPath) 12 | string(REGEX REPLACE "^([a-zA-Z]):/" "/\\1/" ${ResultingPath} "${MsysPath}") 13 | endmacro() 14 | 15 | # enable if doxygen found 16 | find_package(Doxygen 1.8.0) 17 | message(STATUS "Can build doc? ${DOXYGEN_FOUND}") 18 | if(DOXYGEN_FOUND) 19 | # Search for plantUML for creating UML diagrams from doxygen 20 | find_program(PLANT_UML_PATH plantuml.jar PATH_SUFFIXES PlantUML plantuml Plantuml 21 | PATHS /usr/share /usr/local/share/ /usr/local/bin c/Program\ Files* ) 22 | if(NOT PLANT_UML_PATH) 23 | message(WARNING "Looking for PlantUML - not found, some UML diagrams will not be generated via doxygen.") 24 | else() 25 | message(STATUS " + PlantUML - for custom UML YES ") 26 | endif() 27 | 28 | #Search for DOT for autogenerated UML diagrams from doxygen 29 | find_program(DOT_PATH dot PATH_SUFFIXES graphviz2.38/bin graphviz/bin) 30 | if(NOT DOT_PATH) 31 | message(WARNING "Looking for DOT (Graphviz) - not found, some UML diagrams will not be generated via doxygen.") 32 | else() 33 | message(STATUS " + Graphviz/Dot - for generated graphs YES ") 34 | endif() 35 | 36 | path_win_to_linux(${CMAKE_CURRENT_SOURCE_DIR} CMAKE_CURRENT_SOURCE_DIR_LINUX) 37 | path_win_to_linux(${PROJECT_SOURCE_DIR} PROJECT_SOURCE_DIR_LINUX) 38 | path_win_to_linux(${DOT_PATH} DOT_PATH_LINUX) 39 | path_win_to_linux(${PLANT_UML_PATH} PLANT_UML_PATH_LINUX) 40 | path_win_to_linux(${CMAKE_CURRENT_BINARY_DIR} CMAKE_CURRENT_BINARY_DIR_LINUX) 41 | 42 | # configure doxygen configuration file 43 | set(doxyfile_in ${CMAKE_CURRENT_SOURCE_DIR}/doxygen/Doxyfile.in) 44 | set(doxyfile ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) 45 | configure_file(${doxyfile_in} ${doxyfile} @ONLY) 46 | 47 | # doc build only target, target is not in default build, so it must be 48 | # triggered explicitly 49 | add_custom_target(doc 50 | COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile} 51 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 52 | COMMENT "Generating API documentation with Doxygen" 53 | VERBATIM) 54 | 55 | # Where docs will be installed. 56 | # Note: if docs shall be not a part of final release, leave this commented out 57 | # docs will be only available in [build_dir]/doc/doc/index.html 58 | # install( 59 | # DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/ 60 | # DESTINATION share/doc/${PROJECT_NAME} 61 | # OPTIONAL) 62 | endif() 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /cpp/source/rest/public/Contract.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Details; 5 | using AsyncContractResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Public { 8 | 9 | struct Contract { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/public/contract"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto getAsync(Callback cb, const ContractRequest& request) noexcept -> void { 19 | static_assert( std::is_invocable_v ); 20 | auto result = getAsync(request); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto getAsync(const ContractRequest& request) noexcept -> AsyncContractResponse { 26 | return std::async(std::launch::async, [&request](){return get(request);}); 27 | } 28 | 29 | template 30 | [[nodiscard]] static auto get(const ContractRequest& request) noexcept 31 | -> ContractResponse { 32 | auto rawResponse = Dispatcher()(uri(), request); 33 | return processResponse(std::move(rawResponse)); 34 | } 35 | 36 | static auto processResponse(json&& rawResponse) -> ContractResponse { 37 | ContractResponse contractResponse; 38 | contractResponse.statusCode_ = rawResponse["statusCode"].get(); 39 | contractResponse.errors_ = rawResponse["error"].get(); 40 | auto contract = rawResponse["result"]; 41 | contractResponse.instrument = contract["instrument"].get(); 42 | contractResponse.details = contract["details"].get(); 43 | contractResponse.pricingSource = 44 | contract["pricing_source"].get(); 45 | contractResponse.bitwyreIndexPrice = 46 | std::stold(contract["bitwyre_index_price"].get()); 47 | contractResponse.bitwyreIndexPriceCurrency = 48 | contract["bitwyre_index_price_currency"].get(); 49 | contractResponse.volume24h = 50 | std::stold(contract["24h_volume"].get()); 51 | contractResponse.volume24hCurrency = 52 | contract["24h_volume_currency"].get(); 53 | contractResponse.openInterest = 54 | contract["open_interest"].get(); 55 | contractResponse.interestRate = 56 | contract["interest_rate"].get(); 57 | contractResponse.contractValue = 58 | contract["contract_value"].get(); 59 | contractResponse.initialMarginBaseValue = 60 | contract["initial_margin_base_value"].get(); 61 | contractResponse.maintenanceMarginBaseValue = 62 | contract["maintenance_margin_base_value"].get(); 63 | return contractResponse; 64 | } 65 | }; 66 | } // namespace Bitwyre::Rest::Public 67 | -------------------------------------------------------------------------------- /kotlin/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /js/packages/public/test/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | getAnnouncements, 3 | getAssetPairs, 4 | getAssets, 5 | getDepth, 6 | getMarkets, 7 | getProducts, 8 | getServerTime, 9 | getTicker, 10 | getTrades, 11 | } from '../src'; 12 | import * as dotenv from 'dotenv'; 13 | 14 | dotenv.config({ path: `${__dirname}/../.env` }); 15 | 16 | describe('Public API Tests', () => { 17 | global.console = { 18 | ...console, 19 | log: jest.fn(), 20 | debug: jest.fn(), 21 | info: jest.fn(), 22 | warn: jest.fn(), 23 | error: jest.fn(), 24 | }; 25 | 26 | const BASE_URL = process.env.BASE_URL ?? ''; 27 | 28 | it('get server time should return', async () => { 29 | // Arrange 30 | 31 | // Act 32 | const res = await getServerTime(BASE_URL); 33 | 34 | // Assert 35 | expect(res.status).toEqual(200); 36 | expect(res.data.error.length).toEqual(0); 37 | }, 2000); 38 | 39 | it('get asset pairs should return', async () => { 40 | // Arrange 41 | 42 | // Act 43 | const res = await getAssetPairs(BASE_URL, 'market', 'product', 'country'); 44 | 45 | // Assert 46 | expect(res.status).toEqual(200); 47 | expect(res.data.error.length).toEqual(0); 48 | }, 2000); 49 | 50 | it('get ticker should return', async () => { 51 | // Arrange 52 | 53 | // Act 54 | const res = await getTicker(BASE_URL, 'btc_idr_spot'); 55 | 56 | // Assert 57 | expect(res.status).toEqual(200); 58 | expect(res.data.error.length).toEqual(0); 59 | }, 2000); 60 | 61 | it('get trades should return', async () => { 62 | // Arrange 63 | 64 | // Act 65 | const res = await getTrades(BASE_URL, 1, 'btc_idr_spot'); 66 | 67 | // Assert 68 | expect(res.status).toEqual(200); 69 | expect(res.data.error.length).toEqual(0); 70 | }, 2000); 71 | 72 | it('get depth should return', async () => { 73 | // Arrange 74 | 75 | // Act 76 | const res = await getDepth(BASE_URL, 'btc_idr_spot', 1); 77 | 78 | // Assert 79 | expect(res.status).toEqual(200); 80 | expect(res.data.error.length).toEqual(0); 81 | }, 2000); 82 | 83 | it('get assets should return', async () => { 84 | // Arrange 85 | 86 | // Act 87 | const res = await getAssets(BASE_URL); 88 | 89 | // Assert 90 | expect(res.status).toEqual(200); 91 | expect(res.data.error.length).toEqual(0); 92 | }, 2000); 93 | 94 | it('get markets should return', async () => { 95 | // Arrange 96 | 97 | // Act 98 | const res = await getMarkets(BASE_URL); 99 | 100 | // Assert 101 | expect(res.status).toEqual(200); 102 | expect(res.data.error.length).toEqual(0); 103 | }, 2000); 104 | 105 | it('get products should return', async () => { 106 | // Arrange 107 | 108 | // Act 109 | const res = await getProducts(BASE_URL); 110 | 111 | // Assert 112 | expect(res.status).toEqual(200); 113 | expect(res.data.error.length).toEqual(0); 114 | }, 2000); 115 | 116 | it('get announcements should return', async () => { 117 | // Arrange 118 | 119 | // Act 120 | const res = await getAnnouncements(BASE_URL); 121 | 122 | // Assert 123 | expect(res.status).toEqual(200); 124 | expect(res.data.error.length).toEqual(0); 125 | }, 2000); 126 | }); 127 | -------------------------------------------------------------------------------- /cpp/cmake/cleanCppExtensions.cmake: -------------------------------------------------------------------------------- 1 | # Helper macro for creating convenient targets 2 | find_program(GDB_PATH gdb) 3 | 4 | # Adds -run and -dbg targets 5 | macro(addRunAndDebugTargets TARGET) 6 | add_custom_target(${TARGET}-run 7 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 8 | USES_TERMINAL 9 | DEPENDS ${TARGET} 10 | COMMAND ./${TARGET}) 11 | 12 | # convenience run gdb target 13 | if(GDB_PATH) 14 | add_custom_target(${TARGET}-gdb 15 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 16 | USES_TERMINAL 17 | DEPENDS ${TARGET} 18 | COMMAND ${GDB_PATH} ./${TARGET}) 19 | endif() 20 | endmacro() 21 | 22 | #------------------------------------------------------------------------------ 23 | # Other MISC targets - formatting, static analysis 24 | # format, cppcheck, tidy 25 | macro(addMiscTargets) 26 | file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.cc *.c) 27 | file(GLOB_RECURSE ALL_HEADER_FILES *.h *.hpp) 28 | 29 | # Static analysis via clang-tidy target 30 | # We check for program, since when it is not here, target makes no sense 31 | find_program(TIDY_PATH clang-tidy PATHS /usr/local/Cellar/llvm/*/bin) 32 | if(TIDY_PATH) 33 | message(STATUS "clang-tidy - static analysis YES ") 34 | add_custom_target(tidy 35 | COMMAND ${TIDY_PATH} -header-filter=.* ${ALL_SOURCE_FILES} -p=./ ) 36 | else() 37 | message(STATUS "clang-tidy - static analysis NO ") 38 | endif() 39 | 40 | # cpp check static analysis 41 | find_program(CPPCHECK_PATH cppcheck) 42 | if(CPPCHECK_PATH) 43 | message(STATUS "cppcheck - static analysis YES ") 44 | add_custom_target( 45 | cppcheck 46 | COMMAND ${CPPCHECK_PATH} 47 | --enable=warning,performance,portability,information,missingInclude 48 | --std=c++11 49 | --template=gcc 50 | --verbose 51 | --quiet 52 | ${ALL_SOURCE_FILES} 53 | ) 54 | else() 55 | message(STATUS "cppcheck - static analysis NO ") 56 | endif() 57 | 58 | # run clang-format on all files 59 | find_program(FORMAT_PATH clang-format) 60 | if(FORMAT_PATH) 61 | message(STATUS "clang-format - code formating YES ") 62 | add_custom_target(format 63 | COMMAND ${FORMAT_PATH} -i ${ALL_SOURCE_FILES} ${ALL_HEADER_FILES} ) 64 | else() 65 | message(STATUS "clang-format - code formating NO ") 66 | endif() 67 | endmacro() 68 | 69 | #------------------------------------------------------------------------------ 70 | # Force compilers, this was deprecated in CMake, but still comes handy sometimes 71 | macro(FORCE_C_COMPILER compiler id) 72 | set(CMAKE_C_COMPILER "${compiler}") 73 | set(CMAKE_C_COMPILER_ID_RUN TRUE) 74 | set(CMAKE_C_COMPILER_ID ${id}) 75 | set(CMAKE_C_COMPILER_FORCED TRUE) 76 | 77 | # Set old compiler id variables. 78 | if(CMAKE_C_COMPILER_ID MATCHES "GNU") 79 | set(CMAKE_COMPILER_IS_GNUCC 1) 80 | endif() 81 | endmacro() 82 | 83 | macro(FORCE_CXX_COMPILER compiler id) 84 | set(CMAKE_CXX_COMPILER "${compiler}") 85 | set(CMAKE_CXX_COMPILER_ID_RUN TRUE) 86 | set(CMAKE_CXX_COMPILER_ID ${id}) 87 | set(CMAKE_CXX_COMPILER_FORCED TRUE) 88 | 89 | # Set old compiler id variables. 90 | if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") 91 | set(CMAKE_COMPILER_IS_GNUCXX 1) 92 | endif() 93 | endmacro() 94 | -------------------------------------------------------------------------------- /websocket_python/websocket_python_sdk/public.py: -------------------------------------------------------------------------------- 1 | import json 2 | import websocket 3 | 4 | from websocket import WebSocket 5 | 6 | from utils import ( 7 | BASE_URL, 8 | PRINT_DEBUGS, 9 | parse_codes 10 | ) 11 | 12 | subscription_message = { 13 | "op": "subscribe", 14 | "args": None 15 | } 16 | 17 | class PublicBitwyreWSClient: 18 | def __init__( 19 | self, 20 | url:str = BASE_URL, 21 | debugs:str = PRINT_DEBUGS 22 | ): 23 | websocket.enableTrace(debugs) 24 | self.url = url 25 | self.ws = websocket.WebSocket() 26 | 27 | def close(self): 28 | self.ws.close() 29 | 30 | def connect(self, url) -> WebSocket: 31 | print(f"opening ws connection to {url}") 32 | self.ws.connect(url) 33 | print("ws connection success") 34 | return self.ws 35 | 36 | def send_message(self, message: dict): 37 | print(f"sending message {message}") 38 | message = json.dumps(message) 39 | 40 | self.ws.send(message) 41 | print("sending message success") 42 | 43 | def receive_conn(self): 44 | status_code, response, error_code, error_msg = self.ws.recv() 45 | success, response, error_code, error_msg = parse_codes(status_code, response, error_code, error_msg) 46 | 47 | return success, response, error_code, error_msg 48 | 49 | def server_time(self) -> WebSocket: 50 | uri = "/ws/public/time" 51 | return self.connect(self.url+uri) 52 | 53 | def instruments( 54 | self, 55 | instrument:str 56 | ) -> WebSocket: 57 | uri = f"/ws/stream?subscribe=instruments:{instrument}" 58 | 59 | subscribe = subscription_message 60 | subscribe["args"] = [f"instruments:{instrument}"] 61 | 62 | self.connect(self.url+uri) 63 | self.send_message(subscribe) 64 | 65 | return self.ws 66 | 67 | def ticker( 68 | self, 69 | instrument:str 70 | ) -> WebSocket: 71 | uri = f"/ws/stream?subscribe=ticker:{instrument}" 72 | 73 | subscribe = subscription_message 74 | subscribe["args"] = [f"ticker:{instrument}"] 75 | 76 | self.connect(self.url+uri) 77 | 78 | self.send_message(subscribe) 79 | 80 | return self.ws 81 | 82 | def trades( 83 | self, 84 | instrument:str 85 | ) -> WebSocket: 86 | uri = f"/ws/stream?subscribe=trades:{instrument}" 87 | 88 | subscribe = subscription_message 89 | subscribe["args"] = [f"trades:{instrument}"] 90 | 91 | self.connect(self.url+uri) 92 | 93 | self.send_message(subscribe) 94 | 95 | return self.ws 96 | 97 | def depth_l2( 98 | self, 99 | instrument:str 100 | ) -> WebSocket: 101 | uri = f"/ws/stream?subscribe=depthL2:{instrument}" 102 | 103 | subscribe = subscription_message 104 | subscribe["args"] = [f"depthL2:{instrument}"] 105 | 106 | self.connect(self.url+uri) 107 | 108 | self.send_message(subscribe) 109 | 110 | return self.ws 111 | 112 | def depth_l2_snapshot25( 113 | self, 114 | instrument:str 115 | ) -> WebSocket: 116 | uri = f"/ws/stream?subscribe=depthL2_25:{instrument}" 117 | 118 | subscribe = subscription_message 119 | subscribe["args"] = [f"depthL2_25:{instrument}"] 120 | 121 | self.connect(self.url+uri) 122 | 123 | self.send_message(subscribe) 124 | 125 | return self.ws -------------------------------------------------------------------------------- /cpp/source/rest/private/TradesHistory.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Types::Private; 5 | using AsyncResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Private { 8 | 9 | struct TradesHistory { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/private/trades"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto getAsync(Callback cb, const TradesHistoryRequest& request) noexcept -> void { 19 | static_assert( std::is_invocable_v); 20 | auto result = getAsync(request); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto getAsync(const TradesHistoryRequest& request) noexcept 26 | -> AsyncResponse { 27 | return std::async(std::launch::async, [&request](){return get(request);}); 28 | } 29 | 30 | template 31 | [[nodiscard]] static auto get(const TradesHistoryRequest& request) noexcept 32 | -> Response { 33 | auto rawResponse = Dispatcher()(uri(), request); 34 | return processResponse(std::move(rawResponse)); 35 | } 36 | 37 | static auto processResponse(json&& rawResponse) -> TradesHistoryResponse { 38 | TradesHistoryResponse tradesHistoryResponse; 39 | tradesHistoryResponse.statusCode_ = rawResponse["statusCode"].get(); 40 | tradesHistoryResponse.errors_ = rawResponse["error"].get(); 41 | 42 | for (auto it = rawResponse["result"].cbegin(); 43 | it != rawResponse["result"].cend(); 44 | ++it) { 45 | std::vector trades; 46 | 47 | for (const auto& trade : it.value()) { 48 | TradesHistoryElement thistoryElmt; 49 | thistoryElmt.execPrice = trade["exec_price"].get(); 50 | thistoryElmt.execQty = trade["exec_qty"].get(); 51 | thistoryElmt.execValue = trade["exec_value"].get(); 52 | thistoryElmt.feePaid = trade["fee_paid"].get(); 53 | thistoryElmt.feeRate = trade["fee_rate"].get(); 54 | thistoryElmt.feeRate = trade["fee_rate"].get(); 55 | thistoryElmt.feeType = trade["fee_type"].get(); 56 | thistoryElmt.notes = trade["notes"].get(); 57 | thistoryElmt.orderUuid = trade["order_uuid"].get(); 58 | thistoryElmt.symbol = trade["symbol"].get(); 59 | thistoryElmt.userUuid = trade["user_uuid"].get(); 60 | 61 | thistoryElmt.orderPrice = trade["order_price"].get(); 62 | thistoryElmt.orderQty = trade["order_qty"].get(); 63 | thistoryElmt.orderRemaining = 64 | trade["order_remaining"].get(); 65 | thistoryElmt.orderType = trade["order_type"].get(); 66 | thistoryElmt.side = trade["side"].get(); 67 | thistoryElmt.status = trade["status"].get(); 68 | thistoryElmt.timestamp = static_cast( 69 | trade["timestamp"].get()); 70 | 71 | trades.push_back(std::move(thistoryElmt)); 72 | } 73 | 74 | tradesHistoryResponse.histories.push_back( 75 | std::make_pair(it.key(), std::move(trades))); 76 | } 77 | return tradesHistoryResponse; 78 | } 79 | }; 80 | } // namespace Bitwyre::Rest::Private -------------------------------------------------------------------------------- /cpp/source/unittest/MockDispatcher.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "details/Types.hpp" 3 | #include "nlohmann/json.hpp" 4 | #include "gmock/gmock.h" 5 | 6 | using ::testing::AtLeast; 7 | using json = nlohmann::json; 8 | using namespace Bitwyre::Types::Public; 9 | using namespace Bitwyre::Types::Private; 10 | 11 | class MockDispatcher { 12 | public: 13 | MOCK_METHOD(json, dispatch, (std::string_view uri, CommonPublicRequest)); 14 | MOCK_METHOD(json, dispatch, (std::string_view uri, InstrumentRequest)); 15 | MOCK_METHOD(json, dispatch, (std::string_view uri, TickerRequest)); 16 | MOCK_METHOD(json, dispatch, (std::string_view uri, TradesRequest)); 17 | MOCK_METHOD(json, dispatch, (std::string_view uri, DepthRequest)); 18 | MOCK_METHOD(json, dispatch, (std::string_view uri, ContractRequest)); 19 | MOCK_METHOD(json, dispatch, (std::string_view uri, AccountBalanceRequest)); 20 | MOCK_METHOD(json, dispatch, (std::string_view uri, AccountStatementRequest)); 21 | MOCK_METHOD(json, dispatch, (std::string_view uri, CancelOrderRequest)); 22 | MOCK_METHOD(json, dispatch, (std::string_view uri, ClosedOrdersRequest)); 23 | MOCK_METHOD(json, dispatch, (std::string_view uri, OpenOrdersRequest)); 24 | MOCK_METHOD(json, dispatch, (std::string_view uri, OrderInfoRequest)); 25 | MOCK_METHOD(json, dispatch, (std::string_view uri, TradesHistoryRequest)); 26 | MOCK_METHOD(json, dispatch, (std::string_view uri, NewOrderRequest)); 27 | MOCK_METHOD(json, dispatch, 28 | (std::string_view uri, TransactionHistoryRequest)); 29 | 30 | auto operator()(std::string_view uri, CommonPublicRequest commonPublicRequest) 31 | -> json { 32 | return dispatch(uri, commonPublicRequest); 33 | } 34 | 35 | auto operator()(std::string_view uri, InstrumentRequest instrumentRequest) 36 | -> json { 37 | return dispatch(uri, instrumentRequest); 38 | } 39 | 40 | auto operator()(std::string_view uri, TickerRequest tickerRequest) -> json { 41 | return dispatch(uri, tickerRequest); 42 | } 43 | 44 | auto operator()(std::string_view uri, TradesRequest tickerRequest) -> json { 45 | return dispatch(uri, tickerRequest); 46 | } 47 | 48 | auto operator()(std::string_view uri, DepthRequest depthRequest) -> json { 49 | return dispatch(uri, depthRequest); 50 | } 51 | 52 | auto operator()(std::string_view uri, ContractRequest contractRequest) 53 | -> json { 54 | return dispatch(uri, contractRequest); 55 | } 56 | 57 | // Private endpoints mocks 58 | 59 | auto operator()(std::string_view uri, 60 | AccountBalanceRequest accountBalanceRequest) -> json { 61 | return dispatch(uri, accountBalanceRequest); 62 | } 63 | 64 | auto operator()(std::string_view uri, 65 | AccountStatementRequest accountStatementRequest) -> json { 66 | return dispatch(uri, accountStatementRequest); 67 | } 68 | 69 | auto operator()(std::string_view uri, CancelOrderRequest cancelOrderRequest) 70 | -> json { 71 | return dispatch(uri, cancelOrderRequest); 72 | } 73 | 74 | auto operator()(std::string_view uri, ClosedOrdersRequest closedOrdersRequest) 75 | -> json { 76 | return dispatch(uri, closedOrdersRequest); 77 | } 78 | 79 | auto operator()(std::string_view uri, OpenOrdersRequest closedOrdersRequest) 80 | -> json { 81 | return dispatch(uri, closedOrdersRequest); 82 | } 83 | 84 | auto operator()(std::string_view uri, OrderInfoRequest orderInfoRequest) 85 | -> json { 86 | return dispatch(uri, orderInfoRequest); 87 | } 88 | 89 | auto operator()(std::string_view uri, 90 | TradesHistoryRequest tradesHistoryRequest) -> json { 91 | return dispatch(uri, tradesHistoryRequest); 92 | } 93 | 94 | auto operator()(std::string_view uri, NewOrderRequest newOrderRequest) 95 | -> json { 96 | return dispatch(uri, newOrderRequest); 97 | } 98 | 99 | auto operator()(std::string_view uri, TransactionHistoryRequest request) 100 | -> json { 101 | return dispatch(uri, request); 102 | } 103 | }; -------------------------------------------------------------------------------- /cpp/source/rest/private/NewOrder.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Types::Private; 5 | using AsyncNewOrderResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Private { 8 | 9 | struct NewOrder { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/private/orders"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto postAsync(Callback cb, const NewOrderRequest& request) noexcept -> void { 19 | static_assert( std::is_invocable_v); 20 | auto result = postAsync(request); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto postAsync(const NewOrderRequest& request) noexcept 26 | -> AsyncNewOrderResponse { 27 | return std::async(std::launch::async, [&request](){return post(request);}); 28 | } 29 | 30 | template 31 | [[nodiscard]] static auto post(const NewOrderRequest& request) noexcept 32 | -> NewOrderResponse { 33 | auto rawResponse = Dispatcher()(uri(), request); 34 | return processResponse(std::move(rawResponse)); 35 | } 36 | 37 | static auto processResponse(json&& rawResponse) -> NewOrderResponse { 38 | NewOrderResponse executionReport; 39 | auto res = rawResponse["result"]; 40 | executionReport.avgPx = std::stold(res["AvgPx"].get()); 41 | executionReport.lastLiquidityInd = 42 | std::stold(res["LastLiquidityInd"].get()); 43 | executionReport.lastPx = std::stold(res["LastPx"].get()); 44 | executionReport.lastQty = std::stold(res["LastQty"].get()); 45 | executionReport.cumQty = std::stold(res["cumqty"].get()); 46 | executionReport.fillPrice = 47 | std::stold(res["fill_price"].get()); 48 | executionReport.leavesQty = 49 | std::stold(res["leavesqty"].get()); 50 | executionReport.orderQty = std::stold(res["orderqty"].get()); 51 | executionReport.price = std::stold(res["price"].get()); 52 | executionReport.stopPx = std::stold(res["stoppx"].get()); 53 | executionReport.value = std::stold(res["value"].get()); 54 | if (res["ordrejreason"].get().size()) { 55 | executionReport.ordRejReason = 56 | std::stold(res["ordrejreason"].get()); 57 | } else { 58 | executionReport.ordRejReason = 0; 59 | } 60 | 61 | executionReport.ordStatusReqId = res["ordstatusReqID"].get(); 62 | executionReport.origcliId = res["origclid"].get(); 63 | executionReport.account = res["account"].get(); 64 | executionReport.clOrdId = res["clorderid"].get(); 65 | executionReport.instrument = res["instrument"].get(); 66 | executionReport.orderId = res["orderid"].get(); 67 | 68 | executionReport.ordStatus = res["ordstatus"].get(); 69 | executionReport.ordType = res["ordtype"].get(); 70 | executionReport.timeInForce = res["time_in_force"].get(); 71 | 72 | executionReport.execId = res["execid"].get(); 73 | executionReport.execType = res["exectype"].get(); 74 | executionReport.expiry = res["expiry"].get(); 75 | executionReport.side = res["side"].get(); 76 | 77 | executionReport.timestamp = 78 | static_cast(res["timestamp"].get()); 79 | executionReport.transactTime = 80 | static_cast(res["transacttime"].get()); 81 | 82 | executionReport.cancelOnDisconnect = 83 | static_cast(res["cancelondisconnect"].get()); 84 | 85 | return executionReport; 86 | } 87 | }; 88 | 89 | } // namespace Bitwyre::Rest::Private -------------------------------------------------------------------------------- /cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.6) 2 | 3 | # Project setup, versioning stuff here, change when changing the version 4 | # Note: keep the project name lower case only for easy linux packaging support 5 | project (bitwyresdk VERSION 0.3.5) 6 | set(VERSION_TYPE "beta" CACHE STRING "version type" FORCE) 7 | site_name(VERSION_HOST) # read hostname to VERSION_HOST 8 | set(VERSION_HOST "${VERSION_HOST}" CACHE STRING "host of build" FORCE) 9 | 10 | message(STATUS "") 11 | message(STATUS " == ${PROJECT_NAME} Project configuration ==") 12 | message(STATUS "") 13 | 14 | #------------------------------------------------------------------------------ 15 | # General settings 16 | 17 | # Be nice to visual studio 18 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 19 | 20 | # Be nice and export compile commands by default, this is handy for clang-tidy 21 | # and for other tools. 22 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 23 | 24 | # We can use include() and find_package() for our scripts in there 25 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) 26 | 27 | # Use gold linker to speed up linking time, see cmake/useGoldLinker.cmake 28 | include(useGoldLinker) 29 | 30 | # Helpful option enable build profiling to identify slowly compiling files 31 | option(MEASURE_ALL "When enabled all commands will be passed through time command" OFF) 32 | if(MEASURE_ALL) 33 | set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "time") 34 | endif() 35 | 36 | #------------------------------------------------------------------------------- 37 | # Set default install location to dist folder in build dir 38 | # we do not want to install to /usr by default 39 | if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 40 | set (CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/dist" CACHE PATH 41 | "Install path prefix, prepended onto install directories." FORCE ) 42 | endif() 43 | #------------------------------------------------------------------------------ 44 | # Custom Install target, used in run target in source/CMakeLists.txt 45 | if (CMAKE_GENERATOR MATCHES "Makefiles") 46 | # Make it multithreaded 47 | add_custom_target( Install_ COMMAND "${CMAKE_COMMAND}" --build . --target 48 | install -- -j WORKING_DIRECTORY "${CMAKE_BINARY_DIR}") 49 | else() 50 | add_custom_target( Install_ COMMAND "${CMAKE_COMMAND}" --build . --target 51 | install WORKING_DIRECTORY "${CMAKE_BINARY_DIR}") 52 | endif() 53 | 54 | #------------------------------------------------------------------------------ 55 | # General settings 56 | 57 | #----Running conan install directly from CMakeLists 58 | 59 | include(cmake/conan.cmake) 60 | conan_add_remote(NAME bitwyre 61 | INDEX 1 62 | URL https://conan.bitwyre.id/artifactory/api/conan/bitwyre 63 | VERIFY_SSL True) 64 | 65 | conan_cmake_run(CONANFILE conanfile.py 66 | BASIC_SETUP CMAKE_TARGETS 67 | BUILD missing 68 | ) 69 | 70 | message(INFO ${CMAKE_BINARY_DIR}) 71 | include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) 72 | conan_basic_setup() 73 | 74 | #------------------------------------------------------------------------------ 75 | # Included CMakeLists.txt 76 | 77 | # Documentation build 78 | if(BITWYRE_INSTALL_DOCS) 79 | add_subdirectory(doc) 80 | add_subdirectory(data) 81 | endif() 82 | 83 | # Testing 84 | option(UNIT_TESTS "When enabled will compile with the unittests" OFF) 85 | if (UNIT_TESTS) 86 | enable_testing() 87 | add_subdirectory(test) 88 | endif () 89 | 90 | # Source code 91 | add_subdirectory(source) 92 | 93 | #------------------------------------------------------------------------------- 94 | # Wrap up of settings printed on build 95 | message(STATUS "") 96 | message(STATUS " == Final overview for ${PROJECT_NAME} ==") 97 | message(STATUS "Version: ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} ${VERSION_TYPE} @ ${VERSION_HOST}") 98 | message(STATUS "Install prefix: ${CMAKE_INSTALL_PREFIX}") 99 | message(STATUS "Compiler: ${CMAKE_CXX_COMPILER}") 100 | message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") 101 | message(STATUS " possible options: Debug Release RelWithDebInfo MinSizeRel") 102 | message(STATUS " set with ` cmake -DCMAKE_BUILD_TYPE=Debug .. `") 103 | message(STATUS "") 104 | 105 | 106 | -------------------------------------------------------------------------------- /cpp/source/rest/private/TransactionHistory.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Types::Private; 5 | using AsyncTransactionHistoryResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Private { 8 | 9 | struct TransactionHistory { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/private/account/transactions"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto getAsync(Callback cb, const TransactionHistoryRequest& request) noexcept -> void { 19 | static_assert( std::is_invocable_v); 20 | auto result = getAsync(request); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto getAsync(const TransactionHistoryRequest& request) noexcept 26 | -> AsyncTransactionHistoryResponse { 27 | return std::async(std::launch::async, [&request](){return get(request);}); 28 | } 29 | 30 | template 31 | [[nodiscard]] static auto get(const TransactionHistoryRequest& request) noexcept 32 | -> TransactionHistoryResponse { 33 | auto rawResponse = Dispatcher()(uri(), request); 34 | return processResponse(std::move(rawResponse)); 35 | } 36 | 37 | static auto processResponse(json&& rawResponse) 38 | -> TransactionHistoryResponse { 39 | TransactionHistoryResponse response; 40 | response.statusCode_ = rawResponse["statusCode"].get(); 41 | response.errors_ = rawResponse["error"].get(); 42 | 43 | auto deposits = rawResponse["result"]["deposit"]; 44 | 45 | for (auto it = deposits.cbegin(); it != deposits.cend(); ++it) { 46 | std::vector historyDeposits; 47 | 48 | for (const auto& deposit : it.value()) { 49 | TxHistoryElement element{}; 50 | element.accountBalanceId = 51 | deposit["account_balance_id"].get(); 52 | element.type = deposit["type"].get(); 53 | element.status = deposit["status"].get(); 54 | element.asset = deposit["asset"].get(); 55 | element.notes = deposit["notes"].get(); 56 | element.amount = std::stold(deposit["amount"].get()); 57 | element.finalBalance = 58 | std::stold(deposit["final_balance"].get()); 59 | element.address = deposit["address"].get(); 60 | element.time = 61 | static_cast(deposit["time"].get()); 62 | 63 | historyDeposits.push_back(std::move(element)); 64 | } 65 | response.deposits.push_back(std::make_pair(it.key(), historyDeposits)); 66 | } 67 | 68 | auto withdrawals = rawResponse["result"]["withdrawal"]; 69 | 70 | for (auto it = withdrawals.cbegin(); it != withdrawals.cend(); ++it) { 71 | std::vector historyWithdrawals; 72 | 73 | for (const auto& withdrawal : it.value()) { 74 | TxHistoryElement element{}; 75 | element.accountBalanceId = 76 | withdrawal["account_balance_id"].get(); 77 | element.type = withdrawal["type"].get(); 78 | element.status = withdrawal["status"].get(); 79 | element.asset = withdrawal["asset"].get(); 80 | element.notes = withdrawal["notes"].get(); 81 | element.amount = std::stold(withdrawal["amount"].get()); 82 | element.finalBalance = 83 | std::stold(withdrawal["final_balance"].get()); 84 | element.address = withdrawal["address"].get(); 85 | element.time = static_cast( 86 | withdrawal["time"].get()); 87 | 88 | historyWithdrawals.push_back(std::move(element)); 89 | } 90 | response.withdrawals.push_back( 91 | std::make_pair(it.key(), historyWithdrawals)); 92 | } 93 | return response; 94 | } 95 | }; 96 | } // namespace Bitwyre::Rest::Private -------------------------------------------------------------------------------- /cpp/source/rest/private/CancelOrder.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Types::Private; 5 | using AsyncExecutionReport = std::future; 6 | 7 | namespace Bitwyre::Rest::Private { 8 | 9 | struct CancelOrder { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/private/orders/cancel"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto delAsync(Callback cb, const CancelOrderRequest& request) noexcept -> void { 19 | static_assert( std::is_invocable_v); 20 | auto result = delAsync(request); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto delAsync(const CancelOrderRequest& request) noexcept 26 | -> AsyncExecutionReport { 27 | return std::async(std::launch::async, [&request](){return del(request);}); 28 | } 29 | 30 | template 31 | [[nodiscard]] static auto del(const CancelOrderRequest& request) noexcept 32 | -> ExecutionReport { 33 | auto rawResponse = Dispatcher()(uri(), request); 34 | return processResponse(std::move(rawResponse)); 35 | } 36 | 37 | static auto processResponse(json&& rawResponse) -> ExecutionReport { 38 | ExecutionReport executionReport{}; 39 | executionReport.statusCode_ = rawResponse["statusCode"].get(); 40 | executionReport.errors_ = rawResponse["error"].get(); 41 | 42 | auto result = rawResponse["result"]; 43 | executionReport.avgPx = std::stold(result["AvgPx"].get()); 44 | executionReport.lastLiquidityInd = 45 | std::stold(result["LastLiquidityInd"].get()); 46 | executionReport.lastPx = std::stold(result["LastPx"].get()); 47 | executionReport.lastQty = 48 | std::stold(result["LastQty"].get()); 49 | executionReport.cumQty = std::stold(result["cumqty"].get()); 50 | executionReport.fillPrice = 51 | std::stold(result["fill_price"].get()); 52 | executionReport.leavesQty = 53 | std::stold(result["leavesqty"].get()); 54 | executionReport.orderQty = 55 | std::stold(result["orderqty"].get()); 56 | executionReport.price = std::stold(result["price"].get()); 57 | executionReport.stopPx = std::stold(result["stoppx"].get()); 58 | executionReport.value = std::stold(result["value"].get()); 59 | if (result["ordrejreason"].get().size()) { 60 | executionReport.ordRejReason = 61 | std::stold(result["ordrejreason"].get()); 62 | } else { 63 | executionReport.ordRejReason = 0; 64 | } 65 | 66 | executionReport.ordStatusReqId = 67 | result["ordstatusReqID"].get(); 68 | executionReport.origcliId = result["origclid"].get(); 69 | executionReport.account = result["account"].get(); 70 | executionReport.clOrdId = result["clorderid"].get(); 71 | executionReport.instrument = result["instrument"].get(); 72 | executionReport.orderId = result["orderid"].get(); 73 | 74 | executionReport.ordStatus = result["ordstatus"].get(); 75 | executionReport.ordType = result["ordtype"].get(); 76 | executionReport.timeInForce = result["time_in_force"].get(); 77 | 78 | executionReport.execId = result["execid"].get(); 79 | executionReport.execType = result["exectype"].get(); 80 | executionReport.expiry = result["expiry"].get(); 81 | executionReport.side = result["side"].get(); 82 | 83 | executionReport.timestamp = 84 | static_cast(result["timestamp"].get()); 85 | executionReport.transactTime = static_cast( 86 | result["transacttime"].get()); 87 | 88 | executionReport.cancelOnDisconnect = 89 | static_cast(result["cancelondisconnect"].get()); 90 | return executionReport; 91 | } 92 | }; 93 | } // namespace Bitwyre::Rest::Private -------------------------------------------------------------------------------- /cpp/source/rest/private/OrderInfo.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Types::Private; 5 | using AsyncOrderInfoResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Private { 8 | 9 | struct OrderInfo { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/private/orders/info"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto getAsync(Callback cb, const OrderInfoRequest& request) noexcept -> void { 19 | static_assert( std::is_invocable_v); 20 | auto result = getAsync(request); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto getAsync(const OrderInfoRequest& request) noexcept 26 | -> AsyncOrderInfoResponse { 27 | return std::async(std::launch::async, [&request](){return get(request);}); 28 | } 29 | 30 | template 31 | [[nodiscard]] static auto get(const OrderInfoRequest& request) noexcept 32 | -> OrderInfoResponse { 33 | auto rawResponse = Dispatcher()(uri(), request); 34 | return processResponse(std::move(rawResponse)); 35 | } 36 | 37 | static auto processResponse(json&& rawResponse) -> OrderInfoResponse { 38 | OrderInfoResponse response{}; 39 | response.statusCode_ = rawResponse["statusCode"].get(); 40 | response.errors_ = rawResponse["error"].get(); 41 | 42 | for (const auto& order : rawResponse["result"]) { 43 | ExecutionReport executionReport; 44 | executionReport.avgPx = std::stold(order["AvgPx"].get()); 45 | executionReport.lastLiquidityInd = 46 | std::stold(order["LastLiquidityInd"].get()); 47 | executionReport.lastPx = std::stold(order["LastPx"].get()); 48 | executionReport.lastQty = 49 | std::stold(order["LastQty"].get()); 50 | executionReport.cumQty = std::stold(order["cumqty"].get()); 51 | executionReport.fillPrice = 52 | std::stold(order["fill_price"].get()); 53 | executionReport.leavesQty = 54 | std::stold(order["leavesqty"].get()); 55 | executionReport.orderQty = 56 | std::stold(order["orderqty"].get()); 57 | executionReport.price = std::stold(order["price"].get()); 58 | executionReport.stopPx = std::stold(order["stoppx"].get()); 59 | executionReport.value = std::stold(order["value"].get()); 60 | if (order["ordrejreason"].get().size()) { 61 | executionReport.ordRejReason = 62 | std::stold(order["ordrejreason"].get()); 63 | } else { 64 | executionReport.ordRejReason = 0; 65 | } 66 | 67 | executionReport.ordStatusReqId = 68 | order["ordstatusReqID"].get(); 69 | executionReport.origcliId = order["origclid"].get(); 70 | executionReport.account = order["account"].get(); 71 | executionReport.clOrdId = order["clorderid"].get(); 72 | executionReport.instrument = order["instrument"].get(); 73 | executionReport.orderId = order["orderid"].get(); 74 | 75 | executionReport.ordStatus = order["ordstatus"].get(); 76 | executionReport.ordType = order["ordtype"].get(); 77 | executionReport.timeInForce = 78 | order["time_in_force"].get(); 79 | 80 | executionReport.execId = order["execid"].get(); 81 | executionReport.execType = order["exectype"].get(); 82 | executionReport.expiry = order["expiry"].get(); 83 | executionReport.side = order["side"].get(); 84 | 85 | executionReport.timestamp = 86 | static_cast(order["timestamp"].get()); 87 | executionReport.transactTime = static_cast( 88 | order["transacttime"].get()); 89 | 90 | executionReport.cancelOnDisconnect = 91 | static_cast(order["cancelondisconnect"].get()); 92 | 93 | response.ordersInfo.push_back(std::move(executionReport)); 94 | } 95 | return response; 96 | } 97 | }; 98 | } // namespace Bitwyre::Rest::Private -------------------------------------------------------------------------------- /cpp/source/rest/public/Ticker.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Details; 5 | using namespace Bitwyre::Types; 6 | using AsyncTickerResponse = std::future; 7 | 8 | namespace Bitwyre::Rest::Public { 9 | 10 | struct Ticker { 11 | 12 | using Callback = std::function; 13 | 14 | [[nodiscard]] static auto uri() noexcept -> std::string { 15 | return "/public/ticker"; 16 | } 17 | 18 | template 19 | [[nodiscard]] static auto getAsync(Callback cb, const TickerRequest& request) noexcept -> void { 20 | static_assert( std::is_invocable_v ); 21 | auto result = getAsync(request); 22 | return cb(result.get()); 23 | } 24 | 25 | template 26 | [[nodiscard]] static auto getAsync(const TickerRequest& request) noexcept -> AsyncTickerResponse { 27 | return std::async(std::launch::async, [&request](){return get(request);}); 28 | } 29 | 30 | template 31 | [[nodiscard]] static auto get(const TickerRequest& request) noexcept 32 | -> TickerResponse { 33 | auto rawResponse = Dispatcher()(uri(), request); 34 | return processResponse(std::move(rawResponse)); 35 | } 36 | 37 | static auto processResponse(json&& rawResponse) -> TickerResponse { 38 | TickerResponse tickerResponse; 39 | tickerResponse.statusCode_ = rawResponse["statusCode"].get(); 40 | tickerResponse.errors_ = rawResponse["error"].get(); 41 | 42 | if (rawResponse["result"].is_array()) { 43 | for (const auto& ticker : rawResponse["result"]) { 44 | TickerElement tickerElement{}; 45 | tickerElement.instrument = ticker["instrument"].get(); 46 | tickerElement.assetBase = ticker["asset_base"].get(); 47 | tickerElement.assetQuote = ticker["asset_quote"].get(); 48 | tickerElement.market = ticker["market"].get(); 49 | tickerElement.isFrozen = ticker["is_frozen"].get(); 50 | tickerElement.high = std::stold(ticker["high"].get()); 51 | tickerElement.low = std::stold(ticker["low"].get()); 52 | tickerElement.percentChange = 53 | std::stold(ticker["percent_change"].get()); 54 | tickerElement.volumeQuote = 55 | std::stold(ticker["volume_quote"].get()); 56 | tickerElement.volumeBase = 57 | std::stold(ticker["volume_base"].get()); 58 | tickerElement.last = std::stold(ticker["last"].get()); 59 | tickerElement.bestBid = 60 | std::stold(ticker["best_bid"].get()); 61 | tickerElement.bestAsk = 62 | std::stold(ticker["best_ask"].get()); 63 | tickerElement.timestamp = 64 | static_cast(ticker["timestamp"].get()); 65 | 66 | tickerResponse.tickers.push_back(std::move(tickerElement)); 67 | } 68 | } else { 69 | TickerElement tickerElement{}; 70 | auto ticker = rawResponse["result"]; 71 | tickerElement.instrument = ticker["instrument"].get(); 72 | tickerElement.assetBase = ticker["asset_base"].get(); 73 | tickerElement.assetQuote = ticker["asset_quote"].get(); 74 | tickerElement.market = ticker["market"].get(); 75 | tickerElement.isFrozen = ticker["is_frozen"].get(); 76 | tickerElement.high = std::stold(ticker["high"].get()); 77 | tickerElement.low = std::stold(ticker["low"].get()); 78 | tickerElement.percentChange = 79 | std::stold(ticker["percent_change"].get()); 80 | tickerElement.volumeQuote = 81 | std::stold(ticker["volume_quote"].get()); 82 | tickerElement.volumeBase = 83 | std::stold(ticker["volume_base"].get()); 84 | tickerElement.last = std::stold(ticker["last"].get()); 85 | tickerElement.bestBid = 86 | std::stold(ticker["best_bid"].get()); 87 | tickerElement.bestAsk = 88 | std::stold(ticker["best_ask"].get()); 89 | tickerElement.timestamp = 90 | static_cast(ticker["timestamp"].get()); 91 | 92 | tickerResponse.tickers.push_back(std::move(tickerElement)); 93 | } 94 | return tickerResponse; 95 | } 96 | }; 97 | } // namespace Bitwyre::Rest::Public 98 | -------------------------------------------------------------------------------- /cpp/README.md: -------------------------------------------------------------------------------- 1 | # Official Bitwyre C++ Software Development Kit 2 | 3 | ## C++ REST SDK 4 | We are building a cross-platform open source library allows one to create asynchronous REST clients. 5 | 6 | The Dispatcher class is responsible to send request. Each end point has to process response, write it to JSON format output. 7 | 8 | The API URL is retrieved from the environment variable `URL_API_BITWYRE`, but if you do not set it, a default one 9 | pointing to our production cluster will be used. 10 | 11 | # Building from source 12 | 13 | ## Requirements 14 | 15 | - Clang 12.0.1 or any Compiler with support of C++17 16 | - Conan version 1.37 or greater for package management 17 | - CMake version 3.20.3 18 | 19 | ## Build commands 20 | 21 | ### general linux distributions 22 | 23 | ```shell 24 | mkdir build 25 | cd build 26 | export CONAN_RUN_TESTS=1 27 | echo $CONAN_RUN_TESTS 28 | cmake .. -DUNIT_TESTS=1 -DBUILD_TESTING=1 -DCMAKE_BUILD_TYPE=Debug 29 | make 30 | ``` 31 | 35 | In order to build the test suite add `-DBUILD_TESTING` definition. 36 | 37 | # Package Managers 38 | 39 | ## Conan 40 | 41 | Add our remote https://conan.bitwyre.id/artifactory/api/conan/bitwyre to your list of remotes 42 | 43 | ``` 44 | conan remote add bitwyre https://conan.bitwyre.id/artifactory/api/conan/bitwyre 45 | ``` 46 | 47 | Then inside your `conanfile.py` or `conanfile.txt` add `bitwyresdk/[>=1.0]` 48 | 49 | ## Vckpg 50 | 51 | Coming Soon 52 | 53 | # Example of usage Public API 54 | 55 | - Getting the Server time https://docs.bitwyre.id/#server-time 56 | 57 | ```c++ 58 | #include "bitwyresdk/rest/public/Time.hpp" 59 | 60 | auto main() -> int { 61 | // TimeResponse here can be replaced with auto 62 | TimeResponse tr = Bitwyre::Rest::Public::Time::get(); 63 | 64 | std::cout << tr.unixtime.count() << "\n"; 65 | } 66 | ``` 67 | 68 | - Getting the list of tickers https://docs.bitwyre.id/#ticker 69 | 70 | ```c++ 71 | #include "rest/public/Ticker.hpp" 72 | 73 | auto main() -> int { 74 | TickerRequest tickReq{InstrumentT{"btc_usd_spot"}}; 75 | TickerResponse tr = Ticker::get(tickReq); 76 | 77 | std::cout << tr.tickers.size() << "\n"; 78 | } 79 | ``` 80 | 81 | # Example of usage Private API 82 | 83 | All private APIs are authenticated following https://docs.bitwyre.id/#authentication. 84 | 85 | For running these endpoints, follow the documentation link above and retrieve your **API-KEY** and **API-SECRET**, they will be 86 | required in order to sign every request. 87 | 88 | Once you've retrieved the API credentials, set them as environment variable. 89 | 90 | ```shell 91 | export BITWYRE_API_SECRET=mysecret 92 | export BITWYRE_API_KEY=mypublic 93 | ``` 94 | 95 | At this point we are all set to run the examples. 96 | 97 | - Opening a new order https://docs.bitwyre.id/#ticker 98 | 99 | ```c++ 100 | #include "rest/public/NewOrder.hpp" 101 | 102 | auto main() -> int { 103 | NewOrderRequest request{ 104 | InstrumentT{"btc_usd_spot"}, 105 | SideT{1}, 106 | OrdType{1}, 107 | PriceT{100}, 108 | QtyT{100}, 109 | }; 110 | 111 | auto result = NewOrder::post(request); 112 | 113 | std::cout << result.instrument << "\n"; 114 | } 115 | ``` 116 | 117 | # License 118 | 119 | > Copyright (c) 2019 Kracejic 120 | > Copyright (c) 2021 Bitwyre LLC 121 | > 122 | > Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 123 | > 124 | > The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 125 | > 126 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 127 | -------------------------------------------------------------------------------- /cpp/doc/start_working.md: -------------------------------------------------------------------------------- 1 | 2 | # How to start working 3 | 4 | ## Build System 5 | 6 | Big help will be the official CMake docs at 7 | [cmake.org/cmake/help/latest/](https://cmake.org/cmake/help/latest/). You can 8 | consult them for function description. 9 | 10 | Other than that CMake is fairly simple language, which can get things done quickly. 11 | 12 | If you found yourself in a situation when you do not know the status of 13 | variables, use `cmake .. -LH` or `cmake .. -LAH` for current variables values. 14 | 15 | Start with reading `project_folder/CMakeLists.txt` and continue to 16 | `project_folder/source/CMakeLists.txt`. If you are interested in testing (you should 17 | be), read also `project_folder/test/CMakeLists.txt` and see how testing is done and so on. 18 | 19 | ## Source code 20 | 21 | Function main is in the `source/main.cpp`. 22 | 23 | If you want to add an file, add it to `source/CMakeLists.txt` into *SRCS* 24 | variable, then it will be compiled to bitwyresdk target. 25 | 26 | ## Change the name of the executable 27 | 28 | ### Manual proces: 29 | 30 | * **packaging/bitwyresdk.desktop.desktop** - rename file, change texts, replace "bitwyresdk" strings with your new executable name 31 | * **packaging/bitwyresdk.ico** - rename file 32 | * **packaging/bitwyresdk.icon.in.rc** - rename file, replace "bitwyresdk" strings with your new executable name 33 | * **packaging/bitwyresdk.png** - rename file 34 | * **packaging/CMakeLists.txt** - change description texts, windows desktop icon name (CPACK_NSIS_DISPLAY_NAME), replace "bitwyresdk" strings with your new executable name 35 | * **test/CMakeLists.txt** - replace "bitwyresdk" strings with your new executable name 36 | * **readme.md** - replace "bitwyresdk" strings with your new executable name 37 | * **source/CMakeLists.txt** - replace "bitwyresdk" strings with your new executable name 38 | * **doc/start_working.md** - replace "bitwyresdk" strings with your new executable name 39 | * **doc/directoryStructure.md** - replace "bitwyresdk" strings with your new executable name 40 | 41 | ### Automatic process (for linux): 42 | 43 | This expect, that you have installed ag, the silver searcher (faster grep with 44 | simpler usage). If you created build directory starting with other than 45 | "build", you may want to delete it (ag respects .gitignore, and it would 46 | happily wreck your build directory with sed). 47 | 48 | We will first rename the files handling icons, then we run sed (streaming 49 | editor) and replace all occurences of bitwyresdk with your new name. 50 | 51 | ~~~bash 52 | cd [root/of/project] 53 | export NEWNAME="newExecutableName" 54 | 55 | git mv packaging/bitwyresdk.desktop packaging/${NEWNAME}.desktop 56 | git mv packaging/bitwyresdk.ico packaging/${NEWNAME}.ico 57 | git mv packaging/bitwyresdk.icon.in.rc packaging/${NEWNAME}.icon.in.rc 58 | git mv packaging/bitwyresdk.png packaging/${NEWNAME}.png 59 | 60 | ag -l bitwyresdk | xargs sed -i -e "s/bitwyresdk/${NEWNAME}/g" 61 | ~~~ 62 | 63 | Then change description in **.desktop** and **packaging/CMakeLists.txt** files. 64 | 65 | ## Change icon 66 | 67 | Just change replace packaging/bitwyresdk.ico and packaging/bitwyresdk.png with 68 | your own images. 69 | 70 | ## Add depenencies 71 | 72 | Look at the `external/CMakeLists.txt` to see examples on adding external 73 | libraries. There are examples for: 74 | 75 | * nlohmann/json - amazing library for json handling 76 | * spdlog - fast and simple logging library 77 | * doctest - alternative to catch unit test library 78 | * fmt - python text/output like formating 79 | * cpr - requests for humans for C++ 80 | 81 | Just uncomment the part of the code and add the dependencies via `target_link_libraries`. 82 | 83 | ## Tests 84 | 85 | ### Unit tests 86 | 87 | Checkout [catch tutorial](https://github.com/philsquared/Catch/blob/master/docs/tutorial.md). 88 | 89 | When you want to add new unit tests, add source file to `test/CMakeLists.txt` 90 | to *SRCTEST* variable. You can use following snippet to add tests to a file: 91 | 92 | ~~~ 93 | #ifdef UNIT_TESTS 94 | #include "catch.hpp" 95 | 96 | TEST_CASE("SomeClass set and get") 97 | { 98 | //setup 99 | ... 100 | 101 | REQUIRE(something.get() != 2); 102 | } 103 | 104 | #endif 105 | ~~~ 106 | 107 | This way you can have tests part of an implementation file and yet they will 108 | not be part of a regular build because *UNIT_TESTS* define is defined only for 109 | producing unit test binary. 110 | 111 | ### Integration tests 112 | 113 | Start with `test/CMakeLists.txt`, it is pretty straightforward. See [cmake 114 | documentation](https://cmake.org/cmake/help/latest/command/add_test.html) for 115 | more information. By default test checks for return value (must be zero), but 116 | with PASS_REGULAR_EXPRESSION and FAIL_REGULAR_EXPRESSION that can be changed. 117 | 118 | -------------------------------------------------------------------------------- /cpp/doc/doxygen/Doxyfile.in: -------------------------------------------------------------------------------- 1 | # Use: `doxygen -g test.txt` to generate all possible settings for this file 2 | 3 | # For modern doxygen style uncomment these three lines: 4 | HTML_EXTRA_STYLESHEET = @CMAKE_CURRENT_SOURCE_DIR@/doxygen/customdoxygen.css 5 | HTML_HEADER = @CMAKE_CURRENT_SOURCE_DIR@/doxygen/header.html 6 | HTML_FOOTER = @CMAKE_CURRENT_SOURCE_DIR@/doxygen/footer.html 7 | 8 | # not interested build output 9 | QUIET = NO 10 | 11 | # Basic settings: 12 | PROJECT_NAME = "@CMAKE_PROJECT_NAME@" 13 | PROJECT_NUMBER = @PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@@VERSION_TYPE@ 14 | STRIP_FROM_PATH = @CMAKE_CURRENT_SOURCE_DIR_LINUX@ \ 15 | @PROJECT_SOURCE_DIR_LINUX@ 16 | INPUT = @PROJECT_SOURCE_DIR_LINUX@/readme.md \ 17 | @CMAKE_CURRENT_SOURCE_DIR_LINUX@ \ 18 | @PROJECT_SOURCE_DIR_LINUX@/source 19 | 20 | FILE_PATTERNS = *.h \ 21 | *.hpp \ 22 | *.hh \ 23 | *.c \ 24 | *.cc \ 25 | *.cpp.in \ 26 | *.cpp \ 27 | *.md 28 | RECURSIVE = YES 29 | USE_MDFILE_AS_MAINPAGE = "@PROJECT_SOURCE_DIR_LINUX@/readme.md" 30 | # output location 31 | HTML_OUTPUT = "@CMAKE_CURRENT_BINARY_DIR_LINUX@/doc" 32 | 33 | IMAGE_PATH = "@CMAKE_CURRENT_SOURCE_DIR_LINUX@" 34 | 35 | # We want to create nice UML graphs 36 | PLANTUML_JAR_PATH = "@PLANT_UML_PATH_LINUX@" 37 | DOT_PATH = "@DOT_PATH_LINUX@" 38 | 39 | # The OUTPUT_LANGUAGE tag is used to specify the language in which all 40 | # documentation generated by doxygen is written. Doxygen will use this 41 | # information to generate all constant output in the proper language. 42 | # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, 43 | # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), 44 | # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, 45 | # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), 46 | # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, 47 | # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, 48 | # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, 49 | # Ukrainian and Vietnamese. 50 | # The default value is: English. 51 | OUTPUT_LANGUAGE = English 52 | 53 | # Color style 54 | HTML_COLORSTYLE_HUE = 220 55 | HTML_COLORSTYLE_SAT = 40 56 | HTML_COLORSTYLE_GAMMA = 80 57 | 58 | # max size 200x55px 59 | PROJECT_LOGO = 60 | 61 | 62 | 63 | 64 | # If the REFERENCED_BY_RELATION tag is set to YES then for each documented 65 | # function all documented functions referencing it will be listed. 66 | # The default value is: NO. 67 | REFERENCED_BY_RELATION = YES 68 | 69 | # If the REFERENCES_RELATION tag is set to YES then for each documented function 70 | # all documented entities called/used by that function will be listed. 71 | # The default value is: NO. 72 | REFERENCES_RELATION = YES 73 | 74 | # This is nice to have - callgraphs of functions 75 | HAVE_DOT = YES 76 | CALL_GRAPH = YES 77 | CALLER_GRAPH = YES 78 | 79 | GRAPHICAL_HIERARCHY = YES 80 | DIRECTORY_GRAPH = YES 81 | GENERATE_LEGEND = YES 82 | INCLUDED_BY_GRAPH = YES 83 | INCLUDE_GRAPH = YES 84 | DOT_IMAGE_FORMAT = svg 85 | INTERACTIVE_SVG = YES 86 | 87 | # More insight to templates, generaly not needed 88 | TEMPLATE_RELATIONS = NO 89 | 90 | # in class diagrams, you will have members and such 91 | # Also they will be bigger 92 | UML_LOOK = YES 93 | UML_LIMIT_NUM_FIELDS = 6 94 | 95 | 96 | 97 | # should all pictures be collapsed? 98 | HTML_DYNAMIC_SECTIONS = NO 99 | 100 | 101 | # use with: /// @todo Do more stuff. 102 | GENERATE_TODOLIST = YES 103 | 104 | # we want all we can get 105 | EXTRACT_ALL = YES 106 | EXTRACT_STATIC = YES 107 | EXTRACT_PRIVATE = YES 108 | 109 | # We do not need latex output 110 | GENERATE_LATEX = NO 111 | USE_PDFLATEX = NO 112 | 113 | # this makes first sentence from comment block a brief description. 114 | # It is VERY useful 115 | JAVADOC_AUTOBRIEF = YES 116 | 117 | # Why not... 118 | BUILTIN_STL_SUPPORT = YES 119 | 120 | # Do we want source code browser? YES! Do we want strip comments? NO 121 | SOURCE_BROWSER = YES 122 | STRIP_CODE_COMMENTS = NO 123 | 124 | # Side panel 125 | # If you enable this, change .container max-width: 960px; to 1240px 126 | GENERATE_TREEVIEW = YES 127 | -------------------------------------------------------------------------------- /rust/tests/private.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod test { 3 | use rust_sdk::{ 4 | private, 5 | public::config 6 | }; 7 | use serde::{Deserialize, Serialize}; 8 | 9 | #[derive(Serialize, Deserialize)] 10 | struct ResultString { 11 | error: Vec, 12 | } 13 | 14 | #[tokio::test] 15 | async fn get_account_balance_async_should_work() { 16 | let data = private::get_account_balance_async().await; 17 | assert!(data.is_ok()); 18 | 19 | let r: ResultString = serde_json::from_str( 20 | &data.unwrap() 21 | ).unwrap(); 22 | assert!(r.error.is_empty()); 23 | } 24 | 25 | #[tokio::test] 26 | async fn get_account_statement_async_should_work() { 27 | let data = private::get_account_statement_async().await; 28 | assert!(data.is_ok()); 29 | 30 | let r: ResultString = serde_json::from_str( 31 | &data.unwrap() 32 | ).unwrap(); 33 | assert!(r.error.is_empty()); 34 | } 35 | 36 | #[tokio::test] 37 | async fn get_transaction_histories_async_should_work() { 38 | let data = private::get_transaction_histories_async().await; 39 | assert!(data.is_ok()); 40 | 41 | let r: ResultString = serde_json::from_str( 42 | &data.unwrap() 43 | ).unwrap(); 44 | assert!(r.error.is_empty()); 45 | } 46 | 47 | #[tokio::test] 48 | async fn get_open_orders_async_should_work() { 49 | let instrument = config::bitwyre_instrument("1"); 50 | let data = private::get_open_orders_async(instrument, 0, 0).await; 51 | assert!(data.is_ok()); 52 | 53 | let r: ResultString = serde_json::from_str( 54 | &data.unwrap() 55 | ).unwrap(); 56 | assert!(r.error.is_empty()); 57 | } 58 | 59 | #[tokio::test] 60 | async fn get_closed_orders_async_should_work() { 61 | let instrument = config::bitwyre_instrument("1"); 62 | let data = private::get_closed_orders_async(instrument, 0, 0).await; 63 | assert!(data.is_ok()); 64 | 65 | let r: ResultString = serde_json::from_str( 66 | &data.unwrap() 67 | ).unwrap(); 68 | assert!(r.error.is_empty()); 69 | } 70 | 71 | #[tokio::test] 72 | async fn get_order_info_async_should_work() { 73 | let data = private::get_order_info_async("3f128876-a082-4b18-8fd4-abbcc4aa7915").await; 74 | assert!(data.is_ok()); 75 | 76 | let r: ResultString = serde_json::from_str( 77 | &data.unwrap() 78 | ).unwrap(); 79 | assert!(r.error.is_empty()); 80 | } 81 | 82 | #[tokio::test] 83 | async fn get_trade_history_async_should_work() { 84 | let instrument = config::bitwyre_instrument("1"); 85 | let data = private::get_trade_history_async(instrument, 2, 0, 0).await; 86 | assert!(data.is_ok()); 87 | 88 | let r: ResultString = serde_json::from_str( 89 | &data.unwrap() 90 | ).unwrap(); 91 | assert!(r.error.is_empty()); 92 | } 93 | 94 | #[tokio::test] 95 | async fn cancelling_open_order_per_instrument_async_should_work() { 96 | let instrument = config::bitwyre_instrument("1"); 97 | let data = private::cancelling_open_order_per_instrument_async(instrument).await; 98 | assert!(data.is_ok()); 99 | 100 | let r: ResultString = serde_json::from_str( 101 | &data.unwrap() 102 | ).unwrap(); 103 | assert!(r.error.is_empty()); 104 | } 105 | 106 | #[tokio::test] 107 | async fn cancelling_open_order_per_orderids_async_should_work() { 108 | let data = private::cancelling_open_order_per_orderids_async( 109 | vec!["5033216a-dad5-4cb6-87d6-0084603be699", "3d19d8d1-c576-4109-8671-5e4115cf6e5e"], vec![-1, -1] 110 | ).await; 111 | assert!(data.is_ok()); 112 | 113 | let r: ResultString = serde_json::from_str( 114 | &data.unwrap() 115 | ).unwrap(); 116 | assert!(r.error.is_empty()); 117 | } 118 | 119 | #[tokio::test] 120 | async fn opening_new_order_async_should_work() { 121 | let instrument = config::bitwyre_instrument("1"); 122 | let data = private::opening_new_order_async(instrument, 1, Some(35000.to_string()), 2, "0.0001").await; 123 | assert!(data.is_ok()); 124 | 125 | let r: ResultString = serde_json::from_str( 126 | &data.unwrap() 127 | ).unwrap(); 128 | assert!(r.error.is_empty()); 129 | 130 | let data = private::opening_new_order_async(instrument, 1, Some("".to_string()), 1, "0.0001").await; 131 | assert!(data.is_ok()); 132 | 133 | let r: ResultString = serde_json::from_str( 134 | &data.unwrap() 135 | ).unwrap(); 136 | assert!(r.error.is_empty()); 137 | } 138 | } -------------------------------------------------------------------------------- /websocket_python/websocket_python_sdk/private.py: -------------------------------------------------------------------------------- 1 | import json 2 | import hmac 3 | from urllib import response 4 | import websocket 5 | import logging 6 | 7 | from websocket import WebSocket 8 | from time import time_ns 9 | from hashlib import sha256, sha512 10 | 11 | from public import PublicBitwyreWSClient 12 | 13 | from utils import ( 14 | BASE_URL, 15 | PRINT_DEBUGS, 16 | parse_codes 17 | ) 18 | logging.basicConfig( 19 | format='%(asctime)s %(message)s', 20 | filemode='w' 21 | ) 22 | logger = logging.getLogger() 23 | logger.setLevel(logging.DEBUG) 24 | 25 | 26 | def sign_deprecated(secret_key: str, uri_path: str, payload: str): 27 | nonce = int(time_ns()) 28 | payload = json.dumps(payload, separators=(',', ':')) 29 | 30 | json_payload = json.dumps(payload) 31 | json_payload = json.dumps(json_payload) 32 | 33 | checksum = sha256(str(json_payload).encode("utf-8")).hexdigest() 34 | nonce_checksum = sha256(str(nonce).encode("utf-8") + str(checksum).encode("utf-8")).hexdigest() 35 | signature = hmac.new( 36 | secret_key.encode("utf-8"), uri_path.encode("utf-8") + nonce_checksum.encode("utf-8"), sha512 37 | ).hexdigest() 38 | 39 | return (nonce, checksum, signature, payload) 40 | 41 | 42 | class PrivateBitwyreWSClient: 43 | def __init__( 44 | self, 45 | url:str = BASE_URL, 46 | api_key:str = None, 47 | api_secret:str = None, 48 | debugs:str = PRINT_DEBUGS, 49 | ): 50 | websocket.enableTrace(debugs) 51 | self.url = url 52 | self.uri = "" 53 | self.ws = websocket.WebSocket() 54 | self.api_key = api_key 55 | self.api_secret = api_secret 56 | self.command = "" 57 | self.params = { 58 | "command": None, 59 | "payload": "" 60 | } 61 | 62 | 63 | @staticmethod 64 | def sign(secret_key: str): 65 | signature = hmac.new( 66 | secret_key.encode("utf-8"), "".encode("utf-8"), sha512 67 | ).hexdigest() 68 | return signature 69 | 70 | def close(self): 71 | self.ws.close() 72 | 73 | def connect(self) -> WebSocket: 74 | url = self.url + self.uri 75 | 76 | signature = self.sign(self.api_secret) 77 | 78 | header = { 79 | "api_key": self.api_key, 80 | "api_sign": signature 81 | } 82 | 83 | header = json.dumps(header) 84 | 85 | header = [f"API-Data: {header}"] 86 | 87 | logging.debug(f"opening ws connection to {url}") 88 | logging.debug(f"Header is {header}") 89 | self.ws.connect(url, header=header) 90 | logging.debug("ws connection success") 91 | return self.ws 92 | 93 | def send_message(self, message: dict): 94 | message = json.dumps(message) 95 | 96 | logging.debug(f"sending payload {message}") 97 | self.ws.send(message) 98 | logging.debug("sending payload success") 99 | 100 | def receive_conn(self, payload:str = None): 101 | if payload is None: 102 | payload = "" 103 | else: 104 | payload = json.dumps(payload) 105 | 106 | self.params["command"] = self.command 107 | self.params["payload"] = payload 108 | 109 | self.send_message(self.params) 110 | 111 | status_code, response, error_code, error_msg = self.ws.recv() 112 | success, response, error_code, error_msg = parse_codes(status_code, response, error_code, error_msg) 113 | 114 | return success, response, error_code, error_msg 115 | 116 | def account_balance(self) -> WebSocket: 117 | self.uri = "/ws/private/account/balance" 118 | 119 | self.command = "get" 120 | self.connect() 121 | 122 | return self.ws 123 | 124 | def account_statement(self) -> WebSocket: 125 | self.uri = "/ws/private/account/statement" 126 | self.command = "get" 127 | 128 | self.connect() 129 | return self.ws 130 | 131 | def create_order(self) -> WebSocket: 132 | self.uri = "/ws/private/orders/control" 133 | self.command = "create" 134 | 135 | self.connect() 136 | return self.ws 137 | 138 | def cancel_order(self) -> WebSocket: 139 | self.uri = "/ws/private/orders/control" 140 | self.command = "cancel" 141 | 142 | self.connect() 143 | return self.ws 144 | 145 | def order_status(self) -> WebSocket: 146 | self.uri = "/ws/private/orders/status" 147 | self.command = "get" 148 | 149 | self.connect() 150 | return self.ws 151 | 152 | def order_events(self) -> WebSocket: 153 | self.uri = "/ws/private/orders/events" 154 | self.command = "subscribe" 155 | 156 | self.connect() 157 | return self.ws 158 | 159 | def trade_histories(self) -> WebSocket: 160 | self.uri = "/ws/private/orders/events" 161 | self.command = "get" 162 | 163 | self.connect() 164 | return self.ws -------------------------------------------------------------------------------- /cpp/source/rest/private/AccountStatement.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Types.hpp" 3 | #include "../../details/Dispatcher.hpp" 4 | 5 | using namespace Bitwyre::Types::Private; 6 | using AsyncAccountStatementResponse = std::future; 7 | 8 | namespace Bitwyre::Rest::Private { 9 | 10 | struct AccountStatement { 11 | 12 | using Callback = std::function; 13 | 14 | [[nodiscard]] static auto uri() noexcept -> std::string { 15 | return "/private/account/statement"; 16 | } 17 | 18 | template 19 | [[nodiscard]] static auto getAsync(Callback cb, const AccountStatementRequest& request) noexcept -> void { 20 | static_assert( std::is_invocable_v); 21 | auto result = getAsync(request); 22 | return cb(result.get()); 23 | } 24 | 25 | template 26 | [[nodiscard]] static auto getAsync(const AccountStatementRequest& request) noexcept 27 | -> AsyncAccountStatementResponse { 28 | return std::async(std::launch::async, [&request](){return get(request);}); 29 | } 30 | 31 | template 32 | [[nodiscard]] static auto get(const AccountStatementRequest& request) noexcept 33 | -> AccountStatementResponse { 34 | auto rawResponse = Dispatcher()(uri(), request); 35 | return processResponse(std::move(rawResponse)); 36 | } 37 | 38 | static auto processResponse(json&& rawResponse) 39 | -> AccountStatementResponse { 40 | AccountStatementResponse statementResponse; 41 | statementResponse.statusCode_ = rawResponse["statusCode"].get(); 42 | statementResponse.errors_ = rawResponse["error"].get(); 43 | 44 | auto deposits = rawResponse["result"]["deposit"]; 45 | 46 | for (auto it = deposits.cbegin(); it != deposits.cend(); ++it) { 47 | std::vector assetDeposits; 48 | 49 | for (const auto& deposit : it.value()) { 50 | AccountStatementElement statementElement{}; 51 | statementElement.fee = deposit["fee"].get(); 52 | statementElement.grossAmount = 53 | deposit["gross_amount"].get(); 54 | statementElement.nettAmount = 55 | deposit["nett_amount"].get(); 56 | statementElement.id = deposit["id"].get(); 57 | statementElement.provider = deposit["provider"].get(); 58 | statementElement.type = deposit["type"].get(); 59 | statementElement.status = deposit["status"].get(); 60 | if (statementElement.type == "crypto") { 61 | statementElement.txId = deposit["tx_id"].get(); 62 | statementElement.networkConfirmation = 63 | deposit["network_confirmation"].get(); 64 | } 65 | 66 | statementElement.submitTime = static_cast( 67 | deposit["submit_time"].get()); 68 | statementElement.successTime = static_cast( 69 | deposit["success_time"].get()); 70 | assetDeposits.push_back(std::move(statementElement)); 71 | } 72 | statementResponse.deposits.push_back( 73 | std::make_pair(it.key(), assetDeposits)); 74 | } 75 | 76 | auto withdrawals = rawResponse["result"]["withdrawal"]; 77 | 78 | for (auto it = withdrawals.cbegin(); it != withdrawals.cend(); ++it) { 79 | std::vector assetDeposits; 80 | for (const auto& withdrawal : it.value()) { 81 | AccountStatementElement statementElement{}; 82 | statementElement.fee = withdrawal["fee"].get(); 83 | statementElement.grossAmount = 84 | withdrawal["gross_amount"].get(); 85 | statementElement.nettAmount = 86 | withdrawal["nett_amount"].get(); 87 | statementElement.id = withdrawal["id"].get(); 88 | statementElement.provider = withdrawal["provider"].get(); 89 | statementElement.type = withdrawal["type"].get(); 90 | statementElement.status = withdrawal["status"].get(); 91 | if (statementElement.type == "crypto") { 92 | statementElement.txId = withdrawal["tx_id"].get(); 93 | statementElement.networkConfirmation = 94 | withdrawal["network_confirmation"].get(); 95 | } 96 | 97 | statementElement.submitTime = static_cast( 98 | withdrawal["submit_time"].get()); 99 | statementElement.successTime = static_cast( 100 | withdrawal["success_time"].get()); 101 | assetDeposits.push_back(std::move(statementElement)); 102 | } 103 | statementResponse.withdrawals.push_back( 104 | std::make_pair(it.key(), assetDeposits)); 105 | } 106 | return statementResponse; 107 | } 108 | }; 109 | }// namespace Bitwyre::Rest::Private -------------------------------------------------------------------------------- /cpp/source/rest/private/OpenOrders.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Types::Private; 5 | using AsyncResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Private { 8 | 9 | struct OpenOrders { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/private/orders/open"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto getAsync(Callback cb, const OpenOrdersRequest& request) noexcept -> void { 19 | static_assert( std::is_invocable_v); 20 | auto result = getAsync(request); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto getAsync(const OpenOrdersRequest& request) noexcept 26 | -> AsyncResponse { 27 | return std::async(std::launch::async, [&request](){return get(request);}); 28 | } 29 | 30 | template 31 | [[nodiscard]] static auto get(const OpenOrdersRequest& request) noexcept 32 | -> Response { 33 | auto rawResponse = Dispatcher()(uri(), request); 34 | return processResponse(std::move(rawResponse)); 35 | } 36 | 37 | static auto processResponse(json&& rawResponse) -> OpenOrdersResponse { 38 | OpenOrdersResponse response; 39 | response.statusCode_ = rawResponse["statusCode"].get(); 40 | response.errors_ = rawResponse["error"].get(); 41 | 42 | auto closedOrders = rawResponse["result"]; 43 | 44 | for (auto it = closedOrders.cbegin(); it != closedOrders.cend(); ++it) { 45 | std::vector orders; 46 | 47 | for (const auto& openOrder : it.value()) { 48 | ExecutionReport executionReport; 49 | executionReport.avgPx = 50 | std::stold(openOrder["AvgPx"].get()); 51 | executionReport.lastLiquidityInd = 52 | std::stold(openOrder["LastLiquidityInd"].get()); 53 | executionReport.lastPx = 54 | std::stold(openOrder["LastPx"].get()); 55 | executionReport.lastQty = 56 | std::stold(openOrder["LastQty"].get()); 57 | executionReport.cumQty = 58 | std::stold(openOrder["cumqty"].get()); 59 | executionReport.fillPrice = 60 | std::stold(openOrder["fill_price"].get()); 61 | executionReport.leavesQty = 62 | std::stold(openOrder["leavesqty"].get()); 63 | executionReport.orderQty = 64 | std::stold(openOrder["orderqty"].get()); 65 | executionReport.price = 66 | std::stold(openOrder["price"].get()); 67 | executionReport.stopPx = 68 | std::stold(openOrder["stoppx"].get()); 69 | executionReport.value = 70 | std::stold(openOrder["value"].get()); 71 | if (openOrder["ordrejreason"].get().size()) { 72 | executionReport.ordRejReason = 73 | std::stold(openOrder["ordrejreason"].get()); 74 | } else { 75 | executionReport.ordRejReason = 0; 76 | } 77 | 78 | executionReport.ordStatusReqId = 79 | openOrder["ordstatusReqID"].get(); 80 | executionReport.origcliId = openOrder["origclid"].get(); 81 | executionReport.account = openOrder["account"].get(); 82 | executionReport.clOrdId = openOrder["clorderid"].get(); 83 | executionReport.instrument = 84 | openOrder["instrument"].get(); 85 | executionReport.orderId = openOrder["orderid"].get(); 86 | 87 | executionReport.ordStatus = 88 | openOrder["ordstatus"].get(); 89 | executionReport.ordType = openOrder["ordtype"].get(); 90 | executionReport.timeInForce = 91 | openOrder["time_in_force"].get(); 92 | 93 | executionReport.execId = openOrder["execid"].get(); 94 | executionReport.execType = openOrder["exectype"].get(); 95 | executionReport.expiry = openOrder["expiry"].get(); 96 | executionReport.side = openOrder["side"].get(); 97 | 98 | executionReport.timestamp = static_cast( 99 | openOrder["timestamp"].get()); 100 | executionReport.transactTime = static_cast( 101 | openOrder["transacttime"].get()); 102 | 103 | executionReport.cancelOnDisconnect = 104 | static_cast(openOrder["cancelondisconnect"].get()); 105 | 106 | orders.push_back(std::move(executionReport)); 107 | } 108 | response.openOrders.push_back( 109 | std::make_pair(it.key(), std::move(orders))); 110 | } 111 | return response; 112 | } 113 | }; 114 | } // namespace Bitwyre::Rest::Private -------------------------------------------------------------------------------- /cpp/source/rest/private/ClosedOrders.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../../details/Dispatcher.hpp" 3 | 4 | using namespace Bitwyre::Types::Private; 5 | using AsyncCloseOrdersResponse = std::future; 6 | 7 | namespace Bitwyre::Rest::Private { 8 | 9 | struct ClosedOrders { 10 | 11 | using Callback = std::function; 12 | 13 | [[nodiscard]] static auto uri() noexcept -> std::string { 14 | return "/private/orders/closed"; 15 | } 16 | 17 | template 18 | [[nodiscard]] static auto getAsync(Callback cb, const ClosedOrdersRequest& request) noexcept -> void{ 19 | static_assert( std::is_invocable_v); 20 | auto result = getAsync(request); 21 | return cb(result.get()); 22 | } 23 | 24 | template 25 | [[nodiscard]] static auto getAsync(const ClosedOrdersRequest& request) noexcept 26 | -> AsyncCloseOrdersResponse { 27 | return std::async(std::launch::async, [&request](){return get(request);}); 28 | } 29 | 30 | template 31 | [[nodiscard]] static auto get(const ClosedOrdersRequest& request) noexcept 32 | -> ClosedOrdersResponse { 33 | 34 | auto rawResponse = Dispatcher()(uri(), request); 35 | return processResponse(std::move(rawResponse)); 36 | } 37 | 38 | static auto processResponse(json&& rawResponse) -> ClosedOrdersResponse { 39 | ClosedOrdersResponse response; 40 | response.statusCode_ = rawResponse["statusCode"].get(); 41 | response.errors_ = rawResponse["error"].get(); 42 | 43 | auto closedOrders = rawResponse["result"]; 44 | 45 | for (auto it = closedOrders.cbegin(); it != closedOrders.cend(); ++it) { 46 | std::vector orders; 47 | 48 | for (const auto& closedOrder : it.value()) { 49 | ExecutionReport executionReport; 50 | executionReport.avgPx = 51 | std::stold(closedOrder["AvgPx"].get()); 52 | executionReport.lastLiquidityInd = 53 | std::stold(closedOrder["LastLiquidityInd"].get()); 54 | executionReport.lastPx = 55 | std::stold(closedOrder["LastPx"].get()); 56 | executionReport.lastQty = 57 | std::stold(closedOrder["LastQty"].get()); 58 | executionReport.cumQty = 59 | std::stold(closedOrder["cumqty"].get()); 60 | executionReport.fillPrice = 61 | std::stold(closedOrder["fill_price"].get()); 62 | executionReport.leavesQty = 63 | std::stold(closedOrder["leavesqty"].get()); 64 | executionReport.orderQty = 65 | std::stold(closedOrder["orderqty"].get()); 66 | executionReport.price = 67 | std::stold(closedOrder["price"].get()); 68 | executionReport.stopPx = 69 | std::stold(closedOrder["stoppx"].get()); 70 | executionReport.value = 71 | std::stold(closedOrder["value"].get()); 72 | if (closedOrder["ordrejreason"].get().size()) { 73 | executionReport.ordRejReason = 74 | std::stold(closedOrder["ordrejreason"].get()); 75 | } else { 76 | executionReport.ordRejReason = 0; 77 | } 78 | executionReport.ordStatusReqId = 79 | closedOrder["ordstatusReqID"].get(); 80 | executionReport.origcliId = 81 | closedOrder["origclid"].get(); 82 | executionReport.account = closedOrder["account"].get(); 83 | executionReport.clOrdId = closedOrder["clorderid"].get(); 84 | executionReport.instrument = 85 | closedOrder["instrument"].get(); 86 | executionReport.orderId = closedOrder["orderid"].get(); 87 | 88 | executionReport.ordStatus = 89 | closedOrder["ordstatus"].get(); 90 | executionReport.ordType = closedOrder["ordtype"].get(); 91 | executionReport.timeInForce = 92 | closedOrder["time_in_force"].get(); 93 | 94 | executionReport.execId = closedOrder["execid"].get(); 95 | executionReport.execType = 96 | closedOrder["exectype"].get(); 97 | executionReport.expiry = closedOrder["expiry"].get(); 98 | executionReport.side = closedOrder["side"].get(); 99 | 100 | executionReport.timestamp = static_cast( 101 | closedOrder["timestamp"].get()); 102 | executionReport.transactTime = static_cast( 103 | closedOrder["transacttime"].get()); 104 | 105 | executionReport.cancelOnDisconnect = 106 | static_cast(closedOrder["cancelondisconnect"].get()); 107 | 108 | orders.push_back(std::move(executionReport)); 109 | } 110 | response.closedOrders.push_back( 111 | std::make_pair(it.key(), std::move(orders))); 112 | } 113 | return response; 114 | } 115 | }; 116 | 117 | }; // namespace Bitwyre::Rest::Private -------------------------------------------------------------------------------- /cpp/source/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Adds convenience methods, see cmake/cleanCppExtensions.cmake 2 | include(cleanCppExtensions) 3 | 4 | # Creates options to turn on sanitizers, see cmake/sanitizers.cmake 5 | include(sanitizers) 6 | 7 | # Enable helpfull warnings and C++20 for all files 8 | if(MSVC) 9 | add_compile_options(/std:c++17 /W3 /WX ) 10 | else() 11 | add_compile_options(-std=c++17 -Wall -Wextra -Wshadow -Wnon-virtual-dtor -Wunused -pedantic) 12 | endif() 13 | 14 | # configure version.cpp.in with selected version 15 | configure_file ( 16 | "${CMAKE_CURRENT_SOURCE_DIR}/version.cpp.in" 17 | "${CMAKE_CURRENT_BINARY_DIR}/version.cpp" 18 | ) 19 | # If you want to have date and time of the build, your targets has to depend on this. 20 | # This will force recompilation of version.o and thus forcing gcc to update __DATE__ macro. 21 | add_custom_target(versionFileTouchForRebuild 22 | COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_CURRENT_BINARY_DIR}/version.cpp") 23 | 24 | 25 | #------------------------------------------------------------------------------ 26 | # Libraries dependencies 27 | find_package (Threads REQUIRED) #threading 28 | 29 | add_library(bitwyresdk 30 | ${CMAKE_CURRENT_BINARY_DIR}/version.cpp 31 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/public/Time.hpp 32 | ${CMAKE_CURRENT_SOURCE_DIR}/details/Config.hpp 33 | ${CMAKE_CURRENT_SOURCE_DIR}/details/ConstexprMap.hpp 34 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/public/Market.hpp 35 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/public/Product.hpp 36 | ${CMAKE_CURRENT_SOURCE_DIR}/details/Response.hpp 37 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/public/Asset.hpp 38 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/public/CryptoAsset.hpp 39 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/public/FiatAsset.hpp 40 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/public/Instrument.hpp 41 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/public/Ticker.hpp 42 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/public/Trades.hpp 43 | ${CMAKE_CURRENT_SOURCE_DIR}/details/Types.hpp 44 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/public/Depth.hpp 45 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/public/Contract.hpp 46 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/public/Announcements.hpp 47 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/public/OrderTypes.hpp 48 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/public/SupportedLanguages.hpp 49 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/private/AccountBalance.hpp 50 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/private/AccountStatement.hpp 51 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/private/TradesHistory.hpp 52 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/private/CancelOrder.hpp 53 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/private/ClosedOrders.hpp 54 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/private/OrderInfo.hpp 55 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/private/NewOrder.hpp 56 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/private/OpenOrders.hpp 57 | ${CMAKE_CURRENT_SOURCE_DIR}/rest/private/TransactionHistory.hpp 58 | ${CMAKE_CURRENT_SOURCE_DIR}/details/Utils.hpp 59 | ${CMAKE_CURRENT_SOURCE_DIR}/details/Dispatcher.hpp 60 | ${CMAKE_CURRENT_SOURCE_DIR}/version.h) 61 | 62 | add_dependencies(bitwyresdk versionFileTouchForRebuild) # We want precise time of build in version 63 | 64 | target_include_directories( 65 | ${PROJECT_NAME} 66 | ${BITWYRE_SYSTEM_INCLUDE} INTERFACE 67 | $ 68 | $ 69 | ) 70 | 71 | target_link_libraries (bitwyresdk PRIVATE Threads::Threads ${CONAN_LIBS}) 72 | add_library(bitwyresdk::bitwyresdk ALIAS bitwyresdk) 73 | 74 | install( 75 | TARGETS bitwyresdk 76 | EXPORT bitwyresdk 77 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 78 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 79 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 80 | install( 81 | DIRECTORY "${PROJECT_SOURCE_DIR}/source/" 82 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/bitwyresdk" 83 | ) 84 | 85 | file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/version.h 86 | DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) 87 | # Using macro from cmake/cleanCpppExtensions.cpp included on the top 88 | # Provides bitwyresdk-run a nd bitwyresdk-dbg 89 | addRunAndDebugTargets(bitwyresdk) 90 | 91 | # short convenience target from cmake/cleanCpppExtensions.cpp 92 | add_custom_target(run DEPENDS bitwyresdk-run) 93 | 94 | #------------------------------------------------------------------------------ 95 | # Unit tests 96 | if(BUILD_TESTING) 97 | add_subdirectory(unittest) 98 | endif() 99 | #------------------------------------------------------------------------------- 100 | # Copy MINGW needed libraries for building on windows 101 | 102 | if(MINGW) 103 | message(STATUS "MinGW detected") 104 | get_filename_component(GCC_PATH ${CMAKE_C_COMPILER} PATH) 105 | if(${GCC_PATH} MATCHES "mingw64/bin") 106 | set(libgcc "libgcc_s_seh-1.dll") #64bit 107 | message(STATUS " 64bit dlls is building") 108 | else() 109 | set(libgcc "libgcc_s_dw2-1.dll") #32bit 110 | message(STATUS " 32bit dlls is building") 111 | endif() 112 | 113 | install(FILES ${GCC_PATH}/${libgcc} 114 | ${GCC_PATH}/libwinpthread-1.dll 115 | ${GCC_PATH}/libstdc++-6.dll 116 | DESTINATION ./bin/ 117 | ) 118 | endif(MINGW) 119 | 120 | 121 | #------------------------------------------------------------------------------ 122 | # Other MISC targets 123 | 124 | # Adds misc targets: format, cppcheck, tidy, see cmake/cleanCppExtensions.cmake 125 | addMiscTargets() 126 | 127 | 128 | --------------------------------------------------------------------------------