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;
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
add a comment
|
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
1
Suggestion: maybe editing your tags would help. Tagapi
is meaningless: if you hover it, you'll see it says "DO NOT USE". Maybe addvb.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
add a comment
|
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
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
vb.net rest api
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. Tagapi
is meaningless: if you hover it, you'll see it says "DO NOT USE". Maybe addvb.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
add a comment
|
1
Suggestion: maybe editing your tags would help. Tagapi
is meaningless: if you hover it, you'll see it says "DO NOT USE". Maybe addvb.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
add a comment
|
2 Answers
2
active
oldest
votes
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.
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
|
show 3 more comments
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
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
add a comment
|
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
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
|
show 3 more comments
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.
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
|
show 3 more comments
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.
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.
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
|
show 3 more comments
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
|
show 3 more comments
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
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
add a comment
|
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
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
add a comment
|
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
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
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
add a comment
|
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
add a comment
|
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 addvb.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