Browse Source

Merge pull request #545 from jl777/dev

new coins to notarize, barterDEX core release candidate
beta
jl777 7 years ago
committed by GitHub
parent
commit
eae2690c16
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      .gitignore
  2. 1
      crypto777/OS_portable.h
  3. 6
      crypto777/OS_time.c
  4. 14
      crypto777/bitcoind_RPC.c
  5. 2
      crypto777/iguana_OS.c
  6. 15
      crypto777/ramcoder.c
  7. 2
      iguana/coins/axo_7776
  8. 2
      iguana/coins/basilisk/axo
  9. 1
      iguana/coins/basilisk/btch
  10. 2
      iguana/coins/basilisk/etomic
  11. 0
      iguana/coins/basilisk/mshark
  12. 2
      iguana/coins/btch_7776
  13. 2
      iguana/coins/etomic_7776
  14. 0
      iguana/coins/genREVS
  15. 8
      iguana/exchanges/LP_NXT.c
  16. 211
      iguana/exchanges/LP_bitcoin.c
  17. 24
      iguana/exchanges/LP_coins.c
  18. 68
      iguana/exchanges/LP_commands.c
  19. 29
      iguana/exchanges/LP_include.h
  20. 229
      iguana/exchanges/LP_instantdex.c
  21. 708
      iguana/exchanges/LP_mmjson.c
  22. 211
      iguana/exchanges/LP_nativeDEX.c
  23. 2
      iguana/exchanges/LP_network.c
  24. 56
      iguana/exchanges/LP_ordermatch.c
  25. 385
      iguana/exchanges/LP_portfolio.c
  26. 165
      iguana/exchanges/LP_prices.c
  27. 102
      iguana/exchanges/LP_privkey.c
  28. 195
      iguana/exchanges/LP_remember.c
  29. 98
      iguana/exchanges/LP_rpc.c
  30. 1
      iguana/exchanges/LP_scan.c
  31. 13
      iguana/exchanges/LP_secp.c
  32. 9
      iguana/exchanges/LP_signatures.c
  33. 9
      iguana/exchanges/LP_socket.c
  34. 955
      iguana/exchanges/LP_statemachine.c
  35. 59
      iguana/exchanges/LP_stats.c
  36. 40
      iguana/exchanges/LP_swap.c
  37. 9
      iguana/exchanges/LP_tradebots.c
  38. 176
      iguana/exchanges/LP_transaction.c
  39. 103
      iguana/exchanges/LP_utxo.c
  40. 2
      iguana/exchanges/auto_chipsbtc
  41. 2
      iguana/exchanges/auto_chipskmd
  42. 3
      iguana/exchanges/autofill
  43. 3
      iguana/exchanges/autotrade
  44. 3
      iguana/exchanges/balances
  45. 4
      iguana/exchanges/bots
  46. 4
      iguana/exchanges/coins
  47. 4
      iguana/exchanges/coins.json
  48. 4
      iguana/exchanges/dex
  49. 14
      iguana/exchanges/enable
  50. 4
      iguana/exchanges/fundvalue
  51. 15
      iguana/exchanges/get_supernet
  52. 4
      iguana/exchanges/hodl
  53. 2
      iguana/exchanges/install
  54. 4
      iguana/exchanges/jumblr
  55. 943
      iguana/exchanges/mm 17740.c
  56. 928
      iguana/exchanges/mm.c
  57. 4
      iguana/exchanges/mshark
  58. 3
      iguana/exchanges/pendingswaps
  59. 44
      iguana/exchanges/prices/autoprice
  60. 3
      iguana/exchanges/prices/bet
  61. 3
      iguana/exchanges/prices/bots
  62. 3
      iguana/exchanges/prices/crypto
  63. 3
      iguana/exchanges/prices/dex
  64. 3
      iguana/exchanges/prices/jumblr
  65. 3
      iguana/exchanges/prices/mgw
  66. 3
      iguana/exchanges/prices/pangea
  67. 3
      iguana/exchanges/prices/revs
  68. 12
      iguana/exchanges/stats.c
  69. 20
      iguana/exchanges/supernet
  70. 3
      iguana/exchanges/ticker
  71. 2
      iguana/exchanges/trackbtc
  72. 2
      iguana/iguana_notary.c
  73. 3
      iguana/m_notary_run
  74. 65
      iguana/m_splitfund
  75. 252
      iguana/mini-gmp.c

6
.gitignore

@ -493,3 +493,9 @@ iguana/DB/KMD/0/.tmpmarker
iguana/myipaddr
iguana/DB/UNSPENTS/.tmpmarker
*.RQ4z6KrMZeEnCSCsChv1ZoR9ExQitHjbpg
iguana/DB/instantdex_RQ4z6KrMZeEnCSCsChv1ZoR9ExQitHjbpg_append.json
iguana/DB/instantdex_RQ4z6KrMZeEnCSCsChv1ZoR9ExQitHjbpg.json

1
crypto777/OS_portable.h

@ -326,6 +326,7 @@ int32_t btc_convaddr(char *hexaddr,char *addr58);
uint64_t RS_decode(char *rs);
int32_t RS_encode(char *rsaddr,uint64_t id);
char *cmc_ticker(char *base);
void calc_sha1(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len);
void calc_md2(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len);

6
crypto777/OS_time.c

@ -21,7 +21,7 @@
#define TAI_PACK 8
#define TAI_UTC_DIFF ((uint64_t)4611686018427387914ULL)
//#define UTC_ADJUST -36
//#define UTC_ADJUST -37
#define tai_approx(t) ((double) ((t)->x))
#define tai_less(t,u) ((t)->x < (u)->x)
@ -300,7 +300,7 @@ void tai_add(struct tai *t,struct tai *u,struct tai *v) { t->x = u->x + v->x; }
void tai_sub(struct tai *t,struct tai *u,struct tai *v) { t->x = u->x - v->x; }
// {"leapseconds":["+1972-06-30", "+1972-12-31", "+1973-12-31", "+1974-12-31", "+1975-12-31", "+1976-12-31", "+1977-12-31", "+1982-06-30", "+1983-06-30", "+1985-06-30", "+1987-12-31", "+1989-12-31", "+1990-12-31", "+1992-06-30", "+1993-06-30", "+1994-06-30", "+1995-12-31", "+1997-06-30", "+1998-12-31", "+2005-12-31", "+2008-12-31", "+2012-06-30", "+2015-06-30"]}
char *leapseconds[] = { "+1972-06-30", "+1972-12-31", "+1973-12-31", "+1974-12-31", "+1975-12-31", "+1976-12-31", "+1977-12-31", "+1982-06-30", "+1983-06-30", "+1985-06-30", "+1987-12-31", "+1989-12-31", "+1990-12-31", "+1992-06-30", "+1993-06-30", "+1994-06-30", "+1995-12-31", "+1997-06-30", "+1998-12-31", "+2005-12-31", "+2008-12-31", "+2012-06-30", "+2015-06-30" };
char *leapseconds[] = { "+1972-06-30", "+1972-12-31", "+1973-12-31", "+1974-12-31", "+1975-12-31", "+1976-12-31", "+1977-12-31", "+1982-06-30", "+1983-06-30", "+1985-06-30", "+1987-12-31", "+1989-12-31", "+1990-12-31", "+1992-06-30", "+1993-06-30", "+1994-06-30", "+1995-12-31", "+1997-06-30", "+1998-12-31", "+2005-12-31", "+2008-12-31", "+2012-06-30", "+2015-06-30", "+2016-12-31" };
struct tai leaptais[sizeof(leapseconds)/sizeof(*leapseconds)];
char *dayname[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } ;
@ -355,7 +355,7 @@ struct tai tai_now()
{
First_TAI = t, First_utc = (uint32_t)now;
#ifndef DISABLE_LEAPS
UTC_ADJUST = -36;
UTC_ADJUST = -37;
#endif
//printf("TAINOW.%llu %03.3f UTC.%u vs %u [diff %d]\n",(long long)t.x,t.millis,First_utc,tai2utc(t),UTC_ADJUST);
}

14
crypto777/bitcoind_RPC.c

@ -30,6 +30,7 @@ void *LP_alloc(uint64_t len);
void LP_free(void *ptr);
char *LP_clonestr(char *str);*/
int32_t bitcoind_RPC_inittime;
#if LIQUIDITY_PROVIDER
#include <curl/curl.h>
@ -73,7 +74,7 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *
char *retstr = 0;
cJSON *json,*result,*error;
#ifdef FROM_MARKETMAKER
usleep(3000);
//usleep(3000);
#endif
//printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr);
if ( command == 0 || rpcstr == 0 || rpcstr[0] == 0 )
@ -190,7 +191,16 @@ try_again:
curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash
curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback
if ( timeout > 0 )
curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT, timeout); // causes problems with iguana timeouts
{
if ( bitcoind_RPC_inittime != 0 )
{
#ifndef _WIN32
curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT,1);
#else
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT_MS, timeout*100);
#endif
} else curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT,timeout); // causes problems with iguana timeouts
}
if ( strncmp(url,"https",5) == 0 )
{
curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0);

2
crypto777/iguana_OS.c

@ -877,7 +877,7 @@ void *OS_loadfile(char *fname,char **bufp,long *lenp,long *allocsizep)
{
fclose(fp);
*lenp = 0;
printf("OS_loadfile null size.(%s)\n",fname);
//printf("OS_loadfile null size.(%s)\n",fname);
return(0);
}
if ( filesize > buflen-1 )

15
crypto777/ramcoder.c

@ -430,19 +430,22 @@ int32_t ramcoder_decoder(struct ramcoder *coder,int32_t updateprobs,uint8_t *buf
return(n);
}
int32_t ramcoder_compress(uint8_t *bits,int32_t maxlen,uint8_t *data,int32_t datalen,bits256 seed)
int32_t ramcoder_compress(uint8_t *bits,int32_t maxlen,uint8_t *data,int32_t datalen,bits256 origseed)
{
int32_t numbits; HUFF H,*hp = &H;
uint64_t histo[256]; bits256 seed; char str[65]; int32_t numbits; HUFF H,*hp = &H;
_init_HUFF(hp,maxlen,bits);
if ( ramcoder_encoder(0,1,data,datalen,hp,0,&seed) < 0 )
memset(histo,0,sizeof(histo));
seed = origseed;
if ( ramcoder_encoder(0,1,data,datalen,hp,histo,&seed) < 0 )
return(-1);
printf("seed.%s\n",bits256_str(str,seed));
numbits = hp->bitoffset;
if ( (0) )
if ( (1) )
{
void *malloc(size_t); void free(void *);
int32_t i,checklen; uint8_t *checkbuf;
checkbuf = malloc(datalen*2);
memset(seed.bytes,0,sizeof(seed));
seed = origseed;
hrewind(hp);
checklen = ramcoder_decoder(0,1,checkbuf,datalen*2,hp,&seed);
if ( checklen != datalen || memcmp(checkbuf,data,datalen) != 0 )
@ -457,7 +460,7 @@ int32_t ramcoder_compress(uint8_t *bits,int32_t maxlen,uint8_t *data,int32_t dat
printf("%02x ",checkbuf[i]);
printf("checklen.%d\n",checklen);
getchar();
} // else printf("CODEC passed datalen.%d -> numbits %d %d\n",datalen,numbits,numbits/8);
} else printf("CODEC passed datalen.%d -> numbits %d %d origseed.%s\n",datalen,numbits,numbits/8,bits256_str(str,origseed));
free(checkbuf);
}
return(numbits);

2
iguana/coins/axo_7776

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"AXO.conf\",\"path\":\"${HOME#"/"}/.komodo/AXO\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"AXO\",\"name\":\"AXO\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"ba009d17\",\"p2p\":12926,\"rpc\":12927,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}"

2
iguana/coins/basilisk/axo

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"AXO.conf\",\"path\":\"${HOME#"/"}/.komodo/AXO\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":0,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"AXO\",\"name\":\"AXO\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"ba009d17\",\"p2p\":12926,\"rpc\":12927,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}"

1
iguana/coins/basilisk/btch

@ -0,0 +1 @@
curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"BTCH.conf\",\"path\":\"${HOME#"/"}/.komodo/BTCH\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":0,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"BTCH\",\"name\":\"BTCH\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"b0ed1968\",\"p2p\":10160,\"rpc\":10161,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}"

2
iguana/coins/basilisk/etomic

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7778" --data "{\"conf\":\"ETOMIC.conf\",\"path\":\"${HOME#"/"}/.komodo/ETOMIC\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":0,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"ETOMIC\",\"name\":\"ETOMIC\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"072a90e8\",\"p2p\":10270,\"rpc\":10271,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}"

0
iguana/coins/basilisk/mshark

2
iguana/coins/btch_7776

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"BTCH.conf\",\"path\":\"${HOME#"/"}/.komodo/BTCH\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"BTCH\",\"name\":\"BTCH\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"b0ed1968\",\"p2p\":10160,\"rpc\":10161,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}"

2
iguana/coins/etomic_7776

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7776" --data "{\"conf\":\"ETOMIC.conf\",\"path\":\"${HOME#"/"}/.komodo/ETOMIC\",\"unitval\":\"20\",\"zcash\":1,\"RELAY\":-1,\"VALIDATE\":0,\"prefetchlag\":-1,\"poll\":100,\"active\":1,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":4,\"endpend\":4,\"services\":129,\"maxpeers\":8,\"newcoin\":\"ETOMIC\",\"name\":\"ETOMIC\",\"hasheaders\":1,\"useaddmultisig\":0,\"netmagic\":\"072a90e8\",\"p2p\":10270,\"rpc\":10271,\"pubval\":60,\"p2shval\":85,\"wifval\":188,\"txfee_satoshis\":\"10000\",\"isPoS\":0,\"minoutput\":10000,\"minconfirms\":2,\"genesishash\":\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\",\"protover\":170002,\"genesisblock\":\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\",\"debug\":0,\"seedipaddr\":\"78.47.196.146\"}"

0
iguana/coins/genREVS

8
iguana/exchanges/LP_NXT.c

@ -33,7 +33,7 @@ static char *assetids[][4] =
{ "13476425053110940554", "CRYPTO", "1000", "100000" },
{ "6932037131189568014", "HODL", "1", "100000000" },
//{ "3006420581923704757", "SHARK", "10000", "10000" },
{ "3006420581923704757", "MSHARK", "10000", "10000000" },
{ "3006420581923704757", "MSHARK", "10", "10000000" },
{ "17571711292785902558", "BOTS", "1", "100000000" },
{ "10524562908394749924", "MGW", "1", "100000000" },
{ "8217222248380501882", "MESH", "10000", "10000" },
@ -202,8 +202,10 @@ void NXTventure_liquidation()
cJSON *LP_NXT_redeems()
{
char url[1024],*retstr,*recv,*method,*msgstr,assetname[128]; uint64_t totals[2][sizeof(assetids)/sizeof(*assetids)],mult,txnum,assetid,qty; int32_t i,ind,numtx=0,past_marker=0; cJSON *item,*attach,*decjson,*array,*msgjson,*encjson,*retjson=0;
uint64_t txnum_marker = calc_nxt64bits("5509605741355242617");
uint64_t txnum_marker2 = calc_nxt64bits("7256847492742571143");
//sleep 1; fiat/supernet sendtoaddress RNZZuQYu8xJLZHuekhd96hYfoQuiCMz99T 1001.44150000 # txnum.8537615468620726612
//sleep 1; fiat/pangea sendtoaddress RWMdRaUmMZqKkEibwEhY6XS3RLCXJDWHTi 22.10910000 # txnum.2649622877615958504
uint64_t txnum_marker = calc_nxt64bits("8537615468620726612"); // 2649622877615958504"); // set to most recent processed
uint64_t txnum_marker2 = calc_nxt64bits("7256847492742571143"); // dont change, end marker
char *passphrase = "";
char *account = "NXT-MRBN-8DFH-PFMK-A4DBM";
memset(totals,0,sizeof(totals));

211
iguana/exchanges/LP_bitcoin.c

@ -2137,30 +2137,46 @@ int32_t base58encode_checkbuf(uint8_t taddr,uint8_t addrtype,uint8_t *data,int32
int32_t bitcoin_wif2priv(uint8_t wiftaddr,uint8_t *addrtypep,bits256 *privkeyp,char *wifstr)
{
int32_t offset,len = -1; bits256 hash; uint8_t buf[256];
int32_t offset,len = -1; bits256 hash; uint8_t buf[256],*ptr;
offset = 1 + (wiftaddr != 0);
memset(buf,0,sizeof(buf));
memset(privkeyp,0,sizeof(*privkeyp));
if ( (len= bitcoin_base58decode(buf,wifstr)) >= 4 )
{
// validate with trailing hash, then remove hash
if ( len < 38 )
if ( len >= 32+offset )
memcpy(privkeyp,buf+offset,32);
else
{
//printf("wif %s -> buf too short len.%d\n",wifstr,len);
return(-1);
}
ptr = buf;
/*if ( len < 38 )
{
memset(pbuf,0,sizeof(pbuf));
memcpy(pbuf,buf,len-4);
memcpy(&pbuf[34],&buf[len-4],4);
ptr = pbuf;
int32_t i; for (i=0; i<38; i++)
printf("%02x ",pbuf[i]);
printf("pbuf from %d\n",len);
len = 38;
hash = bits256_doublesha256(0,buf,len - 4);
*addrtypep = (wiftaddr == 0) ? *buf : buf[1];
memcpy(privkeyp,buf+offset,32);
if ( (buf[len - 4]&0xff) == hash.bytes[31] && (buf[len - 3]&0xff) == hash.bytes[30] &&(buf[len - 2]&0xff) == hash.bytes[29] && (buf[len - 1]&0xff) == hash.bytes[28] )
}*/
hash = bits256_doublesha256(0,ptr,len - 4);
*addrtypep = (wiftaddr == 0) ? *ptr : ptr[1];
if ( (ptr[len - 4]&0xff) == hash.bytes[31] && (ptr[len - 3]&0xff) == hash.bytes[30] &&(ptr[len - 2]&0xff) == hash.bytes[29] && (ptr[len - 1]&0xff) == hash.bytes[28] )
{
//int32_t i; for (i=0; i<len; i++)
// printf("%02x ",buf[i]);
//printf(" buf, hash.%02x %02x %02x %02x ",hash.bytes[28],hash.bytes[29],hash.bytes[30],hash.bytes[31]);
// printf("%02x ",ptr[i]);
//printf(" ptr, hash.%02x %02x %02x %02x ",hash.bytes[28],hash.bytes[29],hash.bytes[30],hash.bytes[31]);
//printf("wifstr.(%s) valid len.%d\n",wifstr,len);
return(32);
}
else
else if ( 0 ) // gets errors when len is 37
{
int32_t i; for (i=0; i<len; i++)
printf("%02x ",buf[i]);
printf(" buf, hash.%02x %02x %02x %02x\n",hash.bytes[28],hash.bytes[29],hash.bytes[30],hash.bytes[31]);
printf(" buf, hash.%02x %02x %02x %02x len.%d\n",hash.bytes[28],hash.bytes[29],hash.bytes[30],hash.bytes[31],len);
}
}
return(-1);
@ -2180,13 +2196,26 @@ int32_t bitcoin_wif2addr(void *ctx,uint8_t wiftaddr,uint8_t taddr,uint8_t pubtyp
int32_t bitcoin_priv2wif(uint8_t wiftaddr,char *wifstr,bits256 privkey,uint8_t addrtype)
{
uint8_t data[128]; int32_t offset,len = 32;
memcpy(data+1,privkey.bytes,sizeof(privkey));
offset = 1 + (wiftaddr != 0);
if ( wiftaddr != 0 )
{
//data[0] = wiftaddr;
//data[1] = addrtype;
offset = 2;
}
else
{
//data[0] = addrtype;
offset = 1;
}
memcpy(data+offset,privkey.bytes,len);
data[offset + len++] = 1;
len = base58encode_checkbuf(wiftaddr,addrtype,data,len);
if ( bitcoin_base58encode(wifstr,data,len) == 0 )
{
char str[65]; printf("error making wif from %s\n",bits256_str(str,privkey));
return(-1);
if ( 1 )
}
if ( 0 )
{
uint8_t checktype; bits256 checkpriv; char str[65],str2[65];
if ( bitcoin_wif2priv(wiftaddr,&checktype,&checkpriv,wifstr) == sizeof(bits256) )
@ -2206,7 +2235,7 @@ int32_t bitcoin_priv2wiflong(uint8_t wiftaddr,char *wifstr,bits256 privkey,uint8
len = base58encode_checkbuf(wiftaddr,addrtype,data,len);
if ( bitcoin_base58encode(wifstr,data,len) == 0 )
return(-1);
if ( 1 )
if ( 0 )
{
uint8_t checktype; bits256 checkpriv; char str[65],str2[65];
if ( bitcoin_wif2priv(wiftaddr,&checktype,&checkpriv,wifstr) == sizeof(bits256) )
@ -2578,39 +2607,6 @@ int32_t iguana_calcrmd160(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,char *a
return(vp->type);
}
/*uint32_t iguana_vinscriptparse(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,struct vin_info *vp,uint32_t *sigsizep,uint32_t *pubkeysizep,uint32_t *p2shsizep,uint32_t *userdatalenp,uint8_t *vinscript,int32_t scriptlen,int32_t zcash)
{
uint32_t hashtype; uint8_t *userdata = 0;
*sigsizep = *pubkeysizep = *p2shsizep = *userdatalenp = 0;
if ( bitcoin_scriptget(symbol,taddr,pubtype,p2shtype,&hashtype,sigsizep,pubkeysizep,&userdata,userdatalenp,vp,vinscript,scriptlen,0,zcash) < 0 )
{
printf("iguana_vinscriptparse: error parsing vinscript?\n");
return(-1);
}
if ( userdata != 0 && *userdatalenp > 0 )
memcpy(vp->userdata,userdata,*userdatalenp);
if ( vp->type == IGUANA_SCRIPT_P2SH )
{
*p2shsizep = vp->p2shlen + 1 + (vp->p2shlen >= 0xfd)*2;
//printf("P2SHSIZE.%d\n",*p2shsizep);
}
return(hashtype);
}*/
/*char *iguana_scriptget(struct iguana_info *coin,char *scriptstr,char *asmstr,int32_t max,int32_t hdrsi,uint32_t unspentind,bits256 txid,int32_t vout,uint8_t *rmd160,int32_t type,uint8_t *pubkey33)
{
int32_t scriptlen; uint8_t script[IGUANA_MAXSCRIPTSIZE]; struct vin_info V,*vp = &V;
memset(vp,0,sizeof(*vp));
scriptstr[0] = 0;
if ( asmstr != 0 )
asmstr[0] = 0;
if ( pubkey33 != 0 && bitcoin_pubkeylen(pubkey33) > 0 )
memcpy(vp->signers[0].pubkey,pubkey33,33);
scriptlen = iguana_scriptgen(coin,&vp->M,&vp->N,vp->coinaddr,script,asmstr,rmd160,type,(const struct vin_info *)vp,vout);
init_hexbytes_noT(scriptstr,script,scriptlen);
return(scriptstr);
}*/
cJSON *bitcoin_txscript(char *asmstr,char **vardata,int32_t numvars)
{
int32_t i; cJSON *scriptjson,*array;
@ -3278,19 +3274,21 @@ int32_t iguana_rwmsgtx(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shty
bits256 bitcoin_sigtxid(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,uint8_t *serialized,int32_t maxlen,struct iguana_msgtx *msgtx,int32_t vini,uint8_t *spendscript,int32_t spendlen,uint64_t spendamount,uint32_t hashtype,char *vpnstr,int32_t suppress_pubkeys,int32_t zcash)
{
int32_t i,len; bits256 sigtxid,txid,revsigtxid; struct iguana_msgtx dest;
int32_t i,len,sbtcflag = 0; bits256 sigtxid,txid,revsigtxid; struct iguana_msgtx dest;
dest = *msgtx;
dest.vins = calloc(dest.tx_in,sizeof(*dest.vins));
dest.vouts = calloc(dest.tx_out,sizeof(*dest.vouts));
memcpy(dest.vins,msgtx->vins,dest.tx_in * sizeof(*dest.vins));
memcpy(dest.vouts,msgtx->vouts,dest.tx_out * sizeof(*dest.vouts));
memset(sigtxid.bytes,0,sizeof(sigtxid));
if ( strcmp(symbol,"SBTC") == 0 )
sbtcflag = 1;
if ( ((hashtype & ~SIGHASH_FORKID) & 0xff) != SIGHASH_ALL )
{
printf("currently only SIGHASH_ALL supported, not %d\n",hashtype);
return(sigtxid);
}
if ( (hashtype & SIGHASH_FORKID) == 0 )
if ( (hashtype & SIGHASH_FORKID) == 0 || sbtcflag != 0 )
{
for (i=0; i<dest.tx_in; i++)
{
@ -3320,10 +3318,70 @@ bits256 bitcoin_sigtxid(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2sht
hashtype |= (0x777 << 20);
#endif
len += iguana_rwnum(1,&serialized[len],sizeof(hashtype),&hashtype);
if ( sbtcflag != 0 )
{
memcpy(&serialized[len],"sbtc",4);
len += 4;
}
}
revsigtxid = bits256_doublesha256(0,serialized,len);
for (i=0; i<sizeof(revsigtxid); i++)
sigtxid.bytes[31-i] = revsigtxid.bytes[i];
}
else
{
/*
https://github.com/Bitcoin-UAHF/spec/blob/master/replay-protected-sighash.md
CHashWriter ss(SER_GETHASH, 0);
// Version
ss << txTo.nVersion;
// Input prevouts/nSequence (none/all, depending on flags)
ss << hashPrevouts;
ss << hashSequence;
// The input being signed (replacing the scriptSig with scriptCode +
// amount). The prevout may already be contained in hashPrevout, and the
// nSequence may already be contain in hashSequence.
ss << txTo.vin[nIn].prevout;
ss << static_cast<const CScriptBase &>(scriptCode);
ss << amount;
ss << txTo.vin[nIn].nSequence;
// Outputs (none/one/all, depending on flags)
ss << hashOutputs;
// Locktime
ss << txTo.nLockTime;
// Sighash type
ss << ((GetForkId() << 8) | nHashType);
return ss.GetHash();
}
Computation of midstates:
uint256 GetPrevoutHash(const CTransaction &txTo) {
CHashWriter ss(SER_GETHASH, 0);
for (unsigned int n = 0; n < txTo.vin.size(); n++) {
ss << txTo.vin[n].prevout;
}
return ss.GetHash();
}
uint256 GetSequenceHash(const CTransaction &txTo) {
CHashWriter ss(SER_GETHASH, 0);
for (unsigned int n = 0; n < txTo.vin.size(); n++) {
ss << txTo.vin[n].nSequence;
}
return ss.GetHash();
}
uint256 GetOutputsHash(const CTransaction &txTo) {
CHashWriter ss(SER_GETHASH, 0);
for (unsigned int n = 0; n < txTo.vout.size(); n++) {
ss << txTo.vout[n];
}
return ss.GetHash();
}
*/
bits256 prevouthash,seqhash,outputhash;
for (i=len=0; i<dest.tx_in; i++)
{
@ -3331,35 +3389,66 @@ bits256 bitcoin_sigtxid(char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2sht
len += iguana_rwnum(1,&serialized[len],sizeof(dest.vins[i].prev_vout),&dest.vins[i].prev_vout);
}
prevouthash = bits256_doublesha256(0,serialized,len);
for (i=0; i<sizeof(prevouthash); i++)
prevouthash.bytes[31-i] = prevouthash.bytes[i];
for (i=len=0; i<dest.tx_in; i++)
len += iguana_rwnum(1,&serialized[len],sizeof(dest.vins[i].sequence),&dest.vins[i].sequence);
seqhash = bits256_doublesha256(0,serialized,len);
for (i=0; i<sizeof(seqhash); i++)
seqhash.bytes[31-i] = seqhash.bytes[i];
for (i=len=0; i<dest.tx_out; i++)
len += iguana_voutparse(1,&serialized[len],&dest.vouts[i]);
outputhash = bits256_doublesha256(0,serialized,len);
for (i=0; i<sizeof(outputhash); i++)
outputhash.bytes[31-i] = outputhash.bytes[i];
char str[65]; printf("prevouthash.%s ",bits256_str(str,prevouthash));
printf("seqhash.%s ",bits256_str(str,seqhash));
printf("outputhash.%s ",bits256_str(str,outputhash));
printf("vini.%d prev.%s/v%d\n",vini,bits256_str(str,dest.vins[vini].prev_hash),dest.vins[vini].prev_vout);
/*01000000
997c1040c67ee2f9ab21abf7457f7aec4503970e974e532b6578f326c270b7eb
445066705e799022b7095f7ceca255149f43acfc47e7f59e551f7bce2930b13b
b19ce2c564f7dc57b3f95593e2b287c72d388e86de12dc562d9f8a6bea65b310 01000000
1976a91459fdba29ea85c65ad90f6d38f7a6646476b26b1688ac
5be9290000000000
ffffffff
a919fd9f636c08f4989be95c999230408dbc0f602c3f000bcedba9d5bbe98914
00000000
41000000*/
/*
01000000 ss.write size.4
ebb770c226f378652b534e970e970345ec7a7f45f7ab21abf9e27ec640107c99 ss.write size.32
3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044 ss.write size.32
10b365ea6b8a9f2d56dc12de868e382dc787b2e29355f9b357dcf764c5e29cb1 ss.write size.32
01000000 ss.write size.4
19 ss.write size.1
76a91459fdba29ea85c65ad90f6d38f7a6646476b26b1688ac ss.write size.25
76a91459fdba29ea85c65ad90f6d38f7a6646476b26b1688ac scriptCode
5be9290000000000 ss.write size.8
ffffffff ss.write size.4
hashtype.41 locktime.0 seq.ffffffff amount 29e95b
1489e9bbd5a9dbce0b003f2c600fbc8d403092995ce99b98f4086c639ffd19a9 ss.write size.32
00000000 ss.write size.4
41000000 ss.write size.4
-> sighash.fc55acc3666c43b8f75908ca06ea2d343cd09eb846f14c5d7d0748a11e081a9d*/
len = 0;
len += iguana_rwnum(1,&serialized[len],sizeof(dest.version),&dest.version);
len += iguana_rwbignum(1,&serialized[len],sizeof(prevouthash),prevouthash.bytes);
len += iguana_rwbignum(1,&serialized[len],sizeof(seqhash),seqhash.bytes);
len += iguana_rwbignum(1,&serialized[len],sizeof(dest.vins[vini].prev_hash),dest.vins[vini].prev_hash.bytes);
len += iguana_rwnum(1,&serialized[len],sizeof(dest.vins[vini].prev_vout),&dest.vins[vini].prev_vout);
serialized[len++] = spendlen;
memcpy(&serialized[len],spendscript,spendlen), len += spendlen;
len += iguana_rwnum(1,&serialized[len],sizeof(spendamount),&spendamount);
len += iguana_rwnum(1,&serialized[len],sizeof(dest.vins[vini].sequence),&dest.vins[vini].sequence);
len += iguana_rwbignum(1,&serialized[len],sizeof(outputhash),outputhash.bytes);
len += iguana_rwnum(1,&serialized[len],sizeof(dest.lock_time),&dest.lock_time);
len += iguana_rwnum(1,&serialized[len],sizeof(hashtype),&hashtype);
printf("B path spendamount %.8f\n",dstr(spendamount));
//for (i=0; i<len; i++)
// printf("%02x",serialized[i]);
revsigtxid = bits256_doublesha256(0,serialized,len);
//printf(" B path version.%08x spendamount %.8f locktime %u hashtype %08x %s\n",dest.version,dstr(spendamount),dest.lock_time,hashtype,bits256_str(str,revsigtxid));
for (i=0; i<sizeof(revsigtxid); i++)
sigtxid.bytes[31-i] = revsigtxid.bytes[i];
//sigtxid = revsigtxid;
}
revsigtxid = bits256_doublesha256(0,serialized,len);
for (i=0; i<sizeof(revsigtxid); i++)
sigtxid.bytes[31-i] = revsigtxid.bytes[i];
//char str[65]; printf("SIGTXID.(%s) numvouts.%d\n",bits256_str(str,sigtxid),dest.tx_out);
free(dest.vins);
free(dest.vouts);
@ -3403,6 +3492,8 @@ uint32_t LP_sighash(char *symbol,int32_t zcash)
sighash |= SIGHASH_FORKID;
sighash |= (LP_IS_BITCOINGOLD << 8);
}
else if ( strcmp(symbol,"SBTC") == 0 )
sighash |= SIGHASH_FORKID;
return(sighash);
}

24
iguana/exchanges/LP_coins.c

@ -101,7 +101,7 @@ void LP_statefname(char *fname,char *symbol,char *assetname,char *str,char *name
{
#if defined(NATIVE_WINDOWS)
// need to do something with "confpath":"`${process.env.HOME}`/.muecore/mue.conf" under Windows
char *ht = "`${process.env.HOME}`", *ht_start, *p_ht;
char *ht = "`${process.env.USERHOME}`", *ht_start, *p_ht;
char ht_symbol[2];
ht_start = strstr(confpath, ht);
@ -214,7 +214,7 @@ uint16_t LP_userpass(char *userpass,char *symbol,char *assetname,char *confroot,
cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif)
{
struct electrum_info *ep; int32_t notarized; uint64_t balance; char wifstr[128],ipaddr[64]; uint8_t tmptype; bits256 checkkey; cJSON *item = cJSON_CreateObject();
struct electrum_info *ep; bits256 zero; int32_t notarized; uint64_t balance; char wifstr[128],ipaddr[64]; uint8_t tmptype; bits256 checkkey; cJSON *item = cJSON_CreateObject();
jaddstr(item,"coin",coin->symbol);
if ( showwif != 0 )
{
@ -259,6 +259,17 @@ cJSON *LP_coinjson(struct iguana_info *coin,int32_t showwif)
jaddnum(item,"p2shtype",coin->p2shtype);
jaddnum(item,"wiftype",coin->wiftype);
jaddnum(item,"txfee",strcmp(coin->symbol,"BTC") != 0 ? coin->txfee : LP_txfeecalc(coin,0,0));
if ( strcmp(coin->symbol,"KMD") == 0 )
{
memset(zero.bytes,0,sizeof(zero));
if ( strcmp(coin->smartaddr,coin->instantdex_address) != 0 )
{
LP_instantdex_depositadd(coin->smartaddr,zero);
strcpy(coin->instantdex_address,coin->smartaddr);
}
jaddnum(item,"zcredits",dstr(LP_myzcredits()));
jadd(item,"zdebits",LP_myzdebits());
}
return(item);
}
@ -498,3 +509,12 @@ struct iguana_info *LP_coincreate(cJSON *item)
return(0);
}
void LP_otheraddress(char *destcoin,char *otheraddr,char *srccoin,char *coinaddr)
{
uint8_t addrtype,rmd160[20]; struct iguana_info *src,*dest;
if ( (src= LP_coinfind(srccoin)) != 0 && (dest= LP_coinfind(destcoin)) != 0 )
{
bitcoin_addr2rmd160(src->taddr,&addrtype,rmd160,coinaddr);
bitcoin_address(otheraddr,dest->taddr,dest->pubtype,rmd160,20);
} else printf("couldnt find %s or %s\n",srccoin,destcoin);
}

68
iguana/exchanges/LP_commands.c

@ -110,6 +110,7 @@ enable(coin)\n\
disable(coin)\n\
notarizations(coin)\n\
statsdisp(starttime=0, endtime=0, gui="", pubkey="", base="", rel="")\n\
ticker(base="", rel="")\n\
tradesarray(base, rel, starttime=<now>-timescale*1024, endtime=<now>, timescale=60) -> [timestamp, high, low, open, close, relvolume, basevolume, aveprice, numtrades]\n\
pricearray(base, rel, starttime=0, endtime=0, timescale=60) -> [timestamp, avebid, aveask, highbid, lowask]\n\
getrawtransaction(coin, txid)\n\
@ -119,7 +120,7 @@ buy(base, rel, price, relvolume, timeout=10, duration=3600, nonce)\n\
sell(base, rel, price, basevolume, timeout=10, duration=3600, nonce)\n\
withdraw(coin, outputs[])\n\
sendrawtransaction(coin, signedtx)\n\
swapstatus()\n\
swapstatus(pending=0)\n\
swapstatus(coin, limit=10)\n\
swapstatus(base, rel, limit=10)\n\
swapstatus(requestid, quoteid)\n\
@ -135,6 +136,8 @@ listunspent(coin, address)\n\
setconfirms(coin, numconfirms, maxconfirms=6)\n\
trust(pubkey, trust) # positive to trust, 0 for normal, negative to blacklist\n\
balance(coin, address)\n\
balances(address)\n\
fundvalue(address="", holdings=[], divisor=0)\n\
orderbook(base, rel, duration=3600)\n\
getprices()\n\
getprice(base, rel)\n\
@ -155,7 +158,7 @@ bot_settings(botid, newprice, newvolume)\n\
bot_status(botid)\n\
bot_stop(botid)\n\
bot_pause(botid)\n\
instantdex_deposit(weeks, amount, broadcast=0)\n\
instantdex_deposit(weeks, amount, broadcast=1)\n\
instantdex_claim()\n\
\"}"));
//sell(base, rel, price, basevolume, timeout=10, duration=3600)\n\
@ -170,19 +173,22 @@ instantdex_claim()\n\
{
if ( G.USERPASS_COUNTER == 0 )
{
char pub33str[67];
G.USERPASS_COUNTER = 1;
retjson = cJSON_CreateObject();
jaddstr(retjson,"userpass",G.USERPASS);
jaddbits256(retjson,"mypubkey",G.LP_mypub25519);
init_hexbytes_noT(pub33str,G.LP_pubsecp,33);
jaddstr(retjson,"pubsecp",pub33str);
jadd(retjson,"coins",LP_coinsjson(LP_showwif));
return(jprint(retjson,1));
}
if ( strcmp(method,"passphrase") != 0 && ((userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,G.USERPASS) != 0) )
if ( ((userpass= jstr(argjson,"userpass")) == 0 || strcmp(userpass,G.USERPASS) != 0) ) //strcmp(method,"passphrase") != 0 &&
return(clonestr("{\"error\":\"authentication error you need to make sure userpass is set\"}"));
jdelete(argjson,"userpass");
if ( strcmp(method,"passphrase") == 0 )
{
char coinaddr[64];
char coinaddr[64],pub33str[67];
G.USERPASS_COUNTER = 1;
if ( LP_passphrase_init(jstr(argjson,"passphrase"),jstr(argjson,"gui")) < 0 )
return(clonestr("{\"error\":\"couldnt change passphrase\"}"));
@ -191,11 +197,14 @@ instantdex_claim()\n\
jaddstr(retjson,"result","success");
jaddstr(retjson,"userpass",G.USERPASS);
jaddbits256(retjson,"mypubkey",G.LP_mypub25519);
init_hexbytes_noT(pub33str,G.LP_pubsecp,33);
jaddstr(retjson,"pubsecp",pub33str);
bitcoin_address(coinaddr,0,60,G.LP_myrmd160,20);
jaddstr(retjson,"KMD",coinaddr);
bitcoin_address(coinaddr,0,0,G.LP_myrmd160,20);
jaddstr(retjson,"BTC",coinaddr);
jaddstr(retjson,"NXT",G.LP_NXTaddr);
jadd(retjson,"coins",LP_coinsjson(LP_showwif));
return(jprint(retjson,1));
}
}
@ -205,7 +214,7 @@ instantdex_claim()\n\
{
if ( jint(argjson,"weeks") <= 0 || jdouble(argjson,"amount") < 10. )
return(clonestr("{\"error\":\"instantdex_deposit needs to have weeks and amount\"}"));
else return(LP_instantdex_deposit(ptr,juint(argjson,"weeks"),jdouble(argjson,"amount"),jint(argjson,"broadcast")));
else return(LP_instantdex_deposit(ptr,juint(argjson,"weeks"),jdouble(argjson,"amount"),jobj(argjson,"broadcast") != 0 ? jint(argjson,"broadcast") : 1));
}
return(clonestr("{\"error\":\"cant find KMD\"}"));
}
@ -276,6 +285,10 @@ instantdex_claim()\n\
{
return(jprint(LP_statslog_disp(juint(argjson,"starttime"),juint(argjson,"endtime"),jstr(argjson,"gui"),jbits256(argjson,"pubkey"),jstr(argjson,"base"),jstr(argjson,"rel")),1));
}
else if ( strcmp(method,"ticker") == 0 )
{
return(LP_ticker(jstr(argjson,"base"),jstr(argjson,"rel")));
}
else if ( strcmp(method,"secretaddresses") == 0 )
{
uint8_t taddr,pubtype;
@ -287,14 +300,12 @@ instantdex_claim()\n\
{
uint32_t requestid,quoteid;
if ( (requestid= juint(argjson,"requestid")) != 0 && (quoteid= juint(argjson,"quoteid")) != 0 )
{
return(basilisk_swapentry(requestid,quoteid,1));
}
else if ( coin[0] != 0 )
return(basilisk_swapentries(coin,0,jint(argjson,"limit")));
else if ( base[0] != 0 && rel[0] != 0 )
return(basilisk_swapentries(base,rel,jint(argjson,"limit")));
else return(basilisk_swaplist(0,0,0));
else return(basilisk_swaplist(0,0,0,jint(argjson,"pending")));
}
else if ( strcmp(method,"dynamictrust") == 0 )
{
@ -320,22 +331,10 @@ instantdex_claim()\n\
double price,bid,ask;
if ( strcmp(method,"autoprice") == 0 )
{
if ( LP_autoprice(base,rel,argjson) < 0 )
if ( LP_autoprice(ctx,base,rel,argjson) < 0 )
return(clonestr("{\"error\":\"couldnt set autoprice\"}"));
else return(clonestr("{\"result\":\"success\"}"));
}
else if ( strcmp(method,"getprice") == 0 )
{
double price;
price = LP_price(base,rel);
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"base",base);
jaddstr(retjson,"rel",rel);
jaddnum(retjson,"timestamp",time(NULL));
jaddnum(retjson,"price",price);
return(jprint(retjson,1));
}
else if ( strcmp(method,"pricearray") == 0 )
{
uint32_t firsttime;
@ -359,7 +358,7 @@ instantdex_claim()\n\
return(clonestr("{\"error\":\"couldnt set price\"}"));
//else if ( LP_mypriceset(&changed,rel,base,1./price) < 0 )
// return(clonestr("{\"error\":\"couldnt set price\"}"));
else if ( jobj(argjson,"broadcast") == 0 || jint(argjson,"broadcast") != 0 )
else if ( price == 0. || jobj(argjson,"broadcast") == 0 || jint(argjson,"broadcast") != 0 )
return(LP_pricepings(ctx,myipaddr,LP_mypubsock,base,rel,price * LP_profitratio));
else return(clonestr("{\"result\":\"success\"}"));
}
@ -432,6 +431,8 @@ instantdex_claim()\n\
if ( strcmp(ptr->symbol,"KMD") == 0 )
LP_importaddress("KMD",BOTS_BONDADDRESS);
}
if ( 0 && strcmp(coin,"BCH") == 0 )
test_validate(ptr,"010000000110b365ea6b8a9f2d56dc12de868e382dc787b2e29355f9b357dcf764c5e29cb1010000006b483045022100c605b993f1db5f31046ebb9065bea0a047f478342bbad8fcfc6af81d05236bd502206e9993a737a8814b935b5e522e750c915e7d37e3bd8367f087d4510f66acac47412102ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92ffffffff014bc22900000000001976a91459fdba29ea85c65ad90f6d38f7a6646476b26b1688ac00000000");
array = cJSON_CreateArray();
jaddi(array,LP_coinjson(ptr,0));
return(jprint(array,1));
@ -462,7 +463,7 @@ instantdex_claim()\n\
LP_address(ptr,coinaddr);
if ( strcmp(coinaddr,ptr->smartaddr) == 0 && bits256_nonz(G.LP_privkey) != 0 )
{
//LP_listunspent_issue(coin,coinaddr,2);
LP_listunspent_issue(coin,coinaddr,2,zero,zero);
//LP_privkey_init(-1,ptr,G.LP_privkey,G.LP_mypub25519);
}
return(jprint(LP_listunspent(coin,coinaddr,zero,zero),1));
@ -634,6 +635,27 @@ instantdex_claim()\n\
return(LP_notify_recv(argjson));
else if ( strcmp(method,"getpeers") == 0 )
retstr = clonestr("{\"error\":\"deprecated\"}");
else if ( strcmp(method,"balances") == 0 )
return(jprint(LP_balances(jstr(argjson,"address")),1));
else if ( strcmp(method,"fundvalue") == 0 )
return(jprint(LP_fundvalue(argjson),1));
else if ( strcmp(method,"getprice") == 0 )
{
double price,bid,ask;
ask = LP_price(base,rel);
if ( (bid= LP_price(rel,base)) > SMALLVAL )
bid = 1./bid;
price = _pairaved(bid,ask);
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddstr(retjson,"base",base);
jaddstr(retjson,"rel",rel);
jaddnum(retjson,"timestamp",time(NULL));
jaddnum(retjson,"bid",bid);
jaddnum(retjson,"ask",ask);
jaddnum(retjson,"price",price);
return(jprint(retjson,1));
}
/*else if ( strcmp(method,"getpeers") == 0 )
{
char *tmpstr;

29
iguana/exchanges/LP_include.h

@ -22,15 +22,19 @@
#define LP_INCLUDE_H
#ifdef FROMGUI
#define printf(...)
#define printf dontprintf
voind dontprintf(char *formatstr,...) {}
#endif
#define LP_MAJOR_VERSION "0"
#define LP_MINOR_VERSION "1"
#define LP_BUILD_NUMBER "17667"
#define LP_BUILD_NUMBER "17752"
#define LP_BARTERDEX_VERSION 1
#define LP_MAGICBITS 1
#define LP_DONT_IMPORTPRIVKEY
#ifdef FROM_JS
#include <emscripten.h>
#define sleep(x) emscripten_usleep((x) * 1000000)
@ -49,7 +53,7 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping
#define LP_HTTP_TIMEOUT 3 // 1 is too small due to edge cases of time(NULL)
#define LP_AUTOTRADE_TIMEOUT 60
#define LP_RESERVETIME 600 //(LP_AUTOTRADE_TIMEOUT * 2)
#define ELECTRUM_TIMEOUT 7
#define ELECTRUM_TIMEOUT 13
#define LP_ELECTRUM_KEEPALIVE 60
#define LP_ELECTRUM_MAXERRORS 777
#define LP_MEMPOOL_TIMEINCR 10
@ -180,12 +184,12 @@ struct vin_info
uint8_t rmd160[20],spendscript[10000],p2shscript[10000],userdata[10000];
};
struct basilisk_swapmessage
/*struct basilisk_swapmessage
{
bits256 srchash,desthash;
uint32_t crc32,msgbits,quoteid,datalen;
uint8_t *data;
};
};*/
struct basilisk_swap;
@ -294,7 +298,7 @@ struct iguana_info
int32_t numutxos,notarized,longestchain,firstrefht,firstscanht,lastscanht,bussock,height; uint16_t busport;
uint32_t dPoWtime,loadedcache,electrumlist,lastunspent,importedprivkey,lastpushtime,lastutxosync,addr_listunspent_requested,lastutxos,updaterate,counter,inactive,lastmempool,lastgetinfo,ratetime,heighttime,lastmonitor,obooktime;
uint8_t pubtype,p2shtype,isPoS,wiftype,wiftaddr,taddr,noimportprivkey_flag,userconfirms,isassetchain,maxconfirms;
char symbol[128],smartaddr[64],userpass[1024],serverport[128];
char symbol[128],smartaddr[64],userpass[1024],serverport[128],instantdex_address[64];
// portfolio
double price_kmd,force,perc,goal,goalperc,relvolume,rate;
void *electrum; void *ctx;
@ -363,6 +367,7 @@ struct LP_quoteinfo
{
struct basilisk_request R;
bits256 srchash,desthash,txid,txid2,desttxid,feetxid,privkey;
int64_t othercredits;
uint64_t satoshis,txfee,destsatoshis,desttxfee,aliceid;
uint32_t timestamp,quotetime,tradeid;
int32_t vout,vout2,destvout,feevout,pair;
@ -383,11 +388,10 @@ struct basilisk_swap
struct basilisk_swapinfo I;
struct basilisk_rawtx bobdeposit,bobpayment,alicepayment,myfee,otherfee,aliceclaim,alicespend,bobreclaim,bobspend,bobrefund,alicereclaim;
bits256 privkeys[INSTANTDEX_DECKSIZE];
struct basilisk_swapmessage *messages; int32_t nummessages,sentflag;
//struct basilisk_swapmessage *messages; int32_t nummessages,sentflag;
char Bdeposit[64],Bpayment[64];
uint64_t aliceid,otherdeck[INSTANTDEX_DECKSIZE][2],deck[INSTANTDEX_DECKSIZE][2];
uint8_t persistent_pubkey33[33],persistent_other33[33],changermd160[20],pad[15],verifybuf[100000];
};
struct LP_pubkey_quote
@ -483,6 +487,7 @@ int32_t LP_coinbus(uint16_t coin_busport);
int32_t LP_nanomsg_recvs(void *ctx);
int32_t LP_numconfirms(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t mempool);
void LP_aliceid(uint32_t tradeid,uint64_t aliceid,char *event,uint32_t requestid,uint32_t quoteid);
void LP_autoprices_update(char *method,char *base,double basevol,char *rel,double relvol);
cJSON *LP_cache_transaction(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len);
cJSON *LP_transaction_fromdata(struct iguana_info *coin,bits256 txid,uint8_t *serialized,int32_t len);
uint64_t LP_RTsmartbalance(struct iguana_info *coin);
@ -506,6 +511,9 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_
//void LP_butxo_swapfields_set(struct LP_utxoinfo *butxo);
struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout);
int64_t LP_myzcredits();
void test_validate(struct iguana_info *coin,char *signedtx);
void LP_instantdex_depositadd(char *coinaddr,bits256 txid);
int64_t LP_instantdex_creditcalc(struct iguana_info *coin,int32_t dispflag,bits256 txid,char *refaddr);
int32_t LP_destaddr(char *destaddr,cJSON *item);
int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration);
cJSON *LP_statslog_disp(uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey,char *refbase,char *refrel);
@ -517,6 +525,7 @@ cJSON *LP_transactioninit(struct iguana_info *coin,bits256 txid,int32_t iter,cJS
int32_t LP_mempoolscan(char *symbol,bits256 searchtxid);
int32_t LP_txheight(struct iguana_info *coin,bits256 txid);
int32_t LP_numpeers();
double LP_CMCbtcprice(double *price_usdp,char *symbol);
char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid,int32_t forceflag);
int64_t LP_KMDvalue(struct iguana_info *coin,int64_t balance);
int32_t LP_address_utxoadd(uint32_t timestamp,char *debug,struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout,uint64_t value,int32_t height,int32_t spendheight);
@ -527,6 +536,8 @@ cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout);
void LP_postutxos(char *symbol,char *coinaddr);
int32_t LP_listunspent_both(char *symbol,char *coinaddr,int32_t fullflag);
uint16_t LP_randpeer(char *destip);
void LP_tradebot_pauseall();
void LP_portfolio_reset();
uint32_t LP_atomic_locktime(char *base,char *rel);
struct LP_pubkey_info *LP_pubkeyfind(bits256 pubkey);
char *issue_LP_psock(char *destip,uint16_t destport,int32_t ispaired);
@ -538,7 +549,7 @@ int32_t LP_gettx_presence(char *symbol,bits256 expectedtxid);
double LP_getestimatedrate(struct iguana_info *coin);
struct LP_utxoinfo *_LP_utxofind(int32_t iambob,bits256 txid,int32_t vout);
struct LP_utxoinfo *_LP_utxo2find(int32_t iambob,bits256 txid,int32_t vout);
int64_t LP_dynamictrust(bits256 pubkey,int64_t kmdvalue);
int64_t LP_dynamictrust(int64_t credits,bits256 pubkey,int64_t kmdvalue);
struct LP_address *LP_addressfind(struct iguana_info *coin,char *coinaddr);
int64_t LP_outpoint_amount(char *symbol,bits256 txid,int32_t vout);

229
iguana/exchanges/LP_instantdex.c

@ -19,28 +19,36 @@
// marketmaker
//
void LP_instantdex_txidaddfname(char *fname,char *afname)
void LP_instantdex_txidaddfname(char *fname,char *afname,char *coinaddr)
{
sprintf(fname,"%s/instantdex.json",GLOBAL_DBDIR);
sprintf(afname,"%s/instantdex_append.json",GLOBAL_DBDIR);
if ( coinaddr == 0 || coinaddr[0] == 0 )
{
sprintf(fname,"%s/instantdex.json",GLOBAL_DBDIR);
sprintf(afname,"%s/instantdex_append.json",GLOBAL_DBDIR);
}
else
{
sprintf(fname,"%s/instantdex_%s.json",GLOBAL_DBDIR,coinaddr);
sprintf(afname,"%s/instantdex_%s_append.json",GLOBAL_DBDIR,coinaddr);
}
}
cJSON *LP_instantdex_txids()
cJSON *LP_instantdex_txids(int32_t appendonly,char *coinaddr)
{
char *filestr,fname[1024],afname[1024]; long fsize; cJSON *retjson=0;
LP_instantdex_txidaddfname(fname,afname);
if ( (filestr= OS_filestr(&fsize,fname)) != 0 )
LP_instantdex_txidaddfname(fname,afname,coinaddr);
if ( (filestr= OS_filestr(&fsize,appendonly != 0 ? afname : fname)) != 0 )
{
retjson = cJSON_Parse(filestr);
free(filestr);
} else printf("couldnt open (%s)\n",fname);
} else printf("couldnt open (%s) or (%s)\n",fname,afname);
return(retjson);
}
void LP_instantdex_filewrite(int32_t appendfile,cJSON *array)
void LP_instantdex_filewrite(int32_t appendfile,cJSON *array,char *coinaddr)
{
FILE *fp; char *filestr,fname[1024],afname[1024];
LP_instantdex_txidaddfname(fname,afname);
LP_instantdex_txidaddfname(fname,afname,coinaddr);
if ( (fp= fopen(appendfile == 0 ? fname : afname,"wb")) != 0 )
{
filestr = jprint(array,0);
@ -50,25 +58,99 @@ void LP_instantdex_filewrite(int32_t appendfile,cJSON *array)
}
}
void LP_instantdex_txidadd(bits256 txid)
void LP_instantdex_deposituniq(FILE *fp,bits256 txid)
{
cJSON *array; int32_t i,n;
if ( (array= LP_instantdex_txids()) == 0 )
array = cJSON_CreateArray();
if ( (n= cJSON_GetArraySize(array)) >= 0 )
int32_t i,n; bits256 prevtxid; char str[65];
n = (int32_t)(ftell(fp) / sizeof(txid));
for (i=0; i<n; i++)
{
fseek(fp,sizeof(prevtxid) * i,SEEK_SET);
fread(&prevtxid,1,sizeof(prevtxid),fp);
if ( bits256_cmp(prevtxid,txid) == 0 )
{
//printf("%s duplicate of deposits[%d]\n",bits256_str(str,prevtxid),i);
break;
}
}
if ( i == n )
{
fwrite(&txid,1,sizeof(txid),fp);
printf("uniq %s, ftell.%ld\n",bits256_str(str,txid),ftell(fp));
} else fseek(fp,n * sizeof(txid),SEEK_SET);
}
void LP_instantdex_filescreate(char *coinaddr)
{
char fname[512]; FILE *fp; bits256 txid; int32_t i,n; cJSON *array,*newarray,*txobj;
sprintf(fname,"%s/deposits.%s",GLOBAL_DBDIR,coinaddr), OS_compatible_path(fname);
if ( (fp= fopen(fname,"rb")) != 0 )
{
array = cJSON_CreateArray();
newarray = cJSON_CreateArray();
fseek(fp,0,SEEK_END);
n = (int32_t)(ftell(fp) / sizeof(txid));
for (i=0; i<n; i++)
if ( bits256_cmp(jbits256i(array,i),txid) == 0 )
break;
if ( i == n )
{
fseek(fp,sizeof(txid) * i,SEEK_SET);
fread(&txid,1,sizeof(txid),fp);
jaddibits256(array,txid);
LP_instantdex_filewrite(0,array);
LP_instantdex_filewrite(1,array);
if ( (txobj= LP_gettxout("KMD",coinaddr,txid,0)) != 0 )
free_json(txobj);
else
{
char str[65]; printf("%s/v%d is already spent\n",bits256_str(str,txid),0);
continue;
}
jaddibits256(newarray,txid);
}
}
if ( array != 0 )
fclose(fp);
LP_instantdex_filewrite(0,newarray,coinaddr);
free_json(newarray);
LP_instantdex_filewrite(1,array,coinaddr);
free_json(array);
}
}
void LP_instantdex_depositadd(char *coinaddr,bits256 txid)
{
FILE *fp; struct iguana_info *coin; char fname[512],*addr; bits256 prevtxid; cJSON *array; int32_t i,n,iter;
coin = LP_coinfind("KMD");
sprintf(fname,"%s/deposits.%s",GLOBAL_DBDIR,coinaddr), OS_compatible_path(fname);
if ( (fp= fopen(fname,"rb+")) == 0 )
{
if ( (fp= fopen(fname,"wb+")) != 0 )
{
for (iter=0; iter<4; iter++)
{
if ( iter < 2 )
addr = coinaddr;
else addr = "";
if ( coin != 0 && (array= LP_instantdex_txids(iter&1,addr)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
prevtxid = jbits256i(array,i);
//char str[65]; printf("instantdex iter.%d i.%d check %s\n",iter,i,bits256_str(str,prevtxid));
if ( LP_instantdex_creditcalc(coin,0,prevtxid,coinaddr) > 0 )
{
LP_instantdex_deposituniq(fp,prevtxid);
fflush(fp);
}
}
}
free_json(array);
}
}
}
} else fseek(fp,0,SEEK_END);
if ( fp != 0 && bits256_nonz(txid) != 0 )
{
LP_instantdex_deposituniq(fp,txid);
fclose(fp);
}
LP_instantdex_filescreate(coinaddr);
}
int32_t LP_deposit_addr(char *p2shaddr,uint8_t *script,uint8_t taddr,uint8_t p2shtype,uint32_t timestamp,uint8_t *pubsecp33)
@ -93,7 +175,7 @@ char *LP_instantdex_deposit(struct iguana_info *coin,int32_t weeks,double amount
{
timestamp = (uint32_t)time(NULL);
timestamp /= LP_WEEKMULT;
timestamp += weeks+1;
timestamp += weeks+2;
timestamp *= LP_WEEKMULT;
weeki = (timestamp - LP_FIRSTWEEKTIME) / LP_WEEKMULT;
if ( weeks >= 10000 )
@ -127,8 +209,6 @@ char *LP_instantdex_deposit(struct iguana_info *coin,int32_t weeks,double amount
if ( (obj= jobj(retjson,"complete")) != 0 && is_cJSON_True(obj) != 0 && (hexstr= jstr(retjson,"hex")) != 0 )
{
txid = jbits256(retjson,"txid");
if ( bits256_nonz(txid) != 0 )
LP_instantdex_txidadd(txid);
if ( broadcast != 0 )
{
if (bits256_nonz(txid) != 0 )
@ -145,6 +225,7 @@ char *LP_instantdex_deposit(struct iguana_info *coin,int32_t weeks,double amount
{
jaddstr(retjson,"result","success");
jaddbits256(retjson,"broadcast",sendtxid);
LP_instantdex_depositadd(coin->smartaddr,txid);
free(retstr);
return(jprint(retjson,1));
}
@ -186,7 +267,7 @@ int64_t LP_claimtx(void *ctx,struct iguana_info *coin,bits256 *claimtxidp,bits25
userdatalen = 1;
utxovout = 0;
memset(claimtxidp,0,sizeof(*claimtxidp));
char str[65]; printf("satoshis %.8f %s/v%d\n",dstr(satoshis),bits256_str(str,utxotxid),utxovout);
char str[65]; printf("LP_claimtx satoshis %.8f %s/v%d\n",dstr(satoshis),bits256_str(str,utxotxid),utxovout);
if ( (signedtx= basilisk_swap_bobtxspend(&signedtxid,10000,"instantdexclaim",coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,G.LP_privkey,0,redeemscript,redeemlen,userdata,userdatalen,utxotxid,utxovout,coin->smartaddr,G.LP_pubsecp,0,claimtime,&destamount,0,0,vinaddr,1,coin->zcash)) != 0 )
{
printf("signedtx.(%s)\n",signedtx);
@ -204,7 +285,7 @@ int64_t LP_claimtx(void *ctx,struct iguana_info *coin,bits256 *claimtxidp,bits25
int32_t LP_claim_submit(void *ctx,cJSON *txids,int64_t *sump,struct iguana_info *coin,bits256 utxotxid)
{
uint8_t redeemscript[512]; bits256 claimtxid; cJSON *txjson,*vout0,*vout1,*vout2,*vouts,*item; int32_t numvouts; char str[65],vinaddr[64],destaddr[64],checkaddr[64]; int32_t j,utxovout,flagi = 0,redeemlen,weeki; int64_t weeksatoshis,satoshis; uint32_t expiration,claimtime;
uint8_t redeemscript[512]; bits256 claimtxid; cJSON *txjson,*vout0,*vout1,*vout2,*vouts,*item; int32_t numvouts; char str[65],vinaddr[64],destaddr[64],checkaddr[64]; int32_t j,utxovout,flagi = 0,redeemlen,weeki,iter; int64_t weeksatoshis,satoshis; uint32_t expiration,claimtime;
if ( (txjson= LP_gettx(coin->symbol,utxotxid,1)) != 0 )
{
if ( (vouts= jarray(&numvouts,txjson,"vout")) != 0 && numvouts >= 3 )
@ -219,10 +300,11 @@ int32_t LP_claim_submit(void *ctx,cJSON *txids,int64_t *sump,struct iguana_info
vout1 = jitem(vouts,1);
weeksatoshis = LP_value_extract(vout1,0);
weeki = (int32_t)(weeksatoshis % 10000);
for (j=0; j<2*168; j++)
for (iter=0; iter<2; iter++)
for (j=-168; j<=168; j++)
{
if ( j >= 168 )
expiration = ((weeki * LP_WEEKMULTBAD + (j-168)*3600) + LP_FIRSTWEEKTIME);
if ( iter == 1 )
expiration = ((weeki * LP_WEEKMULTBAD + j*3600) + LP_FIRSTWEEKTIME);
else expiration = ((weeki * LP_WEEKMULT + j*3600) + LP_FIRSTWEEKTIME);
redeemlen = LP_deposit_addr(checkaddr,redeemscript,coin->taddr,coin->p2shtype,expiration,G.LP_pubsecp);
if ( strcmp(checkaddr,vinaddr) == 0 )
@ -237,7 +319,7 @@ int32_t LP_claim_submit(void *ctx,cJSON *txids,int64_t *sump,struct iguana_info
else jaddnum(item,"interest",dstr(LP_komodo_interest(utxotxid,satoshis)));
if ( claimtime <= expiration )
{
printf("claimtime.%u vs %u, wait %d seconds to %s claim %.8f\n",claimtime,expiration,(int32_t)expiration-claimtime,bits256_str(str,utxotxid),dstr(satoshis));
printf("iter.%d j.%d claimtime.%u vs %u, wait %d seconds to %s claim %.8f\n",iter,j,claimtime,expiration,(int32_t)expiration-claimtime,bits256_str(str,utxotxid),dstr(satoshis));
jaddnum(item,"waittime",(int32_t)expiration-claimtime);
jaddi(txids,item);
break;
@ -259,13 +341,13 @@ int32_t LP_claim_submit(void *ctx,cJSON *txids,int64_t *sump,struct iguana_info
} else printf("vout2 dest.(%s) != %s\n",destaddr,coin->smartaddr);
} else printf("numvouts %d != 3\n",numvouts);
free_json(txjson);
} else printf("cant get transaction\n");
} else printf("cant get transaction flagi.%d\n",flagi);
return(flagi);
}
char *LP_instantdex_claim(struct iguana_info *coin)
{
static void *ctx;
static void *ctx; static int32_t firsttime = 1;
int32_t i,n; cJSON *array,*txids,*newarray,*retjson; int64_t sum; bits256 utxotxid;
if ( ctx == 0 )
ctx = bitcoin_ctx();
@ -274,7 +356,7 @@ char *LP_instantdex_claim(struct iguana_info *coin)
sum = 0;
txids = cJSON_CreateArray();
newarray = cJSON_CreateArray();
if ( (array= LP_instantdex_txids()) != 0 )
if ( (array= LP_instantdex_txids(firsttime,coin->smartaddr)) != 0 )
{
printf("claiming from.(%s)\n",jprint(array,0));
if ( (n= cJSON_GetArraySize(array)) > 0 )
@ -282,14 +364,16 @@ char *LP_instantdex_claim(struct iguana_info *coin)
for (i=0; i<n; i++)
{
utxotxid = jbits256i(array,i);
//char str[65]; printf("%s\n",bits256_str(str,utxotxid));
if ( LP_claim_submit(ctx,txids,&sum,coin,utxotxid) == 0 )
jaddibits256(newarray,utxotxid);
}
}
free_json(array);
}
firsttime = 0;
if ( cJSON_GetArraySize(newarray) > 0 )
LP_instantdex_filewrite(0,newarray);
LP_instantdex_filewrite(0,newarray,coin->smartaddr);
free_json(newarray);
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
@ -308,9 +392,7 @@ int64_t LP_instantdex_credit(int32_t dispflag,char *coinaddr,int64_t satoshis,in
{
ap->instantdex_credits += satoshis;
ap->didinstantdex = 1;
if ( strcmp(coinaddr,coin->smartaddr) == 0 )
LP_instantdex_txidadd(txid);
if ( dispflag != 0 )
if ( 0 && dispflag != 0 )
printf("InstantDEX credit.(%s) %.8f weeki.%d (%s) -> sum %.8f\n",coinaddr,dstr(satoshis),weeki,p2shaddr,dstr(ap->instantdex_credits));
return(satoshis);
} //else printf("null ap.%p or expired %ld\n",ap,time(NULL) - (timestamp-60*3600));
@ -336,14 +418,14 @@ int64_t LP_instantdex_creditcalc(struct iguana_info *coin,int32_t dispflag,bits2
weeki = (amount64 % 10000);
item = jitem(vouts,0);
satoshis = LP_value_extract(item,0);
//printf("%s %s funded %.8f weeki.%d (%s)\n",bits256_str(str,txid),destaddr,dstr(satoshis),weeki,jprint(item,0));
//char str[65]; printf("%s %s funded %.8f weeki.%d (%s)\n",bits256_str(str,txid),destaddr,dstr(satoshis),weeki,jprint(item,0));
if ( LP_destaddr(p2shaddr,item) == 0 )
{
if ( (txobj= LP_gettxout(coin->symbol,p2shaddr,txid,0)) != 0 )
{
free_json(txobj);
LP_instantdex_credit(dispflag,destaddr,satoshis,weeki,p2shaddr,txid);
} else printf("already spent\n");
} //else printf("already spent\n");
} else printf("error getting p2shaddr.(%s)\n",p2shaddr);
}
}
@ -384,51 +466,78 @@ void LP_instantdex_deposits(struct iguana_info *coin)
}
#endif
int64_t LP_dynamictrust(bits256 pubkey,int64_t kmdvalue)
int64_t LP_dynamictrust(int64_t credits,bits256 pubkey,int64_t kmdvalue)
{
struct LP_pubswap *ptr,*tmp; struct LP_swapstats *sp; struct LP_pubkey_info *pubp; struct LP_address *ap; char coinaddr[64]; struct iguana_info *coin; int64_t swaps_kmdvalue = 0;
if ( (coin= LP_coinfind("KMD")) != 0 && (pubp= LP_pubkeyfind(pubkey)) != 0 )
{
bitcoin_address(coinaddr,coin->taddr,coin->pubtype,pubp->pubsecp,33);
if ((ap= LP_address(coin,coinaddr)) != 0 )//&& ap->instantdex_credits >= kmdvalue )
DL_FOREACH_SAFE(pubp->bobswaps,ptr,tmp)
{
DL_FOREACH_SAFE(pubp->bobswaps,ptr,tmp)
{
if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 )
swaps_kmdvalue += LP_kmdvalue(sp->Q.srccoin,sp->Q.satoshis);
}
DL_FOREACH_SAFE(pubp->aliceswaps,ptr,tmp)
if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 )
swaps_kmdvalue += LP_kmdvalue(sp->Q.srccoin,sp->Q.satoshis);
}
DL_FOREACH_SAFE(pubp->aliceswaps,ptr,tmp)
{
if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 )
swaps_kmdvalue += LP_kmdvalue(sp->Q.destcoin,sp->Q.destsatoshis);
}
if ( credits == 0 && (ap= LP_address(coin,coinaddr)) != 0 )
credits = ap->instantdex_credits;
if ( credits != 0 && (swaps_kmdvalue+kmdvalue) > credits )
{
if ( 0 )
{
if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 )
swaps_kmdvalue += LP_kmdvalue(sp->Q.destcoin,sp->Q.destsatoshis);
DL_FOREACH_SAFE(pubp->bobswaps,ptr,tmp)
{
if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 )
printf("unfinished bob %llu r%u-r%u src.%s %.8f dest.%s %.8f -> price %.8f value %.8f\n",(long long)sp->aliceid,sp->Q.R.requestid,sp->Q.R.quoteid,sp->Q.srccoin,dstr(sp->Q.satoshis),sp->Q.destcoin,dstr(sp->Q.destsatoshis),(double)sp->Q.destsatoshis/(sp->Q.satoshis+1),dstr(LP_kmdvalue(sp->Q.destcoin,sp->Q.destsatoshis)));
}
DL_FOREACH_SAFE(pubp->aliceswaps,ptr,tmp)
{
if ( (sp= ptr->swap) != 0 && LP_swap_finished(sp,1) == 0 )
printf("unfinished alice %llu r%u-r%u src.%s %.8f dest.%s %.8f -> price %.8f value %.8f\n",(long long)sp->aliceid,sp->Q.R.requestid,sp->Q.R.quoteid,sp->Q.srccoin,dstr(sp->Q.satoshis),sp->Q.destcoin,dstr(sp->Q.destsatoshis),(double)sp->Q.destsatoshis/(sp->Q.satoshis+1),dstr(LP_kmdvalue(sp->Q.destcoin,sp->Q.destsatoshis)));
}
}
if ( ap->instantdex_credits != 0 && (swaps_kmdvalue+kmdvalue) > ap->instantdex_credits )
printf("%s instantdex_credits %.8f vs (%.8f + current %.8f)\n",coinaddr,dstr(ap->instantdex_credits),dstr(swaps_kmdvalue),dstr(kmdvalue));
//if ( ap->instantdex_credits > swaps_kmdvalue+kmdvalue )
return(ap->instantdex_credits - (swaps_kmdvalue+kmdvalue));
printf("REJECT: %s instantdex_credits %.8f vs (%.8f + current %.8f)\n",coinaddr,dstr(credits),dstr(swaps_kmdvalue),dstr(kmdvalue));
}
if ( 0 && credits != 0 )
printf("%s %s othercredits %.8f debits %.8f + %.8f -> %.8f\n",coin->symbol,coinaddr,dstr(credits),dstr(swaps_kmdvalue),dstr(kmdvalue),dstr(credits - (swaps_kmdvalue+kmdvalue)));
return(credits - (swaps_kmdvalue+kmdvalue));
}
return(0);
}
int64_t LP_instantdex_proofcheck(char *coinaddr,cJSON *proof,int32_t num)
{
uint8_t rmd160[20],addrtype; int32_t i; int64_t net = 0; char othersmartaddr[64]; struct iguana_info *coin; struct LP_address *ap = 0;
uint8_t rmd160[20],addrtype; int64_t credits=0; int32_t i,j; bits256 prevtxid,txid; char othersmartaddr[64]; struct iguana_info *coin; struct LP_address *ap = 0;
if ( (coin= LP_coinfind("KMD")) != 0 )
{
bitcoin_addr2rmd160(0,&addrtype,rmd160,coinaddr);
bitcoin_address(othersmartaddr,0,60,rmd160,20);
if ((ap= LP_address(coin,othersmartaddr)) != 0 )//&& (coin->electrum == 0 || ap->didinstantdex == 0) )
//printf("proofcheck addrtype.%d (%s) -> %s\n",addrtype,coinaddr,othersmartaddr);
if ((ap= LP_address(coin,othersmartaddr)) != 0 )
{
ap->instantdex_credits = 0;
for (i=0; i<num; i++)
LP_instantdex_creditcalc(coin,1,jbits256i(proof,i),othersmartaddr);
{
txid = jbits256i(proof,i);
for (j=0; j<i; j++)
{
prevtxid = jbits256i(proof,j);
if ( bits256_cmp(prevtxid,txid) == 0 )
break;
}
if ( j == i )
LP_instantdex_creditcalc(coin,1,txid,othersmartaddr);
}
credits = ap->instantdex_credits;
ap->didinstantdex = 1;
//if ( ap->instantdex_credits > 0 )
printf("validated instantdex %s.[%d] proof.(%s) credits %.8f net %.8f\n",othersmartaddr,num,jprint(proof,0),dstr(ap->instantdex_credits),dstr(net));
if ( 0 && ap->instantdex_credits > 0 )
printf("validated instantdex %s.[%d] proof.(%s) credits %.8f\n",othersmartaddr,num,jprint(proof,0),dstr(ap->instantdex_credits));
} //else printf("cant find ap.%p or already did %d %.8f\n",ap,ap!=0?ap->didinstantdex:-1,ap!=0?dstr(ap->instantdex_credits):-1);
}
return(ap->instantdex_credits);
return(credits);
}
int64_t LP_myzcredits()
@ -436,7 +545,7 @@ int64_t LP_myzcredits()
cJSON *proof; struct iguana_info *coin; int64_t zcredits;
if ( (coin= LP_coinfind("KMD")) != 0 )
{
if ( (proof= LP_instantdex_txids()) != 0 )
if ( (proof= LP_instantdex_txids(0,coin->smartaddr)) != 0 )
{
zcredits = LP_instantdex_proofcheck(coin->smartaddr,proof,cJSON_GetArraySize(proof));
free_json(proof);

708
iguana/exchanges/LP_mmjson.c

@ -0,0 +1,708 @@
/******************************************************************************
* 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. *
* *
******************************************************************************/
//
// LP_mmjson.c
// marketmaker
//
#define MMJSON_IPADDR 255
#define MMJSON_BITS256 254
#define MMJSON_SECP33 253
#define MMJSON_SIG 252
#define MMJSON_RMD160 251
#define MMJSON_DECIMAL8 250
#define MMJSON_DECIMAL8STR 249
#define MMJSON_DECIMAL16 248
#define MMJSON_DECIMAL16STR 247
#define MMJSON_DECIMAL24 246
#define MMJSON_DECIMAL24STR 245
#define MMJSON_DECIMAL32 244
#define MMJSON_DECIMAL32STR 243
#define MMJSON_DECIMAL40 242
#define MMJSON_DECIMAL40STR 241
#define MMJSON_DECIMAL48 240
#define MMJSON_DECIMAL48STR 239
#define MMJSON_DOUBLE 238
#define MMJSON_DECIMAL64 237
#define MMJSON_DECIMAL64STR 236
#define MMJSON_TIMESTAMP 235
#define MMJSON_TIMEDIFF8 234
#define MMJSON_TIMEDIFF16 233
#define MMJSON_ZERO 232
#define MMJSON_ZEROSTR 231
#define MMJSON_COIN 230
#define MMJSON_STRING 229
#define MMJSON_ARRAY8 228
#define MMJSON_ARRAY16 227
#define MMJSON_ARRAY32 226
#define MMJSON_BOUNDARY 98
int32_t MM_numfields;
char *MM_fields[256] =
{
"timestamp", "getdPoW", "dPoW", "aliceid", "src", "base", "basevol", "dest", "rel", "relvol", "price", "requestid", "quoteid", "finished", "expired", "bobdeposit", "alicepayment", "bobpayment", "paymentspent", "Apaymentspent", "depositspent", "ind", "method", "swapstatus", "method2", "gettradestatus", "coin", "rmd160", "pub", "pubsecp", "sig", "session", "notify", "pubkey", "price64", "credits", "utxocoin", "n", "bal", "min", "max", "postprice", "notarized", "notarizedhash", "notarizationtxid", "wantnotify", "isLP", "gui", "nogui", "tradeid", "address", "txid", "vout", "srchash", "txfee", "quotetime", "satoshis", "desthash", "txid2", "vout2", "destaddr", "desttxid", "destvout", "feetxid", "feevout", "desttxfee", "destsatoshis", "pending", "reserved", "broadcast", "ismine", "simplegui", "request", "proof", "connect", "expiration", "iambob", "Bgui", "", "Agui", "bob", "srcamount", "bobtxfee", "alice", "destamount", "alicetxfee", "sentflags", "values", "result", "success", "status", "finishtime", "tradestatus", "pair", "connected", "warning", "critical", "endcritical",
};
char *MM_coins[256] =
{
"KMD", "BTC", "CRC", "VOT", "INN", "MOON", "CRW", "EFL", "GBX", "BCO", "BLK", "BTG", "BCH", "ABY", "STAK", "XZC", "QTUM", "PURA", "DSR", "MNZ", "BTCZ", "MAGA", "BSD", "IOP", "BLOCK", "CHIPS", "888", "ARG", "GLT", "ZER", "HODLC", "UIS", "HUC", "PIVX", "BDL", "ARC", "ZCL", "VIA", "ERC", "FAIR", "FLO", "SXC", "CREA", "TRC", "BTA", "SMC", "NMC", "NAV", "EMC2", "SYS", "I0C", "DASH", "STRAT", "MUE", "MONA", "XMY", "MAC", "BTX", "XRE", "LBC", "SIB", "VTC", "REVS", "JUMBLR", "DOGE", "HUSH", "ZEC", "DGB", "ZET", "GAME", "LTC", "SUPERNET", "WLC", "PANGEA", "DEX", "BET", "CRYPTO", "HODL", "MSHARK", "BOTS", "MGW", "COQUI", "KV", "CEAL", "MESH",
};
int32_t mmjson_coinfind(char *symbol)
{
int32_t i;
for (i=0; i<sizeof(MM_coins)/sizeof(*MM_coins); i++)
{
if ( MM_coins[i] == 0 )
return(-1);
if ( strcmp(MM_coins[i],symbol) == 0 )
return(i);
}
return(-1);
};
int32_t mmadd(char *field)
{
MM_fields[MM_numfields] = calloc(1,strlen(field)+1);
strcpy(MM_fields[MM_numfields],field);
return(MM_numfields++);
}
int32_t mmfind(char *field)
{
int32_t i;
if ( MM_numfields == 0 )
{
for (i=0; i<sizeof(MM_fields)/sizeof(*MM_fields); i++)
if ( MM_fields[i] == 0 )
break;
MM_numfields = i;
}
for (i=0; i<MM_numfields; i++)
{
if ( strcmp(MM_fields[i],field) == 0 )
return(i);
}
return(-1);
}
int32_t MMJSON_rwnum(int32_t rwflag,uint8_t *buf,uint64_t *longp,int32_t n)
{
int32_t i; uint64_t l = 0;
if ( rwflag != 0 )
{
l = *longp;
for (i=0; i<n; i++)
{
buf[i] = (uint8_t)l;
l >>= 8;
}
}
else
{
for (i=n-1; i>=0; i--)
{
l <<= 8;
l |= buf[i];
}
*longp = l;
}
return(n);
}
int32_t MMJSON_decodeitem(cJSON *lineobj,uint8_t *linebuf,int32_t i,int32_t len,char *fieldstr,uint32_t *timestampp)
{
int32_t c,valind,j; char tmpstr[64],ipaddr[64],hexstr[256],arbstr[8192]; uint64_t l;
switch ( (valind= linebuf[i++]) )
{
case MMJSON_IPADDR:
i += MMJSON_rwnum(0,&linebuf[i],&l,4);
expand_ipbits(ipaddr,(uint32_t)l);
jaddstr(lineobj,fieldstr,ipaddr);
break;
case MMJSON_BITS256:
init_hexbytes_noT(hexstr,&linebuf[i],32);
i += 32;
jaddstr(lineobj,fieldstr,hexstr);
break;
case MMJSON_SECP33:
init_hexbytes_noT(hexstr,&linebuf[i],33);
i += 33;
jaddstr(lineobj,fieldstr,hexstr);
break;
case MMJSON_SIG:
init_hexbytes_noT(hexstr,&linebuf[i],65);
i += 65;
jaddstr(lineobj,fieldstr,hexstr);
break;
case MMJSON_RMD160:
init_hexbytes_noT(hexstr,&linebuf[i],20);
i += 20;
jaddstr(lineobj,fieldstr,hexstr);
break;
case MMJSON_DECIMAL8:
l = linebuf[i++];
jaddnum(lineobj,fieldstr,l);
break;
case MMJSON_DECIMAL8STR:
l = linebuf[i++];
jadd64bits(lineobj,fieldstr,l);
break;
case MMJSON_DECIMAL16:
i += MMJSON_rwnum(0,&linebuf[i],&l,2);
jaddnum(lineobj,fieldstr,l);
break;
case MMJSON_DECIMAL16STR:
i += MMJSON_rwnum(0,&linebuf[i],&l,2);
jadd64bits(lineobj,fieldstr,l);
break;
case MMJSON_DECIMAL24:
i += MMJSON_rwnum(0,&linebuf[i],&l,3);
jaddnum(lineobj,fieldstr,l);
break;
case MMJSON_DECIMAL24STR:
i += MMJSON_rwnum(0,&linebuf[i],&l,3);
sprintf(tmpstr,"%llu",(long long)l);
jaddstr(lineobj,fieldstr,tmpstr);
break;
case MMJSON_DECIMAL32:
i += MMJSON_rwnum(0,&linebuf[i],&l,4);
//printf("decimal32.%u %08x\n",(uint32_t)l,(uint32_t)l);
jaddnum(lineobj,fieldstr,l);
break;
case MMJSON_DECIMAL32STR:
i += MMJSON_rwnum(0,&linebuf[i],&l,4);
//printf("decimal32.%u %08x\n",(uint32_t)l,(uint32_t)l);
jadd64bits(lineobj,fieldstr,l);
break;
case MMJSON_DECIMAL40:
i += MMJSON_rwnum(0,&linebuf[i],&l,5);
jaddnum(lineobj,fieldstr,l);
break;
case MMJSON_DECIMAL40STR:
i += MMJSON_rwnum(0,&linebuf[i],&l,5);
jadd64bits(lineobj,fieldstr,l);
break;
case MMJSON_DECIMAL48:
i += MMJSON_rwnum(0,&linebuf[i],&l,6);
jaddnum(lineobj,fieldstr,l);
break;
case MMJSON_DECIMAL48STR:
i += MMJSON_rwnum(0,&linebuf[i],&l,6);
jadd64bits(lineobj,fieldstr,l);
break;
case MMJSON_DOUBLE:
i += MMJSON_rwnum(0,&linebuf[i],&l,8);
//printf("double %llu -> %.8f\n",(long long)l,dstr(l));
jaddnum(lineobj,fieldstr,dstr(l));
break;
case MMJSON_DECIMAL64:
i += MMJSON_rwnum(0,&linebuf[i],&l,8);
jadd64bits(lineobj,fieldstr,l);
break;
case MMJSON_DECIMAL64STR:
i += MMJSON_rwnum(0,&linebuf[i],&l,8);
jadd64bits(lineobj,fieldstr,l);
break;
case MMJSON_TIMESTAMP:
if ( *timestampp == 0 )
{
i += MMJSON_rwnum(0,&linebuf[i],&l,4);
*timestampp = (uint32_t)l;
jaddnum(lineobj,fieldstr,l);
}
else
{
printf("timestamp %u already exists\n",*timestampp);
free_json(lineobj);
return(-1);
}
break;
case MMJSON_TIMEDIFF8:
jaddnum(lineobj,fieldstr,*timestampp + linebuf[i++]);
break;
case MMJSON_TIMEDIFF16:
i += MMJSON_rwnum(0,&linebuf[i],&l,2);
jaddnum(lineobj,fieldstr,*timestampp + l);
break;
case MMJSON_ZERO:
jaddnum(lineobj,fieldstr,0);
break;
case MMJSON_ZEROSTR:
//printf("%s.zerostr\n",fieldstr);
jadd64bits(lineobj,fieldstr,0);
break;
case MMJSON_COIN:
jaddstr(lineobj,fieldstr,MM_coins[linebuf[i++]]);
break;
case MMJSON_STRING:
j = 0;
while ( (c= linebuf[i++]) != 0 )
{
if ( i > len )
{
printf("string overflow i.%d vs len.%d\n",i,len);
free_json(lineobj);
return(-1);
}
arbstr[j++] = c;
}
arbstr[j] = 0;
jaddstr(lineobj,fieldstr,arbstr);
break;
default:
if ( valind < MMJSON_BOUNDARY )
jaddstr(lineobj,fieldstr,MM_fields[valind]);
else
{
printf("%s unhandled valind.%d k.%d len.%d (%s)\n",fieldstr,valind,i,len,jprint(lineobj,0));
free_json(lineobj);
return(-1);
}
break;
}
return(i);
}
char *MMJSON_decode(uint8_t *linebuf,int32_t len)
{
uint32_t timestamp = 0; char *fieldstr; uint64_t l; int32_t ind,i=0,j,m=-1; cJSON *obj,*item,*array,*lineobj = cJSON_CreateObject();
while ( i+1 < len )
{
//printf("ind.%d i.%d vs len.%d\n",linebuf[i],i,len);
if ( (ind= linebuf[i++]) >= MMJSON_BOUNDARY )
{
if ( ind != MMJSON_STRING )
{
printf("illegal field ind.%d (%s)\n",ind,jprint(lineobj,0));
free_json(lineobj);
return(0);
}
else
{
fieldstr = (char *)&linebuf[i++];
while ( linebuf[i] != 0 )
i++;
i++;
}
} else fieldstr = MM_fields[ind];
if ( linebuf[i] == MMJSON_ARRAY8 )
{
i++;
m = linebuf[i++];
}
else if ( linebuf[i] == MMJSON_ARRAY16 )
{
i++;
i += MMJSON_rwnum(0,&linebuf[i],&l,2);
m = (int32_t)l;
}
else if ( linebuf[i] == MMJSON_ARRAY32 )
{
i++;
i += MMJSON_rwnum(0,&linebuf[i],&l,4);
m = (int32_t)l;
} else m = -1;
if ( m >= 0 )
{
//printf("%s i.%d m.%d\n",fieldstr,i,m);
array = cJSON_CreateArray();
for (j=0; j<m; j++)
{
item = cJSON_CreateObject();
if ( (i= MMJSON_decodeitem(item,linebuf,i,len,fieldstr,&timestamp)) < 0 )
{
printf("error decoding item ind.%s (%s)\n",fieldstr,jprint(lineobj,0));
free_json(array);
free_json(lineobj);
return(0);
}
obj = jobj(item,fieldstr);
jaddi(array,jduplicate(obj));
free_json(item);
}
jadd(lineobj,fieldstr,array);
}
else if ( (i= MMJSON_decodeitem(lineobj,linebuf,i,len,fieldstr,&timestamp)) < 0 )
{
printf("error decoding item ind.%s (%s)\n",fieldstr,jprint(lineobj,0));
free_json(lineobj);
return(0);
}
//printf("i.%d/%d ind.%d %s valind.%d\n",i,len,ind,MM_fields[ind],linebuf[i]);
}
return(jprint(lineobj,1));
}
int32_t MMJSON_encodeval(uint8_t *linebuf,int32_t k,int32_t ind,char *v,uint32_t *timestampp,cJSON *ptr,char *fieldstr)
{
double val; char checkstr[512]; uint64_t l; int32_t valind,len,isstr=0,coinind,j,dots,diff;
if ( ind >= 0 )
{
fieldstr = MM_fields[ind];
if ( strcmp("utxocoin",fieldstr) == 0 || strcmp("alice",fieldstr) == 0 || strcmp("bob",fieldstr) == 0 || strcmp("base",fieldstr) == 0 || strcmp("rel",fieldstr) == 0 || strcmp("coin",fieldstr) == 0 || strcmp("txfee",fieldstr) == 0 || strcmp("desttxfee",fieldstr) == 0 || strcmp("price64",fieldstr) == 0 || strcmp("satoshis",fieldstr) == 0 || strcmp("destsatoshis",fieldstr) == 0 )
isstr = 1;
else isstr = 0;
}
//printf("%s.(%s) k.%d\n",fieldstr,v,k);
if ( (valind= mmfind(v)) >= 0 )
{
linebuf[k++] = valind;
return(k);
}
else if ( strcmp("0",v) == 0 )
{
if ( isstr != 0 )
linebuf[k++] = MMJSON_ZEROSTR;
else linebuf[k++] = MMJSON_ZERO;
return(k);
}
for (j=dots=0; v[j]!=0; j++)
{
if ( (v[j] < '0' || v[j] > '9') && v[j] != '.' )
break;
else if ( v[j] == '.' )
dots++;
}
if ( dots == 3 && v[j] == 0 && strlen(v) < 17 && is_ipaddr(v) != 0 )
{
//printf("<ipaddr> ");
linebuf[k++] = MMJSON_IPADDR;
l = calc_ipbits(v);
k += MMJSON_rwnum(1,&linebuf[k],&l,4);
}
else if ( dots == 1 && v[j] == 0 )
{
if ( (val= atof(v)) > SMALLVAL )
{
l = SATOSHIDEN * (val + 0.000000005);
sprintf(checkstr,"%.8f",dstr(l));
if ( strcmp(checkstr,v) == 0 )
{
//printf("<double> ");
linebuf[k++] = MMJSON_DOUBLE;
k += MMJSON_rwnum(1,&linebuf[k],&l,8);
} else printf("ERR.<%s %s> ",v,checkstr);
}
}
else if ( (len= is_hexstr(v,0)) == 64 )
{
//printf("<bits256> ");
linebuf[k++] = MMJSON_BITS256;
decode_hex(&linebuf[k],32,v), k += 32;
}
else if ( len == 66 )
{
//printf("<secp33> ");
linebuf[k++] = MMJSON_SECP33;
decode_hex(&linebuf[k],33,v), k += 33;
}
else if ( len == 65*2 )
{
//printf("<sig> ");
linebuf[k++] = MMJSON_SIG;
decode_hex(&linebuf[k],65,v), k += 65;
}
else if ( len == 40 )
{
//printf("<rmd160> ");
linebuf[k++] = MMJSON_RMD160;
decode_hex(&linebuf[k],20,v), k += 20;
}
else if ( len > 40 )
{
printf("ERR.<hex.%d> ",len/2);
}
else if ( is_decimalstr(v) != 0 && (l= calc_nxt64bits(v)) > 0 )
{
if ( l < 0x100 )
{
//printf("<decimal8> ");
if ( l == 0 )
{
linebuf[k++] = isstr != 0 ? MMJSON_ZEROSTR : MMJSON_ZERO;
}
else
{
linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL8STR : MMJSON_DECIMAL8;
linebuf[k++] = (uint8_t)l;
}
}
else if ( l < 0x10000 )
{
//printf("<decimal16> ");
linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL16STR : MMJSON_DECIMAL16;
k += MMJSON_rwnum(1,&linebuf[k],&l,2);
}
else if ( l < 0x1000000 )
{
linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL24STR : MMJSON_DECIMAL24;
//printf("decimal24 %llu %s (%s) %d\n",(long long)l,v,fieldstr,linebuf[k-1]);
k += MMJSON_rwnum(1,&linebuf[k],&l,3);
}
else if ( l < 0x100000000LL )
{
if ( v[0] != '"' && *timestampp == 0 && strcmp(fieldstr,"timestamp") == 0 )
{
*timestampp = (uint32_t)atol(v);
//printf("<timestamp> ");
linebuf[k++] = MMJSON_TIMESTAMP;
l = *timestampp;
k += MMJSON_rwnum(1,&linebuf[k],&l,4);
}
else if ( v[0] != '"' && *timestampp != 0 && (diff= ((uint32_t)atol(v)-*timestampp)) < 0x100 && diff >= 0 )
{
//printf("<timediff.8> ");
linebuf[k++] = MMJSON_TIMEDIFF8;
linebuf[k++] = (uint8_t)diff;
}
else if ( v[0] != '"' && *timestampp != 0 && (diff= ((uint32_t)atol(v)-*timestampp)) < 0x10000 && diff >= 0 )
{
//printf("<timediff.16> ");
linebuf[k++] = MMJSON_TIMEDIFF16;
l = diff;
k += MMJSON_rwnum(1,&linebuf[k],&l,2);
}
else
{
//printf("<decimal32>.%u %08x\n",(uint32_t)l,(uint32_t)l);
linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL32STR : MMJSON_DECIMAL32;
k += MMJSON_rwnum(1,&linebuf[k],&l,4);
}
}
else if ( l < 0x10000000000LL )
{
//printf("<decimal40> ");
linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL40STR : MMJSON_DECIMAL40;
k += MMJSON_rwnum(1,&linebuf[k],&l,5);
}
else if ( l < 0x1000000000000LL )
{
//printf("<decimal48> ");
linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL48STR : MMJSON_DECIMAL48;
k += MMJSON_rwnum(1,&linebuf[k],&l,6);
}
//else if ( l < 0x100000000000000LL )
// printf("<decimal56> ");
else
{
//printf("<decimal64> ");
linebuf[k++] = isstr != 0 ? MMJSON_DECIMAL64STR : MMJSON_DECIMAL64;
k += MMJSON_rwnum(1,&linebuf[k],&l,8);
}
}
else
{
if ( (ind= mmfind(v)) >= 0 )
linebuf[k++] = ind;
else
{
for (j=0; v[j]!=0; j++)
{
if ( v[j] >= 'a' && v[j] <= 'z' )
continue;
else break;
}
if ( v[j] == 0 )
{
printf("unexpected missing string value.(%s)\n",v);
//ind = mmadd(v);
//printf("%s.<%s>.%d ",s,v,ind);
//linebuf[k++] = ind;
linebuf[k++] = MMJSON_STRING;
memcpy(&linebuf[k],v,strlen(v)+1);
k += (int32_t)strlen(v) + 1;
}
else
{
for (j=0; v[j]!=0; j++)
{
if ( v[j] >= 'A' && v[j] <= 'Z' )
continue;
else break;
}
if ( v[j] == 0 && (coinind= mmjson_coinfind(v)) >= 0 )
{
//printf("<coin> ");
linebuf[k++] = MMJSON_COIN;
linebuf[k++] = coinind;
}
/*else if ( strlen(v) == 34 )
{
printf("<coinaddr> ");
k += 22;
}*/
else
{
linebuf[k++] = MMJSON_STRING;
if ( v[0] == '"' )
{
v++;
v[strlen(v)-1] = 0;
}
//printf("str.<%s> ",v);
memcpy(&linebuf[k],v,strlen(v)+1);
k += (int32_t)strlen(v) + 1;
}
}
}
}
return(k);
}
int32_t MMJSON_encode(uint8_t *linebuf,char *line)
{
uint32_t timestamp; uint64_t l; char *decodestr,*s,*v=0; cJSON *lineobj,*array,*ptr; int32_t k=0,m,i,asize,ind,z,allocv_flag;
timestamp = 0;
if ( (lineobj= cJSON_Parse(line)) != 0 )
{
if ( line[strlen(line)-1] == '\n' )
line[strlen(line)-1] = 0;
//printf("%s\n",jprint(lineobj,0));
if ( (m= cJSON_GetArraySize(lineobj)) > 0 )
{
ptr = lineobj->child;
for (i=0; i<m; i++,ptr=ptr->next)
{
allocv_flag = 0;
s = jfieldname(ptr);
if ( (ind= mmfind(s)) < 0 )
{
printf("missing field.(%s) add to MM_fields[]\n",s);
linebuf[k++] = MMJSON_STRING;
memcpy(&linebuf[k],s,strlen(s)+1);
k += (int32_t)strlen(s) + 1;
//ind = mmadd(s);
} else linebuf[k++] = ind;
//printf("%s ",s);
if ( (array= jobj(lineobj,s)) != 0 && is_cJSON_Array(array) != 0 )
{
asize = cJSON_GetArraySize(array);
if ( asize < 0x100 )
{
linebuf[k++] = MMJSON_ARRAY8;
linebuf[k++] = asize;
}
else if ( asize < 0x10000 )
{
linebuf[k++] = MMJSON_ARRAY16;
l = asize;
k += MMJSON_rwnum(1,&linebuf[k],&l,2);
}
else
{
linebuf[k++] = MMJSON_ARRAY32;
l = asize;
k += MMJSON_rwnum(1,&linebuf[k],&l,4);
}
for (z=0; z<asize; z++)
{
if ( (v= jprint(jitem(array,z),0)) != 0 )
{
//printf("%d.(%s k.%d).%d ",z,v,k,asize);
k = MMJSON_encodeval(linebuf,k,ind,v,&timestamp,ptr,s);
free(v);
} else printf("ERROR.(%s) ",jprint(jitem(array,z),0));
}
//printf("%s array.%d k.%d\n",fieldstr,asize,k);
continue;
}
else if ( (v= jstr(lineobj,s)) == 0 )
{
v = jprint(jobj(lineobj,s),0);
//printf("allocate v.%p\n",v);
allocv_flag = 1;
}
if ( v != 0 )
{
//printf("%s\n",v);
k = MMJSON_encodeval(linebuf,k,ind,v,&timestamp,ptr,s);
}
else printf("ERROR.(%s) ",jprint(jobj(lineobj,s),0));
if ( allocv_flag != 0 && v != 0 )
{
//printf("free allocated v\n");
free(v);
}
//printf("m.%d values\n",m);
}
}
free_json(lineobj);
if ( (decodestr= MMJSON_decode(linebuf,k)) == 0 || strcmp(decodestr,line) != 0 )
{
for (i=0; i<k; i++)
printf("%d ",linebuf[i]);
printf(" k.%d error decoding (%s) -> (%s)\n",k,line,decodestr==0?"":decodestr);
if ( decodestr != 0 )
free(decodestr);
return(-1);
} //else printf("decoded\n");
free(decodestr);
}
return(k);
}
#ifndef FROM_MARKETMAKER
#define packetout "/Users/mac/mmjson/packet.out"
#define packetlog "/Users/mac/mmjson/packet.log"
int main(int argc, const char * argv[])
{
FILE *fp,*outfp; uint8_t linebuf[8192]; char line[8192],str[65]; int32_t i,k,compressed=0,n=0,total = 0;
outfp = fopen(packetout,"wb");
if ( (fp= fopen(packetlog,"rb")) != 0 )
{
while ( fgets(line,sizeof(line),fp) > 0 )
{
n++;
total += strlen(line);
if ( (k= MMJSON_encode(linebuf,line)) > 0 )
{
//printf("\n");
if ( outfp != 0 )
fwrite(linebuf,1,k,outfp);
compressed += k;
}
else
{
compressed += strlen(line);
//printf("error parsing.(%s)\n",line);
}
}
fclose(fp);
if ( outfp != 0 )
{
uint8_t *data,*bits; int32_t numbits; bits256 seed; long fsize = ftell(outfp);
fclose(outfp);
if ( (0) && (outfp= fopen(packetout,"rb")) != 0 )
{
data = calloc(1,fsize);
bits = calloc(1,fsize);
if ( fread(data,1,fsize,outfp) == fsize )
{
memset(seed.bytes,0,sizeof(seed));
decode_hex(seed.bytes,32,"ffffff070000810478800084000800b200101400002001400404844402d29fc4");
numbits = ramcoder_compress(bits,(int32_t)fsize,data,(int32_t)fsize,seed);
fclose(outfp);
printf("numbits.%d %d bytes %.1f seed.%s\n",numbits,numbits/8+1,(double)compressed/(numbits/8),bits256_str(str,seed));
}
}
}
} else printf("cant find packet.log\n");
printf("char *MM_fields[256] = \n{\n");
for (i=0; i<MM_numfields; i++)
printf("\"%s\", ",MM_fields[i]);
printf("\n};\nnumlines.%d size %d compressed.%d %.3f maxind.%d\n",n,total,compressed,(double)total/compressed,MM_numfields);
}
#endif

211
iguana/exchanges/LP_nativeDEX.c

@ -17,18 +17,17 @@
// LP_nativeDEX.c
// marketmaker
//
// https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki for signing BCH/BTG
// big BTC swaps, assetchain markets
//
// compress packets
// cancel bid/ask
// portfolio to set prices from historical
// portfolio value based on ask?
//
// else claim path
//
// WONTFIX:
// dPoW security -> 4: KMD notarized, 5: BTC notarized, after next notary elections
// bigendian architectures need to use little endian for sighash calcs
// improve critical section detection when parallel trades
// use electrum in case of addr change in swap
// locktime claiming on sporadic assetchains
// there is an issue about waiting for notarization for a swap that never starts (expiration ok)
#include <stdio.h>
@ -41,6 +40,7 @@ struct LP_millistats
char name[64];
} LP_psockloop_stats,LP_reserved_msgs_stats,utxosQ_loop_stats,command_rpcloop_stats,queue_loop_stats,prices_loop_stats,LP_coinsloop_stats,LP_coinsloopBTC_stats,LP_coinsloopKMD_stats,LP_pubkeysloop_stats,LP_swapsloop_stats,LP_gcloop_stats,LP_tradesloop_stats;
extern int32_t IAMLP;
char LP_methodstr[64];
void LP_millistats_update(struct LP_millistats *mp)
{
@ -77,7 +77,7 @@ void LP_millistats_update(struct LP_millistats *mp)
if ( mp->threshold != 0. && elapsed > mp->threshold )
{
//if ( IAMLP == 0 )
printf("%32s elapsed %10.2f millis > threshold %10.2f, ave %10.2f millis, count.%u\n",mp->name,elapsed,mp->threshold,mp->millisum/mp->count,mp->count);
printf("%32s elapsed %10.2f millis > threshold %10.2f, ave %10.2f millis, count.%u %s\n",mp->name,elapsed,mp->threshold,mp->millisum/mp->count,mp->count,LP_methodstr);
}
mp->lastmilli = millis;
}
@ -164,6 +164,7 @@ char *blocktrail_listtransactions(char *symbol,char *coinaddr,int32_t num,int32_
return(0);
}
#include "LP_mmjson.c"
#include "LP_socket.c"
#include "LP_secp.c"
#include "LP_bitcoin.c"
@ -346,11 +347,15 @@ char *LP_process_message(void *ctx,char *typestr,char *myipaddr,int32_t pubsock,
int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int32_t sock,char *remoteaddr,int32_t maxdepth)
{
int32_t recvlen=1,nonz = 0; cJSON *argjson; void *ptr; char methodstr[64],*retstr,*str; struct nn_pollfd pfd;
static char *line;
int32_t recvlen=1,msglen,nonz = 0; cJSON *argjson,*recvjson; void *ptr,*msg; char methodstr[64],*decodestr,*retstr,*str; struct nn_pollfd pfd;
if ( line == 0 )
line = calloc(1,1024*1024);
if ( sock >= 0 )
{
while ( nonz < maxdepth && recvlen > 0 )
{
decodestr = 0;
nonz++;
memset(&pfd,0,sizeof(pfd));
pfd.fd = sock;
@ -358,56 +363,67 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int
if ( nn_poll(&pfd,1,1) != 1 )
break;
ptr = 0;
//buf = malloc(1000000);
//if ( (recvlen= nn_recv(sock,buf,1000000,0)) > 0 )
if ( (recvlen= nn_recv(sock,&ptr,NN_MSG,0)) > 0 )
{
//ptr = buf;
methodstr[0] = 0;
//printf("%s.(%s)\n",typestr,(char *)ptr);
if ( 0 )
decodestr = 0;
if ( recvlen > 32768 )
{
printf("unexpectedly large packet\n");
}
else
{
cJSON *recvjson; char *mstr;//,*cstr;
if ( (recvjson= cJSON_Parse((char *)ptr)) != 0 )
msg = ptr;
msglen = recvlen;
if ( (recvjson= cJSON_Parse((char *)ptr)) == 0 )
{
if ( (mstr= jstr(recvjson,"method")) != 0 )//&& strcmp(mstr,"uitem") == 0 && (cstr= jstr(recvjson,"coin")) != 0 && strcmp(cstr,"REVS") == 0 )
if ( (decodestr= MMJSON_decode(ptr,recvlen)) != 0 )
{
//printf("%s RECV.(%s)\n",typestr,(char *)ptr);
}
safecopy(methodstr,jstr(recvjson,"method"),sizeof(methodstr));
free_json(recvjson);
if ( (recvjson= cJSON_Parse(decodestr)) != 0 )
{
msg = decodestr;
msglen = (int32_t)strlen(decodestr) + 1;
}
//printf("decoded.(%s)\n",decodestr);
} else printf("couldnt decode linebuf[%d]\n",recvlen);
}
}
int32_t validreq = 0;
if ( strlen((char *)ptr)+sizeof(bits256) <= recvlen )
{
if ( LP_magic_check(ptr,recvlen,remoteaddr) <= 0 )
methodstr[0] = 0;
//printf("%s.(%s)\n",typestr,(char *)ptr);
if ( recvjson != 0 )
{
//printf("magic check error\n");
} else validreq = 1;
recvlen -= sizeof(bits256);
}
if ( validreq != 0 )
{
if ( (retstr= LP_process_message(ctx,typestr,myipaddr,pubsock,ptr,recvlen,sock)) != 0 )
free(retstr);
if ( Broadcaststr != 0 )
safecopy(LP_methodstr,jstr(recvjson,"method"),sizeof(LP_methodstr));
free_json(recvjson);
}
int32_t validreq = 1;
/*if ( strlen((char *)ptr)+sizeof(bits256) <= recvlen )
{
if ( LP_magic_check(ptr,recvlen,remoteaddr) <= 0 )
{
//printf("magic check error\n");
} else validreq = 1;
recvlen -= sizeof(bits256);
}*/
if ( validreq != 0 )
{
//printf("self broadcast.(%s)\n",Broadcaststr);
str = Broadcaststr;
Broadcaststr = 0;
if ( (argjson= cJSON_Parse(str)) != 0 )
if ( (retstr= LP_process_message(ctx,typestr,myipaddr,pubsock,msg,msglen,sock)) != 0 )
free(retstr);
if ( Broadcaststr != 0 )
{
portable_mutex_lock(&LP_commandmutex);
if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,0,0) <= 0 )
//printf("self broadcast.(%s)\n",Broadcaststr);
str = Broadcaststr;
Broadcaststr = 0;
if ( (argjson= cJSON_Parse(str)) != 0 )
{
if ( (retstr= stats_JSON(ctx,myipaddr,pubsock,argjson,remoteaddr,0)) != 0 )
free(retstr);
portable_mutex_lock(&LP_commandmutex);
if ( LP_tradecommand(ctx,myipaddr,pubsock,argjson,0,0) <= 0 )
{
if ( (retstr= stats_JSON(ctx,myipaddr,pubsock,argjson,remoteaddr,0)) != 0 )
free(retstr);
}
portable_mutex_unlock(&LP_commandmutex);
free_json(argjson);
}
portable_mutex_unlock(&LP_commandmutex);
free_json(argjson);
free(str);
}
free(str);
}
}
}
@ -416,6 +432,8 @@ int32_t LP_sock_check(char *typestr,void *ctx,char *myipaddr,int32_t pubsock,int
nn_freemsg(ptr), ptr = 0;
//free(buf);
}
if ( decodestr != 0 )
free(decodestr);
}
}
return(nonz);
@ -461,7 +479,7 @@ void command_rpcloop(void *ctx)
{
int32_t nonz = 0;
strcpy(command_rpcloop_stats.name,"command_rpcloop");
command_rpcloop_stats.threshold = 1000.;
command_rpcloop_stats.threshold = 2500.;
while ( 1 )
{
LP_millistats_update(&command_rpcloop_stats);
@ -616,21 +634,26 @@ void LP_coinsloop(void *_coins)
coin->lastscanht = coin->firstscanht;
continue;
}
nonz++;
if ( 0 && coin->lastscanht < coin->longestchain-3 )
printf("[%s]: %s ref.%d scan.%d to %d, longest.%d\n",coins,coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain);
for (j=0; j<100; j++)
if ( strcmp(coin->symbol,"BTC") != 0 && strcmp(coin->symbol,"KMD") != 0 ) // SPV as backup
{
if ( LP_blockinit(coin,coin->lastscanht) < 0 )
nonz++;
if ( strcmp("BTC",coins) == 0 )//&& coin->lastscanht < coin->longestchain-3 )
printf("[%s]: %s ref.%d scan.%d to %d, longest.%d\n",coins,coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain);
for (j=0; j<100; j++)
{
static uint32_t counter;
if ( counter++ < 3 )
printf("blockinit.%s %d error\n",coin->symbol,coin->lastscanht);
break;
if ( LP_blockinit(coin,coin->lastscanht) < 0 )
{
static uint32_t counter;
if ( counter++ < 3 )
printf("blockinit.%s %d error\n",coin->symbol,coin->lastscanht);
break;
}
coin->lastscanht++;
if ( coin->lastscanht == coin->longestchain+1 || strcmp("BTC",coins) == 0 )
break;
}
coin->lastscanht++;
if ( coin->lastscanht == coin->longestchain+1 )
break;
if ( strcmp("BTC",coins) == 0 )
printf("done [%s]: %s ref.%d scan.%d to %d, longest.%d\n",coins,coin->symbol,coin->firstrefht,coin->firstscanht,coin->lastscanht,coin->longestchain);
}
}
if ( coins == 0 )
@ -692,12 +715,9 @@ void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins)
int32_t i,n,notarized; cJSON *item; char *symbol; struct iguana_info *coin;
for (i=0; i<sizeof(activecoins)/sizeof(*activecoins); i++)
{
printf("%s ",activecoins[i]);
printf("%s, ",activecoins[i]);
LP_coinfind(activecoins[i]);
LP_priceinfoadd(activecoins[i]);
//test_validate("02000000010e62f95ff5881de8853ce1a5ddbaad731a62879d719367f539103600f1895477010000006b483045022100c684a0871689519bd97f2e61275752124f0f1498360750c87cf99a8acf06fd8c022047e7e62a7bfd481599130e6f40c95833f6ed6f44aa8b6ead7b0ec86a738b98a041210361857e1ba609aadff520a2ca9886fe7548c7154fab2cbe108c3b0e1e7635eb1ffeffffff02a0860100000000001976a9146cfa0a987f4c8f2ffee7e9944ef0c86fcda9671d88ac1e6f0700000000001976a9147f4b7113f9e26d84b150f2cc6d219baaf27f884488ace6b00700");
//test_validate("01000000011434b89cc4d41bcbbda87db58b5167bce50ea025d5fba3f4d7bbd9ec1b620d98000000006a47304402205aba01fa2b895df6069dc7458fcc7aac6da1ffbc2811eb43382a5a342a342c6202207da60859f45893785322fede2f82b1f7c76cd9882b6a8ed6d25037f4184b60514121029d1e15b82fc3e11b51b61eb65545b0c93baebb17de5118979f261a086575bcd6ffffffff0210270000000000001976a9146cfa0a987f4c8f2ffee7e9944ef0c86fcda9671d88ac80380100000000001976a9146cfa0a987f4c8f2ffee7e9944ef0c86fcda9671d88ac00000000");
//getchar();
if ( (coin= LP_coinfind(activecoins[i])) != 0 )
{
if ( LP_getheight(&notarized,coin) <= 0 )
@ -706,7 +726,10 @@ void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins)
{
LP_unspents_load(coin->symbol,coin->smartaddr);
if ( strcmp(coin->symbol,"KMD") == 0 )
{
LP_importaddress("KMD",BOTS_BONDADDRESS);
LP_dPoW_request(coin);
}
}
if ( coin->txfee == 0 && strcmp(coin->symbol,"BTC") != 0 )
coin->txfee = LP_MIN_TXFEE;
@ -719,7 +742,7 @@ void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins)
item = jitem(coins,i);
if ( (symbol= jstr(item,"coin")) != 0 )
{
printf("%s ",jstr(item,"coin"));
printf("%s, ",jstr(item,"coin"));
LP_coincreate(item);
LP_priceinfoadd(jstr(item,"coin"));
if ( (coin= LP_coinfind(symbol)) != 0 )
@ -732,6 +755,11 @@ void LP_initcoins(void *ctx,int32_t pubsock,cJSON *coins)
}
}
}
for (i=0; i<n; i++)
{
item = jitem(coins,i);
printf("\"%s\", ",jstr(item,"coin"));
}
}
printf("privkey updates\n");
}
@ -849,7 +877,7 @@ void gc_loop(void *ctx)
void queue_loop(void *ctx)
{
struct LP_queue *ptr,*tmp; int32_t sentbytes,nonz,flag,duplicate,n=0;
struct LP_queue *ptr,*tmp; cJSON *json; uint8_t linebuf[32768]; int32_t k,sentbytes,nonz,flag,duplicate,n=0;
strcpy(queue_loop_stats.name,"queue_loop");
queue_loop_stats.threshold = 1000.;
while ( 1 )
@ -867,12 +895,39 @@ void queue_loop(void *ctx)
{
if ( LP_sockcheck(ptr->sock) > 0 )
{
bits256 magic;
magic = LP_calc_magic(ptr->msg,(int32_t)(ptr->msglen - sizeof(bits256)));
memcpy(&ptr->msg[ptr->msglen - sizeof(bits256)],&magic,sizeof(magic));
if ( (sentbytes= nn_send(ptr->sock,ptr->msg,ptr->msglen,0)) != ptr->msglen )
printf("%d LP_send sent %d instead of %d\n",n,sentbytes,ptr->msglen);
else flag++;
//bits256 magic;
//magic = LP_calc_magic(ptr->msg,(int32_t)(ptr->msglen - sizeof(bits256)));
//memcpy(&ptr->msg[ptr->msglen - sizeof(bits256)],&magic,sizeof(magic));
if ( 0 )
{
static FILE *fp;
if ( fp == 0 )
fp = fopen("packet.log","wb");
if ( fp != 0 )
{
fprintf(fp,"%s\n",(char *)ptr->msg);
fflush(fp);
}
}
if ( (json= cJSON_Parse((char *)ptr->msg)) != 0 )
{
if ( ptr->msglen < sizeof(linebuf) )
{
if ( (k= MMJSON_encode(linebuf,(char *)ptr->msg)) > 0 )
{
if ( (sentbytes= nn_send(ptr->sock,linebuf,k,0)) != k )
printf("%d LP_send mmjson sent %d instead of %d\n",n,sentbytes,k);
else flag++;
}
}
free_json(json);
}
if ( flag == 0 )
{
if ( (sentbytes= nn_send(ptr->sock,ptr->msg,ptr->msglen,0)) != ptr->msglen )
printf("%d LP_send sent %d instead of %d\n",n,sentbytes,ptr->msglen);
else flag++;
}
ptr->sock = -1;
if ( ptr->peerind > 0 )
ptr->starttime = (uint32_t)time(NULL);
@ -995,10 +1050,13 @@ int32_t LP_reserved_msg(int32_t priority,char *base,char *rel,bits256 pubkey,cha
return(n);
}
extern int32_t bitcoind_RPC_inittime;
void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybusport,char *passphrase,int32_t amclient,char *userhome,cJSON *argjson)
{
char *myipaddr=0,version[64]; long filesize,n; int32_t valid,timeout,pubsock=-1; struct LP_peerinfo *mypeer=0; char pushaddr[128],subaddr[128],bindaddr[128],*coins_str=0; cJSON *coinsjson=0; void *ctx = bitcoin_ctx();
sprintf(version,"Marketmaker %s.%s %s rsize.%ld",LP_MAJOR_VERSION,LP_MINOR_VERSION,LP_BUILD_NUMBER,sizeof(struct basilisk_request));
bitcoind_RPC_inittime = 1;
printf("%s %u\n",version,calc_crc32(0,version,(int32_t)strlen(version)));
if ( LP_MAXPRICEINFOS > 256 )
{
@ -1147,9 +1205,12 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
exit(-1);
}
LP_initcoins(ctx,pubsock,coinsjson);
G.waiting = 1;
LP_passphrase_init(passphrase,jstr(argjson,"gui"));
//char coinaddr[64]; bits256 zero;
//bitcoin_address(coinaddr,0,60,G.LP_myrmd160,20);
//memset(zero.bytes,0,sizeof(zero));
//LP_instantdex_depositadd(coinaddr,zero);
#ifndef FROM_JS
if ( IAMLP != 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_psockloop,(void *)myipaddr) != 0 )
{
@ -1217,11 +1278,6 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
printf("error launching LP_tradessloop for ctx.%p\n",ctx);
exit(-1);
}
/*if ( 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_privkeysloop,ctx) != 0 )
{
printf("error launching LP_privkeysloop for ctx.%p\n",ctx);
exit(-1);
}*/
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_swapsloop,ctx) != 0 )
{
printf("error launching LP_swapsloop for ctx.%p\n",ctx);
@ -1229,6 +1285,7 @@ void LPinit(uint16_t myport,uint16_t mypullport,uint16_t mypubport,uint16_t mybu
}
int32_t nonz;
LP_statslog_parse();
bitcoind_RPC_inittime = 0;
while ( 1 )
{
nonz = 0;

2
iguana/exchanges/LP_network.c

@ -152,7 +152,7 @@ void _LP_sendqueueadd(uint32_t crc32,int32_t sock,uint8_t *msg,int32_t msglen,in
ptr->crc32 = crc32;
ptr->sock = sock;
ptr->peerind = peerind;
ptr->msglen = (int32_t)(msglen + sizeof(bits256));
ptr->msglen = (int32_t)(msglen + 0*sizeof(bits256));
memcpy(ptr->msg,msg,msglen); // sizeof(bits256) at the end all zeroes
DL_APPEND(LP_Q,ptr);
LP_Qenqueued++;

56
iguana/exchanges/LP_ordermatch.c

@ -85,23 +85,6 @@ uint64_t LP_txfeecalc(struct iguana_info *coin,uint64_t txfee,int32_t txlen)
return(txfee);
}
/*double LP_qprice_calc(int64_t *destsatoshisp,int64_t *satoshisp,double price,uint64_t b_satoshis,uint64_t txfee,uint64_t a_value,uint64_t maxdestsatoshis,uint64_t desttxfee)
{
uint64_t destsatoshis,satoshis;
a_value -= (desttxfee + 1);
destsatoshis = ((b_satoshis - txfee) * price);
if ( destsatoshis > a_value )
destsatoshis = a_value;
if ( maxdestsatoshis != 0 && destsatoshis > maxdestsatoshis-desttxfee-1 )
destsatoshis = maxdestsatoshis-desttxfee-1;
satoshis = (destsatoshis / price + 0.49) - txfee;
*destsatoshisp = destsatoshis;
*satoshisp = satoshis;
if ( satoshis > 0 )
return((double)destsatoshis / satoshis);
else return(0.);
}*/
int32_t LP_quote_checkmempool(struct LP_quoteinfo *qp,struct LP_utxoinfo *autxo,struct LP_utxoinfo *butxo)
{
int32_t selector,spendvini; bits256 spendtxid;
@ -428,7 +411,7 @@ struct LP_utxoinfo *LP_address_myutxopair(struct LP_utxoinfo *butxo,int32_t iamb
{
up = utxos[mini];
utxos[mini] = 0;
//printf("found mini.%d %.8f for targetval %.8f -> targetval2 %.8f, ratio %.2f\n",mini,dstr(up->U.value),dstr(targetval),dstr(targetval2),(double)up->U.value/targetval);
printf("found mini.%d %.8f for targetval %.8f -> targetval2 %.8f, ratio %.2f\n",mini,dstr(up->U.value),dstr(targetval),dstr(targetval2),(double)up->U.value/targetval);
if ( (double)up->U.value/targetval < ratio-1 )
{
@ -461,7 +444,7 @@ struct LP_utxoinfo *LP_address_myutxopair(struct LP_utxoinfo *butxo,int32_t iamb
int32_t LP_connectstartbob(void *ctx,int32_t pubsock,char *base,char *rel,double price,struct LP_quoteinfo *qp)
{
char pairstr[512]; cJSON *reqjson; bits256 privkey; int32_t pair=-1,retval = -1,DEXselector = 0; struct basilisk_swap *swap; struct iguana_info *coin;
char pairstr[512],otheraddr[64]; cJSON *reqjson; bits256 privkey; int32_t pair=-1,retval = -1,DEXselector = 0; struct basilisk_swap *swap; struct iguana_info *coin,*kmdcoin;
qp->quotetime = (uint32_t)time(NULL);
if ( (coin= LP_coinfind(qp->srccoin)) == 0 )
{
@ -477,7 +460,7 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,char *base,char *rel,double
printf("requestid.%u quoteid.%u is already in progres\n",qp->R.requestid,qp->R.quoteid);
return(-1);
}
if ( (swap= LP_swapinit(1,0,privkey,&qp->R,qp,LP_dynamictrust(qp->desthash,LP_kmdvalue(qp->destcoin,qp->destsatoshis)) > 0)) == 0 )
if ( (swap= LP_swapinit(1,0,privkey,&qp->R,qp,LP_dynamictrust(qp->othercredits,qp->desthash,LP_kmdvalue(qp->destcoin,qp->destsatoshis)) > 0)) == 0 )
{
printf("cant initialize swap\n");
return(-1);
@ -492,7 +475,8 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,char *base,char *rel,double
reqjson = LP_quotejson(qp);
jaddstr(reqjson,"method","connected");
jaddstr(reqjson,"pair",pairstr);
jadd(reqjson,"proof",LP_instantdex_txids());
if ( (kmdcoin= LP_coinfind("KMD")) != 0 )
jadd(reqjson,"proof",LP_instantdex_txids(0,kmdcoin->smartaddr));
char str[65]; printf("BOB pubsock.%d binds to %d (%s)\n",pubsock,pair,bits256_str(str,qp->desthash));
bits256 zero;
memset(zero.bytes,0,sizeof(zero));
@ -504,6 +488,9 @@ int32_t LP_connectstartbob(void *ctx,int32_t pubsock,char *base,char *rel,double
}
LP_reserved_msg(0,base,rel,zero,jprint(reqjson,0));
free_json(reqjson);
LP_importaddress(qp->destcoin,qp->destaddr);
LP_otheraddress(qp->srccoin,otheraddr,qp->destcoin,qp->destaddr);
LP_importaddress(qp->srccoin,otheraddr);
retval = 0;
} else printf("error launching swaploop\n");
} else printf("couldnt bind to any port %s\n",pairstr);
@ -572,7 +559,7 @@ int32_t LP_alice_eligible(uint32_t quotetime)
char *LP_connectedalice(struct LP_quoteinfo *qp,char *pairstr) // alice
{
cJSON *retjson; double bid,ask,price,qprice; int32_t pairsock = -1; int32_t DEXselector = 0; struct LP_utxoinfo *autxo,A,B,*butxo; struct basilisk_swap *swap; struct iguana_info *coin;
cJSON *retjson; char otheraddr[64]; double bid,ask,price,qprice; int32_t pairsock = -1; int32_t DEXselector = 0; struct LP_utxoinfo *autxo,A,B,*butxo; struct basilisk_swap *swap; struct iguana_info *coin;
/*if ( LP_quoteparse(&Q,argjson) < 0 )
{
LP_aliceid(Q.tradeid,Q.aliceid,"error0",0,0);
@ -609,7 +596,7 @@ char *LP_connectedalice(struct LP_quoteinfo *qp,char *pairstr) // alice
LP_availableset(qp->desttxid,qp->vout);
LP_availableset(qp->feetxid,qp->feevout);
LP_aliceid(qp->tradeid,qp->aliceid,"error4",0,0);
printf("quote validate error %.0f\n",qprice);
printf("quote %s/%s validate error %.0f\n",qp->srccoin,qp->destcoin,qprice);
return(clonestr("{\"error\":\"quote validation error\"}"));
}
if ( LP_myprice(&bid,&ask,qp->srccoin,qp->destcoin) <= SMALLVAL || bid <= SMALLVAL )
@ -632,7 +619,7 @@ char *LP_connectedalice(struct LP_quoteinfo *qp,char *pairstr) // alice
if ( bits256_nonz(qp->privkey) != 0 )//&& qp->quotetime >= qp->timestamp-3 )
{
retjson = cJSON_CreateObject();
if ( (swap= LP_swapinit(0,0,qp->privkey,&qp->R,qp,LP_dynamictrust(qp->srchash,LP_kmdvalue(qp->srccoin,qp->satoshis)) > 0)) == 0 )
if ( (swap= LP_swapinit(0,0,qp->privkey,&qp->R,qp,LP_dynamictrust(qp->othercredits,qp->srchash,LP_kmdvalue(qp->srccoin,qp->satoshis)) > 0)) == 0 )
{
jaddstr(retjson,"error","couldnt swapinit");
LP_availableset(qp->desttxid,qp->vout);
@ -654,8 +641,11 @@ char *LP_connectedalice(struct LP_quoteinfo *qp,char *pairstr) // alice
swap->N.pair = pairsock;
//autxo->S.swap = swap;
//swap->utxo = autxo;
LP_importaddress(qp->srccoin,qp->coinaddr);
LP_otheraddress(qp->destcoin,otheraddr,qp->srccoin,qp->coinaddr);
LP_importaddress(qp->srccoin,otheraddr);
LP_aliceid(qp->tradeid,qp->aliceid,"started",qp->R.requestid,qp->R.quoteid);
printf("alice pairstr.(%s) pairsock.%d\n",pairstr,pairsock);
printf("alice pairstr.(%s) pairsock.%d pthread_t %ld\n",pairstr,pairsock,sizeof(pthread_t));
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_aliceloop,(void *)swap) == 0 )
{
retjson = LP_quotejson(qp);
@ -829,7 +819,7 @@ double LP_trades_pricevalidate(struct LP_quoteinfo *qp,struct iguana_info *coin,
}
if ( (qprice= LP_quote_validate(autxo,butxo,qp,1)) <= SMALLVAL )
{
printf("quote validate error %.0f\n",qprice);
printf("quote %s/%s validate error %.0f\n",qp->srccoin,qp->destcoin,qprice);
return(-3);
}
if ( qprice < (price - 0.00000001) * 0.998 )
@ -866,7 +856,7 @@ struct LP_quoteinfo *LP_trades_gotrequest(void *ctx,struct LP_quoteinfo *qp,stru
memset(&qp->txid2,0,sizeof(qp->txid2));
qp->vout = qp->vout2 = -1;
} else return(0);
printf("LP_trades_gotrequest qprice %.8f vs myprice %.8f\n",qprice,myprice);
//printf("LP_trades_gotrequest qprice %.8f vs myprice %.8f\n",qprice,myprice);
if ( qprice > myprice )
{
r = (LP_rand() % 100);
@ -993,7 +983,7 @@ int32_t LP_trades_bestpricecheck(void *ctx,struct LP_trade *tp)
if ( (retstr= LP_quotereceived(&Q)) != 0 )
free(retstr);
//LP_trades_gotreserved(ctx,&Q,&tp->Qs[LP_RESERVED]);
dynamictrust = LP_dynamictrust(Q.srchash,LP_kmdvalue(Q.srccoin,Q.satoshis));
dynamictrust = LP_dynamictrust(Q.othercredits,Q.srchash,LP_kmdvalue(Q.srccoin,Q.satoshis));
if ( tp->bestprice == 0. )
flag = 1;
else if ( qprice < tp->bestprice && pubp->slowresponse <= tp->bestresponse*1.05 )
@ -1176,6 +1166,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
LP_requestinit(&Q.R,Q.srchash,Q.desthash,Q.srccoin,Q.satoshis-Q.txfee,Q.destcoin,Q.destsatoshis-Q.desttxfee,Q.timestamp,Q.quotetime,DEXselector);
LP_tradecommand_log(argjson);
printf("%-4d (%-10u %10u) %12s id.%22llu %5s/%-5s %12.8f -> %11.8f price %11.8f | RT.%d %d\n",(uint32_t)time(NULL) % 3600,Q.R.requestid,Q.R.quoteid,method,(long long)Q.aliceid,Q.srccoin,Q.destcoin,dstr(Q.satoshis),dstr(Q.destsatoshis),(double)Q.destsatoshis/Q.satoshis,LP_RTcount,LP_swapscount);
LP_autoprices_update(method,Q.srccoin,dstr(Q.satoshis),Q.destcoin,dstr(Q.destsatoshis));
retval = 1;
aliceid = j64bits(argjson,"aliceid");
qprice = jdouble(argjson,"price");
@ -1216,7 +1207,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
{
//printf("CONNECTED.(%s)\n",jprint(argjson,0));
if ( (proof= jarray(&num,argjson,"proof")) != 0 && num > 0 )
LP_instantdex_proofcheck(Q.coinaddr,proof,num);
Q.othercredits = LP_instantdex_proofcheck(Q.coinaddr,proof,num);
if ( Qtrades == 0 )
LP_trades_gotconnected(ctx,&Q,&Q2,jstr(argjson,"pair"));
else LP_tradecommandQ(&Q,jstr(argjson,"pair"),LP_CONNECTED);
@ -1252,7 +1243,7 @@ int32_t LP_tradecommand(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,
{
printf("CONNECT.(%s)\n",jprint(argjson,0));
if ( (proof= jarray(&num,argjson,"proof")) != 0 && num > 0 )
LP_instantdex_proofcheck(Q.destaddr,proof,num);
Q.othercredits = LP_instantdex_proofcheck(Q.destaddr,proof,num);
if ( Qtrades == 0 )
LP_trades_gotconnect(ctx,&Q,&Q2,jstr(argjson,"pair"));
else LP_tradecommandQ(&Q,jstr(argjson,"pair"),LP_CONNECT);
@ -1313,7 +1304,7 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel
memset(&A,0,sizeof(A));
LP_address_utxo_reset(relcoin);
if ( (autxo= LP_address_myutxopair(&A,0,utxos,max,relcoin,relcoin->smartaddr,txfee,dstr(destsatoshis),maxprice,desttxfee)) == 0 )
return(clonestr("{\"error\":\"cant find alice utxo that is close enough in size\"}"));
return(clonestr("{\"error\":\"cant find a deposit that is close enough in size. make another deposit that is just a bit larger than what you want to trade\"}"));
//printf("bestfit selected alice (%.8f %.8f) for %.8f sats %.8f\n",dstr(autxo->payment.value),dstr(autxo->fee.value),dstr(destsatoshis),dstr(autxo->swap_satoshis));
if ( destsatoshis - desttxfee < autxo->swap_satoshis )
{
@ -1330,7 +1321,7 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel
if ( destsatoshis < (autxo->payment.value / LP_MINCLIENTVOL) || autxo->payment.value < desttxfee*LP_MINSIZE_TXFEEMULT )
{
printf("destsatoshis %.8f vs utxo %.8f this would have triggered an quote error -13\n",dstr(destsatoshis),dstr(autxo->payment.value));
return(clonestr("{\"error\":\"cant find alice utxo that is small enough\"}"));
return(clonestr("{\"error\":\"cant find a deposit that is close enough in size. make another deposit that is just a bit larger than what you want to trade\"}"));
}
bestsatoshis = 1.001 * LP_basesatoshis(dstr(destsatoshis),maxprice,txfee,desttxfee);
memset(&B,0,sizeof(B));
@ -1341,6 +1332,7 @@ char *LP_autobuy(void *ctx,char *myipaddr,int32_t mypubsock,char *base,char *rel
return(clonestr("{\"error\":\"cant set ordermatch quote info\"}"));
int32_t changed;
LP_mypriceset(&changed,autxo->coin,base,1. / maxprice);
LP_mypriceset(&changed,base,autxo->coin,0.);
return(LP_trade(ctx,myipaddr,mypubsock,&Q,maxprice,timeout,duration,tradeid,destpubkey));
}

385
iguana/exchanges/LP_portfolio.c

@ -18,9 +18,53 @@
// marketmaker
//
struct LP_portfoliotrade { double metric; char buycoin[65],sellcoin[65]; };
struct LP_autoprice_ref
{
char refbase[65],refrel[65],base[65],rel[65],fundbid[16],fundask[16];
double margin,factor,offset,lastbid,lastask;
cJSON *fundvalue;
uint32_t count;
} LP_autorefs[1024];
int32_t LP_autoprices,num_LP_autorefs;
char LP_portfolio_base[128],LP_portfolio_rel[128];
double LP_portfolio_relvolume;
void LP_portfolio_reset()
{
struct iguana_info *coin,*tmp; cJSON *fundjson; int32_t i; struct LP_autoprice_ref *ptr;
for (i=0; i<num_LP_autorefs; i++)
{
ptr = &LP_autorefs[i];
if ( (fundjson= ptr->fundvalue) != 0 )
{
ptr->fundvalue = 0;
free_json(fundjson);
}
}
memset(LP_autorefs,0,sizeof(LP_autorefs));
LP_autoprices = 0;
num_LP_autorefs = 0;
strcpy(LP_portfolio_base,"");
strcpy(LP_portfolio_rel,"");
LP_portfolio_relvolume = 0.;
HASH_ITER(hh,LP_coins,coin,tmp)
{
coin->maxamount = 0;
coin->perc = 0;
coin->goal = 0;
coin->goalperc = 0;
coin->relvolume = 0;
coin->force = 0;
coin->balanceA = 0;
coin->valuesumA = 0;
coin->balanceB = 0;
coin->valuesumB = 0;
}
}
cJSON *LP_portfolio_entry(struct iguana_info *coin)
{
cJSON *item = cJSON_CreateObject();
@ -201,13 +245,6 @@ char *LP_portfolio_goal(char *symbol,double goal)
} else return(clonestr("{\"error\":\"cant set goal for inactive coin\"}"));
}
int32_t LP_autoprices,num_LP_autorefs;
struct LP_autoprice_ref
{
char refbase[65],refrel[65],base[65],rel[65];
} LP_autorefs[100];
/*int32_t LP_autofill(char *base,char *rel,double maxprice,double totalrelvolume)
{
struct LP_priceinfo *basepp,*relpp;
@ -221,59 +258,7 @@ struct LP_autoprice_ref
return(-1);
}*/
int32_t LP_autoprice(char *base,char *rel,cJSON *argjson)
{
//curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"MNZ\",\"rel\":\"KMD\",\"offset\":0.1,\"refbase\":\"KMD\",\refrel\":\"BTC\",\"factor\":15000,\"margin\":0.01}"
struct LP_priceinfo *basepp,*relpp; int32_t i; char *refbase="",*refrel=""; double minprice,margin,offset,factor,fixedprice;
//printf("autoprice.(%s %s) %s\n",base,rel,jprint(argjson,0));
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
if ( jobj(argjson,"minprice") != 0 )
minprice = jdouble(argjson,"minprice");
else minprice = 0.;
margin = jdouble(argjson,"margin");
offset = jdouble(argjson,"offset");
factor = jdouble(argjson,"factor");
fixedprice = jdouble(argjson,"fixed");
basepp->fixedprices[relpp->ind] = fixedprice;
basepp->minprices[relpp->ind] = minprice;
basepp->margins[relpp->ind] = margin;
basepp->offsets[relpp->ind] = offset;
basepp->factors[relpp->ind] = factor;
if ( fixedprice > SMALLVAL || ((refbase= jstr(argjson,"refbase")) != 0 && (refrel= jstr(argjson,"refrel")) != 0) )
{
if ( fixedprice > SMALLVAL )
{
refbase = base;
refrel = rel;
}
for (i=0; i<num_LP_autorefs; i++)
{
if ( strcmp(base,LP_autorefs[i].base) == 0 && strcmp(rel,LP_autorefs[i].rel) == 0 )
{
safecopy(LP_autorefs[i].refbase,refbase,sizeof(LP_autorefs[i].refbase));
safecopy(LP_autorefs[i].refrel,refrel,sizeof(LP_autorefs[i].refrel));
printf("%d Update ref %s/%s for %s/%s factor %.8f offset %.8f\n",i,refbase,refrel,base,rel,factor,offset);
break;
}
}
if ( i == num_LP_autorefs && num_LP_autorefs < sizeof(LP_autorefs)/sizeof(*LP_autorefs) )
{
safecopy(LP_autorefs[num_LP_autorefs].refbase,refbase,sizeof(LP_autorefs[num_LP_autorefs].refbase));
safecopy(LP_autorefs[num_LP_autorefs].refrel,refrel,sizeof(LP_autorefs[num_LP_autorefs].refrel));
safecopy(LP_autorefs[num_LP_autorefs].base,base,sizeof(LP_autorefs[num_LP_autorefs].base));
safecopy(LP_autorefs[num_LP_autorefs].rel,rel,sizeof(LP_autorefs[num_LP_autorefs].rel));
printf("%d Using ref %s/%s for %s/%s factor %.8f, offset %.8f, margin %.8f fixed %.8f\n",num_LP_autorefs,refbase,refrel,base,rel,factor,offset,margin,fixedprice);
num_LP_autorefs++;
}
}
LP_autoprices++;
return(0);
}
return(-1);
}
void LP_autopriceset(void *ctx,int32_t dir,struct LP_priceinfo *basepp,struct LP_priceinfo *relpp,double price,char *refbase,char *refrel)
void LP_autopriceset(int32_t ind,void *ctx,int32_t dir,struct LP_priceinfo *basepp,struct LP_priceinfo *relpp,double price,char *refbase,char *refrel)
{
static uint32_t lasttime;
double margin,minprice,newprice,oppomargin,fixedprice,factor,offset; double bid,ask; int32_t changed;
@ -311,8 +296,15 @@ void LP_autopriceset(void *ctx,int32_t dir,struct LP_priceinfo *basepp,struct LP
else newprice = (price * (1. + margin));
if ( (minprice= basepp->minprices[relpp->ind]) == 0. || price >= minprice )
{
if ( ind >= 0 )
{
if ( LP_autorefs[ind].lastask < SMALLVAL )
LP_autorefs[ind].lastask = newprice;
else LP_autorefs[ind].lastask = (LP_autorefs[ind].lastask * 0.9) + (0.1 *newprice);
newprice = LP_autorefs[ind].lastask;
//printf("autopriceset %s/%s <- %.8f %.8f (%.8f %.8f)\n",basepp->symbol,relpp->symbol,price,newprice,LP_autorefs[ind].lastbid,LP_autorefs[ind].lastask);
}
LP_mypriceset(&changed,relpp->symbol,basepp->symbol,newprice);
//printf("autoprice changed.%d %s/%s <- %.8f\n",changed,basepp->symbol,relpp->symbol,price);
if ( changed != 0 || time(NULL) > lasttime+LP_ORDERBOOK_DURATION*.777)
{
lasttime = (uint32_t)time(NULL);
@ -399,8 +391,8 @@ double LP_pricesparse(void *ctx,int32_t trexflag,char *retstr,struct LP_priceinf
//printf("have trex: iter.%d trexflag.%d %s %.8f %.8f\n",iter,trexflag,symbol,coinpp->bid[1],coinpp->ask[1]);
continue;
}
LP_autopriceset(ctx,1,coinpp,refpp,price,0,0);
LP_autopriceset(ctx,-1,refpp,coinpp,price,0,0);
LP_autopriceset(-1,ctx,1,coinpp,refpp,price,0,0);
LP_autopriceset(-1,ctx,-1,refpp,coinpp,price,0,0);
}
}
}
@ -416,9 +408,49 @@ double LP_pricesparse(void *ctx,int32_t trexflag,char *retstr,struct LP_priceinf
return(nxtkmd);
}
double LP_autoprice_newprice(int32_t bidask,double price,double newprice)
{
double gap; int32_t r;
if ( (bidask == 0 && newprice < price) || (bidask != 0 && newprice > price) )
{
gap = fabs(newprice - price) * 2;
r = (rand() % 100);
if ( bidask == 0 )
price -= (gap * r) / 100.;
else price += (gap * r) / 100.;
}
else if ( price > SMALLVAL )
price = (price * 0.95) + (0.05 * newprice);
else price = newprice;
return(price);
}
double LP_tickered_price(int32_t bidask,char *base,char *rel,double price,cJSON *tickerjson)
{
int32_t i,n; cJSON *item; double basevol,relvol,itemprice;
//printf("%s %s/%s %.8f -> ",bidask == 0 ? "bid" : "ask",base,rel,price);
if ( (n= cJSON_GetArraySize(tickerjson)) > 0 )
{
for (i=n-1; i>=0; i--)
{
// {"timestamp":1513235320,"KMD":860.45202538,"SUPERNET":20.00010000,"price":0.02324371}
item = jitem(tickerjson,i);
if ( (basevol= jdouble(item,base)) > SMALLVAL && (relvol= jdouble(item,rel)) > SMALLVAL )
{
itemprice = (relvol / basevol);
//printf("%.8f ",itemprice);
price = LP_autoprice_newprice(bidask,price,itemprice);
}
}
}
//printf("-> %.8f\n",price);
return(price);
}
void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp)
{
char *retstr; cJSON *retjson,*bid,*ask; uint64_t bidsatoshis,asksatoshis; int32_t i; double nxtkmd,price; struct LP_priceinfo *kmdpp,*fiatpp,*nxtpp,*basepp,*relpp;
static cJSON *tickerjson; static uint32_t lasttime;
char *retstr,*base,*rel; cJSON *retjson,*bid,*ask,*fundjson,*argjson; uint64_t bidsatoshis,asksatoshis; int32_t i,changed; double bch_usd,bch_btc,nxtkmd,price,factor,offset,newprice,margin,price_btc,price_usd,kmd_btc,kmd_usd; struct LP_priceinfo *kmdpp,*fiatpp,*nxtpp,*basepp,*relpp;
if ( (retstr= issue_curlt("https://bittrex.com/api/v1.1/public/getmarketsummaries",LP_HTTP_TIMEOUT*10)) == 0 )
{
printf("trex error getting marketsummaries\n");
@ -438,21 +470,21 @@ void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp)
if ( (kmdpp= LP_priceinfofind("KMD")) != 0 )
{
for (i=0; i<32; i++)
{
{break;
if ( (fiatpp= LP_priceinfofind(CURRENCIES[i])) != 0 )
{
if ( (retjson= LP_paxprice(CURRENCIES[i])) != 0 )
{
//printf("(%s %.8f %.8f) ",CURRENCIES[i],jdouble(retjson,"price"),jdouble(retjson,"invprice"));
price = jdouble(retjson,"price");
LP_autopriceset(ctx,1,fiatpp,kmdpp,price,0,0);
LP_autopriceset(ctx,-1,kmdpp,fiatpp,price,0,0);
LP_autopriceset(-1,ctx,1,fiatpp,kmdpp,price,0,0);
LP_autopriceset(-1,ctx,-1,kmdpp,fiatpp,price,0,0);
free_json(retjson);
}
}
}
}
if ( nxtkmd > SMALLVAL )
if ( 0 && nxtkmd > SMALLVAL )
{
for (i=0; i<sizeof(assetids)/sizeof(*assetids); i++)
{
@ -469,26 +501,225 @@ void LP_autoprice_iter(void *ctx,struct LP_priceinfo *btcpp)
if ( bidsatoshis != 0 && asksatoshis != 0 )
price = 0.5 * dstr(bidsatoshis + asksatoshis) * nxtkmd;
}
LP_autopriceset(ctx,1,nxtpp,kmdpp,price,0,0);
LP_autopriceset(ctx,-1,kmdpp,nxtpp,price,0,0);
LP_autopriceset(-1,ctx,1,nxtpp,kmdpp,price,0,0);
LP_autopriceset(-1,ctx,-1,kmdpp,nxtpp,price,0,0);
//printf("%s %s -> (%s) nxtkmd %.8f %.8f %.8f\n",assetids[i][1],assetids[i][0],jprint(retjson,0),nxtkmd,0.5*dstr(bidsatoshis + asksatoshis),price);
free_json(retjson);
}
}
}
}
if ( time(NULL) > lasttime+60 )
{
if ( tickerjson != 0 )
free_json(tickerjson);
if ( (retstr= LP_ticker("","")) != 0 )
{
tickerjson = cJSON_Parse(retstr);
free(retstr);
}
}
kmd_btc = LP_CMCbtcprice(&kmd_usd,"komodo");
bch_btc = LP_CMCbtcprice(&bch_usd,"bitcoin-cash");
for (i=0; i<num_LP_autorefs; i++)
{
basepp = LP_priceinfofind(LP_autorefs[i].base);
relpp = LP_priceinfofind(LP_autorefs[i].rel);
if ( basepp != 0 && relpp != 0 )
rel = LP_autorefs[i].rel;
base = LP_autorefs[i].base;
margin = LP_autorefs[i].margin;
offset = LP_autorefs[i].offset;
factor = LP_autorefs[i].factor;
if ( (argjson= LP_autorefs[i].fundvalue) != 0 )
{
if ( (fundjson= LP_fundvalue(argjson)) != 0 )
{
if ( jint(fundjson,"missing") == 0 )
{
if ( LP_autorefs[i].fundbid[0] != 0 && (price= jdouble(fundjson,LP_autorefs[i].fundbid)) > SMALLVAL )
{
if ( tickerjson != 0 && LP_autorefs[i].count == 0 )
price = LP_tickered_price(0,base,rel,price,tickerjson);
newprice = (1. / price) * (1. + margin);
if ( LP_autorefs[i].lastbid < SMALLVAL )
LP_autorefs[i].lastbid = newprice;
else LP_autorefs[i].lastbid = (LP_autorefs[i].lastbid * 0.9) + (0.1 *newprice);
newprice = LP_autorefs[i].lastbid;
LP_mypriceset(&changed,rel,base,newprice);
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,rel,base,newprice);
//printf("fundbid %.8f margin %.8f newprice %.8f\n",price,margin,newprice);
}
if ( LP_autorefs[i].fundask[0] != 0 && (price= jdouble(fundjson,LP_autorefs[i].fundask)) > SMALLVAL )
{
if ( tickerjson != 0 && LP_autorefs[i].count == 0 )
price = LP_tickered_price(1,base,rel,price,tickerjson);
newprice = (price * (1. + margin));
if ( LP_autorefs[i].lastask < SMALLVAL )
LP_autorefs[i].lastask = newprice;
else LP_autorefs[i].lastask = (LP_autorefs[i].lastask * 0.9) + (0.1 *newprice);
newprice = LP_autorefs[i].lastask;
LP_mypriceset(&changed,base,rel,newprice);
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,base,rel,newprice);
//printf("fundask %.8f margin %.8f newprice %.8f\n",price,margin,newprice);
}
LP_autorefs[i].count++;
}
free_json(fundjson);
}
}
else if ( strcmp(LP_autorefs[i].refrel,"coinmarketcap") == 0 )
{
//printf("%s/%s for %s/%s margin %.8f\n",base,rel,LP_autorefs[i].refbase,LP_autorefs[i].refrel,margin);
if ( (price_btc= LP_CMCbtcprice(&price_usd,LP_autorefs[i].refbase)) > SMALLVAL )
{
if ( strcmp(rel,"KMD") == 0 )
price = kmd_btc / price_btc;
else if ( strcmp(rel,"BCH") == 0 )
price = bch_btc / price_btc;
else if ( strcmp(rel,"BTC") == 0 )
price = 1. / price_btc;
else continue;
if ( factor > 0. )
price = (price * factor) + offset;
newprice = (price * (1. + margin));
if ( LP_autorefs[i].lastbid < SMALLVAL )
LP_autorefs[i].lastbid = newprice;
else LP_autorefs[i].lastbid = (LP_autorefs[i].lastbid * 0.9) + (0.1 *newprice);
newprice = LP_autorefs[i].lastbid;
LP_mypriceset(&changed,rel,base,newprice);
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,rel,base,newprice);
//printf("price %.8f margin %.8f newprice %.8f %.8f\n",price,margin,newprice,(1. / price) * (1. + margin));
newprice = (1. / price) * (1. + margin);
if ( LP_autorefs[i].lastask < SMALLVAL )
LP_autorefs[i].lastask = newprice;
else LP_autorefs[i].lastask = (LP_autorefs[i].lastask * 0.9) + (0.1 *newprice);
newprice = LP_autorefs[i].lastask;
LP_mypriceset(&changed,base,rel,newprice);
LP_pricepings(ctx,LP_myipaddr,LP_mypubsock,base,rel,newprice);
}
}
else
{
basepp = LP_priceinfofind(base);
relpp = LP_priceinfofind(rel);
if ( basepp != 0 && relpp != 0 )
{
//printf("check ref-autoprice %s/%s %f %f (%.8f %.8f)\n",LP_autorefs[i].refbase,LP_autorefs[i].refrel,relpp->fixedprices[basepp->ind],basepp->fixedprices[relpp->ind],LP_autorefs[i].lastbid,LP_autorefs[i].lastask);
LP_autopriceset(i,ctx,1,basepp,relpp,0.,LP_autorefs[i].refbase,LP_autorefs[i].refrel);
}
}
}
}
void LP_autoprices_update(char *method,char *base,double basevol,char *rel,double relvol)
{
int32_t i; double price,newprice;
if ( basevol > 0. && relvol > 0. )
{
price = relvol/basevol;
for (i=0; i<num_LP_autorefs; i++)
{
//printf("check ref-autoprice %s/%s %f %f\n",LP_autorefs[i].refbase,LP_autorefs[i].refrel,relpp->fixedprices[basepp->ind],basepp->fixedprices[relpp->ind]);
LP_autopriceset(ctx,1,basepp,relpp,0.,LP_autorefs[i].refbase,LP_autorefs[i].refrel);
if ( strcmp(LP_autorefs[i].rel,rel) == 0 && strcmp(base,LP_autorefs[i].base) == 0 )
{
newprice = (LP_autorefs[i].lastask * 0.99) + (0.01 * price);
if ( LP_autorefs[i].lastask > 0 )
{
printf("%s: autoprice ask update %s/%s %.8f vs myprice %.8f/%.8f -> %.8f\n",method,base,rel,price,LP_autorefs[i].lastbid,LP_autorefs[i].lastask,newprice);
LP_autorefs[i].lastask = newprice;
} // else printf("%s: autoprice ask skip update %s/%s %.8f vs myprice %.8f/%.8f -> %.8f\n",method,base,rel,price,LP_autorefs[i].lastbid,LP_autorefs[i].lastask,newprice);
}
else if ( strcmp(LP_autorefs[i].rel,base) == 0 && strcmp(rel,LP_autorefs[i].base) == 0 )
{
newprice = (LP_autorefs[i].lastbid * 0.99) + (0.01 * price);
if ( LP_autorefs[i].lastbid > 0 )
{
printf("%s: autoprice bid update %s/%s %.8f vs myprice %.8f/%.8f -> %.8f\n",method,base,rel,price,LP_autorefs[i].lastbid,LP_autorefs[i].lastask,newprice);
LP_autorefs[i].lastbid = newprice;
} // else printf("%s: autoprice bid skip update %s/%s %.8f vs myprice %.8f/%.8f -> %.8f\n",method,base,rel,price,LP_autorefs[i].lastbid,LP_autorefs[i].lastask,newprice);
}
}
}
}
int32_t LP_autoprice(void *ctx,char *base,char *rel,cJSON *argjson)
{
//curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"MNZ\",\"rel\":\"KMD\",\"offset\":0.1,\"refbase\":\"KMD\",\refrel\":\"BTC\",\"factor\":15000,\"margin\":0.01}"
struct LP_priceinfo *basepp,*relpp; int32_t i,retval = -1; char *fundvalue_bid,*fundvalue_ask,*refbase="",*refrel=""; double minprice,margin,offset,factor,fixedprice; cJSON *fundvalue;
//printf("autoprice.(%s %s) %s\n",base,rel,jprint(argjson,0));
if ( (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
if ( jobj(argjson,"minprice") != 0 )
minprice = jdouble(argjson,"minprice");
else minprice = 0.;
margin = jdouble(argjson,"margin");
offset = jdouble(argjson,"offset");
factor = jdouble(argjson,"factor");
fixedprice = jdouble(argjson,"fixed");
basepp->fixedprices[relpp->ind] = fixedprice;
basepp->minprices[relpp->ind] = minprice;
basepp->margins[relpp->ind] = margin;
basepp->offsets[relpp->ind] = offset;
basepp->factors[relpp->ind] = factor;
refbase = jstr(argjson,"refbase");
refrel = jstr(argjson,"refrel");
fundvalue_bid = jstr(argjson,"fundvalue_bid");
fundvalue_ask = jstr(argjson,"fundvalue_ask");
if ( fundvalue_bid != 0 || fundvalue_ask != 0 || fixedprice > SMALLVAL || (refbase != 0 && refrel != 0) )
{
if ( fixedprice > SMALLVAL )
{
refbase = base;
refrel = rel;
}
for (i=0; i<num_LP_autorefs; i++)
{
if ( strcmp(base,LP_autorefs[i].base) == 0 && strcmp(rel,LP_autorefs[i].rel) == 0 )
{
if ( fundvalue_bid != 0 || fundvalue_ask != 0 )
{
fundvalue = jduplicate(argjson);
jdelete(fundvalue,"method");
jaddstr(fundvalue,"method","fundvalue");
LP_autorefs[i].fundvalue = fundvalue;
safecopy(LP_autorefs[i].fundbid,fundvalue_bid,sizeof(LP_autorefs[i].fundbid));
safecopy(LP_autorefs[i].fundask,fundvalue_ask,sizeof(LP_autorefs[i].fundask));
}
LP_autorefs[i].margin = margin;
LP_autorefs[i].factor = factor;
LP_autorefs[i].offset = offset;
safecopy(LP_autorefs[i].refbase,refbase,sizeof(LP_autorefs[i].refbase));
safecopy(LP_autorefs[i].refrel,refrel,sizeof(LP_autorefs[i].refrel));
printf("%d Update ref %s/%s for %s/%s factor %.8f offset %.8f\n",i,refbase,refrel,base,rel,factor,offset);
break;
}
}
if ( i == num_LP_autorefs && num_LP_autorefs < sizeof(LP_autorefs)/sizeof(*LP_autorefs) )
{
if ( fundvalue_bid != 0 || fundvalue_ask != 0 )
{
fundvalue = jduplicate(argjson);
jdelete(fundvalue,"method");
jaddstr(fundvalue,"method","fundvalue");
LP_autorefs[num_LP_autorefs].fundvalue = fundvalue;
safecopy(LP_autorefs[num_LP_autorefs].fundbid,fundvalue_bid,sizeof(LP_autorefs[num_LP_autorefs].fundbid));
safecopy(LP_autorefs[num_LP_autorefs].fundask,fundvalue_ask,sizeof(LP_autorefs[num_LP_autorefs].fundask));
}
LP_autorefs[num_LP_autorefs].margin = margin;
LP_autorefs[num_LP_autorefs].factor = factor;
LP_autorefs[num_LP_autorefs].offset = offset;
safecopy(LP_autorefs[num_LP_autorefs].refbase,refbase,sizeof(LP_autorefs[num_LP_autorefs].refbase));
safecopy(LP_autorefs[num_LP_autorefs].refrel,refrel,sizeof(LP_autorefs[num_LP_autorefs].refrel));
safecopy(LP_autorefs[num_LP_autorefs].base,base,sizeof(LP_autorefs[num_LP_autorefs].base));
safecopy(LP_autorefs[num_LP_autorefs].rel,rel,sizeof(LP_autorefs[num_LP_autorefs].rel));
printf("%d Using ref %s/%s for %s/%s factor %.8f, offset %.8f, margin %.8f fixed %.8f\n",num_LP_autorefs,refbase,refrel,base,rel,factor,offset,margin,fixedprice);
num_LP_autorefs++;
}
}
LP_autoprices++;
retval = 0;
}
//LP_autoprice_iter(ctx,LP_priceinfofind("BTC"));
return(retval);
}
int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,struct iguana_info *buy,struct iguana_info *sell,double relvolume,int32_t setbaserel,char *gui)
{
char *retstr2; uint64_t txfee,desttxfee; double bid,ask,maxprice; bits256 zero; uint32_t requestid,quoteid,iter,i; cJSON *retjson2; struct LP_utxoinfo A; struct LP_address_utxo *utxos[1000]; int32_t max=(int32_t)(sizeof(utxos)/sizeof(*utxos));
@ -558,8 +789,6 @@ int32_t LP_portfolio_trade(void *ctx,uint32_t *requestidp,uint32_t *quoteidp,str
else return(-1);
}
struct LP_portfoliotrade { double metric; char buycoin[65],sellcoin[65]; };
int32_t LP_portfolio_order(struct LP_portfoliotrade *trades,int32_t max,cJSON *array)
{
int32_t i,j,m,n = 0; cJSON *item; struct LP_portfoliotrade coins[256];
@ -610,7 +839,7 @@ void prices_loop(void *ctx)
{
char *retstr; cJSON *retjson,*array; char *buycoin,*sellcoin; struct iguana_info *buy,*sell; uint32_t requestid,quoteid; int32_t i,n,m; struct LP_portfoliotrade trades[256]; struct LP_priceinfo *btcpp;
strcpy(prices_loop_stats.name,"prices_loop");
prices_loop_stats.threshold = 91000.;
prices_loop_stats.threshold = 191000.;
while ( 1 )
{
//printf("prices loop autoprices.%d autorefs.%d\n",LP_autoprices,num_LP_autorefs);

165
iguana/exchanges/LP_prices.c

@ -33,7 +33,7 @@ struct LP_priceinfo
char symbol[68];
uint64_t coinbits;
int32_t ind,pad;
double diagval,high[2],low[2],last[2],bid[2],ask[2]; //volume,btcvolume,prevday; // mostly bittrex info
double diagval,high[2],low[2],last[2],bid[2],ask[2];
double relvals[LP_MAXPRICEINFOS];
double myprices[LP_MAXPRICEINFOS];
double minprices[LP_MAXPRICEINFOS]; // autoprice
@ -41,9 +41,6 @@ struct LP_priceinfo
double margins[LP_MAXPRICEINFOS];
double offsets[LP_MAXPRICEINFOS];
double factors[LP_MAXPRICEINFOS];
//double maxprices[LP_MAXPRICEINFOS]; // autofill of base/rel
//double relvols[LP_MAXPRICEINFOS];
//FILE *fps[LP_MAXPRICEINFOS];
} LP_priceinfos[LP_MAXPRICEINFOS];
int32_t LP_numpriceinfos;
@ -56,6 +53,20 @@ struct LP_cacheinfo
uint32_t timestamp;
} *LP_cacheinfos;
void LP_priceinfos_clear()
{
int32_t i; struct LP_priceinfo *pp;
for (i=0; i<LP_numpriceinfos; i++)
{
pp = &LP_priceinfos[i];
memset(pp->myprices,0,sizeof(pp->myprices));
memset(pp->minprices,0,sizeof(pp->minprices));
memset(pp->fixedprices,0,sizeof(pp->fixedprices));
memset(pp->margins,0,sizeof(pp->margins));
memset(pp->offsets,0,sizeof(pp->offsets));
memset(pp->factors,0,sizeof(pp->factors));
}
}
float LP_pubkey_price(int32_t *numutxosp,int64_t *avesatoshisp,int64_t *maxsatoshisp,struct LP_pubkey_info *pubp,uint32_t baseind,uint32_t relind)
{
@ -503,8 +514,20 @@ int32_t LP_mypriceset(int32_t *changedp,char *base,char *rel,double price)
if ( base != 0 && rel != 0 && (basepp= LP_priceinfofind(base)) != 0 && (relpp= LP_priceinfofind(rel)) != 0 )
{
if ( fabs(basepp->myprices[relpp->ind] - price)/price > 0.001 )
if ( price == 0. || fabs(basepp->myprices[relpp->ind] - price)/price > 0.001 )
*changedp = 1;
if ( price == 0. )
{
relpp->minprices[basepp->ind] = 0.;
relpp->fixedprices[basepp->ind] = 0.;
relpp->margins[basepp->ind] = 0.;
relpp->offsets[basepp->ind] = 0.;
relpp->factors[basepp->ind] = 0.;
}
/*else if ( basepp->myprices[relpp->ind] > SMALLVAL )
{
price = (basepp->myprices[relpp->ind] * 0.9) + (0.1 * price);
}*/
basepp->myprices[relpp->ind] = price; // ask
//printf("LP_mypriceset base.%s rel.%s <- price %.8f\n",base,rel,price);
//relpp->myprices[basepp->ind] = (1. / price); // bid
@ -526,7 +549,9 @@ double LP_price(char *base,char *rel)
if ( (basepp= LP_priceinfoptr(&relind,base,rel)) != 0 )
{
if ( (price= basepp->myprices[relind]) == 0. )
{
price = basepp->relvals[relind];
}
}
return(price);
}
@ -908,34 +933,10 @@ int64_t LP_KMDvalue(struct iguana_info *coin,int64_t balance)
{
if ( strcmp(coin->symbol,"KMD") == 0 )
KMDvalue = balance;
/*else if ( (retstr= LP_orderbook(coin->symbol,"KMD",-1)) != 0 )
{
if ( (orderbook= cJSON_Parse(retstr)) != 0 )
{
if ( (asks= jarray(&numasks,orderbook,"asks")) != 0 && numasks > 0 )
{
item = jitem(asks,0);
price = ask = jdouble(item,"price");
//printf("%s/%s ask %.8f\n",coin->symbol,"KMD",ask);
}
if ( (bids= jarray(&numbids,orderbook,"bids")) != 0 && numbids > 0 )
{
item = jitem(asks,0);
bid = jdouble(item,"price");
if ( price == 0. )
price = bid;
else price = (bid + ask) * 0.5;
//printf("%s/%s bid %.8f ask %.8f price %.8f\n",coin->symbol,"KMD",bid,ask,price);
}
KMDvalue = price * balance;
free_json(orderbook);
}
free(retstr);
}*/
else
{
price = LP_price(coin->symbol,"KMD");
KMDvalue = price * balance;
if ( (price= LP_price(coin->symbol,"KMD")) > SMALLVAL )
KMDvalue = price * balance;
}
}
return(KMDvalue);
@ -1138,3 +1139,105 @@ void LP_pricefeedupdate(bits256 pubkey,char *base,char *rel,double price,char *u
// printf("error finding %s/%s %.8f\n",base,rel,price);
}
double LP_CMCbtcprice(double *price_usdp,char *symbol)
{
char *retstr; cJSON *ticker,*item; double price_btc = 0.;
*price_usdp = 0.;
if ( (retstr= cmc_ticker(symbol)) != 0 )
{
if ( (ticker= cJSON_Parse(retstr)) != 0 )
{
item = jitem(ticker,0);
price_btc = jdouble(item,"price_btc");
*price_usdp = jdouble(item,"price_usd");
//printf("%.8f item.(%s)\n",price_btc,jprint(item,0));
free_json(ticker);
}
free(retstr);
}
return(price_btc);
}
cJSON *LP_fundvalue(cJSON *argjson)
{
cJSON *holdings,*item,*newitem,*array,*retjson; int32_t i,iter,n,missing=0; double usdprice,divisor,btcprice,balance,btcsum,KMDholdings,numKMD; struct iguana_info *coin; char *symbol,*coinaddr; int64_t fundvalue,KMDvalue = 0;
fundvalue = 0;
KMDholdings = btcsum = 0.;
array = cJSON_CreateArray();
for (iter=0; iter<2; iter++)
{
if ( iter == 0 )
holdings = jarray(&n,argjson,"holdings");
else
{
if ( (coinaddr= jstr(argjson,"address")) != 0 )
{
holdings = LP_balances(coinaddr);
n = cJSON_GetArraySize(holdings);
} else break;
}
if ( holdings != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(holdings,i);
if ( (symbol= jstr(item,"coin")) != 0 && (balance= jdouble(item,"balance")) > SMALLVAL )
{
newitem = cJSON_CreateObject();
jaddstr(newitem,"coin",symbol);
jaddnum(newitem,"balance",balance);
if ( (coin= LP_coinfind(symbol)) != 0 && (KMDvalue= LP_KMDvalue(coin,SATOSHIDEN * balance)) > 0 )
{
jaddnum(newitem,"KMD",dstr(KMDvalue));
fundvalue += KMDvalue;
if ( strcmp(symbol,"KMD") == 0 )
KMDholdings += dstr(KMDvalue);
}
else if ( iter == 0 && (btcprice= LP_CMCbtcprice(&usdprice,symbol)) > SMALLVAL )
{
btcsum += btcprice * balance;
jaddnum(newitem,"BTC",btcprice * balance);
}
else jaddstr(newitem,"error","no price source");
jaddi(array,newitem);
} else missing++;
}
}
}
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jaddnum(retjson,"missing",missing);
jadd(retjson,"holdings",array);
btcprice = LP_CMCbtcprice(&usdprice,"komodo");
divisor = jdouble(argjson,"divisor");
jaddnum(retjson,"KMDholdings",KMDholdings);
if ( btcsum != 0 )
{
if ( btcprice > SMALLVAL )
{
numKMD = (btcsum / btcprice);
fundvalue += numKMD * SATOSHIDEN;
jaddnum(retjson,"KMD_BTC",btcprice);
jaddnum(retjson,"btcsum",btcsum);
numKMD += KMDholdings;
jaddnum(retjson,"btc2kmd",numKMD);
if ( divisor != 0 )
{
jaddnum(retjson,"NAV_KMD",numKMD/divisor);
jaddnum(retjson,"NAV_BTC",(btcsum + (KMDholdings * btcprice))/divisor);
jaddnum(retjson,"NAV_USD",(usdprice * numKMD)/divisor);
}
}
}
jaddnum(retjson,"fundvalue",dstr(fundvalue));
if ( divisor != 0 )
{
jaddnum(retjson,"divisor",divisor);
numKMD = dstr(fundvalue);
jaddnum(retjson,"assetNAV_KMD",numKMD/divisor);
jaddnum(retjson,"assetNAV_BTC",(btcprice * numKMD)/divisor);
jaddnum(retjson,"assetNAV_USD",(usdprice * numKMD)/divisor);
}
return(retjson);
}

102
iguana/exchanges/LP_privkey.c

@ -202,30 +202,72 @@ char *LP_secretaddresses(void *ctx,char *prefix,char *passphrase,int32_t n,uint8
return(jprint(retjson,1));
}
static const char base58_chars[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
int32_t LP_wifstr_valid(char *wifstr)
{
bits256 privkey,cmpkey; uint8_t wiftype; char cmpstr[128],cmpstr2[128]; int32_t i;
memset(privkey.bytes,0,sizeof(privkey));
memset(cmpkey.bytes,0,sizeof(cmpkey));
for (i=0; wifstr[i]!=0; i++)
if ( strchr(base58_chars,wifstr[i]) == 0 )
return(0);
bitcoin_wif2priv(0,&wiftype,&privkey,wifstr);
bitcoin_priv2wif(0,cmpstr,privkey,wiftype);
if ( strcmp(cmpstr,wifstr) == 0 )
{
printf("%s is valid wif\n",wifstr);
return(1);
}
else if ( bits256_nonz(privkey) != 0 )
{
bitcoin_wif2priv(0,&wiftype,&cmpkey,cmpstr);
bitcoin_priv2wiflong(0,cmpstr2,privkey,wiftype);
char str[65],str2[65]; printf("mismatched wifstr %s -> %s -> %s %s %s\n",wifstr,bits256_str(str,privkey),cmpstr,bits256_str(str2,cmpkey),cmpstr2);
if ( bits256_cmp(privkey,cmpkey) == 0 )
return(1);
}
return(0);
}
bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguana_info *coin,char *passphrase,char *wifstr)
{
//static uint32_t counter;
bits256 privkey,userpub,zero,userpass,checkkey; char tmpstr[128]; cJSON *retjson; uint8_t tmptype; int32_t notarized;
bits256 privkey,userpub,zero,userpass,checkkey,tmpkey; char tmpstr[128]; cJSON *retjson; uint8_t tmptype; int32_t notarized; uint64_t nxtaddr;
if ( (wifstr == 0 || wifstr[0] == 0) && LP_wifstr_valid(passphrase) > 0 )
{
wifstr = passphrase;
passphrase = 0;
}
if ( passphrase != 0 && passphrase[0] != 0 )
{
calc_NXTaddr(G.LP_NXTaddr,userpub.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
conv_NXTpassword(privkey.bytes,pubkeyp->bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
privkey.bytes[0] &= 248, privkey.bytes[31] &= 127, privkey.bytes[31] |= 64;
//vcalc_sha256(0,checkkey.bytes,(uint8_t *)passphrase,(int32_t)strlen(passphrase));
//printf("SHA256.(%s) ",bits256_str(pstr,checkkey));
//printf("privkey.(%s)\n",bits256_str(pstr,privkey));
bitcoin_priv2wif(coin->wiftaddr,tmpstr,privkey,coin->wiftype);
bitcoin_wif2priv(coin->wiftaddr,&tmptype,&checkkey,tmpstr);
if ( bits256_cmp(privkey,checkkey) != 0 )
{
char str[65],str2[65]; printf("mismatched privkeys from wif conversion: %s -> %s -> %s\n",bits256_str(str,privkey),tmpstr,bits256_str(str2,checkkey));
exit(1);
}
}
else
{
bitcoin_wif2priv(coin->wiftaddr,&tmptype,&privkey,wifstr);
if ( 0 )
bitcoin_priv2wif(coin->wiftaddr,tmpstr,privkey,tmptype);
if ( strcmp(tmpstr,wifstr) != 0 )
{
char str[65],str2[65];
checkkey = iguana_wif2privkey(wifstr);
if ( bits256_cmp(checkkey,privkey) != 0 )
printf("WIF.(%s) -> %s or %s?\n",wifstr,bits256_str(str,privkey),bits256_str(str2,checkkey));
printf("error reproducing the wifstr, likely edge case like non-supported uncompressed pubkey\n");
exit(1);
}
tmpkey = privkey;
nxtaddr = conv_NXTpassword(tmpkey.bytes,pubkeyp->bytes,0,0);
RS_encode(G.LP_NXTaddr,nxtaddr);
}
privkey.bytes[0] &= 248, privkey.bytes[31] &= 127, privkey.bytes[31] |= 64;
bitcoin_priv2pub(ctx,coin->pubkey33,coin->smartaddr,privkey,coin->taddr,coin->pubtype);
if ( coin->counter == 0 )
{
@ -235,8 +277,6 @@ bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguan
bitcoin_addr2rmd160(coin->taddr,&tmptype,G.LP_myrmd160,coin->smartaddr);
LP_privkeyadd(privkey,G.LP_myrmd160);
G.LP_privkey = privkey;
if ( 0 && (coin->pubtype != 60 || strcmp(coin->symbol,"KMD") == 0) )
printf("%s (%s) %d wif.(%s) (%s)\n",coin->symbol,coin->smartaddr,coin->pubtype,tmpstr,passphrase);
if ( G.counter++ == 0 )
{
bitcoin_priv2wif(coin->wiftaddr,G.USERPASS_WIFSTR,privkey,188);
@ -260,7 +300,7 @@ bits256 LP_privkeycalc(void *ctx,uint8_t *pubkey33,bits256 *pubkeyp,struct iguan
{
if ( jobj(retjson,"error") != 0 )
{
printf("cant importprivkey.%s -> (%s), abort session\n",coin->symbol,jprint(retjson,1));
printf("cant importprivkey.%s %s -> (%s), abort session\n",coin->symbol,coin->smartaddr,jprint(retjson,1));
exit(-1);
}
free_json(retjson);
@ -321,34 +361,34 @@ int32_t LP_passphrase_init(char *passphrase,char *gui)
printf("waiting for G.waiting\n");
sleep(5);
}
/*for (iambob=0; iambob<2; iambob++)
{
if ( G.LP_utxoinfos[iambob] != 0 )
{
HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp)
{
HASH_DELETE(hh,G.LP_utxoinfos[iambob],utxo);
//free(utxo);
}
}
if ( G.LP_utxoinfos2[iambob] != 0 )
{
G.LP_utxoinfos2[iambob] = 0;
//HASH_ITER(hh,G.LP_utxoinfos2[iambob],utxo,tmp)
//{
// HASH_DELETE(hh,G.LP_utxoinfos2[iambob],utxo);
// free(utxo);
//}
}
}*/
memset(&G,0,sizeof(G));
LP_privkey_updates(ctx,LP_mypubsock,passphrase);
init_hexbytes_noT(G.LP_myrmd160str,G.LP_myrmd160,20);
G.LP_sessionid = (uint32_t)time(NULL);
safecopy(G.gui,gui,sizeof(G.gui));
LP_tradebot_pauseall();
LP_portfolio_reset();
LP_priceinfos_clear();
G.USERPASS_COUNTER = counter;
G.initializing = 0;
return(0);
}
void LP_privkey_tests()
{
char wifstr[64],str[65],str2[65]; bits256 privkey,checkkey; int32_t i; uint8_t tmptype;
for (i=0; i<200000000; i++)
{
privkey = rand256(0);
bitcoin_priv2wif(0,wifstr,privkey,0xff);
bitcoin_wif2priv(0,&tmptype,&checkkey,wifstr);
if ( bits256_cmp(privkey,checkkey) != 0 )
{
printf("i.%d: %s vs %s\n",i,bits256_str(str,privkey),bits256_str(str2,checkkey));
exit(-1);
}
if ( (i % 1000000) == 0 )
fprintf(stderr,"%.1f%% ",100.*(double)i/200000000);
}
printf("%d privkeys checked\n",i);
}

195
iguana/exchanges/LP_remember.c

@ -243,6 +243,7 @@ bits256 basilisk_swap_privbob_extract(char *symbol,bits256 spendtxid,int32_t vin
bits256 basilisk_swap_privBn_extract(bits256 *bobrefundp,char *bobcoin,bits256 bobdeposit,bits256 privBn)
{
char destaddr[64];
destaddr[0] = 0;
if ( bits256_nonz(privBn) == 0 )
{
if ( bits256_nonz(bobdeposit) != 0 )
@ -253,12 +254,16 @@ bits256 basilisk_swap_privBn_extract(bits256 *bobrefundp,char *bobcoin,bits256 b
return(privBn);
}
bits256 basilisk_swap_spendupdate(int32_t iambob,char *symbol,char *spentaddr,int32_t *sentflags,bits256 *txids,int32_t utxoind,int32_t alicespent,int32_t bobspent,int32_t vout,char *aliceaddr,char *bobaddr,char *Adest,char *dest)
bits256 basilisk_swap_spendupdate(int32_t iambob,char *symbol,char *spentaddr,int32_t *sentflags,bits256 *txids,int32_t utxoind,int32_t alicespent,int32_t bobspent,int32_t utxovout,char *aliceaddr,char *bobaddr,char *Adest,char *dest)
{
bits256 spendtxid,txid; char destaddr[64],str[65]; int32_t i,n,m; struct iguana_info *coin; cJSON *array,*txobj,*vins,*vin;
if ( (coin= LP_coinfind(symbol)) != 0 && coin->electrum != 0 )
bits256 spendtxid,txid; char destaddr[64],str[65]; int32_t i,n; struct iguana_info *coin; cJSON *array,*txobj;
memset(&spendtxid,0,sizeof(spendtxid));
destaddr[0] = 0;
if ( (coin= LP_coinfind(symbol)) == 0 )
return(spendtxid);
//printf("spentaddr.%s aliceaddr.%s bobaddr.%s Adest.%s Bdest.%s\n",spentaddr,aliceaddr,bobaddr,Adest,dest);
if ( coin->electrum != 0 )
{
//printf("spentaddr.%s aliceaddr.%s bobaddr.%s Adest.%s Bdest.%s\n",spentaddr,aliceaddr,bobaddr,Adest,dest);
if ( (array= electrum_address_gethistory(symbol,coin->electrum,&array,spentaddr,txids[utxoind])) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
@ -269,16 +274,8 @@ bits256 basilisk_swap_spendupdate(int32_t iambob,char *symbol,char *spentaddr,in
//printf("i.%d of %d: %s\n",i,n,bits256_str(str,txid));
if ( bits256_cmp(txid,txids[utxoind]) != 0 )
{
if ( (txobj= LP_gettx(symbol,txid,1)) != 0 )
{
//printf("txobj.(%s)\n",jprint(txobj,0));
if ( (vins= jarray(&m,txobj,"vin")) != 0 )
{
vin = jitem(vins,0);
//printf("vin0.(%s)\n",jprint(vin,0));
}
if ( (txobj= LP_gettx(symbol,txid,1)) != 0 ) // good side effects
free_json(txobj);
}
}
}
}
@ -286,12 +283,16 @@ bits256 basilisk_swap_spendupdate(int32_t iambob,char *symbol,char *spentaddr,in
free_json(array);
}
}
else
{
if ( iambob != 0 )
strcpy(destaddr,aliceaddr);
else strcpy(destaddr,bobaddr);
}
txid = txids[utxoind];
memset(&spendtxid,0,sizeof(spendtxid));
if ( bits256_nonz(txid) != 0 )//&& sentflags[utxoind] != 0 )
{
destaddr[0] = 0;
spendtxid = LP_swap_spendtxid(symbol,destaddr,txid,vout);
spendtxid = LP_swap_spendtxid(symbol,destaddr,txid,utxovout);
if ( bits256_nonz(spendtxid) != 0 )
{
sentflags[utxoind] = 1;
@ -374,11 +375,18 @@ int32_t basilisk_swap_isfinished(int32_t iambob,bits256 *txids,int32_t *sentflag
}
else if ( bits256_nonz(Apaymentspent) != 0 )
return(1);
else if ( bits256_nonz(paymentspent) != 0 && bits256_nonz(depositspent) != 0 )
return(1);
}
else
{
if ( bits256_nonz(txids[BASILISK_ALICEPAYMENT]) == 0 && sentflags[BASILISK_ALICEPAYMENT] == 0 )
return(1);
if ( sentflags[BASILISK_ALICEPAYMENT] == 0 )
{
if ( bits256_nonz(txids[BASILISK_ALICEPAYMENT]) == 0 )
return(1);
else if ( sentflags[BASILISK_BOBPAYMENT] != 0 && sentflags[BASILISK_BOBREFUND] != 0 )
return(1);
}
else
{
if ( sentflags[BASILISK_ALICERECLAIM] != 0 || sentflags[BASILISK_ALICESPEND] != 0 )
@ -728,7 +736,11 @@ int32_t LP_swap_load(struct LP_swap_remember *rswap,int32_t forceflag)
rswap->iambob = jint(txobj,"iambob");
txid = jbits256(txobj,"txid");
if ( bits256_nonz(txid) == 0 )
{
free(fstr);
free_json(txobj);
continue;
}
rswap->txids[i] = txid;
if ( jstr(txobj,"Apayment") != 0 )
safecopy(rswap->alicepaymentaddr,jstr(txobj,"Apayment"),sizeof(rswap->alicepaymentaddr));
@ -875,12 +887,14 @@ int32_t LP_spends_set(struct LP_swap_remember *rswap)
return(numspent);
}
cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid,int32_t forceflag)
cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requestid,uint32_t quoteid,int32_t forceflag,int32_t pendingonly)
{
static void *ctx;
struct LP_swap_remember rswap; int32_t i,j,flag,numspent,len,secretstart,redeemlen; char str[65],*srcAdest,*srcBdest,*destAdest,*destBdest,otheraddr[64]; cJSON *item,*txoutobj; bits256 rev,signedtxid,zero,deadtxid; struct iguana_info *bob=0,*alice=0; uint8_t redeemscript[1024],userdata[1024];
if ( ctx == 0 )
ctx = bitcoin_ctx();
if ( requestid == 0 || quoteid == 0 )
return(cJSON_Parse("{\"error\":\"null requestid or quoteid\"}"));
if ( (rswap.iambob= LP_rswap_init(&rswap,requestid,quoteid,forceflag)) < 0 )
return(cJSON_Parse("{\"error\":\"couldnt initialize rswap, are all coins active?\"}"));
decode_hex(deadtxid.bytes,32,"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
@ -890,8 +904,13 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
srcAdest = srcBdest = destAdest = destBdest = 0;
if ( rswap.bobcoin[0] == 0 || rswap.alicecoin[0] == 0 || strcmp(rswap.bobcoin,rswap.src) != 0 || strcmp(rswap.alicecoin,rswap.dest) != 0 )
{
//printf("legacy DB SWAPS.(%u %u) %llu files BOB.(%s) Alice.(%s) src.(%s) dest.(%s)\n",rswap.requestid,rswap.quoteid,(long long)rswap.aliceid,rswap.bobcoin,rswap.alicecoin,rswap.src,rswap.dest);
return(cJSON_Parse("{\"error\":\"mismatched bob/alice vs src/dest coins??\"}"));
//printf("legacy r%u-q%u DB SWAPS.(%u %u) %llu files BOB.(%s) Alice.(%s) src.(%s) dest.(%s)\n",requestid,quoteid,rswap.requestid,rswap.quoteid,(long long)rswap.aliceid,rswap.bobcoin,rswap.alicecoin,rswap.src,rswap.dest);
cJSON *retjson = cJSON_CreateObject();
jaddstr(retjson,"error","swap never started");
jaddnum(retjson,"requestid",requestid);
jaddnum(retjson,"quoteid",quoteid);
return(retjson);
//return(cJSON_Parse("{\"error\":\"mismatched bob/alice vs src/dest coins??\"}"));
}
alice = LP_coinfind(rswap.alicecoin);
bob = LP_coinfind(rswap.bobcoin);
@ -904,6 +923,15 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
bitcoin_address(otheraddr,alice->taddr,alice->pubtype,rswap.other33,33);
destBdest = otheraddr;
destAdest = rswap.Adestaddr;
if ( strcmp(alice->smartaddr,rswap.Adestaddr) != 0 )
{
printf("this isnt my swap! alice.(%s vs %s)\n",alice->smartaddr,rswap.Adestaddr);
cJSON *retjson = cJSON_CreateObject();
jaddstr(retjson,"error","swap for different account");
jaddnum(retjson,"requestid",requestid);
jaddnum(retjson,"quoteid",quoteid);
return(retjson);
}
}
if ( (bob= LP_coinfind(rswap.bobcoin)) != 0 )
{
@ -919,6 +947,15 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
bitcoin_address(otheraddr,bob->taddr,bob->pubtype,rswap.other33,33);
srcAdest = otheraddr;
srcBdest = rswap.destaddr;
if ( strcmp(bob->smartaddr,rswap.destaddr) != 0 )
{
printf("this isnt my swap! bob.(%s vs %s)\n",bob->smartaddr,rswap.destaddr);
cJSON *retjson = cJSON_CreateObject();
jaddstr(retjson,"error","swap for different account");
jaddnum(retjson,"requestid",requestid);
jaddnum(retjson,"quoteid",quoteid);
return(retjson);
}
}
if ( (alice= LP_coinfind(rswap.alicecoin)) != 0 )
{
@ -997,7 +1034,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
}
if ( rswap.sentflags[BASILISK_ALICECLAIM] == 0 && rswap.sentflags[BASILISK_BOBDEPOSIT] != 0 && bits256_nonz(rswap.txids[BASILISK_BOBDEPOSIT]) != 0 && bits256_nonz(rswap.depositspent) == 0 )
{
if ( time(NULL) > rswap.expiration )
if ( time(NULL) > rswap.expiration+777 )
{
flag = 0;
if ( bob->electrum == 0 )
@ -1086,7 +1123,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
free_json(txoutobj), flag = 0;
else flag = -1, rswap.paymentspent = deadtxid;
}
if ( flag == 0 && time(NULL) > rswap.expiration )
if ( flag == 0 && time(NULL) > rswap.expiration+777 )
{
// bobreclaim
redeemlen = basilisk_swap_bobredeemscript(0,&secretstart,redeemscript,rswap.plocktime,rswap.pubA0,rswap.pubB0,rswap.pubB1,zero,rswap.privBn,rswap.secretAm,rswap.secretAm256,rswap.secretBn,rswap.secretBn256);
@ -1115,7 +1152,7 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
free_json(txoutobj), flag = 0;
else flag = -1, rswap.depositspent = deadtxid;
}
if ( flag == 0 && (bits256_nonz(rswap.Apaymentspent) != 0 || time(NULL) > rswap.expiration) )
if ( flag == 0 && (bits256_nonz(rswap.Apaymentspent) != 0 || time(NULL) > rswap.expiration+777) )
{
printf("do the refund! paymentspent.%s now.%u vs expiration.%u\n",bits256_str(str,rswap.paymentspent),(uint32_t)time(NULL),rswap.expiration);
//if ( txbytes[BASILISK_BOBREFUND] == 0 )
@ -1185,10 +1222,37 @@ cJSON *basilisk_remember(int64_t *KMDtotals,int64_t *BTCtotals,uint32_t requesti
for (i=0; i<sizeof(txnames)/sizeof(*txnames); i++)
if ( rswap.txbytes[i] != 0 )
free(rswap.txbytes[i]), rswap.txbytes[i] = 0;
return(item);
if ( pendingonly != 0 && rswap.origfinishedflag != 0 )
{
free_json(item);
item = 0;
}
return(item);
}
char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid,int32_t forceflag)
void for_satinder()
{
void *ctx; char *signedtx,*paymentaddr,*rscript; int32_t redeemlen,len; uint8_t pubkey33[33],redeemscript[512],userdata[512]; uint32_t expiration; bits256 zero,priv1,signedtxid,utxotxid; int64_t satoshis; struct iguana_info *coin;
ctx = bitcoin_ctx();
coin = LP_coinfind("ZEC");
expiration = 1511219708;
rscript = "63048543135ab1752103b1168377dec884dc7d615c64e0963a5efeaf3c34f8c88be04dec2ee5cc0608c0ac67a914fcfc9291cad04225e574b374516656f80b991c808821021a53a4a59017258f12b6a293fee7644dff98899d3e4a8917b4b3204ee50995a1ac68";
redeemlen = (int32_t)strlen(rscript)/2;
decode_hex(redeemscript,redeemlen,rscript);
decode_hex(utxotxid.bytes,32,"ef5b1d463715e6b5bd51c3161147f1aabebc7f3f88438cbdc744590c2b9856e6");
decode_hex(pubkey33,33,"02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92");
paymentaddr = "t1Y9ukZMkNAYonCFVp3jSdx7NT8dEsXss7k";
satoshis = 1344 * SATOSHIDEN - 10000;
memset(zero.bytes,0,sizeof(zero));
decode_hex(priv1.bytes,32,"00000000000000000000000000000000bebc7f3f88438cbdc744590c2b9856e6"); // need to put the actual privkey here
len = basilisk_swapuserdata(userdata,zero,1,priv1,redeemscript,redeemlen);
if ( (signedtx= basilisk_swap_bobtxspend(&signedtxid,coin->txfee,"satinder",coin->symbol,coin->wiftaddr,coin->taddr,coin->pubtype,coin->p2shtype,coin->isPoS,coin->wiftype,ctx,priv1,0,redeemscript,redeemlen,userdata,len,utxotxid,0,0,pubkey33,0,expiration,&satoshis,0,0,paymentaddr,1,coin->zcash)) != 0 )
{
char str[65]; printf("satinder %s signedtx.(%s)\n",bits256_str(str,signedtxid),signedtx);
} else printf("error with satinder tx\n");
}
char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid,int32_t forceflag,int32_t pendingonly)
{
uint64_t ridqids[4096],ridqid; char fname[512]; FILE *fp; cJSON *item,*retjson,*array,*totalsobj; uint32_t r,q,quoteid,requestid; int64_t KMDtotals[LP_MAXPRICEINFOS],BTCtotals[LP_MAXPRICEINFOS],Btotal,Ktotal; int32_t i,j,count=0;
portable_mutex_lock(&LP_swaplistmutex);
@ -1201,7 +1265,7 @@ char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid,int32_t forc
if ( origrequestid != 0 && origquoteid != 0 )
{
//printf("orig req.%u q.%u\n",origrequestid,origquoteid);
if ( (item= basilisk_remember(KMDtotals,BTCtotals,origrequestid,origquoteid,forceflag)) != 0 )
if ( (item= basilisk_remember(KMDtotals,BTCtotals,origrequestid,origquoteid,forceflag,0)) != 0 )
jaddi(array,item);
//printf("got.(%s)\n",jprint(item,0));
}
@ -1215,19 +1279,22 @@ char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid,int32_t forc
while ( fread(&requestid,1,sizeof(requestid),fp) == sizeof(requestid) && fread(&quoteid,1,sizeof(quoteid),fp) == sizeof(quoteid) )
{
flag = 0;
for (i=0; i<G.LP_numskips; i++)
if ( pendingonly == 0 )
{
r = (uint32_t)(G.LP_skipstatus[i] >> 32);
q = (uint32_t)G.LP_skipstatus[i];
if ( r == requestid && q == quoteid )
for (i=0; i<G.LP_numskips; i++)
{
item = cJSON_CreateObject();
jaddstr(item,"status","realtime");
jaddnum(item,"requestid",r);
jaddnum(item,"quoteid",q);
jaddi(array,item);
flag = 1;
break;
r = (uint32_t)(G.LP_skipstatus[i] >> 32);
q = (uint32_t)G.LP_skipstatus[i];
if ( r == requestid && q == quoteid )
{
item = cJSON_CreateObject();
jaddstr(item,"status","realtime");
jaddnum(item,"requestid",r);
jaddnum(item,"quoteid",q);
jaddi(array,item);
flag = 1;
break;
}
}
}
if ( flag == 0 )
@ -1240,7 +1307,7 @@ char *basilisk_swaplist(uint32_t origrequestid,uint32_t origquoteid,int32_t forc
{
if ( count < sizeof(ridqids)/sizeof(*ridqids) )
ridqids[count++] = ridqid;
if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid,0)) != 0 )
if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid,0,pendingonly)) != 0 )
jaddi(array,item);
}
}
@ -1278,7 +1345,7 @@ char *basilisk_swapentry(uint32_t requestid,uint32_t quoteid,int32_t forceflag)
cJSON *item; int64_t KMDtotals[LP_MAXPRICEINFOS],BTCtotals[LP_MAXPRICEINFOS];
memset(KMDtotals,0,sizeof(KMDtotals));
memset(BTCtotals,0,sizeof(BTCtotals));
if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid,forceflag)) != 0 )
if ( (item= basilisk_remember(KMDtotals,BTCtotals,requestid,quoteid,forceflag,0)) != 0 )
return(jprint(item,1));
else return(clonestr("{\"error\":\"cant find requestid-quoteid\"}"));
}
@ -1288,7 +1355,10 @@ extern uint32_t Alice_expiration;
char *LP_recent_swaps(int32_t limit)
{
char fname[512]; long fsize,offset; FILE *fp; int32_t i=0; uint32_t requestid,quoteid; cJSON *array,*item,*retjson;
char fname[512],*retstr,*base,*rel,*statusstr; long fsize,offset; FILE *fp; int32_t baseind,relind,i=0; uint32_t requestid,quoteid; cJSON *array,*item,*retjson,*subitem,*swapjson; int64_t KMDtotals[LP_MAXPRICEINFOS],BTCtotals[LP_MAXPRICEINFOS]; double srcamount,destamount,netamounts[LP_MAXPRICEINFOS];
memset(KMDtotals,0,sizeof(KMDtotals));
memset(BTCtotals,0,sizeof(BTCtotals));
memset(netamounts,0,sizeof(netamounts));
if ( limit <= 0 )
limit = 3;
sprintf(fname,"%s/SWAPS/list",GLOBAL_DBDIR), OS_compatible_path(fname);
@ -1310,6 +1380,36 @@ char *LP_recent_swaps(int32_t limit)
item = cJSON_CreateArray();
jaddinum(item,requestid);
jaddinum(item,quoteid);
if ( (retstr= basilisk_swapentry(requestid,quoteid,0)) != 0 )
{
if ( (swapjson= cJSON_Parse(retstr)) != 0 )
{
base = jstr(swapjson,"bob");
rel = jstr(swapjson,"alice");
statusstr = jstr(swapjson,"status");
baseind = relind = -1;
if ( base != 0 && rel != 0 && statusstr != 0 && strcmp(statusstr,"finished") == 0 && (baseind= LP_priceinfoind(base)) >= 0 && (relind= LP_priceinfoind(rel)) >= 0 )
{
srcamount = jdouble(swapjson,"srcamount");
destamount = jdouble(swapjson,"destamount");
if ( jint(swapjson,"iambob") != 0 )
srcamount = -srcamount;
else destamount = -destamount;
if ( srcamount != 0. && destamount != 0. )
{
netamounts[baseind] += srcamount;
netamounts[relind] += destamount;
subitem = cJSON_CreateObject();
jaddnum(subitem,base,srcamount);
jaddnum(subitem,rel,destamount);
jaddnum(subitem,"price",-destamount/srcamount);
jaddi(item,subitem);
}
} else printf("base.%p rel.%p statusstr.%p baseind.%d relind.%d\n",base,rel,statusstr,baseind,relind);
free_json(swapjson);
} else printf("error parsing.(%s)\n",retstr);
free(retstr);
}
jaddi(array,item);
} else break;
} else break;
@ -1319,6 +1419,17 @@ char *LP_recent_swaps(int32_t limit)
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
jadd(retjson,"swaps",array);
array = cJSON_CreateArray();
for (i=0; i<LP_MAXPRICEINFOS; i++)
{
if ( netamounts[i] != 0. )
{
item = cJSON_CreateObject();
jaddnum(item,LP_priceinfostr(i),netamounts[i]);
jaddi(array,item);
}
}
jadd(retjson,"netamounts",array);
if ( time(NULL) < Alice_expiration )
{
item = cJSON_CreateObject();
@ -1368,7 +1479,7 @@ char *basilisk_swapentries(char *refbase,char *refrel,int32_t limit)
limit = 10;
memset(ridqids,0,sizeof(ridqids));
retarray = cJSON_CreateArray();
if ( (liststr= basilisk_swaplist(0,0,0)) != 0 )
if ( (liststr= basilisk_swaplist(0,0,0,0)) != 0 )
{
//printf("swapentry.(%s)\n",liststr);
if ( (retjson= cJSON_Parse(liststr)) != 0 )

98
iguana/exchanges/LP_rpc.c

@ -301,7 +301,12 @@ cJSON *LP_validateaddress(char *symbol,char *address)
jaddstr(retjson,"address",address);
bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,address);
bitcoin_address(checkaddr,coin->taddr,addrtype,rmd160,20);
jadd(retjson,"isvalid",strcmp(address,checkaddr)==0? cJSON_CreateTrue() : cJSON_CreateFalse());
if ( addrtype != coin->pubtype && addrtype != coin->p2shtype )
{
jadd(retjson,"isvalid",cJSON_CreateFalse());
return(retjson);
}
jadd(retjson,"isvalid",strcmp(address,checkaddr)==0 ? cJSON_CreateTrue() : cJSON_CreateFalse());
if ( addrtype == coin->pubtype )
{
strcpy(script,"76a914");
@ -312,7 +317,7 @@ cJSON *LP_validateaddress(char *symbol,char *address)
jaddstr(retjson,"scriptPubKey",script);
}
bitcoin_address(coinaddr,coin->taddr,coin->pubtype,G.LP_myrmd160,20);
jadd(retjson,"ismine",strcmp(address,coin->smartaddr) == 0 ? cJSON_CreateTrue() : cJSON_CreateFalse());
jadd(retjson,"ismine",strcmp(coinaddr,coin->smartaddr) == 0 ? cJSON_CreateTrue() : cJSON_CreateFalse());
jadd(retjson,"iswatchonly",cJSON_CreateTrue());
jadd(retjson,"isscript",addrtype == coin->p2shtype ? cJSON_CreateTrue() : cJSON_CreateFalse());
return(retjson);
@ -342,17 +347,17 @@ int32_t LP_address_ismine(char *symbol,char *address)
return(doneflag);
}
int32_t LP_address_iswatched(char *symbol,char *address)
int32_t LP_address_iswatchonly(char *symbol,char *address)
{
int32_t doneflag = 0; cJSON *retjson,*obj;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
if ( (retjson= LP_validateaddress(symbol,address)) != 0 )
{
if ( (obj= jobj(retjson,"iswatched")) != 0 && is_cJSON_True(obj) != 0 )
if ( (obj= jobj(retjson,"iswatchonly")) != 0 && is_cJSON_True(obj) != 0 )
{
doneflag = 1;
//printf("%s ismine (%s)\n",address,jprint(retjson,0));
//printf("%s iswatchonly (%s)\n",address,jprint(retjson,0));
}
//printf("%s\n",jprint(retjson,0));
free_json(retjson);
@ -388,7 +393,7 @@ cJSON *LP_listunspent(char *symbol,char *coinaddr,bits256 reftxid,bits256 reftxi
return(cJSON_Parse("{\"error\":\"no coin\"}"));
if ( coin->electrum == 0 )
{
if ( (ap= LP_addressfind(coin,symbol)) != 0 )
if ( (ap= LP_addressfind(coin,coinaddr)) != 0 )
{
if ( ap->unspenttime == 0 )
usecache = 0;
@ -401,13 +406,14 @@ cJSON *LP_listunspent(char *symbol,char *coinaddr,bits256 reftxid,bits256 reftxi
return(retjson);
}
}
if ( LP_address_ismine(symbol,coinaddr) > 0 || LP_address_iswatched(symbol,coinaddr) > 0 )
//printf("%s %s usecache.%d iswatched.%d\n",coin->symbol,coinaddr,usecache,LP_address_iswatchonly(symbol,coinaddr));
if ( LP_address_ismine(symbol,coinaddr) > 0 || LP_address_iswatchonly(symbol,coinaddr) > 0 )
{
if ( strcmp(symbol,"BTC") == 0 )
numconfs = 0;
else numconfs = 1;
sprintf(buf,"[%d, 99999999, [\"%s\"]]",numconfs,coinaddr);
//printf("LP_listunspent.(%s %s)\n",symbol,coinaddr);
//printf("LP_listunspent.(%s %s)\n",symbol,coinaddr);
retjson = bitcoin_json(coin,"listunspent",buf);
retstr = jprint(retjson,0);
LP_unspents_cache(coin->symbol,coinaddr,retstr,1);
@ -473,7 +479,7 @@ int64_t LP_listunspent_parseitem(struct iguana_info *coin,bits256 *txidp,int32_t
int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag,bits256 reftxid,bits256 reftxid2)
{
struct iguana_info *coin; int32_t n = 0; cJSON *retjson=0; char *retstr=0;
struct iguana_info *coin; struct LP_address *ap; int32_t n = 0; cJSON *retjson=0; char *retstr=0;
if ( symbol == 0 || symbol[0] == 0 )
return(0);
if ( (coin= LP_coinfind(symbol)) != 0 )
@ -488,6 +494,8 @@ int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag,bits25
}
else
{
if ( fullflag == 2 && (ap= LP_addressfind(coin,coinaddr)) != 0 )
ap->unspenttime = 0;
retjson = LP_listunspent(symbol,coinaddr,reftxid,reftxid2);
coin->numutxos = cJSON_GetArraySize(retjson);
if ( retjson != 0 )
@ -508,39 +516,6 @@ int32_t LP_listunspent_issue(char *symbol,char *coinaddr,int32_t fullflag,bits25
return(n);
}
cJSON *LP_importprivkey(char *symbol,char *wifstr,char *label,int32_t flag)
{
static void *ctx;
char buf[512],address[64]; cJSON *retjson; struct iguana_info *coin; int32_t doneflag = 0;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
if ( coin == 0 )
return(cJSON_Parse("{\"error\":\"no coin\"}"));
if ( coin->electrum != 0 )
return(cJSON_Parse("{\"result\":\"electrum should have local wallet\"}"));
if ( ctx == 0 )
ctx = bitcoin_ctx();
bitcoin_wif2addr(ctx,coin->wiftaddr,coin->taddr,coin->pubtype,address,wifstr);
if ( (retjson= LP_validateaddress(symbol,address)) != 0 )
{
if ( jobj(retjson,"ismine") != 0 && is_cJSON_True(jobj(retjson,"ismine")) != 0 )
{
doneflag = 1;
//printf("%s already ismine\n",address);
}
//printf("%s\n",jprint(retjson,0));
free_json(retjson);
}
if ( doneflag == 0 )
{
if ( coin->noimportprivkey_flag != 0 )
sprintf(buf,"[\"%s\"]",wifstr);
else sprintf(buf,"\"%s\", \"%s\", %s",wifstr,label,flag < 0 ? "false" : "true");
return(bitcoin_json(coin,"importprivkey",buf));
} else return(cJSON_Parse("{\"result\":\"success\"}"));
}
int32_t LP_importaddress(char *symbol,char *address)
{
char buf[1024],*retstr; cJSON *validatejson; int32_t isvalid=0,doneflag = 0; struct iguana_info *coin;
@ -583,6 +558,45 @@ int32_t LP_importaddress(char *symbol,char *address)
}
}
cJSON *LP_importprivkey(char *symbol,char *wifstr,char *label,int32_t flag)
{
static void *ctx;
char buf[512],address[64]; cJSON *retjson; struct iguana_info *coin; int32_t doneflag = 0;
if ( symbol == 0 || symbol[0] == 0 )
return(cJSON_Parse("{\"error\":\"null symbol\"}"));
coin = LP_coinfind(symbol);
if ( coin == 0 )
return(cJSON_Parse("{\"error\":\"no coin\"}"));
if ( coin->electrum != 0 )
return(cJSON_Parse("{\"result\":\"electrum should have local wallet\"}"));
if ( ctx == 0 )
ctx = bitcoin_ctx();
bitcoin_wif2addr(ctx,coin->wiftaddr,coin->taddr,coin->pubtype,address,wifstr);
#ifdef LP_DONT_IMPORTPRIVKEY
bitcoin_wif2addr(ctx,coin->wiftaddr,coin->taddr,coin->pubtype,address,wifstr);
if ( LP_importaddress(symbol,address) < 0 )
return(cJSON_Parse("{\"error\":\"couldnt import\"}"));
else return(cJSON_Parse("{\"result\":\"success\"}"));
#endif
if ( (retjson= LP_validateaddress(symbol,address)) != 0 )
{
if ( jobj(retjson,"ismine") != 0 && is_cJSON_True(jobj(retjson,"ismine")) != 0 )
{
doneflag = 1;
//printf("%s already ismine\n",address);
}
//printf("%s\n",jprint(retjson,0));
free_json(retjson);
}
if ( doneflag == 0 )
{
if ( coin->noimportprivkey_flag != 0 )
sprintf(buf,"[\"%s\"]",wifstr);
else sprintf(buf,"\"%s\", \"%s\", %s",wifstr,label,flag < 0 ? "false" : "true");
return(bitcoin_json(coin,"importprivkey",buf));
} else return(cJSON_Parse("{\"result\":\"success\"}"));
}
double _LP_getestimatedrate(struct iguana_info *coin)
{
char buf[512],*retstr=0; int32_t numblocks; cJSON *errjson,*retjson; double rate = 0.00000020;

1
iguana/exchanges/LP_scan.c

@ -26,6 +26,7 @@ int32_t LP_blockinit(struct iguana_info *coin,int32_t height)
{
if ( (txs= jarray(&numtx,blockobj,"tx")) != 0 )
{
//printf("LP_blockinit %s ht.%d numtx.%d\n",coin->symbol,height,numtx);
for (iter=0; iter<2; iter++)
{
txobj = 0;

13
iguana/exchanges/LP_secp.c

@ -86,21 +86,28 @@ bits256 bitcoin_pub256(void *ctx,bits256 *privkeyp,uint8_t odd_even)
int32_t bitcoin_sign(void *ctx,char *symbol,uint8_t *sig,bits256 txhash2,bits256 privkey,int32_t recoverflag)
{
int32_t fCompressed = 1;
secp256k1_ecdsa_signature SIG; secp256k1_ecdsa_recoverable_signature rSIG; bits256 extra_entropy,seed; int32_t recid,retval = -1; size_t siglen = 72; secp256k1_pubkey SECPUB,CHECKPUB;
secp256k1_ecdsa_signature SIG; void *funcp; secp256k1_ecdsa_recoverable_signature rSIG; bits256 extra_entropy,seed; uint8_t *entropy; int32_t recid,retval = -1; size_t siglen = 72; secp256k1_pubkey SECPUB,CHECKPUB;
seed = rand256(0);
extra_entropy = rand256(0);
SECP_ENSURE_CTX
{
funcp = secp256k1_nonce_function_rfc6979;
if ( secp256k1_ec_seckey_verify(ctx,privkey.bytes) == 0 )
{
//printf("bitcoin_sign illegal privkey\n");
return(-1);
}
if ( strcmp(symbol,"BCH") == 0 || strcmp(symbol,"BTG") == 0 )
{
char str[65]; printf("BCH/BTG deterministic signature %s\n",bits256_str(str,txhash2));
funcp = 0;
entropy = 0;
} else entropy = extra_entropy.bytes;
if ( secp256k1_context_randomize(ctx,seed.bytes) != 0 )
{
if ( recoverflag != 0 )
{
if ( secp256k1_ecdsa_sign_recoverable(ctx,&rSIG,txhash2.bytes,privkey.bytes,secp256k1_nonce_function_rfc6979,extra_entropy.bytes) != 0 )
if ( secp256k1_ecdsa_sign_recoverable(ctx,&rSIG,txhash2.bytes,privkey.bytes,funcp,entropy) != 0 )
{
recid = -1;
secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx,sig+1,&recid,&rSIG);
@ -125,7 +132,7 @@ int32_t bitcoin_sign(void *ctx,char *symbol,uint8_t *sig,bits256 txhash2,bits256
}
else
{
if ( secp256k1_ecdsa_sign(ctx,&SIG,txhash2.bytes,privkey.bytes,secp256k1_nonce_function_rfc6979,extra_entropy.bytes) != 0 )
if ( secp256k1_ecdsa_sign(ctx,&SIG,txhash2.bytes,privkey.bytes,funcp,entropy) != 0 )
{
if ( secp256k1_ecdsa_signature_serialize_der(ctx,sig,&siglen,&SIG) != 0 )
retval = (int32_t)siglen;

9
iguana/exchanges/LP_signatures.c

@ -440,7 +440,7 @@ char *LP_postprice_recv(cJSON *argjson)
if ( LP_price_sigcheck(juint(argjson,"timestamp"),jstr(argjson,"sig"),jstr(argjson,"pubsecp"),pubkey,base,rel,j64bits(argjson,"price64")) == 0 )
{
//printf("call pricefeed update\n");
LP_pricefeedupdate(pubkey,base,rel,price,jstr(argjson,"utxocoin"),jint(argjson,"n"),jdouble(argjson,"bal")*SATOSHIDEN,jdouble(argjson,"min")*SATOSHIDEN,jdouble(argjson,"max")*SATOSHIDEN,jdouble(argjson,"credits")*SATOSHIDEN);
LP_pricefeedupdate(pubkey,base,rel,price,jstr(argjson,"utxocoin"),jint(argjson,"n"),jdouble(argjson,"bal")*SATOSHIDEN,jdouble(argjson,"min")*SATOSHIDEN,jdouble(argjson,"max")*SATOSHIDEN,jdouble(argjson,"credits")*SATOSHIDEN);
return(clonestr("{\"result\":\"success\"}"));
}
else
@ -643,7 +643,7 @@ void LP_listunspent_query(char *symbol,char *coinaddr)
void LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_quoteinfo *qp)
{
cJSON *reqjson; bits256 zero; char *msg; int32_t flag = 0;
cJSON *reqjson; bits256 zero; char *msg; struct iguana_info *coin; int32_t flag = 0;
if ( strcmp(method,"request") == 0 )
{
if ( LP_allocated(qp->desttxid,qp->destvout) == 0 && LP_allocated(qp->feetxid,qp->feevout) == 0 )
@ -665,7 +665,10 @@ void LP_query(void *ctx,char *myipaddr,int32_t mypubsock,char *method,struct LP_
if ( jobj(reqjson,"timestamp") == 0 )
jaddnum(reqjson,"timestamp",time(NULL));
if ( strcmp(method,"connect") == 0 )
jadd(reqjson,"proof",LP_instantdex_txids());
{
if ( (coin= LP_coinfind("KMD")) != 0 )
jadd(reqjson,"proof",LP_instantdex_txids(0,coin->smartaddr));
}
msg = jprint(reqjson,1);
printf("QUERY.(%s)\n",msg);
//if ( bits256_nonz(qp->srchash) == 0 || strcmp(method,"request") != 0 )

9
iguana/exchanges/LP_socket.c

@ -1034,8 +1034,10 @@ void LP_dedicatedloop(void *arg)
}
else
{
#ifndef _WIN32
printf("no more electrum data when expected2\n");
electrum_kickstart(ep);
#endif
break;
}
}
@ -1130,6 +1132,13 @@ cJSON *LP_electrumserver(struct iguana_info *coin,char *ipaddr,uint16_t port)
LP_cacheptrs_init(coin);
coin->loadedcache = (uint32_t)time(NULL);
}
if ( 0 && strcmp(coin->symbol,"ZEC") == 0 )
{
void for_satinder();
sleep(3);
for_satinder();
getchar();
}
}
}
else

955
iguana/exchanges/LP_statemachine.c

@ -17,7 +17,801 @@
// LP_statemachine.c
// marketmaker
//
char DEX_baseaddr[64],DEX_reladdr[64];
struct mmpending_order
{
double price,volume;
int32_t dir;
uint32_t pending,completed,canceled,cancelstarted,reported;
cJSON *errorjson;
char exchange[16],base[65],rel[65],orderid[64];
} *Pending_orders;
int32_t Num_Pending;
#define IGUANA_URL "http://127.0.0.1:7778"
/*char CURRENCIES[][8] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", // major currencies
"CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", // end of currencies
};*/
double PAXPRICES[sizeof(CURRENCIES)/sizeof(*CURRENCIES)];
uint32_t PAXACTIVE;
char *DEX_swapstatus()
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"getswaplist\"}");
return(bitcoind_RPC(0,"InstantDEX",url,0,"getswaplist",postdata,0));
}
char *DEX_amlp(char *blocktrail)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"amlp\",\"blocktrail\":\"%s\"}",blocktrail);
return(bitcoind_RPC(0,"tradebot",url,0,"amlp",postdata,0));
}
char *DEX_openorders(char *exchange)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"openorders\",\"exchange\":\"%s\"}",exchange);
return(bitcoind_RPC(0,"InstantDEX",url,0,"openorders",postdata,0));
}
char *DEX_tradehistory(char *exchange)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"tradehistory\",\"exchange\":\"%s\"}",exchange);
return(bitcoind_RPC(0,"InstantDEX",url,0,"tradehistory",postdata,0));
}
char *DEX_orderstatus(char *exchange,char *orderid)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"orderstatus\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid);
return(bitcoind_RPC(0,"InstantDEX",url,0,"orderstatus",postdata,0));
}
char *DEX_cancelorder(char *exchange,char *orderid)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"cancelorder\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid);
return(bitcoind_RPC(0,"InstantDEX",url,0,"cancelorder",postdata,0));
}
char *DEX_balance(char *exchange,char *base,char *coinaddr)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
if ( strcmp(exchange,"DEX") == 0 )
{
sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"getbalance\",\"address\":\"%s\",\"symbol\":\"%s\"}",coinaddr,base);
return(bitcoind_RPC(0,"dex",url,0,"getbalance",postdata,0));
}
else
{
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"balance\",\"exchange\":\"%s\",\"base\":\"%s\"}",exchange,base);
return(bitcoind_RPC(0,"InstantDEX",url,0,"balance",postdata,0));
}
}
char *DEX_apikeypair(char *exchange,char *apikey,char *apisecret)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"apikeypair\",\"exchange\":\"%s\",\"apikey\":\"%s\",\"apisecret\":\"%s\"}",exchange,apikey,apisecret);
return(bitcoind_RPC(0,"InstantDEX",url,0,"apikeypair",postdata,0));
}
char *DEX_setuserid(char *exchange,char *userid,char *tradepassword)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"setuserid\",\"exchange\":\"%s\",\"userid\":\"%s\",\"tradepassword\":\"%s\"}",exchange,userid,tradepassword);
return(bitcoind_RPC(0,"InstantDEX",url,0,"setuserid",postdata,0));
}
char *DEX_trade(char *exchange,char *base,char *rel,int32_t dir,double price,double volume)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"%s\",\"exchange\":\"%s\",\"base\":\"%s\",\"rel\":\"%s\",\"price\":%.8f,\"volume\":%.8f,\"dotrade\":1}",dir>0?"buy":"sell",exchange,base,rel,price,volume);
//printf("DEX_trade.(%s)\n",postdata);
return(bitcoind_RPC(0,"InstantDEX",url,0,dir>0?"buy":"sell",postdata,0));
}
char *DEX_withdraw(char *exchange,char *base,char *destaddr,double amount)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"withdraw\",\"exchange\":\"%s\",\"destaddr\":\"%s\",\"amount\":%.8f}",exchange,destaddr,amount);
return(bitcoind_RPC(0,"InstantDEX",url,0,"withdraw",postdata,0));
}
char *iguana_walletpassphrase(char *passphrase,int32_t timeout)
{
char url[512],postdata[1024];
sprintf(url,"%s/coin=KMD&agent=bitcoinrpc&method=walletpassphrase?",IGUANA_URL);
sprintf(postdata,"[\"%s\", %d]",passphrase,timeout);
return(bitcoind_RPC(0,"",url,0,"walletpassphrase",postdata,0));
}
/*char *iguana_listunspent(char *coin,char *coinaddr)
{
char url[512],postdata[1024];
sprintf(url,"%s/coin=%s&agent=bitcoinrpc&method=listunspent?",IGUANA_URL,coin);
sprintf(postdata,"[\"%s\"]",coinaddr);
return(bitcoind_RPC(0,"",url,0,"listunspent",postdata));
}*/
/*char *issue_LP_intro(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers)
{
char url[512];
sprintf(url,"http://%s:%u/api/stats/intro?ipaddr=%s&port=%u&numpeers=%d",destip,destport,ipaddr,port,numpeers);
printf("(%s)\n",url);
return(issue_curl(url));
}*/
//
// http://127.0.0.1:7779/api/stats/getpeers
char *DEX_listunspent(char *coin,char *coinaddr)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"listunspent\",\"address\":\"%s\",\"symbol\":\"%s\",\"timeout\":60000}",coinaddr,coin);
return(bitcoind_RPC(0,"dex",url,0,"listunspent",postdata,0));
}
bits256 iguana_wif2privkey(char *wifstr)
{
char url[512],postdata[1024],*retstr,*privstr; bits256 privkey; cJSON *retjson;
memset(privkey.bytes,0,sizeof(privkey));
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"SuperNET\",\"method\":\"wif2priv\",\"wif\":\"%s\"}",wifstr);
if ( (retstr= bitcoind_RPC(0,"SuperNET",url,0,"wif2priv",postdata,0)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (privstr= jstr(retjson,"privkey")) != 0 )
{
if ( strlen(privstr) == 64 )
decode_hex(privkey.bytes,32,privstr);
}
free_json(retjson);
}
free(retstr);
}
return(privkey);
}
double bittrex_balance(char *base,char *coinaddr)
{
char *retstr; cJSON *retjson; double balance = 0.;
if ( (retstr= DEX_balance("bittrex",base,coinaddr)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
balance = jdouble(retjson,"balance");
free_json(retjson);
}
free(retstr);
}
return(balance);
}
double dex_balance(char *base,char *coinaddr)
{
char *retstr; cJSON *retjson; double balance = 0.;
if ( (retstr= DEX_balance("DEX",base,coinaddr)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
balance = jdouble(retjson,"balance");
free_json(retjson);
}
free(retstr);
}
return(balance);
}
int32_t komodo_baseid(char *base)
{
int32_t i;
for (i=0; i<sizeof(CURRENCIES)/sizeof(*CURRENCIES); i++)
if ( strcmp(base,CURRENCIES[i]) == 0 )
return(i);
return(-1);
}
cJSON *yahoo_allcurrencies()
{
char *retstr; cJSON *retjson = 0;
if ( (retstr= issue_curl("http://finance.yahoo.com/webservice/v1/symbols/allcurrencies/quote?format=json")) != 0 )
{
retjson = cJSON_Parse(retstr);
free(retstr);
}
return(retjson);
}
void _marketmaker_fiatupdate(int32_t baseid,double price)
{
PAXPRICES[baseid] = price * PAXPRICES[0];
printf("%.6f %s per USD, %.8f %s per KMD\n",price,CURRENCIES[baseid],PAXPRICES[baseid],CURRENCIES[baseid]);
}
uint32_t marketmaker_fiatupdate(cJSON *fiatjson)
{
int32_t i,n,baseid; cJSON *item,*array; double price; char *name; uint64_t mask = 0;
fiatjson = jobj(fiatjson,"list");
if ( fiatjson != 0 && (array= jarray(&n,fiatjson,"resources")) > 0 )
{
for (i=0; i<n; i++)
{
/*
"resource" : {
"classname" : "Quote",
"fields" : {
"name" : "USD/BRX",
"price" : "3.063200",
"symbol" : "BRX=X",
"ts" : "1487866204",
"type" : "currency",
"utctime" : "2017-02-23T16:10:04+0000",
"volume" : "0"
}
*/
item = jitem(array,i);
if ( (item= jobj(item,"resource")) != 0 )
item = jobj(item,"fields");
if ( item != 0 )
{
price = jdouble(item,"price");
if ( price > SMALLVAL && (name= jstr(item,"name")) != 0 && strncmp(name,"USD/",4) == 0 )
{
if ( (baseid= komodo_baseid(name+4)) >= 0 && baseid < 32 )
{
if ( ((1LL << baseid) & mask) == 0 )
{
_marketmaker_fiatupdate(baseid,price);
mask |= (1LL << baseid);
} else if ( fabs(price*PAXPRICES[0] - PAXPRICES[baseid]) > SMALLVAL )
printf("DUPLICATE PRICE? %s %.8f vs %.8f\n",name+4,price*PAXPRICES[0],PAXPRICES[baseid]);
}
}
}
}
}
printf("pax mask.%x\n",(uint32_t)mask);
return((uint32_t)mask);
}
void marketmaker_cancel(struct mmpending_order *ptr)
{
char *retstr; cJSON *retjson;
if ( ptr->pending != 0 && ptr->cancelstarted == 0 )
{
ptr->cancelstarted = (uint32_t)time(NULL);
if ( (retstr= DEX_cancelorder(ptr->exchange,ptr->orderid)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
printf("cancel %s (%s/%s) %.8f vol %.8f dir.%d -> (%s)\n",ptr->exchange,ptr->base,ptr->rel,ptr->price,ptr->volume,ptr->dir,jprint(retjson,0));
free_json(retjson);
ptr->pending = 0;
ptr->canceled = (uint32_t)time(NULL);
}
free(retstr);
}
}
}
void marketmaker_queue(char *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *retjson)
{
struct mmpending_order *ptr; char *orderid;
//DEX_trade.({"success":true,"message":"","result":{"uuid":"d5faa9e4-660d-436f-a257-2c6a40442d8c"},"tag":"11271578410079391025"}
if ( is_cJSON_True(jobj(retjson,"success")) != 0 && jobj(retjson,"result") != 0 )
retjson = jobj(retjson,"result");
printf("QUEUE.%s %s/%s dir.%d %.8f %.6f (%s)\n",exchange,base,rel,dir,price,volume,jprint(retjson,0));
Pending_orders = realloc(Pending_orders,(1 + Num_Pending) * sizeof(*Pending_orders));
ptr = &Pending_orders[Num_Pending++];
memset(ptr,0,sizeof(*ptr));
ptr->price = price;
ptr->volume = volume;
ptr->dir = dir;
ptr->pending = (uint32_t)time(NULL);
strcpy(ptr->exchange,exchange);
strcpy(ptr->base,base);
strcpy(ptr->rel,rel);
if ( (orderid= jstr(retjson,"OrderUuid")) != 0 || (orderid= jstr(retjson,"uuid")) != 0 )
strcpy(ptr->orderid,orderid);
else strcpy(ptr->orderid,"0");
}
void marketmaker_pendingupdate(char *exchange,char *base,char *rel)
{
char *retstr; cJSON *retjson,*obj; int32_t i; struct mmpending_order *ptr;
for (i=0; i<Num_Pending; i++)
{
ptr = &Pending_orders[i];
if ( strcmp(exchange,ptr->exchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 )
continue;
if ( ptr->completed == 0 && (retstr= DEX_orderstatus(exchange,ptr->orderid)) != 0 )
{
//printf("%s status.(%s)\n",ptr->orderid,retstr);
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
obj = jobj(retjson,"result");
if ( is_cJSON_Array(obj) != 0 )
obj = jitem(retjson,0);
if ( jdouble(obj,"QuantityRemaining") == 0. || is_cJSON_True(jobj(obj,"IsOpen")) == 0 )
{
//{"Uuid":null,"OrderUuid":"e7b0789c-0c4e-413b-a768-3d5734d9cbe5","Exchange":"BTC-KMD","OrderType":"LIMIT_SELL","Quantity":877.77700000,"QuantityRemaining":462.50512234,"Limit":0.00011770,"CommissionPaid":0.00012219,"Price":0.04887750,"PricePerUnit":0.00011769,"Opened":"2017-02-20T13:16:22.29","Closed":null,"CancelInitiated":false,"ImmediateOrCancel":false,"IsConditional":false,"Condition":"NONE","ConditionTarget":null} printf("uuid.(%s) finished.(%s)\n",ptr->orderid,jprint(retjson,0));
ptr->completed = (uint32_t)time(NULL);
ptr->pending = 0;
}
free_json(retjson);
}
free(retstr);
}
}
}
void marketmaker_pendinginit(char *exchange,char *base,char *rel)
{
char *retstr,*orderid,*pairstr,relbase[65]; cJSON *retjson,*array,*item; int32_t i,j,n,dir; struct mmpending_order *ptr;
sprintf(relbase,"%s-%s",rel,base);
if ( (retstr= DEX_openorders(exchange)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
//printf("%s\n",jprint(retjson,0));
if ( is_cJSON_True(jobj(retjson,"success")) != 0 && (array= jarray(&n,retjson,"result")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( (pairstr= jstr(item,"Exchange")) == 0 )
continue;
if ( strcmp(pairstr,relbase) != 0 )
{
printf("skip %s when %s\n",pairstr,relbase);
continue;
}
//printf("(%s)\n",jprint(item,0));
//{"success":true,"message":"","result":[{"Uuid":null,"OrderUuid":"81ad3e37-65d4-4fee-9c29-03b050f5192b","Exchange":"BTC-KMD","OrderType":"LIMIT_BUY","Quantity":885.19934578,"QuantityRemaining":885.19934578,"Limit":0.00011184,"CommissionPaid":0,"Price":0,"PricePerUnit":null,"Opened":"2017-02-19T19:14:02.94","Closed":null,"CancelInitiated":false,"ImmediateOrCancel":false,"IsConditional":false,"Condition":"NONE","ConditionTarget":null}],"tag":"10056789044100011414"}
if ( (orderid= jstr(item,"OrderUuid")) != 0 && is_cJSON_Null(jobj(item,"Closed")) != 0 && is_cJSON_False(jobj(item,"CancelInitiated")) != 0 )
{
for (j=0; j<Num_Pending; j++)
{
ptr = &Pending_orders[j];
if ( strcmp(exchange,ptr->exchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 )
continue;
if ( strcmp(ptr->orderid,orderid) == 0 )
{
ptr->pending = (uint32_t)time(NULL);
ptr->completed = 0;
printf("%s pending\n",orderid);
break;
}
}
if ( j == Num_Pending )
{
if ( jstr(item,"OrderType") != 0 )
{
if ( strcmp(jstr(item,"OrderType"),"LIMIT_BUY") == 0 )
dir = 1;
else if ( strcmp(jstr(item,"OrderType"),"LIMIT_SELL") == 0 )
dir = -1;
else dir = 0;
if ( dir != 0 )
marketmaker_queue(exchange,base,rel,dir,jdouble(item,"Limit"),jdouble(item,"QuantityRemaining"),item);
else printf("no dir (%s) (%s)\n",jprint(item,0),jstr(item,"OrderType"));
}
}
}
}
}
free_json(retjson);
}
free(retstr);
}
}
double marketmaker_filled(char *exchange,char *base,char *rel,double *buyvolp,double *sellvolp,double *pendingbidsp,double *pendingasksp)
{
double pricesum = 0.,volsum = 0.; struct mmpending_order *ptr; int32_t i;
*pendingbidsp = *pendingasksp = 0.;
for (i=0; i<Num_Pending; i++)
{
ptr = &Pending_orders[i];
if ( strcmp(exchange,ptr->exchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 )
continue;
if ( ptr->completed != 0 )
{
if ( ptr->reported == 0 )
{
if ( ptr->dir > 0 )
(*buyvolp) += ptr->volume;
else if ( ptr->dir < 0 )
(*sellvolp) += ptr->volume;
pricesum += ptr->volume * ptr->price;
volsum += ptr->volume;
ptr->reported = (uint32_t)time(NULL);
printf("REPORT dir.%d vol %.8f\n",ptr->dir,ptr->volume);
}
}
else if ( ptr->pending != 0 ) // alternative is error or cancelled
{
if ( ptr->dir > 0 )
(*pendingbidsp) += ptr->volume;
else if ( ptr->dir < 0 )
(*pendingasksp) += ptr->volume;
}
}
if ( volsum != 0. )
pricesum /= volsum;
return(pricesum);
}
int32_t marketmaker_prune(char *exchange,char *base,char *rel,int32_t polarity,double bid,double ask,double separation)
{
int32_t i,n = 0; struct mmpending_order *ptr;
for (i=0; i<Num_Pending; i++)
{
ptr = &Pending_orders[i];
if ( strcmp(exchange,ptr->exchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 )
continue;
if ( ptr->pending != 0 && ptr->cancelstarted == 0 )
{
if ( polarity != 0 )
{
if ( ((ptr->dir*polarity > 0 && ptr->price < bid-separation) || (ptr->dir*polarity < 0 && ptr->price > ask+separation)) )
{
printf("polarity.%d dir.%d price.%f bid.%f ask.%f\n",polarity,ptr->dir,ptr->price,bid,ask);
marketmaker_cancel(ptr), n++;
}
}
/*else
{,*prunebid=0,*pruneask=0; double lowbid=0.,highask=0.
if ( ptr->dir > 0 && (lowbid == 0. || ptr->price < lowbid) )
{
lowbid = ptr->price;
prunebid = ptr;
}
else if ( ptr->dir < 0 && (highask == 0. || ptr->price > highask) )
{
highask = ptr->price;
pruneask = ptr;
}
}*/
}
}
/*if ( polarity == 0 )
{
if ( prunebid != 0 && fabs(prunebid->price - bid) > separation )
marketmaker_cancel(prunebid), n++;
if ( pruneask != 0 && fabs(pruneask->price - ask) > separation )
marketmaker_cancel(pruneask), n++;
}*/
return(n);
}
void marketmaker_volumeset(double *bidincrp,double *askincrp,double incr,double buyvol,double pendingbids,double sellvol,double pendingasks,double maxexposure)
{
*bidincrp = *askincrp = incr;
//if ( pendingbids >= pendingasks+maxexposure )
// *bidincrp = 0.;
//else if ( pendingasks >= pendingbids+maxexposure )
// *askincrp = 0.;
if ( *bidincrp > 0. && pendingbids + *bidincrp > maxexposure )
*bidincrp = (maxexposure - *bidincrp);
if ( *askincrp > 0. && pendingasks + *askincrp > maxexposure )
*askincrp = (maxexposure - *askincrp);
if ( *bidincrp < 0. )
*bidincrp = 0.;
if ( *askincrp < 0. )
*askincrp = 0.;
}
int32_t marketmaker_spread(char *exchange,char *base,char *rel,double bid,double bidvol,double ask,double askvol,double separation)
{
int32_t nearflags[2],i,n = 0; struct mmpending_order *ptr; cJSON *retjson,*vals; char *retstr,postdata[1024],url[128]; double vol,spread_ratio;
memset(nearflags,0,sizeof(nearflags));
if ( strcmp("DEX",exchange) != 0 )
{
for (i=0; i<Num_Pending; i++)
{
ptr = &Pending_orders[i];
if ( strcmp(exchange,ptr->exchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 )
continue;
if ( ptr->pending != 0 && ptr->cancelstarted == 0 )
{
if ( bid > SMALLVAL && bidvol > SMALLVAL && ptr->dir > 0 && fabs(bid - ptr->price) < separation )
{
//printf("bid %.8f near %.8f\n",bid,ptr->price);
nearflags[0]++;
}
if ( ask > SMALLVAL && askvol > SMALLVAL && ptr->dir < 0 && fabs(ask - ptr->price) < separation )
{
//printf("%.8f near %.8f\n",ask,ptr->price);
nearflags[1]++;
}
}
}
}
//printf("spread.%s (%.8f %.6f) (%.8f %.6f)\n",exchange,bid,bidvol,ask,askvol);
if ( bid > SMALLVAL && bidvol > SMALLVAL && nearflags[0] == 0 )
{
if ( strcmp("DEX",exchange) == 0 && strcmp(base,"KMD") == 0 && strcmp(rel,"BTC") == 0 )
{
if ( ask > SMALLVAL && askvol > SMALLVAL )
{
/*li.profit = jdouble(vals,"profit");
li.refprice = jdouble(vals,"refprice");
li.bid = jdouble(vals,"bid");
li.ask = jdouble(vals,"ask");
if ( (li.minvol= jdouble(vals,"minvol")) <= 0. )
li.minvol = (strcmp("BTC",base) == 0) ? 0.0001 : 0.001;
if ( (li.maxvol= jdouble(vals,"maxvol")) < li.minvol )
li.maxvol = li.minvol;*/
//curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"MVP\",\"vals\":{\"rel\":\"USD\",\"bid\":0.09,\"ask\":0.11,\"maxvol\":100}}"
vals = cJSON_CreateObject();
jaddstr(vals,"rel","BTC");
jaddnum(vals,"bid",bid);
jaddnum(vals,"ask",ask);
vol = bidvol > askvol ? askvol : bidvol;
jaddnum(vals,"maxvol",vol);
jaddnum(vals,"minvol",vol*0.1 > 100 ? 100 : vol * 0.1);
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}",base,jprint(vals,1));
//printf("(%s)\n",postdata);
if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata,0)) != 0 )
{
//printf("(%s) -> (%s)\n",postdata,retstr);
free(retstr);
}
spread_ratio = .5 * ((ask - bid) / (bid + ask));
for (i=0; i<sizeof(CURRENCIES)/sizeof(*CURRENCIES); i++)
{
if ( (PAXACTIVE & (1<<i)) == 0 )
continue;
if ( PAXPRICES[i] > SMALLVAL )
{
vals = cJSON_CreateObject();
jaddstr(vals,"rel",CURRENCIES[i]);
jaddnum(vals,"bid",PAXPRICES[i] * (1. - spread_ratio));
jaddnum(vals,"ask",PAXPRICES[i] * (1. + spread_ratio));
jaddnum(vals,"maxvol",vol * PAXPRICES[i]);
jaddnum(vals,"minvol",MAX(1,(int32_t)(vol * 0.01 * PAXPRICES[i])));
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}","KMD",jprint(vals,1));
if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata,0)) != 0 )
{
//printf("(%s) -> (%s)\n",postdata,retstr);
free(retstr);
}
}
//break;
}
} else printf("unsupported ask only for DEX %s/%s\n",base,rel);
}
else if ( (retstr= DEX_trade(exchange,base,rel,1,bid,bidvol)) != 0 )
{
//printf("DEX_trade.(%s)\n",retstr);
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
marketmaker_queue(exchange,base,rel,1,bid,bidvol,retjson);
free_json(retjson);
}
free(retstr);
} //else printf("skip bid %s %.8f vol %f\n",exchange,bid,bidvol);
}
if ( ask > SMALLVAL && askvol > SMALLVAL && nearflags[1] == 0 && strcmp("DEX",exchange) != 0 )
{
if ( (retstr= DEX_trade(exchange,base,rel,-1,ask,askvol)) != 0 )
{
//printf("DEX_trade.(%s)\n",retstr);
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
marketmaker_queue(exchange,base,rel,-1,ask,askvol,retjson);
free_json(retjson);
}
free(retstr);
}
} //else printf("skip ask %s %.8f vol %f\n",exchange,bid,bidvol);
return(n);
}
double marketmaker_updateprice(char *name,char *base,char *rel,double theoretical,double *incrp)
{
static uint32_t counter;
cJSON *fiatjson; double USD_average=0.,usdprice=0.,CMC_average=0.,avebid=0.,aveask=0.,val,changes[3],highbid=0.,lowask=0.;
if ( (val= get_theoretical(&avebid,&aveask,&highbid,&lowask,&CMC_average,changes,name,base,rel,&USD_average)) != 0. )
{
if ( theoretical == 0. )
{
theoretical = val;
if ( *incrp > 2 )
{
*incrp = (int32_t)*incrp;
*incrp += 0.777;
}
} else theoretical = (theoretical + val) * 0.5;
if ( (counter++ % 12) == 0 )
{
if ( USD_average > SMALLVAL && CMC_average > SMALLVAL && theoretical > SMALLVAL )
{
usdprice = USD_average * (theoretical / CMC_average);
printf("USD %.4f <- (%.6f * (%.8f / %.8f))\n",usdprice,USD_average,theoretical,CMC_average);
PAXPRICES[0] = usdprice;
if ( (fiatjson= yahoo_allcurrencies()) != 0 )
{
marketmaker_fiatupdate(fiatjson);
free_json(fiatjson);
}
}
}
LP_priceupdate(base,rel,theoretical,avebid,aveask,highbid,lowask,PAXPRICES);
}
return(theoretical);
}
void marketmaker(double minask,double maxbid,char *baseaddr,char *reladdr,double start_BASE,double start_REL,double profitmargin,double maxexposure,double ratioincr,char *exchange,char *name,char *base,char *rel)
{
char *retstr; double bid,ask,start_DEXbase,start_DEXrel,DEX_base = 0.,DEX_rel = 0.,balance_base=0.,balance_rel=0.,mmbid,mmask,aveprice,incr,pendingbids,pendingasks,buyvol,sellvol,bidincr,askincr,filledprice,avebid=0.,aveask=0.,highbid=0.,lowask=0.,theoretical = 0.; uint32_t lasttime = 0;
incr = maxexposure * ratioincr;
buyvol = sellvol = 0.;
start_DEXbase = dex_balance(base,baseaddr);
start_DEXrel = dex_balance(rel,reladdr);
while ( 1 )
{
if ( time(NULL) > lasttime+60 )
{
if ( (theoretical= marketmaker_updateprice(name,base,rel,theoretical,&incr)) != 0. )
{
if ( lasttime == 0 )
maxexposure /= theoretical;
}
if ( strcmp(exchange,"bittrex") == 0 )
{
balance_base = bittrex_balance(base,"");
balance_rel = bittrex_balance(rel,"");
DEX_base = dex_balance(base,baseaddr);
DEX_rel = dex_balance(rel,reladdr);
} else printf("add support for %s balance\n",exchange);
lasttime = (uint32_t)time(NULL);
}
marketmaker_pendingupdate(exchange,base,rel);
if ( theoretical > SMALLVAL && avebid > SMALLVAL && aveask > SMALLVAL )
{
aveprice = (avebid + aveask) * 0.5;
// if order is filled, theoretical <- filled (theoretical + price)/2
if ( (filledprice= marketmaker_filled(exchange,base,rel,&buyvol,&sellvol,&pendingbids,&pendingasks)) != 0. )
theoretical = (theoretical + filledprice) * 0.5;
buyvol = sellvol = 0;
if ( (balance_base + DEX_base) < (start_BASE + start_DEXbase) )
sellvol += ((start_BASE + start_DEXbase) - (balance_base + DEX_base));
else buyvol += ((balance_base + DEX_base) - (start_BASE + start_DEXbase));
if ( (balance_rel + DEX_rel) < (start_REL + start_DEXrel) )
buyvol += ((start_REL + start_DEXrel) - (balance_rel + DEX_rel)) / theoretical;
else sellvol += ((balance_rel + DEX_rel) - (start_REL + start_DEXrel)) / theoretical;
mmbid = theoretical - theoretical*profitmargin;
mmask = theoretical + theoretical*profitmargin;
// if any existing order exceeds double margin distance, cancel
marketmaker_prune(exchange,base,rel,1,mmbid - theoretical*profitmargin,mmask + theoretical*profitmargin,0.);
// if new prices crosses existing order, cancel old order first
marketmaker_prune(exchange,base,rel,-1,mmbid,mmask,0.);
//printf("(%.8f %.8f) ",mmbid,mmask);
if ( (1) )
{
if ( mmbid >= lowask || (maxbid > SMALLVAL && mmbid > maxbid) ) //mmbid < highbid ||
{
printf("clear mmbid %.8f lowask %.8f maxbid %.8f\n",mmbid,lowask,maxbid);
mmbid = 0.;
}
if ( mmask <= highbid || (minask > SMALLVAL && mmask < minask) ) // mmask > lowask ||
mmask = 0.;
}
marketmaker_volumeset(&bidincr,&askincr,incr,buyvol,pendingbids,sellvol,pendingasks,maxexposure);
printf("AVE.(%.8f %.8f) hbla %.8f %.8f bid %.8f ask %.8f theory %.8f buys.(%.6f %.6f) sells.(%.6f %.6f) incr.(%.6f %.6f) balances.(%.8f + %.8f, %.8f + %.8f) test %f\n",avebid,aveask,highbid,lowask,mmbid,mmask,theoretical,buyvol,pendingbids,sellvol,pendingasks,bidincr,askincr,balance_base,DEX_base,balance_rel,DEX_rel,(aveask - avebid)/aveprice);
if ( (retstr= DEX_swapstatus()) != 0 )
printf("%s\n",retstr), free(retstr);
printf("%s %s %s, %s %s %s\n",base,DEX_baseaddr,DEX_balance("DEX",base,DEX_baseaddr),rel,DEX_reladdr,DEX_balance("DEX",rel,DEX_reladdr));
if ( (aveask - avebid)/aveprice > profitmargin )
bid = highbid * (1 - profitmargin), ask = lowask * (1 + profitmargin);
else bid = avebid - profitmargin*aveprice, ask = avebid + profitmargin*aveprice;
marketmaker_spread("DEX",base,rel,bid,incr,ask,incr,profitmargin*aveprice*0.5);
if ( (pendingbids + buyvol) > (pendingasks + sellvol) && (pendingbids + buyvol) > bidincr )
{
bidincr *= ((double)(pendingasks + sellvol) / ((pendingbids + buyvol) + (pendingasks + sellvol)));
printf("bidincr %f buy.(%f + %f) sell.(%f + %f)\n",bidincr,pendingbids,buyvol,pendingasks,sellvol);
if ( bidincr < 0.1*incr )
bidincr = 0.1*incr;
if ( bidincr > 1. )
bidincr = (int32_t)bidincr + 0.777;
}
if ( (pendingbids + buyvol) < (pendingasks + sellvol) && (pendingasks + sellvol) > askincr )
{
askincr *= (double)(pendingbids + buyvol) / ((pendingbids + buyvol) + (pendingasks + sellvol));
if ( askincr < 0.1*incr )
askincr = 0.1*incr;
if ( askincr > 1. )
askincr = (int32_t)askincr + 0.777;
}
//printf("mmbid %.8f %.6f, mmask %.8f %.6f\n",mmbid,bidincr,mmask,askincr);
marketmaker_spread(exchange,base,rel,mmbid,bidincr,mmask,askincr,profitmargin*aveprice*0.5);
sleep(60);
}
}
}
profitmargin = jdouble(retjson,"profitmargin");
minask = jdouble(retjson,"minask");
maxbid = jdouble(retjson,"maxbid");
maxexposure = jdouble(retjson,"maxexposure");
incrratio = jdouble(retjson,"lotratio");
start_base = jdouble(retjson,"start_base");
start_rel = jdouble(retjson,"start_rel");
apikey = jstr(retjson,"apikey");
apisecret = jstr(retjson,"apisecret");
base = jstr(retjson,"base");
name = jstr(retjson,"name");
rel = jstr(retjson,"rel");
blocktrail = jstr(retjson,"blocktrail");
exchange = jstr(retjson,"exchange");
//PAXACTIVE = juint(retjson,"paxactive");
if ( profitmargin < 0. || maxexposure <= 0. || incrratio <= 0. || apikey == 0 || apisecret == 0 || base == 0 || name == 0 || rel == 0 || exchange == 0 || blocktrail == 0 )
{
printf("illegal parameter (%s)\n",jprint(retjson,0));
exit(-1);
}
if ( (retstr= iguana_walletpassphrase(passphrase,999999)) != 0 )
{
printf("(%s/%s) login.(%s)\n",base,rel,retstr);
if ( (loginjson= cJSON_Parse(retstr)) != 0 )
{
if ( PAXACTIVE != 0 )
{
for (i=0; i<32; i++)
{
if ( ((1<<i) & PAXACTIVE) != 0 )
{
if ( jstr(loginjson,CURRENCIES[i]) == 0 )
PAXACTIVE &= ~(1 << i);
}
}
}
if ( (baseaddr= jstr(loginjson,base)) == 0 || (reladdr= jstr(loginjson,rel)) == 0 )
{
printf("Need to activate both %s and %s before marketmaker\n",base,rel);
exit(1);
}
printf("%s\n",DEX_apikeypair(exchange,apikey,apisecret));
marketmaker_pendinginit(exchange,base,rel);
if ( baseaddr != 0 && reladdr != 0 )
{
printf("PAXACTIVE.%08x %s\n",PAXACTIVE,DEX_amlp(blocktrail));
strncpy(DEX_baseaddr,baseaddr,sizeof(DEX_baseaddr)-1);
strncpy(DEX_reladdr,reladdr,sizeof(DEX_reladdr)-1);
printf("%s.%s %s\n",base,baseaddr,DEX_balance("DEX",base,baseaddr));
printf("%s.%s %s\n",rel,reladdr,DEX_balance("DEX",rel,reladdr));
// initialize state using DEX_pendingorders, etc.
marketmaker(minask,maxbid,baseaddr,reladdr,start_base,start_rel,profitmargin,maxexposure,incrratio,exchange,name,base,rel);
}
free_json(loginjson);
} else printf("ERROR parsing.(%s)\n",retstr);
free(retstr);
}
free_json(retjson);
}
#endif
else
{
CTransaction tx; uint256 hashBlock; int32_t numvouts,len; uint8_t *ptr;
@ -447,6 +1241,71 @@ void issue_LP_uitem(char *destip,uint16_t destport,char *symbol,char *coinaddr,b
portable_mutex_unlock(&LP_cJSONmutex);
} //else printf("cJSON_unregister of unknown %p %u\n",item,item->cjsonid);
}*/
void LP_instantdex_txidadd(bits256 txid)
{
cJSON *array; int32_t i,n;
if ( (array= LP_instantdex_txids()) == 0 )
array = cJSON_CreateArray();
if ( (n= cJSON_GetArraySize(array)) >= 0 )
{
for (i=0; i<n; i++)
if ( bits256_cmp(jbits256i(array,i),txid) == 0 )
break;
if ( i == n )
{
jaddibits256(array,txid);
LP_instantdex_filewrite(0,array);
LP_instantdex_filewrite(1,array);
}
}
if ( array != 0 )
free_json(array);
}
/*if ( 0 && OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_privkeysloop,ctx) != 0 )
{
printf("error launching LP_privkeysloop for ctx.%p\n",ctx);
exit(-1);
}*/
/*double LP_qprice_calc(int64_t *destsatoshisp,int64_t *satoshisp,double price,uint64_t b_satoshis,uint64_t txfee,uint64_t a_value,uint64_t maxdestsatoshis,uint64_t desttxfee)
{
uint64_t destsatoshis,satoshis;
a_value -= (desttxfee + 1);
destsatoshis = ((b_satoshis - txfee) * price);
if ( destsatoshis > a_value )
destsatoshis = a_value;
if ( maxdestsatoshis != 0 && destsatoshis > maxdestsatoshis-desttxfee-1 )
destsatoshis = maxdestsatoshis-desttxfee-1;
satoshis = (destsatoshis / price + 0.49) - txfee;
*destsatoshisp = destsatoshis;
*satoshisp = satoshis;
if ( satoshis > 0 )
return((double)destsatoshis / satoshis);
else return(0.);
}*/
/*for (iambob=0; iambob<2; iambob++)
{
if ( G.LP_utxoinfos[iambob] != 0 )
{
HASH_ITER(hh,G.LP_utxoinfos[iambob],utxo,tmp)
{
HASH_DELETE(hh,G.LP_utxoinfos[iambob],utxo);
//free(utxo);
}
}
if ( G.LP_utxoinfos2[iambob] != 0 )
{
G.LP_utxoinfos2[iambob] = 0;
//HASH_ITER(hh,G.LP_utxoinfos2[iambob],utxo,tmp)
//{
// HASH_DELETE(hh,G.LP_utxoinfos2[iambob],utxo);
// free(utxo);
//}
}
}*/
char *issue_LP_getprices(char *destip,uint16_t destport)
{
char url[512];
@ -2095,6 +2954,87 @@ char *LP_postutxos_recv(cJSON *argjson)
return(clonestr("{\"error\":\"sig failure\"}"));
}
/*MERK d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a ht.518777 -> {"pos":1,"merkle":["526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8", "f68b03a7b6e418c9b306d8d8b21917ae5a584696f9b0b8cb0741733d7097fdfd"],"block_height":518777} root.(0000000000000000000000000000000000000000000000000000000000000000)
MERK c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543 ht.518777 -> {"pos":2,"merkle":["fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501", "8c116e974c842ad3ad8b3ddbd71da3debb150e3fe692f5bd628381bc167311a7"],"block_height":518777} root.(0000000000000000000000000000000000000000000000000000000000000000)*/
/*526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8
d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a
c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543
fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501*/
/*0: 526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8
1: d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a
2: c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543
3: fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501
4: 8c116e974c842ad3ad8b3ddbd71da3debb150e3fe692f5bd628381bc167311a7
5: f68b03a7b6e418c9b306d8d8b21917ae5a584696f9b0b8cb0741733d7097fdfd
6: a87ee259560f20b20182760c0e7cc7896d44381f0ad58a2e755a2b6b895b01ec*/
/*
0 1 2 3
4 5
6
1 -> [0, 5]
2 -> [3, 4]
if odd -> right, else left
then /= 2
*/
/*void testmerk()
{
bits256 tree[256],roothash,txid; int32_t i; char str[65];
memset(tree,0,sizeof(tree));
decode_hex(tree[0].bytes,32,"526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8");
decode_hex(tree[1].bytes,32,"d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a");
decode_hex(tree[2].bytes,32,"c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543");
decode_hex(tree[3].bytes,32,"fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501");
roothash = iguana_merkle(tree,4);
for (i=0; i<256; i++)
{
if ( bits256_nonz(tree[i]) == 0 )
break;
printf("%d: %s\n",i,bits256_str(str,tree[i]));
}
memset(tree,0,sizeof(tree));
decode_hex(tree[0].bytes,32,"526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8");
decode_hex(tree[1].bytes,32,"f68b03a7b6e418c9b306d8d8b21917ae5a584696f9b0b8cb0741733d7097fdfd");
decode_hex(txid.bytes,32,"d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a");
roothash = validate_merkle(1,txid,tree,2);
printf("validate 1: %s\n",bits256_str(str,roothash));
memset(tree,0,sizeof(tree));
decode_hex(tree[0].bytes,32,"fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501");
decode_hex(tree[1].bytes,32,"8c116e974c842ad3ad8b3ddbd71da3debb150e3fe692f5bd628381bc167311a7");
decode_hex(txid.bytes,32,"c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543");
roothash = validate_merkle(2,txid,tree,2);
printf("validate 2: %s\n",bits256_str(str,roothash));
}*/
/*else if ( (retstr= LP_orderbook(coin->symbol,"KMD",-1)) != 0 )
{
if ( (orderbook= cJSON_Parse(retstr)) != 0 )
{
if ( (asks= jarray(&numasks,orderbook,"asks")) != 0 && numasks > 0 )
{
item = jitem(asks,0);
price = ask = jdouble(item,"price");
//printf("%s/%s ask %.8f\n",coin->symbol,"KMD",ask);
}
if ( (bids= jarray(&numbids,orderbook,"bids")) != 0 && numbids > 0 )
{
item = jitem(asks,0);
bid = jdouble(item,"price");
if ( price == 0. )
price = bid;
else price = (bid + ask) * 0.5;
//printf("%s/%s bid %.8f ask %.8f price %.8f\n",coin->symbol,"KMD",bid,ask,price);
}
KMDvalue = price * balance;
free_json(orderbook);
}
free(retstr);
}*/
int32_t LP_utxosQ_process()
{
struct LP_utxos_qitem *uitem; int32_t n; char *symbol,*coinaddr; struct LP_address *ap; struct iguana_info *coin; cJSON *array;
@ -3597,6 +4537,21 @@ void LP_price_broadcastloop(void *ctx)
break;
}
return(clonestr("{\"error\":\"no instantdex deposits to claim\"}"));*/
/*else
{
if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
balance += j64bits(item,"value");
}
}
free_json(array);
}
}*/
//else if ( strcmp(method,"checktxid") == 0 )

59
iguana/exchanges/LP_stats.c

@ -297,6 +297,10 @@ int32_t LP_finished_lastheight(struct LP_swapstats *sp)
int32_t height = 1; struct iguana_info *bob,*alice; //char str[65];
if ( (bob= LP_coinfind(sp->Q.srccoin)) != 0 && (alice= LP_coinfind(sp->Q.destcoin)) != 0 )
{
if ( strcmp(bob->symbol,"BTC") == 0 )
sp->bobneeds_dPoW = 0;
if ( strcmp(alice->symbol,"BTC") == 0 )
sp->aliceneeds_dPoW = 0;
if ( sp->bobneeds_dPoW != 0 )
{
if ( bits256_nonz(sp->bobdeposit) != 0 && sp->bobdeposit_ht == 0 )
@ -451,6 +455,7 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
{
HASH_ITER(hh,LP_swapstats,sp,tmp)
{
static uint32_t counter;
if ( sp->Q.R.requestid == requestid && sp->Q.R.quoteid == quoteid )
{
sp->methodind = methodind;
@ -459,7 +464,8 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
flag = 1;
break;
}
printf("error after delayed match\n");
if ( counter++ < 10 )
printf("error after delayed match\n");
}
}
}
@ -643,7 +649,7 @@ char *LP_gettradestatus(uint64_t aliceid,uint32_t requestid,uint32_t quoteid)
//printf("gettradestatus.(%llu)\n",(long long)aliceid);
if ( IAMLP != 0 )
{
if ( (sp= LP_swapstats_find(aliceid)) != 0 )
if ( (sp= LP_swapstats_find(aliceid)) != 0 && sp->Q.satoshis != 0 && sp->Q.destsatoshis != 0 && bits256_nonz(sp->bobdeposit) != 0 )
{
if ( time(NULL) > sp->lasttime+60 )
{
@ -693,9 +699,9 @@ int32_t LP_stats_dispiter(cJSON *array,struct LP_swapstats *sp,uint32_t starttim
dispflag = 1;
else if ( sp->Q.timestamp >= starttime && sp->Q.timestamp <= endtime )
dispflag = 1;
if ( refbase != 0 && strcmp(refbase,sp->Q.srccoin) != 0 && strcmp(refbase,sp->Q.destcoin) != 0 )
if ( refbase != 0 && refbase[0] != 0 && strcmp(refbase,sp->Q.srccoin) != 0 && strcmp(refbase,sp->Q.destcoin) != 0 )
dispflag = 0;
if ( refrel != 0 && strcmp(refrel,sp->Q.srccoin) != 0 && strcmp(refrel,sp->Q.destcoin) != 0 )
if ( refrel != 0 && refrel[0] != 0 && strcmp(refrel,sp->Q.srccoin) != 0 && strcmp(refrel,sp->Q.destcoin) != 0 )
dispflag = 0;
if ( dispflag != 0 )
{
@ -756,7 +762,7 @@ cJSON *LP_statslog_disp(uint32_t starttime,uint32_t endtime,char *refgui,bits256
}
HASH_ITER(hh,LP_pubkeyinfos,pubp,ptmp)
{
pubp->dynamictrust = LP_dynamictrust(pubp->pubkey,0);
pubp->dynamictrust = LP_dynamictrust(0,pubp->pubkey,0);
}
//printf("RT.%d completed.%d\n",LP_RTcount,LP_swapscount);
jadd(retjson,"swaps",array);
@ -789,7 +795,34 @@ cJSON *LP_statslog_disp(uint32_t starttime,uint32_t endtime,char *refgui,bits256
return(retjson);
}
//tradesarray(base, rel, starttime=<now>-timescale*1024, endtime=<now>, timescale=60) -> [timestamp, high, low, open, close, relvolume, basevolume, aveprice, numtrades]
char *LP_ticker(char *refbase,char *refrel)
{
cJSON *logjson,*retjson,*item,*retitem,*swapsjson; double basevol,relvol; char *base,*rel; int32_t i,n; bits256 zero; uint32_t now = (uint32_t)time(NULL);
memset(zero.bytes,0,sizeof(zero));
if ( (logjson= LP_statslog_disp(now - 3600*24,now,"",zero,refbase,refrel)) != 0 )
{
retjson = cJSON_CreateArray();
if ( (swapsjson= jarray(&n,logjson,"swaps")) != 0 )
{
for (i=n-1; i>=0; i--)
{
item = jitem(swapsjson,i);
retitem = cJSON_CreateObject();
if ( (base= jstr(item,"base")) != 0 && (rel= jstr(item,"rel")) != 0 && (basevol= jdouble(item,"basevol")) > SMALLVAL )
{
relvol = jdouble(item,"relvol");
jaddnum(retitem,"timestamp",juint(item,"timestamp"));
jaddnum(retitem,base,basevol);
jaddnum(retitem,rel,relvol);
jaddnum(retitem,"price",relvol/basevol);
}
jaddi(retjson,retitem);
}
}
free_json(logjson);
return(jprint(retjson,1));
} else return(clonestr("{\"error\":\"couldnt get logjson\"}"));
}
struct LP_ohlc
{
@ -803,8 +836,9 @@ cJSON *LP_ohlc_json(struct LP_ohlc *bar,struct LP_ohlc *prevbar)
memset(&tmp,0,sizeof(tmp));
if ( bar->numtrades == 0 )
{
tmp = *prevbar;
memset(&tmp,0,sizeof(tmp));
tmp.timestamp = bar->timestamp;
tmp.open = tmp.high = tmp.low = tmp.close = prevbar->close;
tmp.numtrades = 0;
tmp.relsum = tmp.basesum = 0.;
} else tmp = *bar;
@ -851,9 +885,9 @@ void LP_ohlc_update(struct LP_ohlc *bar,uint32_t timestamp,double basevol,double
}
}
cJSON *LP_tradesarray(char *base,char *rel,uint32_t starttime,uint32_t endtime,int32_t timescale)
cJSON *LP_tradesarray(char *refbase,char *refrel,uint32_t starttime,uint32_t endtime,int32_t timescale)
{
struct LP_ohlc *bars,nonz; cJSON *array,*item,*statsjson,*swaps; uint32_t timestamp; bits256 zero; int32_t i,n,numbars,bari;
struct LP_ohlc *bars,nonz; cJSON *array,*item,*statsjson,*swaps; uint32_t timestamp; bits256 zero; char *base,*rel; int32_t i,n,numbars,bari;
if ( timescale < 60 )
return(cJSON_Parse("{\"error\":\"one minute is shortest timescale\"}"));
memset(zero.bytes,0,sizeof(zero));
@ -865,7 +899,7 @@ cJSON *LP_tradesarray(char *base,char *rel,uint32_t starttime,uint32_t endtime,i
bars = calloc(numbars,sizeof(*bars));
for (bari=0; bari<numbars; bari++)
bars[bari].timestamp = starttime + bari*timescale;
if ( (statsjson= LP_statslog_disp(starttime,endtime,"",zero,base,rel)) != 0 )
if ( (statsjson= LP_statslog_disp(starttime,endtime,"",zero,refbase,refrel)) != 0 )
{
if ( (swaps= jarray(&n,statsjson,"swaps")) != 0 )
{
@ -875,7 +909,12 @@ cJSON *LP_tradesarray(char *base,char *rel,uint32_t starttime,uint32_t endtime,i
if ( (timestamp= juint(item,"timestamp")) != 0 && timestamp >= starttime && timestamp <= endtime )
{
bari = (timestamp - starttime) / timescale;
base = jstr(item,"base");
rel = jstr(item,"rel");
if ( strcmp(base,refbase) == 0 && strcmp(rel,refrel) == 0 )
LP_ohlc_update(&bars[bari],timestamp,jdouble(item,"basevol"),jdouble(item,"relvol"));
else if ( strcmp(rel,refbase) == 0 && strcmp(base,refrel) == 0 )
LP_ohlc_update(&bars[bari],timestamp,jdouble(item,"relvol"),jdouble(item,"basevol"));
} else printf("skip.(%s)\n",jprint(item,0));
}
}

40
iguana/exchanges/LP_swap.c

@ -126,8 +126,8 @@ void basilisk_rawtx_purge(struct basilisk_rawtx *rawtx)
void basilisk_swap_finished(struct basilisk_swap *swap)
{
int32_t i;
/*if ( swap->utxo != 0 && swap->sentflag == 0 )
/*int32_t i;
if ( swap->utxo != 0 && swap->sentflag == 0 )
{
LP_availableset(swap->utxo);
swap->utxo = 0;
@ -159,11 +159,11 @@ void basilisk_swap_finished(struct basilisk_swap *swap)
basilisk_rawtx_purge(&swap->bobspend);
basilisk_rawtx_purge(&swap->bobrefund);
basilisk_rawtx_purge(&swap->alicereclaim);
for (i=0; i<swap->nummessages; i++)
/*for (i=0; i<swap->nummessages; i++)
if ( swap->messages[i].data != 0 )
free(swap->messages[i].data), swap->messages[i].data = 0;
free(swap->messages), swap->messages = 0;
swap->nummessages = 0;
swap->nummessages = 0;*/
if ( swap->N.pair >= 0 )
nn_close(swap->N.pair), swap->N.pair = -1;
}
@ -823,9 +823,9 @@ void LP_bobloop(void *_swap)
printf("error bobscripts payment\n");
else
{
if ( strcmp(swap->I.alicestr,"BTC") == 0 )
/*if ( strcmp(swap->I.alicestr,"BTC") == 0 )
m = 0;
else m = swap->I.aliceconfirms;
else*/ m = swap->I.aliceconfirms;
while ( (n= LP_numconfirms(swap->I.alicestr,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,1)) < m ) // sync with alice
{
LP_swap_critical = (uint32_t)time(NULL);
@ -837,7 +837,7 @@ void LP_bobloop(void *_swap)
printf("error sending bobpayment\n");
//if ( LP_waitfor(swap->N.pair,swap,10,LP_verify_alicespend) < 0 )
// printf("error waiting for alicespend\n");
swap->sentflag = 1;
//swap->sentflag = 1;
swap->bobreclaim.utxovout = 0;
swap->bobreclaim.utxotxid = swap->bobpayment.I.signedtxid;
basilisk_bobpayment_reclaim(swap,swap->I.callduration);
@ -848,10 +848,11 @@ void LP_bobloop(void *_swap)
}
}
}
basilisk_swap_finished(swap);
free(swap);
} else printf("swap timed out\n");
G.LP_pendingswaps--;
basilisk_swap_finished(swap);
free(swap);
free(data);
}
void LP_aliceloop(void *_swap)
@ -882,9 +883,9 @@ void LP_aliceloop(void *_swap)
printf("error waiting for bobdeposit\n");
else
{
if ( strcmp(swap->I.bobstr,"BTC") == 0 )
/*if ( strcmp(swap->I.bobstr,"BTC") == 0 )
m = 0;
else m = swap->I.bobconfirms;
else*/ m = swap->I.bobconfirms;
while ( (n= LP_numconfirms(swap->I.bobstr,swap->bobdeposit.I.destaddr,swap->bobdeposit.I.signedtxid,0,1)) < m )
{
LP_swap_critical = (uint32_t)time(NULL);
@ -895,16 +896,16 @@ void LP_aliceloop(void *_swap)
printf("error sending alicepayment\n");
else
{
if ( strcmp(swap->I.alicestr,"BTC") == 0 )
/*if ( strcmp(swap->I.alicestr,"BTC") == 0 )
m = 0;
else m = swap->I.aliceconfirms;
else*/ m = swap->I.aliceconfirms;
while ( (n= LP_numconfirms(swap->I.alicestr,swap->alicepayment.I.destaddr,swap->alicepayment.I.signedtxid,0,1)) < m )
{
LP_swap_critical = (uint32_t)time(NULL);
char str[65];printf("%d wait for alicepayment %s numconfs.%d %s %s\n",n,swap->alicepayment.I.destaddr,m,swap->I.alicestr,bits256_str(str,swap->alicepayment.I.signedtxid));
sleep(10);
}
swap->sentflag = 1;
//swap->sentflag = 1;
LP_swap_critical = (uint32_t)time(NULL);
if ( LP_waitfor(swap->N.pair,swap,1800,LP_verify_bobpayment) < 0 )
printf("error waiting for bobpayment\n");
@ -925,6 +926,7 @@ void LP_aliceloop(void *_swap)
}*/
if ( swap->N.pair >= 0 )
nn_close(swap->N.pair), swap->N.pair = -1;
LP_swap_endcritical = (uint32_t)time(NULL);
LP_swapwait(swap,swap->I.req.requestid,swap->I.req.quoteid,LP_atomic_locktime(swap->I.bobstr,swap->I.alicestr)*2,swap->I.aliceconfirms == 0 ? 3 : 30);
}
}
@ -932,13 +934,7 @@ void LP_aliceloop(void *_swap)
}
}
free(data);
if ( swap->N.pair >= 0 )
{
nn_close(swap->N.pair);
swap->N.pair = -1;
}
basilisk_swap_finished(swap);
printf("finish swap.%p\n",swap);
free(swap);
G.LP_pendingswaps--;
}
@ -1134,12 +1130,12 @@ struct basilisk_swap *bitcoin_swapinit(bits256 privkey,uint8_t *pubkey33,bits256
}
if ( strcmp("BTC",swap->I.bobstr) == 0 )
{
swap->I.bobconfirms = (1 + sqrt(dstr(swap->I.bobsatoshis) * .1));
swap->I.bobconfirms = 1;//(1 + sqrt(dstr(swap->I.bobsatoshis) * .1));
swap->I.aliceconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
}
else if ( strcmp("BTC",swap->I.alicestr) == 0 )
{
swap->I.aliceconfirms = (1 + sqrt(dstr(swap->I.alicesatoshis) * .1));
swap->I.aliceconfirms = 1;//(1 + sqrt(dstr(swap->I.alicesatoshis) * .1));
swap->I.bobconfirms = BASILISK_DEFAULT_NUMCONFIRMS;
}
else

9
iguana/exchanges/LP_tradebots.c

@ -40,6 +40,15 @@ struct LP_tradebot
struct LP_tradebot_trade *trades[LP_TRADEBOTS_MAXTRADES];
} *LP_tradebots;
void LP_tradebot_pauseall()
{
struct LP_tradebot *bot,*tmp;
DL_FOREACH_SAFE(LP_tradebots,bot,tmp)
{
bot->userpause = bot->pause = (uint32_t)time(NULL);
}
}
void LP_tradebot_updatestats(struct LP_tradebot *bot,struct LP_tradebot_trade *tp)
{
char *swapstr,*status; int32_t flag; cJSON *swapjson;

176
iguana/exchanges/LP_transaction.c

@ -397,12 +397,12 @@ int32_t iguana_vininfo_create(uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uin
int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype,uint8_t p2shtype,uint8_t isPoS,int32_t height,bits256 *signedtxidp,char **signedtx,struct iguana_msgtx *msgtx,uint8_t *serialized,int32_t maxlen,struct vin_info *V,uint32_t sighash,int32_t signtx,int32_t suppress_pubkeys,int32_t zcash)
{
bits256 sigtxid; uint8_t *sig,*script; struct vin_info *vp; char vpnstr[64]; int32_t scriptlen,complete=0,j,vini=0,flag=0,siglen,numvouts,numsigs;
bits256 sigtxid; int64_t spendamount; uint8_t *sig,*script; struct vin_info *vp; char vpnstr[64]; int32_t scriptlen,complete=0,j,vini=0,flag=0,siglen,numvouts,numsigs;
numvouts = msgtx->tx_out;
vpnstr[0] = 0;
*signedtx = 0;
memset(signedtxidp,0,sizeof(*signedtxidp));
//printf("bitcoin_verifyvins numvins.%d numvouts.%d\n",msgtx->tx_in,numvouts);
//printf("bitcoin_verifyvins numvins.%d numvouts.%d signtx.%d privkey.%d M.%d N.%d\n",msgtx->tx_in,numvouts,signtx,bits256_nonz(V[0].signers[0].privkey),V[0].M,V[0].N);
for (vini=0; vini<msgtx->tx_in; vini++)
{
if ( V->p2shscript[0] != 0 && V->p2shlen != 0 )
@ -415,13 +415,8 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype,
script = msgtx->vins[vini].spendscript;
scriptlen = msgtx->vins[vini].spendlen;
}
//for (j=0; j<scriptlen; j++)
// printf("%02x",script[j]);
//printf(" scriptlen.%d\n",scriptlen);
//printf("bitcoin_verifyvins scriptlen.%d siglen.%d\n",scriptlen,V[vini].signers[0].siglen);
//spendamount = LP_outpoint_amount(symbol,msgtx->vins[vini].prev_hash,msgtx->vins[vini].prev_vout);
sigtxid = bitcoin_sigtxid(symbol,taddr,pubtype,p2shtype,isPoS,height,serialized,maxlen,msgtx,vini,script,scriptlen,V[vini].amount,sighash,vpnstr,suppress_pubkeys,zcash);
//printf("bitcoin_verifyvins scriptlen.%d siglen.%d\n",scriptlen,V[vini].signers[0].siglen);
spendamount = LP_outpoint_amount(symbol,msgtx->vins[vini].prev_hash,msgtx->vins[vini].prev_vout);
sigtxid = bitcoin_sigtxid(symbol,taddr,pubtype,p2shtype,isPoS,height,serialized,maxlen,msgtx,vini,script,scriptlen,spendamount,sighash,vpnstr,suppress_pubkeys,zcash);
if ( bits256_nonz(sigtxid) != 0 )
{
vp = &V[vini];
@ -441,7 +436,7 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype,
int32_t i; for (i=0; i<siglen; i++)
printf("%02x",sig[i]);
printf(" sig, ");
for (i=0; i<plen; i++)
for (i=0; i<33; i++)
printf("%02x",vp->signers[j].pubkey[i]);
// s2 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1;
printf(" SIGNEDTX.[%02x] siglen.%d priv.%s\n",sig[siglen-1],siglen,bits256_str(str,vp->signers[j].privkey));*/
@ -474,10 +469,11 @@ int32_t bitcoin_verifyvins(void *ctx,char *symbol,uint8_t taddr,uint8_t pubtype,
}
if ( numsigs >= vp->M )
complete = 1;
}
} else if ( signtx != 0 )
printf("bitcoin_verifyvins cant without privkey\n");
}
iguana_msgtx_Vset(serialized,maxlen,msgtx,V);
cJSON *txobj = cJSON_CreateObject();
cJSON *txobj = 0;//cJSON_CreateObject();
*signedtx = iguana_rawtxbytes(symbol,taddr,pubtype,p2shtype,isPoS,height,txobj,msgtx,suppress_pubkeys,zcash);
//printf("SIGNEDTX.(%s)\n",jprint(txobj,1));
*signedtxidp = msgtx->txid;
@ -665,29 +661,22 @@ char *iguana_validaterawtx(void *ctx,struct iguana_info *coin,struct iguana_msgt
if ( V[i].N < V[i].M )
V[i].N = V[i].M;
item = jitem(vins,i);
if ( strcmp(jstr(item,"txid"),"775489f100361039f56793719d87621a73adbadda5e13c85e81d88f55ff9620e") == 0 && jint(item,"vout") == 1 )
{
V[i].spendlen = 25;
decode_hex(V[i].spendscript,V[i].spendlen,"76a9145baf32629848126250861381382d1117a3d6efaa88ac");
V[i].amount = SATOSHIDEN * 0.00587427;
strcpy(V[i].coinaddr,"19MnNLzxNTNXWUdfxpQvWK3CPwFXJbmLb8");
V[i].suppress_pubkeys = 0;
sobj = cJSON_CreateObject();
jaddstr(sobj,"hex","76a9145baf32629848126250861381382d1117a3d6efaa88ac");
jadd(item,"scriptPubKey",sobj);
printf("match special txid A\n");
}
else if ( strcmp(jstr(item,"txid"),"980d621becd9bbd7f4a3fbd525a00ee5bc67518bb57da8bdcb1bd4c49cb83414") == 0 && jint(item,"vout") == 0 )
if ( strcmp(jstr(item,"txid"),"b19ce2c564f7dc57b3f95593e2b287c72d388e86de12dc562d9f8a6bea65b310") == 0 && jint(item,"vout") == 1 )
{
V[i].spendlen = 25;
decode_hex(V[i].spendscript,V[i].spendlen,"76a9146cfa0a987f4c8f2ffee7e9944ef0c86fcda9671d88ac");
V[i].amount = SATOSHIDEN * 0.001;
strcpy(V[i].coinaddr,"1AwDWu5rZKyGMUu16gf9Kow8ohnKmc7tGH");
decode_hex(V[i].spendscript,V[i].spendlen,"76a91459fdba29ea85c65ad90f6d38f7a6646476b26b1688ac");
msgtx->lock_time = 0;
V[i].amount = 2746715;
strcpy(V[i].coinaddr,"19Cq6MBaD8LY7trqs99ypqKAms3GcLs6J9");
V[i].suppress_pubkeys = 0;
decode_hex(msgtx->vins[i].prev_hash.bytes,32,"b19ce2c564f7dc57b3f95593e2b287c72d388e86de12dc562d9f8a6bea65b310");
msgtx->vins[i].prev_vout = 1;
msgtx->vins[i].sequence = 0xffffffff;
sobj = cJSON_CreateObject();
jaddstr(sobj,"hex","76a9146cfa0a987f4c8f2ffee7e9944ef0c86fcda9671d88ac");
jaddstr(sobj,"hex","76a91459fdba29ea85c65ad90f6d38f7a6646476b26b1688ac");
jadd(item,"scriptPubKey",sobj);
printf("match special txid B\n");
V[i].signers[0].privkey = G.LP_privkey;
}
msgtx->vins[i].spendscript = V[i].spendscript;
msgtx->vins[i].spendlen = V[i].spendlen;
@ -720,24 +709,21 @@ char *iguana_validaterawtx(void *ctx,struct iguana_info *coin,struct iguana_msgt
inputsum += V[i].amount;
if ( msgtx->vins[i].sequence < IGUANA_SEQUENCEID_FINAL )
finalized = 0;
//for (j=0; j<msgtx->vins[i].spendlen; j++)
// printf("%02x",msgtx->vins[i].spendscript[j]);
//printf(" spendscript, vin.%d (%s) scriptlen.%d spendlen.%d:%d finalize.%d\n",i,jprint(item,0),msgtx->vins[i].scriptlen,V[i].spendlen,msgtx->vins[i].spendlen,finalized);
}
sighash = LP_sighash(symbol,zcash);
complete = bitcoin_verifyvins(ctx,symbol,taddr,pubtype,p2shtype,isPoS,height,&signedtxid,&signedtx,msgtx,serialized2,maxsize,V,sighash,0,V[0].suppress_pubkeys,zcash);
msgtx->txid = signedtxid;
cJSON *log = cJSON_CreateArray();
/*cJSON *log = cJSON_CreateArray();
if ( iguana_interpreter(ctx,log,0,V,numinputs) < 0 )
jaddstr(retjson,"error","interpreter rejects tx");
else complete = 1;
jadd(retjson,"interpreter",log);
jadd(retjson,"interpreter",log);*/
jadd(retjson,"complete",complete!=0?jtrue():jfalse());
free(serialized), free(serialized2);
if ( signedtx != 0 )
free(signedtx);
free(V);
}
free(serialized), free(serialized2);
}
//char str[65]; printf("got txid.(%s)\n",bits256_str(str,txid));
}
@ -749,10 +735,10 @@ char *iguana_validaterawtx(void *ctx,struct iguana_info *coin,struct iguana_msgt
return(jprint(retjson,1));
}
void test_validate(char *signedtx)
void test_validate(struct iguana_info *coin,char *signedtx)
{
char *retstr; uint8_t extraspace[8192]; int32_t mempool=0; struct iguana_msgtx msgtx; struct iguana_info *coin = LP_coinfind("BTC");
retstr = iguana_validaterawtx(bitcoin_ctx(),coin,&msgtx,extraspace,sizeof(extraspace),signedtx,mempool,0,LP_IS_BITCOINCASH);
char *retstr; uint8_t extraspace[8192]; int32_t mempool=0; struct iguana_msgtx msgtx;
retstr = iguana_validaterawtx(bitcoin_ctx(),coin,&msgtx,extraspace,sizeof(extraspace),signedtx,mempool,0,coin->zcash);
printf("validate test.(%s)\n",retstr);
}
@ -951,19 +937,33 @@ int32_t LP_vin_select(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t
above = gap;
abovei = i;
}
} else gap = (value - atx_value);
if ( below == 0 || gap < below )
}
else
{
below = gap;
belowi = i;
gap = (value - atx_value);
if ( below == 0 || gap < below )
{
below = gap;
belowi = i;
}
}
//printf("value %.8f gap %.8f abovei.%d %.8f belowi.%d %.8f\n",dstr(value),dstr(gap),abovei,dstr(above),belowi,dstr(below));
}
*aboveip = abovei;
*abovep = above;
*belowip = belowi;
*belowp = below;
//printf("above.%d below.%d\n",abovei,belowi);
return(abovei >= 0 && above < (below>>1) ? abovei : belowi);
if ( abovei >= 0 && belowi >= 0 )
{
if ( above < (below >> 1) )
return(abovei);
else return(belowi);
}
else if ( abovei >= 0 )
return(abovei);
else return(belowi);
//return(abovei >= 0 && above < (below>>1) ? abovei : belowi);
}
cJSON *LP_inputjson(bits256 txid,int32_t vout,char *spendscriptstr)
@ -1166,7 +1166,7 @@ int32_t LP_vins_select(void *ctx,struct iguana_info *coin,int64_t *totalp,int64_
char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_info *coin,struct vin_info *V,int32_t max,bits256 privkey,cJSON *outputs,cJSON *vins,cJSON *privkeys,int64_t txfee,bits256 utxotxid,int32_t utxovout,uint32_t locktime)
{
static void *ctx;
cJSON *txobj,*item; uint8_t addrtype,rmd160[20],script[64],spendscript[256]; char *coinaddr,*rawtxbytes; bits256 txid; uint32_t timestamp; int64_t change=0,adjust=0,total,value,amount = 0; int32_t i,dustcombine,scriptlen,spendlen,suppress_pubkeys,ignore_cltverr,numvouts=0,numvins=0,numutxos=0; struct LP_address_utxo *utxos[LP_MAXVINS*16]; struct LP_address *ap;
cJSON *txobj,*item; uint8_t addrtype,rmd160[20],script[64],spendscript[256]; char *coinaddr,*rawtxbytes; bits256 txid; uint32_t timestamp; int64_t change=0,adjust=0,total,value,amount = 0; int32_t i,dustcombine,scriptlen,spendlen,suppress_pubkeys,ignore_cltverr,numvouts=0,numvins=0,numutxos=0; struct LP_address_utxo *utxos[LP_MAXVINS*256]; struct LP_address *ap;
if ( ctx == 0 )
ctx = bitcoin_ctx();
*numvinsp = 0;
@ -1194,7 +1194,7 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf
{
if ( LP_address_isvalid(coin->symbol,coinaddr) <= 0 )
{
printf("LP_createrawtransaction %s i.%d of %d is invalid\n",coinaddr,i,numvouts);
printf("%s LP_createrawtransaction %s i.%d of %d is invalid\n",coin->symbol,coinaddr,i,numvouts);
return(0);
}
if ( (value= SATOSHIDEN * jdouble(item,coinaddr)) <= 0 )
@ -1217,7 +1217,7 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf
return(0);
}
memset(utxos,0,sizeof(utxos));
if ( (numutxos= LP_address_utxo_ptrs(coin,0,utxos,max,ap,coin->smartaddr)) <= 0 )
if ( (numutxos= LP_address_utxo_ptrs(coin,0,utxos,(int32_t)(sizeof(utxos)/sizeof(*utxos)),ap,coin->smartaddr)) <= 0 )
{
if ( bits256_nonz(utxotxid) == 0 )
{
@ -1255,6 +1255,7 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf
if ( (value= SATOSHIDEN * jdouble(item,coinaddr)) <= 0 )
{
printf("cant get value i.%d of %d %s\n",i,numvouts,jprint(outputs,0));
free_json(txobj);
return(0);
}
bitcoin_addr2rmd160(coin->taddr,&addrtype,rmd160,coinaddr);
@ -1272,6 +1273,7 @@ char *LP_createrawtransaction(cJSON **txobjp,int32_t *numvinsp,struct iguana_inf
else
{
printf("cant get fieldname.%d of %d %s\n",i,numvouts,jprint(outputs,0));
free_json(txobj);
return(0);
}
}
@ -1325,11 +1327,13 @@ char *LP_withdraw(struct iguana_info *coin,cJSON *argjson)
if ( (ap= LP_address_utxo_reset(coin)) == 0 )
{
printf("LP_withdraw error utxo reset %s\n",coin->symbol);
free(V);
return(0);
}
privkeys = cJSON_CreateArray();
vins = cJSON_CreateArray();
memset(V,0,sizeof(*V) * maxV);
numvins = 0;
if ( (rawtx= LP_createrawtransaction(&txobj,&numvins,coin,V,maxV,privkey,outputs,vins,privkeys,iter == 0 ? txfee : newtxfee,utxotxid,utxovout,locktime)) != 0 )
{
completed = 0;
@ -1342,11 +1346,11 @@ char *LP_withdraw(struct iguana_info *coin,cJSON *argjson)
printf("incomplete signing withdraw (%s)\n",jprint(vins,0));
if ( signedtx != 0 )
free(signedtx), signedtx = 0;
} else printf("LP_withdraw %s -> %s\n",jprint(argjson,0),bits256_str(str,signedtxid));
} else printf("LP_withdraw.%s %s -> %s\n",coin->symbol,jprint(argjson,0),bits256_str(str,signedtxid));
if ( signedtx == 0 )
break;
datalen = (int32_t)strlen(signedtx) / 2;
if ( strcmp(coin->symbol,"BTC") == 0 )
if ( iter == 0 && strcmp(coin->symbol,"BTC") == 0 )
{
newtxfee = LP_txfeecalc(coin,0,datalen);
printf("txfee %.8f -> newtxfee %.8f, numvins.%d\n",dstr(txfee),dstr(newtxfee),numvins);
@ -1356,17 +1360,30 @@ char *LP_withdraw(struct iguana_info *coin,cJSON *argjson)
//printf("set available %s\n",jprint(item,0));
LP_availableset(jbits256(item,"txid"),jint(item,"vout"));
}
free_json(vins), vins = 0;
free_json(txobj), txobj = 0;
free_json(privkeys), privkeys = 0;
if ( rawtx != 0 )
free(rawtx), rawtx = 0;
if ( signedtx != 0 )
free(signedtx), signedtx = 0;
} else break;
} else break;
free_json(vins), vins = 0;
free_json(txobj), txobj = 0;
free_json(privkeys), privkeys = 0;
if ( rawtx != 0 )
free(rawtx), rawtx = 0;
}
free(V);
if ( vins != 0 )
{
if ( completed == 0 && (numvins= cJSON_GetArraySize(vins)) > 0 )
{
for (i=0; i<numvins; i++)
{
item = jitem(vins,i);
LP_availableset(jbits256(item,"txid"),jint(item,"vout"));
}
}
free_json(vins);
}
if ( privkeys != 0 )
free_json(privkeys);
retjson = cJSON_CreateObject();
@ -1621,25 +1638,56 @@ bits256 _LP_swap_spendtxid(char *symbol,char *destaddr,char *coinaddr,bits256 ut
}
#endif
bits256 LP_swap_spendtxid(char *symbol,char *destaddr,bits256 utxotxid,int32_t vout)
bits256 LP_swap_spendtxid(char *symbol,char *destaddr,bits256 utxotxid,int32_t utxovout)
{
bits256 spendtxid; int32_t spendvin; char coinaddr[64],str[65]; cJSON *retjson; struct iguana_info *coin;
bits256 spendtxid,txid,vintxid; int32_t spendvin,i,m,n; char coinaddr[64]; cJSON *array,*vins,*vin,*txobj; struct iguana_info *coin;
// listtransactions or listspents
destaddr[0] = 0;
coinaddr[0] = 0;
memset(&spendtxid,0,sizeof(spendtxid));
if ( LP_spendsearch(destaddr,&spendtxid,&spendvin,symbol,utxotxid,vout) > 0 )
if ( LP_spendsearch(destaddr,&spendtxid,&spendvin,symbol,utxotxid,utxovout) > 0 )
{
//printf("spend of %s/v%d detected\n",bits256_str(str,utxotxid),vout);
//char str[65]; printf("spend of %s/v%d detected\n",bits256_str(str,utxotxid),utxovout);
}
else if ( 0 && (coin= LP_coinfind(symbol)) != 0 && coin->electrum == 0 )
else if ( (coin= LP_coinfind(symbol)) != 0 && coin->electrum == 0 )
{
if ( (retjson= LP_gettxout(symbol,coinaddr,utxotxid,vout)) == 0 )
if ( (array= LP_listreceivedbyaddress(symbol,destaddr)) != 0 )
{
decode_hex(spendtxid.bytes,32,"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
printf("couldnt find spend of %s/v%d, but no gettxout\n",bits256_str(str,utxotxid),vout);
} else free_json(retjson);
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
txid = jbits256i(array,i);
if ( (txobj= LP_gettx(symbol,txid,1)) != 0 )
{
if ( (vins= jarray(&m,txobj,"vin")) != 0 )
{
//printf("vins.(%s)\n",jprint(vins,0));
if ( utxovout < m )
{
vin = jitem(vins,utxovout);
vintxid = jbits256(vin,"txid");
if ( bits256_cmp(vintxid,utxotxid) == 0 )
{
LP_txdestaddr(destaddr,txid,0,txobj);
char str[65],str2[65],str3[65]; printf("LP_swap_spendtxid: found %s/v%d spends %s vs %s found.%d destaddr.(%s)\n",bits256_str(str,txid),utxovout,bits256_str(str2,vintxid),bits256_str(str3,utxotxid),bits256_cmp(vintxid,utxotxid) == 0,destaddr);
spendtxid = txid;
break;
}
}
}
free_json(txobj);
}
}
}
free_json(array);
}
}
/* if ( (retjson= LP_gettxout(symbol,coinaddr,utxotxid,vout)) == 0 )
{
decode_hex(spendtxid.bytes,32,"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
printf("couldnt find spend of %s/v%d, but no gettxout\n",bits256_str(str,utxotxid),vout);
} else free_json(retjson);
*/
return(spendtxid);
//char str[65]; printf("swap %s spendtxid.(%s)\n",symbol,bits256_str(str,utxotxid));
}
@ -2017,7 +2065,7 @@ int32_t LP_verify_otherfee(struct basilisk_swap *swap,uint8_t *data,int32_t data
diff = swap->otherfee.I.locktime - (swap->I.started+1);
if ( diff < 0 )
diff = -diff;
if ( diff < 10 )
if ( diff < LP_AUTOTRADE_TIMEOUT )
printf("dexfee verified\n");
else printf("locktime mismatch in otherfee, reject %u vs %u\n",swap->otherfee.I.locktime,swap->I.started+1);
return(0);

103
iguana/exchanges/LP_utxo.c

@ -49,7 +49,7 @@ int32_t _LP_inuse_delete(bits256 txid,int32_t vout)
*lp = LP_inuse[--LP_numinuse];
lp->ind = ind;
memset(&LP_inuse[LP_numinuse],0,sizeof(struct LP_inuse_info));
printf("_LP_inuse_delete mark as free %s/v%d find.%p\n",bits256_str(str,txid),vout,_LP_inuse_find(txid,vout));
//printf("_LP_inuse_delete mark as free %s/v%d find.%p\n",bits256_str(str,txid),vout,_LP_inuse_find(txid,vout));
for (ind=0; ind<LP_numinuse; ind++)
if ( LP_inuse[ind].ind != ind )
printf("ind.%d of %d: mismatched ind.%d\n",ind,LP_numinuse,LP_inuse[ind].ind);
@ -484,7 +484,11 @@ struct LP_address *LP_address_utxo_reset(struct iguana_info *coin)
LP_address_utxoadd(now,"withdraw",coin,coin->smartaddr,txid,vout,value,height,-1);
if ( (up= LP_address_utxofind(coin,coin->smartaddr,txid,vout)) == 0 )
printf("couldnt find just added %s/%d ht.%d %.8f\n",bits256_str(str,txid),vout,height,dstr(value));
else m++;
else
{
m++;
//printf("%.8f ",dstr(value));
}
}
//printf("added %d from listunspents\n",m);
}
@ -578,9 +582,9 @@ cJSON *LP_address_utxos(struct iguana_info *coin,char *coinaddr,int32_t electrum
cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electrumret)
{
cJSON *array,*retjson,*item; bits256 zero; int32_t i,n; uint64_t balance = 0;
memset(zero.bytes,0,sizeof(zero));
if ( coin->electrum == 0 )
{
memset(zero.bytes,0,sizeof(zero));
if ( (array= LP_listunspent(coin->symbol,coinaddr,zero,zero)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
@ -596,23 +600,12 @@ cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electr
}
else
{
//if ( strcmp(coin->smartaddr,coinaddr) == 0 )
balance = LP_unspents_load(coin->symbol,coinaddr);
/*else
if ( strcmp(coin->smartaddr,coinaddr) != 0 )
{
if ( (array= LP_address_utxos(coin,coinaddr,1)) != 0 )
{
if ( (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
balance += j64bits(item,"value");
}
}
free_json(array);
}
}*/
if ( (retjson= electrum_address_listunspent(coin->symbol,coin->electrum,&retjson,coinaddr,2,zero,zero)) != 0 )
free_json(retjson);
}
balance = LP_unspents_load(coin->symbol,coinaddr);
}
retjson = cJSON_CreateObject();
jaddstr(retjson,"result","success");
@ -627,6 +620,78 @@ cJSON *LP_address_balance(struct iguana_info *coin,char *coinaddr,int32_t electr
return(retjson);
}
cJSON *LP_balances(char *coinaddr)
{
struct iguana_info *coin,*tmp; char address[64]; uint8_t taddr,addrtype,rmd160[20]; uint64_t balance,KMDvalue,sum = 0; cJSON *array,*item,*retjson;
if ( coinaddr != 0 && coinaddr[0] == 't' && (coinaddr[1] == '1' || coinaddr[1] == '3') )
taddr = 1;
else taddr = 0;
array = cJSON_CreateArray();
HASH_ITER(hh,LP_coins,coin,tmp)
{
if ( coin->electrum != 0 || (coinaddr != 0 && coinaddr[0] != 0 && strcmp(coinaddr,coin->smartaddr) != 0) )
{
if ( coinaddr == 0 || coinaddr[0] == 0 )
strcpy(address,coin->smartaddr);
else
{
bitcoin_addr2rmd160(taddr,&addrtype,rmd160,coinaddr);
bitcoin_address(address,coin->taddr,coin->pubtype,rmd160,20);
//printf("%s taddr.%d addrtype.%u %s -> %s [%c %c].%d\n",coin->symbol,taddr,addrtype,coinaddr,address,coinaddr[0],coinaddr[1],coinaddr[0] == 't' && (coinaddr[1] == '1' || coinaddr[1] == '3'));
}
if ( (retjson= LP_address_balance(coin,address,1)) != 0 )
{
if ( (balance= jdouble(retjson,"balance")*SATOSHIDEN) > 0 )
{
item = cJSON_CreateObject();
jaddstr(item,"coin",coin->symbol);
jaddnum(item,"balance",dstr(balance));
if ( (KMDvalue= LP_KMDvalue(coin,balance)) != 0 )
{
jaddnum(item,"KMDvalue",dstr(KMDvalue));
sum += KMDvalue;
}
if ( coin->electrum != 0 && strcmp(address,coin->smartaddr) == 0 && strcmp(coin->symbol,"KMD") == 0 )
{
jaddnum(item,"zcredits",dstr(LP_myzcredits()));
//jadd(item,"zdebits",LP_myzdebits());
}
jaddi(array,item);
}
free_json(retjson);
}
}
else
{
if ( (balance= LP_RTsmartbalance(coin)) != 0 )
{
item = cJSON_CreateObject();
jaddstr(item,"coin",coin->symbol);
jaddnum(item,"balance",dstr(balance));
if ( (KMDvalue= LP_KMDvalue(coin,balance)) != 0 )
{
jaddnum(item,"KMDvalue",dstr(KMDvalue));
sum += KMDvalue;
}
if ( strcmp(coin->symbol,"KMD") == 0 )
{
jaddnum(item,"zcredits",dstr(LP_myzcredits()));
//jadd(item,"zdebits",LP_myzdebits());
}
jaddi(array,item);
}
}
}
if ( sum != 0 )
{
item = cJSON_CreateObject();
jaddstr(item,"coin","total");
jaddnum(item,"balance",dstr(sum));
jaddi(array,item);
}
return(array);
}
int32_t LP_unspents_array(struct iguana_info *coin,char *coinaddr,cJSON *array)
{
int32_t i,n,v,errs,height,count=0; uint64_t value,val; cJSON *item,*txobj; bits256 txid;

2
iguana/exchanges/auto_chipsbtc

@ -0,0 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"CHIPS\",\"rel\":\"BTC\",\"margin\":0.01,\"refbase\":\"chips\",\"refrel\":\"coinmarketcap\"}"

2
iguana/exchanges/auto_chipskmd

@ -0,0 +1,2 @@
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"CHIPS\",\"rel\":\"KMD\",\"margin\":0.01,\"refbase\":\"chips\",\"refrel\":\"coinmarketcap\"}"

3
iguana/exchanges/autofill

@ -1,3 +0,0 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autofill\",\"base\":\"KMD\",\"rel\":\"BTC\",\"price\":0.0005,\"relvolume\":0.1}"

3
iguana/exchanges/autotrade

@ -1,3 +0,0 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autotrade\",\"base\":\"REVS\",\"rel\":\"KMD\",\"relvolume\":1.01,\"price\":1.234}"

3
iguana/exchanges/balances

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"balances\"}"

4
iguana/exchanges/bots

@ -0,0 +1,4 @@
#!/bin/bash
source userpass
# this will only work for watchonly addresses that have been rescanned and with active coins
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RNdqHx26GWy9bk8MtmH1UiXjQcXE4RKK2P\",\"divisor\":1000000}"

4
iguana/exchanges/coins

File diff suppressed because one or more lines are too long

4
iguana/exchanges/coins.json

File diff suppressed because one or more lines are too long

4
iguana/exchanges/dex

@ -0,0 +1,4 @@
#!/bin/bash
source userpass
# this will only work for watchonly addresses that have been rescanned and with active coins
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RThtXup6Zo7LZAi8kRWgjAyi1s4u6U9Cpf\",\"divisor\":1000000}"

14
iguana/exchanges/enable

@ -1,5 +1,15 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"REVS\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"CHIPS\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"MNZ\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"KMD\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BTC\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"SUPERNET\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"CRYPTO\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"DEX\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BOTS\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"BET\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"HODL\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"MSHARK\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"MGW\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"PANGEA\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"enable\",\"coin\":\"JUMBLR\"}"

4
iguana/exchanges/fundvalue

@ -0,0 +1,4 @@
#!/bin/bash
source userpass
# this will only work for watchonly addresses that have been rescanned and with active coins
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":13000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":10000}, {\"coin\":\"syscoin\",\"balance\":20000000}, {\"coin\":\"waves\",\"balance\":700000}, {\"coin\":\"bitcoin\",\"balance\":625}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":375000}, {\"coin\":\"chips\",\"balance\":2577006 }, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }],\"divisor\":650000}"

15
iguana/exchanges/get_supernet

@ -0,0 +1,15 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"REVS\",\"rel\":\"KMD\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"CHIPS\",\"rel\":\"KMD\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"KMD\",\"rel\":\"BTC\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"SUPERNET\",\"rel\":\"KMD\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"CRYPTO\",\"rel\":\"KMD\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"DEX\",\"rel\":\"KMD\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"BOTS\",\"rel\":\"KMD\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"BET\",\"rel\":\"KMD\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"HODL\",\"rel\":\"KMD\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"MSHARK\",\"rel\":\"KMD\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"MGW\",\"rel\":\"KMD\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"PANGEA\",\"rel\":\"KMD\"}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"getprice\",\"base\":\"JUMBLR\",\"rel\":\"KMD\"}"

4
iguana/exchanges/hodl

@ -0,0 +1,4 @@
#!/bin/bash
source userpass
# this will only work for watchonly addresses that have been rescanned and with active coins
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RNcUaMUEFLxVwtTo7rgruhwYanGk1jTkeU\",\"holdings\":[{\"coin\":\"siacoin\",\"balance\":185000000,\"comment\":\"using siafunds equal to million siacoin\"}],\"divisor\":10000000}"

2
iguana/exchanges/install

@ -1,5 +1,5 @@
#!/bin/bash
cp dynamictrust getcoin kickstart tradesarray claim deposit10 deposit1 invreset sendrawtransaction processfiles stop millis mnzservers bot_buy bot_list bot_statuslist bot_pause bot_resume bot_sell bot_settings bot_status bot_stop guistats pubkeystats pendings coinswaps baserelswaps setpassphrase notarizations getrawtransaction parselog statsdisp m_js trust trusted setconfirms balance listunspent electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug buy sell bestfit orderbook client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices help inv setprice status ../dexscripts
cp install get_supernet trackbtc auto_chipskmd auto_chipsbtc pendingswaps fundvalue balances dynamictrust getcoin kickstart tradesarray claim deposit10 deposit1 invreset sendrawtransaction processfiles stop millis mnzservers bot_buy bot_list bot_statuslist bot_pause bot_resume bot_sell bot_settings bot_status bot_stop guistats pubkeystats pendings coinswaps baserelswaps setpassphrase notarizations getrawtransaction parselog statsdisp m_js trust trusted setconfirms balance listunspent electrum snapshot_balance snapshot_loop secretaddresses dividends snapshot goals goal portfolio autoprice deletemessages getmessages debug buy sell bestfit orderbook client run_osx client_osx run coins disable enable myprice myprices getcoins getpeers getpeersIP getprices help inv setprice status ../dexscripts
cp coins.json ..
cd ../dexscripts
#cp ../exchanges/passphrase ../exchanges/userpass .

4
iguana/exchanges/jumblr

@ -0,0 +1,4 @@
#!/bin/bash
source userpass
# this will only work for watchonly addresses that have been rescanned and with active coins
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RGhxXpXSSBTBm9EvNsXnTQczthMCxHX91t\",\"divisor\":1000000}"

943
iguana/exchanges/mm 17740.c

@ -0,0 +1,943 @@
/******************************************************************************
* 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. *
* *
******************************************************************************/
//
// main.c
// marketmaker
//
// Copyright © 2017 SuperNET. All rights reserved.
//
void PNACL_message(char *arg,...)
{
}
#define FROM_MARKETMAKER
#include <stdio.h>
#include <stdint.h>
#ifndef NATIVE_WINDOWS
#include "OS_portable.h"
#else
#include "../../crypto777/OS_portable.h"
#endif // !_WIN_32
uint32_t DOCKERFLAG;
#define MAX(a,b) ((a) > (b) ? (a) : (b))
char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *remoteaddr,uint16_t port);
#include "stats.c"
void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveask,double highbid,double lowask,double PAXPRICES[32]);
//defined(__APPLE__) ||
#ifdef FROM_JS // defined(WIN32) || defined(USE_STATIC_NANOMSG)
#include "../../crypto777/nanosrc/nn.h"
#include "../../crypto777/nanosrc/bus.h"
#include "../../crypto777/nanosrc/pubsub.h"
#include "../../crypto777/nanosrc/pipeline.h"
#include "../../crypto777/nanosrc/reqrep.h"
#include "../../crypto777/nanosrc/tcp.h"
#include "../../crypto777/nanosrc/pair.h"
#else
#if defined(WIN32) || defined(USE_STATIC_NANOMSG)
#include "../../crypto777/nanosrc/nn.h"
#include "../../crypto777/nanosrc/bus.h"
#include "../../crypto777/nanosrc/pubsub.h"
#include "../../crypto777/nanosrc/pipeline.h"
#include "../../crypto777/nanosrc/reqrep.h"
#include "../../crypto777/nanosrc/tcp.h"
#include "../../crypto777/nanosrc/pair.h"
#else
#include "/usr/local/include/nanomsg/nn.h"
#include "/usr/local/include/nanomsg/bus.h"
#include "/usr/local/include/nanomsg/pubsub.h"
#include "/usr/local/include/nanomsg/pipeline.h"
#include "/usr/local/include/nanomsg/reqrep.h"
#include "/usr/local/include/nanomsg/tcp.h"
#include "/usr/local/include/nanomsg/pair.h"
#endif
#endif
char DEX_baseaddr[64],DEX_reladdr[64];
struct mmpending_order
{
double price,volume;
int32_t dir;
uint32_t pending,completed,canceled,cancelstarted,reported;
cJSON *errorjson;
char exchange[16],base[65],rel[65],orderid[64];
} *Pending_orders;
int32_t Num_Pending;
#define IGUANA_URL "http://127.0.0.1:7778"
/*char CURRENCIES[][8] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", // major currencies
"CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", // end of currencies
};*/
double PAXPRICES[sizeof(CURRENCIES)/sizeof(*CURRENCIES)];
uint32_t PAXACTIVE;
char *DEX_swapstatus()
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"getswaplist\"}");
return(bitcoind_RPC(0,"InstantDEX",url,0,"getswaplist",postdata,0));
}
char *DEX_amlp(char *blocktrail)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"amlp\",\"blocktrail\":\"%s\"}",blocktrail);
return(bitcoind_RPC(0,"tradebot",url,0,"amlp",postdata,0));
}
char *DEX_openorders(char *exchange)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"openorders\",\"exchange\":\"%s\"}",exchange);
return(bitcoind_RPC(0,"InstantDEX",url,0,"openorders",postdata,0));
}
char *DEX_tradehistory(char *exchange)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"tradehistory\",\"exchange\":\"%s\"}",exchange);
return(bitcoind_RPC(0,"InstantDEX",url,0,"tradehistory",postdata,0));
}
char *DEX_orderstatus(char *exchange,char *orderid)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"orderstatus\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid);
return(bitcoind_RPC(0,"InstantDEX",url,0,"orderstatus",postdata,0));
}
char *DEX_cancelorder(char *exchange,char *orderid)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"cancelorder\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid);
return(bitcoind_RPC(0,"InstantDEX",url,0,"cancelorder",postdata,0));
}
char *DEX_balance(char *exchange,char *base,char *coinaddr)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
if ( strcmp(exchange,"DEX") == 0 )
{
sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"getbalance\",\"address\":\"%s\",\"symbol\":\"%s\"}",coinaddr,base);
return(bitcoind_RPC(0,"dex",url,0,"getbalance",postdata,0));
}
else
{
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"balance\",\"exchange\":\"%s\",\"base\":\"%s\"}",exchange,base);
return(bitcoind_RPC(0,"InstantDEX",url,0,"balance",postdata,0));
}
}
char *DEX_apikeypair(char *exchange,char *apikey,char *apisecret)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"apikeypair\",\"exchange\":\"%s\",\"apikey\":\"%s\",\"apisecret\":\"%s\"}",exchange,apikey,apisecret);
return(bitcoind_RPC(0,"InstantDEX",url,0,"apikeypair",postdata,0));
}
char *DEX_setuserid(char *exchange,char *userid,char *tradepassword)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"setuserid\",\"exchange\":\"%s\",\"userid\":\"%s\",\"tradepassword\":\"%s\"}",exchange,userid,tradepassword);
return(bitcoind_RPC(0,"InstantDEX",url,0,"setuserid",postdata,0));
}
char *DEX_trade(char *exchange,char *base,char *rel,int32_t dir,double price,double volume)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"%s\",\"exchange\":\"%s\",\"base\":\"%s\",\"rel\":\"%s\",\"price\":%.8f,\"volume\":%.8f,\"dotrade\":1}",dir>0?"buy":"sell",exchange,base,rel,price,volume);
//printf("DEX_trade.(%s)\n",postdata);
return(bitcoind_RPC(0,"InstantDEX",url,0,dir>0?"buy":"sell",postdata,0));
}
char *DEX_withdraw(char *exchange,char *base,char *destaddr,double amount)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"withdraw\",\"exchange\":\"%s\",\"destaddr\":\"%s\",\"amount\":%.8f}",exchange,destaddr,amount);
return(bitcoind_RPC(0,"InstantDEX",url,0,"withdraw",postdata,0));
}
char *iguana_walletpassphrase(char *passphrase,int32_t timeout)
{
char url[512],postdata[1024];
sprintf(url,"%s/coin=KMD&agent=bitcoinrpc&method=walletpassphrase?",IGUANA_URL);
sprintf(postdata,"[\"%s\", %d]",passphrase,timeout);
return(bitcoind_RPC(0,"",url,0,"walletpassphrase",postdata,0));
}
/*char *iguana_listunspent(char *coin,char *coinaddr)
{
char url[512],postdata[1024];
sprintf(url,"%s/coin=%s&agent=bitcoinrpc&method=listunspent?",IGUANA_URL,coin);
sprintf(postdata,"[\"%s\"]",coinaddr);
return(bitcoind_RPC(0,"",url,0,"listunspent",postdata));
}*/
/*char *issue_LP_intro(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers)
{
char url[512];
sprintf(url,"http://%s:%u/api/stats/intro?ipaddr=%s&port=%u&numpeers=%d",destip,destport,ipaddr,port,numpeers);
printf("(%s)\n",url);
return(issue_curl(url));
}*/
//
// http://127.0.0.1:7779/api/stats/getpeers
char *DEX_listunspent(char *coin,char *coinaddr)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"listunspent\",\"address\":\"%s\",\"symbol\":\"%s\",\"timeout\":60000}",coinaddr,coin);
return(bitcoind_RPC(0,"dex",url,0,"listunspent",postdata,0));
}
bits256 iguana_wif2privkey(char *wifstr)
{
char url[512],postdata[1024],*retstr,*privstr; bits256 privkey; cJSON *retjson;
memset(privkey.bytes,0,sizeof(privkey));
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"SuperNET\",\"method\":\"wif2priv\",\"wif\":\"%s\"}",wifstr);
if ( (retstr= bitcoind_RPC(0,"SuperNET",url,0,"wif2priv",postdata,0)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (privstr= jstr(retjson,"privkey")) != 0 )
{
if ( strlen(privstr) == 64 )
decode_hex(privkey.bytes,32,privstr);
}
free_json(retjson);
}
free(retstr);
}
return(privkey);
}
double bittrex_balance(char *base,char *coinaddr)
{
char *retstr; cJSON *retjson; double balance = 0.;
if ( (retstr= DEX_balance("bittrex",base,coinaddr)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
balance = jdouble(retjson,"balance");
free_json(retjson);
}
free(retstr);
}
return(balance);
}
double dex_balance(char *base,char *coinaddr)
{
char *retstr; cJSON *retjson; double balance = 0.;
if ( (retstr= DEX_balance("DEX",base,coinaddr)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
balance = jdouble(retjson,"balance");
free_json(retjson);
}
free(retstr);
}
return(balance);
}
int32_t komodo_baseid(char *base)
{
int32_t i;
for (i=0; i<sizeof(CURRENCIES)/sizeof(*CURRENCIES); i++)
if ( strcmp(base,CURRENCIES[i]) == 0 )
return(i);
return(-1);
}
cJSON *yahoo_allcurrencies()
{
char *retstr; cJSON *retjson = 0;
if ( (retstr= issue_curl("http://finance.yahoo.com/webservice/v1/symbols/allcurrencies/quote?format=json")) != 0 )
{
retjson = cJSON_Parse(retstr);
free(retstr);
}
return(retjson);
}
void _marketmaker_fiatupdate(int32_t baseid,double price)
{
PAXPRICES[baseid] = price * PAXPRICES[0];
printf("%.6f %s per USD, %.8f %s per KMD\n",price,CURRENCIES[baseid],PAXPRICES[baseid],CURRENCIES[baseid]);
}
uint32_t marketmaker_fiatupdate(cJSON *fiatjson)
{
int32_t i,n,baseid; cJSON *item,*array; double price; char *name; uint64_t mask = 0;
fiatjson = jobj(fiatjson,"list");
if ( fiatjson != 0 && (array= jarray(&n,fiatjson,"resources")) > 0 )
{
for (i=0; i<n; i++)
{
/*
"resource" : {
"classname" : "Quote",
"fields" : {
"name" : "USD/BRX",
"price" : "3.063200",
"symbol" : "BRX=X",
"ts" : "1487866204",
"type" : "currency",
"utctime" : "2017-02-23T16:10:04+0000",
"volume" : "0"
}
*/
item = jitem(array,i);
if ( (item= jobj(item,"resource")) != 0 )
item = jobj(item,"fields");
if ( item != 0 )
{
price = jdouble(item,"price");
if ( price > SMALLVAL && (name= jstr(item,"name")) != 0 && strncmp(name,"USD/",4) == 0 )
{
if ( (baseid= komodo_baseid(name+4)) >= 0 && baseid < 32 )
{
if ( ((1LL << baseid) & mask) == 0 )
{
_marketmaker_fiatupdate(baseid,price);
mask |= (1LL << baseid);
} else if ( fabs(price*PAXPRICES[0] - PAXPRICES[baseid]) > SMALLVAL )
printf("DUPLICATE PRICE? %s %.8f vs %.8f\n",name+4,price*PAXPRICES[0],PAXPRICES[baseid]);
}
}
}
}
}
printf("pax mask.%x\n",(uint32_t)mask);
return((uint32_t)mask);
}
void marketmaker_cancel(struct mmpending_order *ptr)
{
char *retstr; cJSON *retjson;
if ( ptr->pending != 0 && ptr->cancelstarted == 0 )
{
ptr->cancelstarted = (uint32_t)time(NULL);
if ( (retstr= DEX_cancelorder(ptr->exchange,ptr->orderid)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
printf("cancel %s (%s/%s) %.8f vol %.8f dir.%d -> (%s)\n",ptr->exchange,ptr->base,ptr->rel,ptr->price,ptr->volume,ptr->dir,jprint(retjson,0));
free_json(retjson);
ptr->pending = 0;
ptr->canceled = (uint32_t)time(NULL);
}
free(retstr);
}
}
}
void marketmaker_queue(char *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *retjson)
{
struct mmpending_order *ptr; char *orderid;
//DEX_trade.({"success":true,"message":"","result":{"uuid":"d5faa9e4-660d-436f-a257-2c6a40442d8c"},"tag":"11271578410079391025"}
if ( is_cJSON_True(jobj(retjson,"success")) != 0 && jobj(retjson,"result") != 0 )
retjson = jobj(retjson,"result");
printf("QUEUE.%s %s/%s dir.%d %.8f %.6f (%s)\n",exchange,base,rel,dir,price,volume,jprint(retjson,0));
Pending_orders = realloc(Pending_orders,(1 + Num_Pending) * sizeof(*Pending_orders));
ptr = &Pending_orders[Num_Pending++];
memset(ptr,0,sizeof(*ptr));
ptr->price = price;
ptr->volume = volume;
ptr->dir = dir;
ptr->pending = (uint32_t)time(NULL);
strcpy(ptr->exchange,exchange);
strcpy(ptr->base,base);
strcpy(ptr->rel,rel);
if ( (orderid= jstr(retjson,"OrderUuid")) != 0 || (orderid= jstr(retjson,"uuid")) != 0 )
strcpy(ptr->orderid,orderid);
else strcpy(ptr->orderid,"0");
}
void marketmaker_pendingupdate(char *exchange,char *base,char *rel)
{
char *retstr; cJSON *retjson,*obj; int32_t i; struct mmpending_order *ptr;
for (i=0; i<Num_Pending; i++)
{
ptr = &Pending_orders[i];
if ( strcmp(exchange,ptr->exchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 )
continue;
if ( ptr->completed == 0 && (retstr= DEX_orderstatus(exchange,ptr->orderid)) != 0 )
{
//printf("%s status.(%s)\n",ptr->orderid,retstr);
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
obj = jobj(retjson,"result");
if ( is_cJSON_Array(obj) != 0 )
obj = jitem(retjson,0);
if ( jdouble(obj,"QuantityRemaining") == 0. || is_cJSON_True(jobj(obj,"IsOpen")) == 0 )
{
//{"Uuid":null,"OrderUuid":"e7b0789c-0c4e-413b-a768-3d5734d9cbe5","Exchange":"BTC-KMD","OrderType":"LIMIT_SELL","Quantity":877.77700000,"QuantityRemaining":462.50512234,"Limit":0.00011770,"CommissionPaid":0.00012219,"Price":0.04887750,"PricePerUnit":0.00011769,"Opened":"2017-02-20T13:16:22.29","Closed":null,"CancelInitiated":false,"ImmediateOrCancel":false,"IsConditional":false,"Condition":"NONE","ConditionTarget":null} printf("uuid.(%s) finished.(%s)\n",ptr->orderid,jprint(retjson,0));
ptr->completed = (uint32_t)time(NULL);
ptr->pending = 0;
}
free_json(retjson);
}
free(retstr);
}
}
}
void marketmaker_pendinginit(char *exchange,char *base,char *rel)
{
char *retstr,*orderid,*pairstr,relbase[65]; cJSON *retjson,*array,*item; int32_t i,j,n,dir; struct mmpending_order *ptr;
sprintf(relbase,"%s-%s",rel,base);
if ( (retstr= DEX_openorders(exchange)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
//printf("%s\n",jprint(retjson,0));
if ( is_cJSON_True(jobj(retjson,"success")) != 0 && (array= jarray(&n,retjson,"result")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( (pairstr= jstr(item,"Exchange")) == 0 )
continue;
if ( strcmp(pairstr,relbase) != 0 )
{
printf("skip %s when %s\n",pairstr,relbase);
continue;
}
//printf("(%s)\n",jprint(item,0));
//{"success":true,"message":"","result":[{"Uuid":null,"OrderUuid":"81ad3e37-65d4-4fee-9c29-03b050f5192b","Exchange":"BTC-KMD","OrderType":"LIMIT_BUY","Quantity":885.19934578,"QuantityRemaining":885.19934578,"Limit":0.00011184,"CommissionPaid":0,"Price":0,"PricePerUnit":null,"Opened":"2017-02-19T19:14:02.94","Closed":null,"CancelInitiated":false,"ImmediateOrCancel":false,"IsConditional":false,"Condition":"NONE","ConditionTarget":null}],"tag":"10056789044100011414"}
if ( (orderid= jstr(item,"OrderUuid")) != 0 && is_cJSON_Null(jobj(item,"Closed")) != 0 && is_cJSON_False(jobj(item,"CancelInitiated")) != 0 )
{
for (j=0; j<Num_Pending; j++)
{
ptr = &Pending_orders[j];
if ( strcmp(exchange,ptr->exchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 )
continue;
if ( strcmp(ptr->orderid,orderid) == 0 )
{
ptr->pending = (uint32_t)time(NULL);
ptr->completed = 0;
printf("%s pending\n",orderid);
break;
}
}
if ( j == Num_Pending )
{
if ( jstr(item,"OrderType") != 0 )
{
if ( strcmp(jstr(item,"OrderType"),"LIMIT_BUY") == 0 )
dir = 1;
else if ( strcmp(jstr(item,"OrderType"),"LIMIT_SELL") == 0 )
dir = -1;
else dir = 0;
if ( dir != 0 )
marketmaker_queue(exchange,base,rel,dir,jdouble(item,"Limit"),jdouble(item,"QuantityRemaining"),item);
else printf("no dir (%s) (%s)\n",jprint(item,0),jstr(item,"OrderType"));
}
}
}
}
}
free_json(retjson);
}
free(retstr);
}
}
double marketmaker_filled(char *exchange,char *base,char *rel,double *buyvolp,double *sellvolp,double *pendingbidsp,double *pendingasksp)
{
double pricesum = 0.,volsum = 0.; struct mmpending_order *ptr; int32_t i;
*pendingbidsp = *pendingasksp = 0.;
for (i=0; i<Num_Pending; i++)
{
ptr = &Pending_orders[i];
if ( strcmp(exchange,ptr->exchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 )
continue;
if ( ptr->completed != 0 )
{
if ( ptr->reported == 0 )
{
if ( ptr->dir > 0 )
(*buyvolp) += ptr->volume;
else if ( ptr->dir < 0 )
(*sellvolp) += ptr->volume;
pricesum += ptr->volume * ptr->price;
volsum += ptr->volume;
ptr->reported = (uint32_t)time(NULL);
printf("REPORT dir.%d vol %.8f\n",ptr->dir,ptr->volume);
}
}
else if ( ptr->pending != 0 ) // alternative is error or cancelled
{
if ( ptr->dir > 0 )
(*pendingbidsp) += ptr->volume;
else if ( ptr->dir < 0 )
(*pendingasksp) += ptr->volume;
}
}
if ( volsum != 0. )
pricesum /= volsum;
return(pricesum);
}
int32_t marketmaker_prune(char *exchange,char *base,char *rel,int32_t polarity,double bid,double ask,double separation)
{
int32_t i,n = 0; struct mmpending_order *ptr;
for (i=0; i<Num_Pending; i++)
{
ptr = &Pending_orders[i];
if ( strcmp(exchange,ptr->exchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 )
continue;
if ( ptr->pending != 0 && ptr->cancelstarted == 0 )
{
if ( polarity != 0 )
{
if ( ((ptr->dir*polarity > 0 && ptr->price < bid-separation) || (ptr->dir*polarity < 0 && ptr->price > ask+separation)) )
{
printf("polarity.%d dir.%d price.%f bid.%f ask.%f\n",polarity,ptr->dir,ptr->price,bid,ask);
marketmaker_cancel(ptr), n++;
}
}
/*else
{,*prunebid=0,*pruneask=0; double lowbid=0.,highask=0.
if ( ptr->dir > 0 && (lowbid == 0. || ptr->price < lowbid) )
{
lowbid = ptr->price;
prunebid = ptr;
}
else if ( ptr->dir < 0 && (highask == 0. || ptr->price > highask) )
{
highask = ptr->price;
pruneask = ptr;
}
}*/
}
}
/*if ( polarity == 0 )
{
if ( prunebid != 0 && fabs(prunebid->price - bid) > separation )
marketmaker_cancel(prunebid), n++;
if ( pruneask != 0 && fabs(pruneask->price - ask) > separation )
marketmaker_cancel(pruneask), n++;
}*/
return(n);
}
void marketmaker_volumeset(double *bidincrp,double *askincrp,double incr,double buyvol,double pendingbids,double sellvol,double pendingasks,double maxexposure)
{
*bidincrp = *askincrp = incr;
//if ( pendingbids >= pendingasks+maxexposure )
// *bidincrp = 0.;
//else if ( pendingasks >= pendingbids+maxexposure )
// *askincrp = 0.;
if ( *bidincrp > 0. && pendingbids + *bidincrp > maxexposure )
*bidincrp = (maxexposure - *bidincrp);
if ( *askincrp > 0. && pendingasks + *askincrp > maxexposure )
*askincrp = (maxexposure - *askincrp);
if ( *bidincrp < 0. )
*bidincrp = 0.;
if ( *askincrp < 0. )
*askincrp = 0.;
}
int32_t marketmaker_spread(char *exchange,char *base,char *rel,double bid,double bidvol,double ask,double askvol,double separation)
{
int32_t nearflags[2],i,n = 0; struct mmpending_order *ptr; cJSON *retjson,*vals; char *retstr,postdata[1024],url[128]; double vol,spread_ratio;
memset(nearflags,0,sizeof(nearflags));
if ( strcmp("DEX",exchange) != 0 )
{
for (i=0; i<Num_Pending; i++)
{
ptr = &Pending_orders[i];
if ( strcmp(exchange,ptr->exchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 )
continue;
if ( ptr->pending != 0 && ptr->cancelstarted == 0 )
{
if ( bid > SMALLVAL && bidvol > SMALLVAL && ptr->dir > 0 && fabs(bid - ptr->price) < separation )
{
//printf("bid %.8f near %.8f\n",bid,ptr->price);
nearflags[0]++;
}
if ( ask > SMALLVAL && askvol > SMALLVAL && ptr->dir < 0 && fabs(ask - ptr->price) < separation )
{
//printf("%.8f near %.8f\n",ask,ptr->price);
nearflags[1]++;
}
}
}
}
//printf("spread.%s (%.8f %.6f) (%.8f %.6f)\n",exchange,bid,bidvol,ask,askvol);
if ( bid > SMALLVAL && bidvol > SMALLVAL && nearflags[0] == 0 )
{
if ( strcmp("DEX",exchange) == 0 && strcmp(base,"KMD") == 0 && strcmp(rel,"BTC") == 0 )
{
if ( ask > SMALLVAL && askvol > SMALLVAL )
{
/*li.profit = jdouble(vals,"profit");
li.refprice = jdouble(vals,"refprice");
li.bid = jdouble(vals,"bid");
li.ask = jdouble(vals,"ask");
if ( (li.minvol= jdouble(vals,"minvol")) <= 0. )
li.minvol = (strcmp("BTC",base) == 0) ? 0.0001 : 0.001;
if ( (li.maxvol= jdouble(vals,"maxvol")) < li.minvol )
li.maxvol = li.minvol;*/
//curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"MVP\",\"vals\":{\"rel\":\"USD\",\"bid\":0.09,\"ask\":0.11,\"maxvol\":100}}"
vals = cJSON_CreateObject();
jaddstr(vals,"rel","BTC");
jaddnum(vals,"bid",bid);
jaddnum(vals,"ask",ask);
vol = bidvol > askvol ? askvol : bidvol;
jaddnum(vals,"maxvol",vol);
jaddnum(vals,"minvol",vol*0.1 > 100 ? 100 : vol * 0.1);
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}",base,jprint(vals,1));
//printf("(%s)\n",postdata);
if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata,0)) != 0 )
{
//printf("(%s) -> (%s)\n",postdata,retstr);
free(retstr);
}
spread_ratio = .5 * ((ask - bid) / (bid + ask));
for (i=0; i<sizeof(CURRENCIES)/sizeof(*CURRENCIES); i++)
{
if ( (PAXACTIVE & (1<<i)) == 0 )
continue;
if ( PAXPRICES[i] > SMALLVAL )
{
vals = cJSON_CreateObject();
jaddstr(vals,"rel",CURRENCIES[i]);
jaddnum(vals,"bid",PAXPRICES[i] * (1. - spread_ratio));
jaddnum(vals,"ask",PAXPRICES[i] * (1. + spread_ratio));
jaddnum(vals,"maxvol",vol * PAXPRICES[i]);
jaddnum(vals,"minvol",MAX(1,(int32_t)(vol * 0.01 * PAXPRICES[i])));
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}","KMD",jprint(vals,1));
if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata,0)) != 0 )
{
//printf("(%s) -> (%s)\n",postdata,retstr);
free(retstr);
}
}
//break;
}
} else printf("unsupported ask only for DEX %s/%s\n",base,rel);
}
else if ( (retstr= DEX_trade(exchange,base,rel,1,bid,bidvol)) != 0 )
{
//printf("DEX_trade.(%s)\n",retstr);
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
marketmaker_queue(exchange,base,rel,1,bid,bidvol,retjson);
free_json(retjson);
}
free(retstr);
} //else printf("skip bid %s %.8f vol %f\n",exchange,bid,bidvol);
}
if ( ask > SMALLVAL && askvol > SMALLVAL && nearflags[1] == 0 && strcmp("DEX",exchange) != 0 )
{
if ( (retstr= DEX_trade(exchange,base,rel,-1,ask,askvol)) != 0 )
{
//printf("DEX_trade.(%s)\n",retstr);
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
marketmaker_queue(exchange,base,rel,-1,ask,askvol,retjson);
free_json(retjson);
}
free(retstr);
}
} //else printf("skip ask %s %.8f vol %f\n",exchange,bid,bidvol);
return(n);
}
double marketmaker_updateprice(char *name,char *base,char *rel,double theoretical,double *incrp)
{
static uint32_t counter;
cJSON *fiatjson; double USD_average=0.,usdprice=0.,CMC_average=0.,avebid=0.,aveask=0.,val,changes[3],highbid=0.,lowask=0.;
if ( (val= get_theoretical(&avebid,&aveask,&highbid,&lowask,&CMC_average,changes,name,base,rel,&USD_average)) != 0. )
{
if ( theoretical == 0. )
{
theoretical = val;
if ( *incrp > 2 )
{
*incrp = (int32_t)*incrp;
*incrp += 0.777;
}
} else theoretical = (theoretical + val) * 0.5;
if ( (counter++ % 12) == 0 )
{
if ( USD_average > SMALLVAL && CMC_average > SMALLVAL && theoretical > SMALLVAL )
{
usdprice = USD_average * (theoretical / CMC_average);
printf("USD %.4f <- (%.6f * (%.8f / %.8f))\n",usdprice,USD_average,theoretical,CMC_average);
PAXPRICES[0] = usdprice;
if ( (fiatjson= yahoo_allcurrencies()) != 0 )
{
marketmaker_fiatupdate(fiatjson);
free_json(fiatjson);
}
}
}
LP_priceupdate(base,rel,theoretical,avebid,aveask,highbid,lowask,PAXPRICES);
}
return(theoretical);
}
void marketmaker(double minask,double maxbid,char *baseaddr,char *reladdr,double start_BASE,double start_REL,double profitmargin,double maxexposure,double ratioincr,char *exchange,char *name,char *base,char *rel)
{
char *retstr; double bid,ask,start_DEXbase,start_DEXrel,DEX_base = 0.,DEX_rel = 0.,balance_base=0.,balance_rel=0.,mmbid,mmask,aveprice,incr,pendingbids,pendingasks,buyvol,sellvol,bidincr,askincr,filledprice,avebid=0.,aveask=0.,highbid=0.,lowask=0.,theoretical = 0.; uint32_t lasttime = 0;
incr = maxexposure * ratioincr;
buyvol = sellvol = 0.;
start_DEXbase = dex_balance(base,baseaddr);
start_DEXrel = dex_balance(rel,reladdr);
while ( 1 )
{
if ( time(NULL) > lasttime+60 )
{
if ( (theoretical= marketmaker_updateprice(name,base,rel,theoretical,&incr)) != 0. )
{
if ( lasttime == 0 )
maxexposure /= theoretical;
}
if ( strcmp(exchange,"bittrex") == 0 )
{
balance_base = bittrex_balance(base,"");
balance_rel = bittrex_balance(rel,"");
DEX_base = dex_balance(base,baseaddr);
DEX_rel = dex_balance(rel,reladdr);
} else printf("add support for %s balance\n",exchange);
lasttime = (uint32_t)time(NULL);
}
marketmaker_pendingupdate(exchange,base,rel);
if ( theoretical > SMALLVAL && avebid > SMALLVAL && aveask > SMALLVAL )
{
aveprice = (avebid + aveask) * 0.5;
// if order is filled, theoretical <- filled (theoretical + price)/2
if ( (filledprice= marketmaker_filled(exchange,base,rel,&buyvol,&sellvol,&pendingbids,&pendingasks)) != 0. )
theoretical = (theoretical + filledprice) * 0.5;
buyvol = sellvol = 0;
if ( (balance_base + DEX_base) < (start_BASE + start_DEXbase) )
sellvol += ((start_BASE + start_DEXbase) - (balance_base + DEX_base));
else buyvol += ((balance_base + DEX_base) - (start_BASE + start_DEXbase));
if ( (balance_rel + DEX_rel) < (start_REL + start_DEXrel) )
buyvol += ((start_REL + start_DEXrel) - (balance_rel + DEX_rel)) / theoretical;
else sellvol += ((balance_rel + DEX_rel) - (start_REL + start_DEXrel)) / theoretical;
mmbid = theoretical - theoretical*profitmargin;
mmask = theoretical + theoretical*profitmargin;
// if any existing order exceeds double margin distance, cancel
marketmaker_prune(exchange,base,rel,1,mmbid - theoretical*profitmargin,mmask + theoretical*profitmargin,0.);
// if new prices crosses existing order, cancel old order first
marketmaker_prune(exchange,base,rel,-1,mmbid,mmask,0.);
//printf("(%.8f %.8f) ",mmbid,mmask);
if ( (1) )
{
if ( mmbid >= lowask || (maxbid > SMALLVAL && mmbid > maxbid) ) //mmbid < highbid ||
{
printf("clear mmbid %.8f lowask %.8f maxbid %.8f\n",mmbid,lowask,maxbid);
mmbid = 0.;
}
if ( mmask <= highbid || (minask > SMALLVAL && mmask < minask) ) // mmask > lowask ||
mmask = 0.;
}
marketmaker_volumeset(&bidincr,&askincr,incr,buyvol,pendingbids,sellvol,pendingasks,maxexposure);
printf("AVE.(%.8f %.8f) hbla %.8f %.8f bid %.8f ask %.8f theory %.8f buys.(%.6f %.6f) sells.(%.6f %.6f) incr.(%.6f %.6f) balances.(%.8f + %.8f, %.8f + %.8f) test %f\n",avebid,aveask,highbid,lowask,mmbid,mmask,theoretical,buyvol,pendingbids,sellvol,pendingasks,bidincr,askincr,balance_base,DEX_base,balance_rel,DEX_rel,(aveask - avebid)/aveprice);
if ( (retstr= DEX_swapstatus()) != 0 )
printf("%s\n",retstr), free(retstr);
printf("%s %s %s, %s %s %s\n",base,DEX_baseaddr,DEX_balance("DEX",base,DEX_baseaddr),rel,DEX_reladdr,DEX_balance("DEX",rel,DEX_reladdr));
if ( (aveask - avebid)/aveprice > profitmargin )
bid = highbid * (1 - profitmargin), ask = lowask * (1 + profitmargin);
else bid = avebid - profitmargin*aveprice, ask = avebid + profitmargin*aveprice;
marketmaker_spread("DEX",base,rel,bid,incr,ask,incr,profitmargin*aveprice*0.5);
if ( (pendingbids + buyvol) > (pendingasks + sellvol) && (pendingbids + buyvol) > bidincr )
{
bidincr *= ((double)(pendingasks + sellvol) / ((pendingbids + buyvol) + (pendingasks + sellvol)));
printf("bidincr %f buy.(%f + %f) sell.(%f + %f)\n",bidincr,pendingbids,buyvol,pendingasks,sellvol);
if ( bidincr < 0.1*incr )
bidincr = 0.1*incr;
if ( bidincr > 1. )
bidincr = (int32_t)bidincr + 0.777;
}
if ( (pendingbids + buyvol) < (pendingasks + sellvol) && (pendingasks + sellvol) > askincr )
{
askincr *= (double)(pendingbids + buyvol) / ((pendingbids + buyvol) + (pendingasks + sellvol));
if ( askincr < 0.1*incr )
askincr = 0.1*incr;
if ( askincr > 1. )
askincr = (int32_t)askincr + 0.777;
}
//printf("mmbid %.8f %.6f, mmask %.8f %.6f\n",mmbid,bidincr,mmask,askincr);
marketmaker_spread(exchange,base,rel,mmbid,bidincr,mmask,askincr,profitmargin*aveprice*0.5);
sleep(60);
}
}
}
#include "LP_nativeDEX.c"
void LP_main(void *ptr)
{
char *passphrase; double profitmargin; uint16_t port; cJSON *argjson = ptr;
if ( (passphrase= jstr(argjson,"passphrase")) != 0 )
{
profitmargin = jdouble(argjson,"profitmargin");
LP_profitratio += profitmargin;
if ( (port= juint(argjson,"rpcport")) < 1000 )
port = LP_RPCPORT;
LPinit(port,LP_RPCPORT+10,LP_RPCPORT+20,LP_RPCPORT+30,passphrase,jint(argjson,"client"),jstr(argjson,"userhome"),argjson);
}
}
int main(int argc, const char * argv[])
{
char dirname[512],*base,*rel,*name,*exchange,*apikey,*apisecret,*blocktrail,*retstr,*baseaddr,*reladdr,*passphrase;
double profitmargin,maxexposure,incrratio,start_rel,start_base,minask,maxbid,incr;
cJSON *retjson,*loginjson; int32_t i;
OS_init();
if ( strstr(argv[0],"btc2kmd") != 0 && argv[1] != 0 )
{
uint8_t addrtype,rmd160[20],rmd160b[20]; char coinaddr[64],coinaddr2[64];
bitcoin_addr2rmd160(0,&addrtype,rmd160,(char *)argv[1]);
if ( addrtype == 0 )
{
bitcoin_address(coinaddr,0,60,rmd160,20);
bitcoin_addr2rmd160(0,&addrtype,rmd160b,coinaddr);
bitcoin_address(coinaddr2,0,0,rmd160b,20);
}
else if ( addrtype == 60 )
{
bitcoin_address(coinaddr,0,0,rmd160,20);
bitcoin_addr2rmd160(0,&addrtype,rmd160b,coinaddr);
bitcoin_address(coinaddr2,0,60,rmd160b,20);
}
printf("(%s) -> %s -> %s\n",(char *)argv[1],coinaddr,coinaddr2);
if ( strcmp((char *)argv[1],coinaddr2) != 0 )
printf("ERROR\n");
exit(0);
}
sprintf(dirname,"%s",GLOBAL_DBDIR), OS_ensure_directory(dirname);
sprintf(dirname,"%s/SWAPS",GLOBAL_DBDIR), OS_ensure_directory(dirname);
sprintf(dirname,"%s/PRICES",GLOBAL_DBDIR), OS_ensure_directory(dirname);
sprintf(dirname,"%s/UNSPENTS",GLOBAL_DBDIR), OS_ensure_directory(dirname);
#ifdef FROM_JS
argc = 2;
retjson = cJSON_Parse("{\"client\":1,\"passphrase\":\"test\"}");
printf("calling LP_main(%s)\n",jprint(retjson,0));
LP_main(retjson);
emscripten_set_main_loop(LP_fromjs_iter,1,0);
#else
if ( argc == 1 )
{
LP_NXT_redeems();
sleep(3);
return(0);
}
if ( argc > 1 && (retjson= cJSON_Parse(argv[1])) != 0 )
{
if ( jint(retjson,"docker") == 1 )
DOCKERFLAG = 1;
else if ( jstr(retjson,"docker") != 0 )
DOCKERFLAG = (uint32_t)calc_ipbits(jstr(retjson,"docker"));
if ( (passphrase= jstr(retjson,"passphrase")) == 0 )
jaddstr(retjson,"passphrase","test");
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_main,(void *)retjson) != 0 )
{
printf("error launching LP_main (%s)\n",jprint(retjson,0));
exit(-1);
} //else printf("(%s) launched.(%s)\n",argv[1],passphrase);
incr = 100.;
while ( (1) )
sleep(100000);
profitmargin = jdouble(retjson,"profitmargin");
minask = jdouble(retjson,"minask");
maxbid = jdouble(retjson,"maxbid");
maxexposure = jdouble(retjson,"maxexposure");
incrratio = jdouble(retjson,"lotratio");
start_base = jdouble(retjson,"start_base");
start_rel = jdouble(retjson,"start_rel");
apikey = jstr(retjson,"apikey");
apisecret = jstr(retjson,"apisecret");
base = jstr(retjson,"base");
name = jstr(retjson,"name");
rel = jstr(retjson,"rel");
blocktrail = jstr(retjson,"blocktrail");
exchange = jstr(retjson,"exchange");
PAXACTIVE = juint(retjson,"paxactive");
if ( profitmargin < 0. || maxexposure <= 0. || incrratio <= 0. || apikey == 0 || apisecret == 0 || base == 0 || name == 0 || rel == 0 || exchange == 0 || blocktrail == 0 )
{
printf("illegal parameter (%s)\n",jprint(retjson,0));
exit(-1);
}
if ( (retstr= iguana_walletpassphrase(passphrase,999999)) != 0 )
{
printf("(%s/%s) login.(%s)\n",base,rel,retstr);
if ( (loginjson= cJSON_Parse(retstr)) != 0 )
{
if ( PAXACTIVE != 0 )
{
for (i=0; i<32; i++)
{
if ( ((1<<i) & PAXACTIVE) != 0 )
{
if ( jstr(loginjson,CURRENCIES[i]) == 0 )
PAXACTIVE &= ~(1 << i);
}
}
}
if ( (baseaddr= jstr(loginjson,base)) == 0 || (reladdr= jstr(loginjson,rel)) == 0 )
{
printf("Need to activate both %s and %s before marketmaker\n",base,rel);
exit(1);
}
printf("%s\n",DEX_apikeypair(exchange,apikey,apisecret));
marketmaker_pendinginit(exchange,base,rel);
if ( baseaddr != 0 && reladdr != 0 )
{
printf("PAXACTIVE.%08x %s\n",PAXACTIVE,DEX_amlp(blocktrail));
strncpy(DEX_baseaddr,baseaddr,sizeof(DEX_baseaddr)-1);
strncpy(DEX_reladdr,reladdr,sizeof(DEX_reladdr)-1);
printf("%s.%s %s\n",base,baseaddr,DEX_balance("DEX",base,baseaddr));
printf("%s.%s %s\n",rel,reladdr,DEX_balance("DEX",rel,reladdr));
// initialize state using DEX_pendingorders, etc.
marketmaker(minask,maxbid,baseaddr,reladdr,start_base,start_rel,profitmargin,maxexposure,incrratio,exchange,name,base,rel);
}
free_json(loginjson);
} else printf("ERROR parsing.(%s)\n",retstr);
free(retstr);
}
free_json(retjson);
}
#endif
return 0;
}

928
iguana/exchanges/mm.c

@ -34,6 +34,7 @@ void PNACL_message(char *arg,...)
#include "../../crypto777/OS_portable.h"
#endif // !_WIN_32
uint32_t DOCKERFLAG;
#define MAX(a,b) ((a) > (b) ? (a) : (b))
char *stats_JSON(void *ctx,char *myipaddr,int32_t pubsock,cJSON *argjson,char *remoteaddr,uint16_t port);
#include "stats.c"
@ -68,799 +69,8 @@ void LP_priceupdate(char *base,char *rel,double price,double avebid,double aveas
#endif
#endif
char DEX_baseaddr[64],DEX_reladdr[64];
struct mmpending_order
{
double price,volume;
int32_t dir;
uint32_t pending,completed,canceled,cancelstarted,reported;
cJSON *errorjson;
char exchange[16],base[65],rel[65],orderid[64];
} *Pending_orders;
int32_t Num_Pending;
#define IGUANA_URL "http://127.0.0.1:7778"
/*char CURRENCIES[][8] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD", // major currencies
"CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK", // end of currencies
};*/
double PAXPRICES[sizeof(CURRENCIES)/sizeof(*CURRENCIES)];
uint32_t PAXACTIVE;
char *DEX_swapstatus()
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"getswaplist\"}");
return(bitcoind_RPC(0,"InstantDEX",url,0,"getswaplist",postdata,0));
}
char *DEX_amlp(char *blocktrail)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"amlp\",\"blocktrail\":\"%s\"}",blocktrail);
return(bitcoind_RPC(0,"tradebot",url,0,"amlp",postdata,0));
}
char *DEX_openorders(char *exchange)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"openorders\",\"exchange\":\"%s\"}",exchange);
return(bitcoind_RPC(0,"InstantDEX",url,0,"openorders",postdata,0));
}
char *DEX_tradehistory(char *exchange)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"tradehistory\",\"exchange\":\"%s\"}",exchange);
return(bitcoind_RPC(0,"InstantDEX",url,0,"tradehistory",postdata,0));
}
char *DEX_orderstatus(char *exchange,char *orderid)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"orderstatus\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid);
return(bitcoind_RPC(0,"InstantDEX",url,0,"orderstatus",postdata,0));
}
char *DEX_cancelorder(char *exchange,char *orderid)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"cancelorder\",\"exchange\":\"%s\",\"orderid\":\"%s\"}",exchange,orderid);
return(bitcoind_RPC(0,"InstantDEX",url,0,"cancelorder",postdata,0));
}
char *DEX_balance(char *exchange,char *base,char *coinaddr)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
if ( strcmp(exchange,"DEX") == 0 )
{
sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"getbalance\",\"address\":\"%s\",\"symbol\":\"%s\"}",coinaddr,base);
return(bitcoind_RPC(0,"dex",url,0,"getbalance",postdata,0));
}
else
{
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"balance\",\"exchange\":\"%s\",\"base\":\"%s\"}",exchange,base);
return(bitcoind_RPC(0,"InstantDEX",url,0,"balance",postdata,0));
}
}
char *DEX_apikeypair(char *exchange,char *apikey,char *apisecret)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"apikeypair\",\"exchange\":\"%s\",\"apikey\":\"%s\",\"apisecret\":\"%s\"}",exchange,apikey,apisecret);
return(bitcoind_RPC(0,"InstantDEX",url,0,"apikeypair",postdata,0));
}
char *DEX_setuserid(char *exchange,char *userid,char *tradepassword)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"setuserid\",\"exchange\":\"%s\",\"userid\":\"%s\",\"tradepassword\":\"%s\"}",exchange,userid,tradepassword);
return(bitcoind_RPC(0,"InstantDEX",url,0,"setuserid",postdata,0));
}
char *DEX_trade(char *exchange,char *base,char *rel,int32_t dir,double price,double volume)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"%s\",\"exchange\":\"%s\",\"base\":\"%s\",\"rel\":\"%s\",\"price\":%.8f,\"volume\":%.8f,\"dotrade\":1}",dir>0?"buy":"sell",exchange,base,rel,price,volume);
//printf("DEX_trade.(%s)\n",postdata);
return(bitcoind_RPC(0,"InstantDEX",url,0,dir>0?"buy":"sell",postdata,0));
}
char *DEX_withdraw(char *exchange,char *base,char *destaddr,double amount)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"InstantDEX\",\"method\":\"withdraw\",\"exchange\":\"%s\",\"destaddr\":\"%s\",\"amount\":%.8f}",exchange,destaddr,amount);
return(bitcoind_RPC(0,"InstantDEX",url,0,"withdraw",postdata,0));
}
char *iguana_walletpassphrase(char *passphrase,int32_t timeout)
{
char url[512],postdata[1024];
sprintf(url,"%s/coin=KMD&agent=bitcoinrpc&method=walletpassphrase?",IGUANA_URL);
sprintf(postdata,"[\"%s\", %d]",passphrase,timeout);
return(bitcoind_RPC(0,"",url,0,"walletpassphrase",postdata,0));
}
/*char *iguana_listunspent(char *coin,char *coinaddr)
{
char url[512],postdata[1024];
sprintf(url,"%s/coin=%s&agent=bitcoinrpc&method=listunspent?",IGUANA_URL,coin);
sprintf(postdata,"[\"%s\"]",coinaddr);
return(bitcoind_RPC(0,"",url,0,"listunspent",postdata));
}*/
/*char *issue_LP_intro(char *destip,uint16_t destport,char *ipaddr,uint16_t port,int32_t numpeers)
{
char url[512];
sprintf(url,"http://%s:%u/api/stats/intro?ipaddr=%s&port=%u&numpeers=%d",destip,destport,ipaddr,port,numpeers);
printf("(%s)\n",url);
return(issue_curl(url));
}*/
//
// http://127.0.0.1:7779/api/stats/getpeers
char *DEX_listunspent(char *coin,char *coinaddr)
{
char url[512],postdata[1024];
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"dex\",\"method\":\"listunspent\",\"address\":\"%s\",\"symbol\":\"%s\",\"timeout\":60000}",coinaddr,coin);
return(bitcoind_RPC(0,"dex",url,0,"listunspent",postdata,0));
}
bits256 iguana_wif2privkey(char *wifstr)
{
char url[512],postdata[1024],*retstr,*privstr; bits256 privkey; cJSON *retjson;
memset(privkey.bytes,0,sizeof(privkey));
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"SuperNET\",\"method\":\"wif2priv\",\"wif\":\"%s\"}",wifstr);
if ( (retstr= bitcoind_RPC(0,"SuperNET",url,0,"wif2priv",postdata,0)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (privstr= jstr(retjson,"privkey")) != 0 )
{
if ( strlen(privstr) == 64 )
decode_hex(privkey.bytes,32,privstr);
}
free_json(retjson);
}
free(retstr);
}
return(privkey);
}
double bittrex_balance(char *base,char *coinaddr)
{
char *retstr; cJSON *retjson; double balance = 0.;
if ( (retstr= DEX_balance("bittrex",base,coinaddr)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
balance = jdouble(retjson,"balance");
free_json(retjson);
}
free(retstr);
}
return(balance);
}
double dex_balance(char *base,char *coinaddr)
{
char *retstr; cJSON *retjson; double balance = 0.;
if ( (retstr= DEX_balance("DEX",base,coinaddr)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
balance = jdouble(retjson,"balance");
free_json(retjson);
}
free(retstr);
}
return(balance);
}
int32_t komodo_baseid(char *base)
{
int32_t i;
for (i=0; i<sizeof(CURRENCIES)/sizeof(*CURRENCIES); i++)
if ( strcmp(base,CURRENCIES[i]) == 0 )
return(i);
return(-1);
}
cJSON *yahoo_allcurrencies()
{
char *retstr; cJSON *retjson = 0;
if ( (retstr= issue_curl("http://finance.yahoo.com/webservice/v1/symbols/allcurrencies/quote?format=json")) != 0 )
{
retjson = cJSON_Parse(retstr);
free(retstr);
}
return(retjson);
}
void _marketmaker_fiatupdate(int32_t baseid,double price)
{
PAXPRICES[baseid] = price * PAXPRICES[0];
printf("%.6f %s per USD, %.8f %s per KMD\n",price,CURRENCIES[baseid],PAXPRICES[baseid],CURRENCIES[baseid]);
}
uint32_t marketmaker_fiatupdate(cJSON *fiatjson)
{
int32_t i,n,baseid; cJSON *item,*array; double price; char *name; uint64_t mask = 0;
fiatjson = jobj(fiatjson,"list");
if ( fiatjson != 0 && (array= jarray(&n,fiatjson,"resources")) > 0 )
{
for (i=0; i<n; i++)
{
/*
"resource" : {
"classname" : "Quote",
"fields" : {
"name" : "USD/BRX",
"price" : "3.063200",
"symbol" : "BRX=X",
"ts" : "1487866204",
"type" : "currency",
"utctime" : "2017-02-23T16:10:04+0000",
"volume" : "0"
}
*/
item = jitem(array,i);
if ( (item= jobj(item,"resource")) != 0 )
item = jobj(item,"fields");
if ( item != 0 )
{
price = jdouble(item,"price");
if ( price > SMALLVAL && (name= jstr(item,"name")) != 0 && strncmp(name,"USD/",4) == 0 )
{
if ( (baseid= komodo_baseid(name+4)) >= 0 && baseid < 32 )
{
if ( ((1LL << baseid) & mask) == 0 )
{
_marketmaker_fiatupdate(baseid,price);
mask |= (1LL << baseid);
} else if ( fabs(price*PAXPRICES[0] - PAXPRICES[baseid]) > SMALLVAL )
printf("DUPLICATE PRICE? %s %.8f vs %.8f\n",name+4,price*PAXPRICES[0],PAXPRICES[baseid]);
}
}
}
}
}
printf("pax mask.%x\n",(uint32_t)mask);
return((uint32_t)mask);
}
void marketmaker_cancel(struct mmpending_order *ptr)
{
char *retstr; cJSON *retjson;
if ( ptr->pending != 0 && ptr->cancelstarted == 0 )
{
ptr->cancelstarted = (uint32_t)time(NULL);
if ( (retstr= DEX_cancelorder(ptr->exchange,ptr->orderid)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
printf("cancel %s (%s/%s) %.8f vol %.8f dir.%d -> (%s)\n",ptr->exchange,ptr->base,ptr->rel,ptr->price,ptr->volume,ptr->dir,jprint(retjson,0));
free_json(retjson);
ptr->pending = 0;
ptr->canceled = (uint32_t)time(NULL);
}
free(retstr);
}
}
}
void marketmaker_queue(char *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *retjson)
{
struct mmpending_order *ptr; char *orderid;
//DEX_trade.({"success":true,"message":"","result":{"uuid":"d5faa9e4-660d-436f-a257-2c6a40442d8c"},"tag":"11271578410079391025"}
if ( is_cJSON_True(jobj(retjson,"success")) != 0 && jobj(retjson,"result") != 0 )
retjson = jobj(retjson,"result");
printf("QUEUE.%s %s/%s dir.%d %.8f %.6f (%s)\n",exchange,base,rel,dir,price,volume,jprint(retjson,0));
Pending_orders = realloc(Pending_orders,(1 + Num_Pending) * sizeof(*Pending_orders));
ptr = &Pending_orders[Num_Pending++];
memset(ptr,0,sizeof(*ptr));
ptr->price = price;
ptr->volume = volume;
ptr->dir = dir;
ptr->pending = (uint32_t)time(NULL);
strcpy(ptr->exchange,exchange);
strcpy(ptr->base,base);
strcpy(ptr->rel,rel);
if ( (orderid= jstr(retjson,"OrderUuid")) != 0 || (orderid= jstr(retjson,"uuid")) != 0 )
strcpy(ptr->orderid,orderid);
else strcpy(ptr->orderid,"0");
}
void marketmaker_pendingupdate(char *exchange,char *base,char *rel)
{
char *retstr; cJSON *retjson,*obj; int32_t i; struct mmpending_order *ptr;
for (i=0; i<Num_Pending; i++)
{
ptr = &Pending_orders[i];
if ( strcmp(exchange,ptr->exchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 )
continue;
if ( ptr->completed == 0 && (retstr= DEX_orderstatus(exchange,ptr->orderid)) != 0 )
{
//printf("%s status.(%s)\n",ptr->orderid,retstr);
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
obj = jobj(retjson,"result");
if ( is_cJSON_Array(obj) != 0 )
obj = jitem(retjson,0);
if ( jdouble(obj,"QuantityRemaining") == 0. || is_cJSON_True(jobj(obj,"IsOpen")) == 0 )
{
//{"Uuid":null,"OrderUuid":"e7b0789c-0c4e-413b-a768-3d5734d9cbe5","Exchange":"BTC-KMD","OrderType":"LIMIT_SELL","Quantity":877.77700000,"QuantityRemaining":462.50512234,"Limit":0.00011770,"CommissionPaid":0.00012219,"Price":0.04887750,"PricePerUnit":0.00011769,"Opened":"2017-02-20T13:16:22.29","Closed":null,"CancelInitiated":false,"ImmediateOrCancel":false,"IsConditional":false,"Condition":"NONE","ConditionTarget":null} printf("uuid.(%s) finished.(%s)\n",ptr->orderid,jprint(retjson,0));
ptr->completed = (uint32_t)time(NULL);
ptr->pending = 0;
}
free_json(retjson);
}
free(retstr);
}
}
}
void marketmaker_pendinginit(char *exchange,char *base,char *rel)
{
char *retstr,*orderid,*pairstr,relbase[65]; cJSON *retjson,*array,*item; int32_t i,j,n,dir; struct mmpending_order *ptr;
sprintf(relbase,"%s-%s",rel,base);
if ( (retstr= DEX_openorders(exchange)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
//printf("%s\n",jprint(retjson,0));
if ( is_cJSON_True(jobj(retjson,"success")) != 0 && (array= jarray(&n,retjson,"result")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( (pairstr= jstr(item,"Exchange")) == 0 )
continue;
if ( strcmp(pairstr,relbase) != 0 )
{
printf("skip %s when %s\n",pairstr,relbase);
continue;
}
//printf("(%s)\n",jprint(item,0));
//{"success":true,"message":"","result":[{"Uuid":null,"OrderUuid":"81ad3e37-65d4-4fee-9c29-03b050f5192b","Exchange":"BTC-KMD","OrderType":"LIMIT_BUY","Quantity":885.19934578,"QuantityRemaining":885.19934578,"Limit":0.00011184,"CommissionPaid":0,"Price":0,"PricePerUnit":null,"Opened":"2017-02-19T19:14:02.94","Closed":null,"CancelInitiated":false,"ImmediateOrCancel":false,"IsConditional":false,"Condition":"NONE","ConditionTarget":null}],"tag":"10056789044100011414"}
if ( (orderid= jstr(item,"OrderUuid")) != 0 && is_cJSON_Null(jobj(item,"Closed")) != 0 && is_cJSON_False(jobj(item,"CancelInitiated")) != 0 )
{
for (j=0; j<Num_Pending; j++)
{
ptr = &Pending_orders[j];
if ( strcmp(exchange,ptr->exchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 )
continue;
if ( strcmp(ptr->orderid,orderid) == 0 )
{
ptr->pending = (uint32_t)time(NULL);
ptr->completed = 0;
printf("%s pending\n",orderid);
break;
}
}
if ( j == Num_Pending )
{
if ( jstr(item,"OrderType") != 0 )
{
if ( strcmp(jstr(item,"OrderType"),"LIMIT_BUY") == 0 )
dir = 1;
else if ( strcmp(jstr(item,"OrderType"),"LIMIT_SELL") == 0 )
dir = -1;
else dir = 0;
if ( dir != 0 )
marketmaker_queue(exchange,base,rel,dir,jdouble(item,"Limit"),jdouble(item,"QuantityRemaining"),item);
else printf("no dir (%s) (%s)\n",jprint(item,0),jstr(item,"OrderType"));
}
}
}
}
}
free_json(retjson);
}
free(retstr);
}
}
double marketmaker_filled(char *exchange,char *base,char *rel,double *buyvolp,double *sellvolp,double *pendingbidsp,double *pendingasksp)
{
double pricesum = 0.,volsum = 0.; struct mmpending_order *ptr; int32_t i;
*pendingbidsp = *pendingasksp = 0.;
for (i=0; i<Num_Pending; i++)
{
ptr = &Pending_orders[i];
if ( strcmp(exchange,ptr->exchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 )
continue;
if ( ptr->completed != 0 )
{
if ( ptr->reported == 0 )
{
if ( ptr->dir > 0 )
(*buyvolp) += ptr->volume;
else if ( ptr->dir < 0 )
(*sellvolp) += ptr->volume;
pricesum += ptr->volume * ptr->price;
volsum += ptr->volume;
ptr->reported = (uint32_t)time(NULL);
printf("REPORT dir.%d vol %.8f\n",ptr->dir,ptr->volume);
}
}
else if ( ptr->pending != 0 ) // alternative is error or cancelled
{
if ( ptr->dir > 0 )
(*pendingbidsp) += ptr->volume;
else if ( ptr->dir < 0 )
(*pendingasksp) += ptr->volume;
}
}
if ( volsum != 0. )
pricesum /= volsum;
return(pricesum);
}
int32_t marketmaker_prune(char *exchange,char *base,char *rel,int32_t polarity,double bid,double ask,double separation)
{
int32_t i,n = 0; struct mmpending_order *ptr;
for (i=0; i<Num_Pending; i++)
{
ptr = &Pending_orders[i];
if ( strcmp(exchange,ptr->exchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 )
continue;
if ( ptr->pending != 0 && ptr->cancelstarted == 0 )
{
if ( polarity != 0 )
{
if ( ((ptr->dir*polarity > 0 && ptr->price < bid-separation) || (ptr->dir*polarity < 0 && ptr->price > ask+separation)) )
{
printf("polarity.%d dir.%d price.%f bid.%f ask.%f\n",polarity,ptr->dir,ptr->price,bid,ask);
marketmaker_cancel(ptr), n++;
}
}
/*else
{,*prunebid=0,*pruneask=0; double lowbid=0.,highask=0.
if ( ptr->dir > 0 && (lowbid == 0. || ptr->price < lowbid) )
{
lowbid = ptr->price;
prunebid = ptr;
}
else if ( ptr->dir < 0 && (highask == 0. || ptr->price > highask) )
{
highask = ptr->price;
pruneask = ptr;
}
}*/
}
}
/*if ( polarity == 0 )
{
if ( prunebid != 0 && fabs(prunebid->price - bid) > separation )
marketmaker_cancel(prunebid), n++;
if ( pruneask != 0 && fabs(pruneask->price - ask) > separation )
marketmaker_cancel(pruneask), n++;
}*/
return(n);
}
void marketmaker_volumeset(double *bidincrp,double *askincrp,double incr,double buyvol,double pendingbids,double sellvol,double pendingasks,double maxexposure)
{
*bidincrp = *askincrp = incr;
//if ( pendingbids >= pendingasks+maxexposure )
// *bidincrp = 0.;
//else if ( pendingasks >= pendingbids+maxexposure )
// *askincrp = 0.;
if ( *bidincrp > 0. && pendingbids + *bidincrp > maxexposure )
*bidincrp = (maxexposure - *bidincrp);
if ( *askincrp > 0. && pendingasks + *askincrp > maxexposure )
*askincrp = (maxexposure - *askincrp);
if ( *bidincrp < 0. )
*bidincrp = 0.;
if ( *askincrp < 0. )
*askincrp = 0.;
}
int32_t marketmaker_spread(char *exchange,char *base,char *rel,double bid,double bidvol,double ask,double askvol,double separation)
{
int32_t nearflags[2],i,n = 0; struct mmpending_order *ptr; cJSON *retjson,*vals; char *retstr,postdata[1024],url[128]; double vol,spread_ratio;
memset(nearflags,0,sizeof(nearflags));
if ( strcmp("DEX",exchange) != 0 )
{
for (i=0; i<Num_Pending; i++)
{
ptr = &Pending_orders[i];
if ( strcmp(exchange,ptr->exchange) != 0 || strcmp(base,ptr->base) != 0 || strcmp(rel,ptr->rel) != 0 )
continue;
if ( ptr->pending != 0 && ptr->cancelstarted == 0 )
{
if ( bid > SMALLVAL && bidvol > SMALLVAL && ptr->dir > 0 && fabs(bid - ptr->price) < separation )
{
//printf("bid %.8f near %.8f\n",bid,ptr->price);
nearflags[0]++;
}
if ( ask > SMALLVAL && askvol > SMALLVAL && ptr->dir < 0 && fabs(ask - ptr->price) < separation )
{
//printf("%.8f near %.8f\n",ask,ptr->price);
nearflags[1]++;
}
}
}
}
//printf("spread.%s (%.8f %.6f) (%.8f %.6f)\n",exchange,bid,bidvol,ask,askvol);
if ( bid > SMALLVAL && bidvol > SMALLVAL && nearflags[0] == 0 )
{
if ( strcmp("DEX",exchange) == 0 && strcmp(base,"KMD") == 0 && strcmp(rel,"BTC") == 0 )
{
if ( ask > SMALLVAL && askvol > SMALLVAL )
{
/*li.profit = jdouble(vals,"profit");
li.refprice = jdouble(vals,"refprice");
li.bid = jdouble(vals,"bid");
li.ask = jdouble(vals,"ask");
if ( (li.minvol= jdouble(vals,"minvol")) <= 0. )
li.minvol = (strcmp("BTC",base) == 0) ? 0.0001 : 0.001;
if ( (li.maxvol= jdouble(vals,"maxvol")) < li.minvol )
li.maxvol = li.minvol;*/
//curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"MVP\",\"vals\":{\"rel\":\"USD\",\"bid\":0.09,\"ask\":0.11,\"maxvol\":100}}"
vals = cJSON_CreateObject();
jaddstr(vals,"rel","BTC");
jaddnum(vals,"bid",bid);
jaddnum(vals,"ask",ask);
vol = bidvol > askvol ? askvol : bidvol;
jaddnum(vals,"maxvol",vol);
jaddnum(vals,"minvol",vol*0.1 > 100 ? 100 : vol * 0.1);
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}",base,jprint(vals,1));
//printf("(%s)\n",postdata);
if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata,0)) != 0 )
{
//printf("(%s) -> (%s)\n",postdata,retstr);
free(retstr);
}
spread_ratio = .5 * ((ask - bid) / (bid + ask));
for (i=0; i<sizeof(CURRENCIES)/sizeof(*CURRENCIES); i++)
{
if ( (PAXACTIVE & (1<<i)) == 0 )
continue;
if ( PAXPRICES[i] > SMALLVAL )
{
vals = cJSON_CreateObject();
jaddstr(vals,"rel",CURRENCIES[i]);
jaddnum(vals,"bid",PAXPRICES[i] * (1. - spread_ratio));
jaddnum(vals,"ask",PAXPRICES[i] * (1. + spread_ratio));
jaddnum(vals,"maxvol",vol * PAXPRICES[i]);
jaddnum(vals,"minvol",MAX(1,(int32_t)(vol * 0.01 * PAXPRICES[i])));
sprintf(url,"%s/?",IGUANA_URL);
sprintf(postdata,"{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"%s\",\"vals\":%s}","KMD",jprint(vals,1));
if ( (retstr= bitcoind_RPC(0,"tradebot",url,0,"liqudity",postdata,0)) != 0 )
{
//printf("(%s) -> (%s)\n",postdata,retstr);
free(retstr);
}
}
//break;
}
} else printf("unsupported ask only for DEX %s/%s\n",base,rel);
}
else if ( (retstr= DEX_trade(exchange,base,rel,1,bid,bidvol)) != 0 )
{
//printf("DEX_trade.(%s)\n",retstr);
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
marketmaker_queue(exchange,base,rel,1,bid,bidvol,retjson);
free_json(retjson);
}
free(retstr);
} //else printf("skip bid %s %.8f vol %f\n",exchange,bid,bidvol);
}
if ( ask > SMALLVAL && askvol > SMALLVAL && nearflags[1] == 0 && strcmp("DEX",exchange) != 0 )
{
if ( (retstr= DEX_trade(exchange,base,rel,-1,ask,askvol)) != 0 )
{
//printf("DEX_trade.(%s)\n",retstr);
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
marketmaker_queue(exchange,base,rel,-1,ask,askvol,retjson);
free_json(retjson);
}
free(retstr);
}
} //else printf("skip ask %s %.8f vol %f\n",exchange,bid,bidvol);
return(n);
}
double marketmaker_updateprice(char *name,char *base,char *rel,double theoretical,double *incrp)
{
static uint32_t counter;
cJSON *fiatjson; double USD_average=0.,usdprice=0.,CMC_average=0.,avebid=0.,aveask=0.,val,changes[3],highbid=0.,lowask=0.;
if ( (val= get_theoretical(&avebid,&aveask,&highbid,&lowask,&CMC_average,changes,name,base,rel,&USD_average)) != 0. )
{
if ( theoretical == 0. )
{
theoretical = val;
if ( *incrp > 2 )
{
*incrp = (int32_t)*incrp;
*incrp += 0.777;
}
} else theoretical = (theoretical + val) * 0.5;
if ( (counter++ % 12) == 0 )
{
if ( USD_average > SMALLVAL && CMC_average > SMALLVAL && theoretical > SMALLVAL )
{
usdprice = USD_average * (theoretical / CMC_average);
printf("USD %.4f <- (%.6f * (%.8f / %.8f))\n",usdprice,USD_average,theoretical,CMC_average);
PAXPRICES[0] = usdprice;
if ( (fiatjson= yahoo_allcurrencies()) != 0 )
{
marketmaker_fiatupdate(fiatjson);
free_json(fiatjson);
}
}
}
LP_priceupdate(base,rel,theoretical,avebid,aveask,highbid,lowask,PAXPRICES);
}
return(theoretical);
}
void marketmaker(double minask,double maxbid,char *baseaddr,char *reladdr,double start_BASE,double start_REL,double profitmargin,double maxexposure,double ratioincr,char *exchange,char *name,char *base,char *rel)
{
char *retstr; double bid,ask,start_DEXbase,start_DEXrel,DEX_base = 0.,DEX_rel = 0.,balance_base=0.,balance_rel=0.,mmbid,mmask,aveprice,incr,pendingbids,pendingasks,buyvol,sellvol,bidincr,askincr,filledprice,avebid=0.,aveask=0.,highbid=0.,lowask=0.,theoretical = 0.; uint32_t lasttime = 0;
incr = maxexposure * ratioincr;
buyvol = sellvol = 0.;
start_DEXbase = dex_balance(base,baseaddr);
start_DEXrel = dex_balance(rel,reladdr);
while ( 1 )
{
if ( time(NULL) > lasttime+60 )
{
if ( (theoretical= marketmaker_updateprice(name,base,rel,theoretical,&incr)) != 0. )
{
if ( lasttime == 0 )
maxexposure /= theoretical;
}
if ( strcmp(exchange,"bittrex") == 0 )
{
balance_base = bittrex_balance(base,"");
balance_rel = bittrex_balance(rel,"");
DEX_base = dex_balance(base,baseaddr);
DEX_rel = dex_balance(rel,reladdr);
} else printf("add support for %s balance\n",exchange);
lasttime = (uint32_t)time(NULL);
}
marketmaker_pendingupdate(exchange,base,rel);
if ( theoretical > SMALLVAL && avebid > SMALLVAL && aveask > SMALLVAL )
{
aveprice = (avebid + aveask) * 0.5;
// if order is filled, theoretical <- filled (theoretical + price)/2
if ( (filledprice= marketmaker_filled(exchange,base,rel,&buyvol,&sellvol,&pendingbids,&pendingasks)) != 0. )
theoretical = (theoretical + filledprice) * 0.5;
buyvol = sellvol = 0;
if ( (balance_base + DEX_base) < (start_BASE + start_DEXbase) )
sellvol += ((start_BASE + start_DEXbase) - (balance_base + DEX_base));
else buyvol += ((balance_base + DEX_base) - (start_BASE + start_DEXbase));
if ( (balance_rel + DEX_rel) < (start_REL + start_DEXrel) )
buyvol += ((start_REL + start_DEXrel) - (balance_rel + DEX_rel)) / theoretical;
else sellvol += ((balance_rel + DEX_rel) - (start_REL + start_DEXrel)) / theoretical;
mmbid = theoretical - theoretical*profitmargin;
mmask = theoretical + theoretical*profitmargin;
// if any existing order exceeds double margin distance, cancel
marketmaker_prune(exchange,base,rel,1,mmbid - theoretical*profitmargin,mmask + theoretical*profitmargin,0.);
// if new prices crosses existing order, cancel old order first
marketmaker_prune(exchange,base,rel,-1,mmbid,mmask,0.);
//printf("(%.8f %.8f) ",mmbid,mmask);
if ( (1) )
{
if ( mmbid >= lowask || (maxbid > SMALLVAL && mmbid > maxbid) ) //mmbid < highbid ||
{
printf("clear mmbid %.8f lowask %.8f maxbid %.8f\n",mmbid,lowask,maxbid);
mmbid = 0.;
}
if ( mmask <= highbid || (minask > SMALLVAL && mmask < minask) ) // mmask > lowask ||
mmask = 0.;
}
marketmaker_volumeset(&bidincr,&askincr,incr,buyvol,pendingbids,sellvol,pendingasks,maxexposure);
printf("AVE.(%.8f %.8f) hbla %.8f %.8f bid %.8f ask %.8f theory %.8f buys.(%.6f %.6f) sells.(%.6f %.6f) incr.(%.6f %.6f) balances.(%.8f + %.8f, %.8f + %.8f) test %f\n",avebid,aveask,highbid,lowask,mmbid,mmask,theoretical,buyvol,pendingbids,sellvol,pendingasks,bidincr,askincr,balance_base,DEX_base,balance_rel,DEX_rel,(aveask - avebid)/aveprice);
if ( (retstr= DEX_swapstatus()) != 0 )
printf("%s\n",retstr), free(retstr);
printf("%s %s %s, %s %s %s\n",base,DEX_baseaddr,DEX_balance("DEX",base,DEX_baseaddr),rel,DEX_reladdr,DEX_balance("DEX",rel,DEX_reladdr));
if ( (aveask - avebid)/aveprice > profitmargin )
bid = highbid * (1 - profitmargin), ask = lowask * (1 + profitmargin);
else bid = avebid - profitmargin*aveprice, ask = avebid + profitmargin*aveprice;
marketmaker_spread("DEX",base,rel,bid,incr,ask,incr,profitmargin*aveprice*0.5);
if ( (pendingbids + buyvol) > (pendingasks + sellvol) && (pendingbids + buyvol) > bidincr )
{
bidincr *= ((double)(pendingasks + sellvol) / ((pendingbids + buyvol) + (pendingasks + sellvol)));
printf("bidincr %f buy.(%f + %f) sell.(%f + %f)\n",bidincr,pendingbids,buyvol,pendingasks,sellvol);
if ( bidincr < 0.1*incr )
bidincr = 0.1*incr;
if ( bidincr > 1. )
bidincr = (int32_t)bidincr + 0.777;
}
if ( (pendingbids + buyvol) < (pendingasks + sellvol) && (pendingasks + sellvol) > askincr )
{
askincr *= (double)(pendingbids + buyvol) / ((pendingbids + buyvol) + (pendingasks + sellvol));
if ( askincr < 0.1*incr )
askincr = 0.1*incr;
if ( askincr > 1. )
askincr = (int32_t)askincr + 0.777;
}
//printf("mmbid %.8f %.6f, mmask %.8f %.6f\n",mmbid,bidincr,mmask,askincr);
marketmaker_spread(exchange,base,rel,mmbid,bidincr,mmask,askincr,profitmargin*aveprice*0.5);
sleep(60);
}
}
}
#include "LP_nativeDEX.c"
/*MERK d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a ht.518777 -> {"pos":1,"merkle":["526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8", "f68b03a7b6e418c9b306d8d8b21917ae5a584696f9b0b8cb0741733d7097fdfd"],"block_height":518777} root.(0000000000000000000000000000000000000000000000000000000000000000)
MERK c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543 ht.518777 -> {"pos":2,"merkle":["fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501", "8c116e974c842ad3ad8b3ddbd71da3debb150e3fe692f5bd628381bc167311a7"],"block_height":518777} root.(0000000000000000000000000000000000000000000000000000000000000000)*/
/*526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8
d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a
c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543
fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501*/
/*0: 526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8
1: d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a
2: c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543
3: fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501
4: 8c116e974c842ad3ad8b3ddbd71da3debb150e3fe692f5bd628381bc167311a7
5: f68b03a7b6e418c9b306d8d8b21917ae5a584696f9b0b8cb0741733d7097fdfd
6: a87ee259560f20b20182760c0e7cc7896d44381f0ad58a2e755a2b6b895b01ec*/
/*
0 1 2 3
4 5
6
1 -> [0, 5]
2 -> [3, 4]
if odd -> right, else left
then /= 2
*/
/*void testmerk()
{
bits256 tree[256],roothash,txid; int32_t i; char str[65];
memset(tree,0,sizeof(tree));
decode_hex(tree[0].bytes,32,"526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8");
decode_hex(tree[1].bytes,32,"d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a");
decode_hex(tree[2].bytes,32,"c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543");
decode_hex(tree[3].bytes,32,"fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501");
roothash = iguana_merkle(tree,4);
for (i=0; i<256; i++)
{
if ( bits256_nonz(tree[i]) == 0 )
break;
printf("%d: %s\n",i,bits256_str(str,tree[i]));
}
memset(tree,0,sizeof(tree));
decode_hex(tree[0].bytes,32,"526f8be81718beccc16a541a2c550b612123218d80fa884d9f080f18284e2bd8");
decode_hex(tree[1].bytes,32,"f68b03a7b6e418c9b306d8d8b21917ae5a584696f9b0b8cb0741733d7097fdfd");
decode_hex(txid.bytes,32,"d6071f9b03d1428b648d51ae1268f1605d97f44422ed55ad0335b13fa655f61a");
roothash = validate_merkle(1,txid,tree,2);
printf("validate 1: %s\n",bits256_str(str,roothash));
memset(tree,0,sizeof(tree));
decode_hex(tree[0].bytes,32,"fdff0962fb95120a86a07ddf1ec784fcc5554a2d0a3791a8db2083d593920501");
decode_hex(tree[1].bytes,32,"8c116e974c842ad3ad8b3ddbd71da3debb150e3fe692f5bd628381bc167311a7");
decode_hex(txid.bytes,32,"c007e9c1881a83be453cb6ed3d1bd3bda85efd3b5ce60532c2e20ae3f8a82543");
roothash = validate_merkle(2,txid,tree,2);
printf("validate 2: %s\n",bits256_str(str,roothash));
}*/
void LP_main(void *ptr)
{
char *passphrase; double profitmargin; uint16_t port; cJSON *argjson = ptr;
@ -876,22 +86,83 @@ void LP_main(void *ptr)
int main(int argc, const char * argv[])
{
char dirname[512],*base,*rel,*name,*exchange,*apikey,*apisecret,*blocktrail,*retstr,*baseaddr,*reladdr,*passphrase;
double profitmargin,maxexposure,incrratio,start_rel,start_base,minask,maxbid,incr;
cJSON *retjson,*loginjson; int32_t i;
char dirname[512],*passphrase; double incr; cJSON *retjson;
OS_init();
if ( strstr(argv[0],"btc2kmd") != 0 && argv[1] != 0 )
{
uint8_t addrtype,rmd160[20],rmd160b[20]; char coinaddr[64],coinaddr2[64];
bitcoin_addr2rmd160(0,&addrtype,rmd160,(char *)argv[1]);
bitcoin_address(coinaddr,0,60,rmd160,20);
bitcoin_addr2rmd160(0,&addrtype,rmd160b,coinaddr);
bitcoin_address(coinaddr2,0,0,rmd160b,20);
if ( addrtype == 0 )
{
bitcoin_address(coinaddr,0,60,rmd160,20);
bitcoin_addr2rmd160(0,&addrtype,rmd160b,coinaddr);
bitcoin_address(coinaddr2,0,0,rmd160b,20);
}
else if ( addrtype == 60 )
{
bitcoin_address(coinaddr,0,0,rmd160,20);
bitcoin_addr2rmd160(0,&addrtype,rmd160b,coinaddr);
bitcoin_address(coinaddr2,0,60,rmd160b,20);
}
printf("(%s) -> %s -> %s\n",(char *)argv[1],coinaddr,coinaddr2);
if ( strcmp((char *)argv[1],coinaddr2) != 0 )
printf("ERROR\n");
exit(0);
}
else if ( argv[1] != 0 && strcmp(argv[1],"hush") == 0 )
{
uint32_t timestamp; char str[65],wifstr[128]; bits256 privkey; int32_t i;
timestamp = (uint32_t)time(NULL);
//printf("start hush vanitygen t.%u\n",timestamp);
for (i=0; i<1000000000; i++)
{
OS_randombytes(privkey.bytes,sizeof(privkey));
privkey.bytes[0] = 0x0e;
privkey.bytes[1] = 0x5b;
privkey.bytes[2] = 0xf9;
privkey.bytes[3] = 0xc6;
privkey.bytes[4] = 0x06;
privkey.bytes[5] = 0xdd;
privkey.bytes[6] = 0xbb;
bitcoin_priv2wiflong(0xab,wifstr,privkey,0x36);
if ( wifstr[2] == 'x' && wifstr[4] == 'H' && wifstr[5] == 'u' && wifstr[6] == 's' )//&& wifstr[3] == 'x' )
{
if ( wifstr[7] == 'h' && wifstr[8] == 'L' && wifstr[9] == 'i' )
{
//printf("i.%d %s -> wif.%s\n",i,bits256_str(str,privkey),wifstr);
if ( wifstr[10] == 's' && wifstr[11] == 't' )
{
printf("{\"iters\":%d,\"privkey\":\"%s\",\"wif\":\"%s\"}\n",i,bits256_str(str,privkey),wifstr);
break;
}
}
} //else printf("failed %s\n",wifstr);
}
//printf("done hush vanitygen done %u elapsed %d\n",(uint32_t)time(NULL),(uint32_t)time(NULL) - timestamp);
exit(0);
}
else if ( argv[1] != 0 && strcmp(argv[1],"vanity") == 0 && argv[2] != 0 )
{
uint32_t timestamp; uint8_t pubkey33[33]; char str[65],coinaddr[64],wifstr[128]; bits256 privkey; int32_t i,len; void *ctx;
ctx = bitcoin_ctx();
len = (int32_t)strlen(argv[2]);
timestamp = (uint32_t)time(NULL);
printf("start vanitygen (%s).%d t.%u\n",argv[2],len,timestamp);
for (i=0; i<1000000000; i++)
{
OS_randombytes(privkey.bytes,sizeof(privkey));
bitcoin_priv2pub(ctx,pubkey33,coinaddr,privkey,0,60);
if ( strncmp(coinaddr+1,argv[2],len-1) == 0 )
{
bitcoin_priv2wif(0,wifstr,privkey,188);
printf("i.%d %s -> %s wif.%s\n",i,bits256_str(str,privkey),coinaddr,wifstr);
if ( coinaddr[1+len-1] == argv[2][len-1] )
break;
} //else printf("failed %s\n",wifstr);
}
printf("done vanitygen.(%s) done %u elapsed %d\n",argv[2],(uint32_t)time(NULL),(uint32_t)time(NULL) - timestamp);
exit(0);
}
sprintf(dirname,"%s",GLOBAL_DBDIR), OS_ensure_directory(dirname);
sprintf(dirname,"%s/SWAPS",GLOBAL_DBDIR), OS_ensure_directory(dirname);
sprintf(dirname,"%s/PRICES",GLOBAL_DBDIR), OS_ensure_directory(dirname);
@ -905,12 +176,17 @@ int main(int argc, const char * argv[])
#else
if ( argc == 1 )
{
//LP_privkey_tests();
LP_NXT_redeems();
sleep(3);
return(0);
}
if ( argc > 1 && (retjson= cJSON_Parse(argv[1])) != 0 )
{
if ( jint(retjson,"docker") == 1 )
DOCKERFLAG = 1;
else if ( jstr(retjson,"docker") != 0 )
DOCKERFLAG = (uint32_t)calc_ipbits(jstr(retjson,"docker"));
if ( (passphrase= jstr(retjson,"passphrase")) == 0 )
jaddstr(retjson,"passphrase","test");
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)LP_main,(void *)retjson) != 0 )
@ -921,64 +197,6 @@ int main(int argc, const char * argv[])
incr = 100.;
while ( (1) )
sleep(100000);
profitmargin = jdouble(retjson,"profitmargin");
minask = jdouble(retjson,"minask");
maxbid = jdouble(retjson,"maxbid");
maxexposure = jdouble(retjson,"maxexposure");
incrratio = jdouble(retjson,"lotratio");
start_base = jdouble(retjson,"start_base");
start_rel = jdouble(retjson,"start_rel");
apikey = jstr(retjson,"apikey");
apisecret = jstr(retjson,"apisecret");
base = jstr(retjson,"base");
name = jstr(retjson,"name");
rel = jstr(retjson,"rel");
blocktrail = jstr(retjson,"blocktrail");
exchange = jstr(retjson,"exchange");
PAXACTIVE = juint(retjson,"paxactive");
if ( profitmargin < 0. || maxexposure <= 0. || incrratio <= 0. || apikey == 0 || apisecret == 0 || base == 0 || name == 0 || rel == 0 || exchange == 0 || blocktrail == 0 )
{
printf("illegal parameter (%s)\n",jprint(retjson,0));
exit(-1);
}
if ( (retstr= iguana_walletpassphrase(passphrase,999999)) != 0 )
{
printf("(%s/%s) login.(%s)\n",base,rel,retstr);
if ( (loginjson= cJSON_Parse(retstr)) != 0 )
{
if ( PAXACTIVE != 0 )
{
for (i=0; i<32; i++)
{
if ( ((1<<i) & PAXACTIVE) != 0 )
{
if ( jstr(loginjson,CURRENCIES[i]) == 0 )
PAXACTIVE &= ~(1 << i);
}
}
}
if ( (baseaddr= jstr(loginjson,base)) == 0 || (reladdr= jstr(loginjson,rel)) == 0 )
{
printf("Need to activate both %s and %s before marketmaker\n",base,rel);
exit(1);
}
printf("%s\n",DEX_apikeypair(exchange,apikey,apisecret));
marketmaker_pendinginit(exchange,base,rel);
if ( baseaddr != 0 && reladdr != 0 )
{
printf("PAXACTIVE.%08x %s\n",PAXACTIVE,DEX_amlp(blocktrail));
strncpy(DEX_baseaddr,baseaddr,sizeof(DEX_baseaddr)-1);
strncpy(DEX_reladdr,reladdr,sizeof(DEX_reladdr)-1);
printf("%s.%s %s\n",base,baseaddr,DEX_balance("DEX",base,baseaddr));
printf("%s.%s %s\n",rel,reladdr,DEX_balance("DEX",rel,reladdr));
// initialize state using DEX_pendingorders, etc.
marketmaker(minask,maxbid,baseaddr,reladdr,start_base,start_rel,profitmargin,maxexposure,incrratio,exchange,name,base,rel);
}
free_json(loginjson);
} else printf("ERROR parsing.(%s)\n",retstr);
free(retstr);
}
free_json(retjson);
}
#endif
return 0;

4
iguana/exchanges/mshark

@ -0,0 +1,4 @@
#!/bin/bash
source userpass
# this will only work for watchonly addresses that have been rescanned and with active coins
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RTu3JZZKLJTcfNwBa19dWRagEfQq49STqC\",\"holdings\":[{\"coin\":\"iota\",\"balance\":1500000}, {\"coin\":\"bitcoin-cash\",\"balance\":1200}, {\"coin\":\"bitcoin\",\"balance\":145}],\"divisor\":1400000}"

3
iguana/exchanges/pendingswaps

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"swapstatus\",\"pending\":1}"

44
iguana/exchanges/prices/autoprice

@ -0,0 +1,44 @@
#!/bin/bash
margin=0.02
source userpass
./auto_chipskmd
./auto_chipsbtc
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"BTC\",\"margin\":0.01,\"refbase\":\"komodo\",\"refrel\":\"coinmarketcap\"}"
#curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"BTC\",\"rel\":\"KMD\",\"fixed\":0.00025,\"margin\":0.01}"
#curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"BTC\",\"fixed\":4000,\"margin\":0.01}"
#curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"MNZ\",\"offset\":0.0,\"refbase\":\"KMD\",\"refrel\":\"BTC\",\"factor\":15000,\"margin\":-0.2}"
source crypto
source trackbtc
source dex
source trackbtc
source jumblr
source trackbtc
source pangea
source trackbtc
source bots
source trackbtc
source bet
source trackbtc
source revs
source trackbtc
source mgw
source trackbtc
source revs
source trackbtc
sharkholdings="{\"coin\":\"iota\",\"balance\":1500000}, {\"coin\":\"bitcoin-cash\",\"balance\":1200}, {\"coin\":\"bitcoin\",\"balance\":145}"
curl --url "http://127.0.0.1:7783" --data "{\"base\":\"MSHARK\",\"rel\":\"KMD\",\"fundvalue_bid\":\"NAV_KMD\",\"fundvalue_ask\":\"assetNAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"address\":\"RTu3JZZKLJTcfNwBa19dWRagEfQq49STqC\",\"holdings\":[$sharkholdings],\"divisor\":1400000}"
curl --url "http://127.0.0.1:7783" --data "{\"base\":\"SUPERNET\",\"rel\":\"KMD\",\"fundvalue_bid\":\"NAV_KMD\",\"fundvalue_ask\":\"assetNAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":11000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":10000}, {\"coin\":\"syscoin\",\"balance\":20000000}, {\"coin\":\"waves\",\"balance\":700000}, {\"coin\":\"bitcoin\",\"balance\":625}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":375000}, {\"coin\":\"chips\",\"balance\":2577006 }, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }],\"divisor\":816016}"
curl --url "http://127.0.0.1:7783" --data "{\"margin\":0.01,\"base\":\"HODL\",\"rel\":\"KMD\",\"fundvalue_bid\":\"assetNAV_KMD\",\"fundvalue_ask\":\"assetNAV_KMD\",\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"address\":\"RNcUaMUEFLxVwtTo7rgruhwYanGk1jTkeU\",\"holdings\":[{\"coin\":\"siacoin\",\"balance\":185000000,\"comment\":\"using siafunds equal to million siacoin\"}],\"divisor\":10000000}"

3
iguana/exchanges/prices/bet

@ -0,0 +1,3 @@
coin=BET
price=0.0005
invprice=2000

3
iguana/exchanges/prices/bots

@ -0,0 +1,3 @@
coin=BOTS
price=0.001
invprice=1000

3
iguana/exchanges/prices/crypto

@ -0,0 +1,3 @@
coin=CRYPTO
price=0.002666666
invprice=375

3
iguana/exchanges/prices/dex

@ -0,0 +1,3 @@
coin=DEX
price=0.0015
invprice=666

3
iguana/exchanges/prices/jumblr

@ -0,0 +1,3 @@
coin=JUMBLR
price=0.002
invprice=500

3
iguana/exchanges/prices/mgw

@ -0,0 +1,3 @@
coin=MGW
price=0.00015
invprice=6666

3
iguana/exchanges/prices/pangea

@ -0,0 +1,3 @@
coin=PANGEA
price=0.001
invprice=1000

3
iguana/exchanges/prices/revs

@ -0,0 +1,3 @@
coin=REVS
price=0.0005
invprice=2000

12
iguana/exchanges/stats.c

@ -32,13 +32,15 @@ char *stats_JSON(void *ctx,char *myipaddr,int32_t mypubsock,cJSON *argjson,char
char *stats_validmethods[] =
{
"psock", "getprices", "notify", "getpeers", // from issue_ "uitem", "listunspent",
"orderbook", "statsdisp", "help", "getcoins", "pricearray", "balance", "tradesarray"
"psock", "ticker", "balances", "getprice", "notify", "getpeers", // from issue_ "uitem", "listunspent",
"orderbook", "statsdisp", "fundvalue", "help", "getcoins", "pricearray", "balance", "tradesarray"
};
int32_t LP_valid_remotemethod(cJSON *argjson)
{
char *method; int32_t i;
if ( DOCKERFLAG != 0 )
return(1);
if ( (method= jstr(argjson,"method")) != 0 )
{
for (i=0; i<sizeof(stats_validmethods)/sizeof(*stats_validmethods); i++)
@ -712,7 +714,7 @@ void LP_rpc_processreq(void *_ptr)
response = malloc(strlen(retstr)+1024+1+1);
//printf("alloc response.%p\n",response);
}
sprintf(hdrs,"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Credentials: true\r\nAccess-Control-Allow-Methods: GET, POST\r\nCache-Control : no-cache, no-store, must-revalidate\r\n%sContent-Length : %8d\r\n\r\n",content_type,(int32_t)strlen(retstr));
sprintf(hdrs,"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Credentials: true\r\nAccess-Control-Allow-Methods: GET, POST\r\nCache-Control : no-cache, no-store, must-revalidate\r\n%sContent-Length : %8d\r\n\r\n",content_type,(int32_t)strlen(retstr)+1);
response[0] = '\0';
strcat(response,hdrs);
strcat(response,retstr);
@ -791,7 +793,7 @@ void stats_rpcloop(void *args)
//fcntl(bindsock, F_SETFL, fcntl(bindsock, F_GETFL, 0) | O_NONBLOCK);
#endif
//if ( counter++ < 1 )
printf(">>>>>>>>>> DEX stats 127.0.0.1:%d bind sock.%d DEX stats API enabled <<<<<<<<<\n",port,bindsock);
printf(">>>>>>>>>> DEX stats 127.0.0.1:%d bind sock.%d DEX stats API enabled at unixtime.%u <<<<<<<<<\n",port,bindsock,(uint32_t)time(NULL));
}
//printf("after sock.%d\n",sock);
clilen = sizeof(cli_addr);
@ -815,6 +817,8 @@ void stats_rpcloop(void *args)
}
#endif*/
memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits));
if ( DOCKERFLAG != 0 && (DOCKERFLAG == 1 || ipbits == DOCKERFLAG) )
ipbits = localhostbits;
if ( port == RPC_port && ipbits != localhostbits )
{
//printf("port.%u RPC_port.%u ipbits %x != %x\n",port,RPC_port,ipbits,localhostbits);

20
iguana/exchanges/supernet

@ -0,0 +1,20 @@
#!/bin/bash
source userpass
# this will only work for watchonly addresses that have been rescanned and with active coins
echo mshark
./mshark
echo hodl
./hodl
echo dex
./dex
echo jumblr
./jumblr
echo bots
./bots
echo supernet
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"balances\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\"}"
echo supernet
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":11000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":10000}, {\"coin\":\"syscoin\",\"balance\":20000000}, {\"coin\":\"waves\",\"balance\":700000}, {\"coin\":\"bitcoin\",\"balance\":625}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":375000}, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }],\"divisor\":816016}"
#curl --url "http://5.9.253.196:7782" --data "{\"userpass\":\"$userpass\",\"method\":\"fundvalue\",\"address\":\"RRyyejME7LRTuvdziWsXkAbSW1fdiohGwK\",\"holdings\":[{\"coin\":\"iota\",\"balance\":11000000}, {\"coin\":\"stratis\",\"balance\":1300000}, {\"coin\":\"zcash\",\"balance\":10000}, {\"coin\":\"syscoin\",\"balance\":20000000}, {\"coin\":\"waves\",\"balance\":700000}, {\"coin\":\"bitcoin\",\"balance\":625}, {\"coin\":\"bitcoin-cash\",\"balance\":1500}, {\"coin\":\"heat-ledger\",\"balance\":2323851 }, {\"coin\":\"decred\",\"balance\":20000}, {\"coin\":\"vericoin\",\"balance\":2199368 }, {\"coin\":\"byteball\",\"balance\":4238}, {\"coin\":\"iocoin\",\"balance\":150000}, {\"coin\":\"quantum-resistant-ledger\",\"balance\":375000}, {\"coin\":\"chips\",\"balance\":2577006 }, {\"coin\":\"hush\",\"balance\":100000 }, {\"coin\":\"mobilego\",\"balance\":100000 }],\"divisor\":816016}"

3
iguana/exchanges/ticker

@ -0,0 +1,3 @@
#!/bin/bash
source userpass
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"ticker\",\"base\":\"REVS\",\"rel\":\"KMD\"}"

2
iguana/exchanges/trackbtc

@ -0,0 +1,2 @@
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"KMD\",\"rel\":\"$coin\",\"offset\":0.0,\"refbase\":\"KMD\",\"refrel\":\"BTC\",\"factor\":$invprice,\"margin\":$margin}"
curl --url "http://127.0.0.1:7783" --data "{\"userpass\":\"$userpass\",\"method\":\"autoprice\",\"base\":\"$coin\",\"rel\":\"KMD\",\"offset\":0.0,\"refbase\":\"BTC\",\"refrel\":\"KMD\",\"factor\":$price,\"margin\":$margin}"

2
iguana/iguana_notary.c

@ -558,7 +558,7 @@ STRING_ARG(iguana,addnotary,ipaddr)
char NOTARY_CURRENCIES[][16] = { "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD",
"CNY", "RUB", "MXN", "BRL", "INR", "HKD", "TRY", "ZAR", "PLN", "NOK", "SEK", "DKK", "CZK", "HUF", "ILS", "KRW", "MYR", "PHP", "RON", "SGD", "THB", "BGN", "IDR", "HRK",
"REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "SHARK", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS", "MSHARK" }; // "LTC",
"REVS", "SUPERNET", "DEX", "PANGEA", "JUMBLR", "BET", "CRYPTO", "HODL", "BOTS", "MGW", "COQUI", "WLC", "KV", "CEAL", "MESH", "MNZ", "CHIPS", "MSHARK", "AXO", "ETOMIC", "BTCH" }; // "LTC",
ZERO_ARGS(dpow,notarychains)
{

3
iguana/m_notary_run

@ -41,6 +41,9 @@ coins/kv_7776
coins/ceal_7776
coins/mesh_7776
coins/mnz_7776
coins/axo_7776
coins/etomic_7776
coins/btch_7776
#curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"passthru\",\"method\":\"paxfiats\",\"timeout\":900000}"
#curl --url "http://127.0.0.1:7776" --data "{\"agent\":\"iguana\",\"method\":\"addnotary\",\"ipaddr\":\"$myip\"}"

65
iguana/m_splitfund

@ -14,6 +14,7 @@ curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"BET\",\"agent\":\"iguana\
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CRYPTO\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"HODL\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"SHARK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MSHARK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"BOTS\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MGW\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MVP\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
@ -24,36 +25,36 @@ curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CEAL\",\"agent\":\"iguana
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MESH\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MNZ\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"USD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"EUR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"USD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"EUR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"JPY\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"GBP\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"AUD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CAD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CHF\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"NZD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CNY\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"RUB\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MXN\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"BRL\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"INR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"HKD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"TRY\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"ZAR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"PLN\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"NOK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"SEK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"DKK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CZK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"HUF\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"ILS\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"KRW\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MYR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"PHP\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"RON\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"SGD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"THB\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"BGN\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"IDR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"HRK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"JPY\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"GBP\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"AUD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CAD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CHF\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"NZD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CNY\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"RUB\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MXN\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"BRL\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"INR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"HKD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"TRY\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"ZAR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"PLN\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"NOK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"SEK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"DKK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"CZK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"HUF\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"ILS\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"KRW\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"MYR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"PHP\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"RON\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"SGD\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"THB\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"BGN\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"IDR\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"
#curl --url "http://127.0.0.1:7776" --data "{\"coin\":\"HRK\",\"agent\":\"iguana\",\"method\":\"splitfunds\",\"satoshis\":\"50000\",\"sendflag\":1,\"duplicates\":10}"

252
iguana/mini-gmp.c

@ -2836,89 +2836,90 @@ static int gmp_detect_endian (void)
void *mpz_export (void *r, size_t *countp, int order, size_t size, int endian,size_t nails, const mpz_t u)
{
size_t count;
mp_size_t un;
if (nails != 0)
gmp_die ("mpz_import: Nails not supported.");
assert (order == 1 || order == -1);
assert (endian >= -1 && endian <= 1);
assert (size > 0 || u->_mp_size == 0);
un = u->_mp_size;
count = 0;
if (un != 0)
{
size_t k;
uint8_t *p;
ptrdiff_t word_step;
/* The current (partial) limb. */
mp_limb_t limb;
/* The number of bytes left to to in this limb. */
size_t bytes;
/* The index where the limb was read. */
mp_size_t i;
un = GMP_ABS (un);
/* Count bytes in top limb. */
limb = u->_mp_d[un-1];
assert (limb != 0);
k = 0;
do {
k++; limb >>= CHAR_BIT;
} while (limb != 0);
count = (k + (un-1) * sizeof (mp_limb_t) + size - 1) / size;
if (!r)
r = malloc (count * size);
if (endian == 0)
endian = gmp_detect_endian ();
p = (uint8_t *) r;
word_step = (order != endian) ? 2 * size : 0;
/* Process bytes from the least significant end, so point p at the
least significant word. */
if (order == 1)
{
p += size * (count - 1);
word_step = - word_step;
}
/* And at least significant byte of that word. */
if (endian == 1)
p += (size - 1);
for (bytes = 0, i = 0, k = 0; k < count; k++, p += word_step)
{
size_t j;
for (j = 0; j < size; j++, p -= (ptrdiff_t) endian)
{
if (bytes == 0)
{
if (i < un)
limb = u->_mp_d[i++];
bytes = sizeof (mp_limb_t);
}
*p = limb;
limb >>= CHAR_BIT;
bytes--;
}
}
assert (i == un);
assert (k == count);
size_t count;
mp_size_t un;
if (nails != 0)
gmp_die ("mpz_import: Nails not supported.");
assert (order == 1 || order == -1);
assert (endian >= -1 && endian <= 1);
assert (size > 0 || u->_mp_size == 0);
un = u->_mp_size;
count = 0;
if (un != 0)
{
size_t k;
uint8_t *p;
ptrdiff_t word_step;
/* The current (partial) limb. */
mp_limb_t limb;
/* The number of bytes left to to in this limb. */
size_t bytes;
/* The index where the limb was read. */
mp_size_t i;
un = GMP_ABS (un);
/* Count bytes in top limb. */
limb = u->_mp_d[un-1];
assert (limb != 0);
k = 0;
do {
k++; limb >>= CHAR_BIT;
} while (limb != 0);
count = (k + (un-1) * sizeof (mp_limb_t) + size - 1) / size;
if (!r)
r = malloc (count * size);
if (endian == 0)
endian = gmp_detect_endian ();
p = (uint8_t *) r;
word_step = (order != endian) ? 2 * size : 0;
/* Process bytes from the least significant end, so point p at the
least significant word. */
if (order == 1)
{
p += size * (count - 1);
word_step = - word_step;
}
/* And at least significant byte of that word. */
if (endian == 1)
p += (size - 1);
for (bytes = 0, i = 0, k = 0; k < count; k++, p += word_step)
{
size_t j;
for (j = 0; j < size; j++, p -= (ptrdiff_t) endian)
{
if (bytes == 0)
{
if (i < un)
limb = u->_mp_d[i++];
bytes = sizeof (mp_limb_t);
}
*p = limb;
//printf("{%02x} ",*p);
limb >>= CHAR_BIT;
bytes--;
}
}
assert (i == un);
assert (k == count);
}
if (countp)
*countp = count;
return r;
if (countp)
*countp = count;
//printf("mpz_export.%d\n",(int32_t)count);
return r;
}
/////////////////////////////////
@ -4360,44 +4361,6 @@ char *bitcoin_base58encode(char *coinaddr,uint8_t *data,int32_t datalen)
return(coinaddr);
}
int32_t bitcoin_base58decode(uint8_t *data,char *coinaddr)
{
uint32_t zeroes,be_sz=0; size_t count; const char *p,*p1; mpz_t bn58,bn;
mpz_init_set_ui(bn58,58);
mpz_init_set_ui(bn,0);
while ( isspace((uint32_t)(*coinaddr & 0xff)) )
coinaddr++;
for (p=coinaddr; *p; p++)
{
p1 = strchr(base58_chars,*p);
if ( p1 == 0 )
{
while (isspace((uint32_t)*p))
p++;
if ( *p != '\0' )
{
mpz_clear(bn), mpz_clear(bn58);
return(-1);
}
break;
}
mpz_mul(bn,bn,bn58);
mpz_add_ui(bn,bn,(int32_t)(p1 - base58_chars));
}
zeroes = 0;
for (p=coinaddr; *p==base58_chars[0]; p++)
data[zeroes++] = 0;
mpz_export(data+zeroes,&count,1,sizeof(data[0]),-1,0,bn);
if ( count >= 2 && data[count - 1] == 0 && data[count - 2] >= 0x80 )
count--;
be_sz = (uint32_t)count + (uint32_t)zeroes;
//memset(data,0,be_sz);
//for (i=0; i<count; i++)
// data[i+zeroes] = revdata[count - 1 - i];
//printf(" count.%d len.%d be_sz.%d zeroes.%d data[0] %02x %02x\n",(int32_t)count,be_sz+zeroes,be_sz,zeroes,data[0],data[1]);
mpz_clear(bn), mpz_clear(bn58);
return(be_sz);
}
#include "../includes/curve25519.h"
@ -4423,6 +4386,55 @@ bits256 mpz_to_bits256(mpz_t bn)
return(x);
}
int32_t bitcoin_base58decode(uint8_t *data,char *coinaddr)
{
uint32_t zeroes,be_sz=0; size_t count; const char *p,*p1; mpz_t bn58,bn; int32_t nonz=0;
mpz_init_set_ui(bn58,58);
mpz_init_set_ui(bn,0);
while ( isspace((uint32_t)(*coinaddr & 0xff)) )
coinaddr++;
for (p=coinaddr; *p; p++)
{
p1 = strchr(base58_chars,*p);
if ( p1 == 0 )
{
while (isspace((uint32_t)*p))
p++;
if ( *p != '\0' )
{
printf("bitcoin_base58decode error: p %02x != 0x00\n",*p);
mpz_clear(bn), mpz_clear(bn58);
return(-1);
}
break;
}
mpz_mul(bn,bn,bn58);
mpz_add_ui(bn,bn,(int32_t)(p1 - base58_chars));
//printf("%d ",(int32_t)(p1 - base58_chars));
nonz++;
}
//printf("nonz.%d\n",nonz);
zeroes = 0;
for (p=coinaddr; *p==base58_chars[0]; p++)
data[zeroes++] = 0;
mpz_export(data+zeroes,&count,1,sizeof(data[0]),-1,0,bn);
/*if ( 0 )
{
bits256 privkey; char *bits256_str(char *str,bits256 privkey);
privkey = mpz_to_bits256(bn);
char str[65]; printf("bn -> %s\n",bits256_str(str,privkey));
}*/
if ( count >= 2 && data[count - 1] == 0 && data[count - 2] >= 0x80 )
count--;
be_sz = (uint32_t)count + (uint32_t)zeroes;
//memset(data,0,be_sz);
//for (i=0; i<count; i++)
// data[i+zeroes] = revdata[count - 1 - i];
//printf(" count.%d len.%d be_sz.%d zeroes.%d data[0] %02x %02x\n",(int32_t)count,be_sz+zeroes,be_sz,zeroes,data[0],data[1]);
mpz_clear(bn), mpz_clear(bn58);
return(be_sz);
}
bits256 mpz_muldivcmp(bits256 oldval,int32_t mulval,int32_t divval,bits256 targetval)
{
mpz_t bn,target; bits256 newval;

Loading…
Cancel
Save