Reputation: 47
I am trying to connect to Krakens api, i am successful in connecting to the api but i get an error: "EAPI: Invalid Key" and "EAPI: Invalid Signature". when i get which error depends on how i edit the raw request, specifically the request headers. when i change the key's key to "API-Key: " instead of how they specified "API-Key" then the issue seems to be resolved but then a they throw "EAPI: Invalid Signature". ill do the same thing for the signature and change it to "API-Signature: " and it changes to "EAPI: Bad Request".i'm not sure why this is happening. i just want my balance to show. code is below! if there is anything else you would need from me please let me know via comments and i will edit the question!
Trade.h":
#pragma warning(disable : 4996)
#include <iostream>
#include <iomanip>
#include <string>
#include <cpr/cpr.h>
#include <nlohmann/json.hpp>
#include <chrono>
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
using namespace std;
using namespace cpr;
using namespace chrono;
using json = nlohmann::json;
class Trade
{
private:
string key;
string secret;
string timestamp;
string signature;
string baseUrl;
string postData;
public:
Trade();
//string signature(const string& path, const string& nonce, const string& postdata) const;
void Authenticate();
void getAccounts();
};
Trade.cpp:
#include "Trade.h"
Trade::Trade() {
key = "xxxxxxxxxxxxxxxx";
secret = "xxxxxxxxxxxxxxxxxxx”
postData = "";
timestamp = "";
signature = "";
baseUrl = "https://api.kraken.com/0/private/Balance";
}
// helper function to decode a base64 string to a vector of bytes:
static std::string b64_decode(const std::string& data)
{
// Create a BIO object to wrap the encoded string
BIO * b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
BIO* bio = BIO_new_mem_buf(data.c_str(), data.size());
bio = BIO_push(b64, bio);
// Create a buffer to hold the decoded string
char buffer[512];
int len;
// Decode the string and write the result to the output buffer
std::string decoded;
while ((len = BIO_read(bio, buffer, sizeof(buffer))) > 0) {
decoded.append(buffer, len);
}
// Clean up the BIO objects
BIO_free_all(bio);
return decoded;
}
//helper function to encode a vector of bytes to a base64 string:
static std::string b64_encode(const std::string& data)
{
// Create a base64 BIO
BIO* b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
// Create a memory BIO to store the output
BIO* mem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, mem);
// Encode the input data
BIO_write(b64, data.c_str(), data.length());
BIO_flush(b64);
// Get the encoded data from the memory BIO
BUF_MEM* mem_buf = NULL;
BIO_get_mem_ptr(b64, &mem_buf);
// Copy the data into a std::string
std::string output(mem_buf->data, mem_buf->length);
// Clean up
BIO_free_all(b64);
return output;
}
// helper function to compute SHA256:
static string sha256(const string& str) {
EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
const EVP_MD* md = EVP_sha256();
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int hash_len;
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, str.c_str(), str.size());
EVP_DigestFinal_ex(mdctx, hash, &hash_len);
EVP_MD_CTX_free(mdctx);
std::stringstream ss;
for (int i = 0; i < hash_len; i++) {
ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(hash[i]);
}
return ss.str();
}
// helper function to hash with HMAC algorithm:
static std::string hmac_sha512(const std::string& data, const std::string& key) {
std::string result;
// Set up the HMAC context
HMAC_CTX* hmac_ctx = HMAC_CTX_new();
HMAC_Init_ex(hmac_ctx, key.c_str(), key.length(), EVP_sha512(), NULL);
// Update the HMAC with the data
HMAC_Update(hmac_ctx, (const unsigned char*)data.c_str(), data.length());
// Finalize the HMAC and get the result
unsigned char hmac_result[EVP_MAX_MD_SIZE];
unsigned int hmac_len;
HMAC_Final(hmac_ctx, hmac_result, &hmac_len);
result.assign((const char*)hmac_result, hmac_len);
// Clean up the HMAC context
HMAC_CTX_free(hmac_ctx);
return result;
}
void Trade::Authenticate() {
//calculate timestamp
const auto p1 = system_clock::now();
unsigned int intTimestamp = duration_cast<seconds>(p1.time_since_epoch()).count();
timestamp = to_string(intTimestamp);
//setting auth variables
string path = "/0/private/Balance";
postData = "nonce=" + timestamp;// +"&asset=xbt";
//sha for timestamp + postdata
string S256 = timestamp + postData;
string timepost = sha256(S256);
string hash = path + timepost;
signature = b64_encode(hmac_sha512(hash, b64_decode(secret)));
}
void Trade::getAccounts() {
//variables
Response r;
Header header;
header.insert({ "API-Key: ", key });
header.insert({ "API-Sign: ", signature });
header.insert({ "User-Agent: ", "Kraken C++ API Client" });
header.insert({ "Content-Type: ", "application/x-www-form-urlencoded" });
r = Post(Url{ baseUrl }, Body{postData}, Header{ header });
cout << "Status Code: " << r.status_code << endl;
cout << r.text << endl;
}
main:
#include<iostream>
#include "Trade.h"
using namespace std;
int main() {
Trade trade;
trade.Authenticate();
trade.getAccounts();
}
Im not sure if this is minimal reproducible code or not but if its an issue please let me know and ill edit it!
My keys are wont be the problem as ive changed them a few times just to make sure they were correct and working as intended and kraken support confirmed my keys were okay.
Upvotes: 1
Views: 450