diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index 3922708ed..a46edacae 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -23,7 +23,7 @@ #define LP_MAJOR_VERSION "0" #define LP_MINOR_VERSION "1" -#define LP_BUILD_NUMBER "14288" +#define LP_BUILD_NUMBER "14336" #ifdef FROM_JS #include @@ -238,7 +238,7 @@ struct LP_swap_remember bits256 pubA0,pubB0,pubB1,privAm,privBn,paymentspent,Apaymentspent,depositspent,myprivs[2],txids[sizeof(txnames)/sizeof(*txnames)]; uint64_t Atxfee,Btxfee,srcamount,destamount,aliceid; int64_t values[sizeof(txnames)/sizeof(*txnames)]; - uint32_t tradeid,requestid,quoteid,plocktime,dlocktime,expiration,state,otherstate; + uint32_t finishtime,tradeid,requestid,quoteid,plocktime,dlocktime,expiration,state,otherstate; int32_t iambob,finishedflag,origfinishedflag,Predeemlen,Dredeemlen,sentflags[sizeof(txnames)/sizeof(*txnames)]; uint8_t secretAm[20],secretAm256[32],secretBn[20],secretBn256[32],Predeemscript[1024],Dredeemscript[1024],pubkey33[33],other33[33]; char src[64],dest[64],destaddr[64],Adestaddr[64],Sdestaddr[64],alicepaymentaddr[64],bobpaymentaddr[64],bobdepositaddr[64],alicecoin[64],bobcoin[64],*txbytes[sizeof(txnames)/sizeof(*txnames)]; @@ -443,6 +443,7 @@ struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coina int32_t LP_destaddr(char *destaddr,cJSON *item); int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration); char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey); +uint32_t LP_heighttime(char *symbol,int32_t height); uint64_t LP_unspents_load(char *symbol,char *addr); int32_t LP_validSPV(char *symbol,char *coinaddr,bits256 txid,int32_t vout); struct LP_transaction *LP_transactionfind(struct iguana_info *coin,bits256 txid); diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index 279276789..ce4574d09 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -18,9 +18,10 @@ // LP_nativeDEX.c // marketmaker // -// immediate "request", actual auction +// alice waiting for bestprice +// regen inventory // previously, it used to show amount, kmd equiv, perc -//there is still a pending one with `-1 wait for bobpayment bYoNxkfvwQ42Yufry8J5y8BYi6mQxokvW9 numconfs.1 MNZ c0ea4aa808a653222a15122d96692fecf734dbbacfb9a54cb4711306ea0c3cef`, but that tx is already spent including 6 confirmation +// there is still a pending one with `-1 wait for bobpayment bYoNxkfvwQ42Yufry8J5y8BYi6mQxokvW9 numconfs.1 MNZ c0ea4aa808a653222a15122d96692fecf734dbbacfb9a54cb4711306ea0c3cef`, but that tx is already spent including 6 confirmation // bot safe to exit? // // BCH signing @@ -466,7 +467,7 @@ void utxosQ_loop(void *myipaddr) void LP_coinsloop(void *_coins) { - struct LP_address *ap=0; struct LP_transaction *tx; cJSON *retjson; struct LP_address_utxo *up,*tmp; struct iguana_info *coin,*ctmp; char str[65]; struct electrum_info *ep,*backupep=0; bits256 zero; int32_t oldht,j,nonz; char *coins = _coins; + struct LP_address *ap=0,*atmp; struct LP_transaction *tx; cJSON *retjson; struct LP_address_utxo *up,*tmp; struct iguana_info *coin,*ctmp; char str[65]; struct electrum_info *ep,*backupep=0; bits256 zero; int32_t oldht,j,nonz; char *coins = _coins; if ( strcmp("BTC",coins) == 0 ) { strcpy(LP_coinsloopBTC_stats.name,"BTC coin loop"); @@ -514,14 +515,23 @@ void LP_coinsloop(void *_coins) { if ( (backupep= ep->prev) == 0 ) backupep = ep; - //HASH_ITER(hh,coin->addresses,ap,atmp) + // skip cLP_address MNZ bXcSsYBiVKtTzYErqxvma4UsojZTEf5L6H + //printf("electrum %s\n",coin->symbol); if ( (ap= LP_addressfind(coin,coin->smartaddr)) != 0 ) { if ( (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,ap->coinaddr,1)) != 0 ) free_json(retjson); + } + HASH_ITER(hh,coin->addresses,ap,atmp) + { + //printf("call unspent %s\n",ap->coinaddr); + if ( (retjson= electrum_address_listunspent(coin->symbol,ep,&retjson,ap->coinaddr,1)) != 0 ) + free_json(retjson); + } + HASH_ITER(hh,coin->addresses,ap,atmp) + { DL_FOREACH_SAFE(ap->utxos,up,tmp) { - break; if ( up->U.height > 0 && up->spendheight < 0 ) { if ( up->SPV == 0 ) @@ -813,12 +823,14 @@ void LP_reserved_msgs(void *ignore) if ( num_Reserved_msgs[1] > 0 ) { num_Reserved_msgs[1]--; + //printf("PRIORITY BROADCAST.(%s)\n",Reserved_msgs[1][num_Reserved_msgs[1]]); LP_broadcast_message(LP_mypubsock,"","",zero,Reserved_msgs[1][num_Reserved_msgs[1]]); Reserved_msgs[1][num_Reserved_msgs[1]] = 0; } else if ( num_Reserved_msgs[0] > 0 ) { num_Reserved_msgs[0]--; + //printf("BROADCAST.(%s)\n",Reserved_msgs[0][num_Reserved_msgs[0]]); LP_broadcast_message(LP_mypubsock,"","",zero,Reserved_msgs[0][num_Reserved_msgs[0]]); Reserved_msgs[0][num_Reserved_msgs[0]] = 0; } @@ -845,7 +857,8 @@ int32_t LP_reserved_msg(int32_t priority,char *base,char *rel,bits256 pubkey,cha if ( num_Reserved_msgs[priority] > max_Reserved_msgs[priority] ) { max_Reserved_msgs[priority] = num_Reserved_msgs[priority]; - printf("New priority.%d max_Reserved_msgs.%d\n",priority,max_Reserved_msgs[priority]); + if ( (max_Reserved_msgs[priority] % 100) == 0 ) + printf("New priority.%d max_Reserved_msgs.%d\n",priority,max_Reserved_msgs[priority]); } portable_mutex_unlock(&LP_reservedmutex); return(n); diff --git a/iguana/exchanges/LP_ordermatch.c b/iguana/exchanges/LP_ordermatch.c index c2eba14fb..7bb60dd40 100644 --- a/iguana/exchanges/LP_ordermatch.c +++ b/iguana/exchanges/LP_ordermatch.c @@ -18,6 +18,35 @@ // LP_ordermatch.c // marketmaker // +struct LP_quoteinfo LP_Alicequery; +double LP_Alicemaxprice; +uint32_t Alice_expiration; +struct { uint64_t aliceid; double bestprice; } Bob_competition[512]; + +double LP_bob_competition(uint64_t aliceid,double price) +{ + int32_t i,firsti = -1; + for (i=0; idestcoin,qp->desttxid,qp->destvout,qp->destsatoshis,qp->feetxid,qp->feevout) == 0 ) { - char str[65]; printf("alice not eligible destsatoshis %.8f (%.8f %.8f) %s/v%d\n",dstr(qp->destsatoshis),dstr(destvalue),dstr(destvalue2),bits256_str(str,qp->feetxid),qp->feevout); + char str[65],str2[65]; printf("alice not eligible %.8f -> dest %.8f %.8f (%.8f %.8f) %s/v%d %s/v%d\n",dstr(qp->satoshis),dstr(qp->destsatoshis),(double)qp->destsatoshis/qp->satoshis,dstr(destvalue),dstr(destvalue2),bits256_str(str,qp->desttxid),qp->destvout,bits256_str(str2,qp->feetxid),qp->feevout); return(-3); } if ( (txout= LP_gettxout(qp->destcoin,qp->destaddr,qp->desttxid,qp->destvout)) != 0 ) @@ -413,9 +442,6 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ return(retval); } -struct LP_quoteinfo LP_Alicequery; -double LP_Alicemaxprice; -uint32_t Alice_expiration; char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *qp,double maxprice,int32_t timeout,int32_t duration,uint32_t tradeid) { struct LP_utxoinfo *aliceutxo; double price; //cJSON *bestitem=0; int32_t DEXselector=0; uint32_t expiration; double price; struct LP_pubkeyinfo *pubp; struct basilisk_swap *swap; @@ -486,14 +512,6 @@ char *LP_connectedalice(cJSON *argjson) // alice return(clonestr("{\"result\",\"update stats\"}")); } printf("CONNECTED.(%s) numpending.%d tradeid.%u\n",jprint(argjson,0),G.LP_pendingswaps,Q.tradeid); - /*if ( LP_alice_eligible() == 0 || LP_quotecmp(&Q,&LP_Alicequery) != 0 ) - { - printf("reject mismatched alice query\n"); - return(clonestr("{\"error\",\"mismatched alice query\"}")); - } - memset(&LP_Alicequery,0,sizeof(LP_Alicequery)); - LP_Alicemaxprice = 0.; - Alice_expiration = 0;*/ if ( (autxo= LP_utxopairfind(0,Q.desttxid,Q.destvout,Q.feetxid,Q.feevout)) == 0 ) { printf("cant find autxo\n"); @@ -502,6 +520,7 @@ char *LP_connectedalice(cJSON *argjson) // alice } if ( autxo->S.swap != 0 ) { + printf("ignore duplicate swap\n"); LP_aliceid(Q.tradeid,Q.aliceid,"error3",0,0); return(clonestr("{\"error\":\"ignore duplicate swap\"}")); } @@ -518,7 +537,7 @@ char *LP_connectedalice(cJSON *argjson) // alice } if ( LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin) <= SMALLVAL || bid <= SMALLVAL ) { - //printf("this node has no price for %s/%s (%.8f %.8f)\n",Q.destcoin,Q.srccoin,bid,ask); + printf("this node has no price for %s/%s (%.8f %.8f)\n",Q.destcoin,Q.srccoin,bid,ask); LP_availableset(autxo); LP_aliceid(Q.tradeid,Q.aliceid,"error5",0,0); return(clonestr("{\"error\":\"no price set\"}")); @@ -669,22 +688,26 @@ int32_t LP_validSPV(char *symbol,char *coinaddr,bits256 txid,int32_t vout) int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,uint8_t *data,int32_t datalen) { - char *method,*msg,*retstr,str[65]; int32_t DEXselector = 0; uint64_t value,value2; cJSON *retjson; double qprice,price,bid,ask; struct LP_utxoinfo A,B,*autxo,*butxo; struct iguana_info *coin; struct LP_address_utxo *utxos[1000]; struct LP_quoteinfo Q; int32_t retval = -1,recalc,max=(int32_t)(sizeof(utxos)/sizeof(*utxos)); + char *method,*msg,*retstr,str[65]; int32_t DEXselector = 0; uint64_t aliceid,value,value2; cJSON *retjson; double qprice,range,bestprice,price,bid,ask; struct LP_utxoinfo A,B,*autxo,*butxo; struct iguana_info *coin; struct LP_address_utxo *utxos[1000]; struct LP_quoteinfo Q; int32_t r,retval = -1,recalc,max=(int32_t)(sizeof(utxos)/sizeof(*utxos)); if ( (method= jstr(argjson,"method")) != 0 && (strcmp(method,"reserved") == 0 ||strcmp(method,"connected") == 0 || strcmp(method,"request") == 0 || strcmp(method,"connect") == 0) ) { // LP_checksig LP_quoteparse(&Q,argjson); LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-Q.txfee,Q.destcoin,Q.destsatoshis-Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector); LP_tradecommand_log(argjson); - //printf("LP_tradecommand: check received method %s aliceid.%llx\n",method,(long long)Q.aliceid); + //printf("LP_tradecommand: check received method %12s aliceid.%16llx %5s/%-5s %12.8f -> %12.8f price %12.8f\n",method,(long long)Q.aliceid,Q.srccoin,Q.destcoin,dstr(Q.satoshis),dstr(Q.destsatoshis),(double)Q.destsatoshis/Q.satoshis); retval = 1; autxo = &A; butxo = &B; memset(autxo,0,sizeof(*autxo)); memset(butxo,0,sizeof(*butxo)); LP_abutxo_set(autxo,butxo,&Q); + aliceid = j64bits(argjson,"aliceid"); + qprice = jdouble(argjson,"price"); if ( strcmp(method,"reserved") == 0 ) { + bestprice = LP_bob_competition(aliceid,qprice); + //printf("aliceid.%llx price %.8f -> bestprice %.8f\n",(long long)aliceid,qprice,bestprice); if ( LP_Alicemaxprice == 0. ) return(retval); if ( bits256_cmp(G.LP_mypub25519,Q.desthash) == 0 && bits256_cmp(G.LP_mypub25519,Q.srchash) != 0 && LP_alice_eligible() > 0 ) @@ -699,7 +722,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, printf("%s src %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid)); return(retval); } - else if (LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid2,Q.vout2) < 0 ) + else if ( LP_validSPV(Q.srccoin,Q.coinaddr,Q.txid2,Q.vout2) < 0 ) { printf("%s src2 %s failed SPV check\n",Q.srccoin,bits256_str(str,Q.txid2)); return(retval); @@ -737,11 +760,14 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, } return(retval); } - if ( (coin= LP_coinfind(Q.srccoin)) == 0 || (price= LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin)) <= SMALLVAL || ask <= SMALLVAL ) + price = LP_myprice(&bid,&ask,Q.srccoin,Q.destcoin); + if ( (coin= LP_coinfind(Q.srccoin)) == 0 || price <= SMALLVAL || ask <= SMALLVAL ) { //printf("this node has no price for %s/%s\n",Q.srccoin,Q.destcoin); return(retval); } + price = ask; + //printf("MYPRICE %s/%s %.8f\n",Q.srccoin,Q.destcoin,price); if ( LP_validSPV(Q.destcoin,Q.destaddr,Q.desttxid,Q.destvout) < 0 ) { printf("%s dest %s failed SPV check\n",Q.destcoin,bits256_str(str,Q.desttxid)); @@ -752,7 +778,6 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, printf("%s dexfee %s failed SPV check\n",Q.destcoin,bits256_str(str,Q.feetxid)); return(retval); } - price = ask; if ( LP_aliceonly(Q.srccoin) > 0 ) { printf("{\"error\":\"GAME can only be alice coin\"}\n"); @@ -760,11 +785,11 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, } if ( strcmp(method,"request") == 0 ) { - char str[65],str2[65]; - //printf("address.(%s/%s) request.(%s)\n",Q.coinaddr,coin->smartaddr,jprint(argjson,0)); + char str[65];//,str2[65]; recalc = 0; - if ( bits256_cmp(Q.srchash,G.LP_mypub25519) != 0 || strcmp(butxo->coinaddr,coin->smartaddr) != 0 ) + if ( bits256_cmp(Q.srchash,G.LP_mypub25519) != 0 || strcmp(butxo->coinaddr,coin->smartaddr) != 0 || bits256_nonz(butxo->payment.txid) == 0 || bits256_nonz(butxo->deposit.txid) == 0 ) { + qprice = (double)Q.destsatoshis / Q.satoshis; strcpy(Q.gui,G.gui); strcpy(Q.coinaddr,coin->smartaddr); strcpy(butxo->coinaddr,coin->smartaddr); @@ -776,16 +801,16 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, } else if ( (qprice= LP_quote_validate(autxo,butxo,&Q,1)) < SMALLVAL ) recalc = 1; - else + else if ( price < qprice ) { char tmp[64]; - price = (qprice * 0.5) + (0.5 * price); if ( bits256_nonz(Q.txid) != 0 ) LP_utxos_remove(Q.txid,Q.vout); else recalc = 1; if ( bits256_nonz(Q.txid2) != 0 ) LP_utxos_remove(Q.txid2,Q.vout2); else recalc = 1; + printf("price %.8f qprice %.8f\n",price,qprice); if ( recalc == 0 ) { value = LP_txvalue(tmp,Q.srccoin,Q.txid,Q.vout); @@ -793,13 +818,21 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, //printf("call LP_utxoadd.(%s) %.8f %.8f\n",Q.coinaddr,dstr(value),dstr(value2)); if ( (butxo= LP_utxoadd(1,coin->symbol,Q.txid,Q.vout,value,Q.txid2,Q.vout2,value2,Q.coinaddr,Q.srchash,G.gui,0,Q.satoshis)) == 0 ) recalc = 1; - } - else - { - if ( bits256_cmp(Q.txid,butxo->payment.txid) != 0 || Q.vout != butxo->payment.vout || bits256_cmp(Q.txid2,butxo->deposit.txid) != 0 || Q.vout2 != butxo->deposit.vout ) + else if ( bits256_cmp(Q.txid,butxo->payment.txid) != 0 || Q.vout != butxo->payment.vout || bits256_cmp(Q.txid2,butxo->deposit.txid) != 0 || Q.vout2 != butxo->deposit.vout ) recalc = 1; } - } + } else return(retval); + if ( qprice > price ) + { + r = (rand() % 100); + range = (qprice - price); + printf(">>>>>>>>>>>>> price %.8f qprice %.8f r.%d range %.8f -> %.8f vs bestprice %.8f\n",price,qprice,r,range,price + (r*range)/100.,LP_bob_competition(aliceid,price)); + price += (r * range) / 100.; + bestprice = LP_bob_competition(aliceid,price); + if ( price < bestprice+SMALLVAL ) + return(retval); + } else return(retval); + //printf("recalc.%d address.(%s/%s) price %.8f request.(%s)\n",recalc,Q.coinaddr,coin->smartaddr,price,jprint(argjson,0)); if ( recalc != 0 ) { LP_RTmetrics_update(Q.srccoin,Q.destcoin); @@ -808,7 +841,6 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, printf("request from blacklisted %s, ignore\n",bits256_str(str,Q.desthash)); return(retval); } - //printf("butxo.%p recalc path %p %s, %p %s, %.8f\n",butxo,LP_allocated(butxo->payment.txid,butxo->payment.vout),bits256_str(str,butxo->payment.txid),LP_allocated(butxo->deposit.txid,butxo->deposit.vout),bits256_str(str2,butxo->deposit.txid),LP_quote_validate(autxo,butxo,&Q,1)); LP_listunspent_both(Q.srccoin,Q.coinaddr,0); if ( (butxo= LP_address_utxopair(1,utxos,max,LP_coinfind(Q.srccoin),Q.coinaddr,Q.txfee,dstr(Q.destsatoshis),price,Q.desttxfee)) != 0 ) { @@ -819,8 +851,8 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, Q.vout = butxo->payment.vout; Q.txid2 = butxo->deposit.txid; Q.vout2 = butxo->deposit.vout; - butxo->S.satoshis = Q.satoshis; - printf("set butxo.%p %s/v%d %s/v%d %.8f %.8f -> bsat %.8f asat %.8f\n",butxo,bits256_str(str,butxo->payment.txid),butxo->payment.vout,bits256_str(str2,butxo->deposit.txid),butxo->deposit.vout,dstr(butxo->payment.value),dstr(butxo->deposit.value),dstr(butxo->S.satoshis),dstr(autxo->S.satoshis)); + Q.satoshis = butxo->S.satoshis; + //printf("set butxo.%p %s/v%d %s/v%d %.8f %.8f -> bsat %.8f asat %.8f\n",butxo,bits256_str(str,butxo->payment.txid),butxo->payment.vout,bits256_str(str2,butxo->deposit.txid),butxo->deposit.vout,dstr(butxo->payment.value),dstr(butxo->deposit.value),dstr(butxo->S.satoshis),dstr(autxo->S.satoshis)); } else { @@ -851,9 +883,9 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, printf("quote validate error %.0f\n",qprice); return(-3); } - if ( qprice < (price - 0.00000001) * 0.998 ) + if ( qprice < (ask - 0.00000001) * 0.998 ) { - printf("(%.8f %.8f) quote price %.8f too low vs %.8f for %s/%s\n",bid,ask,qprice,price,Q.srccoin,Q.destcoin); + printf("(%.8f %.8f) quote price %.8f too low vs %.8f for %s/%s %.8f < %.8f\n",bid,ask,qprice,price,Q.srccoin,Q.destcoin,qprice,(ask - 0.00000001) * 0.998); return(retval); } char str[65],str2[65]; printf("butxo.%p (%s %s) TRADECOMMAND.(%s)\n",butxo,butxo!=0?bits256_str(str,butxo->payment.txid):"",butxo!=0?bits256_str(str2,butxo->deposit.txid):"",jprint(argjson,0)); @@ -874,7 +906,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson, jaddstr(retjson,"method","reserved"); msg = jprint(retjson,0); butxo->T.lasttime = (uint32_t)time(NULL); - printf("return after queued RESERVED: set swappending.%u accept qprice %.8f, min %.8f\n(%s)\n",butxo->T.swappending,qprice,price,msg); + printf("return after queued RESERVED: set swappending.%u accept qprice %.8f, min %.8f\n(%s)\n",butxo->T.swappending,qprice,ask,msg); // LP_addsig //msg2 = clonestr(msg); LP_reserved_msg(1,Q.srccoin,Q.destcoin,butxo->S.otherpubkey,clonestr(msg)); @@ -1011,7 +1043,7 @@ struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,i char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel,double maxprice,double relvolume,int32_t timeout,int32_t duration,char *gui,uint32_t nonce,bits256 destpubkey,uint32_t tradeid) { - uint64_t desttxfee,txfee; uint32_t lastnonce; int32_t i,maxiters,numpubs = 0; int64_t bestsatoshis=0,destsatoshis,bestdestsatoshis=0; struct iguana_info *basecoin,*relcoin; struct LP_utxoinfo *autxo,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q; bits256 pubkeys[100]; + uint64_t desttxfee,txfee; uint32_t lastnonce; int32_t i,maxiters,numpubs = 0; int64_t bestsatoshis=0,destsatoshis,bestdestsatoshis=0; struct iguana_info *basecoin,*relcoin; struct LP_utxoinfo *autxo,B,*bestutxo = 0; double qprice,ordermatchprice=0.; struct LP_quoteinfo Q; bits256 pubkeys[100]; basecoin = LP_coinfind(base); relcoin = LP_coinfind(rel); if ( gui == 0 ) @@ -1076,8 +1108,18 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel printf("destsatoshis %.8f vs utxo %.8f this would have triggered an quote error -13\n",dstr(destsatoshis),dstr(autxo->payment.value)); return(clonestr("{\"error\":\"cant find alice utxo that is small enough\"}")); } + bestsatoshis = LP_basesatoshis(dstr(destsatoshis),maxprice,txfee,desttxfee); + memset(&B,0,sizeof(B)); + strcpy(B.coin,base); + if ( LP_quoteinfoinit(&Q,&B,rel,maxprice,bestsatoshis,destsatoshis) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote\"}")); + if ( LP_quotedestinfo(&Q,autxo->payment.txid,autxo->payment.vout,autxo->fee.txid,autxo->fee.vout,G.LP_mypub25519,autxo->coinaddr) < 0 ) + return(clonestr("{\"error\":\"cant set ordermatch quote info\"}")); + int32_t changed; + LP_mypriceset(&changed,autxo->coin,base,1. / maxprice); + return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration,tradeid)); + LP_RTmetrics_update(base,rel); - //return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration,tradeid)); while ( 1 ) { if ( (bestutxo= LP_buyutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,gui,pubkeys,numpubs,destpubkey)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 ) diff --git a/iguana/exchanges/LP_remember.c b/iguana/exchanges/LP_remember.c index f8bc1a227..44d93a71a 100644 --- a/iguana/exchanges/LP_remember.c +++ b/iguana/exchanges/LP_remember.c @@ -450,6 +450,7 @@ cJSON *LP_swap_json(struct LP_swap_remember *rswap) { cJSON *item,*array; int32_t i; item = cJSON_CreateObject(); + jaddnum(item,"expiration",rswap->expiration);// - INSTANTDEX_LOCKTIME*2); jaddnum(item,"tradeid",rswap->tradeid); jaddnum(item,"requestid",rswap->requestid); jaddnum(item,"quoteid",rswap->quoteid); @@ -476,7 +477,10 @@ cJSON *LP_swap_json(struct LP_swap_remember *rswap) jadd(item,"values",array); jaddstr(item,"result","success"); if ( rswap->finishedflag != 0 ) + { jaddstr(item,"status","finished"); + jaddnum(item,"finishtime",rswap->finishtime); + } else jaddstr(item,"status","pending"); jaddbits256(item,"bobdeposit",rswap->txids[BASILISK_BOBDEPOSIT]); jaddbits256(item,"alicepayment",rswap->txids[BASILISK_ALICEPAYMENT]); @@ -657,6 +661,7 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap) { if ( (fileobj= cJSON_Parse(fstr)) != 0 ) { + rswap->finishtime = juint(fileobj,"finishtime"); rswap->origfinishedflag = rswap->finishedflag = 1; free_json(fileobj); } @@ -1115,6 +1120,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti if ( (fp= fopen(fname,"wb")) != 0 ) { jaddstr(item,"method","tradestatus"); + jaddnum(item,"finishtime",rswap.finishtime); jaddstr(item,"gui",G.gui); itemstr = jprint(item,0); fprintf(fp,"%s\n",itemstr); @@ -1131,7 +1137,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid) { - uint64_t ridqids[4096],ridqid; char fname[512]; FILE *fp; cJSON *item,*retjson,*array,*totalsobj; uint32_t r,q,quoteid,requestid; int64_t KMDtotals[16],BTCtotals[16],Btotal,Ktotal; int32_t i,j,count=0; + uint64_t ridqids[4096],ridqid; char fname[512]; FILE *fp; cJSON *item,*retjson,*array,*totalsobj; uint32_t r,q,quoteid,requestid; int64_t KMDtotals[LP_MAXPRICEINFOS],BTCtotals[LP_MAXPRICEINFOS],Btotal,Ktotal; int32_t i,j,count=0; portable_mutex_lock(&LP_swaplistmutex); memset(ridqids,0,sizeof(ridqids)); memset(KMDtotals,0,sizeof(KMDtotals)); @@ -1223,8 +1229,13 @@ char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid) char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid) { - char *liststr,*retstr = 0; cJSON *retjson,*array,*item; int32_t i,n; - if ( (liststr= basilisk_swaplist(requestid,quoteid)) != 0 ) + cJSON *item; int64_t KMDtotals[LP_MAXPRICEINFOS],BTCtotals[LP_MAXPRICEINFOS]; + memset(KMDtotals,0,sizeof(KMDtotals)); + memset(BTCtotals,0,sizeof(BTCtotals)); + if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid)) != 0 ) + return(jprint(item,1)); + else return(clonestr("{\"error\":\"cant find requestid-quoteid\"}")); + /*if ( (liststr= basilisk_swaplist(requestid,quoteid)) != 0 ) { //printf("swapentry.(%s)\n",liststr); if ( (retjson= cJSON_Parse(liststr)) != 0 ) @@ -1246,7 +1257,7 @@ char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid) } free(liststr); } - return(retstr); + return(retstr);*/ } extern struct LP_quoteinfo LP_Alicequery; diff --git a/iguana/exchanges/LP_rpc.c b/iguana/exchanges/LP_rpc.c index 661c476e6..1d952ff6d 100644 --- a/iguana/exchanges/LP_rpc.c +++ b/iguana/exchanges/LP_rpc.c @@ -447,6 +447,23 @@ uint32_t LP_locktime(char *symbol,bits256 txid) return(locktime); } +/*uint32_t LP_txtime(char *symbol,bits256 txid) +{ + struct LP_transaction *tx; struct iguana_info *coin; int32_t timestamp=0,height = 0; + char str[65]; printf("LP_txtime (%s %s)\n",symbol,bits256_str(str,txid)); + if ( (timestamp= LP_locktime(symbol,txid)) != 0 ) + return(timestamp); + if ( (coin= LP_coinfind(symbol)) != 0 ) + { + if ( (tx= LP_transactionfind(coin,txid)) != 0 ) + { + height = tx->height; + timestamp = LP_heighttime(symbol,height); + } + } + return(height); +}*/ + cJSON *LP_gettxout_json(bits256 txid,int32_t vout,int32_t height,char *coinaddr,uint64_t value) { cJSON *retjson,*addresses,*sobj; @@ -1013,6 +1030,37 @@ cJSON *LP_getblockhashstr(char *symbol,char *blockhashstr) return(bitcoin_json(coin,"getblock",buf)); } +uint32_t LP_heighttime(char *symbol,int32_t height) +{ + struct electrum_info *ep; uint32_t timestamp = 0; cJSON *retjson; char *blockhashstr; struct iguana_info *coin = LP_coinfind(symbol); + if ( coin != 0 ) + { + if ( (ep= coin->electrum) == 0 ) + { + if ( (blockhashstr= LP_blockhashstr(symbol,height)) != 0 ) + { + if ( (retjson= cJSON_Parse(blockhashstr)) != 0 ) + { + printf("height.(%s)\n",jprint(retjson,0)); + timestamp = juint(retjson,"time"); + free_json(retjson); + } + free(blockhashstr); + } + } + else + { + if ( (retjson= electrum_getheader(coin->symbol,ep,&retjson,height)) != 0 ) + { + printf("%s\n",jprint(retjson,0)); + timestamp = juint(retjson,"timestamp"); + free_json(retjson); + } + } + } + return(timestamp); +} + cJSON *LP_blockjson(int32_t *heightp,char *symbol,char *blockhashstr,int32_t height) { cJSON *json = 0; int32_t flag = 0; struct iguana_info *coin; diff --git a/iguana/exchanges/LP_socket.c b/iguana/exchanges/LP_socket.c index 5be93ba33..e679ef67f 100644 --- a/iguana/exchanges/LP_socket.c +++ b/iguana/exchanges/LP_socket.c @@ -329,7 +329,7 @@ int32_t electrum_process_array(struct iguana_info *coin,struct electrum_info *ep tx->height = ht; if ( ep != 0 && coin != 0 && tx->SPV == 0 ) { - if ( strcmp(coinaddr,coin->smartaddr) == 0 ) + if ( 0 && strcmp(coinaddr,coin->smartaddr) == 0 ) tx->SPV = LP_merkleproof(coin,coin->smartaddr,ep,txid,tx->height); //printf("%s %s >>>>>>>>>> set %s <- height %d\n",coin->symbol,coinaddr,bits256_str(str,txid),tx->height); } diff --git a/iguana/exchanges/LP_tradebots.c b/iguana/exchanges/LP_tradebots.c index 9f7a94b4e..a2e82ac10 100644 --- a/iguana/exchanges/LP_tradebots.c +++ b/iguana/exchanges/LP_tradebots.c @@ -476,13 +476,14 @@ char *LP_tradebot_buy(int32_t dispdir,char *base,char *rel,double maxprice,doubl free(retstr); txfee = LP_txfeecalc(relcoin,0,0); txfees = 10 * txfee; - printf("%s inventory balance %.8f, relvolume %.8f + txfees %.8f\n",rel,dstr(abalance),relvolume,dstr(txfees)); - if ( dstr(abalance) < relvolume + dstr(txfees) ) + if ( relcoin->electrum != 0 ) + balance = LP_unspents_load(relcoin->symbol,relcoin->smartaddr); + else balance = LP_RTsmartbalance(relcoin); + sum = (relvolume+2*dstr(txfees)) + 3 * ((relvolume+2*dstr(txfees))/777); + printf("%s inventory balance %.8f, relvolume %.8f + txfees %.8f, utxobal %.8f sum %.8f\n",rel,dstr(abalance),relvolume,dstr(txfees),dstr(balance),dstr(sum)); + if ( dstr(abalance) < relvolume + dstr(txfees) && balance > sum+txfee ) { retjson = cJSON_CreateObject(); - if ( relcoin->electrum != 0 ) - balance = LP_unspents_load(relcoin->symbol,relcoin->smartaddr); - else balance = LP_RTsmartbalance(relcoin); jaddstr(retjson,"error","not enough funds"); jaddstr(retjson,"coin",rel); jaddnum(retjson,"abalance",dstr(abalance)); @@ -491,7 +492,6 @@ char *LP_tradebot_buy(int32_t dispdir,char *base,char *rel,double maxprice,doubl jaddnum(retjson,"txfees",dstr(txfees)); shortfall = (relvolume + dstr(txfees)) - dstr(balance); jaddnum(retjson,"shortfall",shortfall); - sum = (relvolume+2*dstr(txfees)) + 3 * ((relvolume+2*dstr(txfees))/777); if ( balance >= sum+txfee ) { char *withdrawstr; cJSON *outputjson,*withdrawjson,*outputs,*item; diff --git a/iguana/exchanges/LP_transaction.c b/iguana/exchanges/LP_transaction.c index d9939432d..bc582236c 100644 --- a/iguana/exchanges/LP_transaction.c +++ b/iguana/exchanges/LP_transaction.c @@ -652,7 +652,7 @@ char *basilisk_swap_bobtxspend(bits256 *signedtxidp,uint64_t txfee,char *name,ch satoshis = value - 3*txfee/4; printf("reduce satoshis %.8f by txfee %.8f to value %.8f\n",dstr(satoshis),dstr(txfee),dstr(value)); } - else if ( value == satoshis && (double)txfee/value < 0.1 ) + else if ( value == satoshis && (double)txfee/value < 0.25 ) { satoshis = value - txfee; printf("txfee allocation from value %.8f identical to satoshis: %.8f txfee %.8f\n",dstr(value),dstr(satoshis),dstr(txfee)); diff --git a/iguana/exchanges/LP_utxo.c b/iguana/exchanges/LP_utxo.c index e76b74a54..bfd1103f3 100644 --- a/iguana/exchanges/LP_utxo.c +++ b/iguana/exchanges/LP_utxo.c @@ -64,7 +64,10 @@ struct LP_address *_LP_address(struct iguana_info *coin,char *coinaddr) { struct LP_address *ap = 0; if ( (ap= _LP_addressfind(coin,coinaddr)) == 0 ) + { ap = _LP_addressadd(coin,coinaddr); + //printf("LP_address %s %s\n",coin->symbol,coinaddr); + } return(ap); } @@ -145,6 +148,7 @@ int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_a //printf("LP_address_utxo_ptrs for (%s).(%s)\n",ap->coinaddr,coinaddr); if ( strcmp(ap->coinaddr,coinaddr) != 0 ) printf("UNEXPECTED coinaddr mismatch (%s) != (%s)\n",ap->coinaddr,coinaddr); + LP_listunspent_issue(coin->symbol,coin->smartaddr,2); portable_mutex_lock(&LP_utxomutex); DL_FOREACH_SAFE(ap->utxos,up,tmp) { @@ -185,7 +189,7 @@ int32_t LP_address_utxo_ptrs(struct iguana_info *coin,int32_t iambob,struct LP_a continue; } } - if ( LP_allocated(up->U.txid,up->U.vout) == 0 && _LP_utxofind(iambob,up->U.txid,up->U.vout) == 0 && _LP_utxo2find(iambob,up->U.txid,up->U.vout) == 0 ) + if ( LP_allocated(up->U.txid,up->U.vout) == 0 && (iambob == 0 || (_LP_utxofind(iambob,up->U.txid,up->U.vout) == 0 && _LP_utxo2find(iambob,up->U.txid,up->U.vout) == 0)) ) { utxos[n++] = up; if ( n >= max ) @@ -660,6 +664,11 @@ int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int } else if ( mempool != 0 && LP_mempoolscan(symbol,txid) >= 0 ) numconfirms = 0; + else if ( (txobj= LP_gettx(symbol,txid)) != 0 ) + { + numconfirms = jint(txobj,"confirmations"); + free_json(txobj); + } } else { @@ -847,7 +856,7 @@ int32_t LP_iseligible(uint64_t *valp,uint64_t *val2p,int32_t iambob,char *symbol } return(1); } - } // else printf("no val2\n"); + } else printf("no val2 %.8f < threshold %.8f\n",dstr(val),dstr(threshold)); } /*char str2[65]; if ( val != 0 && val2 != 0 ) diff --git a/iguana/exchanges/LP_utxos.c b/iguana/exchanges/LP_utxos.c index e82541a63..2d5a04915 100644 --- a/iguana/exchanges/LP_utxos.c +++ b/iguana/exchanges/LP_utxos.c @@ -549,12 +549,12 @@ int32_t LP_privkey_init(int32_t mypubsock,struct iguana_info *coin,bits256 mypri if ( coin->privkeydepth > 0 ) return(0); coin->privkeydepth++; + LP_address(coin,coin->smartaddr); //printf("privkey init.(%s) %s depth.%d\n",coin->symbol,coin->smartaddr,coin->privkeydepth); if ( coin->inactive == 0 ) LP_listunspent_issue(coin->symbol,coin->smartaddr,0); array = LP_listunspent(coin->symbol,coin->smartaddr); //printf("unspent array %ld\n",strlen(jprint(array,0))); - LP_address(coin,coin->smartaddr); if ( array != 0 ) { txfee = LP_txfeecalc(coin,0,0); diff --git a/iguana/exchanges/sell b/iguana/exchanges/sell index fccc4d61e..a48ffaac1 100755 --- a/iguana/exchanges/sell +++ b/iguana/exchanges/sell @@ -1,3 +1,3 @@ #!/bin/bash source userpass -curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"sell\",\"base\":\"KMD\",\"rel\":\"BTC\",\"basevolume\":10.0\",price\":0.0005}" +curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"sell\",\"base\":\"KMD\",\"rel\":\"BTC\",\"basevolume\":10.0\",\"price\":0.0005}"