wizard_draziw
wizard_draziw

Reputation: 515

Access Crypto.Com API with R (translate from Python)

I promise I tried my best but I just couldn't get this to work.

Here's the exact python code from the API Website: https://exchange-docs.crypto.com/spot/index.html?python#digital-signature

import hmac
import hashlib
import json
import requests
import time

API_KEY = "API_KEY"
SECRET_KEY = "SECRET_KEY"

req = {
  "id": 11,
  "method": "private/get-order-detail",
  "api_key": API_KEY,
  "params": {
    "order_id": "337843775021233500",
  },
  "nonce": int(time.time() * 1000)
};

# First ensure the params are alphabetically sorted by key
paramString = ""

if "params" in req:
  for key in sorted(req['params']):
    paramString += key
    paramString += str(req['params'][key])

sigPayload = req['method'] + str(req['id']) + req['api_key'] + paramString + str(req['nonce'])

req['sig'] = hmac.new(
  bytes(str(SECRET_KEY), 'utf-8'),
  msg=bytes(sigPayload, 'utf-8'),
  digestmod=hashlib.sha256
).hexdigest()

I'm not sure if I got anywhere close, but here's what I got but isn't working -- unfortunately I can't for the life of me tell WHAT I'm getting wrong as I just get a generic error message. For example, maybe I'm not formatting my UNIX time the way they want it.. Any ideas, please help!

library(httr)

library(digest)

API_KEY <- "FOO"
SECRET_KEY <- "BAR"

base <- "https://api.crypto.com/v2/"

API.Balance <- function() {
  method <- "private/get-account-summary"
  
  hash<-paste0(method,11,API_KEY,"",ceiling(as.numeric(Sys.time())))
  print(hash)
  hash<-hmac(SECRET_KEY,hash,algo="sha256")
  print(hash)
  
  call1 <- paste0(base,method,"?api_key=",API_KEY,"&sig=",hash)
  print(call1)
  get.req <- GET(call1)
  get.req.txt <- content(get.req, "text",encoding = "UTF-8")
  return(fromJSON(get.req.txt, flatten = TRUE))
}

API.Balance()

This returns:

[1] "private/get-account-summary11FOO5"
[1] "ed19ac611d5342f2cbd93a52c70ce884bbcdb9a4062572b013a494fd2c50fd03"
[1] "https://api.crypto.com/v2/private/get-account-summary?api_key=FOO&sig=ed19ac611d5342f2cbd93a52c70ce884bbcdb9a4062572b013a494fd2c50fd03"
$code
[1] "100001"

$msg
[1] "SYS_ERROR"

So I gave it a few hours but I'm just scratching my head. I know it's something simple I'm missing. Could someone please help me translate the Python approach to R? Thank you.

Upvotes: 1

Views: 788

Answers (1)

wizard_draziw
wizard_draziw

Reputation: 515

Ok I figured it out and for the good of humanity I think I'll post my solution! Complete with sorting params.

I was using a GET instead of a POST and I totally forgot to reinject the hash into the "req" object after it was calculated (and other minor things). Anyway, several hours of tearing out my hair, so you don't have to, you get this:

API.Balance <- function() {
  endpoint <- "private/get-account-summary"
  
  req <- list(
    id=11, #This doesn't matter, you define it
    method=endpoint,
    api_key=API_KEY,
    params=list(
      currency="USDT" #leave blank if no params
    ),
    nonce=floor(as.numeric(Sys.time())*1000)
  )
  
  req$params <- req$params[order(names(req$params))]
  
  params<-""
  for(i in 1:length(req$params)) {
    params=paste0(params,names(req$params)[i])
    params=paste0(params,req$params[[i]])
  }

  hash<-paste0(req$method,
               req$id,
               req$api_key,
               params,
               req$nonce)

  hash<-hmac(SECRET_KEY,
             hash,
             algo="sha256")

  req<-c(req,sig=hash)
  
  response <- POST(url=paste0(base,endpoint),
                     body=req,
                     encode="json")
  
  response.txt <- content(response, "text",encoding = "UTF-8")
  return(fromJSON(response.txt, flatten = TRUE))
}

API.Balance()

Upvotes: 3

Related Questions