From 5ba40582c8a69dbdff4b091785add307f25ab173 Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 5 Jun 2017 10:53:17 +0300 Subject: [PATCH] Test --- iguana/exchanges/LP_coins.c | 24 +- iguana/exchanges/LP_commands.c | 323 +-------------------------- iguana/exchanges/LP_include.h | 3 +- iguana/exchanges/LP_nativeDEX.c | 3 +- iguana/exchanges/LP_prices.c | 27 +-- iguana/exchanges/LP_quotes.c | 344 +++++++++++++++++++++++++++++ iguana/exchanges/LP_rpc.c | 2 +- iguana/exchanges/LP_statemachine.c | 9 +- iguana/exchanges/LP_transaction.c | 3 +- iguana/exchanges/LP_utxos.c | 25 +-- 10 files changed, 393 insertions(+), 370 deletions(-) create mode 100644 iguana/exchanges/LP_quotes.c diff --git a/iguana/exchanges/LP_coins.c b/iguana/exchanges/LP_coins.c index f397ee075..6f32b9372 100644 --- a/iguana/exchanges/LP_coins.c +++ b/iguana/exchanges/LP_coins.c @@ -141,9 +141,29 @@ uint16_t LP_rpcport(char *symbol) return(0); } +cJSON *LP_coinjson(struct iguana_info *coin) +{ + cJSON *item = cJSON_CreateObject(); + jaddstr(item,"coin",coin->symbol); + jaddstr(item,"smartaddress",coin->smartaddr); + jaddstr(item,"rpc",coin->serverport); + jaddnum(item,"pubtype",coin->pubtype); + jaddnum(item,"p2shtype",coin->p2shtype); + jaddnum(item,"wiftype",coin->wiftype); + return(item); +} + +static struct iguana_info *LP_coins; static int32_t LP_numcoins; +cJSON *LP_coinsjson() +{ + int32_t i; cJSON *array = cJSON_CreateArray(); + for (i=0; isrchash = srchash; - rp->srcamount = srcsatoshis; - rp->timestamp = timestamp; - rp->DEXselector = DEXselector; - safecopy(rp->src,src,sizeof(rp->src)); - safecopy(rp->dest,dest,sizeof(rp->dest)); - R = *rp; - rp->requestid = basilisk_requestid(rp); - rp->quotetime = quotetime; - rp->desthash = desthash; - rp->destamount = destsatoshis; - rp->quoteid = basilisk_quoteid(rp); - return(rp); -} - -cJSON *LP_quotejson(struct LP_quoteinfo *qp) -{ - double price; cJSON *retjson = cJSON_CreateObject(); - jaddstr(retjson,"base",qp->srccoin); - jaddstr(retjson,"rel",qp->destcoin); - if ( qp->coinaddr[0] != 0 ) - jaddstr(retjson,"address",qp->coinaddr); - if ( qp->timestamp != 0 ) - jaddnum(retjson,"timestamp",qp->timestamp); - if ( bits256_nonz(qp->txid) != 0 ) - { - jaddbits256(retjson,"txid",qp->txid); - jaddnum(retjson,"vout",qp->vout); - } - if ( bits256_nonz(qp->srchash) != 0 ) - jaddbits256(retjson,"srchash",qp->srchash); - if ( qp->txfee != 0 ) - jadd64bits(retjson,"txfee",qp->txfee); - if ( qp->quotetime != 0 ) - jaddnum(retjson,"quotetime",qp->quotetime); - if ( qp->satoshis != 0 ) - { - jadd64bits(retjson,"satoshis",qp->satoshis); - price = (double)(qp->destsatoshis+qp->desttxfee) / qp->satoshis; - jaddnum(retjson,"price",price); - } - if ( bits256_nonz(qp->desthash) != 0 ) - jaddbits256(retjson,"desthash",qp->desthash); - if ( bits256_nonz(qp->txid2) != 0 ) - { - jaddbits256(retjson,"txid2",qp->txid2); - jaddnum(retjson,"vout2",qp->vout2); - if ( qp->satoshis2 != 0 ) - jadd64bits(retjson,"satoshis2",qp->satoshis2); - } - if ( bits256_nonz(qp->desttxid) != 0 ) - { - if ( qp->destaddr[0] != 0 ) - jaddstr(retjson,"destaddr",qp->destaddr); - jaddbits256(retjson,"desttxid",qp->desttxid); - jaddnum(retjson,"destvout",qp->destvout); - } - if ( bits256_nonz(qp->feetxid) != 0 ) - { - jaddbits256(retjson,"feetxid",qp->feetxid); - jaddnum(retjson,"feevout",qp->feevout); - } - if ( qp->destsatoshis != 0 ) - jadd64bits(retjson,"destsatoshis",qp->destsatoshis); - if ( qp->desttxfee != 0 ) - jadd64bits(retjson,"desttxfee",qp->desttxfee); - if ( qp->change != 0 ) - jaddnum(retjson,"change",dstr(qp->change)); - return(retjson); -} - -int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson) -{ - safecopy(qp->srccoin,jstr(argjson,"base"),sizeof(qp->srccoin)); - safecopy(qp->coinaddr,jstr(argjson,"address"),sizeof(qp->coinaddr)); - safecopy(qp->destcoin,jstr(argjson,"rel"),sizeof(qp->destcoin)); - safecopy(qp->destaddr,jstr(argjson,"destaddr"),sizeof(qp->destaddr)); - qp->timestamp = juint(argjson,"timestamp"); - qp->quotetime = juint(argjson,"quotetime"); - qp->txid = jbits256(argjson,"txid"); - qp->txid2 = jbits256(argjson,"txid2"); - qp->vout = jint(argjson,"vout"); - qp->vout2 = jint(argjson,"vout2"); - qp->feevout = jint(argjson,"feevout"); - qp->srchash = jbits256(argjson,"srchash"); - qp->desttxid = jbits256(argjson,"desttxid"); - qp->feetxid = jbits256(argjson,"feetxid"); - qp->destvout = jint(argjson,"destvout"); - qp->desthash = jbits256(argjson,"desthash"); - if ( (qp->satoshis= j64bits(argjson,"satoshis")) == 0 ) - qp->satoshis = SATOSHIDEN * jdouble(argjson,"value"); - if ( (qp->destsatoshis= j64bits(argjson,"destsatoshis")) == 0 ) - qp->destsatoshis = qp->satoshis * jdouble(argjson,"price"); - qp->change = SATOSHIDEN * jdouble(argjson,"change"); - qp->txfee = j64bits(argjson,"txfee"); - qp->desttxfee = j64bits(argjson,"desttxfee"); - return(0); -} - -int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *destcoin,double price) -{ - memset(qp,0,sizeof(*qp)); - qp->timestamp = (uint32_t)time(NULL); - safecopy(qp->destcoin,destcoin,sizeof(qp->destcoin)); - if ( (qp->txfee= LP_getestimatedrate(utxo->coin)*LP_AVETXSIZE) < 10000 ) - qp->txfee = 10000; - if ( qp->txfee >= utxo->satoshis || qp->txfee >= utxo->satoshis2 ) - return(-1); - qp->txid = utxo->txid; - qp->vout = utxo->vout; - qp->txid2 = utxo->txid2; - qp->vout2 = utxo->vout2; - qp->satoshis2 = utxo->satoshis2 - qp->txfee; - qp->satoshis = utxo->satoshis - qp->txfee; - qp->destsatoshis = qp->satoshis * price; - if ( (qp->desttxfee= LP_getestimatedrate(qp->destcoin) * LP_AVETXSIZE) < 10000 ) - qp->desttxfee = 10000; - if ( qp->desttxfee >= qp->destsatoshis ) - return(-2); - qp->destsatoshis -= qp->desttxfee; - safecopy(qp->srccoin,utxo->coin,sizeof(qp->srccoin)); - safecopy(qp->coinaddr,utxo->coinaddr,sizeof(qp->coinaddr)); - qp->srchash = LP_pubkey(LP_privkey(utxo->coinaddr)); - return(0); -} - -int32_t LP_quoteinfoset(struct LP_quoteinfo *qp,uint32_t timestamp,uint32_t quotetime,uint64_t value,uint64_t txfee,uint64_t destsatoshis,uint64_t desttxfee,bits256 desttxid,int32_t destvout,bits256 desthash,char *destaddr) -{ - if ( txfee != qp->txfee ) - { - if ( txfee >= value ) - return(-1); - qp->txfee = txfee; - qp->satoshis = value - txfee; - } - qp->timestamp = timestamp; - qp->quotetime = quotetime; - qp->destsatoshis = destsatoshis; - qp->desttxfee = desttxfee; - qp->desttxid = desttxid; - qp->destvout = destvout; - qp->desthash = desthash; - safecopy(qp->destaddr,destaddr,sizeof(qp->destaddr)); - return(0); -} - -char *LP_quotereceived(cJSON *argjson) -{ - struct LP_cacheinfo *ptr; double price; struct LP_quoteinfo Q; - LP_quoteparse(&Q,argjson); - price = (double)(Q.destsatoshis + Q.desttxfee) / (Q.satoshis + Q.txfee); - if ( (ptr= LP_cacheadd(Q.srccoin,Q.destcoin,Q.txid,Q.vout,price,&Q)) != 0 ) - { - ptr->Q = Q; - return(clonestr("{\"result\":\"updated\"}")); - } else return(clonestr("{\"error\":\"nullptr\"}")); -} - double LP_query(char *method,struct LP_quoteinfo *qp,char *ipaddr,uint16_t port,char *base,char *rel,bits256 mypub) { cJSON *reqjson; struct LP_peerinfo *peer; int32_t i,flag = 0,pushsock = -1; double price = 0.; @@ -219,164 +57,6 @@ double LP_query(char *method,struct LP_quoteinfo *qp,char *ipaddr,uint16_t port, return(price); } -int32_t LP_sizematch(uint64_t mysatoshis,uint64_t othersatoshis) -{ - if ( mysatoshis >= othersatoshis ) - return(0); - else return(-1); -} - -cJSON *LP_tradecandidates(struct LP_utxoinfo *myutxo,char *base) -{ - struct LP_peerinfo *peer,*tmp; struct LP_quoteinfo Q; char *utxostr,coinstr[16]; cJSON *array,*retarray=0,*item; int32_t i,n; double price; - if ( (price= LP_price(base,myutxo->coin)) == .0 ) - { - printf("no LP_price (%s -> %s)\n",base,myutxo->coin); - return(0); - } - HASH_ITER(hh,LP_peerinfos,peer,tmp) - { - if ( (utxostr= issue_LP_clientgetutxos(peer->ipaddr,peer->port,base,100)) != 0 ) - { - //printf("%s:%u %s\n",peer->ipaddr,peer->port,utxostr); - if ( (array= cJSON_Parse(utxostr)) != 0 ) - { - if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) - { - retarray = cJSON_CreateArray(); - for (i=0; icoin) / 0.975; - if ( (array= LP_tradecandidates(myutxo,base)) != 0 ) - { - //printf("candidates.(%s)\n",jprint(array,0)); - if ( (n= cJSON_GetArraySize(array)) > 0 ) - { - memset(prices,0,sizeof(prices)); - memset(Q,0,sizeof(Q)); - for (i=0; icoin,zero); - Q[i].destsatoshis = price * Q[i].satoshis; - } - if ( (prices[i]= price) != 0. && (bestprice == 0. || price < bestprice) ) - bestprice = price; - //char str[65]; printf("i.%d of %d: (%s) -> txid.%s price %.8f best %.8f dest %.8f\n",i,n,jprint(item,0),bits256_str(str,Q[i].txid),price,bestprice,dstr(Q[i].destsatoshis)); - } - if ( bestprice != 0. ) - { - bestmetric = 0.; - besti = -1; - for (i=0; isatoshis > Q[i].destsatoshis ) - { - metric = price / bestprice; - printf("%f %f %f %f ",price,metric,dstr(Q[i].destsatoshis),metric * metric * metric); - if ( metric < 1.1 ) - { - metric = dstr(Q[i].destsatoshis) * metric * metric * metric; - printf("%f\n",metric); - if ( bestmetric == 0. || metric < bestmetric ) - { - besti = i; - bestmetric = metric; - } - } - } else printf("(%f %f) ",dstr(myutxo->satoshis),dstr(Q[i].destsatoshis)); - } - printf("metrics, best %f\n",bestmetric); - if ( besti >= 0 )//&& bits256_cmp(myutxo->mypub,otherpubs[besti]) == 0 ) - { - i = besti; - bestprice = prices[i]; - item = jitem(array,i); - bestitem = LP_quotejson(&Q[i]); - printf("bestprice %f vs maxprice %f\n",bestprice,maxprice); - if ( maxprice == 0. || bestprice <= maxprice ) - { - Q[i].desttxid = myutxo->txid; - Q[i].destvout = myutxo->vout; - Q[i].feetxid = myutxo->txid2; - Q[i].feevout = myutxo->vout2; - strcpy(Q[i].destaddr,myutxo->coinaddr); - price = LP_query("request",&Q[i],jstr(item,"ipaddr"),jint(item,"port"),base,myutxo->coin,myutxo->mypub); - if ( jobj(bestitem,"price") != 0 ) - jdelete(bestitem,"price"); - jaddnum(bestitem,"price",prices[i]); - if ( price <= maxprice ) - { - Q[i].desttxid = myutxo->txid; - Q[i].destvout = myutxo->vout; - Q[i].feetxid = myutxo->txid2; - Q[i].feevout = myutxo->vout2; - strcpy(Q[i].destaddr,myutxo->coinaddr); - price = LP_query("connect",&Q[i],jstr(item,"ipaddr"),jint(item,"port"),base,myutxo->coin,myutxo->mypub); - LP_requestinit(&R,Q[i].srchash,Q[i].desthash,base,Q[i].satoshis,Q[i].destcoin,Q[i].destsatoshis,Q[i].timestamp,Q[i].quotetime,DEXselector); - jaddstr(bestitem,"status","connected"); - jaddnum(bestitem,"requestid",R.requestid); - jaddnum(bestitem,"quoteid",R.quoteid); - printf("Alice r.%u q.%u\n",R.requestid,R.quoteid); - } else jaddstr(bestitem,"status","too expensive"); - } - } - } - free_json(array); - } - } - if ( bestitem == 0 ) - return(cJSON_Parse("{\"error\":\"no match found\"}")); - return(bestitem); -} - -int32_t LP_priceping(int32_t pubsock,struct LP_utxoinfo *utxo,char *rel,double profitmargin) -{ - double price; uint32_t now; cJSON *retjson; struct LP_quoteinfo Q; char *retstr; - if ( (now= (uint32_t)time(NULL)) > utxo->swappending ) - utxo->swappending = 0; - if ( now > utxo->published+60 && utxo->swappending == 0 && utxo->pair < 0 && utxo->swap == 0 && (price= LP_price(utxo->coin,rel)) != 0. ) - { - //price *= (1. + profitmargin); - if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) - return(-1); - Q.timestamp = (uint32_t)time(NULL); - retjson = LP_quotejson(&Q); - jaddstr(retjson,"method","quote"); - retstr = jprint(retjson,1); - LP_send(pubsock,retstr,1); - utxo->published = now; - return(0); - } - return(-1); -} - int32_t LP_command(struct LP_peerinfo *mypeer,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen,double profitmargin) { char *method,*base,*rel,*retstr,pairstr[512]; cJSON *retjson; double price; bits256 privkey,txid; struct LP_utxoinfo *utxo; int32_t retval = -1,DEXselector = 0; uint64_t destvalue; struct basilisk_request R; struct LP_quoteinfo Q; @@ -523,8 +203,7 @@ char *stats_JSON(cJSON *argjson,char *remoteaddr,uint16_t port) // from rpc port USERPASS_COUNTER = 1; retjson = cJSON_CreateObject(); jaddstr(retjson,"userpass",USERPASS); - jaddstr(retjson,"BTC",BTCADDR); - jaddstr(retjson,"KMD",KMDADDR); + jadd(retjson,"coins",LP_coinsjson()); return(jprint(retjson,1)); } if ( (userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,USERPASS) != 0 ) diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index f7b123941..1ffa32cb7 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -139,7 +139,7 @@ struct iguana_info uint64_t txfee; double estimatedrate; int32_t longestchain; uint8_t pubtype,p2shtype,isPoS,wiftype; - char symbol[16],changeaddr[64],userpass[1024],serverport[128]; + char symbol[16],smartaddr[64],userpass[1024],serverport[128]; }; struct basilisk_swap @@ -200,5 +200,6 @@ uint32_t basilisk_quoteid(struct basilisk_request *rp); struct basilisk_swap *LP_swapinit(int32_t iambob,int32_t optionduration,bits256 privkey,struct basilisk_request *rp,struct LP_quoteinfo *qp); char *bitcoind_passthru(char *coinstr,char *serverport,char *userpass,char *method,char *params); uint32_t LP_swapdata_rawtxsend(int32_t pairsock,struct basilisk_swap *swap,uint32_t msgbits,uint8_t *data,int32_t maxlen,struct basilisk_rawtx *rawtx,uint32_t nextbits,int32_t suppress_swapsend); +double LP_query(char *method,struct LP_quoteinfo *qp,char *ipaddr,uint16_t port,char *base,char *rel,bits256 mypub); #endif diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index 6cb4673fb..ab7251b68 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -28,7 +28,7 @@ struct LP_peerinfo *LP_peerinfos,*LP_mypeer; char *activecoins[] = { "BTC", "KMD", "REVS", "JUMBLR" };//"LTC", "USD", }; char GLOBAL_DBDIR[] = { "DB" }; -char USERPASS[65],USERPASS_WIFSTR[64],BTCADDR[64],KMDADDR[64],USERHOME[512] = { "/root" }; +char USERPASS[65],USERPASS_WIFSTR[64],USERHOME[512] = { "/root" }; char *default_LPnodes[] = { "5.9.253.196", "5.9.253.197", "5.9.253.198", "5.9.253.199", "5.9.253.200", "5.9.253.201", "5.9.253.202", "5.9.253.203", "5.9.253.204" }; //"5.9.253.195", @@ -74,6 +74,7 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_ #include "LP_swap.c" #include "LP_peers.c" #include "LP_utxos.c" +#include "LP_quotes.c" #include "LP_commands.c" void LP_mainloop(struct LP_peerinfo *mypeer,uint16_t mypubport,int32_t pubsock,int32_t pullsock,uint16_t myport,int32_t amclient,char *passphrase,double profitmargin) diff --git a/iguana/exchanges/LP_prices.c b/iguana/exchanges/LP_prices.c index 319c91ed8..999ed3c2b 100644 --- a/iguana/exchanges/LP_prices.c +++ b/iguana/exchanges/LP_prices.c @@ -130,13 +130,20 @@ void LP_priceinfoupdate(char *base,char *rel,double price) double LP_myprice(double *bidp,double *askp,char *base,char *rel) { - struct LP_priceinfo *basepp,*relpp; + struct LP_priceinfo *basepp,*relpp; double val; + *bidp = *askp = 0.; if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 ) { - *askp = basepp->myprices[relpp->ind]; - *bidp = relpp->myprices[basepp->ind]; - return((*askp + *bidp) * 0.5); - } else return(0.); + if ( (*askp= basepp->myprices[relpp->ind]) != 0. ) + { + if ( (val= relpp->myprices[basepp->ind]) != 0. ) + { + *bidp = 1. / val; + return((*askp + *bidp) * 0.5); + } + } + } + return(0.); } int32_t LP_mypriceset(char *base,char *rel,double price) @@ -217,16 +224,6 @@ struct LP_priceinfo *LP_priceinfoadd(char *symbol) safecopy(pp->symbol,symbol,sizeof(pp->symbol)); pp->coinbits = stringbits(symbol); pp->ind = LP_numpriceinfos++; - /*pp->relvals = calloc(LP_numpriceinfos+1,sizeof(*pp->relvals)); - //pp->myprices = calloc(LP_numpriceinfos+1,sizeof(*pp->myprices)); - vecsize = sizeof(*LP_priceinfos[i].relvals) * (LP_numpriceinfos + 1); - for (i=0; isrchash = srchash; + rp->srcamount = srcsatoshis; + rp->timestamp = timestamp; + rp->DEXselector = DEXselector; + safecopy(rp->src,src,sizeof(rp->src)); + safecopy(rp->dest,dest,sizeof(rp->dest)); + R = *rp; + rp->requestid = basilisk_requestid(rp); + rp->quotetime = quotetime; + rp->desthash = desthash; + rp->destamount = destsatoshis; + rp->quoteid = basilisk_quoteid(rp); + return(rp); +} + +cJSON *LP_quotejson(struct LP_quoteinfo *qp) +{ + double price; cJSON *retjson = cJSON_CreateObject(); + jaddstr(retjson,"base",qp->srccoin); + jaddstr(retjson,"rel",qp->destcoin); + if ( qp->coinaddr[0] != 0 ) + jaddstr(retjson,"address",qp->coinaddr); + if ( qp->timestamp != 0 ) + jaddnum(retjson,"timestamp",qp->timestamp); + if ( bits256_nonz(qp->txid) != 0 ) + { + jaddbits256(retjson,"txid",qp->txid); + jaddnum(retjson,"vout",qp->vout); + } + if ( bits256_nonz(qp->srchash) != 0 ) + jaddbits256(retjson,"srchash",qp->srchash); + if ( qp->txfee != 0 ) + jadd64bits(retjson,"txfee",qp->txfee); + if ( qp->quotetime != 0 ) + jaddnum(retjson,"quotetime",qp->quotetime); + if ( qp->satoshis != 0 ) + { + jadd64bits(retjson,"satoshis",qp->satoshis); + price = (double)(qp->destsatoshis+qp->desttxfee) / qp->satoshis; + jaddnum(retjson,"price",price); + } + if ( bits256_nonz(qp->desthash) != 0 ) + jaddbits256(retjson,"desthash",qp->desthash); + if ( bits256_nonz(qp->txid2) != 0 ) + { + jaddbits256(retjson,"txid2",qp->txid2); + jaddnum(retjson,"vout2",qp->vout2); + if ( qp->satoshis2 != 0 ) + jadd64bits(retjson,"satoshis2",qp->satoshis2); + } + if ( bits256_nonz(qp->desttxid) != 0 ) + { + if ( qp->destaddr[0] != 0 ) + jaddstr(retjson,"destaddr",qp->destaddr); + jaddbits256(retjson,"desttxid",qp->desttxid); + jaddnum(retjson,"destvout",qp->destvout); + } + if ( bits256_nonz(qp->feetxid) != 0 ) + { + jaddbits256(retjson,"feetxid",qp->feetxid); + jaddnum(retjson,"feevout",qp->feevout); + } + if ( qp->destsatoshis != 0 ) + jadd64bits(retjson,"destsatoshis",qp->destsatoshis); + if ( qp->desttxfee != 0 ) + jadd64bits(retjson,"desttxfee",qp->desttxfee); + if ( qp->change != 0 ) + jaddnum(retjson,"change",dstr(qp->change)); + return(retjson); +} + +int32_t LP_quoteparse(struct LP_quoteinfo *qp,cJSON *argjson) +{ + safecopy(qp->srccoin,jstr(argjson,"base"),sizeof(qp->srccoin)); + safecopy(qp->coinaddr,jstr(argjson,"address"),sizeof(qp->coinaddr)); + safecopy(qp->destcoin,jstr(argjson,"rel"),sizeof(qp->destcoin)); + safecopy(qp->destaddr,jstr(argjson,"destaddr"),sizeof(qp->destaddr)); + qp->timestamp = juint(argjson,"timestamp"); + qp->quotetime = juint(argjson,"quotetime"); + qp->txid = jbits256(argjson,"txid"); + qp->txid2 = jbits256(argjson,"txid2"); + qp->vout = jint(argjson,"vout"); + qp->vout2 = jint(argjson,"vout2"); + qp->feevout = jint(argjson,"feevout"); + qp->srchash = jbits256(argjson,"srchash"); + qp->desttxid = jbits256(argjson,"desttxid"); + qp->feetxid = jbits256(argjson,"feetxid"); + qp->destvout = jint(argjson,"destvout"); + qp->desthash = jbits256(argjson,"desthash"); + if ( (qp->satoshis= j64bits(argjson,"satoshis")) == 0 ) + qp->satoshis = SATOSHIDEN * jdouble(argjson,"value"); + if ( (qp->destsatoshis= j64bits(argjson,"destsatoshis")) == 0 ) + qp->destsatoshis = qp->satoshis * jdouble(argjson,"price"); + qp->change = SATOSHIDEN * jdouble(argjson,"change"); + qp->txfee = j64bits(argjson,"txfee"); + qp->desttxfee = j64bits(argjson,"desttxfee"); + return(0); +} + +int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *destcoin,double price) +{ + memset(qp,0,sizeof(*qp)); + qp->timestamp = (uint32_t)time(NULL); + safecopy(qp->destcoin,destcoin,sizeof(qp->destcoin)); + if ( (qp->txfee= LP_getestimatedrate(utxo->coin)*LP_AVETXSIZE) < 10000 ) + qp->txfee = 10000; + if ( qp->txfee >= utxo->satoshis || qp->txfee >= utxo->satoshis2 ) + return(-1); + qp->txid = utxo->txid; + qp->vout = utxo->vout; + qp->txid2 = utxo->txid2; + qp->vout2 = utxo->vout2; + qp->satoshis2 = utxo->satoshis2 - qp->txfee; + qp->satoshis = utxo->satoshis - qp->txfee; + qp->destsatoshis = qp->satoshis * price; + if ( (qp->desttxfee= LP_getestimatedrate(qp->destcoin) * LP_AVETXSIZE) < 10000 ) + qp->desttxfee = 10000; + if ( qp->desttxfee >= qp->destsatoshis ) + return(-2); + qp->destsatoshis -= qp->desttxfee; + safecopy(qp->srccoin,utxo->coin,sizeof(qp->srccoin)); + safecopy(qp->coinaddr,utxo->coinaddr,sizeof(qp->coinaddr)); + qp->srchash = LP_pubkey(LP_privkey(utxo->coinaddr)); + return(0); +} + +int32_t LP_quoteinfoset(struct LP_quoteinfo *qp,uint32_t timestamp,uint32_t quotetime,uint64_t value,uint64_t txfee,uint64_t destsatoshis,uint64_t desttxfee,bits256 desttxid,int32_t destvout,bits256 desthash,char *destaddr) +{ + if ( txfee != qp->txfee ) + { + if ( txfee >= value ) + return(-1); + qp->txfee = txfee; + qp->satoshis = value - txfee; + } + qp->timestamp = timestamp; + qp->quotetime = quotetime; + qp->destsatoshis = destsatoshis; + qp->desttxfee = desttxfee; + qp->desttxid = desttxid; + qp->destvout = destvout; + qp->desthash = desthash; + safecopy(qp->destaddr,destaddr,sizeof(qp->destaddr)); + return(0); +} + +char *LP_quotereceived(cJSON *argjson) +{ + struct LP_cacheinfo *ptr; double price; struct LP_quoteinfo Q; + LP_quoteparse(&Q,argjson); + price = (double)(Q.destsatoshis + Q.desttxfee) / (Q.satoshis + Q.txfee); + if ( (ptr= LP_cacheadd(Q.srccoin,Q.destcoin,Q.txid,Q.vout,price,&Q)) != 0 ) + { + ptr->Q = Q; + return(clonestr("{\"result\":\"updated\"}")); + } else return(clonestr("{\"error\":\"nullptr\"}")); +} + + +int32_t LP_sizematch(uint64_t mysatoshis,uint64_t othersatoshis) +{ + if ( mysatoshis >= othersatoshis ) + return(0); + else return(-1); +} + +cJSON *LP_tradecandidates(struct LP_utxoinfo *myutxo,char *base) +{ + struct LP_peerinfo *peer,*tmp; struct LP_quoteinfo Q; char *utxostr,coinstr[16]; cJSON *array,*retarray=0,*item; int32_t i,n; double price; + if ( (price= LP_price(base,myutxo->coin)) == .0 ) + { + printf("no LP_price (%s -> %s)\n",base,myutxo->coin); + return(0); + } + HASH_ITER(hh,LP_peerinfos,peer,tmp) + { + if ( (utxostr= issue_LP_clientgetutxos(peer->ipaddr,peer->port,base,100)) != 0 ) + { + //printf("%s:%u %s\n",peer->ipaddr,peer->port,utxostr); + if ( (array= cJSON_Parse(utxostr)) != 0 ) + { + if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + { + retarray = cJSON_CreateArray(); + for (i=0; icoin) / 0.975; + if ( (array= LP_tradecandidates(myutxo,base)) != 0 ) + { + //printf("candidates.(%s)\n",jprint(array,0)); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + memset(prices,0,sizeof(prices)); + memset(Q,0,sizeof(Q)); + for (i=0; icoin,zero); + Q[i].destsatoshis = price * Q[i].satoshis; + } + if ( (prices[i]= price) != 0. && (bestprice == 0. || price < bestprice) ) + bestprice = price; + //char str[65]; printf("i.%d of %d: (%s) -> txid.%s price %.8f best %.8f dest %.8f\n",i,n,jprint(item,0),bits256_str(str,Q[i].txid),price,bestprice,dstr(Q[i].destsatoshis)); + } + if ( bestprice != 0. ) + { + bestmetric = 0.; + besti = -1; + for (i=0; isatoshis > Q[i].destsatoshis ) + { + metric = price / bestprice; + printf("%f %f %f %f ",price,metric,dstr(Q[i].destsatoshis),metric * metric * metric); + if ( metric < 1.1 ) + { + metric = dstr(Q[i].destsatoshis) * metric * metric * metric; + printf("%f\n",metric); + if ( bestmetric == 0. || metric < bestmetric ) + { + besti = i; + bestmetric = metric; + } + } + } else printf("(%f %f) ",dstr(myutxo->satoshis),dstr(Q[i].destsatoshis)); + } + printf("metrics, best %f\n",bestmetric); + if ( besti >= 0 )//&& bits256_cmp(myutxo->mypub,otherpubs[besti]) == 0 ) + { + i = besti; + bestprice = prices[i]; + item = jitem(array,i); + bestitem = LP_quotejson(&Q[i]); + printf("bestprice %f vs maxprice %f\n",bestprice,maxprice); + if ( maxprice == 0. || bestprice <= maxprice ) + { + Q[i].desttxid = myutxo->txid; + Q[i].destvout = myutxo->vout; + Q[i].feetxid = myutxo->txid2; + Q[i].feevout = myutxo->vout2; + strcpy(Q[i].destaddr,myutxo->coinaddr); + price = LP_query("request",&Q[i],jstr(item,"ipaddr"),jint(item,"port"),base,myutxo->coin,myutxo->mypub); + if ( jobj(bestitem,"price") != 0 ) + jdelete(bestitem,"price"); + jaddnum(bestitem,"price",prices[i]); + if ( price <= maxprice ) + { + Q[i].desttxid = myutxo->txid; + Q[i].destvout = myutxo->vout; + Q[i].feetxid = myutxo->txid2; + Q[i].feevout = myutxo->vout2; + strcpy(Q[i].destaddr,myutxo->coinaddr); + price = LP_query("connect",&Q[i],jstr(item,"ipaddr"),jint(item,"port"),base,myutxo->coin,myutxo->mypub); + LP_requestinit(&R,Q[i].srchash,Q[i].desthash,base,Q[i].satoshis,Q[i].destcoin,Q[i].destsatoshis,Q[i].timestamp,Q[i].quotetime,DEXselector); + jaddstr(bestitem,"status","connected"); + jaddnum(bestitem,"requestid",R.requestid); + jaddnum(bestitem,"quoteid",R.quoteid); + printf("Alice r.%u q.%u\n",R.requestid,R.quoteid); + } else jaddstr(bestitem,"status","too expensive"); + } + } + } + free_json(array); + } + } + if ( bestitem == 0 ) + return(cJSON_Parse("{\"error\":\"no match found\"}")); + return(bestitem); +} + +int32_t LP_priceping(int32_t pubsock,struct LP_utxoinfo *utxo,char *rel,double profitmargin) +{ + double price; uint32_t now; cJSON *retjson; struct LP_quoteinfo Q; char *retstr; + if ( (now= (uint32_t)time(NULL)) > utxo->swappending ) + utxo->swappending = 0; + if ( now > utxo->published+60 && utxo->swappending == 0 && utxo->pair < 0 && utxo->swap == 0 && (price= LP_price(utxo->coin,rel)) != 0. ) + { + if ( LP_quoteinfoinit(&Q,utxo,rel,price) < 0 ) + return(-1); + Q.timestamp = (uint32_t)time(NULL); + retjson = LP_quotejson(&Q); + jaddstr(retjson,"method","quote"); + retstr = jprint(retjson,1); + LP_send(pubsock,retstr,1); + utxo->published = now; + return(0); + } + return(-1); +} + + + + diff --git a/iguana/exchanges/LP_rpc.c b/iguana/exchanges/LP_rpc.c index 96096072d..df6cfd6f2 100644 --- a/iguana/exchanges/LP_rpc.c +++ b/iguana/exchanges/LP_rpc.c @@ -168,7 +168,7 @@ double LP_getestimatedrate(char *symbol) { if ( retstr[0] != '-' ) { - rate = atof(retstr) / 1024.; + coin->estimatedrate = rate = atof(retstr) / 1024.; printf("estimated rate.(%s) %s -> %.8f\n",symbol,retstr,rate); } free(retstr); diff --git a/iguana/exchanges/LP_statemachine.c b/iguana/exchanges/LP_statemachine.c index dc0240c1b..ed4fe4fc8 100644 --- a/iguana/exchanges/LP_statemachine.c +++ b/iguana/exchanges/LP_statemachine.c @@ -404,18 +404,12 @@ cJSON *LP_createvins(struct basilisk_rawtx *dest,struct vin_info *V,struct basil int32_t _basilisk_rawtx_gen(char *str,uint32_t swapstarted,uint8_t *pubkey33,int32_t iambob,int32_t lockinputs,struct basilisk_rawtx *rawtx,uint32_t locktime,uint8_t *script,int32_t scriptlen,int64_t txfee,int32_t minconf,int32_t delay,bits256 privkey) { char scriptstr[1024],wifstr[256],coinaddr[64],*signedtx,*rawtxbytes; uint32_t basilisktag; int32_t retval = -1; cJSON *vins,*privkeys,*addresses,*valsobj; struct vin_info *V; - //bitcoin_address(coinaddr,rawtx->coin->chain->pubtype,myinfo->persistent_pubkey33,33); - if ( rawtx->coin->changeaddr[0] == 0 ) - { - bitcoin_address(rawtx->coin->changeaddr,rawtx->coin->pubtype,pubkey33,33); - printf("set change address.(%s)\n",rawtx->coin->changeaddr); - } init_hexbytes_noT(scriptstr,script,scriptlen); basilisktag = (uint32_t)rand(); valsobj = cJSON_CreateObject(); jaddstr(valsobj,"coin",rawtx->coin->symbol); jaddstr(valsobj,"spendscript",scriptstr); - jaddstr(valsobj,"changeaddr",rawtx->coin->changeaddr); + jaddstr(valsobj,"changeaddr",rawtx->coin->smartaddr); jadd64bits(valsobj,"satoshis",rawtx->I.amount); if ( strcmp(rawtx->coin->symbol,"BTC") == 0 && txfee > 0 && txfee < 50000 ) txfee = 50000; @@ -990,7 +984,6 @@ cJSON *basilisk_privkeyarray(struct iguana_info *coin,cJSON *vins) { cJSON *privkeyarray,*item,*sobj; struct iguana_waddress *waddr; struct iguana_waccount *wacct; char coinaddr[64],account[128],wifstr[64],str[65],typestr[64],*hexstr; uint8_t script[1024]; int32_t i,n,len,vout; bits256 txid,privkey; double bidasks[2]; privkeyarray = cJSON_CreateArray(); - //printf("%s persistent.(%s) (%s) change.(%s) scriptstr.(%s)\n",coin->symbol,myinfo->myaddr.BTC,coinaddr,coin->changeaddr,scriptstr); if ( (n= cJSON_GetArraySize(vins)) > 0 ) { for (i=0; inumutxos = n; - if ( destpeer->numutxos < n ) - { - //destpeer->numutxos = n; - //printf("got.(%s) from %s numutxos.%d\n",retstr,destpeer->ipaddr,destpeer->numutxos); - } } } free_json(array); @@ -273,7 +268,7 @@ int32_t LP_nearestvalue(uint64_t *values,int32_t n,uint64_t targetval) uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *symbol,char *passphrase,char *wifstr,int32_t amclient) { static uint32_t counter; - char coinaddr[64],*script; struct LP_utxoinfo *utxo; cJSON *array,*item,*retjson; bits256 userpass,userpub,txid,deposittxid; int32_t used,i,n,vout,depositvout; uint64_t *values,satoshis,depositval,targetval,value,total = 0; bits256 privkey,pubkey; uint8_t pubkey33[33],tmptype,rmd160[20]; struct iguana_info *coin = LP_coinfind(symbol); + char *script; struct LP_utxoinfo *utxo; cJSON *array,*item,*retjson; bits256 userpass,userpub,txid,deposittxid; int32_t used,i,n,vout,depositvout; uint64_t *values,satoshis,depositval,targetval,value,total = 0; bits256 privkey,pubkey; uint8_t pubkey33[33],tmptype,rmd160[20]; struct iguana_info *coin = LP_coinfind(symbol); if ( coin == 0 ) { printf("cant add privkey for %s, coin not active\n",symbol); @@ -282,11 +277,7 @@ uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *symb if ( passphrase != 0 ) conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); else privkey = iguana_wif2privkey(wifstr); - iguana_priv2pub(pubkey33,coinaddr,privkey,coin->pubtype); - if ( strcmp("BTC",symbol) == 0 ) - strcpy(BTCADDR,coinaddr); - else if ( strcmp("KMD",symbol) == 0 ) - strcpy(KMDADDR,coinaddr); + iguana_priv2pub(pubkey33,coin->smartaddr,privkey,coin->pubtype); if ( counter == 0 ) { char tmpstr[128]; @@ -296,13 +287,13 @@ uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *symb conv_NXTpassword(userpass.bytes,pubkey.bytes,(uint8_t *)tmpstr,(int32_t)strlen(tmpstr)); userpub = curve25519(userpass,curve25519_basepoint9()); printf("userpass.(%s)\n",bits256_str(USERPASS,userpub)); - printf("%s (%s) %d wif.(%s) (%s)\n",symbol,coinaddr,coin->pubtype,tmpstr,passphrase); - if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coinaddr,-1)) != 0 ) + printf("%s (%s) %d wif.(%s) (%s)\n",symbol,coin->smartaddr,coin->pubtype,tmpstr,passphrase); + if ( (retjson= LP_importprivkey(coin->symbol,tmpstr,coin->smartaddr,-1)) != 0 ) printf("importprivkey -> (%s)\n",jprint(retjson,1)); } - bitcoin_addr2rmd160(&tmptype,rmd160,coinaddr); + bitcoin_addr2rmd160(&tmptype,rmd160,coin->smartaddr); LP_privkeyadd(privkey,rmd160); - if ( (array= LP_listunspent(symbol,coinaddr)) != 0 ) + if ( (array= LP_listunspent(symbol,coin->smartaddr)) != 0 ) { if ( is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) { @@ -341,12 +332,12 @@ uint64_t LP_privkey_init(struct LP_peerinfo *mypeer,int32_t mypubsock,char *symb values[i] = 0, used++; if ( amclient == 0 ) { - if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coinaddr,LP_peerinfos[0].ipaddr,LP_peerinfos[0].port,LP_peerinfos[0].profitmargin)) != 0 ) + if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,txid,vout,value,deposittxid,depositvout,depositval,script,coin->smartaddr,LP_peerinfos[0].ipaddr,LP_peerinfos[0].port,LP_peerinfos[0].profitmargin)) != 0 ) utxo->mypub = curve25519(privkey,curve25519_basepoint9()); } else { - if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coinaddr,"127.0.0.1",0,0)) != 0 ) + if ( (utxo= LP_addutxo(amclient,mypeer,mypubsock,symbol,deposittxid,depositvout,depositval,txid,vout,value,script,coin->smartaddr,"127.0.0.1",0,0)) != 0 ) utxo->mypub = curve25519(privkey,curve25519_basepoint9()); } total += value;