// Path: src/main/java/com/github/sbouclier/utils/Base64Utils.java
// public final class Base64Utils {
// 
//     /**
//      * Private constructor
//      */
//     private Base64Utils() {
//         throw new UnsupportedOperationException();
//     }
// 
//     /**
//      * Decode from Base64
//      *
//      * @param input data to decode
//      * @return decoded data
//      */
//     public static byte[] base64Decode(String input) {
//         return Base64.getDecoder().decode(input);
//     }
// 
//     /**
//      * Encode into Base64
//      *
//      * @param data to encode
//      * @return encoded data
//      */
//     public static String base64Encode(byte[] data) {
//         return Base64.getEncoder().encodeToString(data);
//     }
// }
// 
// Path: src/main/java/com/github/sbouclier/utils/ByteUtils.java
// public class ByteUtils {
// 
//     private static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
// 
//     /**
//      * Private constructor
//      */
//     private ByteUtils() {
//         throw new UnsupportedOperationException();
//     }
// 
//     /**
//      * Convert string to bytes using UTF-8 charset
//      *
//      * @param input to convert
//      * @return converted string to bytes array
//      */
//     public static byte[] stringToBytes(String input) {
//         return input.getBytes(UTF8_CHARSET);
//     }
// 
//     /**
//      * Convert bytes array to string using UTF-8 charset
//      *
//      * @param bytes array to convert
//      * @return converted bytes array to string
//      */
//     public static String bytesToString(byte[] bytes) {
//         return new String(bytes, UTF8_CHARSET);
//     }
// 
//     /**
//      * Concatenate arrays of bytes into one
//      *
//      * @param a first array
//      * @param b second array
//      * @return array of bytes concatenated
//      */
//     public static byte[] concatArrays(byte[] a, byte[] b) throws IOException {
//         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//         outputStream.write(a);
//         outputStream.write(b);
// 
//         return outputStream.toByteArray();
//     }
// }
// 
// Path: src/main/java/com/github/sbouclier/utils/CryptoUtils.java
// public class CryptoUtils {
// 
//     /**
//      * Private constructor
//      */
//     private CryptoUtils() {
//         throw new UnsupportedOperationException();
//     }
// 
//     /**
//      * Encode message to SHA-256 cryptographic hash algorithm
//      *
//      * @param message to encod
//      * @return message encoded
//      * @throws NoSuchAlgorithmException
//      */
//     public static byte[] sha256(String message) throws NoSuchAlgorithmException {
//         MessageDigest md = MessageDigest.getInstance("SHA-256");
//         return md.digest(ByteUtils.stringToBytes(message));
//     }
// 
//     /**
//      * Compute HMAC-SHA512 with secret key
//      *
//      * @param key     secret key
//      * @param message to encod
//      * @return generated HMAC-SHA512
//      * @throws InvalidKeyException
//      * @throws NoSuchAlgorithmException
//      */
//     public static byte[] hmacSha512(byte[] key, byte[] message) throws InvalidKeyException, NoSuchAlgorithmException {
//         Mac mac = Mac.getInstance("HmacSHA512");
//         mac.init(new SecretKeySpec(key, "HmacSHA512"));
//         return mac.doFinal(message);
//     }
// }


import com.github.sbouclier.utils.Base64Utils;
import com.github.sbouclier.utils.ByteUtils;
import com.github.sbouclier.utils.CryptoUtils;
import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.util.Map;
    private String buildPostData(Map<String, String> params, String nonce) {
        final StringBuilder postData = new StringBuilder();
        if (params != null && !params.isEmpty()) {
            params.forEach((k, v) -> {
                postData.append(k).append("=").append(v).append("&");
            });
        }
        postData.append("nonce=").append(nonce);
        return postData.toString();
    }

    public String generateNonce() {
        return String.valueOf(System.currentTimeMillis() * 1000);
    }

    /**
     * Generate signature
     *
     * @param path     URI path
     * @param nonce
     * @param postData POST data
     * @return generated signature
     * @throws KrakenApiException
     */
    private String generateSignature(String path, String nonce, String postData) throws KrakenApiException {
        // Algorithm: HMAC-SHA512 of (URI path + SHA256(nonce + POST data)) and base64 decoded secret API key

        String hmacDigest = null;

        try {
// Path: src/main/java/com/github/sbouclier/utils/Base64Utils.java
// public final class Base64Utils {
// 
//     /**
//      * Private constructor
//      */
//     private Base64Utils() {
//         throw new UnsupportedOperationException();
//     }
// 
//     /**
//      * Decode from Base64
//      *
//      * @param input data to decode
//      * @return decoded data
//      */
//     public static byte[] base64Decode(String input) {
//         return Base64.getDecoder().decode(input);
//     }
// 
//     /**
//      * Encode into Base64
//      *
//      * @param data to encode
//      * @return encoded data
//      */
//     public static String base64Encode(byte[] data) {
//         return Base64.getEncoder().encodeToString(data);
//     }
// }
// 
// Path: src/main/java/com/github/sbouclier/utils/ByteUtils.java
// public class ByteUtils {
// 
//     private static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
// 
//     /**
//      * Private constructor
//      */
//     private ByteUtils() {
//         throw new UnsupportedOperationException();
//     }
// 
//     /**
//      * Convert string to bytes using UTF-8 charset
//      *
//      * @param input to convert
//      * @return converted string to bytes array
//      */
//     public static byte[] stringToBytes(String input) {
//         return input.getBytes(UTF8_CHARSET);
//     }
// 
//     /**
//      * Convert bytes array to string using UTF-8 charset
//      *
//      * @param bytes array to convert
//      * @return converted bytes array to string
//      */
//     public static String bytesToString(byte[] bytes) {
//         return new String(bytes, UTF8_CHARSET);
//     }
// 
//     /**
//      * Concatenate arrays of bytes into one
//      *
//      * @param a first array
//      * @param b second array
//      * @return array of bytes concatenated
//      */
//     public static byte[] concatArrays(byte[] a, byte[] b) throws IOException {
//         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//         outputStream.write(a);
//         outputStream.write(b);
// 
//         return outputStream.toByteArray();
//     }
// }
// 
// Path: src/main/java/com/github/sbouclier/utils/CryptoUtils.java
// public class CryptoUtils {
// 
//     /**
//      * Private constructor
//      */
//     private CryptoUtils() {
//         throw new UnsupportedOperationException();
//     }
// 
//     /**
//      * Encode message to SHA-256 cryptographic hash algorithm
//      *
//      * @param message to encod
//      * @return message encoded
//      * @throws NoSuchAlgorithmException
//      */
//     public static byte[] sha256(String message) throws NoSuchAlgorithmException {
//         MessageDigest md = MessageDigest.getInstance("SHA-256");
//         return md.digest(ByteUtils.stringToBytes(message));
//     }
// 
//     /**
//      * Compute HMAC-SHA512 with secret key
//      *
//      * @param key     secret key
//      * @param message to encod
//      * @return generated HMAC-SHA512
//      * @throws InvalidKeyException
//      * @throws NoSuchAlgorithmException
//      */
//     public static byte[] hmacSha512(byte[] key, byte[] message) throws InvalidKeyException, NoSuchAlgorithmException {
//         Mac mac = Mac.getInstance("HmacSHA512");
//         mac.init(new SecretKeySpec(key, "HmacSHA512"));
//         return mac.doFinal(message);
//     }
// }


// Path: src/main/java/com/github/sbouclier/HttpJsonClient.java
import com.github.sbouclier.utils.Base64Utils;
import com.github.sbouclier.utils.ByteUtils;
import com.github.sbouclier.utils.CryptoUtils;
import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.util.Map;

    private String buildPostData(Map<String, String> params, String nonce) {
        final StringBuilder postData = new StringBuilder();
        if (params != null && !params.isEmpty()) {
            params.forEach((k, v) -> {
                postData.append(k).append("=").append(v).append("&");
            });
        }
        postData.append("nonce=").append(nonce);
        return postData.toString();
    }

    public String generateNonce() {
        return String.valueOf(System.currentTimeMillis() * 1000);
    }

    /**
     * Generate signature
     *
     * @param path     URI path
     * @param nonce
     * @param postData POST data
     * @return generated signature
     * @throws KrakenApiException
     */
    private String generateSignature(String path, String nonce, String postData) throws KrakenApiException {
        // Algorithm: HMAC-SHA512 of (URI path + SHA256(nonce + POST data)) and base64 decoded secret API key

        String hmacDigest = null;

        try {
            byte[] bytePath = ByteUtils.stringToBytes(path);