You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1540 lines
61 KiB
1540 lines
61 KiB
/******************************************************************************
|
|
* Copyright © 2014-2016 The SuperNET Developers. *
|
|
* *
|
|
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
|
* the top-level directory of this distribution for the individual copyright *
|
|
* holder information and the developer policies on copyright and licensing. *
|
|
* *
|
|
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
|
* SuperNET software, including this file may be copied, modified, propagated *
|
|
* or distributed except according to the terms contained in the LICENSE file *
|
|
* *
|
|
* Removal or modification of this copyright notice is prohibited. *
|
|
* *
|
|
******************************************************************************/
|
|
|
|
#include "iguana777.h"
|
|
#include "exchanges/bitcoin.h"
|
|
|
|
void scrubfree(char *sensitivestr)
|
|
{
|
|
long len,i;
|
|
if ( sensitivestr != 0 )
|
|
{
|
|
len = strlen(sensitivestr);
|
|
memset(sensitivestr,0,len);
|
|
for (i=0; i<len; i++)
|
|
sensitivestr[i] = rand();
|
|
free(sensitivestr);
|
|
}
|
|
}
|
|
|
|
struct iguana_waddress *iguana_waddressfind(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount *wacct,char *coinaddr)
|
|
{
|
|
struct iguana_waddress *waddr; uint8_t addrtype,rmd160[20];
|
|
bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr);
|
|
HASH_FIND(hh,wacct->waddr,rmd160,sizeof(rmd160),waddr);
|
|
//if ( waddr != 0 && coin != 0 && strcmp(coin->symbol,waddr->symbol) != 0 )
|
|
// return(0);
|
|
//printf("%s (%s).%d in (%s)\n",waddr==0?"couldnt find":"found",coinaddr,len,wacct->account);
|
|
return(waddr);
|
|
}
|
|
|
|
struct iguana_waddress *iguana_waddressalloc(uint8_t addrtype,char *symbol,char *coinaddr,char *redeemScript)
|
|
{
|
|
struct iguana_waddress *waddr; int32_t scriptlen;
|
|
scriptlen = (redeemScript != 0) ? ((int32_t)strlen(redeemScript) >> 1) : 0;
|
|
waddr = mycalloc('w',1,sizeof(*waddr) + scriptlen);
|
|
waddr->addrtype = addrtype;
|
|
strcpy(waddr->coinaddr,coinaddr);
|
|
bitcoin_addr2rmd160(&addrtype,waddr->rmd160,coinaddr);
|
|
strcpy(waddr->symbol,symbol);
|
|
if ( (waddr->scriptlen= scriptlen) != 0 )
|
|
decode_hex(waddr->redeemScript,scriptlen,redeemScript);
|
|
return(waddr);
|
|
}
|
|
|
|
struct iguana_waccount *iguana_waccountfind(struct supernet_info *myinfo,struct iguana_info *coin,char *account)
|
|
{
|
|
struct iguana_waccount *wacct;
|
|
HASH_FIND(hh,myinfo->wallet,account,strlen(account)+1,wacct);
|
|
//printf("waccountfind.(%s) -> wacct.%p\n",account,wacct);
|
|
return(wacct);
|
|
}
|
|
|
|
struct iguana_waccount *iguana_waccountcreate(struct supernet_info *myinfo,struct iguana_info *coin,char *account)
|
|
{
|
|
struct iguana_waccount *wacct,*ptr; int32_t len = (int32_t)strlen(account)+1;
|
|
HASH_FIND(hh,myinfo->wallet,account,len,wacct);
|
|
if ( wacct == 0 )
|
|
{
|
|
wacct = mycalloc('w',1,sizeof(*wacct));
|
|
strcpy(wacct->account,account);
|
|
HASH_ADD_KEYPTR(hh,myinfo->wallet,wacct->account,len,wacct);
|
|
//printf("waccountcreate.(%s) -> wacct.%p\n",account,wacct);
|
|
myinfo->dirty = (uint32_t)time(NULL);
|
|
if ( (ptr= iguana_waccountfind(myinfo,coin,account)) != wacct )
|
|
printf("iguana_waccountcreate verify error %p vs %p\n",ptr,wacct);
|
|
}
|
|
return(wacct);
|
|
}
|
|
|
|
struct iguana_waddress *iguana_waddresscreate(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount *wacct,char *coinaddr,char *redeemScript)
|
|
{
|
|
struct iguana_waddress *waddr,*ptr; uint8_t rmd160[20],addrtype;
|
|
bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr);
|
|
if ( wacct == 0 )
|
|
wacct = iguana_waccountcreate(myinfo,coin,"");
|
|
HASH_FIND(hh,wacct->waddr,rmd160,sizeof(rmd160),waddr);
|
|
if ( waddr == 0 )
|
|
{
|
|
if ( (waddr= iguana_waddressalloc(redeemScript==0?coin->chain->pubtype : coin->chain->p2shtype,coin->symbol,coinaddr,redeemScript)) != 0 )
|
|
{
|
|
HASH_ADD_KEYPTR(hh,wacct->waddr,waddr->rmd160,sizeof(waddr->rmd160),waddr);
|
|
myinfo->dirty = (uint32_t)time(NULL);
|
|
printf("create (%s)scriptlen.%d -> (%s)\n",coinaddr,waddr->scriptlen,wacct->account);
|
|
} else printf("error iguana_waddressalloc null waddr\n");
|
|
} //else printf("have (%s) in (%s)\n",coinaddr,wacct->account);
|
|
if ( (ptr= iguana_waddressfind(myinfo,coin,wacct,coinaddr)) != waddr )
|
|
printf("iguana_waddresscreate verify error %p vs %p\n",ptr,waddr);
|
|
return(waddr);
|
|
}
|
|
|
|
struct iguana_waddress *iguana_waddressadd(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount *wacct,struct iguana_waddress *addwaddr,char *redeemScript)
|
|
{
|
|
struct iguana_waddress *waddr,*ptr; uint8_t rmd160[20],addrtype;
|
|
bitcoin_addr2rmd160(&addrtype,rmd160,addwaddr->coinaddr);
|
|
HASH_FIND(hh,wacct->waddr,rmd160,sizeof(rmd160),waddr);
|
|
if ( waddr == 0 )
|
|
{
|
|
if ( (waddr= iguana_waddressalloc(redeemScript==0?coin->chain->pubtype : coin->chain->p2shtype,coin->symbol,addwaddr->coinaddr,redeemScript)) == 0 )
|
|
{
|
|
printf("error iguana_waddressalloc null waddr\n");
|
|
return(0);
|
|
}
|
|
} //else printf("have (%s) in (%s)\n",waddr->coinaddr,wacct->account);
|
|
if ( waddr != 0 && waddr != addwaddr )
|
|
{
|
|
myinfo->dirty = (uint32_t)time(NULL);
|
|
waddr->wiftype = coin->chain->wiftype;
|
|
if ( redeemScript != 0 && (addwaddr->scriptlen= (int32_t)strlen(redeemScript) >> 1) != 0 )
|
|
{
|
|
if ( waddr->scriptlen != addwaddr->scriptlen )
|
|
{
|
|
if ( waddr->scriptlen < addwaddr->scriptlen )
|
|
{
|
|
printf("unexpected waddr->scriptlen mismatch\n");
|
|
}
|
|
waddr->scriptlen = addwaddr->scriptlen;
|
|
decode_hex(waddr->redeemScript,waddr->scriptlen,redeemScript);
|
|
}
|
|
waddr->addrtype = coin->chain->p2shtype;
|
|
memset(&waddr->privkey,0,sizeof(waddr->privkey));
|
|
memset(waddr->pubkey,0,sizeof(waddr->pubkey));
|
|
calc_rmd160_sha256(waddr->rmd160,waddr->redeemScript,waddr->scriptlen);
|
|
}
|
|
else
|
|
{
|
|
waddr->addrtype = coin->chain->pubtype;
|
|
waddr->wiftype = addwaddr->wiftype;
|
|
if ( bits256_nonz(waddr->privkey) == 0 )
|
|
waddr->privkey = addwaddr->privkey;
|
|
if ( addwaddr->wifstr[0] != 0 )
|
|
strcpy(waddr->wifstr,addwaddr->wifstr);
|
|
memcpy(waddr->pubkey,addwaddr->pubkey,sizeof(waddr->pubkey));
|
|
calc_rmd160_sha256(waddr->rmd160,waddr->pubkey,bitcoin_pubkeylen(waddr->pubkey));
|
|
}
|
|
bitcoin_address(waddr->coinaddr,waddr->addrtype,waddr->rmd160,sizeof(waddr->rmd160));
|
|
myinfo->dirty = (uint32_t)time(NULL);
|
|
}
|
|
if ( (ptr= iguana_waddressfind(myinfo,coin,wacct,waddr->coinaddr)) != waddr )
|
|
{
|
|
HASH_ADD_KEYPTR(hh,wacct->waddr,waddr->rmd160,sizeof(waddr->rmd160),waddr);
|
|
myinfo->dirty = (uint32_t)time(NULL);
|
|
//printf("add (%s).%d scriptlen.%d -> (%s) wif.(%s)\n",waddr->coinaddr,len,waddr->scriptlen,wacct->account,waddr->wifstr);
|
|
}
|
|
if ( waddr != 0 && waddr->symbol[0] == 0 )
|
|
strcpy(waddr->symbol,coin->symbol);
|
|
return(waddr);
|
|
}
|
|
|
|
struct iguana_waddress *iguana_waddressdelete(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount *wacct,char *coinaddr)
|
|
{
|
|
struct iguana_waddress *waddr = 0; uint8_t rmd160[20],addrtype;
|
|
bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr);
|
|
HASH_FIND(hh,wacct->waddr,rmd160,sizeof(rmd160),waddr);
|
|
if ( waddr != 0 )
|
|
{
|
|
HASH_DELETE(hh,wacct->waddr,waddr);
|
|
myinfo->dirty = (uint32_t)time(NULL);
|
|
}
|
|
return(waddr);
|
|
}
|
|
|
|
struct iguana_waddress *iguana_waddresssearch(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount **wacctp,char *coinaddr)
|
|
{
|
|
struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr;
|
|
HASH_ITER(hh,myinfo->wallet,wacct,tmp)
|
|
{
|
|
if ( (waddr= iguana_waddressfind(myinfo,coin,wacct,coinaddr)) != 0 )
|
|
{
|
|
if ( waddr != 0 && bits256_nonz(waddr->privkey) != 0 )
|
|
{
|
|
if ( bitcoin_priv2wif(waddr->wifstr,waddr->privkey,coin->chain->wiftype) > 0 )
|
|
{
|
|
if ( 0 && waddr->wiftype != coin->chain->wiftype )
|
|
printf("waddresssearch warning: mismatched wiftype %02x != %02x\n",waddr->wiftype,coin->chain->wiftype);
|
|
if ( 0 && waddr->addrtype != coin->chain->pubtype )
|
|
printf("waddresssearch warning: mismatched addrtype %02x != %02x\n",waddr->addrtype,coin->chain->pubtype);
|
|
}
|
|
}
|
|
(*wacctp) = wacct;
|
|
return(waddr);
|
|
}
|
|
}
|
|
(*wacctp) = 0;
|
|
return(0);
|
|
}
|
|
|
|
struct iguana_waddress *iguana_waddresscalc(struct supernet_info *myinfo,uint8_t pubtype,uint8_t wiftype,struct iguana_waddress *waddr,bits256 privkey)
|
|
{
|
|
waddr->privkey = privkey;
|
|
bitcoin_address(waddr->coinaddr,pubtype,waddr->rmd160,sizeof(waddr->rmd160));
|
|
if ( bits256_nonz(privkey) != 0 )
|
|
{
|
|
bitcoin_pubkey33(myinfo->ctx,waddr->pubkey,waddr->privkey);
|
|
calc_rmd160_sha256(waddr->rmd160,waddr->pubkey,33);
|
|
myinfo->dirty = (uint32_t)time(NULL);
|
|
if ( bitcoin_priv2wif(waddr->wifstr,waddr->privkey,wiftype) > 0 )
|
|
{
|
|
waddr->wiftype = wiftype;
|
|
waddr->addrtype = pubtype;
|
|
return(waddr);
|
|
}
|
|
} else printf("waddress_calc.(%s) null privkey\n",waddr->coinaddr);
|
|
return(0);
|
|
}
|
|
|
|
struct iguana_waddress *iguana_waccountswitch(struct supernet_info *myinfo,struct iguana_info *coin,char *account,char *coinaddr,char *redeemScript)
|
|
{
|
|
struct iguana_waccount *wacct = 0; struct iguana_waddress addr,*waddr = 0; int32_t flag = 0;
|
|
if ( (waddr= iguana_waddresssearch(myinfo,coin,&wacct,coinaddr)) != 0 )
|
|
{
|
|
if ( strcmp(wacct->account,account) != 0 )
|
|
{
|
|
addr = *waddr;
|
|
flag = 1;
|
|
iguana_waddressdelete(myinfo,coin,wacct,coinaddr);
|
|
}
|
|
}
|
|
if ( (wacct= iguana_waccountcreate(myinfo,coin,account)) != 0 )
|
|
{
|
|
waddr = iguana_waddresscreate(myinfo,coin,wacct,coinaddr,redeemScript);
|
|
if ( flag != 0 && redeemScript == 0 )
|
|
iguana_waddresscalc(myinfo,coin->chain->pubtype,coin->chain->wiftype,waddr,addr.privkey);
|
|
}
|
|
return(waddr);
|
|
}
|
|
|
|
uint8_t *iguana_walletrmds(struct supernet_info *myinfo,struct iguana_info *coin,int32_t *numrmdsp)
|
|
{
|
|
int32_t iter,n,m; struct iguana_waccount *acct,*tmp; uint8_t *pubkeys,*addrtypes,*rmdarray = 0; struct iguana_waddress *waddr,*tmp2;
|
|
for (iter=n=m=0; iter<2; iter++)
|
|
{
|
|
HASH_ITER(hh,myinfo->wallet,acct,tmp)
|
|
{
|
|
HASH_ITER(hh,acct->waddr,waddr,tmp2)
|
|
{
|
|
if ( iter == 0 )
|
|
n++;
|
|
else if ( m < n )
|
|
{
|
|
addrtypes[m] = waddr->addrtype;
|
|
memcpy(&rmdarray[m * 20],waddr->rmd160,20);
|
|
memcpy(&pubkeys[m * 33],waddr->pubkey,33);
|
|
m++;
|
|
}
|
|
}
|
|
}
|
|
if ( iter == 0 )
|
|
{
|
|
rmdarray = calloc(n,20 + 1 + 33);
|
|
addrtypes = &rmdarray[n * 20];
|
|
pubkeys = &rmdarray[n * 21];
|
|
}
|
|
}
|
|
return(rmdarray);
|
|
}
|
|
|
|
cJSON *iguana_getaddressesbyaccount(struct supernet_info *myinfo,struct iguana_info *coin,char *account)
|
|
{
|
|
struct iguana_waccount *subset,*tmp; char coinaddr[64]; struct iguana_waddress *waddr,*tmp2; cJSON *retjson,*array;
|
|
retjson = cJSON_CreateObject();
|
|
array = cJSON_CreateArray();
|
|
if ( account == 0 )
|
|
account = "*";
|
|
if ( strcmp("*",account) != 0 )
|
|
{
|
|
if ( (subset= iguana_waccountfind(myinfo,coin,account)) != 0 )
|
|
{
|
|
HASH_ITER(hh,subset->waddr,waddr,tmp2)
|
|
{
|
|
bitcoin_address(coinaddr,coin->chain->pubtype,waddr->rmd160,20);
|
|
jaddistr(array,coinaddr);
|
|
}
|
|
} else jaddstr(retjson,"result","cant find account");
|
|
}
|
|
else
|
|
{
|
|
HASH_ITER(hh,myinfo->wallet,subset,tmp)
|
|
{
|
|
HASH_ITER(hh,subset->waddr,waddr,tmp2)
|
|
{
|
|
bitcoin_address(coinaddr,coin->chain->pubtype,waddr->rmd160,20);
|
|
jaddistr(array,coinaddr);
|
|
}
|
|
}
|
|
}
|
|
return(array);
|
|
}
|
|
|
|
struct iguana_waddress *iguana_ismine(struct supernet_info *myinfo,struct iguana_info *coin,uint8_t addrtype,uint8_t pubkey[65],uint8_t rmd160[20])
|
|
{
|
|
char coinaddr[65]; struct iguana_waccount *wacct; struct iguana_waddress *waddr = 0;
|
|
if ( bitcoin_address(coinaddr,addrtype,rmd160,20) > 0 )
|
|
waddr = iguana_waddresssearch(myinfo,coin,&wacct,coinaddr);
|
|
return(waddr);
|
|
}
|
|
|
|
int32_t iguana_addressvalidate(struct iguana_info *coin,uint8_t *addrtypep,char *address)
|
|
{
|
|
char checkaddr[64]; uint8_t rmd160[20];
|
|
*addrtypep = 0;
|
|
memset(rmd160,0,sizeof(rmd160));
|
|
bitcoin_addr2rmd160(addrtypep,rmd160,address);
|
|
//int32_t i; for (i=0; i<20; i++)
|
|
// printf("%02x",rmd160[i]); // 764692cd5473f62ffa8a93e55d876f567623de07
|
|
//printf(" rmd160 addrtype.%02x\n",*addrtypep);
|
|
if ( bitcoin_address(checkaddr,*addrtypep,rmd160,20) == checkaddr && strcmp(address,checkaddr) == 0 && (*addrtypep == coin->chain->pubtype || *addrtypep == coin->chain->p2shtype) )
|
|
return(0);
|
|
else
|
|
{
|
|
//printf(" checkaddr.(%s) address.(%s) type.%02x vs (%02x %02x)\n",checkaddr,address,*addrtypep,coin->chain->pubtype,coin->chain->p2shtype);
|
|
return(-1);
|
|
}
|
|
}
|
|
|
|
cJSON *iguana_waddressjson(struct iguana_info *coin,cJSON *item,struct iguana_waddress *waddr)
|
|
{
|
|
char str[256],redeemScript[4096],coinaddr[64];
|
|
if ( item == 0 )
|
|
item = cJSON_CreateObject();
|
|
bitcoin_address(coinaddr,coin->chain->pubtype,waddr->rmd160,20);
|
|
jaddstr(item,"address",coinaddr);
|
|
//jaddstr(item,"privkey",bits256_str(str,waddr->privkey));
|
|
//jaddstr(item,"wif",waddr->wifstr);
|
|
init_hexbytes_noT(str,waddr->rmd160,20);
|
|
jaddstr(item,"rmd160",str);
|
|
jaddstr(item,"coin",waddr->symbol);
|
|
if ( waddr->scriptlen > 0 )
|
|
{
|
|
init_hexbytes_noT(redeemScript,waddr->redeemScript,waddr->scriptlen);
|
|
jaddstr(item,"redeemScript",redeemScript);
|
|
}
|
|
else
|
|
{
|
|
init_hexbytes_noT(str,waddr->pubkey,33);
|
|
jaddstr(item,"pubkey",str);
|
|
}
|
|
return(item);
|
|
}
|
|
|
|
char *setaccount(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waddress **waddrp,char *account,char *coinaddr,char *redeemScript)
|
|
{
|
|
uint8_t addrtype; struct iguana_waddress *waddr=0;
|
|
if ( waddrp != 0 )
|
|
*waddrp = 0;
|
|
if ( coinaddr != 0 && coinaddr[0] != 0 && account != 0 && account[0] != 0 )
|
|
{
|
|
if ( iguana_addressvalidate(coin,&addrtype,coinaddr) < 0 )
|
|
return(clonestr("{\"error\":\"invalid coin address\"}"));
|
|
if ( (waddr= iguana_waccountswitch(myinfo,coin,account,coinaddr,redeemScript)) != 0 )
|
|
{
|
|
if ( waddrp != 0 )
|
|
*waddrp = waddr;
|
|
return(clonestr("{\"result\":\"success\"}"));
|
|
}
|
|
else return(clonestr("{\"error\":\"couldnt set account\"}"));
|
|
}
|
|
return(clonestr("{\"error\":\"need address and account\"}"));
|
|
}
|
|
|
|
char *getaccount(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr)
|
|
{
|
|
struct iguana_waccount *wacct; struct iguana_waddress *waddr; uint8_t addrtype; cJSON *retjson;
|
|
if ( iguana_addressvalidate(coin,&addrtype,coinaddr) < 0 )
|
|
return(clonestr("{\"error\":\"invalid coin address\"}"));
|
|
if ( (waddr= iguana_waddresssearch(myinfo,coin,&wacct,coinaddr)) == 0 )
|
|
return(clonestr("{\"result\":\"no account for address\"}"));
|
|
if ( wacct != 0 )
|
|
{
|
|
retjson = iguana_waddressjson(coin,0,waddr);
|
|
jaddstr(retjson,"account",wacct->account);
|
|
jaddstr(retjson,"result","success");
|
|
return(jprint(retjson,1));
|
|
} else return(clonestr("{\"result\":\"\"}"));
|
|
}
|
|
|
|
char *jsuccess()
|
|
{
|
|
cJSON *retjson = cJSON_CreateObject();
|
|
return(jprint(retjson,1));
|
|
}
|
|
|
|
char *iguana_addressconv(struct iguana_info *coin,char *destaddr,struct iguana_info *other,int32_t isp2sh,uint8_t rmd160[20])
|
|
{
|
|
if ( bitcoin_address(destaddr,isp2sh != 0 ? other->chain->pubtype : other->chain->p2shtype,rmd160,20) == destaddr )
|
|
return(destaddr);
|
|
else return(0);
|
|
}
|
|
|
|
int32_t iguana_loginsave(struct supernet_info *myinfo,struct iguana_info *coin,char *newstr)
|
|
{
|
|
cJSON *loginjson; char *passphrase,destfname[1024];
|
|
if ( (loginjson= cJSON_Parse(newstr)) != 0 )
|
|
{
|
|
if ( (passphrase= jstr(loginjson,"passphrase")) != 0 )
|
|
{
|
|
_SuperNET_encryptjson(destfname,passphrase,0,myinfo->permanentfile,0,loginjson);
|
|
//printf("loginsave.(%s) <= (%s)\n",destfname,newstr);
|
|
//iguana_walletlock(myinfo);
|
|
}
|
|
free_json(loginjson);
|
|
return(0);
|
|
} return(-1);
|
|
}
|
|
|
|
char *iguana_walletvalue(char *buf,struct iguana_waddress *waddr)
|
|
{
|
|
if ( waddr->scriptlen > 0 )
|
|
init_hexbytes_noT(buf,waddr->redeemScript,waddr->scriptlen);
|
|
else init_hexbytes_noT(buf,waddr->privkey.bytes,sizeof(waddr->privkey));
|
|
return(buf);
|
|
}
|
|
|
|
int32_t iguana_payloadupdate(struct supernet_info *myinfo,struct iguana_info *coin,char *retstr,struct iguana_waddress *waddr,char *account)
|
|
{
|
|
cJSON *retjson,*accountobj,*payload; char rmdstr[41],*newstr,*valuestr,valuebuf[IGUANA_MAXSCRIPTSIZE*2+1]; int32_t retval = -1;
|
|
if ( (retjson= cJSON_Parse(retstr)) != 0 )
|
|
{
|
|
if ( account == 0 || account[0] == 0 )
|
|
account = "default";
|
|
payload = cJSON_DetachItemFromObject(retjson,"wallet");
|
|
if ( payload == 0 )
|
|
payload = cJSON_CreateObject();
|
|
if ( waddr != 0 && (valuestr= iguana_walletvalue(valuebuf,waddr)) != 0 )
|
|
{
|
|
init_hexbytes_noT(rmdstr,waddr->rmd160,20);
|
|
if ( (accountobj= jobj(payload,account)) != 0 && jobj(accountobj,rmdstr) != 0 )
|
|
{
|
|
free_json(retjson);
|
|
free_json(payload);
|
|
return(0);
|
|
}
|
|
if ( accountobj == 0 )
|
|
{
|
|
accountobj = cJSON_CreateObject();
|
|
jadd(payload,account,accountobj);
|
|
}
|
|
jaddstr(accountobj,rmdstr,valuestr);
|
|
}
|
|
jadd(retjson,"wallet",payload);
|
|
newstr = jprint(retjson,1);
|
|
retval = iguana_loginsave(myinfo,coin,newstr);
|
|
//printf("newstr.(%s) retval.%d\n",newstr,retval);
|
|
free(newstr);
|
|
} else printf("iguana_payloadupdate: error parsing.(%s)\n",retstr);
|
|
return(retval);
|
|
}
|
|
|
|
cJSON *iguana_payloadmerge(cJSON *loginjson,cJSON *importjson)
|
|
{
|
|
cJSON *retjson,*item,*obj; char *field;
|
|
if ( loginjson == 0 )
|
|
return(importjson);
|
|
else if ( importjson == 0 )
|
|
return(loginjson);
|
|
retjson = jduplicate(loginjson);
|
|
item = importjson->child;
|
|
while ( item != 0 )
|
|
{
|
|
if ( (field= jfieldname(item)) != 0 )
|
|
{
|
|
if ( (obj= jobj(retjson,field)) == 0 )
|
|
{
|
|
if ( strlen(field) == 20*2 )
|
|
jadd(retjson,field,item);
|
|
else jadd(retjson,field,item);
|
|
}
|
|
}
|
|
item = item->next;
|
|
}
|
|
return(retjson);
|
|
}
|
|
|
|
cJSON *iguana_walletadd(struct supernet_info *myinfo,struct iguana_waddress **waddrp,struct iguana_info *coin,char *retstr,char *account,struct iguana_waddress *refwaddr,int32_t setcurrent,char *redeemScript)
|
|
{
|
|
cJSON *retjson=0; struct iguana_waccount *wacct; struct iguana_waddress *waddr;
|
|
if ( (wacct= iguana_waccountfind(myinfo,coin,account)) == 0 )
|
|
wacct = iguana_waccountcreate(myinfo,coin,account);
|
|
if ( wacct != 0 )
|
|
{
|
|
//waddr = iguana_waddressfind(myinfo,coin,wacct,refwaddr->coinaddr);
|
|
waddr = iguana_waddressadd(myinfo,coin,wacct,refwaddr,redeemScript);
|
|
if ( setcurrent != 0 )
|
|
wacct->current = waddr;
|
|
if ( iguana_payloadupdate(myinfo,coin,retstr,waddr,account) < 0 )
|
|
{
|
|
retjson = cJSON_CreateObject();
|
|
jaddstr(retjson,"error","couldnt update wallet payload");
|
|
}
|
|
else
|
|
{
|
|
retjson = iguana_waddressjson(coin,retjson,waddr);
|
|
jaddstr(retjson,"account",account);
|
|
jaddstr(retjson,"result","success");
|
|
}
|
|
}
|
|
if ( waddrp != 0 )
|
|
(*waddrp) = waddr;
|
|
return(retjson);
|
|
}
|
|
|
|
cJSON *iguana_walletjson(struct supernet_info *myinfo)
|
|
{
|
|
struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr,*tmp2; cJSON *wallet,*account; char valuebuf[IGUANA_MAXSCRIPTSIZE*2+1],rmdstr[128];
|
|
wallet = cJSON_CreateObject();
|
|
HASH_ITER(hh,myinfo->wallet,wacct,tmp)
|
|
{
|
|
account = cJSON_CreateObject();
|
|
HASH_ITER(hh,wacct->waddr,waddr,tmp2)
|
|
{
|
|
if ( bits256_nonz(waddr->privkey) == 0 && waddr->scriptlen == 0 )
|
|
{
|
|
//free_json(account);
|
|
//free_json(wallet);
|
|
//printf("found a null privkey in wallet, abort saving\n");
|
|
//return(0);
|
|
}
|
|
init_hexbytes_noT(rmdstr,waddr->rmd160,sizeof(waddr->rmd160));
|
|
jaddstr(account,rmdstr,iguana_walletvalue(valuebuf,waddr));
|
|
}
|
|
jadd(wallet,wacct->account,account);
|
|
}
|
|
return(wallet);
|
|
}
|
|
|
|
char *iguana_walletfields(struct iguana_info *coin,int32_t *p2shflagp,char *wifstr,char *address,char *fieldstr,char *valuestr)
|
|
{
|
|
uint8_t rmd160[20],addrtype,script[IGUANA_MAXSCRIPTSIZE]; int32_t len; bits256 privkey;
|
|
*p2shflagp = 0;
|
|
if ( fieldstr != 0 && valuestr != 0 )
|
|
{
|
|
len = is_hexstr(fieldstr,0);
|
|
if ( len > 0 )
|
|
{
|
|
if ( len == 20*2 )
|
|
decode_hex(rmd160,sizeof(rmd160),fieldstr);
|
|
else
|
|
{
|
|
len >>= 1;
|
|
decode_hex(script,len,valuestr);
|
|
calc_rmd160_sha256(rmd160,script,len);
|
|
bitcoin_address(address,coin->chain->p2shtype,rmd160,20);
|
|
*p2shflagp = 1;
|
|
return(valuestr);
|
|
}
|
|
} else bitcoin_addr2rmd160(&addrtype,rmd160,fieldstr);
|
|
privkey = bits256_conv(valuestr);
|
|
bitcoin_priv2wif(wifstr,privkey,coin->chain->wiftype);
|
|
bitcoin_address(address,coin->chain->pubtype,rmd160,20);
|
|
return(wifstr);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
int32_t iguana_walletemit(struct supernet_info *myinfo,char *fname,struct iguana_info *coin,cJSON *array)
|
|
{
|
|
cJSON *item,*child; char str[64],wifstr[128],*account,coinaddr[64],*privstr; int32_t i,n,p2shflag; FILE *fp;
|
|
if ( (fp= fopen(fname,"wb")) == 0 )
|
|
return(-1);
|
|
n = cJSON_GetArraySize(array);
|
|
item = array->child;
|
|
for (i=0; i<n; i++)
|
|
{
|
|
if ( item != 0 && (account= item->string) != 0 )
|
|
{
|
|
child = item->child;
|
|
while ( child != 0 )
|
|
{
|
|
if ( (privstr= iguana_walletfields(coin,&p2shflag,wifstr,coinaddr,child->string,child->valuestring)) != 0 )
|
|
fprintf(fp,"%s %s %32s=%d # addr=%s\n",privstr,utc_str(str,(uint32_t)time(NULL)),account,i+1,coinaddr);
|
|
child = child->next;
|
|
}
|
|
//printf("account.(%s)\n",account);
|
|
}
|
|
item = item->next;
|
|
}
|
|
fclose(fp);
|
|
return(0);
|
|
}
|
|
|
|
char *walleterrstr[] = { "P2SH_withpriv", "P2SH_withpub", "rmd160_mismatch", "pubkey_mismatch", "missing_pubkey", "account_mismatch" };
|
|
|
|
uint8_t iguana_waddrvalidate(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount *wacct,struct iguana_waddress *waddr,int32_t repairflag,int32_t *errors)
|
|
{
|
|
struct iguana_waccount *checkwacct; struct iguana_waddress *checkwaddr; uint8_t checkpub[33],rmd160[20],addrtype,checktype,plen,flag=0; int32_t i;
|
|
if ( waddr != 0 )
|
|
{
|
|
if ( (checkwaddr= iguana_waddresssearch(myinfo,coin,&checkwacct,waddr->coinaddr)) != waddr || checkwacct != wacct )
|
|
{
|
|
//errors[5]++;
|
|
//flag |= (5 << 0);
|
|
//if ( repairflag > 0 )
|
|
{
|
|
printf("waddrvalidate: need to manually setaccount to fix mismatch (%s:%s) <- (%s:%s)\n",checkwacct != 0 ? checkwacct->account : "",checkwaddr != 0 ? checkwaddr->coinaddr : "",wacct != 0 ? wacct->account : "",waddr->coinaddr);
|
|
}
|
|
}
|
|
if ( waddr->scriptlen > 0 )
|
|
{
|
|
checktype = coin->chain->p2shtype;
|
|
if ( bits256_nonz(waddr->privkey) != 0 )
|
|
{
|
|
errors[0]++;
|
|
flag |= (1 << 0);
|
|
if ( repairflag > 0 )
|
|
{
|
|
myinfo->dirty = (uint32_t)time(NULL);
|
|
memset(&waddr->privkey,0,sizeof(waddr->privkey));
|
|
}
|
|
}
|
|
if ( bitcoin_pubkeylen(waddr->pubkey) > 0 )
|
|
{
|
|
errors[1]++;
|
|
flag |= (1 << 1);
|
|
if ( repairflag > 0 )
|
|
{
|
|
myinfo->dirty = (uint32_t)time(NULL);
|
|
memset(waddr->pubkey,0,sizeof(waddr->pubkey));
|
|
}
|
|
}
|
|
}
|
|
else checktype = coin->chain->pubtype;
|
|
if ( bitcoin_addr2rmd160(&addrtype,rmd160,waddr->coinaddr) != sizeof(rmd160) || addrtype != checktype || memcmp(rmd160,waddr->rmd160,sizeof(rmd160)) != 0 )
|
|
{
|
|
errors[2]++;
|
|
flag |= (1 << 2);
|
|
if ( repairflag > 0 )
|
|
{
|
|
myinfo->dirty = (uint32_t)time(NULL);
|
|
waddr->addrtype = checktype;
|
|
memcpy(waddr->rmd160,rmd160,sizeof(rmd160));
|
|
}
|
|
}
|
|
if ( waddr->scriptlen == 0 )
|
|
{
|
|
if ( bits256_nonz(waddr->privkey) != 0 )
|
|
{
|
|
bitcoin_pubkey33(myinfo->ctx,checkpub,waddr->privkey);
|
|
if ( memcmp(checkpub,waddr->pubkey,sizeof(checkpub)) != 0 )
|
|
{
|
|
errors[3]++;
|
|
flag |= (1 << 3);
|
|
if ( repairflag > 0 )
|
|
{
|
|
myinfo->dirty = (uint32_t)time(NULL);
|
|
memcpy(waddr->pubkey,checkpub,sizeof(checkpub));
|
|
}
|
|
}
|
|
}
|
|
if ( (plen= bitcoin_pubkeylen(waddr->pubkey)) > 0 )
|
|
{
|
|
calc_rmd160_sha256(rmd160,waddr->pubkey,plen);
|
|
if ( memcmp(rmd160,waddr->rmd160,sizeof(rmd160)) != 0 )
|
|
{
|
|
for (i=0; i<20; i++)
|
|
if ( waddr->rmd160[i] != 0 )
|
|
break;
|
|
if ( i != 20 )
|
|
{
|
|
errors[4]++;
|
|
flag |= (1 << 4);
|
|
if ( repairflag > 0 )
|
|
{
|
|
printf("waddrvalidate unrecoverable error: cant determine pubkey from rmd160\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
memcpy(waddr->rmd160,rmd160,20);
|
|
bitcoin_address(waddr->coinaddr,coin->chain->pubtype,rmd160,sizeof(rmd160));
|
|
myinfo->dirty = (uint32_t)time(NULL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return(flag);
|
|
}
|
|
|
|
cJSON *iguana_walletiterate(struct supernet_info *myinfo,struct iguana_info *coin,int32_t flag,cJSON *array,int32_t *goodp,int32_t *badp,int32_t *errors)
|
|
{
|
|
struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr=0,*tmp2; uint8_t errorflags; int32_t i,good=0,bad=0,_errors[8]; cJSON *item; char coinaddr[64];
|
|
if ( errors == 0 )
|
|
errors = _errors;
|
|
HASH_ITER(hh,myinfo->wallet,wacct,tmp)
|
|
{
|
|
HASH_ITER(hh,wacct->waddr,waddr,tmp2)
|
|
{
|
|
if ( flag < 0 )
|
|
{
|
|
memset(&waddr->privkey,0,sizeof(waddr->privkey));
|
|
memset(waddr->wifstr,0,sizeof(waddr->wifstr));
|
|
for (i=0; i<sizeof(waddr->privkey); i++)
|
|
waddr->privkey.bytes[i] = rand();
|
|
for (i=0; i<sizeof(waddr->wifstr); i++)
|
|
waddr->wifstr[i] = rand();
|
|
if ( flag < -1 )
|
|
{
|
|
HASH_DELETE(hh,wacct->waddr,waddr);
|
|
if ( waddr->unspents != 0 )
|
|
free(waddr->unspents);
|
|
//printf("walletiterate: %p free %s\n",waddr,waddr->coinaddr);
|
|
myfree(waddr,sizeof(*waddr) + waddr->scriptlen);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wacct->current = waddr;
|
|
if ( (errorflags= iguana_waddrvalidate(myinfo,coin,wacct,waddr,flag,errors)) != 0 )
|
|
{
|
|
bad++;
|
|
if ( array != 0 && (item= cJSON_CreateObject()) != 0 )
|
|
{
|
|
bitcoin_address(coinaddr,coin->chain->pubtype,waddr->rmd160,20);
|
|
jaddnum(item,coinaddr,errorflags);
|
|
jaddi(array,item);
|
|
}
|
|
} else good++;
|
|
}
|
|
}
|
|
if ( flag < -1 )
|
|
{
|
|
HASH_DELETE(hh,myinfo->wallet,wacct);
|
|
myfree(wacct,sizeof(*wacct));
|
|
}
|
|
}
|
|
if ( goodp != 0 )
|
|
*goodp = good;
|
|
if ( badp != 0 )
|
|
*badp = bad;
|
|
return(array);
|
|
}
|
|
|
|
char *iguana_walletscan(struct supernet_info *myinfo,struct iguana_info *coin,int32_t repairflag)
|
|
{
|
|
cJSON *retjson; int32_t i,good,bad,errors[8];
|
|
memset(errors,0,sizeof(errors));
|
|
good = bad = 0;
|
|
retjson = cJSON_CreateObject();
|
|
jadd(retjson,"result",iguana_walletiterate(myinfo,coin,repairflag,cJSON_CreateArray(),&good,&bad,errors));
|
|
jaddnum(retjson,"good",good);
|
|
jaddnum(retjson,"bad",bad);
|
|
for (i=0; i<sizeof(errors)/sizeof(errors); i++)
|
|
{
|
|
if ( errors[i] != 0 )
|
|
jaddnum(retjson,walleterrstr[i],errors[i]);
|
|
}
|
|
return(jprint(retjson,1));
|
|
}
|
|
|
|
void iguana_walletinitcheck(struct supernet_info *myinfo,struct iguana_info *coin)
|
|
{
|
|
// "wallet":{"test":{"R9S7zZzzvgb4CkiBH1i7gnFcwJuL1MYbxN":"18ab9c89ce83929db720cf26b663bf762532276146cd9d3e1f89086fcdf00053"}}
|
|
cJSON *payload,*item,*array,*child; char *account,coinaddr[128],*privstr,wifstr[128]; int32_t i,p2shflag,n; struct iguana_waccount *wacct; struct iguana_waddress waddr; bits256 privkey;
|
|
if ( myinfo->wallet == 0 && myinfo->decryptstr != 0 && (payload= cJSON_Parse(myinfo->decryptstr)) != 0 )
|
|
{
|
|
if ( (array= jobj(payload,"wallet")) != 0 )
|
|
{
|
|
n = cJSON_GetArraySize(array);
|
|
//printf("item.(%s) size.%d\n",jprint(array,0),n);
|
|
item = array->child;
|
|
for (i=0; i<n; i++)
|
|
{
|
|
if ( item != 0 && (account= item->string) != 0 )
|
|
{
|
|
child = item->child;
|
|
while ( child != 0 )
|
|
{
|
|
if ( (wacct= iguana_waccountcreate(myinfo,coin,account)) != 0 )
|
|
{
|
|
if ( (privstr= iguana_walletfields(coin,&p2shflag,wifstr,coinaddr,child->string,child->valuestring)) != 0 )
|
|
{
|
|
memset(&waddr,0,sizeof(waddr));
|
|
strcpy(waddr.coinaddr,coinaddr);
|
|
if ( p2shflag != 0 )
|
|
iguana_waddressadd(myinfo,coin,wacct,&waddr,child->valuestring);
|
|
else
|
|
{
|
|
privkey = bits256_conv(child->valuestring);
|
|
if ( iguana_waddresscalc(myinfo,coin->chain->pubtype,coin->chain->wiftype,&waddr,privkey) != 0 )
|
|
iguana_waddressadd(myinfo,coin,wacct,&waddr,0);
|
|
}
|
|
}
|
|
}
|
|
child = child->next;
|
|
}
|
|
//printf("account.(%s)\n",account);
|
|
}
|
|
item = item->next;
|
|
}
|
|
}
|
|
free_json(payload);
|
|
myinfo->decryptstr = 0;
|
|
scrubfree(myinfo->decryptstr);
|
|
myinfo->dirty = 0;
|
|
}
|
|
iguana_walletiterate(myinfo,coin,1,0,0,0,0);
|
|
}
|
|
|
|
void iguana_walletlock(struct supernet_info *myinfo,struct iguana_info *coin)
|
|
{
|
|
memset(&myinfo->persistent_priv,0,sizeof(myinfo->persistent_priv));
|
|
memset(myinfo->secret,0,sizeof(myinfo->secret));
|
|
memset(myinfo->permanentfile,0,sizeof(myinfo->permanentfile));
|
|
if ( myinfo->decryptstr != 0 )
|
|
scrubfree(myinfo->decryptstr), myinfo->decryptstr = 0;
|
|
myinfo->expiration = 0;
|
|
iguana_walletiterate(myinfo,coin,-2,0,0,0,0);
|
|
}
|
|
|
|
int64_t iguana_waccountbalance(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_waccount *wacct,int32_t minconf,int32_t lastheight)
|
|
{
|
|
int64_t balance; int32_t numrmds=0,numunspents = 0; uint8_t *rmdarray=0;
|
|
if ( minconf == 0 )
|
|
minconf = 1;
|
|
rmdarray = iguana_rmdarray(myinfo,coin,&numrmds,iguana_getaddressesbyaccount(myinfo,coin,wacct->account),0);
|
|
balance = iguana_unspents(myinfo,coin,0,minconf,(1 << 30),rmdarray,numrmds,lastheight,0,&numunspents);
|
|
if ( rmdarray != 0 )
|
|
free(rmdarray);
|
|
return(balance);
|
|
}
|
|
|
|
cJSON *iguana_privkeysjson(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *vins)
|
|
{
|
|
int32_t i,j,n,numinputs; uint32_t spent_unspentind; int16_t spent_hdrsi; struct iguana_waddress *waddr; struct iguana_waccount *wacct; char *addresses,*address,coinaddr[64]; cJSON *privkeys = cJSON_CreateArray();
|
|
if ( (numinputs= cJSON_GetArraySize(vins)) > 0 )
|
|
{
|
|
addresses = calloc(numinputs,64);
|
|
for (i=n=0; i<numinputs; i++)
|
|
{
|
|
if ( (address= iguana_inputaddress(coin,coinaddr,&spent_hdrsi,&spent_unspentind,jitem(vins,i))) != 0 )
|
|
{
|
|
for (j=0; j<n; j++)
|
|
{
|
|
if ( strcmp(&addresses[64 * j],address) == 0 )
|
|
break;
|
|
}
|
|
if ( j == n )
|
|
strcpy(&addresses[64 * n++],address);
|
|
}
|
|
}
|
|
for (i=0; i<n; i++)
|
|
{
|
|
if ( (waddr= iguana_waddresssearch(myinfo,coin,&wacct,&addresses[i * 64])) != 0 )
|
|
jaddistr(privkeys,waddr->wifstr);
|
|
}
|
|
free(addresses);
|
|
}
|
|
return(privkeys);
|
|
}
|
|
|
|
#include "../includes/iguana_apidefs.h"
|
|
#include "../includes/iguana_apideclares.h"
|
|
|
|
int64_t iguana_addressreceived(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json,char *remoteaddr,cJSON *txids,cJSON *vouts,char *coinaddr,int32_t minconf)
|
|
{
|
|
int64_t balance = 0; cJSON *unspentsjson,*balancejson,*item; int32_t i,n; char *balancestr;
|
|
if ( (balancestr= iguana_balance(IGUANA_CALLARGS,coin->symbol,coinaddr,-1,minconf)) != 0 )
|
|
{
|
|
printf("balancestr.(%s) (%s)\n",balancestr,coinaddr);
|
|
if ( (balancejson= cJSON_Parse(balancestr)) != 0 )
|
|
{
|
|
balance = jdouble(balancejson,"balance") * SATOSHIDEN;
|
|
if ( (txids != 0 || vouts != 0) && (unspentsjson= jarray(&n,balancejson,"unspents")) != 0 )
|
|
{
|
|
for (i=0; i<n; i++)
|
|
{
|
|
item = jitem(unspentsjson,i);
|
|
if ( txids != 0 )
|
|
jaddibits256(txids,jbits256(item,"txid"));
|
|
if ( vouts != 0 )
|
|
jaddinum(vouts,jint(item,"vout"));
|
|
}
|
|
}
|
|
free_json(balancejson);
|
|
}
|
|
free(balancestr);
|
|
}
|
|
return(balance);
|
|
}
|
|
|
|
char *getnewaddress(struct supernet_info *myinfo,struct iguana_waddress **waddrp,struct iguana_info *coin,char *account,char *retstr)
|
|
{
|
|
struct iguana_waddress addr; cJSON *retjson;
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
myinfo->expiration++;
|
|
if ( retstr != 0 )
|
|
{
|
|
memset(&addr,0,sizeof(addr));
|
|
if ( iguana_waddresscalc(myinfo,coin->chain->pubtype,coin->chain->wiftype,&addr,bitcoin_randkey(myinfo->ctx)) != 0 )
|
|
retjson = iguana_walletadd(myinfo,waddrp,coin,retstr,account,&addr,1,0);
|
|
else return(clonestr("{\"error\":\"couldnt calculate waddr\"}"));
|
|
} else return(clonestr("{\"error\":\"no wallet data\"}"));
|
|
return(jprint(retjson,1));
|
|
}
|
|
|
|
STRING_ARG(bitcoinrpc,validateaddress,address)
|
|
{
|
|
cJSON *retjson; int32_t i; uint8_t addrtype,rmd160[20],pubkey[65]; struct iguana_info *other; char str[256];
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( iguana_addressvalidate(coin,&addrtype,address) < 0 )
|
|
return(clonestr("{\"error\":\"invalid coin address\"}"));
|
|
bitcoin_addr2rmd160(&addrtype,rmd160,address);
|
|
retjson = cJSON_CreateObject();
|
|
jaddstr(retjson,"result","success");
|
|
jaddnum(retjson,"addrtype",addrtype);
|
|
init_hexbytes_noT(str+6,rmd160,sizeof(rmd160));
|
|
jaddstr(retjson,"rmd160",str+6);
|
|
memcpy(str,"76a914",6);
|
|
strcat(str,"88ac");
|
|
jaddstr(retjson,"scriptPubKey",str);
|
|
jadd(retjson,"isscript",(addrtype == coin->chain->p2shtype) ? jtrue() : jfalse());
|
|
if ( iguana_ismine(myinfo,coin,addrtype,pubkey,rmd160) > 0 )
|
|
{
|
|
init_hexbytes_noT(str,pubkey,bitcoin_pubkeylen(pubkey));
|
|
jaddstr(retjson,"pubkey",str);
|
|
cJSON_AddTrueToObject(retjson,"ismine");
|
|
}
|
|
else cJSON_AddFalseToObject(retjson,"ismine");
|
|
for (i=0; i<IGUANA_MAXCOINS; i++)
|
|
{
|
|
if ( (other= Coins[i]) != 0 && strcmp(other->symbol,coin->symbol) != 0 )
|
|
{
|
|
iguana_addressconv(coin,str,other,addrtype == coin->chain->p2shtype,rmd160);
|
|
jaddstr(retjson,other->symbol,str);
|
|
}
|
|
}
|
|
return(jprint(retjson,1));
|
|
}
|
|
|
|
ZERO_ARGS(bitcoinrpc,getinfo)
|
|
{
|
|
cJSON *retjson;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
retjson = cJSON_CreateObject();
|
|
if ( coin != 0 )
|
|
{
|
|
jaddstr(retjson,"result","success");
|
|
jaddnum(retjson,"protocolversion",PROTOCOL_VERSION);
|
|
jaddnum(retjson,"kbfee",dstr(coin->txfee_perkb));
|
|
jaddnum(retjson,"txfee",dstr(coin->txfee));
|
|
jaddnum(retjson,"blocks",coin->blocks.hwmchain.height);
|
|
jaddnum(retjson,"longestchain",coin->longestchain);
|
|
jaddnum(retjson,"port",coin->chain->portp2p);
|
|
jaddnum(retjson,"connections",coin->peers.numranked);
|
|
jaddnum(retjson,"difficulty",coin->blocks.hwmchain.PoW);
|
|
jaddstr(retjson,"status",coin->statusstr);
|
|
jaddstr(retjson,"coin",coin->symbol);
|
|
}
|
|
return(jprint(retjson,1));
|
|
}
|
|
|
|
TWO_STRINGS(bitcoinrpc,setaccount,address,account)
|
|
{
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
myinfo->expiration++;
|
|
return(setaccount(myinfo,coin,0,account,address,0));
|
|
}
|
|
|
|
STRING_ARG(bitcoinrpc,getaccount,address)
|
|
{
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
return(getaccount(myinfo,coin,address));
|
|
}
|
|
|
|
STRING_ARG(bitcoinrpc,getnewaddress,account)
|
|
{
|
|
char *retstr,*newretstr; struct iguana_waddress *waddr;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
myinfo->expiration++;
|
|
if ( (retstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,myinfo->secret,myinfo->permanentfile,0)) != 0 )
|
|
{
|
|
free(retstr);
|
|
retstr = myinfo->decryptstr, myinfo->decryptstr = 0;
|
|
newretstr = getnewaddress(myinfo,&waddr,coin,account,retstr);
|
|
if ( retstr != 0 )
|
|
scrubfree(retstr);
|
|
return(newretstr);
|
|
}
|
|
else return(clonestr("{\"error\":\"no wallet payload\"}"));
|
|
}
|
|
|
|
struct iguana_waddress *iguana_getaccountaddress(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json,char *remoteaddr,char *coinaddr,char *account)
|
|
{
|
|
char *newstr,*retstr; struct iguana_waccount *wacct; struct iguana_waddress *waddr=0;
|
|
coinaddr[0] = 0;
|
|
if ( (wacct= iguana_waccountfind(myinfo,coin,account)) == 0 )
|
|
wacct = iguana_waccountcreate(myinfo,coin,account);
|
|
if ( wacct != 0 )
|
|
{
|
|
if ( (waddr= wacct->current) == 0 )
|
|
{
|
|
if ( (retstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,myinfo->secret,myinfo->permanentfile,0)) != 0 )
|
|
{
|
|
free(retstr);
|
|
retstr = myinfo->decryptstr, myinfo->decryptstr = 0;
|
|
newstr = getnewaddress(myinfo,&waddr,coin,account,retstr);
|
|
if ( retstr != 0 )
|
|
scrubfree(retstr);
|
|
retstr = newstr;
|
|
} else return(0);
|
|
}
|
|
}
|
|
if ( waddr != 0 )
|
|
{
|
|
bitcoin_address(coinaddr,coin->chain->pubtype,waddr->rmd160,20);
|
|
return(waddr);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
STRING_ARG(bitcoinrpc,getaccountaddress,account)
|
|
{
|
|
char coinaddr[64]; struct iguana_waddress *waddr=0; cJSON *retjson;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
myinfo->expiration++;
|
|
if ( account != 0 && account[0] != 0 )
|
|
{
|
|
if ( (waddr= iguana_getaccountaddress(myinfo,coin,json,remoteaddr,coinaddr,account)) != 0 )
|
|
retjson = iguana_waddressjson(coin,0,waddr);
|
|
else return(clonestr("{\"error\":\"couldnt create address\"}"));
|
|
jaddstr(retjson,"account",account);
|
|
jaddstr(retjson,"result","success");
|
|
return(jprint(retjson,1));
|
|
}
|
|
return(clonestr("{\"error\":\"no account specified\"}"));
|
|
}
|
|
|
|
ZERO_ARGS(bitcoinrpc,walletlock)
|
|
{
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
iguana_walletlock(myinfo,coin);
|
|
return(jsuccess());
|
|
}
|
|
|
|
TWOSTRINGS_AND_INT(bitcoinrpc,walletpassphrase,password,permanentfile,timeout)
|
|
{
|
|
char *retstr;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( timeout <= 0 )
|
|
return(clonestr("{\"error\":\"timeout must be positive\"}"));
|
|
myinfo->expiration = (uint32_t)time(NULL) + timeout;
|
|
retstr = SuperNET_login(IGUANA_CALLARGS,myinfo->handle,password,permanentfile,0);
|
|
iguana_walletinitcheck(myinfo,coin);
|
|
return(retstr);
|
|
}
|
|
|
|
THREE_STRINGS(bitcoinrpc,encryptwallet,passphrase,password,permanentfile)
|
|
{
|
|
char *retstr;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( password == 0 || password[0] == 0 )
|
|
password = passphrase;
|
|
retstr = SuperNET_login(IGUANA_CALLARGS,myinfo->handle,password,permanentfile,passphrase);
|
|
//iguana_walletlock(myinfo);
|
|
return(retstr);
|
|
}
|
|
|
|
FOUR_STRINGS(bitcoinrpc,walletpassphrasechange,oldpassword,newpassword,oldpermanentfile,newpermanentfile)
|
|
{
|
|
char destfname[1024],*tmpstr,*loginstr,*passphrase,*retstr = 0; cJSON *tmpjson,*loginjson;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( (tmpstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,oldpassword,oldpermanentfile,0)) != 0 )
|
|
{
|
|
free(tmpstr);
|
|
tmpstr = myinfo->decryptstr, myinfo->decryptstr = 0;
|
|
if ( (tmpjson= cJSON_Parse(tmpstr)) != 0 )
|
|
{
|
|
if ( (loginstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,newpassword,newpermanentfile,0)) != 0 )
|
|
{
|
|
if ( myinfo->decryptstr != 0 && (loginjson= cJSON_Parse(myinfo->decryptstr)) != 0 )
|
|
{
|
|
if ( (passphrase= jstr(loginjson,"passphrase")) != 0 )
|
|
{
|
|
_SuperNET_encryptjson(destfname,passphrase,0,newpermanentfile,0,loginjson);
|
|
//iguana_walletlock(myinfo);
|
|
retstr = SuperNET_login(IGUANA_CALLARGS,myinfo->handle,newpassword,newpermanentfile,0);
|
|
}
|
|
free_json(loginjson);
|
|
}
|
|
free(loginstr);
|
|
}
|
|
free_json(tmpjson);
|
|
}
|
|
if ( tmpstr != 0 )
|
|
scrubfree(tmpstr);
|
|
}
|
|
if ( retstr == 0 )
|
|
retstr = clonestr("{\"error\":\"error changing walletpassphrase\"}");
|
|
return(retstr);
|
|
}
|
|
|
|
TWOSTRINGS_AND_INT(bitcoinrpc,importprivkey,wif,account,rescan)
|
|
{
|
|
bits256 privkey; char *retstr,*str; cJSON *retjson; struct iguana_waddress addr,*waddr; struct iguana_waccount *wacct = 0; uint8_t type,redeemScript[4096]; int32_t len; struct vin_info V; bits256 debugtxid;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
myinfo->expiration++;
|
|
if ( account == 0 || account[0] == 0 )
|
|
account = "default";
|
|
len = (int32_t)strlen(wif);
|
|
memset(debugtxid.bytes,0,sizeof(debugtxid));
|
|
if ( is_hexstr(wif,len) > 0 )
|
|
{
|
|
len >>= 1;
|
|
decode_hex(redeemScript,len,wif);
|
|
if ( (type= iguana_calcrmd160(coin,0,&V,redeemScript,len,debugtxid,-1,0xffffffff)) == IGUANA_SCRIPT_P2SH || type == IGUANA_SCRIPT_1of1 || V.N > 1 )
|
|
{
|
|
if ( (str= setaccount(myinfo,coin,&waddr,account,V.coinaddr,wif)) != 0 )
|
|
free(str);
|
|
retjson = iguana_p2shjson(myinfo,coin,0,waddr);
|
|
return(jprint(retjson,1));
|
|
}
|
|
}
|
|
privkey = iguana_str2priv(myinfo,coin,wif);
|
|
if ( bits256_nonz(privkey) == 0 )
|
|
return(clonestr("{\"error\":\"illegal privkey\"}"));
|
|
memset(&addr,0,sizeof(addr));
|
|
if ( iguana_waddresscalc(myinfo,coin->chain->pubtype,coin->chain->wiftype,&addr,privkey) != 0 )
|
|
{
|
|
if ( (waddr= iguana_waddresssearch(myinfo,coin,&wacct,addr.coinaddr)) != 0 )
|
|
{
|
|
waddr = iguana_waccountswitch(myinfo,coin,account,addr.coinaddr,0);
|
|
return(clonestr("{\"result\":\"privkey already in wallet\"}"));
|
|
}
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
myinfo->expiration++;
|
|
if ( (retstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,myinfo->secret,myinfo->permanentfile,0)) != 0 )
|
|
{
|
|
free(retstr);
|
|
retstr = myinfo->decryptstr, myinfo->decryptstr = 0;
|
|
if ( waddr == 0 )
|
|
waddr = &addr;
|
|
iguana_waddresscalc(myinfo,coin->chain->pubtype,coin->chain->wiftype,waddr,privkey);
|
|
iguana_waccountswitch(myinfo,coin,account,waddr->coinaddr,0);
|
|
retjson = iguana_walletadd(myinfo,0,coin,retstr,account,waddr,0,0);
|
|
if ( retstr != 0 )
|
|
scrubfree(retstr);
|
|
return(jprint(retjson,1));
|
|
} else printf("null return from SuperNET_login\n");
|
|
}
|
|
return(clonestr("{\"error\":\"cant calculate waddress\"}"));
|
|
}
|
|
|
|
STRING_ARG(bitcoinrpc,dumpprivkey,address)
|
|
{
|
|
cJSON *retjson; int32_t len,p2shflag=0; struct iguana_waddress *waddr; struct iguana_waccount *wacct; uint8_t addrtype,type,redeemScript[IGUANA_MAXSCRIPTSIZE]; char *coinaddr; struct vin_info V; bits256 debugtxid;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
myinfo->expiration++;
|
|
len = (int32_t)strlen(address);
|
|
coinaddr = address;
|
|
memset(debugtxid.bytes,0,sizeof(debugtxid));
|
|
if ( is_hexstr(address,len) > 0 )
|
|
{
|
|
len >>= 1;
|
|
decode_hex(redeemScript,len,address);
|
|
if ( (type= iguana_calcrmd160(coin,0,&V,redeemScript,len,debugtxid,-1,0xffffffff)) == IGUANA_SCRIPT_P2SH || type == IGUANA_SCRIPT_1of1 || V.N > 1 )
|
|
{
|
|
p2shflag = 1;
|
|
coinaddr = V.coinaddr;
|
|
}
|
|
}
|
|
if ( strlen(coinaddr) > sizeof(V.coinaddr) || iguana_addressvalidate(coin,&addrtype,coinaddr) < 0 )
|
|
return(clonestr(p2shflag == 0 ? "{\"error\":\"invalid address\"}" : "{\"error\":\"invalid P2SH address\"}"));
|
|
if ( (waddr= iguana_waddresssearch(myinfo,coin,&wacct,coinaddr)) != 0 )
|
|
{
|
|
if ( (waddr->wifstr[0] != 0 || waddr->scriptlen > 0) )
|
|
{
|
|
retjson = cJSON_CreateObject();
|
|
if ( waddr->scriptlen == 0 && waddr->wifstr[0] != 0 )
|
|
jaddstr(retjson,"result",waddr->wifstr);
|
|
else iguana_p2shjson(myinfo,coin,retjson,waddr);
|
|
return(jprint(retjson,1));
|
|
} else return(clonestr("{\"error\":\"no privkey for address\"}"));
|
|
} else return(clonestr("{\"error\":\"couldnt find address in wallet\"}"));
|
|
}
|
|
|
|
STRING_ARG(bitcoinrpc,dumpwallet,filename)
|
|
{
|
|
char *retstr,*walletstr; cJSON *retjson,*walletobj,*strobj;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
if ( myinfo->expiration != 0 )
|
|
{
|
|
myinfo->expiration++;
|
|
if ( (retstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,myinfo->secret,myinfo->permanentfile,0)) != 0 )
|
|
{
|
|
if ( (retjson= cJSON_Parse(retstr)) != 0 )
|
|
{
|
|
if ( (walletstr= myinfo->decryptstr) != 0 )
|
|
{
|
|
myinfo->decryptstr = 0;
|
|
if ( (strobj= cJSON_Parse(walletstr)) != 0 )
|
|
{
|
|
if ( (walletobj= jobj(strobj,"wallet")) != 0 )
|
|
jadd(retjson,"wallet",jduplicate(walletobj));
|
|
if ( 0 && (walletobj= iguana_walletjson(myinfo)) != 0 )
|
|
jadd(retjson,"memory",walletobj);
|
|
free_json(strobj);
|
|
}
|
|
scrubfree(walletstr);
|
|
}
|
|
return(jprint(retjson,1));
|
|
} else printf("cant parse retstr.(%s)\n",retstr);
|
|
} else return(clonestr("{\"error\":\"couldnt decrypt wallet\"}"));
|
|
}
|
|
return(clonestr("{\"error\":\"wallet is locked, cant backup\"}"));
|
|
}
|
|
|
|
STRING_ARG(bitcoinrpc,backupwallet,filename)
|
|
{
|
|
char *loginstr,*retstr = 0; cJSON *retjson,*payload;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
if ( myinfo->expiration != 0 )
|
|
{
|
|
myinfo->expiration++;
|
|
if ( (loginstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,myinfo->secret,myinfo->permanentfile,0)) != 0 )
|
|
{
|
|
retstr = clonestr("{\"error\":\"couldnt backup wallet\"}");
|
|
free(loginstr);
|
|
loginstr = myinfo->decryptstr, myinfo->decryptstr = 0;
|
|
if ( (retjson= cJSON_Parse(loginstr)) != 0 )
|
|
{
|
|
if ( (payload= jobj(retjson,"wallet")) != 0 && iguana_walletemit(myinfo,filename,coin,payload) == 0 )
|
|
retstr = clonestr("{\"result\":\"wallet backup saved\"}");
|
|
free_json(retjson);
|
|
}
|
|
if ( loginstr != 0 )
|
|
scrubfree(loginstr);
|
|
return(retstr);
|
|
} else return(clonestr("{\"error\":\"no wallet payload\"}"));
|
|
} else return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
}
|
|
|
|
STRING_ARG(bitcoinrpc,importwallet,filename)
|
|
{
|
|
cJSON *retjson = 0,*importjson,*loginjson = 0; long filesize; char *importstr,*loginstr;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
if ( myinfo->expiration != 0 )
|
|
{
|
|
myinfo->expiration++;
|
|
if ( (importstr= OS_filestr(&filesize,filename)) != 0 )
|
|
{
|
|
if ( (importjson= cJSON_Parse(importstr)) != 0 )
|
|
{
|
|
if ( (loginstr= SuperNET_login(IGUANA_CALLARGS,myinfo->handle,myinfo->secret,myinfo->permanentfile,0)) != 0 )
|
|
{
|
|
free(loginstr);
|
|
loginstr = myinfo->decryptstr, myinfo->decryptstr = 0;
|
|
loginjson = cJSON_Parse(loginstr);
|
|
if ( loginstr != 0 )
|
|
scrubfree(loginstr);
|
|
}
|
|
retjson = iguana_payloadmerge(loginjson,importjson);
|
|
if ( importjson != 0 && importjson != retjson )
|
|
free_json(importjson);
|
|
if ( loginjson != 0 && loginjson != retjson )
|
|
free_json(loginjson);
|
|
}
|
|
else
|
|
{
|
|
free(importstr);
|
|
return(clonestr("{\"error\":\"couldnt parse import file\"}"));
|
|
}
|
|
return(clonestr("{\"result\":\"wallet imported\"}"));
|
|
} else return(clonestr("{\"error\":\"couldnt open import file\"}"));
|
|
}
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
}
|
|
|
|
ZERO_ARGS(bitcoinrpc,checkwallet)
|
|
{
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
myinfo->expiration++;
|
|
return(iguana_walletscan(myinfo,coin,1));
|
|
}
|
|
|
|
ZERO_ARGS(bitcoinrpc,repairwallet)
|
|
{
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
myinfo->expiration++;
|
|
return(iguana_walletscan(myinfo,coin,0));
|
|
}
|
|
|
|
// multiple address
|
|
STRING_AND_THREEINTS(bitcoinrpc,getbalance,account,minconf,includeempty,lastheight)
|
|
{
|
|
int64_t balance; int32_t numunspents,numrmds=0; uint8_t *rmdarray=0; cJSON *retjson;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
if ( account == 0 )
|
|
account = "*";
|
|
if ( minconf == 0 )
|
|
minconf = 1;
|
|
if ( strcmp(account,"*") != 0 )
|
|
rmdarray = iguana_rmdarray(myinfo,coin,&numrmds,iguana_getaddressesbyaccount(myinfo,coin,account),0);
|
|
numunspents = 0;
|
|
balance = iguana_unspents(myinfo,coin,0,minconf,(1 << 30),rmdarray,numrmds,lastheight,0,&numunspents);
|
|
if ( rmdarray != 0 )
|
|
free(rmdarray);
|
|
retjson = cJSON_CreateObject();
|
|
jaddnum(retjson,"result",dstr(balance));
|
|
return(jprint(retjson,1));
|
|
}
|
|
|
|
STRING_ARG(bitcoinrpc,getaddressesbyaccount,account)
|
|
{
|
|
cJSON *retjson;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
retjson = cJSON_CreateObject();
|
|
jadd(retjson,"result",iguana_getaddressesbyaccount(myinfo,coin,account));
|
|
return(jprint(retjson,1));
|
|
}
|
|
|
|
STRING_AND_INT(bitcoinrpc,getreceivedbyaccount,account,minconf)
|
|
{
|
|
cJSON *retjson; struct iguana_waccount *wacct; int64_t balance;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
retjson = cJSON_CreateObject();
|
|
if ( (wacct= iguana_waccountfind(myinfo,coin,account)) != 0 )
|
|
{
|
|
balance = iguana_waccountbalance(myinfo,coin,wacct,minconf,0);
|
|
jaddnum(retjson,"result",dstr(balance));
|
|
}
|
|
return(jprint(retjson,1));
|
|
}
|
|
|
|
STRING_AND_THREEINTS(bitcoinrpc,listtransactions,account,count,skip,includewatchonly)
|
|
{
|
|
cJSON *retjson,*retarray,*txids,*vouts,*item,*array; int32_t vout,i,j,total,m,n = 0; struct iguana_waccount *wacct; char *coinaddr; bits256 txid;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
retjson = cJSON_CreateObject();
|
|
retarray = cJSON_CreateArray();
|
|
if ( (wacct= iguana_waccountfind(myinfo,coin,account)) != 0 )
|
|
{
|
|
if ( (array= iguana_getaddressesbyaccount(myinfo,coin,account)) != 0 )
|
|
{
|
|
if ( (n= cJSON_GetArraySize(array)) > 0 )
|
|
{
|
|
total = 0;
|
|
for (i=0; i<n; i++)
|
|
{
|
|
if ( (coinaddr= jstr(jitem(array,i),0)) != 0 )
|
|
{
|
|
vouts = cJSON_CreateArray();
|
|
txids = cJSON_CreateArray();
|
|
iguana_addressreceived(myinfo,coin,0,remoteaddr,txids,vouts,coinaddr,1);
|
|
if ( (m= cJSON_GetArraySize(txids)) > 0 )
|
|
{
|
|
for (j=0; j<m; j++,total++)
|
|
{
|
|
txid = jbits256(jitem(txids,j),0);
|
|
vout = jint(jitem(vouts,j),0);
|
|
if ( skip < -count )
|
|
break;
|
|
else
|
|
{
|
|
skip--;
|
|
if ( skip <= 0 )
|
|
{
|
|
/*{
|
|
"category": "receive",
|
|
"amount": 0.50000000,
|
|
"label": "",
|
|
"confirmations": 24466,
|
|
"blockhash": "00000000000000000517ce625737579f91162c46ad9eaccad0f52ca13715b156",
|
|
"blockindex": 78,
|
|
"blocktime": 1448045745,
|
|
}*/
|
|
item = cJSON_CreateObject();
|
|
jaddstr(item,"account",wacct->account);
|
|
jaddstr(item,"address",coinaddr);
|
|
jaddbits256(item,"txid",txid);
|
|
jaddnum(item,"vout",vout);
|
|
//return(bitcoinrpc_getrawtransaction(IGUANA_CALLARGS,txid,1));
|
|
|
|
jaddi(retarray,item);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
free_json(txids);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
jadd(retjson,"result",retarray);
|
|
return(jprint(retjson,1));
|
|
}
|
|
|
|
THREE_INTS(bitcoinrpc,listreceivedbyaccount,minconf,includeempty,watchonly)
|
|
{
|
|
cJSON *retjson,*item,*array; struct iguana_waccount *wacct,*tmp; int64_t balance;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
array = cJSON_CreateArray();
|
|
HASH_ITER(hh,myinfo->wallet,wacct,tmp)
|
|
{
|
|
balance = iguana_waccountbalance(myinfo,coin,wacct,minconf,0);
|
|
item = cJSON_CreateObject();
|
|
jaddstr(item,"account",wacct->account);
|
|
jaddnum(item,"amount",dstr(balance));
|
|
jaddnum(item,"confirmations",minconf);
|
|
jaddi(array,item);
|
|
}
|
|
retjson = cJSON_CreateObject();
|
|
jadd(retjson,"result",array);
|
|
return(jprint(retjson,1));
|
|
}
|
|
|
|
THREE_INTS(bitcoinrpc,listreceivedbyaddress,minconf,includeempty,flag)
|
|
{
|
|
cJSON *retjson,*item,*array,*txids,*vouts; struct iguana_waccount *wacct,*tmp; struct iguana_waddress *waddr,*tmp2; uint8_t addrtype; char coinaddr[64];
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
array = cJSON_CreateArray();
|
|
HASH_ITER(hh,myinfo->wallet,wacct,tmp)
|
|
{
|
|
HASH_ITER(hh,wacct->waddr,waddr,tmp2)
|
|
{
|
|
item = cJSON_CreateObject();
|
|
addrtype = (waddr->scriptlen > 0) ? coin->chain->p2shtype : coin->chain->pubtype;
|
|
bitcoin_address(coinaddr,addrtype,waddr->rmd160,20);
|
|
jaddstr(item,"address",coinaddr);
|
|
txids = cJSON_CreateArray();
|
|
vouts = cJSON_CreateArray();
|
|
jaddnum(item,"amount",dstr(iguana_addressreceived(myinfo,coin,0,remoteaddr,txids,vouts,coinaddr,minconf)));
|
|
jadd(item,"txids",txids);
|
|
jadd(item,"vouts",vouts);
|
|
jaddi(array,item);
|
|
}
|
|
}
|
|
retjson = cJSON_CreateObject();
|
|
jadd(retjson,"result",array);
|
|
return(jprint(retjson,1));
|
|
}
|
|
|
|
STRING_AND_INT(bitcoinrpc,getreceivedbyaddress,address,minconf)
|
|
{
|
|
char *balancestr; cJSON *balancejson,*retjson = cJSON_CreateObject();
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
//if ( myinfo->expiration == 0 )
|
|
// return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
if ( (balancestr= iguana_balance(IGUANA_CALLARGS,coin->symbol,address,-1,minconf)) != 0 )
|
|
{
|
|
if ( (balancejson= cJSON_Parse(balancestr)) != 0 )
|
|
{
|
|
jaddnum(retjson,"result",jdouble(balancejson,"balance"));
|
|
free_json(balancejson);
|
|
}
|
|
}
|
|
if ( jobj(retjson,"result") == 0 )
|
|
jaddstr(retjson,"error","couldnt get received by address");
|
|
return(jprint(retjson,1));
|
|
}
|
|
|
|
TWO_INTS(bitcoinrpc,listaccounts,minconf,includewatchonly)
|
|
{
|
|
cJSON *retjson,*array; int64_t balance; struct iguana_waccount *wacct,*tmp;
|
|
if ( remoteaddr != 0 )
|
|
return(clonestr("{\"error\":\"no remote\"}"));
|
|
if ( myinfo->expiration == 0 )
|
|
return(clonestr("{\"error\":\"need to unlock wallet\"}"));
|
|
array = cJSON_CreateObject();
|
|
HASH_ITER(hh,myinfo->wallet,wacct,tmp)
|
|
{
|
|
balance = iguana_waccountbalance(myinfo,coin,wacct,minconf,0);
|
|
jaddnum(array,wacct->account,dstr(balance));
|
|
}
|
|
retjson = cJSON_CreateObject();
|
|
jadd(retjson,"result",array);
|
|
return(jprint(retjson,1));
|
|
}
|
|
|
|
#include "../includes/iguana_apiundefs.h"
|
|
|
|
|