Can't figure out what this API want's me to use as data when using matlab for a POST request

5 views (last 30 days)
If you look at this 2 links:
I have been trying for 2 days now to structure my code so I can authenticate there, but it's just wrong.
What exactly should I put in the data param for the HMAC encryption? How does the body Matlab sends in a webread POST request look? As I said, Im getting nowhere with this.
import matlab.net.*
import matlab.net.http.*
URI = matlab.net.URI('https://testnet.bitmex.com/api/v1/order');
U = '?symbol=XBTUSD&side=Sell&orderQty=30&clOrdLinkID=SoL&ordType=Market&contingencyType=OneCancelsTheOther';
Meth = matlab.net.http.RequestMethod.POST;
Req = matlab.net.http.RequestMessage;
Req.Method = Meth;
Body = matlab.net.http.MessageBody(U);
Req.Body = Body;
ApiExpires = datetime('now','format','yyyy-MM-dd''T''HH:mm:ss''Z') + days(5);
ApiExpires = posixtime(ApiExpires);
ApiExpires = round(ApiExpires);
ApiExpires = num2str(ApiExpires);
ApiSecret = 'Tu9CNn_04cQxvjdgGm3MBV7KsqxzkNMAw_3LtUuLUhqC--iX';
Com = complete(Req,URI);
Path = '/api/v1/order';
Verb = 'POST';
EncData = strcat(Verb,Path,ApiExpires,'?symbol=XBTUSD&side=Sell&orderQty=30&clOrdLinkID=SoL&ordType=Market&contingencyType=OneCancelsTheOther');
signature = HMAC(ApiSecret,EncData,'SHA-256');
signature = lower(signature);
ApiSignature = matlab.net.http.HeaderField('api-signature',signature);
ApiKey2 = matlab.net.http.HeaderField('api-key','C8VW3PArKaNoh04CE103hucF');
ApiExpires2 = matlab.net.http.HeaderField('api-expires',ApiExpires);
Header = [ApiExpires2,ApiKey2,ApiSignature];
Req.Header = Header;
Why is this unauthorized when doing send(Req,URI)? (Testnet so do what you want with the keys)

Accepted Answer

Erik Nyström
Erik Nyström on 31 May 2018
Edited: Erik Nyström on 31 May 2018
Solved it by adding:
ContentType = matlab.net.http.HeaderField('Content-Type','application/x-www-form-urlencoded');
Header = [ContentType,ApiExpires2,ApiKey2,ApiSignature];

More Answers (1)

Lautaro Parada
Lautaro Parada on 19 May 2020
I highly recommend you to separate your script in functions or classes, this helps with the error handling and leads anyone to follow along with the logic of your code. Therefore, I think a more robust approach should be separate your script in 3 functions, and with that, generate your signature for your trading bot.
An example of my suggestion could be the following:
clear; clc;
% Reference information based on the script that you uploaded to mathworks
% please change or delete the key and the secret tokens in your production enviroment!!
key = 'C8VW3PArKaNoh04CE103hucF';
secret = 'Tu9CNn_04cQxvjdgGm3MBV7KsqxzkNMAw_3LtUuLUhqC--iX';
endpoint = '/order';
method = 'post';
server = 'https://testnet.bitmex.com/api/v1';
% Example of which data are you sending to the Exchange
nonce = get_nonce()
signature = get_sign(secret, method, endpoint, nonce)
% making the actual request to the
request(key, secret, server, method, endpoint)
function req = request(key, secret, server, method, endpoint)
% custom request handler for the Api of Bitmex
%
% Arguments
% -------
% key(char): key token of the user from the API
% secret(char): secret token of the user from the API
% endpoint(char): functionality to use from the API
% nonce(double): timestamp in milliseconds
%
% Output
% -------
% data from the API with the custom inputs
% error handling
method = upper(method);
% create the headers for the private calls
nonce = get_nonce();
signature = get_sign(secret, method, endpoint, nonce);
% packaging all the headers into a cell array
headers = {
'api-key' key; ...
'api-expires' nonce; ...
'api-signature' signature; ...
'Content-Type' 'application/x-www-form-urlencoded'};
disp(headers) % this should be removed in a production enviroment!
% weboptions of the request
private_options = weboptions('HeaderFields', headers);
url = [server endpoint];
% sending the request to the Bitmex server
req = webread(url, private_options);
end
function nonce = get_nonce(~)
% The nonce must be an integer that must always
% meet the condition of being greater than the
% last nonce used. This ensures that your requests
% cannot be repeated by a "Man in the middle".
% A (good) way to accomplish this is to use a timestamp.
%
% Arguments
% -------
% None
%
% Output
% -------
% timestamp in microseconds, as a character array.
% Generate a nonce (timestamp in microseconds)
nonce_ = datetime('now','format','yyyy-MM-dd''T''HH:mm:ss''Z') + days(5);
nonce = num2str(round(posixtime(nonce_)));
end
function signature = get_sign(secret, method, endpoint, nonce)
% Java framework used to generate the signature, based
% on the nonce. Please see the Matlab documentation for details.
%
% Arguments
% -------
% secret(char): secret api token
% method(char): http method to use with the API (e.g. GET, POST, etc)
% endpoint(char): functionality to use from the api
% nonce(double): timestamp to be used for the dynamic signature
%
% Output
% -------
% char array with the desired signature using HMACSHA256 encoding format
% prepare the string for the signature
msg = strjoin([method endpoint string(nonce)]);
msg_bytes = unicode2native(msg, 'UTF-8');
secret_key_bytes = unicode2native(string(secret), 'UTF-8');
secret_key_spec = javax.crypto.spec.SecretKeySpec(secret_key_bytes,'HmacSHA256');
hmac_provider = javax.crypto.Mac.getInstance('HmacSHA384');
hmac_provider.init(secret_key_spec);
% creating the signature
signature = org.apache.commons.codec.binary.Hex.encodeHex(hmac_provider.doFinal(msg_bytes)).';
end
Naturally, the server will return the status 401 for this request (since I don't know if the credentials are correct nor the most updated version of these ones). Thereby, please refresh your credentials.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!