Satinder Grewal
7 years ago
committed by
GitHub
1204 changed files with 103486 additions and 44746 deletions
@ -0,0 +1,22 @@ |
|||
{ |
|||
"version": "0.2.0", |
|||
"configurations": [ |
|||
{ |
|||
"name": "C++ Launch (Windows)", |
|||
"type": "cppvsdbg", |
|||
"request": "launch", |
|||
"program": "enter program name, for example ${workspaceRoot}/a.exe", |
|||
"args": [], |
|||
"stopAtEntry": false, |
|||
"cwd": "${workspaceRoot}", |
|||
"environment": [], |
|||
"externalConsole": false |
|||
}, |
|||
{ |
|||
"name": "C++ Attach (Windows)", |
|||
"type": "cppvsdbg", |
|||
"request": "attach", |
|||
"processId": "${command:pickProcess}" |
|||
} |
|||
] |
|||
} |
@ -0,0 +1,22 @@ |
|||
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project"> |
|||
<TemplateData> |
|||
<Name>iguana_template</Name> |
|||
<Description><No description available></Description> |
|||
<ProjectType>VC</ProjectType> |
|||
<ProjectSubType> |
|||
</ProjectSubType> |
|||
<SortOrder>1000</SortOrder> |
|||
<CreateNewFolder>true</CreateNewFolder> |
|||
<DefaultName>iguana_template</DefaultName> |
|||
<ProvideDefaultName>true</ProvideDefaultName> |
|||
<LocationField>Enabled</LocationField> |
|||
<EnableLocationBrowseButton>true</EnableLocationBrowseButton> |
|||
<Icon>__TemplateIcon.ico</Icon> |
|||
</TemplateData> |
|||
<TemplateContent> |
|||
<Project TargetFileName="ConsoleApplication3.vcxproj" File="ConsoleApplication3.vcxproj" ReplaceParameters="true"> |
|||
<ProjectItem ReplaceParameters="false" TargetFileName="$projectname$.vcxproj.filters">ConsoleApplication3.vcxproj.filters</ProjectItem> |
|||
<ProjectItem ReplaceParameters="false" TargetFileName="ReadMe.txt">ReadMe.txt</ProjectItem> |
|||
</Project> |
|||
</TemplateContent> |
|||
</VSTemplate> |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,25 @@ |
|||
## What's this? |
|||
|
|||
This is a first build of **MarketMaker** app from barterDEX for Windows (64-bit) platform. This branch includes all that you need to build marketmaker for Windows. 64-bit build uses MSVC 2015 as a default C/C++ compiler, to build - simply open *marketmaker.sln* project file via File -> Open -> Project/Solution ... next choose Release / x64 configuration and build solution. Your binaries will be placed x64\Release folder. To run marketmaker you also need following dll libraries: |
|||
|
|||
- libcurl.dll |
|||
- nanomsg.dll |
|||
- curl.exe (win64 curl binary, used is scripts) |
|||
|
|||
It already included in this branch. |
|||
|
|||
## How to use? |
|||
|
|||
Please, refer to original barterDEX documentation and Komodo Platform + SuperNET resources to learn how to work this it. Later i will add some examples and useful links here. |
|||
|
|||
Important, coins.json on Windows shouldn't contain coins which haven't running daemons. Add to coins.json only coins that you plan to use, in other case starting marketmaker will too long: about 4 seconds on each not-running coin. |
|||
|
|||
Get the latest binary release from release section and step-by-step run cmd files: |
|||
|
|||
- 1-client.cmd - this runs marketmaker with passphrase taken from a passphrase file. |
|||
- 2-getuserpass.cmd - this will save and output your userpass in userpass file for future use. |
|||
- 3-orderbook.cmd - to get an orderbook (if u downloaded binary release from release section - it's have only REVS in coins.json and orderbook will be shown at KMD/REVS coins pair). |
|||
|
|||
Other scripts will be post later ... this is just for example that it works. |
|||
|
|||
|
@ -0,0 +1,40 @@ |
|||
======================================================================== |
|||
CONSOLE APPLICATION : ConsoleApplication3 Project Overview |
|||
======================================================================== |
|||
|
|||
AppWizard has created this ConsoleApplication3 application for you. |
|||
|
|||
This file contains a summary of what you will find in each of the files that |
|||
make up your ConsoleApplication3 application. |
|||
|
|||
|
|||
ConsoleApplication3.vcxproj |
|||
This is the main project file for VC++ projects generated using an Application Wizard. |
|||
It contains information about the version of Visual C++ that generated the file, and |
|||
information about the platforms, configurations, and project features selected with the |
|||
Application Wizard. |
|||
|
|||
ConsoleApplication3.vcxproj.filters |
|||
This is the filters file for VC++ projects generated using an Application Wizard. |
|||
It contains information about the association between the files in your project |
|||
and the filters. This association is used in the IDE to show grouping of files with |
|||
similar extensions under a specific node (for e.g. ".cpp" files are associated with the |
|||
"Source Files" filter). |
|||
|
|||
ConsoleApplication3.cpp |
|||
This is the main application source file. |
|||
|
|||
///////////////////////////////////////////////////////////////////////////// |
|||
Other standard files: |
|||
|
|||
StdAfx.h, StdAfx.cpp |
|||
These files are used to build a precompiled header (PCH) file |
|||
named ConsoleApplication3.pch and a precompiled types file named StdAfx.obj. |
|||
|
|||
///////////////////////////////////////////////////////////////////////////// |
|||
Other notes: |
|||
|
|||
AppWizard uses "TODO:" comments to indicate parts of the source code you |
|||
should add to or customize. |
|||
|
|||
///////////////////////////////////////////////////////////////////////////// |
After Width: | Height: | Size: 43 KiB |
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,405 @@ |
|||
/******************************************************************************
|
|||
* Copyright © 2014-2016 The SuperNET Developers. * |
|||
* * |
|||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * |
|||
* the top-level directory of this distribution for the individual copyright * |
|||
* holder information and the developer policies on copyright and licensing. * |
|||
* * |
|||
* Unless otherwise agreed in a custom licensing agreement, no part of the * |
|||
* SuperNET software, including this file may be copied, modified, propagated * |
|||
* or distributed except according to the terms contained in the LICENSE file * |
|||
* * |
|||
* Removal or modification of this copyright notice is prohibited. * |
|||
* * |
|||
******************************************************************************/ |
|||
|
|||
#define MAX_ELECTIONS 64 |
|||
|
|||
struct vote_info |
|||
{ |
|||
bits256 commit,vote; |
|||
uint64_t stake,repstake; |
|||
int32_t repid; |
|||
uint8_t sig[74],siglen; |
|||
uint8_t pubkey[33],rmd160[20]; |
|||
}; |
|||
|
|||
struct election_info |
|||
{ |
|||
bits256 hash; |
|||
char name[64]; |
|||
uint32_t expiration,duration,numcandidates,numvotes; |
|||
cJSON *ballot; |
|||
struct vote_info *votes; |
|||
} Elections[MAX_ELECTIONS]; |
|||
|
|||
int64_t basilisk_voter_stake(struct supernet_info *myinfo,uint8_t *rmd160,struct iguana_info *coin,uint8_t *pubkey) |
|||
{ |
|||
char coinaddr[64]; int64_t stake = 1; |
|||
calc_rmd160_sha256(rmd160,pubkey,33); |
|||
bitcoin_address(coinaddr,coin->chain->pubtype,pubkey,33); |
|||
// get stake of address
|
|||
return(stake); |
|||
} |
|||
|
|||
int32_t basilisk_voter_process(struct supernet_info *myinfo,uint8_t *rmd160,struct iguana_info *coin,struct election_info *ep,struct vote_info *vp) |
|||
{ |
|||
int32_t i; |
|||
if ( vp->stake == 0 ) |
|||
vp->stake = 1; |
|||
if ( bits256_nonz(vp->vote) != 0 ) |
|||
{ |
|||
for (i=1; i<8; i++) |
|||
if ( vp->vote.uints[i] != 0 ) |
|||
break; |
|||
if ( i == 8 ) |
|||
return(vp->vote.uints[0]); |
|||
else |
|||
{ |
|||
for (i=0; i<20; i++) |
|||
rmd160[i] = vp->vote.bytes[i + 4]; |
|||
return(ep->numcandidates); |
|||
} |
|||
} |
|||
return(-1); |
|||
} |
|||
|
|||
int32_t basilisk_election_process(struct supernet_info *myinfo,int64_t *tally,struct iguana_info *coin,struct election_info *ep) |
|||
{ |
|||
int32_t i,j,pending = 0; struct vote_info *vp; uint8_t rmd160[20]; |
|||
for (i=0; i<ep->numvotes; i++) |
|||
ep->votes[i].repstake = 0; |
|||
for (i=0; i<ep->numvotes; i++) |
|||
{ |
|||
vp = &ep->votes[i]; |
|||
if ( basilisk_voter_process(myinfo,rmd160,coin,ep,vp) == ep->numcandidates && vp->repid < 0 ) |
|||
{ |
|||
for (j=0; j<ep->numvotes; j++) |
|||
{ |
|||
if ( i != j && memcmp(rmd160,ep->votes[j].rmd160,20) == 0 ) |
|||
{ |
|||
vp->repid = j; |
|||
ep->votes[j].repstake += vp->stake; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
if ( tally != 0 ) |
|||
{ |
|||
memset(tally,0,ep->numcandidates*sizeof(*tally)); |
|||
for (i=0; i<ep->numvotes; i++) |
|||
{ |
|||
vp = &ep->votes[i]; |
|||
if ( vp->repid < 0 && vp->vote.uints[0] > 0 && vp->vote.uints[0] <= ep->numcandidates ) |
|||
tally[vp->vote.uints[0]] += (vp->stake + vp->repstake); |
|||
else if ( vp->repid < 0 ) |
|||
pending++; |
|||
} |
|||
} |
|||
return(pending); |
|||
} |
|||
|
|||
cJSON *basilisk_voterjson(struct supernet_info *myinfo,struct iguana_info *coin,struct election_info *ep,struct vote_info *vp) |
|||
{ |
|||
char coinaddr[64],sigstr[74*2+1]; int32_t i; uint8_t rmd160[20]; cJSON *item; |
|||
item = cJSON_CreateObject(); |
|||
basilisk_voter_process(myinfo,rmd160,coin,ep,vp); |
|||
bitcoin_address(coinaddr,5,vp->pubkey,sizeof(vp->pubkey)); |
|||
jaddstr(item,"coinaddr",coinaddr); |
|||
jaddnum(item,"stake",dstr(vp->stake)); |
|||
if ( vp->repstake != 0 ) |
|||
jaddnum(item,"repstake",dstr(vp->repstake)); |
|||
if ( bits256_nonz(vp->vote) != 0 ) |
|||
{ |
|||
for (i=1; i<8; i++) |
|||
if ( vp->vote.uints[i] != 0 ) |
|||
break; |
|||
if ( i == 8 ) |
|||
{ |
|||
if ( vp->vote.uints[0] <= ep->numcandidates ) |
|||
jaddnum(item,"vote",vp->vote.uints[0]); |
|||
else jaddstr(item,"error","illegal vote"); |
|||
} |
|||
else |
|||
{ |
|||
for (i=0; i<20; i++) |
|||
rmd160[i] = vp->vote.bytes[i + 4]; |
|||
bitcoin_address(coinaddr,5,rmd160,20); |
|||
jaddstr(item,"delegated",coinaddr); |
|||
} |
|||
} |
|||
else if ( bits256_nonz(vp->commit) != 0 ) |
|||
jaddbits256(item,"commit",vp->commit); |
|||
init_hexbytes_noT(sigstr,vp->sig,vp->siglen); |
|||
jaddstr(item,"sig",sigstr); |
|||
return(item); |
|||
} |
|||
|
|||
cJSON *basilisk_electionjson(struct supernet_info *myinfo,struct iguana_info *coin,struct election_info *ep) |
|||
{ |
|||
int32_t i; cJSON *array,*obj = cJSON_CreateObject(); |
|||
jaddstr(obj,"name",ep->name); |
|||
jaddbits256(obj,"hash",ep->hash); |
|||
jaddnum(obj,"expiration",ep->expiration); |
|||
jaddnum(obj,"numcandidates",ep->numcandidates); |
|||
jaddnum(obj,"numvotes",ep->numvotes); |
|||
jadd(obj,"ballot",jduplicate(ep->ballot)); |
|||
array = cJSON_CreateArray(); |
|||
for (i=0; i<ep->numvotes; i++) |
|||
jaddi(array,basilisk_voterjson(myinfo,coin,ep,&ep->votes[i])); |
|||
jadd(obj,"votes",array); |
|||
return(obj); |
|||
} |
|||
|
|||
int32_t basilisk_electionsave(struct election_info *ep) |
|||
{ |
|||
char fname[512],str[65],*ballotstr; int32_t n; FILE *fp; |
|||
OS_ensure_directory("elections"); |
|||
sprintf(fname,"elections/%s",bits256_str(str,ep->hash)); |
|||
OS_compatible_path(fname); |
|||
if ( (fp= fopen(fname,"wb")) != 0 ) |
|||
{ |
|||
if ( fwrite(ep,1,sizeof(*ep),fp) != sizeof(*ep) ) |
|||
printf("error saving election.(%s) to %s\n",ep->name,fname); |
|||
else |
|||
{ |
|||
if ( fwrite(&ep->numvotes,1,sizeof(ep->numvotes),fp) != sizeof(ep->numvotes) ) |
|||
printf("error saving numvotes.%d to %s\n",ep->numvotes,fname); |
|||
else if ( ep->numvotes > 0 ) |
|||
{ |
|||
if ( fwrite(ep->votes,sizeof(*ep->votes),ep->numvotes,fp) != ep->numvotes ) |
|||
printf("error saving votes.%d for %s to %s\n",ep->numvotes,ep->name,fname); |
|||
else |
|||
{ |
|||
if ( (ballotstr= jprint(ep->ballot,0)) != 0 ) |
|||
{ |
|||
n = (int32_t)strlen(ballotstr) + 1; |
|||
if ( fwrite(&n,1,sizeof(n),fp) != sizeof(n) ) |
|||
printf("error saving n.%d for (%s) to %s\n",n,ballotstr,fname); |
|||
else if ( fwrite(ballotstr,1,n,fp) != n ) |
|||
printf("error saving election.(%s) to %s\n",ballotstr,fname); |
|||
free(ballotstr); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
fclose(fp); |
|||
return(0); |
|||
} |
|||
return(-1); |
|||
} |
|||
|
|||
struct vote_info *basilisk_vote_find(struct election_info *ep,struct vote_info *vote) |
|||
{ |
|||
int32_t i; |
|||
for (i=0; i<ep->numvotes; i++) |
|||
{ |
|||
if ( memcmp(ep->votes[i].pubkey,vote->pubkey,33) == 0 ) |
|||
return(&ep->votes[i]); |
|||
} |
|||
return(0); |
|||
} |
|||
|
|||
struct election_info *basilisk_election_find(int32_t createflag,bits256 hash) |
|||
{ |
|||
int32_t i; uint32_t now = (uint32_t)time(NULL); |
|||
for (i=0; i<sizeof(Elections)/sizeof(*Elections); i++) |
|||
{ |
|||
if ( Elections[i].expiration != 0 && now > Elections[i].expiration ) |
|||
{ |
|||
basilisk_electionsave(&Elections[i]); |
|||
memset(&Elections[i],0,sizeof(Elections[i])); |
|||
} |
|||
if ( bits256_nonz(hash) != 0 ) |
|||
{ |
|||
if ( bits256_nonz(Elections[i].hash) == 0 ) |
|||
return(&Elections[i]); |
|||
else if ( bits256_cmp(Elections[i].hash,hash) == 0 ) |
|||
return(0); |
|||
} |
|||
} |
|||
return(0); |
|||
} |
|||
|
|||
int32_t basilisk_vote_extract(struct supernet_info *myinfo,char *coinaddr,struct vote_info *vote,cJSON *item) |
|||
{ |
|||
char str[65],str2[65],str3[65]; uint8_t *sig,*pubkey; int32_t action,siglen,plen; bits256 data,hash; |
|||
memset(vote,0,sizeof(*vote)); |
|||
if ( get_dataptr(0,&sig,&siglen,vote->sig,sizeof(vote->sig),jstr(item,"sig")) != 0 ) |
|||
{ |
|||
vote->siglen = siglen; |
|||
action = juint(item,"action"); |
|||
if ( get_dataptr(0,&pubkey,&plen,vote->pubkey,sizeof(vote->pubkey),jstr(item,"pubkey")) != 0 ) |
|||
{ |
|||
bitcoin_address(coinaddr,5,pubkey,33); |
|||
data = jbits256(item,"data"); |
|||
if ( bitcoin_verify(myinfo->ctx,vote->sig,vote->siglen,data,vote->pubkey,33) == 0 ) |
|||
{ |
|||
if ( (action & 0xff) == 'c' ) |
|||
{ |
|||
vote->commit = data; |
|||
printf("%s commits to %s\n",coinaddr,bits256_str(str,data)); |
|||
return(action); |
|||
} |
|||
else if ( (action & 0xff) == 'r' ) |
|||
{ |
|||
if ( bits256_nonz(vote->commit) != 0 ) |
|||
{ |
|||
vcalc_sha256(0,hash.bytes,data.bytes,sizeof(data)); |
|||
if ( bits256_cmp(hash,vote->commit) == 0 ) |
|||
{ |
|||
printf("%s vote %s -> %s matches commit %s\n",coinaddr,bits256_str(str,data),bits256_str(str2,hash),bits256_str(str3,vote->commit)); |
|||
vote->vote = data; |
|||
// error check vote
|
|||
return(action); |
|||
} |
|||
else |
|||
{ |
|||
printf("%s vote %s -> %s doesnt match commit %s\n",coinaddr,bits256_str(str,data),bits256_str(str2,hash),bits256_str(str3,vote->commit)); |
|||
return(-2); |
|||
} |
|||
} |
|||
} |
|||
} else return(-1); |
|||
} |
|||
} |
|||
return(-1); |
|||
} |
|||
|
|||
char *basilisk_respond_VOT(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk) |
|||
{ |
|||
int32_t i,duration,winner,pending,action,numcandidates; char coinaddr[64],*symbol,*votemethod,*ballotstr; cJSON *item,*array,*electionobj,*ballot,*retjson; struct election_info *ep; struct vote_info vote,*vp; struct iguana_info *coin; int64_t *tally,max; |
|||
retjson = cJSON_CreateObject(); |
|||
if ( (symbol= jstr(valsobj,"coin")) == 0 ) |
|||
symbol = "BTCD"; |
|||
coin = iguana_coinfind(symbol); |
|||
if ( (votemethod= jstr(valsobj,"votemethod")) != 0 ) |
|||
{ |
|||
if ( strcmp(votemethod,"create") == 0 ) |
|||
{ |
|||
if ( (ballot= jarray(&numcandidates,valsobj,"ballot")) != 0 && numcandidates > 0 ) |
|||
{ |
|||
if ( (duration= juint(valsobj,"duration")) == 0 ) |
|||
duration = 3600; |
|||
ballotstr = jprint(ballot,0); |
|||
vcalc_sha256(0,hash.bytes,(uint8_t *)ballotstr,(int32_t)strlen(ballotstr)); |
|||
free(ballotstr); |
|||
if ( (ep= basilisk_election_find(1,hash)) != 0 ) |
|||
{ |
|||
ep->hash = hash; |
|||
ep->duration = duration; |
|||
ep->expiration = (uint32_t)time(NULL) + duration; |
|||
ep->ballot = jduplicate(ballot); |
|||
ep->numcandidates = numcandidates; |
|||
safecopy(ep->name,jstr(valsobj,"name"),sizeof(ep->name)); |
|||
if ( (electionobj= basilisk_electionjson(myinfo,coin,ep)) != 0 ) |
|||
{ |
|||
jaddstr(retjson,"result","success"); |
|||
jadd(retjson,"election",electionobj); |
|||
} else jaddstr(retjson,"error","couldnt create election object"); |
|||
} else jaddstr(retjson,"error","couldnt allocate election slot"); |
|||
} |
|||
} |
|||
else if ( strcmp(votemethod,"list") == 0 ) |
|||
{ |
|||
array = cJSON_CreateArray(); |
|||
for (i=0; i<sizeof(Elections)/sizeof(*Elections); i++) |
|||
{ |
|||
if ( bits256_nonz(Elections[i].hash) != 0 ) |
|||
{ |
|||
item = cJSON_CreateObject(); |
|||
jaddstr(item,"name",Elections[i].name); |
|||
jaddbits256(item,"hash",Elections[i].hash); |
|||
jaddi(array,item); |
|||
} |
|||
} |
|||
jaddstr(retjson,"result","success"); |
|||
jadd(retjson,"elections",array); |
|||
} |
|||
if ( (ep= basilisk_election_find(0,hash)) != 0 ) |
|||
{ |
|||
if ( strcmp(votemethod,"info") == 0 ) |
|||
{ |
|||
jaddstr(retjson,"result","success"); |
|||
tally = calloc(ep->numcandidates+1,sizeof(*tally)); |
|||
pending = basilisk_election_process(myinfo,tally,coin,ep); |
|||
if ( pending != 0 ) |
|||
jaddnum(retjson,"pending",pending); |
|||
jadd(retjson,"election",basilisk_electionjson(myinfo,coin,ep)); |
|||
array = cJSON_CreateArray(); |
|||
max = 0; |
|||
winner = -1; |
|||
for (i=1; i<=ep->numcandidates; i++) |
|||
{ |
|||
if ( tally[i] > max ) |
|||
{ |
|||
max = tally[i]; |
|||
winner = i; |
|||
} |
|||
jaddinum(array,dstr(tally[i])); |
|||
} |
|||
jadd(retjson,"tally",array); |
|||
if ( winner > 0 ) |
|||
{ |
|||
item = jitem(ep->ballot,winner-1); |
|||
jadd(retjson,"winner",item); |
|||
} |
|||
free(tally); |
|||
} |
|||
else if ( strcmp(votemethod,"ratify") == 0 ) |
|||
{ |
|||
// record ratification of tally
|
|||
} |
|||
else if ( (action= basilisk_vote_extract(myinfo,coinaddr,&vote,valsobj)) > 0 ) |
|||
{ |
|||
vp = basilisk_vote_find(ep,&vote); |
|||
if ( strcmp(votemethod,"vote") == 0 ) |
|||
{ |
|||
if ( vp == 0 ) |
|||
{ |
|||
ep->votes = realloc(ep->votes,sizeof(*ep->votes) + (ep->numvotes + 1)); |
|||
vote.repid = -1; |
|||
vote.stake = basilisk_voter_stake(myinfo,vote.rmd160,coin,vote.pubkey); |
|||
ep->votes[ep->numvotes++] = vote; |
|||
jaddstr(retjson,"result","success"); |
|||
} |
|||
else if ( action == 'c' ) |
|||
{ |
|||
*vp = vote; |
|||
jaddstr(retjson,"result","success"); |
|||
} |
|||
else if ( action == 'r' ) |
|||
{ |
|||
*vp = vote; |
|||
jaddstr(retjson,"result","success"); |
|||
} else jaddstr(retjson,"error","illegal vote action"); |
|||
} |
|||
else if ( strcmp(votemethod,"verify") == 0 ) |
|||
{ |
|||
if ( vp == 0 ) |
|||
jaddstr(retjson,"error","cant find voter"); |
|||
else if ( action == 'c' ) |
|||
{ |
|||
if ( bits256_cmp(vote.commit,vp->commit) == 0 ) |
|||
jaddstr(retjson,"result","success"); |
|||
else jaddstr(retjson,"error","mismatched commit"); |
|||
jaddbits256(retjson,"oldcommit",vp->commit); |
|||
jaddbits256(retjson,"newcommit",vote.commit); |
|||
} |
|||
else if ( action == 'r' ) |
|||
{ |
|||
if ( bits256_cmp(vote.vote,vp->vote) == 0 ) |
|||
jaddstr(retjson,"result","success"); |
|||
else jaddstr(retjson,"error","mismatched vote"); |
|||
jaddbits256(retjson,"oldvote",vp->vote); |
|||
jaddbits256(retjson,"newvote",vote.vote); |
|||
} else jaddstr(retjson,"error","illegal vote action"); |
|||
} else jaddstr(retjson,"error","illegal vote method"); |
|||
} else jaddstr(retjson,"error","couldnt extract vote info"); |
|||
} |
|||
} |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
|
@ -0,0 +1,772 @@ |
|||
/******************************************************************************
|
|||
* Copyright © 2014-2017 The SuperNET Developers. * |
|||
* * |
|||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * |
|||
* the top-level directory of this distribution for the individual copyright * |
|||
* holder information and the developer policies on copyright and licensing. * |
|||
* * |
|||
* Unless otherwise agreed in a custom licensing agreement, no part of the * |
|||
* SuperNET software, including this file may be copied, modified, propagated * |
|||
* or distributed except according to the terms contained in the LICENSE file * |
|||
* * |
|||
* Removal or modification of this copyright notice is prohibited. * |
|||
* * |
|||
******************************************************************************/ |
|||
|
|||
// included from basilisk.c
|
|||
// connect DEX to jumblr-core
|
|||
|
|||
/*
|
|||
z_exportkey "zaddr" |
|||
z_exportwallet "filename" |
|||
z_getoperationstatus (["operationid", ... ]) |
|||
z_gettotalbalance ( minconf ) |
|||
z_importkey "zkey" ( rescan ) |
|||
z_importwallet "filename" |
|||
z_listaddresses |
|||
z_sendmany "fromaddress" [{"address":... ,"amount":..., "memo":"<hex>"},...] ( minconf ) ( fee ) |
|||
*/ |
|||
|
|||
#define JUMBLR_ADDR "RGhxXpXSSBTBm9EvNsXnTQczthMCxHX91t" |
|||
#define JUMBLR_BTCADDR "18RmTJe9qMech8siuhYfMtHo8RtcN1obC6" |
|||
|
|||
int32_t jumblr_addresstype(struct supernet_info *myinfo,struct iguana_info *coin,char *addr) |
|||
{ |
|||
if ( strcmp(coin->symbol,"KMD") == 0 ) |
|||
{ |
|||
if ( addr[0] == 'z' && addr[1] == 'c' && strlen(addr) >= 40 ) |
|||
return('z'); |
|||
else if ( strlen(addr) < 40 ) |
|||
return('t'); |
|||
else return(-1); |
|||
} else return('t'); |
|||
} |
|||
|
|||
struct jumblr_item *jumblr_opidfind(struct supernet_info *myinfo,char *opid) |
|||
{ |
|||
struct jumblr_item *ptr; |
|||
HASH_FIND(hh,myinfo->jumblrs,opid,(int32_t)strlen(opid),ptr); |
|||
return(ptr); |
|||
} |
|||
|
|||
struct jumblr_item *jumblr_opidadd(struct supernet_info *myinfo,struct iguana_info *coin,char *opid) |
|||
{ |
|||
struct jumblr_item *ptr; |
|||
if ( (ptr= jumblr_opidfind(myinfo,opid)) == 0 ) |
|||
{ |
|||
ptr = calloc(1,sizeof(*ptr)); |
|||
safecopy(ptr->opid,opid,sizeof(ptr->opid)); |
|||
HASH_ADD_KEYPTR(hh,myinfo->jumblrs,ptr->opid,(int32_t)strlen(ptr->opid),ptr); |
|||
if ( ptr != jumblr_opidfind(myinfo,opid) ) |
|||
printf("jumblr_opidadd.(%s) ERROR, couldnt find after add\n",opid); |
|||
} |
|||
return(ptr); |
|||
} |
|||
|
|||
char *jumblr_validateaddress(struct supernet_info *myinfo,struct iguana_info *coin,char *addr) |
|||
{ |
|||
char params[1024]; |
|||
if ( coin->FULLNODE < 0 ) |
|||
{ |
|||
sprintf(params,"[\"%s\"]",addr); |
|||
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"validateaddress",params)); |
|||
} else return(_dex_validateaddress(myinfo,coin->symbol,addr)); |
|||
} |
|||
|
|||
int32_t jumblr_ismine(struct supernet_info *myinfo,struct iguana_info *coin,char *addr) |
|||
{ |
|||
char params[1024],*retstr; cJSON *retjson,*obj; int32_t retval = -1; |
|||
sprintf(params,"[\"%s\"]",addr); |
|||
if ( (retstr= jumblr_validateaddress(myinfo,coin,addr)) != 0 ) |
|||
{ |
|||
if ( (retjson= cJSON_Parse(retstr)) != 0 ) |
|||
{ |
|||
if ( (obj= jobj(retjson,"ismine")) != 0 && is_cJSON_True(obj) != 0 ) |
|||
retval = 1; |
|||
else retval = 0; |
|||
free_json(retjson); |
|||
} |
|||
free(retstr); |
|||
} |
|||
return(retval); |
|||
} |
|||
|
|||
char *jumblr_zgetnewaddress(struct supernet_info *myinfo,struct iguana_info *coin) |
|||
{ |
|||
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_getnewaddress","")); |
|||
} |
|||
|
|||
char *jumblr_zlistoperationids(struct supernet_info *myinfo,struct iguana_info *coin) |
|||
{ |
|||
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_listoperationids","")); |
|||
} |
|||
|
|||
char *jumblr_zgetoperationresult(struct supernet_info *myinfo,struct iguana_info *coin,char *opid) |
|||
{ |
|||
char params[1024]; |
|||
sprintf(params,"[[\"%s\"]]",opid); |
|||
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_getoperationresult",params)); |
|||
} |
|||
|
|||
char *jumblr_zgetoperationstatus(struct supernet_info *myinfo,struct iguana_info *coin,char *opid) |
|||
{ |
|||
char params[1024]; |
|||
sprintf(params,"[[\"%s\"]]",opid); |
|||
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_getoperationstatus",params)); |
|||
} |
|||
|
|||
char *jumblr_sendt_to_z(struct supernet_info *myinfo,struct iguana_info *coin,char *taddr,char *zaddr,double amount) |
|||
{ |
|||
char params[1024]; double fee = (amount-3*JUMBLR_TXFEE) * JUMBLR_FEE; |
|||
if ( jumblr_addresstype(myinfo,coin,zaddr) != 'z' || jumblr_addresstype(myinfo,coin,taddr) != 't' ) |
|||
return(clonestr("{\"error\":\"illegal address in t to z\"}")); |
|||
sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",taddr,zaddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); |
|||
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_sendmany",params)); |
|||
} |
|||
|
|||
char *jumblr_sendz_to_z(struct supernet_info *myinfo,struct iguana_info *coin,char *zaddrS,char *zaddrD,double amount) |
|||
{ |
|||
char params[1024]; double fee = (amount-2*JUMBLR_TXFEE) * JUMBLR_FEE; |
|||
if ( jumblr_addresstype(myinfo,coin,zaddrS) != 'z' || jumblr_addresstype(myinfo,coin,zaddrD) != 'z' ) |
|||
return(clonestr("{\"error\":\"illegal address in z to z\"}")); |
|||
sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddrS,zaddrD,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); |
|||
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_sendmany",params)); |
|||
} |
|||
|
|||
char *jumblr_sendz_to_t(struct supernet_info *myinfo,struct iguana_info *coin,char *zaddr,char *taddr,double amount) |
|||
{ |
|||
char params[1024]; double fee = (amount-JUMBLR_TXFEE) * JUMBLR_FEE; |
|||
if ( jumblr_addresstype(myinfo,coin,zaddr) != 'z' || jumblr_addresstype(myinfo,coin,taddr) != 't' ) |
|||
return(clonestr("{\"error\":\"illegal address in z to t\"}")); |
|||
sprintf(params,"[\"%s\", [{\"address\":\"%s\",\"amount\":%.8f}, {\"address\":\"%s\",\"amount\":%.8f}], 1, %.8f]",zaddr,taddr,amount-fee-JUMBLR_TXFEE,JUMBLR_ADDR,fee,JUMBLR_TXFEE); |
|||
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_sendmany",params)); |
|||
} |
|||
|
|||
char *jumblr_zlistreceivedbyaddress(struct supernet_info *myinfo,struct iguana_info *coin,char *addr) |
|||
{ |
|||
char params[1024]; |
|||
sprintf(params,"[\"%s\", 1]",addr); |
|||
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_listreceivedbyaddress",params)); |
|||
} |
|||
|
|||
char *jumblr_getreceivedbyaddress(struct supernet_info *myinfo,struct iguana_info *coin,char *addr) |
|||
{ |
|||
char params[1024]; |
|||
sprintf(params,"[\"%s\", 1]",addr); |
|||
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"getreceivedbyaddress",params)); |
|||
} |
|||
|
|||
char *jumblr_importprivkey(struct supernet_info *myinfo,struct iguana_info *coin,char *wifstr) |
|||
{ |
|||
char params[1024]; |
|||
sprintf(params,"[\"%s\", \"\", false]",wifstr); |
|||
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"importprivkey",params)); |
|||
} |
|||
|
|||
char *jumblr_zgetbalance(struct supernet_info *myinfo,struct iguana_info *coin,char *addr) |
|||
{ |
|||
char params[1024]; |
|||
sprintf(params,"[\"%s\", 1]",addr); |
|||
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"z_getbalance",params)); |
|||
} |
|||
|
|||
char *jumblr_listunspent(struct supernet_info *myinfo,struct iguana_info *coin,char *coinaddr) |
|||
{ |
|||
char params[1024]; |
|||
if ( coin->FULLNODE == 0 ) |
|||
return(dex_listunspent(myinfo,coin,0,0,coin->symbol,coinaddr)); |
|||
sprintf(params,"[1, 99999999, [\"%s\"]]",coinaddr); |
|||
return(bitcoind_passthru(coin->symbol,coin->chain->serverport,coin->chain->userpass,"listunspent",params)); |
|||
} |
|||
|
|||
int64_t jumblr_receivedby(struct supernet_info *myinfo,struct iguana_info *coin,char *addr) |
|||
{ |
|||
char *retstr; int64_t total = 0; |
|||
if ( (retstr= jumblr_getreceivedbyaddress(myinfo,coin,addr)) != 0 ) |
|||
{ |
|||
total = atof(retstr) * SATOSHIDEN; |
|||
free(retstr); |
|||
} |
|||
return(total); |
|||
} |
|||
|
|||
int64_t jumblr_balance(struct supernet_info *myinfo,struct iguana_info *coin,char *addr) |
|||
{ |
|||
char *retstr; double val; cJSON *retjson; int32_t i,n; int64_t balance = 0; |
|||
if ( jumblr_addresstype(myinfo,coin,addr) == 't' ) |
|||
{ |
|||
if ( coin->FULLNODE < 0 && iguana_isnotarychain(coin->symbol) < 0 ) |
|||
{ |
|||
if ( (retstr= jumblr_listunspent(myinfo,coin,addr)) != 0 ) |
|||
{ |
|||
printf("jumblr.[%s].(%s)\n",coin->symbol,retstr); |
|||
if ( (retjson= cJSON_Parse(retstr)) != 0 ) |
|||
{ |
|||
if ( (n= cJSON_GetArraySize(retjson)) > 0 ) |
|||
for (i=0; i<n; i++) |
|||
balance += SATOSHIDEN * jdouble(jitem(retjson,i),"amount"); |
|||
free_json(retjson); |
|||
} |
|||
free(retstr); |
|||
} |
|||
} |
|||
else if ( (retstr= dex_getbalance(myinfo,coin,0,0,coin->symbol,addr)) != 0 ) |
|||
{ |
|||
//printf("DEX retstr.(%s)\n",retstr);
|
|||
if ( (retjson= cJSON_Parse(retstr)) != 0 ) |
|||
{ |
|||
balance = jdouble(retjson,"balance") * SATOSHIDEN; |
|||
//printf("GOT BALANCE %s %.8f\n",coin->symbol,dstr(balance));
|
|||
free_json(retjson); |
|||
} |
|||
free(retstr); |
|||
} |
|||
} |
|||
else if ( (retstr= jumblr_zgetbalance(myinfo,coin,addr)) != 0 ) |
|||
{ |
|||
if ( (val= atof(retstr)) > SMALLVAL ) |
|||
balance = val * SATOSHIDEN; |
|||
free(retstr); |
|||
} |
|||
return(balance); |
|||
} |
|||
|
|||
int32_t jumblr_itemset(struct jumblr_item *ptr,cJSON *item,char *status) |
|||
{ |
|||
cJSON *params,*amounts,*dest; char *from,*addr; int32_t i,n; int64_t amount; |
|||
/*"params" : {
|
|||
"fromaddress" : "RDhEGYScNQYetCyG75Kf8Fg61UWPdwc1C5", |
|||
"amounts" : [ |
|||
{ |
|||
"address" : "zc9s3UdkDFTnnwHrMCr1vYy2WmkjhmTxXNiqC42s7BjeKBVUwk766TTSsrRPKfnX31Bbu8wbrTqnjDqskYGwx48FZMPHvft", |
|||
"amount" : 3.00000000 |
|||
} |
|||
], |
|||
"minconf" : 1, |
|||
"fee" : 0.00010000 |
|||
}*/ |
|||
if ( (params= jobj(item,"params")) != 0 ) |
|||
{ |
|||
//printf("params.(%s)\n",jprint(params,0));
|
|||
if ( (from= jstr(params,"fromaddress")) != 0 ) |
|||
{ |
|||
safecopy(ptr->src,from,sizeof(ptr->src)); |
|||
} |
|||
if ( (amounts= jarray(&n,params,"amounts")) != 0 ) |
|||
{ |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
dest = jitem(amounts,i); |
|||
//printf("%s ",jprint(dest,0));
|
|||
if ( (addr= jstr(dest,"address")) != 0 && (amount= jdouble(dest,"amount")*SATOSHIDEN) > 0 ) |
|||
{ |
|||
if ( strcmp(addr,JUMBLR_ADDR) == 0 ) |
|||
ptr->fee = amount; |
|||
else |
|||
{ |
|||
ptr->amount = amount; |
|||
safecopy(ptr->dest,addr,sizeof(ptr->dest)); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
ptr->txfee = jdouble(params,"fee") * SATOSHIDEN; |
|||
} |
|||
return(1); |
|||
} |
|||
|
|||
void jumblr_opidupdate(struct supernet_info *myinfo,struct iguana_info *coin,struct jumblr_item *ptr) |
|||
{ |
|||
char *retstr,*status,KMDjumblr[64],KMDdeposit[64],BTCaddr[64]; cJSON *retjson,*item; |
|||
if ( ptr->status == 0 ) |
|||
{ |
|||
if ( (retstr= jumblr_zgetoperationstatus(myinfo,coin,ptr->opid)) != 0 ) |
|||
{ |
|||
if ( (retjson= cJSON_Parse(retstr)) != 0 ) |
|||
{ |
|||
if ( cJSON_GetArraySize(retjson) == 1 ) |
|||
{ |
|||
item = jitem(retjson,0); |
|||
//printf("%s\n",jprint(item,0));
|
|||
if ( (status= jstr(item,"status")) != 0 ) |
|||
{ |
|||
if ( strcmp(status,"success") == 0 ) |
|||
{ |
|||
ptr->status = jumblr_itemset(ptr,item,status); |
|||
jumblr_privkey(myinfo,BTCaddr,0,KMDdeposit,JUMBLR_DEPOSITPREFIX); |
|||
jumblr_privkey(myinfo,BTCaddr,0,KMDjumblr,""); |
|||
if ( (jumblr_addresstype(myinfo,coin,ptr->src) == 't' && jumblr_addresstype(myinfo,coin,ptr->src) == 'z' && strcmp(ptr->src,KMDdeposit) != 0) || (jumblr_addresstype(myinfo,coin,ptr->src) == 'z' && jumblr_addresstype(myinfo,coin,ptr->src) == 't' && strcmp(ptr->dest,KMDjumblr) != 0) ) |
|||
{ |
|||
printf("a non-jumblr t->z pruned\n"); |
|||
free(jumblr_zgetoperationresult(myinfo,coin,ptr->opid)); |
|||
ptr->status = -1; |
|||
} |
|||
|
|||
} |
|||
else if ( strcmp(status,"failed") == 0 ) |
|||
{ |
|||
printf("%s failed\n",ptr->opid); |
|||
free(jumblr_zgetoperationresult(myinfo,coin,ptr->opid)); |
|||
ptr->status = -1; |
|||
} |
|||
} |
|||
} |
|||
free_json(retjson); |
|||
} |
|||
free(retstr); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void jumblr_prune(struct supernet_info *myinfo,struct iguana_info *coin,struct jumblr_item *ptr) |
|||
{ |
|||
struct jumblr_item *tmp; char oldsrc[128]; int32_t flag = 1; |
|||
printf("PRUNE %s\n",ptr->opid); |
|||
strcpy(oldsrc,ptr->src); |
|||
free(jumblr_zgetoperationresult(myinfo,coin,ptr->opid)); |
|||
while ( flag != 0 ) |
|||
{ |
|||
flag = 0; |
|||
HASH_ITER(hh,myinfo->jumblrs,ptr,tmp) |
|||
{ |
|||
if ( strcmp(oldsrc,ptr->dest) == 0 ) |
|||
{ |
|||
printf("prune %s (%s -> %s) matched oldsrc\n",ptr->opid,ptr->src,ptr->dest); |
|||
free(jumblr_zgetoperationresult(myinfo,coin,ptr->opid)); |
|||
strcpy(oldsrc,ptr->src); |
|||
flag = 1; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
void jumblr_opidsupdate(struct supernet_info *myinfo,struct iguana_info *coin) |
|||
{ |
|||
char *retstr; cJSON *array; int32_t i,n; struct jumblr_item *ptr; |
|||
if ( (retstr= jumblr_zlistoperationids(myinfo,coin)) != 0 ) |
|||
{ |
|||
if ( (array= cJSON_Parse(retstr)) != 0 ) |
|||
{ |
|||
if ( (n= cJSON_GetArraySize(array)) > 0 ) |
|||
{ |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
if ( (ptr= jumblr_opidadd(myinfo,coin,jstri(array,i))) != 0 ) |
|||
{ |
|||
if ( ptr->status == 0 ) |
|||
jumblr_opidupdate(myinfo,coin,ptr); |
|||
//printf("%d: %s -> %s %.8f\n",ptr->status,ptr->src,ptr->dest,dstr(ptr->amount));
|
|||
if ( jumblr_addresstype(myinfo,coin,ptr->src) == 'z' && jumblr_addresstype(myinfo,coin,ptr->dest) == 't' ) |
|||
jumblr_prune(myinfo,coin,ptr); |
|||
} |
|||
} |
|||
} |
|||
free_json(array); |
|||
} |
|||
free(retstr); |
|||
} |
|||
} |
|||
|
|||
int64_t jumblr_DEXsplit(struct supernet_info *myinfo,struct iguana_info *coin,bits256 *splittxidp,char *coinaddr,bits256 txid,int32_t vout,int64_t remaining,double bigprice,double middleprice,double smallprice,double fees[4],cJSON *privkeys,double esttxfee) |
|||
{ |
|||
int64_t values[4],outputs[64],value,total,estfee; int32_t i,n,success=0,completed,sendflag,numoutputs = 0; char *retstr; cJSON *retjson,*utxo,*item; |
|||
total = 0; |
|||
estfee = SATOSHIDEN * esttxfee; |
|||
memset(values,0,sizeof(values)); |
|||
memset(outputs,0,sizeof(outputs)); |
|||
if ( bigprice > SMALLVAL ) |
|||
values[0] = SATOSHIDEN * bigprice; |
|||
if ( middleprice > SMALLVAL ) |
|||
values[1] = SATOSHIDEN * middleprice; |
|||
if ( smallprice > SMALLVAL ) |
|||
values[2] = SATOSHIDEN * smallprice; |
|||
for (i=0; i<4; i++) |
|||
{ |
|||
if ( fees[i] > SMALLVAL ) |
|||
values[3+i] = SATOSHIDEN * fees[i]; |
|||
} |
|||
for (i=0; i<7; i++) |
|||
{ |
|||
if ( (value= values[i]) != 0 ) |
|||
{ |
|||
n = 0; |
|||
while ( n < 10 && remaining > value && numoutputs < sizeof(outputs)/sizeof(*outputs) ) |
|||
{ |
|||
outputs[numoutputs++] = value; |
|||
remaining -= value; |
|||
total += value; |
|||
printf("%.8f ",dstr(value)); |
|||
n++; |
|||
} |
|||
} |
|||
} |
|||
char str[65]; printf("numoutputs.%d total %.8f %s/v%d\n",numoutputs,dstr(total),bits256_str(str,txid),vout); |
|||
if ( numoutputs > 1 ) // no point to make just one
|
|||
{ |
|||
if ( (retstr= _dex_gettxout(myinfo,coin->symbol,txid,vout)) != 0 ) |
|||
{ |
|||
item = cJSON_Parse(retstr); |
|||
jaddbits256(item,"txid",txid); |
|||
jaddnum(item,"vout",vout); |
|||
free(retstr); |
|||
if ( item != 0 ) |
|||
{ |
|||
utxo = cJSON_CreateArray(); |
|||
jaddi(utxo,item); |
|||
sendflag = 0; |
|||
///printf("jitem.(%s)\n",jprint(utxo,0));
|
|||
if ( (retstr= iguana_utxorawtx(myinfo,coin,0,coinaddr,coinaddr,outputs,numoutputs,0,&completed,sendflag,utxo,privkeys)) != 0 ) |
|||
{ |
|||
if ( completed != 0 ) |
|||
{ |
|||
if ( (retjson= cJSON_Parse(retstr)) != 0 ) |
|||
{ |
|||
if ( jobj(retjson,"error") == 0 && jobj(retjson,"sent") != 0 ) |
|||
{ |
|||
*splittxidp = jbits256(retjson,"sent"); |
|||
success = 1; |
|||
printf("DEXsplit success %.8f\n",dstr(total)); |
|||
} |
|||
free_json(retjson); |
|||
} |
|||
} |
|||
free(retstr); |
|||
} |
|||
free_json(utxo); |
|||
} |
|||
} |
|||
} |
|||
return(success * total); |
|||
} |
|||
|
|||
double jumblr_DEXutxosize(double *targetvolBp,double *targetvolMp,double *targetvolSp,int32_t isbob,double kmdprice) |
|||
{ |
|||
double fee,depositfactor = (isbob == 0) ? 1. : 1.2; |
|||
fee = JUMBLR_INCR * JUMBLR_FEE; |
|||
*targetvolBp = depositfactor * kmdprice * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE); |
|||
*targetvolMp = depositfactor * kmdprice * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); |
|||
*targetvolSp = depositfactor * kmdprice * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE); |
|||
return(depositfactor); |
|||
} |
|||
|
|||
int32_t jumblr_DEXutxoind(int32_t *shouldsplitp,double targetvolB,double targetvolM,double targetvolS,double amount,double margin,double dexfeeratio,double esttxfee) |
|||
{ |
|||
*shouldsplitp = 0; |
|||
if ( amount >= targetvolB ) |
|||
{ |
|||
if ( amount > margin * (targetvolB + targetvolS) ) |
|||
*shouldsplitp = 1; |
|||
return(0); |
|||
} |
|||
else |
|||
{ |
|||
if ( amount >= targetvolM ) |
|||
{ |
|||
if ( amount > margin * (targetvolM + targetvolS) ) |
|||
*shouldsplitp = 1; |
|||
return(1); |
|||
} |
|||
else |
|||
{ |
|||
if ( amount >= targetvolS ) |
|||
{ |
|||
if ( amount > margin * targetvolS ) |
|||
*shouldsplitp = 1; |
|||
return(2); |
|||
} |
|||
else if ( amount >= targetvolB/dexfeeratio ) |
|||
{ |
|||
if ( amount > margin * targetvolB/dexfeeratio ) |
|||
*shouldsplitp = 1; |
|||
return(3); |
|||
} |
|||
else if ( amount >= targetvolM/dexfeeratio ) |
|||
{ |
|||
if ( amount > margin * targetvolM/dexfeeratio ) |
|||
*shouldsplitp = 1; |
|||
return(4); |
|||
} |
|||
else if ( amount >= targetvolS/dexfeeratio ) |
|||
{ |
|||
if ( amount > margin * targetvolS/dexfeeratio ) |
|||
*shouldsplitp = 1; |
|||
return(5); |
|||
} |
|||
else if ( amount >= esttxfee ) |
|||
{ |
|||
if ( amount > esttxfee*4 ) |
|||
*shouldsplitp = 1; |
|||
return(6); |
|||
} |
|||
else return(-1); |
|||
} |
|||
} |
|||
} |
|||
|
|||
int32_t jumblr_DEXutxoupdate(struct supernet_info *myinfo,struct iguana_info *coin,int32_t *shouldsplitp,bits256 *splittxidp,char *coinaddr,bits256 privkey,bits256 txid,int32_t vout,uint64_t value,int32_t isbob,double kmdprice,double estfee) |
|||
{ |
|||
double fees[4],targetvolB,amount,targetvolM,targetvolS,depositfactor,dexfeeratio,margin; int32_t ind = -1,i; cJSON *privkeys; char wifstr[128]; |
|||
*shouldsplitp = 0; |
|||
margin = 1.1; |
|||
depositfactor = (isbob == 0) ? 1. : 1.2; |
|||
dexfeeratio = 500.; |
|||
amount = dstr(value); |
|||
memset(splittxidp,0,sizeof(*splittxidp)); |
|||
depositfactor = jumblr_DEXutxosize(&targetvolB,&targetvolM,&targetvolS,isbob,kmdprice); |
|||
printf("depositfactor %.8f targetvols %.8f %.8f %.8f\n",depositfactor,targetvolB,targetvolM,targetvolS); |
|||
fees[0] = (margin * targetvolB) / dexfeeratio; |
|||
fees[1] = (margin * targetvolM) / dexfeeratio; |
|||
fees[2] = (margin * targetvolS) / dexfeeratio; |
|||
fees[3] = (strcmp("BTC",coin->symbol) == 0) ? 50000 : 10000; |
|||
for (i=0; i<4; i++) |
|||
if ( fees[i] < 10000 ) |
|||
fees[i] = 10000; |
|||
if ( (ind= jumblr_DEXutxoind(shouldsplitp,targetvolB,targetvolM,targetvolS,amount,margin,dexfeeratio,fees[3])) >= 0 ) |
|||
{ |
|||
printf("shouldsplit.%d ind.%d\n",*shouldsplitp,ind); |
|||
if ( *shouldsplitp != 0 ) |
|||
{ |
|||
privkeys = cJSON_CreateArray(); |
|||
bitcoin_priv2wif(wifstr,privkey,coin->chain->wiftype); |
|||
jaddistr(privkeys,wifstr); |
|||
if ( jumblr_DEXsplit(myinfo,coin,splittxidp,coinaddr,txid,vout,value,margin * targetvolB,margin * targetvolM,margin * targetvolS,fees,privkeys,estfee) > 0 ) |
|||
ind = -1; |
|||
else *shouldsplitp = 0; |
|||
free_json(privkeys); |
|||
} |
|||
} // else printf("negative ind\n");
|
|||
return(ind); |
|||
} |
|||
|
|||
/*struct DEXcoin_info
|
|||
{ |
|||
bits256 deposit_privkey,jumblr_privkey; |
|||
struct iguana_info *coin; |
|||
cJSON *utxos,*spentutxos,*bigutxos,*normalutxos,*smallutxos,*feeutxos,*otherutxos; |
|||
double btcprice,USD_average,DEXpending,maxbid,minask,avail,KMDavail; |
|||
uint32_t lasttime; |
|||
char CMCname[32],symbol[16],depositaddr[64],KMDdepositaddr[64],KMDjumblraddr[64],jumblraddr[64]; |
|||
};*/ |
|||
|
|||
int32_t jumblr_utxotxidpending(struct supernet_info *myinfo,bits256 *splittxidp,int32_t *indp,struct iguana_info *coin,bits256 txid,int32_t vout) |
|||
{ |
|||
int32_t i; |
|||
memset(splittxidp,0,sizeof(*splittxidp)); |
|||
for (i=0; i<coin->DEXinfo.numpending; i++) |
|||
{ |
|||
if ( coin->DEXinfo.pending[i].vout == vout && bits256_cmp(coin->DEXinfo.pending[i].txid,txid) == 0 ) |
|||
{ |
|||
*indp = coin->DEXinfo.pending[i].ind; |
|||
*splittxidp = coin->DEXinfo.pending[i].splittxid; |
|||
// printf("jumblr_utxotxidpending found txid in slot.%d\n",i);
|
|||
return(i); |
|||
} |
|||
} |
|||
// printf("jumblr_utxotxidpending cant find txid\n");
|
|||
return(-1); |
|||
} |
|||
|
|||
void jumblr_utxotxidpendingadd(struct supernet_info *myinfo,char *dest,struct iguana_info *coin,bits256 txid,int32_t vout,uint64_t value,bits256 splittxid,int32_t ind,double price,double estfee,int32_t shouldsplit) |
|||
{ |
|||
struct jumblr_pending pend; cJSON *vals,*retjson; bits256 hash; char *retstr; |
|||
memset(&pend,0,sizeof(pend)); |
|||
pend.splittxid = splittxid; |
|||
pend.txid = txid; |
|||
pend.vout = vout; |
|||
pend.ind = ind; |
|||
if ( 0 && myinfo->IAMLP == 0 && shouldsplit == 0 && ind < 3 ) |
|||
{ |
|||
static uint32_t num; |
|||
if ( num == 0 && price > SMALLVAL ) |
|||
{ |
|||
num++; |
|||
vals = cJSON_CreateObject(); |
|||
jaddstr(vals,"source",coin->symbol); |
|||
jaddstr(vals,"dest",dest); |
|||
jaddnum(vals,"amount",price * 100);//dstr(value) - estfee);
|
|||
jaddnum(vals,"minprice",price); |
|||
jaddnum(vals,"usejumblr",1); |
|||
memset(hash.bytes,0,sizeof(hash)); |
|||
if ( (retstr= InstantDEX_request(myinfo,coin,0,0,hash,vals,"")) != 0 ) |
|||
{ |
|||
if ( (retjson= cJSON_Parse(retstr)) != 0 ) |
|||
{ |
|||
printf("request.(%s) -> (%s)\n",jprint(vals,0),retstr); |
|||
free_json(retjson); |
|||
} |
|||
free(retstr); |
|||
} |
|||
free_json(vals); |
|||
} |
|||
} |
|||
coin->DEXinfo.pending = realloc(coin->DEXinfo.pending,sizeof(*coin->DEXinfo.pending) * (1 + coin->DEXinfo.numpending)); |
|||
coin->DEXinfo.pending[coin->DEXinfo.numpending++] = pend; |
|||
} |
|||
|
|||
void jumblr_utxoupdate(struct supernet_info *myinfo,char *dest,struct iguana_info *coin,double price,char *coinaddr,bits256 privkey,double estfee) |
|||
{ |
|||
char *retstr; cJSON *array,*item; int32_t shouldsplit,i,n,vout,ind; bits256 txid,splittxid; uint64_t value; |
|||
if ( (retstr= jumblr_listunspent(myinfo,coin,coinaddr)) != 0 ) |
|||
{ |
|||
//printf("%s.(%s)\n",coin->symbol,retstr);
|
|||
if ( (array= cJSON_Parse(retstr)) != 0 ) |
|||
{ |
|||
if ( (n= cJSON_GetArraySize(array)) > 0 ) |
|||
{ |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
if ( (item= jitem(array,i)) == 0 ) |
|||
continue; |
|||
txid = jbits256(item,"txid"); |
|||
vout = jint(item,"vout"); |
|||
value = SATOSHIDEN * jdouble(item,"amount"); |
|||
//printf("price %.8f %llx/v%d %.8f %d of %d\n",price,(long long)txid.txid,vout,dstr(value),i,n);
|
|||
if ( jumblr_utxotxidpending(myinfo,&splittxid,&ind,coin,txid,vout) < 0 ) |
|||
{ |
|||
ind = jumblr_DEXutxoupdate(myinfo,coin,&shouldsplit,&splittxid,coinaddr,privkey,txid,vout,value,myinfo->IAMLP,price,estfee); |
|||
jumblr_utxotxidpendingadd(myinfo,dest,coin,txid,vout,value,splittxid,ind,price,estfee,shouldsplit); |
|||
} |
|||
else |
|||
{ |
|||
// update status of utxo
|
|||
} |
|||
} |
|||
} |
|||
free_json(array); |
|||
} |
|||
free(retstr); |
|||
} |
|||
} |
|||
|
|||
void jumblr_iteration(struct supernet_info *myinfo,struct iguana_info *coin,int32_t selector,int32_t modval) |
|||
{ |
|||
//static uint32_t lasttime;
|
|||
char BTCaddr[64],KMDaddr[64],*zaddr,*retstr; int32_t iter,counter,chosen_one,n; bits256 privkey; uint64_t amount=0,total=0; double fee; struct jumblr_item *ptr,*tmp; uint8_t r,s; |
|||
if ( myinfo->IAMNOTARY != 0 ) |
|||
return; |
|||
fee = JUMBLR_INCR * JUMBLR_FEE; |
|||
OS_randombytes(&r,sizeof(r)); |
|||
//r = 0;
|
|||
// randomize size chosen and order of chunks
|
|||
if ( strcmp(coin->symbol,"KMD") == 0 && coin->FULLNODE < 0 ) |
|||
{ |
|||
s = (selector + (r>>1)) % 3; |
|||
//printf("JUMBLR selector.%d modval.%d r.%d\n",selector,modval,r&7);
|
|||
switch ( s ) |
|||
{ |
|||
case 0: // public -> z, need to importprivkey
|
|||
jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,JUMBLR_DEPOSITPREFIX); |
|||
if ( (total= jumblr_balance(myinfo,coin,KMDaddr)) >= (JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE))*SATOSHIDEN ) |
|||
{ |
|||
if ( (r & 1) == 0 ) |
|||
{ |
|||
if ( (zaddr= jumblr_zgetnewaddress(myinfo,coin)) != 0 ) |
|||
{ |
|||
amount = 0; |
|||
if ( total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE) ) |
|||
amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*100 + 3*JUMBLR_TXFEE); |
|||
if ( (r & 2) != 0 && total >= SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE) ) |
|||
amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee)*10 + 3*JUMBLR_TXFEE); |
|||
if ( (r & 4) != 0 ) |
|||
amount = SATOSHIDEN * ((JUMBLR_INCR + 3*fee) + 3*JUMBLR_TXFEE); |
|||
if ( amount > 0 && (retstr= jumblr_sendt_to_z(myinfo,coin,KMDaddr,zaddr,dstr(amount))) != 0 ) |
|||
{ |
|||
printf("sendt_to_z.(%s)\n",retstr); |
|||
free(retstr); |
|||
} |
|||
free(zaddr); |
|||
} else printf("no zaddr from jumblr_zgetnewaddress\n"); |
|||
} |
|||
} else printf("%s total %.8f vs %.8f\n",KMDaddr,dstr(total),(JUMBLR_INCR + 3*(fee+JUMBLR_TXFEE))); |
|||
break; |
|||
case 1: // z -> z
|
|||
jumblr_opidsupdate(myinfo,coin); |
|||
chosen_one = -1; |
|||
for (iter=counter=0; iter<2; iter++) |
|||
{ |
|||
counter = n = 0; |
|||
HASH_ITER(hh,myinfo->jumblrs,ptr,tmp) |
|||
{ |
|||
if ( jumblr_addresstype(myinfo,coin,ptr->src) == 't' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' ) |
|||
{ |
|||
if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) |
|||
{ |
|||
if ( iter == 1 && counter == chosen_one ) |
|||
{ |
|||
if ( (zaddr= jumblr_zgetnewaddress(myinfo,coin)) != 0 ) |
|||
{ |
|||
if ( (retstr= jumblr_sendz_to_z(myinfo,coin,ptr->dest,zaddr,dstr(total))) != 0 ) |
|||
{ |
|||
printf("n.%d counter.%d chosen_one.%d sendz_to_z.(%s)\n",n,counter,chosen_one,retstr); |
|||
free(retstr); |
|||
} |
|||
ptr->spent = (uint32_t)time(NULL); |
|||
free(zaddr); |
|||
break; |
|||
} |
|||
} |
|||
counter++; |
|||
} |
|||
} |
|||
n++; |
|||
} |
|||
if ( counter == 0 ) |
|||
break; |
|||
if ( iter == 0 ) |
|||
{ |
|||
OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); |
|||
if ( chosen_one < 0 ) |
|||
chosen_one = -chosen_one; |
|||
chosen_one %= counter; |
|||
printf("jumblr z->z chosen_one.%d of %d, from %d\n",chosen_one,counter,n); |
|||
} |
|||
} |
|||
break; |
|||
case 2: // z -> public
|
|||
if ( myinfo->runsilent == 0 ) |
|||
{ |
|||
jumblr_opidsupdate(myinfo,coin); |
|||
chosen_one = -1; |
|||
for (iter=0; iter<2; iter++) |
|||
{ |
|||
counter = n = 0; |
|||
HASH_ITER(hh,myinfo->jumblrs,ptr,tmp) |
|||
{ |
|||
if ( jumblr_addresstype(myinfo,coin,ptr->src) == 'z' && jumblr_addresstype(myinfo,coin,ptr->dest) == 'z' ) |
|||
{ |
|||
if ( (r & 1) == 0 && ptr->spent == 0 && (total= jumblr_balance(myinfo,coin,ptr->dest)) >= (fee + JUMBLR_FEE)*SATOSHIDEN ) |
|||
{ |
|||
if ( iter == 1 && n == chosen_one ) |
|||
{ |
|||
privkey = jumblr_privkey(myinfo,BTCaddr,0,KMDaddr,""); |
|||
if ( (retstr= jumblr_sendz_to_t(myinfo,coin,ptr->dest,KMDaddr,dstr(total))) != 0 ) |
|||
{ |
|||
printf("sendz_to_t.(%s)\n",retstr); |
|||
free(retstr); |
|||
} |
|||
ptr->spent = (uint32_t)time(NULL); |
|||
break; |
|||
} |
|||
counter++; |
|||
} |
|||
} |
|||
n++; |
|||
} |
|||
if ( counter == 0 ) |
|||
break; |
|||
if ( iter == 0 ) |
|||
{ |
|||
OS_randombytes((uint8_t *)&chosen_one,sizeof(chosen_one)); |
|||
if ( chosen_one < 0 ) |
|||
chosen_one = -chosen_one; |
|||
chosen_one %= counter; |
|||
printf("jumblr z->t chosen_one.%d of %d, from %d\n",chosen_one,counter,n); |
|||
} |
|||
} |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
@ -0,0 +1,685 @@ |
|||
/******************************************************************************
|
|||
* Copyright © 2014-2017 The SuperNET Developers. * |
|||
* * |
|||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * |
|||
* the top-level directory of this distribution for the individual copyright * |
|||
* holder information and the developer policies on copyright and licensing. * |
|||
* * |
|||
* Unless otherwise agreed in a custom licensing agreement, no part of the * |
|||
* SuperNET software, including this file may be copied, modified, propagated * |
|||
* or distributed except according to the terms contained in the LICENSE file * |
|||
* * |
|||
* Removal or modification of this copyright notice is prohibited. * |
|||
* * |
|||
******************************************************************************/ |
|||
|
|||
// included from basilisk.c
|
|||
|
|||
// deposit address <coin> -> corresponding KMD address, if KMD deposit starts JUMBLR
|
|||
// jumblr address <coin> is the destination of JUMBLR and JUMBLR BTC (would need tracking to map back to non-BTC)
|
|||
// <symbol> address <coin> is DEX'ed for <SYMBOL>
|
|||
|
|||
// return value convention: -1 error, 0 partial match, >= 1 exact match
|
|||
|
|||
int32_t smartaddress_type(char *typestr) |
|||
{ |
|||
char upper[64]; |
|||
if ( strcmp(typestr,"deposit") != 0 && strcmp(typestr,"jumblr") != 0 && strcmp(typestr,"dividend") != 0 && strcmp(typestr,"pangea") != 0 ) |
|||
{ |
|||
upper[sizeof(upper)-1] = 0; |
|||
strncpy(upper,typestr,sizeof(upper)-1); |
|||
touppercase(upper); |
|||
if ( iguana_coinfind(upper) != 0 ) |
|||
return(0); |
|||
else return(-1); |
|||
} |
|||
return(1); |
|||
} |
|||
|
|||
bits256 jumblr_privkey(struct supernet_info *myinfo,char *coinaddr,uint8_t pubtype,char *KMDaddr,char *prefix) |
|||
{ |
|||
bits256 privkey,pubkey; uint8_t pubkey33[33]; char passphrase[sizeof(myinfo->jumblr_passphrase) + 64]; |
|||
sprintf(passphrase,"%s%s",prefix,myinfo->jumblr_passphrase); |
|||
if ( myinfo->jumblr_passphrase[0] == 0 ) |
|||
strcpy(myinfo->jumblr_passphrase,"password"); |
|||
conv_NXTpassword(privkey.bytes,pubkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase)); |
|||
bitcoin_pubkey33(myinfo->ctx,pubkey33,privkey); |
|||
bitcoin_address(coinaddr,pubtype,pubkey33,33); |
|||
bitcoin_address(KMDaddr,60,pubkey33,33); |
|||
//printf("(%s) -> (%s %s)\n",passphrase,coinaddr,KMDaddr);
|
|||
return(privkey); |
|||
} |
|||
|
|||
cJSON *smartaddress_extrajson(struct smartaddress *ap) |
|||
{ |
|||
cJSON *retjson = cJSON_CreateObject(); |
|||
if ( strcmp(ap->typestr,"dividend") == 0 ) |
|||
{ |
|||
|
|||
} |
|||
return(retjson); |
|||
} |
|||
|
|||
cJSON *smartaddress_json(struct smartaddress *ap) |
|||
{ |
|||
char coinaddr[64],symbol[64]; uint8_t desttype,tmp,rmd160[20]; int32_t j,n; struct iguana_info *coin,*dest; cJSON *array,*item,*retjson; double amount; |
|||
retjson = cJSON_CreateObject(); |
|||
jaddstr(retjson,"type",ap->typestr); |
|||
strcpy(symbol,ap->typestr), touppercase(symbol); |
|||
if ( (dest= iguana_coinfind(symbol)) != 0 ) |
|||
desttype = dest->chain->pubtype; |
|||
else desttype = 60; |
|||
if ( (n= ap->numsymbols) > 0 ) |
|||
{ |
|||
array = cJSON_CreateArray(); |
|||
for (j=0; j<n; j++) |
|||
{ |
|||
if ( (coin= iguana_coinfind(ap->symbols[j].symbol)) != 0 ) |
|||
{ |
|||
bitcoin_address(coinaddr,coin->chain->pubtype,ap->pubkey33,33); |
|||
item = cJSON_CreateObject(); |
|||
jaddstr(item,"coin",coin->symbol); |
|||
jaddstr(item,"address",coinaddr); |
|||
if ( (amount= ap->symbols[j].srcavail) != 0 ) |
|||
jaddnum(item,"sourceamount",amount); |
|||
if ( dest != 0 ) |
|||
{ |
|||
bitcoin_addr2rmd160(&tmp,rmd160,coinaddr); |
|||
bitcoin_address(coinaddr,desttype,rmd160,20); |
|||
jaddstr(item,"dest",coinaddr); |
|||
if ( (amount= ap->symbols[j].destamount) != 0 ) |
|||
jaddnum(item,"destamount",amount); |
|||
if ( coin->DEXinfo.depositaddr[0] != 0 ) |
|||
{ |
|||
jaddstr(item,"jumblr_deposit",coin->DEXinfo.depositaddr); |
|||
jaddnum(item,"deposit_avail",coin->DEXinfo.avail); |
|||
} |
|||
if ( coin->DEXinfo.jumblraddr[0] != 0 ) |
|||
{ |
|||
jaddstr(item,"jumblr",coin->DEXinfo.jumblraddr); |
|||
jaddnum(item,"jumblr_avail",coin->DEXinfo.jumblravail); |
|||
} |
|||
if ( ap->symbols[j].maxbid != 0. ) |
|||
jaddnum(item,"maxbid",ap->symbols[j].maxbid); |
|||
if ( ap->symbols[j].minask != 0. ) |
|||
jaddnum(item,"minask",ap->symbols[j].minask); |
|||
} |
|||
jadd(item,"extra",smartaddress_extrajson(ap)); |
|||
jaddi(array,item); |
|||
} |
|||
} |
|||
jadd(retjson,"coins",array); |
|||
} |
|||
return(retjson); |
|||
} |
|||
|
|||
void smartaddress_symboladd(struct smartaddress *ap,char *symbol,double maxbid,double minask) |
|||
{ |
|||
char tmp[64]; struct smartaddress_symbol *sp; |
|||
strcpy(tmp,ap->typestr), touppercase(tmp); |
|||
if ( strcmp(tmp,symbol) != 0 ) |
|||
{ |
|||
ap->symbols = realloc(ap->symbols,(ap->numsymbols+1) * sizeof(*ap->symbols)); |
|||
sp = &ap->symbols[ap->numsymbols++]; |
|||
memset(sp,0,sizeof(*sp)); |
|||
safecopy(sp->symbol,symbol,sizeof(sp->symbol)); |
|||
sp->maxbid = maxbid; |
|||
sp->minask = minask; |
|||
printf("symboladd.%d (%s) <- (%s %f %f)\n",ap->numsymbols,ap->typestr,symbol,maxbid,minask); |
|||
} |
|||
} |
|||
|
|||
struct smartaddress *smartaddressptr(struct smartaddress_symbol **ptrp,struct supernet_info *myinfo,char *_type,char *_symbol) |
|||
{ |
|||
char type[64],symbol[64]; int32_t i,j,n; struct smartaddress *ap; |
|||
if ( ptrp != 0 ) |
|||
*ptrp = 0; |
|||
strcpy(type,_type), tolowercase(type); |
|||
strcpy(symbol,_symbol), touppercase(symbol); |
|||
for (i=0; i<myinfo->numsmartaddrs; i++) |
|||
{ |
|||
ap = &myinfo->smartaddrs[i]; |
|||
if ( strcmp(type,ap->typestr) == 0 ) |
|||
{ |
|||
n = ap->numsymbols; |
|||
for (j=0; j<n; j++) |
|||
{ |
|||
if ( strcmp(ap->symbols[j].symbol,symbol) == 0 ) |
|||
{ |
|||
if ( ptrp != 0 ) |
|||
*ptrp = &ap->symbols[j]; |
|||
return(ap); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
return(0); |
|||
} |
|||
|
|||
void smartaddress_minmaxupdate(struct supernet_info *myinfo,char *_type,char *_symbol,double maxbid,double minask) |
|||
{ |
|||
struct smartaddress *ap; struct smartaddress_symbol *sp; |
|||
if ( (ap= smartaddressptr(&sp,myinfo,_type,_symbol)) != 0 && sp != 0 ) |
|||
{ |
|||
dxblend(&sp->maxbid,maxbid,0.5); |
|||
dxblend(&sp->minask,minask,0.5); |
|||
} |
|||
} |
|||
|
|||
void smartaddress_availupdate(struct supernet_info *myinfo,char *_type,char *_symbol,double srcavail,double destamount) |
|||
{ |
|||
struct smartaddress *ap; struct smartaddress_symbol *sp; |
|||
if ( (ap= smartaddressptr(&sp,myinfo,_type,_symbol)) != 0 && sp != 0 ) |
|||
{ |
|||
if ( srcavail > SMALLVAL ) |
|||
sp->srcavail = srcavail; |
|||
if ( destamount > SMALLVAL ) |
|||
sp->destamount = destamount; |
|||
} |
|||
} |
|||
|
|||
int32_t _smartaddress_add(struct supernet_info *myinfo,bits256 privkey,char *type,char *symbol,double maxbid,double minask) |
|||
{ |
|||
char coinaddr[64]; uint8_t addrtype,rmd160[20]; struct smartaddress *ap; int32_t i,j,n; |
|||
if ( myinfo->numsmartaddrs < sizeof(myinfo->smartaddrs)/sizeof(*myinfo->smartaddrs) ) |
|||
{ |
|||
for (i=0; i<myinfo->numsmartaddrs; i++) |
|||
{ |
|||
ap = &myinfo->smartaddrs[i]; |
|||
if ( strcmp(type,ap->typestr) == 0 && bits256_cmp(ap->privkey,privkey) == 0 ) |
|||
{ |
|||
n = ap->numsymbols; |
|||
for (j=0; j<n; j++) |
|||
{ |
|||
if ( strcmp(ap->symbols[j].symbol,symbol) == 0 ) |
|||
{ |
|||
ap->symbols[j].maxbid = maxbid; |
|||
ap->symbols[j].minask = minask; |
|||
if ( maxbid > SMALLVAL && minask > SMALLVAL && smartaddress_type(type) == 0 ) |
|||
smartaddress_minmaxupdate(myinfo,symbol,type,1./minask,1./maxbid); |
|||
return(0); |
|||
} |
|||
} |
|||
smartaddress_symboladd(ap,symbol,maxbid,minask); |
|||
return(i+1); |
|||
} |
|||
} |
|||
ap = &myinfo->smartaddrs[myinfo->numsmartaddrs]; |
|||
if ( smartaddress_type(symbol) < 0 ) |
|||
return(-1); |
|||
strcpy(ap->typestr,type); |
|||
smartaddress_symboladd(ap,"KMD",0.,0.); |
|||
smartaddress_symboladd(ap,"BTC",0.,0.); |
|||
ap->privkey = privkey; |
|||
bitcoin_pubkey33(myinfo->ctx,ap->pubkey33,privkey); |
|||
calc_rmd160_sha256(ap->rmd160,ap->pubkey33,33); |
|||
ap->pubkey = curve25519(privkey,curve25519_basepoint9()); |
|||
char str[65]; printf("pubkey.(%s) ",bits256_str(str,ap->pubkey)); |
|||
bitcoin_address(coinaddr,0,ap->pubkey33,33); |
|||
for (i=0; i<20; i++) |
|||
printf("%02x",ap->rmd160[i]); |
|||
bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr); |
|||
printf(", "); |
|||
for (i=0; i<20; i++) |
|||
printf("%02x",rmd160[i]); |
|||
printf (" <- rmd160 for %d %s\n",myinfo->numsmartaddrs,coinaddr); |
|||
return(++myinfo->numsmartaddrs + 1); |
|||
} |
|||
printf("too many smartaddresses %d vs %d\n",myinfo->numsmartaddrs,(int32_t)(sizeof(myinfo->smartaddrs)/sizeof(*myinfo->smartaddrs))); |
|||
return(-1); |
|||
} |
|||
|
|||
int32_t smartaddress_add(struct supernet_info *myinfo,bits256 privkey,char *type,char *symbol,double maxbid,double minask) |
|||
{ |
|||
int32_t retval; |
|||
portable_mutex_lock(&myinfo->smart_mutex); |
|||
retval = _smartaddress_add(myinfo,privkey,type,symbol,maxbid,minask); |
|||
portable_mutex_unlock(&myinfo->smart_mutex); |
|||
return(retval); |
|||
} |
|||
|
|||
int32_t smartaddress_symbolmatch(char *typestr,double *bidaskp,struct smartaddress *ap,char *symbol) |
|||
{ |
|||
int32_t j,n; |
|||
strcpy(typestr,ap->typestr); |
|||
if ( (n= ap->numsymbols) > 0 ) |
|||
{ |
|||
for (j=0; j<n; j++) |
|||
{ |
|||
if ( strcmp(ap->symbols[j].symbol,symbol) == 0 ) |
|||
{ |
|||
bidaskp[0] = ap->symbols[j].maxbid; |
|||
bidaskp[1] = ap->symbols[j].minask; |
|||
return(j); |
|||
} |
|||
} |
|||
} |
|||
return(-1); |
|||
} |
|||
|
|||
int32_t smartaddress(struct supernet_info *myinfo,char *typestr,double *bidaskp,bits256 *privkeyp,char *symbol,char *coinaddr) |
|||
{ |
|||
int32_t i,j,retval = -1; uint8_t addrtype,rmd160[20]; struct smartaddress *ap; |
|||
memset(privkeyp,0,sizeof(*privkeyp)); |
|||
memset(bidaskp,0,sizeof(*bidaskp) * 2); |
|||
bitcoin_addr2rmd160(&addrtype,rmd160,coinaddr); |
|||
portable_mutex_lock(&myinfo->smart_mutex); |
|||
for (i=0; i<myinfo->numsmartaddrs; i++) |
|||
if ( memcmp(myinfo->smartaddrs[i].rmd160,rmd160,20) == 0 ) |
|||
{ |
|||
ap = &myinfo->smartaddrs[i]; |
|||
*privkeyp = ap->privkey; |
|||
if ( (j= smartaddress_symbolmatch(typestr,bidaskp,ap,symbol)) >= 0 ) |
|||
retval = 0; |
|||
else retval = (i+1); |
|||
break; |
|||
} |
|||
portable_mutex_unlock(&myinfo->smart_mutex); |
|||
for (i=0; i<20; i++) |
|||
printf("%02x",rmd160[i]); |
|||
printf(" <- rmd160 smartaddress cant find (%s) of %d\n",coinaddr,myinfo->numsmartaddrs); |
|||
return(retval); |
|||
} |
|||
|
|||
int32_t smartaddress_pubkey(struct supernet_info *myinfo,char *typestr,double *bidaskp,bits256 *privkeyp,char *symbol,bits256 pubkey) |
|||
{ |
|||
int32_t i,j,retval = -1; struct smartaddress *ap; |
|||
memset(privkeyp,0,sizeof(*privkeyp)); |
|||
memset(bidaskp,0,sizeof(*bidaskp) * 2); |
|||
if ( bits256_cmp(myinfo->myaddr.persistent,pubkey) == 0 ) |
|||
{ |
|||
*privkeyp = myinfo->persistent_priv; |
|||
return(myinfo->numsmartaddrs); |
|||
} |
|||
portable_mutex_lock(&myinfo->smart_mutex); |
|||
for (i=0; i<myinfo->numsmartaddrs; i++) |
|||
if ( bits256_cmp(myinfo->smartaddrs[i].pubkey,pubkey) == 0 ) |
|||
{ |
|||
ap = &myinfo->smartaddrs[i]; |
|||
*privkeyp = ap->privkey; |
|||
if ( (j= smartaddress_symbolmatch(typestr,bidaskp,ap,symbol)) >= 0 ) |
|||
retval = 0; |
|||
else retval = (i+1); |
|||
break; |
|||
} |
|||
portable_mutex_unlock(&myinfo->smart_mutex); |
|||
//char str[65]; if ( retval < 0 )
|
|||
// printf("smartaddress_pubkey no match for %s\n",bits256_str(str,pubkey));
|
|||
return(retval); |
|||
} |
|||
|
|||
int32_t smartaddress_pubkey33(struct supernet_info *myinfo,char *typestr,double *bidaskp,bits256 *privkeyp,char *symbol,uint8_t *pubkey33) |
|||
{ |
|||
int32_t i,j,retval = -1; struct smartaddress *ap; |
|||
memset(privkeyp,0,sizeof(*privkeyp)); |
|||
memset(bidaskp,0,sizeof(*bidaskp) * 2); |
|||
portable_mutex_lock(&myinfo->smart_mutex); |
|||
for (i=0; i<myinfo->numsmartaddrs; i++) |
|||
if ( memcmp(myinfo->smartaddrs[i].pubkey33,pubkey33,33) == 0 ) |
|||
{ |
|||
ap = &myinfo->smartaddrs[i]; |
|||
*privkeyp = ap->privkey; |
|||
if ( (j= smartaddress_symbolmatch(typestr,bidaskp,ap,symbol)) >= 0 ) |
|||
retval = 0; |
|||
else retval = (i+1); |
|||
break; |
|||
} |
|||
portable_mutex_unlock(&myinfo->smart_mutex); |
|||
return(retval); |
|||
} |
|||
|
|||
void smartaddress_CMCname(char *CMCname,char *symbol) |
|||
{ |
|||
if ( strcmp(symbol,"KMD") == 0 ) |
|||
strcpy(CMCname,"komodo"); |
|||
else if ( strcmp(symbol,"BTC") == 0 ) |
|||
strcpy(CMCname,"bitcoin"); |
|||
} |
|||
|
|||
void smartaddress_coinupdate(struct supernet_info *myinfo,char *symbol,double BTC2KMD,double KMDavail,double KMD2USD) |
|||
{ |
|||
int32_t r; double avebid,aveask,highbid,lowask,CMC_average,changes[3]; struct iguana_info *coin; struct DEXcoin_info *ptr; |
|||
if ( (coin= iguana_coinfind(symbol)) != 0 ) |
|||
{ |
|||
ptr = &coin->DEXinfo; |
|||
ptr->coin = coin; |
|||
if ( coin->CMCname[0] == 0 ) |
|||
smartaddress_CMCname(coin->CMCname,symbol); |
|||
r = (((symbol[0]^symbol[1]^symbol[2])&0x7f) % 15) - 7; // 53 to 67 seconds
|
|||
if ( time(NULL) > (ptr->lasttime + 60 + r) ) |
|||
{ |
|||
if ( strcmp(symbol,ptr->symbol) != 0 ) |
|||
{ |
|||
safecopy(ptr->symbol,symbol,sizeof(ptr->symbol)); |
|||
safecopy(ptr->CMCname,coin->CMCname,sizeof(ptr->CMCname)); |
|||
} |
|||
ptr->deposit_privkey = jumblr_privkey(myinfo,ptr->depositaddr,coin->chain->pubtype,ptr->KMDdepositaddr,JUMBLR_DEPOSITPREFIX); |
|||
ptr->jumblr_privkey = jumblr_privkey(myinfo,ptr->jumblraddr,coin->chain->pubtype,ptr->KMDjumblraddr,""); |
|||
ptr->avail = dstr(jumblr_balance(myinfo,coin,ptr->depositaddr)); |
|||
ptr->jumblravail = dstr(jumblr_balance(myinfo,ptr->coin,ptr->jumblraddr)); |
|||
if ( strcmp(symbol,"USD") == 0 ) |
|||
{ |
|||
if ( KMD2USD > SMALLVAL ) |
|||
{ |
|||
ptr->kmdprice = 1./ KMD2USD; |
|||
if ( (ptr->BTC2KMD= BTC2KMD) > SMALLVAL ) |
|||
ptr->btcprice = ptr->kmdprice * BTC2KMD; |
|||
} |
|||
printf("USD btcprice %.8f kmdprice %.8f\n",ptr->btcprice,ptr->kmdprice); |
|||
} |
|||
else |
|||
{ |
|||
if ( strcmp(symbol,"BTC") == 0 ) |
|||
ptr->btcprice = 1.; |
|||
else if ( coin->CMCname[0] != 0 && (ptr->btcprice == 0. || (ptr->counter++ % 10) == 0) ) |
|||
ptr->btcprice = get_theoretical(&avebid,&aveask,&highbid,&lowask,&CMC_average,changes,coin->CMCname,symbol,"BTC",&ptr->USD_average); |
|||
if ( strcmp("KMD",symbol) == 0 ) |
|||
ptr->kmdprice = 1.; |
|||
else if ( (ptr->BTC2KMD= BTC2KMD) > SMALLVAL ) |
|||
ptr->kmdprice = ptr->btcprice / BTC2KMD; |
|||
} |
|||
ptr->lasttime = (uint32_t)time(NULL); |
|||
printf("%s avail %.8f KMDavail %.8f btcprice %.8f deposit.(%s %s) -> jumblr.(%s %s)\n",symbol,ptr->avail,KMDavail,ptr->btcprice,ptr->depositaddr,ptr->KMDdepositaddr,ptr->jumblraddr,ptr->KMDjumblraddr); |
|||
} |
|||
} // else printf("skip\n");
|
|||
} |
|||
|
|||
void smartaddress_dex(struct supernet_info *myinfo,char *type,int32_t selector,struct iguana_info *basecoin,char *coinaddr,double maxavail,struct iguana_info *relcoin,double maxbid,double minask,cJSON *extraobj,double maxvol) |
|||
{ |
|||
double minamount,minbtc,price,avail,vol,btc2kmd,basebtc,relbtc,baseusd,relusd; char *retstr; cJSON *vals; bits256 hash; struct smartaddress *ap; |
|||
basebtc = basecoin->DEXinfo.btcprice; |
|||
relbtc = relcoin->DEXinfo.btcprice; |
|||
baseusd = basecoin->DEXinfo.USD_average; |
|||
relusd = relcoin->DEXinfo.USD_average; |
|||
if ( (btc2kmd= basecoin->DEXinfo.BTC2KMD) < SMALLVAL && (btc2kmd= relcoin->DEXinfo.BTC2KMD) < SMALLVAL ) |
|||
return; |
|||
minamount = price = 0.; |
|||
if ( basebtc < SMALLVAL && relbtc < SMALLVAL ) |
|||
return; |
|||
if ( myinfo->DEXratio < .95 || myinfo->DEXratio > 1.01 ) |
|||
myinfo->DEXratio = 0.995; |
|||
if ( basebtc < SMALLVAL || relbtc < SMALLVAL ) |
|||
{ |
|||
if ( (price= maxbid) > SMALLVAL ) |
|||
{ |
|||
if ( basebtc < SMALLVAL ) |
|||
basebtc = price * relbtc, printf("calculated basebtc %.8f from (%.8f * %.8f)\n",basebtc,price,relbtc); |
|||
else if ( relbtc < SMALLVAL ) |
|||
relbtc = basebtc / price, printf("calculated relbtc %.8f from (%.8f / %.8f)\n",relbtc,basebtc,price); // price * relbtc == basebtc
|
|||
} |
|||
} else price = myinfo->DEXratio * (basebtc / relbtc); |
|||
minbtc = btc2kmd * (JUMBLR_INCR + 3*(JUMBLR_INCR * JUMBLR_FEE + JUMBLR_TXFEE)); |
|||
if ( minamount == 0. && basebtc > SMALLVAL ) |
|||
minamount = (minbtc / basebtc); |
|||
printf("DEX %s/%s maxavail %.8f minbtc %.8f btcprice %.8f -> minamount %.8f price %.8f vs maxbid %.8f DEXratio %.5f DEXpending %.8f\n",basecoin->symbol,relcoin->symbol,maxavail,minbtc,basecoin->DEXinfo.btcprice,minamount,price,maxbid,myinfo->DEXratio,basecoin->DEXinfo.DEXpending); |
|||
if ( minamount > SMALLVAL && maxavail > minamount + basecoin->DEXinfo.DEXpending && (maxbid == 0. || price <= maxbid) ) |
|||
{ |
|||
avail = (maxavail - basecoin->DEXinfo.DEXpending); |
|||
/*if ( avail >= (100. * minamount) )
|
|||
vol = (100. * minamount); |
|||
else if ( avail >= (10. * minamount) ) |
|||
vol = (10. * minamount); |
|||
else*/ if ( avail >= minamount ) |
|||
vol = minamount; |
|||
else vol = 0.; |
|||
if ( vol > 0. ) |
|||
{ |
|||
vals = cJSON_CreateObject(); |
|||
jaddstr(vals,"source",basecoin->symbol); |
|||
jaddstr(vals,"dest",relcoin->symbol); |
|||
jaddnum(vals,"amount",vol); |
|||
jaddnum(vals,"minprice",price); |
|||
if ( (ap= smartaddressptr(0,myinfo,type,basecoin->symbol)) != 0 ) |
|||
jaddbits256(vals,"srchash",ap->pubkey); |
|||
if ( selector != 0 ) |
|||
{ |
|||
jaddnum(vals,"usejumblr",selector); |
|||
jaddnum(vals,"DEXselector",selector); |
|||
} |
|||
memset(hash.bytes,0,sizeof(hash)); |
|||
basecoin->DEXinfo.DEXpending += vol; |
|||
if ( (retstr= InstantDEX_request(myinfo,basecoin,0,0,hash,vals,"")) != 0 ) |
|||
{ |
|||
printf("request.(%s) -> (%s)\n",jprint(vals,0),retstr); |
|||
free(retstr); |
|||
} |
|||
free_json(vals); |
|||
} else printf("avail %.8f < minamount %.8f\n",avail,minamount); |
|||
} //else printf("failed if check %d %d %d %d\n",minamount > SMALLVAL,maxavail > minamount + basecoin->DEXinfo.DEXpending,maxbid == 0,price <= maxbid);
|
|||
/*
|
|||
minbtc = (basecoin->DEXinfo.btcprice * 1.2) * (JUMBLR_INCR + 3*(JUMBLR_INCR * JUMBLR_FEE + JUMBLR_TXFEE)); |
|||
btcavail = dstr(jumblr_balance(myinfo,coinbtc,kmdcoin->DEXinfo.depositaddr)); |
|||
avail = (btcavail - coinbtc->DEXinfo.DEXpending); |
|||
printf("BTC.%d deposits %.8f, min %.8f avail %.8f pending %.8f\n",toKMD,btcavail,minbtc,avail,coinbtc->DEXinfo.DEXpending); |
|||
if ( toKMD == 0 && coinbtc != 0 && btcavail > (minbtc + coinbtc->DEXinfo.DEXpending) ) |
|||
{ |
|||
if ( vol > 0. ) |
|||
{ |
|||
vals = cJSON_CreateObject(); |
|||
jaddstr(vals,"source","BTC"); |
|||
jaddstr(vals,"dest","KMD"); |
|||
jaddnum(vals,"amount",vol); |
|||
jaddnum(vals,"minprice",0.985/kmdcoin->DEXinfo.btcprice); |
|||
jaddnum(vals,"usejumblr",1); |
|||
jaddnum(vals,"DEXselector",1); |
|||
memset(hash.bytes,0,sizeof(hash)); |
|||
coinbtc->DEXinfo.DEXpending += vol; |
|||
if ( (retstr= InstantDEX_request(myinfo,coinbtc,0,0,hash,vals,"")) != 0 ) |
|||
{ |
|||
printf("request.(%s) -> (%s)\n",jprint(vals,0),retstr); |
|||
free(retstr); |
|||
} |
|||
free_json(vals); |
|||
// curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"InstantDEX\",\"method\":\"request\",\"vals\":{\"source\":\"KMD\",\"amount\":20,\"dest\":\"USD\",\"minprice\":0.08}}"
|
|||
} |
|||
} //else printf("btcavail %.8f pending %.8f\n",btcavail,pending);
|
|||
minkmd = 100.; |
|||
avail = (kmdcoin->DEXinfo.KMDavail - kmdcoin->DEXinfo.DEXpending); |
|||
printf("KMD.%d deposits %.8f, min %.8f, avail %.8f pending %.8f\n",toKMD,kmdcoin->DEXinfo.KMDavail,minkmd,avail,kmdcoin->DEXinfo.DEXpending); |
|||
if ( toKMD != 0 && coinbtc != 0 && kmdcoin->DEXinfo.KMDavail > (minkmd + kmdcoin->DEXinfo.DEXpending) ) |
|||
{ |
|||
if ( avail > 100.*JUMBLR_INCR ) |
|||
vol = 100.*JUMBLR_INCR; |
|||
else if ( avail > 10.*JUMBLR_INCR ) |
|||
vol = 10.*JUMBLR_INCR; |
|||
else if ( avail >= JUMBLR_INCR ) |
|||
vol = JUMBLR_INCR; |
|||
else vol = 0.; |
|||
if ( vol > 0. ) |
|||
{ |
|||
vals = cJSON_CreateObject(); |
|||
jaddstr(vals,"source","KMD"); |
|||
jaddstr(vals,"dest","BTC"); |
|||
jaddnum(vals,"amount",vol); |
|||
//jaddnum(vals,"destamount",JUMBLR_INCR*kmdcoin->DEXinfo.btcprice);
|
|||
jaddnum(vals,"minprice",0.985 * kmdcoin->DEXinfo.btcprice); |
|||
jaddnum(vals,"usejumblr",2); |
|||
memset(hash.bytes,0,sizeof(hash)); |
|||
kmdcoin->DEXinfo.DEXpending += vol; |
|||
jaddnum(vals,"DEXselector",2); |
|||
if ( (retstr= InstantDEX_request(myinfo,coinbtc,0,0,hash,vals,"")) != 0 ) |
|||
{ |
|||
printf("request.(%s) -> (%s)\n",jprint(vals,0),retstr); |
|||
free(retstr); |
|||
} |
|||
free_json(vals); |
|||
} |
|||
} else printf("kmdavail %.8f pending %.8f\n",kmdcoin->DEXinfo.avail,kmdcoin->DEXinfo.DEXpending);*/ |
|||
} |
|||
|
|||
void smartaddress_depositjumblr(struct supernet_info *myinfo,char *symbol,char *coinaddr,double maxbid,double minask,cJSON *extraobj) |
|||
{ |
|||
struct iguana_info *basecoin,*relcoin; |
|||
if ( (basecoin= iguana_coinfind(symbol)) != 0 && (relcoin= iguana_coinfind("KMD")) != 0 ) |
|||
{ |
|||
if ( strcmp(coinaddr,basecoin->DEXinfo.depositaddr) == 0 ) |
|||
smartaddress_dex(myinfo,"deposit",1,basecoin,coinaddr,basecoin->DEXinfo.avail,relcoin,maxbid,minask,extraobj,0.); |
|||
else printf("smartaddress_jumblr.%s: mismatch deposit address (%s) vs (%s)\n",symbol,coinaddr,basecoin->DEXinfo.depositaddr); |
|||
} |
|||
} |
|||
|
|||
double smartaddress_jumblrcredit(struct supernet_info *myinfo,char *symbol) |
|||
{ |
|||
return(0.); // default to BTC conversion for now
|
|||
} |
|||
|
|||
void smartaddress_jumblr(struct supernet_info *myinfo,char *symbol,char *coinaddr,double maxbid,double minask,cJSON *extraobj) |
|||
{ |
|||
struct iguana_info *basecoin,*relcoin; double credits = 0.; |
|||
if ( strcmp("BTC",symbol) != 0 ) |
|||
{ |
|||
if ( (credits= smartaddress_jumblrcredit(myinfo,symbol)) <= 0. ) |
|||
return; |
|||
} |
|||
if ( (basecoin= iguana_coinfind("KMD")) != 0 && (relcoin= iguana_coinfind(symbol)) != 0 ) |
|||
{ |
|||
if ( strcmp(coinaddr,basecoin->DEXinfo.jumblraddr) == 0 ) |
|||
smartaddress_dex(myinfo,"jumblr",2,basecoin,coinaddr,basecoin->DEXinfo.jumblravail,relcoin,maxbid,minask,extraobj,credits); |
|||
else printf("smartaddress_jumblr.%s: mismatch jumblr address (%s) vs (%s)\n",symbol,coinaddr,basecoin->DEXinfo.jumblraddr); |
|||
} |
|||
} |
|||
|
|||
void smartaddress_dividend(struct supernet_info *myinfo,char *symbol,char *coinaddr,double maxbid,double minask,cJSON *extraobj) |
|||
{ |
|||
// support list of weighted addresses, including snapshots
|
|||
} |
|||
|
|||
void smartaddress_pangea(struct supernet_info *myinfo,char *symbol,char *coinaddr,double maxbid,double minask,cJSON *extraobj) |
|||
{ |
|||
// table deposit
|
|||
} |
|||
|
|||
void smartaddress_action(struct supernet_info *myinfo,int32_t selector,char *typestr,char *symbol,char *coinaddr,double maxbid,double minask,cJSON *extraobj) |
|||
{ |
|||
char rel[64]; struct iguana_info *basecoin,*relcoin; double avail; |
|||
if ( strcmp(typestr,"deposit") == 0 && selector == 0 ) |
|||
smartaddress_depositjumblr(myinfo,symbol,coinaddr,maxbid,minask,extraobj); |
|||
else if ( strcmp(typestr,"jumblr") == 0 && selector == 0 ) |
|||
smartaddress_jumblr(myinfo,symbol,coinaddr,maxbid,minask,extraobj); |
|||
else if ( strcmp(typestr,"dividend") == 0 && selector == 0 ) |
|||
smartaddress_dividend(myinfo,symbol,coinaddr,maxbid,minask,extraobj); |
|||
else if ( strcmp(typestr,"pangea") == 0 && selector == 0 ) |
|||
smartaddress_pangea(myinfo,symbol,coinaddr,maxbid,minask,extraobj); |
|||
else |
|||
{ |
|||
safecopy(rel,typestr,sizeof(rel)); |
|||
touppercase(rel); |
|||
if ( (relcoin= iguana_coinfind(rel)) != 0 && (basecoin= iguana_coinfind(symbol)) != 0 ) |
|||
{ |
|||
if ( myinfo->numswaps == 0 )//|| (basecoin->FULLNODE < 0 && relcoin->FULLNODE < 0) )
|
|||
{ |
|||
if ( (avail= dstr(jumblr_balance(myinfo,basecoin,coinaddr))) > SMALLVAL ) |
|||
{ |
|||
smartaddress_availupdate(myinfo,typestr,symbol,avail,SMALLVAL*0.99); |
|||
smartaddress_dex(myinfo,typestr,0,basecoin,coinaddr,avail,relcoin,maxbid,minask,extraobj,0.); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
void smartaddress_update(struct supernet_info *myinfo,int32_t selector) |
|||
{ |
|||
double maxbid,minask; uint8_t addrtype,rmd160[20]; char *smartstr,*typestr,*symbol,*address,coinaddr[64]; cJSON *smartarray,*extraobj,*item,*array,*coinitem; int32_t iter,i,n,j,m; struct iguana_info *kmdcoin,*coinbtc = 0; |
|||
//printf("smartaddress_update numswaps.%d notary.%d IAMLP.%d %p %p %f\n",myinfo->numswaps,myinfo->IAMNOTARY,myinfo->IAMLP,kmdcoin,coinbtc,kmdcoin->DEXinfo.btcprice);
|
|||
if ( myinfo->IAMNOTARY != 0 || myinfo->IAMLP != 0 || myinfo->secret[0] == 0 ) |
|||
return; |
|||
kmdcoin = iguana_coinfind("KMD"); |
|||
coinbtc = iguana_coinfind("BTC"); |
|||
if ( kmdcoin == 0 || coinbtc == 0 ) |
|||
return; |
|||
smartaddress_coinupdate(myinfo,"KMD",0.,0.,0.); // must be first
|
|||
if ( kmdcoin->DEXinfo.btcprice > SMALLVAL ) |
|||
{ |
|||
if ( (smartstr= InstantDEX_smartaddresses(myinfo,0,0,0)) != 0 ) |
|||
{ |
|||
if ( (smartarray= cJSON_Parse(smartstr)) != 0 ) |
|||
{ |
|||
if ( (n= cJSON_GetArraySize(smartarray)) > 0 ) |
|||
{ |
|||
for (iter=0; iter<2; iter++) |
|||
{ |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
item = jitem(smartarray,i); |
|||
if ( (typestr= jstr(item,"type")) != 0 && (array= jarray(&m,item,"coins")) != 0 ) |
|||
{ |
|||
for (j=0; j<m; j++) |
|||
{ |
|||
coinitem = jitem(array,j); |
|||
if ( (symbol= jstr(coinitem,"coin")) == 0 ) |
|||
continue; |
|||
if ( iter == 0 ) |
|||
smartaddress_coinupdate(myinfo,symbol,kmdcoin->DEXinfo.btcprice,kmdcoin->DEXinfo.avail,kmdcoin->DEXinfo.USD_average); |
|||
else |
|||
{ |
|||
printf("Action.%s (%s)\n",typestr,jprint(coinitem,0)); |
|||
if ( (address= jstr(coinitem,"address")) != 0 ) |
|||
{ |
|||
if ( strcmp(typestr,"jumblr") == 0 ) |
|||
{ |
|||
bitcoin_addr2rmd160(&addrtype,rmd160,address); |
|||
bitcoin_address(coinaddr,kmdcoin->chain->pubtype,rmd160,20); |
|||
} else strcpy(coinaddr,address); |
|||
maxbid = jdouble(coinitem,"maxbid"); |
|||
minask = jdouble(coinitem,"minask"); |
|||
extraobj = jobj(coinitem,"extra"); |
|||
smartaddress_action(myinfo,selector,typestr,symbol,coinaddr,maxbid,minask,extraobj); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
free_json(smartarray); |
|||
} |
|||
free(smartstr); |
|||
} |
|||
} |
|||
} |
|||
|
|||
#include "../includes/iguana_apidefs.h" |
|||
#include "../includes/iguana_apideclares.h" |
|||
#include "../includes/iguana_apideclares2.h" |
|||
|
|||
ZERO_ARGS(InstantDEX,smartaddresses) |
|||
{ |
|||
int32_t i; cJSON *retjson = cJSON_CreateArray(); |
|||
portable_mutex_lock(&myinfo->smart_mutex); |
|||
for (i=0; i<myinfo->numsmartaddrs; i++) |
|||
jaddi(retjson,smartaddress_json(&myinfo->smartaddrs[i])); |
|||
portable_mutex_unlock(&myinfo->smart_mutex); |
|||
return(jprint(retjson,1)); |
|||
} |
|||
|
|||
TWO_STRINGS_AND_TWO_DOUBLES(InstantDEX,smartaddress,type,symbol,maxbid,minask) |
|||
{ |
|||
char prefix[64],coinaddr[64],KMDaddr[64],typestr[64]; double bidask[2]; uint8_t pubkey33[33]; bits256 privkey; |
|||
if ( smartaddress_type(type) < 0 ) |
|||
return(clonestr("{\"error\":\"non-supported smartaddress type\"}")); |
|||
if ( iguana_coinfind(symbol) == 0 ) |
|||
return(clonestr("{\"error\":\"non-supported smartaddress symbol\"}")); |
|||
if ( strcmp(type,"deposit") == 0 || strcmp(type,"jumblr") == 0 ) |
|||
{ |
|||
if ( smartaddress_pubkey(myinfo,typestr,bidask,&privkey,symbol,strcmp(type,"deposit") == 0 ? myinfo->jumblr_depositkey : myinfo->jumblr_pubkey) < 0 ) |
|||
return(clonestr("{\"error\":\"unexpected missing smartaddress deposit/jumblr\"}")); |
|||
} |
|||
else |
|||
{ |
|||
strcpy(prefix,type); |
|||
tolowercase(prefix); |
|||
if ( strcmp(prefix,"btc") == 0 || strcmp(prefix,"kmd") == 0 ) |
|||
return(clonestr("{\"success\":\"no need add BTC or KMD to smartaddress\"}")); |
|||
strcat(prefix," "); |
|||
privkey = jumblr_privkey(myinfo,coinaddr,0,KMDaddr,prefix); |
|||
} |
|||
if ( (coin= iguana_coinfind(symbol)) == 0 ) |
|||
return(clonestr("{\"error\":\"non-supported smartaddress symbol\"}")); |
|||
bitcoin_pubkey33(myinfo->ctx,pubkey33,privkey); |
|||
bitcoin_address(coinaddr,coin->chain->pubtype,pubkey33,33); |
|||
smartaddress_add(myinfo,privkey,type,symbol,maxbid,minask); |
|||
return(InstantDEX_smartaddresses(myinfo,0,0,0)); |
|||
} |
|||
|
|||
#include "../includes/iguana_apiundefs.h" |
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,108 @@ |
|||
/******************************************************************************
|
|||
* Copyright © 2014-2017 The SuperNET Developers. * |
|||
* * |
|||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * |
|||
* the top-level directory of this distribution for the individual copyright * |
|||
* holder information and the developer policies on copyright and licensing. * |
|||
* * |
|||
* Unless otherwise agreed in a custom licensing agreement, no part of the * |
|||
* SuperNET software, including this file may be copied, modified, propagated * |
|||
* or distributed except according to the terms contained in the LICENSE file * |
|||
* * |
|||
* Removal or modification of this copyright notice is prohibited. * |
|||
* * |
|||
******************************************************************************/ |
|||
|
|||
// included from basilisk.c
|
|||
|
|||
// "currency":{"value":%.8f, "pending":%.8f}
|
|||
|
|||
cJSON *tradebot_balancediff(cJSON *item,cJSON *anchoritem) // only item might be null
|
|||
{ |
|||
double current[2],past[2]; int32_t i; cJSON *diffitem = jduplicate(anchoritem); |
|||
memset(current,0,sizeof(current)); |
|||
memset(past,0,sizeof(past)); |
|||
if ( jobj(diffitem,"value") != 0 ) |
|||
jdelete(diffitem,"value"); |
|||
if ( jobj(diffitem,"pending") != 0 ) |
|||
jdelete(diffitem,"pending"); |
|||
for (i=0; i<2; i++) |
|||
{ |
|||
if ( current[i] != 0. || past[i] != 0. ) |
|||
jaddnum(diffitem,i == 0 ? "value" : "pending",current[i] - past[i]); |
|||
} |
|||
return(diffitem); |
|||
} |
|||
|
|||
cJSON *tradebot_balancesdiff(struct supernet_info *myinfo,cJSON *current,cJSON *anchor) |
|||
{ |
|||
cJSON *item,*anchoritem,*diffitem,*array; int32_t i,n; char *field; |
|||
if ( anchor == 0 ) |
|||
return(jduplicate(current)); |
|||
array = cJSON_CreateObject(); |
|||
n = cJSON_GetArraySize(current); |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
item = jitem(current,i); |
|||
field = jfieldname(item); |
|||
if ( (anchoritem= jobj(anchor,field)) != 0 ) |
|||
diffitem = tradebot_balancediff(item,anchoritem); |
|||
else diffitem = jduplicate(item); |
|||
jadd(array,field,diffitem); |
|||
} |
|||
n = cJSON_GetArraySize(anchor); |
|||
for (i=0; i<n; i++) |
|||
{ |
|||
item = jitem(current,i); |
|||
field = jfieldname(item); |
|||
if ( jobj(array,field) == 0 ) |
|||
jadd(array,field,tradebot_balancediff(0,item)); |
|||
} |
|||
return(array); |
|||
} |
|||
|
|||
// get balances from all exchanges, wallets, pending
|
|||
double tradebot_balance(struct supernet_info *myinfo,char *base) |
|||
{ |
|||
cJSON *json; double value = 0.; int32_t i; struct iguana_info *coin = iguana_coinfind(base); |
|||
if ( coin != 0 && (json= iguana_getinfo(myinfo,coin)) != 0 ) |
|||
{ |
|||
value = jdouble(json,"balance"); |
|||
free_json(json); |
|||
} |
|||
for (i=0; i<myinfo->numexchanges; i++) |
|||
{ |
|||
value += 0;//InstantDEX_balance(myinfo,0,0,0,exchange,base);
|
|||
} |
|||
return(value); |
|||
} |
|||
|
|||
void tradebot_pendingadd(struct supernet_info *myinfo,cJSON *tradejson,char *base,double basevolume,char *rel,double relvolume) |
|||
{ |
|||
portable_mutex_lock(&myinfo->pending_mutex); |
|||
// add to myinfo->trades
|
|||
portable_mutex_unlock(&myinfo->pending_mutex); |
|||
} |
|||
|
|||
void tradebot_pendingremove(struct supernet_info *myinfo,char *base,double basevolume,char *rel,double relvolume) |
|||
{ |
|||
portable_mutex_lock(&myinfo->pending_mutex); |
|||
// remove from myinfo->trades
|
|||
portable_mutex_unlock(&myinfo->pending_mutex); |
|||
} |
|||
|
|||
double tradebot_pending(struct supernet_info *myinfo,char *base) |
|||
{ |
|||
double pending = 0.; struct pending_trade *tp,*tmp; |
|||
portable_mutex_lock(&myinfo->pending_mutex); |
|||
HASH_ITER(hh,myinfo->trades,tp,tmp) |
|||
{ |
|||
if ( strcmp(base,tp->base) == 0 ) |
|||
pending += tp->dir * tp->basevolume; |
|||
else if ( strcmp(base,tp->rel) == 0 ) |
|||
pending -= tp->dir * tp->relvolume; |
|||
} |
|||
portable_mutex_unlock(&myinfo->pending_mutex); |
|||
return(pending); |
|||
} |
|||
|
@ -1,4 +1,4 @@ |
|||
git pull |
|||
rm *.o |
|||
gcc -c -DLIQUIDITY_PROVIDER=1 -O2 *.c jpeg/*.c jpeg/unix/*.c -I/usr/lib/x86_64-linux-gnu/curl |
|||
rm -f ../agents/libcrypto777.a; ar rcu ../agents/libcrypto777.a *.o |
|||
rm -f ../agents/libcrypto777.a; ar rc ../agents/libcrypto777.a *.o |
|||
|
@ -0,0 +1,30 @@ |
|||
# Very basic makefile for compiling iguana in Linux with StaticNanoMsg |
|||
# derived from m_LP (used to compile iguana for linux) |
|||
# author: fadedreamz |
|||
|
|||
SRCS=$(wildcard *.c) |
|||
SRCS+=$(wildcard jpeg/*.c) |
|||
SRCS+=$(wildcard jpeg/unix/*.c) |
|||
|
|||
OBJS=$(SRCS:%.c=%.o) |
|||
|
|||
INCLUDE_DIRS+=-I/usr/lib/x86_64-linux-gnu/curl |
|||
PREPROCESSORS+=-DLIQUIDITY_PROVIDER=1 -DUSE_STATIC_NANOMSG |
|||
|
|||
CFLAGS+=-O2 $(PREPROCESSORS) $(INCLUDE_DIRS) |
|||
|
|||
update_repo: |
|||
git pull |
|||
|
|||
clean: |
|||
-rm $(OBJS) |
|||
|
|||
all: update_repo $(OBJS) static |
|||
@echo ' ================' |
|||
@echo '| crypto777 [OK] |' |
|||
@echo ' ================' |
|||
|
|||
static: $(OBJS) |
|||
ar rc ../agents/libcrypto777.a $(OBJS) |
|||
|
|||
.PHONY: update_repo clean all static |
@ -0,0 +1,4 @@ |
|||
git pull |
|||
rm *.o |
|||
gcc -mmacosx-version-min=10.6 -c -DLIQUIDITY_PROVIDER=1 -O2 *.c jpeg/*.c jpeg/unix/*.c -I/usr/lib/x86_64-linux-gnu/curl |
|||
rm -f ../agents/libcrypto777.a; ar rc ../agents/libcrypto777.a *.o |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue