0
votes

I am trying to connect to the coinspot API which has very shoddy documentation. Link below:

https://www.coinspot.com.au/api

It requires an HMAC SHA512 hash attached to the user's secret key, then a nonce key In the parameters of a POST request which is a timestamp turned to an integer to stay unique at each request. The header requires both the API key and the signature.

I use Alamofire's JSON encoded post request through coinspot's private API URL https://www.coinspot.com.au/api

Seems I get a success message for connecting but get an {status = invalid;} response.

The only 2 things I can think of are a wrong POST request (which doesn't seem the case, as if I don't add the nonce key in the parameters, I get a proper response requesting for one from the server), and the HMAC SHA-512 hash. I've taken the code from HMAC SHA512 using CommonCrypto in Swift 3.1

And modified it slightly to just include the SHA512 hashing.

Code below:

extension String{

    var sha512:String{
         return HMAC.hash(inp: self, algo: HMACAlgo.SHA512)
    }
}

public struct HMAC{

    static  func hash(inp: String, algo: HMACAlgo)->String{
        if  let stringData = inp.data(using: String.Encoding.utf8, allowLossyConversion: false){
            return hexStringFromData(input: digest(input: stringData as NSData, algo: algo))
        }
        return ""
    }

    private  static  func digest(input: NSData, algo: HMACAlgo)-> NSData{
        let digestLength = algo.digestLength()
        var hash = [UInt8](repeating: 0, count: digestLength)
        CC_SHA512(input.bytes, UInt32(input.length), &hash)
        return  NSData(bytes: hash, length: digestLength)
    }

    private  static  func hexStringFromData(input: NSData)-> String{
        var bytes = [UInt8](repeating: 0, count: input.length)
        input.getBytes(&bytes, length: input.length)
        var hexString = ""
        for byte in bytes{
            hexString += String(format: "%02x", UInt8(byte))
        }
        return hexString
    }
}

enum HMACAlgo{
    case SHA512

    func digestLength()->Int{
        var result:CInt = 0
        switch self{
        case .SHA512:
            result = CC_SHA512_DIGEST_LENGTH
        }
        return Int(result)
    }
}

The CommonCrypto library has been properly added with an objectiveC bridging file, and printing the result gives me a proper hashed signature.

I've contacted coinspot but they are swarmed with requests and they only have a cookie template response in regards to any technical support for their API.

Here's the Alamofire segment I placed under a function to call any command to the coinspot server:

    func request(_ command: Router, params: [String: AnyObject]?, completion: @escaping (Result<JSON>)-> Void){
        var parameters = ["nonce": Int(Date().timeIntervalSince1970*1000) as AnyObject]
        if params != nil{
            parameters = parameters + params!
        }
let sign = customerSecret.sha512
        print(sign)
        let headers:HTTPHeaders = ["key": APIKey, "sign": sign]
        do{
            try Alamofire.request( command.asURL(), method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: headers).responseJSON{(response) in
                guard let json = response.result.value else {
                    completion(.failure(CoinSpotError.networkError(error: response.result.error)))
                    return
                }
                print(response)
            }
        } catch {
            print("error")
        }
    }

I think the above is correct. Router is just a set of addresses that call to the proper POST request for retrieving data.

Finally, I've changed the request to GET, got rid of both headers and parameters, and I get a status ok and the resulting JSON. I figured I'll just try a command on a browser and it worked,

The API does say every request must be a post method.

1

1 Answers

0
votes

Coinspot API is down, with no ETA: Coinbase API down

I continue to receive {'status': 'invalid'} back from any request I make.

Their publicapi is still up, albeit only for BTC, LTC, and DOGE.

def get_latest_price():
   r = requests.get("https://www.coinspot.com.au/pubapi/latest").json()
   print(r)