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.

1006 lines
58 KiB

9 years ago
/******************************************************************************
9 years ago
* Copyright © 2014-2016 The SuperNET Developers. *
9 years ago
* *
* 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"
9 years ago
#include "SuperNET.h"
9 years ago
9 years ago
cJSON *helpjson(cJSON *json,cJSON *array,cJSON *agents,char *agentstr,char *method,cJSON *methodargs)
{
cJSON *methodobj,*item; int32_t i,n; char url[2048],curl[2048];
/*if ( *agentstrp == 0 || strcmp(*agentstrp,agentstr) != 0 )
{
if ( array != 0 )
jadd(json,*agentstrp,array);
*agentstrp = agentstr;
jaddistr(agents,agentstr);
printf("add agent.(%s)\n",agentstr);
}*/
if ( (n= cJSON_GetArraySize(agents)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(agents,i);
if ( strcmp(agentstr,jstr(item,0)) == 0 )
break;
}
} else i = 0;
if ( i == n )
jaddistr(agents,agentstr);
if ( array == 0 )
array = cJSON_CreateArray();
methodobj = cJSON_CreateObject();
jaddstr(methodobj,"agent",agentstr);
jaddstr(methodobj,"method",method);
sprintf(url,"http://127.0.0.1:7778/api/%s/%s",agentstr,method);
sprintf(curl,"curl --url \"http://127.0.0.1:7778\" --data \"{\\\"agent\\\":\\\"%s\\\",\\\"method\\\":\\\"%s\\\"",agentstr,method);
9 years ago
if ( methodargs != 0 && (n= cJSON_GetArraySize(methodargs)) > 0 )
{
//printf("method.%s n.%d %s\n",method,n,jprint(methodargs,0));
for (i=0; i<n; i++)
{
strcat(url,i==0?"?":"&");
item = jitem(methodargs,i);
sprintf(url+strlen(url),"%s={%s}",get_cJSON_fieldname(item),jstr(item,get_cJSON_fieldname(item)));
sprintf(curl+strlen(curl),",\\\"%s\\\":\\\"{%s}\\\"",get_cJSON_fieldname(item),jstr(item,get_cJSON_fieldname(item)));
9 years ago
}
}
strcat(curl,"}\"");
jaddstr(methodobj,"url",url);
jaddstr(methodobj,"curl",curl);
jadd(methodobj,"fields",methodargs==0?cJSON_CreateArray():methodargs);
jaddi(array,methodobj);
return(array);
}
cJSON *helpitem(char *field,char *type) { cJSON *obj = cJSON_CreateObject(); jaddstr(obj,field,type); return(obj); }
cJSON *helparray(cJSON *array,cJSON *obj0) { jaddi(array,obj0); return(array);}
cJSON *helparray2(cJSON *array,cJSON *obj0,cJSON *obj1) { jaddi(array,obj0); return(helparray(array,obj1)); }
cJSON *helparray3(cJSON *array,cJSON *obj0,cJSON *obj1,cJSON *obj2) { jaddi(array,obj0); return(helparray2(array,obj1,obj2)); }
cJSON *helparray4(cJSON *array,cJSON *obj0,cJSON *obj1,cJSON *obj2,cJSON *obj3) { jaddi(array,obj0); return(helparray3(array,obj1,obj2,obj3)); }
cJSON *helparray5(cJSON *array,cJSON *obj0,cJSON *obj1,cJSON *obj2,cJSON *obj3,cJSON *obj4) { jaddi(array,obj0); return(helparray4(array,obj1,obj2,obj3,obj4)); }
cJSON *helparray6(cJSON *array,cJSON *obj0,cJSON *obj1,cJSON *obj2,cJSON *obj3,cJSON *obj4,cJSON *obj5) { jaddi(array,obj0); return(helparray5(array,obj1,obj2,obj3,obj4,obj5)); }
9 years ago
cJSON *helparray7(cJSON *array,cJSON *obj0,cJSON *obj1,cJSON *obj2,cJSON *obj3,cJSON *obj4,cJSON *obj5,cJSON *obj6) { jaddi(array,obj0); return(helparray6(array,obj1,obj2,obj3,obj4,obj5,obj6)); }
cJSON *helparray8(cJSON *array,cJSON *obj0,cJSON *obj1,cJSON *obj2,cJSON *obj3,cJSON *obj4,cJSON *obj5,cJSON *obj6,cJSON *obj7) { jaddi(array,obj0); return(helparray7(array,obj1,obj2,obj3,obj4,obj5,obj6,obj7)); }
cJSON *helparray9(cJSON *array,cJSON *obj0,cJSON *obj1,cJSON *obj2,cJSON *obj3,cJSON *obj4,cJSON *obj5,cJSON *obj6,cJSON *obj7,cJSON *obj9) { jaddi(array,obj0); return(helparray8(array,obj1,obj2,obj3,obj4,obj5,obj6,obj7,obj9)); }
cJSON *helparray10(cJSON *array,cJSON *obj0,cJSON *obj1,cJSON *obj2,cJSON *obj3,cJSON *obj4,cJSON *obj5,cJSON *obj6,cJSON *obj7,cJSON *obj9,cJSON *obj10) { jaddi(array,obj0); return(helparray9(array,obj1,obj2,obj3,obj4,obj5,obj6,obj7,obj9,obj10)); }
cJSON *helparray11(cJSON *array,cJSON *obj0,cJSON *obj1,cJSON *obj2,cJSON *obj3,cJSON *obj4,cJSON *obj5,cJSON *obj6,cJSON *obj7,cJSON *obj9,cJSON *obj10,cJSON *obj11) { jaddi(array,obj0); return(helparray10(array,obj1,obj2,obj3,obj4,obj5,obj6,obj7,obj9,obj10,obj11)); }
cJSON *helparray12(cJSON *array,cJSON *obj0,cJSON *obj1,cJSON *obj2,cJSON *obj3,cJSON *obj4,cJSON *obj5,cJSON *obj6,cJSON *obj7,cJSON *obj9,cJSON *obj10,cJSON *obj11,cJSON *obj12) { jaddi(array,obj0); return(helparray11(array,obj1,obj2,obj3,obj4,obj5,obj6,obj7,obj9,obj10,obj11,obj12)); }
cJSON *helparray13(cJSON *array,cJSON *obj0,cJSON *obj1,cJSON *obj2,cJSON *obj3,cJSON *obj4,cJSON *obj5,cJSON *obj6,cJSON *obj7,cJSON *obj9,cJSON *obj10,cJSON *obj11,cJSON *obj12,cJSON *obj13) { jaddi(array,obj0); return(helparray12(array,obj1,obj2,obj3,obj4,obj5,obj6,obj7,obj9,obj10,obj11,obj12,obj13)); }
cJSON *helparray14(cJSON *array,cJSON *obj0,cJSON *obj1,cJSON *obj2,cJSON *obj3,cJSON *obj4,cJSON *obj5,cJSON *obj6,cJSON *obj7,cJSON *obj9,cJSON *obj10,cJSON *obj11,cJSON *obj12,cJSON *obj13,cJSON *obj14) { jaddi(array,obj0); return(helparray13(array,obj1,obj2,obj3,obj4,obj5,obj6,obj7,obj9,obj10,obj11,obj12,obj13,obj14)); }
cJSON *helparray15(cJSON *array,cJSON *obj0,cJSON *obj1,cJSON *obj2,cJSON *obj3,cJSON *obj4,cJSON *obj5,cJSON *obj6,cJSON *obj7,cJSON *obj9,cJSON *obj10,cJSON *obj11,cJSON *obj12,cJSON *obj13,cJSON *obj14,cJSON *obj15) { jaddi(array,obj0); return(helparray14(array,obj1,obj2,obj3,obj4,obj5,obj6,obj7,obj9,obj10,obj11,obj12,obj13,obj14,obj15)); }
9 years ago
cJSON *SuperNET_helpjson()
{
cJSON *array=0,*json,*agents;
json = cJSON_CreateObject();
agents = cJSON_CreateArray();
#define IGUANA_ARGS json,array,agents
#define IGUANA_HELP0(agent,name) array = helpjson(IGUANA_ARGS,#agent,#name,0)
#define IGUANA_HELP_S(agent,name,str) array = helpjson(IGUANA_ARGS,#agent,#name,helparray(cJSON_CreateArray(),helpitem(#str,"string")))
#define IGUANA_HELP_SS(agent,name,str,str2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string")))
#define IGUANA_HELP_SSS(agent,name,str,str2,str3) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#str3,"string")))
9 years ago
#define IGUANA_HELP_SDD(agent,name,str,val,val2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#val,"float"),helpitem(#val2,"float")))
many changes blockexplorer tab: needs to allow to input height, blockhash or txid. also please display images/BTC_blocks.jpg below the text as a w800 x h400 bitmap, which is active using the mouse api for coin management, below the active coins have a form that arbitrary json can be input with an add button to the right that will call &#34;addcoin&#34; API. this way I can test adding new coins dynamically. dont worry if it doesnt work, just as long as it submits the json to the C code. I am pretty sure I need to do some debugging of this peers management is not working for me at all. maybe it is due to bad internet. On initialization you need to read in the confs/BTCD_peers.txt from the native filesystem and save it into the chrome app filesystem. same thing for confs/BTCD_hdrs.txt. But this is only to be done if there isnt already such a file inside chrome. if there is, only do it upon a button invoked by the user. the reason is that the pexe is updating this file with the latest. Maybe it is nice to have an &#34;extract&#34; button that will copy out from the chrome storage into the native filesystem. There is also the manifest issue about localstorage vs chrome.localstorage. not sure what is needed to be done, but certainly a priority to get it so everything works as a chrome app. I know before it was making ramchain files inside the chrome filesystem, so it is probably things the GUI is doing. maybe in the settings tab, which has obsolete stuff that can be removed. anyway, the issue about files existing in the native filesystem -&gt; chrome and optionally extracting them is an issue for the confs files and .html template files used to autogenerate the port7778, maybe other files are affected. i think we need a way to have a list of hardcoded files that are just copied into chrome on startup if they dont exist already (or if possible copy over if the native version is bigger?) and buttons to extract them for debug tab: THREE_STRINGS(SuperNET,encryptjson,passphrase,permanentfile,anything); TWO_STRINGS(SuperNET,decryptjson,passphrase,permanentfile); at the top of page a way to put in passphrase and optional permanentfile along with arbitrary json. The standard form template has no easy way to describe to pass in everything as it is oriented to specific fields. but the encryptjson API saves all the fields, so the arbitrary json from the form needs to be combined at the same level as the &#34;agent&#34;, &#34;method&#34;, etc. I know, not the best, but internally it makes it easier. so {&#34;agent&#34;:&#34;SuperNET&#34;,&#34;method&#34;:&#34;encryptjson&#34;,&#34;passphrase&#34;:&#34;&lt;passphrase&gt;&#34;,&#34; permanentfile&#34;:&#34;&lt;filename&gt;&#34;,&#34;fromform&#34;:&#34;valuefromform&#34;,&#34;fromform2&#34;:&#34;valu efromform2&#34;,...rest of form at top level} then this will save it into a file with crazy number (it is a hash like txid) but given the same passphrase and filename, it will regenerate this hash so you dont actually have to store it, but it helps during debugging. for the filename, we must warn quite strongly to the user that if the file is ever lost or even changed in any way that the data will not be recoverable. also best to not allow the user to specify a file that does not exist. I think at this point chrome app version gets a bit tricky. we could simply push the native file into the chrome storage, but then an attacker who gets access to the computer could just get a list of these files and it really wont be much protection. So that means if a filename is specified, it needs to be copied into the chrome space, then immediately deleted... ok, this seems like not a good approach. let us make it so that the permanentfile option is not available from the chrome app, but only if the native version is running. that way we sidestep the issue of the pexe not having access to the specified file. Speaking of native vs pexe, on the startup page we should have a radio button that allows the user to select which the GUI will talk to. It should default based on a self test to the more likely value, but it is possible that the user wants to use the native version, even if the pexe is running. another thing to have on the startup page is a simple login: THREE_STRINGS(SuperNET,login,passphrase,permanentfile,handle); ZERO_ARGS(SuperNET,logout); ZERO_ARGS(SuperNET,activehandle); the handle is a human readable name that is associated with the passphrase/permanentfile. There can only be one active account (though it will be possible to associate different accounts with tradebots). use the activehandle API to find out who is logged in and the associated addresses and pubkeys The above is not yet tested so if it doesnt work, dont fret, just let me know. Once set the handle can be displayed in various places to let the user know which account is logged in. The standard 12 dictionary word passphrases should be used, but any string can be sent in as the password for Pangea: INT_AND_ARRAY(pangea,host,minplayers,params); ZERO_ARGS(pangea,lobby); HASH_AND_STRING(pangea,join,tablehash,handle); HASH_AND_INT(pangea,buyin,tablehash,numchips); HASH_ARG(pangea,start,tablehash); // by host only HASH_ARG(pangea,status,tablehash); HASH_ARG(pangea,call,tablehash); HASH_ARG(pangea,check,tablehash); HASH_AND_INT(pangea,raise,tablehash,numchips); HASH_AND_INT(pangea,bet,tablehash,numchips); HASH_ARG(pangea,fold,tablehash); HASH_AND_STRING(pangea,mode,tablehash,modestr); HASH_ARG(pangea,history,tablehash); HASH_AND_INT(pangea,handhistory,tablehash,hand); The first thing that is done is a &#34;host&#34; by any node. the &#34;params&#34; should be an arbitrary json (like encryptjson) as it needs to be at the top level and it has quite a few different parameters still subject to change. The lobby API will just display all the hosted tables. once a table exists, players can join and then buyin. the buyin is denominated in chips, each chip&#39;s value is determined by the host&#39;s initial parameters. once there are enough players joined with adequate buyin&#39;s verified, the host will be able to do a start. if done before it will (eventually) give an error. for now it will just proceed. The host and players that have joined a tablehash, need to do regular status calls to see if the game has started. Probably just once per 5 or even 10 seconds is fine before the start. Once the game starts (the status will have this info) then once per second polling is needed. Then when it is your turn (as indicated by status) you need to do one of the 5 actions (fold, call, check, raise, bet). do not worry if you dont understand what all these do, just allow the user to do any of these. I guess it is possible to submit it ahead of time. I will support internally remembering the most recent action done prior to it being your turn. once it is your turn and an action is sent to the table, it is too late to change. The last API calls are for getting handhistory where hand is 0 to N-1, being the numbering of the hands played at that table. if just history, all the history for all hands at the table is coming back, so it could be quite big. probably I will make it a summary, but for the GUI just display the returned values. the mode is to change some poker specific modes, so just allow there to be a string entered. do not worry about understanding the pokerness of the API, just the overall flow: host -&gt; creates, join/buyin -&gt; fills up player slots, start -&gt; starts the game status -&gt; to determine when the game starts (or if it is cancelled) and once started actions -&gt; game specific but basically just (button + arg) that is the user input results are via status for current game and history for past ones please try to do the above logic in a generic way so it can be reused for other games. The basic flow should be the same for almost all multiplayer turn based games and even for multiplayer realtime games For InstantDEX: on the apikeypair/userid there needs to be two modes. one for when there is no stored apikey and the current form is fine, just need to make it wider as most apikeys are quite long. Now once there is an apikey saved all that is needed is the passphrase to unlock it. So here is where the encrptjson/decryptjson is used. When saving the apikey for the first time, it can be: a) not saved -&gt; nothing extra to do b) saved without password -&gt; you can just save to a file and use it to load it back in. use confs dir confs/instantdex.exchange.api or something like that c) saved with password (optional filename for native) -&gt; probably best to save in the confs dir to indicate that there is an encrypted file for this, so just that and not the actual passphrase in the file with the above, when the exchange is selected, you can see if the confs file exists and if it has the plaintext, just populate the field, if not, then indicate that a passphrase is needed. if the user provides the passphrase, then decryptjson and populate the fields and autosubmit. A special case is to encrypt the apikeys with the passphrase used when logging in. This is only available if the checkbox to &#34;remember passphrase during session&#34; is set on the main iguana login screen. (i forgot to mention that checkbox!) So the login passphrase is stored in memory, then the GUI simply uses that + encryptjson for storing/decrypting. I would imagine that storing in the confs file that it is encrypted using &#34;handle&#34;&#39;s account login might be a good way to differentiate between this mode of password usage. OK, so we now have the insecure plaintext, the decent using handle&#39;s passphrase and paranoid different passphrase for each exchange (with additional permanentfile for native versions) &#34;SUPPORT&#34; -&gt; &#34;SUPPORTS&#34; just a typo and &#34;allpairs&#34; API is missing from the selection Might as well add a &#34;tradebots&#34; tab: THREE_STRINGS_AND_DOUBLE(tradebot,monitor,exchange,base,rel,commission); STRING_AND_DOUBLE(tradebot,monitorall,exchange,commission); THREE_STRINGS(tradebot,unmonitor,exchange,base,rel); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,accumulate,exchange,base,rel,pr ice,volume,duration); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,divest,exchange,base,rel,price, volume,duration); STRING_ARG(tradebot,activebots,exchange); TWO_STRINGS(tradebot,status,exchange,botid); TWO_STRINGS(tradebot,pause,exchange,botid); TWO_STRINGS(tradebot,stop,exchange,botid); TWO_STRINGS(tradebot,resume,exchange,botid); the above are API for exchange specific bots, most should be self-explanatory. bots are created via &#34;accumulate&#34; or &#34;divest&#34; API call. it returns botid. once created, you can do status, pause, stop, resume to a botid. and an activebots API call lists all the active bots for an exchange. duration is in seconds the &#34;monitor&#34; API starts background monitoring of a specific base/rel, &#34;unmonitor&#34; stops this. &#34;monitorall&#34; just does a monitor to the entire list of &#34;allpairs&#34; for that exchange. Keep in mind that doing a monitorall will not add load to an exchange as the request to each exchange is governed by pollgap, but if you have 3 things monitored, it will take 3*pollgap + time each one takes to execute. and if N are monitored it is N*pollgap + time of each, with the &#34;time of each&#34; possibly taking a very long time. And one final request for today: Bitmap tab. It should be an active bitmap using mouse api. either a dropdown to select the bitmap or a form entry. then the rest of the page (resize the bitmap to the page size) being the active bitmap. So on a small screen the bitmap is smaller x/y dimensions and larger on larger screens. plz make sure the proper dimensions are communicated to the pexe via API if it ever is changed. @vineet.bhargav86: I changed the &#34;passphrase&#34; fieldname to &#34;password&#34; for the encryptjson/decryptjson related API. The reason is that the password is like a wallet password and is only local, so it doesnt need to be as high entropy as passphrase. I also added a field to the login API as I realized that the 12 word &#34;passphrase&#34; is the payload and usually wont be sent in: FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase); using &#34;abiglongpassword&#34; for the passphrase -&gt; {&#34;pubkey&#34;:&#34;6c469ba10b40b3eb9d1dba569d7f929d55a29d8f97cd5425907ef2f38f906 209&#34;,&#34;RS&#34;:&#34;NXT-KGV9-DXX8-TM86-DXR96&#34;,&#34;NXT&#34;:&#34;12834974574569896807&#34;,&#34;btcpu bkey&#34;:&#34;024e7641dc947b211bc30fe3339765258902794687b227121fc217284f9d8503c 8&#34;,&#34;rmd160&#34;:&#34;33453c24914db7b77069b7ea24df44f6be145938&#34;,&#34;BTC&#34;:&#34;15g6QK2dSd iW9ZTQEnnJxKrSph6uP7uU23&#34;,&#34;BTCD&#34;:&#34;RDxHUpuv3TX5DZpbhxmS3rBeaxZW1fvYvC&#34;,&#34;r esult&#34;:&#34;success&#34;,&#34;handle&#34;:&#34;test&#34;,&#34;tag&#34;:&#34;14805226009240621255&#34;} and if you use that to log into NXT, it gives the same address. The BTC and BTCD addresses are all derived from the same privkey so they are all interchangeable with the NXT address. The user can therefore select which coin&#39;s addressing they are most comfortable with I also added an &#34;allin&#34; action API for pangea. all the action API will autocalculate the number of chips if passed in 0 for numchips ***************** security issue ******** please dont use the GET URL method when dealing with passphrase!!! Those URL&#39;s tend to get logged and available in browser histories. so anything dealing with the actual passphrase needs to use the postCall form or POST
9 years ago
#define IGUANA_HELP_SSSS(agent,name,str,str2,str3,str4) array = helpjson(IGUANA_ARGS,#agent,#name,helparray4(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#str3,"string"),helpitem(#str4,"string")))
9 years ago
#define IGUANA_HELP_SSSD(agent,name,str,str2,str3,amount) array = helpjson(IGUANA_ARGS,#agent,#name,helparray4(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#str3,"string"),helpitem(#amount,"float")))
#define IGUANA_HELP_SSSDDD(agent,name,str,str2,str3,amount,val2,val3) array = helpjson(IGUANA_ARGS,#agent,#name,helparray6(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#str3,"string"),helpitem(#amount,"float"),helpitem(#val2,"float"),helpitem(#val3,"float")))
#define IGUANA_HELP_SSSIII(agent,name,str,str2,str3,val,val2,val3) array = helpjson(IGUANA_ARGS,#agent,#name,helparray6(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#str3,"string"),helpitem(#val,"int"),helpitem(#val2,"int"),helpitem(#val3,"int")))
9 years ago
#define IGUANA_HELP_SSH(agent,name,str,str2,hash) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#hash,"hash")))
#define IGUANA_HELP_SSHI(agent,name,str,str2,hash,val) array = helpjson(IGUANA_ARGS,#agent,#name,helparray4(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#hash,"hash"),helpitem(#val,"int")))
9 years ago
#define IGUANA_HELP_SSDD(agent,name,str,str2,val,val2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray4(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#val,"float"),helpitem(#val2,"float")))
9 years ago
#define IGUANA_HELP_SSHII(agent,name,str,str2,hash,val,val2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray5(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#hash,"hash"),helpitem(#val,"int"),helpitem(#val2,"int")))
#define IGUANA_HELP_SSHHII(agent,name,str,str2,hash,hash2,val,val2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray6(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#hash,"hash"),helpitem(#hash2,"hash"),helpitem(#val,"int"),helpitem(#val2,"int")))
9 years ago
#define IGUANA_HELP_SI(agent,name,str,val) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#val,"int")))
many changes blockexplorer tab: needs to allow to input height, blockhash or txid. also please display images/BTC_blocks.jpg below the text as a w800 x h400 bitmap, which is active using the mouse api for coin management, below the active coins have a form that arbitrary json can be input with an add button to the right that will call &#34;addcoin&#34; API. this way I can test adding new coins dynamically. dont worry if it doesnt work, just as long as it submits the json to the C code. I am pretty sure I need to do some debugging of this peers management is not working for me at all. maybe it is due to bad internet. On initialization you need to read in the confs/BTCD_peers.txt from the native filesystem and save it into the chrome app filesystem. same thing for confs/BTCD_hdrs.txt. But this is only to be done if there isnt already such a file inside chrome. if there is, only do it upon a button invoked by the user. the reason is that the pexe is updating this file with the latest. Maybe it is nice to have an &#34;extract&#34; button that will copy out from the chrome storage into the native filesystem. There is also the manifest issue about localstorage vs chrome.localstorage. not sure what is needed to be done, but certainly a priority to get it so everything works as a chrome app. I know before it was making ramchain files inside the chrome filesystem, so it is probably things the GUI is doing. maybe in the settings tab, which has obsolete stuff that can be removed. anyway, the issue about files existing in the native filesystem -&gt; chrome and optionally extracting them is an issue for the confs files and .html template files used to autogenerate the port7778, maybe other files are affected. i think we need a way to have a list of hardcoded files that are just copied into chrome on startup if they dont exist already (or if possible copy over if the native version is bigger?) and buttons to extract them for debug tab: THREE_STRINGS(SuperNET,encryptjson,passphrase,permanentfile,anything); TWO_STRINGS(SuperNET,decryptjson,passphrase,permanentfile); at the top of page a way to put in passphrase and optional permanentfile along with arbitrary json. The standard form template has no easy way to describe to pass in everything as it is oriented to specific fields. but the encryptjson API saves all the fields, so the arbitrary json from the form needs to be combined at the same level as the &#34;agent&#34;, &#34;method&#34;, etc. I know, not the best, but internally it makes it easier. so {&#34;agent&#34;:&#34;SuperNET&#34;,&#34;method&#34;:&#34;encryptjson&#34;,&#34;passphrase&#34;:&#34;&lt;passphrase&gt;&#34;,&#34; permanentfile&#34;:&#34;&lt;filename&gt;&#34;,&#34;fromform&#34;:&#34;valuefromform&#34;,&#34;fromform2&#34;:&#34;valu efromform2&#34;,...rest of form at top level} then this will save it into a file with crazy number (it is a hash like txid) but given the same passphrase and filename, it will regenerate this hash so you dont actually have to store it, but it helps during debugging. for the filename, we must warn quite strongly to the user that if the file is ever lost or even changed in any way that the data will not be recoverable. also best to not allow the user to specify a file that does not exist. I think at this point chrome app version gets a bit tricky. we could simply push the native file into the chrome storage, but then an attacker who gets access to the computer could just get a list of these files and it really wont be much protection. So that means if a filename is specified, it needs to be copied into the chrome space, then immediately deleted... ok, this seems like not a good approach. let us make it so that the permanentfile option is not available from the chrome app, but only if the native version is running. that way we sidestep the issue of the pexe not having access to the specified file. Speaking of native vs pexe, on the startup page we should have a radio button that allows the user to select which the GUI will talk to. It should default based on a self test to the more likely value, but it is possible that the user wants to use the native version, even if the pexe is running. another thing to have on the startup page is a simple login: THREE_STRINGS(SuperNET,login,passphrase,permanentfile,handle); ZERO_ARGS(SuperNET,logout); ZERO_ARGS(SuperNET,activehandle); the handle is a human readable name that is associated with the passphrase/permanentfile. There can only be one active account (though it will be possible to associate different accounts with tradebots). use the activehandle API to find out who is logged in and the associated addresses and pubkeys The above is not yet tested so if it doesnt work, dont fret, just let me know. Once set the handle can be displayed in various places to let the user know which account is logged in. The standard 12 dictionary word passphrases should be used, but any string can be sent in as the password for Pangea: INT_AND_ARRAY(pangea,host,minplayers,params); ZERO_ARGS(pangea,lobby); HASH_AND_STRING(pangea,join,tablehash,handle); HASH_AND_INT(pangea,buyin,tablehash,numchips); HASH_ARG(pangea,start,tablehash); // by host only HASH_ARG(pangea,status,tablehash); HASH_ARG(pangea,call,tablehash); HASH_ARG(pangea,check,tablehash); HASH_AND_INT(pangea,raise,tablehash,numchips); HASH_AND_INT(pangea,bet,tablehash,numchips); HASH_ARG(pangea,fold,tablehash); HASH_AND_STRING(pangea,mode,tablehash,modestr); HASH_ARG(pangea,history,tablehash); HASH_AND_INT(pangea,handhistory,tablehash,hand); The first thing that is done is a &#34;host&#34; by any node. the &#34;params&#34; should be an arbitrary json (like encryptjson) as it needs to be at the top level and it has quite a few different parameters still subject to change. The lobby API will just display all the hosted tables. once a table exists, players can join and then buyin. the buyin is denominated in chips, each chip&#39;s value is determined by the host&#39;s initial parameters. once there are enough players joined with adequate buyin&#39;s verified, the host will be able to do a start. if done before it will (eventually) give an error. for now it will just proceed. The host and players that have joined a tablehash, need to do regular status calls to see if the game has started. Probably just once per 5 or even 10 seconds is fine before the start. Once the game starts (the status will have this info) then once per second polling is needed. Then when it is your turn (as indicated by status) you need to do one of the 5 actions (fold, call, check, raise, bet). do not worry if you dont understand what all these do, just allow the user to do any of these. I guess it is possible to submit it ahead of time. I will support internally remembering the most recent action done prior to it being your turn. once it is your turn and an action is sent to the table, it is too late to change. The last API calls are for getting handhistory where hand is 0 to N-1, being the numbering of the hands played at that table. if just history, all the history for all hands at the table is coming back, so it could be quite big. probably I will make it a summary, but for the GUI just display the returned values. the mode is to change some poker specific modes, so just allow there to be a string entered. do not worry about understanding the pokerness of the API, just the overall flow: host -&gt; creates, join/buyin -&gt; fills up player slots, start -&gt; starts the game status -&gt; to determine when the game starts (or if it is cancelled) and once started actions -&gt; game specific but basically just (button + arg) that is the user input results are via status for current game and history for past ones please try to do the above logic in a generic way so it can be reused for other games. The basic flow should be the same for almost all multiplayer turn based games and even for multiplayer realtime games For InstantDEX: on the apikeypair/userid there needs to be two modes. one for when there is no stored apikey and the current form is fine, just need to make it wider as most apikeys are quite long. Now once there is an apikey saved all that is needed is the passphrase to unlock it. So here is where the encrptjson/decryptjson is used. When saving the apikey for the first time, it can be: a) not saved -&gt; nothing extra to do b) saved without password -&gt; you can just save to a file and use it to load it back in. use confs dir confs/instantdex.exchange.api or something like that c) saved with password (optional filename for native) -&gt; probably best to save in the confs dir to indicate that there is an encrypted file for this, so just that and not the actual passphrase in the file with the above, when the exchange is selected, you can see if the confs file exists and if it has the plaintext, just populate the field, if not, then indicate that a passphrase is needed. if the user provides the passphrase, then decryptjson and populate the fields and autosubmit. A special case is to encrypt the apikeys with the passphrase used when logging in. This is only available if the checkbox to &#34;remember passphrase during session&#34; is set on the main iguana login screen. (i forgot to mention that checkbox!) So the login passphrase is stored in memory, then the GUI simply uses that + encryptjson for storing/decrypting. I would imagine that storing in the confs file that it is encrypted using &#34;handle&#34;&#39;s account login might be a good way to differentiate between this mode of password usage. OK, so we now have the insecure plaintext, the decent using handle&#39;s passphrase and paranoid different passphrase for each exchange (with additional permanentfile for native versions) &#34;SUPPORT&#34; -&gt; &#34;SUPPORTS&#34; just a typo and &#34;allpairs&#34; API is missing from the selection Might as well add a &#34;tradebots&#34; tab: THREE_STRINGS_AND_DOUBLE(tradebot,monitor,exchange,base,rel,commission); STRING_AND_DOUBLE(tradebot,monitorall,exchange,commission); THREE_STRINGS(tradebot,unmonitor,exchange,base,rel); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,accumulate,exchange,base,rel,pr ice,volume,duration); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,divest,exchange,base,rel,price, volume,duration); STRING_ARG(tradebot,activebots,exchange); TWO_STRINGS(tradebot,status,exchange,botid); TWO_STRINGS(tradebot,pause,exchange,botid); TWO_STRINGS(tradebot,stop,exchange,botid); TWO_STRINGS(tradebot,resume,exchange,botid); the above are API for exchange specific bots, most should be self-explanatory. bots are created via &#34;accumulate&#34; or &#34;divest&#34; API call. it returns botid. once created, you can do status, pause, stop, resume to a botid. and an activebots API call lists all the active bots for an exchange. duration is in seconds the &#34;monitor&#34; API starts background monitoring of a specific base/rel, &#34;unmonitor&#34; stops this. &#34;monitorall&#34; just does a monitor to the entire list of &#34;allpairs&#34; for that exchange. Keep in mind that doing a monitorall will not add load to an exchange as the request to each exchange is governed by pollgap, but if you have 3 things monitored, it will take 3*pollgap + time each one takes to execute. and if N are monitored it is N*pollgap + time of each, with the &#34;time of each&#34; possibly taking a very long time. And one final request for today: Bitmap tab. It should be an active bitmap using mouse api. either a dropdown to select the bitmap or a form entry. then the rest of the page (resize the bitmap to the page size) being the active bitmap. So on a small screen the bitmap is smaller x/y dimensions and larger on larger screens. plz make sure the proper dimensions are communicated to the pexe via API if it ever is changed. @vineet.bhargav86: I changed the &#34;passphrase&#34; fieldname to &#34;password&#34; for the encryptjson/decryptjson related API. The reason is that the password is like a wallet password and is only local, so it doesnt need to be as high entropy as passphrase. I also added a field to the login API as I realized that the 12 word &#34;passphrase&#34; is the payload and usually wont be sent in: FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase); using &#34;abiglongpassword&#34; for the passphrase -&gt; {&#34;pubkey&#34;:&#34;6c469ba10b40b3eb9d1dba569d7f929d55a29d8f97cd5425907ef2f38f906 209&#34;,&#34;RS&#34;:&#34;NXT-KGV9-DXX8-TM86-DXR96&#34;,&#34;NXT&#34;:&#34;12834974574569896807&#34;,&#34;btcpu bkey&#34;:&#34;024e7641dc947b211bc30fe3339765258902794687b227121fc217284f9d8503c 8&#34;,&#34;rmd160&#34;:&#34;33453c24914db7b77069b7ea24df44f6be145938&#34;,&#34;BTC&#34;:&#34;15g6QK2dSd iW9ZTQEnnJxKrSph6uP7uU23&#34;,&#34;BTCD&#34;:&#34;RDxHUpuv3TX5DZpbhxmS3rBeaxZW1fvYvC&#34;,&#34;r esult&#34;:&#34;success&#34;,&#34;handle&#34;:&#34;test&#34;,&#34;tag&#34;:&#34;14805226009240621255&#34;} and if you use that to log into NXT, it gives the same address. The BTC and BTCD addresses are all derived from the same privkey so they are all interchangeable with the NXT address. The user can therefore select which coin&#39;s addressing they are most comfortable with I also added an &#34;allin&#34; action API for pangea. all the action API will autocalculate the number of chips if passed in 0 for numchips ***************** security issue ******** please dont use the GET URL method when dealing with passphrase!!! Those URL&#39;s tend to get logged and available in browser histories. so anything dealing with the actual passphrase needs to use the postCall form or POST
9 years ago
#define IGUANA_HELP_SD(agent,name,str,val) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#val,"float")))
9 years ago
#define IGUANA_HELP_SII(agent,name,str,val,val2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#val,"int"),helpitem(#val2,"int")))
#define IGUANA_HELP_SSI(agent,name,str,str2,val) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#val,"int")))
#define IGUANA_HELP_SA(agent,name,str,obj) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#obj,"array")))
#define IGUANA_HELP_SAA(agent,name,str,obj,obj2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#obj,"array"),helpitem(#obj2,"array")))
#define IGUANA_HELP_SIII(agent,name,str,val,val2,val3) array = helpjson(IGUANA_ARGS,#agent,#name,helparray4(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#val,"int"),helpitem(#val2,"int"),helpitem(#val3,"int")))
#define IGUANA_HELP_I(agent,name,val) array = helpjson(IGUANA_ARGS,#agent,#name,helparray(cJSON_CreateArray(),helpitem(#val,"int")))
#define IGUANA_HELP_II(agent,name,val,val2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#val,"int"),helpitem(#val2,"int")))
#define IGUANA_HELP_IA(agent,name,val,obj) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#val,"int"),helpitem(#obj,"array")))
#define IGUANA_HELP_IIA(agent,name,val,val2,obj) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#val,"int"),helpitem(#val2,"int"),helpitem(#obj,"array")))
#define IGUANA_HELP_III(agent,name,val,val2,val3) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#val,"int"),helpitem(#val2,"int"),helpitem(#val3,"int")))
#define IGUANA_HELP_IAS(agent,name,val,obj,str) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#val,"int"),helpitem(#obj,"array"),helpitem(#str,"string")))
9 years ago
#define IGUANA_HELP_64A(agent,name,j64,obj) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#j64,"u64bits"),helpitem(#obj,"array")))
9 years ago
#define IGUANA_HELP_AA(agent,name,obj,obj2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#obj,"array"),helpitem(#obj2,"array")))
9 years ago
#define IGUANA_HELP_AOI(agent,name,obj,obj2,val) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#obj,"array"),helpitem(#obj2,"object"),helpitem(#val,"int")))
9 years ago
#define IGUANA_HELP_D(agent,name,amount) array = helpjson(IGUANA_ARGS,#agent,#name,helparray(cJSON_CreateArray(),helpitem(#amount,"float")))
9 years ago
#define IGUANA_HELP_H(agent,name,hash) array = helpjson(IGUANA_ARGS,#agent,#name,helparray(cJSON_CreateArray(),helpitem(#hash,"hash")))
9 years ago
#define IGUANA_HELP_HI(agent,name,hash,val) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#hash,"hash"),helpitem(#val,"int")))
9 years ago
#define IGUANA_HELP_HH(agent,name,hash,hash2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#hash,"hash"),helpitem(#hash2,"hash")))
9 years ago
#define IGUANA_HELP_HA(agent,name,hash,obj) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#hash,"hash"),helpitem(#obj,"array")))
9 years ago
#define IGUANA_HELP_HS(agent,name,hash,str) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#hash,"hash"),helpitem(#str,"str")))
9 years ago
#define IGUANA_HELP_HII(agent,name,hash,val,val2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#hash,"hash"),helpitem(#val,"int"),helpitem(#val2,"int")))
9 years ago
#define IGUANA_HELP_HHS(agent,name,hash,hash2,str) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#hash,"hash"),helpitem(#hash2,"hash"),helpitem(#str,"str")))
#define IGUANA_HELP_HAS(agent,name,hash,obj,str) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#hash,"hash"),helpitem(#obj,"array"),helpitem(#str,"str")))
9 years ago
#define IGUANA_HELP_SSDIS(agent,name,str,str2,amount,val,str3) array = helpjson(IGUANA_ARGS,#agent,#name,helparray5(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#amount,"float"),helpitem(#val,"int"),helpitem(#str3,"string")))
#define IGUANA_HELP_SSDISS(agent,name,str,str2,amount,val,str3,str4) array = helpjson(IGUANA_ARGS,#agent,#name,helparray6(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#amount,"float"),helpitem(#val,"int"),helpitem(#str3,"string"),helpitem(#str4,"string")))
#define IGUANA_HELP_SAIS(agent,name,str,obj,val,str2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray4(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#obj,"array"),helpitem(#val,"int"),helpitem(#str2,"string")))
9 years ago
#define IGUANA_HELP_SAOS(agent,name,str,obj,obj2,str2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray4(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#obj,"array"),helpitem(#obj2,"object"),helpitem(#str2,"string")))
9 years ago
#define IGUANA_HELP_SDSS(agent,name,str,amount,str2,str3) array = helpjson(IGUANA_ARGS,#agent,#name,helparray4(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#amount,"float"),helpitem(#str2,"string"),helpitem(#str3,"string")))
9 years ago
#define IGUANA_HELP_SHI_SDSD_II_SSSSSS(agent,name,str,hash,val,str2,amount,str3,amount2,val2,val3,str4,str5,str6,str7,str8,str9) array = helpjson(IGUANA_ARGS,#agent,#name,helparray15(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#hash,"hash"),helpitem(#val,"int"),helpitem(#str2,"string"),helpitem(#amount,"float"),helpitem(#str3,"string"),helpitem(#amount2,"float"),helpitem(#val2,"int"),helpitem(#val3,"int"),helpitem(#str4,"string"),helpitem(#str5,"string"),helpitem(#str6,"string"),helpitem(#str7,"string"),helpitem(#str8,"string"),helpitem(#str9,"string")))
9 years ago
// API functions
#define ZERO_ARGS IGUANA_HELP0
#define INT_ARG IGUANA_HELP_I
#define TWO_INTS IGUANA_HELP_II
#define STRING_ARG IGUANA_HELP_S
#define TWO_STRINGS IGUANA_HELP_SS
#define THREE_STRINGS IGUANA_HELP_SSS
many changes blockexplorer tab: needs to allow to input height, blockhash or txid. also please display images/BTC_blocks.jpg below the text as a w800 x h400 bitmap, which is active using the mouse api for coin management, below the active coins have a form that arbitrary json can be input with an add button to the right that will call &#34;addcoin&#34; API. this way I can test adding new coins dynamically. dont worry if it doesnt work, just as long as it submits the json to the C code. I am pretty sure I need to do some debugging of this peers management is not working for me at all. maybe it is due to bad internet. On initialization you need to read in the confs/BTCD_peers.txt from the native filesystem and save it into the chrome app filesystem. same thing for confs/BTCD_hdrs.txt. But this is only to be done if there isnt already such a file inside chrome. if there is, only do it upon a button invoked by the user. the reason is that the pexe is updating this file with the latest. Maybe it is nice to have an &#34;extract&#34; button that will copy out from the chrome storage into the native filesystem. There is also the manifest issue about localstorage vs chrome.localstorage. not sure what is needed to be done, but certainly a priority to get it so everything works as a chrome app. I know before it was making ramchain files inside the chrome filesystem, so it is probably things the GUI is doing. maybe in the settings tab, which has obsolete stuff that can be removed. anyway, the issue about files existing in the native filesystem -&gt; chrome and optionally extracting them is an issue for the confs files and .html template files used to autogenerate the port7778, maybe other files are affected. i think we need a way to have a list of hardcoded files that are just copied into chrome on startup if they dont exist already (or if possible copy over if the native version is bigger?) and buttons to extract them for debug tab: THREE_STRINGS(SuperNET,encryptjson,passphrase,permanentfile,anything); TWO_STRINGS(SuperNET,decryptjson,passphrase,permanentfile); at the top of page a way to put in passphrase and optional permanentfile along with arbitrary json. The standard form template has no easy way to describe to pass in everything as it is oriented to specific fields. but the encryptjson API saves all the fields, so the arbitrary json from the form needs to be combined at the same level as the &#34;agent&#34;, &#34;method&#34;, etc. I know, not the best, but internally it makes it easier. so {&#34;agent&#34;:&#34;SuperNET&#34;,&#34;method&#34;:&#34;encryptjson&#34;,&#34;passphrase&#34;:&#34;&lt;passphrase&gt;&#34;,&#34; permanentfile&#34;:&#34;&lt;filename&gt;&#34;,&#34;fromform&#34;:&#34;valuefromform&#34;,&#34;fromform2&#34;:&#34;valu efromform2&#34;,...rest of form at top level} then this will save it into a file with crazy number (it is a hash like txid) but given the same passphrase and filename, it will regenerate this hash so you dont actually have to store it, but it helps during debugging. for the filename, we must warn quite strongly to the user that if the file is ever lost or even changed in any way that the data will not be recoverable. also best to not allow the user to specify a file that does not exist. I think at this point chrome app version gets a bit tricky. we could simply push the native file into the chrome storage, but then an attacker who gets access to the computer could just get a list of these files and it really wont be much protection. So that means if a filename is specified, it needs to be copied into the chrome space, then immediately deleted... ok, this seems like not a good approach. let us make it so that the permanentfile option is not available from the chrome app, but only if the native version is running. that way we sidestep the issue of the pexe not having access to the specified file. Speaking of native vs pexe, on the startup page we should have a radio button that allows the user to select which the GUI will talk to. It should default based on a self test to the more likely value, but it is possible that the user wants to use the native version, even if the pexe is running. another thing to have on the startup page is a simple login: THREE_STRINGS(SuperNET,login,passphrase,permanentfile,handle); ZERO_ARGS(SuperNET,logout); ZERO_ARGS(SuperNET,activehandle); the handle is a human readable name that is associated with the passphrase/permanentfile. There can only be one active account (though it will be possible to associate different accounts with tradebots). use the activehandle API to find out who is logged in and the associated addresses and pubkeys The above is not yet tested so if it doesnt work, dont fret, just let me know. Once set the handle can be displayed in various places to let the user know which account is logged in. The standard 12 dictionary word passphrases should be used, but any string can be sent in as the password for Pangea: INT_AND_ARRAY(pangea,host,minplayers,params); ZERO_ARGS(pangea,lobby); HASH_AND_STRING(pangea,join,tablehash,handle); HASH_AND_INT(pangea,buyin,tablehash,numchips); HASH_ARG(pangea,start,tablehash); // by host only HASH_ARG(pangea,status,tablehash); HASH_ARG(pangea,call,tablehash); HASH_ARG(pangea,check,tablehash); HASH_AND_INT(pangea,raise,tablehash,numchips); HASH_AND_INT(pangea,bet,tablehash,numchips); HASH_ARG(pangea,fold,tablehash); HASH_AND_STRING(pangea,mode,tablehash,modestr); HASH_ARG(pangea,history,tablehash); HASH_AND_INT(pangea,handhistory,tablehash,hand); The first thing that is done is a &#34;host&#34; by any node. the &#34;params&#34; should be an arbitrary json (like encryptjson) as it needs to be at the top level and it has quite a few different parameters still subject to change. The lobby API will just display all the hosted tables. once a table exists, players can join and then buyin. the buyin is denominated in chips, each chip&#39;s value is determined by the host&#39;s initial parameters. once there are enough players joined with adequate buyin&#39;s verified, the host will be able to do a start. if done before it will (eventually) give an error. for now it will just proceed. The host and players that have joined a tablehash, need to do regular status calls to see if the game has started. Probably just once per 5 or even 10 seconds is fine before the start. Once the game starts (the status will have this info) then once per second polling is needed. Then when it is your turn (as indicated by status) you need to do one of the 5 actions (fold, call, check, raise, bet). do not worry if you dont understand what all these do, just allow the user to do any of these. I guess it is possible to submit it ahead of time. I will support internally remembering the most recent action done prior to it being your turn. once it is your turn and an action is sent to the table, it is too late to change. The last API calls are for getting handhistory where hand is 0 to N-1, being the numbering of the hands played at that table. if just history, all the history for all hands at the table is coming back, so it could be quite big. probably I will make it a summary, but for the GUI just display the returned values. the mode is to change some poker specific modes, so just allow there to be a string entered. do not worry about understanding the pokerness of the API, just the overall flow: host -&gt; creates, join/buyin -&gt; fills up player slots, start -&gt; starts the game status -&gt; to determine when the game starts (or if it is cancelled) and once started actions -&gt; game specific but basically just (button + arg) that is the user input results are via status for current game and history for past ones please try to do the above logic in a generic way so it can be reused for other games. The basic flow should be the same for almost all multiplayer turn based games and even for multiplayer realtime games For InstantDEX: on the apikeypair/userid there needs to be two modes. one for when there is no stored apikey and the current form is fine, just need to make it wider as most apikeys are quite long. Now once there is an apikey saved all that is needed is the passphrase to unlock it. So here is where the encrptjson/decryptjson is used. When saving the apikey for the first time, it can be: a) not saved -&gt; nothing extra to do b) saved without password -&gt; you can just save to a file and use it to load it back in. use confs dir confs/instantdex.exchange.api or something like that c) saved with password (optional filename for native) -&gt; probably best to save in the confs dir to indicate that there is an encrypted file for this, so just that and not the actual passphrase in the file with the above, when the exchange is selected, you can see if the confs file exists and if it has the plaintext, just populate the field, if not, then indicate that a passphrase is needed. if the user provides the passphrase, then decryptjson and populate the fields and autosubmit. A special case is to encrypt the apikeys with the passphrase used when logging in. This is only available if the checkbox to &#34;remember passphrase during session&#34; is set on the main iguana login screen. (i forgot to mention that checkbox!) So the login passphrase is stored in memory, then the GUI simply uses that + encryptjson for storing/decrypting. I would imagine that storing in the confs file that it is encrypted using &#34;handle&#34;&#39;s account login might be a good way to differentiate between this mode of password usage. OK, so we now have the insecure plaintext, the decent using handle&#39;s passphrase and paranoid different passphrase for each exchange (with additional permanentfile for native versions) &#34;SUPPORT&#34; -&gt; &#34;SUPPORTS&#34; just a typo and &#34;allpairs&#34; API is missing from the selection Might as well add a &#34;tradebots&#34; tab: THREE_STRINGS_AND_DOUBLE(tradebot,monitor,exchange,base,rel,commission); STRING_AND_DOUBLE(tradebot,monitorall,exchange,commission); THREE_STRINGS(tradebot,unmonitor,exchange,base,rel); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,accumulate,exchange,base,rel,pr ice,volume,duration); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,divest,exchange,base,rel,price, volume,duration); STRING_ARG(tradebot,activebots,exchange); TWO_STRINGS(tradebot,status,exchange,botid); TWO_STRINGS(tradebot,pause,exchange,botid); TWO_STRINGS(tradebot,stop,exchange,botid); TWO_STRINGS(tradebot,resume,exchange,botid); the above are API for exchange specific bots, most should be self-explanatory. bots are created via &#34;accumulate&#34; or &#34;divest&#34; API call. it returns botid. once created, you can do status, pause, stop, resume to a botid. and an activebots API call lists all the active bots for an exchange. duration is in seconds the &#34;monitor&#34; API starts background monitoring of a specific base/rel, &#34;unmonitor&#34; stops this. &#34;monitorall&#34; just does a monitor to the entire list of &#34;allpairs&#34; for that exchange. Keep in mind that doing a monitorall will not add load to an exchange as the request to each exchange is governed by pollgap, but if you have 3 things monitored, it will take 3*pollgap + time each one takes to execute. and if N are monitored it is N*pollgap + time of each, with the &#34;time of each&#34; possibly taking a very long time. And one final request for today: Bitmap tab. It should be an active bitmap using mouse api. either a dropdown to select the bitmap or a form entry. then the rest of the page (resize the bitmap to the page size) being the active bitmap. So on a small screen the bitmap is smaller x/y dimensions and larger on larger screens. plz make sure the proper dimensions are communicated to the pexe via API if it ever is changed. @vineet.bhargav86: I changed the &#34;passphrase&#34; fieldname to &#34;password&#34; for the encryptjson/decryptjson related API. The reason is that the password is like a wallet password and is only local, so it doesnt need to be as high entropy as passphrase. I also added a field to the login API as I realized that the 12 word &#34;passphrase&#34; is the payload and usually wont be sent in: FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase); using &#34;abiglongpassword&#34; for the passphrase -&gt; {&#34;pubkey&#34;:&#34;6c469ba10b40b3eb9d1dba569d7f929d55a29d8f97cd5425907ef2f38f906 209&#34;,&#34;RS&#34;:&#34;NXT-KGV9-DXX8-TM86-DXR96&#34;,&#34;NXT&#34;:&#34;12834974574569896807&#34;,&#34;btcpu bkey&#34;:&#34;024e7641dc947b211bc30fe3339765258902794687b227121fc217284f9d8503c 8&#34;,&#34;rmd160&#34;:&#34;33453c24914db7b77069b7ea24df44f6be145938&#34;,&#34;BTC&#34;:&#34;15g6QK2dSd iW9ZTQEnnJxKrSph6uP7uU23&#34;,&#34;BTCD&#34;:&#34;RDxHUpuv3TX5DZpbhxmS3rBeaxZW1fvYvC&#34;,&#34;r esult&#34;:&#34;success&#34;,&#34;handle&#34;:&#34;test&#34;,&#34;tag&#34;:&#34;14805226009240621255&#34;} and if you use that to log into NXT, it gives the same address. The BTC and BTCD addresses are all derived from the same privkey so they are all interchangeable with the NXT address. The user can therefore select which coin&#39;s addressing they are most comfortable with I also added an &#34;allin&#34; action API for pangea. all the action API will autocalculate the number of chips if passed in 0 for numchips ***************** security issue ******** please dont use the GET URL method when dealing with passphrase!!! Those URL&#39;s tend to get logged and available in browser histories. so anything dealing with the actual passphrase needs to use the postCall form or POST
9 years ago
#define FOUR_STRINGS IGUANA_HELP_SSSS
9 years ago
#define STRING_AND_INT IGUANA_HELP_SI
#define STRING_AND_TWOINTS IGUANA_HELP_SII
9 years ago
#define HASH_AND_STRING IGUANA_HELP_HS
9 years ago
#define HASH_AND_INT IGUANA_HELP_HI
#define HASH_AND_TWOINTS IGUANA_HELP_HII
#define DOUBLE_ARG IGUANA_HELP_D
#define STRING_AND_ARRAY IGUANA_HELP_SA
#define STRING_AND_TWOARRAYS IGUANA_HELP_SAA
#define TWO_ARRAYS IGUANA_HELP_AA
#define INT_AND_ARRAY IGUANA_HELP_IA
#define INT_ARRAY_STRING IGUANA_HELP_IAS
#define SS_D_I_S IGUANA_HELP_SSDIS
#define SS_D_I_SS IGUANA_HELP_SSDISS
#define S_A_I_S IGUANA_HELP_SAIS
#define S_D_SS IGUANA_HELP_SDSS
#define TWOINTS_AND_ARRAY IGUANA_HELP_IIA
#define STRING_AND_THREEINTS IGUANA_HELP_SIII
#define TWOSTRINGS_AND_INT IGUANA_HELP_SSI
9 years ago
#define TWOSTRINGS_AND_HASH IGUANA_HELP_SSH
9 years ago
#define TWOSTRINGS_AND_HASH_AND_TWOINTS IGUANA_HELP_SSHII
#define TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS IGUANA_HELP_SSHHII
9 years ago
#define THREE_INTS IGUANA_HELP_III
9 years ago
#define TWOHASHES_AND_STRING IGUANA_HELP_HHS
#define HASH_ARRAY_STRING IGUANA_HELP_HAS
9 years ago
#define U64_AND_ARRAY IGUANA_HELP_64A
#define HASH_ARG IGUANA_HELP_H
9 years ago
#define TWO_HASHES IGUANA_HELP_HH
9 years ago
#define HASH_AND_ARRAY IGUANA_HELP_HA
9 years ago
#define THREE_STRINGS_AND_THREE_INTS IGUANA_HELP_SSSIII
#define THREE_STRINGS_AND_THREE_DOUBLES IGUANA_HELP_SSSDDD
#define THREE_STRINGS_AND_DOUBLE IGUANA_HELP_SSSD
many changes blockexplorer tab: needs to allow to input height, blockhash or txid. also please display images/BTC_blocks.jpg below the text as a w800 x h400 bitmap, which is active using the mouse api for coin management, below the active coins have a form that arbitrary json can be input with an add button to the right that will call &#34;addcoin&#34; API. this way I can test adding new coins dynamically. dont worry if it doesnt work, just as long as it submits the json to the C code. I am pretty sure I need to do some debugging of this peers management is not working for me at all. maybe it is due to bad internet. On initialization you need to read in the confs/BTCD_peers.txt from the native filesystem and save it into the chrome app filesystem. same thing for confs/BTCD_hdrs.txt. But this is only to be done if there isnt already such a file inside chrome. if there is, only do it upon a button invoked by the user. the reason is that the pexe is updating this file with the latest. Maybe it is nice to have an &#34;extract&#34; button that will copy out from the chrome storage into the native filesystem. There is also the manifest issue about localstorage vs chrome.localstorage. not sure what is needed to be done, but certainly a priority to get it so everything works as a chrome app. I know before it was making ramchain files inside the chrome filesystem, so it is probably things the GUI is doing. maybe in the settings tab, which has obsolete stuff that can be removed. anyway, the issue about files existing in the native filesystem -&gt; chrome and optionally extracting them is an issue for the confs files and .html template files used to autogenerate the port7778, maybe other files are affected. i think we need a way to have a list of hardcoded files that are just copied into chrome on startup if they dont exist already (or if possible copy over if the native version is bigger?) and buttons to extract them for debug tab: THREE_STRINGS(SuperNET,encryptjson,passphrase,permanentfile,anything); TWO_STRINGS(SuperNET,decryptjson,passphrase,permanentfile); at the top of page a way to put in passphrase and optional permanentfile along with arbitrary json. The standard form template has no easy way to describe to pass in everything as it is oriented to specific fields. but the encryptjson API saves all the fields, so the arbitrary json from the form needs to be combined at the same level as the &#34;agent&#34;, &#34;method&#34;, etc. I know, not the best, but internally it makes it easier. so {&#34;agent&#34;:&#34;SuperNET&#34;,&#34;method&#34;:&#34;encryptjson&#34;,&#34;passphrase&#34;:&#34;&lt;passphrase&gt;&#34;,&#34; permanentfile&#34;:&#34;&lt;filename&gt;&#34;,&#34;fromform&#34;:&#34;valuefromform&#34;,&#34;fromform2&#34;:&#34;valu efromform2&#34;,...rest of form at top level} then this will save it into a file with crazy number (it is a hash like txid) but given the same passphrase and filename, it will regenerate this hash so you dont actually have to store it, but it helps during debugging. for the filename, we must warn quite strongly to the user that if the file is ever lost or even changed in any way that the data will not be recoverable. also best to not allow the user to specify a file that does not exist. I think at this point chrome app version gets a bit tricky. we could simply push the native file into the chrome storage, but then an attacker who gets access to the computer could just get a list of these files and it really wont be much protection. So that means if a filename is specified, it needs to be copied into the chrome space, then immediately deleted... ok, this seems like not a good approach. let us make it so that the permanentfile option is not available from the chrome app, but only if the native version is running. that way we sidestep the issue of the pexe not having access to the specified file. Speaking of native vs pexe, on the startup page we should have a radio button that allows the user to select which the GUI will talk to. It should default based on a self test to the more likely value, but it is possible that the user wants to use the native version, even if the pexe is running. another thing to have on the startup page is a simple login: THREE_STRINGS(SuperNET,login,passphrase,permanentfile,handle); ZERO_ARGS(SuperNET,logout); ZERO_ARGS(SuperNET,activehandle); the handle is a human readable name that is associated with the passphrase/permanentfile. There can only be one active account (though it will be possible to associate different accounts with tradebots). use the activehandle API to find out who is logged in and the associated addresses and pubkeys The above is not yet tested so if it doesnt work, dont fret, just let me know. Once set the handle can be displayed in various places to let the user know which account is logged in. The standard 12 dictionary word passphrases should be used, but any string can be sent in as the password for Pangea: INT_AND_ARRAY(pangea,host,minplayers,params); ZERO_ARGS(pangea,lobby); HASH_AND_STRING(pangea,join,tablehash,handle); HASH_AND_INT(pangea,buyin,tablehash,numchips); HASH_ARG(pangea,start,tablehash); // by host only HASH_ARG(pangea,status,tablehash); HASH_ARG(pangea,call,tablehash); HASH_ARG(pangea,check,tablehash); HASH_AND_INT(pangea,raise,tablehash,numchips); HASH_AND_INT(pangea,bet,tablehash,numchips); HASH_ARG(pangea,fold,tablehash); HASH_AND_STRING(pangea,mode,tablehash,modestr); HASH_ARG(pangea,history,tablehash); HASH_AND_INT(pangea,handhistory,tablehash,hand); The first thing that is done is a &#34;host&#34; by any node. the &#34;params&#34; should be an arbitrary json (like encryptjson) as it needs to be at the top level and it has quite a few different parameters still subject to change. The lobby API will just display all the hosted tables. once a table exists, players can join and then buyin. the buyin is denominated in chips, each chip&#39;s value is determined by the host&#39;s initial parameters. once there are enough players joined with adequate buyin&#39;s verified, the host will be able to do a start. if done before it will (eventually) give an error. for now it will just proceed. The host and players that have joined a tablehash, need to do regular status calls to see if the game has started. Probably just once per 5 or even 10 seconds is fine before the start. Once the game starts (the status will have this info) then once per second polling is needed. Then when it is your turn (as indicated by status) you need to do one of the 5 actions (fold, call, check, raise, bet). do not worry if you dont understand what all these do, just allow the user to do any of these. I guess it is possible to submit it ahead of time. I will support internally remembering the most recent action done prior to it being your turn. once it is your turn and an action is sent to the table, it is too late to change. The last API calls are for getting handhistory where hand is 0 to N-1, being the numbering of the hands played at that table. if just history, all the history for all hands at the table is coming back, so it could be quite big. probably I will make it a summary, but for the GUI just display the returned values. the mode is to change some poker specific modes, so just allow there to be a string entered. do not worry about understanding the pokerness of the API, just the overall flow: host -&gt; creates, join/buyin -&gt; fills up player slots, start -&gt; starts the game status -&gt; to determine when the game starts (or if it is cancelled) and once started actions -&gt; game specific but basically just (button + arg) that is the user input results are via status for current game and history for past ones please try to do the above logic in a generic way so it can be reused for other games. The basic flow should be the same for almost all multiplayer turn based games and even for multiplayer realtime games For InstantDEX: on the apikeypair/userid there needs to be two modes. one for when there is no stored apikey and the current form is fine, just need to make it wider as most apikeys are quite long. Now once there is an apikey saved all that is needed is the passphrase to unlock it. So here is where the encrptjson/decryptjson is used. When saving the apikey for the first time, it can be: a) not saved -&gt; nothing extra to do b) saved without password -&gt; you can just save to a file and use it to load it back in. use confs dir confs/instantdex.exchange.api or something like that c) saved with password (optional filename for native) -&gt; probably best to save in the confs dir to indicate that there is an encrypted file for this, so just that and not the actual passphrase in the file with the above, when the exchange is selected, you can see if the confs file exists and if it has the plaintext, just populate the field, if not, then indicate that a passphrase is needed. if the user provides the passphrase, then decryptjson and populate the fields and autosubmit. A special case is to encrypt the apikeys with the passphrase used when logging in. This is only available if the checkbox to &#34;remember passphrase during session&#34; is set on the main iguana login screen. (i forgot to mention that checkbox!) So the login passphrase is stored in memory, then the GUI simply uses that + encryptjson for storing/decrypting. I would imagine that storing in the confs file that it is encrypted using &#34;handle&#34;&#39;s account login might be a good way to differentiate between this mode of password usage. OK, so we now have the insecure plaintext, the decent using handle&#39;s passphrase and paranoid different passphrase for each exchange (with additional permanentfile for native versions) &#34;SUPPORT&#34; -&gt; &#34;SUPPORTS&#34; just a typo and &#34;allpairs&#34; API is missing from the selection Might as well add a &#34;tradebots&#34; tab: THREE_STRINGS_AND_DOUBLE(tradebot,monitor,exchange,base,rel,commission); STRING_AND_DOUBLE(tradebot,monitorall,exchange,commission); THREE_STRINGS(tradebot,unmonitor,exchange,base,rel); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,accumulate,exchange,base,rel,pr ice,volume,duration); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,divest,exchange,base,rel,price, volume,duration); STRING_ARG(tradebot,activebots,exchange); TWO_STRINGS(tradebot,status,exchange,botid); TWO_STRINGS(tradebot,pause,exchange,botid); TWO_STRINGS(tradebot,stop,exchange,botid); TWO_STRINGS(tradebot,resume,exchange,botid); the above are API for exchange specific bots, most should be self-explanatory. bots are created via &#34;accumulate&#34; or &#34;divest&#34; API call. it returns botid. once created, you can do status, pause, stop, resume to a botid. and an activebots API call lists all the active bots for an exchange. duration is in seconds the &#34;monitor&#34; API starts background monitoring of a specific base/rel, &#34;unmonitor&#34; stops this. &#34;monitorall&#34; just does a monitor to the entire list of &#34;allpairs&#34; for that exchange. Keep in mind that doing a monitorall will not add load to an exchange as the request to each exchange is governed by pollgap, but if you have 3 things monitored, it will take 3*pollgap + time each one takes to execute. and if N are monitored it is N*pollgap + time of each, with the &#34;time of each&#34; possibly taking a very long time. And one final request for today: Bitmap tab. It should be an active bitmap using mouse api. either a dropdown to select the bitmap or a form entry. then the rest of the page (resize the bitmap to the page size) being the active bitmap. So on a small screen the bitmap is smaller x/y dimensions and larger on larger screens. plz make sure the proper dimensions are communicated to the pexe via API if it ever is changed. @vineet.bhargav86: I changed the &#34;passphrase&#34; fieldname to &#34;password&#34; for the encryptjson/decryptjson related API. The reason is that the password is like a wallet password and is only local, so it doesnt need to be as high entropy as passphrase. I also added a field to the login API as I realized that the 12 word &#34;passphrase&#34; is the payload and usually wont be sent in: FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase); using &#34;abiglongpassword&#34; for the passphrase -&gt; {&#34;pubkey&#34;:&#34;6c469ba10b40b3eb9d1dba569d7f929d55a29d8f97cd5425907ef2f38f906 209&#34;,&#34;RS&#34;:&#34;NXT-KGV9-DXX8-TM86-DXR96&#34;,&#34;NXT&#34;:&#34;12834974574569896807&#34;,&#34;btcpu bkey&#34;:&#34;024e7641dc947b211bc30fe3339765258902794687b227121fc217284f9d8503c 8&#34;,&#34;rmd160&#34;:&#34;33453c24914db7b77069b7ea24df44f6be145938&#34;,&#34;BTC&#34;:&#34;15g6QK2dSd iW9ZTQEnnJxKrSph6uP7uU23&#34;,&#34;BTCD&#34;:&#34;RDxHUpuv3TX5DZpbhxmS3rBeaxZW1fvYvC&#34;,&#34;r esult&#34;:&#34;success&#34;,&#34;handle&#34;:&#34;test&#34;,&#34;tag&#34;:&#34;14805226009240621255&#34;} and if you use that to log into NXT, it gives the same address. The BTC and BTCD addresses are all derived from the same privkey so they are all interchangeable with the NXT address. The user can therefore select which coin&#39;s addressing they are most comfortable with I also added an &#34;allin&#34; action API for pangea. all the action API will autocalculate the number of chips if passed in 0 for numchips ***************** security issue ******** please dont use the GET URL method when dealing with passphrase!!! Those URL&#39;s tend to get logged and available in browser histories. so anything dealing with the actual passphrase needs to use the postCall form or POST
9 years ago
#define STRING_AND_DOUBLE IGUANA_HELP_SD
9 years ago
#define TWO_STRINGS_AND_TWO_DOUBLES IGUANA_HELP_SSDD
9 years ago
#define STRING_AND_TWO_DOUBLES IGUANA_HELP_SDD
9 years ago
#define P2SH_SPENDAPI IGUANA_HELP_SHI_SDSD_II_SSSSSS
9 years ago
#define ARRAY_OBJ_INT IGUANA_HELP_AOI
9 years ago
#define STRING_ARRAY_OBJ_STRING IGUANA_HELP_SAOS
9 years ago
9 years ago
#include "../includes/iguana_apideclares.h"
#include "../includes/iguana_apiundefs.h"
if ( array != 0 )
jadd(json,"API",array);
jadd(json,"agents",agents);
return(json);
}
int32_t agentform(FILE *fp,char *form,int32_t max,char *agent,cJSON *methoditem)
{
cJSON *item,*fieldsarray; int32_t j,m,width,size = 0;
char *methodstr,*typestr,outstr[2048],outstr2[2048],fields[8192],str[2],agent_method[256],*fieldname;
form[0] = 0;
if ( (methodstr= jstr(methoditem,"method")) == 0 )
methodstr = "method";
if ( agent == 0 )
agent = "agent";
outstr[0] = outstr2[0] = 0;
str[1] = 0;
fields[0] = 0;
sprintf(agent_method,"%s %s",agent,methodstr);
if ( (fieldsarray= jarray(&m,methoditem,"fields")) != 0 )
{
for (j=0; j<m; j++)
{
item = jitem(fieldsarray,j);
fieldname = get_cJSON_fieldname(item);
// printf("item.(%s) %s\n",jprint(item,0),jstr(item,fieldname));
if ( (typestr= jstr(item,fieldname)) != 0 )
{
if ( strcmp(typestr,"string") == 0 )
width = 44;
else if ( strcmp(typestr,"hash") == 0 )
width = 65;
else if ( strcmp(typestr,"int") == 0 )
9 years ago
width = 12;
9 years ago
else if ( strcmp(typestr,"float") == 0 )
9 years ago
width = 24;
else if ( strcmp(typestr,"u64bits") == 0 )
width = 24;
9 years ago
else if ( strcmp(typestr,"array") == 0 )
width = 64;
else if ( strcmp(typestr,"object") == 0 )
width = 64;
9 years ago
else width = 0;
}
//sprintf(buf,"<input type=\"text\" name=\"%s\"/>",fieldname);
// sprintf(buf,"<textarea cols=\"%d\" rows=\"%d\" name=\"%s\" %s></textarea>",
sprintf(fields+strlen(fields),"<b>%s</b> %s <textarea name=\"%s\" rows=\"1\" cols=\"%d\" %s></textarea>",j==0?agent_method:"",fieldname,fieldname,width,fieldname);
if ( j > 0 )
{
strcat(outstr,"+");
strcat(outstr2," ");
}
strcat(outstr,fieldname);
strcat(outstr2,fieldname);
//printf("fields[%d] (%s)\n",j,fields);
}
} else sprintf(fields+strlen(fields),"<b>%s</b> <textarea rows=\"0\" cols=\"0\"></textarea>",agent_method);
sprintf(&form[size],"<form action=\"http://127.0.0.1:7778/api/%s/%s\" oninput=\"%s\">%s<output for=\"%s\"></output><input type=\"submit\" value=\"%s\"></form>",agent,methodstr,outstr,fields,outstr2,methodstr);
if ( fp != 0 )
9 years ago
fprintf(fp,"%s\n",&form[size]);
//printf("%s\n",&form[size]);
9 years ago
return((int32_t)strlen(form));
}
9 years ago
#define HTML_EMIT(str,n) memcpy(&retbuf[size],str,n), size += (n)
int32_t template_emit(char *retbuf,int32_t maxsize,char *template,char *varname,char *value)
{
int32_t offset,valuelen,varnamelen,position,size = 0; char *match;
offset = 0;
valuelen = (int32_t)strlen(value);
varnamelen = (int32_t)strlen(varname);
while ( (match= strstr(varname,&template[offset])) != 0 )
{
position = (int32_t)((long)match - (long)&template[offset]);
printf("found match.(%s) at %d offset.%d\n",varname,position,offset);
if ( size + (valuelen + position) > maxsize )
return(-1);
HTML_EMIT(&template[offset],position), offset += position + varnamelen;
HTML_EMIT(value,valuelen);
}
HTML_EMIT(&template[offset],strlen(&template[offset])+1);
return(size);
}
#define MAX_TEMPLATESIZE 32768
int32_t templates_emit(char *retbuf,int32_t maxsize,char *template,char *agent,char *method,char *fieldnames,char *fieldnames2)
{
char buf[MAX_TEMPLATESIZE+4096];
strcpy(buf,template);
template_emit(retbuf,maxsize,buf,"$AGENT",agent), strcpy(buf,retbuf);
template_emit(retbuf,maxsize,buf,"$METHOD",method), strcpy(buf,retbuf);
template_emit(retbuf,maxsize,buf,"$FIELDNAMES",fieldnames), strcpy(buf,retbuf);
return(template_emit(retbuf,maxsize,buf,"$FIELDNAMES2",fieldnames2));
}
int32_t pretty_form(FILE *fp,char *formheader,char *formfooter,char *fieldtemplate,char *agent,cJSON *methoditem,cJSON *helpitem,char *suffix)
9 years ago
{
cJSON *item,*fieldsarray; int32_t j,m,formsize,fieldsize,iter,width,size = 0;
char *methodstr,*typestr,*fieldname,*helpstr,*curlstr,*urlstr,*itemhelp;
9 years ago
char outstr[2048],outstr2[2048],str[2],widthstr[16],both[512];
9 years ago
if ( (methodstr= jstr(methoditem,"method")) == 0 )
methodstr = "method";
if ( agent == 0 )
agent = "agent";
9 years ago
sprintf(both,"%s-%s",agent,methodstr);
9 years ago
outstr[0] = outstr2[0] = str[1] = 0;
formsize = fieldsize = 0;
if ( (helpstr= jstr(helpitem,"help")) == 0 )
helpstr = "Some description of this API Call.";
if ( (urlstr= jstr(methoditem,"url")) == 0 )
urlstr = "url";
if ( (curlstr= jstr(methoditem,"curl")) == 0 )
curlstr = "curl";
9 years ago
for (iter=0; iter<2; iter++)
9 years ago
{
9 years ago
if ( iter == 1 )
{
if ( strcmp(suffix,"html") == 0 )
fprintf(fp,formheader,both,both,both,agent,methodstr,both,both,agent,methodstr,outstr);
else if ( strcmp(suffix,"md") == 0 )
fprintf(fp,formheader,methodstr,helpstr,curlstr,urlstr);
}
9 years ago
if ( (fieldsarray= jarray(&m,methoditem,"fields")) != 0 )
9 years ago
{
for (j=0; j<m; j++)
{
item = jitem(fieldsarray,j);
fieldname = get_cJSON_fieldname(item);
if ( (itemhelp= jstr(helpitem,fieldname)) == 0 )
itemhelp = "no help info";
9 years ago
// printf("item.(%s) %s\n",jprint(item,0),jstr(item,fieldname));
if ( iter == 0 )
{
if ( j > 0 )
{
strcat(outstr,"+");
strcat(outstr2," ");
}
strcat(outstr,fieldname);
strcat(outstr2,fieldname);
}
else
{
if ( (typestr= jstr(item,fieldname)) != 0 )
{
if ( strcmp(typestr,"string") == 0 )
width = 44;
else if ( strcmp(typestr,"hash") == 0 )
width = 65;
else if ( strcmp(typestr,"int") == 0 )
width = 12;
else if ( strcmp(typestr,"float") == 0 )
width = 24;
else if ( strcmp(typestr,"u64bits") == 0 )
width = 24;
else width = 0;
}
sprintf(widthstr,"%d",width);
if ( strcmp(suffix,"html") == 0 )
fprintf(fp,fieldtemplate,fieldname,fieldname,fieldname,widthstr,fieldname);
else if ( strcmp(suffix,"md") == 0 )
fprintf(fp,fieldtemplate,fieldname,typestr,itemhelp);
9 years ago
}
}
}
9 years ago
if ( iter == 1 )
{
if ( strcmp(suffix,"html") == 0 )
fprintf(fp,formfooter,outstr2,methodstr,methodstr);
else if ( strcmp(suffix,"md") == 0 )
fprintf(fp,formfooter,"");
}
9 years ago
}
return(size);
}
cJSON *update_docjson(cJSON *docjson,char *agent,char *method)
{
cJSON *item = 0; long allocsize; char *docstr,fname[512],stubstr[4096]; FILE *fp;
if ( agent != 0 && method != 0 )
{
sprintf(stubstr,"{\"agent\":\"%s\",\"method\":\"%s\",\"field0\":\"put in helpful info field0\",\"field1\":\"put in helpful info for field1\",\"help\":\"put helpful info here\",\"teststatus\":[{\"tester\":\"bob\",\"result\":\"put result here\",\"notes\":\"put useful notes here\",\"automated\":\"notyet\",\"sourcefile\":\"%s_%s_test.py\"}]}",agent,method,agent,method);
9 years ago
sprintf(fname,"%s/%s_%s.json",GLOBAL_HELPDIR,agent,method);
if ( (docstr= OS_filestr(&allocsize,fname)) != 0 )
{
if ( (item= cJSON_Parse(docstr)) == 0 )
printf("WARNING: cant parse %s\n",fname);
free(docstr);
}
else if ( (fp= fopen(fname,"w")) != 0 )
{
if ( (item= cJSON_Parse(stubstr)) == 0 )
printf("WARNING: cant parse stubstr %s\n",stubstr);
else
{
fprintf(fp,"%s\n",stubstr);
fclose(fp);
}
}
if ( item == 0 )
item = cJSON_Parse(stubstr);
if ( item != 0 )
jaddi(docjson,item);
}
return(item);
}
char *formfname(char *name,char *suffix)
9 years ago
{
static char retbuf[512];
9 years ago
sprintf(retbuf,"%s/%s.%s",GLOBAL_HELPDIR,name,suffix);
return(retbuf);
}
int32_t pretty_forms(char *fname,char *agentstr,char *suffix)
{
char *str,*header,*footer,*agent,*agenthelp,*prevagent=0,*formheader,*formfooter,*field,*docstr; long allocsize; FILE *fp,*docfp;
int32_t i,n,len,err=0,size = 0; cJSON *helpjson,*array,*item,*docjson=0,*helpitem;
header = OS_filestr(&allocsize,formfname("header",suffix)); if ( allocsize > MAX_TEMPLATESIZE ) err++;
footer = OS_filestr(&allocsize,formfname("footer",suffix)); if ( allocsize > MAX_TEMPLATESIZE ) err++;
formheader = OS_filestr(&allocsize,formfname("formheader",suffix)); if ( allocsize > MAX_TEMPLATESIZE ) err++;
formfooter = OS_filestr(&allocsize,formfname("formfooter",suffix)); if ( allocsize > MAX_TEMPLATESIZE ) err++;
field = OS_filestr(&allocsize,formfname("field",suffix)); if ( allocsize > MAX_TEMPLATESIZE ) err++;
agent = OS_filestr(&allocsize,formfname("agent",suffix)); if ( allocsize > MAX_TEMPLATESIZE ) err++;
9 years ago
fp = fopen(fname,"w");
docjson = cJSON_CreateArray();
9 years ago
if ( fp != 0 && err == 0 && header != 0 && footer != 0 && formheader != 0 && formfooter != 0 && field != 0 )
{
//HTML_EMIT(header,strlen(header));
fprintf(fp,"%s\n",header);
if ( (helpjson= SuperNET_helpjson()) != 0 )
{
9 years ago
//printf("JSON.(%s)\n",jprint(helpjson,0));
9 years ago
if ( (array= jarray(&n,helpjson,"API")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( (str = jstr(item,"agent")) == 0 )
continue;
if ( prevagent == 0 || strcmp(str,prevagent) != 0 )
{
if ( agent != 0 )
{
char errbuf[512];
sprintf(errbuf,"need to create help/%s.md file",str);
if ( (agenthelp= OS_filestr(&allocsize,formfname(str,"md"))) != 0 )
{
fprintf(fp,agent,str,agenthelp);
free(agenthelp);
} else fprintf(fp,agent,str,errbuf);
}
prevagent = str;
}
helpitem = update_docjson(docjson,str,jstr(item,"method"));
9 years ago
if ( agentstr == 0 || agentstr[0] == 0 || (str != 0 && strcmp(str,agentstr) == 0) )
{
len = pretty_form(fp,formheader,formfooter,field,str!=0?str:"agent",item,helpitem,suffix);
9 years ago
size += len;
//printf("%s.%s\n",str,jstr(item,"method"));
9 years ago
} //else printf("agentstr.%p (%s) (%s) str.%p \n",agentstr,agentstr,str,str);
}
}
free_json(helpjson);
}
fprintf(fp,"%s\n",footer);
fclose(fp);
//HTML_EMIT(footer,strlen(footer));
}
if ( suffix != 0 && docjson != 0 && (docfp= fopen("help.json","w")) != 0 )
{
docstr = jprint(docjson,1);
fprintf(docfp,"%s\n",docstr);
fclose(docfp);
free(docstr);
}
9 years ago
if ( header != 0 ) free(header);
if ( footer != 0 ) free(footer);
if ( formheader != 0 ) free(formheader);
if ( formfooter != 0 ) free(formfooter);
if ( field != 0 ) free(field);
return(size);
}
#undef HTML_EMIT
9 years ago
9 years ago
char *SuperNET_htmlstr(char *fname,char *htmlstr,int32_t maxsize,char *agentstr)
9 years ago
{
int32_t i,n,len,size = 0; long filesize; cJSON *helpjson,*item,*array; char *str; FILE *fp = 0;
9 years ago
htmlstr[0] = 0;
pretty_forms(fname,agentstr,"html");
9 years ago
printf("autocreate %s\n","_API.md");
pretty_forms("_API.md",0,"md");
9 years ago
return(OS_filestr(&filesize,"index7778.html"));
9 years ago
sprintf(htmlstr,"<!DOCTYPE HTML><html> <head><title>SuperUGLY GUI></title></head> <body> ");
size = (int32_t)strlen(htmlstr);
if ( (helpjson= SuperNET_helpjson()) != 0 )
{
if ( (array= jarray(&n,helpjson,"API")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
str = jstr(item,"agent");
if ( agentstr == 0 || agentstr[0] == 0 || (str != 0 && strcmp(str,agentstr) == 0) )
{
9 years ago
len = agentform(fp,&htmlstr[size],maxsize - size,str!=0?str:"agent",item);
9 years ago
size += len;
} //else printf("agentstr.%p (%s) (%s) str.%p \n",agentstr,agentstr,str,str);
}
}
9 years ago
//free_json(helpjson);
return(jprint(helpjson,1));
9 years ago
}
strcat(htmlstr,"<br><br/></body></html><br><br/>");
9 years ago
printf("<br><br/></body></html><br><br/>\n");
9 years ago
return(htmlstr);
}
9 years ago
cJSON *iguana_peerjson(struct iguana_info *coin,struct iguana_peer *addr)
{
cJSON *array,*json = cJSON_CreateObject();
jaddstr(json,"ipaddr",addr->ipaddr);
9 years ago
if ( addr->supernet != 0 )
jaddstr(json,"ipaddr",addr->ipaddr);
jaddstr(json,"supernet","yes");
9 years ago
jaddnum(json,"protover",addr->protover);
jaddnum(json,"relay",addr->relayflag);
jaddnum(json,"height",addr->height);
jaddnum(json,"rank",addr->rank);
jaddnum(json,"usock",addr->usock);
if ( addr->dead != 0 )
jaddnum(json,"dead",addr->dead);
jaddnum(json,"ready",addr->ready);
jaddnum(json,"recvblocks",addr->recvblocks);
jaddnum(json,"recvtotal",addr->recvtotal);
jaddnum(json,"lastcontact",addr->lastcontact);
if ( addr->numpings > 0 )
jaddnum(json,"aveping",addr->pingsum/addr->numpings);
array = cJSON_CreateObject();
jaddnum(array,"version",addr->msgcounts.version);
jaddnum(array,"verack",addr->msgcounts.verack);
jaddnum(array,"getaddr",addr->msgcounts.getaddr);
jaddnum(array,"addr",addr->msgcounts.addr);
jaddnum(array,"inv",addr->msgcounts.inv);
jaddnum(array,"getdata",addr->msgcounts.getdata);
jaddnum(array,"notfound",addr->msgcounts.notfound);
jaddnum(array,"getblocks",addr->msgcounts.getblocks);
jaddnum(array,"getheaders",addr->msgcounts.getheaders);
jaddnum(array,"headers",addr->msgcounts.headers);
jaddnum(array,"tx",addr->msgcounts.tx);
jaddnum(array,"block",addr->msgcounts.block);
jaddnum(array,"mempool",addr->msgcounts.mempool);
jaddnum(array,"ping",addr->msgcounts.ping);
jaddnum(array,"pong",addr->msgcounts.pong);
jaddnum(array,"reject",addr->msgcounts.reject);
jaddnum(array,"filterload",addr->msgcounts.filterload);
jaddnum(array,"filteradd",addr->msgcounts.filteradd);
jaddnum(array,"filterclear",addr->msgcounts.filterclear);
jaddnum(array,"merkleblock",addr->msgcounts.merkleblock);
jaddnum(array,"alert",addr->msgcounts.alert);
jadd(json,"msgcounts",array);
return(json);
}
9 years ago
cJSON *iguana_peersjson(struct iguana_info *coin,int32_t addronly)
9 years ago
{
cJSON *retjson,*array; int32_t i; struct iguana_peer *addr;
9 years ago
if ( coin == 0 )
return(0);
9 years ago
array = cJSON_CreateArray();
for (i=0; i<coin->MAXPEERS; i++)
{
addr = &coin->peers.active[i];
if ( addr->usock >= 0 && addr->ipbits != 0 && addr->ipaddr[0] != 0 )
9 years ago
{
if ( addronly != 0 )
jaddistr(array,addr->ipaddr);
else jaddi(array,iguana_peerjson(coin,addr));
}
}
if ( addronly == 0 )
{
retjson = cJSON_CreateObject();
jadd(retjson,"peers",array);
jaddnum(retjson,"maxpeers",coin->MAXPEERS);
jaddstr(retjson,"coin",coin->symbol);
return(retjson);
9 years ago
}
9 years ago
else return(array);
9 years ago
}
9 years ago
#include "../includes/iguana_apidefs.h"
9 years ago
STRING_ARG(iguana,peers,activecoin)
9 years ago
{
9 years ago
if ( coin != 0 )
9 years ago
return(jprint(iguana_peersjson(coin,0),1));
9 years ago
else return(clonestr("{\"error\":\"peers needs coin\"}"));
}
9 years ago
STRING_ARG(iguana,getconnectioncount,activecoin)
9 years ago
{
int32_t i,num = 0; char buf[512];
if ( coin != 0 )
9 years ago
{
for (i=0; i<sizeof(coin->peers.active)/sizeof(*coin->peers.active); i++)
if ( coin->peers.active[i].usock >= 0 )
num++;
sprintf(buf,"{\"result\":\"%d\"}",num);
return(clonestr(buf));
9 years ago
} else return(clonestr("{\"error\":\"getconnectioncount needs coin\"}"));
}
9 years ago
STRING_ARG(iguana,addcoin,newcoin)
9 years ago
{
char *symbol; int32_t retval;
9 years ago
if ( (symbol= newcoin) == 0 && coin != 0 )
9 years ago
symbol = coin->symbol;
if ( symbol != 0 )
9 years ago
{
9 years ago
printf(">> addcoin.%s\n",symbol);
9 years ago
#ifdef __PNACL__
9 years ago
// if ( strcmp(symbol,"BTC") == 0 )
// return(clonestr("{\"result\":\"BTC for chrome app is not yet\"}"));
9 years ago
#endif
9 years ago
if ( (retval= iguana_launchcoin(symbol,json)) > 0 )
9 years ago
{
if ( myinfo->rpcsymbol[0] == 0 )
safecopy(myinfo->rpcsymbol,symbol,sizeof(myinfo->rpcsymbol));
9 years ago
return(clonestr("{\"result\":\"coin added\"}"));
9 years ago
}
9 years ago
else if ( retval == 0 )
return(clonestr("{\"result\":\"coin already there\"}"));
else return(clonestr("{\"error\":\"error adding coin\"}"));
9 years ago
} else return(clonestr("{\"error\":\"addcoin needs newcoin\"}"));
9 years ago
}
9 years ago
STRING_ARG(iguana,startcoin,activecoin)
9 years ago
{
9 years ago
if ( coin != 0 )
9 years ago
{
9 years ago
coin->active = 1;
return(clonestr("{\"result\":\"coin started\"}"));
} else return(clonestr("{\"error\":\"startcoin needs coin\"}"));
9 years ago
}
9 years ago
9 years ago
STRING_ARG(iguana,stopcoin,activecoin)
{
if ( coin != 0 )
{
coin->active = 0;
iguana_coinpurge(coin);
return(clonestr("{\"result\":\"coin stopped\"}"));
} else return(clonestr("{\"error\":\"stopcoin needs coin\"}"));
}
9 years ago
STRING_ARG(iguana,pausecoin,activecoin)
9 years ago
{
9 years ago
if ( coin != 0 )
9 years ago
{
9 years ago
coin->active = 0;
return(clonestr("{\"result\":\"coin paused\"}"));
} else return(clonestr("{\"error\":\"pausecoin needs coin\"}"));
9 years ago
}
9 years ago
TWO_STRINGS(iguana,addnode,activecoin,ipaddr)
9 years ago
{
9 years ago
struct iguana_peer *addr;
if ( coin == 0 )
coin = iguana_coinfind(activecoin);
printf("coin.%p.[%s] addnode.%s -> %s\n",coin,coin!=0?coin->symbol:"",activecoin,ipaddr);
if ( coin != 0 && ipaddr != 0 && is_ipaddr(ipaddr) != 0 )
9 years ago
{
9 years ago
//iguana_possible_peer(coin,ipaddr);
if ( (addr= iguana_peerslot(coin,(uint32_t)calc_ipbits(ipaddr),0)) != 0 )
{
if ( addr->pending == 0 )
{
addr->pending = (uint32_t)time(NULL);
iguana_launch(coin,"connection",iguana_startconnection,addr,IGUANA_CONNTHREAD);
return(clonestr("{\"result\":\"addnode submitted\"}"));
} else return(clonestr("{\"result\":\"addnode connection was already pending\"}"));
} else return(clonestr("{\"result\":\"addnode cant find peer slot\"}"));
9 years ago
}
else if ( coin == 0 )
return(clonestr("{\"error\":\"addnode needs active coin, do an addcoin first\"}"));
else return(clonestr("{\"error\":\"addnode needs ipaddr\"}"));
9 years ago
}
9 years ago
TWO_STRINGS(iguana,persistent,activecoin,ipaddr)
{
int32_t i;
if ( coin != 0 && ipaddr != 0 )
{
for (i=0; i<IGUANA_MAXPEERS; i++)
{
if ( strcmp(coin->peers.active[i].ipaddr,ipaddr) == 0 )
{
coin->peers.active[i].persistent_peer = juint(json,"interval")+3;
return(clonestr("{\"result\":\"node marked as persistent\"}"));
}
}
return(clonestr("{\"result\":\"node wasnt active\"}"));
} else return(clonestr("{\"error\":\"persistent needs coin and ipaddr\"}"));
}
9 years ago
TWO_STRINGS(iguana,removenode,activecoin,ipaddr)
9 years ago
{
9 years ago
int32_t i;
if ( coin != 0 && ipaddr != 0 )
9 years ago
{
9 years ago
for (i=0; i<IGUANA_MAXPEERS; i++)
9 years ago
{
9 years ago
if ( strcmp(coin->peers.active[i].ipaddr,ipaddr) == 0 )
9 years ago
{
9 years ago
coin->peers.active[i].rank = 0;
coin->peers.active[i].dead = (uint32_t)time(NULL);
return(clonestr("{\"result\":\"node marked as dead\"}"));
9 years ago
}
}
9 years ago
return(clonestr("{\"result\":\"node wasnt active\"}"));
} else return(clonestr("{\"error\":\"removenode needs coin and ipaddr\"}"));
9 years ago
}
9 years ago
TWO_STRINGS(iguana,oneshot,activecoin,ipaddr)
9 years ago
{
9 years ago
if ( coin != 0 && ipaddr != 0 )
9 years ago
{
9 years ago
iguana_possible_peer(coin,ipaddr);
return(clonestr("{\"result\":\"addnode submitted\"}"));
} else return(clonestr("{\"error\":\"addnode needs coin and ipaddr\"}"));
9 years ago
}
9 years ago
TWO_STRINGS(iguana,nodestatus,activecoin,ipaddr)
9 years ago
{
9 years ago
int32_t i; struct iguana_peer *addr;
if ( coin != 0 && ipaddr != 0 )
9 years ago
{
9 years ago
for (i=0; i<coin->MAXPEERS; i++)
9 years ago
{
9 years ago
addr = &coin->peers.active[i];
if ( strcmp(addr->ipaddr,ipaddr) == 0 )
return(jprint(iguana_peerjson(coin,addr),1));
9 years ago
}
9 years ago
return(clonestr("{\"result\":\"nodestatus couldnt find ipaddr\"}"));
} else return(clonestr("{\"error\":\"nodestatus needs ipaddr\"}"));
9 years ago
}
9 years ago
9 years ago
STRING_AND_INT(iguana,maxpeers,activecoin,max)
9 years ago
{
9 years ago
cJSON *retjson; int32_t i; struct iguana_peer *addr;
if ( coin != 0 )
9 years ago
{
9 years ago
retjson = cJSON_CreateObject();
if ( max > IGUANA_MAXPEERS )
max = IGUANA_MAXPEERS;
if ( max > coin->MAXPEERS )
9 years ago
{
9 years ago
for (i=max; i<coin->MAXPEERS; i++)
if ( (addr= coin->peers.ranked[i]) != 0 )
addr->dead = 1;
9 years ago
}
9 years ago
coin->MAXPEERS = max;
jaddnum(retjson,"maxpeers",coin->MAXPEERS);
jaddstr(retjson,"coin",coin->symbol);
return(jprint(retjson,1));
} else return(clonestr("{\"error\":\"maxpeers needs coin\"}"));
9 years ago
}
9 years ago
char *hmac_dispatch(char *(*hmacfunc)(char *dest,char *key,int32_t key_size,char *message),char *name,char *message,char *password)
9 years ago
{
9 years ago
char hexstr[1025]; cJSON *json;
if ( message != 0 && password != 0 && message[0] != 0 && password[0] != 0 )
9 years ago
{
9 years ago
memset(hexstr,0,sizeof(hexstr));
9 years ago
(*hmacfunc)(hexstr,password,password==0?0:(int32_t)strlen(password),message);
json = cJSON_CreateObject();
jaddstr(json,"result","hmac calculated");
jaddstr(json,"message",message);
jaddstr(json,name,hexstr);
return(jprint(json,1));
} else return(clonestr("{\"error\":\"hmac needs message and passphrase\"}"));
9 years ago
}
9 years ago
char *hash_dispatch(void (*hashfunc)(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len),char *name,char *message)
9 years ago
{
9 years ago
char hexstr[16384]; uint8_t databuf[8192]; cJSON *json;
if ( message != 0 && message[0] != 0 )
9 years ago
{
9 years ago
memset(hexstr,0,sizeof(hexstr));
9 years ago
(*hashfunc)(hexstr,databuf,(uint8_t *)message,(int32_t)strlen(message));
json = cJSON_CreateObject();
jaddstr(json,"result","hash calculated");
jaddstr(json,"message",message);
jaddstr(json,name,hexstr);
return(jprint(json,1));
} else return(clonestr("{\"error\":\"hash needs message\"}"));
9 years ago
}
9 years ago
TWO_HASHES(hash,curve25519_pair,element,scalar)
{
cJSON *retjson = cJSON_CreateObject();
jaddbits256(retjson,"result",curve25519(element,scalar));
return(jprint(retjson,1));
}
9 years ago
STRING_ARG(hash,NXT,passphrase) { return(hash_dispatch(calc_NXTaddr,"NXT",passphrase)); }
STRING_ARG(hash,curve25519,pubkey) { return(hash_dispatch(calc_curve25519_str,"curve25519",pubkey)); }
STRING_ARG(hash,crc32,message) { return(hash_dispatch(calc_crc32str,"crc32",message)); }
STRING_ARG(hash,base64_encode,message) { return(hash_dispatch(calc_base64_encodestr,"base64_encode",message)); }
STRING_ARG(hash,base64_decode,message) { return(hash_dispatch(calc_base64_decodestr,"base64_decode",message)); }
STRING_ARG(hash,rmd160_sha256,message) { return(hash_dispatch(rmd160ofsha256,"rmd160_sha256",message)); }
STRING_ARG(hash,sha256_sha256,message) { return(hash_dispatch(sha256_sha256,"sha256_sha256",message)); }
9 years ago
STRING_ARG(hash,hex,message) { return(hash_dispatch(calc_hexstr,"hex",message)); }
STRING_ARG(hash,unhex,message) { return(hash_dispatch(calc_unhexstr,"unhex",message)); }
9 years ago
STRING_ARG(hash,sha224,message) { return(hash_dispatch(calc_sha224,"sha224",message)); }
STRING_ARG(hash,sha256,message) { return(hash_dispatch(vcalc_sha256,"sha256",message)); }
STRING_ARG(hash,sha384,message) { return(hash_dispatch(calc_sha384,"sha384",message)); }
STRING_ARG(hash,sha512,message) { return(hash_dispatch(calc_sha512,"sha512",message)); }
STRING_ARG(hash,rmd128,message) { return(hash_dispatch(calc_rmd128,"rmd128",message)); }
STRING_ARG(hash,rmd160,message) { return(hash_dispatch(calc_rmd160,"rmd160",message)); }
STRING_ARG(hash,rmd256,message) { return(hash_dispatch(calc_rmd256,"rmd256",message)); }
STRING_ARG(hash,rmd320,message) { return(hash_dispatch(calc_rmd320,"rmd320",message)); }
STRING_ARG(hash,sha1,message) { return(hash_dispatch(calc_sha1,"sha1",message)); }
STRING_ARG(hash,md2,message) { return(hash_dispatch(calc_md2str,"md2",message)); }
STRING_ARG(hash,md4,message) { return(hash_dispatch(calc_md4str,"md4",message)); }
STRING_ARG(hash,md5,message) { return(hash_dispatch(calc_md5str,"md5",message)); }
9 years ago
STRING_ARG(hash,tiger192_3,message) { return(hash_dispatch(calc_tiger,"tiger",message)); }
9 years ago
STRING_ARG(hash,whirlpool,message) { return(hash_dispatch(calc_whirlpool,"whirlpool",message)); }
TWO_STRINGS(hmac,sha224,message,passphrase) { return(hmac_dispatch(hmac_sha224_str,"sha224",message,passphrase)); }
TWO_STRINGS(hmac,sha256,message,passphrase) { return(hmac_dispatch(hmac_sha256_str,"sha256",message,passphrase)); }
TWO_STRINGS(hmac,sha384,message,passphrase) { return(hmac_dispatch(hmac_sha384_str,"sha384",message,passphrase)); }
TWO_STRINGS(hmac,sha512,message,passphrase) { return(hmac_dispatch(hmac_sha512_str,"sha512",message,passphrase)); }
TWO_STRINGS(hmac,rmd128,message,passphrase) { return(hmac_dispatch(hmac_rmd128_str,"rmd128",message,passphrase)); }
TWO_STRINGS(hmac,rmd160,message,passphrase) { return(hmac_dispatch(hmac_rmd160_str,"rmd160",message,passphrase)); }
TWO_STRINGS(hmac,rmd256,message,passphrase) { return(hmac_dispatch(hmac_rmd256_str,"rmd256",message,passphrase)); }
TWO_STRINGS(hmac,rmd320,message,passphrase) { return(hmac_dispatch(hmac_rmd320_str,"rmd320",message,passphrase)); }
TWO_STRINGS(hmac,sha1,message,passphrase) { return(hmac_dispatch(hmac_sha1_str,"sha1",message,passphrase)); }
TWO_STRINGS(hmac,md2,message,passphrase) { return(hmac_dispatch(hmac_md2_str,"md2",message,passphrase)); }
TWO_STRINGS(hmac,md4,message,passphrase) { return(hmac_dispatch(hmac_md4_str,"md4",message,passphrase)); }
TWO_STRINGS(hmac,md5,message,passphrase) { return(hmac_dispatch(hmac_md5_str,"md5",message,passphrase)); }
9 years ago
TWO_STRINGS(hmac,tiger192_3,message,passphrase) { return(hmac_dispatch(hmac_tiger_str,"tiger",message,passphrase)); }
9 years ago
TWO_STRINGS(hmac,whirlpool,message,passphrase) { return(hmac_dispatch(hmac_whirlpool_str,"whirlpool",message,passphrase)); }
STRING_ARG(SuperNET,bitcoinrpc,setcoin)
9 years ago
{
9 years ago
char buf[1024];
9 years ago
if ( setcoin != 0 && setcoin[0] != 0 )
9 years ago
{
9 years ago
strcpy(myinfo->rpcsymbol,setcoin);
touppercase(myinfo->rpcsymbol);
9 years ago
printf("bitcoinrpc.%s\n",myinfo->rpcsymbol);
9 years ago
if ( iguana_launchcoin(myinfo->rpcsymbol,json) < 0 )
return(clonestr("{\"error\":\"error creating coin\"}"));
9 years ago
else
{
sprintf(buf,"{\"result\":\"success\",\"setcoin\":\"%s\"}",setcoin);
return(clonestr(buf));
}
9 years ago
} else return(clonestr("{\"error\":\"bitcoinrpc needs setcoin value\"}"));
9 years ago
}
9 years ago
ZERO_ARGS(SuperNET,help)
9 years ago
{
9 years ago
cJSON *helpjson,*retjson;
if ( (helpjson= SuperNET_helpjson()) != 0 )
{
retjson = cJSON_CreateObject();
jadd(retjson,"result",helpjson);
return(jprint(retjson,1));
} else return(clonestr("{\"error\":\"cant get helpjson\"}"));
9 years ago
}
9 years ago
TWO_STRINGS(SuperNET,html,agentform,htmlfile)
9 years ago
{
9 years ago
char *htmlstr; cJSON *retjson; int32_t max = 4*1024*1024;
9 years ago
if ( htmlfile == 0 || htmlfile[0] == 0 )
9 years ago
htmlfile = "forms.html";
//if ( (fp= fopen(htmlfile,"w")) == 0 )
// printf("error opening htmlfile.(%s)\n",htmlfile);
9 years ago
htmlstr = malloc(max);
9 years ago
htmlstr = SuperNET_htmlstr(htmlfile,htmlstr,max,agentform);
9 years ago
retjson = cJSON_CreateObject();
jaddstr(retjson,"result",htmlstr);
free(htmlstr);
9 years ago
//if ( fp != 0 )
// fclose(fp);
9 years ago
return(jprint(retjson,1));
9 years ago
}
9 years ago
9 years ago
#undef IGUANA_ARGS
#include "../includes/iguana_apiundefs.h"
9 years ago
9 years ago
char *SuperNET_parser(struct supernet_info *myinfo,char *agentstr,char *method,cJSON *json,char *remoteaddr)
9 years ago
{
9 years ago
char *coinstr; struct iguana_info *coin = 0;
9 years ago
if ( remoteaddr != 0 && (remoteaddr[0] == 0 || strcmp(remoteaddr,"127.0.0.1") == 0) )
remoteaddr = 0;
9 years ago
if ( (coinstr= jstr(json,"activecoin")) == 0 && (coinstr= jstr(json,"coin")) == 0 )
coinstr = myinfo->rpcsymbol;
if ( coinstr != 0 && coinstr[0] != 0 )
9 years ago
coin = iguana_coinfind(coinstr);
if ( strcmp(agentstr,"bitcoinrpc") == 0 && coin == 0 )
return(clonestr("{\"error\":\"bitcoinrpc needs coin\"}"));
9 years ago
#define IGUANA_ARGS myinfo,coin,json,remoteaddr
9 years ago
#define IGUANA_DISPATCH0(agent,name) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS))
#define IGUANA_DISPATCH_S(agent,name,str) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str)))
#define IGUANA_DISPATCH_SS(agent,name,str,str2) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2)))
many changes blockexplorer tab: needs to allow to input height, blockhash or txid. also please display images/BTC_blocks.jpg below the text as a w800 x h400 bitmap, which is active using the mouse api for coin management, below the active coins have a form that arbitrary json can be input with an add button to the right that will call &#34;addcoin&#34; API. this way I can test adding new coins dynamically. dont worry if it doesnt work, just as long as it submits the json to the C code. I am pretty sure I need to do some debugging of this peers management is not working for me at all. maybe it is due to bad internet. On initialization you need to read in the confs/BTCD_peers.txt from the native filesystem and save it into the chrome app filesystem. same thing for confs/BTCD_hdrs.txt. But this is only to be done if there isnt already such a file inside chrome. if there is, only do it upon a button invoked by the user. the reason is that the pexe is updating this file with the latest. Maybe it is nice to have an &#34;extract&#34; button that will copy out from the chrome storage into the native filesystem. There is also the manifest issue about localstorage vs chrome.localstorage. not sure what is needed to be done, but certainly a priority to get it so everything works as a chrome app. I know before it was making ramchain files inside the chrome filesystem, so it is probably things the GUI is doing. maybe in the settings tab, which has obsolete stuff that can be removed. anyway, the issue about files existing in the native filesystem -&gt; chrome and optionally extracting them is an issue for the confs files and .html template files used to autogenerate the port7778, maybe other files are affected. i think we need a way to have a list of hardcoded files that are just copied into chrome on startup if they dont exist already (or if possible copy over if the native version is bigger?) and buttons to extract them for debug tab: THREE_STRINGS(SuperNET,encryptjson,passphrase,permanentfile,anything); TWO_STRINGS(SuperNET,decryptjson,passphrase,permanentfile); at the top of page a way to put in passphrase and optional permanentfile along with arbitrary json. The standard form template has no easy way to describe to pass in everything as it is oriented to specific fields. but the encryptjson API saves all the fields, so the arbitrary json from the form needs to be combined at the same level as the &#34;agent&#34;, &#34;method&#34;, etc. I know, not the best, but internally it makes it easier. so {&#34;agent&#34;:&#34;SuperNET&#34;,&#34;method&#34;:&#34;encryptjson&#34;,&#34;passphrase&#34;:&#34;&lt;passphrase&gt;&#34;,&#34; permanentfile&#34;:&#34;&lt;filename&gt;&#34;,&#34;fromform&#34;:&#34;valuefromform&#34;,&#34;fromform2&#34;:&#34;valu efromform2&#34;,...rest of form at top level} then this will save it into a file with crazy number (it is a hash like txid) but given the same passphrase and filename, it will regenerate this hash so you dont actually have to store it, but it helps during debugging. for the filename, we must warn quite strongly to the user that if the file is ever lost or even changed in any way that the data will not be recoverable. also best to not allow the user to specify a file that does not exist. I think at this point chrome app version gets a bit tricky. we could simply push the native file into the chrome storage, but then an attacker who gets access to the computer could just get a list of these files and it really wont be much protection. So that means if a filename is specified, it needs to be copied into the chrome space, then immediately deleted... ok, this seems like not a good approach. let us make it so that the permanentfile option is not available from the chrome app, but only if the native version is running. that way we sidestep the issue of the pexe not having access to the specified file. Speaking of native vs pexe, on the startup page we should have a radio button that allows the user to select which the GUI will talk to. It should default based on a self test to the more likely value, but it is possible that the user wants to use the native version, even if the pexe is running. another thing to have on the startup page is a simple login: THREE_STRINGS(SuperNET,login,passphrase,permanentfile,handle); ZERO_ARGS(SuperNET,logout); ZERO_ARGS(SuperNET,activehandle); the handle is a human readable name that is associated with the passphrase/permanentfile. There can only be one active account (though it will be possible to associate different accounts with tradebots). use the activehandle API to find out who is logged in and the associated addresses and pubkeys The above is not yet tested so if it doesnt work, dont fret, just let me know. Once set the handle can be displayed in various places to let the user know which account is logged in. The standard 12 dictionary word passphrases should be used, but any string can be sent in as the password for Pangea: INT_AND_ARRAY(pangea,host,minplayers,params); ZERO_ARGS(pangea,lobby); HASH_AND_STRING(pangea,join,tablehash,handle); HASH_AND_INT(pangea,buyin,tablehash,numchips); HASH_ARG(pangea,start,tablehash); // by host only HASH_ARG(pangea,status,tablehash); HASH_ARG(pangea,call,tablehash); HASH_ARG(pangea,check,tablehash); HASH_AND_INT(pangea,raise,tablehash,numchips); HASH_AND_INT(pangea,bet,tablehash,numchips); HASH_ARG(pangea,fold,tablehash); HASH_AND_STRING(pangea,mode,tablehash,modestr); HASH_ARG(pangea,history,tablehash); HASH_AND_INT(pangea,handhistory,tablehash,hand); The first thing that is done is a &#34;host&#34; by any node. the &#34;params&#34; should be an arbitrary json (like encryptjson) as it needs to be at the top level and it has quite a few different parameters still subject to change. The lobby API will just display all the hosted tables. once a table exists, players can join and then buyin. the buyin is denominated in chips, each chip&#39;s value is determined by the host&#39;s initial parameters. once there are enough players joined with adequate buyin&#39;s verified, the host will be able to do a start. if done before it will (eventually) give an error. for now it will just proceed. The host and players that have joined a tablehash, need to do regular status calls to see if the game has started. Probably just once per 5 or even 10 seconds is fine before the start. Once the game starts (the status will have this info) then once per second polling is needed. Then when it is your turn (as indicated by status) you need to do one of the 5 actions (fold, call, check, raise, bet). do not worry if you dont understand what all these do, just allow the user to do any of these. I guess it is possible to submit it ahead of time. I will support internally remembering the most recent action done prior to it being your turn. once it is your turn and an action is sent to the table, it is too late to change. The last API calls are for getting handhistory where hand is 0 to N-1, being the numbering of the hands played at that table. if just history, all the history for all hands at the table is coming back, so it could be quite big. probably I will make it a summary, but for the GUI just display the returned values. the mode is to change some poker specific modes, so just allow there to be a string entered. do not worry about understanding the pokerness of the API, just the overall flow: host -&gt; creates, join/buyin -&gt; fills up player slots, start -&gt; starts the game status -&gt; to determine when the game starts (or if it is cancelled) and once started actions -&gt; game specific but basically just (button + arg) that is the user input results are via status for current game and history for past ones please try to do the above logic in a generic way so it can be reused for other games. The basic flow should be the same for almost all multiplayer turn based games and even for multiplayer realtime games For InstantDEX: on the apikeypair/userid there needs to be two modes. one for when there is no stored apikey and the current form is fine, just need to make it wider as most apikeys are quite long. Now once there is an apikey saved all that is needed is the passphrase to unlock it. So here is where the encrptjson/decryptjson is used. When saving the apikey for the first time, it can be: a) not saved -&gt; nothing extra to do b) saved without password -&gt; you can just save to a file and use it to load it back in. use confs dir confs/instantdex.exchange.api or something like that c) saved with password (optional filename for native) -&gt; probably best to save in the confs dir to indicate that there is an encrypted file for this, so just that and not the actual passphrase in the file with the above, when the exchange is selected, you can see if the confs file exists and if it has the plaintext, just populate the field, if not, then indicate that a passphrase is needed. if the user provides the passphrase, then decryptjson and populate the fields and autosubmit. A special case is to encrypt the apikeys with the passphrase used when logging in. This is only available if the checkbox to &#34;remember passphrase during session&#34; is set on the main iguana login screen. (i forgot to mention that checkbox!) So the login passphrase is stored in memory, then the GUI simply uses that + encryptjson for storing/decrypting. I would imagine that storing in the confs file that it is encrypted using &#34;handle&#34;&#39;s account login might be a good way to differentiate between this mode of password usage. OK, so we now have the insecure plaintext, the decent using handle&#39;s passphrase and paranoid different passphrase for each exchange (with additional permanentfile for native versions) &#34;SUPPORT&#34; -&gt; &#34;SUPPORTS&#34; just a typo and &#34;allpairs&#34; API is missing from the selection Might as well add a &#34;tradebots&#34; tab: THREE_STRINGS_AND_DOUBLE(tradebot,monitor,exchange,base,rel,commission); STRING_AND_DOUBLE(tradebot,monitorall,exchange,commission); THREE_STRINGS(tradebot,unmonitor,exchange,base,rel); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,accumulate,exchange,base,rel,pr ice,volume,duration); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,divest,exchange,base,rel,price, volume,duration); STRING_ARG(tradebot,activebots,exchange); TWO_STRINGS(tradebot,status,exchange,botid); TWO_STRINGS(tradebot,pause,exchange,botid); TWO_STRINGS(tradebot,stop,exchange,botid); TWO_STRINGS(tradebot,resume,exchange,botid); the above are API for exchange specific bots, most should be self-explanatory. bots are created via &#34;accumulate&#34; or &#34;divest&#34; API call. it returns botid. once created, you can do status, pause, stop, resume to a botid. and an activebots API call lists all the active bots for an exchange. duration is in seconds the &#34;monitor&#34; API starts background monitoring of a specific base/rel, &#34;unmonitor&#34; stops this. &#34;monitorall&#34; just does a monitor to the entire list of &#34;allpairs&#34; for that exchange. Keep in mind that doing a monitorall will not add load to an exchange as the request to each exchange is governed by pollgap, but if you have 3 things monitored, it will take 3*pollgap + time each one takes to execute. and if N are monitored it is N*pollgap + time of each, with the &#34;time of each&#34; possibly taking a very long time. And one final request for today: Bitmap tab. It should be an active bitmap using mouse api. either a dropdown to select the bitmap or a form entry. then the rest of the page (resize the bitmap to the page size) being the active bitmap. So on a small screen the bitmap is smaller x/y dimensions and larger on larger screens. plz make sure the proper dimensions are communicated to the pexe via API if it ever is changed. @vineet.bhargav86: I changed the &#34;passphrase&#34; fieldname to &#34;password&#34; for the encryptjson/decryptjson related API. The reason is that the password is like a wallet password and is only local, so it doesnt need to be as high entropy as passphrase. I also added a field to the login API as I realized that the 12 word &#34;passphrase&#34; is the payload and usually wont be sent in: FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase); using &#34;abiglongpassword&#34; for the passphrase -&gt; {&#34;pubkey&#34;:&#34;6c469ba10b40b3eb9d1dba569d7f929d55a29d8f97cd5425907ef2f38f906 209&#34;,&#34;RS&#34;:&#34;NXT-KGV9-DXX8-TM86-DXR96&#34;,&#34;NXT&#34;:&#34;12834974574569896807&#34;,&#34;btcpu bkey&#34;:&#34;024e7641dc947b211bc30fe3339765258902794687b227121fc217284f9d8503c 8&#34;,&#34;rmd160&#34;:&#34;33453c24914db7b77069b7ea24df44f6be145938&#34;,&#34;BTC&#34;:&#34;15g6QK2dSd iW9ZTQEnnJxKrSph6uP7uU23&#34;,&#34;BTCD&#34;:&#34;RDxHUpuv3TX5DZpbhxmS3rBeaxZW1fvYvC&#34;,&#34;r esult&#34;:&#34;success&#34;,&#34;handle&#34;:&#34;test&#34;,&#34;tag&#34;:&#34;14805226009240621255&#34;} and if you use that to log into NXT, it gives the same address. The BTC and BTCD addresses are all derived from the same privkey so they are all interchangeable with the NXT address. The user can therefore select which coin&#39;s addressing they are most comfortable with I also added an &#34;allin&#34; action API for pangea. all the action API will autocalculate the number of chips if passed in 0 for numchips ***************** security issue ******** please dont use the GET URL method when dealing with passphrase!!! Those URL&#39;s tend to get logged and available in browser histories. so anything dealing with the actual passphrase needs to use the postCall form or POST
9 years ago
#define IGUANA_DISPATCH_SD(agent,name,str,val) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jdouble(json,#val)))
9 years ago
#define IGUANA_DISPATCH_SSS(agent,name,str,str2,str3) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3)))
many changes blockexplorer tab: needs to allow to input height, blockhash or txid. also please display images/BTC_blocks.jpg below the text as a w800 x h400 bitmap, which is active using the mouse api for coin management, below the active coins have a form that arbitrary json can be input with an add button to the right that will call &#34;addcoin&#34; API. this way I can test adding new coins dynamically. dont worry if it doesnt work, just as long as it submits the json to the C code. I am pretty sure I need to do some debugging of this peers management is not working for me at all. maybe it is due to bad internet. On initialization you need to read in the confs/BTCD_peers.txt from the native filesystem and save it into the chrome app filesystem. same thing for confs/BTCD_hdrs.txt. But this is only to be done if there isnt already such a file inside chrome. if there is, only do it upon a button invoked by the user. the reason is that the pexe is updating this file with the latest. Maybe it is nice to have an &#34;extract&#34; button that will copy out from the chrome storage into the native filesystem. There is also the manifest issue about localstorage vs chrome.localstorage. not sure what is needed to be done, but certainly a priority to get it so everything works as a chrome app. I know before it was making ramchain files inside the chrome filesystem, so it is probably things the GUI is doing. maybe in the settings tab, which has obsolete stuff that can be removed. anyway, the issue about files existing in the native filesystem -&gt; chrome and optionally extracting them is an issue for the confs files and .html template files used to autogenerate the port7778, maybe other files are affected. i think we need a way to have a list of hardcoded files that are just copied into chrome on startup if they dont exist already (or if possible copy over if the native version is bigger?) and buttons to extract them for debug tab: THREE_STRINGS(SuperNET,encryptjson,passphrase,permanentfile,anything); TWO_STRINGS(SuperNET,decryptjson,passphrase,permanentfile); at the top of page a way to put in passphrase and optional permanentfile along with arbitrary json. The standard form template has no easy way to describe to pass in everything as it is oriented to specific fields. but the encryptjson API saves all the fields, so the arbitrary json from the form needs to be combined at the same level as the &#34;agent&#34;, &#34;method&#34;, etc. I know, not the best, but internally it makes it easier. so {&#34;agent&#34;:&#34;SuperNET&#34;,&#34;method&#34;:&#34;encryptjson&#34;,&#34;passphrase&#34;:&#34;&lt;passphrase&gt;&#34;,&#34; permanentfile&#34;:&#34;&lt;filename&gt;&#34;,&#34;fromform&#34;:&#34;valuefromform&#34;,&#34;fromform2&#34;:&#34;valu efromform2&#34;,...rest of form at top level} then this will save it into a file with crazy number (it is a hash like txid) but given the same passphrase and filename, it will regenerate this hash so you dont actually have to store it, but it helps during debugging. for the filename, we must warn quite strongly to the user that if the file is ever lost or even changed in any way that the data will not be recoverable. also best to not allow the user to specify a file that does not exist. I think at this point chrome app version gets a bit tricky. we could simply push the native file into the chrome storage, but then an attacker who gets access to the computer could just get a list of these files and it really wont be much protection. So that means if a filename is specified, it needs to be copied into the chrome space, then immediately deleted... ok, this seems like not a good approach. let us make it so that the permanentfile option is not available from the chrome app, but only if the native version is running. that way we sidestep the issue of the pexe not having access to the specified file. Speaking of native vs pexe, on the startup page we should have a radio button that allows the user to select which the GUI will talk to. It should default based on a self test to the more likely value, but it is possible that the user wants to use the native version, even if the pexe is running. another thing to have on the startup page is a simple login: THREE_STRINGS(SuperNET,login,passphrase,permanentfile,handle); ZERO_ARGS(SuperNET,logout); ZERO_ARGS(SuperNET,activehandle); the handle is a human readable name that is associated with the passphrase/permanentfile. There can only be one active account (though it will be possible to associate different accounts with tradebots). use the activehandle API to find out who is logged in and the associated addresses and pubkeys The above is not yet tested so if it doesnt work, dont fret, just let me know. Once set the handle can be displayed in various places to let the user know which account is logged in. The standard 12 dictionary word passphrases should be used, but any string can be sent in as the password for Pangea: INT_AND_ARRAY(pangea,host,minplayers,params); ZERO_ARGS(pangea,lobby); HASH_AND_STRING(pangea,join,tablehash,handle); HASH_AND_INT(pangea,buyin,tablehash,numchips); HASH_ARG(pangea,start,tablehash); // by host only HASH_ARG(pangea,status,tablehash); HASH_ARG(pangea,call,tablehash); HASH_ARG(pangea,check,tablehash); HASH_AND_INT(pangea,raise,tablehash,numchips); HASH_AND_INT(pangea,bet,tablehash,numchips); HASH_ARG(pangea,fold,tablehash); HASH_AND_STRING(pangea,mode,tablehash,modestr); HASH_ARG(pangea,history,tablehash); HASH_AND_INT(pangea,handhistory,tablehash,hand); The first thing that is done is a &#34;host&#34; by any node. the &#34;params&#34; should be an arbitrary json (like encryptjson) as it needs to be at the top level and it has quite a few different parameters still subject to change. The lobby API will just display all the hosted tables. once a table exists, players can join and then buyin. the buyin is denominated in chips, each chip&#39;s value is determined by the host&#39;s initial parameters. once there are enough players joined with adequate buyin&#39;s verified, the host will be able to do a start. if done before it will (eventually) give an error. for now it will just proceed. The host and players that have joined a tablehash, need to do regular status calls to see if the game has started. Probably just once per 5 or even 10 seconds is fine before the start. Once the game starts (the status will have this info) then once per second polling is needed. Then when it is your turn (as indicated by status) you need to do one of the 5 actions (fold, call, check, raise, bet). do not worry if you dont understand what all these do, just allow the user to do any of these. I guess it is possible to submit it ahead of time. I will support internally remembering the most recent action done prior to it being your turn. once it is your turn and an action is sent to the table, it is too late to change. The last API calls are for getting handhistory where hand is 0 to N-1, being the numbering of the hands played at that table. if just history, all the history for all hands at the table is coming back, so it could be quite big. probably I will make it a summary, but for the GUI just display the returned values. the mode is to change some poker specific modes, so just allow there to be a string entered. do not worry about understanding the pokerness of the API, just the overall flow: host -&gt; creates, join/buyin -&gt; fills up player slots, start -&gt; starts the game status -&gt; to determine when the game starts (or if it is cancelled) and once started actions -&gt; game specific but basically just (button + arg) that is the user input results are via status for current game and history for past ones please try to do the above logic in a generic way so it can be reused for other games. The basic flow should be the same for almost all multiplayer turn based games and even for multiplayer realtime games For InstantDEX: on the apikeypair/userid there needs to be two modes. one for when there is no stored apikey and the current form is fine, just need to make it wider as most apikeys are quite long. Now once there is an apikey saved all that is needed is the passphrase to unlock it. So here is where the encrptjson/decryptjson is used. When saving the apikey for the first time, it can be: a) not saved -&gt; nothing extra to do b) saved without password -&gt; you can just save to a file and use it to load it back in. use confs dir confs/instantdex.exchange.api or something like that c) saved with password (optional filename for native) -&gt; probably best to save in the confs dir to indicate that there is an encrypted file for this, so just that and not the actual passphrase in the file with the above, when the exchange is selected, you can see if the confs file exists and if it has the plaintext, just populate the field, if not, then indicate that a passphrase is needed. if the user provides the passphrase, then decryptjson and populate the fields and autosubmit. A special case is to encrypt the apikeys with the passphrase used when logging in. This is only available if the checkbox to &#34;remember passphrase during session&#34; is set on the main iguana login screen. (i forgot to mention that checkbox!) So the login passphrase is stored in memory, then the GUI simply uses that + encryptjson for storing/decrypting. I would imagine that storing in the confs file that it is encrypted using &#34;handle&#34;&#39;s account login might be a good way to differentiate between this mode of password usage. OK, so we now have the insecure plaintext, the decent using handle&#39;s passphrase and paranoid different passphrase for each exchange (with additional permanentfile for native versions) &#34;SUPPORT&#34; -&gt; &#34;SUPPORTS&#34; just a typo and &#34;allpairs&#34; API is missing from the selection Might as well add a &#34;tradebots&#34; tab: THREE_STRINGS_AND_DOUBLE(tradebot,monitor,exchange,base,rel,commission); STRING_AND_DOUBLE(tradebot,monitorall,exchange,commission); THREE_STRINGS(tradebot,unmonitor,exchange,base,rel); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,accumulate,exchange,base,rel,pr ice,volume,duration); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,divest,exchange,base,rel,price, volume,duration); STRING_ARG(tradebot,activebots,exchange); TWO_STRINGS(tradebot,status,exchange,botid); TWO_STRINGS(tradebot,pause,exchange,botid); TWO_STRINGS(tradebot,stop,exchange,botid); TWO_STRINGS(tradebot,resume,exchange,botid); the above are API for exchange specific bots, most should be self-explanatory. bots are created via &#34;accumulate&#34; or &#34;divest&#34; API call. it returns botid. once created, you can do status, pause, stop, resume to a botid. and an activebots API call lists all the active bots for an exchange. duration is in seconds the &#34;monitor&#34; API starts background monitoring of a specific base/rel, &#34;unmonitor&#34; stops this. &#34;monitorall&#34; just does a monitor to the entire list of &#34;allpairs&#34; for that exchange. Keep in mind that doing a monitorall will not add load to an exchange as the request to each exchange is governed by pollgap, but if you have 3 things monitored, it will take 3*pollgap + time each one takes to execute. and if N are monitored it is N*pollgap + time of each, with the &#34;time of each&#34; possibly taking a very long time. And one final request for today: Bitmap tab. It should be an active bitmap using mouse api. either a dropdown to select the bitmap or a form entry. then the rest of the page (resize the bitmap to the page size) being the active bitmap. So on a small screen the bitmap is smaller x/y dimensions and larger on larger screens. plz make sure the proper dimensions are communicated to the pexe via API if it ever is changed. @vineet.bhargav86: I changed the &#34;passphrase&#34; fieldname to &#34;password&#34; for the encryptjson/decryptjson related API. The reason is that the password is like a wallet password and is only local, so it doesnt need to be as high entropy as passphrase. I also added a field to the login API as I realized that the 12 word &#34;passphrase&#34; is the payload and usually wont be sent in: FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase); using &#34;abiglongpassword&#34; for the passphrase -&gt; {&#34;pubkey&#34;:&#34;6c469ba10b40b3eb9d1dba569d7f929d55a29d8f97cd5425907ef2f38f906 209&#34;,&#34;RS&#34;:&#34;NXT-KGV9-DXX8-TM86-DXR96&#34;,&#34;NXT&#34;:&#34;12834974574569896807&#34;,&#34;btcpu bkey&#34;:&#34;024e7641dc947b211bc30fe3339765258902794687b227121fc217284f9d8503c 8&#34;,&#34;rmd160&#34;:&#34;33453c24914db7b77069b7ea24df44f6be145938&#34;,&#34;BTC&#34;:&#34;15g6QK2dSd iW9ZTQEnnJxKrSph6uP7uU23&#34;,&#34;BTCD&#34;:&#34;RDxHUpuv3TX5DZpbhxmS3rBeaxZW1fvYvC&#34;,&#34;r esult&#34;:&#34;success&#34;,&#34;handle&#34;:&#34;test&#34;,&#34;tag&#34;:&#34;14805226009240621255&#34;} and if you use that to log into NXT, it gives the same address. The BTC and BTCD addresses are all derived from the same privkey so they are all interchangeable with the NXT address. The user can therefore select which coin&#39;s addressing they are most comfortable with I also added an &#34;allin&#34; action API for pangea. all the action API will autocalculate the number of chips if passed in 0 for numchips ***************** security issue ******** please dont use the GET URL method when dealing with passphrase!!! Those URL&#39;s tend to get logged and available in browser histories. so anything dealing with the actual passphrase needs to use the postCall form or POST
9 years ago
#define IGUANA_DISPATCH_SSSS(agent,name,str,str2,str3,str4) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3),jstr(json,#str4)))
9 years ago
#define IGUANA_DISPATCH_SSSD(agent,name,str,str2,str3,amount) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3),jdouble(json,#amount)))
9 years ago
#define IGUANA_DISPATCH_SSDD(agent,name,str,str2,val,val2) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jdouble(json,#val),jdouble(json,#val2)))
9 years ago
#define IGUANA_DISPATCH_SSSDDD(agent,name,str,str2,str3,val,val2,val3) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3),jdouble(json,#val),jdouble(json,#val2),jdouble(json,#val3)))
#define IGUANA_DISPATCH_SSSIII(agent,name,str,str2,str3,val,val2,val3) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3),jint(json,#val),jint(json,#val2),jint(json,#val3)))
#define IGUANA_DISPATCH_SSH(agent,name,str,str2,hash) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jbits256(json,#hash)))
#define IGUANA_DISPATCH_SSHI(agent,name,str,str2,hash,val) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jbits256(json,#hash),juint(json,#val)))
#define IGUANA_DISPATCH_SSHII(agent,name,str,str2,hash,val,val2) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jbits256(json,#hash),juint(json,#val),juint(json,#val2)))
#define IGUANA_DISPATCH_SSHHII(agent,name,str,str2,hash,hash2,val,val2) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jbits256(json,#hash),jbits256(json,#hash2),juint(json,#val),juint(json,#val2)))
#define IGUANA_DISPATCH_SI(agent,name,str,val) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),juint(json,#val)))
#define IGUANA_DISPATCH_SII(agent,name,str,val,val2) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),juint(json,#val),juint(json,#val2)))
#define IGUANA_DISPATCH_SSI(agent,name,str,str2,val) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),juint(json,#val)))
9 years ago
#define IGUANA_DISPATCH_SDD(agent,name,str,val,val2) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jdouble(json,#val),jdouble(json,#val2)))
9 years ago
#define IGUANA_DISPATCH_SA(agent,name,str,array) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jobj(json,#array)))
#define IGUANA_DISPATCH_SAA(agent,name,str,array,array2) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jobj(json,#array),jobj(json,#array2)))
9 years ago
#define IGUANA_DISPATCH_AOI(agent,name,array,object,val) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jobj(json,#array),jobj(json,#object),juint(json,#val)))
9 years ago
#define IGUANA_DISPATCH_SIII(agent,name,str,val,val2,val3) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),juint(json,#val),juint(json,#val2),juint(json,#val3)))
#define IGUANA_DISPATCH_I(agent,name,val) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,juint(json,#val)))
#define IGUANA_DISPATCH_II(agent,name,val,val2) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,juint(json,#val),juint(json,#val2)))
#define IGUANA_DISPATCH_IIA(agent,name,val,val2,array) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,juint(json,#val),juint(json,#val2),jobj(json,#array)))
#define IGUANA_DISPATCH_III(agent,name,val,val2,val3) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,juint(json,#val),juint(json,#val2),juint(json,#val3)))
#define IGUANA_DISPATCH_IA(agent,name,val,array) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,juint(json,#val),jobj(json,#array)))
#define IGUANA_DISPATCH_IAS(agent,name,val,array,str) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,juint(json,#val),jobj(json,#array),jstr(json,#str)))
9 years ago
9 years ago
#define IGUANA_DISPATCH_64A(agent,name,j64,array) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,j64bits(json,#j64),jobj(json,#array)))
#define IGUANA_DISPATCH_AA(agent,name,array,array2) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jobj(json,#array),jobj(json,#array2)))
9 years ago
9 years ago
#define IGUANA_DISPATCH_D(agent,name,amount) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jdouble(json,#amount)))
9 years ago
9 years ago
#define IGUANA_DISPATCH_H(agent,name,hash) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jbits256(json,#hash)))
#define IGUANA_DISPATCH_HI(agent,name,hash,val) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jbits256(json,#hash),juint(json,#val)))
#define IGUANA_DISPATCH_HH(agent,name,hash,hash2) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jbits256(json,#hash),jbits256(json,#hash2)))
#define IGUANA_DISPATCH_HA(agent,name,hash,array) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jbits256(json,#hash),jobj(json,#array)))
#define IGUANA_DISPATCH_HS(agent,name,hash,str) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jbits256(json,#hash),jstr(json,#str)))
#define IGUANA_DISPATCH_HII(agent,name,hash,val,val2) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jbits256(json,#hash),juint(json,#val),juint(json,#val2)))
#define IGUANA_DISPATCH_HHS(agent,name,hash,hash2,str) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jbits256(json,#hash),jbits256(json,#hash2),jstr(json,#str)))
#define IGUANA_DISPATCH_HAS(agent,name,hash,array,str) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jbits256(json,#hash),jobj(json,#array),jstr(json,#str)))
#define IGUANA_DISPATCH_SSDIS(agent,name,str,str2,amount,val,str3) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jdouble(json,#amount),juint(json,#val),jstr(json,#str3)))
#define IGUANA_DISPATCH_SSDISS(agent,name,str,str2,amount,val,str3,str4) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jdouble(json,#amount),juint(json,#val),jstr(json,#str3),jstr(json,#str4)))
#define IGUANA_DISPATCH_SAIS(agent,name,str,array,val,str2) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jobj(json,#array),juint(json,#val),jstr(json,#str2)))
9 years ago
#define IGUANA_DISPATCH_SAOS(agent,name,str,array,object,str2) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jobj(json,#array),jobj(json,#object),jstr(json,#str2)))
9 years ago
#define IGUANA_DISPATCH_SDSS(agent,name,str,amount,str2,str3) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jdouble(json,#amount),jstr(json,#str2),jstr(json,#str3)))
9 years ago
9 years ago
#define IGUANA_DISPATCH_SHI_SDSD_II_SSSSSS(agent,name,str,hash,val,str2,amount,str3,amount2,val2,val3,str4,str5,str6,str7,str8,str9) else if ( strcmp(#agent,agentstr) == 0 && strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jbits256(json,#hash),jint(json,#val),jstr(json,#str2),jdouble(json,#amount),jstr(json,#str3),jdouble(json,#amount2),juint(json,#val2),juint(json,#val3),jstr(json,#str4),jstr(json,#str5),jstr(json,#str6),jstr(json,#str7),jstr(json,#str8),jstr(json,#str9)))
9 years ago
// API functions
#define ZERO_ARGS IGUANA_DISPATCH0
#define INT_ARG IGUANA_DISPATCH_I
#define TWO_INTS IGUANA_DISPATCH_II
#define STRING_ARG IGUANA_DISPATCH_S
#define TWO_STRINGS IGUANA_DISPATCH_SS
#define THREE_STRINGS IGUANA_DISPATCH_SSS
many changes blockexplorer tab: needs to allow to input height, blockhash or txid. also please display images/BTC_blocks.jpg below the text as a w800 x h400 bitmap, which is active using the mouse api for coin management, below the active coins have a form that arbitrary json can be input with an add button to the right that will call &#34;addcoin&#34; API. this way I can test adding new coins dynamically. dont worry if it doesnt work, just as long as it submits the json to the C code. I am pretty sure I need to do some debugging of this peers management is not working for me at all. maybe it is due to bad internet. On initialization you need to read in the confs/BTCD_peers.txt from the native filesystem and save it into the chrome app filesystem. same thing for confs/BTCD_hdrs.txt. But this is only to be done if there isnt already such a file inside chrome. if there is, only do it upon a button invoked by the user. the reason is that the pexe is updating this file with the latest. Maybe it is nice to have an &#34;extract&#34; button that will copy out from the chrome storage into the native filesystem. There is also the manifest issue about localstorage vs chrome.localstorage. not sure what is needed to be done, but certainly a priority to get it so everything works as a chrome app. I know before it was making ramchain files inside the chrome filesystem, so it is probably things the GUI is doing. maybe in the settings tab, which has obsolete stuff that can be removed. anyway, the issue about files existing in the native filesystem -&gt; chrome and optionally extracting them is an issue for the confs files and .html template files used to autogenerate the port7778, maybe other files are affected. i think we need a way to have a list of hardcoded files that are just copied into chrome on startup if they dont exist already (or if possible copy over if the native version is bigger?) and buttons to extract them for debug tab: THREE_STRINGS(SuperNET,encryptjson,passphrase,permanentfile,anything); TWO_STRINGS(SuperNET,decryptjson,passphrase,permanentfile); at the top of page a way to put in passphrase and optional permanentfile along with arbitrary json. The standard form template has no easy way to describe to pass in everything as it is oriented to specific fields. but the encryptjson API saves all the fields, so the arbitrary json from the form needs to be combined at the same level as the &#34;agent&#34;, &#34;method&#34;, etc. I know, not the best, but internally it makes it easier. so {&#34;agent&#34;:&#34;SuperNET&#34;,&#34;method&#34;:&#34;encryptjson&#34;,&#34;passphrase&#34;:&#34;&lt;passphrase&gt;&#34;,&#34; permanentfile&#34;:&#34;&lt;filename&gt;&#34;,&#34;fromform&#34;:&#34;valuefromform&#34;,&#34;fromform2&#34;:&#34;valu efromform2&#34;,...rest of form at top level} then this will save it into a file with crazy number (it is a hash like txid) but given the same passphrase and filename, it will regenerate this hash so you dont actually have to store it, but it helps during debugging. for the filename, we must warn quite strongly to the user that if the file is ever lost or even changed in any way that the data will not be recoverable. also best to not allow the user to specify a file that does not exist. I think at this point chrome app version gets a bit tricky. we could simply push the native file into the chrome storage, but then an attacker who gets access to the computer could just get a list of these files and it really wont be much protection. So that means if a filename is specified, it needs to be copied into the chrome space, then immediately deleted... ok, this seems like not a good approach. let us make it so that the permanentfile option is not available from the chrome app, but only if the native version is running. that way we sidestep the issue of the pexe not having access to the specified file. Speaking of native vs pexe, on the startup page we should have a radio button that allows the user to select which the GUI will talk to. It should default based on a self test to the more likely value, but it is possible that the user wants to use the native version, even if the pexe is running. another thing to have on the startup page is a simple login: THREE_STRINGS(SuperNET,login,passphrase,permanentfile,handle); ZERO_ARGS(SuperNET,logout); ZERO_ARGS(SuperNET,activehandle); the handle is a human readable name that is associated with the passphrase/permanentfile. There can only be one active account (though it will be possible to associate different accounts with tradebots). use the activehandle API to find out who is logged in and the associated addresses and pubkeys The above is not yet tested so if it doesnt work, dont fret, just let me know. Once set the handle can be displayed in various places to let the user know which account is logged in. The standard 12 dictionary word passphrases should be used, but any string can be sent in as the password for Pangea: INT_AND_ARRAY(pangea,host,minplayers,params); ZERO_ARGS(pangea,lobby); HASH_AND_STRING(pangea,join,tablehash,handle); HASH_AND_INT(pangea,buyin,tablehash,numchips); HASH_ARG(pangea,start,tablehash); // by host only HASH_ARG(pangea,status,tablehash); HASH_ARG(pangea,call,tablehash); HASH_ARG(pangea,check,tablehash); HASH_AND_INT(pangea,raise,tablehash,numchips); HASH_AND_INT(pangea,bet,tablehash,numchips); HASH_ARG(pangea,fold,tablehash); HASH_AND_STRING(pangea,mode,tablehash,modestr); HASH_ARG(pangea,history,tablehash); HASH_AND_INT(pangea,handhistory,tablehash,hand); The first thing that is done is a &#34;host&#34; by any node. the &#34;params&#34; should be an arbitrary json (like encryptjson) as it needs to be at the top level and it has quite a few different parameters still subject to change. The lobby API will just display all the hosted tables. once a table exists, players can join and then buyin. the buyin is denominated in chips, each chip&#39;s value is determined by the host&#39;s initial parameters. once there are enough players joined with adequate buyin&#39;s verified, the host will be able to do a start. if done before it will (eventually) give an error. for now it will just proceed. The host and players that have joined a tablehash, need to do regular status calls to see if the game has started. Probably just once per 5 or even 10 seconds is fine before the start. Once the game starts (the status will have this info) then once per second polling is needed. Then when it is your turn (as indicated by status) you need to do one of the 5 actions (fold, call, check, raise, bet). do not worry if you dont understand what all these do, just allow the user to do any of these. I guess it is possible to submit it ahead of time. I will support internally remembering the most recent action done prior to it being your turn. once it is your turn and an action is sent to the table, it is too late to change. The last API calls are for getting handhistory where hand is 0 to N-1, being the numbering of the hands played at that table. if just history, all the history for all hands at the table is coming back, so it could be quite big. probably I will make it a summary, but for the GUI just display the returned values. the mode is to change some poker specific modes, so just allow there to be a string entered. do not worry about understanding the pokerness of the API, just the overall flow: host -&gt; creates, join/buyin -&gt; fills up player slots, start -&gt; starts the game status -&gt; to determine when the game starts (or if it is cancelled) and once started actions -&gt; game specific but basically just (button + arg) that is the user input results are via status for current game and history for past ones please try to do the above logic in a generic way so it can be reused for other games. The basic flow should be the same for almost all multiplayer turn based games and even for multiplayer realtime games For InstantDEX: on the apikeypair/userid there needs to be two modes. one for when there is no stored apikey and the current form is fine, just need to make it wider as most apikeys are quite long. Now once there is an apikey saved all that is needed is the passphrase to unlock it. So here is where the encrptjson/decryptjson is used. When saving the apikey for the first time, it can be: a) not saved -&gt; nothing extra to do b) saved without password -&gt; you can just save to a file and use it to load it back in. use confs dir confs/instantdex.exchange.api or something like that c) saved with password (optional filename for native) -&gt; probably best to save in the confs dir to indicate that there is an encrypted file for this, so just that and not the actual passphrase in the file with the above, when the exchange is selected, you can see if the confs file exists and if it has the plaintext, just populate the field, if not, then indicate that a passphrase is needed. if the user provides the passphrase, then decryptjson and populate the fields and autosubmit. A special case is to encrypt the apikeys with the passphrase used when logging in. This is only available if the checkbox to &#34;remember passphrase during session&#34; is set on the main iguana login screen. (i forgot to mention that checkbox!) So the login passphrase is stored in memory, then the GUI simply uses that + encryptjson for storing/decrypting. I would imagine that storing in the confs file that it is encrypted using &#34;handle&#34;&#39;s account login might be a good way to differentiate between this mode of password usage. OK, so we now have the insecure plaintext, the decent using handle&#39;s passphrase and paranoid different passphrase for each exchange (with additional permanentfile for native versions) &#34;SUPPORT&#34; -&gt; &#34;SUPPORTS&#34; just a typo and &#34;allpairs&#34; API is missing from the selection Might as well add a &#34;tradebots&#34; tab: THREE_STRINGS_AND_DOUBLE(tradebot,monitor,exchange,base,rel,commission); STRING_AND_DOUBLE(tradebot,monitorall,exchange,commission); THREE_STRINGS(tradebot,unmonitor,exchange,base,rel); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,accumulate,exchange,base,rel,pr ice,volume,duration); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,divest,exchange,base,rel,price, volume,duration); STRING_ARG(tradebot,activebots,exchange); TWO_STRINGS(tradebot,status,exchange,botid); TWO_STRINGS(tradebot,pause,exchange,botid); TWO_STRINGS(tradebot,stop,exchange,botid); TWO_STRINGS(tradebot,resume,exchange,botid); the above are API for exchange specific bots, most should be self-explanatory. bots are created via &#34;accumulate&#34; or &#34;divest&#34; API call. it returns botid. once created, you can do status, pause, stop, resume to a botid. and an activebots API call lists all the active bots for an exchange. duration is in seconds the &#34;monitor&#34; API starts background monitoring of a specific base/rel, &#34;unmonitor&#34; stops this. &#34;monitorall&#34; just does a monitor to the entire list of &#34;allpairs&#34; for that exchange. Keep in mind that doing a monitorall will not add load to an exchange as the request to each exchange is governed by pollgap, but if you have 3 things monitored, it will take 3*pollgap + time each one takes to execute. and if N are monitored it is N*pollgap + time of each, with the &#34;time of each&#34; possibly taking a very long time. And one final request for today: Bitmap tab. It should be an active bitmap using mouse api. either a dropdown to select the bitmap or a form entry. then the rest of the page (resize the bitmap to the page size) being the active bitmap. So on a small screen the bitmap is smaller x/y dimensions and larger on larger screens. plz make sure the proper dimensions are communicated to the pexe via API if it ever is changed. @vineet.bhargav86: I changed the &#34;passphrase&#34; fieldname to &#34;password&#34; for the encryptjson/decryptjson related API. The reason is that the password is like a wallet password and is only local, so it doesnt need to be as high entropy as passphrase. I also added a field to the login API as I realized that the 12 word &#34;passphrase&#34; is the payload and usually wont be sent in: FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase); using &#34;abiglongpassword&#34; for the passphrase -&gt; {&#34;pubkey&#34;:&#34;6c469ba10b40b3eb9d1dba569d7f929d55a29d8f97cd5425907ef2f38f906 209&#34;,&#34;RS&#34;:&#34;NXT-KGV9-DXX8-TM86-DXR96&#34;,&#34;NXT&#34;:&#34;12834974574569896807&#34;,&#34;btcpu bkey&#34;:&#34;024e7641dc947b211bc30fe3339765258902794687b227121fc217284f9d8503c 8&#34;,&#34;rmd160&#34;:&#34;33453c24914db7b77069b7ea24df44f6be145938&#34;,&#34;BTC&#34;:&#34;15g6QK2dSd iW9ZTQEnnJxKrSph6uP7uU23&#34;,&#34;BTCD&#34;:&#34;RDxHUpuv3TX5DZpbhxmS3rBeaxZW1fvYvC&#34;,&#34;r esult&#34;:&#34;success&#34;,&#34;handle&#34;:&#34;test&#34;,&#34;tag&#34;:&#34;14805226009240621255&#34;} and if you use that to log into NXT, it gives the same address. The BTC and BTCD addresses are all derived from the same privkey so they are all interchangeable with the NXT address. The user can therefore select which coin&#39;s addressing they are most comfortable with I also added an &#34;allin&#34; action API for pangea. all the action API will autocalculate the number of chips if passed in 0 for numchips ***************** security issue ******** please dont use the GET URL method when dealing with passphrase!!! Those URL&#39;s tend to get logged and available in browser histories. so anything dealing with the actual passphrase needs to use the postCall form or POST
9 years ago
#define FOUR_STRINGS IGUANA_DISPATCH_SSSS
9 years ago
#define STRING_AND_INT IGUANA_DISPATCH_SI
#define STRING_AND_TWOINTS IGUANA_DISPATCH_SII
#define HASH_AND_INT IGUANA_DISPATCH_HI
9 years ago
#define HASH_AND_STRING IGUANA_DISPATCH_HS
9 years ago
#define HASH_AND_TWOINTS IGUANA_DISPATCH_HII
#define DOUBLE_ARG IGUANA_DISPATCH_D
#define STRING_AND_ARRAY IGUANA_DISPATCH_SA
#define STRING_AND_TWOARRAYS IGUANA_DISPATCH_SAA
#define TWO_ARRAYS IGUANA_DISPATCH_AA
#define INT_AND_ARRAY IGUANA_DISPATCH_IA
#define INT_ARRAY_STRING IGUANA_DISPATCH_IAS
#define SS_D_I_S IGUANA_DISPATCH_SSDIS
#define SS_D_I_SS IGUANA_DISPATCH_SSDISS
#define S_A_I_S IGUANA_DISPATCH_SAIS
#define S_D_SS IGUANA_DISPATCH_SDSS
#define TWOINTS_AND_ARRAY IGUANA_DISPATCH_IIA
#define STRING_AND_THREEINTS IGUANA_DISPATCH_SIII
#define TWOSTRINGS_AND_INT IGUANA_DISPATCH_SSI
9 years ago
#define TWOSTRINGS_AND_HASH IGUANA_DISPATCH_SSH
9 years ago
#define TWOSTRINGS_AND_HASH_AND_TWOINTS IGUANA_DISPATCH_SSHII
#define TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS IGUANA_DISPATCH_SSHHII
9 years ago
#define THREE_INTS IGUANA_DISPATCH_III
9 years ago
#define TWOHASHES_AND_STRING IGUANA_DISPATCH_HHS
#define HASH_ARRAY_STRING IGUANA_DISPATCH_HAS
9 years ago
#define U64_AND_ARRAY IGUANA_DISPATCH_64A
#define HASH_ARG IGUANA_DISPATCH_H
9 years ago
#define TWO_HASHES IGUANA_DISPATCH_HH
9 years ago
#define HASH_AND_ARRAY IGUANA_DISPATCH_HA
9 years ago
#define THREE_STRINGS_AND_THREE_INTS IGUANA_DISPATCH_SSSIII
#define THREE_STRINGS_AND_THREE_DOUBLES IGUANA_DISPATCH_SSSDDD
#define THREE_STRINGS_AND_DOUBLE IGUANA_DISPATCH_SSSD
many changes blockexplorer tab: needs to allow to input height, blockhash or txid. also please display images/BTC_blocks.jpg below the text as a w800 x h400 bitmap, which is active using the mouse api for coin management, below the active coins have a form that arbitrary json can be input with an add button to the right that will call &#34;addcoin&#34; API. this way I can test adding new coins dynamically. dont worry if it doesnt work, just as long as it submits the json to the C code. I am pretty sure I need to do some debugging of this peers management is not working for me at all. maybe it is due to bad internet. On initialization you need to read in the confs/BTCD_peers.txt from the native filesystem and save it into the chrome app filesystem. same thing for confs/BTCD_hdrs.txt. But this is only to be done if there isnt already such a file inside chrome. if there is, only do it upon a button invoked by the user. the reason is that the pexe is updating this file with the latest. Maybe it is nice to have an &#34;extract&#34; button that will copy out from the chrome storage into the native filesystem. There is also the manifest issue about localstorage vs chrome.localstorage. not sure what is needed to be done, but certainly a priority to get it so everything works as a chrome app. I know before it was making ramchain files inside the chrome filesystem, so it is probably things the GUI is doing. maybe in the settings tab, which has obsolete stuff that can be removed. anyway, the issue about files existing in the native filesystem -&gt; chrome and optionally extracting them is an issue for the confs files and .html template files used to autogenerate the port7778, maybe other files are affected. i think we need a way to have a list of hardcoded files that are just copied into chrome on startup if they dont exist already (or if possible copy over if the native version is bigger?) and buttons to extract them for debug tab: THREE_STRINGS(SuperNET,encryptjson,passphrase,permanentfile,anything); TWO_STRINGS(SuperNET,decryptjson,passphrase,permanentfile); at the top of page a way to put in passphrase and optional permanentfile along with arbitrary json. The standard form template has no easy way to describe to pass in everything as it is oriented to specific fields. but the encryptjson API saves all the fields, so the arbitrary json from the form needs to be combined at the same level as the &#34;agent&#34;, &#34;method&#34;, etc. I know, not the best, but internally it makes it easier. so {&#34;agent&#34;:&#34;SuperNET&#34;,&#34;method&#34;:&#34;encryptjson&#34;,&#34;passphrase&#34;:&#34;&lt;passphrase&gt;&#34;,&#34; permanentfile&#34;:&#34;&lt;filename&gt;&#34;,&#34;fromform&#34;:&#34;valuefromform&#34;,&#34;fromform2&#34;:&#34;valu efromform2&#34;,...rest of form at top level} then this will save it into a file with crazy number (it is a hash like txid) but given the same passphrase and filename, it will regenerate this hash so you dont actually have to store it, but it helps during debugging. for the filename, we must warn quite strongly to the user that if the file is ever lost or even changed in any way that the data will not be recoverable. also best to not allow the user to specify a file that does not exist. I think at this point chrome app version gets a bit tricky. we could simply push the native file into the chrome storage, but then an attacker who gets access to the computer could just get a list of these files and it really wont be much protection. So that means if a filename is specified, it needs to be copied into the chrome space, then immediately deleted... ok, this seems like not a good approach. let us make it so that the permanentfile option is not available from the chrome app, but only if the native version is running. that way we sidestep the issue of the pexe not having access to the specified file. Speaking of native vs pexe, on the startup page we should have a radio button that allows the user to select which the GUI will talk to. It should default based on a self test to the more likely value, but it is possible that the user wants to use the native version, even if the pexe is running. another thing to have on the startup page is a simple login: THREE_STRINGS(SuperNET,login,passphrase,permanentfile,handle); ZERO_ARGS(SuperNET,logout); ZERO_ARGS(SuperNET,activehandle); the handle is a human readable name that is associated with the passphrase/permanentfile. There can only be one active account (though it will be possible to associate different accounts with tradebots). use the activehandle API to find out who is logged in and the associated addresses and pubkeys The above is not yet tested so if it doesnt work, dont fret, just let me know. Once set the handle can be displayed in various places to let the user know which account is logged in. The standard 12 dictionary word passphrases should be used, but any string can be sent in as the password for Pangea: INT_AND_ARRAY(pangea,host,minplayers,params); ZERO_ARGS(pangea,lobby); HASH_AND_STRING(pangea,join,tablehash,handle); HASH_AND_INT(pangea,buyin,tablehash,numchips); HASH_ARG(pangea,start,tablehash); // by host only HASH_ARG(pangea,status,tablehash); HASH_ARG(pangea,call,tablehash); HASH_ARG(pangea,check,tablehash); HASH_AND_INT(pangea,raise,tablehash,numchips); HASH_AND_INT(pangea,bet,tablehash,numchips); HASH_ARG(pangea,fold,tablehash); HASH_AND_STRING(pangea,mode,tablehash,modestr); HASH_ARG(pangea,history,tablehash); HASH_AND_INT(pangea,handhistory,tablehash,hand); The first thing that is done is a &#34;host&#34; by any node. the &#34;params&#34; should be an arbitrary json (like encryptjson) as it needs to be at the top level and it has quite a few different parameters still subject to change. The lobby API will just display all the hosted tables. once a table exists, players can join and then buyin. the buyin is denominated in chips, each chip&#39;s value is determined by the host&#39;s initial parameters. once there are enough players joined with adequate buyin&#39;s verified, the host will be able to do a start. if done before it will (eventually) give an error. for now it will just proceed. The host and players that have joined a tablehash, need to do regular status calls to see if the game has started. Probably just once per 5 or even 10 seconds is fine before the start. Once the game starts (the status will have this info) then once per second polling is needed. Then when it is your turn (as indicated by status) you need to do one of the 5 actions (fold, call, check, raise, bet). do not worry if you dont understand what all these do, just allow the user to do any of these. I guess it is possible to submit it ahead of time. I will support internally remembering the most recent action done prior to it being your turn. once it is your turn and an action is sent to the table, it is too late to change. The last API calls are for getting handhistory where hand is 0 to N-1, being the numbering of the hands played at that table. if just history, all the history for all hands at the table is coming back, so it could be quite big. probably I will make it a summary, but for the GUI just display the returned values. the mode is to change some poker specific modes, so just allow there to be a string entered. do not worry about understanding the pokerness of the API, just the overall flow: host -&gt; creates, join/buyin -&gt; fills up player slots, start -&gt; starts the game status -&gt; to determine when the game starts (or if it is cancelled) and once started actions -&gt; game specific but basically just (button + arg) that is the user input results are via status for current game and history for past ones please try to do the above logic in a generic way so it can be reused for other games. The basic flow should be the same for almost all multiplayer turn based games and even for multiplayer realtime games For InstantDEX: on the apikeypair/userid there needs to be two modes. one for when there is no stored apikey and the current form is fine, just need to make it wider as most apikeys are quite long. Now once there is an apikey saved all that is needed is the passphrase to unlock it. So here is where the encrptjson/decryptjson is used. When saving the apikey for the first time, it can be: a) not saved -&gt; nothing extra to do b) saved without password -&gt; you can just save to a file and use it to load it back in. use confs dir confs/instantdex.exchange.api or something like that c) saved with password (optional filename for native) -&gt; probably best to save in the confs dir to indicate that there is an encrypted file for this, so just that and not the actual passphrase in the file with the above, when the exchange is selected, you can see if the confs file exists and if it has the plaintext, just populate the field, if not, then indicate that a passphrase is needed. if the user provides the passphrase, then decryptjson and populate the fields and autosubmit. A special case is to encrypt the apikeys with the passphrase used when logging in. This is only available if the checkbox to &#34;remember passphrase during session&#34; is set on the main iguana login screen. (i forgot to mention that checkbox!) So the login passphrase is stored in memory, then the GUI simply uses that + encryptjson for storing/decrypting. I would imagine that storing in the confs file that it is encrypted using &#34;handle&#34;&#39;s account login might be a good way to differentiate between this mode of password usage. OK, so we now have the insecure plaintext, the decent using handle&#39;s passphrase and paranoid different passphrase for each exchange (with additional permanentfile for native versions) &#34;SUPPORT&#34; -&gt; &#34;SUPPORTS&#34; just a typo and &#34;allpairs&#34; API is missing from the selection Might as well add a &#34;tradebots&#34; tab: THREE_STRINGS_AND_DOUBLE(tradebot,monitor,exchange,base,rel,commission); STRING_AND_DOUBLE(tradebot,monitorall,exchange,commission); THREE_STRINGS(tradebot,unmonitor,exchange,base,rel); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,accumulate,exchange,base,rel,pr ice,volume,duration); THREE_STRINGS_AND_THREE_DOUBLES(tradebot,divest,exchange,base,rel,price, volume,duration); STRING_ARG(tradebot,activebots,exchange); TWO_STRINGS(tradebot,status,exchange,botid); TWO_STRINGS(tradebot,pause,exchange,botid); TWO_STRINGS(tradebot,stop,exchange,botid); TWO_STRINGS(tradebot,resume,exchange,botid); the above are API for exchange specific bots, most should be self-explanatory. bots are created via &#34;accumulate&#34; or &#34;divest&#34; API call. it returns botid. once created, you can do status, pause, stop, resume to a botid. and an activebots API call lists all the active bots for an exchange. duration is in seconds the &#34;monitor&#34; API starts background monitoring of a specific base/rel, &#34;unmonitor&#34; stops this. &#34;monitorall&#34; just does a monitor to the entire list of &#34;allpairs&#34; for that exchange. Keep in mind that doing a monitorall will not add load to an exchange as the request to each exchange is governed by pollgap, but if you have 3 things monitored, it will take 3*pollgap + time each one takes to execute. and if N are monitored it is N*pollgap + time of each, with the &#34;time of each&#34; possibly taking a very long time. And one final request for today: Bitmap tab. It should be an active bitmap using mouse api. either a dropdown to select the bitmap or a form entry. then the rest of the page (resize the bitmap to the page size) being the active bitmap. So on a small screen the bitmap is smaller x/y dimensions and larger on larger screens. plz make sure the proper dimensions are communicated to the pexe via API if it ever is changed. @vineet.bhargav86: I changed the &#34;passphrase&#34; fieldname to &#34;password&#34; for the encryptjson/decryptjson related API. The reason is that the password is like a wallet password and is only local, so it doesnt need to be as high entropy as passphrase. I also added a field to the login API as I realized that the 12 word &#34;passphrase&#34; is the payload and usually wont be sent in: FOUR_STRINGS(SuperNET,login,handle,password,permanentfile,passphrase); using &#34;abiglongpassword&#34; for the passphrase -&gt; {&#34;pubkey&#34;:&#34;6c469ba10b40b3eb9d1dba569d7f929d55a29d8f97cd5425907ef2f38f906 209&#34;,&#34;RS&#34;:&#34;NXT-KGV9-DXX8-TM86-DXR96&#34;,&#34;NXT&#34;:&#34;12834974574569896807&#34;,&#34;btcpu bkey&#34;:&#34;024e7641dc947b211bc30fe3339765258902794687b227121fc217284f9d8503c 8&#34;,&#34;rmd160&#34;:&#34;33453c24914db7b77069b7ea24df44f6be145938&#34;,&#34;BTC&#34;:&#34;15g6QK2dSd iW9ZTQEnnJxKrSph6uP7uU23&#34;,&#34;BTCD&#34;:&#34;RDxHUpuv3TX5DZpbhxmS3rBeaxZW1fvYvC&#34;,&#34;r esult&#34;:&#34;success&#34;,&#34;handle&#34;:&#34;test&#34;,&#34;tag&#34;:&#34;14805226009240621255&#34;} and if you use that to log into NXT, it gives the same address. The BTC and BTCD addresses are all derived from the same privkey so they are all interchangeable with the NXT address. The user can therefore select which coin&#39;s addressing they are most comfortable with I also added an &#34;allin&#34; action API for pangea. all the action API will autocalculate the number of chips if passed in 0 for numchips ***************** security issue ******** please dont use the GET URL method when dealing with passphrase!!! Those URL&#39;s tend to get logged and available in browser histories. so anything dealing with the actual passphrase needs to use the postCall form or POST
9 years ago
#define STRING_AND_DOUBLE IGUANA_DISPATCH_SD
9 years ago
#define TWO_STRINGS_AND_TWO_DOUBLES IGUANA_DISPATCH_SSDD
9 years ago
#define STRING_AND_TWO_DOUBLES IGUANA_DISPATCH_SDD
9 years ago
#define P2SH_SPENDAPI IGUANA_DISPATCH_SHI_SDSD_II_SSSSSS
9 years ago
#define ARRAY_OBJ_INT IGUANA_DISPATCH_AOI
9 years ago
#define STRING_ARRAY_OBJ_STRING IGUANA_DISPATCH_SAOS
9 years ago
9 years ago
#include "../includes/iguana_apideclares.h"
9 years ago
//#undef IGUANA_ARGS
9 years ago
#include "../includes/iguana_apiundefs.h"
9 years ago
char errstr[512];
sprintf(errstr,"{\"error\":\"unsupported call\",\"agent\":\"%s\",\"method\":\"%s\"}",agentstr,method);
return(clonestr(errstr));
9 years ago
}