What is wrong with this coinmex API?Best practices for API versioning?What exactly is RESTful programming?What is a NullReferenceException, and how do I fix it?Kraken private API with F# returns EGeneral: invalid argumentsSignature Version 4 Signing Process in PHP to access API Gateway endpointDelphi 10.1: How to get JSON string stored in the body parameter of a REST request (TCustomRESTRequest.Body)?Java GDAX Authenticated REST Request HTTP GET Error 400Binance API Hmac SignatureAccess Coinbase API using HTTR and RGetting The remote server returned an error: (403) Forbidden in C# during calling API with AWS authntication

Is differentiation as a map discontinuous?

Is there a concept of "peer review" in Rabbinical Judaism?

Would you write key signatures for non-conventional scales?

Clear text passwords in Unix

What is the white pattern on trim wheel for?

Intheritance at package visibility in Java

Why was Logo created?

Windows 10 deletes lots of tiny files super slowly. Anything that can be done to speed it up?

Two side-by-side squares are inscribed in a semicircle. The diameter of the semicircle is 16. What is the sum of the two squares' areas?

Is a Middle Name a Given Name?

Align all symbols in a LaTeX equation

How to deal with a PC being played as homophobic?

Can you trip a breaker from a different circuit?

Should the average user with no special access rights be worried about SMS-based 2FA being theoretically interceptable?

What exactly did this mechanic sabotage on the American Airlines 737, and how dangerous was it?

My Project Manager does not accept carry-over in Scrum, Is that normal?

Why does the leading tone (G#) go to E rather than A in this example?

How to justify getting additional team member when the current team is doing well?

Designing a time thief proof safe

Garage door sticks on a bolt

Medic abilities

Diminutive -ula

I am not a pleasant sight

When does a Sea Sorcerer choose to use Curse of the Sea's additional effect?



What is wrong with this coinmex API?


Best practices for API versioning?What exactly is RESTful programming?What is a NullReferenceException, and how do I fix it?Kraken private API with F# returns EGeneral: invalid argumentsSignature Version 4 Signing Process in PHP to access API Gateway endpointDelphi 10.1: How to get JSON string stored in the body parameter of a REST request (TCustomRESTRequest.Body)?Java GDAX Authenticated REST Request HTTP GET Error 400Binance API Hmac SignatureAccess Coinbase API using HTTR and RGetting The remote server returned an error: (403) Forbidden in C# during calling API with AWS authntication






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








3















Protected Overrides Function getJsonPrivate(method As String, otherParameters() As Tuple(Of String, String)) As String
Dim base = "https://www.coinmex.com"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = getEstimatedTimeStamp().ToString

Dim stringtosign = timestampstring + "GET" + longmethod + "" '1553784499976GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(_secret1))
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = System.Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@Qsqr**
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response
End Function

Public Overrides Sub readbalances()
typicalReadBalances("account/assets", "data", "currencyCode", "available", "frozen", "", )
End Sub


I think I did it like what's listed here
https://github.com/coinmex/coinmex-official-api-docs/blob/master/README_EN.md#1-access-account-information



# Request
GET /api/v1/spot/ccex/account/assets

# Response
[

"available":"0.1",
"balance":"0.1",
"currencyCode":"ETH",
"frozen":"0",
"id":1
,

"available":"1",
"balance":"1",
"currencyCode":"USDT",
"frozen":"0",
"id":1

]


And for Signature



This is the manual says




The ACCESS-SIGN header is the output generated by using HMAC SHA256 to
create the HMAC SHA256 using the BASE64 decoding secret key in the
prehash string to generate timestamp + method + requestPath + "?" +
queryString + body (where ‘+’ represents the string concatenation) and
BASE64 encoded output. The timestamp value is the same as the
ACCESS-TIMESTAMP header. This body is the request body string or
omitted if there is no request body (usually the GET request). This
method should be capitalized.



Remember that before using it as the key to HMAC, base64 decoding (the
result is 64 bytes) is first performed on the 64-bit alphanumeric
password string. In addition, the digest output is base64 encoded
before sending the header.



User submitted parameters must be signed except for sign. First, the
string to be signed is ordered according to the parameter name (first
compare the first letter of all parameter names, in alphabetic order,
if you encounter the same first letter, then you move to the second
letter, and so on).



For example, if we sign the following parameters



curl "https://www.coinmex.com/api/v1/spot/ccex/orders?limit=100" 

Timestamp = 1590000000.281
Method = "POST"
requestPath = "/api/v1/spot/ccex/orders"
queryString= "?limit=100"
body =
'code': 'ct_usdt',
'side': 'buy',
'type': 'limit',
'size': '1',
'price': '1',
'funds': '',



Generate the string to be signed



Message = '1590000000.281GET/api/v1/spot/ccex/orders?limit=100"code": "ct_usdt", "side": "buy", "type": "limit", "size": "1", "price": "0.1", "funds": ""'


Then, the character to be signed is added with the private key
parameters to generate the final character string to be signed.



For example:



hmac = hmac(secretkey, Message, SHA256)
Signature = base64.encode(hmac.digest())



I thought may be the _secret1 is a base64 string rather than utf8 so I changed to



Dim base = "https://www.coinmex.com"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = getEstimatedTimeStamp().ToString

'Dim stringtosign = timestampstring + "GET" + longmethod + "" '1553784499976GET/api/v1/spot/ccex/account/assets also doesn't work
Dim stringtosign = timestampstring + "GET" + longmethod '1553784499976GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(_secret1)) 'secret looks like 43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@Qsq***
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response


Not working either.



The secret key (I truncated a few letters) look like



43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2



Is this something that should be decoded as base 64 or utf8 or what?



The spec says it's 64. However, it doesn't look like a 64 encoded string. It looks like the letters are from 0-f



Best answers will:
1. Tell me what went wrong in the code. I made the change. Try. Run. Works. Awesome.



A good answer will
2. A sample simulation with a fake/real signatures/nonce/passphrase and real actual headers and signatures. So I can see where exactly I have a wrong result.



Update: I modified the code again. I change the timestamp to seconds instead of milisecons. I remove the . I use both way.



 Dim base = "https://www.coinmex.com"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = (getEstimatedTimeStamp() / 1000).ToString

Dim stringtosign = timestampstring + "GET" + longmethod '1555154812.857GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(_secret1)) '"43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2******
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@QsqrYZ
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response


Still doesn't work.



Current Error is



Message = "The remote server returned an error: (401) Unauthorized."



I would love to give some read-only API key. Hang on. Or create an empty account and then have a read only API key










share|improve this question





















  • 1





    Suggestion: maybe editing your tags would help. Tag api is meaningless: if you hover it, you'll see it says "DO NOT USE". Maybe add vb.net, as it looks like what you're using.

    – Hugues M.
    Apr 12 at 21:40











  • Thanks. I add vb.net. However, any language, like PhP where I can verify that I compute the signature correctly would also help a lot.

    – user4951
    Apr 13 at 8:03

















3















Protected Overrides Function getJsonPrivate(method As String, otherParameters() As Tuple(Of String, String)) As String
Dim base = "https://www.coinmex.com"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = getEstimatedTimeStamp().ToString

Dim stringtosign = timestampstring + "GET" + longmethod + "" '1553784499976GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(_secret1))
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = System.Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@Qsqr**
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response
End Function

Public Overrides Sub readbalances()
typicalReadBalances("account/assets", "data", "currencyCode", "available", "frozen", "", )
End Sub


I think I did it like what's listed here
https://github.com/coinmex/coinmex-official-api-docs/blob/master/README_EN.md#1-access-account-information



# Request
GET /api/v1/spot/ccex/account/assets

# Response
[

"available":"0.1",
"balance":"0.1",
"currencyCode":"ETH",
"frozen":"0",
"id":1
,

"available":"1",
"balance":"1",
"currencyCode":"USDT",
"frozen":"0",
"id":1

]


And for Signature



This is the manual says




The ACCESS-SIGN header is the output generated by using HMAC SHA256 to
create the HMAC SHA256 using the BASE64 decoding secret key in the
prehash string to generate timestamp + method + requestPath + "?" +
queryString + body (where ‘+’ represents the string concatenation) and
BASE64 encoded output. The timestamp value is the same as the
ACCESS-TIMESTAMP header. This body is the request body string or
omitted if there is no request body (usually the GET request). This
method should be capitalized.



Remember that before using it as the key to HMAC, base64 decoding (the
result is 64 bytes) is first performed on the 64-bit alphanumeric
password string. In addition, the digest output is base64 encoded
before sending the header.



User submitted parameters must be signed except for sign. First, the
string to be signed is ordered according to the parameter name (first
compare the first letter of all parameter names, in alphabetic order,
if you encounter the same first letter, then you move to the second
letter, and so on).



For example, if we sign the following parameters



curl "https://www.coinmex.com/api/v1/spot/ccex/orders?limit=100" 

Timestamp = 1590000000.281
Method = "POST"
requestPath = "/api/v1/spot/ccex/orders"
queryString= "?limit=100"
body =
'code': 'ct_usdt',
'side': 'buy',
'type': 'limit',
'size': '1',
'price': '1',
'funds': '',



Generate the string to be signed



Message = '1590000000.281GET/api/v1/spot/ccex/orders?limit=100"code": "ct_usdt", "side": "buy", "type": "limit", "size": "1", "price": "0.1", "funds": ""'


Then, the character to be signed is added with the private key
parameters to generate the final character string to be signed.



For example:



hmac = hmac(secretkey, Message, SHA256)
Signature = base64.encode(hmac.digest())



I thought may be the _secret1 is a base64 string rather than utf8 so I changed to



Dim base = "https://www.coinmex.com"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = getEstimatedTimeStamp().ToString

'Dim stringtosign = timestampstring + "GET" + longmethod + "" '1553784499976GET/api/v1/spot/ccex/account/assets also doesn't work
Dim stringtosign = timestampstring + "GET" + longmethod '1553784499976GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(_secret1)) 'secret looks like 43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@Qsq***
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response


Not working either.



The secret key (I truncated a few letters) look like



43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2



Is this something that should be decoded as base 64 or utf8 or what?



The spec says it's 64. However, it doesn't look like a 64 encoded string. It looks like the letters are from 0-f



Best answers will:
1. Tell me what went wrong in the code. I made the change. Try. Run. Works. Awesome.



A good answer will
2. A sample simulation with a fake/real signatures/nonce/passphrase and real actual headers and signatures. So I can see where exactly I have a wrong result.



Update: I modified the code again. I change the timestamp to seconds instead of milisecons. I remove the . I use both way.



 Dim base = "https://www.coinmex.com"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = (getEstimatedTimeStamp() / 1000).ToString

Dim stringtosign = timestampstring + "GET" + longmethod '1555154812.857GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(_secret1)) '"43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2******
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@QsqrYZ
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response


Still doesn't work.



Current Error is



Message = "The remote server returned an error: (401) Unauthorized."



I would love to give some read-only API key. Hang on. Or create an empty account and then have a read only API key










share|improve this question





















  • 1





    Suggestion: maybe editing your tags would help. Tag api is meaningless: if you hover it, you'll see it says "DO NOT USE". Maybe add vb.net, as it looks like what you're using.

    – Hugues M.
    Apr 12 at 21:40











  • Thanks. I add vb.net. However, any language, like PhP where I can verify that I compute the signature correctly would also help a lot.

    – user4951
    Apr 13 at 8:03













3












3








3


0






Protected Overrides Function getJsonPrivate(method As String, otherParameters() As Tuple(Of String, String)) As String
Dim base = "https://www.coinmex.com"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = getEstimatedTimeStamp().ToString

Dim stringtosign = timestampstring + "GET" + longmethod + "" '1553784499976GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(_secret1))
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = System.Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@Qsqr**
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response
End Function

Public Overrides Sub readbalances()
typicalReadBalances("account/assets", "data", "currencyCode", "available", "frozen", "", )
End Sub


I think I did it like what's listed here
https://github.com/coinmex/coinmex-official-api-docs/blob/master/README_EN.md#1-access-account-information



# Request
GET /api/v1/spot/ccex/account/assets

# Response
[

"available":"0.1",
"balance":"0.1",
"currencyCode":"ETH",
"frozen":"0",
"id":1
,

"available":"1",
"balance":"1",
"currencyCode":"USDT",
"frozen":"0",
"id":1

]


And for Signature



This is the manual says




The ACCESS-SIGN header is the output generated by using HMAC SHA256 to
create the HMAC SHA256 using the BASE64 decoding secret key in the
prehash string to generate timestamp + method + requestPath + "?" +
queryString + body (where ‘+’ represents the string concatenation) and
BASE64 encoded output. The timestamp value is the same as the
ACCESS-TIMESTAMP header. This body is the request body string or
omitted if there is no request body (usually the GET request). This
method should be capitalized.



Remember that before using it as the key to HMAC, base64 decoding (the
result is 64 bytes) is first performed on the 64-bit alphanumeric
password string. In addition, the digest output is base64 encoded
before sending the header.



User submitted parameters must be signed except for sign. First, the
string to be signed is ordered according to the parameter name (first
compare the first letter of all parameter names, in alphabetic order,
if you encounter the same first letter, then you move to the second
letter, and so on).



For example, if we sign the following parameters



curl "https://www.coinmex.com/api/v1/spot/ccex/orders?limit=100" 

Timestamp = 1590000000.281
Method = "POST"
requestPath = "/api/v1/spot/ccex/orders"
queryString= "?limit=100"
body =
'code': 'ct_usdt',
'side': 'buy',
'type': 'limit',
'size': '1',
'price': '1',
'funds': '',



Generate the string to be signed



Message = '1590000000.281GET/api/v1/spot/ccex/orders?limit=100"code": "ct_usdt", "side": "buy", "type": "limit", "size": "1", "price": "0.1", "funds": ""'


Then, the character to be signed is added with the private key
parameters to generate the final character string to be signed.



For example:



hmac = hmac(secretkey, Message, SHA256)
Signature = base64.encode(hmac.digest())



I thought may be the _secret1 is a base64 string rather than utf8 so I changed to



Dim base = "https://www.coinmex.com"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = getEstimatedTimeStamp().ToString

'Dim stringtosign = timestampstring + "GET" + longmethod + "" '1553784499976GET/api/v1/spot/ccex/account/assets also doesn't work
Dim stringtosign = timestampstring + "GET" + longmethod '1553784499976GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(_secret1)) 'secret looks like 43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@Qsq***
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response


Not working either.



The secret key (I truncated a few letters) look like



43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2



Is this something that should be decoded as base 64 or utf8 or what?



The spec says it's 64. However, it doesn't look like a 64 encoded string. It looks like the letters are from 0-f



Best answers will:
1. Tell me what went wrong in the code. I made the change. Try. Run. Works. Awesome.



A good answer will
2. A sample simulation with a fake/real signatures/nonce/passphrase and real actual headers and signatures. So I can see where exactly I have a wrong result.



Update: I modified the code again. I change the timestamp to seconds instead of milisecons. I remove the . I use both way.



 Dim base = "https://www.coinmex.com"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = (getEstimatedTimeStamp() / 1000).ToString

Dim stringtosign = timestampstring + "GET" + longmethod '1555154812.857GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(_secret1)) '"43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2******
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@QsqrYZ
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response


Still doesn't work.



Current Error is



Message = "The remote server returned an error: (401) Unauthorized."



I would love to give some read-only API key. Hang on. Or create an empty account and then have a read only API key










share|improve this question
















Protected Overrides Function getJsonPrivate(method As String, otherParameters() As Tuple(Of String, String)) As String
Dim base = "https://www.coinmex.com"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = getEstimatedTimeStamp().ToString

Dim stringtosign = timestampstring + "GET" + longmethod + "" '1553784499976GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(_secret1))
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = System.Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@Qsqr**
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response
End Function

Public Overrides Sub readbalances()
typicalReadBalances("account/assets", "data", "currencyCode", "available", "frozen", "", )
End Sub


I think I did it like what's listed here
https://github.com/coinmex/coinmex-official-api-docs/blob/master/README_EN.md#1-access-account-information



# Request
GET /api/v1/spot/ccex/account/assets

# Response
[

"available":"0.1",
"balance":"0.1",
"currencyCode":"ETH",
"frozen":"0",
"id":1
,

"available":"1",
"balance":"1",
"currencyCode":"USDT",
"frozen":"0",
"id":1

]


And for Signature



This is the manual says




The ACCESS-SIGN header is the output generated by using HMAC SHA256 to
create the HMAC SHA256 using the BASE64 decoding secret key in the
prehash string to generate timestamp + method + requestPath + "?" +
queryString + body (where ‘+’ represents the string concatenation) and
BASE64 encoded output. The timestamp value is the same as the
ACCESS-TIMESTAMP header. This body is the request body string or
omitted if there is no request body (usually the GET request). This
method should be capitalized.



Remember that before using it as the key to HMAC, base64 decoding (the
result is 64 bytes) is first performed on the 64-bit alphanumeric
password string. In addition, the digest output is base64 encoded
before sending the header.



User submitted parameters must be signed except for sign. First, the
string to be signed is ordered according to the parameter name (first
compare the first letter of all parameter names, in alphabetic order,
if you encounter the same first letter, then you move to the second
letter, and so on).



For example, if we sign the following parameters



curl "https://www.coinmex.com/api/v1/spot/ccex/orders?limit=100" 

Timestamp = 1590000000.281
Method = "POST"
requestPath = "/api/v1/spot/ccex/orders"
queryString= "?limit=100"
body =
'code': 'ct_usdt',
'side': 'buy',
'type': 'limit',
'size': '1',
'price': '1',
'funds': '',



Generate the string to be signed



Message = '1590000000.281GET/api/v1/spot/ccex/orders?limit=100"code": "ct_usdt", "side": "buy", "type": "limit", "size": "1", "price": "0.1", "funds": ""'


Then, the character to be signed is added with the private key
parameters to generate the final character string to be signed.



For example:



hmac = hmac(secretkey, Message, SHA256)
Signature = base64.encode(hmac.digest())



I thought may be the _secret1 is a base64 string rather than utf8 so I changed to



Dim base = "https://www.coinmex.com"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = getEstimatedTimeStamp().ToString

'Dim stringtosign = timestampstring + "GET" + longmethod + "" '1553784499976GET/api/v1/spot/ccex/account/assets also doesn't work
Dim stringtosign = timestampstring + "GET" + longmethod '1553784499976GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(_secret1)) 'secret looks like 43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@Qsq***
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response


Not working either.



The secret key (I truncated a few letters) look like



43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2



Is this something that should be decoded as base 64 or utf8 or what?



The spec says it's 64. However, it doesn't look like a 64 encoded string. It looks like the letters are from 0-f



Best answers will:
1. Tell me what went wrong in the code. I made the change. Try. Run. Works. Awesome.



A good answer will
2. A sample simulation with a fake/real signatures/nonce/passphrase and real actual headers and signatures. So I can see where exactly I have a wrong result.



Update: I modified the code again. I change the timestamp to seconds instead of milisecons. I remove the . I use both way.



 Dim base = "https://www.coinmex.com"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = (getEstimatedTimeStamp() / 1000).ToString

Dim stringtosign = timestampstring + "GET" + longmethod '1555154812.857GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(_secret1)) '"43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2******
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@QsqrYZ
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response


Still doesn't work.



Current Error is



Message = "The remote server returned an error: (401) Unauthorized."



I would love to give some read-only API key. Hang on. Or create an empty account and then have a read only API key







vb.net rest api






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Apr 14 at 9:32







user4951

















asked Mar 28 at 18:37









user4951user4951

14.4k45 gold badges149 silver badges256 bronze badges




14.4k45 gold badges149 silver badges256 bronze badges










  • 1





    Suggestion: maybe editing your tags would help. Tag api is meaningless: if you hover it, you'll see it says "DO NOT USE". Maybe add vb.net, as it looks like what you're using.

    – Hugues M.
    Apr 12 at 21:40











  • Thanks. I add vb.net. However, any language, like PhP where I can verify that I compute the signature correctly would also help a lot.

    – user4951
    Apr 13 at 8:03












  • 1





    Suggestion: maybe editing your tags would help. Tag api is meaningless: if you hover it, you'll see it says "DO NOT USE". Maybe add vb.net, as it looks like what you're using.

    – Hugues M.
    Apr 12 at 21:40











  • Thanks. I add vb.net. However, any language, like PhP where I can verify that I compute the signature correctly would also help a lot.

    – user4951
    Apr 13 at 8:03







1




1





Suggestion: maybe editing your tags would help. Tag api is meaningless: if you hover it, you'll see it says "DO NOT USE". Maybe add vb.net, as it looks like what you're using.

– Hugues M.
Apr 12 at 21:40





Suggestion: maybe editing your tags would help. Tag api is meaningless: if you hover it, you'll see it says "DO NOT USE". Maybe add vb.net, as it looks like what you're using.

– Hugues M.
Apr 12 at 21:40













Thanks. I add vb.net. However, any language, like PhP where I can verify that I compute the signature correctly would also help a lot.

– user4951
Apr 13 at 8:03





Thanks. I add vb.net. However, any language, like PhP where I can verify that I compute the signature correctly would also help a lot.

– user4951
Apr 13 at 8:03












2 Answers
2






active

oldest

votes


















2







+100









The documentation states




This body is the request body string or omitted if there is no request body (usually the GET request)




Note: emphasis mine



yet you include an empty JSON object on a GET request



Dim stringtosign = timestampstring + "GET" + longmethod + "" '1553784499976GET/api/v1/spot/ccex/account/assets


That should not be included in a GET request.



'1553784499976GET/api/v1/spot/ccex/account/assets
Dim stringtosign = timestampstring + "GET" + longmethod


So it appears you were not constructing the signature correctly as per documentation.



Noticed that the docs




The root URL for REST access:https://www.coinmex.pro




while you are trying to call "https://www.coinmex.com"




Timestamp



Unless otherwise specified, all timestamps in APIs are returned in microseconds.



The ACCESS-TIMESTAMP header must be the number of seconds since UTC's
time Unix Epoch. Decimal values are allowed. Your timestamp must be
within 30 seconds of the API service time, otherwise your request will
be considered expired and rejected.
If you think there is a large time
difference between your server and the API server, then we recommend
that you use the time point to check the API server time.




note: emphasis mine



Following extension method was used to calculate time stamp



private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

/// <summary>
/// Converts the value of the current <see cref="System.DateTime"/> object to Unix Time.
/// </summary>
/// <param name="dateTime"></param>
/// <remarks>
/// </remarks>
/// This method first converts the current instance to UTC before returning its Unix time.
/// <returns>
/// A <see cref="System.Int64"/> defined as the number of seconds that have elapsed since midnight Coordinated Universal Time (UTC), January 1, 1970, not counting leap seconds.
/// </returns>
public static long ToUnixTimeSeconds(this DateTime dateTime)
if (dateTime.ToUniversalTime() < Epoch)
return 0;


var totalSeconds = dateTime.ToUniversalTime().Subtract(Epoch).TotalSeconds;
var timestamp = Convert.ToInt64(totalSeconds);

return timestamp;



I did the following Test to see if I could call the API following the documentation and it appears to have worked.



I used c# however



[TestClass]
public class CoinMaxAPITests
const string apiKey1 = "cmx-1027e54e4723b09810576f8e7a5413**";
const string fakeSecret = "43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac23==";
const string passphrase1 = "1Us6&f%*K@QsqrYZ";

Lazy<HttpClient> http = new Lazy<HttpClient>(() =>
var rootUrl = "https://www.coinmex.pro";

CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler
CookieContainer = cookies,
UseCookies = true,

;
var client = new HttpClient()
BaseAddress = new Uri(rootUrl)
;
client.DefaultRequestHeaders.TryAddWithoutValidation("ACCESS-KEY", apiKey1);
client.DefaultRequestHeaders.TryAddWithoutValidation("ACCESS-PASSPHRASE", passphrase1);
return client;
);

[TestMethod]
public async Task Should_Accept_Signature()
//Arrange
var requestPath = "/api/v1/spot/public/time";
var method = "GET";
var timeStamp = getEstimatedTimeStamp().ToString(); //"1555253371"

var message = timeStamp + method + requestPath; //"1555253371GET/api/v1/spot/public/time"

var secretKey = Convert.FromBase64String(fakeSecret);
var hmac = new HMACSHA256(secretKey);
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
var signature = Convert.ToBase64String(hash);//Jzui/eO3iyLTD6L9qVkUO0EBpZP/lFhx1HlsbuSNt/8=

var request = new HttpRequestMessage(HttpMethod.Get, requestPath);
request.Headers.TryAddWithoutValidation("ACCESS-TIMESTAMP", timeStamp);
request.Headers.TryAddWithoutValidation("ACCESS-SIGN", signature);

//Act
var response = await http.Value.SendAsync(request);

//Assert
response.EnsureSuccessStatusCode();

var json = await response.Content.ReadAsStringAsync();
//""epoch":"1555253501.225","iso":"2019-04-14T14:51:41.225Z","timestamp":1555253501225"
var server = JsonConvert.DeserializeObject<ServerTime>(json);

server.Should().NotBeNull();
server.Iso.Date.Should().Be(DateTime.Today);


long getEstimatedTimeStamp()
return DateTime.Now.ToUnixTimeSeconds(); //custom extension method




public partial class ServerTime
[JsonProperty("epoch")]
public string Epoch get; set;

[JsonProperty("iso")]
public DateTime Iso get; set;

[JsonProperty("timestamp")]
public long Timestamp get; set;



And was able to get a valid JSON response calling /api/v1/spot/public/time that I was able to deserialize for my assertion, even with the fake keys. Probably as this is the public API. This does prove that the URL called is correct.



When the request path is changed to



"/api/v1/spot/ccex/account/assets"


And tested for more secure private data from the API, the response is 400 Bad Request with the following content in the body of the response



"message":"Encrypted key does not exist"


which is as expected given that the keys I used were fake.



This gives me every indication that the API does in fact work as expected provided that you follow what is suggested in the linked documentation.






share|improve this answer



























  • I did both way. With or without ()

    – user4951
    Apr 13 at 12:12











  • Thank you very much. I will check and see how it works

    – user4951
    Apr 14 at 9:09











  • oh you got message. I got empty stuff. Let me check.

    – user4951
    Apr 14 at 9:09











  • The response is empty I got this in exception object Message = "The remote server returned an error: (401) Unauthorized."

    – user4951
    Apr 14 at 9:32











  • Would you print the intermediate strings. Also changging to coinmex.pro doesn't help

    – user4951
    Apr 14 at 9:44


















0
















I wonder what I should pick as the answer due to this conflict of interest.



What happened is he go the extra mile of trying some API. I decided to create a new API key and post it here. It's read-only and can't possibly go wrong anyway. Before I posted here I try to run it once more expecting that it won't work like usual.



It turns out my code simply works. It seems that there are error in API key, secret, or password.



Here is the code that finally work



Protected Overrides Function getJsonPrivate(method As String, otherParameters() As Tuple(Of String, String)) As String
Dim base = "https://www.coinmex.pro"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = (getEstimatedTimeStamp() / 1000).ToString

Dim stringtosign = timestampstring + "GET" + longmethod '1555154812.857GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(_secret1)) '"43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2******
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@QsqrYZ
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response
End Function





share|improve this answer

























  • I upvoted Nkosi's answer.

    – user4951
    Apr 14 at 15:57











  • Nkosi explanation that the shouldn't be there also helped. I tried both ways. But because of his explanation, I do not need to try both ways. I just need to try the one right way. That's not where the issue is.

    – user4951
    Apr 14 at 15:59






  • 1





    Next time, when I have a problem like this again, I will create a temporary read only API key and secret and share that. After that people can easil try this with real API

    – user4951
    Apr 14 at 16:09











  • Yes having an actual temp key would have been ideal. I wanted to help but was torn about having to create an account in order to get around the limitations of not having a usable key.

    – Nkosi
    Apr 14 at 19:40














Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);














draft saved

draft discarded
















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55404704%2fwhat-is-wrong-with-this-coinmex-api%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









2







+100









The documentation states




This body is the request body string or omitted if there is no request body (usually the GET request)




Note: emphasis mine



yet you include an empty JSON object on a GET request



Dim stringtosign = timestampstring + "GET" + longmethod + "" '1553784499976GET/api/v1/spot/ccex/account/assets


That should not be included in a GET request.



'1553784499976GET/api/v1/spot/ccex/account/assets
Dim stringtosign = timestampstring + "GET" + longmethod


So it appears you were not constructing the signature correctly as per documentation.



Noticed that the docs




The root URL for REST access:https://www.coinmex.pro




while you are trying to call "https://www.coinmex.com"




Timestamp



Unless otherwise specified, all timestamps in APIs are returned in microseconds.



The ACCESS-TIMESTAMP header must be the number of seconds since UTC's
time Unix Epoch. Decimal values are allowed. Your timestamp must be
within 30 seconds of the API service time, otherwise your request will
be considered expired and rejected.
If you think there is a large time
difference between your server and the API server, then we recommend
that you use the time point to check the API server time.




note: emphasis mine



Following extension method was used to calculate time stamp



private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

/// <summary>
/// Converts the value of the current <see cref="System.DateTime"/> object to Unix Time.
/// </summary>
/// <param name="dateTime"></param>
/// <remarks>
/// </remarks>
/// This method first converts the current instance to UTC before returning its Unix time.
/// <returns>
/// A <see cref="System.Int64"/> defined as the number of seconds that have elapsed since midnight Coordinated Universal Time (UTC), January 1, 1970, not counting leap seconds.
/// </returns>
public static long ToUnixTimeSeconds(this DateTime dateTime)
if (dateTime.ToUniversalTime() < Epoch)
return 0;


var totalSeconds = dateTime.ToUniversalTime().Subtract(Epoch).TotalSeconds;
var timestamp = Convert.ToInt64(totalSeconds);

return timestamp;



I did the following Test to see if I could call the API following the documentation and it appears to have worked.



I used c# however



[TestClass]
public class CoinMaxAPITests
const string apiKey1 = "cmx-1027e54e4723b09810576f8e7a5413**";
const string fakeSecret = "43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac23==";
const string passphrase1 = "1Us6&f%*K@QsqrYZ";

Lazy<HttpClient> http = new Lazy<HttpClient>(() =>
var rootUrl = "https://www.coinmex.pro";

CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler
CookieContainer = cookies,
UseCookies = true,

;
var client = new HttpClient()
BaseAddress = new Uri(rootUrl)
;
client.DefaultRequestHeaders.TryAddWithoutValidation("ACCESS-KEY", apiKey1);
client.DefaultRequestHeaders.TryAddWithoutValidation("ACCESS-PASSPHRASE", passphrase1);
return client;
);

[TestMethod]
public async Task Should_Accept_Signature()
//Arrange
var requestPath = "/api/v1/spot/public/time";
var method = "GET";
var timeStamp = getEstimatedTimeStamp().ToString(); //"1555253371"

var message = timeStamp + method + requestPath; //"1555253371GET/api/v1/spot/public/time"

var secretKey = Convert.FromBase64String(fakeSecret);
var hmac = new HMACSHA256(secretKey);
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
var signature = Convert.ToBase64String(hash);//Jzui/eO3iyLTD6L9qVkUO0EBpZP/lFhx1HlsbuSNt/8=

var request = new HttpRequestMessage(HttpMethod.Get, requestPath);
request.Headers.TryAddWithoutValidation("ACCESS-TIMESTAMP", timeStamp);
request.Headers.TryAddWithoutValidation("ACCESS-SIGN", signature);

//Act
var response = await http.Value.SendAsync(request);

//Assert
response.EnsureSuccessStatusCode();

var json = await response.Content.ReadAsStringAsync();
//""epoch":"1555253501.225","iso":"2019-04-14T14:51:41.225Z","timestamp":1555253501225"
var server = JsonConvert.DeserializeObject<ServerTime>(json);

server.Should().NotBeNull();
server.Iso.Date.Should().Be(DateTime.Today);


long getEstimatedTimeStamp()
return DateTime.Now.ToUnixTimeSeconds(); //custom extension method




public partial class ServerTime
[JsonProperty("epoch")]
public string Epoch get; set;

[JsonProperty("iso")]
public DateTime Iso get; set;

[JsonProperty("timestamp")]
public long Timestamp get; set;



And was able to get a valid JSON response calling /api/v1/spot/public/time that I was able to deserialize for my assertion, even with the fake keys. Probably as this is the public API. This does prove that the URL called is correct.



When the request path is changed to



"/api/v1/spot/ccex/account/assets"


And tested for more secure private data from the API, the response is 400 Bad Request with the following content in the body of the response



"message":"Encrypted key does not exist"


which is as expected given that the keys I used were fake.



This gives me every indication that the API does in fact work as expected provided that you follow what is suggested in the linked documentation.






share|improve this answer



























  • I did both way. With or without ()

    – user4951
    Apr 13 at 12:12











  • Thank you very much. I will check and see how it works

    – user4951
    Apr 14 at 9:09











  • oh you got message. I got empty stuff. Let me check.

    – user4951
    Apr 14 at 9:09











  • The response is empty I got this in exception object Message = "The remote server returned an error: (401) Unauthorized."

    – user4951
    Apr 14 at 9:32











  • Would you print the intermediate strings. Also changging to coinmex.pro doesn't help

    – user4951
    Apr 14 at 9:44















2







+100









The documentation states




This body is the request body string or omitted if there is no request body (usually the GET request)




Note: emphasis mine



yet you include an empty JSON object on a GET request



Dim stringtosign = timestampstring + "GET" + longmethod + "" '1553784499976GET/api/v1/spot/ccex/account/assets


That should not be included in a GET request.



'1553784499976GET/api/v1/spot/ccex/account/assets
Dim stringtosign = timestampstring + "GET" + longmethod


So it appears you were not constructing the signature correctly as per documentation.



Noticed that the docs




The root URL for REST access:https://www.coinmex.pro




while you are trying to call "https://www.coinmex.com"




Timestamp



Unless otherwise specified, all timestamps in APIs are returned in microseconds.



The ACCESS-TIMESTAMP header must be the number of seconds since UTC's
time Unix Epoch. Decimal values are allowed. Your timestamp must be
within 30 seconds of the API service time, otherwise your request will
be considered expired and rejected.
If you think there is a large time
difference between your server and the API server, then we recommend
that you use the time point to check the API server time.




note: emphasis mine



Following extension method was used to calculate time stamp



private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

/// <summary>
/// Converts the value of the current <see cref="System.DateTime"/> object to Unix Time.
/// </summary>
/// <param name="dateTime"></param>
/// <remarks>
/// </remarks>
/// This method first converts the current instance to UTC before returning its Unix time.
/// <returns>
/// A <see cref="System.Int64"/> defined as the number of seconds that have elapsed since midnight Coordinated Universal Time (UTC), January 1, 1970, not counting leap seconds.
/// </returns>
public static long ToUnixTimeSeconds(this DateTime dateTime)
if (dateTime.ToUniversalTime() < Epoch)
return 0;


var totalSeconds = dateTime.ToUniversalTime().Subtract(Epoch).TotalSeconds;
var timestamp = Convert.ToInt64(totalSeconds);

return timestamp;



I did the following Test to see if I could call the API following the documentation and it appears to have worked.



I used c# however



[TestClass]
public class CoinMaxAPITests
const string apiKey1 = "cmx-1027e54e4723b09810576f8e7a5413**";
const string fakeSecret = "43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac23==";
const string passphrase1 = "1Us6&f%*K@QsqrYZ";

Lazy<HttpClient> http = new Lazy<HttpClient>(() =>
var rootUrl = "https://www.coinmex.pro";

CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler
CookieContainer = cookies,
UseCookies = true,

;
var client = new HttpClient()
BaseAddress = new Uri(rootUrl)
;
client.DefaultRequestHeaders.TryAddWithoutValidation("ACCESS-KEY", apiKey1);
client.DefaultRequestHeaders.TryAddWithoutValidation("ACCESS-PASSPHRASE", passphrase1);
return client;
);

[TestMethod]
public async Task Should_Accept_Signature()
//Arrange
var requestPath = "/api/v1/spot/public/time";
var method = "GET";
var timeStamp = getEstimatedTimeStamp().ToString(); //"1555253371"

var message = timeStamp + method + requestPath; //"1555253371GET/api/v1/spot/public/time"

var secretKey = Convert.FromBase64String(fakeSecret);
var hmac = new HMACSHA256(secretKey);
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
var signature = Convert.ToBase64String(hash);//Jzui/eO3iyLTD6L9qVkUO0EBpZP/lFhx1HlsbuSNt/8=

var request = new HttpRequestMessage(HttpMethod.Get, requestPath);
request.Headers.TryAddWithoutValidation("ACCESS-TIMESTAMP", timeStamp);
request.Headers.TryAddWithoutValidation("ACCESS-SIGN", signature);

//Act
var response = await http.Value.SendAsync(request);

//Assert
response.EnsureSuccessStatusCode();

var json = await response.Content.ReadAsStringAsync();
//""epoch":"1555253501.225","iso":"2019-04-14T14:51:41.225Z","timestamp":1555253501225"
var server = JsonConvert.DeserializeObject<ServerTime>(json);

server.Should().NotBeNull();
server.Iso.Date.Should().Be(DateTime.Today);


long getEstimatedTimeStamp()
return DateTime.Now.ToUnixTimeSeconds(); //custom extension method




public partial class ServerTime
[JsonProperty("epoch")]
public string Epoch get; set;

[JsonProperty("iso")]
public DateTime Iso get; set;

[JsonProperty("timestamp")]
public long Timestamp get; set;



And was able to get a valid JSON response calling /api/v1/spot/public/time that I was able to deserialize for my assertion, even with the fake keys. Probably as this is the public API. This does prove that the URL called is correct.



When the request path is changed to



"/api/v1/spot/ccex/account/assets"


And tested for more secure private data from the API, the response is 400 Bad Request with the following content in the body of the response



"message":"Encrypted key does not exist"


which is as expected given that the keys I used were fake.



This gives me every indication that the API does in fact work as expected provided that you follow what is suggested in the linked documentation.






share|improve this answer



























  • I did both way. With or without ()

    – user4951
    Apr 13 at 12:12











  • Thank you very much. I will check and see how it works

    – user4951
    Apr 14 at 9:09











  • oh you got message. I got empty stuff. Let me check.

    – user4951
    Apr 14 at 9:09











  • The response is empty I got this in exception object Message = "The remote server returned an error: (401) Unauthorized."

    – user4951
    Apr 14 at 9:32











  • Would you print the intermediate strings. Also changging to coinmex.pro doesn't help

    – user4951
    Apr 14 at 9:44













2







+100







2







+100



2






+100





The documentation states




This body is the request body string or omitted if there is no request body (usually the GET request)




Note: emphasis mine



yet you include an empty JSON object on a GET request



Dim stringtosign = timestampstring + "GET" + longmethod + "" '1553784499976GET/api/v1/spot/ccex/account/assets


That should not be included in a GET request.



'1553784499976GET/api/v1/spot/ccex/account/assets
Dim stringtosign = timestampstring + "GET" + longmethod


So it appears you were not constructing the signature correctly as per documentation.



Noticed that the docs




The root URL for REST access:https://www.coinmex.pro




while you are trying to call "https://www.coinmex.com"




Timestamp



Unless otherwise specified, all timestamps in APIs are returned in microseconds.



The ACCESS-TIMESTAMP header must be the number of seconds since UTC's
time Unix Epoch. Decimal values are allowed. Your timestamp must be
within 30 seconds of the API service time, otherwise your request will
be considered expired and rejected.
If you think there is a large time
difference between your server and the API server, then we recommend
that you use the time point to check the API server time.




note: emphasis mine



Following extension method was used to calculate time stamp



private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

/// <summary>
/// Converts the value of the current <see cref="System.DateTime"/> object to Unix Time.
/// </summary>
/// <param name="dateTime"></param>
/// <remarks>
/// </remarks>
/// This method first converts the current instance to UTC before returning its Unix time.
/// <returns>
/// A <see cref="System.Int64"/> defined as the number of seconds that have elapsed since midnight Coordinated Universal Time (UTC), January 1, 1970, not counting leap seconds.
/// </returns>
public static long ToUnixTimeSeconds(this DateTime dateTime)
if (dateTime.ToUniversalTime() < Epoch)
return 0;


var totalSeconds = dateTime.ToUniversalTime().Subtract(Epoch).TotalSeconds;
var timestamp = Convert.ToInt64(totalSeconds);

return timestamp;



I did the following Test to see if I could call the API following the documentation and it appears to have worked.



I used c# however



[TestClass]
public class CoinMaxAPITests
const string apiKey1 = "cmx-1027e54e4723b09810576f8e7a5413**";
const string fakeSecret = "43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac23==";
const string passphrase1 = "1Us6&f%*K@QsqrYZ";

Lazy<HttpClient> http = new Lazy<HttpClient>(() =>
var rootUrl = "https://www.coinmex.pro";

CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler
CookieContainer = cookies,
UseCookies = true,

;
var client = new HttpClient()
BaseAddress = new Uri(rootUrl)
;
client.DefaultRequestHeaders.TryAddWithoutValidation("ACCESS-KEY", apiKey1);
client.DefaultRequestHeaders.TryAddWithoutValidation("ACCESS-PASSPHRASE", passphrase1);
return client;
);

[TestMethod]
public async Task Should_Accept_Signature()
//Arrange
var requestPath = "/api/v1/spot/public/time";
var method = "GET";
var timeStamp = getEstimatedTimeStamp().ToString(); //"1555253371"

var message = timeStamp + method + requestPath; //"1555253371GET/api/v1/spot/public/time"

var secretKey = Convert.FromBase64String(fakeSecret);
var hmac = new HMACSHA256(secretKey);
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
var signature = Convert.ToBase64String(hash);//Jzui/eO3iyLTD6L9qVkUO0EBpZP/lFhx1HlsbuSNt/8=

var request = new HttpRequestMessage(HttpMethod.Get, requestPath);
request.Headers.TryAddWithoutValidation("ACCESS-TIMESTAMP", timeStamp);
request.Headers.TryAddWithoutValidation("ACCESS-SIGN", signature);

//Act
var response = await http.Value.SendAsync(request);

//Assert
response.EnsureSuccessStatusCode();

var json = await response.Content.ReadAsStringAsync();
//""epoch":"1555253501.225","iso":"2019-04-14T14:51:41.225Z","timestamp":1555253501225"
var server = JsonConvert.DeserializeObject<ServerTime>(json);

server.Should().NotBeNull();
server.Iso.Date.Should().Be(DateTime.Today);


long getEstimatedTimeStamp()
return DateTime.Now.ToUnixTimeSeconds(); //custom extension method




public partial class ServerTime
[JsonProperty("epoch")]
public string Epoch get; set;

[JsonProperty("iso")]
public DateTime Iso get; set;

[JsonProperty("timestamp")]
public long Timestamp get; set;



And was able to get a valid JSON response calling /api/v1/spot/public/time that I was able to deserialize for my assertion, even with the fake keys. Probably as this is the public API. This does prove that the URL called is correct.



When the request path is changed to



"/api/v1/spot/ccex/account/assets"


And tested for more secure private data from the API, the response is 400 Bad Request with the following content in the body of the response



"message":"Encrypted key does not exist"


which is as expected given that the keys I used were fake.



This gives me every indication that the API does in fact work as expected provided that you follow what is suggested in the linked documentation.






share|improve this answer















The documentation states




This body is the request body string or omitted if there is no request body (usually the GET request)




Note: emphasis mine



yet you include an empty JSON object on a GET request



Dim stringtosign = timestampstring + "GET" + longmethod + "" '1553784499976GET/api/v1/spot/ccex/account/assets


That should not be included in a GET request.



'1553784499976GET/api/v1/spot/ccex/account/assets
Dim stringtosign = timestampstring + "GET" + longmethod


So it appears you were not constructing the signature correctly as per documentation.



Noticed that the docs




The root URL for REST access:https://www.coinmex.pro




while you are trying to call "https://www.coinmex.com"




Timestamp



Unless otherwise specified, all timestamps in APIs are returned in microseconds.



The ACCESS-TIMESTAMP header must be the number of seconds since UTC's
time Unix Epoch. Decimal values are allowed. Your timestamp must be
within 30 seconds of the API service time, otherwise your request will
be considered expired and rejected.
If you think there is a large time
difference between your server and the API server, then we recommend
that you use the time point to check the API server time.




note: emphasis mine



Following extension method was used to calculate time stamp



private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

/// <summary>
/// Converts the value of the current <see cref="System.DateTime"/> object to Unix Time.
/// </summary>
/// <param name="dateTime"></param>
/// <remarks>
/// </remarks>
/// This method first converts the current instance to UTC before returning its Unix time.
/// <returns>
/// A <see cref="System.Int64"/> defined as the number of seconds that have elapsed since midnight Coordinated Universal Time (UTC), January 1, 1970, not counting leap seconds.
/// </returns>
public static long ToUnixTimeSeconds(this DateTime dateTime)
if (dateTime.ToUniversalTime() < Epoch)
return 0;


var totalSeconds = dateTime.ToUniversalTime().Subtract(Epoch).TotalSeconds;
var timestamp = Convert.ToInt64(totalSeconds);

return timestamp;



I did the following Test to see if I could call the API following the documentation and it appears to have worked.



I used c# however



[TestClass]
public class CoinMaxAPITests
const string apiKey1 = "cmx-1027e54e4723b09810576f8e7a5413**";
const string fakeSecret = "43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac23==";
const string passphrase1 = "1Us6&f%*K@QsqrYZ";

Lazy<HttpClient> http = new Lazy<HttpClient>(() =>
var rootUrl = "https://www.coinmex.pro";

CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler
CookieContainer = cookies,
UseCookies = true,

;
var client = new HttpClient()
BaseAddress = new Uri(rootUrl)
;
client.DefaultRequestHeaders.TryAddWithoutValidation("ACCESS-KEY", apiKey1);
client.DefaultRequestHeaders.TryAddWithoutValidation("ACCESS-PASSPHRASE", passphrase1);
return client;
);

[TestMethod]
public async Task Should_Accept_Signature()
//Arrange
var requestPath = "/api/v1/spot/public/time";
var method = "GET";
var timeStamp = getEstimatedTimeStamp().ToString(); //"1555253371"

var message = timeStamp + method + requestPath; //"1555253371GET/api/v1/spot/public/time"

var secretKey = Convert.FromBase64String(fakeSecret);
var hmac = new HMACSHA256(secretKey);
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
var signature = Convert.ToBase64String(hash);//Jzui/eO3iyLTD6L9qVkUO0EBpZP/lFhx1HlsbuSNt/8=

var request = new HttpRequestMessage(HttpMethod.Get, requestPath);
request.Headers.TryAddWithoutValidation("ACCESS-TIMESTAMP", timeStamp);
request.Headers.TryAddWithoutValidation("ACCESS-SIGN", signature);

//Act
var response = await http.Value.SendAsync(request);

//Assert
response.EnsureSuccessStatusCode();

var json = await response.Content.ReadAsStringAsync();
//""epoch":"1555253501.225","iso":"2019-04-14T14:51:41.225Z","timestamp":1555253501225"
var server = JsonConvert.DeserializeObject<ServerTime>(json);

server.Should().NotBeNull();
server.Iso.Date.Should().Be(DateTime.Today);


long getEstimatedTimeStamp()
return DateTime.Now.ToUnixTimeSeconds(); //custom extension method




public partial class ServerTime
[JsonProperty("epoch")]
public string Epoch get; set;

[JsonProperty("iso")]
public DateTime Iso get; set;

[JsonProperty("timestamp")]
public long Timestamp get; set;



And was able to get a valid JSON response calling /api/v1/spot/public/time that I was able to deserialize for my assertion, even with the fake keys. Probably as this is the public API. This does prove that the URL called is correct.



When the request path is changed to



"/api/v1/spot/ccex/account/assets"


And tested for more secure private data from the API, the response is 400 Bad Request with the following content in the body of the response



"message":"Encrypted key does not exist"


which is as expected given that the keys I used were fake.



This gives me every indication that the API does in fact work as expected provided that you follow what is suggested in the linked documentation.







share|improve this answer














share|improve this answer



share|improve this answer








edited Apr 14 at 15:36

























answered Apr 13 at 9:40









NkosiNkosi

137k23 gold badges180 silver badges241 bronze badges




137k23 gold badges180 silver badges241 bronze badges















  • I did both way. With or without ()

    – user4951
    Apr 13 at 12:12











  • Thank you very much. I will check and see how it works

    – user4951
    Apr 14 at 9:09











  • oh you got message. I got empty stuff. Let me check.

    – user4951
    Apr 14 at 9:09











  • The response is empty I got this in exception object Message = "The remote server returned an error: (401) Unauthorized."

    – user4951
    Apr 14 at 9:32











  • Would you print the intermediate strings. Also changging to coinmex.pro doesn't help

    – user4951
    Apr 14 at 9:44

















  • I did both way. With or without ()

    – user4951
    Apr 13 at 12:12











  • Thank you very much. I will check and see how it works

    – user4951
    Apr 14 at 9:09











  • oh you got message. I got empty stuff. Let me check.

    – user4951
    Apr 14 at 9:09











  • The response is empty I got this in exception object Message = "The remote server returned an error: (401) Unauthorized."

    – user4951
    Apr 14 at 9:32











  • Would you print the intermediate strings. Also changging to coinmex.pro doesn't help

    – user4951
    Apr 14 at 9:44
















I did both way. With or without ()

– user4951
Apr 13 at 12:12





I did both way. With or without ()

– user4951
Apr 13 at 12:12













Thank you very much. I will check and see how it works

– user4951
Apr 14 at 9:09





Thank you very much. I will check and see how it works

– user4951
Apr 14 at 9:09













oh you got message. I got empty stuff. Let me check.

– user4951
Apr 14 at 9:09





oh you got message. I got empty stuff. Let me check.

– user4951
Apr 14 at 9:09













The response is empty I got this in exception object Message = "The remote server returned an error: (401) Unauthorized."

– user4951
Apr 14 at 9:32





The response is empty I got this in exception object Message = "The remote server returned an error: (401) Unauthorized."

– user4951
Apr 14 at 9:32













Would you print the intermediate strings. Also changging to coinmex.pro doesn't help

– user4951
Apr 14 at 9:44





Would you print the intermediate strings. Also changging to coinmex.pro doesn't help

– user4951
Apr 14 at 9:44













0
















I wonder what I should pick as the answer due to this conflict of interest.



What happened is he go the extra mile of trying some API. I decided to create a new API key and post it here. It's read-only and can't possibly go wrong anyway. Before I posted here I try to run it once more expecting that it won't work like usual.



It turns out my code simply works. It seems that there are error in API key, secret, or password.



Here is the code that finally work



Protected Overrides Function getJsonPrivate(method As String, otherParameters() As Tuple(Of String, String)) As String
Dim base = "https://www.coinmex.pro"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = (getEstimatedTimeStamp() / 1000).ToString

Dim stringtosign = timestampstring + "GET" + longmethod '1555154812.857GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(_secret1)) '"43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2******
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@QsqrYZ
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response
End Function





share|improve this answer

























  • I upvoted Nkosi's answer.

    – user4951
    Apr 14 at 15:57











  • Nkosi explanation that the shouldn't be there also helped. I tried both ways. But because of his explanation, I do not need to try both ways. I just need to try the one right way. That's not where the issue is.

    – user4951
    Apr 14 at 15:59






  • 1





    Next time, when I have a problem like this again, I will create a temporary read only API key and secret and share that. After that people can easil try this with real API

    – user4951
    Apr 14 at 16:09











  • Yes having an actual temp key would have been ideal. I wanted to help but was torn about having to create an account in order to get around the limitations of not having a usable key.

    – Nkosi
    Apr 14 at 19:40
















0
















I wonder what I should pick as the answer due to this conflict of interest.



What happened is he go the extra mile of trying some API. I decided to create a new API key and post it here. It's read-only and can't possibly go wrong anyway. Before I posted here I try to run it once more expecting that it won't work like usual.



It turns out my code simply works. It seems that there are error in API key, secret, or password.



Here is the code that finally work



Protected Overrides Function getJsonPrivate(method As String, otherParameters() As Tuple(Of String, String)) As String
Dim base = "https://www.coinmex.pro"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = (getEstimatedTimeStamp() / 1000).ToString

Dim stringtosign = timestampstring + "GET" + longmethod '1555154812.857GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(_secret1)) '"43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2******
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@QsqrYZ
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response
End Function





share|improve this answer

























  • I upvoted Nkosi's answer.

    – user4951
    Apr 14 at 15:57











  • Nkosi explanation that the shouldn't be there also helped. I tried both ways. But because of his explanation, I do not need to try both ways. I just need to try the one right way. That's not where the issue is.

    – user4951
    Apr 14 at 15:59






  • 1





    Next time, when I have a problem like this again, I will create a temporary read only API key and secret and share that. After that people can easil try this with real API

    – user4951
    Apr 14 at 16:09











  • Yes having an actual temp key would have been ideal. I wanted to help but was torn about having to create an account in order to get around the limitations of not having a usable key.

    – Nkosi
    Apr 14 at 19:40














0














0










0









I wonder what I should pick as the answer due to this conflict of interest.



What happened is he go the extra mile of trying some API. I decided to create a new API key and post it here. It's read-only and can't possibly go wrong anyway. Before I posted here I try to run it once more expecting that it won't work like usual.



It turns out my code simply works. It seems that there are error in API key, secret, or password.



Here is the code that finally work



Protected Overrides Function getJsonPrivate(method As String, otherParameters() As Tuple(Of String, String)) As String
Dim base = "https://www.coinmex.pro"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = (getEstimatedTimeStamp() / 1000).ToString

Dim stringtosign = timestampstring + "GET" + longmethod '1555154812.857GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(_secret1)) '"43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2******
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@QsqrYZ
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response
End Function





share|improve this answer













I wonder what I should pick as the answer due to this conflict of interest.



What happened is he go the extra mile of trying some API. I decided to create a new API key and post it here. It's read-only and can't possibly go wrong anyway. Before I posted here I try to run it once more expecting that it won't work like usual.



It turns out my code simply works. It seems that there are error in API key, secret, or password.



Here is the code that finally work



Protected Overrides Function getJsonPrivate(method As String, otherParameters() As Tuple(Of String, String)) As String
Dim base = "https://www.coinmex.pro"
Dim premethod = "/api/v1/spot/ccex/"
Dim longmethod = premethod + method

Dim timestampstring = (getEstimatedTimeStamp() / 1000).ToString

Dim stringtosign = timestampstring + "GET" + longmethod '1555154812.857GET/api/v1/spot/ccex/account/assets

Dim hasher = New System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(_secret1)) '"43a90185f5b7ab25af045e9e64bac5dc745934f359f1806fcdd2a4af80ac2******
Dim sighashbyte = hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(stringtosign))
Dim signature = Convert.ToBase64String(sighashbyte) '"FIgrJFDOQctqnkOTyuv6+uTy6xw3OZiP4waC1u6P5LU="=
Dim url = base + longmethod 'https://www.coinmex.com/api/v1/spot/ccex/account/assets

'_apiKey1="cmx-1027e54e4723b09810576f8e7a5413**"
'_passphrase1= 1Us6&f%*K@QsqrYZ
'
Dim response = CookieAwareWebClient.downloadString1(url, "", Tuple.Create("ACCESS-KEY", _apiKey1), Tuple.Create("ACCESS-SIGN", signature), Tuple.Create("ACCESS-TIMESTAMP", timestampstring), Tuple.Create("ACCESS-PASSPHRASE", _passphrase1))

Return response
End Function






share|improve this answer












share|improve this answer



share|improve this answer










answered Apr 14 at 15:56









user4951user4951

14.4k45 gold badges149 silver badges256 bronze badges




14.4k45 gold badges149 silver badges256 bronze badges















  • I upvoted Nkosi's answer.

    – user4951
    Apr 14 at 15:57











  • Nkosi explanation that the shouldn't be there also helped. I tried both ways. But because of his explanation, I do not need to try both ways. I just need to try the one right way. That's not where the issue is.

    – user4951
    Apr 14 at 15:59






  • 1





    Next time, when I have a problem like this again, I will create a temporary read only API key and secret and share that. After that people can easil try this with real API

    – user4951
    Apr 14 at 16:09











  • Yes having an actual temp key would have been ideal. I wanted to help but was torn about having to create an account in order to get around the limitations of not having a usable key.

    – Nkosi
    Apr 14 at 19:40


















  • I upvoted Nkosi's answer.

    – user4951
    Apr 14 at 15:57











  • Nkosi explanation that the shouldn't be there also helped. I tried both ways. But because of his explanation, I do not need to try both ways. I just need to try the one right way. That's not where the issue is.

    – user4951
    Apr 14 at 15:59






  • 1





    Next time, when I have a problem like this again, I will create a temporary read only API key and secret and share that. After that people can easil try this with real API

    – user4951
    Apr 14 at 16:09











  • Yes having an actual temp key would have been ideal. I wanted to help but was torn about having to create an account in order to get around the limitations of not having a usable key.

    – Nkosi
    Apr 14 at 19:40

















I upvoted Nkosi's answer.

– user4951
Apr 14 at 15:57





I upvoted Nkosi's answer.

– user4951
Apr 14 at 15:57













Nkosi explanation that the shouldn't be there also helped. I tried both ways. But because of his explanation, I do not need to try both ways. I just need to try the one right way. That's not where the issue is.

– user4951
Apr 14 at 15:59





Nkosi explanation that the shouldn't be there also helped. I tried both ways. But because of his explanation, I do not need to try both ways. I just need to try the one right way. That's not where the issue is.

– user4951
Apr 14 at 15:59




1




1





Next time, when I have a problem like this again, I will create a temporary read only API key and secret and share that. After that people can easil try this with real API

– user4951
Apr 14 at 16:09





Next time, when I have a problem like this again, I will create a temporary read only API key and secret and share that. After that people can easil try this with real API

– user4951
Apr 14 at 16:09













Yes having an actual temp key would have been ideal. I wanted to help but was torn about having to create an account in order to get around the limitations of not having a usable key.

– Nkosi
Apr 14 at 19:40






Yes having an actual temp key would have been ideal. I wanted to help but was torn about having to create an account in order to get around the limitations of not having a usable key.

– Nkosi
Apr 14 at 19:40



















draft saved

draft discarded















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55404704%2fwhat-is-wrong-with-this-coinmex-api%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

SQL error code 1064 with creating Laravel foreign keysForeign key constraints: When to use ON UPDATE and ON DELETEDropping column with foreign key Laravel error: General error: 1025 Error on renameLaravel SQL Can't create tableLaravel Migration foreign key errorLaravel php artisan migrate:refresh giving a syntax errorSQLSTATE[42S01]: Base table or view already exists or Base table or view already exists: 1050 Tableerror in migrating laravel file to xampp serverSyntax error or access violation: 1064:syntax to use near 'unsigned not null, modelName varchar(191) not null, title varchar(191) not nLaravel cannot create new table field in mysqlLaravel 5.7:Last migration creates table but is not registered in the migration table

은진 송씨 목차 역사 본관 분파 인물 조선 왕실과의 인척 관계 집성촌 항렬자 인구 같이 보기 각주 둘러보기 메뉴은진 송씨세종실록 149권, 지리지 충청도 공주목 은진현