- PVSM.RU - https://www.pvsm.ru -
Добрый день, дорогой %username%!
Совсем недавно я узнал про такую замечательную вещь, как биткоин [1]. Не секрет, что последние 2-3 месяца наблюдался бурный рост этой криптовалюты. Казалось бы, ну есть у нас криптовалюта, а сбывать ее где? После моего предыдущего поста [2] у меня появилось несколько лайткоинов. Естественно, я начал думать о способе сбыта легкой криптовалюты. Немного погуглив, я набрел на биржу BTC-E [3] и, о великий котэ, увидел заветную кнопочку «Trade API».
С этого момента судьба следующих пары-тройки дней для меня была предопределена — я загорелся идеей воспользоваться этим самым API и сделать миллионы грязных долларов написать бота, который автоматически бы сбывал и покупал ресурсы. А так как я fully proficient (взято с моего профиля на elance.com) в Objective C, на нем я писать и буду.
Три дня прошло, и я все-таки осилил API. Зачем я выкладываю все это в открытый доступ? Что же, на это есть ряд причин:
Внимание! Под катом разбор основных моментов работы с API; подводные камни, о которые мне пришлось споткнуться; исходники.
Заходим на сайт биржы в раздел FAQ [4], открываем вкладку «API». Можно покликать по Public Api, ответы будут приходить в JSON формате. Нравится мне этот формат. Уже хорошо, идем дальше.
Переходим по ссылке «Trade Api» [5]. Что мы видим? Нужно просто отправлять POST запросы и будет нам счастье! Отлично, а как это на Objective C-то реализовать? Вот незадача! До этого момента я ведь никогда и не думал о подобном на моем родном языке. Ничего страшного, разберемся.
Что у нас тут? Посылаем ключ API из профиля в заголовок «api»; POST запрос добавляем как тело запроса; а в «sign» передаем хеш нашего тела запроса, подписанный секретным ключом «secret». Круто. Где их взять? Заходим в профиль.
Ничего себе! И то, и то в одном месте! Вот это да, пока что я иду на правильном пути. Главное не забыть установить нужные права для наших ключей.
Давайте взглянем на тело стандартного ответа с публичного запроса из API. Попробуем узнать курс BTC/USD. Шлепнем по запросу [6]. Получаем примерно следующее:
{"ticker":{"high":139,"low":126.6,"avg":132.8,"vol":971784.85609,"vol_cur":7345.76864,"last":136.396,"buy":137,"sell":136.396,"server_time":1365246479}}
Про JSON рассказывать не буду, в интернете по нему полно туториалов. Нас интересуют покупка и продажа. Напишем небольшой код для реализации запроса и его обработки! Вперед к коду!
- (void)updateLtcToUsdRate {
dispatch_async(kBgQueue, ^{
NSData *data = [apiHandler getResponseFromPublicServerUrl:@"https://btc-e.com/api/2/ltc_usd/ticker"];
NSError* error;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:&error];
NSDictionary* ticker = [json objectForKey:@"ticker"];
NSString *sell = [ticker objectForKey:@"sell"];
NSString *buy = [ticker objectForKey:@"buy"];
ltcToUsdSellRateLabel.stringValue = addDollarSign(sell);
ltcToUsdBuyRateLabel.stringValue = addDollarSign(buy);
});
}
- (NSData *)getResponseFromPublicServerUrl:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [NSData dataWithContentsOfURL:url];
return data;
}
Пройдемся по коду. В проекте у нас пара классов, и BtceApiHandler работает с запросами на сервер. getResponseFromPublicServerUrl — это метод BtceApiHandler класса. Здесь никаких POST запросов отправлять не нужно, просто забираем данные с сервера. Дальше слегка обрабатываем JSON и получаем значения sell и buy. Покажем их на экран нашему пользователю (пока что только нам).
А что за addDollarSign? А вот тут я постиг приятные плюшки функций в Objective C. До сегодняшнего момента я их редко использовал, старался их избегать, но теперь легким движением руки появляются вот такие крендельки. Мелочь, а приятно.
NSString *addDollarSign(NSString *string) {
NSString *newString = [NSString stringWithFormat:@"$%@",string];
return newString;
}
Ну, с публичным API вроде как разобрались, если нет — Вам дорога к мануалу [4].
Что же происходит с личным API? Пока я разобрался с POST запросами в Objective C, я потерял приличное количество нервных клеток. Да и в самом API есть примеры алгоритмов и ввода, а что должно быть на выходе между Вами и сервером — не понятно. Пришлось спрашивать в чате самой биржи. Благо, приятные люди там есть, и мне помогли.
В чем проблема? Наверное, в том, что я никогда и не работал с POST запросами на своем родном языке. Только Java, только хардкор. Прыгнем в код класса BtceApiHandler.
- (void)setupInitialValues {
api_key = @"P55XJOOF-207D9CCC-A7NDKIYK-KIMFCOXC-WJPJ21XY";
secret_key = @"5bb4f0c55d6100d583505dc98eaff1df7d1ba281b5f8365686090d5cbbdb9846";
}
Нужно инициализировать две важные переменные. Позже можно будет сделать специальное окошко и так далее, но я просто захордкодил ключи. Не обольщайтесь, их я уже отключил.
- (NSData *)getResponseFromServerForPost:(NSDictionary *)postDictionary {
NSString *post;
int i = 0;
for (NSString *key in [postDictionary allKeys]) {
NSString *value = [postDictionary objectForKey:key];
if (i==0)
post = [NSString stringWithFormat:@"%@=%@", key, value];
else
post = [NSString stringWithFormat:@"%@&%@=%@", post, key, value];
i++;
}
post = [NSString stringWithFormat:@"%@&nonce=%@", post, getNonce()];
NSString *signedPost = hmacForKeyAndData(secret_key, post);
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
initWithURL:
[NSURL URLWithString:@"https://btc-e.com/tapi"]];
[request setHTTPMethod:@"POST"];
[request setValue:api_key forHTTPHeaderField:@"key"];
[request setValue:signedPost forHTTPHeaderField:@"sign"];
[request setHTTPBody:[post dataUsingEncoding: NSUTF8StringEncoding]];
NSURLResponse *theResponse = NULL;
NSError *theError = NULL;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&theResponse error:&theError];
return responseData;
}
А вот и монструозный метод отправки и обработки POST запроса! Мы передаем в него аргументом NSDictionary, в котором храним связки параметр-значение. Первая часть преобразует наш словарь в POST запрос, вторая часть забивает наш запрос стандартными данными (тип данных, url, key, sign), третья часть посылает запрос и возвращает NSData c ответом.
NSString *hmacForKeyAndData(NSString *key, NSString *data) {
const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
unsigned char cHMAC[CC_SHA512_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA512, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSMutableString *hashString = [NSMutableString stringWithCapacity:sizeof(cHMAC) * 2];
for (int i = 0; i < sizeof(cHMAC); i++) {
[hashString appendFormat:@"%02x", cHMAC[i]];
}
return hashString;
}
Особое внимание стоит уделить коду подписи данных в «sign». Почему? Да я на него убил больше суток! Больше суток хождения по интернетам и стаковерфловам. Происходит все просто: используя встроенные возможности языка, мы подписываем ключом данные и вытягиваем SHA512 хеш. Цикл, думаю, объяснять не стоит — там и так все очевидно. Раньше пытался получить значение через description наших данных — не получалось. Пришлось спросить на stackoverflow про этот небольшой циклик.
NSString *getNonce() {
NSTimeInterval timeStamp = [[NSDate date] timeIntervalSinceDate:[NSDate dateWithString:@"2012-04-18 00:00:01 +0600"]];
int currentNonce = [NSNumber numberWithDouble: timeStamp].intValue;
NSString *nonceString = [NSString stringWithFormat:@"%i",currentNonce];
return nonceString;
}
А еще есть функция getNonce(). Параметр nonce передавать в POST запросе обязательно. Это инкремент, так что каждое последующее число должно быть больше предыдущего. Вот такие пироги. Ах да, эта функция считает время, прошедшее с моего совершеннолетия.
Пока мы можем мониторить интересную информацию, смотреть за ростом и падением криптовалют. Ничего особенного, можно сказать, я просто обернул API в Objective C. Небольшой скриншот програмки-на-коленке:
API побеждено, дело техники закончено. Впереди автоматизация процесса — а это уйма работы над алгоритмами. Сам я далеко не финансист, да что уж, даже не начинающий трейдер на рынке. Если вдруг кто из желающих здесь захочет со мной поработать, и возможно даже поднять немного денег — милости прошу ко мне в различные IM, контакты есть в моем хабрацентре [7].
А вдруг кто из Objective C программистов захочет позаниматься в свободное время этими механизмами и созданием со мной юзер-френдли UI? Опять же, милости прошу в IM.
Исходники тут [8]. Приятного просмотра. Все под лицензией GPL (первая попавшаяся мне open source лицензия). Качайте, компилируйте, пользуйтесь, распространяйте. Имя автора сохраняйте.
Если Вы нашли какую-то опечатку иили неточность — напишите, пожалуйста, мне в личку или в комментарии. Всем спасибо, а я пойду спать. Это API заставляло меня спать по 4-6 часов в сутки. Наконец-то высплюсь. Всем спасибо.
Автор: backmeupplz
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/e-lektronnaya-kommertsiya/31403
Ссылки в тексте:
[1] биткоин: http://bitcoin.org/en/
[2] предыдущего поста: http://habrahabr.ru/post/174651/
[3] BTC-E: https://btc-e.com
[4] FAQ: https://btc-e.com/page/2
[5] «Trade Api»: https://btc-e.com/api/documentation
[6] запросу: https://btc-e.com/api/2/btc_usd/ticker
[7] моем хабрацентре: http://habrahabr.ru/users/backmeupplz/
[8] тут: https://github.com/backmeupplz/BTCEBot
[9] Источник: http://habrahabr.ru/post/175703/
Нажмите здесь для печати.