Código de exemplo para API REST e WebSocket em Java

Última atualização: 2/04/2025

Introdução

Abaixo está um script de exemplo em Java que pode ser referenciado para a implementação REST e WebSocket da API da Kraken.

Demonstra a seguinte funcionalidade:

  • Endpoints Públicos da API REST

  • Endpoints Privados da API REST

  • Subscrições Públicas da API WebSocket

  • Subscrições Privadas da API WebSocket

Instalação

Para executar localmente, pode copiar/colar o código abaixo.

Note que definir a instrução if de 1 == 0 para 1 == 1 executará o bloco de código específico.

Antes de executar o script, precisa de atualizar o script com as suas Chaves de API Pública e Privada.

Pode descarregar este ficheiro aqui.

Código Java


bash

Bash

import java.net.Socket;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.CountDownLatch;
import java.net.http.WebSocket;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import java.security.MessageDigest;
import java.security.PrivateKey;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;

public class App {

    public static void main(String[] args) throws Exception {
        // TODO: UPDATE WITH YOUR KEYS :)
        String apiPublicKey = "YOUR_PUBLIC_KEY";
        String apiPrivateKey = "YOUR_PRIVATE_KEY";

        try {
            System.out.println("|=========================================|");
            System.out.println("|         KRAKEN.COM JAVA TEST APP          |");
            System.out.println("|=========================================|");
            System.out.println();

            // PUBLIC REST API Examples
            if (1 == 0) {
                CompletableFuture<String> publicResponse;

                String publicEndpoint = "SystemStatus";
                String publicInputParameters = "";

                // MORE PUBLIC REST EXAMPLES
                // *

                // String publicEndpoint = "AssetPairs";
                // String publicInputParameters = "pair=ethusd,xbtusd";

                // String publicEndpoint = "Ticker";
                // String publicInputParameters = "pair=ethusd";

                // String publicEndpoint = "Trades";
                // String publicInputParameters = "pair=ethusd&since=0";

                // *

                publicResponse = QueryPublicEndpoint(publicEndpoint, publicInputParameters);

                while (publicResponse.isDone() == false) {
                    // WAIT
                }

                System.out.println(publicResponse.get());
            }

            // PRIVATE REST API Examples
            if (1 == 0) {
                String privateResponse = "";

                String privateEndpoint = "Balance";
                String privateInputParameters = "";

                // MORE PRIVATE REST EXAMPLES
                // *

                // String privateEndpoint = "AddOrder";
                // String privateInputParameters = "pair=xbteur&type=buy&ordertype=limit&price=1.00&volume=1";

                // String privateEndpoint = "AddOrder"
                // String privateInputParameters = "pair=xdgeur&type=sell&ordertype=limit&volume=3000&price=%2b10.0%" //Positive Percentage Example (%2 represtes +, which is a reseved character in HTTP)

                // String privateEndpoint = "AddOrder"
                // String privateInputParameters = "pair=xdgeur&type=sell&ordertype=limit&volume=3000&price=-10.0%" //Negative Percentage Example

                // String privateEndpoint = "AddOrder"
                // String privateInputParameters = "pair=xdgeur&type=buy&ordertype=market&volume=3000&userref=789" //Userref Example

                // String privateEndpoint = "Balance" //{"error":[]} IS SUCCESS, Means EMPTY BALANCE
                // String privateInputParameters = ""

                // String privateEndpoint = "QueryOrders"
                // String privateInputParameters = "txid=OFUSL6-GXIIT-KZ2JDJ"

                // String privateEndpoint = "AddOrder"
                // String privateInputParameters = "pair=xdgusd&type=buy&ordertype=market&volume=5000"

                // String privateEndpoint = "DepositAddresses"
                // String privateInputParameters = "asset=xbt&method=Bitcoin"

                // String privateEndpoint = "DepositMethods"
                // String privateInputParameters = "asset=eth"

                // String privateEndpoint = "WalletTransfer"
                // String privateInputParameters = "asset=xbt&to=Futures Wallet&from=Spot Wallet&amount=0.0045"

                // String privateEndpoint = "TradesHistory"
                // String privateInputParameters = "start=1577836800&end=1609459200"

                // String privateEndpoint = "GetWebSocketsToken"
                // String privateInputParameters = ""

                // *

                privateResponse = QueryPrivateEndpoint(privateEndpoint, privateInputParameters, apiPublicKey, apiPrivateKey);

                System.out.println(privateResponse);
            }

            // PUBLIC WEBSOCKET Examples
            if (1 == 0) {
                String publicWebSocketURL = "wss://ws.kraken.com/";

                String publicWebSocketSubscriptionMsg = "{ \"event\":\"subscribe\", \"subscription\":{\"name\":\"trade\"},\"pair\":[\"XBT/USD\"] }";

                // MORE PUBLIC WEBSOCKET EXAMPLES
                // *

                // String publicWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"interval\": 1440, \"name\": \"ohlc\"}, \"pair\": [ \"XBT/EUR\" ]}"

                // ;

                // String publicWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"name\": \"spread\"}, \"pair\": [ \"XBT/EUR\",\"ETH/USD\" ]}"

                // ;

                OpenAndStreamWebSocketSubscription(publicWebSocketURL, publicWebSocketSubscriptionMsg);
            }

            // PRIVATE WEBSOCKET Examples
            if (1 == 0) {
                String privateWebSocketURL = "wss://ws-auth.kraken.com/";

                // GET THE WEBSOCKET TOKEN FROM THE JSON RESPONSE

                Object webSocketToken = "";

                String tokenQuery = QueryPrivateEndpoint("GetWebSocketsToken", "", apiPublicKey, apiPrivateKey);

                JsonFactory factory = new JsonFactory();

                ObjectMapper mapper = new ObjectMapper(factory);

                TypeReference<HashMap<String, Object>> typeRef = new TypeReference<HashMap<String, Object>>() {
                };

                HashMap<String, HashMap<String, Object>> o = mapper.readValue(tokenQuery, typeRef);

                webSocketToken = o.get("result").get("token");

                // MORE PRIVATE WEBSOCKET EXAMPLES
                // *

                // String privateWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"name\": \"openOrders\", \"token\": \"" + webSocketToken + "\" }}";

                // String privateWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"name\": \"balances\", \"token\": \"" + webSocketToken + "\" }}";

                // String privateWebSocketSubscriptionMsg = "{ \"event\":\"addOrder\",\"reqid\":1234,\"ordertype\":\"limit\",\"pair\":\"XBT/EUR\",\"token\":\"" + webSocketToken + "\",\"type\":\"buy\",\"volume\":\"1\", \"price\":\"1.00\"}";

                // *

                // REPLACE PLACEHOLDER WITH TOKEN

                String privateWebSocketSubscriptionMsg = "{ \"event\": \"subscribe\", \"subscription\": { \"name\": \"balances\", \"token\": \"" + webSocketToken + "\" }}";

                System.out.println(privateWebSocketSubscriptionMsg);

                OpenAndStreamWebSocketSubscription(privateWebSocketURL, privateWebSocketSubscriptionMsg);
            }

            System.out.println("|=======================================|");
            System.out.println("| END OF PROGRAM - HAVE A GOOD DAY :) |");
            System.out.println("|=======================================|");
            System.out.println("\n");
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    // Public REST API Endpoints
    public static CompletableFuture<String> QueryPublicEndpoint(String endPointName, String inputParameters) {
        CompletableFuture<String> jsonData;

        String baseDomain = "https://api.kraken.com";
        String publicPath = "/0/public/";
        String apiEndpointFullURL = baseDomain + publicPath + endPointName + "?" + inputParameters;

        HttpClient client = HttpClient.newHttpClient();

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(apiEndpointFullURL))
                .build();

        jsonData = client.sendAsync(request, BodyHandlers.ofString())
                .thenApply(HttpResponse::body);

        return jsonData;
    }

    // Private REST API Endpoints
    public static String QueryPrivateEndpoint(String endPointName, String inputParameters, String apiPublicKey, String apiPrivateKey) {
        String responseJson = "";

        String baseDomain = "https://api.kraken.com";
        String privatePath = "/0/private/";

        String apiEndpointFullURL = baseDomain + privatePath + endPointName + "?" + inputParameters;

        String nonce = String.valueOf(System.currentTimeMillis());

        String apiPostBodyData = "nonce=" + nonce + "&" + inputParameters;

        String signature = CreateAuthenticationSignature(apiPrivateKey, privatePath, endPointName, nonce, apiPostBodyData);

        // CREATE HTTP CONNECTION
        try {
            HttpsURLConnection httpConnection = null;

            URL apiUrl = new URL(apiEndpointFullURL);

            httpConnection = (HttpsURLConnection) apiUrl.openConnection();

            httpConnection.setRequestMethod("POST");

            httpConnection.setRequestProperty("API-Key", apiPublicKey);

            httpConnection.setRequestProperty("API-Sign", signature);

            httpConnection.setDoOutput(true);

            DataOutputStream os = new DataOutputStream(httpConnection.getOutputStream());

            os.writeBytes(apiPostBodyData);

            os.flush();

            os.close();

            BufferedReader br = null;

            // GET JSON RESPONSE DATA
            br = new BufferedReader(new InputStreamReader((httpConnection.getInputStream())));

            String line;

            while ((line = br.readLine()) != null) {
                responseJson += line;
            }
        } catch (Exception e) {
            System.out.println(e);
        }

        return responseJson;
    }

    // Authentication Algorithm
    public static String CreateAuthenticationSignature(String apiPrivateKey, String apiPath, String endPointName, String nonce, String apiPostBodyData) {
        try {
            // GET 256 HASH
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update((nonce + apiPostBodyData).getBytes());
            byte[] sha256Hash = md.digest();

            // GET 512 HASH
            Mac mac = Mac.getInstance("HmacSHA512");
            mac.init(new SecretKeySpec(Base64.getDecoder().decode(apiPrivateKey.getBytes()), "HmacSHA512"));
            mac.update((apiPath + endPointName).getBytes());

            // CREATE API SIGNATURE
            String signature = new String(Base64.getEncoder().encodeToString(mac.doFinal(sha256Hash)));

            return signature;
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    // WebSocket API
    public static void OpenAndStreamWebSocketSubscription(String connectionURL, String webSocketSubscription) {
        try {
            CountDownLatch latch = new CountDownLatch(1);

            WebSocket ws = HttpClient
                    .newHttpClient()
                    .newWebSocketBuilder()
                    .buildAsync(URI.create(connectionURL), new WebSocketClient(latch))
                    .join();

            ws.sendText(webSocketSubscription, true);

            latch.await();
        } catch (Exception e) {
            System.out.println();
            System.out.println("AN EXCEPTION OCCURED :(");
            System.out.println(e);
        }
    }

    private static class WebSocketClient implements WebSocket.Listener {
        private final CountDownLatch latch;

        public WebSocketClient(CountDownLatch latch) {
            this.latch = latch;
        }

        @Override
        public void onOpen(WebSocket webSocket) {
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime now = LocalDateTime.now();
            System.out.println(dtf.format(now) + ": " + webSocket.getSubprotocol());
            WebSocket.Listener.super.onOpen(webSocket);
        }

        @Override
        public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime now = LocalDateTime.now();
            System.out.println(dtf.format(now) + ": " + data);
            return WebSocket.Listener.super.onText(webSocket, data, false);
        }

        @Override
        public void onError(WebSocket webSocket, Throwable error) {
            System.out.println("ERROR OCCURED: " + webSocket.toString());
            WebSocket.Listener.super.onError(webSocket, error);
        }
    }
}

Precisa de mais ajuda?