Hi, team!
I’ve edited GitHub - binance/binance-signature-examples: Examples of generating HMAC and RSA signature for Binance API C++ example with my data and after running it:
/*
### public data endpoint, call send_public_request #####
get klines
*/
parameters.insert({
{"symbol", "BTCUSDT"},
{"interval", "1d"},
{"limit", "10"}});
sendPublicRequest(curl, "/api/v3/klines", parameters);
/*
get account informtion
if you can see the account details, then the API key/secret is correct
*/
sendSignedRequest(curl, "GET", "/api/v3/account", parameters);
sendPublicRequest function works fine, but
sendSignedRequest function cause an error:
- URL rejected: Malformed input to a URL function
- Closing connection
curl_easy_perform() failed: URL using bad/illegal format or missing URL
, URL rejected: Malformed input to a URL function
Could you please give me a hint what can be the cause of it?
Thanks!
/*
public data endpoint, call send_public_request
get klines
*/
parameters.insert({
{“symbol”, “BTCUSDT”},
{“interval”, “1d”},
{“limit”, “10”}});
sendPublicRequest(curl, “/api/v3/klines”, parameters);
/*
get account information
if you can see the account details, then the API key/secret is correct
*/
// Error: Using ‘parameters’ meant for ‘klines’ endpoint which may not have necessary info for ‘account’ endpoint
// sendSignedRequest(curl, “GET”, “/api/v3/account”, parameters);
// Corrected: Clear or create a new map for appropriate parameters for account information
parameters.clear(); // Correction: Clear existing parameters to ensure correct and relevant data for account endpoint
sendSignedRequest(curl, “GET”, “/api/v3/account”, parameters);
The parameters
map used in the sendPublicRequest
function for the /api/v3/klines
endpoint is reused as-is for the /api/v3/account
endpoint. This might include unwanted parameters for the account endpoint which could cause the malformed URL error.
Before calling sendSignedRequest
, you should clear or recreate the parameters
map to make sure it contains only the necessary and relevant parameters for the account endpoint. In the provided correction, I used parameters.clear()
to empty the map, ensuring that no incorrect or irrelevant parameters are sent in the request to the /api/v3/account
endpoint.
This should resolve the issue of the malformed URL as it ensures that each endpoint receives only the parameters that are appropriate and expected.
1 Like
Yes, I change parameters for /api/v3/account endpoint:
parameters.insert({
{"omitZeroBalances", "true"}}
);
sendSignedRequest(curl, "GET", "/api/v3/account", parameters);
But error stay the same:
- URL rejected: Malformed input to a URL function
- Closing connection
curl_easy_perform() failed: URL using bad/illegal format or missing URL
, URL rejected: Malformed input to a URL function
I think for solve the issue I should URL encode signature.
Try the below example:
#include <curl/curl.h> // Include the CURL library for making HTTP requests
#include // Include map for handling parameters
#include // Standard C++ library for input and output
// Function to URL encode a string
std::string urlencode(const std::string &s) {
CURL *curl = curl_easy_init();
if(curl) {
char *output = curl_easy_escape(curl, s.c_str(), s.length());
if(output) {
std::string encoded(output); // Store the encoded string
curl_free(output); // Free the output string
curl_easy_cleanup(curl); // Clean up the CURL object
return encoded; // Return the encoded string
}
curl_easy_cleanup(curl); // Clean up the CURL object if encoding fails
}
return “”; // Return an empty string if CURL fails to initialize
}
// Function to send a public request using CURL
void sendPublicRequest(CURL *curl, const std::string &url, const std::map<std::string, std::string> ¶ms) {
std::string query_string;
for (const auto ¶m : params) {
if (!query_string.empty()) query_string += “&”; // Separate parameters with &
// Append the encoded key and value to the query string
query_string += urlencode(param.first) + “=” + urlencode(param.second);
}
std::string full_url = url + "?" + query_string; // Construct the full URL
curl_easy_setopt(curl, CURLOPT_URL, full_url.c_str()); // Set the URL for the CURL request
CURLcode res = curl_easy_perform(curl); // Perform the CURL request
if (res != CURLE_OK) {
std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
}
}
int main() {
CURL *curl = curl_easy_init(); // Initialize a CURL object
if(curl) {
std::map<std::string, std::string> parameters; // Map to store API parameters
parameters.insert({“symbol”, “BTCUSDT”});
parameters.insert({“interval”, “1d”});
parameters.insert({“limit”, “10”});
// Send a public API request
sendPublicRequest(curl, "https://api.binance.com/api/v3/klines", parameters);
curl_easy_cleanup(curl); // Clean up the CURL object
}
return 0;
}
Sorry a bit rusty in C++.
1 Like
After I added curl_easy_escape:
std::string getSignature(std::string query) {
std::string signature = encryptWithEd25519(apiSecret.c_str(), query.c_str());
std::unique_ptr<char, decltype(&curl_free)> urlEncodedSignatureUnqPtr{
curl_easy_escape(curl, signature.c_str(), signature.length())
, curl_free
};
std::string urlEncodedSignature(urlEncodedSignatureUnqPtr.get());
return "&signature=" + urlEncodedSignature;
}
I’ve got an error:
< HTTP/2 400
- Connection #0 to host api.binance.com left intact
{
“code” : -1022,
“msg” : “Signature for this request is not valid.”
}
Final URL is :
https://api.binance.com/api/v3/account?omitZeroBalances=true×tamp=1725370200382&signature=vt5hWNQCpie5m%2BOwCu9Wxch3x1yipmD9s1dSu6aazTOqzbXEzOJLgDPM4E%2F4SVod
2I1%2BLEQ4aM0NTZUIf7RXDg%3D%3D
After I removing any newlines that would normally be inserted every 64 characters by OpenSSL base64 encoding, my version of https://github.com/binance/binance-signature-examples.git started to work fine:
std::string getSignature(std::string query) {
std::string signature = encryptWithEd25519(apiSecret.c_str(), query.c_str());
signature.erase(std::remove_if(signature.begin(), signature.end()
, [](char c) {
return c == '\n' || c == '\r';
}
)
, signature.end()
);
return "&signature=" + signature;
}
@Asheesh_Kumar thanks for your help!