<commit_before>
//  Created by jl777
//  MIT License
//

#ifndef gateway_NXTutils_h
#define gateway_NXTutils_h

#ifndef in_addr_t
#define in_addr_t uint32_t
#endif

void *loadfile(int32_t *allocsizep,char *fname)
{
    FILE *fp;
    long  filesize;
    char *buf = 0;
    *allocsizep = 0;
    if ( (fp= fopen(fname,"rb")) != 0 )
    {
        fseek(fp,0,SEEK_END);
        filesize = ftell(fp);
        *allocsizep = (int32_t)filesize;
        if ( filesize == 0 )
        {
            fclose(fp);
            return(0);
        }
        buf = calloc(1,filesize + 1);
        rewind(fp);
        if ( buf == 0 )
        {
            printf("loadfile: Null buf for (%s).%ld???\n",fname,filesize);
            return(0);
        }
        else
        {
            if ( fread(buf,1,filesize,fp) != filesize )
                printf("error reading filesize.%ld\n",filesize);
            buf[filesize] = 0;
        }
        fclose(fp);
    }
    return(buf);
}

char *load_file(char *fname,char **bufp,int64_t  *lenp,int64_t  *allocsizep)
{
    FILE *fp;
    int64_t  filesize,buflen = *allocsizep;
    char *buf = *bufp;
    *lenp = 0;
    if ( (fp= fopen(fname,"rb")) != 0 )
    {
        fseek(fp,0,SEEK_END);
        filesize = ftell(fp);
        if ( filesize == 0 )
        {
            fclose(fp);
            *lenp = 0;
            return(0);
        }
        if ( filesize > buflen-1 )
        {
            *allocsizep = filesize+1;
            *bufp = buf = realloc(buf,(long)*allocsizep);
            //buflen = filesize+1;
        }
        rewind(fp);
        if ( buf == 0 )
            printf("Null buf ???\n");
        else
        {
            if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize )
                printf("error reading filesize.%ld\n",(long)filesize);
            buf[filesize] = 0;
        }
        fclose(fp);
        
        *lenp = filesize;
    }
    return(buf);
}

#ifndef WIN32
char *_issue_cmd_to_buffer(char *prog,char *arg1,char *arg2,char *arg3)
{
    char buffer[4096],cmd[512];
    int32_t fd[2];
    unsigned long len;
	static portable_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 	portable_mutex_lock(&mutex);
    if ( pipe(fd) != 0 )
        printf("_issue_cmd_to_buffer error doing pipe(fd)\n");
    pid_t pid = fork();
    if ( pid == 0 )
    {
        dup2(fd[1],STDOUT_FILENO);
        close(fd[0]);
        sprintf(cmd,"%s %s %s %s",prog,arg1,arg2,arg3);
#ifdef DEBUG_MODE
        if ( strcmp(arg1,"getinfo") != 0 && strcmp(arg1,"getrawtransaction") != 0 &&
            strcmp(arg1,"decoderawtransaction") != 0 && strcmp(arg1,"validateaddress") != 0 &&
            strcmp(arg1,"getaccountaddress") != 0 )
#endif
        fprintf(stderr,"pid.0 ISSUE.(%s)\n",cmd);
        if ( system(cmd) != 0 )
            printf("error issuing system(%s)\n",cmd);
        exit(0);
    }
    else
    {
        fprintf(stderr,"pid != 0 ISSUE.(%s)\n",prog);
        dup2(fd[0],STDIN_FILENO);
        close(fd[1]);
        len = 0;
        buffer[0] = 0;
        while ( fgets(buffer+len,(int32_t)(sizeof(buffer)-len),stdin) != 0 )
        {
            printf("%s\n",buffer+len);
            len += strlen(buffer+len);
        }
        waitpid(pid,NULL,0);
        while ( len > 2 && (buffer[len-1] == '\r' || buffer[len-1] == '\n' || buffer[len-1] == '\t' || buffer[len-1] == ' ') )
            len--;
        buffer[len] = 0;
        while ( fgetc(stdin) != EOF )
            ;
        portable_mutex_unlock(&mutex);
        if ( len > 0 )
            return(clonestr(buffer));
    }
    return(0);
}

char *oldget_ipaddr()
{
    static char *ipaddr;
    char *devs[] = { "eth0", "em1" };
    int32_t iter;
    char *retstr,*tmp;
    if ( ipaddr != 0 )
        return(ipaddr);
    for (iter=0; iter<(int32_t)((sizeof(devs))/(sizeof(*devs))); iter++)
    {
        printf("iter.%d\n",iter);
        retstr = _issue_cmd_to_buffer("ifconfig",devs[iter],"| grep \"inet addr\" | awk '{print $2}'","");
        if ( retstr != 0 && strncmp(retstr,"addr:",strlen("addr:")) == 0 )
        {
            tmp = clonestr(retstr + strlen("addr:"));
            myfree(retstr,"1");
            if ( ipaddr != 0 )
                myfree(ipaddr,"12");
            ipaddr = tmp;
            return(ipaddr);
        } else ipaddr = 0;
    }
    ipaddr = clonestr("127.0.0.1");
    return(ipaddr);
}
#endif

char *get_ipaddr()
{
    static CURL *curl_handle;
    static char *_ipaddr;
    char *ipsrcs[] = { "http://ip-api.com/json", "http://ip.jsontest.com/?showMyIP", "http://www.telize.com/jsonip", "http://www.trackip.net/ip?json"};
    int32_t i,match = 1;
    cJSON *json,*obj;
    char *jsonstr,ipaddr[MAX_JSON_FIELD],str[MAX_JSON_FIELD];
  //  return(0);
    if ( _ipaddr != 0 )
        return(_ipaddr);
    if ( curl_handle == 0 )
        curl_handle = curl_easy_init();
    if ( curl_handle == 0 )
        return(0);
    ipaddr[0] = 0;
    for (i=0; i<(int32_t)(sizeof(ipsrcs)/sizeof(*ipsrcs)); i++)
    {
        jsonstr = issue_curl(curl_handle,ipsrcs[i]);
        if ( jsonstr != 0 )
        {
            json = cJSON_Parse(jsonstr);
            if ( json != 0 )
            {
                obj = cJSON_GetObjectItem(json,(i==0)?"query":"ip");
                copy_cJSON(str,obj);
                printf("(%s) ",str);
                if ( strcmp(str,ipaddr) != 0 )
                    strcpy(ipaddr,str);
                else match++;
                free_json(json);
            }
            free(jsonstr);
        }
    }
    if ( match != i )
        printf("-> (%s) ipaddr matches.%d vs queries.%d\n",ipaddr,match,i);
    if ( ipaddr[0] != 0 )
        _ipaddr = clonestr(ipaddr);
    return(_ipaddr);
}

/*const char *choose_poolserver(char *NXTaddr)
{
    //static int32_t lastind = -1;
   // uint64_t hashval;
    return(SERVER_NAMEA);
    while ( 1 )
    {
        if ( lastind == -1 )
        {
            hashval = calc_decimalhash(NXTaddr);
            lastind = (hashval % Numguardians);
        }
        else lastind = ((lastind+1) % Numguardians);
        if ( Guardian_names[lastind][0] != 0 )
            break;
    }
    return(Guardian_names[lastind]);
}*/

union NXTtype extract_NXTfield(CURL *curl_handle,char *origoutput,char *cmd,char *field,int32_t type)
{
    char *jsonstr,*output,NXTaddr[MAX_NXTADDR_LEN];
    cJSON *json,*obj,*errobj;
    union NXTtype retval;
    retval.nxt64bits = 0;
    if ( origoutput == 0 )
        output = NXTaddr;
    else output = origoutput;
    jsonstr = issue_NXTPOST(curl_handle,cmd);
    if ( jsonstr != 0 )
    {
        if ( field != 0 && strcmp(field,"transactionId") == 0 )
            printf("jsonstr.(%s)\n",jsonstr);
        json = cJSON_Parse(jsonstr);
        if ( json == 0 ) printf("Error before: (%s) -> [%s]\n",jsonstr,cJSON_GetErrorPtr());
        else
        {
            errobj = cJSON_GetObjectItem(json,"errorCode");
            if ( errobj != 0 )
            {
                printf("cmd.(%s) -> %s\n",cmd,jsonstr);
            }
            if ( field == 0 )
            {
                if ( origoutput == 0 )
                    retval.json = json;
                else
                {
                    copy_cJSON(origoutput,json);
                    retval.str = origoutput;
                    free_json(json);
                }
            }
            else
            {
                obj = cJSON_GetObjectItem(json,field);
                if ( obj != 0 )
                {
                    copy_cJSON(output,obj);
                    //if ( strcmp(field,"transactionId") == 0 )
                    //    printf("obj.(%s) type.%d\n",output,type);
                    switch ( type )
                    {
                        case sizeof(double):
                            retval.dval = atof(output);
                            break;
                        case sizeof(uint32_t):
                            retval.uval = atoi(output);
                            break;
                        case -(int32_t)sizeof(int32_t):
                            retval.val = atoi(output);
                            break;
                        case -(int32_t)sizeof(int64_t):
                            retval.lval = calc_nxt64bits(output);
                            break;
                        case 64:
                            retval.nxt64bits = calc_nxt64bits(output);
                            //if ( strcmp(field,"transactionId") == 0 )
                            //    printf("transactionId.%s\n",nxt64str(retval.nxt64bits));
                           break;
                        case 0:
                            if ( origoutput != 0 )
                                retval.str = origoutput;
                            else retval.str = 0;
                            break;
                        default: printf("extract_NXTfield: warning unknown type.%d\n",type);
                    }
                }
                free_json(json);
            }
        }
        myfree(jsonstr,"33");
    }
    else printf("ERROR submitting cmd.(%s)\n",cmd);
    return(retval);
}

int32_t issue_getTime(CURL *curl_handle)
{
    char cmd[4096];
    union NXTtype ret;
    sprintf(cmd,"%s=getTime",_NXTSERVER);
    ret = extract_NXTfield(curl_handle,0,cmd,"time",sizeof(int32_t));
    return(ret.val);
}

uint64_t issue_getAccountId(CURL *curl_handle,char *password)
{
    char cmd[4096];
    union NXTtype ret;
    bits256 mysecret,mypublic;
    return(conv_NXTpassword(mysecret.bytes,mypublic.bytes,password));
    sprintf(cmd,"%s=getAccountId&secretPhrase=%s",_NXTSERVER,password);
    ret = extract_NXTfield(curl_handle,0,cmd,"accountId",64);
    if ( ret.nxt64bits == 0 )
        ret = extract_NXTfield(curl_handle,0,cmd,"account",64);
    return(ret.nxt64bits);
}

int32_t issue_startForging(CURL *curl_handle,char *secret)
{
    char cmd[4096];
    union NXTtype ret;
    sprintf(cmd,"%s=startForging&secretPhrase=%s",_NXTSERVER,secret);
    ret = extract_NXTfield(curl_handle,0,cmd,"deadline",sizeof(int32_t));
    printf("startforging deadline.%d\n",ret.val);
    return(ret.val);
}

uint64_t issue_broadcastTransaction(int32_t *errcodep,char **retstrp,char *txbytes,char *NXTACCTSECRET)
{
    cJSON *json,*errjson;
    uint64_t txid = 0;
    char cmd[4096],*retstr;
    sprintf(cmd,"%s=broadcastTransaction&secretPhrase=%s&transactionBytes=%s",_NXTSERVER,NXTACCTSECRET,txbytes);
    retstr = issue_NXTPOST(0,cmd);
    *errcodep = -1;
    if ( retstrp != 0 )
        *retstrp = retstr;
    if ( retstr != 0 )
    {
        //printf("broadcast got.(%s)\n",retstr);
        if ( (json= cJSON_Parse(retstr)) != 0 )
        {
            errjson = cJSON_GetObjectItem(json,"errorCode");
            if ( errjson != 0 )
            {
                //printf("ERROR broadcasting.(%s)\n",retstr);
                *errcodep = (int32_t)get_cJSON_int(json,"errorCode");
            }
            else
            {
                if ( (txid = get_satoshi_obj(json,"transaction")) != 0 )
                    *errcodep = 0;
            }
        }
        if ( retstrp == 0 )
            free(retstr);
    }
    return(txid);
}

char *issue_signTransaction(CURL *curl_handle,char *txbytes,char *NXTACCTSECRET)
{
    char cmd[4096];
    sprintf(cmd,"%s=signTransaction&secretPhrase=%s&unsignedTransactionBytes=%s",_NXTSERVER,NXTACCTSECRET,txbytes);
    return(issue_NXTPOST(curl_handle,cmd));
}

uint64_t issue_transferAsset(char **retstrp,CURL *curl_handle,char *secret,char *recipient,char *asset,int64_t quantity,int64_t feeNQT,int32_t deadline,char *comment,char *destpubkey)
{
    char cmd[4096],numstr[MAX_JSON_FIELD],*jsontxt;
    uint64_t txid = 0;
    cJSON *json,*errjson,*txidobj;
    *retstrp = 0;
    if ( strcmp(asset,NXT_ASSETIDSTR) == 0 )
        sprintf(cmd,"%s=sendMoney&amountNQT=%lld",_NXTSERVER,(long long)quantity);
    else sprintf(cmd,"%s=transferAsset&asset=%s&quantityQNT=%lld",_NXTSERVER,asset,(long long)quantity);
    sprintf(cmd+strlen(cmd),"&secretPhrase=%s&recipient=%s&feeNQT=%lld&deadline=%d",secret,recipient,(long long)feeNQT,deadline);
    if ( destpubkey != 0 )
        sprintf(cmd+strlen(cmd),"&recipientPublicKey=%s",destpubkey);
    if ( comment != 0 )
    {
        strcat(cmd,"&message=");
        strcat(cmd,comment);
    }
//printf("would have (%s)\n",cmd);
//return(0);
    jsontxt = issue_NXTPOST(curl_handle,cmd);
    if ( jsontxt != 0 )
    {
        printf(" transferAsset.(%s) -> %s\n",cmd,jsontxt);
        //if ( field != 0 && strcmp(field,"transactionId") == 0 )
        //    printf("jsonstr.(%s)\n",jsonstr);
        json = cJSON_Parse(jsontxt);
        if ( json != 0 )
        {
            errjson = cJSON_GetObjectItem(json,"error");
            if ( errjson != 0 )
            {
                //printf("ERROR submitting assetxfer.(%s)\n",jsontxt);
                if ( retstrp != 0 )
                    *retstrp = jsontxt;
            }
            else
            {
                txidobj = cJSON_GetObjectItem(json,"transaction");
                copy_cJSON(numstr,txidobj);
                txid = calc_nxt64bits(numstr);
                if ( txid == 0 )
                {
                    //printf("ERROR WITH ASSET TRANSFER.(%s) -> \n%s\n",cmd,jsontxt);
                    if ( retstrp != 0 )
                        *retstrp = jsontxt;
                }
            }
            free_json(json);
        } else printf("error issuing asset.(%s) -> %s\n",cmd,jsontxt);
    }
    if ( *retstrp == 0 && jsontxt != 0 )
        free(jsontxt);
    return(txid);
}

cJSON *issue_getAccountInfo(CURL *curl_handle,int64_t *amountp,char *name,char *username,char *NXTaddr,char *groupname)
{
    union NXTtype retval;
    cJSON *obj,*json = 0;
    char buf[MAX_JSON_FIELD];
    *amountp = 0;
    sprintf(buf,"%s=getAccount&account=%s",_NXTSERVER,NXTaddr);
    retval = extract_NXTfield(curl_handle,0,buf,0,0);
    if ( retval.json != 0 )
    {
        //printf("%s\n",cJSON_Print(retval.json));
        obj = cJSON_GetObjectItem(retval.json,"balanceNQT");
        copy_cJSON(buf,obj);
        *amountp = calc_nxt64bits(buf);
        obj = cJSON_GetObjectItem(retval.json,"name");
        copy_cJSON(name,obj);
        obj = cJSON_GetObjectItem(retval.json,"description");
        copy_cJSON(buf,obj);
        unstringify(buf);
        json = cJSON_Parse(buf);
        if ( json != 0 )
        {
            //printf("%s\n",cJSON_Print(json));
            obj = cJSON_GetObjectItem(json,"username");
            copy_cJSON(username,obj);
            obj = cJSON_GetObjectItem(json,"group");
            copy_cJSON(groupname,obj);
            //printf("name.%s username.%s groupname.%s\n%s\n",name,username,cJSON_Print(json),groupname);
        }
        free_json(retval.json);
    }
    return(json);
}

uint64_t _get_bestassetprice(char *assetcmd,char *arrayfield,uint64_t assetid)
{
    char cmd[4096],*jsonstr;
    cJSON *array,*json;
    uint64_t price = 0;
    int32_t n;
    sprintf(cmd,"%s=%s&asset=%llu&firstIndex=0&lastIndex=0",NXTSERVER,assetcmd,(long long)assetid);
    if ( (jsonstr= issue_curl(0,cmd)) != 0 )
    {
        printf("cmd.(%s) -> (%s)\n",cmd,jsonstr);
        if ( (json= cJSON_Parse(jsonstr)) != 0 )
        {
            if ( (array= cJSON_GetObjectItem(json,arrayfield)) != 0 && is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) == 1 )
                price = get_API_nxt64bits(cJSON_GetObjectItem(cJSON_GetArrayItem(array,0),"priceNQT"));
            free_json(json);
        }
        free(jsonstr);
    }
    return(price);
}

uint64_t get_nxtlowask(uint64_t assetid) { return(_get_bestassetprice("getAskOrders","bidOrders",assetid)); }
uint64_t get_nxthighbid(uint64_t assetid) { return(_get_bestassetprice("getBidOrders","askOrders",assetid)); }
uint64_t get_nxtlastprice(uint64_t assetid) { return(_get_bestassetprice("getTrades","trades",assetid)); }

char *issue_getAsset(int32_t isMScoin,char *assetidstr)
{
    char cmd[4096];
    //sprintf(cmd,"%s=getAsset&asset=%s",_NXTSERVER,assetidstr);
    //printf("cmd.(%s)\n",cmd);
    //return(issue_curl(0,cmd));
    //return(issue_NXTPOST(0,cmd));<commit_msg>on top<commit_after>
//  Created by jl777
//  MIT License
//

#ifndef gateway_NXTutils_h
#define gateway_NXTutils_h

#ifndef in_addr_t
#define in_addr_t uint32_t
#endif

void *loadfile(int32_t *allocsizep,char *fname)
{
    FILE *fp;
    long  filesize;
    char *buf = 0;
    *allocsizep = 0;
    if ( (fp= fopen(fname,"rb")) != 0 )
    {
        fseek(fp,0,SEEK_END);
        filesize = ftell(fp);
        *allocsizep = (int32_t)filesize;
        if ( filesize == 0 )
        {
            fclose(fp);
            return(0);
        }
        buf = calloc(1,filesize + 1);
        rewind(fp);
        if ( buf == 0 )
        {
            printf("loadfile: Null buf for (%s).%ld???\n",fname,filesize);
            return(0);
        }
        else
        {
            if ( fread(buf,1,filesize,fp) != filesize )
                printf("error reading filesize.%ld\n",filesize);
            buf[filesize] = 0;
        }
        fclose(fp);
    }
    return(buf);
}

char *load_file(char *fname,char **bufp,int64_t  *lenp,int64_t  *allocsizep)
{
    FILE *fp;
    int64_t  filesize,buflen = *allocsizep;
    char *buf = *bufp;
    *lenp = 0;
    if ( (fp= fopen(fname,"rb")) != 0 )
    {
        fseek(fp,0,SEEK_END);
        filesize = ftell(fp);
        if ( filesize == 0 )
        {
            fclose(fp);
            *lenp = 0;
            return(0);
        }
        if ( filesize > buflen-1 )
        {
            *allocsizep = filesize+1;
            *bufp = buf = realloc(buf,(long)*allocsizep);
            //buflen = filesize+1;
        }
        rewind(fp);
        if ( buf == 0 )
            printf("Null buf ???\n");
        else
        {
            if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize )
                printf("error reading filesize.%ld\n",(long)filesize);
            buf[filesize] = 0;
        }
        fclose(fp);
        
        *lenp = filesize;
    }
    return(buf);
}

#ifndef WIN32
char *_issue_cmd_to_buffer(char *prog,char *arg1,char *arg2,char *arg3)
{
    char buffer[4096],cmd[512];
    int32_t fd[2];
    unsigned long len;
	static portable_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 	portable_mutex_lock(&mutex);
    if ( pipe(fd) != 0 )
        printf("_issue_cmd_to_buffer error doing pipe(fd)\n");
    pid_t pid = fork();
    if ( pid == 0 )
    {
        dup2(fd[1],STDOUT_FILENO);
        close(fd[0]);
        sprintf(cmd,"%s %s %s %s",prog,arg1,arg2,arg3);
#ifdef DEBUG_MODE
        if ( strcmp(arg1,"getinfo") != 0 && strcmp(arg1,"getrawtransaction") != 0 &&
            strcmp(arg1,"decoderawtransaction") != 0 && strcmp(arg1,"validateaddress") != 0 &&
            strcmp(arg1,"getaccountaddress") != 0 )
#endif
        fprintf(stderr,"pid.0 ISSUE.(%s)\n",cmd);
        if ( system(cmd) != 0 )
            printf("error issuing system(%s)\n",cmd);
        exit(0);
    }
    else
    {
        fprintf(stderr,"pid != 0 ISSUE.(%s)\n",prog);
        dup2(fd[0],STDIN_FILENO);
        close(fd[1]);
        len = 0;
        buffer[0] = 0;
        while ( fgets(buffer+len,(int32_t)(sizeof(buffer)-len),stdin) != 0 )
        {
            printf("%s\n",buffer+len);
            len += strlen(buffer+len);
        }
        waitpid(pid,NULL,0);
        while ( len > 2 && (buffer[len-1] == '\r' || buffer[len-1] == '\n' || buffer[len-1] == '\t' || buffer[len-1] == ' ') )
            len--;
        buffer[len] = 0;
        while ( fgetc(stdin) != EOF )
            ;
        portable_mutex_unlock(&mutex);
        if ( len > 0 )
            return(clonestr(buffer));
    }
    return(0);
}

char *oldget_ipaddr()
{
    static char *ipaddr;
    char *devs[] = { "eth0", "em1" };
    int32_t iter;
    char *retstr,*tmp;
    if ( ipaddr != 0 )
        return(ipaddr);
    for (iter=0; iter<(int32_t)((sizeof(devs))/(sizeof(*devs))); iter++)
    {
        printf("iter.%d\n",iter);
        retstr = _issue_cmd_to_buffer("ifconfig",devs[iter],"| grep \"inet addr\" | awk '{print $2}'","");
        if ( retstr != 0 && strncmp(retstr,"addr:",strlen("addr:")) == 0 )
        {
            tmp = clonestr(retstr + strlen("addr:"));
            myfree(retstr,"1");
            if ( ipaddr != 0 )
                myfree(ipaddr,"12");
            ipaddr = tmp;
            return(ipaddr);
        } else ipaddr = 0;
    }
    ipaddr = clonestr("127.0.0.1");
    return(ipaddr);
}
#endif

char *get_ipaddr()
{
    static CURL *curl_handle;
    static char *_ipaddr;
    char *ipsrcs[] = { "http://ip-api.com/json", "http://ip.jsontest.com/?showMyIP", "http://www.telize.com/jsonip", "http://www.trackip.net/ip?json"};
    int32_t i,match = 1;
    cJSON *json,*obj;
    char *jsonstr,ipaddr[MAX_JSON_FIELD],str[MAX_JSON_FIELD];
  //  return(0);
    if ( _ipaddr != 0 )
        return(_ipaddr);
    if ( curl_handle == 0 )
        curl_handle = curl_easy_init();
    if ( curl_handle == 0 )
        return(0);
    ipaddr[0] = 0;
    for (i=0; i<(int32_t)(sizeof(ipsrcs)/sizeof(*ipsrcs)); i++)
    {
        jsonstr = issue_curl(curl_handle,ipsrcs[i]);
        if ( jsonstr != 0 )
        {
            json = cJSON_Parse(jsonstr);
            if ( json != 0 )
            {
                obj = cJSON_GetObjectItem(json,(i==0)?"query":"ip");
                copy_cJSON(str,obj);
                printf("(%s) ",str);
                if ( strcmp(str,ipaddr) != 0 )
                    strcpy(ipaddr,str);
                else match++;
                free_json(json);
            }
            free(jsonstr);
        }
    }
    if ( match != i )
        printf("-> (%s) ipaddr matches.%d vs queries.%d\n",ipaddr,match,i);
    if ( ipaddr[0] != 0 )
        _ipaddr = clonestr(ipaddr);
    return(_ipaddr);
}

/*const char *choose_poolserver(char *NXTaddr)
{
    //static int32_t lastind = -1;
   // uint64_t hashval;
    return(SERVER_NAMEA);
    while ( 1 )
    {
        if ( lastind == -1 )
        {
            hashval = calc_decimalhash(NXTaddr);
            lastind = (hashval % Numguardians);
        }
        else lastind = ((lastind+1) % Numguardians);
        if ( Guardian_names[lastind][0] != 0 )
            break;
    }
    return(Guardian_names[lastind]);
}*/

union NXTtype extract_NXTfield(CURL *curl_handle,char *origoutput,char *cmd,char *field,int32_t type)
{
    char *jsonstr,*output,NXTaddr[MAX_NXTADDR_LEN];
    cJSON *json,*obj,*errobj;
    union NXTtype retval;
    retval.nxt64bits = 0;
    if ( origoutput == 0 )
        output = NXTaddr;
    else output = origoutput;
    jsonstr = issue_NXTPOST(curl_handle,cmd);
    if ( jsonstr != 0 )
    {
        if ( field != 0 && strcmp(field,"transactionId") == 0 )
            printf("jsonstr.(%s)\n",jsonstr);
        json = cJSON_Parse(jsonstr);
        if ( json == 0 ) printf("Error before: (%s) -> [%s]\n",jsonstr,cJSON_GetErrorPtr());
        else
        {
            errobj = cJSON_GetObjectItem(json,"errorCode");
            if ( errobj != 0 )
            {
                printf("cmd.(%s) -> %s\n",cmd,jsonstr);
            }
            if ( field == 0 )
            {
                if ( origoutput == 0 )
                    retval.json = json;
                else
                {
                    copy_cJSON(origoutput,json);
                    retval.str = origoutput;
                    free_json(json);
                }
            }
            else
            {
                obj = cJSON_GetObjectItem(json,field);
                if ( obj != 0 )
                {
                    copy_cJSON(output,obj);
                    //if ( strcmp(field,"transactionId") == 0 )
                    //    printf("obj.(%s) type.%d\n",output,type);
                    switch ( type )
                    {
                        case sizeof(double):
                            retval.dval = atof(output);
                            break;
                        case sizeof(uint32_t):
                            retval.uval = atoi(output);
                            break;
                        case -(int32_t)sizeof(int32_t):
                            retval.val = atoi(output);
                            break;
                        case -(int32_t)sizeof(int64_t):
                            retval.lval = calc_nxt64bits(output);
                            break;
                        case 64:
                            retval.nxt64bits = calc_nxt64bits(output);
                            //if ( strcmp(field,"transactionId") == 0 )
                            //    printf("transactionId.%s\n",nxt64str(retval.nxt64bits));
                           break;
                        case 0:
                            if ( origoutput != 0 )
                                retval.str = origoutput;
                            else retval.str = 0;
                            break;
                        default: printf("extract_NXTfield: warning unknown type.%d\n",type);
                    }
                }
                free_json(json);
            }
        }
        myfree(jsonstr,"33");
    }
    else printf("ERROR submitting cmd.(%s)\n",cmd);
    return(retval);
}

int32_t issue_getTime(CURL *curl_handle)
{
    char cmd[4096];
    union NXTtype ret;
    sprintf(cmd,"%s=getTime",_NXTSERVER);
    ret = extract_NXTfield(curl_handle,0,cmd,"time",sizeof(int32_t));
    return(ret.val);
}

uint64_t issue_getAccountId(CURL *curl_handle,char *password)
{
    char cmd[4096];
    union NXTtype ret;
    bits256 mysecret,mypublic;
    return(conv_NXTpassword(mysecret.bytes,mypublic.bytes,password));
    sprintf(cmd,"%s=getAccountId&secretPhrase=%s",_NXTSERVER,password);
    ret = extract_NXTfield(curl_handle,0,cmd,"accountId",64);
    if ( ret.nxt64bits == 0 )
        ret = extract_NXTfield(curl_handle,0,cmd,"account",64);
    return(ret.nxt64bits);
}

int32_t issue_startForging(CURL *curl_handle,char *secret)
{
    char cmd[4096];
    union NXTtype ret;
    sprintf(cmd,"%s=startForging&secretPhrase=%s",_NXTSERVER,secret);
    ret = extract_NXTfield(curl_handle,0,cmd,"deadline",sizeof(int32_t));
    printf("startforging deadline.%d\n",ret.val);
    return(ret.val);
}

uint64_t issue_broadcastTransaction(int32_t *errcodep,char **retstrp,char *txbytes,char *NXTACCTSECRET)
{
    cJSON *json,*errjson;
    uint64_t txid = 0;
    char cmd[4096],*retstr;
    sprintf(cmd,"%s=broadcastTransaction&secretPhrase=%s&transactionBytes=%s",_NXTSERVER,NXTACCTSECRET,txbytes);
    retstr = issue_NXTPOST(0,cmd);
    *errcodep = -1;
    if ( retstrp != 0 )
        *retstrp = retstr;
    if ( retstr != 0 )
    {
        //printf("broadcast got.(%s)\n",retstr);
        if ( (json= cJSON_Parse(retstr)) != 0 )
        {
            errjson = cJSON_GetObjectItem(json,"errorCode");
            if ( errjson != 0 )
            {
                //printf("ERROR broadcasting.(%s)\n",retstr);
                *errcodep = (int32_t)get_cJSON_int(json,"errorCode");
            }
            else
            {
                if ( (txid = get_satoshi_obj(json,"transaction")) != 0 )
                    *errcodep = 0;
            }
        }
        if ( retstrp == 0 )
            free(retstr);
    }
    return(txid);
}

char *issue_signTransaction(CURL *curl_handle,char *txbytes,char *NXTACCTSECRET)
{
    char cmd[4096];
    sprintf(cmd,"%s=signTransaction&secretPhrase=%s&unsignedTransactionBytes=%s",_NXTSERVER,NXTACCTSECRET,txbytes);
    return(issue_NXTPOST(curl_handle,cmd));
}

uint64_t issue_transferAsset(char **retstrp,CURL *curl_handle,char *secret,char *recipient,char *asset,int64_t quantity,int64_t feeNQT,int32_t deadline,char *comment,char *destpubkey)
{
    char cmd[4096],numstr[MAX_JSON_FIELD],*jsontxt;
    uint64_t txid = 0;
    cJSON *json,*errjson,*txidobj;
    *retstrp = 0;
    if ( strcmp(asset,NXT_ASSETIDSTR) == 0 )
        sprintf(cmd,"%s=sendMoney&amountNQT=%lld",_NXTSERVER,(long long)quantity);
    else sprintf(cmd,"%s=transferAsset&asset=%s&quantityQNT=%lld",_NXTSERVER,asset,(long long)quantity);
    sprintf(cmd+strlen(cmd),"&secretPhrase=%s&recipient=%s&feeNQT=%lld&deadline=%d",secret,recipient,(long long)feeNQT,deadline);
    if ( destpubkey != 0 )
        sprintf(cmd+strlen(cmd),"&recipientPublicKey=%s",destpubkey);
    if ( comment != 0 )
    {
        strcat(cmd,"&message=");
        strcat(cmd,comment);
    }
//printf("would have (%s)\n",cmd);
//return(0);
    jsontxt = issue_NXTPOST(curl_handle,cmd);
    if ( jsontxt != 0 )
    {
        printf(" transferAsset.(%s) -> %s\n",cmd,jsontxt);
        //if ( field != 0 && strcmp(field,"transactionId") == 0 )
        //    printf("jsonstr.(%s)\n",jsonstr);
        json = cJSON_Parse(jsontxt);
        if ( json != 0 )
        {
            errjson = cJSON_GetObjectItem(json,"error");
            if ( errjson != 0 )
            {
                //printf("ERROR submitting assetxfer.(%s)\n",jsontxt);
                if ( retstrp != 0 )
                    *retstrp = jsontxt;
            }
            else
            {
                txidobj = cJSON_GetObjectItem(json,"transaction");
                copy_cJSON(numstr,txidobj);
                txid = calc_nxt64bits(numstr);
                if ( txid == 0 )
                {
                    //printf("ERROR WITH ASSET TRANSFER.(%s) -> \n%s\n",cmd,jsontxt);
                    if ( retstrp != 0 )
                        *retstrp = jsontxt;
                }
            }
            free_json(json);
        } else printf("error issuing asset.(%s) -> %s\n",cmd,jsontxt);
    }
    if ( *retstrp == 0 && jsontxt != 0 )
        free(jsontxt);
    return(txid);
}

cJSON *issue_getAccountInfo(CURL *curl_handle,int64_t *amountp,char *name,char *username,char *NXTaddr,char *groupname)
{
    union NXTtype retval;
    cJSON *obj,*json = 0;
    char buf[MAX_JSON_FIELD];
    *amountp = 0;
    sprintf(buf,"%s=getAccount&account=%s",_NXTSERVER,NXTaddr);
    retval = extract_NXTfield(curl_handle,0,buf,0,0);
    if ( retval.json != 0 )
    {
        //printf("%s\n",cJSON_Print(retval.json));
        obj = cJSON_GetObjectItem(retval.json,"balanceNQT");
        copy_cJSON(buf,obj);
        *amountp = calc_nxt64bits(buf);
        obj = cJSON_GetObjectItem(retval.json,"name");
        copy_cJSON(name,obj);
        obj = cJSON_GetObjectItem(retval.json,"description");
        copy_cJSON(buf,obj);
        unstringify(buf);
        json = cJSON_Parse(buf);
        if ( json != 0 )
        {
            //printf("%s\n",cJSON_Print(json));
            obj = cJSON_GetObjectItem(json,"username");
            copy_cJSON(username,obj);
            obj = cJSON_GetObjectItem(json,"group");
            copy_cJSON(groupname,obj);
            //printf("name.%s username.%s groupname.%s\n%s\n",name,username,cJSON_Print(json),groupname);
        }
        free_json(retval.json);
    }
    return(json);
}

uint64_t _get_bestassetprice(char *assetcmd,char *arrayfield,uint64_t assetid)
{
    char cmd[4096],*jsonstr;
    cJSON *array,*json;
    uint64_t price = 0;
    int32_t n;
    sprintf(cmd,"%s=%s&asset=%llu&firstIndex=0&lastIndex=0",NXTSERVER,assetcmd,(long long)assetid);
    if ( (jsonstr= issue_curl(0,cmd)) != 0 )
    {
        printf("cmd.(%s) -> (%s)\n",cmd,jsonstr);
        if ( (json= cJSON_Parse(jsonstr)) != 0 )
        {
            if ( (array= cJSON_GetObjectItem(json,arrayfield)) != 0 && is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) == 1 )
                price = get_API_nxt64bits(cJSON_GetObjectItem(cJSON_GetArrayItem(array,0),"priceNQT"));
            free_json(json);
        }
        free(jsonstr);
    }
    return(price);
}

uint64_t get_nxtlowask(uint64_t assetid) { return(_get_bestassetprice("getAskOrders","askOrders",assetid)); }
uint64_t get_nxthighbid(uint64_t assetid) { return(_get_bestassetprice("getBidOrders","bidOrders",assetid)); }
uint64_t get_nxtlastprice(uint64_t assetid) { return(_get_bestassetprice("getTrades","trades",assetid)); }

char *issue_getAsset(int32_t isMScoin,char *assetidstr)
{
    char cmd[4096];
    //sprintf(cmd,"%s=getAsset&asset=%s",_NXTSERVER,assetidstr);
    //printf("cmd.(%s)\n",cmd);
    //return(issue_curl(0,cmd));
    //return(issue_NXTPOST(0,cmd));
{'fraction_non_alphanumeric': 0.15103600385200833, 'fraction_numerical': 0.021061787456121275, 'mean_word_length': 1.994047619047619, 'pattern_counts': {'":': 2, '<': 7, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '70153', 'n_tokens_mistral': 11578, 'n_tokens_neox': 10973, 'n_words': 1714}