Advanced Binance API Usage: Retrieving Wallet History in Spring Boot

·

2 min read

We will extend our exploration of the Binance API in our Java Spring Boot application.

Account Endpoint and Authentication

The endpoint to retrieve wallet history, or more precisely account information, is a secured endpoint. Unlike the trades data we fetched in the last post, account data is sensitive and requires authentication.

Binance uses an HMAC SHA256 signature, generated from your API Secret. Your API Key and the generated signature will be included in the request header to authenticate yourself.

Updating the BinanceService

Let's update our BinanceService class to include a new method getAccountData(). We'll need a new dependency javax.crypto to generate the signature. Add this dependency to your Maven pom.xml:

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.0</version>
</dependency>

Updated BinanceService:

import okhttp3.*;
import org.springframework.stereotype.Service;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Instant;

@Service
public class BinanceService {
    private final OkHttpClient client;
    private static final String API_URL = "https://api.binance.com";
    private static final String API_KEY = "your-api-key";
    private static final String API_SECRET = "your-api-secret";
    private static final String HMAC_SHA256 = "HmacSHA256";

    public BinanceService() {
        this.client = new OkHttpClient();
    }

    public String getAccountData() throws IOException {
        long timestamp = Instant.now().toEpochMilli();
        String queryString = "timestamp=" + timestamp;
        String signature = hashHmac(queryString, API_SECRET);

        HttpUrl.Builder urlBuilder = HttpUrl.parse(API_URL + "/api/v3/account").newBuilder();
        urlBuilder.addQueryParameter("timestamp", String.valueOf(timestamp));
        urlBuilder.addQueryParameter("signature", signature);

        Request request = new Request.Builder()
                .url(urlBuilder.build())
                .addHeader("X-MBX-APIKEY", API_KEY)
                .build();

        try (Response response = client.newCall(request).execute()) {
            return response.body().string();
        }
    }

    private String hashHmac(String data, String secret) {
        try {
            Mac sha256_HMAC = Mac.getInstance(HMAC_SHA256);
            SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), HMAC_SHA256);
            sha256_HMAC.init(secret_key);
            byte[] raw = sha256_HMAC.doFinal(data.getBytes(StandardCharsets.UTF_8));
            StringBuilder hex = new StringBuilder(2 * raw.length);
            for (byte b : raw) {
                hex.append(String.format("%02x", b));
            }
            return hex.toString();
        } catch (Exception e) {
            throw new RuntimeException("Unable to hash data", e);
        }
    }
}

Of course api-key and api-secret can be used the same that we have in previous post.

Updating the BinanceController

Update our BinanceController to expose the new service as a HTTP endpoint:

javaCopy codeimport org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class BinanceController {

    private final BinanceService binanceService;

    public BinanceController(BinanceService binanceService) {
        this.binanceService = binanceService;
    }

    @GetMapping("/account")
    public String getAccountData() throws IOException {
        return binanceService.getAccountData();
    }
}

If you navigate to http://localhost:8080/account, you should see your account data, including your wallet history.