Browse Source

Merge pull request #401 from jl777/spvdex

destpubkey for trades
swapstatus(coin,limit)  and swapstatus(base,rel,limit)
orderbook depth field
fix passphrase to not require userpass
other fixes

I added a destpubkey field to the buy/sell trade api, this allows to ordermatch to a specific entry in the orderbook. I will also be adding a "depth" field to the orderbook, which will just be the sum of the max size utxo from each orderbook entry. alternatively I could sum the total balance at each orderbook entry, though at any given time you can only buy one utxo. i guess it should be easy enough for the GUI to sum the max utxo size, so I will make the depth the theoretical max depth, summing the entire balances

I also now added automated broadcast of any setprices, which will occur automatically when you do a buy/sell for the coin you are buying with, as long as you are not using electrum. to be a bob, you need the native coin. with the pruning of the orderbook to most recent 2 minutes, it required the setprice to be called regularly. I have internalized that so a single setprice is all that is needed. If you want to "cancel" it you can setprice to 0

this means GUI can now post bob orders if you have native coins enabled
etomic
jl777 7 years ago
committed by GitHub
parent
commit
ed849fdd53
  1. 74
      iguana/exchanges/LP_commands.c
  2. 2
      iguana/exchanges/LP_include.h
  3. 41
      iguana/exchanges/LP_nativeDEX.c
  4. 68
      iguana/exchanges/LP_ordermatch.c
  5. 5
      iguana/exchanges/LP_portfolio.c
  6. 48
      iguana/exchanges/LP_prices.c
  7. 134
      iguana/exchanges/LP_remember.c
  8. 7
      iguana/exchanges/LP_rpc.c
  9. 25
      iguana/exchanges/LP_statemachine.c
  10. 5
      iguana/exchanges/LP_utxo.c
  11. 11
      iguana/exchanges/LP_utxos.c
  12. 3
      iguana/exchanges/baserelswaps
  13. 3
      iguana/exchanges/coinswaps
  14. 2
      iguana/exchanges/install
  15. 3
      iguana/exchanges/setpassphrase

74
iguana/exchanges/LP_commands.c

@ -106,18 +106,20 @@ enable(coin)\n\
disable(coin)\n\
notarizations(coin)\n\
parselog()\n\
statsdisp(starttime=0, endtime=0)\n\
statsdisp(starttime=0, endtime=0, gui="", pubkey="")\n\
getrawtransaction(coin, txid)\n\
inventory(coin)\n\
bestfit(rel, relvolume)\n\
lastnonce()\n\
buy(base, rel, price, relvolume, timeout=10, duration=3600, nonce)\n\
sell(base, rel, price, basevolume, timeout=10, duration=3600, nonce)\n\
buy(base, rel, price, relvolume, timeout=10, duration=3600, nonce, pubkey="")\n\
sell(base, rel, price, basevolume, timeout=10, duration=3600, nonce, pubkey="")\n\
withdraw(coin, outputs[])\n\
sendrawtransaction(coin, signedtx)\n\
swapstatus()\n\
recentswaps(limit=3)\n\
swapstatus(coin, limit=10)\n\
swapstatus(base, rel, limit=10)\n\
swapstatus(requestid, quoteid)\n\
recentswaps(limit=3)\n\
public API:\n \
getcoins()\n\
getcoin(coin)\n\
@ -156,10 +158,23 @@ stop()\n\
jadd(retjson,"coins",LP_coinsjson(LP_showwif));
return(jprint(retjson,1));
}
if ( (userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,G.USERPASS) != 0 )
if ( strcmp(method,"passphrase") != 0 && ((userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,G.USERPASS) != 0) )
return(clonestr("{\"error\":\"authentication error you need to make sure userpass is set\"}"));
jdelete(argjson,"userpass");
if ( strcmp(method,"sendmessage") == 0 )
if ( strcmp(method,"passphrase") == 0 )
{
G.USERPASS_COUNTER = 1;
if ( LP_passphrase_init(jstr(argjson,"passphrase"),jstr(argjson,"gui")) < 0 )
return(clonestr("{\"error\":\"couldnt change passphrase\"}"));
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"userpass",G.USERPASS);
jaddbits256(retjson,"mypubkey",G.LP_mypub25519);
return(jprint(retjson,1));
}
}
else if ( strcmp(method,"sendmessage") == 0 )
{
if ( jobj(argjson,"method2") == 0 )
{
@ -187,18 +202,6 @@ stop()\n\
LP_deletemessages(jint(argjson,"firsti"),jint(argjson,"num"));
return(clonestr("{\"result\":\"success\"}"));
}
else if ( strcmp(method,"passphrase") == 0 )
{
if ( LP_passphrase_init(jstr(argjson,"passphrase"),jstr(argjson,"gui")) < 0 )
return(clonestr("{\"error\":\"couldnt change passphrase\"}"));
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"userpass",G.USERPASS);
jaddbits256(retjson,"mypubkey",G.LP_mypub25519);
return(jprint(retjson,1));
}
}
else if ( strcmp(method,"notarizations") == 0 )
{
int32_t height,bestheight;
@ -234,6 +237,17 @@ stop()\n\
taddr = (jobj(argjson,"taddr") == 0) ? 0 : juint(argjson,"taddr");
return(LP_secretaddresses(ctx,jstr(argjson,"prefix"),jstr(argjson,"passphrase"),juint(argjson,"num"),taddr,pubtype));
}
else if ( strcmp(method,"swapstatus") == 0 )
{
uint32_t requestid,quoteid;
if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 )
return(basilisk_swapentry(requestid,quoteid));
else if ( coin != 0 && coin[0] != 0 )
return(basilisk_swapentries(coin,0,jint(argjson,"limit")));
else if ( base != 0 && base[0] != 0 && rel != 0 && rel[0] != 0 )
return(basilisk_swapentries(base,rel,jint(argjson,"limit")));
else return(basilisk_swaplist(0,0));
}
if ( base != 0 && rel != 0 )
{
double price,bid,ask;
@ -242,14 +256,11 @@ stop()\n\
price = jdouble(argjson,"price");
if ( strcmp(method,"setprice") == 0 )
{
if ( price > SMALLVAL )
{
if ( LP_mypriceset(&changed,base,rel,price) < 0 )
return(clonestr("{\"error\":\"couldnt set price\"}"));
//else if ( LP_mypriceset(&changed,rel,base,1./price) < 0 )
// return(clonestr("{\"error\":\"couldnt set price\"}"));
else return(LP_pricepings(ctx,myipaddr,LP_mypubsock,base,rel,price * LP_profitratio));
} else return(clonestr("{\"error\":\"no price\"}"));
if ( LP_mypriceset(&changed,base,rel,price) < 0 )
return(clonestr("{\"error\":\"couldnt set price\"}"));
//else if ( LP_mypriceset(&changed,rel,base,1./price) < 0 )
// return(clonestr("{\"error\":\"couldnt set price\"}"));
else return(LP_pricepings(ctx,myipaddr,LP_mypubsock,base,rel,price * LP_profitratio));
}
else if ( strcmp(method,"autoprice") == 0 )
{
@ -278,7 +289,7 @@ stop()\n\
//*
if ( price > SMALLVAL )
{
return(LP_autobuy(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"),juint(argjson,"nonce")));
return(LP_autobuy(ctx,myipaddr,pubsock,base,rel,price,jdouble(argjson,"relvolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"),juint(argjson,"nonce"),jbits256(argjson,"pubkey")));
} else return(clonestr("{\"error\":\"no price set\"}"));
}
else if ( strcmp(method,"sell") == 0 )
@ -286,7 +297,7 @@ stop()\n\
//*
if ( price > SMALLVAL )
{
return(LP_autobuy(ctx,myipaddr,pubsock,rel,base,1./price,jdouble(argjson,"basevolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"),juint(argjson,"nonce")));
return(LP_autobuy(ctx,myipaddr,pubsock,rel,base,1./price,jdouble(argjson,"basevolume"),jint(argjson,"timeout"),jint(argjson,"duration"),jstr(argjson,"gui"),juint(argjson,"nonce"),jbits256(argjson,"pubkey")));
} else return(clonestr("{\"error\":\"no price set\"}"));
}
}
@ -420,13 +431,6 @@ stop()\n\
}
else if ( strcmp(method,"goal") == 0 )
return(LP_portfolio_goal("*",100.));
else if ( strcmp(method,"swapstatus") == 0 )
{
uint32_t requestid,quoteid;
if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 )
return(basilisk_swapentry(requestid,quoteid));
else return(basilisk_swaplist(0,0));
}
else if ( strcmp(method,"lastnonce") == 0 )
{
cJSON *retjson = cJSON_CreateObject();

2
iguana/exchanges/LP_include.h

@ -60,7 +60,7 @@ void emscripten_usleep(int32_t x);
#define LP_SWAPSTEP_TIMEOUT 30
#define LP_MIN_TXFEE 10000
#define LP_MINVOL 20
#define LP_MINCLIENTVOL 50
#define LP_MINCLIENTVOL 1000
#define LP_MINSIZE_TXFEEMULT 10
#define LP_REQUIRED_TXFEE 0.8

41
iguana/exchanges/LP_nativeDEX.c

@ -21,13 +21,13 @@
// ZEC LP_transaction_fromdata mismatched txid e2a3eebcf5bef6fe63296f53ce35d2f2c6e3b29c7c907da4171a580f50c93c74 vs 1ed5c15bbf991ff42c73b1492d1bb50e91d1d731c86cb3058405cff95cd9bd70
//0200000000018c343500000000001976a9141462c3dd3f936d595c9af55978003b27c250441f88ac000000000100000000000000009c5b3500000000005a6c707fc604699d0166b2a750c8a2ff21c8aed0b6e6fe160f651da8cf865c2aa079a7f71f7782604785e1f9a7300cd6c89ca50b5d91f6c0ae5f293ea5a72e62bb0f05da84510e6431c5d4be7a372221265fd98dbccee11f5ed064c5afaa19eff27fd12c30a7a5205f70c99f22b7090c00048c1c9767eea1c79e54ed60c08c138758ad73d43f2692fcb05f data2json n.44 vs len.
// process stats.log local file -> map of realtime activity!
// handles <-> pubkeys, deal with offline pubkeys, reputations, bonds etc.
// select oldest utxo first
// verify portfolio, pricearray, interest to KMD withdraw
// handles <-> pubkeys, deal with offline pubkeys, reputations, bonds etc.
// depth
// verify portfolio, pricearray, interest to KMD withdraw, pricebroadcast loop, trade to pubkey
// dPoW security -> 4: KMD notarized, 5: BTC notarized, after next notary elections
// bigendian architectures need to use little endian for sighash calcs
//statsdisp(starttime=0, endtime=0, gui="", pubkey="")\n\
#include <stdio.h>
#include "LP_include.h"
@ -737,6 +737,26 @@ void LP_pubkeysloop(void *ctx)
}
}
void LP_price_broadcastloop(void *ctx)
{
struct LP_priceinfo *basepp,*relpp; double price; int32_t baseind,relind;
sleep(30);
while ( 1 )
{
for (baseind=0; baseind<LP_MAXPRICEINFOS; baseind++)
{
basepp = LP_priceinfo(baseind);
for (relind=0; relind<LP_MAXPRICEINFOS; relind++)
{
relpp = LP_priceinfo(relind);
if ( basepp != 0 && relpp != 0 && (price= basepp->myprices[relpp->ind]) > SMALLVAL)
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,relpp->symbol,basepp->symbol,price);
}
}
sleep(60);
}
}
void LP_privkeysloop(void *ctx)
{
sleep(20);
@ -1007,12 +1027,17 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
printf("error launching LP_pubkeysloop for ctx.%p\n",ctx);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_privkeysloop,(void *)&myipaddr) != 0 )
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_privkeysloop,(void *)myipaddr) != 0 )
{
printf("error launching LP_privkeysloop for ctx.%p\n",ctx);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_swapsloop,(void *)&myipaddr) != 0 )
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_swapsloop,(void *)myipaddr) != 0 )
{
printf("error launching LP_swapsloop for port.%u\n",myport);
exit(-1);
}
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_price_broadcastloop,(void *)ctx) != 0 )
{
printf("error launching LP_swapsloop for port.%u\n",myport);
exit(-1);
@ -1078,10 +1103,10 @@ void LP_fromjs_iter()
LP_nanomsg_recvs(ctx);
LP_mainloop_iter(ctx,LP_myipaddr,0,LP_mypubsock,LP_publicaddr,LP_RPCPORT);
queue_loop(0);
if ( (LP_counter % 10) == 0 )
if ( (LP_counter % 10) == 0 ) // 10 seconds
{
LP_coinsloop(0);
if ( (LP_counter % 100) == 0 )
if ( (LP_counter % 100) == 0 ) // 100 seconds
{
LP_notify_pubkeys(ctx,LP_mypubsock);
LP_privkey_updates(ctx,LP_mypubsock,0);

68
iguana/exchanges/LP_ordermatch.c

@ -531,7 +531,7 @@ char *LP_connectedalice(cJSON *argjson) // alice
int32_t LP_listunspent_both(char *symbol,char *coinaddr,int32_t fullflag)
{
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);
int32_t i,v,numconfs,height,n=0; uint64_t value; bits256 txid; char buf[512]; cJSON *array,*item; struct iguana_info *coin = LP_coinfind(symbol);
if ( coin != 0 )//&& (IAMLP != 0 || coin->inactive == 0) )
{
if ( coin->electrum != 0 || LP_address_ismine(symbol,coinaddr) <= 0 )
@ -543,8 +543,11 @@ int32_t LP_listunspent_both(char *symbol,char *coinaddr,int32_t fullflag)
}
else
{
if ( strcmp(symbol,"BTC") == 0 )
numconfs = 0;
else numconfs = 1;
//printf("my coin electrum.%p\n",coin->electrum);
sprintf(buf,"[1, 99999999, [\"%s\"]]",coinaddr);
sprintf(buf,"[%d, 99999999, [\"%s\"]]",numconfs,coinaddr);
if ( (array= bitcoin_json(coin,"listunspent",buf)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
@ -761,7 +764,7 @@ struct LP_utxoinfo *LP_ordermatch_iter(struct LP_address_utxo **utxos,int32_t ma
return(0);
}
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)
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 destpubkey)
{
bits256 pubkey; char *obookstr,coinaddr[64]; cJSON *orderbook,*asks,*item; int32_t maxiters,i,j,numasks,max; struct LP_address_utxo **utxos; double price; struct LP_pubkeyinfo *pubp; uint64_t asatoshis; struct iguana_info *basecoin; struct LP_utxoinfo *bestutxo = 0;
maxiters = 100;
@ -790,41 +793,36 @@ struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,i
price = jdouble(item,"price");
price *= 1.005;
pubkey = jbits256(item,"pubkey");
if ( bits256_nonz(destpubkey) != 0 && bits256_cmp(destpubkey,pubkey) != 0 )
continue;
//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_nonz(destpubkey) == 0 )
{
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));
asatoshis = autxo->S.satoshis;
/*if ( basecoin->electrum != 0 )
{
price *= 1.01;
*ordermatchpricep = price;
*bestsatoshisp = LP_basesatoshis(dstr(asatoshis),price,txfee,desttxfee);
*bestdestsatoshisp = asatoshis;
}
else*/
{
LP_listunspent_query(base,coinaddr);
LP_listunspent_both(base,coinaddr,1);
for (j=0; j<maxiters; j++)
for (j=0; j<maxiters; j++)
{
if ( (bestutxo= LP_ordermatch_iter(utxos,max,ordermatchpricep,bestsatoshisp,bestdestsatoshisp,basecoin,coinaddr,asatoshis,price,txfee,desttxfee,pubp->pubkey,gui)) != 0 )
{
if ( (bestutxo= LP_ordermatch_iter(utxos,max,ordermatchpricep,bestsatoshisp,bestdestsatoshisp,basecoin,coinaddr,asatoshis,price,txfee,desttxfee,pubp->pubkey,gui)) != 0 )
{
printf("j.%d/%d ordermatch %.8f best satoshis %.8f destsatoshis %.8f txfees (%.8f %.8f)\n",j,maxiters,price,dstr(*bestsatoshisp),dstr(*bestdestsatoshisp),dstr(txfee),dstr(desttxfee));
break;
}
asatoshis = (asatoshis / 64) * 63;
}
if ( j < maxiters )
printf("j.%d/%d ordermatch %.8f best satoshis %.8f destsatoshis %.8f txfees (%.8f %.8f)\n",j,maxiters,price,dstr(*bestsatoshisp),dstr(*bestdestsatoshisp),dstr(txfee),dstr(desttxfee));
break;
}
asatoshis = (asatoshis / 64) * 63;
}
if ( j < maxiters )
break;
} else printf("self trading or blacklisted peer\n");
}
else
@ -847,7 +845,7 @@ struct LP_utxoinfo *LP_buyutxo(double *ordermatchpricep,int64_t *bestsatoshisp,i
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,uint32_t nonce)
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)
{
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];
basecoin = LP_coinfind(base);
@ -897,9 +895,14 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel
return(clonestr("{\"error\":\"cant find alice utxo that is big enough\"}"));
if ( destsatoshis < autxo->S.satoshis )
autxo->S.satoshis = destsatoshis;
if ( destsatoshis < (autxo->payment.value / LP_MINCLIENTVOL) || autxo->payment.value < desttxfee*LP_MINSIZE_TXFEEMULT )
{
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\"}"));
}
while ( 1 )
{
if ( (bestutxo= LP_buyutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,gui,pubkeys,numpubs)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 )
if ( (bestutxo= LP_buyutxo(&ordermatchprice,&bestsatoshis,&bestdestsatoshis,autxo,base,maxprice,duration,txfee,desttxfee,gui,pubkeys,numpubs,destpubkey)) == 0 || ordermatchprice == 0. || bestdestsatoshis == 0 )
{
printf("bestutxo.%p ordermatchprice %.8f bestdestsatoshis %.8f\n",bestutxo,ordermatchprice,dstr(bestdestsatoshis));
return(clonestr("{\"error\":\"cant find ordermatch utxo, need to change relvolume to be closer to available\"}"));
@ -929,12 +932,13 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel
if ( i == maxiters || qprice > maxprice )
{
printf("i.%d maxiters.%d qprice %.8f vs maxprice %.8f, no acceptable quote for this pubkey\n",i,maxiters,dstr(qprice),dstr(maxprice));
continue;
if ( bits256_nonz(destpubkey) == 0 )
continue;
else return(clonestr("{\"error\":\"cant ordermatch to destpubkey\"}"));
}
break;
return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration));
}
//printf("do quote.(%s)\n",jprint(LP_quotejson(&Q),1));
return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration));
return(clonestr("{\"error\":\"cant get here\"}"));
}

5
iguana/exchanges/LP_portfolio.c

@ -484,7 +484,7 @@ void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp)
int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,struct iguana_info *buy,struct iguana_info *sell,double relvolume,int32_t setbaserel,char *gui)
{
char *retstr2; double bid,ask,maxprice; uint32_t requestid,quoteid,iter,i; cJSON *retjson2;
char *retstr2; double bid,ask,maxprice; bits256 zero; uint32_t requestid,quoteid,iter,i; cJSON *retjson2;
requestid = quoteid = 0;
LP_myprice(&bid,&ask,buy->symbol,sell->symbol);
maxprice = ask;
@ -504,7 +504,8 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str
break;
if ( LP_utxo_bestfit(sell->symbol,SATOSHIDEN * relvolume) != 0 )
{
if ( (retstr2= LP_autobuy(ctx,"127.0.0.1",-1,buy->symbol,sell->symbol,maxprice,relvolume,60,24*3600,gui,LP_lastnonce+1)) != 0 )
memset(zero.bytes,0,sizeof(zero));
if ( (retstr2= LP_autobuy(ctx,"127.0.0.1",-1,buy->symbol,sell->symbol,maxprice,relvolume,60,24*3600,gui,LP_lastnonce+1,zero)) != 0 )
{
if ( (retjson2= cJSON_Parse(retstr2)) != 0 )
{

48
iguana/exchanges/LP_prices.c

@ -18,7 +18,7 @@
// marketmaker
//
struct LP_orderbookentry { bits256 pubkey; double price; uint64_t minsatoshis,maxsatoshis; uint32_t timestamp; int32_t numutxos; char coinaddr[64]; };
struct LP_orderbookentry { bits256 pubkey; double price; uint64_t minsatoshis,maxsatoshis,depth; uint32_t timestamp; int32_t numutxos; char coinaddr[64]; };
struct LP_priceinfo
{
@ -47,6 +47,13 @@ struct LP_cacheinfo
uint32_t timestamp;
} *LP_cacheinfos;
struct LP_priceinfo *LP_priceinfo(int32_t ind)
{
if ( ind < 0 || ind >= LP_MAXPRICEINFOS )
return(0);
else return(&LP_priceinfos[ind]);
}
char *LP_priceinfostr(int32_t ind)
{
if ( ind < 0 || ind >= LP_MAXPRICEINFOS )
@ -478,7 +485,7 @@ int32_t LP_mypriceset(int32_t *changedp,char *base,char *rel,double price)
{
struct LP_priceinfo *basepp,*relpp; struct LP_pubkeyinfo *pubp;
*changedp = 0;
if ( base != 0 && rel != 0 && LP_pricevalid(price) > 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
if ( base != 0 && rel != 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
if ( fabs(basepp->myprices[relpp->ind] - price) > SMALLVAL )
@ -666,13 +673,14 @@ cJSON *LP_orderbookjson(char *symbol,struct LP_orderbookentry *op)
jaddnum(item,"numutxos",op->numutxos);
jaddnum(item,"minvolume",dstr(op->minsatoshis)*0.8);
jaddnum(item,"maxvolume",dstr(op->maxsatoshis)*0.8);
jaddnum(item,"depth",dstr(op->depth)*0.8);
jaddbits256(item,"pubkey",op->pubkey);
jaddnum(item,"age",time(NULL)-op->timestamp);
}
return(item);
}
struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,uint64_t minsatoshis,uint64_t maxsatoshis,bits256 pubkey,uint32_t timestamp)
struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,double price,int32_t numutxos,uint64_t minsatoshis,uint64_t maxsatoshis,bits256 pubkey,uint32_t timestamp,uint64_t depth)
{
struct LP_orderbookentry *op;
if ( (op= calloc(1,sizeof(*op))) != 0 )
@ -684,6 +692,7 @@ struct LP_orderbookentry *LP_orderbookentry(char *address,char *base,char *rel,d
op->maxsatoshis = maxsatoshis;
op->pubkey = pubkey;
op->timestamp = timestamp;
op->depth = depth;
}
return(op);
}
@ -708,7 +717,7 @@ void LP_pubkeys_query()
int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *rel,struct LP_orderbookentry *(**arrayp),int32_t num,int32_t cachednum,int32_t duration)
{
char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkeyinfo *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; uint64_t minsatoshis,maxsatoshis;
char coinaddr[64]; uint8_t zeroes[20]; struct LP_pubkeyinfo *pubp=0,*tmp; struct LP_priceinfo *basepp; struct LP_orderbookentry *op; struct LP_address *ap; struct iguana_info *basecoin; uint32_t oldest; double price; int32_t baseid,relid,n; uint64_t minsatoshis,maxsatoshis,balance,depth;
if ( (basepp= LP_priceinfoptr(&relid,base,rel)) != 0 )
baseid = basepp->ind;
else return(num);
@ -717,6 +726,7 @@ int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *
now = (uint32_t)time(NULL);
oldest = now - duration;
memset(zeroes,0,sizeof(zeroes));
depth = 0;
HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp)
{
if ( memcmp(zeroes,pubp->rmd160,sizeof(pubp->rmd160)) == 0 )
@ -733,15 +743,17 @@ int32_t LP_orderbook_utxoentries(uint32_t now,int32_t polarity,char *base,char *
{
if ( (ap= LP_addressfind(basecoin,coinaddr)) != 0 )
{
n = LP_address_minmax(&minsatoshis,&maxsatoshis,ap);
n = LP_address_minmax(&balance,&minsatoshis,&maxsatoshis,ap);
if ( polarity > 0 )
{
balance *= price;
minsatoshis *= price;
maxsatoshis *= price;
}
depth += balance;
//printf("%s/%s %s n.%d ap->n.%d %.8f\n",base,rel,coinaddr,n,ap->n,dstr(ap->total));
}
if ( (op= LP_orderbookentry(coinaddr,base,rel,polarity > 0 ? price : 1./price,n,minsatoshis,maxsatoshis,pubp->pubkey,pubp->timestamp)) != 0 )
if ( (op= LP_orderbookentry(coinaddr,base,rel,polarity > 0 ? price : 1./price,n,minsatoshis,maxsatoshis,pubp->pubkey,pubp->timestamp,depth)) != 0 )
{
*arrayp = realloc(*arrayp,sizeof(*(*arrayp)) * (num+1));
(*arrayp)[num++] = op;
@ -875,30 +887,6 @@ uint64_t LP_KMDvalue(struct iguana_info *coin,uint64_t balance)
return(KMDvalue);
}
/*char *LP_pricestr(char *base,char *rel,double origprice)
{
cJSON *retjson; double price = 0.;
if ( base != 0 && base[0] != 0 && rel != 0 && rel[0] != 0 )
{
price = LP_price(base,rel);
if ( origprice > SMALLVAL && origprice < price )
price = origprice;
}
if ( LP_pricevalid(price) > 0 )
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"method","postprice");
jaddbits256(retjson,"pubkey",G.LP_mypub25519);
jaddstr(retjson,"base",base);
jaddstr(retjson,"rel",rel);
jaddnum(retjson,"price",price);
jadd(retjson,"theoretical",LP_priceinfomatrix(0));
jadd(retjson,"quotes",LP_priceinfomatrix(1));
return(jprint(retjson,1));
} else return(clonestr("{\"error\":\"cant find baserel pair\"}"));
}*/
void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32])
{
LP_priceinfoupdate(base,rel,price);

134
iguana/exchanges/LP_remember.c

@ -1148,8 +1148,9 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid)
{
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;
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;
portable_mutex_lock(&LP_swaplistmutex);
memset(ridqids,0,sizeof(ridqids));
memset(KMDtotals,0,sizeof(KMDtotals));
memset(BTCtotals,0,sizeof(BTCtotals));
//,statebits; int32_t optionduration; struct basilisk_request R; bits256 privkey;
@ -1189,8 +1190,17 @@ char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid)
}
if ( flag == 0 )
{
if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid)) != 0 )
jaddi(array,item);
ridqid = ((uint64_t)requestid << 32) | quoteid;
for (j=0; j<count; j++)
if ( ridqid == ridqids[j] )
break;
if ( j == count )
{
if ( count < sizeof(ridqids)/sizeof(*ridqids) )
ridqids[count++] = ridqid;
if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid)) != 0 )
jaddi(array,item);
}
}
}
fclose(fp);
@ -1297,11 +1307,129 @@ char *LP_recent_swaps(int32_t limit)
item = cJSON_CreateObject();
jaddnum(item,"expiration",Alice_expiration);
jaddnum(item,"timeleft",Alice_expiration-time(NULL));
jaddnum(item,"requestid",LP_Alicequery.R.requestid);
jaddnum(item,"quoteid",LP_Alicequery.R.quoteid);
jaddstr(item,"bob",LP_Alicequery.srccoin);
jaddstr(item,"base",LP_Alicequery.srccoin);
jaddnum(item,"basevalue",dstr(LP_Alicequery.satoshis));
jaddstr(item,"alice",LP_Alicequery.destcoin);
jaddstr(item,"rel",LP_Alicequery.destcoin);
jaddnum(item,"relvalue",dstr(LP_Alicequery.destsatoshis));
jadd(retjson,"pending",item);
} else Alice_expiration = 0;
return(jprint(retjson,1));
}
uint64_t basilisk_swap_addarray(cJSON *item,char *refbase,char *refrel)
{
char *base,*rel; uint32_t requestid,quoteid; uint64_t ridqid = 0;
base = jstr(item,"bob");
rel = jstr(item,"alice");
if ( refrel == 0 || refrel[0] == 0 )
{
if ( strcmp(base,refbase) == 0 || strcmp(rel,refbase) == 0 )
ridqid = 1;
}
else if ( strcmp(base,refbase) == 0 && strcmp(rel,refrel) == 0 )
ridqid = 1;
if ( ridqid != 0 )
{
requestid = juint(item,"requestid");
quoteid = juint(item,"quoteid");
ridqid = ((uint64_t)requestid << 32) | quoteid;
//printf("%u %u -> %16llx\n",requestid,quoteid,(long long)ridqid);
}
return(ridqid);
}
char *basilisk_swapentries(char *refbase,char *refrel,int32_t limit)
{
uint64_t ridqids[1024],ridqid; char *liststr,*retstr2; cJSON *retjson,*array,*pending,*swapjson,*item,*retarray; int32_t i,j,n,count = 0; uint32_t requestid,quoteid;
if ( limit <= 0 )
limit = 10;
memset(ridqids,0,sizeof(ridqids));
retarray = cJSON_CreateArray();
if ( (liststr= basilisk_swaplist(0,0)) != 0 )
{
//printf("swapentry.(%s)\n",liststr);
if ( (retjson= cJSON_Parse(liststr)) != 0 )
{
if ( (array= jarray(&n,retjson,"swaps")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( (ridqid= basilisk_swap_addarray(item,refbase,refrel)) > 0 )
{
if ( count < sizeof(ridqids)/sizeof(*ridqids) )
{
ridqids[count++] = ridqid;
//printf("add ridqid.%16llx\n",(long long)ridqid);
}
jaddi(retarray,jduplicate(item));
}
}
}
free_json(retjson);
}
free(liststr);
}
if ( (liststr= LP_recent_swaps(limit)) != 0 )
{
if ( (retjson= cJSON_Parse(liststr)) != 0 )
{
if ( (array= jarray(&n,retjson,"swaps")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
requestid = juint(jitem(item,0),0);
quoteid = juint(jitem(item,1),0);
ridqid = ((uint64_t)requestid << 32) | quoteid;
for (j=0; j<count; j++)
if ( ridqid == ridqids[j] )
break;
//printf("j.%d count.%d %u %u ridqid.%16llx\n",j,count,requestid,quoteid,(long long)ridqid);
if ( j == count )
{
if ( (retstr2= basilisk_swapentry(requestid,quoteid)) != 0 )
{
if ( (swapjson= cJSON_Parse(retstr2)) != 0 )
{
if ( (ridqid= basilisk_swap_addarray(swapjson,refbase,refrel)) > 0 )
{
if ( count < sizeof(ridqids)/sizeof(*ridqids) )
ridqids[count++] = ridqid;
jaddi(retarray,swapjson);
} else free_json(swapjson);
}
free(retstr2);
}
}
}
}
if ( (pending= jobj(retjson,"pending")) != 0 )
{
requestid = juint(pending,"requestid");
quoteid = juint(pending,"quoteid");
j = 0;
if ( (ridqid= ((uint64_t)requestid << 32) | quoteid) != 0 )
{
for (j=0; j<count; j++)
if ( ridqid == ridqids[j] )
break;
}
if ( ridqid == 0 || j == count )
{
if ( basilisk_swap_addarray(pending,refbase,refrel) > 0 )
jaddi(retarray,pending);
else free_json(pending);
} else free_json(pending);
}
free_json(retjson);
}
free(liststr);
}
return(jprint(retarray,1));
}

7
iguana/exchanges/LP_rpc.c

@ -477,7 +477,7 @@ int32_t LP_address_isvalid(char *symbol,char *address)
cJSON *LP_listunspent(char *symbol,char *coinaddr)
{
char buf[128]; cJSON *retjson; struct iguana_info *coin;
char buf[128]; cJSON *retjson; int32_t numconfs; struct iguana_info *coin;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
@ -488,7 +488,10 @@ cJSON *LP_listunspent(char *symbol,char *coinaddr)
{
if ( LP_address_ismine(symbol,coinaddr) > 0 )
{
sprintf(buf,"[0, 99999999, [\"%s\"]]",coinaddr);
if ( strcmp(symbol,"BTC") == 0 )
numconfs = 0;
else numconfs = 1;
sprintf(buf,"[%d, 99999999, [\"%s\"]]",numconfs,coinaddr);
return(bitcoin_json(coin,"listunspent",buf));
} else return(LP_address_utxos(coin,coinaddr,0));
} else return(electrum_address_listunspent(symbol,coin->electrum,&retjson,coinaddr,1));

25
iguana/exchanges/LP_statemachine.c

@ -1882,6 +1882,31 @@ void LP_utxo_clientpublish(struct LP_utxoinfo *utxo)
return(clonestr("{\"result\":\"marked as spent\"}"));
return(clonestr("{\"error\":\"cant find txid to check spent status\"}"));
}*/
/*char *LP_pricestr(char *base,char *rel,double origprice)
{
cJSON *retjson; double price = 0.;
if ( base != 0 && base[0] != 0 && rel != 0 && rel[0] != 0 )
{
price = LP_price(base,rel);
if ( origprice > SMALLVAL && origprice < price )
price = origprice;
}
if ( LP_pricevalid(price) > 0 )
{
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"method","postprice");
jaddbits256(retjson,"pubkey",G.LP_mypub25519);
jaddstr(retjson,"base",base);
jaddstr(retjson,"rel",rel);
jaddnum(retjson,"price",price);
jadd(retjson,"theoretical",LP_priceinfomatrix(0));
jadd(retjson,"quotes",LP_priceinfomatrix(1));
return(jprint(retjson,1));
} else return(clonestr("{\"error\":\"cant find baserel pair\"}"));
}*/
void LP_utxo_spentcheck(int32_t pubsock,struct LP_utxoinfo *utxo)
{
struct _LP_utxoinfo u; struct iguana_info *coin; char str[65]; uint32_t now = (uint32_t)time(NULL);

5
iguana/exchanges/LP_utxo.c

@ -92,10 +92,10 @@ struct LP_address *LP_address(struct iguana_info *coin,char *coinaddr)
return(ap);
}
int32_t LP_address_minmax(uint64_t *minp,uint64_t *maxp,struct LP_address *ap)
int32_t LP_address_minmax(uint64_t *balancep,uint64_t *minp,uint64_t *maxp,struct LP_address *ap)
{
struct LP_address_utxo *up,*tmp; int32_t n = 0;
*minp = *maxp = 0;
*minp = *maxp = *balancep = 0;
DL_FOREACH_SAFE(ap->utxos,up,tmp)
{
if ( up->spendheight <= 0 )
@ -104,6 +104,7 @@ int32_t LP_address_minmax(uint64_t *minp,uint64_t *maxp,struct LP_address *ap)
*maxp = up->U.value;
if ( *minp == 0 || up->U.value < *minp )
*minp = up->U.value;
*balancep += up->U.value;
n++;
}
}

11
iguana/exchanges/LP_utxos.c

@ -762,7 +762,7 @@ void LP_privkey_updates(void *ctx,int32_t pubsock,char *passphrase)
int32_t LP_passphrase_init(char *passphrase,char *gui)
{
static void *ctx; int32_t iambob; struct LP_utxoinfo *utxo,*tmp;
static void *ctx; int32_t iambob,counter; struct LP_utxoinfo *utxo,*tmp;
if ( ctx == 0 )
ctx = bitcoin_ctx();
if ( G.LP_pendingswaps != 0 )
@ -770,6 +770,7 @@ int32_t LP_passphrase_init(char *passphrase,char *gui)
G.initializing = 1;
if ( gui == 0 )
gui = "cli";
counter = G.USERPASS_COUNTER;
while ( G.waiting == 0 )
{
printf("waiting for G.waiting\n");
@ -782,16 +783,17 @@ int32_t LP_passphrase_init(char *passphrase,char *gui)
HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp)
{
HASH_DELETE(hh,G.LP_utxoinfos[iambob],utxo);
free(utxo);
//free(utxo);
}
}
if ( G.LP_utxoinfos2[iambob] != 0 )
{
HASH_ITER(hh,G.LP_utxoinfos2[iambob],utxo,tmp)
G.LP_utxoinfos2[iambob] = 0;
/*HASH_ITER(hh,G.LP_utxoinfos2[iambob],utxo,tmp)
{
HASH_DELETE(hh,G.LP_utxoinfos2[iambob],utxo);
free(utxo);
}
}*/
}
}
memset(&G,0,sizeof(G));
@ -799,6 +801,7 @@ int32_t LP_passphrase_init(char *passphrase,char *gui)
init_hexbytes_noT(G.LP_myrmd160str,G.LP_myrmd160,20);
G.LP_sessionid = (uint32_t)time(NULL);
safecopy(G.gui,gui,sizeof(G.gui));
G.USERPASS_COUNTER = counter;
return(0);
}

3
iguana/exchanges/baserelswaps

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"swapstatus\",\"base\":\"MNZ\",\"rel\":\"KMD\"}"

3
iguana/exchanges/coinswaps

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"swapstatus\",\"coin\":\"CHIPS\"}"

2
iguana/exchanges/install

@ -1,5 +1,5 @@
#!/bin/bash
cp notarizations getrawtransaction parselog statsdisp m_js trust trusted setconfirms balance listunspent electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug buy sell bestfit orderbook client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices help inv setprice status ../dexscripts
cp pendings coinswaps baserelswaps setpassphrase notarizations getrawtransaction parselog statsdisp m_js trust trusted setconfirms balance listunspent electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug buy sell bestfit orderbook client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices help inv setprice status ../dexscripts
cp coins.json ..
cd ../dexscripts
#cp ../exchanges/passphrase ../exchanges/userpass .

3
iguana/exchanges/setpassphrase

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"passphrase\",\"passphrase\":\"put the passphrase here\",\"gui\":\"buildog\"}"
Loading…
Cancel
Save