|
|
@ -27,12 +27,21 @@ |
|
|
|
z_sendmany "fromaddress" [{"address":... ,"amount":..., "memo":"<hex>"},...] ( minconf ) ( fee ) |
|
|
|
*/ |
|
|
|
|
|
|
|
#define JUMBLR_INCR 99 |
|
|
|
#define JUMBLR_INCR 99.65 |
|
|
|
#define JUMBLR_TXFEE 0.01 |
|
|
|
#define JUMBLR_ADDR "RGhxXpXSSBTBm9EvNsXnTQczthMCxHX91t" |
|
|
|
#define JUMBLR_BTCADDR "18RmTJe9qMech8siuhYfMtHo8RtcN1obC6" |
|
|
|
#define JUMBLR_FEE 0.001 |
|
|
|
|
|
|
|
int32_t jumblr_addresstype(struct supernet_info *myinfo,struct iguana_info *coin,char *addr) |
|
|
|
{ |
|
|
|
if ( addr[0] == 'z' && addr[1] == 'c' && strlen(addr) >= 40 ) |
|
|
|
return('z'); |
|
|
|
else if ( strlen(addr) < 40 ) |
|
|
|
return('t'); |
|
|
|
else return(-1); |
|
|
|
} |
|
|
|
|
|
|
|
struct jumblr_item *jumblr_opidfind(struct supernet_info *myinfo,char *opid) |
|
|
|
{ |
|
|
|
struct jumblr_item *ptr; |
|
|
@ -71,9 +80,18 @@ char *jumblr_zgetoperationresult(struct supernet_info *myinfo,struct iguana_info |
|
|
|
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_getoperationresult",params)); |
|
|
|
} |
|
|
|
|
|
|
|
char *jumblr_zgetoperationstatus(struct supernet_info *myinfo,struct iguana_info *coin,char *opid) |
|
|
|
{ |
|
|
|
char params[1024]; |
|
|
|
sprintf(params,"[[\"%s\"]]",opid); |
|
|
|
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_getoperationstatus",params)); |
|
|
|
} |
|
|
|
|
|
|
|
char *jumblr_sendt_to_z(struct supernet_info *myinfo,struct iguana_info *coin,char *taddr,char *zaddr,double amount) |
|
|
|
{ |
|
|
|
char params[1024]; double fee = (amount-3*JUMBLR_TXFEE) * JUMBLR_FEE; |
|
|
|
if ( jumblr_addresstype(myinfo,coin,zaddr) != 'z' || jumblr_addresstype(myinfo,coin,taddr) != 't' ) |
|
|
|
return(clonestr("{\"error\":\"illegal address in t to z\"}")); |
|
|
|
sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",taddr,zaddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); |
|
|
|
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_sendmany",params)); |
|
|
|
} |
|
|
@ -81,6 +99,8 @@ char *jumblr_sendt_to_z(struct supernet_info *myinfo,struct iguana_info *coin,ch |
|
|
|
char *jumblr_sendz_to_z(struct supernet_info *myinfo,struct iguana_info *coin,char *zaddrS,char *zaddrD,double amount) |
|
|
|
{ |
|
|
|
char params[1024]; double fee = (amount-2*JUMBLR_TXFEE) * JUMBLR_FEE; |
|
|
|
if ( jumblr_addresstype(myinfo,coin,zaddrS) != 'z' || jumblr_addresstype(myinfo,coin,zaddrD) != 'z' ) |
|
|
|
return(clonestr("{\"error\":\"illegal address in z to z\"}")); |
|
|
|
sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); |
|
|
|
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_sendmany",params)); |
|
|
|
} |
|
|
@ -88,6 +108,8 @@ char *jumblr_sendz_to_z(struct supernet_info *myinfo,struct iguana_info *coin,ch |
|
|
|
char *jumblr_sendz_to_t(struct supernet_info *myinfo,struct iguana_info *coin,char *zaddr,char *taddr,double amount) |
|
|
|
{ |
|
|
|
char params[1024]; double fee = (amount-JUMBLR_TXFEE) * JUMBLR_FEE; |
|
|
|
if ( jumblr_addresstype(myinfo,coin,zaddr) != 'z' || jumblr_addresstype(myinfo,coin,taddr) != 't' ) |
|
|
|
return(clonestr("{\"error\":\"illegal address in z to t\"}")); |
|
|
|
sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddr,taddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); |
|
|
|
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_sendmany",params)); |
|
|
|
} |
|
|
@ -120,24 +142,18 @@ char *jumblr_zgetbalance(struct supernet_info *myinfo,struct iguana_info *coin,c |
|
|
|
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_getbalance",params)); |
|
|
|
} |
|
|
|
|
|
|
|
char *jumblr_listunspent(struct supernet_info *myinfo,struct iguana_info *coin,char *addr) |
|
|
|
{ |
|
|
|
char params[1024]; |
|
|
|
sprintf(params,"[1, 99999999, [\"%s\"]]",addr); |
|
|
|
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"listunspent",params)); |
|
|
|
} |
|
|
|
|
|
|
|
int64_t jumblr_receivedby(struct supernet_info *myinfo,struct iguana_info *coin,char *addr) |
|
|
|
{ |
|
|
|
char *retstr; int64_t total = 0; //cJSON *retjson,*item; int32_t i,n;
|
|
|
|
char *retstr; int64_t total = 0; |
|
|
|
if ( (retstr= jumblr_getreceivedbyaddress(myinfo,coin,addr)) != 0 ) |
|
|
|
{ |
|
|
|
printf("jumblr_getreceivedbyaddress.(%s) -> (%s)\n",addr,retstr); |
|
|
|
/*if ( (retjson= cJSON_Parse(retstr)) != 0 )
|
|
|
|
{ |
|
|
|
if ( (n= cJSON_GetArraySize(retjson)) > 0 ) |
|
|
|
{ |
|
|
|
for (i=0; i<n; i++) |
|
|
|
{ |
|
|
|
item = jitem(retjson,i); |
|
|
|
total += jdouble(item,"amount") * SATOSHIDEN; |
|
|
|
} |
|
|
|
} |
|
|
|
free_json(retjson); |
|
|
|
}*/ |
|
|
|
total = atof(retstr) * SATOSHIDEN; |
|
|
|
free(retstr); |
|
|
|
} |
|
|
@ -146,16 +162,20 @@ int64_t jumblr_receivedby(struct supernet_info *myinfo,struct iguana_info *coin, |
|
|
|
|
|
|
|
int64_t jumblr_balance(struct supernet_info *myinfo,struct iguana_info *coin,char *addr) |
|
|
|
{ |
|
|
|
char *retstr; double val; cJSON *retjson; int64_t balance = 0; |
|
|
|
if ( strlen(addr) < 40 ) |
|
|
|
char *retstr; double val; cJSON *retjson; int32_t i,n; int64_t balance = 0; |
|
|
|
if ( jumblr_addresstype(myinfo,coin,addr) == 't' ) |
|
|
|
{ |
|
|
|
if ( (retstr= _dex_getbalance(myinfo,coin->symbol,addr)) != 0 ) |
|
|
|
if ( (retstr= jumblr_listunspent(myinfo,coin,addr)) != 0 ) |
|
|
|
{ |
|
|
|
if ( (retjson= cJSON_Parse(retstr)) != 0 ) |
|
|
|
{ |
|
|
|
balance = jdouble(retjson,"balance") * SATOSHIDEN; |
|
|
|
if ( (n= cJSON_GetArraySize(retjson)) > 0 ) |
|
|
|
for (i=0; i<n; i++) |
|
|
|
balance += SATOSHIDEN * jdouble(jitem(retjson,i),"amount"); |
|
|
|
free_json(retjson); |
|
|
|
} |
|
|
|
//if ( balance == 0 )
|
|
|
|
// printf("listunspent.(%s)\n",addr);
|
|
|
|
free(retstr); |
|
|
|
} |
|
|
|
} |
|
|
@ -168,7 +188,7 @@ int64_t jumblr_balance(struct supernet_info *myinfo,struct iguana_info *coin,cha |
|
|
|
return(balance); |
|
|
|
} |
|
|
|
|
|
|
|
void jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status) |
|
|
|
int32_t jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status) |
|
|
|
{ |
|
|
|
cJSON *params,*amounts,*dest; char *from,*addr; int32_t i,n; int64_t amount; |
|
|
|
/*"params" : {
|
|
|
@ -184,6 +204,7 @@ void jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status) |
|
|
|
}*/ |
|
|
|
if ( (params= jobj(item,"params")) != 0 ) |
|
|
|
{ |
|
|
|
//printf("params.(%s)\n",jprint(params,0));
|
|
|
|
if ( (from= jstr(params,"fromaddress")) != 0 ) |
|
|
|
safecopy(ptr->src,from,sizeof(ptr->src)); |
|
|
|
if ( (amounts= jarray(&n,params,"amounts")) != 0 ) |
|
|
@ -191,6 +212,7 @@ void jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status) |
|
|
|
for (i=0; i<n; i++) |
|
|
|
{ |
|
|
|
dest = jitem(amounts,i); |
|
|
|
//printf("%s ",jprint(dest,0));
|
|
|
|
if ( (addr= jstr(dest,"address")) != 0 && (amount= jdouble(dest,"amount")*SATOSHIDEN) > 0 ) |
|
|
|
{ |
|
|
|
if ( strcmp(addr,JUMBLR_ADDR) == 0 ) |
|
|
@ -205,19 +227,36 @@ void jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status) |
|
|
|
} |
|
|
|
ptr->txfee = jdouble(params,"fee") * SATOSHIDEN; |
|
|
|
} |
|
|
|
return(1); |
|
|
|
} |
|
|
|
|
|
|
|
void jumblr_opidupdate(struct supernet_info *myinfo,struct iguana_info *coin,struct jumblr_item *ptr) |
|
|
|
{ |
|
|
|
char *retstr,*status; cJSON *retjson; |
|
|
|
char *retstr,*status; cJSON *retjson,*item; |
|
|
|
if ( ptr->status == 0 ) |
|
|
|
{ |
|
|
|
if ( (retstr= jumblr_zgetoperationresult(myinfo,coin,ptr->opid)) != 0 ) |
|
|
|
if ( (retstr= jumblr_zgetoperationstatus(myinfo,coin,ptr->opid)) != 0 ) |
|
|
|
{ |
|
|
|
if ( (retjson= cJSON_Parse(retstr)) != 0 ) |
|
|
|
{ |
|
|
|
if ( (status= jstr(retjson,"status")) != 0 && strcmp(status,"pending") != 0 ) |
|
|
|
jumblr_itemset(ptr,retjson,status); |
|
|
|
if ( cJSON_GetArraySize(retjson) == 1 ) |
|
|
|
{ |
|
|
|
item = jitem(retjson,0); |
|
|
|
//printf("%s\n",jprint(item,0));
|
|
|
|
if ( (status= jstr(item,"status")) != 0 ) |
|
|
|
{ |
|
|
|
if ( strcmp(status,"success") == 0 ) |
|
|
|
{ |
|
|
|
ptr->status = jumblr_itemset(ptr,item,status); |
|
|
|
} |
|
|
|
else if ( strcmp(status,"failed") == 0 ) |
|
|
|
{ |
|
|
|
printf("%s failed\n",ptr->opid); |
|
|
|
free(jumblr_zgetoperationresult(myinfo,coin,ptr->opid)); |
|
|
|
ptr->status = -1; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
free_json(retjson); |
|
|
|
} |
|
|
|
free(retstr); |
|
|
@ -225,6 +264,29 @@ void jumblr_opidupdate(struct supernet_info *myinfo,struct iguana_info *coin,str |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void jumblr_prune(struct supernet_info *myinfo,struct iguana_info *coin,struct jumblr_item *ptr) |
|
|
|
{ |
|
|
|
struct jumblr_item *tmp; char oldsrc[128]; int32_t flag = 1; |
|
|
|
printf("PRUNE %s\n",ptr->opid); |
|
|
|
strcpy(oldsrc,ptr->src); |
|
|
|
free(jumblr_zgetoperationresult(myinfo,coin,ptr->opid)); |
|
|
|
while ( flag != 0 ) |
|
|
|
{ |
|
|
|
flag = 0; |
|
|
|
HASH_ITER(hh,myinfo->jumblrs,ptr,tmp) |
|
|
|
{ |
|
|
|
if ( strcmp(oldsrc,ptr->dest) == 0 ) |
|
|
|
{ |
|
|
|
printf("prune %s (%s -> %s) matched oldsrc\n",ptr->opid,ptr->src,ptr->dest); |
|
|
|
free(jumblr_zgetoperationresult(myinfo,coin,ptr->opid)); |
|
|
|
strcpy(oldsrc,ptr->src); |
|
|
|
flag = 1; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void jumblr_opidsupdate(struct supernet_info *myinfo,struct iguana_info *coin) |
|
|
|
{ |
|
|
|
char *retstr; cJSON *array; int32_t i,n; struct jumblr_item *ptr; |
|
|
@ -235,8 +297,16 @@ void jumblr_opidsupdate(struct supernet_info *myinfo,struct iguana_info *coin) |
|
|
|
if ( (n= cJSON_GetArraySize(array)) > 0 ) |
|
|
|
{ |
|
|
|
for (i=0; i<n; i++) |
|
|
|
if ( (ptr= jumblr_opidadd(myinfo,coin,jstri(array,i))) != 0 && ptr->status == 0 ) |
|
|
|
jumblr_opidupdate(myinfo,coin,ptr); |
|
|
|
{ |
|
|
|
if ( (ptr= jumblr_opidadd(myinfo,coin,jstri(array,i))) != 0 ) |
|
|
|
{ |
|
|
|
if ( ptr->status == 0 ) |
|
|
|
jumblr_opidupdate(myinfo,coin,ptr); |
|
|
|
printf("%d: %s -> %s %.8f\n",ptr->status,ptr->src,ptr->dest,dstr(ptr->amount)); |
|
|
|
if ( jumblr_addresstype(myinfo,coin,ptr->src) == 'z' && jumblr_addresstype(myinfo,coin,ptr->dest) == 't' ) |
|
|
|
jumblr_prune(myinfo,coin,ptr); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
free_json(array); |
|
|
|
} |
|
|
@ -272,7 +342,7 @@ r = 0; |
|
|
|
priv0 = jumblr_privkey(myinfo,BTCaddr,KMDaddr,JUMBLR_DEPOSITPREFIX); |
|
|
|
if ( (total= jumblr_balance(myinfo,coin,KMDaddr)) >= (JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE))*SATOSHIDEN ) |
|
|
|
{ |
|
|
|
if ( (r & 7) == 0 ) |
|
|
|
if ( (r & 1) == 0 ) |
|
|
|
{ |
|
|
|
if ( (zaddr= jumblr_zgetnewaddress(myinfo,coin)) != 0 ) |
|
|
|
{ |
|
|
@ -289,15 +359,15 @@ r = 0; |
|
|
|
free(zaddr); |
|
|
|
} else printf("no zaddr from jumblr_zgetnewaddress\n"); |
|
|
|
} |
|
|
|
} else printf("%s total %.8f vs %.8f\n",KMDaddr,dstr(total),(JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE))); |
|
|
|
} //else printf("%s total %.8f vs %.8f\n",KMDaddr,dstr(total),(JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE)));
|
|
|
|
break; |
|
|
|
case 1: // z -> z
|
|
|
|
jumblr_opidsupdate(myinfo,coin); |
|
|
|
HASH_ITER(hh,myinfo->jumblrs,ptr,tmp) |
|
|
|
{ |
|
|
|
if ( strlen(ptr->src) < 40 ) |
|
|
|
if ( jumblr_addresstype(myinfo,coin,ptr->src) == 't' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' ) |
|
|
|
{ |
|
|
|
if ( (r & 7) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) |
|
|
|
if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) |
|
|
|
{ |
|
|
|
if ( (zaddr= jumblr_zgetnewaddress(myinfo,coin)) != 0 ) |
|
|
|
{ |
|
|
@ -318,9 +388,9 @@ r = 0; |
|
|
|
jumblr_opidsupdate(myinfo,coin); |
|
|
|
HASH_ITER(hh,myinfo->jumblrs,ptr,tmp) |
|
|
|
{ |
|
|
|
if ( strlen(ptr->src) >= 40 ) |
|
|
|
if ( jumblr_addresstype(myinfo,coin,ptr->src) == 'z' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' ) |
|
|
|
{ |
|
|
|
if ( (r & 7) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) |
|
|
|
if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) |
|
|
|
{ |
|
|
|
priv0 = jumblr_privkey(myinfo,BTCaddr,KMDaddr,""); |
|
|
|
if ( (retstr= jumblr_sendz_to_t(myinfo,coin,ptr->dest,KMDaddr,dstr(total))) != 0 ) |
|
|
@ -367,7 +437,7 @@ STRING_ARG(jumblr,setpassphrase,passphrase) |
|
|
|
|
|
|
|
ZERO_ARGS(jumblr,status) |
|
|
|
{ |
|
|
|
cJSON *retjson; char KMDaddr[64],BTCaddr[64]; struct jumblr_item *ptr,*tmp; int64_t deposited,step_t2z,step_z2z,step_z2t,finished; |
|
|
|
cJSON *retjson; char KMDaddr[64],BTCaddr[64]; struct jumblr_item *ptr,*tmp; int64_t received,deposited,jumblred,step_t2z,step_z2z,step_z2t,finished; |
|
|
|
if ( strcmp(coin->symbol,"KMD") == 0 && coin->FULLNODE < 0 && myinfo->jumblr_passphrase[0] != 0 ) |
|
|
|
{ |
|
|
|
jumblr_opidsupdate(myinfo,coin); |
|
|
@ -376,11 +446,13 @@ ZERO_ARGS(jumblr,status) |
|
|
|
jumblr_privkey(myinfo,BTCaddr,KMDaddr,JUMBLR_DEPOSITPREFIX); |
|
|
|
jaddstr(retjson,"BTCdeposit","notyet"); |
|
|
|
jaddstr(retjson,"KMDdeposit",KMDaddr); |
|
|
|
deposited = jumblr_receivedby(myinfo,coin,KMDaddr); |
|
|
|
received = jumblr_receivedby(myinfo,coin,KMDaddr); |
|
|
|
deposited = jumblr_balance(myinfo,coin,KMDaddr); |
|
|
|
jumblr_privkey(myinfo,BTCaddr,KMDaddr,""); |
|
|
|
jaddstr(retjson,"BTCjumblr","notyet"); |
|
|
|
jaddstr(retjson,"KMDjumblr",KMDaddr); |
|
|
|
finished = jumblr_receivedby(myinfo,coin,KMDaddr); |
|
|
|
jumblred = jumblr_balance(myinfo,coin,KMDaddr); |
|
|
|
HASH_ITER(hh,myinfo->jumblrs,ptr,tmp) |
|
|
|
{ |
|
|
|
if ( strlen(ptr->src) >= 40 ) |
|
|
@ -388,16 +460,16 @@ ZERO_ARGS(jumblr,status) |
|
|
|
if ( strlen(ptr->dest) >= 40 ) |
|
|
|
step_z2z += ptr->amount; |
|
|
|
else step_z2t += ptr->amount; |
|
|
|
} |
|
|
|
else step_t2z += ptr->amount; |
|
|
|
} else step_t2z += ptr->amount; |
|
|
|
} |
|
|
|
jaddstr(retjson,"result","success"); |
|
|
|
jaddnum(retjson,"deposited",dstr(deposited)); |
|
|
|
jaddnum(retjson,"deposits",dstr(deposited)); |
|
|
|
jaddnum(retjson,"t_to_z",dstr(step_t2z)); |
|
|
|
jaddnum(retjson,"z_to_z",dstr(step_z2z)); |
|
|
|
jaddnum(retjson,"z_to_t",dstr(step_z2t)); |
|
|
|
jaddnum(retjson,"jumblred",dstr(jumblred)); |
|
|
|
jaddnum(retjson,"received",dstr(received)); |
|
|
|
jaddnum(retjson,"finished",dstr(finished)); |
|
|
|
jaddnum(retjson,"pending",dstr(deposited) - dstr(finished)); |
|
|
|
return(jprint(retjson,1)); |
|
|
|
} else return(clonestr("{\"error\":\"no passphrase or no native komodod\"}")); |
|
|
|
} |
|
|
|