Java Guide

Prerequisites

Overview

📘

Fireblocks API Java SDK (beta)

Visit this link to try out the new Java SDK beta. Instructions for setup and usage can be found in the Github readme.

Java developers have two options to interact with the Fireblocks API:

  1. Use the Fireblocks API Java SDK (currently in beta)
  2. Use the standard HTTP REST requests when calling the Fireblocks API

In this guide, we explain in detail the setup for the "non-SDK" usage (including signing the JWT token).

Using the Fireblocks API

Install Java 8 or newer

While this guide specifies Java 8 or newer. You can check which version of Java you already have installed by running the following command.

java -version

Learn how to install or update Java to a newer version.

Your First Fireblocks Java program!

Now that you're set up, run a quick check for the API. The script will query existing vaults, create a new vault and then query again to see that the vaults were created.

This Maven-based implementation will require some library dependencies:

📘

Use the correct API Base URL

In the following script, make sure you're using the correct value for baseUrl for your environment:

  • For Sandbox workspaces: https://sandbox-api.fireblocks.io
  • For Mainnet or Testnet workspaces: https://api.fireblocks.io

Learn more about workspace differences.

package com.fireblocks.developers.example;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import java.util.Base64;
import okhttp3.*;
import org.json.JSONObject;
import java.util.concurrent.TimeUnit;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.interfaces.RSAKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Stream;

public class FireblocksSDKExample {

    public FireblocksSDKExample() {
        StringBuilder secretBuilder = new StringBuilder();
        String API_SECRET_PATH = "SECRET_KEY_PATH";
        try (Stream<String> stream = Files.lines(Paths.get(API_SECRET_PATH), StandardCharsets.UTF_8)) {
            stream.forEach(s -> secretBuilder.append(s).append("\n"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        String API_KEY = "API_KEY";
        String BASE_URL = "https://api.fireblocks.io"; // 

        FireblocksHttpClient httpClient = new FireblocksHttpClient(API_KEY, secretBuilder.toString(), BASE_URL);

        JSONObject getVaultsResponse = httpClient.get("/v1/vault/accounts_paged");
        System.out.println(getVaultsResponse.toString(4));

        JSONObject newVaultRequest = new JSONObject().put("name", "MyJavaVault").put("hiddenOnUI", true);
        JSONObject newVaultResponse = httpClient.post("/v1/vault/accounts", newVaultRequest);
        System.out.println(newVaultResponse.toString(4));

    }

    private static class FireblocksHttpClient {

        private String baseUrl = "https://api.fireblocks.io";
        private final String apiKey;

        private final PrivateKey privateKey;
        private final OkHttpClient client;

        public FireblocksHttpClient(String apiKey, String apiSecret) {
            this(apiKey, apiSecret, "https://api.fireblocks.io");
        }

        public FireblocksHttpClient(String apiKey, String apiSecret, String baseUrl) {
            Objects.requireNonNull(apiKey);
            Objects.requireNonNull(apiSecret);
            if (baseUrl != null && !this.baseUrl.equals(baseUrl)) {
                this.baseUrl = baseUrl;
            }
            this.apiKey = apiKey;
            this.client = new OkHttpClient.Builder()
                    .connectTimeout(30, TimeUnit.SECONDS) // Set connection timeout here
                    .build();
            try {
                // Use java.util.Base64 to decode the secret
                byte[] keyBytes = Base64.getDecoder().decode(apiSecret
                        .replace("-----BEGIN PRIVATE KEY-----", "")
                        .replace("-----END PRIVATE KEY-----", "")
                        .replace("\n", ""));
                PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
                KeyFactory factory = KeyFactory.getInstance("RSA");
                this.privateKey = factory.generatePrivate(keySpec);
            } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
                throw new RuntimeException(e);
            }
        }

        public JSONObject get(String path) {
            Request req = new Request.Builder()
                    .url(this.baseUrl + path)
                    .addHeader("X-API-Key", this.apiKey)
                    .addHeader("Authorization", "Bearer " + this.signJwt(path))
                    .build();
            try (Response resp = this.client.newCall(req).execute()) {
                ResponseBody body = resp.body();
                if (body == null) {
                    return new JSONObject();
                }
                return new JSONObject(body.string());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        public JSONObject post(String path, JSONObject data) {
            Request req = new Request.Builder()
                    .url(this.baseUrl + path)
                    .addHeader("X-API-Key", this.apiKey)
                    .addHeader("Authorization", "Bearer " + this.signJwt(path, data.toString()))
                    .post(RequestBody.create(data.toString().getBytes(), MediaType.parse("application/json; charset=utf-8")))
                    .build();
            try (Response resp = this.client.newCall(req).execute()) {
                ResponseBody body = resp.body();
                if (body == null) {
                    return new JSONObject();
                }
                return new JSONObject(body.string());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        private String signJwt(String path) {
            return this.signJwt(path, "");
        }

        private String signJwt(String path, String dataJSONString) {
            String bodyHash;
            try {
                MessageDigest digest = MessageDigest.getInstance("SHA-256");
                digest.update(dataJSONString.getBytes());
                BigInteger number = new BigInteger(1, digest.digest());
                StringBuilder hexString = new StringBuilder(number.toString(16));
                while (hexString.length() < 64) {
                    hexString.insert(0, '0');
                }
                bodyHash = hexString.toString();
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException(e);
            }
            Algorithm algo = Algorithm.RSA256((RSAKey) this.privateKey);
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.SECOND, 55);
            return JWT.create()
                    .withSubject(this.apiKey)
                    .withIssuedAt(new Date())
                    .withExpiresAt(cal.getTime())
                    .withClaim("nonce", UUID.randomUUID().toString())
                    .withClaim("uri", path)
                    .withClaim("bodyHash", bodyHash)
                    .sign(algo);
        }
    }

    public static void main(String[] args) {
        new FireblocksSDKExample();
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.fireblocks.developers.example</groupId>
    <artifactId>FireblocksSDKExample</artifactId>
    <version>1.0.0</version>
    <dependencies>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20220320</version>
        </dependency>
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>4.2.1</version>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.10.0</version>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

</project>

🚧

Warning - Reference only

These examples are not production-ready and are used only for reference.

Please follow our security guidelines for secure API interaction.