Мастера DELPHI, Delphi programming community Рейтинг@Mail.ru Титульная страница Поиск, карта сайта Написать письмо 
| Новости |
Новости сайта
Поиск |
Поиск по лучшим сайтам о Delphi
FAQ |
Огромная база часто задаваемых вопросов и, конечно же, ответы к ним ;)
Статьи |
Подборка статей на самые разные темы. Все о DELPHI
Книги |
Новинки книжного рынка
Новости VCL
Обзор свежих компонент со всего мира, по-русски!
|
| Форумы
Здесь вы можете задать свой вопрос и наверняка получите ответ
| ЧАТ |
Место для общения :)
Орешник |
Коллекция курьезных вопросов из форумов
KOL и MCK |
KOL и MCK - Компактные программы на Delphi
Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / rsdn.org

 
Чтобы не потерять эту дискуссию, сделайте закладку « предыдущая ветвь | форум | следующая ветвь »

работа с API биржи bittrex.com


tippa   (30.08.14 22:00

Добрый день.
подскажите как в делфи купить что-то на бирже bittrex.com через апи?
создал ключ API Keys, он состоит из 2 частей: Key и Secret.

в документации [https://bittrex.com/Home/Api] указано, что купить можно с помощью запроса
https://bittrex.com/api/v1.1/market/buymarket?apikey=API_KEY&market=BTC-LTC&quantity=1.2  
собственно что нужно писать вместо API_KEY в этом запросе?
использую Delphi7 и библиотеку Synapse.


junglecat   (31.08.14 00:31[1]

судя по всему, apisecret нужен для подписи http-заголовка в запросе, apisign


tippa   (31.08.14 08:07[2]

junglecat, да, я немного поразбирался, на странице апи есть пример использования ключа, насколько я понимаю - это PHP
$apikey='xxx';
$apisecret='xxx';
$nonce=time();
$uri='https://bittrex.com/api/v1.1/market/getopenorders?apikey='.$apikey.'&nonce='.$nonce;
$sign=hash_hmac('sha512',$uri,$apisecret);
$ch = curl_init($uri);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('apisign:'.$sign));
$execResult = curl_exec($ch);
$obj = json_decode($execResult);

и главная загвозка в функции
$sign=hash_hmac('sha512',$uri,$apisecret)
где можно найти аналогичную функцию для делфи, или научите пользоваться гуглом, так как ничего путного найти не смог


brother ©   (31.08.14 08:34[3]

http://hashcode.ru/questions/214460/sha2-hmac-sha512-%D0%B2-delphi
?


tippa   (31.08.14 21:56[4]

нашел в сети модуль для различных хэш функций, cHash.pas
https://code.google.com/p/fundamentals/source/browse/trunk/Source/Utils/cHash.pas?r=30

хэш находится верно, проверял на сторонних онлайн сервисах.
Но биржа упорно возвращает ошибку, вроде все сделал по образцу из PHP-примера.

var key, secret:string;
   url,sign:string;
   HTTP:THttpSend;
   Data:TStringStream;
   list:TStringList;
begin
key:='xxx';
secret:='xxx';

url:='https://bittrex.com/api/v1.1/account/getbalances?apikey='+key+'&nonce='+inttostr(DateTimeToUnix(now));
sign:=SHA512DigestToHex(CalcHMAC_SHA512(secret, url));

HTTP:=THttpSend.Create;
Data := TStringStream.Create('');
Data.WriteString('apisign:'+sign);
Data.Position:=0;
HTTP.Document.LoadFromStream(Data);
Data.free;
HTTP.HTTPMethod('GET','https://bittrex.com/api/v1.1/account/getbalances?apikey='+key);
list:=TStringList.Create;
list.LoadFromStream(HTTP.Document);
showmessage(inttostr(HTTP.ResultCode)+#13#10+list.Text);
list.Free;
HTTP.Free;

end;


выдает
200
{"success":false,"message":"NONCE_NOT_PROVIDED","result":null}


по ссылке выше через TIdHMACSHA512 тоже пробовал, но что-то на моей 7 делфи не хватает, например не работает функция StringOf для перевода TidBytes в строку. Пробовал колхозить через Chr() - какие-то кракозябры получаются. Но первый вариант же должен работать, что может быть не так?


junglecat   (31.08.14 22:18[5]

а не так надо?
HTTP.HTTPMethod('GET','https://bittrex.com/api/v1.1/account/getbalances?apikey='+key+'&nonce='+inttostr(DateTimeToUnix(now)));


tippa   (01.09.14 08:17[6]

junglecat, да, вы правы. Исправил, но опять не хочет работать. Ниже поправленный код.
var key, secret:string;
   url,sign:string;
   HTTP:THttpSend;
   Data:TStringStream;
   list:TStringList;
   nonce:string;
begin
key:='c446699bf07f438b9d95e6240f2ac504';
secret:='d09f4a1ee901498f8c7d4fbc7af2fd2f';
nonce:=inttostr(DateTimeToUnix(now));

url:='https://bittrex.com/api/v1.1/account/getbalances?apikey='+key+'&nonce='+nonce;
sign:=SHA512DigestToHex(CalcHMAC_SHA512(secret, url));

HTTP:=THttpSend.Create;
Data := TStringStream.Create('');
Data.WriteString('apisign:'+sign);
Data.Position:=0;
HTTP.Document.LoadFromStream(Data);
Data.free;
HTTP.HTTPMethod('GET',url);
list:=TStringList.Create;
list.LoadFromStream(HTTP.Document);
memo1.Lines.Add(inttostr(HTTP.ResultCode)+#13#10+list.Text);
list.Free;
HTTP.Free;

end;

ключи в примере реальные, для получения баланса их достаточно.
теперь возвращает ответ в виде:
200
{"success":false,"message":"APISIGN_NOT_PROVIDED","result":null}


не знаю куда еще копнуть, грешу на
sign:=SHA512DigestToHex(CalcHMAC_SHA512(secret, url));
хотя проверял её работу на сайте http://www.freeformatter.com/hmac-generator.html, результат сходится.


junglecat   (01.09.14 09:23[7]

> [6] tippa   (01.09.14 08:17)

видимо, apisign должен быть в заголовке http-запроса, а не в самом запросе


tippa   (01.09.14 09:45[8]


> junglecat   (01.09.14 09:23) [7]

о да, наконец-то, спасибо
вот рабочий вариант если кому интересно
var key, secret:string;
   url,sign:string;
   HTTP:THttpSend;
   list:TStringList;
   nonce:string;
begin
key:='xxx';
secret:='xxx';
nonce:=inttostr(DateTimeToUnix(now));

url:='https://bittrex.com/api/v1.1/account/getbalances?apikey='+key+'&nonce='+nonce;
sign:=SHA512DigestToHex(CalcHMAC_SHA512(secret, url));

HTTP:=THttpSend.Create;
HTTP.Headers.Add('apisign:'+sign);
HTTP.HTTPMethod('GET',url);
list:=TStringList.Create;
list.LoadFromStream(HTTP.Document);
memo1.Lines.Add(inttostr(HTTP.ResultCode)+#13#10+list.Text);
list.Free;
HTTP.Free;

end;


rebelperm ©   (01.02.18 22:50[9]

Отличный код. Мне понравился.
Сейчас как раз пишу программу и решил начать с запроса баланса.
А ни кто не задавался написать подобные запросы к API на Delphi к другим биржам
Cucoin или Cruptopia?
Нашел проект на C# и на PHP, но толку переделать запрос баланса не хватает. :-(


rebelperm ©   (03.02.18 23:01[10]

const metod = 'GetBalance';
     //rq ='';
     rq ='CurrencyId:2';
var key, secret:string;
  url,sign:string;
  HTTP:TidHTTP;
  list:TStringList;
  nonce:string;
  post_data : string;
  m : string;
  requestContentBase64String : string;
  signature : string;
  hmacsignature : string;
  header_value : string;
  headers : string;

 data: TIdMultiPartFormDataStream;

 begin
 key:='xxx';
 secret:='xxx';
 nonce:=inttostr(DateTimeToUnix(now));
url:='https://www.cryptopia.co.nz/Api/'+metod;
// url:='https://www.cryptopia.co.nz/Api/SubmitTrade';
post_data:=rq;
m:=md5(post_data);
requestContentBase64String:=EncodeBase64(m);
signature:=key + 'POST' + AnsiLowerCase(url) + nonce + requestContentBase64String;
hmacsignature:= EncodeBase64(SHA256DigestToHexa(chash.CalcHMAC_SHA256(DecodeBase64(secret),signa ture)));
header_value:= 'amx ' + key + ':' + hmacsignature + ':' + nonce;
HTTP:=TidHTTP.Create;
HTTP.IOHandler:=form1.IdSSLIOHandlerSocketOpenSSL1;
HTTP.Request.CustomHeaders.Add('Authorization:'+ header_value);
HTTP.Request.CustomHeaders.Add('Content-Type: application/json; charset=utf-8');
HTTP.Request.URL:=url;
data := TIdMultiPartFormDataStream.Create;
data.AddFormField('CurrencyId', '2');
form1.memo1.Text:=HTTP.post(url,data);   {}
data.Free;
HTTP.Free;


rebelperm ©   (03.02.18 23:01[11]

const metod = 'GetBalance';
     //rq ='';
     rq ='CurrencyId:2';
var key, secret:string;
  url,sign:string;
  HTTP:TidHTTP;
  list:TStringList;
  nonce:string;
  post_data : string;
  m : string;
  requestContentBase64String : string;
  signature : string;
  hmacsignature : string;
  header_value : string;
  headers : string;

 data: TIdMultiPartFormDataStream;

 begin
 key:='xxx';
 secret:='xxx';
 nonce:=inttostr(DateTimeToUnix(now));
url:='https://www.cryptopia.co.nz/Api/'+metod;
// url:='https://www.cryptopia.co.nz/Api/SubmitTrade';
post_data:=rq;
m:=md5(post_data);
requestContentBase64String:=EncodeBase64(m);
signature:=key + 'POST' + AnsiLowerCase(url) + nonce + requestContentBase64String;
hmacsignature:= EncodeBase64(SHA256DigestToHexa(chash.CalcHMAC_SHA256(DecodeBase64(secret),signa ture)));
header_value:= 'amx ' + key + ':' + hmacsignature + ':' + nonce;
HTTP:=TidHTTP.Create;
HTTP.IOHandler:=form1.IdSSLIOHandlerSocketOpenSSL1;
HTTP.Request.CustomHeaders.Add('Authorization:'+ header_value);
HTTP.Request.CustomHeaders.Add('Content-Type: application/json; charset=utf-8');
HTTP.Request.URL:=url;
data := TIdMultiPartFormDataStream.Create;
data.AddFormField('CurrencyId', '2');
form1.memo1.Text:=HTTP.post(url,data);   {}
data.Free;
HTTP.Free;


Fernando Rizzato   (14.02.18 20:31[12]

const
 apiKey: String = 'your apiKey';
 apiSecret: String = 'your apiSecret';
 requestURL: String = 'https://www.cryptopia.co.nz/Api/GetBalance';

var
 FHTTPClient: THTTPClient;
 LPOSTRequest: IHTTPRequest;
 LResponse: IHTTPResponse;
 LHeaders: TNetHeaders;

 Data: TJSONObject;
 nonce: String;
 signature: String;
 hmacsignature: String;
 header_value: String;
 requestB64: String;
begin
 Data := TJSONObject.Create;
 FHTTPClient := THTTPClient.Create;
 try
   // get the POST request
   LPOSTRequest := FHTTPClient.GetRequest('POST', requestURL);

   // Create the body request
   Data.AddPair(TJSONPair.Create('Currency', 'DOT'));
   LPOSTRequest.SourceStream := TStringStream.Create(Data.ToJSON);

   // Authentication
   requestB64 := TNetEncoding.Base64.EncodeBytesToString
     (THashMD5.GetHashBytes(Data.ToJSON));

   // Create random nonce for each request
   nonce := IntToStr(DateTimeToUnix(Now));

   // Creating the raw signature string
   signature := apiKey + 'POST' + LowerCase(TNetEncoding.URL.Encode(requestURL)
     ) + nonce + requestB64;

   hmacsignature := TNetEncoding.Base64.EncodeBytesToString
     (THashSHA2.GetHMACAsBytes(signature,
     TNetEncoding.Base64.DecodeStringToBytes(apiSecret)));

   header_value := 'amx ' + apiKey + ':' + hmacsignature + ':' + nonce;

   LHeaders := [
     TNetHeader.Create('Content-Type', 'application/json; charset=utf-8'),
     TNetHeader.Create('Authorization', header_value)];
   LResponse := FHTTPClient.Execute(LPOSTRequest, nil, LHeaders);

   memResult.Text := LResponse.ContentAsString;
 finally
   FHTTPClient.Free;
 end;​


albe ©   (24.04.18 01:27[13]

Существуют десятки языков программирования, которыми можно создать Бота – программу для получения доступа по API к своему счету на криптобирже и все они сводятся к одной идее. В некий «черный ящик» вводим несколько входных параметров:
1. КЛЮЧ (получаем на сайте биржи); [a8a7ac9c2746496febfea43fd0906625]
2. СЕКРЕТ (получаем на сайте биржи); [/pK9WVQxQc/ITOTJI67LWuXC2WH7/rkByu0ZaVdO0gJ=]
3. WWW – адрес отправки запроса (получаем на сайте биржи); [https://www.cryptopia.co.nz/api/]
4. МЕТОД (Запрос баланса, запрос истории, установка/удаление ордеров и т.п.); [GetBalance]
5. ПАРАМЕТРЫ запроса (некие дополнения к методу). [Currency: BTC]
Этот «черный ящик» обрабатывает наши запросы, шифрует, хеширует, кодирует, в общем, создает  правильные (понятные серверу биржи) абракадабровские строки. Затем отправляет их на сервер и возвращает нам, более менее понятный ответ на наш запрос. Так вот в этом черном ящике все так запутано и непонятно, а нигде толком не найти разъяснения. Самостоятельно поразбирался в этом с биржей CRIPTOPIA выяснил кое-что. Нужны методы хеширования MD5, Кодирования/Раскодирования методом Base64, шифрования методом HMAC-SHA256. Вот, как я понял, такая последовательность операций в «ченом ящике»:
1. Хешируем ПАРАМЕТРЫ запроса методом MD5 - (S1). [e69aeb3fdec45a367dddc510e924fc02]
2. Кодируем захешированные параметры (S1) методом Base64 - (S2). [ZTY5YWViM2ZkZWM0NWEzNjdkZGRjNTEwZTkyNGZjMDI=]
3. Нумеруем свой запрос (S3), NONCE = количество секунд, от какой то там древней даты (тут все ясно). [1989294]
4. Конструируем некую строку (S4) таким образом:
S4=КЛЮЧ + "POST" + WWW+МЕТОД + S3 + S2; [a8a7ac9c2746496febfea43fd0906625POSThttps://www.cryptopia.co.nz/api/getbalance1989294ZTY5YWViM2ZkZWM0NWEzNjdkZGRjNTEwZTkyNGZjMDI=]
5. Декодирую СЕКРЕТ методом Base64 (S5); [þ’½YT1AÏÈLäÉ#®ËZåÂÙa 1;þ¹ Êí iWNÒ ]
6. Шифрую методом HMAC-SHA256 сконструированную строчку (S4) с помощью декодированного СЕКРЕТА (S5), получаю еще более непонятную строку (S6); [9353f8320d6f295a19051c7f75132bfb66b2ae64e9b08a6e803c1266ee39d182]
7. Кодирую эту (S6) строку методом Base64, получаю (S7); [OTM1M2Y4MzIwZDZmMjk1YTE5MDUxYzdmNzUxMzJiZmI2NmIyYWU2NGU5YjA4YTZlODAzYzEyNjZlZTM 5ZDE4Mg==]
8. Конструируем еще одну некую строку (S8) таким образом:
S8= "amx" + КЛЮЧ + ":" + S7 + ":" + S3; [amxa8a7ac9c2746496febfea43fd0906625:OTM1M2Y4MzIwZDZmMjk1YTE5MDUxYzdmNzUxMzJiZmI 2NmIyYWU2NGU5YjA4YTZlODAzYzEyNjZlZTM5ZDE4Mg==:1989294]
9. В компоненте POST-запроса (у меня в Delphi это TIdHTTP) в заголовок пишем 'authorization' и строку S7.
IdHTTP1.Request.CustomHeaders.AddValue('authorization',S8);
Все эти сложности, начиная с первого пункта, делались лишь для того, чтобы в заголовок нашей компоненты вписать эту сложнейшую строчку, которая позволит авторизоваться и получить доступ в нашему счету на бирже.
10. Делаем запрос серверу биржи:
Lin.Text:=IdHTTP1.Post(WWW,Par);
Ответ сервера записан в переменную Lin и ответ этот, к моему глубокому сожалению,  все еще: {"Success":false,"Error":"Invalid authorization header."}.
Подскажите, пожалуйста, где я неправ, что я упустил.
СПАСИБО.


albe ©   (24.04.18 01:37[14]

УПС, Конечно же так правильно : Lin.Text:=IdHTTP1.Post(WWW+МЕТОД,ПАРАМЕТРЫ);


версия для печати

Написать ответ

Ваше имя (регистрация  E-mail 







Разрешается использование тегов форматирования текста:
<b>жирный</b> <i>наклонный</i> <u>подчеркнутый</u>,
а для выделения текста программ, используйте <code> ... </code>
и не забывайте закрывать теги! </b></i></u></code> :)


Наверх

  Рейтинг@Mail.ru     Титульная страница Поиск, карта сайта Написать письмо