1

I am having trouble with a (400) bad request on POST requests. I am able to execute all Get and Delete requests with the same signature process, but obviously the body is string.empty. We have tested all sorts of different JSON formatting to try and get this to work, but it is not working. We have not been able to find an example of ANY prehash signature to compare to. Also, unless the POST server time is different than the GET and DELETE server times we have the correct timestamp as we are within 1 second of the GET/time API call for server time. GDAX allows for 30 second buffer to authenticate.

Public Shared Function placeOrder()
    Try
        Dim Body As String = "{""type"":""limit"",""side"":""sell"",""product_id"":""BTC-USD"",""price"":""20000"",""size\"":""0.02235229""}"
        Dim ts As String = GetNonce()
        Dim method As String = "/orders"
        Dim str_GDAX_Main As String = "https://api.gdax.com"
        Dim sig As String = GetSignature(ts, "POST", method, Body)
        Dim fr As System.Net.HttpWebRequest
        Dim targetURI As New Uri(str_GDAX_Main & method)
        'Dim response As String

        Dim jsonDataBytes As Byte() = Encoding.UTF8.GetBytes(Body)


        fr = DirectCast(HttpWebRequest.Create(targetURI), System.Net.HttpWebRequest)
        fr.Headers.Add("CB-ACCESS-KEY", config_API_Key)
        fr.Headers.Add("CB-ACCESS-SIGN", sig)
        fr.Headers.Add("CB-ACCESS-TIMESTAMP", ts)
        fr.Headers.Add("CB-ACCESS-PASSPHRASE", config_API_Passphrase)
        fr.UserAgent = UserAgent
        fr.Accept = "application/json"
        fr.Method = "POST"
        fr.ContentLength = jsonDataBytes.Length

        Dim stream = fr.GetRequestStream()
        stream.Write(jsonDataBytes, 0, jsonDataBytes.Length)
        stream.Close()

        Dim response = fr.GetResponse().GetResponseStream()

        Dim reader As New StreamReader(response)
        Dim res = reader.ReadToEnd()
        reader.Close()
        response.Close()
        Return res

        'If (fr.GetResponse().ContentLength > 0) Then
        '    Dim str As New System.IO.StreamReader(fr.GetResponse().GetResponseStream())
        '    response = (str.ReadToEnd())
        '    str.Close()
        'End If

        'Form1.RichTextBox1.Text = (response)
    Catch ex As System.Net.WebException
        MessageBox.Show(ex.Message)
        'Error in accessing the resource, handle it
    End Try
End Function

Public Shared Function GetNonce() As String
    Return (DateTime.UtcNow - New DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds.ToString()
End Function

Public Shared Function GetSignature(nonce As String, method As String, url As String, body As String) As String
    Dim message As String = String.Concat(nonce, method.ToUpper(), url, body)
    Dim encoding = New ASCIIEncoding()
    Dim keyByte As Byte() = Convert.FromBase64String(config_API_Secret)
    Dim messageBytes As Byte() = encoding.GetBytes(message)
    Using hmacsha256 = New HMACSHA256(keyByte)
        Dim hashmessage As Byte() = hmacsha256.ComputeHash(messageBytes)
        Return Convert.ToBase64String(hashmessage)
    End Using
End Function

We have no idea if our body is incorrect or if the URI is incorrect or what the problem is. If someone can take a look at it and figure out where our body syntax error is. Or if we should look elsewhere.

1
  • Why don't you try sending your POST request via an HTTP debugging tool such as PostMan? Once you're communicating with the server correctly, then you can try to get your code to behave in the same way. Commented Dec 20, 2017 at 16:13

3 Answers 3

1

your "Public Shared Function GetSignature" works fine! I have been racking my head for a couple of days writing my own but with no luck! Thanks for your snippet!

As far as your problem someone may have already answered it.

To troubleshoot further problems I recommend after you get an HTTP Error to continue your stream and GDAX will give you helpful information.

here is how I handle a web exception.

          Catch ex As WebException

        Dim output As New ClassWebRequestOutput
        output._ErrorMessage = ex.Message.ToString

        Dim exResponse As String
        output._Error = True

        exResponse = New StreamReader(ex.Response.GetResponseStream()).ReadToEnd
        output._Resopnse = exResponse

        Return output
        Exit Function

This continues the web connection with helpful hints.

0

I did not go in detail into your code, but seems to be that you get the 400 error that it is a generic one. With the code that I am using I get more specific details, but I have problems with the signature getting always "message": "invalid signature". It is clear that I am reaching the server but the signature is not built in the right way.

I attach my code, if it of some help for you.

PS. I tried PostMan to perform some testings, but the problem persists.

I would appreciate if we could share our findings to solve this issue.

Private Function PrivateRequest(sMethod As String, sData As String) As String
    Dim key As String = "MY KEY"
    Dim secret As String = "MY SECRET"
    Dim url As String = "https://api.gdax.com"
    Dim nonce As String = (TimeToUnix(DateTime.Now) - 3600).ToString
    Dim targetURI As New Uri(url & sMethod)

    Dim postdataStr As String = sData
    Dim postdata = New Byte(postdataStr.Count - 1) {}
    Dim encText As New System.Text.UTF8Encoding()
    postdata = encText.GetBytes(postdataStr)

    Dim messageStr As String = String.Concat(nonce, "POST", targetURI, sData)

    Dim base64DecodedSecret As Byte() = Convert.FromBase64String(secret)

    Dim message = New Byte(messageStr.Count - 1) {}
    Dim encText1 As New System.Text.UTF8Encoding()
    message = encText1.GetBytes(messageStr)

    Dim signature = getHash(base64DecodedSecret, message)
    Dim signatureStr = Convert.ToBase64String(signature)

    Dim webRequest__1 As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
    webRequest__1.ContentType = ("application/json")
    webRequest__1.Method = "POST"
    webRequest__1.UserAgent = ".NET Framework Test Client"
    webRequest__1.Headers.Add("CB-ACCESS-SIGN", signatureStr)
    webRequest__1.Headers.Add("CB-ACCESS-TIMESTAMP", nonce)
    webRequest__1.Headers.Add("CB-ACCESS-KEY", key)
    webRequest__1.Headers.Add("CB-ACCESS-PASSPHRASE", "MY PASSPHRASE")

    Dim postreqstream As Stream = webRequest__1.GetRequestStream()
    postreqstream.Write(postdata, 0, postdata.Length)
    postreqstream.Close()

    Try
        Using webResponse As WebResponse = webRequest__1.GetResponse()
            Using str As Stream = webResponse.GetResponseStream()
                Using sr As New StreamReader(str)
                    Dim responseContent3 As String = sr.ReadToEnd
                    Return responseContent3
                End Using
            End Using
        End Using
    Catch wex As WebException
        Using response As HttpWebResponse = DirectCast(wex.Response, HttpWebResponse)
            Using str As Stream = response.GetResponseStream()
                Using sr As New StreamReader(str)
                    Dim responseContent3 As String = sr.ReadToEnd
                    Return responseContent3
                End Using
            End Using
        End Using
    End Try
End Function

Private Function getHash(keyByte As Byte(), messageBytes As Byte()) As Byte()
    Using hmacsha256 = New HMACSHA256(keyByte)
        Dim result As [Byte]() = hmacsha256.ComputeHash(messageBytes)
        Return result
    End Using
End Function

Public Function TimeToUnix(ByVal dteDate As Date) As String
    If dteDate.IsDaylightSavingTime = True Then
        dteDate = DateAdd(DateInterval.Hour, -1, dteDate)
    End If
    TimeToUnix = DateDiff(DateInterval.Second, #1/1/1970#, dteDate)
End Function

    MethodString = "/accounts"
    DataString = "{}"
    response = PrivateRequest(MethodString, DataString)

`

0

change "size\" to "size" that was your error. It worked great for me just now. also IDK if itd required but I also set fr.ContentType = "application/json", i saw it as an option and tried it before i went char by char through the message... Thank you so much, this was a great starting point for me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.