|
|
@ -14,13 +14,243 @@ |
|
|
|
******************************************************************************/ |
|
|
|
|
|
|
|
// included from basilisk.c
|
|
|
|
void basilisk_swap_balancingtrade(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t iambob) |
|
|
|
{ |
|
|
|
// update balance, compare to target balance, issue balancing trade via central exchanges, if needed
|
|
|
|
double price,volume,srcamount,destamount,profitmargin,dir=0.,dotrade=1.; char base[64],rel[64]; |
|
|
|
srcamount = swap->I.req.srcamount; |
|
|
|
destamount = swap->I.req.destamount; |
|
|
|
profitmargin = (double)swap->I.req.profitmargin / 1000000.; |
|
|
|
if ( srcamount <= SMALLVAL || destamount <= SMALLVAL ) |
|
|
|
{ |
|
|
|
printf("illegal amount for balancing %f %f\n",srcamount,destamount); |
|
|
|
return; |
|
|
|
} |
|
|
|
strcpy(rel,"BTC"); |
|
|
|
if ( strcmp(swap->I.req.src,"BTC") == 0 ) |
|
|
|
{ |
|
|
|
strcpy(base,swap->I.req.dest); |
|
|
|
price = (srcamount / destamount); |
|
|
|
volume = destamount / SATOSHIDEN; |
|
|
|
dir = -1.; |
|
|
|
} |
|
|
|
else if ( strcmp(swap->I.req.dest,"BTC") == 0 ) |
|
|
|
{ |
|
|
|
strcpy(base,swap->I.req.src); |
|
|
|
price = (destamount / srcamount); |
|
|
|
volume = srcamount / SATOSHIDEN; |
|
|
|
dir = 1.; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
printf("only BTC trades can be balanced, not (%s/%s)\n",swap->I.req.src,swap->I.req.dest); |
|
|
|
return; |
|
|
|
} |
|
|
|
if ( iambob != 0 ) |
|
|
|
{ |
|
|
|
if ( myinfo->IAMLP != 0 ) |
|
|
|
{ |
|
|
|
printf("BOB: price %f * vol %f -> %s newprice %f margin %.2f%%\n",price,volume,dir < 0. ? "buy" : "sell",price + dir * price * profitmargin,100*profitmargin); |
|
|
|
if ( dir < 0. ) |
|
|
|
InstantDEX_buy(myinfo,0,0,0,"poloniex",base,rel,price,volume,dotrade); |
|
|
|
else InstantDEX_sell(myinfo,0,0,0,"poloniex",base,rel,price,volume,dotrade); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
if ( myinfo->IAMLP != 0 ) |
|
|
|
{ |
|
|
|
printf("ALICE: price %f * vol %f -> %s newprice %f margin %.2f%%\n",price,volume,dir > 0. ? "buy" : "sell",price - dir * price * profitmargin,100*profitmargin); |
|
|
|
if ( dir > 0. ) |
|
|
|
InstantDEX_buy(myinfo,0,0,0,"poloniex",base,rel,price,volume,dotrade); |
|
|
|
else InstantDEX_sell(myinfo,0,0,0,"poloniex",base,rel,price,volume,dotrade); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
cJSON *basilisk_rawtxobj(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx) |
|
|
|
{ |
|
|
|
char hexstr[sizeof(rawtx->I)*2+1+4096]; cJSON *obj = cJSON_CreateObject(); |
|
|
|
jaddstr(obj,"name",rawtx->name); |
|
|
|
init_hexbytes_noT(hexstr,(void *)&rawtx->I,sizeof(rawtx->I)); |
|
|
|
jaddstr(obj,"info",hexstr); |
|
|
|
if ( rawtx->I.datalen < sizeof(hexstr)/2 ) |
|
|
|
{ |
|
|
|
init_hexbytes_noT(hexstr,(void *)rawtx->txbytes,rawtx->I.datalen); |
|
|
|
jaddstr(obj,"txbytes",hexstr); |
|
|
|
} |
|
|
|
return(obj); |
|
|
|
} |
|
|
|
|
|
|
|
struct basilisk_rawtx *basilisk_nameconv(struct supernet_info *myinfo,struct basilisk_swap *swap,char *name) |
|
|
|
{ |
|
|
|
if ( strcmp("myfee",name) == 0 ) |
|
|
|
return(&swap->myfee); |
|
|
|
else if ( strcmp("otherfee",name) == 0 ) |
|
|
|
return(&swap->otherfee); |
|
|
|
else if ( strcmp("bobdeposit",name) == 0 ) |
|
|
|
return(&swap->bobdeposit); |
|
|
|
else if ( strcmp("bobrefund",name) == 0 ) |
|
|
|
return(&swap->bobrefund); |
|
|
|
else if ( strcmp("aliceclaim",name) == 0 ) |
|
|
|
return(&swap->aliceclaim); |
|
|
|
else if ( strcmp("bobpayment",name) == 0 ) |
|
|
|
return(&swap->bobpayment); |
|
|
|
else if ( strcmp("alicespend",name) == 0 ) |
|
|
|
return(&swap->alicespend); |
|
|
|
else if ( strcmp("bobreclaim",name) == 0 ) |
|
|
|
return(&swap->bobreclaim); |
|
|
|
else if ( strcmp("alicepayment",name) == 0 ) |
|
|
|
return(&swap->alicepayment); |
|
|
|
else if ( strcmp("bobspend",name) == 0 ) |
|
|
|
return(&swap->bobspend); |
|
|
|
else if ( strcmp("alicereclaim",name) == 0 ) |
|
|
|
return(&swap->alicereclaim); |
|
|
|
else return(0); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t basilisk_txitem(struct supernet_info *myinfo,struct basilisk_swap *swap,cJSON *obj) |
|
|
|
{ |
|
|
|
char *hexstr,*name; struct basilisk_rawtx *rawtx = 0; |
|
|
|
if ( (name= jstr(obj,"name")) == 0 || (rawtx= basilisk_nameconv(myinfo,swap,name)) == 0 ) |
|
|
|
{ |
|
|
|
printf("basilisk_txitem illegal name.(%s)\n",name); |
|
|
|
return(-1); |
|
|
|
} |
|
|
|
if ( rawtx != 0 && (hexstr= jstr(obj,"info")) != 0 && strlen(hexstr) == sizeof(rawtx->I)*2 ) |
|
|
|
{ |
|
|
|
decode_hex((void *)&rawtx->I,sizeof(rawtx->I),hexstr); |
|
|
|
if ( (hexstr= jstr(obj,"txbytes")) != 0 && strlen(hexstr) == rawtx->I.datalen*2 ) |
|
|
|
{ |
|
|
|
if ( rawtx->txbytes == 0 ) |
|
|
|
{ |
|
|
|
printf("free (%s) txbytes\n",name); |
|
|
|
free(rawtx->txbytes); |
|
|
|
} |
|
|
|
rawtx->txbytes = calloc(1,rawtx->I.datalen); |
|
|
|
decode_hex((void *)rawtx->txbytes,rawtx->I.datalen,hexstr); |
|
|
|
} |
|
|
|
printf("PROCESS.(%s)\n",jprint(obj,0)); |
|
|
|
return(0); |
|
|
|
} |
|
|
|
return(-1); |
|
|
|
} |
|
|
|
|
|
|
|
cJSON *basilisk_swapobj(struct supernet_info *myinfo,struct basilisk_swap *swap) |
|
|
|
{ |
|
|
|
char hexstr[sizeof(swap->I)*2+1]; cJSON *obj = cJSON_CreateObject(); |
|
|
|
init_hexbytes_noT(hexstr,(void *)&swap->I,sizeof(swap->I)); |
|
|
|
jaddstr(obj,"name","swap"); |
|
|
|
jaddnum(obj,"requestid",swap->I.req.requestid); |
|
|
|
jaddnum(obj,"quoteid",swap->I.req.quoteid); |
|
|
|
jadd(obj,"req",basilisk_requestjson(&swap->I.req)); |
|
|
|
jaddstr(obj,"info",hexstr); |
|
|
|
return(obj); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t basilisk_swapconv(struct supernet_info *myinfo,struct basilisk_swap *swap,cJSON *obj) |
|
|
|
{ |
|
|
|
char *hexstr; |
|
|
|
if ( (hexstr= jstr(obj,"info")) != 0 && strlen(hexstr) == sizeof(swap->I)*2 ) |
|
|
|
{ |
|
|
|
decode_hex((void *)&swap->I,sizeof(swap->I),hexstr); |
|
|
|
if ( juint(obj,"requestid") == swap->I.req.requestid && juint(obj,"quoteid") == swap->I.req.quoteid ) |
|
|
|
return(0); |
|
|
|
printf("swapconv mismatched req/quote %d %d, %d %d\n",juint(obj,"requestid"),swap->I.req.requestid,juint(obj,"quoteid"),swap->I.req.quoteid); |
|
|
|
} else printf("no info field in swap obj\n"); |
|
|
|
return(-1); |
|
|
|
} |
|
|
|
|
|
|
|
struct basilisk_swap *basilisk_swapstore(struct supernet_info *myinfo,struct basilisk_swap *swap) |
|
|
|
{ |
|
|
|
// save based on requestid/quoteid
|
|
|
|
return(swap); |
|
|
|
} |
|
|
|
|
|
|
|
struct basilisk_swap *basilisk_swapload(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t requestid,uint32_t quoteid) |
|
|
|
{ |
|
|
|
return(swap); |
|
|
|
} |
|
|
|
|
|
|
|
void basilisk_swapstart(struct supernet_info *myinfo) // scan saved tmpswap, purge if complete, else Q
|
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
void basilisk_txlog(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx,int32_t delay) |
|
|
|
{ |
|
|
|
char fname[1024],*jsonstr; long filesize; cJSON *item,*dexobj = 0; int32_t i,n,pending; struct basilisk_swap tmpswap,*swapptr; |
|
|
|
sprintf(fname,"%s/DEX.log",GLOBAL_DBDIR), OS_compatible_path(fname); |
|
|
|
if ( myinfo->dexfp == 0 ) |
|
|
|
{ |
|
|
|
if ( (jsonstr= OS_filestr(&filesize,fname)) != 0 ) |
|
|
|
{ |
|
|
|
jsonstr[strlen(jsonstr)-1] = ']'; |
|
|
|
if ( jsonstr[strlen(jsonstr)-2] == ',' ) |
|
|
|
jsonstr[strlen(jsonstr)-2] = ' '; |
|
|
|
if ( jsonstr[strlen(jsonstr)-3] == ',' ) |
|
|
|
jsonstr[strlen(jsonstr)-3] = ' '; |
|
|
|
if ( (dexobj= cJSON_Parse(jsonstr)) != 0 ) |
|
|
|
{ |
|
|
|
if ( is_cJSON_Array(dexobj) != 0 && (n= cJSON_GetArraySize(dexobj)) > 0 ) |
|
|
|
{ |
|
|
|
pending = 0; |
|
|
|
memset(&tmpswap,0,sizeof(tmpswap)); |
|
|
|
swapptr = 0; |
|
|
|
for (i=0; i<n; i++) |
|
|
|
{ |
|
|
|
item = jitem(dexobj,i); |
|
|
|
if ( jstr(item,"name") != 0 && strcmp(jstr(item,"name"),"swap") == 0 ) |
|
|
|
{ |
|
|
|
if ( basilisk_swapconv(myinfo,&tmpswap,item) == 0 ) |
|
|
|
swapptr = basilisk_swapstore(myinfo,&tmpswap); |
|
|
|
} |
|
|
|
else if ( swapptr != 0 ) |
|
|
|
{ |
|
|
|
if ( swapptr->I.req.requestid == juint(item,"requestid") && swapptr->I.req.quoteid == juint(item,"quoteid") ) |
|
|
|
basilisk_txitem(myinfo,swapptr,item); |
|
|
|
} |
|
|
|
else if ( (swapptr= basilisk_swapload(myinfo,&tmpswap,juint(item,"requestid"),juint(item,"quoteid"))) != 0 ) |
|
|
|
basilisk_txitem(myinfo,swapptr,item); |
|
|
|
} |
|
|
|
basilisk_swapstart(myinfo); |
|
|
|
} |
|
|
|
free_json(dexobj); |
|
|
|
dexobj = 0; |
|
|
|
} else printf("basilisk_txlog error parsing.(%s)\n",jsonstr); |
|
|
|
free(jsonstr); |
|
|
|
} |
|
|
|
if ( (myinfo->dexfp= fopen(fname,"rb+")) != 0 ) |
|
|
|
fseek(myinfo->dexfp,0,SEEK_END); |
|
|
|
else if ( (myinfo->dexfp= fopen(fname,"wb")) != 0 ) |
|
|
|
fprintf(myinfo->dexfp,"[\n"); |
|
|
|
} |
|
|
|
if ( rawtx != 0 ) |
|
|
|
{ |
|
|
|
// delay -1 -> dont issue, else submit after block timestamp is delay after swap->started
|
|
|
|
dexobj = basilisk_rawtxobj(myinfo,swap,rawtx); |
|
|
|
} |
|
|
|
else if ( swap != 0 ) |
|
|
|
dexobj = basilisk_swapobj(myinfo,swap); |
|
|
|
if ( dexobj != 0 && (jsonstr= jprint(dexobj,1)) != 0 ) |
|
|
|
{ |
|
|
|
//printf("%s\n",jsonstr);
|
|
|
|
if ( myinfo->dexfp != 0 ) |
|
|
|
{ |
|
|
|
fprintf(myinfo->dexfp,"%s,\n",jsonstr); |
|
|
|
fflush(myinfo->dexfp); |
|
|
|
} |
|
|
|
free(jsonstr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
uint32_t basilisk_requestid(struct basilisk_request *rp) |
|
|
|
{ |
|
|
|
struct basilisk_request R; |
|
|
|
R = *rp; |
|
|
|
R.requestid = R.quoteid = R.quotetime = 0; |
|
|
|
R.destamount = 0; |
|
|
|
R.destamount = R.profitmargin = 0; |
|
|
|
//R.relaybits = 0;
|
|
|
|
memset(R.desthash.bytes,0,sizeof(R.desthash.bytes)); |
|
|
|
if ( 0 ) |
|
|
@ -38,7 +268,7 @@ uint32_t basilisk_quoteid(struct basilisk_request *rp) |
|
|
|
{ |
|
|
|
struct basilisk_request R; |
|
|
|
R = *rp; |
|
|
|
R.requestid = R.quoteid = 0; //R.relaybits =
|
|
|
|
R.requestid = R.quoteid = R.profitmargin = 0; //R.relaybits =
|
|
|
|
return(calc_crc32(0,(void *)&R,sizeof(R))); |
|
|
|
} |
|
|
|
|
|
|
@ -75,26 +305,12 @@ struct basilisk_request *basilisk_parsejson(struct basilisk_request *rp,cJSON *r |
|
|
|
return(rp); |
|
|
|
} |
|
|
|
|
|
|
|
void basilisk_swap_balancingtrade(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t iambob) |
|
|
|
{ |
|
|
|
// update balance, compare to target balance, issue balancing trade via central exchanges, if needed
|
|
|
|
if ( iambob != 0 ) |
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct basilisk_swap *basilisk_request_started(struct supernet_info *myinfo,uint32_t requestid) |
|
|
|
{ |
|
|
|
int32_t i; struct basilisk_swap *active = 0; |
|
|
|
portable_mutex_lock(&myinfo->DEX_swapmutex); |
|
|
|
for (i=0; i<myinfo->numswaps; i++) |
|
|
|
if ( myinfo->swaps[i]->req.requestid == requestid ) |
|
|
|
if ( myinfo->swaps[i]->I.req.requestid == requestid ) |
|
|
|
{ |
|
|
|
//printf("REQUEST STARTED.[%d] <- req.%u\n",i,requestid);
|
|
|
|
active = myinfo->swaps[i]; |
|
|
@ -160,12 +376,16 @@ double tradebot_liquidity_active(struct supernet_info *myinfo,double *refpricep, |
|
|
|
|
|
|
|
double basilisk_request_listprocess(struct supernet_info *myinfo,struct basilisk_request *issueR,struct basilisk_request *list,int32_t n) |
|
|
|
{ |
|
|
|
int32_t i,noquoteflag=0,havequoteflag=0,myrequest=0,maxi=-1; uint64_t balance=0,destamount,minamount = 0,maxamount = 0; uint32_t pendingid=0; struct basilisk_swap *active; double metric = 0.; |
|
|
|
int32_t i,noquoteflag=0,havequoteflag=0,myrequest=0,maxi=-1; int64_t balance=0,destamount,minamount = 0,maxamount = 0; uint32_t pendingid=0; struct basilisk_swap *active; double metric = 0.; |
|
|
|
memset(issueR,0,sizeof(*issueR)); |
|
|
|
minamount = list[0].minamount; |
|
|
|
//printf("need to verify null quoteid is list[0] requestid.%u quoteid.%u\n",list[0].requestid,list[0].quoteid);
|
|
|
|
if ( (active= basilisk_request_started(myinfo,list[0].requestid)) != 0 ) |
|
|
|
pendingid = active->req.quoteid; |
|
|
|
{ |
|
|
|
if ( active->I.req.quoteid != 0 ) |
|
|
|
return(0.); |
|
|
|
pendingid = active->I.req.quoteid; |
|
|
|
} |
|
|
|
if ( bits256_cmp(myinfo->myaddr.persistent,list[0].srchash) == 0 ) // my request
|
|
|
|
myrequest = 1; |
|
|
|
for (i=0; i<n; i++) |
|
|
@ -198,7 +418,9 @@ double basilisk_request_listprocess(struct supernet_info *myinfo,struct basilisk |
|
|
|
aveprice = refprice; |
|
|
|
if ( fabs(aveprice) < SMALLVAL ) |
|
|
|
return(0); |
|
|
|
destamount = (1.0 - profitmargin) * aveprice * list[0].srcamount; |
|
|
|
printf("avebid %f bidvol %f, aveask %f askvol %f\n",retvals[0],retvals[1],retvals[2],retvals[3]); |
|
|
|
//retvals[0] = avebid, retvals[1] = bidvol, retvals[2] = aveask, retvals[3] = askvol;
|
|
|
|
destamount = (1.0 - profitmargin) * retvals[0] * list[0].srcamount; |
|
|
|
if ( (retstr= InstantDEX_available(myinfo,iguana_coinfind(list[0].dest),0,0,list[0].dest)) != 0 ) |
|
|
|
{ |
|
|
|
if ( (retjson= cJSON_Parse(retstr)) != 0 ) |
|
|
@ -210,13 +432,14 @@ double basilisk_request_listprocess(struct supernet_info *myinfo,struct basilisk |
|
|
|
} |
|
|
|
// BTC balance 0.00500000 destamount 0.00041951 aveprice 0.00421619 minamount 0.00020000
|
|
|
|
printf("%s balance %.8f destamount %.8f aveprice %.8f minamount %.8f\n",list[0].dest,dstr(balance),dstr(destamount),aveprice,dstr(minamount)); |
|
|
|
if ( balance > destamount && destamount > 0 && destamount >= maxamount && destamount >= minamount ) |
|
|
|
if ( balance > destamount && (int64_t)destamount > 0 && destamount >= maxamount && destamount >= minamount ) |
|
|
|
{ |
|
|
|
metric = 1.; |
|
|
|
*issueR = list[0]; |
|
|
|
issueR->desthash = myinfo->myaddr.persistent; |
|
|
|
issueR->destamount = destamount; |
|
|
|
issueR->quotetime = (uint32_t)time(NULL); |
|
|
|
issueR->profitmargin = (uint32_t)(profitmargin * 1000000); |
|
|
|
printf("issueR set!\n"); |
|
|
|
} |
|
|
|
} |
|
|
|