示例#1
0
struct basilisk_request *basilisk_parsejson(struct basilisk_request *rp,cJSON *reqjson)
{
    uint32_t requestid,quoteid;
    memset(rp,0,sizeof(*rp));
    rp->hash = jbits256(reqjson,"hash");
    rp->desthash = jbits256(reqjson,"desthash");
    rp->srcamount = j64bits(reqjson,"srcamount");
    rp->minamount = j64bits(reqjson,"minamount");
    rp->destamount = j64bits(reqjson,"destamount");
    requestid = juint(reqjson,"requestid");
    quoteid = juint(reqjson,"quoteid");
    if ( jstr(reqjson,"relay") != 0 )
        rp->relaybits = (uint32_t)calc_ipbits(jstr(reqjson,"relay"));
    rp->timestamp = juint(reqjson,"timestamp");
    rp->quotetime = juint(reqjson,"quotetime");
    safecopy(rp->src,jstr(reqjson,"src"),sizeof(rp->src));
    safecopy(rp->dest,jstr(reqjson,"dest"),sizeof(rp->dest));
    if ( quoteid != 0 )
    {
        rp->quoteid = basilisk_quoteid(rp);
        if ( quoteid != rp->quoteid )
            printf("basilisk_parsejson quoteid.%u != %u error\n",quoteid,rp->quoteid);
    }
    rp->requestid = basilisk_requestid(rp);
    if ( requestid != rp->requestid )
        printf("basilisk_parsejson requestid.%u != %u error\n",requestid,rp->requestid);
    return(rp);
}
示例#2
0
uint64_t TRADE(char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume)
{
    char payload[1024],pairstr[64],pricestr[64],*extra,*method; cJSON *json; int32_t type; uint64_t txid = 0;
    if ( (extra= *retstrp) != 0 )
        *retstrp = 0;
    if ( (dir= flipstr_for_exchange(exchange,pairstr,"%s%s",dir,&price,&volume,base,rel)) == 0 )
    {
        printf("cant find baserel (%s/%s)\n",base,rel);
        return(0);
    }
    if ( extra != 0 && strcmp(extra,"market") == 0 )
        method = (dir > 0) ? "buy_market" : "sell_market";
    else method = (dir > 0) ? "buy" : "sell", sprintf(pricestr,"&price=%.2f",price);
    if ( strcmp(pairstr,"btccny") == 0 )
        type = 1;
    else if ( strcmp(pairstr,"ltccny") == 0 )
        type = 2;
    else
    {
        printf("cant find baserel (%s/%s)\n",base,rel);
        return(0);
    }
    sprintf(payload,"&amount=%.4f&coin_type=%d%s",volume,type,pricestr);
    if ( (json= huobi_issue_auth(exchange,method,payload)) != 0 )
    {
        txid = j64bits(json,"order_id");
        free_json(json);
    }
    return(txid);
}
示例#3
0
uint64_t TRADE(char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume)
{
    char payload[1024],pairstr[512],*typestr,*method,*extra; cJSON *json; uint64_t txid = 0;
    if ( (extra= *retstrp) != 0 )
        *retstrp = 0;
    if ( (dir= flipstr_for_exchange(exchange,pairstr,"%s%s",dir,&price,&volume,base,rel)) == 0 )
    {
        printf("cant find baserel (%s/%s)\n",base,rel);
        return(0);
    }
    method = "order/new";
    //Either "market" / "limit" / "stop" / "trailing-stop" / "fill-or-kill" / "exchange market" / "exchange limit" / "exchange stop" / "exchange trailing-stop" / "exchange fill-or-kill". (type starting by "exchange " are exchange orders, others are margin trading orders)
    if ( (typestr= extra) == 0 )
        typestr = "exchange limit";
    sprintf(payload,"{\"request\":\"/v1/%s\",\"nonce\":\"%llu\",\"exchange\":\"bitfinex\",\"side\":\"%s\",\"type\":\"%s\",\"price\":\"%.8f\",\"amount\":\"%.8f\",\"symbol\":\"%s\"}",method,(long long)exchange_nonce(exchange),dir>0?"buy":"sell",typestr,price,volume,pairstr);
    if ( (json= SIGNPOST(retstrp,exchange,payload,method)) != 0 )
    {
        if ( (txid= j64bits(json,"order_id")) == 0 )
        {
            if ( dir != 0 )
                printf("bitfinex: no txid error\n");
        }
        free_json(json);
    }
    return(txid);
}
示例#4
0
文件: okcoin.c 项目: Miyurz/SuperNET
uint64_t TRADE(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume)
{
    char payload[1024],buf[1024],url[1024],digest[512],pairstr[512],pricestr[64],*extra,*typestr;
    cJSON *json; uint64_t txid = 0;
    if ( (extra= *retstrp) != 0 )
        *retstrp = 0;
    if ( (dir= flipstr_for_exchange(exchange,pairstr,"%s_%s",dir,&price,&volume,base,rel)) == 0 )
    {
        printf("cant find baserel (%s/%s)\n",base,rel);
        return(0);
    }
    if ( extra != 0 && strcmp(extra,"market") == 0 )
        typestr = (dir > 0) ? "buy_market" : "sell_market", sprintf(pricestr,"&price=%.2f",price); // docs say market orders put volume in price
    else typestr = (dir > 0) ? "buy" : "sell";
    sprintf(pricestr,"&price=%.2f",price);
    sprintf(buf,"amount=%.4f&api_key=%s%ssymbol=%s&type=%s&secret_key=%s",volume,exchange->apikey,pricestr,pairstr,typestr,exchange->apisecret);
    calc_md5(digest,buf,(int32_t)strlen(buf));
    touppercase(digest);
    sprintf(payload,"amount=%.4f&api_key=%s%s&symbol=%s&type=%s&sign=%s",volume,exchange->apikey,pricestr,pairstr,typestr,digest);
    sprintf(url,"%s/%s",EXCHANGE_AUTHURL,"trade.do");
    if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume) == 0 && (json= SIGNPOST(cHandlep,dotrade,retstrp,exchange,url,payload)) != 0 )
    {
        txid = j64bits(json,"order_id");
        free_json(json);
    }
    return(txid);
}
示例#5
0
cJSON *gecko_paymentsobj(struct supernet_info *myinfo,cJSON *txjson,cJSON *valsobj,int32_t reusedaddrs)
{
    cJSON *item,*array; char *coinaddr; uint64_t satoshis; uint8_t addrtype,pubkey33[33],rmd160[20],outputscript[512]; int32_t i,n,scriptlen; uint32_t locktime,txversion; struct iguana_waddress *waddr; struct iguana_waccount *wacct;
    locktime = jint(valsobj,"locktime");
    if ( (txversion= juint(valsobj,"txversion")) == 0 )
        txversion = (locktime == 0) ? IGUANA_NORMAL_TXVERSION : IGUANA_LOCKTIME_TXVERSION;
    if ( txjson == 0 )
        txjson = bitcoin_txcreate(1,locktime,txversion);
    if ( (array= jarray(&n,valsobj,"payments")) != 0 && n > 0 )
    {
        for (i=0; i<n; i++)
        {
            item = jitem(array,i);
            if ( (coinaddr= jfieldname(item)) != 0 && (satoshis= j64bits(item,coinaddr)) > 0 )
            {
                printf("payment.%s <- %.8f\n",coinaddr,dstr(satoshis));
                bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr);
                scriptlen = 0;
                if ( reusedaddrs == 0 )
                {
                    if ( (waddr= iguana_waddresssearch(myinfo,&wacct,coinaddr)) != 0 )
                    {
                        if ( bitcoin_pubkeylen(waddr->pubkey) > 0 )
                            scriptlen = bitcoin_pubkeyspend(outputscript,0,pubkey33);
                    }
                }
                if ( scriptlen == 0 )
                    scriptlen = bitcoin_standardspend(outputscript,0,rmd160);
                bitcoin_txoutput(txjson,outputscript,scriptlen,satoshis);
            }
        }
    }
    return(txjson);
}
示例#6
0
uint64_t TRADE(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume)
{
    char payload[1024],market[16],coinname[16],fmtstr[512],*pricefmt,*extra,*volfmt = "%.3f";
    cJSON *json,*resultobj;
    uint64_t txid = 0;
    if ( (extra= *retstrp) != 0 )
        *retstrp = 0;
    if ( (dir= cny_flip(market,coinname,base,rel,dir,&price,&volume)) == 0 )
    {
        fprintf(stderr,"btc38_trade illegal base.(%s) or rel.(%s)\n",base,rel);
        return(0);
    }
    if ( strcmp(market,"cny") == 0 )
        pricefmt = "%.5f";
    else pricefmt = "%.6f";
    //sprintf(fmtstr,"key=%%s&time=%%llu&md5=%%s&type=%%s&mk_type=%%s&coinname=%%s&price=%s&amount=%s",pricefmt,volfmt);
    //sprintf(payload,fmtstr,exchange->apikey,(long long)nonce,digest,dir>0?"1":"2",market,coinname,price,volume);
    sprintf(fmtstr,"&type=%%s&mk_type=%%s&coinname=%%s&price=%s&amount=%s",pricefmt,volfmt);
    sprintf(payload,fmtstr,dir>0?"1":"2",market,coinname,price,volume);
    if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume) == 0 && (json= SIGNPOST(cHandlep,dotrade,retstrp,exchange,payload,"submitOrder.php")) != 0 )
    {
        if ( juint(json,"success") > 0 && (resultobj= jobj(json,"return")) != 0 )
        {
            if ( (txid= j64bits(resultobj,"order_id")) == 0 )
            {
                if ( j64bits(resultobj,"remains") == 0 )
                    txid = _crc32(0,payload,strlen(payload));
            }
        }
        free_json(json);
        if ( retstrp != 0 && *retstrp != 0 )
        {
            if ( (json= cJSON_Parse(*retstrp)) == 0 )
            {
                json = cJSON_CreateObject();
                jaddstr(json,"result",*retstrp);
                free(*retstrp);
                *retstrp = jprint(json,1);
            } else free_json(json);
        }
    }
    return(txid);
}
char *bidask_func(int32_t localaccess,int32_t valid,char *sender,cJSON *json,char *origargstr)
{
    struct destbuf gui,exchangestr,name,base,rel,offerNXT; struct InstantDEX_quote iQ;
    copy_cJSON(&offerNXT,jobj(json,"offerNXT"));
//printf("got (%s)\n",origargstr);
    if ( strcmp(SUPERNET.NXTADDR,offerNXT.buf) != 0 )
    {
        if ( bidask_parse(&exchangestr,&name,&base,&rel,&gui,&iQ,json) == 0 )
            return(InstantDEX_placebidask(sender,j64bits(json,"orderid"),exchangestr.buf,name.buf,base.buf,rel.buf,&iQ,jstr(json,"extra"),jstr(json,"secret"),jstr(json,"activenxt"),json));
        else printf("error with incoming bidask\n");
    } else fprintf(stderr,"got my bidask from network (%s)\n",origargstr);
    return(clonestr("{\"result\":\"got loopback bidask\"}"));
}
示例#8
0
文件: main.c 项目: botvs/SuperNET
char *SuperNET_processJSON(struct supernet_info *myinfo,cJSON *json,char *remoteaddr)
{
    cJSON *retjson; uint64_t tag; uint32_t timeout; char *jsonstr,*method,*retjsonstr,*retstr = 0;
    //char str[65]; printf("processJSON %p %s\n",&myinfo->privkey,bits256_str(str,myinfo->privkey));
    if ( json != 0 )
    {
        if ( (tag= j64bits(json,"tag")) == 0 )
        {
            OS_randombytes((uint8_t *)&tag,sizeof(tag));
            jadd64bits(json,"tag",tag);
        }
        if ( (timeout= juint(json,"timeout")) == 0 )
            timeout = IGUANA_JSONTIMEOUT;
        if ( (method= jstr(json,"method")) != 0 && strcmp(method,"DHT") == 0 && remoteaddr != 0 )
        {
            SuperNET_hexmsgprocess(myinfo,0,json,jstr(json,"hexmsg"),remoteaddr);
            return(clonestr("{\"result\":\"processed remote DHT\"}"));
        }
        jsonstr = jprint(json,0);
        if ( remoteaddr == 0 || jstr(json,"immediate") != 0 )
            retjsonstr = SuperNET_jsonstr(myinfo,jsonstr,remoteaddr);
        else retjsonstr = iguana_blockingjsonstr(myinfo,jsonstr,tag,timeout,remoteaddr);
        if ( retjsonstr != 0 )
        {
            if ( (retjson= cJSON_Parse(retjsonstr)) != 0 )
            {
                jdelete(retjson,"tag");
                jadd64bits(retjson,"tag",tag);
                retstr = jprint(retjson,1);
                //printf("retstr.(%s) retjsonstr.%p retjson.%p\n",retstr,retjsonstr,retjson);
                free(retjsonstr);//,strlen(retjsonstr)+1);
            } else retstr = retjsonstr;
        }
        free(jsonstr);
    } else retstr = clonestr("{\"error\":\"cant parse JSON\"}");
    if ( retstr == 0 )
        retstr = clonestr("{\"error\":\"null return\"}");
    return(retstr);
}
示例#9
0
cJSON *LP_NXT_redeems()
{
    char url[1024],*retstr,*recv,*method,*msgstr,assetname[128]; uint64_t totals[2][sizeof(assetids)/sizeof(*assetids)],mult,txnum,assetid,qty; int32_t i,ind,numtx=0,past_marker=0; cJSON *item,*attach,*decjson,*array,*msgjson,*encjson,*retjson=0;
    //sleep 1; fiat/supernet sendtoaddress RNZZuQYu8xJLZHuekhd96hYfoQuiCMz99T 1001.44150000 # txnum.8537615468620726612
    //sleep 1; fiat/pangea sendtoaddress RWMdRaUmMZqKkEibwEhY6XS3RLCXJDWHTi 22.10910000 # txnum.2649622877615958504
    uint64_t txnum_marker = calc_nxt64bits("8537615468620726612"); // 2649622877615958504"); // set to most recent processed
    uint64_t txnum_marker2 = calc_nxt64bits("7256847492742571143"); // dont change, end marker
    char *passphrase = "";
    char *account = "NXT-MRBN-8DFH-PFMK-A4DBM";
    memset(totals,0,sizeof(totals));
    sprintf(url,"http://127.0.0.1:7876/nxt?requestType=getBlockchainTransactions&account=%s",account);
    //printf("calling (%s)\n",url);
    if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 )
    {
        //printf("got.(%s)\n",retstr);
        if ( (retjson= cJSON_Parse(retstr)) != 0 )
        {
            if ( (array= jarray(&numtx,retjson,"transactions")) != 0 )
            {
                for (i=0; i<numtx; i++)
                {
                    msgjson = encjson = decjson = 0;
                    txnum = assetid = qty = 0;
                    item = jitem(array,i);
                    msgstr = jstr(item,"message");
                    txnum = j64bits(item,"transaction");
                    if ( txnum == txnum_marker )
                        past_marker = 1;
                    //printf("%d: %s\n",i,jprint(item,0));
                    if ( (recv= jstr(item,"recipientRS")) != 0 && strcmp(recv,"NXT-MRBN-8DFH-PFMK-A4DBM") == 0 )
                    {
                        if ( (attach= jobj(item,"attachment")) != 0 && jint(attach,"version.AssetTransfer") == 1 )
                        {
                            assetid = j64bits(attach,"asset");
                            qty = j64bits(attach,"quantityQNT");
                            //printf("txnum.%llu (%s)\n",(long long)txnum,jprint(attach,0));
                            if ( (msgstr == 0 || msgstr[0] == 0) && jint(attach,"version.PrunablePlainMessage") == 1 )
                            {
                                method = "getPrunableMessage";
                                if ( (msgjson= LP_NXT_message(method,txnum,"test")) != 0 )
                                {
                                    msgstr = jstr(msgjson,"message");
                                    //printf("%d method.(%s) (%s)\n",i,method,msgstr);
                                }
                            }
                            if ( msgstr == 0 || msgstr[0] == 0 )
                                msgstr = jstr(attach,"message");
                            if ( msgstr == 0 || msgstr[0] == 0 )
                            {
                                
                                if ( (encjson= jobj(attach,"encryptedMessage")) != 0 )
                                {
                                    msgstr = "encryptedMessage";//jstr(encjson,"data");
                                    if ( (decjson= LP_NXT_decrypt(txnum,account,jstr(encjson,"data"),jstr(encjson,"nonce"),passphrase)) != 0 )
                                    {
                                        //printf("%s\n",jprint(decjson,0));
                                        if ( jstr(decjson,"decryptedMessage") != 0 )
                                            msgstr = jstr(decjson,"decryptedMessage");
                                    }
                                }
                            }
                        }
                        mult = LP_assetid_mult(&ind,assetname,assetid);
                        if ( ind >= 0 )
                            totals[past_marker][ind] += qty * mult;
                        if ( msgstr != 0 && assetname[0] != 0 && qty != 0 )
                        {
                            char validaddress[64]; int32_t z,n;
                            n = (int32_t)strlen(msgstr);
                            for (z=0; z<n; z++)
                            {
                                if ( msgstr[z] == 'R' )
                                    break;
                            }
                            memset(validaddress,0,sizeof(validaddress));
                            if ( n-z >= 34 )
                                strncpy(validaddress,&msgstr[z],34);
                            if ( txnum == calc_nxt64bits("4545341872872347590") )
                                strcpy(validaddress,"RKuwq4oi4mqQ2V4r54mPEthn3TBrEwu2Ni");
                            if ( past_marker == 0 )
                            {
                                if ( strlen(validaddress) == 34 || strlen(validaddress) == 33 )
                                {
                                    //printf("%-4d: (%34s) <- %13.5f %10s tx.%llu past_marker.%d\n",i,validaddress,dstr(qty * mult),assetname,(long long)txnum,past_marker);
                                    LP_sendtoaddress_line(validaddress,assetname,(qty * mult),txnum);
                                } else printf("%-4d: (%34s) <- %13.5f %10s tx.%llu\n",i,msgstr!=0?msgstr:jprint(item,0),dstr(qty * mult),assetname,(long long)txnum);
                            }
                        }
                        if ( msgjson != 0 )
                            free_json(msgjson);
                        if ( decjson != 0 )
                            free_json(decjson);
                    }
                    if ( txnum == txnum_marker2 )
                        break;
                }
            }
            //free_json(retjson);
        }
        free(retstr);
    } else printf("null return from NXT api call\n");
    printf("\nTotal redeemed.%d\n",numtx);
    for (past_marker=0; past_marker<2; past_marker++)
    {
        for (i=0; i<sizeof(totals[0])/sizeof(*totals[0]); i++)
        {
            if ( totals[past_marker][i] != 0 )
                printf("%-10s %13.5f past_marker.%d\n",assetids[i][1],dstr(totals[past_marker][i]),past_marker);
        }
        printf("\n>>>>>>>>>> already processed:\n");
    }
    return(retjson);
}
示例#10
0
void NXTventure_liquidation()
{
    /*{"quantityQNT":"607438148","unconfirmedQuantityQNT":"607438148","decimals":4,"name":"ARDR","asset":""},
     {"quantityQNT":"451991779","unconfirmedQuantityQNT":"451991779","decimals":4,"name":"SuperNET","asset":"12071612744977229797"},
     {"quantityQNT":"146960000","unconfirmedQuantityQNT":"146960000","decimals":4,"name":"Privatebet","asset":"17083334802666450484"},
     {"quantityQNT":"79500188","unconfirmedQuantityQNT":"79500188","decimals":3,"name":"crypto777","asset":"13476425053110940554"},
     {"quantityQNT":"1495473","unconfirmedQuantityQNT":"1495473","decimals":0,"name":"jl777hodl","asset":"6932037131189568014"},
     {"quantityQNT":"7250","unconfirmedQuantityQNT":"7250","decimals":0,"name":"InstantDEX","asset":"15344649963748848799"},*/
    char *assetids[][4] =
    {
        { "12422608354438203866", "607438148", "ARDR", "10000" },
        { "12071612744977229797", "451991779", "SuperNET", "10000" },
        { "17083334802666450484", "146960000", "Privatebet", "10000" },
        { "13476425053110940554", "79500188", "crypto777", "1000" },
        { "6932037131189568014", "1495473", "jl777hodl", "1" },
        { "15344649963748848799", "7250", "InstantDEX", "1" },
    };
    void *cHandle=0; char *retstr,*retstr2,url[1024],*account; uint64_t txid,qty,qtyA,assetid,sum; double ratio; cJSON *array,*retjson2,*item,*retjson; int32_t i,j,decimals,numassetids=(int32_t)(sizeof(assetids)/sizeof(*assetids)),n=0;
    char *passphrase = "";
    sprintf(url,"http://127.0.0.1:7876/nxt?requestType=getAssetAccounts&asset=16212446818542881180");
    if ( (retstr= issue_curlt(url,LP_HTTP_TIMEOUT)) != 0 )
    {
        if ( (retjson= cJSON_Parse(retstr)) != 0 )
        {
            if ( (array= jarray(&n,retjson,"accountAssets")) != 0 )
            {
                for (j=0; j<numassetids; j++)
                {
                    assetid = calc_nxt64bits(assetids[j][0]);
                    qtyA = calc_nxt64bits(assetids[j][1]);
                    decimals = (int32_t)calc_nxt64bits(assetids[j][3]);
                    printf("distribute %llu QNT of %s assetid %llu %.8f\n",(long long)qtyA,assetids[j][2],(long long)assetid,(double)qtyA / decimals);
                    sum = 0;
                    for (i=0; i<n; i++)
                    {
                        item = jitem(array,i);
                        qty = j64bits(item,"quantityQNT");
                        ratio = (double)qty / (1000000. - 13000.);
                        if ( (account= jstr(item,"accountRS")) != 0 && qtyA*ratio >= 1 )
                        {
                            if ( strcmp(account,"NXT-XRK4-5HYK-5965-9FH4Z") != 0 )
                            {
                                sum += (long long)(qtyA * ratio);
                                sprintf(url,"requestType=transferAsset&secretPhrase=%s&recipient=%s&asset=%llu&quantityQNT=%llu&feeNQT=100000000&deadline=60",passphrase,account,(long long)assetid,(long long)(qtyA * ratio));
                                if ( (retstr2= curl_post(&cHandle,"http://127.0.0.1:7876/nxt","",url,"","","","")) != 0 )
                                {
                                    if ( (retjson2= cJSON_Parse(retstr2)) != 0 )
                                    {
                                        txid = j64bits(retjson2,"transaction");
                                        printf("%s %.6f %8llu QNT %s -> %llu %.8f txid %llu\n",account,ratio,(long long)qtyA,assetids[j][2],(long long)(qtyA * ratio),((double)(long long)(qtyA * ratio))/decimals,(long long)txid);
                                        free_json(retjson2);
                                    }
                                    free(retstr2);
                                }
                                usleep(250000);
                            }
                        }
                    }
                    printf("%s distribution total %llu QNT %.8f\n",assetids[j][2],(long long)sum,(double)sum/decimals);
                }
            }
            free_json(retjson);
        }
        printf("NXTventure assethodlers.%d\n",n);
        free(retstr);
    }
}
char *InstantDEX(char *jsonstr,char *remoteaddr,int32_t localaccess)
{
    char *prices777_allorderbooks();
    char *InstantDEX_openorders();
    char *InstantDEX_tradehistory(int32_t firsti,int32_t endi);
    char *InstantDEX_cancelorder(char *activenxt,char *secret,uint64_t sequenceid,uint64_t quoteid);
    struct destbuf exchangestr,method,gui,name,base,rel; double balance;
    char *retstr = 0,key[512],retbuf[1024],*activenxt,*secret,*coinstr; struct InstantDEX_quote iQ; struct exchange_info *exchange;
    cJSON *json; uint64_t assetbits,sequenceid; uint32_t maxdepth; int32_t invert=0,keysize,allfields; struct prices777 *prices;
    //printf("INSTANTDEX.(%s)\n",jsonstr);
    if ( INSTANTDEX.readyflag == 0 )
        return(0);
    if ( jsonstr != 0 && (json= cJSON_Parse(jsonstr)) != 0 )
    {
        // test: asset/asset, asset/external, external/external, autofill and automatch
        // peggy integration
        bidask_parse(&exchangestr,&name,&base,&rel,&gui,&iQ,json);
        if ( iQ.s.offerNXT == 0 )
            iQ.s.offerNXT = SUPERNET.my64bits;
        //printf("isask.%d base.(%s) rel.(%s)\n",iQ.s.isask,base.buf,rel.buf);
        copy_cJSON(&method,jobj(json,"method"));
        if ( (sequenceid= j64bits(json,"orderid")) == 0 )
            sequenceid = j64bits(json,"sequenceid");
        allfields = juint(json,"allfields");
        if ( (maxdepth= juint(json,"maxdepth")) <= 0 )
            maxdepth = MAX_DEPTH;
        if ( exchangestr.buf[0] == 0 )
        {
            if ( iQ.s.baseid != 0 && iQ.s.relid != 0 )
                strcpy(exchangestr.buf,"nxtae");
            else strcpy(exchangestr.buf,"basket");
        }
        assetbits = InstantDEX_name(key,&keysize,exchangestr.buf,name.buf,base.buf,&iQ.s.baseid,rel.buf,&iQ.s.relid);
        //printf("2nd isask.%d base.(%s) rel.(%s)\n",iQ.s.isask,base.buf,rel.buf);
        exchange = exchange_find(exchangestr.buf);
        secret = jstr(json,"secret"), activenxt = jstr(json,"activenxt");
        if ( secret == 0 )
        {
            secret = SUPERNET.NXTACCTSECRET;
            activenxt = SUPERNET.NXTADDR;
        }
        if ( strcmp(method.buf,"allorderbooks") == 0 )
            retstr = prices777_allorderbooks();
        /*else if ( strcmp(method.buf,"coinshuffle") == 0 )
        {
            if ( strcmp(exchangestr.buf,"shuffle") == 0 )
                retstr = InstantDEX_coinshuffle(base.buf,&iQ,json);
            else retstr = clonestr("{\"error\":\"coinshuffle must use shuffle exchange\"}");
        }*/
        else if ( strcmp(method.buf,"openorders") == 0 )
            retstr = InstantDEX_openorders(SUPERNET.NXTADDR,juint(json,"allorders"));
        else if ( strcmp(method.buf,"allexchanges") == 0 )
            retstr = jprint(exchanges_json(),1);
        else if ( strcmp(method.buf,"cancelorder") == 0 )
            retstr = InstantDEX_cancelorder(jstr(json,"activenxt"),jstr(json,"secret"),sequenceid,iQ.s.quoteid);
        else if ( strcmp(method.buf,"orderstatus") == 0 )
            retstr = InstantDEX_orderstatus(sequenceid,iQ.s.quoteid);
        else if ( strcmp(method.buf,"tradehistory") == 0 )
            retstr = InstantDEX_tradehistory(juint(json,"firsti"),juint(json,"endi"));
        else if ( strcmp(method.buf,"lottostats") == 0 )
            retstr = jprint(InstantDEX_lottostats(),1);
        else if ( strcmp(method.buf,"balance") == 0 )
        {
            if ( exchange != 0 && exchange->trade != 0 )
            {
                if ( (coinstr= jstr(json,"base")) != 0 )
                {
                    if ( exchange->coinbalance != 0 )
                    {
                        if ( exchange->balancejson == 0 )
                        {
                            (*exchange->trade)(&retstr,exchange,0,0,0,0,0);
                            if ( retstr != 0 )
                            {
                                exchange->balancejson = cJSON_Parse(retstr);
                                free(retstr);
                            }
                        }
                        return((*exchange->coinbalance)(exchange,&balance,coinstr));
                    }
                    else retstr = clonestr("{\"error\":\"coinbalance missing\"}");
                }
                else (*exchange->trade)(&retstr,exchange,0,0,0,0,0);
            } else retstr = clonestr("{\"error\":\"cant find exchange\"}");
            printf("%s ptr%.p trade.%p\n",exchangestr.buf,exchange,exchange!=0?exchange->trade:0);
        }
        else if ( strcmp(method.buf,"tradesequence") == 0 )
        {
            //printf("call tradesequence.(%s)\n",jsonstr);
            retstr = InstantDEX_tradesequence(activenxt,secret,json);
        }
        else if ( strcmp(method.buf,"makebasket") == 0 )
        {
            if ( (prices= prices777_makebasket(0,json,1,"basket",0,0)) != 0 )
                retstr = clonestr("{\"result\":\"basket made\"}");
            else retstr = clonestr("{\"error\":\"couldnt make basket\"}");
        }
        else if ( strcmp(method.buf,"peggyrates") == 0 )
        {
            if ( SUPERNET.peggy != 0 )
                retstr = peggyrates(juint(json,"timestamp"));
            else retstr = clonestr("{\"error\":\"peggy disabled\"}");
        }
        else if ( strcmp(method.buf,"LSUM") == 0 )
        {
            sprintf(retbuf,"{\"result\":\"%s\",\"amount\":%d}",(rand() & 1) ? "BUY" : "SELL",(rand() % 100) * 100000);
            retstr = clonestr(retbuf);
        }
        else if ( strcmp(method.buf,"placebid") == 0 || strcmp(method.buf,"placeask") == 0 )
            return(InstantDEX_placebidask(0,sequenceid,exchangestr.buf,name.buf,base.buf,rel.buf,&iQ,jstr(json,"extra"),secret,activenxt,json));
        else if ( strcmp(exchangestr.buf,"active") == 0 && strcmp(method.buf,"orderbook") == 0 )
            retstr = prices777_activebooks(name.buf,base.buf,rel.buf,iQ.s.baseid,iQ.s.relid,maxdepth,allfields,strcmp(exchangestr.buf,"active") == 0 || juint(json,"tradeable"));
        else if ( (prices= prices777_find(&invert,iQ.s.baseid,iQ.s.relid,exchangestr.buf)) == 0 )
        {
            if ( (prices= prices777_poll(exchangestr.buf,name.buf,base.buf,iQ.s.baseid,rel.buf,iQ.s.relid)) != 0 )
            {
                if ( prices777_equiv(prices->baseid) == prices777_equiv(iQ.s.baseid) && prices777_equiv(prices->relid) == prices777_equiv(iQ.s.relid) )
                    invert = 0;
                else if ( prices777_equiv(prices->baseid) == prices777_equiv(iQ.s.relid) && prices777_equiv(prices->relid) == prices777_equiv(iQ.s.baseid) )
                    invert = 1;
                else invert = 0, printf("baserel not matching (%s %s) %llu %llu vs (%s %s) %llu %llu\n",prices->base,prices->rel,(long long)prices->baseid,(long long)prices->relid,base.buf,rel.buf,(long long)iQ.s.baseid,(long long)iQ.s.relid);
            }
        }
        if ( retstr == 0 && prices != 0 )
        {
            if ( strcmp(method.buf,"disable") == 0 )
            {
                if ( prices != 0 )
                {
                    if ( strcmp(prices->exchange,"unconf") == 0 )
                        return(clonestr("{\"error\":\"cannot disable unconf\"}"));
                    prices->disabled = 1;
                    return(clonestr("{\"result\":\"success\"}"));
                }
                else return(clonestr("{\"error\":\"no prices to disable\"}"));
            }
            else if ( strcmp(method.buf,"enable") == 0 )
            {
                if ( prices != 0 )
                {
                    prices->disabled = 0;
                    return(clonestr("{\"result\":\"success\"}"));
                }
                else return(clonestr("{\"error\":\"no prices to enable\"}"));
            }
            else if ( strcmp(method.buf,"orderbook") == 0 )
            {
                if ( maxdepth < MAX_DEPTH )
                    return(prices777_orderbook_jsonstr(invert,SUPERNET.my64bits,prices,&prices->O,maxdepth,allfields));
                else if ( (retstr= prices->orderbook_jsonstrs[invert][allfields]) == 0 )
                {
                    retstr = prices777_orderbook_jsonstr(invert,SUPERNET.my64bits,prices,&prices->O,MAX_DEPTH,allfields);
                    portable_mutex_lock(&prices->mutex);
                    if ( prices->orderbook_jsonstrs[invert][allfields] != 0 )
                        free(prices->orderbook_jsonstrs[invert][allfields]);
                    prices->orderbook_jsonstrs[invert][allfields] = retstr;
                    portable_mutex_unlock(&prices->mutex);
                    if ( retstr == 0 )
                        retstr = clonestr("{}");
                }
                if ( retstr != 0 )
                    retstr = clonestr(retstr);
            }
        }
        //if ( Debuglevel > 2 )
            printf("(%s) %p exchange.(%s) base.(%s) %llu rel.(%s) %llu | name.(%s) %llu\n",retstr!=0?retstr:"",prices,exchangestr.buf,base.buf,(long long)iQ.s.baseid,rel.buf,(long long)iQ.s.relid,name.buf,(long long)assetbits);
    }
    return(retstr);
}
int32_t bidask_parse(struct destbuf *exchangestr,struct destbuf *name,struct destbuf *base,struct destbuf *rel,struct destbuf *gui,struct InstantDEX_quote *iQ,cJSON *json)
{
    uint64_t basemult,relmult,baseamount,relamount; double price,volume; int32_t exchangeid,keysize,flag; char key[1024],buf[64],*methodstr;
    memset(iQ,0,sizeof(*iQ));
    iQ->s.baseid = j64bits(json,"baseid"); iQ->s.relid = j64bits(json,"relid");
    iQ->s.baseamount = j64bits(json,"baseamount"), iQ->s.relamount = j64bits(json,"relamount");
    iQ->s.vol = jdouble(json,"volume"); iQ->s.price = jdouble(json,"price");
    copy_cJSON(exchangestr,jobj(json,"exchange"));
    if ( exchangestr->buf[0] == 0 || find_exchange(&exchangeid,exchangestr->buf) == 0 )
        exchangeid = -1;
    iQ->exchangeid = exchangeid;
    copy_cJSON(base,jobj(json,"base"));
    copy_cJSON(rel,jobj(json,"rel"));
    copy_cJSON(name,jobj(json,"name"));
    methodstr = jstr(json,"method");
    if ( methodstr != 0 && (strcmp(methodstr,"placeask") == 0 || strcmp(methodstr,"ask") == 0) )
        iQ->s.isask = 1;
    if ( strcmp(exchangestr->buf,"wallet") == 0 && (iQ->s.baseid == NXT_ASSETID || strcmp(base->buf,"NXT") == 0) )
    {
        flag = 1;
        if ( strcmp(methodstr,"placeask") == 0 )
            methodstr = "placebid";
        else if ( strcmp(methodstr,"placebid") == 0 )
            methodstr = "placeask";
        else if ( strcmp(methodstr,"ask") == 0 )
            methodstr = "bid";
        else if ( strcmp(methodstr,"bid") == 0 )
            methodstr = "ask";
        else flag = 0;
        if ( flag != 0 )
        {
            iQ->s.baseid = iQ->s.relid, iQ->s.relid = NXT_ASSETID;
            strcpy(base->buf,rel->buf), strcpy(rel->buf,"NXT");
            baseamount = iQ->s.baseamount;
            iQ->s.baseamount = iQ->s.relamount, iQ->s.relamount = baseamount;
            name->buf[0] = 0;
            if ( iQ->s.vol > SMALLVAL && iQ->s.price > SMALLVAL )
            {
                iQ->s.vol *= iQ->s.price;
                iQ->s.price = 1. / iQ->s.price;
            }
            iQ->s.isask ^= 1;
            printf("INVERT\n");
        }
    }
    if ( (iQ->s.timestamp= juint(json,"timestamp")) == 0 )
        iQ->s.timestamp = (uint32_t)time(NULL);
    copy_cJSON(gui,jobj(json,"gui")), strncpy(iQ->gui,gui->buf,sizeof(iQ->gui)-1);
    iQ->s.automatch = juint(json,"automatch");
    iQ->s.minperc = juint(json,"minperc");
    if ( (iQ->s.duration= juint(json,"duration")) == 0 || iQ->s.duration > ORDERBOOK_EXPIRATION )
        iQ->s.duration = ORDERBOOK_EXPIRATION;
    InstantDEX_name(key,&keysize,exchangestr->buf,name->buf,base->buf,&iQ->s.baseid,rel->buf,&iQ->s.relid);
    //printf(">>>>>>>>>>>> BASE.(%s) REL.(%s)\n",base->buf,rel->buf);
    iQ->s.basebits = stringbits(base->buf);
    iQ->s.relbits = stringbits(rel->buf);
    iQ->s.offerNXT = j64bits(json,"offerNXT");
    iQ->s.quoteid = j64bits(json,"quoteid");
    if ( strcmp(exchangestr->buf,"shuffle") == 0 )
    {
        if ( iQ->s.price == 0. )
            iQ->s.price = 1.;
        if ( iQ->s.vol == 0. )
            iQ->s.vol = 1.;
        if ( iQ->s.baseamount == 0 )
            iQ->s.baseamount = iQ->s.price * SATOSHIDEN;
    }
    else
    {
        if ( iQ->s.baseamount == 0 || iQ->s.relamount == 0 )
        {
            if ( iQ->s.price <= SMALLVAL || iQ->s.vol <= SMALLVAL )
                return(-1);
            set_best_amounts(&iQ->s.baseamount,&iQ->s.relamount,iQ->s.price,iQ->s.vol);
        }
    }
    if ( iQ->s.quoteid == 0 )
        iQ->s.quoteid = calc_quoteid(iQ);
    else if ( iQ->s.quoteid != calc_quoteid(iQ) )
    {
        printf("bidask_parse quoteid.%llu != calc.%llu\n",(long long)iQ->s.quoteid,(long long)calc_quoteid(iQ));
        return(-1);
    }
    if ( iQ->s.price > SMALLVAL && iQ->s.vol > SMALLVAL && iQ->s.baseid != 0 && iQ->s.relid != 0 )
    {
        buf[0] = 0, _set_assetname(&basemult,buf,0,iQ->s.baseid);
        //printf("baseid.%llu -> %s mult.%llu\n",(long long)iQ->baseid,buf,(long long)basemult);
        buf[0] = 0, _set_assetname(&relmult,buf,0,iQ->s.relid);
        //printf("relid.%llu -> %s mult.%llu\n",(long long)iQ->relid,buf,(long long)relmult);
        //basemult = get_assetmult(iQ->baseid), relmult = get_assetmult(iQ->relid);
        baseamount = (iQ->s.baseamount + basemult/2) / basemult, baseamount *= basemult;
        relamount = (iQ->s.relamount + relmult/2) / relmult, relamount *= relmult;
        if ( iQ->s.price != 0. && iQ->s.vol != 0 )
        {
            price = prices777_price_volume(&volume,baseamount,relamount);
            if ( fabs(iQ->s.price - price)/price > 0.001 )
            {
                printf("cant create accurate price ref.(%f %f) -> (%f %f)\n",iQ->s.price,iQ->s.vol,price,volume);
                return(-1);
            }
        }
    }
    return(0);
}