You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

284 lines
12 KiB

/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#define EXCHANGE_NAME "lakebtc"
#define UPDATE prices777_ ## lakebtc
#define SUPPORTS lakebtc ## _supports
#define SIGNPOST lakebtc ## _signpost
#define TRADE lakebtc ## _trade
#define ORDERSTATUS lakebtc ## _orderstatus
#define CANCELORDER lakebtc ## _cancelorder
#define OPENORDERS lakebtc ## _openorders
#define TRADEHISTORY lakebtc ## _tradehistory
#define BALANCES lakebtc ## _balances
#define PARSEBALANCE lakebtc ## _parsebalance
#define WITHDRAW lakebtc ## _withdraw
#define CHECKBALANCE lakebtc ## _checkbalance
double UPDATE(struct prices777 *prices,int32_t maxdepth)
{
if ( prices->url[0] == 0 )
{
if ( strcmp(prices->rel,"USD") == 0 )
sprintf(prices->url,"https://www.LakeBTC.com/api_v1/bcorderbook");
else if ( strcmp(prices->rel,"CNY") == 0 )
sprintf(prices->url,"https://www.LakeBTC.com/api_v1/bcorderbook_cny");
else printf("illegal lakebtc pair.(%s/%s)\n",prices->base,prices->rel);
}
return(prices777_standard("lakebtc",prices->url,prices,0,0,maxdepth,0));
}
int32_t SUPPORTS(char *base,char *rel)
{
char *baserels[][2] = { {"btc","usd"}, {"btc","cny"} };
int32_t polarity;
polarity = baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel);
printf("lakebtc.(%s %s) polarity.%d\n",base,rel,polarity);
return(polarity);
}
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *payload,char *hdr1,uint64_t tonce)
{
char hdr2[512],cmdbuf[1024],buf64[1024],hdr3[512],dest[1025],hdr4[512],*sig,*data = 0; cJSON *json;
hdr2[0] = hdr3[0] = hdr4[0] = 0;
json = 0;
if ( (sig= hmac_sha1_str(dest,exchange->apisecret,(int32_t)strlen(exchange->apisecret),hdr1)) != 0 )
{
sprintf(cmdbuf,"%s:%s",exchange->userid,sig);
nn_base64_encode((void *)cmdbuf,strlen(cmdbuf),buf64,sizeof(buf64));
sprintf(hdr1,"Authorization:Basic %s",buf64);
sprintf(hdr2,"Json-Rpc-Tonce: %llu",(long long)tonce);
if ( dotrade == 0 )
data = exchange_would_submit(payload,hdr1,hdr2,hdr3,hdr4);
else if ( (data= curl_post(cHandlep,"https://www.LakeBTC.com/api_v1",0,payload,hdr1,hdr2,hdr3,hdr4)) != 0 )
json = cJSON_Parse(data);
}
if ( retstrp != 0 )
*retstrp = data;
else if ( data != 0 )
free(data);
return(json);
}
/* LakeBTC provides trading JSON-RPC API interface. HMAC (Hash-based Message Authentication Code) is employed as our authentication mechanisms. You need at 0.1 BTC in your account to retrieve your private key.
Besides your private key, the client needs to prepare the following attributes
tonce (timestamp in microseconds, i.e., unixtime × 1000000, make sure your clock is correctly adjusted)
accesskey (your registered email address at LakeBTC)
requestmethod (post)
id (JSON-RPC request id, an integer)
method (JSON-RPC method)
params (JSON-RPC parameters)
Concatenate the above parameters with &, in that order. Parameters can be blank. For example, $signature =
tonce=1389067414466757&accesskey=foo@bar.com&requestmethod=post&id=123&method=ticker&params=
Create HMAC signature with your private key by using SHA1. $hash =
hash_hmac('sha1', $signature, $privatetkey) #php
Join your email and the hash signature with colon (:), and sign with Base64. $b64 =
base64_encode("foo@bar.com:<hash>") #php YXRjQHF3amlhbi5jb206ZmEzM2UzYzg5MDZjg5MzdiYzFiYw==
Set HTTP Header. Note tonce is the same as that in Step 2.
Json-Rpc-Tonce: 1389067414466757 #HTTP HEADER
Authorization: Basic YXRjQHF3amlhbi5jb206ZmEzM2UzYzg5MDZjg5MzdiYzFiYw== #HTTP HEADER
POST params data in JSON format to this url:
https://www.LakeBTC.com/api_v1
API Methods
getAccountInfo
method=getAccountInfo
params= (i.e., blank)
static CURL *cHandle;
char *data,*method,buf64[4096],paramstr[128],jsonbuf[1024],base[64],rel[64],pairstr[64],params[1024],dest[512],url[1024],cmdbuf[8192],*sig,hdr1[4096],hdr2[4096],buf[4096]; cJSON *json; uint64_t tonce,nonce,txid = 0;
*retstrp = 0;
params[0] = 0;
nonce = exchange_nonce(exchange);
tonce = (nonce * 1000000 + ((uint64_t)milliseconds() % 1000) * 1000);
if ( dir == 0 )
{
method = "getAccountInfo";
sprintf(buf,"tonce=%llu&accesskey=%s&requestmethod=post&id=1&method=%s&params=",(long long)tonce,exchange->userid,method);
sprintf(jsonbuf,"{\"method\":\"%s\",\"params\":[\"%s\"],\"id\":1}",method,params);
}
else
{
if ( (dir= flipstr_for_exchange(exchange,pairstr,"%s_%s",dir,&price,&volume,base,rel)) == 0 )
{
printf("cant find baserel (%s/%s)\n",base,rel);
return(0);
}
method = (dir > 0) ? "buyOrder" : "sellOrder";
touppercase(rel);
sprintf(paramstr,"%.2f,%.4f,%s",price,volume,rel);
sprintf(buf,"tonce=%llu&accesskey=%s&requestmethod=post&id=1&method=%s&params=%s",(long long)tonce,exchange->userid,method,paramstr);
sprintf(jsonbuf,"{\"method\":\"%s\",\"params\":[\"%s\"],\"id\":1}",method,paramstr);
}
if ( (sig= hmac_sha1_str(dest,exchange->apisecret,(int32_t)strlen(exchange->apisecret),buf)) != 0 )
{
sprintf(cmdbuf,"%s:%s",exchange->userid,sig);
nn_base64_encode((void *)cmdbuf,strlen(cmdbuf),buf64,sizeof(buf64));
sprintf(url,"https://www.lakebtc.com/api_v1");
sprintf(hdr1,"Authorization:Basic %s",buf64);
sprintf(hdr2,"Json-Rpc-Tonce: %llu",(long long)tonce);
if ( (data= curl_post(&cHandle,url,0,jsonbuf,hdr1,hdr2,0,0)) != 0 )
{
//printf("submit cmd.(%s) [%s]\n",jsonbuf,data);
if ( (json= cJSON_Parse(data)) != 0 )
{
txid = j64bits(json,"order_id");
free_json(json);
}
} else fprintf(stderr,"submit err cmd.(%s)\n",cmdbuf);
if ( retstrp != 0 )
*retstrp = data;
else if ( data != 0 )
free(data);
}
*/
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr)
{
char field[128],*str,*itemstr = 0; cJSON *obj=0,*item=0,*prof=0; double locked = 0;
*balancep = 0.;
strcpy(field,coinstr);
touppercase(field);
if ( exchange->balancejson != 0 && (obj= jobj(exchange->balancejson,"balance")) != 0 && (item= jobj(exchange->balancejson,"locked")) != 0 && (prof= jobj(exchange->balancejson,"profile")) != 0 )
{
*balancep = jdouble(obj,field);
locked = jdouble(item,field);
obj = cJSON_CreateObject();
jaddstr(obj,"base",field);
jaddnum(obj,"balance",*balancep);
jaddnum(obj,"locked",locked);
if ( (str= jstr(prof,"btc_deposit_addres")) != 0 )
jaddstr(obj,"deposit_address",str);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
cJSON *BALANCES(void **cHandlep,struct exchange_info *exchange)
{
char payload[1024],jsonbuf[1024],*method; uint64_t tonce;
method = "getAccountInfo";
tonce = (exchange_nonce(exchange) * 1000000 + ((uint64_t)milliseconds() % 1000) * 1000);
sprintf(payload,"tonce=%llu&accesskey=%s&requestmethod=post&id=1&method=%s&params=",(long long)tonce,exchange->userid,method);
sprintf(jsonbuf,"{\"method\":\"%s\",\"params\":[\"%s\"],\"id\":1}",method,"");
return(SIGNPOST(cHandlep,1,0,exchange,jsonbuf,payload,tonce));
}
#include "checkbalance.c"
uint64_t TRADE(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume)
{
char payload[1024],jsonbuf[1024],pairstr[64],paramstr[512],*extra,*method;
cJSON *json; uint64_t tonce,txid = 0;
if ( (extra= *retstrp) != 0 )
*retstrp = 0;
tonce = (exchange_nonce(exchange) * 1000000 + ((uint64_t)milliseconds() % 1000) * 1000);
if ( (dir= flipstr_for_exchange(exchange,pairstr,"%s_%s",dir,&price,&volume,base,rel)) == 0 )
{
printf("cant find baserel (%s/%s)\n",base,rel);
return(0);
}
method = (dir > 0) ? "buyOrder" : "sellOrder";
touppercase(rel);
sprintf(paramstr,"%.2f,%.4f,%s",price,volume,rel);
sprintf(payload,"tonce=%llu&accesskey=%s&requestmethod=post&id=1&method=%s&params=%s",(long long)tonce,exchange->userid,method,paramstr);
sprintf(jsonbuf,"{\"method\":\"%s\",\"params\":[\"%s\"],\"id\":1}",method,paramstr);
if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume) == 0 && (json= SIGNPOST(cHandlep,dotrade,retstrp,exchange,jsonbuf,payload,tonce)) != 0 )
{
txid = j64bits(json,"order_id");
free_json(json);
}
return(txid);
}
char *CANCELORDER(void **cHandlep,struct exchange_info *exchange,cJSON *argjson,uint64_t quoteid)
{
char payload[1024],jsonbuf[1024],*method,*retstr = 0; cJSON *json; uint64_t tonce;
method = "cancelOrder";
tonce = (exchange_nonce(exchange) * 1000000 + ((uint64_t)milliseconds() % 1000) * 1000);
sprintf(jsonbuf,"{\"method\":\"%s\",\"params\":[\"%llu\"],\"id\":1}",method,(long long)quoteid);
if ( (json= SIGNPOST(cHandlep,1,&retstr,exchange,payload,jsonbuf,tonce)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized cancelorder
}
char *OPENORDERS(void **cHandlep,struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],jsonbuf[1024],*method,*retstr = 0; cJSON *json; uint64_t tonce;
method = "getOrders";
tonce = (exchange_nonce(exchange) * 1000000 + ((uint64_t)milliseconds() % 1000) * 1000);
sprintf(jsonbuf,"{\"method\":\"%s\",\"params\":[\"%s\"],\"id\":1}",method,"");
if ( (json= SIGNPOST(cHandlep,1,&retstr,exchange,payload,jsonbuf,tonce)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized open orders
}
char *TRADEHISTORY(void **cHandlep,struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],jsonbuf[1024],timestr[64],*method,*retstr = 0;
cJSON *json; uint64_t tonce; uint32_t starttime;
method = "getTrades";
if ( (starttime= juint(argjson,"start")) != 0 )
sprintf(timestr,"%u",starttime);
else timestr[0] = 0;
tonce = (exchange_nonce(exchange) * 1000000 + ((uint64_t)milliseconds() % 1000) * 1000);
sprintf(jsonbuf,"{\"method\":\"%s\",\"params\":[%s],\"id\":1}",method,timestr);
if ( (json= SIGNPOST(cHandlep,1,&retstr,exchange,payload,jsonbuf,tonce)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized tradehistory
}
char *ORDERSTATUS(void **cHandlep,struct exchange_info *exchange,cJSON *argjson,uint64_t quoteid)
{
char *status,*retstr;
status = OPENORDERS(cHandlep,exchange,argjson);
if ( (retstr= exchange_extractorderid(0,status,quoteid,"id")) != 0 )
{
free(status);
return(retstr);
}
free(status);
return(clonestr("{\"error\":\"cant find quoteid\"}"));
}
char *WITHDRAW(void **cHandlep,struct exchange_info *exchange,cJSON *argjson)
{
return(clonestr("{\"error\":\"lakebtc doesnt seem to have withdraw api!\"}"));
}
struct exchange_funcs lakebtc_funcs = EXCHANGE_FUNCS(lakebtc,EXCHANGE_NAME);
#undef UPDATE
#undef SUPPORTS
#undef SIGNPOST
#undef TRADE
#undef ORDERSTATUS
#undef CANCELORDER
#undef OPENORDERS
#undef TRADEHISTORY
#undef BALANCES
#undef PARSEBALANCE
#undef WITHDRAW
#undef EXCHANGE_NAME
#undef CHECKBALANCE