{"id":28435930,"url":"https://github.com/larscom/bitvavo-java","last_synced_at":"2025-10-04T02:29:55.347Z","repository":{"id":294401477,"uuid":"984021502","full_name":"larscom/bitvavo-java","owner":"larscom","description":"Java library to interact with the Bitvavo platform using the Bitvavo v2 API","archived":false,"fork":false,"pushed_at":"2025-09-09T21:05:49.000Z","size":156,"stargazers_count":1,"open_issues_count":13,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-10T00:55:51.447Z","etag":null,"topics":["api","async","bitvavo","crypto","cryptocurrency","exchange","http","java","reactive","rest","websockets","ws"],"latest_commit_sha":null,"homepage":"https://central.sonatype.com/artifact/io.github.larscom/bitvavo-java","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/larscom.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-15T09:19:45.000Z","updated_at":"2025-09-09T21:05:36.000Z","dependencies_parsed_at":"2025-07-21T21:06:29.829Z","dependency_job_id":"3c919f79-6735-4b43-9abe-ad4508d75634","html_url":"https://github.com/larscom/bitvavo-java","commit_stats":null,"previous_names":["larscom/bitvavo-java"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/larscom/bitvavo-java","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/larscom%2Fbitvavo-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/larscom%2Fbitvavo-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/larscom%2Fbitvavo-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/larscom%2Fbitvavo-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/larscom","download_url":"https://codeload.github.com/larscom/bitvavo-java/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/larscom%2Fbitvavo-java/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278254713,"owners_count":25956662,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-04T02:00:05.491Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","async","bitvavo","crypto","cryptocurrency","exchange","http","java","reactive","rest","websockets","ws"],"created_at":"2025-06-05T21:09:23.159Z","updated_at":"2025-10-04T02:29:55.342Z","avatar_url":"https://github.com/larscom.png","language":"Java","readme":"# Bitvavo Java\n\n![Maven Central Version](https://img.shields.io/maven-central/v/io.github.larscom/bitvavo-java)\n[![workflow](https://github.com/larscom/bitvavo-java/actions/workflows/workflow.yml/badge.svg)](https://github.com/larscom/bitvavo-java/actions/workflows/workflow.yml)\n[![License MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nReactive `non-blocking` Java `21` library to interact with the Bitvavo platform using the Bitvavo v2 API (\nsee: https://docs.bitvavo.com)\n\n\u003e [!NOTE]\n\u003e This library is in development and breaking changes may be made up until a 1.0 release.\n\n## ✨ Features\n\n- **Reactive WebSocket Client**: Listen to all events occurring on the Bitvavo platform (tickers, tickers24h, candles,\n  books, trades, orders, fills)\n    - **Automatic Reconnect**: The `ReactiveWebSocketClient` keeps you connected at all times.\n    - **Read Only**: The `ReactiveWebSocketClient` is `read-only`, meaning you can only receive data via the websocket.\n    - **Reactive**: The `ReactiveWebSocketClient` is `reactive` and `non-blocking`, it\n      uses [RxJava](https://github.com/ReactiveX/RxJava) under the hood.\n\n- **Reactive Http Client**:  You can do things like placing orders or withdraw assets from your account.\n    - **Read / Write**: The http client allows you to receive data and send data.\n    - **Non Blocking**: By default, http calls don't block unless you tell to do so.\n\n## 📦 Installation\n\n\u003e **Note**: Minimum version of `Java 21` is required.\n\nAdd `bitvavo-java` to your `pom.xml`:\n\n```xml\n\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.larscom\u003c/groupId\u003e\n    \u003cartifactId\u003ebitvavo-java\u003c/artifactId\u003e\n    \u003cversion\u003e0.1.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## 🔧 Usage\n\n### WebSocket Client\n\nHere's a quick example to get you started with the websocket client:\n\n```java\nimport io.github.larscom.bitvavo.websocket.channel.Channel;\nimport io.github.larscom.bitvavo.websocket.channel.ChannelName;\nimport io.github.larscom.bitvavo.websocket.client.PublicApi;\nimport io.github.larscom.bitvavo.websocket.client.ReactiveWebSocketClient;\n\nimport java.util.Set;\n\nclass Main {\n\n    public static void main(final String[] args) throws InterruptedException {\n        // creates a public client, only contains public endpoints\n        final PublicApi client = ReactiveWebSocketClient.newPublic();\n\n        final Channel channel = Channel.builder()\n            .name(ChannelName.TICKER)\n            .markets(Set.of(\"ETH-EUR\", \"BTC-EUR\", \"POLYX-EUR\", \"APT-EUR\", \"VANRY-EUR\"))\n            .build();\n\n        // you can call this function mutliple times to subscribe to more markets at a later moment.\n        client.subscribe(Set.of(channel));\n\n        // receive errors, mostly for debug purposes\n        client.errors().subscribe(System.out::println);\n\n        // receive data\n        client.tickers().subscribe(System.out::println);\n\n        // keep this thread alive\n        Thread.currentThread().join();\n    }\n}\n```\n\n### Http Client\n\nHere's a quick example to get you started with the http client:\n\n```java\nimport io.github.larscom.bitvavo.http.client.PublicApi;\nimport io.github.larscom.bitvavo.http.client.ReactiveHttpClient;\n\n\nclass Main {\n    public static void main(final String[] args) throws InterruptedException {\n        final PublicApi client = ReactiveHttpClient.newPublic();\n\n        // non-blocking, see examples if you need a blocking call.\n        client.getMarkets().subscribe((markets, throwable) -\u003e {\n            System.out.println(markets);\n        });\n\n        // keep this thread alive        \n        Thread.currentThread().join();\n    }\n}\n```\n\n## 📚 Examples WebSocket\n\n### Authentication\n\nSubscribing to `orders` and `fills` requires authentication (`api key` / `api secret`) which you can setup\nin [Bitvavo](https://account.bitvavo.com/user/api)\n\n```java\nimport io.github.larscom.bitvavo.websocket.channel.Channel;\nimport io.github.larscom.bitvavo.websocket.channel.ChannelName;\nimport io.github.larscom.bitvavo.account.Credentials;\nimport io.github.larscom.bitvavo.websocket.client.PrivateApi;\nimport io.github.larscom.bitvavo.websocket.client.ReactiveWebSocketClient;\n\nimport java.util.Set;\n\nclass Main {\n\n    public static void main(final String[] args) throws InterruptedException {\n        // create credentials\n        final Credentials credentials = new Credentials(\"MY_API_KEY\", \"MY_API_SECRET\");\n\n        // create a private client (it contains all public endpoints as well)\n        final PrivateApi client = ReactiveWebSocketClient.newPrivate(credentials);\n\n        final Channel channel = Channel.builder()\n            .name(ChannelName.ACCOUNT)\n            .markets(Set.of(\"ETH-EUR\", \"BTC-EUR\"))\n            .build();\n\n        client.subscribe(Set.of(channel));\n\n        // receive errors, mostly for debug purposes\n        client.errors().subscribe(System.out::println);\n\n        // receive private data\n        client.orders().subscribe(System.out::println);\n        client.fills().subscribe(System.out::println);\n\n        Thread.currentThread().join();\n    }\n}\n```\n\n### Proxy\n\nIf you need a proxy you can simply pass a `java.net.Proxy` object.\n\n```java\nimport io.github.larscom.bitvavo.websocket.channel.Channel;\nimport io.github.larscom.bitvavo.websocket.channel.ChannelName;\nimport io.github.larscom.bitvavo.websocket.client.PublicApi;\nimport io.github.larscom.bitvavo.websocket.client.ReactiveWebSocketClient;\n\nimport java.net.InetSocketAddress;\nimport java.net.Proxy;\nimport java.util.Set;\n\nclass Main {\n\n    public static void main(final String[] args) throws InterruptedException {\n        final Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(\"proxy.example.com\", 8080));\n\n        // pass the proxy\n        final PublicApi client = ReactiveWebSocketClient.newPublic(proxy);\n\n        final Channel channel = Channel.builder()\n            .name(ChannelName.TICKER)\n            .markets(Set.of(\"ETH-EUR\", \"BTC-EUR\", \"POLYX-EUR\", \"APT-EUR\", \"VANRY-EUR\"))\n            .build();\n\n        client.subscribe(Set.of(channel));\n\n        // receive errors, mostly for debug purposes\n        client.errors().subscribe(System.out::println);\n\n        // receive data\n        client.tickers().subscribe(System.out::println);\n\n        // keep this thread alive\n        Thread.currentThread().join();\n    }\n}\n```\n\n### Single Stream\n\nIf you want to handle multiple events in a single stream you can use `instanceof`\n\n```java\nimport io.github.larscom.bitvavo.websocket.channel.ChannelName;\nimport io.github.larscom.bitvavo.websocket.channel.Channel;\nimport io.github.larscom.bitvavo.websocket.book.Book;\nimport io.github.larscom.bitvavo.websocket.client.PublicApi;\nimport io.github.larscom.bitvavo.websocket.client.ReactiveWebSocketClient;\nimport io.github.larscom.bitvavo.websocket.ticker.Ticker;\n\nimport java.util.Set;\n\nclass Main {\n\n    public static void main(final String[] args) throws InterruptedException {\n        final PublicApi client = ReactiveWebSocketClient.newPublic();\n\n        final Set\u003cChannel\u003e channels = Set.of(\n            Channel.builder().name(ChannelName.TICKER).markets(Set.of(\"ETH-EUR\")).build(),\n            Channel.builder().name(ChannelName.BOOK).markets(Set.of(\"ETH-EUR\")).build()\n        );\n\n        client.subscribe(channels);\n\n        // single stream to handle all message types.\n        client.messages().subscribe(messageIn -\u003e {\n            if (messageIn instanceof final Ticker ticker) {\n                System.out.println(\"Ticker: \" + ticker);\n            }\n\n            if (messageIn instanceof final Book book) {\n                System.out.println(\"Book: \" + book);\n            }\n        });\n\n        // keep this thread alive\n        Thread.currentThread().join();\n    }\n}\n```\n\n## 📚 Examples Http\n\n### Authentication\n\n```java\nimport io.github.larscom.bitvavo.account.Credentials;\nimport io.github.larscom.bitvavo.http.client.PrivateApi;\nimport io.github.larscom.bitvavo.http.client.ReactiveHttpClient;\n\n\nclass Main {\n\n    public static void main(final String[] args) throws InterruptedException {\n        // create credentials\n        final Credentials credentials = new Credentials(\"MY_API_KEY\", \"MY_API_SECRET\");\n\n        final PrivateApi client = ReactiveHttpClient.newPrivate(credentials);\n\n        client.getBalance().subscribe((balance, throwable) -\u003e {\n            System.out.println(balance);\n        });\n\n        Thread.currentThread().join();\n    }\n}\n```\n\n### Proxy\n\n```java\nimport io.github.larscom.bitvavo.http.client.PublicApi;\nimport io.github.larscom.bitvavo.http.client.ReactiveHttpClient;\n\nimport java.net.InetSocketAddress;\n\n\nclass Main {\n    \n    public static void main(final String[] args) throws InterruptedException {\n        final PublicApi client = ReactiveHttpClient.newPublic(new InetSocketAddress(\"proxy.example.com\", 8080));\n\n        client.getMarkets().subscribe((markets, throwable) -\u003e {\n            System.out.println(markets);\n        });\n\n        Thread.currentThread().join();\n    }\n}\n```\n\n### Blocking call\n\n```java\nimport io.github.larscom.bitvavo.http.client.PublicApi;\nimport io.github.larscom.bitvavo.http.client.ReactiveHttpClient;\nimport io.github.larscom.bitvavo.http.market.Market;\n\nimport java.util.List;\n\n\nclass Main {\n    \n    public static void main(final String[] args) {\n        final PublicApi client = ReactiveHttpClient.newPublic();\n\n        final List\u003cMarket\u003e markets = client.getMarkets().blockingGet();\n        System.out.println(markets);\n\n    }\n}\n```\n\n### Running The Example\n\nThere is an `Example.java` file in this repository which you can run using the following command:\n\n```sh\nmvn exec:java\n```\n\nThe example subscribes to all available (public) channels (tickers, tickers24h, candles,\nbooks, trades)\n\n## License\n\nCopyright (c) 2025 Lars Kniep\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n---\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flarscom%2Fbitvavo-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flarscom%2Fbitvavo-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flarscom%2Fbitvavo-java/lists"}