在R中实现Bitfinex API身份认证遇阻求助
Hey there! Let’s break down why you might be stuck replicating that Bitfinex API auth flow in R, especially since you’ve got a working Python example to reference. Here are the most common pitfalls and actionable fixes to get you up and running:
1. HMAC Signature Mismatches (The #1 Culprit)
Bitfinex relies on HMAC-SHA384 signatures, and R and Python handle string-to-byte conversions differently by default. In Python, you’re probably encoding your payload and secret to bytes explicitly—but in R, you need to be intentional about converting strings to raw bytes before generating the signature.
For example, in your Python code you might have something like:
signature = hmac.new(api_secret.encode(), payload.encode(), hashlib.sha384).hexdigest()
In R, replicate this with the digest package by using charToRaw() for both the secret and payload JSON:
signature <- digest::hmac( key = charToRaw(api_secret), object = charToRaw(payload_json), algo = "sha384", raw = FALSE )
Skipping the charToRaw() step will generate an incorrect signature every time.
2. Payload JSON Formatting That Doesn’t Match Python
Bitfinex is strict about the exact structure of the payload JSON—even extra spaces or out-of-order keys will break authentication. Here’s how to mirror your Python payload in R:
- Use
jsonlite::toJSON()withauto_unbox = TRUE(to handle scalar values likenoncecorrectly) andpretty = FALSE(to avoid extra whitespace). - Ensure the order of keys matches your Python code (e.g.,
requestfirst, thennonce). - Generate the
nonceas a string of milliseconds (not a numeric value—this avoids scientific notation issues).
Example payload setup:
payload <- list( request = "/v1/balances", # Match the endpoint in your Python example nonce = as.character(as.integer(Sys.time() * 1000)) ) payload_json <- jsonlite::toJSON(payload, auto_unbox = TRUE, pretty = FALSE, json_verbatim = TRUE)
3. Misplacing the Payload (Headers vs. Request Body)
A common mistake is putting the payload in the request body instead of the headers. Bitfinex expects the base64-encoded payload in the X-BFX-PAYLOAD header, not in the POST body. Here’s how to set up your headers correctly in R:
headers <- c( "X-BFX-APIKEY" = "YOUR_API_KEY", "X-BFX-PAYLOAD" = base64enc::base64encode(charToRaw(payload_json)), "X-BFX-SIGNATURE" = signature )
Then send your request with httr::POST() without a body:
response <- httr::POST( url = "https://api.bitfinex.com/v1/balances", httr::add_headers(.headers = headers) )
4. Debugging to Pinpoint Exact Issues
If you’re still stuck, compare every step between Python and R to find discrepancies:
- Print the raw payload JSON in both languages—they should be identical (no extra spaces, same key order).
- Compare the base64-encoded payload string.
- Check the HMAC signature output—even one character off means your signature logic is wrong.
- Use
httr::content(response, "text")to read Bitfinex’s error message—they’ll often tell you if it’s a bad signature, invalid nonce, or missing header.
Full Working Example
Here’s a complete, minimal R script that mirrors the standard Bitfinex auth flow:
library(httr) library(jsonlite) library(digest) library(base64enc) # Replace with your actual credentials api_key <- "YOUR_BITFINEX_API_KEY" api_secret <- "YOUR_BITFINEX_API_SECRET" # 1. Generate valid nonce (millisecond timestamp as string) nonce <- as.character(as.integer(Sys.time() * 1000)) # 2. Build payload JSON payload <- list( request = "/v1/balances", nonce = nonce ) payload_json <- toJSON(payload, auto_unbox = TRUE, pretty = FALSE, json_verbatim = TRUE) # 3. Generate HMAC-SHA384 signature signature <- hmac( key = charToRaw(api_secret), object = charToRaw(payload_json), algo = "sha384", raw = FALSE ) # 4. Set up request headers headers <- c( "X-BFX-APIKEY" = api_key, "X-BFX-PAYLOAD" = base64encode(charToRaw(payload_json)), "X-BFX-SIGNATURE" = signature ) # 5. Send authenticated request response <- POST( url = "https://api.bitfinex.com/v1/balances", add_headers(.headers = headers) ) # Check results cat("Status Code:", status_code(response), "\n") cat("Response:", content(response, "text"), "\n")
If you’re still hitting errors, share the exact error message from Bitfinex and any differences you see between your Python and R payload/signature values—I’ll help you narrow it down further!
内容的提问来源于stack exchange,提问作者Davis

