@ -25,10 +25,15 @@ uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee)
{
if ( strcmp ( coin - > symbol , " BTC " ) = = 0 )
{
if ( txfee = = 0 & & ( txfee = LP_getestimatedrate ( coin ) * LP_AVETXSIZE ) < LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE ;
}
else txfee = coin - > txfee ;
coin - > rate = LP_getestimatedrate ( coin ) ;
if ( ( txfee = SATOSHIDEN * coin - > rate * LP_AVETXSIZE ) < = LP_MIN_TXFEE )
{
coin - > rate = - 1. ;
coin - > rate = _LP_getestimatedrate ( coin ) ;
if ( ( txfee = SATOSHIDEN * coin - > rate * LP_AVETXSIZE ) < = LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE ;
}
} else txfee = coin - > txfee ;
if ( txfee < LP_MIN_TXFEE )
txfee = LP_MIN_TXFEE ;
}
@ -39,6 +44,7 @@ void LP_txfees(uint64_t *txfeep,uint64_t *desttxfeep,char *base,char *rel)
{
* txfeep = LP_txfeecalc ( LP_coinfind ( base ) , 0 ) ;
* desttxfeep = LP_txfeecalc ( LP_coinfind ( rel ) , 0 ) ;
printf ( " LP_txfees(%.8f %.8f) \n " , dstr ( * txfeep ) , dstr ( * desttxfeep ) ) ;
}
double LP_qprice_calc ( int64_t * destsatoshisp , int64_t * satoshisp , double price , uint64_t b_satoshis , uint64_t txfee , uint64_t a_value , uint64_t maxdestsatoshis , uint64_t desttxfee )
@ -126,7 +132,7 @@ cJSON *LP_quotejson(struct LP_quoteinfo *qp)
jadd64bits ( retjson , " destsatoshis " , qp - > destsatoshis ) ;
if ( qp - > satoshis ! = 0 )
{
price = ( double ) qp - > destsatoshis / qp - > satoshis ;
price = ( double ) qp - > destsatoshis / ( qp - > satoshis - qp - > txfee ) ;
jaddnum ( retjson , " price " , price ) ;
}
}
@ -167,11 +173,11 @@ int32_t LP_quoteinfoinit(struct LP_quoteinfo *qp,struct LP_utxoinfo *utxo,char *
LP_txfees ( & qp - > txfee , & qp - > desttxfee , utxo - > coin , qp - > destcoin ) ;
qp - > satoshis = satoshis ; //(destsatoshis / price) + 0.49;
qp - > destsatoshis = destsatoshis ;
if ( utxo - > iambob = = 0 | | qp - > txfee > = qp - > satoshis | | qp - > txfee > = utxo - > deposit . value | | utxo - > deposit . value < LP_DEPOSITSATOSHIS ( qp - > satoshis ) )
/*if ( qp->txfee >= qp->satoshis || qp->txfee >= utxo->deposit.value || utxo->deposit.value < LP_DEPOSITSATOSHIS(qp->satoshis) ) //utxo->iambob == 0 ||
{
printf ( " quoteinit error.(%d %d %d %d) %.8f vs %.8f \n " , utxo - > iambob = = 0 , qp - > txfee > = qp - > satoshis , qp - > txfee > = utxo - > deposit . value , utxo - > deposit . value < LP_DEPOSITSATOSHIS ( qp - > satoshis ) , dstr ( utxo - > deposit . value ) , dstr ( LP_DEPOSITSATOSHIS ( qp - > satoshis ) ) ) ;
return ( - 1 ) ;
}
} */
qp - > txid = utxo - > payment . txid ;
qp - > vout = utxo - > payment . vout ;
qp - > txid2 = utxo - > deposit . txid ;
@ -202,7 +208,7 @@ char *LP_quotereceived(cJSON *argjson)
{
struct LP_cacheinfo * ptr ; double price ; struct LP_quoteinfo Q ;
LP_quoteparse ( & Q , argjson ) ;
price = ( double ) Q . destsatoshis / Q . satoshis ;
price = ( double ) Q . destsatoshis / ( Q . satoshis - Q . txfee ) ;
if ( ( ptr = LP_cacheadd ( Q . srccoin , Q . destcoin , Q . txid , Q . vout , price , & Q ) ) ! = 0 )
{
ptr - > Q = Q ;
@ -215,7 +221,7 @@ char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *re
{
bits256 zero ; char * msg ; cJSON * reqjson = cJSON_CreateObject ( ) ;
memset ( zero . bytes , 0 , sizeof ( zero ) ) ;
jaddbits256 ( reqjson , " pubkey " , LP_mypub25519 ) ;
jaddbits256 ( reqjson , " pubkey " , G . LP_mypub25519 ) ;
jaddstr ( reqjson , " base " , base ) ;
jaddstr ( reqjson , " rel " , rel ) ;
jaddnum ( reqjson , " price " , price ) ;
@ -225,6 +231,19 @@ char *LP_pricepings(void *ctx,char *myipaddr,int32_t pubsock,char *base,char *re
return ( clonestr ( " { \" result \" : \" success \" } " ) ) ;
}
void LP_notify_pubkeys ( void * ctx , int32_t pubsock )
{
bits256 zero ; char * msg , secpstr [ 67 ] ; cJSON * reqjson = cJSON_CreateObject ( ) ;
memset ( zero . bytes , 0 , sizeof ( zero ) ) ;
jaddstr ( reqjson , " method " , " notify " ) ;
jaddstr ( reqjson , " rmd160 " , G . LP_myrmd160str ) ;
jaddbits256 ( reqjson , " pub " , G . LP_mypub25519 ) ;
init_hexbytes_noT ( secpstr , G . LP_pubsecp , 33 ) ;
jaddstr ( reqjson , " pubsecp " , secpstr ) ;
msg = jprint ( reqjson , 1 ) ;
LP_broadcast_message ( pubsock , " " , " " , zero , msg ) ;
}
char * LP_postedprice ( cJSON * argjson )
{
bits256 pubkey ; double price ; char * base , * rel ;
@ -241,15 +260,15 @@ char *LP_postedprice(cJSON *argjson)
return ( clonestr ( " { \" error \" : \" missing fields in posted price \" } " ) ) ;
}
int32_t LP_quote_checkmempool ( struct LP_quoteinfo * qp )
int32_t LP_quote_checkmempool ( struct LP_quoteinfo * qp , struct LP_utxoinfo * autxo , struct LP_utxoinfo * butxo )
{
int32_t selector , spendvini ; bits256 spendtxid ;
if ( ( selector = LP_mempool_vinscan ( & spendtxid , & spendvini , qp - > srccoin , qp - > coinaddr , qp - > txid , qp - > vout , qp - > txid2 , qp - > vout2 ) ) > = 0 )
if ( butxo ! = 0 & & ( selector = LP_mempool_vinscan ( & spendtxid , & spendvini , qp - > srccoin , qp - > coinaddr , qp - > txid , qp - > vout , qp - > txid2 , qp - > vout2 ) ) > = 0 )
{
char str [ 65 ] ; printf ( " LP_tradecommand selector.%d in mempool %s vini.%d " , selector , bits256_str ( str , spendtxid ) , spendvini ) ;
return ( - 1 ) ;
}
if ( ( selector = LP_mempool_vinscan ( & spendtxid , & spendvini , qp - > destcoin , qp - > destaddr , qp - > desttxid , qp - > destvout , qp - > feetxid , qp - > feevout ) ) > = 0 )
if ( autxo ! = 0 & & ( selector = LP_mempool_vinscan ( & spendtxid , & spendvini , qp - > destcoin , qp - > destaddr , qp - > desttxid , qp - > destvout , qp - > feetxid , qp - > feevout ) ) > = 0 )
{
char str [ 65 ] ; printf ( " LP_tradecommand dest selector.%d in mempool %s vini.%d " , selector , bits256_str ( str , spendtxid ) , spendvini ) ;
return ( - 1 ) ;
@ -257,57 +276,83 @@ int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp)
return ( 0 ) ;
}
double LP_quote_validate ( struct LP_utxoinfo * * autxop , struct LP_utxoinfo * * butxop , struct LP_quoteinfo * qp , int32_t iambob )
double LP_quote_validate ( struct LP_utxoinfo * autxo , struct LP_utxoinfo * butxo , struct LP_quoteinfo * qp , int32_t iambob )
{
double qprice ; uint64_t txfee , desttxfee , srcvalue , srcvalue2 , destvalue , destvalue2 ;
* autxop = * butxop = 0 ;
if ( LP_iseligible ( & srcvalue , & srcvalue2 , 1 , qp - > srccoin , qp - > txid , qp - > vout , qp - > satoshis , qp - > txid2 , qp - > vout2 ) = = 0 )
double qprice = 0. ; uint64_t txfee , desttxfee , srcvalue = 0 , srcvalue2 = 0 , destvalue = 0 , destvalue2 = 0 ;
printf ( " quote %s %.8f -> %s %.8f \n " , qp - > srccoin , dstr ( qp - > satoshis ) , qp - > destcoin , dstr ( qp - > destsatoshis ) ) ;
if ( butxo ! = 0 )
{
printf ( " bob not eligible \n " ) ;
return ( - 2 ) ;
if ( LP_iseligible ( & srcvalue , & srcvalue2 , 1 , qp - > srccoin , qp - > txid , qp - > vout , qp - > satoshis , qp - > txid2 , qp - > vout2 ) = = 0 )
{
printf ( " bob not eligible %s \n " , jprint ( LP_quotejson ( qp ) , 1 ) ) ;
return ( - 2 ) ;
}
if ( bits256_cmp ( butxo - > deposit . txid , qp - > txid2 ) ! = 0 | | butxo - > deposit . vout ! = qp - > vout2 )
{
char str [ 65 ] , str2 [ 65 ] ; printf ( " %s != %s v%d != %d \n " , bits256_str ( str , butxo - > deposit . txid ) , bits256_str ( str2 , qp - > txid2 ) , butxo - > deposit . vout , qp - > vout2 ) ;
return ( - 6 ) ;
}
if ( strcmp ( butxo - > coinaddr , qp - > coinaddr ) ! = 0 )
{
printf ( " (%s) != (%s) \n " , butxo - > coinaddr , qp - > coinaddr ) ;
return ( - 7 ) ;
}
}
if ( LP_iseligible ( & destvalue , & destvalue2 , 0 , qp - > destcoin , qp - > desttxid , qp - > destvout , qp - > destsatoshis , qp - > feetxid , qp - > feevout ) = = 0 )
if ( autxo ! = 0 & & LP_iseligible ( & destvalue , & destvalue2 , 0 , qp - > destcoin , qp - > desttxid , qp - > destvout , qp - > destsatoshis , qp - > feetxid , qp - > feevout ) = = 0 )
{
char str [ 65 ] ; printf ( " alice not eligible (%.8f %.8f) %s/v%d \n " , dstr ( destvalue ) , dstr ( destvalue2 ) , bits256_str ( str , qp - > feetxid ) , qp - > feevout ) ;
return ( - 3 ) ;
}
if ( LP_quote_checkmempool ( qp ) < 0 )
if ( LP_quote_checkmempool ( qp , autxo , butxo ) < 0 )
return ( - 4 ) ;
if ( ( * butxop = LP_utxofind ( 1 , qp - > txid , qp - > vout ) ) = = 0 )
return ( - 5 ) ;
if ( bits256_cmp ( ( * butxop ) - > deposit . txid , qp - > txid2 ) ! = 0 | | ( * butxop ) - > deposit . vout ! = qp - > vout2 )
return ( - 6 ) ;
if ( strcmp ( ( * butxop ) - > coinaddr , qp - > coinaddr ) ! = 0 )
return ( - 7 ) ;
if ( iambob = = 0 )
{
if ( ( * autxop = LP_utxofind ( 0 , qp - > desttxid , qp - > destvout ) ) = = 0 )
return ( - 8 ) ;
if ( bits256_cmp ( ( * autxop ) - > fee . txid , qp - > feetxid ) ! = 0 | | ( * autxop ) - > fee . vout ! = qp - > feevout )
//if ( iambob != 0 && (*butxop= LP_utxofind(1,qp->txid,qp->vout)) == 0 )
// return(-5);
if ( iambob = = 0 & & autxo ! = 0 )
{
//if ( (*autxop= LP_utxofind(0,qp->desttxid,qp->destvout)) == 0 )
// return(-8);
if ( bits256_cmp ( autxo - > fee . txid , qp - > feetxid ) ! = 0 | | autxo - > fee . vout ! = qp - > feevout )
return ( - 9 ) ;
if ( strcmp ( ( * autxop ) - > coinaddr , qp - > destaddr ) ! = 0 )
if ( strcmp ( autxo - > coinaddr , qp - > destaddr ) ! = 0 )
return ( - 10 ) ;
}
if ( destvalue < qp - > desttxfee + qp - > destsatoshis | | srcvalue < qp - > txfee + qp - > satoshis )
if ( autxo ! = 0 & & destvalue < qp - > desttxfee + qp - > destsatoshis )
{
printf ( " destvalue %.8f srcvalue %.8f, destsatoshis %.8f or satoshis %.8f is too small txfees %.8f %.8f? \n " , dstr ( destvalue ) , dstr ( srcvalue ) , dstr ( qp - > destsatoshis ) , dstr ( qp - > satoshis ) , dstr ( qp - > desttxfee ) , dstr ( qp - > txfee ) ) ;
printf ( " destvalue %.8f destsatoshis %.8f is too small txfee %.8f? \n " , dstr ( destvalue ) , dstr ( qp - > destsatoshis ) , dstr ( qp - > desttxfee ) ) ;
return ( - 11 ) ;
}
qprice = ( ( double ) qp - > destsatoshis / qp - > satoshis ) ;
if ( qp - > satoshis < ( srcvalue / LP_MINVOL ) | | srcvalue < qp - > txfee * LP_MINSIZE_TXFEEMULT )
if ( butxo ! = 0 & & srcvalue < qp - > txfee + qp - > satoshis )
{
printf ( " utxo payment %.8f is less than %f covered by Q %.8f or <10x txfee %.8f \n " , dstr ( srcvalue ) , 1. / LP_MINVOL , dstr ( qp - > satoshis ) , dstr ( qp - > txfee ) ) ;
return ( - 12 ) ;
}
if ( qp - > destsatoshis < ( destvalue / LP_MINCLIENTVOL ) | | destvalue < qp - > desttxfee * LP_MINSIZE_TXFEEMULT )
{
printf ( " destsatoshis %.8f is less than %f of value %.8f or < 10x txfee %.8f \n " , dstr ( qp - > destsatoshis ) , 1. / LP_MINCLIENTVOL , dstr ( destvalue ) , dstr ( qp - > desttxfee ) ) ;
return ( - 13 ) ;
printf ( " srcvalue %.8f [%.8f] satoshis %.8f is too small txfee %.8f? \n " , dstr ( srcvalue ) , dstr ( srcvalue ) - dstr ( qp - > txfee + qp - > satoshis ) , dstr ( qp - > satoshis ) , dstr ( qp - > txfee ) ) ;
return ( - 33 ) ;
}
if ( qp - > satoshis ! = 0 )
qprice = ( ( double ) qp - > destsatoshis / ( qp - > satoshis - qp - > txfee ) ) ;
LP_txfees ( & txfee , & desttxfee , qp - > srccoin , qp - > destcoin ) ;
if ( txfee < qp - > txfee )
txfee = qp - > txfee ;
if ( desttxfee < qp - > desttxfee )
desttxfee = qp - > desttxfee ;
printf ( " qprice %.8f <- %.8f/%.8f txfees.(%.8f %.8f) vs (%.8f %.8f) \n " , qprice , dstr ( qp - > destsatoshis ) , dstr ( qp - > satoshis ) , dstr ( qp - > txfee ) , dstr ( qp - > desttxfee ) , dstr ( txfee ) , dstr ( desttxfee ) ) ;
if ( qp - > txfee < LP_REQUIRED_TXFEE * txfee | | qp - > desttxfee < LP_REQUIRED_TXFEE * desttxfee )
return ( - 14 ) ;
if ( butxo ! = 0 )
{
//qprice 2259.01692494 <- 10.34279604/0.00457845 txfees.(0.00042631 0.00010000) vs (0.00042791 0.00010000)
if ( qp - > satoshis < ( srcvalue / LP_MINVOL ) | | srcvalue < qp - > txfee * LP_MINSIZE_TXFEEMULT )
{
printf ( " utxo payment %.8f is less than %f covered by Q %.8f or <10x txfee %.8f \n " , dstr ( srcvalue ) , 1. / LP_MINVOL , dstr ( qp - > satoshis ) , dstr ( qp - > txfee ) ) ;
return ( - 12 ) ;
}
}
if ( autxo ! = 0 )
{
if ( qp - > destsatoshis < ( destvalue / LP_MINCLIENTVOL ) | | destvalue < qp - > desttxfee * LP_MINSIZE_TXFEEMULT )
{
printf ( " destsatoshis %.8f is less than %f of value %.8f or < 10x txfee %.8f \n " , dstr ( qp - > destsatoshis ) , 1. / LP_MINCLIENTVOL , dstr ( destvalue ) , dstr ( qp - > desttxfee ) ) ;
return ( - 13 ) ;
}
}
return ( qprice ) ;
}
@ -325,7 +370,7 @@ int32_t LP_arrayfind(cJSON *array,bits256 txid,int32_t vout)
double LP_query ( void * ctx , char * myipaddr , int32_t mypubsock , char * method , struct LP_quoteinfo * qp )
{
cJSON * reqjson ; char * msg ; int32_t i , flag = 0 ; double price = 0. ; struct LP_utxoinfo * utxo ;
cJSON * reqjson ; bits256 zero ; char * msg ; int32_t i , flag = 0 ; double price = 0. ; struct LP_utxoinfo * utxo ;
if ( strcmp ( method , " request " ) = = 0 )
{
if ( ( utxo = LP_utxofind ( 0 , qp - > desttxid , qp - > destvout ) ) ! = 0 & & LP_ismine ( utxo ) > 0 & & LP_isavailable ( utxo ) > 0 )
@ -343,7 +388,12 @@ double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct L
jaddstr ( reqjson , " method " , method ) ;
msg = jprint ( reqjson , 1 ) ;
printf ( " QUERY.(%s) \n " , msg ) ;
LP_broadcast_message ( LP_mypubsock , qp - > srccoin , qp - > destcoin , qp - > srchash , msg ) ;
memset ( & zero , 0 , sizeof ( zero ) ) ;
if ( 1 & & strcmp ( method , " request " ) = = 0 )
{
sleep ( 3 ) ;
LP_broadcast_message ( LP_mypubsock , qp - > srccoin , qp - > destcoin , zero , msg ) ;
} else LP_broadcast_message ( LP_mypubsock , qp - > srccoin , qp - > destcoin , qp - > srchash , msg ) ;
for ( i = 0 ; i < 30 ; i + + )
{
if ( ( price = LP_pricecache ( qp , qp - > srccoin , qp - > destcoin , qp - > txid , qp - > vout ) ) > SMALLVAL )
@ -354,7 +404,7 @@ double LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct L
break ;
}
}
usleep ( 10 0000) ;
usleep ( 25 0000) ;
}
return ( price ) ;
}
@ -391,6 +441,107 @@ int32_t LP_nanobind(void *ctx,char *pairstr)
return ( pairsock ) ;
}
int32_t LP_nearest_utxovalue ( struct LP_address_utxo * * utxos , int32_t n , uint64_t targetval )
{
int32_t i , mini = - 1 ; int64_t dist ; uint64_t mindist = ( 1LL < < 60 ) ;
for ( i = 0 ; i < n ; i + + )
{
if ( utxos [ i ] ! = 0 )
{
dist = ( utxos [ i ] - > U . value - targetval ) ;
if ( dist > = 0 & & dist < mindist )
{
printf ( " (%.8f %.8f %.8f).%d " , dstr ( utxos [ i ] - > U . value ) , dstr ( dist ) , dstr ( mindist ) , mini ) ;
mini = i ;
mindist = dist ;
}
}
}
return ( mini ) ;
}
uint64_t LP_basesatoshis ( double relvolume , double price , uint64_t txfee , uint64_t desttxfee )
{
printf ( " basesatoshis %.8f (rel %.8f / price %.8f) \n " , dstr ( SATOSHIDEN * ( ( relvolume ) / price ) + 2 * txfee ) , relvolume , price ) ;
if ( relvolume > dstr ( desttxfee ) & & price > SMALLVAL )
return ( SATOSHIDEN * ( relvolume / price ) + 2 * txfee ) ;
else return ( 0 ) ;
}
struct LP_utxoinfo * LP_address_utxopair ( int32_t iambob , struct LP_address_utxo * * utxos , int32_t max , struct iguana_info * coin , char * coinaddr , uint64_t txfee , double relvolume , double price , uint64_t desttxfee )
{
struct LP_address * ap ; uint64_t targetval , targetval2 ; int32_t m , mini ; struct LP_address_utxo * up , * up2 ; struct LP_utxoinfo * utxo = 0 ;
if ( coin ! = 0 & & ( ap = LP_addressfind ( coin , coinaddr ) ) ! = 0 )
{
if ( ( m = LP_address_utxo_ptrs ( iambob , utxos , max , ap ) ) > 1 )
{
targetval = LP_basesatoshis ( relvolume , price , txfee , desttxfee ) ;
if ( 1 )
{
int32_t i ;
for ( i = 0 ; i < m ; i + + )
printf ( " %.8f " , dstr ( utxos [ i ] - > U . value ) ) ;
printf ( " targetval %.8f vol %.8f price %.8f txfee %.8f %s \n " , dstr ( targetval ) , relvolume , price , dstr ( txfee ) , coinaddr ) ;
}
mini = - 1 ;
if ( targetval ! = 0 & & ( mini = LP_nearest_utxovalue ( utxos , m , targetval ) ) > = 0 & & ( double ) utxos [ mini ] - > U . value / targetval < LP_MINVOL - 1 )
{
up = utxos [ mini ] ;
utxos [ mini ] = 0 ;
targetval2 = ( up - > U . value / 8 ) * 9 + 2 * txfee ;
if ( ( mini = LP_nearest_utxovalue ( utxos , m , targetval2 ) ) > = 0 )
{
if ( up ! = 0 & & ( up2 = utxos [ mini ] ) ! = 0 )
{
if ( ( utxo = LP_utxoadd ( 1 , coin - > symbol , up - > U . txid , up - > U . vout , up - > U . value , up2 - > U . txid , up2 - > U . vout , up2 - > U . value , coinaddr , ap - > pubkey , G . gui , 0 ) ) ! = 0 )
{
utxo - > S . satoshis = targetval ;
char str [ 65 ] , str2 [ 65 ] ; printf ( " butxo.%p targetval %.8f, found val %.8f %s | targetval2 %.8f val2 %.8f %s \n " , utxo , dstr ( targetval ) , dstr ( up - > U . value ) , bits256_str ( str , utxo - > payment . txid ) , dstr ( targetval2 ) , dstr ( up2 - > U . value ) , bits256_str ( str2 , utxo - > deposit . txid ) ) ;
return ( utxo ) ;
}
}
} else printf ( " cant find targetval2 %.8f \n " , dstr ( targetval2 ) ) ;
} else if ( targetval ! = 0 & & mini > = 0 )
printf ( " targetval %.8f mini.%d ratio %.8f \n " , dstr ( targetval ) , mini , ( double ) utxos [ mini ] - > U . value / targetval ) ;
} else printf ( " no utxos pass LP_address_utxo_ptrs filter \n " ) ;
} else printf ( " couldnt find %s %s \n " , coin - > symbol , coinaddr ) ;
return ( 0 ) ;
}
void LP_abutxo_set ( struct LP_utxoinfo * autxo , struct LP_utxoinfo * butxo , struct LP_quoteinfo * qp )
{
if ( butxo ! = 0 )
{
memset ( butxo , 0 , sizeof ( * butxo ) ) ;
butxo - > pubkey = qp - > srchash ;
safecopy ( butxo - > coin , qp - > srccoin , sizeof ( butxo - > coin ) ) ;
safecopy ( butxo - > coinaddr , qp - > coinaddr , sizeof ( butxo - > coinaddr ) ) ;
butxo - > payment . txid = qp - > txid ;
butxo - > payment . vout = qp - > vout ;
//butxo->payment.value = qp->value;
butxo - > iambob = 1 ;
butxo - > deposit . txid = qp - > txid2 ;
butxo - > deposit . vout = qp - > vout2 ;
//butxo->deposit.value = up2->U.value;
butxo - > S . satoshis = qp - > satoshis ;
}
if ( autxo ! = 0 )
{
memset ( autxo , 0 , sizeof ( * autxo ) ) ;
autxo - > pubkey = qp - > desthash ;
safecopy ( autxo - > coin , qp - > destcoin , sizeof ( autxo - > coin ) ) ;
safecopy ( autxo - > coinaddr , qp - > destaddr , sizeof ( autxo - > coinaddr ) ) ;
autxo - > payment . txid = qp - > desttxid ;
autxo - > payment . vout = qp - > destvout ;
//autxo->payment.value = qp->value;
autxo - > iambob = 0 ;
autxo - > fee . txid = qp - > feetxid ;
autxo - > fee . vout = qp - > feevout ;
//autxo->deposit.value = up2->U.value;
autxo - > S . satoshis = qp - > destsatoshis ;
}
}
int32_t LP_connectstartbob ( void * ctx , int32_t pubsock , struct LP_utxoinfo * utxo , cJSON * argjson , char * base , char * rel , double price , struct LP_quoteinfo * qp )
{
char pairstr [ 512 ] , * msg ; cJSON * retjson ; bits256 privkey ; int32_t pair = - 1 , retval = - 1 , DEXselector = 0 ; struct basilisk_swap * swap ; struct iguana_info * coin ;
@ -402,12 +553,14 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ
return ( - 1 ) ;
}
privkey = LP_privkey ( utxo - > coinaddr , coin - > taddr ) ;
if ( bits256_nonz ( privkey ) ! = 0 & & qp - > quotetime > = qp - > timestamp - 3 & & qp - > quotetime < = utxo - > T . swappending & & bits256_cmp ( LP_mypub25519 , qp - > srchash ) = = 0 )
if ( bits256_nonz ( privkey ) ! = 0 & & bits256_cmp ( G . LP_mypub25519 , qp - > srchash ) = = 0 ) //qp->quotetime >= qp->timestamp-3 && qp->quotetime <= utxo->T.swappending &&
{
if ( ( pair = LP_nanobind ( ctx , pairstr ) ) > = 0 )
{
LP_requestinit ( & qp - > R , qp - > srchash , qp - > desthash , base , qp - > satoshis - qp - > txfee , rel , qp - > destsatoshis - qp - > desttxfee , qp - > timestamp , qp - > quotetime , DEXselector ) ;
printf ( " call swapinit \n " ) ;
swap = LP_swapinit ( 1 , 0 , privkey , & qp - > R , qp ) ;
printf ( " swapinit.%p \n " , swap ) ;
swap - > N . pair = pair ;
utxo - > S . swap = swap ;
swap - > utxo = utxo ;
@ -427,7 +580,7 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ
}
else
{
printf ( " dest %.8f vs required %.8f (%d %d %d %d %d) \n " , dstr ( qp - > destsatoshis ) , dstr ( price * ( utxo - > S . satoshis - qp - > txfee ) ) , bits256_nonz ( privkey ) ! = 0 , qp - > timestamp = = utxo - > T . swappending - LP_RESERVETIME , qp - > quotetime > = qp - > timestamp - 3 , qp - > quotetime < utxo - > T . swappending , bits256_cmp ( LP_mypub25519 , qp - > srchash ) = = 0 ) ;
printf ( " dest %.8f vs required %.8f (%d %d %d %d %d) \n " , dstr ( qp - > destsatoshis ) , dstr ( price * ( utxo - > S . satoshis - qp - > txfee ) ) , bits256_nonz ( privkey ) ! = 0 , qp - > timestamp = = utxo - > T . swappending - LP_RESERVETIME , qp - > quotetime > = qp - > timestamp - 3 , qp - > quotetime < utxo - > T . swappending , bits256_cmp ( G . LP_mypub25519 , qp - > srchash ) = = 0 ) ;
}
if ( retval < 0 )
{
@ -435,21 +588,57 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,struct LP_utxoinfo *utxo,cJ
nn_close ( pair ) ;
LP_availableset ( utxo ) ;
} else LP_unavailableset ( utxo , utxo - > S . otherpubkey ) ;
//LP_butxo_swapfields(utxo);
return ( retval ) ;
}
char * LP_connectedalice ( cJSON * argjson ) // alice
{
cJSON * retjson ; double bid , ask , price , qprice ; int32_t pairsock = - 1 ; char * pairstr ; int32_t DEXselector = 0 ; struct LP_utxoinfo * autxo , * butxo ; struct LP_quoteinfo Q ; struct basilisk_swap * swap ; struct iguana_info * coin ;
cJSON * retjson ; double bid , ask , price , qprice ; int32_t pairsock = - 1 ; char * pairstr ; int32_t DEXselector = 0 ; struct LP_utxoinfo * autxo , B , * butxo ; struct LP_quoteinfo Q ; struct basilisk_swap * swap ; struct iguana_info * coin ; //uint64_t value,value2;
if ( LP_quoteparse ( & Q , argjson ) < 0 )
clonestr ( " { \" error \" : \" cant parse quote \" } " ) ;
if ( bits256_cmp ( Q . desthash , LP_mypub25519 ) ! = 0 )
if ( bits256_cmp ( Q . desthash , G . LP_mypub25519 ) ! = 0 )
return ( clonestr ( " { \" result \" , \" update stats \" } " ) ) ;
printf ( " CONNECTED.(%s) \n " , jprint ( argjson , 0 ) ) ;
if ( ( qprice = LP_quote_validate ( & autxo , & butxo , & Q , 0 ) ) < = SMALLVAL )
printf ( " CONNECTED.(%s) numpending.%d \n " , jprint ( argjson , 0 ) , G . LP_pendingswaps ) ;
/*if ( G.LP_pendingswaps > 0 )
{
printf ( " swap already pending \n " ) ;
return ( clonestr ( " { \" error \" : \" swap already pending \" } " ) ) ;
} */
if ( ( autxo = LP_utxopairfind ( 0 , Q . desttxid , Q . destvout , Q . feetxid , Q . feevout ) ) = = 0 )
{
printf ( " cant find autxo \n " ) ;
return ( clonestr ( " { \" error \" : \" cant find autxo \" } " ) ) ;
}
if ( autxo - > S . swap ! = 0 )
return ( clonestr ( " { \" error \" : \" ignore duplicate swap \" } " ) ) ;
butxo = & B ;
memset ( butxo , 0 , sizeof ( * butxo ) ) ;
LP_abutxo_set ( 0 , butxo , & Q ) ;
/*if ( (butxo= LP_utxopairfind(1,Q.txid,Q.vout,Q.txid2,Q.vout2)) == 0 )
{
value = LP_txvalue ( Q . coinaddr , Q . srccoin , Q . txid , Q . vout ) ;
value2 = LP_txvalue ( Q . coinaddr , Q . srccoin , Q . txid2 , Q . vout2 ) ;
if ( value = = 0 | | value2 = = 0 )
{
printf ( " zero value %.8f or value2 %.8f \n " , dstr ( value ) , dstr ( value2 ) ) ;
return ( clonestr ( " { \" error \" : \" spent txid or txid2 for bob? \" } " ) ) ;
}
if ( ( butxo = LP_utxoadd ( 1 , Q . srccoin , Q . txid , Q . vout , value , Q . txid2 , Q . vout2 , value2 , Q . coinaddr , Q . srchash , LP_gui , 0 ) ) = = 0 )
{
printf ( " cant find or create butxo \n " ) ;
return ( clonestr ( " { \" error \" : \" cant find or create butxo \" } " ) ) ;
}
if ( value < Q . satoshis )
{
printf ( " butxo value %.8f less satoshis %.8f \n " , dstr ( value ) , dstr ( Q . satoshis ) ) ;
return ( clonestr ( " { \" error \" : \" butxo value less than satoshis \" } " ) ) ;
}
} */
if ( ( qprice = LP_quote_validate ( autxo , butxo , & Q , 0 ) ) < = SMALLVAL )
{
LP_availableset ( autxo ) ;
LP_pendingswaps - - ;
//G.LP_pendingswaps--;
printf ( " quote validate error %.0f \n " , qprice ) ;
return ( clonestr ( " { \" error \" : \" quote validation error \" } " ) ) ;
}
@ -457,22 +646,14 @@ char *LP_connectedalice(cJSON *argjson) // alice
{
printf ( " this node has no price for %s/%s (%.8f %.8f) \n " , Q . destcoin , Q . srccoin , bid , ask ) ;
LP_availableset ( autxo ) ;
LP_pendingswaps - - ;
//G.LP_pendingswaps--;
return ( clonestr ( " { \" error \" : \" no price set \" } " ) ) ;
}
printf ( " %s/%s bid %.8f ask %.8f \n " , Q . srccoin , Q . destcoin , bid , ask ) ;
//if ( (price= ask) == 0. )
price = bid ;
/*if ( SATOSHIDEN*qprice > (SATOSHIDEN * price) * 1.001 + 10 )
{
printf ( " qprice %.8f too big vs %.8f \n " , qprice , price ) ;
LP_availableset ( autxo ) ;
LP_pendingswaps - - ;
return ( clonestr ( " { \" error \" : \" quote price too expensive \" } " ) ) ;
} */
printf ( " %s/%s bid %.8f ask %.8f values %.8f %.8f \n " , Q . srccoin , Q . destcoin , bid , ask , dstr ( butxo - > payment . value ) , dstr ( butxo - > deposit . value ) ) ;
price = bid ;
if ( ( coin = LP_coinfind ( Q . destcoin ) ) = = 0 )
{
LP_pendingswaps - - ;
//G.LP_pendingswaps--;
return ( clonestr ( " { \" error \" : \" cant get alicecoin \" } " ) ) ;
}
Q . privkey = LP_privkey ( Q . destaddr , coin - > taddr ) ;
@ -503,7 +684,7 @@ char *LP_connectedalice(cJSON *argjson) // alice
printf ( " connected result.(%s) \n " , jprint ( retjson , 0 ) ) ;
if ( jobj ( retjson , " error " ) ! = 0 )
LP_availableset ( autxo ) ;
else LP_pendingswaps + + ;
else G . LP_pendingswaps + + ;
return ( jprint ( retjson , 1 ) ) ;
}
else
@ -514,22 +695,104 @@ char *LP_connectedalice(cJSON *argjson) // alice
}
}
int32_t LP_listunspent_both ( char * symbol , char * coinaddr )
{
int32_t i , v , height , n = 0 ; uint64_t value ; bits256 txid ; char buf [ 512 ] ; cJSON * array , * item ; struct iguana_info * coin = LP_coinfind ( symbol ) ;
if ( coin ! = 0 & & coin - > inactive = = 0 )
{
if ( coin - > electrum ! = 0 | | LP_address_ismine ( symbol , coinaddr ) < = 0 )
{
//printf("issue path electrum.%p\n",coin->electrum);
//if ( coin->electrum != 0 && (array= electrum_address_gethistory(symbol,coin->electrum,&array,coinaddr)) != 0 )
// free_json(array);
n = LP_listunspent_issue ( symbol , coinaddr ) ;
}
else
{
//printf("my coin electrum.%p\n",coin->electrum);
sprintf ( buf , " [1, 99999999, [ \" %s \" ]] " , coinaddr ) ;
if ( ( array = bitcoin_json ( coin , " listunspent " , buf ) ) ! = 0 )
{
if ( ( n = cJSON_GetArraySize ( array ) ) > 0 )
{
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
txid = jbits256 ( item , " txid " ) ;
v = jint ( item , " vout " ) ;
value = LP_value_extract ( item , 0 ) ;
height = LP_txheight ( coin , txid ) ;
//char str[65]; printf("LP_listunspent_both: %s/v%d ht.%d %.8f\n",bits256_str(str,txid),v,height,dstr(value));
LP_address_utxoadd ( coin , coinaddr , txid , v , value , height , - 1 ) ;
}
}
}
}
} //else printf("%s coin.%p inactive.%d\n",symbol,coin,coin!=0?coin->inactive:-1);
return ( n ) ;
}
int32_t LP_tradecommand ( void * ctx , char * myipaddr , int32_t pubsock , cJSON * argjson , uint8_t * data , int32_t datalen )
{
char * method , * msg ; cJSON * retjson ; double qprice , price , bid , ask ; struct LP_utxoinfo * autxo , * butxo ; int32_t retval = - 1 ; struct LP_quoteinfo Q ;
char * method , * msg ; 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 , max = ( int32_t ) ( sizeof ( utxos ) / sizeof ( * utxos ) ) ;
if ( ( method = jstr ( argjson , " method " ) ) ! = 0 & & ( strcmp ( method , " request " ) = = 0 | | strcmp ( method , " connect " ) = = 0 ) )
{
printf ( " TRADECOMMAND.(%s) \n " , jprint ( argjson , 0 ) ) ;
printf ( " LP_tradecommand: check received %s \n " , method ) ;
retval = 1 ;
if ( LP_quoteparse ( & Q , argjson ) = = 0 & & bits256_cmp ( LP_mypub25519 , Q . srchash ) = = 0 )
if ( LP_quoteparse ( & Q , argjson ) = = 0 & & bits256_cmp ( G . LP_mypub25519 , Q . srchash ) = = 0 & & bits256_cmp ( G . LP_mypub25519 , Q . desthash ) ! = 0 )
{
if ( ( price = LP_myprice ( & bid , & ask , Q . srccoin , Q . destcoin ) ) < = SMALLVAL | | ask < = SMALLVAL )
if ( ( coin = LP_coinfind ( Q . srccoin ) ) = = 0 | | ( price = LP_myprice ( & bid , & ask , Q . srccoin , Q . destcoin ) ) < = SMALLVAL | | ask < = SMALLVAL )
{
printf ( " this node has no price for %s/%s \n " , Q . srccoin , Q . destcoin ) ;
return ( - 3 ) ;
}
price = ask ;
if ( ( qprice = LP_quote_validate ( & autxo , & butxo , & Q , 1 ) ) < = SMALLVAL )
autxo = & A ;
butxo = & B ;
memset ( autxo , 0 , sizeof ( * autxo ) ) ;
memset ( butxo , 0 , sizeof ( * butxo ) ) ;
LP_abutxo_set ( autxo , butxo , & Q ) ;
if ( ( butxo = LP_utxopairfind ( 1 , Q . txid , Q . vout , Q . txid2 , Q . vout2 ) ) = = 0 )
butxo = & B ;
//LP_butxo_swapfields(butxo);
if ( strcmp ( method , " request " ) = = 0 )
{
char str [ 65 ] , str2 [ 65 ] ;
if ( LP_allocated ( butxo - > payment . txid , butxo - > payment . vout ) ! = 0 | | LP_allocated ( butxo - > deposit . txid , butxo - > deposit . vout ) ! = 0 | | ( qprice = LP_quote_validate ( autxo , butxo , & Q , 1 ) ) < = SMALLVAL )
{
printf ( " butxo.%p replace 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 ) ;
if ( ( butxo = LP_address_utxopair ( 1 , utxos , max , LP_coinfind ( Q . srccoin ) , Q . coinaddr , Q . txfee , dstr ( Q . destsatoshis ) , price , Q . desttxfee ) ) ! = 0 )
{
Q . txid = butxo - > payment . txid ;
Q . vout = butxo - > payment . vout ;
Q . txid2 = butxo - > deposit . txid ;
Q . vout2 = butxo - > deposit . vout ;
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 printf ( " cant find utxopair \n " ) ;
//LP_abutxo_set(0,butxo,&Q);
//LP_butxo_swapfields(butxo);
}
else
{
printf ( " other path %p %p %.8f \n " , LP_allocated ( butxo - > payment . txid , butxo - > payment . vout ) , LP_allocated ( butxo - > deposit . txid , butxo - > deposit . vout ) , LP_quote_validate ( autxo , butxo , & Q , 1 ) ) ;
}
}
if ( butxo = = 0 | | butxo = = & B )
butxo = LP_utxopairfind ( 1 , Q . txid , Q . vout , Q . txid2 , Q . vout2 ) ;
if ( butxo = = 0 )
{
value = LP_txvalue ( Q . coinaddr , Q . srccoin , Q . txid , Q . vout ) ;
value2 = LP_txvalue ( Q . coinaddr , Q . srccoin , Q . txid2 , Q . vout2 ) ;
butxo = LP_utxoadd ( 1 , Q . srccoin , Q . txid , Q . vout , value , Q . txid2 , Q . vout2 , value2 , Q . coinaddr , Q . srchash , LP_gui , 0 ) ;
}
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 ) ) ;
if ( butxo = = 0 | | bits256_nonz ( butxo - > payment . txid ) = = 0 | | bits256_nonz ( butxo - > deposit . txid ) = = 0 | | butxo - > payment . vout < 0 | | butxo - > deposit . vout < 0 )
{
char str [ 65 ] , str2 [ 65 ] ; printf ( " couldnt find bob utxos for autxo %s/v%d %s/v%d %.8f -> %.8f \n " , bits256_str ( str , Q . txid ) , Q . vout , bits256_str ( str2 , Q . txid2 ) , Q . vout2 , dstr ( Q . satoshis ) , dstr ( Q . destsatoshis ) ) ;
return ( 1 ) ;
}
if ( ( qprice = LP_quote_validate ( autxo , butxo , & Q , 1 ) ) < = SMALLVAL )
{
printf ( " quote validate error %.0f \n " , qprice ) ;
return ( - 4 ) ;
@ -555,148 +818,38 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
jaddbits256 ( retjson , " pubkey " , butxo - > S . otherpubkey ) ;
jaddstr ( retjson , " method " , " reserved " ) ;
msg = jprint ( retjson , 1 ) ;
printf ( " set swappending.%u accept qprice %.8f, min %.8f \n (%s) " , butxo - > T . swappending , qprice , price , msg ) ;
LP_broadcast_message ( pubsock , Q . srccoin , Q . destcoin , butxo - > S . otherpubkey , msg ) ;
butxo - > T . lasttime = ( uint32_t ) time ( NULL ) ;
printf ( " set swappending.%u accept qprice %.8f, min %.8f \n (%s) \n " , butxo - > T . swappending , qprice , price , msg ) ;
{
bits256 zero ; char * msg2 ;
memset ( & zero , 0 , sizeof ( zero ) ) ;
msg2 = clonestr ( msg ) ;
LP_broadcast_message ( pubsock , Q . srccoin , Q . destcoin , zero , msg ) ;
LP_broadcast_message ( pubsock , Q . srccoin , Q . destcoin , butxo - > S . otherpubkey , msg2 ) ;
//LP_butxo_swapfields_set(butxo);
printf ( " return after RESERVED \n " ) ;
return ( 2 ) ;
}
} else printf ( " warning swappending.%u swap.%p \n " , butxo - > T . swappending , butxo - > S . swap ) ;
}
else if ( strcmp ( method , " connect " ) = = 0 ) // bob
{
retval = 4 ;
if ( butxo - > T . swappending ! = 0 & & butxo - > S . swap = = 0 )
if ( butxo - > S . swap = = 0 & & butxo - > T . swappending ! = 0 )
{
// validate SPV alice
LP_connectstartbob ( ctx , pubsock , butxo , argjson , Q . srccoin , Q . destcoin , qprice , & Q ) ;
//LP_butxo_swapfields_set(butxo);
return ( 3 ) ;
}
else printf ( " pend.%u swap %p when connect came in (%s) \ n " ,butxo->T.swappending,butxo->S.swap,jprint(argjson,0)) ;
}
//LP_butxo_swapfields_set(butxo);
}
}
return ( retval ) ;
}
struct LP_utxoinfo * LP_bestutxo ( double * ordermatchpricep , int64_t * bestsatoshisp , int64_t * bestdestsatoshisp , struct LP_utxoinfo * autxo , char * base , double maxprice , int32_t duration , uint64_t txfee , uint64_t desttxfee , uint64_t maxdestsatoshis )
{
int64_t satoshis , destsatoshis ; uint64_t val , val2 ; bits256 txid , pubkey ; char * obookstr ; cJSON * orderbook , * asks , * item ; struct LP_utxoinfo * butxo , * bestutxo = 0 ; int32_t i , n , j , vout , numasks ; double bestmetric = 0. , metric , vol , price , qprice , bestprice = 0. ; struct LP_pubkeyinfo * pubp ;
* ordermatchpricep = 0. ;
* bestsatoshisp = * bestdestsatoshisp = 0 ;
if ( duration < = 0 )
duration = LP_ORDERBOOK_DURATION ;
if ( maxprice < = 0. | | LP_priceinfofind ( base ) = = 0 )
return ( 0 ) ;
LP_txfees ( & txfee , & desttxfee , base , autxo - > coin ) ;
if ( ( obookstr = LP_orderbook ( base , autxo - > coin , duration ) ) ! = 0 )
{
if ( ( orderbook = cJSON_Parse ( obookstr ) ) ! = 0 )
{
if ( ( asks = jarray ( & numasks , orderbook , " asks " ) ) ! = 0 )
{
for ( i = 0 ; i < numasks ; i + + )
{
item = jitem ( asks , i ) ;
price = jdouble ( item , " price " ) ;
if ( LP_pricevalid ( price ) > 0 & & price < = maxprice )
{
//price *= 1.0001;
//if ( price > maxprice )
// price = maxprice;
pubkey = jbits256 ( item , " pubkey " ) ;
if ( bits256_cmp ( pubkey , LP_mypub25519 ) ! = 0 & & ( pubp = LP_pubkeyadd ( pubkey ) ) ! = 0 & & pubp - > numerrors < LP_MAXPUBKEY_ERRORS )
{
if ( bestprice = = 0. ) // assumes price ordered asks
bestprice = price ;
//printf("item.[%d] %s\n",i,jprint(item,0));
txid = jbits256 ( item , " txid " ) ;
vout = jint ( item , " vout " ) ;
vol = jdouble ( item , " volume " ) ;
metric = price / bestprice ;
if ( ( butxo = LP_utxofind ( 1 , txid , vout ) ) ! = 0 & & ( long long ) ( vol * SATOSHIDEN ) = = butxo - > S . satoshis & & LP_isavailable ( butxo ) > 0 & & LP_ismine ( butxo ) = = 0 & & butxo - > T . bestflag = = 0 )
{
if ( LP_iseligible ( & val , & val2 , butxo - > iambob , butxo - > coin , butxo - > payment . txid , butxo - > payment . vout , butxo - > S . satoshis , butxo - > deposit . txid , butxo - > deposit . vout ) > 0 )
{
destsatoshis = ( ( butxo - > S . satoshis - txfee ) * price ) ;
satoshis = ( destsatoshis / price + 0.49 ) - txfee ;
if ( satoshis < = 0 )
continue ;
qprice = ( double ) destsatoshis / satoshis ;
n = ( int32_t ) ( ( double ) destsatoshis / desttxfee ) ;
if ( n < 10 )
n = 10 ;
else n = 3 ;
for ( j = 0 ; j < n ; j + + )
{
if ( ( qprice = LP_qprice_calc ( & destsatoshis , & satoshis , ( price * ( 100. + j ) ) / 100. , butxo - > S . satoshis , txfee , autxo - > payment . value , maxdestsatoshis , desttxfee ) ) > price + SMALLVAL )
break ;
}
//printf("j.%d/%d qprice %.8f vs price %.8f best.(%.8f %.8f)\n",j,n,qprice,price,dstr(satoshis),dstr(destsatoshis));
if ( metric < 1.2 & & destsatoshis > desttxfee & & destsatoshis - desttxfee > ( autxo - > payment . value / LP_MINCLIENTVOL ) & & satoshis - txfee > ( butxo - > S . satoshis / LP_MINVOL ) & & satoshis < = butxo - > payment . value - txfee )
{
printf ( " value %.8f price %.8f/%.8f best %.8f destsatoshis %.8f * metric %.8f -> (%f) \n " , dstr ( autxo - > payment . value ) , price , bestprice , bestmetric , dstr ( destsatoshis ) , metric , dstr ( destsatoshis ) * metric * metric * metric ) ;
metric = dstr ( destsatoshis ) * metric * metric * metric ;
if ( bestmetric = = 0. | | metric < bestmetric )
{
bestutxo = butxo ;
* ordermatchpricep = price ;
* bestdestsatoshisp = destsatoshis ;
* bestsatoshisp = satoshis ;
bestmetric = metric ;
printf ( " set best! \n " ) ;
}
} // else printf("skip.(%d %d %d %d %d) metric %f destsatoshis %.8f value %.8f destvalue %.8f txfees %.8f %.8f sats %.8f\n",metric < 1.2,destsatoshis > desttxfee,destsatoshis-desttxfee > (autxo->payment.value / LP_MINCLIENTVOL),satoshis-txfee > (butxo->S.satoshis / LP_MINVOL),satoshis < butxo->payment.value-txfee,metric,dstr(destsatoshis),dstr(butxo->S.satoshis),dstr(autxo->payment.value),dstr(txfee),dstr(desttxfee),dstr(satoshis));
}
else
{
printf ( " ineligible.(%.8f %.8f) \n " , price , dstr ( butxo - > S . satoshis ) ) ;
//if ( butxo->T.spentflag == 0 )
// butxo->T.spentflag = (uint32_t)time(NULL);
}
}
else
{
if ( butxo ! = 0 )
printf ( " %llu %llu %d %d %d: " , ( long long ) ( vol * SATOSHIDEN ) , ( long long ) butxo - > S . satoshis , vol * SATOSHIDEN = = butxo - > S . satoshis , LP_isavailable ( butxo ) > 0 , LP_ismine ( butxo ) = = 0 ) ;
printf ( " cant find butxo.%p or value mismatch %.8f != %.8f or bestflag.%d \n " , butxo , vol , butxo ! = 0 ? dstr ( butxo - > S . satoshis ) : 0 , butxo - > T . bestflag ) ;
}
} else printf ( " self trading or blacklisted peer \n " ) ;
}
else
{
if ( i = = 0 )
printf ( " maxprice %.8f vs %.8f \n " , maxprice , price ) ;
break ;
}
}
if ( bestutxo = = 0 )
{
int32_t numrestraints ;
for ( i = numrestraints = 0 ; i < numasks ; i + + )
{
item = jitem ( asks , i ) ;
pubkey = jbits256 ( item , " pubkey " ) ;
if ( bits256_cmp ( pubkey , LP_mypub25519 ) ! = 0 & & ( pubp = LP_pubkeyadd ( pubkey ) ) ! = 0 )
{
txid = jbits256 ( item , " txid " ) ;
vout = jint ( item , " vout " ) ;
if ( ( butxo = LP_utxofind ( 1 , txid , vout ) ) ! = 0 )
{
numrestraints + + ;
butxo - > T . bestflag = 0 ;
pubp - > numerrors = 0 ;
}
}
}
printf ( " no bob utxo found -> cleared %d restraints \n " , numrestraints ) ;
}
}
free_json ( orderbook ) ;
}
free ( obookstr ) ;
}
if ( bestutxo = = 0 | | * ordermatchpricep = = 0. | | * bestdestsatoshisp = = 0 )
return ( 0 ) ;
bestutxo - > T . bestflag = 1 ;
int32_t changed ;
LP_mypriceset ( & changed , autxo - > coin , base , 1. / * ordermatchpricep ) ;
return ( bestutxo ) ;
}
char * LP_bestfit ( char * rel , double relvolume )
{
struct LP_utxoinfo * autxo ;
@ -707,35 +860,14 @@ char *LP_bestfit(char *rel,double relvolume)
return ( jprint ( LP_utxojson ( autxo ) , 1 ) ) ;
}
char * LP_ordermatch ( char * base , int64_t txfee , double maxprice , double maxvolume , char * rel , bits256 txid , int32_t vout , bits256 feetxid , int32_t feevout , int64_t desttxfee , int32_t duration )
{
struct LP_quoteinfo Q ; int64_t bestsatoshis = 0 , bestdestsatoshis = 0 ; double ordermatchprice = 0. ; struct LP_utxoinfo * autxo , * bestutxo ;
txfee = LP_txfeecalc ( LP_coinfind ( base ) , txfee ) ;
desttxfee = LP_txfeecalc ( LP_coinfind ( rel ) , desttxfee ) ;
if ( ( autxo = LP_utxopairfind ( 0 , txid , vout , feetxid , feevout ) ) = = 0 )
return ( clonestr ( " { \" error \" : \" cant find alice utxopair \" } " ) ) ;
if ( ( bestutxo = LP_bestutxo ( & ordermatchprice , & bestsatoshis , & bestdestsatoshis , autxo , base , maxprice , duration , txfee , desttxfee , SATOSHIDEN * maxvolume ) ) = = 0 | | ordermatchprice = = 0. | | bestdestsatoshis = = 0 )
return ( clonestr ( " { \" error \" : \" cant find ordermatch utxo \" } " ) ) ;
if ( LP_quoteinfoinit ( & Q , bestutxo , rel , ordermatchprice , bestsatoshis , bestdestsatoshis ) < 0 )
return ( clonestr ( " { \" error \" : \" cant set ordermatch quote \" } " ) ) ;
if ( LP_quotedestinfo ( & Q , autxo - > payment . txid , autxo - > payment . vout , autxo - > fee . txid , autxo - > fee . vout , LP_mypub25519 , autxo - > coinaddr ) < 0 )
return ( clonestr ( " { \" error \" : \" cant set ordermatch quote info \" } " ) ) ;
return ( jprint ( LP_quotejson ( & Q ) , 1 ) ) ;
}
char * LP_trade ( void * ctx , char * myipaddr , int32_t mypubsock , struct LP_quoteinfo * qp , double maxprice , int32_t timeout , int32_t duration )
{
struct LP_utxoinfo * bobutxo , * aliceutxo ; cJSON * bestitem = 0 ; int32_t DEXselector = 0 ; uint32_t expiration ; double price ; struct LP_pubkeyinfo * pubp ;
struct LP_utxoinfo * aliceutxo ; cJSON * bestitem = 0 ; int32_t DEXselector = 0 ; uint32_t expiration ; double price ; struct LP_pubkeyinfo * pubp ; struct basilisk_swap * swap ;
if ( ( aliceutxo = LP_utxopairfind ( 0 , qp - > desttxid , qp - > destvout , qp - > feetxid , qp - > feevout ) ) = = 0 )
{
char str [ 65 ] , str2 [ 65 ] ; printf ( " dest.(%s)/v%d fee.(%s)/v%d \n " , bits256_str ( str , qp - > desttxid ) , qp - > destvout , bits256_str ( str2 , qp - > feetxid ) , qp - > feevout ) ;
return ( clonestr ( " { \" error \" : \" cant find alice utxopair \" } " ) ) ;
}
if ( ( bobutxo = LP_utxopairfind ( 1 , qp - > txid , qp - > vout , qp - > txid2 , qp - > vout2 ) ) = = 0 )
return ( clonestr ( " { \" error \" : \" cant find bob utxopair \" } " ) ) ;
bobutxo - > T . bestflag = ( uint32_t ) time ( NULL ) ;
//if ( (retstr= LP_registerall(0)) != 0 )
// free(retstr);
price = LP_query ( ctx , myipaddr , mypubsock , " request " , qp ) ;
bestitem = LP_quotejson ( qp ) ;
if ( LP_pricevalid ( price ) > 0 )
@ -743,25 +875,29 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q
if ( price < = maxprice )
{
price = LP_query ( ctx , myipaddr , mypubsock , " connect " , qp ) ;
LP_requestinit ( & qp - > R , qp - > srchash , qp - > desthash , bobutxo - > coin , qp - > satoshis - qp - > txfee , qp - > destcoin , qp - > destsatoshis - qp - > desttxfee , qp - > timestamp , qp - > quotetime , DEXselector ) ;
LP_requestinit ( & qp - > R , qp - > srchash , qp - > desthash , qp - > src coin, qp - > satoshis - qp - > txfee , qp - > destcoin , qp - > destsatoshis - qp - > desttxfee , qp - > timestamp , qp - > quotetime , DEXselector ) ;
expiration = ( uint32_t ) time ( NULL ) + timeout ;
while ( time ( NULL ) < expiration )
{
if ( aliceutxo - > S . swap ! = 0 )
break ;
sleep ( 1 ) ;
sleep ( 3 ) ;
}
if ( aliceutxo - > S . swap = = 0 )
jaddnum ( bestitem , " quotedprice " , price ) ;
jaddnum ( bestitem , " maxprice " , maxprice ) ;
if ( ( swap = aliceutxo - > S . swap ) = = 0 )
{
if ( ( pubp = LP_pubkeyadd ( bobutxo - > pubkey ) ) ! = 0 )
if ( ( pubp = LP_pubkeyadd ( qp - > srchash ) ) ! = 0 )
pubp - > numerrors + + ;
jaddstr ( bestitem , " status " , " couldnt establish connection " ) ;
} else jaddstr ( bestitem , " status " , " connected " ) ;
jaddnum ( bestitem , " quotedprice " , price ) ;
jaddnum ( bestitem , " maxprice " , maxprice ) ;
jaddnum ( bestitem , " requestid " , qp - > R . requestid ) ;
jaddnum ( bestitem , " quoteid " , qp - > R . quoteid ) ;
printf ( " Alice r.%u qp->%u \n " , qp - > R . requestid , qp - > R . quoteid ) ;
}
else
{
jaddstr ( bestitem , " status " , " connected " ) ;
jaddnum ( bestitem , " requestid " , swap - > I . req . requestid ) ;
jaddnum ( bestitem , " quoteid " , swap - > I . req . quoteid ) ;
printf ( " Alice r.%u qp->%u \n " , swap - > I . req . requestid , swap - > I . req . quoteid ) ;
}
}
else
{
@ -772,6 +908,7 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q
}
else
{
printf ( " invalid price %.8f \n " , price ) ;
jaddnum ( bestitem , " maxprice " , maxprice ) ;
jaddstr ( bestitem , " status " , " no response to request " ) ;
}
@ -780,36 +917,120 @@ char *LP_trade(void *ctx,char *myipaddr,int32_t mypubsock,struct LP_quoteinfo *q
return ( jprint ( bestitem , 0 ) ) ;
}
char * LP_autotrade ( void * ctx , char * myipaddr , int32_t mypubsock , char * base , char * rel , double maxprice , double relvolume , int32_t timeout , int32_t duration )
struct LP_utxoinfo * LP_buyutxo ( double * ordermatchpricep , int64_t * bestsatoshisp , int64_t * bestdestsatoshisp , struct LP_utxoinfo * autxo , char * base , double maxprice , int32_t duration , uint64_t txfee , uint64_t desttxfee , char * gui , bits256 * avoids , int32_t numavoids )
{
bits256 pubkey ; char * obookstr , coinaddr [ 64 ] , str [ 65 ] ; cJSON * orderbook , * asks , * item ; int32_t i , j , n , numasks , max = 10000 ; struct LP_address_utxo * * utxos ; double price ; struct LP_pubkeyinfo * pubp ; struct iguana_info * basecoin ; uint64_t basesatoshis ; struct LP_utxoinfo * bestutxo = 0 ;
* ordermatchpricep = 0. ;
* bestsatoshisp = * bestdestsatoshisp = 0 ;
basecoin = LP_coinfind ( base ) ;
if ( duration < = 0 )
duration = LP_ORDERBOOK_DURATION ;
if ( maxprice < = 0. | | LP_priceinfofind ( base ) = = 0 | | basecoin = = 0 )
return ( 0 ) ;
utxos = calloc ( max , sizeof ( * utxos ) ) ;
LP_txfees ( & txfee , & desttxfee , base , autxo - > coin ) ;
printf ( " LP_buyutxo maxprice %.8f relvol %.8f %s/%s %.8f %.8f \n " , maxprice , dstr ( autxo - > S . satoshis ) , base , autxo - > coin , dstr ( txfee ) , dstr ( desttxfee ) ) ;
if ( ( obookstr = LP_orderbook ( base , autxo - > coin , duration ) ) ! = 0 )
{
if ( ( orderbook = cJSON_Parse ( obookstr ) ) ! = 0 )
{
if ( ( asks = jarray ( & numasks , orderbook , " asks " ) ) ! = 0 )
{
for ( i = 0 ; i < numasks ; i + + )
{
item = jitem ( asks , i ) ;
price = jdouble ( item , " price " ) ;
pubkey = jbits256 ( item , " pubkey " ) ;
printf ( " [%d/%d] %s pubcmp %d price %.8f vs maxprice %.8f \n " , i , numasks , jprint ( item , 0 ) , bits256_cmp ( pubkey , G . LP_mypub25519 ) , price , maxprice ) ;
if ( LP_pricevalid ( price ) > 0 & & price < = maxprice )
{
for ( j = 0 ; j < numavoids ; j + + )
if ( bits256_cmp ( pubkey , avoids [ j ] ) = = 0 )
break ;
if ( j ! = numavoids )
continue ;
if ( bits256_cmp ( pubkey , G . LP_mypub25519 ) ! = 0 & & ( pubp = LP_pubkeyadd ( pubkey ) ) ! = 0 )
{
bitcoin_address ( coinaddr , basecoin - > taddr , basecoin - > pubtype , pubp - > rmd160 , sizeof ( pubp - > rmd160 ) ) ;
n = LP_listunspent_both ( base , coinaddr ) ;
//printf("unspent.(%s) n.%d\n",coinaddr,n);
if ( n > 1 )
{
basesatoshis = LP_basesatoshis ( dstr ( autxo - > S . satoshis ) , price , txfee , desttxfee ) ;
if ( basesatoshis ! = 0 & & ( bestutxo = LP_address_utxopair ( 0 , utxos , max , basecoin , coinaddr , txfee , dstr ( basesatoshis ) * price , price , desttxfee ) ) ! = 0 )
{
bestutxo - > pubkey = pubp - > pubkey ;
safecopy ( bestutxo - > gui , gui , sizeof ( bestutxo - > gui ) ) ;
* bestsatoshisp = basesatoshis ;
* ordermatchpricep = price ;
* bestdestsatoshisp = autxo - > S . satoshis ;
printf ( " ordermatch %.8f %.8f %.8f txfees (%.8f %.8f) \n " , price , dstr ( * bestsatoshisp ) , dstr ( * bestdestsatoshisp ) , dstr ( txfee ) , dstr ( desttxfee ) ) ;
break ;
}
} else printf ( " no unspents %s %s %s \n " , base , coinaddr , bits256_str ( str , pubkey ) ) ;
} else printf ( " self trading or blacklisted peer \n " ) ;
}
else
{
if ( i = = 0 )
printf ( " too expensive maxprice %.8f vs %.8f \n " , maxprice , price ) ;
break ;
}
}
}
free_json ( orderbook ) ;
}
free ( obookstr ) ;
}
free ( utxos ) ;
if ( * ordermatchpricep = = 0. | | * bestdestsatoshisp = = 0 )
return ( 0 ) ;
int32_t changed ;
LP_mypriceset ( & changed , autxo - > coin , base , 1. / * ordermatchpricep ) ;
return ( bestutxo ) ;
}
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 )
{
uint64_t desttxfee , txfee ; int64_t bestsatoshis = 0 , bestdestsatoshis = 0 ; struct LP_utxoinfo * autxo , * butxo , * bestutxo = 0 ; double qprice , ordermatchprice = 0. ; struct LP_quoteinfo Q ;
uint64_t desttxfee , txfee ; int32_t numpubs = 0 ; int64_t bestsatoshis = 0 , destsatoshis , bestdestsatoshis = 0 ; struct LP_utxoinfo * autxo , * bestutxo = 0 ; double qprice , ordermatchprice = 0. ; struct LP_quoteinfo Q ; bits256 pubkeys [ 100 ] ;
printf ( " LP_autobuy %s/%s price %.8f vol %.8f \n " , base , rel , maxprice , relvolume ) ;
if ( duration < = 0 )
duration = LP_ORDERBOOK_DURATION ;
if ( timeout < = 0 )
timeout = LP_AUTOTRADE_TIMEOUT ;
if ( maxprice < = 0. | | relvolume < = 0. | | LP_priceinfofind ( base ) = = 0 | | LP_priceinfofind ( rel ) = = 0 )
return ( clonestr ( " { \" error \" : \" invalid parameter \" } " ) ) ;
if ( ( autxo = LP_utxo_bestfit ( rel , SATOSHIDEN * relvolume ) ) = = 0 )
return ( clonestr ( " { \" error \" : \" cant find utxo that is big enough \" } " ) ) ;
if ( strcmp ( " BTC " , rel ) = = 0 )
maxprice * = 1.01 ;
else maxprice * = 1.001 ;
memset ( pubkeys , 0 , sizeof ( pubkeys ) ) ;
LP_txfees ( & txfee , & desttxfee , base , rel ) ;
if ( ( bestutxo = LP_bestutxo ( & ordermatchprice , & bestsatoshis , & bestdestsatoshis , autxo , base , maxprice , duration , txfee , desttxfee , SATOSHIDEN * relvolume ) ) = = 0 | | ordermatchprice = = 0. | | bestdestsatoshis = = 0 )
{
printf ( " bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f \n " , bestutxo , ordermatchprice , dstr ( bestdestsatoshis ) ) ;
return ( clonestr ( " { \" error \" : \" cant find ordermatch utxo \" } " ) ) ;
}
if ( LP_quoteinfoinit ( & Q , bestutxo , rel , ordermatchprice , bestsatoshis , bestdestsatoshis ) < 0 )
return ( clonestr ( " { \" error \" : \" cant set ordermatch quote \" } " ) ) ;
if ( LP_quotedestinfo ( & Q , autxo - > payment . txid , autxo - > payment . vout , autxo - > fee . txid , autxo - > fee . vout , LP_mypub25519 , autxo - > coinaddr ) < 0 )
return ( clonestr ( " { \" error \" : \" cant set ordermatch quote info \" } " ) ) ;
if ( ( qprice = LP_quote_validate ( & autxo , & butxo , & Q , 0 ) ) < = SMALLVAL )
destsatoshis = SATOSHIDEN * relvolume + 2 * desttxfee ;
if ( ( autxo = LP_utxo_bestfit ( rel , destsatoshis ) ) = = 0 )
return ( clonestr ( " { \" error \" : \" cant find utxo that is big enough \" } " ) ) ;
if ( destsatoshis < autxo - > S . satoshis )
autxo - > S . satoshis = destsatoshis ;
while ( 1 )
{
printf ( " quote validate error %.0f \n " , qprice ) ;
return ( clonestr ( " { \" error \" : \" quote validation error \" } " ) ) ;
if ( ( bestutxo = LP_buyutxo ( & ordermatchprice , & bestsatoshis , & bestdestsatoshis , autxo , base , maxprice , duration , txfee , desttxfee , gui , pubkeys , numpubs ) ) = = 0 | | ordermatchprice = = 0. | | bestdestsatoshis = = 0 )
{
printf ( " bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f \n " , bestutxo , ordermatchprice , dstr ( bestdestsatoshis ) ) ;
return ( clonestr ( " { \" error \" : \" cant find ordermatch utxo \" } " ) ) ;
}
pubkeys [ numpubs + + ] = bestutxo - > pubkey ;
if ( LP_quoteinfoinit ( & Q , bestutxo , rel , ordermatchprice , bestsatoshis , bestdestsatoshis ) < 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 \" } " ) ) ;
if ( ( qprice = LP_quote_validate ( autxo , 0 , & Q , 0 ) ) < = SMALLVAL )
{
printf ( " continue searching, quote validate error %.0f \n " , qprice ) ;
continue ;
}
break ;
}
printf ( " do quote.(%s) \n " , jprint ( LP_quotejson ( & Q ) , 1 ) ) ;
//printf("do quote.(%s)\n",jprint(LP_quotejson(&Q),1));
return ( LP_trade ( ctx , myipaddr , mypubsock , & Q , maxprice , timeout , duration ) ) ;
}