Skip to content

Commit 96f955a

Browse files
Merge branch '2.5.0' into 'master'
2.5.0 Feat(new and update endpoints) See merge request exchange/code/sdk/bitmart-java-sdk-api!28
2 parents 5ce4517 + 8f1f6f4 commit 96f955a

84 files changed

Lines changed: 2024 additions & 106 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.local.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"permissions": {
3+
"allow": ["Bash(find / -type d -name \"w-sdk-for-*\")"]
4+
}
5+
}

.env.example

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# BitMart Java SDK — local credentials & endpoints for tests/examples.
2+
#
3+
# Copy this file to ".env" in the project root and fill in your values:
4+
# cp .env.example .env
5+
#
6+
# Resolution priority (see com.bitmart.examples.EnvConfig):
7+
# .env file > system environment variable > hardcoded default
8+
#
9+
# ".env" is git-ignored — never commit real credentials.
10+
11+
# API credentials (https://www.bitmart.com -> API Management)
12+
BITMART_API_KEY=your_api_key
13+
BITMART_SECRET_KEY=your_secret_key
14+
BITMART_MEMO=your_memo
15+
16+
# Endpoint (used as both spot & futures host; defaults apply when unset)
17+
BITMART_API_URL=https://api-cloud.bitmart.com

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,9 @@
1818
/.nb-gradle/
1919

2020
### Vscode ###
21-
.vscode
21+
.vscode
22+
23+
### Local credentials ###
24+
# Project-local API credentials / URLs read by tests & examples (see EnvConfig).
25+
# Never commit real keys; copy .env.example to .env and fill in your values.
26+
.env

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,34 @@
22
Changelog
33
=========================
44

5+
### v2.5.0 Release
6+
#### New Features
7+
- New
8+
- `/spot/v4/algo/submit_order` Submit Algo Order(v4) (SIGNED)
9+
- `/spot/v4/algo/cancel_order` Cancel Algo Order(v4) (SIGNED)
10+
- `/spot/v4/algo/cancel_all` Cancel All Algo Orders(v4) (SIGNED)
11+
- `/spot/v4/query/algo/order` Query Algo Order by orderId(v4) (SIGNED)
12+
- `/spot/v4/query/algo/client-order` Query Algo Order by clientOrderId(v4) (SIGNED)
13+
- `/spot/v4/query/algo/open-orders` Query Algo Current Orders(v4) (SIGNED)
14+
- `/spot/v4/query/algo/history-orders` Query Algo History Orders(v4) (SIGNED)
15+
- `/contract/public/funding-rate-v2` Get Current Funding Rate V2
16+
- `/contract/private/auto_repayment` Query Auto Repayment Records (KEYED)
17+
- `/contract/private/cross_collateral/interest_log` Query Interest Accrual Log (KEYED)
18+
- `/contract/private/claim` Claim Demo Assets (SIGNED)
19+
- `/contract/private/affiliate/rebate-inviteUser` Query Invited Users Rebate (KEYED)
20+
- `/contract/private/affiliate/invite-check` Check Invited User (KEYED)
21+
- `/contract/private/affiliate/rebate-user` Query Single User Rebate (KEYED)
22+
- `/contract/private/affiliate/rebate-api` Query Single API User Rebate (KEYED)
23+
- `/contract/private/affiliate/deposit-withdrawal-list` Query Invited Users Deposit And Withdraw (KEYED)
24+
- `/contract/private/affiliate/aff-customer-info` Query Invited User Contract Account Info (KEYED)
25+
- `/contract/private/affiliate/rebate-list` Query Rebate Records (KEYED)
26+
- `/contract/private/affiliate/trade-list` Query Invited Users Trade Records (KEYED)
27+
- `spot/bookTicker:{symbol}` [WebSocket] New public Best Order (bookTicker) channel
28+
- Update
29+
- `/contract/private/trades` Get Order Trade (KEYED): Add new request field **order_id**, **client_order_id**
30+
31+
---
32+
533
### v2.4.0 Release
634
#### New Features
735
- New

CLAUDE.md

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# CLAUDE.md
2+
3+
Guidance for working in this repository.
4+
5+
## Project Overview
6+
7+
`bitmart-java-sdk-api` is the official BitMart Exchange Java client for the
8+
BitMart Cloud API. It wraps BitMart's REST endpoints and WebSocket streams
9+
described in the online docs at <https://developer.bitmart.com/spot> (changelog:
10+
<https://developer-pro.bitmart.com/en/spot/#change-log>).
11+
12+
- **GroupId/ArtifactId:** `io.github.bitmartexchange:bitmart-java-sdk-api`
13+
- **Java:** compiled for Java 8 (`maven.compiler.source/target = 8`)
14+
- **Published to:** Maven Central via the Sonatype Central Portal (`release` profile)
15+
- Current version is the `<version>` in [pom.xml](pom.xml) and the `USER_AGENT`
16+
constant in [Call.java](src/main/java/com/bitmart/api/Call.java). **Keep these
17+
two in sync when bumping the version.**
18+
19+
## Build & Test
20+
21+
```bash
22+
mvn install # build + install to local repo
23+
mvn test # run JUnit 5 tests
24+
mvn package # build the jar
25+
mvn -Prelease deploy # sign (GPG) + publish to Central (release only)
26+
```
27+
28+
Tests live under `src/test/java`:
29+
- `com.bitmart.unit.*` — JUnit 5 unit tests grouped by domain (`api`, `websocket`, `data`).
30+
- `com.bitmart.examples.*` — runnable `main()` examples mirroring the README, one
31+
class per endpoint/stream. These double as living usage documentation.
32+
33+
Many tests/examples need real API credentials (key/secret/memo). They hit live
34+
endpoints, so treat them as integration samples, not pure unit tests.
35+
36+
## Architecture
37+
38+
Two independent subsystems share the auth/key/common code:
39+
40+
### 1. REST client (`com.bitmart.api`)
41+
42+
The flow is **build a Request object → pass it to `Call.callCloud()` → get a `CloudResponse`**.
43+
44+
- [Call.java](src/main/java/com/bitmart/api/Call.java) — the HTTP engine (OkHttp).
45+
Dispatches GET vs POST based on `request.getMethod()`, builds headers, and
46+
wraps the result in `CloudResponse` (raw JSON body + HTTP status + rate-limit
47+
headers `X-BM-RateLimit-*`).
48+
- [CloudContext.java](src/main/java/com/bitmart/api/CloudContext.java) — holds
49+
the base URL, timeouts, custom headers, and the `CloudKey`. Default URL is
50+
`GlobalConst.CLOUD_URL`. Construct with a `CloudKey` for authenticated calls,
51+
or no-arg for public-only.
52+
- [CloudRequest.java](src/main/java/com/bitmart/api/request/CloudRequest.java)
53+
base class for **every** request. Subclasses set `path`, `method`, and `auth`
54+
in their constructor via `super(...)`, and declare parameter fields.
55+
- [Method.java](src/main/java/com/bitmart/api/request/Method.java)`GET`/`POST`.
56+
- [Auth.java](src/main/java/com/bitmart/api/request/Auth.java)`NONE` (public),
57+
`KEYED` (sends `X-BM-KEY` only), `SIGNED` (adds `X-BM-TIMESTAMP` + `X-BM-SIGN`).
58+
59+
### Request parameter mechanism (`@ParamKey` + reflection)
60+
61+
Request classes use Lombok (`@Data @Accessors(chain = true)`) and annotate each
62+
parameter field with
63+
[`@ParamKey(value="...", required=...)`](src/main/java/com/bitmart/api/annotations/ParamKey.java).
64+
At call time,
65+
[`CommonUtils.genRequestMap()`](src/main/java/com/bitmart/api/common/CommonUtils.java)
66+
reflects over the **declared fields of the leaf class only** (it intentionally
67+
does NOT walk superclass fields), builds a sorted `TreeMap` of `key → value`,
68+
skips nulls, and throws `CloudException` if a `required` field is null. Because
69+
only leaf fields are scanned, request subclasses must declare all of their own
70+
params directly — don't push shared params up into a base class expecting them
71+
to be serialized.
72+
73+
- GET: the map becomes a `key=value&...` query string.
74+
- POST: the map is serialized to a JSON body.
75+
76+
The same query/body string is what gets HMAC-signed.
77+
78+
### Signing (`SIGNED` endpoints)
79+
80+
[CloudSignature.java](src/main/java/com/bitmart/api/key/CloudSignature.java)
81+
produces `X-BM-SIGN = HMAC-SHA256(secret, "{timestamp}#{memo}#{payload}")`
82+
(hex-encoded), where `payload` is the query string (GET) or JSON body (POST),
83+
and sets `X-BM-TIMESTAMP` to `System.currentTimeMillis()`.
84+
85+
### Adding a new REST endpoint
86+
87+
1. Create a `*Request` class in the correct package under
88+
`com.bitmart.api.request` (see layout below).
89+
2. Extend `CloudRequest`; in the constructor call
90+
`super("/the/api/path", Method.GET_or_POST, Auth.LEVEL)`.
91+
3. Add fields annotated with `@ParamKey`, plus Lombok annotations
92+
(`@EqualsAndHashCode(callSuper=true) @Data @ToString @Accessors(chain=true)`).
93+
4. Add an example under `src/test/java/com/bitmart/examples/...` and/or a unit test.
94+
95+
### Request package layout (`src/main/java/com/bitmart/api/request`)
96+
97+
Convention: `<domain>/<pub|prv>[/<version>]`, where `pub` = public/unauthenticated
98+
and `prv` = private/authenticated.
99+
100+
- `spot/pub/market` — spot market data, V3 (`V3TickerRequest`, `V3DepthRequest`, `V3HistoryKlineRequest`, …)
101+
- `spot/prv` — spot trading (`SubmitOrderRequest`, `BatchOrdersRequest`, `CancelOrderRequest`, margin orders, …)
102+
- `spot/prv/v4` — V4 signed query endpoints (`V4QueryOpenOrdersRequest`, `V4QueryHistoryOrdersRequest`, trades, …)
103+
- `contract/pub` — futures market data (`DepthRequest`, `KlineRequest`, `FundingRateRequest`, `LeverageBracketRequest`, …)
104+
- `contract/prv` — futures trading/account (orders, plan/tp-sl/trail orders, positions, leverage, transfers, …)
105+
- `account/pub``AccountCurrenciesRequest`
106+
- `account/prv` — wallet, deposit/withdraw, withdraw address, isolated margin transfer, trade-fee
107+
- `margin_loan/prv` — isolated margin borrow/repay + records and pairs
108+
- `system/pub``SystemServiceRequest`, `SystemTimeRequest`
109+
- `broker``BrokerRebateRequest`
110+
111+
### 2. WebSocket client (`com.bitmart.websocket`)
112+
113+
Netty-based WS client supporting four endpoints defined in
114+
[GlobalConst.java](src/main/java/com/bitmart/api/common/GlobalConst.java):
115+
spot public/private and futures public/private (`CLOUD_*_WS_*_URL`).
116+
117+
- [WebSocketClient.java](src/main/java/com/bitmart/websocket/WebSocketClient.java) /
118+
[ContractWebSocket.java](src/main/java/com/bitmart/websocket/ContractWebSocket.java)
119+
connect, auto-reconnect (replaying subscribed channels + re-login), keepalive
120+
(`ping` every 10s), and `login()` for private streams.
121+
- Login signs the literal string `"bitmart.WebSocket"` and sends
122+
`{"op":"login","args":[apiKey, timestamp, sign]}`.
123+
- Subscribe via [OpParam](src/main/java/com/bitmart/websocket/OpParam.java):
124+
`send(new OpParam().setOp("subscribe").setArgs(ImmutableList.of("spot/ticker:BTC_USDT")))`.
125+
- Implement [WebSocketCallBack](src/main/java/com/bitmart/websocket/WebSocketCallBack.java)
126+
`onMessage(String)` to receive frames.
127+
- Channel name constants:
128+
[spot/WebSocketConstant](src/main/java/com/bitmart/websocket/spot/WebSocketConstant.java),
129+
[contract/ContractWebSocketConstant](src/main/java/com/bitmart/websocket/contract/ContractWebSocketConstant.java).
130+
Use `createChannel(channel, symbol)` to build `"channel:symbol"` args.
131+
132+
## Conventions
133+
134+
- **Lombok everywhere.** Request/response/data classes rely on `@Data`,
135+
`@Accessors(chain = true)` (fluent setters return `this`), `@ToString`,
136+
`@EqualsAndHashCode(callSuper = true)`. Setters are chainable by design.
137+
- **No business logic in request classes** — they are pure parameter holders.
138+
All serialization/signing is centralized in `Call` + `CommonUtils` + `CloudSignature`.
139+
- Responses are returned as **raw JSON strings** (`CloudResponse.getResponseContent()`);
140+
the SDK does not deserialize into typed response models.
141+
- Errors surface as `CloudException` (checked).
142+
- Class naming mirrors the API doc endpoint name, with a version prefix
143+
(`V3`/`V4`) where the API is versioned.
144+
145+
## Key dependencies
146+
147+
OkHttp (REST transport), Netty (WebSocket), Gson (JSON), Guava, Apache Commons
148+
(codec/lang3/collections4), SLF4J (logging API), Lombok (provided). Tests:
149+
JUnit Jupiter 5, Logback.

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>io.github.bitmartexchange</groupId>
88
<artifactId>bitmart-java-sdk-api</artifactId>
9-
<version>2.4.0</version>
9+
<version>2.5.0</version>
1010
<packaging>jar</packaging>
1111
<name>${project.groupId}:${project.artifactId}</name>
1212
<description>A Java SDK specially used to call BitMart OpenAPI</description>

src/main/java/com/bitmart/api/Call.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public final class Call {
2020

2121
private final CloudContext cloudContext;
2222
private final OkHttpClient okHttpClient;
23-
private static final String USER_AGENT = "bitmart-java-sdk-api/2.4.0";
23+
private static final String USER_AGENT = "bitmart-java-sdk-api/2.5.0";
2424

2525
private static OkHttpClient createOkHttpClient(CloudContext cloudContext) {
2626
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.bitmart.api.request.contract.prv;
2+
3+
import com.bitmart.api.annotations.ParamKey;
4+
import com.bitmart.api.request.Auth;
5+
import com.bitmart.api.request.CloudRequest;
6+
import com.bitmart.api.request.Method;
7+
import lombok.Data;
8+
import lombok.EqualsAndHashCode;
9+
import lombok.ToString;
10+
import lombok.experimental.Accessors;
11+
12+
/**
13+
* Affiliate — query the total contract assets and equity (in USDT) of an invited user by userId
14+
*/
15+
@EqualsAndHashCode(callSuper = true)
16+
@Data
17+
@ToString
18+
@Accessors(chain = true)
19+
public class AffiliateAffCustomerInfoRequest extends CloudRequest {
20+
21+
/**
22+
* The invited user ID to query
23+
*/
24+
@ParamKey(value = "userId", required = true)
25+
private Long userId;
26+
27+
public AffiliateAffCustomerInfoRequest() {
28+
super("/contract/private/affiliate/aff-customer-info", Method.GET, Auth.KEYED);
29+
}
30+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.bitmart.api.request.contract.prv;
2+
3+
import com.bitmart.api.annotations.ParamKey;
4+
import com.bitmart.api.request.Auth;
5+
import com.bitmart.api.request.CloudRequest;
6+
import com.bitmart.api.request.Method;
7+
import lombok.Data;
8+
import lombok.EqualsAndHashCode;
9+
import lombok.ToString;
10+
import lombok.experimental.Accessors;
11+
12+
/**
13+
* Affiliate — query the deposit and withdrawal records of a specified invited user within a time range
14+
*/
15+
@EqualsAndHashCode(callSuper = true)
16+
@Data
17+
@ToString
18+
@Accessors(chain = true)
19+
public class AffiliateDepositWithdrawalListRequest extends CloudRequest {
20+
21+
/**
22+
* Current page
23+
*/
24+
@ParamKey(value = "page", required = true)
25+
private Integer page;
26+
27+
/**
28+
* Page size
29+
*/
30+
@ParamKey(value = "size", required = true)
31+
private Integer size;
32+
33+
/**
34+
* Optional, 1 deposit, 2 withdraw
35+
*/
36+
@ParamKey("type")
37+
private Integer type;
38+
39+
/**
40+
* Query user CID
41+
*/
42+
@ParamKey(value = "cid", required = true)
43+
private Long cid;
44+
45+
/**
46+
* Start time(Timestamp in Seconds)
47+
*/
48+
@ParamKey(value = "start_time", required = true)
49+
private Long startTime;
50+
51+
/**
52+
* End time(Timestamp in Seconds)
53+
*/
54+
@ParamKey(value = "end_time", required = true)
55+
private Long endTime;
56+
57+
public AffiliateDepositWithdrawalListRequest() {
58+
super("/contract/private/affiliate/deposit-withdrawal-list", Method.GET, Auth.KEYED);
59+
}
60+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.bitmart.api.request.contract.prv;
2+
3+
import com.bitmart.api.annotations.ParamKey;
4+
import com.bitmart.api.request.Auth;
5+
import com.bitmart.api.request.CloudRequest;
6+
import com.bitmart.api.request.Method;
7+
import lombok.Data;
8+
import lombok.EqualsAndHashCode;
9+
import lombok.ToString;
10+
import lombok.experimental.Accessors;
11+
12+
/**
13+
* Affiliate — check whether a user is invited by the affiliate
14+
*/
15+
@EqualsAndHashCode(callSuper = true)
16+
@Data
17+
@ToString
18+
@Accessors(chain = true)
19+
public class AffiliateInviteCheckRequest extends CloudRequest {
20+
21+
/**
22+
* Query user CID
23+
*/
24+
@ParamKey(value = "cid", required = true)
25+
private Long cid;
26+
27+
public AffiliateInviteCheckRequest() {
28+
super("/contract/private/affiliate/invite-check", Method.GET, Auth.KEYED);
29+
}
30+
}

0 commit comments

Comments
 (0)