Browse Source

exchanges API

release/v0.1
jl777 9 years ago
parent
commit
64094392ef
  1. 2
      InstantDEX/exchanges/coinbase.c
  2. 2
      crypto777/OS_portable.h
  3. 1
      crypto777/bitcoind_RPC.c
  4. 1772
      iguana/BTCD_hdrs.txt
  5. 49
      iguana/BTCD_peers.txt
  6. 195
      iguana/BTC_hdrs.txt
  7. 137
      iguana/BTC_peers.txt
  8. 582
      iguana/InstantDEX/InstantDEX.c
  9. 223
      iguana/InstantDEX/InstantDEX_quote.h
  10. 1407
      iguana/InstantDEX/exchange_trades.h
  11. 1208
      iguana/InstantDEX/exchangeparse.h
  12. 1812
      iguana/InstantDEX/prices777.c
  13. 880
      iguana/InstantDEX/quotes.h
  14. 1016
      iguana/InstantDEX/quotes777.c
  15. 1496
      iguana/InstantDEX/subatomic.h
  16. 323
      iguana/InstantDEX/tradebots.h
  17. 1583
      iguana/InstantDEX/trades.h
  18. 262
      iguana/exchanges/bitfinex.c
  19. 170
      iguana/exchanges/bitstamp.c
  20. 245
      iguana/exchanges/bittrex.c
  21. 321
      iguana/exchanges/btc38.c
  22. 216
      iguana/exchanges/btce.c
  23. 53
      iguana/exchanges/checkbalance.c
  24. 229
      iguana/exchanges/coinbase.c
  25. 184
      iguana/exchanges/huobi.c
  26. 283
      iguana/exchanges/lakebtc.c
  27. 243
      iguana/exchanges/okcoin.c
  28. 230
      iguana/exchanges/poloniex.c
  29. 185
      iguana/exchanges/quadriga.c
  30. 68
      iguana/exchanges777.h
  31. 1
      iguana/iguana777.h
  32. 726
      iguana/iguana_exchanges.c
  33. 16
      iguana/iguana_json.c
  34. 2
      iguana/iguana_peers.c
  35. 5177
      iguana/index7778.html
  36. 3
      iguana/main.c
  37. 3456
      iguana/orderbooks.h
  38. 2
      iguana/pangea_hand.c
  39. 13
      includes/iguana_apideclares.h
  40. 7
      includes/iguana_apidefs.h
  41. 4
      includes/iguana_apiundefs.h

2
InstantDEX/exchanges/coinbase.c

@ -93,7 +93,7 @@ cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_i
sprintf(hdr2,"CB-ACCESS-SIGN:%s",sig64);
sprintf(hdr3,"CB-ACCESS-TIMESTAMP:%llu",(long long)nonce);
//sprintf(hdr4,"CB-ACCESS-PASSPHRASE:%s; content-type:application/json; charset=utf-8",exchange->userid);
sprintf(hdr4,"CB-ACCESS-PASSPHRASE:%s",exchange->userid);
sprintf(hdr4,"CB-ACCESS-PASSPHRASE:%s",exchange->tradepassword);
sprintf(url,"%s/%s",EXCHANGE_AUTHURL,path);
if ( dotrade == 0 )
data = exchange_would_submit(payload,hdr1,hdr2,hdr3,hdr4);

2
crypto777/OS_portable.h

@ -96,6 +96,8 @@ void _init_HUFF(HUFF *hp,int32_t allocsize,void *buf);
#define portable_mutex_unlock pthread_mutex_unlock
#define OS_thread_create pthread_create
#define issue_curl(cmdstr) bitcoind_RPC(0,"curl",cmdstr,0,0,0)
struct allocitem { uint32_t allocsize,type; } __attribute__((packed));
struct queueitem { struct queueitem *next,*prev; uint32_t allocsize,type; } __attribute__((packed));
typedef struct queue

1
crypto777/bitcoind_RPC.c

@ -18,7 +18,6 @@
#include <curl/curl.h>
#include <curl/easy.h>
#define issue_curl(cmdstr) bitcoind_RPC(0,"curl",cmdstr,0,0,0)
// return data from the server
struct return_string {

1772
iguana/BTCD_hdrs.txt

File diff suppressed because it is too large

49
iguana/BTCD_peers.txt

@ -1,49 +0,0 @@
78.47.58.62
67.212.70.88
94.102.50.69
50.179.58.158
194.135.94.30
109.236.85.42
104.236.127.154
68.45.147.145
37.59.14.7
78.47.115.250
188.40.138.8
62.75.143.120
82.241.71.230
217.23.6.2
73.28.172.128
45.55.149.34
192.0.242.54
81.181.155.53
91.66.185.97
85.25.217.233
144.76.239.66
95.80.9.112
80.162.193.118
173.65.129.85
2.26.173.58
78.14.250.69
188.226.253.77
58.107.67.39
124.191.37.212
176.226.137.238
69.145.25.85
24.168.14.28
73.201.180.47
76.188.171.53
63.247.147.166
121.108.241.247
36.74.36.125
106.186.119.171
188.166.91.37
223.134.228.208
89.248.160.244
178.33.209.212
71.53.156.38
88.198.10.165
24.117.221.0
74.14.104.57
158.69.27.82
110.174.129.213
75.130.163.51

195
iguana/BTC_hdrs.txt

@ -1,195 +0,0 @@
386001
0 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
2000 00000000dfd5d65c9d8561b4b8f60a63018fe3933ecb131fb37f905f87da951a
4000 00000000922e2aa9e84a474350a3555f49f06061fd49df50a9352f156692a842
6000 00000000dbbb79792303bdd1c6c4d7ab9c21bba0667213c2eca955e11230c5a5
8000 0000000094fbacdffec05aea9847000522a258c269ae37a74a818afb96fc27d9
10000 0000000099c744455f58e6c6e98b671e1bf7f37346bfd4cf5d0274ad8ee660cb
12000 0000000011d1d9f1af3e1d038cebba251f933102dbe181d46a7966191b3299ee
14000 000000002d9050318ec8112057423e30b9570b39998aacd00ca648216525fce3
16000 00000000679a1ab3af6da03f13a0bc96d7215e65458b2d2edfa030b5b431e8b3
18000 00000000f914f0d0692e56bd06565ac4de668251b6a29fe0535d1e0031cfd0de
20000 00000000770ebe897270ca5f6d539d8afb4ea4f4e757761a34ca82e17207d886
22000 000000004625a14242beccb38c63a1f770a76ee5788764e6c0abd4129bbc1b9d
24000 00000000f04fccc81f37002707e9501a3f7bdcf25f65531f386a2da8af20122e
26000 000000006d6c151db6d4d67356d590a897a11cd7d8111ee989de6f2f548410bf
28000 00000000172c5ed49d7dfc29bf9a18a53fa2d050fa37aa210d6d4080fd0c7e67
30000 00000000de1250dc2df5cf4d877e055f338d6ed1ab504d5b71c097cdccd00e13
32000 00000000049172ba3ec1b673cf13e3d0049c1c07bb103ed3fa300e3833480055
34000 00000000495968d19210d3be15bd24fdc19805a0ef15026b0bb4482b04a9da3c
36000 0000000080c3deea35dc3df90a5fbe5f27db52f5e01018ae7d62f8b454c71335
38000 000000002dfebce284d1e08b6cf04452530891579b7377669865889498de8f3f
40000 00000000504d5fa0ad2cb90af16052a4eb2aea70fa1cba653b90a4583c5193e4
42000 000000000f80c09687893406279f62da437a6a0b95b8dc096b30c10ce088fc64
44000 000000000122898b31073a770a97cf599c00672fc8d6ae15652235862f8b76d8
46000 000000001dd39771dbe4f9fc6da07327f13f894dd2c1a46cdfcedf930fbbc52b
48000 000000000f3d40ea2bfa8d779010e52cff4720c072ec4b12ed576cf5cf93c947
50000 000000001aeae195809d120b5d66a39c83eb48792e068f8ea1fea19d84a4278a
52000 00000000082bc4398c4aa5bd8d9fc452d60d533ef68baabf594c9e7d6649049f
54000 00000000144197f54afa21ae7db2bc93eee604432101fc0ebe7966a52bb27e61
56000 000000000dfa452ea45e0426dd8914c35e24dfd4399037c5e6deb9f18f58d6d3
58000 0000000013e3791d288d9db814c52fbdf240b2206eb8e19d7dc80013c60c0c00
60000 000000000b554c46f8eb7264d7d5e334382c6fc3098dabf734de37962ccd7495
62000 0000000006dd4bc72daabef992f860e703820de119af3e24a1ea6f6c81521011
64000 0000000003d7055b51d7b9ab693de84c03201fe0396af61dbb30bf31445d3f55
66000 00000000071d7e8a0f4895e60c1073df9311d65a85244be1ee6369c9506281af
68000 0000000000d991791fdfdbccbbc2a73d2f86ccf78e2d0a7ce7675f40b5986b3e
70000 00000000002b8cd0faa58444df3ba2a22af2b5838c7e4a5b687444f913a575c2
72000 0000000000eb357d4c6fef6ad9a6fade126985ad36042a99cf215a4454545977
74000 0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20
76000 0000000000571138ff757a28ddf9b56f28c4a461e170660bb5ae79a556069bb6
78000 00000000001f3fe62641b473673c9ababbe207046a109f0861af95c905a918fa
80000 000000000043a8c0fd1d6f726790caa2a406010d19efd2780db27bdbbd93baf6
82000 00000000000c9d1c4acc114afb58d55db5ec44a963263cf6247220b7a3f85c5c
84000 00000000001385326e30864192ba84ed2f9cbfadf0698655b1c25f93c92f22ad
86000 000000000000ff4e1adb14f07774dad6b34968a5e19d1a2fe1fc9157e7c2b85d
88000 00000000000ae9e98b82b39a912cdc0ebed97c26376780ac996c84d9ec3264a4
90000 0000000000071694daf735a6b5da101d77a04c7e6008c680e461f0025ba7b7af
92000 0000000000001df90b0c523a4d7e4731336b00cf4ba9d8e02d111523df80998c
94000 000000000002a4c42580d51f0ddfd867eaaa790781c484c633a69167d17b48ec
96000 000000000002c86b568cdd2d0f4b0430cccf42bcde3361f63a32e23b5d839e99
98000 000000000002272a6dfb695d9db936d813bf0055ae92e920c2791d4c5f7290f1
100000 000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506
102000 00000000000335c47dd6ae953912d172a4d9839355f2083165043bb6f43c2f58
104000 000000000000a9887c91956b638bb3c0651321fdb24715354c3fc6633f5a16a3
106000 00000000000058d919f52d255f394ed0aa3a344432676fd30f1aab4e10c22fad
108000 00000000000167cea0b43ff7ce22f330d3e302832187eb31c61b15bb1511e118
110000 000000000001bbda3f22ef8e476b470a2d3ae16821c23a6d22db77318d0799a9
112000 0000000000001d69b3899a49f37799c375a7471829953d5470f468f48ff70432
114000 0000000000003195a1e6dc48a540264d37e9ef79b552bd78ea4b93a3b6e7e449
116000 00000000000007ff257fb2edd3fdbd7b00c127a66dae1288fc5e26c402d13bf7
118000 000000000000774a7f8a7a12dc906ddb9e17e75d684f15e00f8767f9e8f36553
120000 0000000000000e07595fca57b37fea8522e95e0f6891779cfd34d7e537524471
122000 0000000000002fe5f29af38282ac1c8f4ea2bf8a0855946150130419491b6c05
124000 00000000000023e9a0523cfac29afe07a07acf81e273cd892c51ff8318846620
126000 000000000000166b7d480aada35af1e6f9a2835d68f9c2fbd272073dc6c9d5fb
128000 00000000000003b8ddd8692769e1965554a8bb030863e0566a28bc0dc952864e
130000 00000000000011906b491883ab0f16f0e690b133ca860b199b775c3cf6581c21
132000 00000000000000a7a0483857f0d951983ff2834a47c38fdcc22563ac0f8f707b
134000 00000000000007e3e442ce1423496a064a7c34342ba98be164ac0c9f9b872213
136000 00000000000004da0d6d69fd474fa08fe2ff3111ff1e9e01f72899dcd9d897f0
138000 0000000000000044c7b6a5511c0b2ae64ec545abccac8053f31cf7bba23bb886
140000 000000000000086e28cf4717a80066def0ec26c53d660582bd997221fef297db
142000 00000000000006379826f5f10cd23739b9c29f87ca10f199f9f4b72006311f85
144000 0000000000000681a73f1bb50454cee419048d24e1091bcddadded89df53fd07
146000 0000000000000188cbeebda87456f040370995dc11eb3a1e76b1577b6e0b588d
148000 00000000000008be94b219a94752bde6a6a1c5b9d72abf2aaab53df7d93c5fa6
150000 0000000000000a3290f20e75860d505ce0e948a1d1d846bec7e39015d242884b
152000 0000000000000aca2b3a267dab498adc48afd15b60cbf21fa58dc26c86a6dc13
154000 0000000000000a7446d1a63b8229670aa02d1d9fdfd729b89107fe5d88dacd8e
156000 00000000000002adfcffbd5f09744ae3b930597dd0ea684cd37b816783ba3762
158000 00000000000000e50d56f13c7ce64183386abcac63462ca745b711be27568f52
160000 000000000000066c6e629b2fb49c7fcc52b82fe9833f328e0c3943856facf231
162000 00000000000001a83f5b20cd132f38f792fc02a17eb14d494c780ea9d1c82acc
164000 00000000000005a38f162cf308edea0a0a5d000bdb2073cba2386ebb1df7a2cf
166000 00000000000003b3402f35327d144a465f3768d6e6cb06cd8a2d8fc1328b2477
168000 000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763
170000 000000000000051f68f43e9d455e72d9c4e4ce52e8a00c5e24c07340632405cb
172000 0000000000000837e82c3a4ebe35a1d1d943e056234dba7c629922c6d4052d4c
174000 0000000000000504d3e701deb624eee4370f50c3d688fd1c27be5bbef07d76dd
176000 00000000000004659b5b8602b2132b62973994079a1c828df6ef8d6427e4686b
178000 00000000000009eae2697a7aaf57e730b707b9f4530449c16d924d534d41f297
180000 00000000000004ff83b6c10460b239ef4a6aa320e5fffd6c7bcedefa8c78593c
182000 000000000000068dce12903c1447e4c5b60311b61e443a25d5fc82c77f4f9a8f
184000 000000000000060405a235c6b968ccb18fd6b3800ae9742c2524e28863367359
186000 000000000000072ede9629fd1fd1af3cc2baa0e637f1959f34884be0e160dd1c
188000 000000000000004cf0c72d6dedfde88ca4c3dae129563210072ee68acded0ab1
190000 0000000000000708bf3b261ffc963b6a768d915f9cfc9ec0a6c2a09969efad1a
192000 00000000000000af130d565291ba49208c546685c69b48a293aaf06387fc22ef
194000 000000000000046242d4984ecf2217e9afa113f2835bffbff118f2df4d80b216
196000 00000000000006ae59396d4a289e83fe1b9967630752a5799f064620af7836a9
198000 000000000000000f2ad431ff18ab1673d911395c8fa1f6801e054c5dcb54f8fb
200000 000000000000034a7dedef4a161fa058a2d67a173a90155f3a2fe6fc132e0ebf
202000 00000000000003282fe1d5533e4275fd9f51e6ba0352ec01f32914e9fbaeaf55
204000 0000000000000423eb625dc140272ab97fea3ba6baf1dc56de77deabcc492872
206000 0000000000000130b815d40fd6d8851438cd21ac9e428615ba03a1285ef1374c
208000 000000000000001db5a1515a5f8534c941b1628f60466e6b709b3b320254afff
210000 000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e
212000 00000000000003d906e4131c39f7655b72df40146d2967f5d75113a09610de61
214000 00000000000003e6427f9fafa8b0e1af0859f15cea90d911f64445d296a2781a
216000 00000000000001f79a2db15d0ec6d951729e044749372caf504679bba5b1e65e
218000 0000000000000569070e338293af66258adba29dcdd5f33212314dff752ff458
220000 000000000000002fdd2c741ed50bc3975a640ca419081711f30f553939641303
222000 00000000000002c752a481ce0c45450ab046e640d38d6532178721e7700d8148
224000 0000000000000107ee276d037218bf1780dbf6d4256bd7e05c66ca133bbc9ac5
226000 000000000000012c614cf477c3b155d339f29d565c0258f9846c2f4dd402ff9b
228000 00000000000000efc4311c93fafbccedb6fdc682b566cba9519f1736b9788a67
230000 000000000000012cfb19f5662707816e122ad60dd9b1cd646c6c9899be2c9667
232000 000000000000018f47636e1c3a946db77624880ae484ffb0233f5aac6316b3bb
234000 00000000000000597f9263ea97bed4d3b10fbd55733a73bd1027f1a9b6c1451a
236000 00000000000000f2f5e55e89dde082cecc9b4a46a10bbb4197f5e35b16612db5
238000 000000000000010014007d4b51ab60063684665401e448c6b0b1971a7398a442
240000 000000000000000e7ad69c72afc00dc4e05fc15ae3061c47d3591d07c09f2928
242000 00000000000000c95233d37a8c78dff10afecb14060347151b7eb7a04a2a5a3c
244000 000000000000006ded1526017d5b87ca22e1bd0da3921872cc99e9ec77ee5166
246000 000000000000004c318a3ad2ebac28d140fada215b11f5b7d8e9151ff0b000af
248000 000000000000004d945017c14b75a3a58a2aa6772cacbfcaf907b3bee6d7f344
250000 000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214
252000 00000000000000200e99940b296ded4ce16462bba1950453b29abf313ba7cc47
254000 000000000000004753be91559a2c74c6cb8a5d2be6db1df2ca0b2385697e53ff
256000 00000000000000252b217c0ce5c4d96b825b90dacbe8e4dcf5f6a8ba6749f3c2
258000 00000000000000159f682a983465761f471dd24300746efe8db5642411f1b631
260000 000000000000001fb91fbcebaaba0e2d926f04908d798a8b598c3bd962951080
262000 000000000000001002ac67e026c523c3779b1ff2e3b9e2b7bfa6022ee1afae2a
264000 000000000000000d05c31485c532503939ca0b88d7e322dff79900ee6cdd5ed4
266000 0000000000000009d755c65d58c7c1fde9167ba632a85574de3bb11c8a862e35
268000 000000000000000048974ba0669938f7f8463650cd5c48c027aafd88c00a46af
270000 0000000000000002a775aec59dc6a9e4bb1c025cf1b8c2195dd9dc3998c827c5
272000 00000000000000050a89e2ffb28757d35e14615f23b981eca68906c8c71f65f2
274000 0000000000000003fe2d3425e9f9b906f02f40b3db90d908ba0fbd1e44cf43f8
276000 0000000000000004b8ed801f8a09ba8c1248a5b1dd1533a35124a80438573f59
278000 0000000000000001bcadd1e4b4d01063a17347dfca126c63893d2aa37d82eb7f
280000 0000000000000001c091ada69f444dc0282ecaabe4808ddbb2532e5555db0c03
282000 0000000000000002337ad25e6a9767420766309cfea79f13dd9c910bcf5ca063
284000 0000000000000000eac86582f121e5431734e2ea36bf73347022c99c1adae37f
286000 00000000000000004388ae444347bde423f2f3aa6ef335b50909f5bc27d31ea3
288000 00000000000000003c395f08779c3ac1301488b8a18c0999c008129a55610785
290000 0000000000000000fa0b2badd05db0178623ebf8dd081fe7eb874c26e27d0b3b
292000 0000000000000000620671231acb6a68134a0396235dcb0e53f4fc82bbaa1184
294000 0000000000000000cb2540b3f00ce422887904c75b24bf75b8a73817302a4138
296000 00000000000000009570102278e59ecf045c16ec8c8a5ea85bf823d0ec72e3d0
298000 000000000000000047d2f2eb7278e3f4aded9acaf502f5ec27bab5018b5871f2
300000 000000000000000082ccf8f1557c5d40b21edabb18d2d691cfbf87118bac7254
302000 0000000000000000072268c9bb18603566ed5012378c29bb4d37e34cead7448d
304000 00000000000000003558a1ceec3f5338c0e887b4171410195a7fa0a81bcaa628
306000 00000000000000002bb3265a8bf67ec2aa436c297ac7e56fcedd4dbaecccacc0
308000 00000000000000001d55aa114bddd81938d09e2dccd432dec59a4078ca0bc0f4
310000 0000000000000000125a28cc9e9209ddb75718f599a8039f6c9e7d9f1fb021e0
312000 00000000000000002bd1fa27964e31fe9861b40940e7ece2cfa359765b219a49
314000 000000000000000008ae6cb20997f3c4aacc50ee2f0d08a0c3691907fe7357a3
316000 00000000000000000d77a89ab1069e47d1213ae509de95ee0d9ab095a725f7d7
318000 00000000000000002583a647dc5f084a312e12bb90a70c3fe1eb1e4d419f35b6
320000 000000000000000015aab005b28a326ade60f07515c33517ea5cb598f28fb7ea
322000 0000000000000000177da809382f93ca1c4336811e4a910050689d317d62264e
324000 00000000000000000b9880c40075d763b2a5f04fc01444a6278c5d2d442cda0b
326000 00000000000000001e95e7216072cd53353b964054b592f7ce84d3743aab125a
328000 000000000000000009cb9a303d105e7b96b36546a3196f6f79ece4b43712cbb2
330000 00000000000000000faabab19f17c0178c754dbed023e6c871dcaf74159c5f02
332000 00000000000000001799255bc0c35f91f7d4fddfbf7e84dedf94fc59cde9b7f2
334000 000000000000000008d1ff7b7673837e9d7e1324dc7ab8498405ea583f43f53d
336000 0000000000000000125e3e6f327edcd7163b486efc16e79b8a996270127b54df
338000 00000000000000001983dc4a87df627b63cdce28e5321cb867fbbb74c0e87e8e
340000 00000000000000000d9b2508615d569e18f00c034d71474fc44a43af8d4a5003
342000 0000000000000000007220892af98a563a1c891c756e94be3f14edddcf637c3e
344000 000000000000000005f0a16f5a9f95eeb95c5eed0eb221e8f5dc5a9943a03aee
346000 0000000000000000068d33fd865621cb7eedbf05c6b235191fa1cb8ee2c797d7
348000 00000000000000001598a651988bb3a45237c4f801cf8049be20f74aed8e827a
350000 0000000000000000053cf64f0400bb38e0c4b3872c38795ddde27acb40a112bb
352000 00000000000000001635a4b5f27d2ec458f7bca550d71f490b93e98e7a07cbca
354000 00000000000000000cf8af9be2709e9d7adf2c33b3789aeeff517987f4be22e8
356000 0000000000000000138ce5493b612b0e90b66e2a76714088d6b3e6a4770215af
358000 0000000000000000073aceefab8c381c3c4edb4f87a6d5d2ae32184278218429
360000 00000000000000000ca6e07cf681390ff888b7f96790286a440da0f2b87c8ea6
362000 00000000000000000bfcad6c331dd152cfc713e9e0790978a10e0bfda3e030d5
364000 00000000000000000e20bcf213a0bbd6be88d5fede6b060c737f7f8b7f1df504
366000 0000000000000000138e108e780fdb71eb4cad533b46445ab6befbf9687f561f
368000 00000000000000000d39970aac12754eb89c2dcfda539b65562e5c3fec102c24
370000 000000000000000002cad3026f68357229dd6eaa6bcef6fe5166e1e53b039b8c
372000 0000000000000000028093cc8035a6bc4e0d1b40932c2f8b50312a3fc86bf3da
374000 00000000000000001016aa3783721673bebbcd1efa49946b52cceb09a81465a6
376000 0000000000000000106e9e99cf4fce4e8a4abc97f3e883956e26d76b3a1133ce
378000 00000000000000000516cd5b5f4b7e528d6e61c643595cc818f1d02f53da4281
380000 00000000000000000b06cee3cee10d2617e2024a996f5c613f7d786b15a571ff
382000 000000000000000003cf98590769bde40ffcd6800733ab47dd406d8203e65a89
384000 000000000000000005dc7ea53e2f6eeb09798cc9d2214f09d249661c36c288b3
386000 00000000000000000d94c8c0b0ddec874d2a597e988154733d9ea614292c08bb

137
iguana/BTC_peers.txt

@ -1,137 +0,0 @@
108.58.252.82
74.207.233.193
130.211.146.81
71.193.19.234
173.66.1.180
104.158.113.201
108.207.245.69
107.4.134.66
96.231.100.124
209.6.208.31
69.141.89.74
82.20.129.167
5.9.222.226
149.210.234.41
168.235.85.242
52.91.247.30
191.237.64.28
173.236.101.34
73.189.2.240
106.186.113.184
173.64.13.6
73.166.27.56
70.106.255.189
168.62.188.213
71.234.225.255
24.41.10.204
72.175.146.90
184.107.155.82
162.220.47.150
12.23.127.150
169.228.66.43
192.227.137.5
71.205.232.181
207.182.151.130
46.4.22.45
198.50.238.171
174.59.182.120
66.172.10.4
75.73.82.209
91.121.108.61
24.6.74.4
37.187.78.27
96.32.46.235
107.170.13.184
148.251.151.48
178.62.70.16
144.76.185.151
144.76.92.199
91.121.210.159
76.105.242.7
54.84.231.113
89.187.134.220
64.15.77.36
212.51.147.153
216.15.33.203
74.100.90.30
185.18.6.3
104.131.65.197
89.248.174.54
128.8.124.7
54.232.245.146
67.205.101.120
72.207.119.149
192.95.27.144
69.61.93.240
209.91.190.202
50.35.82.152
66.175.220.212
23.239.22.219
73.229.104.201
207.244.73.8
78.129.251.170
139.162.211.181
172.245.5.156
98.144.123.251
177.238.90.180
198.71.92.236
73.254.38.48
75.189.201.141
52.24.104.64
71.231.209.66
87.224.35.189
73.162.143.196
82.204.103.94
91.148.210.17
94.242.229.158
188.121.252.243
70.39.8.97
95.97.112.190
109.228.152.9
91.209.77.101
217.76.121.251
79.136.29.43
178.212.136.92
178.255.41.123
84.212.200.24
91.145.49.56
162.220.246.101
95.167.109.125
153.163.32.61
78.67.29.111
92.247.229.163
210.195.201.103
95.84.162.95
106.38.234.67
186.88.0.18
121.208.106.80
120.55.193.136
124.171.128.201
54.94.163.92
98.217.125.225
104.156.97.121
162.255.117.230
129.13.252.36
79.120.12.63
108.5.176.30
69.144.244.229
76.22.18.34
115.29.186.22
78.46.193.75
213.91.211.17
164.177.179.162
134.249.141.40
69.140.88.12
178.212.136.108
109.120.250.3
154.127.61.55
123.120.167.101
73.210.74.120
82.136.95.220
124.122.212.150
81.191.80.160
96.58.196.51
77.23.111.25
14.175.245.51
76.164.234.12
92.156.214.192

582
iguana/InstantDEX/InstantDEX.c

@ -0,0 +1,582 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#define _issue_curl(curl_handle,label,url) bitcoind_RPC(curl_handle,label,url,0,0,0)
#define INSTANTDEX_MINVOL 75
#define INSTANTDEX_MINVOLPERC ((double)INSTANTDEX_MINVOL / 100.)
#define INSTANTDEX_PRICESLIPPAGE 0.001
#define FINISH_HEIGHT 7
#define INSTANTDEX_TRIGGERDEADLINE 120
#define JUMPTRADE_SECONDS 100
#define INSTANTDEX_ACCT "4383817337783094122"
#define INSTANTDEX_FEE ((long)(2.5 * SATOSHIDEN))
#include "../iguana777.h"
#include "InstantDEX_quote.h"
#define INSTANTDEX_LOCALAPI "allorderbooks", "orderbook", "lottostats", "LSUM", "makebasket", "disable", "enable", "peggyrates", "tradesequence", "placebid", "placeask", "orderstatus", "openorders", "cancelorder", "tradehistory", "balance", "allexchanges",
typedef char *(*json_handler)(int32_t localaccess,int32_t valid,char *sender,cJSON **objs,int32_t numobjs,char *origargstr);
queue_t InstantDEXQ,TelepathyQ,Pending_offersQ;
cJSON *InstantDEX_lottostats();
//#include "NXT_tx.h"
#include "trades.h"
#include "quotes.h"
#include "subatomic.h"
#include "orderbooks.h"
#include "exchangeparse.h"
#include "exchange_trades.h"
#include "exchanges/poloniex.c"
#include "exchanges/bittrex.c"
#include "exchanges/btce.c"
#include "exchanges/bitfinex.c"
#include "exchanges/btc38.c"
#include "exchanges/huobi.c"
#include "exchanges/lakebtc.c"
#include "exchanges/quadriga.c"
#include "exchanges/okcoin.c"
#include "exchanges/coinbase.c"
#include "exchanges/bitstamp.c"
// {"plugin":"InstantDEX","method":"orderbook","baseid":"8688289798928624137","rel":"USD","exchange":"active","allfields":1}
// {"plugin":"InstantDEX","method":"orderbook","baseid":"17554243582654188572","rel":"12071612744977229797","exchange":"active","allfields":1}
// {"plugin":"InstantDEX","method":"orderbook","baseid":"6918149200730574743","rel":"XMR","exchange":"active","allfields":1}
void idle()
{
char *jsonstr,*str; cJSON *json; int32_t n = 0; uint32_t nonce;
/*printf("INSTANTDEX.readyflag.%d\n",INSTANTDEX.readyflag);
while ( INSTANTDEX.readyflag == 0 )
sleep(1);
printf("INSTANTDEX.readyflag.%d\n",INSTANTDEX.readyflag);*/
while ( 1 )
{
if ( n == 0 )
sleep(1);
n = 0;
if ( (jsonstr= queue_dequeue(&InstantDEXQ,1)) != 0 )
{
printf("Dequeued InstantDEX.(%s)\n",jsonstr);
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
//fprintf(stderr,"dequeued\n");
if ( (str= busdata_sync(&nonce,jsonstr,"allnodes",0)) != 0 )
{
//fprintf(stderr,"busdata.(%s)\n",str);
free(str);
}
free_json(json);
n++;
} else printf("error parsing (%s) from InstantDEXQ\n",jsonstr);
free_queueitem(jsonstr);
}
}
}
uint32_t _get_NXTheight(uint32_t *firsttimep)
{
static uint32_t last,lastheight,lastNXTtime;
cJSON *json; uint32_t height = 0; char cmd[256],*jsonstr;
if ( time(NULL) > last+10 )
{
sprintf(cmd,"requestType=getState");
if ( (jsonstr= issue_NXTPOST(cmd)) != 0 )
{
//printf("(%s) -> (%s)\n",cmd,jsonstr);
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
if ( firsttimep != 0 )
lastNXTtime = *firsttimep = (uint32_t)get_cJSON_int(json,"time");
height = (int32_t)get_cJSON_int(json,"numberOfBlocks");
if ( height > 0 )
height--;
lastheight = height;
free_json(json);
}
free(jsonstr);
}
last = (uint32_t)time(NULL);
}
else
{
height = lastheight;
if ( firsttimep != 0 )
*firsttimep = lastNXTtime;
}
return(height);
}
void idle2()
{
static double lastmilli;
uint32_t NXTblock;
//while ( INSTANTDEX.readyflag == 0 )
// sleep(1);
while ( 1 )
{
if ( milliseconds() < (lastmilli + 5000) )
sleep(1);
NXTblock = _get_NXTheight(0);
if ( 1 && NXTblock != prices777_NXTBLOCK )
{
prices777_NXTBLOCK = NXTblock;
InstantDEX_update(IGUANA_NXTADDR,IGUANA_NXTACCTSECRET);//,SUPERNET.);
//fprintf(stderr,"done idle NXT\n");
}
lastmilli = milliseconds();
}
}
cJSON *InstantDEX_lottostats()
{
char cmdstr[1024],NXTaddr[64],buf[1024],*jsonstr; struct destbuf receiverstr;
cJSON *json,*array,*txobj; int32_t i,n,totaltickets = 0; uint64_t amount,senderbits; uint32_t timestamp = 0;
if ( timestamp == 0 )
timestamp = 38785003;
sprintf(cmdstr,"requestType=getBlockchainTransactions&account=%s&timestamp=%u&type=0&subtype=0",INSTANTDEX_ACCT,timestamp);
//printf("cmd.(%s)\n",cmdstr);
if ( (jsonstr= issue_NXTPOST(cmdstr)) != 0 )
{
// printf("jsonstr.(%s)\n",jsonstr);
// mm string.({"requestProcessingTime":33,"transactions":[{"fullHash":"2a2aab3b84dadf092cf4cedcd58a8b5a436968e836338e361c45651bce0ef97e","confirmations":203,"signatureHash":"52a4a43d9055fe4861b3d13fbd03a42fecb8c9ad4ac06a54da7806a8acd9c5d1","transaction":"711527527619439146","amountNQT":"1100000000","transactionIndex":2,"ecBlockHeight":360943,"block":"6797727125503999830","recipientRS":"NXT-74VC-NKPE-RYCA-5LMPT","type":0,"feeNQT":"100000000","recipient":"4383817337783094122","version":1,"sender":"423766016895692955","timestamp":38929220,"ecBlockId":"10121077683890606382","height":360949,"subtype":0,"senderPublicKey":"4e5bbad625df3d536fa90b1e6a28c3f5a56e1fcbe34132391c8d3fd7f671cb19","deadline":1440,"blockTimestamp":38929430,"senderRS":"NXT-8E6V-YBWH-5VMR-26ESD","signature":"4318f36d9cf68ef0a8f58303beb0ed836b670914065a868053da5fe8b096bc0c268e682c0274e1614fc26f81be4564ca517d922deccf169eafa249a88de58036"}]})
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
if ( (array= cJSON_GetObjectItem(json,"transactions")) != 0 && is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
txobj = cJSON_GetArrayItem(array,i);
copy_cJSON(&receiverstr,cJSON_GetObjectItem(txobj,"recipient"));
if ( strcmp(receiverstr.buf,INSTANTDEX_ACCT) == 0 )
{
if ( (senderbits = get_API_nxt64bits(cJSON_GetObjectItem(txobj,"sender"))) != 0 )
{
expand_nxt64bits(NXTaddr,senderbits);
amount = get_API_nxt64bits(cJSON_GetObjectItem(txobj,"amountNQT"));
if ( amount == INSTANTDEX_FEE )
totaltickets++;
else if ( amount >= 2*INSTANTDEX_FEE )
totaltickets += 2;
}
}
}
}
free_json(json);
}
free(jsonstr);
}
sprintf(buf,"{\"result\":\"lottostats\",\"totaltickets\":\"%d\"}",totaltickets);
return(cJSON_Parse(buf));
}
void set_best_amounts(int64_t *baseamountp,int64_t *relamountp,double price,double volume)
{
double checkprice,checkvol,distA,distB,metric,bestmetric = (1. / SMALLVAL);
uint64_t baseamount,relamount,bestbaseamount = 0,bestrelamount = 0;
int32_t i,j;
baseamount = volume * SATOSHIDEN;
relamount = ((price * volume) * SATOSHIDEN);
//*baseamountp = baseamount, *relamountp = relamount;
//return;
for (i=-1; i<=1; i++)
for (j=-1; j<=1; j++)
{
checkprice = prices777_price_volume(&checkvol,baseamount+i,relamount+j);
distA = (checkprice - price);
distA *= distA;
distB = (checkvol - volume);
distB *= distB;
metric = sqrt(distA + distB);
if ( metric < bestmetric )
{
bestmetric = metric;
bestbaseamount = baseamount + i;
bestrelamount = relamount + j;
//printf("i.%d j.%d metric. %f\n",i,j,metric);
}
}
*baseamountp = bestbaseamount;
*relamountp = bestrelamount;
}
int32_t bidask_parse(int32_t localaccess,struct destbuf *exchangestr,struct destbuf *name,struct destbuf *base,struct destbuf *rel,struct destbuf *gui,struct InstantDEX_quote *iQ,cJSON *json)
{
uint64_t basemult,relmult,baseamount,relamount; double price,volume; int32_t exchangeid,keysize,flag; char key[1024],buf[64],*methodstr;
memset(iQ,0,sizeof(*iQ));
iQ->s.baseid = j64bits(json,"baseid"); iQ->s.relid = j64bits(json,"relid");
iQ->s.baseamount = j64bits(json,"baseamount"), iQ->s.relamount = j64bits(json,"relamount");
iQ->s.vol = jdouble(json,"volume"); iQ->s.price = jdouble(json,"price");
copy_cJSON(exchangestr,jobj(json,"exchange"));
if ( exchangestr->buf[0] == 0 || find_exchange(&exchangeid,exchangestr->buf) == 0 )
exchangeid = -1;
iQ->exchangeid = exchangeid;
copy_cJSON(base,jobj(json,"base"));
copy_cJSON(rel,jobj(json,"rel"));
copy_cJSON(name,jobj(json,"name"));
methodstr = jstr(json,"method");
if ( methodstr != 0 && (strcmp(methodstr,"placeask") == 0 || strcmp(methodstr,"ask") == 0) )
iQ->s.isask = 1;
if ( iQ->s.vol < 0. )
{
iQ->s.vol = -iQ->s.vol;
iQ->s.isask ^= 1;
}
if ( methodstr != 0 && strcmp(exchangestr->buf,"wallet") == 0 && (iQ->s.baseid == NXT_ASSETID || strcmp(base->buf,"NXT") == 0) )
{
flag = 1;
if ( strcmp(methodstr,"placeask") == 0 )
methodstr = "placebid";
else if ( strcmp(methodstr,"placebid") == 0 )
methodstr = "placeask";
else if ( strcmp(methodstr,"ask") == 0 )
methodstr = "bid";
else if ( strcmp(methodstr,"bid") == 0 )
methodstr = "ask";
else flag = 0;
if ( flag != 0 )
{
iQ->s.baseid = iQ->s.relid, iQ->s.relid = NXT_ASSETID;
strcpy(base->buf,rel->buf), strcpy(rel->buf,"NXT");
baseamount = iQ->s.baseamount;
iQ->s.baseamount = iQ->s.relamount, iQ->s.relamount = baseamount;
name->buf[0] = 0;
if ( iQ->s.vol > SMALLVAL && iQ->s.price > SMALLVAL )
{
iQ->s.vol *= iQ->s.price;
iQ->s.price = 1. / iQ->s.price;
}
iQ->s.isask ^= 1;
printf("INVERT\n");
}
}
if ( (iQ->s.timestamp= juint(json,"timestamp")) == 0 )
iQ->s.timestamp = (uint32_t)time(NULL);
copy_cJSON(gui,jobj(json,"gui")), strncpy(iQ->gui,gui->buf,sizeof(iQ->gui)-1);
iQ->s.automatch = juint(json,"automatch");
iQ->s.minperc = juint(json,"minperc");
if ( (iQ->s.duration= juint(json,"duration")) == 0 || iQ->s.duration > ORDERBOOK_EXPIRATION )
iQ->s.duration = ORDERBOOK_EXPIRATION;
InstantDEX_name(key,&keysize,exchangestr->buf,name->buf,base->buf,&iQ->s.baseid,rel->buf,&iQ->s.relid);
//printf(">>>>>>>>>>>> BASE.(%s) REL.(%s)\n",base->buf,rel->buf);
iQ->s.basebits = stringbits(base->buf);
iQ->s.relbits = stringbits(rel->buf);
safecopy(iQ->base,base->buf,sizeof(iQ->base));
safecopy(iQ->rel,rel->buf,sizeof(iQ->rel));
iQ->s.offerNXT = j64bits(json,"offerNXT");
iQ->s.quoteid = j64bits(json,"quoteid");
if ( strcmp(exchangestr->buf,"jumblr") == 0 || strcmp(exchangestr->buf,"pangea") == 0 )
{
if ( strcmp(exchangestr->buf,"pangea") == 0 )
{
if ( juint(json,"rakemillis") != 0 )
iQ->s.minperc = juint(json,"rakemillis");
if ( j64bits(json,"bigblind") != 0 )
{
iQ->s.baseamount = j64bits(json,"bigblind");
iQ->s.vol = ((double)iQ->s.baseamount / SATOSHIDEN);
}
if ( j64bits(json,"ante") != 0 )
iQ->s.relamount = j64bits(json,"ante");
iQ->s.minbuyin = juint(json,"minbuyin");
iQ->s.maxbuyin = juint(json,"maxbuyin");
/*if ( (iQ->s.maxrake= j64bits(json,"maxrake")) != 0 )
{
if ( strcmp(base->buf,"BTC") == 0 && iQ->s.maxrake < SATOSHIDEN/10 )
iQ->s.maxrake = SATOSHIDEN/10;
else if ( iQ->s.maxrake < 10*SATOSHIDEN )
iQ->s.maxrake = 10*SATOSHIDEN;
}*/
}
if ( iQ->s.price == 0. )
iQ->s.price = 1.;
if ( iQ->s.vol == 0. )
iQ->s.vol = 1.;
if ( iQ->s.baseamount == 0 )
iQ->s.baseamount = iQ->s.vol * SATOSHIDEN;
if ( localaccess != 0 && strcmp(exchangestr->buf,"jumblr") == 0 )
{
#ifdef later
struct coin777 *coin; int32_t maxamount;
if ( (coin= coin777_find(base->buf,0)) != 0 )
{
if ( coin->jvin == 0 && coin->jvinaddr[0] == 0 )
{
coin->jvin = -1;
printf("initial state for jumblr.%s detected\n",coin->name);
sleep(5);
}
if ( coin->jvin < 0 )
{
printf("no %s unspents available for jumblr/pangea jvin.%d %.8f\n",coin->name,coin->jvin,dstr(coin->junspent));
return(-1);
}
maxamount = coin->junspent - coin->mgw.txfee*2 - (coin->junspent>>10);
if ( iQ->s.baseamount > maxamount )
iQ->s.baseamount = maxamount;
else if ( iQ->s.baseamount < coin->mgw.txfee )
{
printf("jumblr/pangea amount %.8f less than txfee %.8f\n",dstr(iQ->s.baseamount),dstr(coin->mgw.txfee));
return(-1);
}
}
else
{
printf("%s not initialized for jumblr\n",base->buf);
return(-1);
}
#endif
}
}
else
{
if ( iQ->s.baseamount == 0 || iQ->s.relamount == 0 )
{
if ( iQ->s.price <= SMALLVAL || iQ->s.vol <= SMALLVAL )
return(-1);
set_best_amounts(&iQ->s.baseamount,&iQ->s.relamount,iQ->s.price,iQ->s.vol);
}
}
if ( iQ->s.quoteid == 0 )
iQ->s.quoteid = calc_quoteid(iQ);
else if ( iQ->s.quoteid != calc_quoteid(iQ) )
{
printf("bidask_parse quoteid.%llu != calc.%llu\n",(long long)iQ->s.quoteid,(long long)calc_quoteid(iQ));
return(-1);
}
if ( iQ->s.price > SMALLVAL && iQ->s.vol > SMALLVAL && iQ->s.baseid != 0 && iQ->s.relid != 0 )
{
buf[0] = 0, _set_assetname(&basemult,buf,0,iQ->s.baseid);
printf("baseid.%llu -> %s mult.%llu\n",(long long)iQ->s.baseid,buf,(long long)basemult);
buf[0] = 0, _set_assetname(&relmult,buf,0,iQ->s.relid);
printf("relid.%llu -> %s mult.%llu\n",(long long)iQ->s.relid,buf,(long long)relmult);
//basemult = get_assetmult(iQ->baseid), relmult = get_assetmult(iQ->relid);
baseamount = (iQ->s.baseamount + basemult/2) / basemult, baseamount *= basemult;
relamount = (iQ->s.relamount + relmult/2) / relmult, relamount *= relmult;
if ( iQ->s.price != 0. && iQ->s.vol != 0 )
{
price = prices777_price_volume(&volume,baseamount,relamount);
if ( fabs(iQ->s.price - price)/price > 0.001 )
{
printf("cant create accurate price ref.(%f %f) -> (%f %f)\n",iQ->s.price,iQ->s.vol,price,volume);
return(-1);
}
}
}
return(0);
}
char *InstantDEX(char *jsonstr,char *remoteaddr,int32_t localaccess)
{
char *prices777_allorderbooks();
char *InstantDEX_tradehistory(cJSON *json,int32_t firsti,int32_t endi);
char *InstantDEX_cancelorder(cJSON *json,char *activenxt,char *secret,uint64_t sequenceid,uint64_t quoteid);
struct destbuf exchangestr,method,gui,name,base,rel; double balance;
char *retstr = 0,key[512],retbuf[1024],*activenxt,*secret,*coinstr; struct InstantDEX_quote iQ; struct exchange_info *exchange;
cJSON *json; uint64_t assetbits,sequenceid; uint32_t maxdepth; int32_t invert=0,keysize,allfields; struct prices777 *prices = 0;
//printf("INSTANTDEX.(%s)\n",jsonstr);
//if ( INSTANTDEX.readyflag == 0 )
// return(0);
if ( jsonstr != 0 && (json= cJSON_Parse(jsonstr)) != 0 )
{
// test: asset/asset, asset/external, external/external, autofill and automatch
// peggy integration
if ( bidask_parse(localaccess,&exchangestr,&name,&base,&rel,&gui,&iQ,json) < 0 && (strcmp(exchangestr.buf,"jumblr") == 0 || strcmp(exchangestr.buf,"pangea") == 0) )
{
//return(clonestr("{\"error\":\"invalid parameters\"}"));
}
if ( iQ.s.offerNXT == 0 )
iQ.s.offerNXT = IGUANA_MY64BITS;
printf("isask.%d base.(%s) rel.(%s)\n",iQ.s.isask,base.buf,rel.buf);
copy_cJSON(&method,jobj(json,"method"));
if ( (sequenceid= j64bits(json,"orderid")) == 0 )
sequenceid = j64bits(json,"sequenceid");
allfields = juint(json,"allfields");
if ( (maxdepth= juint(json,"maxdepth")) <= 0 )
maxdepth = MAX_DEPTH;
if ( exchangestr.buf[0] == 0 )
{
if ( iQ.s.baseid != 0 && iQ.s.relid != 0 )
strcpy(exchangestr.buf,"nxtae");
else strcpy(exchangestr.buf,"basket");
}
assetbits = InstantDEX_name(key,&keysize,exchangestr.buf,name.buf,base.buf,&iQ.s.baseid,rel.buf,&iQ.s.relid);
//printf("2nd isask.%d base.(%s) rel.(%s)\n",iQ.s.isask,base.buf,rel.buf);
exchange = exchange_find(exchangestr.buf);
secret = jstr(json,"secret"), activenxt = jstr(json,"activenxt");
if ( secret == 0 )
{
secret = IGUANA_NXTACCTSECRET;
activenxt = IGUANA_NXTADDR;
}
if ( strcmp(method.buf,"exit") == 0 )
{
printf("getchar and then exit\n");
getchar();
exit(0);
}
if ( strcmp(method.buf,"orderstatus") == 0 )
retstr = InstantDEX_orderstatus(json,sequenceid,iQ.s.quoteid);
else if ( strcmp(method.buf,"cancelorder") == 0 )
retstr = InstantDEX_cancelorder(json,jstr(json,"activenxt"),jstr(json,"secret"),sequenceid,iQ.s.quoteid);
else if ( strcmp(method.buf,"openorders") == 0 )
retstr = InstantDEX_openorders(json,IGUANA_NXTADDR,juint(json,"allorders"));
else if ( strcmp(method.buf,"tradehistory") == 0 )
retstr = InstantDEX_tradehistory(json,juint(json,"firsti"),juint(json,"endi"));
else if ( strcmp(method.buf,"withdraw") == 0 )
retstr = InstantDEX_withdraw(json);
else if ( strcmp(method.buf,"balance") == 0 )
{
if ( exchange != 0 && exchange->issue.trade != 0 )
{
if ( exchange->issue.balances != 0 )
{
if ( exchange->balancejson != 0 )
free_json(exchange->balancejson), exchange->balancejson = 0;
exchange->lastbalancetime = (uint32_t)time(NULL);
if ( (exchange->balancejson= (*exchange->issue.balances)(&exchange->cHandle,exchange)) != 0 )
{
if ( (coinstr= jstr(json,"base")) != 0 )
retstr = (*exchange->issue.parsebalance)(exchange,&balance,coinstr);
else retstr = jprint(exchange->balancejson,0);
} else retstr = clonestr("{\"error\":\"balances null return\"}");
} else retstr = clonestr("{\"error\":\"no balances function\"}");
} else retstr = clonestr("{\"error\":\"cant find exchange trade or balances function\"}");
printf("%s ptr.%p trade.%p\n",exchangestr.buf,exchange,exchange!=0?exchange->issue.trade:0);
}
else if ( strcmp(method.buf,"allorderbooks") == 0 )
retstr = prices777_allorderbooks();
else if ( strcmp(method.buf,"allexchanges") == 0 )
retstr = jprint(exchanges_json(),1);
else if ( strcmp(method.buf,"lottostats") == 0 )
retstr = jprint(InstantDEX_lottostats(),1);
/* else if ( strcmp(method.buf,"tradesequence") == 0 )
{
//printf("call tradesequence.(%s)\n",jsonstr);
int32_t dotrade,numtrades; struct prices777_order trades[256]; struct pending_trade *pend;
dotrade = juint(json,"dotrade");
retstr = InstantDEX_tradesequence(0,0,0,&numtrades,trades,(int32_t)(sizeof(trades)/sizeof(*trades)),dotrade,activenxt,secret,json);
if ( dotrade != 0 )
{
pend = calloc(1,sizeof(*pend));
pend->dir = iQ.s.isask == 0 ? 1 : -1, pend->price = iQ.s.price, pend->volume = iQ.s.vol, pend->orderid = iQ.s.quoteid;
pend->tradesjson = json;
pend->type = 'S';
pend->timestamp = (uint32_t)time(NULL);
//InstantDEX_history(0,pend,0);
queue_enqueue("PendingQ",&Pending_offersQ.pingpong[0],&pend->DL,0);
}
}*/
else if ( strcmp(method.buf,"makebasket") == 0 )
{
if ( (prices= prices777_makebasket(0,json,1,"basket",0,0)) != 0 )
retstr = clonestr("{\"result\":\"basket made\"}");
else retstr = clonestr("{\"error\":\"couldnt make basket\"}");
}
else if ( strcmp(method.buf,"peggyrates") == 0 )
{
//if ( SUPERNET.peggy != 0 )
// retstr = peggyrates(juint(json,"timestamp"),jstr(json,"name"));
//else retstr = clonestr("{\"error\":\"peggy disabled\"}");
}
else if ( strcmp(method.buf,"LSUM") == 0 )
{
sprintf(retbuf,"{\"result\":\"%s\",\"amount\":%d}",(rand() & 1) ? "BUY" : "SELL",(rand() % 100) * 100000);
retstr = clonestr(retbuf);
}
else if ( strcmp(method.buf,"placebid") == 0 || strcmp(method.buf,"placeask") == 0 )
return(InstantDEX_placebidask(0,sequenceid,exchangestr.buf,name.buf,base.buf,rel.buf,&iQ,jstr(json,"extra"),secret,activenxt,json));
else if ( strcmp(exchangestr.buf,"active") == 0 && strcmp(method.buf,"orderbook") == 0 )
retstr = prices777_activebooks(name.buf,base.buf,rel.buf,iQ.s.baseid,iQ.s.relid,maxdepth,allfields,strcmp(exchangestr.buf,"active") == 0 || juint(json,"tradeable"));
else if ( (prices= prices777_find(&invert,iQ.s.baseid,iQ.s.relid,exchangestr.buf)) == 0 )
{
if ( (prices= prices777_poll(exchangestr.buf,name.buf,base.buf,iQ.s.baseid,rel.buf,iQ.s.relid)) != 0 )
{
if ( prices777_equiv(prices->baseid) == prices777_equiv(iQ.s.baseid) && prices777_equiv(prices->relid) == prices777_equiv(iQ.s.relid) )
invert = 0;
else if ( prices777_equiv(prices->baseid) == prices777_equiv(iQ.s.relid) && prices777_equiv(prices->relid) == prices777_equiv(iQ.s.baseid) )
invert = 1;
else invert = 0, printf("baserel not matching (%s %s) %llu %llu vs (%s %s) %llu %llu\n",prices->base,prices->rel,(long long)prices->baseid,(long long)prices->relid,base.buf,rel.buf,(long long)iQ.s.baseid,(long long)iQ.s.relid);
}
}
if ( retstr == 0 && prices != 0 )
{
if ( strcmp(method.buf,"disablequotes") == 0 )
{
if ( prices != 0 )
{
if ( strcmp(prices->exchange,"unconf") == 0 )
return(clonestr("{\"error\":\"cannot disable unconf\"}"));
prices->disabled = 1;
return(clonestr("{\"result\":\"success\"}"));
}
else return(clonestr("{\"error\":\"no prices to disable\"}"));
}
else if ( strcmp(method.buf,"enablequotes") == 0 )
{
if ( prices != 0 )
{
prices->disabled = 0;
return(clonestr("{\"result\":\"success\"}"));
}
else return(clonestr("{\"error\":\"no prices to enable\"}"));
}
else if ( strcmp(method.buf,"orderbook") == 0 )
{
if ( maxdepth < MAX_DEPTH )
return(prices777_orderbook_jsonstr(invert,IGUANA_MY64BITS,prices,&prices->O,maxdepth,allfields));
else if ( (retstr= prices->orderbook_jsonstrs[invert][allfields]) == 0 )
{
retstr = prices777_orderbook_jsonstr(invert,IGUANA_MY64BITS,prices,&prices->O,MAX_DEPTH,allfields);
portable_mutex_lock(&prices->mutex);
if ( prices->orderbook_jsonstrs[invert][allfields] != 0 )
free(prices->orderbook_jsonstrs[invert][allfields]);
prices->orderbook_jsonstrs[invert][allfields] = retstr;
portable_mutex_unlock(&prices->mutex);
if ( retstr == 0 )
retstr = clonestr("{}");
}
if ( retstr != 0 )
retstr = clonestr(retstr);
}
//else if ( strcmp(method.buf,"tradebot") == 0 )
// retstr = InstantDEX_tradebot(prices,json,&iQ,invert);
}
//if ( Debuglevel > 2 )
printf("(%s) %p exchange.(%s) base.(%s) %llu rel.(%s) %llu | name.(%s) %llu\n",retstr!=0?retstr:"",prices,exchangestr.buf,base.buf,(long long)iQ.s.baseid,rel.buf,(long long)iQ.s.relid,name.buf,(long long)assetbits);
}
return(retstr);
}
char *bidask_func(int32_t localaccess,int32_t valid,char *sender,cJSON *json,char *origargstr)
{
struct destbuf gui,exchangestr,name,base,rel,offerNXT; struct InstantDEX_quote iQ;
copy_cJSON(&offerNXT,jobj(json,"offerNXT"));
//printf("got (%s)\n",origargstr);
if ( strcmp(IGUANA_NXTADDR,offerNXT.buf) != 0 )
{
if ( bidask_parse(localaccess,&exchangestr,&name,&base,&rel,&gui,&iQ,json) == 0 )
return(InstantDEX_placebidask(sender,j64bits(json,"orderid"),exchangestr.buf,name.buf,base.buf,rel.buf,&iQ,jstr(json,"extra"),jstr(json,"secret"),jstr(json,"activenxt"),json));
else printf("error with incoming bidask\n");
} else fprintf(stderr,"got my bidask from network (%s)\n",origargstr);
return(clonestr("{\"result\":\"got loopback bidask\"}"));
}

223
iguana/InstantDEX/InstantDEX_quote.h

@ -0,0 +1,223 @@
//
// sha256.h
// crypto777
//
// Created by James on 4/9/15.
// Copyright (c) 2015 jl777. All rights reserved.
//
#ifndef crypto777_InstantDEX_quote_h
#define crypto777_InstantDEX_quote_h
#include <stdint.h>
#include "../includes/uthash.h"
#define NXT_ASSETID ('N' + ((uint64_t)'X'<<8) + ((uint64_t)'T'<<16)) // 5527630
#define MAX_BUYNXT 10
#define MIN_NQTFEE 100000000
#define NXT_TOKEN_LEN 160
#define GENESISACCT "1739068987193023818" // NXT-MRCC-2YLS-8M54-3CMAJ
#define GENESISPUBKEYSTR "1259ec21d31a30898d7cd1609f80d9668b4778e3d97e941044b39f0c44d2e51b"
#define GENESISPRIVKEYSTR "1259ec21d31a30898d7cd1609f80d9668b4778e3d97e941044b39f0c44d2e51b"
#define GENESIS_SECRET "It was a bright cold day in April, and the clocks were striking thirteen."
#define GENESISBLOCK "2680262203532249785"
#define NXT_GENESISTIME 1385294400
#define DEFAULT_NXT_DEADLINE 720
#define issue_curl(cmdstr) bitcoind_RPC(0,"curl",cmdstr,0,0,0)
#define issue_NXT(cmdstr) bitcoind_RPC(0,"NXT",cmdstr,0,0,0)
#define issue_NXTPOST(cmdstr) bitcoind_RPC(0,"curl",NXTAPIURL,0,0,cmdstr)
#define fetch_URL(url) bitcoind_RPC(0,"fetch",url,0,0,0)
#define INSTANTDEX_TRIGGERDEADLINE 120
#define _issue_curl(curl_handle,label,url) bitcoind_RPC(curl_handle,label,url,0,0,0)
#define ORDERBOOK_EXPIRATION 3600
#define INSTANTDEX_MINVOL 75
#define INSTANTDEX_MINVOLPERC ((double)INSTANTDEX_MINVOL / 100.)
#define INSTANTDEX_PRICESLIPPAGE 0.001
#define INSTANTDEX_TRIGGERDEADLINE 120
#define JUMPTRADE_SECONDS 100
#define INSTANTDEX_ACCT "4383817337783094122"
#define INSTANTDEX_FEE ((long)(2.5 * SATOSHIDEN))
#define INSTANTDEX_NAME "InstantDEX"
#define INSTANTDEX_NXTAENAME "nxtae"
#define INSTANTDEX_NXTAEUNCONF "unconf"
#define INSTANTDEX_BASKETNAME "basket"
#define INSTANTDEX_ACTIVENAME "active"
#define INSTANTDEX_EXCHANGEID 0
#define INSTANTDEX_UNCONFID 1
#define INSTANTDEX_NXTAEID 2
#define MAX_EXCHANGES 64
#define ORDERBOOK_EXPIRATION 3600
#define NXT_ASSETID ('N' + ((uint64_t)'X'<<8) + ((uint64_t)'T'<<16)) // 5527630
#define BTC_ASSETID ('B' + ((uint64_t)'T'<<8) + ((uint64_t)'C'<<16)) // 4412482
#define LTC_ASSETID ('L' + ((uint64_t)'T'<<8) + ((uint64_t)'C'<<16))
#define PPC_ASSETID ('P' + ((uint64_t)'P'<<8) + ((uint64_t)'C'<<16))
#define NMC_ASSETID ('N' + ((uint64_t)'M'<<8) + ((uint64_t)'C'<<16))
#define DASH_ASSETID ('D' + ((uint64_t)'A'<<8) + ((uint64_t)'S'<<16) + ((uint64_t)'H'<<24))
#define BTCD_ASSETID ('B' + ((uint64_t)'T'<<8) + ((uint64_t)'C'<<16) + ((uint64_t)'D'<<24))
#define USD_ASSETID ('U' + ((uint64_t)'S'<<8) + ((uint64_t)'D'<<16))
#define CNY_ASSETID ('C' + ((uint64_t)'N'<<8) + ((uint64_t)'Y'<<16))
#define EUR_ASSETID ('E' + ((uint64_t)'U'<<8) + ((uint64_t)'R'<<16))
#define RUR_ASSETID ('R' + ((uint64_t)'U'<<8) + ((uint64_t)'R'<<16))
struct InstantDEX_shared
{
double price,vol;
uint64_t quoteid,offerNXT,basebits,relbits,baseid,relid; int64_t baseamount,relamount;
uint32_t timestamp;
uint16_t duration:14,wallet:1,a:1,isask:1,expired:1,closed:1,swap:1,responded:1,matched:1,feepaid:1,automatch:1,pending:1,minperc:7;
uint16_t minbuyin,maxbuyin;
};
struct InstantDEX_quote
{
UT_hash_handle hh;
struct InstantDEX_shared s; // must be here
char exchangeid,gui[9],base[8],rel[8];
char walletstr[];
};
struct InstantDEX_quote *delete_iQ(uint64_t quoteid);
struct InstantDEX_quote *find_iQ(uint64_t quoteid);
struct InstantDEX_quote *create_iQ(struct InstantDEX_quote *iQ,char *walletstr);
uint64_t calc_quoteid(struct InstantDEX_quote *iQ);
cJSON *set_walletstr(cJSON *walletitem,char *walletstr,struct InstantDEX_quote *iQ);
cJSON *InstantDEX_specialorders(uint64_t *quoteidp,uint64_t nxt64bits,char *base,char *special,uint64_t baseamount,int32_t addrtype);
int32_t bidask_parse(int32_t localaccess,struct destbuf *exchangestr,struct destbuf *name,struct destbuf *base,struct destbuf *rel,struct destbuf *gui,struct InstantDEX_quote *iQ,cJSON *json);
int32_t coin777_addrtype(uint8_t *p2shtypep,char *coinstr);
struct prices777_order
{
struct InstantDEX_shared s; cJSON *retitem; struct prices777 *source; struct pending_trade *pend;
uint64_t id; double wt,ratio; uint16_t slot_ba;
};
struct prices777_basket
{
struct prices777 *prices; double wt;
int32_t groupid,groupsize,aski,bidi;
char base[64],rel[64];
};
struct prices777_orderentry { struct prices777_order bid,ask; };
#define MAX_GROUPS 8
#define _MAX_DEPTH 100
struct prices777_basketinfo
{
int32_t numbids,numasks; uint32_t timestamp;
struct prices777_orderentry book[MAX_GROUPS+1][_MAX_DEPTH];
};
struct NXTtx { uint64_t txid; char fullhash[MAX_JSON_FIELD],utxbytes[MAX_JSON_FIELD],utxbytes2[MAX_JSON_FIELD],txbytes[MAX_JSON_FIELD],sighash[MAX_JSON_FIELD]; };
struct pending_trade
{
struct queueitem DL;
struct NXTtx trigger; struct prices777_order order;
uint64_t triggertxid,txid,quoteid,orderid,my64bits;
struct prices777 *prices; void *cHandlep; struct exchange_info *exchange; void *bot;
char *triggertx,*txbytes,extra[128]; uint8_t nxtsecret[2048]; cJSON *tradesjson,*item;
double price,volume; uint32_t timestamp,finishtime,expiration;
int32_t dir,type,version,size,dotrade,queueflag,*curlingp;
};
struct prices777
{
char url[512],exchange[64],base[64],rel[64],lbase[64],lrel[64],key[512],oppokey[512],contract[64],origbase[64],origrel[64];
uint64_t contractnum,ap_mult,baseid,relid,basemult,relmult; double lastupdate,decay,oppodecay,lastprice,lastbid,lastask;
uint32_t pollnxtblock,exchangeid,numquotes,updated,lasttimestamp,RTflag,disabled,dirty; int32_t keysize,oppokeysize;
portable_mutex_t mutex;
char *orderbook_jsonstrs[2][2];
struct prices777_basketinfo O,O2; double groupwts[MAX_GROUPS + 1];
uint8_t changed,type; uint8_t **dependents; int32_t numdependents,numgroups,basketsize; double commission;
void *tradebot;
struct prices777_basket basket[];
};
struct exchange_info;
struct exchange_funcs
{
char *exchange;
double (*update)(struct prices777 *prices,int32_t maxdepth);
int32_t (*supports)(char *base,char *rel);
uint64_t (*trade)(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume);
char *(*orderstatus)(void **cHandlep,struct exchange_info *exchange,cJSON *argjson,uint64_t quoteid);
char *(*cancelorder)(void **cHandlep,struct exchange_info *exchange,cJSON *argjson,uint64_t quoteid);
char *(*openorders)(void **cHandlep,struct exchange_info *exchange,cJSON *argjson);
char *(*tradehistory)(void **cHandlep,struct exchange_info *exchange,cJSON *argjson);
cJSON *(*balances)(void **cHandlep,struct exchange_info *exchange);
char *(*parsebalance)(struct exchange_info *exchange,double *balancep,char *coinstr);
char *(*withdraw)(void **cHandlep,struct exchange_info *exchange,cJSON *argjson);
};
#define EXCHANGE_FUNCS(xchg,name) { name, prices777_ ## xchg, xchg ## _supports, xchg ## _trade, xchg ## _orderstatus, xchg ## _cancelorder, xchg ## _openorders, xchg ## _tradehistory, xchg ## _balances, xchg ## _parsebalance, xchg ## _withdraw }
struct exchange_info
{
struct exchange_funcs issue;
char name[16],apikey[MAX_JSON_FIELD],apisecret[MAX_JSON_FIELD],userid[MAX_JSON_FIELD];
cJSON *balancejson;
uint32_t num,exchangeid,pollgap,refcount,polling,lastbalancetime;
uint64_t nxt64bits,lastnonce; double lastupdate,commission;
void *cHandle;
portable_mutex_t mutex;
};
#define calc_predisplinex(startweekind,clumpsize,weekind) (((weekind) - (startweekind))/(clumpsize))
#define _extrapolate_Spline(Splines,gap) ((double)(Splines)[0] + ((gap) * ((double)(Splines)[1] + ((gap) * ((double)(Splines)[2] + ((gap) * (double)(Splines)[3]))))))
#define _extrapolate_Slope(Splines,gap) ((double)(Splines)[1] + ((gap) * ((double)(Splines)[2] + ((gap) * (double)(Splines)[3]))))
#define PRICE_BLEND(oldval,newval,decay,oppodecay) ((oldval == 0.) ? newval : ((oldval * decay) + (oppodecay * newval)))
#define PRICE_BLEND64(oldval,newval,decay,oppodecay) ((oldval == 0) ? newval : ((oldval * decay) + (oppodecay * newval) + 0.499))
struct prices777 *prices777_initpair(int32_t needfunc,char *exchange,char *base,char *rel,double decay,char *name,uint64_t baseid,uint64_t relid,int32_t basketsize);
struct exchange_info *get_exchange(int32_t exchangeid);
char *exchange_str(int32_t exchangeid);
struct exchange_info *exchange_find(char *exchangestr);
void prices777_exchangeloop(void *ptr);
uint64_t InstantDEX_name(char *key,int32_t *keysizep,char *exchange,char *name,char *base,uint64_t *baseidp,char *rel,uint64_t *relidp);
struct prices777 *prices777_find(int32_t *invertedp,uint64_t baseid,uint64_t relid,char *exchange);
struct exchange_info *find_exchange(int32_t *exchangeidp,char *exchangestr);
double prices777_InstantDEX(struct prices777 *prices,int32_t maxdepth);
uint64_t prices777_equiv(uint64_t assetid);
char *prices777_trade(int32_t *curlingp,void *bot,struct pending_trade **pendp,void **cHandlep,int32_t dotrade,cJSON *item,char *activenxt,char *secret,struct prices777 *prices,int32_t dir,double price,double volume,struct InstantDEX_quote *iQ,struct prices777_order *order,uint64_t orderid,char *extra);
double prices777_price_volume(double *volumep,uint64_t baseamount,uint64_t relamount);
struct prices777 *prices777_poll(char *exchangestr,char *name,char *base,uint64_t refbaseid,char *rel,uint64_t refrelid);
void set_best_amounts(int64_t *baseamountp,int64_t *relamountp,double price,double volume);
int32_t _set_assetname(uint64_t *multp,char *buf,char *jsonstr,uint64_t assetid);
char *InstantDEX_withdraw(cJSON *argjson);
cJSON *exchanges_json();
char *InstantDEX_tradesequence(int32_t curlings[],void *bot,void *cHandles[],int32_t *nump,struct prices777_order *trades,int32_t maxtrades,int32_t dotrade,char *activenxt,char *secret,cJSON *json);
struct prices777 *prices777_makebasket(char *basketstr,cJSON *_basketjson,int32_t addbasket,char *typestr,struct prices777 *ptrs[],int32_t num);
char *prices777_activebooks(char *name,char *_base,char *_rel,uint64_t baseid,uint64_t relid,int32_t maxdepth,int32_t allflag,int32_t tradeable);
char *prices777_orderbook_jsonstr(int32_t invert,uint64_t nxt64bits,struct prices777 *prices,struct prices777_basketinfo *OB,int32_t maxdepth,int32_t allflag);
int32_t get_assetname(char *name,uint64_t assetid);
int32_t is_mscoin(char *assetidstr);
uint32_t _get_NXTheight(uint32_t *firsttimep);
char *fill_nxtae(int32_t dotrade,uint64_t *txidp,uint64_t nxt64bits,char *secret,int32_t dir,double price,double volume,uint64_t baseid,uint64_t relid);
uint64_t get_assetmult(uint64_t assetid);
int32_t InstantDEX_verify(uint64_t destNXTaddr,uint64_t sendasset,uint64_t sendqty,cJSON *txobj,uint64_t recvasset,uint64_t recvqty);
int32_t verify_NXTtx(cJSON *json,uint64_t refasset,uint64_t qty,uint64_t destNXTbits);
uint64_t assetmult(char *assetidstr);
int64_t get_asset_quantity(int64_t *unconfirmedp,char *NXTaddr,char *assetidstr);
uint64_t calc_asset_qty(uint64_t *availp,uint64_t *priceNQTp,char *NXTaddr,int32_t checkflag,uint64_t assetid,double price,double vol);
cJSON *InstantDEX_orderbook(struct prices777 *prices);
char *hmac_sha512_str(char dest[(512>>3)*2 + 1],char *key,unsigned int key_size,char *message);
char *hmac_sha384_str(char *dest,char *key,int32_t key_size,char *message);
char *hmac_sha1_str(char *dest,char *key,int32_t key_size,char *message);
char *hmac_sha256_str(char *dest,char *key,int32_t key_size,char *message);
extern uint32_t MAX_DEPTH;
extern char NXTAPIURL[],IGUANA_NXTACCTSECRET[],IGUANA_NXTADDR[];
extern int32_t FIRST_EXTERNAL,IGUANA_disableNXT,Debuglevel,prices777_NXTBLOCK;
extern uint64_t IGUANA_MY64BITS;
#endif

1407
iguana/InstantDEX/exchange_trades.h

File diff suppressed because it is too large

1208
iguana/InstantDEX/exchangeparse.h

File diff suppressed because it is too large

1812
iguana/InstantDEX/prices777.c

File diff suppressed because it is too large

880
iguana/InstantDEX/quotes.h

@ -0,0 +1,880 @@
/******************************************************************************
* Copyright © 2014-2015 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. *
* *
******************************************************************************/
#ifndef xcode_quotes_h
#define xcode_quotes_h
#ifdef oldway
int32_t make_jumpiQ(uint64_t refbaseid,uint64_t refrelid,int32_t flip,struct InstantDEX_quote *iQ,struct InstantDEX_quote *baseiQ,struct InstantDEX_quote *reliQ,char *gui,int32_t duration)
{
uint64_t baseamount,relamount,frombase,fromrel,tobase,torel;
double vol;
char exchange[64];
uint32_t timestamp;
frombase = baseiQ->baseamount, fromrel = baseiQ->relamount;
tobase = reliQ->baseamount, torel = reliQ->relamount;
if ( make_jumpquote(refbaseid,refrelid,&baseamount,&relamount,&frombase,&fromrel,&tobase,&torel) == 0. )
return(0);
if ( (timestamp= reliQ->timestamp) > baseiQ->timestamp )
timestamp = baseiQ->timestamp;
iQ_exchangestr(exchange,iQ);
create_InstantDEX_quote(iQ,timestamp,0,calc_quoteid(baseiQ) ^ calc_quoteid(reliQ),0.,0.,refbaseid,baseamount,refrelid,relamount,exchange,0,gui,baseiQ,reliQ,duration);
if ( Debuglevel > 2 )
printf("jump%s: %f (%llu/%llu) %llu %llu (%f %f) %llu %llu\n",flip==0?"BID":"ASK",calc_price_volume(&vol,iQ->baseamount,iQ->relamount),(long long)baseamount,(long long)relamount,(long long)frombase,(long long)fromrel,calc_price_volume(&vol,frombase,fromrel),calc_price_volume(&vol,tobase,torel),(long long)tobase,(long long)torel);
iQ->isask = flip;
iQ->minperc = baseiQ->minperc;
if ( reliQ->minperc > iQ->minperc )
iQ->minperc = reliQ->minperc;
return(1);
}
#else
struct InstantDEX_quote *AllQuotes;
void clear_InstantDEX_quoteflags(struct InstantDEX_quote *iQ)
{
//duration:14,wallet:1,a:1,isask:1,expired:1,closed:1,swap:1,responded:1,matched:1,feepaid:1,automatch:1,pending:1,minperc:7;
iQ->s.a = iQ->s.expired = iQ->s.swap = iQ->s.feepaid = 0;
iQ->s.closed = iQ->s.pending = iQ->s.responded = iQ->s.matched = 0;
}
void cancel_InstantDEX_quote(struct InstantDEX_quote *iQ) { iQ->s.closed = 1; }
int32_t InstantDEX_uncalcsize() { struct InstantDEX_quote iQ; return(sizeof(iQ.hh) + sizeof(iQ.s.quoteid) + sizeof(iQ.s.price) + sizeof(iQ.s.vol)); }
int32_t iQcmp(struct InstantDEX_quote *iQA,struct InstantDEX_quote *iQB)
{
if ( iQA->s.isask == iQB->s.isask && iQA->s.baseid == iQB->s.baseid && iQA->s.relid == iQB->s.relid && iQA->s.baseamount == iQB->s.baseamount && iQA->s.relamount == iQB->s.relamount )
return(0);
else if ( iQA->s.isask != iQB->s.isask && iQA->s.baseid == iQB->s.relid && iQA->s.relid == iQB->s.baseid && iQA->s.baseamount == iQB->s.relamount && iQA->s.relamount == iQB->s.baseamount )
return(0);
return(-1);
}
uint64_t calc_txid(unsigned char *buf,int32_t len)
{
bits256 hash;
vcalc_sha256(0,hash.bytes,buf,len);
return(hash.txid);
}
uint64_t calc_quoteid(struct InstantDEX_quote *iQ)
{
struct InstantDEX_quote Q;
if ( iQ == 0 )
return(0);
if ( iQ->s.duration == 0 || iQ->s.duration > ORDERBOOK_EXPIRATION )
iQ->s.duration = ORDERBOOK_EXPIRATION;
if ( iQ->s.quoteid == 0 )
{
Q = *iQ;
clear_InstantDEX_quoteflags(&Q);
if ( Q.s.isask != 0 )
{
Q.s.baseid = iQ->s.relid, Q.s.baseamount = iQ->s.relamount;
Q.s.relid = iQ->s.baseid, Q.s.relamount = iQ->s.baseamount;
Q.s.isask = Q.s.minperc = 0;
}
return(calc_txid((uint8_t *)((long)&Q + InstantDEX_uncalcsize()),sizeof(Q) - InstantDEX_uncalcsize()));
} return(iQ->s.quoteid);
}
struct InstantDEX_quote *find_iQ(uint64_t quoteid)
{
struct InstantDEX_quote *iQ;
HASH_FIND(hh,AllQuotes,&quoteid,sizeof(quoteid),iQ);
return(iQ);
}
struct InstantDEX_quote *delete_iQ(uint64_t quoteid)
{
struct InstantDEX_quote *iQ;
if ( (iQ= find_iQ(quoteid)) != 0 )
{
HASH_DELETE(hh,AllQuotes,iQ);
}
return(iQ);
}
struct InstantDEX_quote *findquoteid(uint64_t quoteid,int32_t evenclosed)
{
struct InstantDEX_quote *iQ;
if ( (iQ= find_iQ(quoteid)) != 0 )
{
if ( evenclosed != 0 || iQ->s.closed == 0 )
{
if ( calc_quoteid(iQ) == quoteid )
return(iQ);
else printf("calc_quoteid %llu vs %llu\n",(long long)calc_quoteid(iQ),(long long)quoteid);
} //else printf("quoteid.%llu closed.%d\n",(long long)quoteid,iQ->closed);
} else printf("couldnt find %llu\n",(long long)quoteid);
return(0);
}
int32_t cancelquote(char *NXTaddr,uint64_t quoteid)
{
struct InstantDEX_quote *iQ;
if ( (iQ= findquoteid(quoteid,0)) != 0 && iQ->s.offerNXT == calc_nxt64bits(NXTaddr) && iQ->exchangeid == INSTANTDEX_EXCHANGEID )
{
cancel_InstantDEX_quote(iQ);
return(1);
}
return(0);
}
struct InstantDEX_quote *create_iQ(struct InstantDEX_quote *iQ,char *walletstr)
{
struct InstantDEX_quote *newiQ,*tmp; struct prices777 *prices; int32_t inverted; long len = 0;
if ( walletstr != 0 && (len= strlen(walletstr)) > 0 )
iQ->s.wallet = 1, len++;
calc_quoteid(iQ);
printf("createiQ %llu/%llu %f %f quoteid.%llu offerNXT.%llu wallet.%d (%s)\n",(long long)iQ->s.baseid,(long long)iQ->s.relid,iQ->s.price,iQ->s.vol,(long long)iQ->s.quoteid,(long long)iQ->s.offerNXT,iQ->s.wallet,walletstr!=0?walletstr:"");
if ( (newiQ= find_iQ(iQ->s.quoteid)) != 0 )
return(newiQ);
newiQ = calloc(1,sizeof(*newiQ) + len);
*newiQ = *iQ;
if ( len != 0 )
memcpy(newiQ->walletstr,walletstr,len);
HASH_ADD(hh,AllQuotes,s.quoteid,sizeof(newiQ->s.quoteid),newiQ);
if ( (prices= prices777_find(&inverted,iQ->s.baseid,iQ->s.relid,INSTANTDEX_NAME)) != 0 )
prices->dirty++;
{
struct InstantDEX_quote *checkiQ;
if ( (checkiQ= find_iQ(iQ->s.quoteid)) == 0 || iQcmp(iQ,checkiQ) != 0 )//memcmp((uint8_t *)((long)checkiQ + sizeof(checkiQ->hh) + sizeof(checkiQ->quoteid)),(uint8_t *)((long)iQ + sizeof(iQ->hh) + sizeof(iQ->quoteid)),sizeof(*iQ) - sizeof(iQ->hh) - sizeof(iQ->quoteid)) != 0 )
{
int32_t i;
for (i=(sizeof(iQ->hh) - sizeof(iQ->s.quoteid)); i<sizeof(*iQ) - sizeof(iQ->hh) - sizeof(iQ->s.quoteid); i++)
printf("%02x ",((uint8_t *)iQ)[i]);
printf("iQ\n");
for (i=(sizeof(checkiQ->hh) + sizeof(checkiQ->s.quoteid)); i<sizeof(*checkiQ) - sizeof(checkiQ->hh) - sizeof(checkiQ->s.quoteid); i++)
printf("%02x ",((uint8_t *)checkiQ)[i]);
printf("checkiQ\n");
printf("error finding iQ after adding %llu vs %llu\n",(long long)checkiQ->s.quoteid,(long long)iQ->s.quoteid);
}
}
HASH_ITER(hh,AllQuotes,iQ,tmp)
{
if ( iQ->s.expired != 0 )
{
printf("quoteid.%llu expired, purging\n",(long long)iQ->s.expired);
delete_iQ(iQ->s.quoteid);
}
}
return(newiQ);
}
#ifdef later
cJSON *pangea_walletitem(cJSON *walletitem,struct coin777 *coin,int32_t rakemillis,int64_t bigblind,int64_t ante,int32_t minbuyin,int32_t maxbuyin)
{
char *addr; struct destbuf pubkey;
if ( walletitem == 0 )
walletitem = cJSON_CreateObject();
//printf("call get_acct_coinaddr.%s (%s) (%s)\n",coin->name,coin->serverport,coin->userpass);
if ( coin->pangeapubkey[0] == 0 || coin->pangeacoinaddr[0] == 0 )
{
if ( strcmp("NXT",coin->name) == 0 )
{
}
else if ( (addr= get_acct_coinaddr(coin->pangeacoinaddr,coin->name,coin->serverport,coin->userpass,"pangea")) != 0 )
{
//printf("get_pubkey\n");
get_pubkey(&pubkey,coin->name,coin->serverport,coin->userpass,coin->pangeacoinaddr);
strcpy(coin->pangeapubkey,pubkey.buf);
}
}
jaddstr(walletitem,"pubkey",coin->pangeapubkey);
jaddstr(walletitem,"coinaddr",coin->pangeacoinaddr);
jaddnum(walletitem,"rakemillis",rakemillis);
jaddnum(walletitem,"minbuyin",minbuyin);
jaddnum(walletitem,"maxbuyin",maxbuyin);
jadd64bits(walletitem,"bigblind",bigblind);
jadd64bits(walletitem,"ante",ante);
return(walletitem);
}
cJSON *set_walletstr(cJSON *walletitem,char *walletstr,struct InstantDEX_quote *iQ)
{
char pubkeystr[128],pkhash[128],base[64],rel[64],fieldA[64],fieldB[64],fieldpkhash[64],*pubA,*pubB,*pkhashstr,*str,*exchangestr;
struct coin777 *coin; int32_t flip = 0;
if ( walletstr != 0 && walletitem == 0 )
walletitem = cJSON_Parse(walletstr);
if ( walletitem == 0 )
walletitem = cJSON_CreateObject();
unstringbits(base,iQ->s.basebits), unstringbits(rel,iQ->s.relbits);
flip = (iQ->s.offerNXT != IGUANA_MY64BITS);
if ( strcmp(base,"NXT") != 0 )
coin = coin777_find(base,1);
else if ( strcmp(rel,"NXT") != 0 )
coin = coin777_find(rel,1), flip ^= 1;
else coin = 0;
if ( coin != 0 )
{
if ( (exchangestr= exchange_str(iQ->exchangeid)) != 0 && strcmp(exchangestr,"pangea") == 0 )
pangea_walletitem(walletitem,coin,iQ->s.minperc,iQ->s.baseamount,iQ->s.relamount,iQ->s.minbuyin,iQ->s.maxbuyin);
else
{
//printf("START.(%s)\n",jprint(walletitem,0));
if ( (iQ->s.isask ^ flip) == 0 )
{
sprintf(fieldA,"%spubA",coin->name);
if ( (pubA= jstr(walletitem,fieldA)) != 0 )
cJSON_DeleteItemFromObject(walletitem,fieldA);
jaddstr(walletitem,fieldA,coin->atomicsendpubkey);
//printf("replaceA\n");
}
else
{
sprintf(fieldB,"%spubB",coin->name);
if ( (pubB= jstr(walletitem,fieldB)) != 0 )
cJSON_DeleteItemFromObject(walletitem,fieldB);
jaddstr(walletitem,fieldB,coin->atomicrecvpubkey);
sprintf(fieldpkhash,"%spkhash",coin->name);
if ( (pkhashstr= jstr(walletitem,fieldpkhash)) != 0 )
cJSON_DeleteItemFromObject(walletitem,fieldpkhash);
subatomic_pubkeyhash(pubkeystr,pkhash,coin,iQ->s.quoteid);
jaddstr(walletitem,fieldpkhash,pkhash);
//printf("replaceB\n");
}
}
str = jprint(walletitem,0);
strcpy(walletstr,str);
free(str);
return(walletitem);
}
return(0);
}
#endif
char *InstantDEX_str(char *walletstr,char *buf,int32_t extraflag,struct InstantDEX_quote *iQ)
{
cJSON *json; char _buf[4096],base[64],rel[64],*str;
unstringbits(base,iQ->s.basebits), unstringbits(rel,iQ->s.relbits);
if ( buf == 0 )
buf = _buf;
sprintf(buf,"{\"quoteid\":\"%llu\",\"base\":\"%s\",\"baseid\":\"%llu\",\"baseamount\":\"%llu\",\"rel\":\"%s\",\"relid\":\"%llu\",\"relamount\":\"%llu\",\"price\":%.8f,\"volume\":%.8f,\"offerNXT\":\"%llu\",\"timestamp\":\"%u\",\"isask\":\"%u\",\"exchange\":\"%s\",\"gui\":\"%s\"}",(long long)iQ->s.quoteid,base,(long long)iQ->s.baseid,(long long)iQ->s.baseamount,rel,(long long)iQ->s.relid,(long long)iQ->s.relamount,iQ->s.price,iQ->s.vol,(long long)iQ->s.offerNXT,iQ->s.timestamp,iQ->s.isask,exchange_str(iQ->exchangeid),iQ->gui);
if ( extraflag != 0 )
{
sprintf(buf + strlen(buf) - 1,",\"plugin\":\"relay\",\"destplugin\":\"InstantDEX\",\"method\":\"busdata\",\"submethod\":\"%s\"}",(iQ->s.isask != 0) ? "ask" : "bid");
}
//printf("InstantDEX_str.(%s)\n",buf);
if ( (json= cJSON_Parse(buf)) != 0 )
{
#ifdef later
char _buf[4096],_walletstr[256],base[64],rel[64],*exchange,*str; cJSON *walletitem,*json; struct coin777 *coin;
if ( walletstr == 0 )
{
walletstr = _walletstr;
walletstr[0] = 0;
}
if ( (exchange= exchange_str(iQ->exchangeid)) != 0 )
{
coin = coin777_find(base,0);
if ( strcmp(exchange,"wallet") == 0 )
walletitem = set_walletstr(0,walletstr,iQ);
else if ( strcmp(exchange,"pangea") == 0 && walletstr[0] == 0 && coin != 0 )
walletitem = pangea_walletitem(0,coin,iQ->s.minperc,iQ->s.baseamount,iQ->s.relamount,iQ->s.minbuyin,iQ->s.maxbuyin);
else walletitem = 0;
if ( walletitem != 0 )
{
jadd(json,"wallet",walletitem);
strcpy(walletstr,jprint(walletitem,0));
}
//printf("exchange.(%s) iswallet.%d (%s) base.(%s) coin.%p (%s)\n",exchange,iQ->s.wallet,walletstr,base,coin,jprint(json,0));
} else printf("InstantDEX_str cant find exchangeid.%d\n",iQ->exchangeid);
#endif
str = jprint(json,1);
strcpy(buf,str);
//printf("str.(%s) %p\n",buf,buf);
free(str);
} else printf("InstantDEX_str cant parse.(%s)\n",buf);
if ( buf == _buf )
return(clonestr(buf));
else return(buf);
}
uint64_t _get_AEquote(char *str,uint64_t orderid)
{
cJSON *json;
uint64_t nxt64bits = 0;
char cmd[256],*jsonstr;
sprintf(cmd,"requestType=get%sOrder&order=%llu",str,(long long)orderid);
if ( (jsonstr= issue_NXTPOST(cmd)) != 0 )
{
//printf("(%s) -> (%s)\n",cmd,jsonstr);
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
nxt64bits = get_API_nxt64bits(cJSON_GetObjectItem(json,"account"));
free_json(json);
}
free(jsonstr);
}
return(nxt64bits);
}
char *cancel_NXTorderid(char *NXTaddr,char *nxtsecret,uint64_t orderid)
{
uint64_t nxt64bits; char cmd[1025],secret[8192],*str = "Bid",*retstr = 0;
if ( (nxt64bits= _get_AEquote(str,orderid)) == 0 )
str = "Ask", nxt64bits = _get_AEquote(str,orderid);
if ( nxt64bits == calc_nxt64bits(NXTaddr) )
{
escape_code(secret,nxtsecret);
sprintf(cmd,"requestType=cancel%sOrder&secretPhrase=%s&feeNQT=%lld&deadline=%d&order=%llu",str,secret,(long long)MIN_NQTFEE,DEFAULT_NXT_DEADLINE,(long long)orderid);
retstr = issue_NXTPOST(cmd);
//printf("(%s) -> (%s)\n",cmd,retstr);
}
return(retstr);
}
char *InstantDEX_cancelorder(cJSON *argjson,char *activenxt,char *secret,uint64_t orderid,uint64_t quoteid)
{
struct InstantDEX_quote *iQ; cJSON *json,*array,*item; char numstr[64],*retstr,*exchangestr;
uint64_t quoteids[256]; int32_t i,exchangeid,n=0; struct exchange_info *exchange;
if ( (exchangestr= jstr(argjson,"exchange")) != 0 && (exchange= find_exchange(&exchangeid,exchangestr)) != 0 )
{
if ( exchange->issue.cancelorder != 0 )
{
if ( (retstr= (*exchange->issue.cancelorder)(&exchange->cHandle,exchange,argjson,quoteid)) == 0 )
retstr = clonestr("{\"result\":\"nothing returned from exchange\"}");
return(retstr);
}
else return(clonestr("{\"error\":\"no cancelorder function\"}"));
}
memset(quoteids,0,sizeof(quoteids));
json = cJSON_CreateObject(), array = cJSON_CreateArray();
if ( quoteid != 0 )
quoteids[n++] = quoteid;
//n += InstantDEX_quoteids(quoteids+n,orderid);
for (i=0; i<n; i++)
{
quoteid = quoteids[i];
if ( (retstr= cancel_NXTorderid(activenxt,secret,quoteid)) != 0 )
{
if ( (iQ= findquoteid(quoteid,0)) != 0 && iQ->s.offerNXT == calc_nxt64bits(activenxt) )
cancel_InstantDEX_quote(iQ);
if ( (item= cJSON_Parse(retstr)) != 0 )
jaddi(array,item);
free(retstr);
}
cancelquote(activenxt,quoteid);
}
if ( orderid != 0 )
{
if ( cancelquote(activenxt,orderid) != 0 )
sprintf(numstr,"%llu",(long long)orderid), jaddstr(json,"ordercanceled",numstr);
}
return(jprint(json,1));
}
char *InstantDEX_orderstatus(cJSON *argjson,uint64_t orderid,uint64_t quoteid)
{
struct InstantDEX_quote *iQ = 0; char *exchangestr,*str; struct exchange_info *exchange; int32_t exchangeid;
if ( (exchangestr= jstr(argjson,"exchange")) != 0 && (exchange= find_exchange(&exchangeid,exchangestr)) != 0 )
{
if ( exchange->issue.orderstatus != 0 )
{
if ( (str= (*exchange->issue.orderstatus)(&exchange->cHandle,exchange,argjson,quoteid)) == 0 )
str = clonestr("{\"result\":\"nothing returned from exchange\"}");
return(str);
}
else return(clonestr("{\"error\":\"no orderstatus function\"}"));
}
if ( (iQ= find_iQ(orderid)) != 0 || (iQ= find_iQ(quoteid)) != 0 )
return(InstantDEX_str(0,0,0,iQ));
return(clonestr("{\"error\":\"couldnt find orderid\"}"));
}
char *InstantDEX_openorders(cJSON *argjson,char *NXTaddr,int32_t allorders)
{
struct InstantDEX_quote *iQ,*tmp; char buf[4096],*exchangestr,*jsonstr,*str; uint32_t now,duration;
cJSON *json,*array,*item; uint64_t nxt64bits; struct exchange_info *exchange; int32_t exchangeid;
if ( (exchangestr= jstr(argjson,"exchange")) != 0 && (exchange= find_exchange(&exchangeid,exchangestr)) != 0 )
{
if ( exchange->issue.openorders != 0 )
{
if ( (str= (*exchange->issue.openorders)(&exchange->cHandle,exchange,argjson)) == 0 )
str = clonestr("{\"result\":\"nothing returned from exchange\"}");
return(str);
}
else return(clonestr("{\"error\":\"no orderstatus function\"}"));
}
nxt64bits = calc_nxt64bits(NXTaddr);
now = (uint32_t)time(NULL);
json = cJSON_CreateObject(), array = cJSON_CreateArray();
HASH_ITER(hh,AllQuotes,iQ,tmp)
{
if ( (duration= iQ->s.duration) == 0 )
duration = ORDERBOOK_EXPIRATION;
if ( iQ->s.timestamp > (now + duration) )
iQ->s.expired = iQ->s.closed = 1;
if ( iQ->s.offerNXT == nxt64bits && (allorders != 0 || iQ->s.closed == 0) )
{
if ( (jsonstr= InstantDEX_str(0,buf,0,iQ)) != 0 && (item= cJSON_Parse(jsonstr)) != 0 )
jaddi(array,item);
}
}
jadd(json,"openorders",array);
return(jprint(json,1));
}
cJSON *InstantDEX_specialorders(uint64_t *quoteidp,uint64_t nxt64bits,char *base,char *special,uint64_t baseamount,int32_t addrtype)
{
struct InstantDEX_quote *iQ,*tmp; int32_t exchangeid; uint32_t i,n,now,duration,ismine = 0;
uint64_t basebits; cJSON *item=0,*array = 0; char *coinaddr=0,*pubkey,checkaddr[128];
now = (uint32_t)time(NULL);
basebits = stringbits(base);
if ( special == 0 || find_exchange(&exchangeid,special) == 0 )
exchangeid = 0;
n = 0;
*quoteidp = 0;
HASH_ITER(hh,AllQuotes,iQ,tmp)
{
//printf("iter Q.%llu b.%llu\n",(long long)iQ->s.quoteid,(long long)iQ->s.basebits);
if ( (duration= iQ->s.duration) == 0 )
duration = ORDERBOOK_EXPIRATION;
if ( iQ->s.timestamp > (now + duration) )
{
iQ->s.expired = iQ->s.closed = 1;
printf("expire order %llu\n",(long long)iQ->s.quoteid);
continue;
}
if ( iQ->s.basebits == basebits && (exchangeid == 0 || iQ->exchangeid == exchangeid) )
{
//printf("matched basebits\n");
if ( strcmp(special,"pangea") == 0 )
{
checkaddr[0] = 0;
if ( iQ->s.wallet != 0 && (item= cJSON_Parse(iQ->walletstr)) != 0 && (coinaddr= jstr(item,"coinaddr")) != 0 && coinaddr[0] != 0 && (pubkey= jstr(item,"pubkey")) != 0 && pubkey[0] != 0 )
btc_coinaddr(coinaddr,addrtype,pubkey);
if ( item != 0 )
free_json(item);
if ( coinaddr == 0 || strcmp(coinaddr,checkaddr) != 0 )
{
printf("mismatched pangea coinaddr (%s) vs (%s) or baseamount %.8f vs %.8f\n",coinaddr,checkaddr,dstr(baseamount),dstr(iQ->s.baseamount));
continue;
}
}
if ( n > 0 )
{
for (i=0; i<n; i++)
{
if ( iQ->s.offerNXT == j64bits(jitem(array,i),0) )
break;
}
//printf("found duplicate\n");
} else i = 0;
if ( i == n )
{
if ( iQ->s.offerNXT == nxt64bits )
{
ismine = 1;
if ( *quoteidp == 0 )
*quoteidp = iQ->s.quoteid;
}
if ( array == 0 )
array = cJSON_CreateArray();
jaddi64bits(array,iQ->s.offerNXT);
//printf("add %llu\n",(long long)iQ->s.offerNXT);
}
} //else printf("quote.%llu basebits.%llu\n",(long long)iQ->s.quoteid,(long long)iQ->s.basebits);
}
if ( ismine == 0 )
free_json(array), array = 0;
//printf("ismine.%d n.%d array.%d\n",ismine,n,array==0?0:cJSON_GetArraySize(array));
return(array);
}
int _decreasing_quotes(const void *a,const void *b)
{
#define order_a ((struct InstantDEX_quote *)a)
#define order_b ((struct InstantDEX_quote *)b)
if ( order_b->s.price > order_a->s.price )
return(1);
else if ( order_b->s.price < order_a->s.price )
return(-1);
return(0);
#undef order_a
#undef order_b
}
int _increasing_quotes(const void *a,const void *b)
{
#define order_a ((struct InstantDEX_quote *)a)
#define order_b ((struct InstantDEX_quote *)b)
if ( order_b->s.price > order_a->s.price )
return(-1);
else if ( order_b->s.price < order_a->s.price )
return(1);
return(0);
#undef order_a
#undef order_b
}
cJSON *prices777_orderjson(struct InstantDEX_quote *iQ)
{
cJSON *item = cJSON_CreateArray();
jaddinum(item,iQ->s.price);
jaddinum(item,iQ->s.vol);
jaddi64bits(item,iQ->s.quoteid);
return(item);
}
cJSON *InstantDEX_orderbook(struct prices777 *prices)
{
struct InstantDEX_quote *ptr,iQ,*tmp,*askvals=0,*bidvals=0; cJSON *json,*bids,*asks; uint32_t now,duration;
int32_t i,isask,iter,n,m,numbids,numasks,invert;
json = cJSON_CreateObject(), bids = cJSON_CreateArray(), asks = cJSON_CreateArray();
now = (uint32_t)time(NULL);
for (iter=numbids=numasks=n=m=0; iter<2; iter++)
{
HASH_ITER(hh,AllQuotes,ptr,tmp)
{
iQ = *ptr;
if ( (duration= iQ.s.duration) == 0 )
duration = ORDERBOOK_EXPIRATION;
if ( iQ.s.timestamp > (now + duration) )
{
iQ.s.expired = iQ.s.closed = 1;
continue;
}
if ( Debuglevel > 2 )
printf("iterate quote.%llu\n",(long long)iQ.s.quoteid);
if ( prices777_equiv(ptr->s.baseid) == prices777_equiv(prices->baseid) && prices777_equiv(ptr->s.relid) == prices777_equiv(prices->relid) )
invert = 0;
else if ( prices777_equiv(ptr->s.relid) == prices777_equiv(prices->baseid) && prices777_equiv(ptr->s.baseid) == prices777_equiv(prices->relid) )
invert = 1;
else continue;
if ( ptr->s.pending != 0 )
continue;
isask = iQ.s.isask;
if ( invert != 0 )
isask ^= 1;
if ( invert != 0 )
{
if ( iQ.s.price > SMALLVAL )
iQ.s.vol *= iQ.s.price, iQ.s.price = 1. / iQ.s.price;
else iQ.s.price = prices777_price_volume(&iQ.s.vol,iQ.s.relamount,iQ.s.baseamount);
}
else if ( iQ.s.price <= SMALLVAL )
iQ.s.price = prices777_price_volume(&iQ.s.vol,iQ.s.baseamount,iQ.s.relamount);
if ( iter == 0 )
{
if ( isask != 0 )
numasks++;
else numbids++;
}
else
{
if ( isask == 0 && n < numbids )
bidvals[n++] = iQ;
else if ( isask != 0 && m < numasks )
askvals[m++] = iQ;
}
}
if ( iter == 0 )
{
if ( numbids > 0 )
bidvals = calloc(numbids,sizeof(*bidvals));
if ( numasks > 0 )
askvals = calloc(numasks,sizeof(*askvals));
}
}
if ( numbids > 0 )
{
if ( n > 0 )
{
qsort(bidvals,n,sizeof(*bidvals),_decreasing_quotes);
for (i=0; i<n; i++)
jaddi(bids,prices777_orderjson(&bidvals[i]));
}
free(bidvals);
}
if ( numasks > 0 )
{
if ( m > 0 )
{
qsort(askvals,m,sizeof(*askvals),_increasing_quotes);
for (i=0; i<m; i++)
jaddi(asks,prices777_orderjson(&askvals[i]));
}
free(askvals);
}
jadd(json,"bids",bids), jadd(json,"asks",asks);
return(json);
}
double ordermetric(double price,double vol,int32_t dir,double refprice,double refvol)
{
double metric = 0.;
if ( vol > (refvol * INSTANTDEX_MINVOLPERC) )//&& refvol > (vol * iQ->s.minperc * .01) )
{
if ( vol < refvol )
metric = (vol / refvol);
else metric = 1.;
if ( dir > 0 && price < (refprice * (1. + INSTANTDEX_PRICESLIPPAGE) + SMALLVAL) )
metric *= (1. + (refprice - price)/refprice);
else if ( dir < 0 && price > (refprice * (1. - INSTANTDEX_PRICESLIPPAGE) - SMALLVAL) )
metric *= (1. + (price - refprice)/refprice);
else metric = 0.;
if ( metric != 0. )
{
printf("price %.8f vol %.8f | %.8f > %.8f? %.8f > %.8f?\n",price,vol,vol,(refvol * INSTANTDEX_MINVOLPERC),refvol,(vol * INSTANTDEX_MINVOLPERC));
printf("price %f against %f or %f\n",price,(refprice * (1. + INSTANTDEX_PRICESLIPPAGE) + SMALLVAL),(refprice * (1. - INSTANTDEX_PRICESLIPPAGE) - SMALLVAL));
printf("metric %f\n",metric);
}
}
return(metric);
}
char *autofill(char *remoteaddr,struct InstantDEX_quote *refiQ,char *NXTaddr,char *NXTACCTSECRET)
{
double price,volume,revprice,revvol,metric,bestmetric = 0.; int32_t dir,inverted; uint64_t nxt64bits; char *retstr=0;
struct InstantDEX_quote *iQ,*tmp,*bestiQ; struct prices777 *prices; uint32_t duration,now = (uint32_t)time(NULL);
return(0);
nxt64bits = calc_nxt64bits(NXTaddr);
memset(&bestiQ,0,sizeof(bestiQ));
dir = (refiQ->s.isask != 0) ? -1 : 1;
HASH_ITER(hh,AllQuotes,iQ,tmp)
{
if ( (duration= refiQ->s.duration) == 0 )
duration = ORDERBOOK_EXPIRATION;
if ( iQ->s.timestamp > (now + duration) )
iQ->s.expired = iQ->s.closed = 1;
if ( iQ->s.offerNXT == nxt64bits && iQ->s.closed == 0 && iQ->s.pending == 0 )
{
if ( iQ->s.baseid == refiQ->s.baseid && iQ->s.relid == refiQ->s.relid && iQ->s.isask != refiQ->s.isask && (metric= ordermetric(iQ->s.price,iQ->s.vol,dir,refiQ->s.price,refiQ->s.vol)) > bestmetric )
{
bestmetric = metric;
bestiQ = iQ;
}
else if ( iQ->s.baseid == refiQ->s.relid && iQ->s.relid == refiQ->s.baseid && iQ->s.isask == refiQ->s.isask && iQ->s.price > SMALLVAL )
{
revvol = (iQ->s.price * iQ->s.vol), revprice = (1. / iQ->s.price);
if ( (metric= ordermetric(revprice,revvol,dir,refiQ->s.price,refiQ->s.vol)) > bestmetric )
{
bestmetric = metric;
bestiQ = iQ;
}
}
}
}
if ( bestmetric > 0. )
{
if ( (prices= prices777_find(&inverted,bestiQ->s.baseid,bestiQ->s.relid,exchange_str(bestiQ->exchangeid))) != 0 )
{
printf("isask.%d %f %f -> bestmetric %f inverted.%d autofill dir.%d price %f vol %f\n",bestiQ->s.isask,bestiQ->s.price,bestiQ->s.vol,bestmetric,inverted,dir,refiQ->s.price,refiQ->s.vol);
if ( bestiQ->s.isask != 0 )
dir = -1;
else dir = 1;
if ( inverted != 0 )
{
dir *= -1;
volume = (bestiQ->s.price * bestiQ->s.vol);
price = 1. / bestiQ->s.price;
printf("price inverted (%f %f) -> (%f %f)\n",bestiQ->s.price,bestiQ->s.vol,price,volume);
} else price = bestiQ->s.price, volume = bestiQ->s.vol;
retstr = prices777_trade(0,0,0,0,1,0,NXTaddr,NXTACCTSECRET,prices,dir,price,volume,bestiQ,0,bestiQ->s.quoteid,0);
}
}
return(retstr);
}
char *automatch(struct prices777 *prices,int32_t dir,double refprice,double refvol,char *NXTaddr,char *NXTACCTSECRET)
{
int32_t i,n=0; struct prices777_order order,bestorder; char *retstr = 0; double metric,bestmetric = 0.;
return(0);
memset(&bestorder,0,sizeof(bestorder));
if ( dir > 0 )
n = prices->O.numasks;
else if ( dir < 0 )
n = prices->O.numbids;
if ( n > 0 )
{
for (i=0; i<n; i++)
{
order = (dir > 0) ? prices->O.book[MAX_GROUPS][i].ask : prices->O.book[MAX_GROUPS][i].bid;
if ( (metric= ordermetric(order.s.price,order.s.vol,dir,refprice,refvol)) > bestmetric )
{
bestmetric = metric;
bestorder = order;
}
}
}
//printf("n.%d\n",n);
if ( bestorder.source != 0 )
retstr = prices777_trade(0,0,0,0,1,0,NXTaddr,NXTACCTSECRET,bestorder.source,bestorder.s.isask!=0?-1:1,bestorder.s.price,bestorder.s.vol,0,&bestorder,bestorder.s.quoteid,0);
return(retstr);
}
int offer_checkitem(struct pending_trade *pend,cJSON *item)
{
uint64_t quoteid; struct InstantDEX_quote *iQ;
if ( (quoteid= j64bits(item,"quoteid")) != 0 && (iQ= find_iQ(quoteid)) != 0 && iQ->s.closed != 0 )
return(0);
return(-1);
}
void trades_update()
{
#ifdef later
int32_t iter; struct pending_trade *pend;
for (iter=0; iter<2; iter++)
{
while ( (pend= queue_dequeue(&Pending_offersQ.pingpong[iter],0)) != 0 )
{
if ( time(NULL) > pend->expiration )
{
printf("now.%ld vs timestamp.%u vs expiration %u | ",(long)time(NULL),pend->timestamp,pend->expiration);
printf("offer_statemachine %llu/%llu %d %f %f\n",(long long)pend->orderid,(long long)pend->quoteid,pend->dir,pend->price,pend->volume);
//InstantDEX_history(1,pend,retstr);
if ( pend->bot == 0 )
free_pending(pend);
else pend->finishtime = (uint32_t)time(NULL);
}
else
{
printf("InstantDEX_update requeue %llu/%llu %d %f %f\n",(long long)pend->orderid,(long long)pend->quoteid,pend->dir,pend->price,pend->volume);
queue_enqueue("requeue",&Pending_offersQ.pingpong[iter ^ 1],&pend->DL,0);
}
}
}
#endif
}
void InstantDEX_update(char *NXTaddr,char *NXTACCTSECRET)
{
int32_t dir; double price,volume; uint32_t now; char *retstr = 0;
int32_t inverted; struct InstantDEX_quote *iQ,*tmp; struct prices777 *prices; uint64_t nxt64bits = calc_nxt64bits(NXTaddr);
now = (uint32_t)time(NULL);
HASH_ITER(hh,AllQuotes,iQ,tmp)
{
if ( iQ->s.timestamp > (now + ORDERBOOK_EXPIRATION) )
iQ->s.expired = iQ->s.closed = 1;
if ( iQ->s.offerNXT == nxt64bits && iQ->s.closed == 0 && iQ->s.pending == 0 )
{
if ( (prices= prices777_find(&inverted,iQ->s.baseid,iQ->s.relid,exchange_str(iQ->exchangeid))) != 0 )
{
if ( iQ->s.isask != 0 )
dir = -1;
else dir = 1;
if ( inverted != 0 )
{
dir *= -1;
volume = (iQ->s.price * iQ->s.vol);
price = 1. / iQ->s.price;
printf("price inverted (%f %f) -> (%f %f)\n",iQ->s.price,iQ->s.vol,price,volume);
} else price = iQ->s.price, volume = iQ->s.vol;
if ( (retstr= automatch(prices,dir,price,volume,NXTaddr,NXTACCTSECRET)) != 0 )
{
printf("automatched %s isask.%d %f %f (%s)\n",prices->contract,iQ->s.isask,iQ->s.price,iQ->s.vol,retstr);
free(retstr);
}
}
}
}
trades_update();
}
int32_t is_specialexchange(char *exchangestr)
{
if ( strcmp(exchangestr,"InstantDEX") == 0 || strcmp(exchangestr,"jumblr") == 0 || strcmp(exchangestr,"pangea") == 0 || strcmp(exchangestr,"peggy") == 0 || strcmp(exchangestr,"wallet") == 0 || strcmp(exchangestr,"active") == 0 || strncmp(exchangestr,"basket",strlen("basket")) == 0 )
return(1);
return(0);
}
char *InstantDEX_placebidask(char *remoteaddr,uint64_t orderid,char *exchangestr,char *name,char *base,char *rel,struct InstantDEX_quote *iQ,char *extra,char *secret,char *activenxt,cJSON *origjson)
{
struct exchange_info *exchange; cJSON *obj;
char walletstr[256],*str,*retstr = 0; int32_t inverted,dir; struct prices777 *prices; double price,volume;
if ( secret == 0 || activenxt == 0 )
{
secret = IGUANA_NXTACCTSECRET;
activenxt = IGUANA_NXTADDR;
}
//printf("placebidask.(%s)\n",jprint(origjson,0));
if ( (obj= jobj(origjson,"wallet")) != 0 )
{
str = jprint(obj,1);
safecopy(walletstr,str,sizeof(walletstr));
free(str), str = 0;
}
else walletstr[0] = 0;
if ( exchangestr != 0 && (exchange= exchange_find(exchangestr)) != 0 )
iQ->exchangeid = exchange->exchangeid;
if ( iQ->exchangeid < 0 || (exchangestr= exchange_str(iQ->exchangeid)) == 0 )
{
printf("exchangestr.%s id.%d\n",exchangestr,iQ->exchangeid);
return(clonestr("{\"error\":\"exchange not active, check SuperNET.conf exchanges array\"}\n"));
}
//printf("walletstr.(%s)\n",walletstr);
if ( (prices= prices777_find(&inverted,iQ->s.baseid,iQ->s.relid,exchangestr)) == 0 )
prices = prices777_poll(exchangestr,name,base,iQ->s.baseid,rel,iQ->s.relid);
if ( prices != 0 )
{
price = iQ->s.price, volume = iQ->s.vol;
if ( price < SMALLVAL || volume < SMALLVAL )
{
printf("price %f volume %f error\n",price,volume);
return(clonestr("{\"error\":\"prices777_trade invalid price or volume\"}\n"));
}
if ( iQ->s.isask != 0 )
dir = -1;
else dir = 1;
if ( inverted != 0 )
{
dir *= -1;
volume *= price;
price = 1. / price;
printf("price inverted (%f %f) -> (%f %f)\n",iQ->s.price,iQ->s.vol,price,volume);
}
//printf("dir.%d price %f vol %f isask.%d remoteaddr.%p\n",dir,price,volume,iQ->s.isask,remoteaddr);
if ( remoteaddr == 0 )
{
if ( is_specialexchange(exchangestr) == 0 )
return(prices777_trade(0,0,0,0,1,0,activenxt,secret,prices,dir,price,volume,iQ,0,iQ->s.quoteid,extra));
//printf("check automatch\n");
//if ( strcmp(exchangestr,"wallet") != 0 && strcmp(exchangestr,"jumblr") != 0 && strcmp(exchangestr,"pangea") != 0 && iQ->s.automatch != 0 && (SUPERNET.automatch & 1) != 0 && (retstr= automatch(prices,dir,volume,price,activenxt,secret)) != 0 )
// return(retstr);
if ( strcmp(IGUANA_NXTACCTSECRET,secret) != 0 )
return(clonestr("{\"error\":\"cant do queued requests with non-default accounts\"}"));
retstr = InstantDEX_str(walletstr,0,1,iQ);
//printf("create_iQ.(%llu) quoteid.%llu walletstr.(%s) %p\n",(long long)iQ->s.offerNXT,(long long)iQ->s.quoteid,walletstr,walletstr);
iQ = create_iQ(iQ,walletstr);
printf("local got create_iQ.(%llu) quoteid.%llu wallet.(%s) baseamount %llu iswallet.%d\n",(long long)iQ->s.offerNXT,(long long)iQ->s.quoteid,walletstr,(long long)iQ->s.baseamount,iQ->s.wallet);
prices777_InstantDEX(prices,MAX_DEPTH);
queue_enqueue("InstantDEX",&InstantDEXQ,queueitem(retstr),0);
}
else
{
iQ = create_iQ(iQ,walletstr);
if ( (retstr= autofill(remoteaddr,iQ,activenxt,secret)) == 0 )
{
//printf("create_iQ.(%llu) quoteid.%llu\n",(long long)iQ->s.offerNXT,(long long)iQ->s.quoteid);
if ( strcmp(IGUANA_NXTACCTSECRET,secret) != 0 )
return(clonestr("{\"error\":\"cant do queued requests with non-default accounts\"}"));
prices777_InstantDEX(prices,MAX_DEPTH);
printf("remote got create_iQ.(%llu) quoteid.%llu wallet.(%s) baseamount %llu\n",(long long)iQ->s.offerNXT,(long long)iQ->s.quoteid,walletstr,(long long)iQ->s.baseamount);
}
return(retstr);
}
} else printf("cant find prices\n");
if ( retstr == 0 )
retstr = clonestr("{\"error\":\"cant get prices ptr\"}");
return(retstr);
}
#endif
#endif

1016
iguana/InstantDEX/quotes777.c

File diff suppressed because it is too large

1496
iguana/InstantDEX/subatomic.h

File diff suppressed because it is too large

323
iguana/InstantDEX/tradebots.h

@ -0,0 +1,323 @@
/******************************************************************************
* Copyright © 2014-2015 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. *
* *
******************************************************************************/
#ifndef xcode_tradebots_h
#define xcode_tradebots_h
#define TRADEBOT_DEFAULT_DURATION (600)
struct tradebot_info
{
char buf[512],name[64],*prevobookstr,NXTADDR[64],NXTACCTSECRET[64];
uint32_t starttime,expiration,finishtime,startedtrades,apitag;
int32_t numtrades,havetrade,numlinks;
double price,volume;
struct prices777_order trades[256]; void *cHandles[256]; int32_t curlings[256];
struct tradebot_info *linkedbots[8];
struct apitag_info *api;
struct tradebot_info *oppo;
struct InstantDEX_quote iQ;
};
// ./SNapi "{\"allfields\":1,\"agent\":\"InstantDEX\",\"method\":\"orderbook\",\"exchange\":\"active\",\"base\":\"NXT\",\"rel\":\"BTC\"}"
// test balance verifier
// test tradeleg verifier
// test pass through quotes
// user lockin addrs
// atomic swaps using 2of3 msig
// broadcast request to all marketmakers
// pick best response and do BTC <-> NXT and NXT <-> ABC
int32_t tradebot_havealltrades(struct tradebot_info *bot)
{
int32_t i;
if ( bot->havetrade != 0 )
{
if ( bot->numlinks > 0 )
{
for (i=0; i<bot->numlinks; i++)
if ( bot->linkedbots[i] == 0 || bot->linkedbots[i]->havetrade == 0 )
return(0);
}
return(1);
}
return(0);
}
struct tradebot_info *tradebot_compile(cJSON *argjson,struct InstantDEX_quote *iQ,struct apitag_info *api)
{
static uint64_t lastmonce;
uint64_t monce; char *name,*tmp,*tmp2; int32_t duration; struct tradebot_info *bot = calloc(1,sizeof(*bot));
monce = (long long)(1000*time(NULL) + milliseconds());
if ( monce == lastmonce )
monce++;
lastmonce = monce;
bot->iQ = *iQ;
bot->api = api;
if ( (duration= juint(argjson,"duration")) == 0 )
duration = TRADEBOT_DEFAULT_DURATION;
bot->expiration = (uint32_t)time(NULL) + duration;
if ( (name= jstr(argjson,"name")) != 0 )
safecopy(bot->name,name,sizeof(bot->name));
else sprintf(bot->name,"bot.%llu",monce);
if ( (tmp= jstr(argjson,"botnxt")) == 0 || (tmp2= jstr(argjson,"secret")) == 0 )
{
safecopy(bot->NXTADDR,SUPERNET.NXTADDR,sizeof(bot->NXTADDR));
safecopy(bot->NXTACCTSECRET,SUPERNET.NXTACCTSECRET,sizeof(bot->NXTACCTSECRET));
}
else
{
safecopy(bot->NXTADDR,tmp,sizeof(bot->NXTADDR));
safecopy(bot->NXTACCTSECRET,tmp2,sizeof(bot->NXTACCTSECRET));
}
//bot->arbmargin = jdouble(argjson,"arbmargin");
return(bot);
}
int32_t tradebot_acceptable(struct tradebot_info *bot,cJSON *item)
{
double price,volume; int32_t dir,i,n; cJSON *trades,*trade;
if ( bot->iQ.s.isask != 0 )
dir = -1;
else dir = 1;
bot->price = price = jdouble(item,"price");
bot->volume = volume = jdouble(item,"volume");
if ( (trades= jarray(&n,item,"trades")) != 0 )
{
/*{
"plugin": "InstantDEX",
"method": "tradesequence",
"dotrade": 1,
"price": 0.00001858,
"volume": 484.39181916,
"trades": [
{
"basket": "bid",
"price": 0.00001858,
"volume": 484.39181916,
"group": 0,
"exchange": "bittrex",
"base": "NXT",
"rel": "BTC",
"trade": "sell",
"name": "NXT/BTC",
"orderprice": 0.00001858,
"ordervolume": 484.39181916
}
]
}*/
if ( n == 1 && is_cJSON_Array(jitem(trades,0)) != 0 )
{
//printf("NESTED ARRAY DETECTED\n");
trades = jitem(trades,0);
n = cJSON_GetArraySize(trades);
}
sprintf(bot->buf,"[%s %s%s %.8f %.4f] <- ",bot->iQ.s.isask != 0 ? "sell" : "buy ",bot->iQ.base,bot->iQ.rel,price,volume);
for (i=0; i<n; i++)
{
trade = jitem(trades,i);
sprintf(bot->buf+strlen(bot->buf),"[%s %s %.8f %.4f] ",jstr(trade,"exchange"),jstr(trade,"trade"),jdouble(trade,"orderprice"),jdouble(trade,"ordervolume"));
}
sprintf(bot->buf+strlen(bot->buf),"n.%d\n",n);
if ( bot->iQ.s.isask == 0 && bot->oppo != 0 && bot->price > 0. && bot->oppo->price > 0 )
{
//if ( bot->price < bot->oppo->price )
{
printf("%s%s%.8f -> %.8f = gain %.3f%%\n\n",bot->buf,bot->oppo->buf,bot->price,bot->oppo->price,(bot->oppo->price/bot->price - 1)*100);
}
}
}
//printf("%s: dir.%d price %.8f vol %f vs bot price %.8f vol %f\n",bot->name,dir,price,volume,bot->iQ.s.price,bot->iQ.s.vol);
//if ( (dir > 0 && price < bot->iQ.s.price) || (dir < 0 && price >= bot->iQ.s.price) )
return(1);
return(0);
}
int32_t tradebot_isvalidtrade(struct tradebot_info *bot,struct prices777_order *order,cJSON *retjson)
{
cJSON *array,*item; char *resultval; double balance,required; int32_t i,n,valid = 0;
if ( (array= jarray(&n,retjson,"traderesults")) != 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( jstr(item,"error") == 0 && (resultval= jstr(item,"success")) != 0 )
{
balance = jdouble(item,"balance");
required = jdouble(item,"required");
printf("[%s %f R%f] ",resultval,balance,required);
valid++;
}
}
//printf("valid.%d of %d\n",valid,n);
if ( valid == n )
return(0);
}
return(-1);
}
int32_t tradebot_tradedone(struct tradebot_info *bot,struct prices777_order *order)
{
struct pending_trade *pend;
if ( (pend= order->pend) != 0 && pend->finishtime != 0 )
return(1);
else return(0);
}
int32_t tradebot_haspending(struct tradebot_info *bot)
{
int32_t i,finished;
for (i=finished=0; i<bot->numtrades; i++)
{
if ( tradebot_tradedone(bot,&bot->trades[i]) > 0 )
finished++;
}
return(finished < bot->numtrades);
}
void tradebot_free(struct tradebot_info *bot)
{
int32_t i; struct pending_trade *pend;
for (i=0; i<bot->numtrades; i++)
{
if ( (pend= bot->trades[i].pend) != 0 )
free_pending(pend);
if ( bot->trades[i].retitem != 0 )
free_json(bot->trades[i].retitem);
if ( bot->cHandles[i] != 0 )
{
while ( bot->curlings[i] != 0 )
{
fprintf(stderr,"%s: wait for curlrequest[%d] to finish\n",bot->name,i);
sleep(3);
}
curlhandle_free(bot->cHandles[i]);
}
}
if ( bot->prevobookstr != 0 )
free(bot->prevobookstr);
free(bot);
}
void Tradebot_loop(void *ptr)
{
int32_t i,n,dotrade; char *obookstr,*retstr; cJSON *json,*array,*item,*retjson,*submit;
char jsonstr[1024]; struct tradebot_info *bot = ptr;
printf("START Tradebot.(%s)\n",bot->name);
while ( bot->finishtime == 0 && time(NULL) < bot->expiration )
{
if ( bot->startedtrades == 0 )
{
sprintf(jsonstr,"{\"allfields\":1,\"agent\":\"InstantDEX\",\"method\":\"orderbook\",\"exchange\":\"active\",\"base\":\"%s\",\"rel\":\"%s\"}",bot->iQ.base,bot->iQ.rel);
if ( (json= cJSON_Parse(jsonstr)) == 0 )
{
printf("cant parse.(%s)\n",jsonstr);
exit(-1);
}
obookstr = SuperNET_SNapi(bot->api,json,0,1);
//printf("GOT.(%s)\n",obookstr);
free_json(json);
if ( bot->prevobookstr == 0 || strcmp(obookstr,bot->prevobookstr) != 0 )
{
if ( bot->prevobookstr != 0 )
free(bot->prevobookstr);
bot->prevobookstr = obookstr;
//printf("UPDATE.(%s)\n",obookstr);
submit = 0;
if ( (json= cJSON_Parse(obookstr)) != 0 )
{
array = (bot->iQ.s.isask != 0) ? jarray(&n,json,"bids") : jarray(&n,json,"asks");
if ( array != 0 && n > 0 )
{
dotrade = 0;
for (i=0; i<1; i++)
{
item = jitem(array,i);
if ( tradebot_acceptable(bot,item) > 0 )
{
submit = cJSON_Duplicate(item,1);
if ( jobj(submit,"dotrade") == 0 )
jaddnum(submit,"dotrade",0);
else cJSON_ReplaceItemInObject(submit,"dotrade",cJSON_CreateNumber(0));
retstr = SuperNET_SNapi(bot->api,submit,0,1);
free_json(submit);
//retstr = InstantDEX_tradesequence(bot->curlings,bot,bot->cHandles,&bot->numtrades,bot->trades,(int32_t)( sizeof(bot->trades)/sizeof(*bot->trades)),dotrade,bot->NXTADDR,bot->NXTACCTSECRET,item);
if ( retstr != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( tradebot_isvalidtrade(bot,&bot->trades[i],retjson) > 0 )
bot->havetrade = 1;
free_json(retjson);
}
free(retstr);
if ( bot->havetrade == 0 )
continue;
}
}
break;
}
if ( 0 && submit != 0 && tradebot_havealltrades(bot) != 0 )
{
dotrade = 1;
cJSON_ReplaceItemInObject(submit,"dotrade",cJSON_CreateNumber(1));
bot->startedtrades = (uint32_t)time(NULL);
retstr = InstantDEX_tradesequence(bot->curlings,bot,bot->cHandles,&bot->numtrades,bot->trades,(int32_t)(sizeof(bot->trades)/sizeof(*bot->trades)),dotrade,bot->NXTADDR,bot->NXTACCTSECRET,item);
printf("TRADE RESULT.(%s)\n",retstr);
break;
}
}
free_json(json);
}
}
}
else if ( bot->startedtrades != 0 )
{
if ( tradebot_haspending(bot) > 0 && bot->finishtime == 0 )
bot->finishtime = (uint32_t)time(NULL);
}
usleep(5000000);
}
while ( tradebot_haspending(bot) != 0 )
sleep(60);
printf("FINISHED Tradebot.(%s) at %u finishtime.%u expiration.%u\n",bot->name,(uint32_t)time(NULL),bot->finishtime,bot->expiration);
tradebot_free(bot);
}
char *Tradebot_parser(cJSON *argjson,struct InstantDEX_quote *iQ,struct apitag_info *api)
{
char *submethod,*exchange; struct tradebot_info *bot,*oppobot;
printf("InstantDEX_tradebot.(%s) (%s/%s)\n",jprint(argjson,0),iQ->base,iQ->rel);
if ( (submethod= jstr(argjson,"submethod")) != 0 && (exchange= jstr(argjson,"exchange")) != 0 && strcmp(exchange,"active") == 0 && iQ != 0 )
{
if ( strcmp(submethod,"simplebot") == 0 )
{
if ( (bot= tradebot_compile(argjson,iQ,api)) == 0 )
return(clonestr("{\"error\":\"tradebot compiler error\"}"));
iQ->s.isask ^= 1;
if ( (oppobot= tradebot_compile(argjson,iQ,api)) == 0 )
return(clonestr("{\"error\":\"tradebot compiler error\"}"));
bot->oppo = oppobot;
oppobot->oppo = bot;
iguana_launch("bot",(void *)Tradebot_loop,bot);
iguana_launch("oppobot",(void *)Tradebot_loop,oppobot);
return(clonestr("{\"result\":\"tradebot started\"}"));
} else return(clonestr("{\"error\":\"unrecognized tradebot command\"}"));
return(clonestr("{\"result\":\"tradebot command processed\"}"));
} else return(clonestr("{\"error\":\"no prices777 or no tradebot submethod or not active exchange\"}"));
}
#endif

1583
iguana/InstantDEX/trades.h

File diff suppressed because it is too large

262
iguana/exchanges/bitfinex.c

@ -0,0 +1,262 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#define EXCHANGE_NAME "bitfinex"
#define UPDATE bitfinex ## _price
#define SUPPORTS bitfinex ## _supports
#define SIGNPOST bitfinex ## _signpost
#define TRADE bitfinex ## _trade
#define ORDERSTATUS bitfinex ## _orderstatus
#define CANCELORDER bitfinex ## _cancelorder
#define OPENORDERS bitfinex ## _openorders
#define TRADEHISTORY bitfinex ## _tradehistory
#define BALANCES bitfinex ## _balances
#define PARSEBALANCE bitfinex ## _parsebalance
#define WITHDRAW bitfinex ## _withdraw
#define CHECKBALANCE bitfinex ## _checkbalance
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,cJSON *argjson)
{
char url[1024];
sprintf(url,"https://api.bitfinex.com/v1/book/%s%s",base,rel);
return(exchanges777_standardprices(exchange,base,rel,url,quotes,"price","amount",maxdepth,0));
}
int32_t SUPPORTS(struct exchange_info *exchange,char *base,char *rel,cJSON *argjson)
{
char *baserels[][2] = { {"btc","usd"}, {"ltc","usd"}, {"ltc","btc"} };
return(baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel));
}
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
//[[{"type":"deposit","currency":"btc","amount":"0.0","available":"0.0"},{"type":"deposit","currency":"usd","amount":"0.0","available":"0.0"},{"type":"exchange","currency":"btc","amount":"0.01065851","available":"0.01065851"},{"type":"exchange","currency":"usd","amount":"23386.37278962","available":"0.00378962"},{"type":"trading","currency":"btc","amount":"0.0","available":"0.0"},{"type":"trading","currency":"usd","amount":"0.0","available":"0.0"}]]
int32_t i,n,ind; char field[64],*str,*typestr,*itemstr = 0; cJSON *item,*obj,*array; double amounts[3],avail[3],val0,val1;
*balancep = 0.;
strcpy(field,coinstr), tolowercase(field);
memset(amounts,0,sizeof(amounts));
memset(avail,0,sizeof(avail));
if ( argjson != 0 && is_cJSON_Array(argjson) != 0 && (n= cJSON_GetArraySize(argjson)) > 0 )
{
for (i=0; i<n; i++)
{
if ( (item= jitem(argjson,i)) != 0 )
{
if ( (str= jstr(item,"currency")) != 0 && strcmp(field,str) == 0 )
{
val0 = jdouble(item,"amount");
val1 = jdouble(item,"available");
if ( (typestr= jstr(item,"type")) != 0 )
{
if ( strcmp(typestr,"deposit") == 0 )
ind = 0;
else if ( strcmp(typestr,"exchange") == 0 )
ind = 1;
else if ( strcmp(typestr,"trading") == 0 )
ind = 2;
else ind = -1;
if ( ind >= 0 )
{
amounts[ind] = val0;
avail[ind] = val1;
}
}
}
}
}
if ( (obj= cJSON_CreateObject()) != 0 )
{
touppercase(field);
*balancep = avail[0] + avail[1] + avail[2];
jaddstr(obj,"base",field);
jaddnum(obj,"balance",*balancep);
jaddnum(obj,"total",amounts[0]+amounts[1]+amounts[2]);
array = cJSON_CreateArray(), jaddinum(array,avail[0]), jaddinum(array,amounts[0]), jadd(obj,"deposit",array);
array = cJSON_CreateArray(), jaddinum(array,avail[1]), jaddinum(array,amounts[1]), jadd(obj,"exchange",array);
array = cJSON_CreateArray(), jaddinum(array,avail[2]), jaddinum(array,amounts[2]), jadd(obj,"trading",array);
itemstr = jprint(obj,1);
}
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *payload,char *method)
{
char dest[1025],url[1024],hdr1[512],hdr2[512],hdr3[512],hdr4[512],req[1024],*sig,*data = 0; cJSON *json;
hdr1[0] = hdr2[0] = hdr3[0] = hdr4[0] = 0;
json = 0;
nn_base64_encode((void *)payload,strlen(payload),req,sizeof(req));
if ( (sig= hmac_sha384_str(dest,exchange->apisecret,(int32_t)strlen(exchange->apisecret),req)) != 0 )
{
sprintf(hdr1,"X-BFX-APIKEY:%s",exchange->apikey);
sprintf(hdr2,"X-BFX-PAYLOAD:%s",req);
sprintf(hdr3,"X-BFX-SIGNATURE:%s",sig);
//printf("req.(%s) H0.(%s) H1.(%s) H2.(%s)\n",req,hdr1,hdr2,hdr3);
sprintf(url,"https://api.bitfinex.com/v1/%s",method);
if ( dotrade == 0 )
data = exchange_would_submit(req,hdr1,hdr2,hdr3,hdr4);
else if ( (data= curl_post(&exchange->cHandle,url,0,req,hdr1,hdr2,hdr3,hdr4)) != 0 )
json = cJSON_Parse(data);
if ( retstrp != 0 )
*retstrp = data;
else if ( data != 0 )
free(data);
}
return(json);
}
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],*method;
method = "balances";
sprintf(payload,"{\"request\":\"/v1/%s\",\"nonce\":\"%llu\"}",method,(long long)exchange_nonce(exchange));
return(SIGNPOST(&exchange->cHandle,1,0,exchange,payload,method));
}
#include "checkbalance.c"
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
{
char payload[1024],pairstr[512],*typestr,*method,*extra; cJSON *json; uint64_t txid = 0;
if ( (extra= *retstrp) != 0 )
*retstrp = 0;
if ( (dir= flipstr_for_exchange(exchange,pairstr,"%s%s",dir,&price,&volume,base,rel,argjson)) == 0 )
{
printf("cant find baserel (%s/%s)\n",base,rel);
return(0);
}
method = "order/new";
//Either "market" / "limit" / "stop" / "trailing-stop" / "fill-or-kill" / "exchange market" / "exchange limit" / "exchange stop" / "exchange trailing-stop" / "exchange fill-or-kill". (type starting by "exchange " are exchange orders, others are margin trading orders)
if ( (typestr= extra) == 0 )
typestr = "exchange limit";
sprintf(payload,"{\"request\":\"/v1/%s\",\"nonce\":\"%llu\",\"exchange\":\"bitfinex\",\"side\":\"%s\",\"type\":\"%s\",\"price\":\"%.8f\",\"amount\":\"%.8f\",\"symbol\":\"%s\"}",method,(long long)exchange_nonce(exchange),dir>0?"buy":"sell",typestr,price,volume,pairstr);
if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume,argjson) == 0 && (json= SIGNPOST(&exchange->cHandle,dotrade,retstrp,exchange,payload,method)) != 0 )
{
if ( (txid= j64bits(json,"order_id")) == 0 )
{
if ( dir != 0 )
printf("bitfinex: no txid error\n");
}
free_json(json);
}
return(txid);
}
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char payload[1024],*method,*retstr = 0; cJSON *json;
method = "order/status";
sprintf(payload,"{\"request\":\"/v1/%s\",\"nonce\":\"%llu\",\"order_id\":%llu}",method,(long long)exchange_nonce(exchange),(long long)quoteid);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,payload,method)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized orderstatus
}
char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char payload[1024],*method,*retstr = 0; cJSON *json;
method = "order/cancel";
sprintf(payload,"{\"request\":\"/v1/%s\",\"nonce\":\"%llu\",\"order_id\":%llu}",method,(long long)exchange_nonce(exchange),(long long)quoteid);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,payload,method)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized cancelorder
}
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],*method,*retstr = 0; cJSON *json;
method = "orders";
sprintf(payload,"{\"request\":\"/v1/%s\",\"nonce\":\"%llu\"}",method,(long long)exchange_nonce(exchange));
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,payload,method)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized open orders
}
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],baserel[16],*method,*base,*rel,*retstr = 0; uint32_t timestamp; cJSON *json;
method = "mytrades";
base = jstr(argjson,"base");
rel = jstr(argjson,"rel");
if ( base == 0 || rel == 0 )
{
base = "BTC";
rel = "USD";
}
sprintf(baserel,"%s%s",base,rel);
timestamp = juint(argjson,"start");
sprintf(payload,"{\"request\":\"/v1/%s\",\"nonce\":\"%llu\",\"symbol\":\"%s\",\"timestamp\":%u}",method,(long long)exchange_nonce(exchange),baserel,timestamp);
//printf("TRADEHISTORY.(%s)\n",payload);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,payload,method)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized tradehistory
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
char payload[1024],*method,*type,*retstr = 0; cJSON *json;
if ( base == 0 || base[0] == 0 )
return(clonestr("{\"error\":\"base not specified\"}"));
if ( destaddr == 0 || destaddr[0] == 0 )
return(clonestr("{\"error\":\"destaddr not specified\"}"));
if ( amount < SMALLVAL )
return(clonestr("{\"error\":\"amount not specified\"}"));
if ( base == 0 )
base = "bitcoin";
else if ( strcmp(base,"BTC") == 0 )
base = "bitcoin";
else if ( strcmp(base,"LTC") == 0 )
base = "litecoin";
else if ( strcmp(base,"DRK") == 0 )
base = "darkcoin";
else return(clonestr("{\"error\":\"invalid base specified\"}"));
if ( (type= jstr(argjson,"extra")) == 0 )
type = "exchange";
else if ( strcmp(type,"exchange") != 0 && strcmp(type,"trading") != 0 && strcmp(type,"deposit") != 0 )
return(clonestr("{\"error\":\"invalid wallet type specified\"}"));
method = "withdraw";
sprintf(payload,"{\"request\":\"/v1/%s\",\"nonce\":\"%llu\",\"amount\":\"%.6f\",\"withdraw_type\":\"%s\",\"walletselected\":\"%s\",\"address\":\"%s\"}",method,(long long)exchange_nonce(exchange),amount,base,type,destaddr);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,payload,method)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized withdraw
}
struct exchange_funcs bitfinex_funcs = EXCHANGE_FUNCS(bitfinex,EXCHANGE_NAME);
#undef UPDATE
#undef SUPPORTS
#undef SIGNPOST
#undef TRADE
#undef ORDERSTATUS
#undef CANCELORDER
#undef OPENORDERS
#undef TRADEHISTORY
#undef BALANCES
#undef PARSEBALANCE
#undef WITHDRAW
#undef EXCHANGE_NAME
#undef CHECKBALANCE

170
iguana/exchanges/bitstamp.c

@ -0,0 +1,170 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#define EXCHANGE_NAME "bitstamp"
#define UPDATE bitstamp ## _price
#define SUPPORTS bitstamp ## _supports
#define SIGNPOST bitstamp ## _signpost
#define TRADE bitstamp ## _trade
#define ORDERSTATUS bitstamp ## _orderstatus
#define CANCELORDER bitstamp ## _cancelorder
#define OPENORDERS bitstamp ## _openorders
#define TRADEHISTORY bitstamp ## _tradehistory
#define BALANCES bitstamp ## _balances
#define PARSEBALANCE bitstamp ## _parsebalance
#define WITHDRAW bitstamp ## _withdraw
#define EXCHANGE_AUTHURL "https://www.bitstamp.net/api"
#define CHECKBALANCE bitstamp ## _checkbalance
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,cJSON *argjson)
{
char url[1024];
sprintf(url,"https://www.bitstamp.net/api/order_book/");
return(exchanges777_standardprices(exchange,base,rel,url,quotes,0,0,maxdepth,0));
}
int32_t SUPPORTS(struct exchange_info *exchange,char *base,char *rel,cJSON *argjson)
{
char *baserels[][2] = { {"btc","usd"} };
return(baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel));
}
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *method,char *payload)
{
/*signature is a HMAC-SHA256 encoded message containing: nonce, customer ID (can be found here) and API key. The HMAC-SHA256 code must be generated using a secret key that was generated with your API key. This code must be converted to it's hexadecimal representation (64 uppercase characters).Example (Python):
message = nonce + customer_id + api_key
signature = hmac.new(API_SECRET, msg=message, digestmod=hashlib.sha256).hexdigest().upper()
key - API key
signature - signature
nonce - nonce
*/
char dest[1025],url[1024],req[1024],hdr1[512],hdr2[512],hdr3[512],hdr4[512],*sig,*data = 0;
cJSON *json; uint64_t nonce;
hdr1[0] = hdr2[0] = hdr3[0] = hdr4[0] = 0;
nonce = exchange_nonce(exchange);
sprintf(req,"%llu%s%s",(long long)nonce,exchange->userid,exchange->apikey);
json = 0;
if ( (sig= hmac_sha256_str(dest,exchange->apisecret,(int32_t)strlen(exchange->apisecret),req)) != 0 )
{
//touppercase(sig);
//printf("req.(%s) sig.(%s)\n",req,sig);
//sprintf(req,"{\"key\":\"%s\",\"signature\":\"%s\",\"nonce\":%llu%s}",exchange->apikey,sig,(long long)nonce,payload);
sprintf(req,"key=%s&signature=%s&nonce=%llu%s",exchange->apikey,sig,(long long)nonce,payload);
//printf("submit.(%s)\n",req);
sprintf(url,"%s/%s/",EXCHANGE_AUTHURL,method);
if ( dotrade == 0 )
data = exchange_would_submit(req,hdr1,hdr2,hdr3,hdr4);
else if ( (data= curl_post(&exchange->cHandle,url,0,req,req,hdr2,hdr3,hdr4)) != 0 )
json = cJSON_Parse(data);
}
if ( retstrp != 0 )
*retstrp = data;
else if ( data != 0 )
free(data);
return(json);
}
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
char field[128],*itemstr = 0; cJSON *obj,*item;
*balancep = 0.;
strcpy(field,coinstr);
tolowercase(field);
if ( argjson != 0 && (obj= jobj(argjson,"return")) != 0 && (item= jobj(obj,"funds")) != 0 )
{
*balancep = jdouble(item,field);
obj = cJSON_CreateObject();
touppercase(field);
jaddstr(obj,"base",field);
jaddnum(obj,"balance",*balancep);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
return(SIGNPOST(&exchange->cHandle,1,0,exchange,"balance",""));
}
#include "checkbalance.c"
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
{
char payload[1024],url[512],pairstr[512],*extra; cJSON *json; uint64_t txid = 0;
if ( (extra= *retstrp) != 0 )
*retstrp = 0;
if ( (dir= flipstr_for_exchange(exchange,pairstr,"%s%s",dir,&price,&volume,base,rel,argjson)) == 0 )
{
printf("cant find baserel (%s/%s)\n",base,rel);
return(0);
}
sprintf(url,"%s/%s/",EXCHANGE_AUTHURL,dir>0 ? "buy" : "sell");
if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume,argjson) == 0 && (json= SIGNPOST(&exchange->cHandle,dotrade,retstrp,exchange,url,payload)) != 0 )
{
// parse json and set txid
free_json(json);
}
return(txid);
}
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char jsonbuf[128];
sprintf(jsonbuf,"&id=%llu",(long long)quoteid);
return(jprint(SIGNPOST(&exchange->cHandle,1,0,exchange,"order_status",jsonbuf),1));
}
char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char jsonbuf[128];
sprintf(jsonbuf,"&id=%llu",(long long)quoteid);
return(jprint(SIGNPOST(&exchange->cHandle,1,0,exchange,"cancel_order",jsonbuf),1));
}
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
return(jprint(SIGNPOST(&exchange->cHandle,1,0,exchange,"open_orders",""),1));
}
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
return(jprint(SIGNPOST(&exchange->cHandle,1,0,exchange,"user_transactions",""),1));
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
return(clonestr("{\"error\":\"withdraw not yet\"}"));
}
struct exchange_funcs bitstamp_funcs = EXCHANGE_FUNCS(bitstamp,EXCHANGE_NAME);
#undef UPDATE
#undef SUPPORTS
#undef SIGNPOST
#undef TRADE
#undef ORDERSTATUS
#undef CANCELORDER
#undef OPENORDERS
#undef TRADEHISTORY
#undef BALANCES
#undef PARSEBALANCE
#undef WITHDRAW
#undef EXCHANGE_NAME
#undef EXCHANGE_AUTHURL
#undef CHECKBALANCE

245
iguana/exchanges/bittrex.c

@ -0,0 +1,245 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#define EXCHANGE_NAME "bittrex"
#define UPDATE bittrex ## _price
#define SUPPORTS bittrex ## _supports
#define SIGNPOST bittrex ## _signpost
#define TRADE bittrex ## _trade
#define ORDERSTATUS bittrex ## _orderstatus
#define CANCELORDER bittrex ## _cancelorder
#define OPENORDERS bittrex ## _openorders
#define TRADEHISTORY bittrex ## _tradehistory
#define BALANCES bittrex ## _balances
#define PARSEBALANCE bittrex ## _parsebalance
#define WITHDRAW bittrex ## _withdraw
#define CHECKBALANCE bittrex ## _checkbalance
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,cJSON *argjson)
{
cJSON *json,*obj; char *jsonstr,market[128],url[1024]; double hbla = 0.;
sprintf(market,"%s-%s",rel,base);
sprintf(url,"https://bittrex.com/api/v1.1/public/getorderbook?market=%s&type=both&depth=%d",market,maxdepth);
jsonstr = issue_curl(url);
if ( jsonstr != 0 )
{
if ( (json = cJSON_Parse(jsonstr)) != 0 )
{
if ( (obj= cJSON_GetObjectItem(json,"success")) != 0 && is_cJSON_True(obj) != 0 )
hbla = exchanges777_json_orderbook(exchange,base,rel,quotes,maxdepth,json,"result","buy","sell","Rate","Quantity");
free_json(json);
}
free(jsonstr);
}
return(hbla);
}
int32_t SUPPORTS(struct exchange_info *exchange,char *base,char *rel,cJSON *argjson)
{
if ( strlen(base) > 5 || strlen(rel) > 5 || strcmp(rel,"CNY") == 0 || strcmp(base,"CNY") == 0 || strcmp(rel,"USD") == 0 || strcmp(base,"USD") == 0 )
return(0);
if ( strcmp(rel,"BTC") == 0 )
return(1);
else if ( strcmp(base,"BTC") == 0 )
return(-1);
else return(0);
}
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *url,char *payload)
{
char dest[(512>>3)*2+1],hdr1[512],hdr2[512],hdr3[512],hdr4[512],*data,*sig; cJSON *json;
hdr1[0] = hdr2[0] = hdr3[0] = hdr4[0] = 0;
json = 0;
if ( (sig= hmac_sha512_str(dest,exchange->apisecret,(int32_t)strlen(exchange->apisecret),payload)) != 0 )
sprintf(hdr1,"apisign:%s",sig);
if ( dotrade == 0 )
data = exchange_would_submit(payload,hdr1,hdr2,hdr3,hdr4);
else if ( (data= curl_post(&exchange->cHandle,url,0,payload,hdr1,hdr2,hdr3,hdr4)) != 0 )
json = cJSON_Parse(data);
if ( retstrp != 0 )
*retstrp = data;
else if ( data != 0 )
free(data);
return(json);
}
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024];
sprintf(payload,"https://bittrex.com/api/v1.1/account/getbalances?apikey=%s&nonce=%llu",exchange->apikey,(long long)exchange_nonce(exchange));
return(SIGNPOST(&exchange->cHandle,1,0,exchange,payload,payload));
}
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
int32_t i,n; char *str,*itemstr = 0; cJSON *item,*array,*obj; double total,pending;
*balancep = 0.;
if ( argjson != 0 && (array= jarray(&n,argjson,"result")) != 0 )
{
for (i=0; i<n; i++)
{
if ( (item= jitem(array,i)) != 0 )
{
if ( (str= jstr(item,"Currency")) != 0 && strcmp(coinstr,str) == 0 )
{
itemstr = jprint(item,0);
*balancep = jdouble(item,"Available");
total = jdouble(item,"Balance");
pending = jdouble(item,"Pending");
if ( (obj= cJSON_Parse(itemstr)) != 0 )
{
jaddnum(obj,"balance",*balancep);
jaddnum(obj,"total",total);
jaddnum(obj,"pending",pending);
if ( (str= jstr(obj,"CryptoAddress")) != 0 )
jaddstr(obj,"deposit_address",str);
free(itemstr);
itemstr = jprint(obj,1);
}
break;
}
}
}
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance, are you sure it isnt empty account?\"}"));
return(itemstr);
}
#include "checkbalance.c"
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
{
char payload[1024],pairstr[512],*extra; cJSON *json,*resultobj; uint64_t txid = 0; int32_t i,j,n;
struct destbuf uuidstr; uint8_t databuf[512];
if ( (extra= *retstrp) != 0 )
*retstrp = 0;
if ( (dir= flip_for_exchange(pairstr,"%s-%s","BTC",dir,&price,&volume,base,rel)) == 0 )
{
return(0);
}
sprintf(payload,"https://bittrex.com/api/v1.1/market/%slimit?apikey=%s&nonce=%llu&market=%s&rate=%.8f&quantity=%.8f",dir>0?"buy":"sell",exchange->apikey,(long long)exchange_nonce(exchange),pairstr,price,volume);
if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume,argjson) == 0 && (json= SIGNPOST(&exchange->cHandle,dotrade,retstrp,exchange,payload,payload)) != 0 )
{
if ( is_cJSON_True(cJSON_GetObjectItem(json,"success")) != 0 && (resultobj= cJSON_GetObjectItem(json,"result")) != 0 )
{
copy_cJSON(&uuidstr,cJSON_GetObjectItem(resultobj,"uuid"));
for (i=j=0; uuidstr.buf[i]!=0; i++)
if ( uuidstr.buf[i] != '-' )
uuidstr.buf[j++] = uuidstr.buf[i];
uuidstr.buf[j] = 0;
n = (int32_t)strlen(uuidstr.buf);
printf("-> uuidstr.(%s).%d\n",uuidstr.buf,n);
decode_hex(databuf,n/2,uuidstr.buf);
if ( n >= 16 )
for (i=0; i<8; i++)
databuf[i] ^= databuf[8 + i];
memcpy(&txid,databuf,8);
printf("-> %llx\n",(long long)txid);
}
free_json(json);
}
return(txid);
}
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char payload[1024],*retstr = 0; cJSON *json;
sprintf(payload,"https://bittrex.com/api/v1.1/account/getorder?apikey=%s&nonce=%llu&uuid=%llu",exchange->apikey,(long long)exchange_nonce(exchange),(long long)quoteid);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,payload,payload)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized orderstatus
}
char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char payload[1024],*retstr = 0; cJSON *json;
sprintf(payload,"https://bittrex.com/api/v1.1/market/cancel?apikey=%s&nonce=%llu&uuid=%llu",exchange->apikey,(long long)exchange_nonce(exchange),(long long)quoteid);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,payload,payload)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized cancelorder
}
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],market[64],*base,*rel,*retstr = 0; cJSON *json;
sprintf(payload,"https://bittrex.com/api/v1.1/market/getopenorders?apikey=%s&nonce=%llu",exchange->apikey,(long long)exchange_nonce(exchange));
if ( (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 )
{
sprintf(market,"%s-%s",rel,base);
sprintf(payload + strlen(payload),"&market=%s",market);
}
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,payload,payload)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized open orders
}
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],market[64],*base,*rel,*retstr = 0; cJSON *json;
sprintf(payload,"https://bittrex.com/api/v1.1/account/getorderhistory?apikey=%s&nonce=%llu",exchange->apikey,(long long)exchange_nonce(exchange));
if ( (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 )
{
sprintf(market,"%s-%s",rel,base);
sprintf(payload + strlen(payload),"&market=%s",market);
}
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,payload,payload)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized tradehistory
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
char payload[1024],*paymentid,*retstr = 0; cJSON *json;
if ( base == 0 || base[0] == 0 )
return(clonestr("{\"error\":\"base not specified\"}"));
if ( destaddr == 0 || destaddr[0] == 0 )
return(clonestr("{\"error\":\"destaddr not specified\"}"));
if ( amount < SMALLVAL )
return(clonestr("{\"error\":\"amount not specified\"}"));
paymentid = jstr(argjson,"paymentid");
sprintf(payload,"https://bittrex.com/api/v1.1/account/withdraw?apikey=%s&nonce=%llu&currency=%s&amount=%.4f&address=%s",exchange->apikey,(long long)exchange_nonce(exchange),base,amount,destaddr);
if ( paymentid != 0 )
sprintf(payload + strlen(payload),"&paymentid=%s",paymentid);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,payload,payload)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized withdraw
}
struct exchange_funcs bittrex_funcs = EXCHANGE_FUNCS(bittrex,EXCHANGE_NAME);
#undef UPDATE
#undef SUPPORTS
#undef SIGNPOST
#undef TRADE
#undef ORDERSTATUS
#undef CANCELORDER
#undef OPENORDERS
#undef TRADEHISTORY
#undef BALANCES
#undef PARSEBALANCE
#undef WITHDRAW
#undef EXCHANGE_NAME
#undef CHECKBALANCE

321
iguana/exchanges/btc38.c

@ -0,0 +1,321 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#define EXCHANGE_NAME "btc38"
#define UPDATE btc38 ## _price
#define SUPPORTS btc38 ## _supports
#define SIGNPOST btc38 ## _signpost
#define TRADE btc38 ## _trade
#define ORDERSTATUS btc38 ## _orderstatus
#define CANCELORDER btc38 ## _cancelorder
#define OPENORDERS btc38 ## _openorders
#define TRADEHISTORY btc38 ## _tradehistory
#define BALANCES btc38 ## _balances
#define PARSEBALANCE btc38 ## _parsebalance
#define WITHDRAW btc38 ## _withdraw
#define EXCHANGE_AUTHURL "http://www.btc38.com/trade/t_api"
#define CHECKBALANCE btc38 ## _checkbalance
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,cJSON *argjson)
{
char url[1024],lrel[16],lbase[16];
strcpy(lrel,rel), strcpy(lbase,base);
tolowercase(lrel), tolowercase(lbase);
if ( strcmp(lbase,"cny") == 0 && strcmp(lrel,"btc") == 0 )
sprintf(url,"http://api.btc38.com/v1/depth.php?c=%s&mk_type=%s","btc","cny");
else sprintf(url,"http://api.btc38.com/v1/depth.php?c=%s&mk_type=%s",lbase,lrel);
return(exchanges777_standardprices(exchange,base,rel,url,quotes,0,0,maxdepth,0));
}
int32_t SUPPORTS(struct exchange_info *exchange,char *_base,char *_rel,cJSON *argjson)
{
char *cnypairs[] = { "BTC", "LTC", "DOGE", "XRP", "BTS", "STR", "NXT", "BLK", "BC", "VPN", "BILS", "BOST", "PPC", "APC", "ZCC", "XPM", "DGC", "MEC", "WDC", "QRK", "BEC", "ANC", "UNC", "RIC", "SRC", "TAG" };
char *btcpairs[] = { "TMC", "LTC", "DOGE", "XRP", "BTS", "XEM", "VPN", "XCN", "VOOT", "SYS", "NRS", "NAS", "SYNC", "MED", "EAC" };
int32_t i; char base[64],rel[64];
strcpy(base,_base), strcpy(rel,_rel);
touppercase(base), touppercase(rel);
if ( strlen(base) > 5 || strlen(rel) > 5 )
return(0);
if ( strcmp(base,"BTC") == 0 && strcmp(rel,"CNY") == 0 )
return(1);
else if ( strcmp(base,"CNY") == 0 && strcmp(rel,"BTC") == 0 )
return(-1);
else if ( strcmp(base,"BTC") == 0 )
{
for (i=0; i<sizeof(btcpairs)/sizeof(*btcpairs); i++)
if ( strcmp(btcpairs[i],rel) == 0 )
return(-1);
}
else if ( strcmp(rel,"BTC") == 0 )
{
for (i=0; i<sizeof(btcpairs)/sizeof(*btcpairs); i++)
if ( strcmp(btcpairs[i],base) == 0 )
return(1);
}
else if ( strcmp(base,"CNY") == 0 )
{
for (i=0; i<sizeof(cnypairs)/sizeof(*cnypairs); i++)
if ( strcmp(cnypairs[i],rel) == 0 )
return(-1);
}
else if ( strcmp(rel,"CNY") == 0 )
{
for (i=0; i<sizeof(cnypairs)/sizeof(*cnypairs); i++)
if ( strcmp(cnypairs[i],base) == 0 )
return(1);
}
printf("BTC38 doesnt support (%s/%s)\n",base,rel);
return(0);
}
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *payload,char *path)
{
char cmdbuf[2048],url[1024],buf[1024],hdr1[512],hdr2[512],hdr3[512],hdr4[512],digest[33],*data;
cJSON *json; uint64_t nonce;
hdr1[0] = hdr2[0] = hdr3[0] = hdr4[0] = 0;
json = 0;
nonce = exchange_nonce(exchange);
sprintf(buf,"%s_%s_%s_%llu",exchange->apikey,exchange->userid,exchange->apisecret,(long long)nonce);
//printf("MD5.(%s)\n",buf);
calc_md5(digest,buf,(int32_t)strlen(buf));
sprintf(cmdbuf,"key=%s&time=%llu&md5=%s%s",exchange->apikey,(long long)nonce,digest,payload);
sprintf(url,"%s/%s",EXCHANGE_AUTHURL,path);
if ( dotrade == 0 )
data = exchange_would_submit(payload,hdr1,hdr2,hdr3,hdr4);
else if ( (data= curl_post(&exchange->cHandle,url,0,cmdbuf,hdr1,hdr2,hdr3,hdr4)) != 0 )
json = cJSON_Parse(data);
if ( retstrp != 0 )
*retstrp = data;
else if ( data != 0 )
free(data);
return(json);
}
/* $ Stamp = $ date-> getTimestamp ();
type, 1 for the purchase of Entry, 2 entry order to sell, can not be empty / the type of the order
$ Mdt = "_ public here to write here write here to write user ID_ private _" $ stamp.;
$ Mdt = md5 ($ mdt);
$ Data = array ("key" => "here to write public", "time" => $ stamp, "md5" => $ mdt, "type" => 1, "mk_type" => "cny",
"Price" => "0.0001", "amount" => "100", "coinname" => "XRP");
// $ Data_string = json_encode ($ data);
$ Ch = curl_init ();
curl_setopt ($ ch, CURLOPT_URL, 'http://www.btc38.com/trade/t_api/submitOrder.php');
curl_setopt ($ ch, CURLOPT_POST, 1);
curl_setopt ($ ch, CURLOPT_POSTFIELDS, $ data);
curl_setopt ($ ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ ch, CURLOPT_HEADER, 0); */
/*
static CURL *cHandle;
char *data,*path,url[1024],cmdbuf[8192],buf[512],digest[33],market[16],base[64],rel[64],coinname[16],fmtstr[512],*pricefmt,*volfmt = "%.3f";
cJSON *json,*resultobj; uint64_t nonce,txid = 0;
if ( _base != 0 && _rel != 0 )
{
strcpy(base,_base), strcpy(rel,_rel);
touppercase(base), touppercase(rel);
if ( btc38_supports(base,rel) == 0 )
{
*retstrp = clonestr("{\"error\":\"invalid contract pair\"}");
return(0);
}
}
nonce = exchange_nonce(exchange);
sprintf(buf,"%s_%s_%s_%llu",exchange->apikey,exchange->userid,exchange->apisecret,(long long)nonce);
//printf("MD5.(%s)\n",buf);
calc_md5(digest,buf,(int32_t)strlen(buf));
*retstrp = 0;
if ( dir == 0 )
{
path = "getMyBalance.php";
sprintf(cmdbuf,"key=%s&time=%llu&md5=%s",exchange->apikey,(long long)nonce,digest);
}
else
{
if ( (data= curl_post(&cHandle,url,0,cmdbuf,0,0,0,0)) != 0 )
{
//printf("submit cmd.(%s) [%s]\n",cmdbuf,data);
if ( (json= cJSON_Parse(data)) != 0 )
{
if ( juint(json,"success") > 0 && (resultobj= cJSON_GetObjectItem(json,"return")) != 0 )
{
if ( (txid= get_API_nxt64bits(cJSON_GetObjectItem(resultobj,"order_id"))) == 0 )
{
if ( get_API_nxt64bits(cJSON_GetObjectItem(resultobj,"remains")) == 0 )
txid = _crc32(0,cmdbuf,strlen(cmdbuf));
}
}
free_json(json);
}
} else fprintf(stderr,"submit err cmd.(%s)\n",cmdbuf);
if ( retstrp != 0 && data != 0 )
{
if ( (json= cJSON_Parse(data)) == 0 )
{
json = cJSON_CreateObject();
jaddstr(json,"result",data);
data = jprint(json,1);
} else free_json(json);
//printf("btc38 returning.(%s) in %p\n",data,data);
*retstrp = data;
}
else if ( data != 0 )
free(data);
return(txid);
*/
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
return(SIGNPOST(&exchange->cHandle,1,0,exchange,"","getMyBalance.php"));
}
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
char field[128],*str,*itemstr = 0; cJSON *obj; double lockbalance,imma;
*balancep = 0.;
strcpy(field,coinstr);
tolowercase(field);
strcat(field,"_balance");
if ( argjson != 0 && (str= jstr(argjson,field)) != 0 )
{
*balancep = jdouble(argjson,field);
strcpy(field,coinstr), tolowercase(field), strcat(field,"_balance_lock");
lockbalance = jdouble(argjson,field);
strcpy(field,coinstr), tolowercase(field), strcat(field,"_balance_imma");
imma = jdouble(argjson,field);
obj = cJSON_CreateObject();
jaddnum(obj,"balance",*balancep);
jaddnum(obj,"locked_balance",lockbalance);
jaddnum(obj,"imma_balance",imma);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
#include "checkbalance.c"
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
{
char payload[1024],market[16],coinname[16],fmtstr[512],*pricefmt,*extra,*volfmt = "%.3f";
cJSON *json,*resultobj; uint64_t txid = 0;
if ( (extra= *retstrp) != 0 )
*retstrp = 0;
if ( (dir= cny_flip(market,coinname,base,rel,dir,&price,&volume)) == 0 )
{
fprintf(stderr,"btc38_trade illegal base.(%s) or rel.(%s)\n",base,rel);
return(0);
}
if ( strcmp(market,"cny") == 0 )
pricefmt = "%.5f";
else pricefmt = "%.6f";
//sprintf(fmtstr,"key=%%s&time=%%llu&md5=%%s&type=%%s&mk_type=%%s&coinname=%%s&price=%s&amount=%s",pricefmt,volfmt);
//sprintf(payload,fmtstr,exchange->apikey,(long long)nonce,digest,dir>0?"1":"2",market,coinname,price,volume);
sprintf(fmtstr,"&type=%%s&mk_type=%%s&coinname=%%s&price=%s&amount=%s",pricefmt,volfmt);
sprintf(payload,fmtstr,dir>0?"1":"2",market,coinname,price,volume);
if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume,argjson) == 0 && (json= SIGNPOST(&exchange->cHandle,dotrade,retstrp,exchange,payload,"submitOrder.php")) != 0 )
{
if ( juint(json,"success") > 0 && (resultobj= jobj(json,"return")) != 0 )
{
if ( (txid= j64bits(resultobj,"order_id")) == 0 )
{
if ( j64bits(resultobj,"remains") == 0 )
txid = calc_crc32(0,payload,strlen(payload));
}
}
free_json(json);
if ( retstrp != 0 && *retstrp != 0 )
{
if ( (json= cJSON_Parse(*retstrp)) == 0 )
{
json = cJSON_CreateObject();
jaddstr(json,"result",*retstrp);
free(*retstrp);
*retstrp = jprint(json,1);
} else free_json(json);
}
}
return(txid);
}
char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char payload[1024],*rel,*retstr = 0; cJSON *json;
if ( (rel= jstr(argjson,"rel")) == 0 )
rel = "cny";
sprintf(payload,"&mk_type=%s&order_id=%llu",rel,(long long)quoteid);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,payload,"cancelOrder.php")) != 0 )
{
free_json(json);
}
return(retstr); // return standardized cancelorder
}
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],*base,*rel,*retstr = 0; cJSON *json;
if ( (rel= jstr(argjson,"rel")) == 0 )
rel = "cny";
sprintf(payload,"&mk_type=%s",rel);
if ( (base= jstr(argjson,"base")) != 0 )
sprintf(payload + strlen(payload),"&coinname=%s",base);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,payload,"getOrderList.php")) != 0 )
{
free_json(json);
}
return(retstr); // return standardized open orders
}
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
return(clonestr("{\"error\":\"btc38 doesnt seem to have trade history api!\"}"));
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
return(clonestr("{\"error\":\"btc38 doesnt seem to have withdraw api!\"}"));
}
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char *status,*retstr;
status = OPENORDERS(exchange,argjson);
if ( (retstr= exchange_extractorderid(0,status,quoteid,"order_id")) != 0 )
{
free(status);
return(retstr);
}
free(status);
return(clonestr("{\"result\":\"order not pending\"}"));
}
struct exchange_funcs btc38_funcs = EXCHANGE_FUNCS(btc38,EXCHANGE_NAME);
#undef UPDATE
#undef SUPPORTS
#undef SIGNPOST
#undef TRADE
#undef ORDERSTATUS
#undef CANCELORDER
#undef OPENORDERS
#undef TRADEHISTORY
#undef BALANCES
#undef PARSEBALANCE
#undef WITHDRAW
#undef EXCHANGE_NAME
#undef EXCHANGE_AUTHURL
#undef CHECKBALANCE

216
iguana/exchanges/btce.c

@ -0,0 +1,216 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#define EXCHANGE_NAME "btce"
#define UPDATE btce ## _price
#define SUPPORTS btce ## _supports
#define SIGNPOST btce ## _signpost
#define TRADE btce ## _trade
#define ORDERSTATUS btce ## _orderstatus
#define CANCELORDER btce ## _cancelorder
#define OPENORDERS btce ## _openorders
#define TRADEHISTORY btce ## _tradehistory
#define BALANCES btce ## _balances
#define PARSEBALANCE btce ## _parsebalance
#define WITHDRAW btce ## _withdraw
#define EXCHANGE_AUTHURL "https://btc-e.com/tapi"
#define CHECKBALANCE btce ## _checkbalance
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,cJSON *argjson)
{
char field[64],url[1024],lbase[16],lrel[16];
strcpy(lrel,rel), strcpy(lbase,base);
tolowercase(lrel), tolowercase(lbase);
sprintf(field,"%s_%s",lbase,lrel);
sprintf(url,"https://btc-e.com/api/3/depth/%s",field);
return(exchanges777_standardprices(exchange,base,rel,url,quotes,0,0,maxdepth,field));
}
int32_t SUPPORTS(struct exchange_info *exchange,char *base,char *rel,cJSON *argjson)
{
char *baserels[][2] = { {"btc","usd"}, {"btc","rur"}, {"btc","eur"}, {"ltc","btc"}, {"ltc","usd"}, {"ltc","rur"}, {"ltc","eur"}, {"nmc","btc"}, {"nmc","usd"}, {"nvc","btc"}, {"nvc","usd"}, {"eur","usd"}, {"eur","rur"}, {"ppc","btc"}, {"ppc","usd"} };
return(baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel));
}
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *url,char *payload)
{
char dest[(512>>3)*2+1],hdr1[512],hdr2[512],hdr3[512],hdr4[512],*data,*sig; cJSON *json;
hdr1[0] = hdr2[0] = hdr3[0] = hdr4[0] = 0;
json = 0;
if ( (sig= hmac_sha512_str(dest,exchange->apisecret,(int32_t)strlen(exchange->apisecret),payload)) != 0 )
sprintf(hdr1,"Sign:%s",sig);
else hdr1[0] = 0;
sprintf(hdr2,"Key:%s",exchange->apikey);
if ( dotrade == 0 )
data = exchange_would_submit(payload,hdr1,hdr2,hdr3,hdr4);
else if ( (data= curl_post(&exchange->cHandle,url,0,payload,hdr1,hdr2,hdr3,hdr4)) != 0 )
json = cJSON_Parse(data);
if ( retstrp != 0 )
*retstrp = data;
else if ( data != 0 )
free(data);
return(json);
}
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024];
sprintf(payload,"method=getInfo&nonce=%llu",(long long)exchange_nonce(exchange));
return(SIGNPOST(&exchange->cHandle,1,0,exchange,EXCHANGE_AUTHURL,payload));
}
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
//btce.({"success":1,"return":{"funds":{"usd":73.02571846,"btc":0,"ltc":0,"nmc":0,"rur":0,"eur":0,"nvc":0.0000322,"trc":0,"ppc":0.00000002,"ftc":0,"xpm":2.28605349,"cnh":0,"gbp":0},"rights":{"info":1,"trade":1,"withdraw":0},"transaction_count":0,"open_orders":3,"server_time":1441918649}})
char field[128],*itemstr = 0; cJSON *obj,*item;
*balancep = 0.;
strcpy(field,coinstr);
tolowercase(field);
if ( argjson != 0 && (obj= jobj(argjson,"return")) != 0 && (item= jobj(obj,"funds")) != 0 )
{
*balancep = jdouble(item,field);
obj = cJSON_CreateObject();
touppercase(field);
jaddstr(obj,"base",field);
jaddnum(obj,"balance",*balancep);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
#include "checkbalance.c"
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
{
char payload[1024],pairstr[512],*extra; cJSON *json,*resultobj; uint64_t txid = 0;
if ( (extra= *retstrp) != 0 )
*retstrp = 0;
if ( (dir= flipstr_for_exchange(exchange,pairstr,"%s_%s",dir,&price,&volume,base,rel,argjson)) == 0 )
{
printf("cant find baserel (%s/%s)\n",base,rel);
return(0);
}
sprintf(payload,"method=Trade&nonce=%llu&pair=%s&type=%s&rate=%.3f&amount=%.6f",(long long)exchange_nonce(exchange),pairstr,dir>0?"buy":"sell",price,volume);
if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume,argjson) == 0 && (json= SIGNPOST(&exchange->cHandle,dotrade,retstrp,exchange,EXCHANGE_AUTHURL,payload)) != 0 )
{
//{ "success":1, "return":{ "received":0.1, "remains":0, "order_id":0, "funds":{ "usd":325, "btc":2.498, } } }
if ( juint(json,"success") > 0 && (resultobj= jobj(json,"return")) != 0 )
{
if ( (txid= j64bits(resultobj,"order_id")) == 0 )
{
if ( j64bits(resultobj,"remains") == 0 )
txid = calc_crc32(0,payload,strlen(payload));
}
}
free_json(json);
}
return(txid);
}
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char payload[1024],*retstr = 0; cJSON *json;
sprintf(payload,"method=OrderInfo&nonce=%llu&order_id=%llu",(long long)exchange_nonce(exchange),(long long)quoteid);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,EXCHANGE_AUTHURL,payload)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized orderstatus
}
char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char payload[1024],*retstr = 0; cJSON *json;
sprintf(payload,"method=CancelOrder&nonce=%llu&order_id=%llu",(long long)exchange_nonce(exchange),(long long)quoteid);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,EXCHANGE_AUTHURL,payload)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized cancelorder
}
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],market[64],*base,*rel,*retstr = 0; cJSON *json;
sprintf(payload,"method=ActiveOrders&nonce=%llu",(long long)exchange_nonce(exchange));
if ( (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 )
{
sprintf(market,"%s_%s",base,rel);
tolowercase(market);
sprintf(payload + strlen(payload),"&pair=%s",market);
}
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,EXCHANGE_AUTHURL,payload)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized open orders
}
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],market[64],*base,*rel,*retstr = 0; cJSON *json; uint32_t starttime,endtime;
sprintf(payload,"method=TradeHistory&nonce=%llu",(long long)exchange_nonce(exchange));
if ( (starttime= juint(argjson,"start")) != 0 )
sprintf(payload + strlen(payload),"&since=%u",starttime);
if ( (endtime= juint(argjson,"end")) != 0 )
sprintf(payload + strlen(payload),"&end=%u",endtime);
if ( (base= jstr(argjson,"base")) != 0 && (rel= jstr(argjson,"rel")) != 0 )
{
sprintf(market,"%s_%s",base,rel);
tolowercase(market);
sprintf(payload + strlen(payload),"&pair=%s",market);
}
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,EXCHANGE_AUTHURL,payload)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized tradehistory
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
char payload[1024],*retstr = 0; cJSON *json;
if ( base == 0 || base[0] == 0 )
return(clonestr("{\"error\":\"base not specified\"}"));
if ( destaddr == 0 || destaddr[0] == 0 )
return(clonestr("{\"error\":\"destaddr not specified\"}"));
if ( amount < SMALLVAL )
return(clonestr("{\"error\":\"amount not specified\"}"));
sprintf(payload,"method=WithdrawCoin&nonce=%llu&coinName=%s&amount=%.6f&address=%s",(long long)exchange_nonce(exchange),base,amount,destaddr);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,EXCHANGE_AUTHURL,payload)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized withdraw
}
struct exchange_funcs btce_funcs = EXCHANGE_FUNCS(btce,EXCHANGE_NAME);
#undef UPDATE
#undef SUPPORTS
#undef SIGNPOST
#undef TRADE
#undef ORDERSTATUS
#undef CANCELORDER
#undef OPENORDERS
#undef TRADEHISTORY
#undef BALANCES
#undef PARSEBALANCE
#undef WITHDRAW
#undef EXCHANGE_NAME
#undef EXCHANGE_AUTHURL
#undef CHECKBALANCE

53
iguana/exchanges/checkbalance.c

@ -0,0 +1,53 @@
/******************************************************************************
* Copyright © 2014-2015 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. *
* *
******************************************************************************/
int32_t CHECKBALANCE(char **retstrp,int32_t skipflag,struct exchange_info *exchange,int32_t dir,char *base,char *rel,double price,double volume,cJSON *argjson)
{
cJSON *json; char *coinstr,*balancestr,*resultstr,*resultval; double balance; int32_t retval = -1;
if ( skipflag == 0 )
{
coinstr = (dir > 0) ? rel : base;
if ( (balancestr= PARSEBALANCE(exchange,&balance,coinstr,argjson)) != 0 )
{
json = cJSON_Parse(balancestr);
free(balancestr);
printf("%s balance.%s %f vs %f\n",exchange->name,coinstr,balance,dir > 0 ? volume : volume * price);
if ( (dir > 0 && balance < volume) || (dir < 0 && balance < (volume * price)) )
{
resultstr = "error";
resultval = "not enough balance";
}
else
{
resultval = "balance";
resultstr = "success";
retval = 0;
}
if ( retstrp != 0 )
{
if ( json == 0 )
json = cJSON_CreateObject();
jaddstr(json,"coin",coinstr);
jaddnum(json,"balance",balance);
jaddnum(json,"required",volume * (dir < 0 ? price : 1.));
jaddstr(json,resultstr,resultval);
*retstrp = jprint(json,1);
}
else if ( json != 0 )
free_json(json);
}
} else retval = 0;
return(retval);
}

229
iguana/exchanges/coinbase.c

@ -0,0 +1,229 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#define EXCHANGE_NAME "coinbase"
#define UPDATE coinbase ## _price
#define SUPPORTS coinbase ## _supports
#define SIGNPOST coinbase ## _signpost
#define TRADE coinbase ## _trade
#define ORDERSTATUS coinbase ## _orderstatus
#define CANCELORDER coinbase ## _cancelorder
#define OPENORDERS coinbase ## _openorders
#define TRADEHISTORY coinbase ## _tradehistory
#define BALANCES coinbase ## _balances
#define PARSEBALANCE coinbase ## _parsebalance
#define WITHDRAW coinbase ## _withdraw
#define EXCHANGE_AUTHURL "https://api.exchange.coinbase.com"
#define CHECKBALANCE coinbase ## _checkbalance
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,cJSON *argjson)
{
char url[1024];
sprintf(url,"https://api.exchange.coinbase.com/products/%s-%s/book?level=2",base,rel);
return(exchanges777_standardprices(exchange,base,rel,url,quotes,0,0,maxdepth,0));
}
int32_t SUPPORTS(struct exchange_info *exchange,char *base,char *rel,cJSON *argjson)
{
char *baserels[][2] = { {"btc","usd"} };
return(baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel));
}
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *payload,uint64_t nonce,char *path,char *method)
{
/*All REST requests must contain the following headers:
CB-ACCESS-KEY The api key as a string.
CB-ACCESS-SIGN The base64-encoded signature (see Signing a Message).
CB-ACCESS-TIMESTAMP A timestamp for your request.
CB-ACCESS-PASSPHRASE The passphrase you specified when creating the API key.
All request bodies should have content type application/json and be valid JSON.
Signing a Message
The CB-ACCESS-SIGN header is generated by creating a sha256 HMAC using the base64-decoded
secret key on the prehash string timestamp + method + requestPath + body (where + represents string concatenation)
and base64-encode the output. The timestamp value is the same as the CB-ACCESS-TIMESTAMP header.
The body is the request body string or omitted if there is no request body (typically for GET requests).
The method should be UPPER CASE
Remember to first base64-decode the alphanumeric secret string (resulting in 64 bytes) before using it as the key for HMAC. Also, base64-encode the digest output before sending in the header.
*/
/* def __call__(self, request):
timestamp = str(time.time())
message = timestamp + request.method + request.path_url + (request.body or '')
hmac_key = base64.b64decode(self.secret_key)
signature = hmac.new(hmac_key, message, hashlib.sha256)
signature_b64 = signature.digest().encode('base64').rstrip('\n')
request.headers.update({
'CB-ACCESS-SIGN': signature_b64,
'CB-ACCESS-TIMESTAMP': timestamp,
'CB-ACCESS-KEY': self.api_key,
'CB-ACCESS-PASSPHRASE': self.passphrase,
'Content-Type': 'application/json'
})*/
char url[1024],hdr1[512],hdr2[512],hdr3[512],hdr4[512],dest[1024]; cJSON *json; int32_t n;
char prehash64[512],prehash[512],decodedsecret[512],sig64[512],*sig,*data = 0;
hdr1[0] = hdr2[0] = hdr3[0] = hdr4[0] = 0;
json = 0;
n = nn_base64_decode((void *)exchange->apisecret,strlen(exchange->apisecret),(void *)decodedsecret,sizeof(decodedsecret));
sprintf(prehash,"%llu%s/%s%s",(long long)nonce,method,path,payload);
nn_base64_encode((void *)prehash,strlen(prehash),prehash64,sizeof(prehash64));
if ( (sig= hmac_sha256_str(dest,decodedsecret,n,prehash64)) != 0 )
{
nn_base64_encode((void *)sig,strlen(sig),sig64,sizeof(sig64));
//CB-ACCESS-KEY The api key as a string.
//CB-ACCESS-SIGN The base64-encoded signature (see Signing a Message).
//CB-ACCESS-TIMESTAMP A timestamp for your request.
//CB-ACCESS-PASSPHRASE The passphrase you specified when creating the API key.
sprintf(hdr1,"CB-ACCESS-KEY:%s",exchange->apikey);
sprintf(hdr2,"CB-ACCESS-SIGN:%s",sig64);
sprintf(hdr3,"CB-ACCESS-TIMESTAMP:%llu",(long long)nonce);
//sprintf(hdr4,"CB-ACCESS-PASSPHRASE:%s; content-type:application/json; charset=utf-8",exchange->userid);
sprintf(hdr4,"CB-ACCESS-PASSPHRASE:%s",exchange->userid);
sprintf(url,"%s/%s",EXCHANGE_AUTHURL,path);
if ( dotrade == 0 )
data = exchange_would_submit(payload,hdr1,hdr2,hdr3,hdr4);
else if ( (data= curl_post(&exchange->cHandle,url,0,payload,hdr1,hdr2,hdr3,hdr4)) != 0 )
json = cJSON_Parse(data);
}
if ( retstrp != 0 )
*retstrp = data;
else if ( data != 0 )
free(data);
return(json);
}
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
return(SIGNPOST(&exchange->cHandle,1,0,exchange,"",exchange_nonce(exchange),"accounts","GET"));
}
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
char field[128],*itemstr = 0; cJSON *obj,*item;
*balancep = 0.;
strcpy(field,coinstr);
tolowercase(field);
if ( argjson != 0 && (obj= jobj(argjson,"return")) != 0 && (item= jobj(obj,"funds")) != 0 )
{
*balancep = jdouble(item,field);
obj = cJSON_CreateObject();
touppercase(field);
jaddstr(obj,"base",field);
jaddnum(obj,"balance",*balancep);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
#include "checkbalance.c"
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
{
char payload[1024],pairstr[512],method[32],*path,*extra;
cJSON *json; uint64_t nonce,txid = 0;
if ( (extra= *retstrp) != 0 )
*retstrp = 0;
path = "trade", strcpy(method,"POST");
if ( (dir= flip_for_exchange(pairstr,"%s_%s","BTC",dir,&price,&volume,base,rel)) == 0 )
{
printf("cant find baserel (%s/%s)\n",base,rel);
return(0);
}
nonce = exchange_nonce(exchange);
sprintf(payload,"method=Trade&nonce=%llu&pair=%s&type=%s&rate=%.6f&amount=%.6f",(long long)nonce,pairstr,dir>0?"buy":"sell",price,volume);
if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume,argjson) == 0 && (json= SIGNPOST(&exchange->cHandle,dotrade,retstrp,exchange,payload,nonce,path,method)) != 0 )
{
// parse json and set txid
free_json(json);
}
return(txid);
}
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char payload[1024],*retstr = 0; cJSON *json;
// generate payload
if ( (json= SIGNPOST(&exchange->cHandle,1,0,exchange,payload,exchange_nonce(exchange),"accounts","GET")) != 0 )
{
free_json(json);
}
return(retstr); // return standardized orderstatus
}
char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char payload[1024],*retstr = 0; cJSON *json;
// generate payload
if ( (json= SIGNPOST(&exchange->cHandle,1,0,exchange,payload,exchange_nonce(exchange),"accounts","GET")) != 0 )
{
free_json(json);
}
return(retstr); // return standardized cancelorder
}
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],*retstr = 0; cJSON *json;
// generate payload
if ( (json= SIGNPOST(&exchange->cHandle,1,0,exchange,payload,exchange_nonce(exchange),"accounts","GET")) != 0 )
{
free_json(json);
}
return(retstr); // return standardized open orders
}
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],*retstr = 0; cJSON *json;
// generate payload
if ( (json= SIGNPOST(&exchange->cHandle,1,0,exchange,payload,exchange_nonce(exchange),"accounts","GET")) != 0 )
{
free_json(json);
}
return(retstr); // return standardized tradehistory
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
char payload[1024],*retstr = 0; cJSON *json;
// generate payload
if ( (json= SIGNPOST(&exchange->cHandle,1,0,exchange,payload,exchange_nonce(exchange),"accounts","GET")) != 0 )
{
free_json(json);
}
return(retstr); // return standardized withdraw
}
struct exchange_funcs coinbase_funcs = EXCHANGE_FUNCS(coinbase,EXCHANGE_NAME);
#undef UPDATE
#undef SUPPORTS
#undef SIGNPOST
#undef TRADE
#undef ORDERSTATUS
#undef CANCELORDER
#undef OPENORDERS
#undef TRADEHISTORY
#undef BALANCES
#undef PARSEBALANCE
#undef WITHDRAW
#undef EXCHANGE_NAME
#undef EXCHANGE_AUTHURL
#undef CHECKBALANCE

184
iguana/exchanges/huobi.c

@ -0,0 +1,184 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#define EXCHANGE_NAME "huobi"
#define UPDATE huobi ## _price
#define SUPPORTS huobi ## _supports
#define SIGNPOST huobi ## _signpost
#define TRADE huobi ## _trade
#define ORDERSTATUS huobi ## _orderstatus
#define CANCELORDER huobi ## _cancelorder
#define OPENORDERS huobi ## _openorders
#define TRADEHISTORY huobi ## _tradehistory
#define BALANCES huobi ## _balances
#define PARSEBALANCE huobi ## _parsebalance
#define WITHDRAW huobi ## _withdraw
#define CHECKBALANCE huobi ## _checkbalance
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,cJSON *argjson)
{
char url[1024],lbase[16];
strcpy(lbase,base), tolowercase(lbase);
sprintf(url,"http://api.huobi.com/staticmarket/depth_%s_json.js ",lbase);
return(exchanges777_standardprices(exchange,base,rel,url,quotes,0,0,maxdepth,0));
}
int32_t SUPPORTS(struct exchange_info *exchange,char *base,char *rel,cJSON *argjson)
{
char *baserels[][2] = { {"btc","cny"}, {"ltc","cny"} };
return(baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel));
}
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *payload)
{
char *data; cJSON *json;
json = 0;
//if ( (data= curl_post(&cHandle,"https://api.huobi.com/apiv3",0,payload,"Content-Type:application/x-www-form-urlencoded",0,0,0)) != 0 )
if ( dotrade == 0 )
data = exchange_would_submit(payload,"","","","");
else if ( (data= curl_post(&exchange->cHandle,"https://api.huobi.com/apiv3",0,payload,"",0,0,0)) != 0 )
json = cJSON_Parse(data);
if ( retstrp != 0 )
*retstrp = data;
else if ( data != 0 )
free(data);
return(json);
}
cJSON *huobi_issue_auth(void **cHandlep,struct exchange_info *exchange,char *method,char *buf)
{
char payload[1024],digest[33],tmp[1024]; uint64_t nonce;
nonce = exchange_nonce(exchange);
sprintf(tmp,"access_key=%s&created=%llu&method=%s%s",exchange->apikey,(long long)nonce,method,buf);
sprintf(payload,"%s&secret_key=%s",tmp,exchange->apisecret);
//printf("tmp.(%s) payload.(%s)\n",tmp,payload);
calc_md5(digest,payload,(int32_t)strlen(payload));
sprintf(payload,"%s&sign=%s",tmp,digest);
//printf("-> (%s)\n",payload);
return(SIGNPOST(&exchange->cHandle,1,0,exchange,payload));
}
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
char field[128],*itemstr = 0; cJSON *obj,*item;
*balancep = 0.;
strcpy(field,coinstr);
tolowercase(field);
if ( argjson != 0 && (obj= jobj(argjson,"return")) != 0 && (item= jobj(obj,"funds")) != 0 )
{
*balancep = jdouble(item,field);
obj = cJSON_CreateObject();
touppercase(field);
jaddstr(obj,"base",field);
jaddnum(obj,"balance",*balancep);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
return(huobi_issue_auth(&exchange->cHandle,exchange,"get_account_info",""));
}
#include "checkbalance.c"
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
{
char payload[1024],pairstr[64],pricestr[64],*extra,*method; cJSON *json; int32_t type; uint64_t txid = 0;
if ( (extra= *retstrp) != 0 )
*retstrp = 0;
if ( (dir= flipstr_for_exchange(exchange,pairstr,"%s%s",dir,&price,&volume,base,rel,argjson)) == 0 )
{
printf("cant find baserel (%s/%s)\n",base,rel);
return(0);
}
if ( extra != 0 && strcmp(extra,"market") == 0 )
method = (dir > 0) ? "buy_market" : "sell_market";
else method = (dir > 0) ? "buy" : "sell", sprintf(pricestr,"&price=%.2f",price);
if ( strcmp(pairstr,"btccny") == 0 )
type = 1;
else if ( strcmp(pairstr,"ltccny") == 0 )
type = 2;
else
{
printf("cant find baserel (%s/%s)\n",base,rel);
return(0);
}
sprintf(payload,"&amount=%.4f&coin_type=%d%s",volume,type,pricestr);
if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume,argjson) == 0 && (json= huobi_issue_auth(&exchange->cHandle,exchange,method,payload)) != 0 )
{
txid = j64bits(json,"order_id");
free_json(json);
}
return(txid);
}
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char payload[1024];
sprintf(payload,"&id=%llu&coin_type=1",(long long)quoteid);
return(jprint(huobi_issue_auth(&exchange->cHandle,exchange,"order_info",payload),1));
}
char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char payload[1024];
sprintf(payload,"&id=%llu&coin_type=1",(long long)quoteid);
return(jprint(huobi_issue_auth(&exchange->cHandle,exchange,"cancel_order",payload),1));
}
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
return(jprint(huobi_issue_auth(&exchange->cHandle,exchange,"get_orders","&coin_type=1"),1));
}
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
return(clonestr("{\"error\":\"huobi doesnt seem to have trade history api!\"}"));
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
char payload[1024],*method;
if ( base == 0 || base[0] == 0 )
return(clonestr("{\"error\":\"base not specified\"}"));
if ( destaddr == 0 || destaddr[0] == 0 )
return(clonestr("{\"error\":\"destaddr not specified\"}"));
if ( amount < SMALLVAL )
return(clonestr("{\"error\":\"amount not specified\"}"));
method = "withdraw_coin";
sprintf(payload,"&coin_type=1&withdraw_address=%s&withdraw_amount=%.4f",destaddr,amount);
return(jprint(huobi_issue_auth(&exchange->cHandle,exchange,method,payload),1));
}
struct exchange_funcs huobi_funcs = EXCHANGE_FUNCS(huobi,EXCHANGE_NAME);
#undef UPDATE
#undef SUPPORTS
#undef SIGNPOST
#undef TRADE
#undef ORDERSTATUS
#undef CANCELORDER
#undef OPENORDERS
#undef TRADEHISTORY
#undef BALANCES
#undef PARSEBALANCE
#undef WITHDRAW
#undef EXCHANGE_NAME
#undef CHECKBALANCE

283
iguana/exchanges/lakebtc.c

@ -0,0 +1,283 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#define EXCHANGE_NAME "lakebtc"
#define UPDATE lakebtc ## _price
#define SUPPORTS lakebtc ## _supports
#define SIGNPOST lakebtc ## _signpost
#define TRADE lakebtc ## _trade
#define ORDERSTATUS lakebtc ## _orderstatus
#define CANCELORDER lakebtc ## _cancelorder
#define OPENORDERS lakebtc ## _openorders
#define TRADEHISTORY lakebtc ## _tradehistory
#define BALANCES lakebtc ## _balances
#define PARSEBALANCE lakebtc ## _parsebalance
#define WITHDRAW lakebtc ## _withdraw
#define CHECKBALANCE lakebtc ## _checkbalance
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,cJSON *argjson)
{
char url[1024];
if ( strcmp(rel,"USD") == 0 )
sprintf(url,"https://www.LakeBTC.com/api_v1/bcorderbook");
else if ( strcmp(rel,"CNY") == 0 )
sprintf(url,"https://www.LakeBTC.com/api_v1/bcorderbook_cny");
else printf("illegal lakebtc pair.(%s/%s)\n",base,rel);
return(exchanges777_standardprices(exchange,base,rel,url,quotes,0,0,maxdepth,0));
}
int32_t SUPPORTS(struct exchange_info *exchange,char *base,char *rel,cJSON *argjson)
{
char *baserels[][2] = { {"btc","usd"}, {"btc","cny"} };
int32_t polarity;
polarity = baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel);
printf("lakebtc.(%s %s) polarity.%d\n",base,rel,polarity);
return(polarity);
}
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *payload,char *hdr1,uint64_t tonce)
{
char hdr2[512],cmdbuf[1024],buf64[1024],hdr3[512],dest[1025],hdr4[512],*sig,*data = 0; cJSON *json;
hdr2[0] = hdr3[0] = hdr4[0] = 0;
json = 0;
if ( (sig= hmac_sha1_str(dest,exchange->apisecret,(int32_t)strlen(exchange->apisecret),hdr1)) != 0 )
{
sprintf(cmdbuf,"%s:%s",exchange->userid,sig);
nn_base64_encode((void *)cmdbuf,strlen(cmdbuf),buf64,sizeof(buf64));
sprintf(hdr1,"Authorization:Basic %s",buf64);
sprintf(hdr2,"Json-Rpc-Tonce: %llu",(long long)tonce);
if ( dotrade == 0 )
data = exchange_would_submit(payload,hdr1,hdr2,hdr3,hdr4);
else if ( (data= curl_post(&exchange->cHandle,"https://www.LakeBTC.com/api_v1",0,payload,hdr1,hdr2,hdr3,hdr4)) != 0 )
json = cJSON_Parse(data);
}
if ( retstrp != 0 )
*retstrp = data;
else if ( data != 0 )
free(data);
return(json);
}
/* LakeBTC provides trading JSON-RPC API interface. HMAC (Hash-based Message Authentication Code) is employed as our authentication mechanisms. You need at 0.1 BTC in your account to retrieve your private key.
Besides your private key, the client needs to prepare the following attributes
tonce (timestamp in microseconds, i.e., unixtime × 1000000, make sure your clock is correctly adjusted)
accesskey (your registered email address at LakeBTC)
requestmethod (post)
id (JSON-RPC request id, an integer)
method (JSON-RPC method)
params (JSON-RPC parameters)
Concatenate the above parameters with &, in that order. Parameters can be blank. For example, $signature =
tonce=1389067414466757&accesskey=foo@bar.com&requestmethod=post&id=123&method=ticker&params=
Create HMAC signature with your private key by using SHA1. $hash =
hash_hmac('sha1', $signature, $privatetkey) #php
Join your email and the hash signature with colon (:), and sign with Base64. $b64 =
base64_encode("foo@bar.com:<hash>") #php YXRjQHF3amlhbi5jb206ZmEzM2UzYzg5MDZjg5MzdiYzFiYw==
Set HTTP Header. Note tonce is the same as that in Step 2.
Json-Rpc-Tonce: 1389067414466757 #HTTP HEADER
Authorization: Basic YXRjQHF3amlhbi5jb206ZmEzM2UzYzg5MDZjg5MzdiYzFiYw== #HTTP HEADER
POST params data in JSON format to this url:
https://www.LakeBTC.com/api_v1
API Methods
getAccountInfo
method=getAccountInfo
params= (i.e., blank)
static CURL *cHandle;
char *data,*method,buf64[4096],paramstr[128],jsonbuf[1024],base[64],rel[64],pairstr[64],params[1024],dest[512],url[1024],cmdbuf[8192],*sig,hdr1[4096],hdr2[4096],buf[4096]; cJSON *json; uint64_t tonce,nonce,txid = 0;
*retstrp = 0;
params[0] = 0;
nonce = exchange_nonce(exchange);
tonce = (nonce * 1000000 + ((uint64_t)milliseconds() % 1000) * 1000);
if ( dir == 0 )
{
method = "getAccountInfo";
sprintf(buf,"tonce=%llu&accesskey=%s&requestmethod=post&id=1&method=%s&params=",(long long)tonce,exchange->userid,method);
sprintf(jsonbuf,"{\"method\":\"%s\",\"params\":[\"%s\"],\"id\":1}",method,params);
}
else
{
if ( (dir= flipstr_for_exchange(exchange,pairstr,"%s_%s",dir,&price,&volume,base,rel)) == 0 )
{
printf("cant find baserel (%s/%s)\n",base,rel);
return(0);
}
method = (dir > 0) ? "buyOrder" : "sellOrder";
touppercase(rel);
sprintf(paramstr,"%.2f,%.4f,%s",price,volume,rel);
sprintf(buf,"tonce=%llu&accesskey=%s&requestmethod=post&id=1&method=%s&params=%s",(long long)tonce,exchange->userid,method,paramstr);
sprintf(jsonbuf,"{\"method\":\"%s\",\"params\":[\"%s\"],\"id\":1}",method,paramstr);
}
if ( (sig= hmac_sha1_str(dest,exchange->apisecret,(int32_t)strlen(exchange->apisecret),buf)) != 0 )
{
sprintf(cmdbuf,"%s:%s",exchange->userid,sig);
nn_base64_encode((void *)cmdbuf,strlen(cmdbuf),buf64,sizeof(buf64));
sprintf(url,"https://www.lakebtc.com/api_v1");
sprintf(hdr1,"Authorization:Basic %s",buf64);
sprintf(hdr2,"Json-Rpc-Tonce: %llu",(long long)tonce);
if ( (data= curl_post(&cHandle,url,0,jsonbuf,hdr1,hdr2,0,0)) != 0 )
{
//printf("submit cmd.(%s) [%s]\n",jsonbuf,data);
if ( (json= cJSON_Parse(data)) != 0 )
{
txid = j64bits(json,"order_id");
free_json(json);
}
} else fprintf(stderr,"submit err cmd.(%s)\n",cmdbuf);
if ( retstrp != 0 )
*retstrp = data;
else if ( data != 0 )
free(data);
}
*/
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
//lakebtc.({"balance":{"BTC":0.1},"locked":{"BTC":0.0},"profile":{"email":"jameslee777@yahoo.com","id":"U137561934","btc_deposit_addres":"1RyKrNJjezeFfvYaicnJEozHfhWfYzbuh"}})
char field[128],*str,*itemstr = 0; cJSON *obj=0,*item=0,*prof=0; double locked = 0;
*balancep = 0.;
strcpy(field,coinstr);
touppercase(field);
if ( argjson != 0 && (obj= jobj(argjson,"balance")) != 0 && (item= jobj(argjson,"locked")) != 0 && (prof= jobj(argjson,"profile")) != 0 )
{
*balancep = jdouble(obj,field);
locked = jdouble(item,field);
obj = cJSON_CreateObject();
jaddstr(obj,"base",field);
jaddnum(obj,"balance",*balancep);
jaddnum(obj,"locked",locked);
if ( (str= jstr(prof,"btc_deposit_addres")) != 0 )
jaddstr(obj,"deposit_address",str);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],jsonbuf[1024],*method; uint64_t tonce;
method = "getAccountInfo";
tonce = (exchange_nonce(exchange) * 1000000 + ((uint64_t)OS_milliseconds() % 1000) * 1000);
sprintf(payload,"tonce=%llu&accesskey=%s&requestmethod=post&id=1&method=%s&params=",(long long)tonce,exchange->userid,method);
sprintf(jsonbuf,"{\"method\":\"%s\",\"params\":[\"%s\"],\"id\":1}",method,"");
return(SIGNPOST(&exchange->cHandle,1,0,exchange,jsonbuf,payload,tonce));
}
#include "checkbalance.c"
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
{
char payload[1024],jsonbuf[1024],pairstr[64],paramstr[512],*extra,*method;
cJSON *json; uint64_t tonce,txid = 0;
if ( (extra= *retstrp) != 0 )
*retstrp = 0;
tonce = (exchange_nonce(exchange) * 1000000 + ((uint64_t)OS_milliseconds() % 1000) * 1000);
if ( (dir= flipstr_for_exchange(exchange,pairstr,"%s_%s",dir,&price,&volume,base,rel,argjson)) == 0 )
{
printf("cant find baserel (%s/%s)\n",base,rel);
return(0);
}
method = (dir > 0) ? "buyOrder" : "sellOrder";
touppercase(rel);
sprintf(paramstr,"%.2f,%.4f,%s",price,volume,rel);
sprintf(payload,"tonce=%llu&accesskey=%s&requestmethod=post&id=1&method=%s&params=%s",(long long)tonce,exchange->userid,method,paramstr);
sprintf(jsonbuf,"{\"method\":\"%s\",\"params\":[\"%s\"],\"id\":1}",method,paramstr);
if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume,argjson) == 0 && (json= SIGNPOST(&exchange->cHandle,dotrade,retstrp,exchange,jsonbuf,payload,tonce)) != 0 )
{
txid = j64bits(json,"order_id");
free_json(json);
}
return(txid);
}
char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char payload[1024],jsonbuf[1024],*method,*retstr = 0; cJSON *json; uint64_t tonce;
method = "cancelOrder";
tonce = (exchange_nonce(exchange) * 1000000 + ((uint64_t)OS_milliseconds() % 1000) * 1000);
sprintf(jsonbuf,"{\"method\":\"%s\",\"params\":[\"%llu\"],\"id\":1}",method,(long long)quoteid);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,payload,jsonbuf,tonce)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized cancelorder
}
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],jsonbuf[1024],*method,*retstr = 0; cJSON *json; uint64_t tonce;
method = "getOrders";
tonce = (exchange_nonce(exchange) * 1000000 + ((uint64_t)OS_milliseconds() % 1000) * 1000);
sprintf(jsonbuf,"{\"method\":\"%s\",\"params\":[\"%s\"],\"id\":1}",method,"");
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,payload,jsonbuf,tonce)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized open orders
}
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],jsonbuf[1024],timestr[64],*method,*retstr = 0;
cJSON *json; uint64_t tonce; uint32_t starttime;
method = "getTrades";
if ( (starttime= juint(argjson,"start")) != 0 )
sprintf(timestr,"%u",starttime);
else timestr[0] = 0;
tonce = (exchange_nonce(exchange) * 1000000 + ((uint64_t)OS_milliseconds() % 1000) * 1000);
sprintf(jsonbuf,"{\"method\":\"%s\",\"params\":[%s],\"id\":1}",method,timestr);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,payload,jsonbuf,tonce)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized tradehistory
}
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char *status,*retstr;
status = OPENORDERS(exchange,argjson);
if ( (retstr= exchange_extractorderid(0,status,quoteid,"id")) != 0 )
{
free(status);
return(retstr);
}
free(status);
return(clonestr("{\"error\":\"cant find quoteid\"}"));
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
return(clonestr("{\"error\":\"lakebtc doesnt seem to have withdraw api!\"}"));
}
struct exchange_funcs lakebtc_funcs = EXCHANGE_FUNCS(lakebtc,EXCHANGE_NAME);
#undef UPDATE
#undef SUPPORTS
#undef SIGNPOST
#undef TRADE
#undef ORDERSTATUS
#undef CANCELORDER
#undef OPENORDERS
#undef TRADEHISTORY
#undef BALANCES
#undef PARSEBALANCE
#undef WITHDRAW
#undef EXCHANGE_NAME
#undef CHECKBALANCE

243
iguana/exchanges/okcoin.c

@ -0,0 +1,243 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#define EXCHANGE_NAME "okcoin"
#define UPDATE okcoin ## _price
#define SUPPORTS okcoin ## _supports
#define SIGNPOST okcoin ## _signpost
#define TRADE okcoin ## _trade
#define ORDERSTATUS okcoin ## _orderstatus
#define CANCELORDER okcoin ## _cancelorder
#define OPENORDERS okcoin ## _openorders
#define TRADEHISTORY okcoin ## _tradehistory
#define BALANCES okcoin ## _balances
#define PARSEBALANCE okcoin ## _parsebalance
#define WITHDRAW okcoin ## _withdraw
#define EXCHANGE_AUTHURL "https://www.okcoin.com/api/v1"
#define CHECKBALANCE okcoin ## _checkbalance
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,cJSON *argjson)
{
char url[1024],lrel[16],lbase[16];
strcpy(lrel,rel), strcpy(lbase,base);
tolowercase(lrel), tolowercase(lbase);
sprintf(url,"https://www.okcoin.com/api/v1/depth.do?symbol=%s_%s",lbase,lrel);
if ( strcmp(rel,"USD") != 0 && strcmp(rel,"BTC") != 0 )
{
fprintf(stderr,">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FATAL ERROR OKCOIN.(%s) only supports USD\n",url);
printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FATAL ERROR OKCOIN.(%s) only supports USD\n",url);
exit(-1);
return(0);
}
return(exchanges777_standardprices(exchange,base,rel,url,quotes,0,0,maxdepth,0));
}
int32_t SUPPORTS(struct exchange_info *exchange,char *base,char *rel,cJSON *argjson)
{
char *baserels[][2] = { {"btc","usd"}, {"ltc","usd"} };
return(baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel));
}
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *url,char *payload)
{
char hdr1[512],hdr2[512],hdr3[512],hdr4[512],*data; cJSON *json;
hdr1[0] = hdr2[0] = hdr3[0] = hdr4[0] = 0;
json = 0;
if ( dotrade == 0 )
data = exchange_would_submit(payload,hdr1,hdr2,hdr3,hdr4);
else if ( (data= curl_post(&exchange->cHandle,url,0,payload,hdr1,hdr2,hdr3,hdr4)) != 0 )
json = cJSON_Parse(data);
if ( retstrp != 0 )
*retstrp = data;
else if ( data != 0 )
free(data);
return(json);
}
/*
static CURL *cHandle;
char *data,*path,*typestr,*extra,pricestr[64],base[64],rel[64],pairstr[64],url[1024],cmdbuf[8192],buf[512],digest[33]; cJSON *json; uint64_t nonce,txid = 0;
nonce = exchange_nonce(exchange);
if ( (extra= *retstrp) != 0 )
*retstrp = 0;
if ( dir == 0 )
{
path = "userinfo.do";
sprintf(buf,"api_key=%s&secret_key=%s",exchange->apikey,exchange->apisecret);
calc_md5(digest,buf,(int32_t)strlen(buf));
touppercase(digest);
sprintf(cmdbuf,"api_key=%s&sign=%s",exchange->apikey,digest);
}
else
{
path = "trade.do";
if ( (dir= flipstr_for_exchange(exchange,pairstr,"%s_%s",dir,&price,&volume,base,rel)) == 0 )
{
printf("cant find baserel (%s/%s)\n",base,rel);
return(0);
}
if ( extra != 0 && strcmp(extra,"market") == 0 )
typestr = (dir > 0) ? "buy_market" : "sell_market", sprintf(pricestr,"&price=%.2f",price); // docs say market orders put volume in price
else typestr = (dir > 0) ? "buy" : "sell", sprintf(pricestr,"&price=%.2f",price);
sprintf(buf,"amount=%.4f&api_key=%s%ssymbol=%s&type=%s&secret_key=%s",volume,exchange->apikey,pricestr,pairstr,typestr,exchange->apisecret);
calc_md5(digest,buf,(int32_t)strlen(buf));
touppercase(digest);
sprintf(cmdbuf,"amount=%.4f&api_key=%s%s&symbol=%s&type=%s&sign=%s",volume,exchange->apikey,pricestr,pairstr,typestr,digest);
}
//printf("MD5.(%s)\n",buf);
sprintf(url,"https://www.okcoin.com/api/v1/%s",path);
if ( (data= curl_post(&cHandle,url,0,cmdbuf,0,0,0,0)) != 0 ) // "{\"Content-type\":\"application/x-www-form-urlencoded\"}","{\"User-Agent\":\"OKCoin Javascript API Client\"}"
{
//printf("submit cmd.(%s) [%s]\n",cmdbuf,data);
if ( (json= cJSON_Parse(data)) != 0 )
{
txid = j64bits(json,"order_id");
free_json(json);
}
} else fprintf(stderr,"submit err cmd.(%s)\n",cmdbuf);
*/
cJSON *okcoin_issue_auth(void **cHandlep,struct exchange_info *exchange,char *method,char *buf)
{
char payload[1024],tmp[1024],digest[512],url[512];
sprintf(tmp,"api_key=%s%s",exchange->apikey,buf);
sprintf(payload,"%s&secret_key=%s",tmp,exchange->apisecret);
//printf("tmp.(%s) payload.(%s)\n",tmp,payload);
calc_md5(digest,payload,(int32_t)strlen(payload));
touppercase(digest);
sprintf(payload,"%s&sign=%s",tmp,digest);
sprintf(url,"%s/%s",EXCHANGE_AUTHURL,method);
return(SIGNPOST(&exchange->cHandle,1,0,exchange,url,payload));
}
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
//okcoin.({"info":{"funds":{"asset":{"net":"0","total":"0"},"free":{"btc":"0","ltc":"0","usd":"0"},"freezed":{"btc":"0","ltc":"0","usd":"0"}}},"result":true})
char field[128],*itemstr = 0; cJSON *obj,*item,*avail,*locked; double lockval = 0;
*balancep = 0.;
strcpy(field,coinstr);
tolowercase(field);
if ( argjson != 0 && (obj= jobj(argjson,"info")) != 0 && (item= jobj(obj,"funds")) != 0 )
{
if ( (avail= jobj(item,"free")) != 0 )
*balancep = jdouble(avail,field);
if ( (locked= jobj(item,"freezed")) != 0 )
lockval = jdouble(locked,field);
obj = cJSON_CreateObject();
touppercase(field);
jaddstr(obj,"base",field);
jaddnum(obj,"balance",*balancep);
jaddnum(obj,"locked",lockval);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
return(okcoin_issue_auth(&exchange->cHandle,exchange,"userinfo.do",""));
}
#include "checkbalance.c"
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
{
char payload[1024],buf[1024],url[1024],digest[512],pairstr[512],pricestr[64],*extra,*typestr;
cJSON *json; uint64_t txid = 0;
if ( (extra= *retstrp) != 0 )
*retstrp = 0;
if ( (dir= flipstr_for_exchange(exchange,pairstr,"%s_%s",dir,&price,&volume,base,rel,argjson)) == 0 )
{
printf("cant find baserel (%s/%s)\n",base,rel);
return(0);
}
if ( extra != 0 && strcmp(extra,"market") == 0 )
typestr = (dir > 0) ? "buy_market" : "sell_market", sprintf(pricestr,"&price=%.2f",price); // docs say market orders put volume in price
else typestr = (dir > 0) ? "buy" : "sell";
sprintf(pricestr,"&price=%.2f",price);
sprintf(buf,"amount=%.4f&api_key=%s%ssymbol=%s&type=%s&secret_key=%s",volume,exchange->apikey,pricestr,pairstr,typestr,exchange->apisecret);
calc_md5(digest,buf,(int32_t)strlen(buf));
touppercase(digest);
sprintf(payload,"amount=%.4f&api_key=%s%s&symbol=%s&type=%s&sign=%s",volume,exchange->apikey,pricestr,pairstr,typestr,digest);
sprintf(url,"%s/%s",EXCHANGE_AUTHURL,"trade.do");
if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume,argjson) == 0 && (json= SIGNPOST(&exchange->cHandle,dotrade,retstrp,exchange,url,payload)) != 0 )
{
txid = j64bits(json,"order_id");
free_json(json);
}
return(txid);
}
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char buf[64];
sprintf(buf,"&symbol=btc_usd&order_id=%llu",(long long)quoteid);
return(jprint(okcoin_issue_auth(&exchange->cHandle,exchange,"order_info.do",buf),1));
}
char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char buf[64];
sprintf(buf,"&symbol=btc_usd&order_id=%llu",(long long)quoteid);
return(jprint(okcoin_issue_auth(&exchange->cHandle,exchange,"cancel_order.do",buf),1));
}
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
return(jprint(okcoin_issue_auth(&exchange->cHandle,exchange,"orders_info.do",""),1));
}
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
return(jprint(okcoin_issue_auth(&exchange->cHandle,exchange,"orders_history.do","&status=1&symbol=btc_usd&current_page=0&page_length=200"),1));
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
char payload[1024],*method,*tradepassword;
if ( base == 0 || base[0] == 0 )
return(clonestr("{\"error\":\"base not specified\"}"));
if ( destaddr == 0 || destaddr[0] == 0 )
return(clonestr("{\"error\":\"destaddr not specified\"}"));
if ( amount < SMALLVAL )
return(clonestr("{\"error\":\"amount not specified\"}"));
if ( (tradepassword= jstr(argjson,"tradepassword")) == 0 )
tradepassword = exchange->tradepassword;
if ( tradepassword == 0 || tradepassword[0] == 0 )
return(clonestr("{\"error\":\"tradepassword not specified\"}"));
method = "withdraw_coin";
sprintf(payload,"&symbol=btc_usd&chargefee=0.0001&withdraw_address=%s&withdraw_amount=%.4f&trade_pwd=%s",destaddr,amount,tradepassword);
return(jprint(okcoin_issue_auth(&exchange->cHandle,exchange,method,payload),1));
}
struct exchange_funcs okcoin_funcs = EXCHANGE_FUNCS(okcoin,EXCHANGE_NAME);
#undef UPDATE
#undef SUPPORTS
#undef SIGNPOST
#undef TRADE
#undef ORDERSTATUS
#undef CANCELORDER
#undef OPENORDERS
#undef TRADEHISTORY
#undef BALANCES
#undef PARSEBALANCE
#undef WITHDRAW
#undef EXCHANGE_NAME
#undef EXCHANGE_AUTHURL
#undef CHECKBALANCE

230
iguana/exchanges/poloniex.c

@ -0,0 +1,230 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#define EXCHANGE_NAME "poloniex"
#define UPDATE poloniex ## _price
#define SUPPORTS poloniex ## _supports
#define SIGNPOST poloniex ## _signpost
#define TRADE poloniex ## _trade
#define ORDERSTATUS poloniex ## _orderstatus
#define CANCELORDER poloniex ## _cancelorder
#define OPENORDERS poloniex ## _openorders
#define TRADEHISTORY poloniex ## _tradehistory
#define BALANCES poloniex ## _balances
#define PARSEBALANCE poloniex ## _parsebalance
#define WITHDRAW poloniex ## _withdraw
#define EXCHANGE_AUTHURL "https://poloniex.com/tradingApi"
#define CHECKBALANCE poloniex ## _checkbalance
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,cJSON *argjson)
{
char market[128],url[1024];
sprintf(market,"%s_%s",rel,base);
sprintf(url,"https://poloniex.com/public?command=returnOrderBook&currencyPair=%s&depth=%d",market,maxdepth);
return(exchanges777_standardprices(exchange,base,rel,url,quotes,0,0,maxdepth,0));
}
int32_t SUPPORTS(struct exchange_info *exchange,char *base,char *rel,cJSON *argjson)
{
//char *baserels[][2] = { {"btc","usd"} };
//return(baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel));
if ( strlen(base) > 5 || strlen(rel) > 5 || strcmp(rel,"CNY") == 0 || strcmp(base,"CNY") == 0 || strcmp(rel,"USD") == 0 || strcmp(base,"USD") == 0 )
return(0);
if ( strcmp(rel,"BTC") == 0 )
return(1);
else if ( strcmp(base,"BTC") == 0 )
return(-1);
else return(0);
}
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *url,char *payload)
{
char dest[(512>>3)*2+1],hdr1[512],hdr2[512],hdr3[512],hdr4[512],*data,*sig; cJSON *json;
hdr1[0] = hdr2[0] = hdr3[0] = hdr4[0] = 0;
json = 0;
if ( (sig= hmac_sha512_str(dest,exchange->apisecret,(int32_t)strlen(exchange->apisecret),payload)) != 0 )
sprintf(hdr1,"Sign:%s",sig);
else hdr1[0] = 0;
sprintf(hdr2,"Key:%s",exchange->apikey);
if ( dotrade == 0 )
data = exchange_would_submit(payload,hdr1,hdr2,hdr3,hdr4);
else if ( (data= curl_post(&exchange->cHandle,url,0,payload,hdr1,hdr2,hdr3,hdr4)) != 0 )
json = cJSON_Parse(data);
if ( retstrp != 0 )
*retstrp = data;
else if ( data != 0 )
free(data);
return(json);
}
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024];
sprintf(payload,"command=returnCompleteBalances&nonce=%llu",(long long)exchange_nonce(exchange));
return(SIGNPOST(&exchange->cHandle,1,0,exchange,EXCHANGE_AUTHURL,payload));
}
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
char *itemstr = 0; cJSON *item,*obj; double onorders,btcvalue;
*balancep = 0.;
if ( argjson != 0 && (item= jobj(argjson,coinstr)) != 0 )
{
itemstr = jprint(item,0);
*balancep = jdouble(item,"available");
onorders = jdouble(item,"onOrders");
btcvalue = jdouble(item,"btcValue");
if ( (obj= cJSON_Parse(itemstr)) != 0 )
{
free(itemstr);
jaddstr(obj,"base",coinstr);
jaddnum(obj,"balance",*balancep);
jaddnum(obj,"onOrders",onorders);
jaddnum(obj,"btcvalue",btcvalue);
itemstr = jprint(obj,1);
}
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
#include "checkbalance.c"
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
{
char payload[1024],pairstr[64],*extra,*typestr; cJSON *json; uint64_t nonce,txid = 0;
nonce = exchange_nonce(exchange);
if ( (extra= *retstrp) != 0 )
*retstrp = 0;
dir = flip_for_exchange(pairstr,"%s_%s","BTC",dir,&price,&volume,base,rel);
if ( extra != 0 && strcmp(extra,"margin") == 0 )
typestr = (dir > 0) ? "marginBuy":"marginSell";
else typestr = (dir > 0) ? "buy":"sell";
sprintf(payload,"command=%s&nonce=%lld&currencyPair=%s&rate=%.8f&amount=%.8f",typestr,(long long)nonce,pairstr,price,volume);
if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume,argjson) == 0 && (json= SIGNPOST(&exchange->cHandle,dotrade,retstrp,exchange,EXCHANGE_AUTHURL,payload)) != 0 )
{
txid = (get_API_nxt64bits(cJSON_GetObjectItem(json,"orderNumber")) << 32) | get_API_nxt64bits(cJSON_GetObjectItem(json,"tradeID"));
free_json(json);
}
return(txid);
}
void poloniex_setpair(char *pair,cJSON *argjson)
{
char *base,*rel;
base = jstr(argjson,"base");
rel = jstr(argjson,"rel");
if ( base == 0 || rel == 0 )
strcpy(pair,"all");
else sprintf(pair,"%s_%s",rel,base);
}
char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char payload[1024],*retstr = 0; cJSON *json;
sprintf(payload,"command=cancelOrder&nonce=%llu&orderNumber=%llu",(long long)exchange_nonce(exchange),(long long)quoteid);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,EXCHANGE_AUTHURL,payload)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized cancelorder
}
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],pair[64],*retstr = 0; cJSON *json;
poloniex_setpair(pair,argjson);
sprintf(payload,"command=returnOpenOrders&nonce=%llu&currencyPair=%s",(long long)exchange_nonce(exchange),pair);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,EXCHANGE_AUTHURL,payload)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized open orders
}
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
char payload[1024],pair[64],*retstr = 0; cJSON *json; uint32_t timestamp,endstamp;
poloniex_setpair(pair,argjson);
timestamp = juint(argjson,"start");
endstamp = juint(argjson,"end");
sprintf(payload,"command=returnTradeHistory&nonce=%llu&currencyPair=%s",(long long)exchange_nonce(exchange),pair);
if ( timestamp != 0 )
sprintf(payload + strlen(payload),"&start=%u",timestamp);
if ( endstamp != 0 )
sprintf(payload + strlen(payload),"&end=%u",endstamp);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,EXCHANGE_AUTHURL,payload)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized tradehistory
}
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char *status,*retstr; uint32_t iter;
for (iter=0; iter<2; iter++)
{
if ( iter == 0 )
status = OPENORDERS(exchange,argjson);
else status = TRADEHISTORY(exchange,argjson);
if ( (retstr= exchange_extractorderid(iter,status,quoteid,"orderNumber")) != 0 )
{
free(status);
return(retstr);
}
free(status);
}
return(clonestr("{\"error\":\"cant find quoteid\"}"));
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
char payload[1024],*paymentid,*retstr = 0; cJSON *json;
if ( base == 0 || base[0] == 0 )
return(clonestr("{\"error\":\"base not specified\"}"));
if ( destaddr == 0 || destaddr[0] == 0 )
return(clonestr("{\"error\":\"destaddr not specified\"}"));
if ( amount < SMALLVAL )
return(clonestr("{\"error\":\"amount not specified\"}"));
paymentid = jstr(argjson,"paymentid");
sprintf(payload,"command=withdraw&nonce=%llu&currency=%s&amount=%.6f&address=%s",(long long)exchange_nonce(exchange),base,amount,destaddr);
if ( paymentid != 0 )
sprintf(payload + strlen(payload),"&paymentId=%s",paymentid);
if ( (json= SIGNPOST(&exchange->cHandle,1,&retstr,exchange,EXCHANGE_AUTHURL,payload)) != 0 )
{
free_json(json);
}
return(retstr); // return standardized withdraw
}
struct exchange_funcs poloniex_funcs = EXCHANGE_FUNCS(poloniex,EXCHANGE_NAME);
#undef UPDATE
#undef SUPPORTS
#undef SIGNPOST
#undef TRADE
#undef ORDERSTATUS
#undef CANCELORDER
#undef OPENORDERS
#undef TRADEHISTORY
#undef BALANCES
#undef PARSEBALANCE
#undef WITHDRAW
#undef EXCHANGE_NAME
#undef EXCHANGE_AUTHURL
#undef CHECKBALANCE

185
iguana/exchanges/quadriga.c

@ -0,0 +1,185 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#define EXCHANGE_NAME "quadriga"
#define UPDATE quadriga ## _price
#define SUPPORTS quadriga ## _supports
#define SIGNPOST quadriga ## _signpost
#define TRADE quadriga ## _trade
#define ORDERSTATUS quadriga ## _orderstatus
#define CANCELORDER quadriga ## _cancelorder
#define OPENORDERS quadriga ## _openorders
#define TRADEHISTORY quadriga ## _tradehistory
#define BALANCES quadriga ## _balances
#define PARSEBALANCE quadriga ## _parsebalance
#define WITHDRAW quadriga ## _withdraw
#define CHECKBALANCE quadriga ## _checkbalance
double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,cJSON *argjson)
{
char url[1024],lrel[16],lbase[16];
strcpy(lrel,rel), strcpy(lbase,base);
tolowercase(lrel), tolowercase(lbase);
sprintf(url,"https://api.quadrigacx.com/v2/order_book?book=%s_%s",lbase,lrel);
return(exchanges777_standardprices(exchange,base,rel,url,quotes,0,0,maxdepth,0));
}
int32_t SUPPORTS(struct exchange_info *exchange,char *base,char *rel,cJSON *argjson)
{
char *baserels[][2] = { {"btc","usd"}, {"btc","cad"} };
return(baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel));
}
cJSON *SIGNPOST(void **cHandlep,int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *payload,char *path)
{
char url[1024],req[1024],md5secret[128],tmp[1024],dest[1025],hdr1[512],hdr2[512],hdr3[512],hdr4[512],*sig,*data = 0;
cJSON *json; uint64_t nonce;
hdr1[0] = hdr2[0] = hdr3[0] = hdr4[0] = 0;
json = 0;
nonce = exchange_nonce(exchange) * 1000 + ((uint64_t)OS_milliseconds() % 1000);
sprintf(tmp,"%llu%s%s",(long long)nonce,exchange->userid,exchange->apikey);
calc_md5(md5secret,exchange->apisecret,(int32_t)strlen(exchange->apisecret));
if ( (sig= hmac_sha256_str(dest,md5secret,(int32_t)strlen(md5secret),tmp)) != 0 )
{
sprintf(req,"{\"key\":\"%s\",%s\"nonce\":%llu,\"signature\":\"%s\"}",exchange->apikey,payload,(long long)nonce,sig);
sprintf(hdr1,"Content-Type:application/json");
sprintf(hdr2,"charset=utf-8");
sprintf(hdr3,"Content-Length:%ld",(long)strlen(req));
sprintf(url,"https://api.quadrigacx.com/v2/%s",path);
if ( dotrade == 0 )
data = exchange_would_submit(req,hdr1,hdr2,hdr3,hdr4);
else if ( (data= curl_post(&exchange->cHandle,url,0,req,hdr1,hdr2,hdr3,hdr4)) != 0 )
json = cJSON_Parse(data);
}
if ( retstrp != 0 )
*retstrp = data;
else if ( data != 0 )
free(data);
return(json);
}
char *PARSEBALANCE(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson)
{
//[{"btc_available":"0.00000000","btc_reserved":"0.00000000","btc_balance":"0.00000000","cad_available":"0.00","cad_reserved":"0.00","cad_balance":"0.00","usd_available":"0.00","usd_reserved":"0.00","usd_balance":"0.00","xau_available":"0.000000","xau_reserved":"0.000000","xau_balance":"0.000000","fee":"0.5000"}]
char field[128],*str,*itemstr = 0; cJSON *obj; double reserv,total;
*balancep = 0.;
strcpy(field,coinstr);
tolowercase(field);
strcat(field,"_available");
if ( argjson != 0 && (str= jstr(argjson,field)) != 0 )
{
*balancep = jdouble(argjson,field);
strcpy(field,coinstr), tolowercase(field), strcat(field,"_reserved");
reserv = jdouble(argjson,field);
strcpy(field,coinstr), tolowercase(field), strcat(field,"_balance");
total = jdouble(argjson,field);
obj = cJSON_CreateObject();
jaddnum(obj,"balance",*balancep);
jaddnum(obj,"locked_balance",reserv);
jaddnum(obj,"total",total);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
cJSON *BALANCES(struct exchange_info *exchange,cJSON *argjson)
{
return(SIGNPOST(&exchange->cHandle,1,0,exchange,"","balance"));
}
#include "checkbalance.c"
uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson)
{
char payload[1024],pairstr[64],*extra,*path; cJSON *json; uint64_t txid = 0;
if ( (extra= *retstrp) != 0 )
*retstrp = 0;
if ( (dir= flipstr_for_exchange(exchange,pairstr,"%s_%s",dir,&price,&volume,base,rel,argjson)) == 0 )
{
printf("cant find baserel (%s/%s)\n",base,rel);
return(0);
}
path = (dir > 0) ? "buy" : "sell";
//key - API key
//signature - signature
//nonce - nonce
//amount - amount of major currency
//price - price to buy at
//book - optional, if not specified, will default to btc_cad
sprintf(payload,"\"amount\":%.6f,\"price\":%.3f,\"book\":\"%s_%s\",",volume,price,base,rel);
if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume,argjson) == 0 && (json= SIGNPOST(&exchange->cHandle,dotrade,retstrp,exchange,payload,path)) != 0 )
{
// parse json and set txid
free_json(json);
}
return(txid);
}
char *ORDERSTATUS(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char buf[64];
sprintf(buf,"\"id\":%llu,",(long long)quoteid);
return(jprint(SIGNPOST(&exchange->cHandle,1,0,exchange,buf,"lookup_order"),1));
}
char *CANCELORDER(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson)
{
char buf[64];
sprintf(buf,"\"id\":%llu,",(long long)quoteid);
return(jprint(SIGNPOST(&exchange->cHandle,1,0,exchange,buf,"cancel_order"),1));
}
char *OPENORDERS(struct exchange_info *exchange,cJSON *argjson)
{
return(jprint(SIGNPOST(&exchange->cHandle,1,0,exchange,"","open_orders"),1));
}
char *TRADEHISTORY(struct exchange_info *exchange,cJSON *argjson)
{
return(jprint(SIGNPOST(&exchange->cHandle,1,0,exchange,"","user_transactions"),1));
}
char *WITHDRAW(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson)
{
char buf[1024];
if ( base == 0 || base[0] == 0 )
return(clonestr("{\"error\":\"base not specified\"}"));
if ( destaddr == 0 || destaddr[0] == 0 )
return(clonestr("{\"error\":\"destaddr not specified\"}"));
if ( amount < SMALLVAL )
return(clonestr("{\"error\":\"amount not specified\"}"));
sprintf(buf,"\"amount\":%.4f,\"address\":\"%s\",",amount,destaddr);
printf("submit.(%s)\n",buf);
return(jprint(SIGNPOST(&exchange->cHandle,1,0,exchange,"","bitcoin_withdrawal"),1));
}
struct exchange_funcs quadriga_funcs = EXCHANGE_FUNCS(quadriga,EXCHANGE_NAME);
#undef UPDATE
#undef SUPPORTS
#undef SIGNPOST
#undef TRADE
#undef ORDERSTATUS
#undef CANCELORDER
#undef OPENORDERS
#undef TRADEHISTORY
#undef BALANCES
#undef PARSEBALANCE
#undef WITHDRAW
#undef EXCHANGE_NAME
#undef CHECKBALANCE

68
iguana/exchanges777.h

@ -0,0 +1,68 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#ifndef EXCHANGES777_H
#define EXCHANGES777_H
#include "iguana777.h"
#include <curl/curl.h>
#include <curl/easy.h>
#define EXCHANGES777_MAXDEPTH 200
#define EXCHANGES777_DEFAULT_TIMEOUT 30
struct exchange_info;
struct exchange_quote { double price,volume; uint64_t orderid,offerNXT; uint32_t timestamp; };
struct exchange_request
{
struct queueitem DL;
cJSON *argjson; char **retstrp;
double price,volume,hbla,lastbid,lastask;
uint64_t orderid;
int32_t dir,depth,func,numbids,numasks;
char base[16],rel[16],destaddr[64],invert,allflag,dotrade;
struct exchange_quote bidasks[];
};
struct exchange_funcs
{
char name[32];
double (*price)(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *quotes,int32_t maxdepth,cJSON *argjson);
int32_t (*supports)(struct exchange_info *exchange,char *base,char *rel,cJSON *argjson);
char *(*parsebalance)(struct exchange_info *exchange,double *balancep,char *coinstr,cJSON *argjson);
cJSON *(*balances)(struct exchange_info *exchange,cJSON *argjson);
uint64_t (*trade)(int32_t dotrade,char **retstrp,struct exchange_info *exchange,char *base,char *rel,int32_t dir,double price,double volume,cJSON *argjson);
char *(*orderstatus)(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson);
char *(*cancelorder)(struct exchange_info *exchange,uint64_t quoteid,cJSON *argjson);
char *(*openorders)(struct exchange_info *exchange,cJSON *argjson);
char *(*tradehistory)(struct exchange_info *exchange,cJSON *argjson);
char *(*withdraw)(struct exchange_info *exchange,char *base,double amount,char *destaddr,cJSON *argjson);
};
#define EXCHANGE_FUNCS(xchg,name) { name, xchg ## _price, xchg ## _supports, xchg ## _parsebalance, xchg ## _balances, xchg ## _trade, xchg ## _orderstatus, xchg ## _cancelorder, xchg ## _openorders, xchg ## _tradehistory, xchg ## _withdraw }
struct exchange_info
{
struct exchange_funcs issue;
char name[16],apikey[MAX_JSON_FIELD],apisecret[MAX_JSON_FIELD],tradepassword[MAX_JSON_FIELD],userid[MAX_JSON_FIELD];
uint32_t exchangeid,pollgap,lastpoll;
uint64_t lastnonce; double commission;
CURL *cHandle; queue_t requestQ,pricesQ,pendingQ[2];
};
void *curl_post(void **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3);
void prices777_processprice(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth);
#endif

1
iguana/iguana777.h

@ -721,6 +721,7 @@ cJSON *iguana_voutjson(struct iguana_info *coin,struct iguana_msgvout *vout,int3
cJSON *iguana_vinjson(struct iguana_info *coin,struct iguana_msgvin *vin);
char *iguana_rawtxbytes(struct iguana_info *coin,cJSON *json,uint8_t *data,int32_t datalen);
int32_t iguana_send_VPNversion(struct iguana_info *coin,struct iguana_peer *addr,uint64_t myservices);
void exchanges777_init(int32_t sleepflag);
extern queue_t bundlesQ;

726
iguana/iguana_exchanges.c

@ -0,0 +1,726 @@
/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#include "exchanges777.h"
#define EXCHANGE777_DONE 1
#define EXCHANGE777_ISPENDING 2
#define EXCHANGE777_REQUEUE 3
char *Exchange_names[] = { "bitfinex", "btc38", "bitstamp", "btce", "poloniex", "bittrex", "huobi", "coinbase", "okcoin", "lakebtc", "quadriga", "truefx", "ecb", "instaforex", "fxcm", "yahoo" };
struct exchange_info *Exchanges[sizeof(Exchange_names)/sizeof(*Exchange_names)];
void prices777_processprice(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth)
{
}
cJSON *exchanges777_quotejson(struct exchange_quote *quote,int32_t allflag)
{
cJSON *json; char str[65];
if ( allflag != 0 )
{
json = cJSON_CreateObject();
jaddnum(json,"price",quote->price);
jaddnum(json,"volume",quote->volume);
jaddstr(json,"time",utc_str(str,quote->timestamp));
if ( quote->orderid > 0 )
jadd64bits(json,"orderid",quote->orderid);
if ( quote->offerNXT > 0 )
jadd64bits(json,"offerNXT",quote->offerNXT);
return(json);
} else return(cJSON_CreateNumber(quote->price));
}
char *exchanges777_orderbook_jsonstr(struct exchange_info *exchange,char *_base,char *_rel,struct exchange_quote *bidasks,int32_t maxdepth,int32_t invert,int32_t allflag)
{
struct exchange_quote *bid,*ask; cJSON *json,*bids,*asks; double highbid,lowask; uint32_t timestamp;
int32_t slot,numbids,numasks,enda,endb; char baserel[64],base[64],rel[64],str[65];
if ( invert == 0 )
{
strcpy(base,_base), strcpy(rel,_rel);
sprintf(baserel,"%s/%s",base,rel);
}
else
{
strcpy(base,_rel), strcpy(rel,_base);
sprintf(baserel,"%s/%s",rel,base);
}
json = cJSON_CreateObject(), bids = cJSON_CreateArray(), asks = cJSON_CreateArray();
highbid = lowask = 0.;
for (slot=numbids=numasks=enda=endb=0; slot<maxdepth; slot++)
{
bid = &bidasks[slot << 1], ask = &bidasks[(slot << 1) + 1];
if ( endb == 0 && bid->price > SMALLVAL )
{
jaddi(bids,exchanges777_quotejson(bid,allflag));
if ( numbids++ == 0 )
highbid = bid->price;
} else endb = 1;
if ( enda == 0 && ask->price > SMALLVAL )
{
jaddi(asks,exchanges777_quotejson(ask,allflag));
if ( numasks++ == 0 )
lowask = ask->price;
} else enda = 1;
}
jaddstr(json,"exchange",exchange->name);
jaddnum(json,"inverted",invert);
jaddstr(json,"base",base);
if ( rel[0] != 0 )
jaddstr(json,"rel",rel);
jadd(json,"bids",bids);
jadd(json,"asks",asks);
if ( invert == 0 )
{
jaddnum(json,"numbids",numbids);
jaddnum(json,"numasks",numasks);
if ( highbid > SMALLVAL )
jaddnum(json,"highbid",highbid);
if ( lowask > SMALLVAL )
jaddnum(json,"lowask",lowask);
}
else
{
jaddnum(json,"numbids",numasks);
jaddnum(json,"numasks",numbids);
if ( lowask > SMALLVAL )
jaddnum(json,"highbid",1. / lowask);
if ( highbid > SMALLVAL )
jaddnum(json,"lowask",1. / highbid);
}
timestamp = (uint32_t)time(NULL);
jaddnum(json,"timestamp",timestamp);
jaddstr(json,"time",utc_str(str,timestamp));
jaddnum(json,"maxdepth",maxdepth);
return(jprint(json,1));
}
void exchanges777_json_quotes(struct exchange_info *exchange,char *base,char *rel,double *lastbidp,double *lastaskp,double *hblap,struct exchange_quote *bidasks,cJSON *bids,cJSON *asks,int32_t maxdepth,char *pricefield,char *volfield,uint32_t reftimestamp)
{
int32_t i,slot,n=0,m=0,dir,bidask,slot_ba,numitems,numbids,numasks; uint64_t orderid,offerNXT;
cJSON *item; struct exchange_quote *quote; uint32_t timestamp; double price,volume,hbla = 0.;
*lastbidp = *lastaskp = 0.;
numbids = numasks = 0;
if ( reftimestamp == 0 )
reftimestamp = (uint32_t)time(NULL);
if ( bids != 0 )
{
n = cJSON_GetArraySize(bids);
if ( maxdepth != 0 && n > maxdepth )
n = maxdepth;
}
if ( asks != 0 )
{
m = cJSON_GetArraySize(asks);
if ( maxdepth != 0 && m > maxdepth )
m = maxdepth;
}
for (i=0; i<n||i<m; i++)
{
for (bidask=0; bidask<2; bidask++)
{
offerNXT = orderid = 0;
price = volume = 0.;
dir = (bidask == 0) ? 1 : -1;
if ( bidask == 0 && i >= n )
continue;
else if ( bidask == 1 && i >= m )
continue;
//if ( strcmp(prices->exchange,"bter") == 0 && dir < 0 )
// slot = ((bidask==0?n:m) - 1) - i;
//else
slot = i;
timestamp = 0;
item = jitem(bidask==0?bids:asks,slot);
if ( pricefield != 0 && volfield != 0 )
price = jdouble(item,pricefield), volume = jdouble(item,volfield);
else if ( is_cJSON_Array(item) != 0 && (numitems= cJSON_GetArraySize(item)) != 0 ) // big assumptions about order within nested array!
{
price = jdouble(jitem(item,0),0), volume = jdouble(jitem(item,1),0);
if ( strcmp(exchange->name,"kraken") == 0 )
timestamp = juint(jitem(item,2),0);
else orderid = j64bits(jitem(item,2),0);
}
else continue;
if ( price > SMALLVAL && volume > SMALLVAL )
{
if ( exchange->commission != 0. )
{
//printf("price %f fee %f -> ",price,prices->commission * price);
if ( bidask == 0 )
price -= exchange->commission * price;
else price += exchange->commission * price;
//printf("%f\n",price);
}
quote = (bidask == 0) ? &bidasks[numbids<<1] : &bidasks[(numbids<<1) + 1];
quote->price = price, quote->volume = volume, quote->timestamp = timestamp, quote->orderid = orderid, quote->offerNXT = offerNXT;
if ( bidask == 0 )
slot_ba = (numbids++ << 1);
else slot_ba = (numasks++ << 1) | 1;
if ( i == 0 )
{
if ( bidask == 0 )
*lastbidp = price;
else *lastaskp = price;
if ( hbla == 0. )
hbla = price;
else hbla = 0.5 * (hbla + price);
}
printf("%d,%d: %-8s %s %5s/%-5s %13.8f vol %13.8f | invert %13.8f vol %13.8f | timestamp.%u\n",numbids,numasks,exchange->name,dir>0?"bid":"ask",base,rel,price,volume,1./price,volume*price,timestamp);
}
}
}
if ( hbla != 0. )
*hblap = hbla;
}
double exchanges777_json_orderbook(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,cJSON *json,char *resultfield,char *bidfield,char *askfield,char *pricefield,char *volfield)
{
cJSON *obj = 0,*bidobj=0,*askobj=0; double lastbid,lastask,hbla = 0.; int32_t numasks=0,numbids=0;
if ( resultfield == 0 )
obj = json;
if ( maxdepth == 0 )
maxdepth = EXCHANGES777_MAXDEPTH;
if ( resultfield == 0 || (obj= jobj(json,resultfield)) != 0 )
{
bidobj = jarray(&numbids,obj,bidfield);
askobj = jarray(&numasks,obj,askfield);
if ( bidobj != 0 || askobj != 0 )
{
exchanges777_json_quotes(exchange,base,rel,&lastbid,&lastask,&hbla,bidasks,bidobj,askobj,maxdepth,pricefield,volfield,0);
}
}
return(hbla);
}
double exchanges777_standardprices(struct exchange_info *exchange,char *base,char *rel,char *url,struct exchange_quote *quotes,char *price,char *volume,int32_t maxdepth,char *field)
{
char *jsonstr; cJSON *json; double hbla = 0.;
if ( (jsonstr= issue_curl(url)) != 0 )
{
//if ( strcmp(exchangestr,"btc38") == 0 )
printf("(%s) -> (%s)\n",url,jsonstr);
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
hbla = exchanges777_json_orderbook(exchange,base,rel,quotes,maxdepth,json,field,"bids","asks",price,volume);
free_json(json);
}
free(jsonstr);
}
return(hbla);
}
char *exchange_would_submit(char *postreq,char *hdr1,char *hdr2,char *hdr3, char *hdr4)
{
char *data; cJSON *json;
json = cJSON_CreateObject();
jaddstr(json,"post",postreq);
if ( hdr1[0] != 0 )
jaddstr(json,"hdr1",hdr1);
if ( hdr2[0] != 0 )
jaddstr(json,"hdr2",hdr2);
if ( hdr3[0] != 0 )
jaddstr(json,"hdr3",hdr3);
if ( hdr4[0] != 0 )
jaddstr(json,"hdr4",hdr4);
data = jprint(json,1);
json = 0;
return(data);
}
uint64_t exchange_nonce(struct exchange_info *exchange)
{
uint64_t nonce;
nonce = time(NULL);
if ( nonce < exchange->lastnonce )
nonce = exchange->lastnonce + 1;
exchange->lastnonce = nonce;
return(nonce);
}
int32_t flip_for_exchange(char *pairstr,char *fmt,char *refstr,int32_t dir,double *pricep,double *volumep,char *base,char *rel)
{
if ( strcmp(rel,refstr) == 0 )
sprintf(pairstr,fmt,rel,base);
else
{
if ( strcmp(base,refstr) == 0 )
{
sprintf(pairstr,fmt,base,rel);
dir = -dir;
*volumep *= *pricep;
*pricep = (1. / *pricep);
}
else sprintf(pairstr,fmt,rel,base);
}
return(dir);
}
int32_t flipstr_for_exchange(struct exchange_info *exchange,char *pairstr,char *fmt,int32_t dir,double *pricep,double *volumep,char *_base,char *_rel,cJSON *argjson)
{
int32_t polarity; char base[64],rel[64];
strcpy(base,_base), strcpy(rel,_rel);
tolowercase(base), tolowercase(rel);
polarity = (*exchange->issue.supports)(exchange,base,rel,argjson);
if ( dir > 0 )
sprintf(pairstr,fmt,base,rel);
else if ( dir < 0 )
{
*volumep *= *pricep;
*pricep = (1. / *pricep);
sprintf(pairstr,fmt,rel,base);
}
return(dir);
}
int32_t cny_flip(char *market,char *coinname,char *base,char *rel,int32_t dir,double *pricep,double *volumep)
{
char pairstr[512],lbase[16],lrel[16],*refstr=0;
strcpy(lbase,base), tolowercase(lbase), strcpy(lrel,rel), tolowercase(lrel);
if ( strcmp(lbase,"cny") == 0 || strcmp(lrel,"cny") == 0 )
{
dir = flip_for_exchange(pairstr,"%s_%s","cny",dir,pricep,volumep,lbase,lrel);
refstr = "cny";
}
else if ( strcmp(lbase,"btc") == 0 || strcmp(lrel,"btc") == 0 )
{
dir = flip_for_exchange(pairstr,"%s_%s","btc",dir,pricep,volumep,lbase,lrel);
refstr = "btc";
}
if ( market != 0 && coinname != 0 && refstr != 0 )
{
strcpy(market,refstr);
if ( strcmp(lbase,"refstr") != 0 )
strcpy(coinname,lbase);
else strcpy(coinname,lrel);
touppercase(coinname);
}
return(dir);
}
char *exchange_extractorderid(int32_t historyflag,char *status,uint64_t quoteid,char *quoteid_field)
{
cJSON *array,*item,*json; int32_t i,n; uint64_t txid;
if ( status != 0 )
{
if ( (array= cJSON_Parse(status)) != 0 && is_cJSON_Array(array) != 0 && (n= cJSON_GetArraySize(array)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( (txid= juint(item,quoteid_field)) == quoteid )
{
json = cJSON_CreateObject();
jaddstr(json,"result",historyflag == 0 ? "order still pending" : "order completed");
jadd(json,"order",cJSON_Duplicate(item,1));
free_json(array);
return(jprint(json,1));
}
}
}
if ( array != 0 )
free_json(array);
}
return(0);
}
int32_t baserel_polarity(char *pairs[][2],int32_t n,char *_base,char *_rel)
{
int32_t i; char base[16],rel[16];
strcpy(base,_base), tolowercase(base);
strcpy(rel,_rel), tolowercase(rel);
for (i=0; i<n; i++)
{
if ( strcmp(pairs[i][0],base) == 0 && strcmp(pairs[i][1],rel) == 0 )
return(1);
else if ( strcmp(pairs[i][0],rel) == 0 && strcmp(pairs[i][1],base) == 0 )
return(-1);
}
printf("cant find.(%s/%s) [%s/%s].%d\n",base,rel,pairs[0][0],pairs[0][1],n);
return(0);
}
// following includes C code directly
#include "exchanges/poloniex.c"
#include "exchanges/bittrex.c"
#include "exchanges/btce.c"
#include "exchanges/bitfinex.c"
#include "exchanges/btc38.c"
#include "exchanges/huobi.c"
#include "exchanges/lakebtc.c"
#include "exchanges/quadriga.c"
#include "exchanges/okcoin.c"
#include "exchanges/coinbase.c"
#include "exchanges/bitstamp.c"
char *exchanges777_process(struct exchange_info *exchange,int32_t *retvalp,struct exchange_request *req)
{
char *retstr = 0; int32_t dir; uint64_t orderid; double balance; cJSON *balancejson,*retjson;
*retvalp = EXCHANGE777_DONE;
switch ( req->func )
{
case 'Q':
memset(req->bidasks,0,req->depth * sizeof(*req->bidasks) * 2);
(*exchange->issue.price)(exchange,req->base,req->rel,req->bidasks,req->depth,req->argjson);
retstr = exchanges777_orderbook_jsonstr(exchange,req->base,req->rel,req->bidasks,req->depth,req->invert,req->allflag);
break;
case 'S':
dir = (*exchange->issue.supports)(exchange,req->base,req->rel,req->argjson);
retjson = cJSON_CreateObject();
jaddnum(retjson,"result",dir);
retstr = jprint(retjson,1);
break;
case 'T':
orderid = (*exchange->issue.trade)(req->dotrade,&retstr,exchange,req->base,req->rel,req->dir,req->price,req->volume,req->argjson);
if ( retstr == 0 )
{
retjson = cJSON_CreateObject();
if ( orderid != 0 )
jadd64bits(retjson,"result",orderid);
else jaddstr(retjson,"error","no return value from trade call");
retstr = jprint(retjson,1);
}
break;
case 'B':
if ( (balancejson= (*exchange->issue.balances)(exchange,req->argjson)) != 0 )
{
retstr = (*exchange->issue.parsebalance)(exchange,&balance,req->base,balancejson);
free_json(balancejson);
}
break;
case 'P':
retstr = (*exchange->issue.orderstatus)(exchange,req->orderid,req->argjson);
break;
case 'C':
retstr = (*exchange->issue.cancelorder)(exchange,req->orderid,req->argjson);
break;
case 'O':
retstr = (*exchange->issue.openorders)(exchange,req->argjson);
break;
case 'H':
retstr = (*exchange->issue.tradehistory)(exchange,req->argjson);
break;
case 'W':
retstr = (*exchange->issue.withdraw)(exchange,req->base,req->volume,req->destaddr,req->argjson);
break;
}
return(retstr);
}
void exchanges777_loop(void *ptr)
{
int32_t flag,retval; struct exchange_request *req; char *retstr; struct exchange_info *exchange = ptr;
while ( 1 )
{
flag = retval = 0;
retstr = 0;
if ( (req= queue_dequeue(&exchange->requestQ,0)) != 0 )
{
printf("dequeued %s.%c\n",exchange->name,req->func);
retstr = exchanges777_process(exchange,&retval,req);
if ( retval == EXCHANGE777_DONE )
{
if ( retstr != 0 )
{
if ( req->retstrp != 0 )
*req->retstrp = retstr;
else free(retstr);
}
free(req);
flag++;
}
else
{
if ( retstr != 0 )
free(retstr);
if ( retval == EXCHANGE777_ISPENDING )
queue_enqueue("Xpending",&exchange->pendingQ[0],&req->DL,0), flag++;
else if ( retval == EXCHANGE777_REQUEUE )
queue_enqueue("requeue",&exchange->requestQ,&req->DL,0);
else
{
printf("exchanges777_process: illegal retval.%d\n",retval);
free(req);
}
}
}
if ( flag == 0 && time(NULL) > exchange->lastpoll+exchange->pollgap )
{
printf("check %s pricesQ\n",exchange->name);
if ( (req= queue_dequeue(&exchange->pricesQ,0)) != 0 )
{
exchange->lastpoll = (uint32_t)time(NULL);
req->hbla = (*exchange->issue.price)(exchange,req->base,req->rel,req->bidasks,req->depth,req->argjson);
prices777_processprice(exchange,req->base,req->rel,req->bidasks,req->depth);
queue_enqueue("pricesQ",&exchange->pricesQ,&req->DL,0);
}
}
if ( flag == 0 )
sleep(exchange->pollgap/2 + 1);
}
}
char *exchanges777_submit(struct exchange_info *exchange,char **retstrp,struct exchange_request *req,int32_t func,int32_t maxseconds)
{
int32_t i;
req->func = func;
if ( maxseconds == 0 )
maxseconds = EXCHANGES777_DEFAULT_TIMEOUT;
queue_enqueue("exchangeQ",&exchange->requestQ,&req->DL,0);
for (i=0; i<maxseconds; i++)
if ( *retstrp != 0 )
return(*retstrp);
return(clonestr("{\"error\":\"request timed out\"}"));
}
char *exchanges777_Qtrade(struct exchange_info *exchange,char *base,char *rel,int32_t maxseconds,int32_t dotrade,int32_t dir,double price,double volume,cJSON *argjson)
{
struct exchange_request *req; char *retstr = 0;
if ( base[0] == 0 || rel[0] == 0 )
return(clonestr("{\"error\":\"invalid base or rel\"}"));
req = calloc(1,sizeof(*req));
req->argjson = argjson; req->retstrp = &retstr;
safecopy(req->base,base,sizeof(req->base));
safecopy(req->rel,rel,sizeof(req->rel));
req->price = price, req->volume = volume;
req->dir = dir, req->dotrade = dotrade;
return(exchanges777_submit(exchange,&retstr,req,'T',maxseconds));
}
char *exchanges777_Qprices(struct exchange_info *exchange,char *base,char *rel,int32_t maxseconds,int32_t allfields,int32_t invert,int32_t depth,cJSON *argjson)
{
struct exchange_request *req; char *retstr = 0;
if ( base[0] == 0 || rel[0] == 0 )
return(clonestr("{\"error\":\"invalid base or rel\"}"));
req = calloc(1,sizeof(*req) + sizeof(*req->bidasks)*depth*2);
req->argjson = argjson; req->retstrp = &retstr;
safecopy(req->base,base,sizeof(req->base));
safecopy(req->rel,rel,sizeof(req->rel));
req->depth = depth, req->allflag = allfields, req->invert = invert;
return(exchanges777_submit(exchange,&retstr,req,'Q',maxseconds));
}
char *exchanges777_Qrequest(struct exchange_info *exchange,int32_t func,char *base,char *rel,int32_t maxseconds,uint64_t orderid,char *destaddr,double amount,cJSON *argjson)
{
struct exchange_request *req; char *retstr = 0;
req = calloc(1,sizeof(*req));
req->volume = amount;
safecopy(req->destaddr,destaddr,sizeof(req->destaddr));
safecopy(req->base,base,sizeof(req->base));
safecopy(req->rel,rel,sizeof(req->rel));
req->orderid = orderid;
return(exchanges777_submit(exchange,&retstr,req,func,maxseconds));
}
int32_t exchanges777_id(char *exchangestr)
{
int32_t i;
for (i=0; i<sizeof(Exchange_names)/sizeof(*Exchange_names); i++)
{
if ( strcmp(exchangestr,Exchange_names[i]) == 0 )
return(i);
}
return(-1);
}
struct exchange_info *exchanges777_find(char *exchangestr)
{
int32_t exchangeid;
if ( (exchangeid= exchanges777_id(exchangestr)) >= 0 )
return(Exchanges[exchangeid]);
return(0);
}
struct exchange_info *exchange_create(char *exchangestr,cJSON *argjson)
{
struct exchange_funcs funcs[] =
{
{"truefx", 0 }, {"ecb", 0 }, {"instaforex", 0 }, {"fxcm", 0 }, {"yahoo", 0 },
poloniex_funcs, bittrex_funcs, btce_funcs, bitfinex_funcs, btc38_funcs,
huobi_funcs, lakebtc_funcs, quadriga_funcs, okcoin_funcs, coinbase_funcs, bitstamp_funcs
};
char *key,*secret,*userid,*tradepassword; struct exchange_info *exchange; int32_t i,exchangeid;
if ( (exchangeid= exchanges777_id(exchangestr)) < 0 )
{
printf("exchange_create: cant find.(%s)\n",exchangestr);
return(0);
}
for (i=0; i<sizeof(funcs)/sizeof(*funcs); i++)
{
if ( strcmp(exchangestr,funcs[i].name) == 0 )
{
break;
}
}
if ( i == sizeof(funcs)/sizeof(*funcs) )
{
printf("cant find exchange.(%s)\n",exchangestr);
return(0);
}
exchange = calloc(1,sizeof(*exchange));
exchange->issue = funcs[i];
iguana_initQ(&exchange->pricesQ,"prices");
iguana_initQ(&exchange->requestQ,"request");
iguana_initQ(&exchange->pendingQ[0],"pending0");
iguana_initQ(&exchange->pendingQ[1],"pending1");
exchange->exchangeid = exchangeid;
safecopy(exchange->name,exchangestr,sizeof(exchange->name));
exchange->pollgap = juint(argjson,"pollgap");
if ( (key= jstr(argjson,"apikey")) != 0 || (key= jstr(argjson,"key")) != 0 )
safecopy(exchange->apikey,key,sizeof(exchange->apikey));
if ( (secret= jstr(argjson,"apisecret")) != 0 || (secret= jstr(argjson,"secret")) != 0 )
safecopy(exchange->apisecret,secret,sizeof(exchange->apisecret));
if ( (userid= jstr(argjson,"userid")) != 0 )
safecopy(exchange->userid,userid,sizeof(exchange->userid));
if ( (tradepassword= jstr(argjson,"tradepassword")) != 0 )
safecopy(exchange->tradepassword,tradepassword,sizeof(exchange->tradepassword));
if ( (exchange->commission= jdouble(argjson,"commission")) > 0. )
exchange->commission *= .01;
printf("ADDEXCHANGE.(%s) [%s, %s, %s] commission %.3f%%\n",exchangestr,exchange->apikey,exchange->userid,exchange->apisecret,exchange->commission * 100.);
Exchanges[exchangeid] = exchange;
return(exchange);
}
struct exchange_info *exchanges777_info(char *exchangestr,int32_t sleepflag,cJSON *json)
{
struct exchange_info *exchange;
if ( (exchange= exchanges777_find(exchangestr)) == 0 )
{
if ( (exchange= exchange_create(exchangestr,json)) != 0 )
{
iguana_launch(iguana_coinadd("BTCD"),"exchangeloop",(void *)exchanges777_loop,exchange,IGUANA_EXCHANGETHREAD);
if ( sleepflag > 0 )
sleep(sleepflag);
}
}
return(exchange);
}
void exchanges777_init(int32_t sleepflag)
{
int32_t i; cJSON *argjson = cJSON_CreateObject();
for (i=0; i<sizeof(Exchange_names)/sizeof(*Exchange_names); i++)
exchanges777_info(Exchange_names[i],sleepflag,argjson);
}
#include "../includes/iguana_apidefs.h"
THREE_STRINGS_AND_THREE_INTS(InstantDEX,orderbook,exchange,base,rel,depth,allfields,invert)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json)) != 0 )
return(exchanges777_Qprices(ptr,base,rel,juint(json,"maxseconds"),allfields,invert,depth,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
}
THREE_STRINGS_AND_THREE_DOUBLES(InstantDEX,buy,exchange,base,rel,price,volume,dotrade)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json)) != 0 )
return(exchanges777_Qtrade(ptr,base,rel,juint(json,"maxseconds"),dotrade,1,price,volume,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
}
THREE_STRINGS_AND_THREE_DOUBLES(InstantDEX,sell,exchange,base,rel,price,volume,dotrade)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json)) != 0 )
return(exchanges777_Qtrade(ptr,base,rel,juint(json,"maxseconds"),dotrade,-1,price,volume,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
}
THREE_STRINGS_AND_DOUBLE(InstantDEX,withdraw,exchange,base,destaddr,amount)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json)) != 0 )
return(exchanges777_Qrequest(ptr,'W',base,0,juint(json,"maxseconds"),0,destaddr,amount,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
}
THREE_STRINGS(InstantDEX,supports,exchange,base,rel)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json)) != 0 )
return(exchanges777_Qrequest(ptr,'S',base,rel,juint(json,"maxseconds"),0,0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
}
TWO_STRINGS(InstantDEX,balance,exchange,base)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json)) != 0 )
return(exchanges777_Qrequest(ptr,'B',base,0,juint(json,"maxseconds"),0,0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
}
TWO_STRINGS(InstantDEX,orderstatus,exchange,orderid)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json)) != 0 )
return(exchanges777_Qrequest(ptr,'P',0,0,juint(json,"maxseconds"),calc_nxt64bits(orderid),0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
}
TWO_STRINGS(InstantDEX,cancelorder,exchange,orderid)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json)) != 0 )
return(exchanges777_Qrequest(ptr,'C',0,0,juint(json,"maxseconds"),calc_nxt64bits(orderid),0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
}
STRING_ARG(InstantDEX,openorders,exchange)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json)) != 0 )
return(exchanges777_Qrequest(ptr,'O',0,0,juint(json,"maxseconds"),0,0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
}
STRING_ARG(InstantDEX,tradehistory,exchange)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json)) != 0 )
return(exchanges777_Qrequest(ptr,'H',0,0,juint(json,"maxseconds"),0,0,0,json));
else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
}
THREE_STRINGS(InstantDEX,apikeypair,exchange,apikey,apisecret)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json)) != 0 )
{
if ( apikey != 0 && apikey[0] != 0 && apisecret != 0 && apisecret[0] != 0 )
{
safecopy(ptr->apikey,apikey,sizeof(ptr->apikey));
safecopy(ptr->apisecret,apisecret,sizeof(ptr->apisecret));
return(clonestr("{\"result\":\"set apikey and apisecret\"}"));
} else return(clonestr("{\"error\":\"need both userid and password\"}"));
} else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
}
THREE_STRINGS(InstantDEX,setuserid,exchange,userid,tradepassword)
{
struct exchange_info *ptr;
if ( (ptr= exchanges777_info(exchange,1,json)) != 0 )
{
safecopy(ptr->userid,userid,sizeof(ptr->userid));
safecopy(ptr->tradepassword,tradepassword,sizeof(ptr->tradepassword));
return(clonestr("{\"result\":\"set userid and/or tradepassword\"}"));
} else return(clonestr("{\"error\":\"cant find or create exchange\"}"));
}
#include "../includes/iguana_apiundefs.h"

16
iguana/iguana_json.c

@ -82,6 +82,10 @@ cJSON *SuperNET_helpjson()
#define IGUANA_HELP_S(agent,name,str) array = helpjson(IGUANA_ARGS,#agent,#name,helparray(cJSON_CreateArray(),helpitem(#str,"string")))
#define IGUANA_HELP_SS(agent,name,str,str2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray2(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string")))
#define IGUANA_HELP_SSS(agent,name,str,str2,str3) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#str3,"string")))
#define IGUANA_HELP_SSSD(agent,name,str,str2,str3,amount) array = helpjson(IGUANA_ARGS,#agent,#name,helparray4(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#str3,"string"),helpitem(#amount,"float")))
#define IGUANA_HELP_SSSDDD(agent,name,str,str2,str3,amount,val2,val3) array = helpjson(IGUANA_ARGS,#agent,#name,helparray6(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#str3,"string"),helpitem(#amount,"float"),helpitem(#val2,"float"),helpitem(#val3,"float")))
#define IGUANA_HELP_SSSIII(agent,name,str,str2,str3,val,val2,val3) array = helpjson(IGUANA_ARGS,#agent,#name,helparray6(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#str3,"string"),helpitem(#val,"int"),helpitem(#val2,"int"),helpitem(#val3,"int")))
#define IGUANA_HELP_SSH(agent,name,str,str2,hash) array = helpjson(IGUANA_ARGS,#agent,#name,helparray3(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#hash,"hash")))
#define IGUANA_HELP_SSHI(agent,name,str,str2,hash,val) array = helpjson(IGUANA_ARGS,#agent,#name,helparray4(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#hash,"hash"),helpitem(#val,"int")))
#define IGUANA_HELP_SSHII(agent,name,str,str2,hash,val,val2) array = helpjson(IGUANA_ARGS,#agent,#name,helparray5(cJSON_CreateArray(),helpitem(#str,"string"),helpitem(#str2,"string"),helpitem(#hash,"hash"),helpitem(#val,"int"),helpitem(#val2,"int")))
@ -153,6 +157,9 @@ cJSON *SuperNET_helpjson()
#define HASH_ARG IGUANA_HELP_H
#define TWO_HASHES IGUANA_HELP_HH
#define HASH_AND_ARRAY IGUANA_HELP_HA
#define THREE_STRINGS_AND_THREE_INTS IGUANA_HELP_SSSIII
#define THREE_STRINGS_AND_THREE_DOUBLES IGUANA_HELP_SSSDDD
#define THREE_STRINGS_AND_DOUBLE IGUANA_HELP_SSSD
#include "../includes/iguana_apideclares.h"
@ -324,7 +331,7 @@ int32_t pretty_forms(char *fname,char *agentstr)
fprintf(fp,"%s\n",header);
if ( (helpjson= SuperNET_helpjson()) != 0 )
{
printf("JSON.(%s)\n",jprint(helpjson,0));
//printf("JSON.(%s)\n",jprint(helpjson,0));
if ( (array= jarray(&n,helpjson,"API")) != 0 )
{
for (i=0; i<n; i++)
@ -743,6 +750,10 @@ char *SuperNET_parser(struct supernet_info *myinfo,char *agent,char *method,cJSO
#define IGUANA_DISPATCH_S(agent,name,str) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str)))
#define IGUANA_DISPATCH_SS(agent,name,str,str2) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2)))
#define IGUANA_DISPATCH_SSS(agent,name,str,str2,str3) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3)))
#define IGUANA_DISPATCH_SSSD(agent,name,str,str2,str3,amount) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3),jdouble(json,#amount)))
#define IGUANA_DISPATCH_SSSDDD(agent,name,str,str2,str3,val,val2,val3) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3),jdouble(json,#val),jdouble(json,#val2),jdouble(json,#val3)))
#define IGUANA_DISPATCH_SSSIII(agent,name,str,str2,str3,val,val2,val3) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jstr(json,#str3),jint(json,#val),jint(json,#val2),jint(json,#val3)))
#define IGUANA_DISPATCH_SSH(agent,name,str,str2,hash) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jbits256(json,#hash)))
#define IGUANA_DISPATCH_SSHI(agent,name,str,str2,hash,val) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jbits256(json,#hash),juint(json,#val)))
#define IGUANA_DISPATCH_SSHII(agent,name,str,str2,hash,val,val2) else if ( strcmp(method,#name) == 0 ) return(agent ## _ ## name(IGUANA_ARGS,jstr(json,#str),jstr(json,#str2),jbits256(json,#hash),juint(json,#val),juint(json,#val2)))
@ -815,6 +826,9 @@ char *SuperNET_parser(struct supernet_info *myinfo,char *agent,char *method,cJSO
#define HASH_ARG IGUANA_DISPATCH_H
#define TWO_HASHES IGUANA_DISPATCH_HH
#define HASH_AND_ARRAY IGUANA_DISPATCH_HA
#define THREE_STRINGS_AND_THREE_INTS IGUANA_DISPATCH_SSSIII
#define THREE_STRINGS_AND_THREE_DOUBLES IGUANA_DISPATCH_SSSDDD
#define THREE_STRINGS_AND_DOUBLE IGUANA_DISPATCH_SSSD
#include "../includes/iguana_apideclares.h"
//#undef IGUANA_ARGS

2
iguana/iguana_peers.c

@ -711,7 +711,7 @@ uint32_t iguana_possible_peer(struct iguana_info *coin,char *ipaddr)
char checkaddr[64]; uint64_t ipbits; uint32_t now = (uint32_t)time(NULL); int32_t i,n; struct iguana_iAddr *iA;
if ( ipaddr != 0 )
{
printf("%p Q possible peer.%s\n",coin,ipaddr);
//printf("%p Q possible peer.%s\n",coin,ipaddr);
queue_enqueue("possibleQ",&coin->possibleQ,queueitem(ipaddr),1);
return((uint32_t)time(NULL));
}

5177
iguana/index7778.html

File diff suppressed because it is too large

3
iguana/main.c

@ -288,6 +288,7 @@ void iguana_main(void *arg)
iguana_chaingenesis(1,1317972665,0x1e0ffff0,2084524493,bits256_conv("97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9")); // LTC
mycalloc(0,0,0);
//exchanges777_init(0);
iguana_initQ(&helperQ,"helperQ");
OS_ensure_directory("confs");
OS_ensure_directory("DB");
@ -480,7 +481,7 @@ void iguana_main(void *arg)
iguana_launch(iguana_coinadd("BTCD"),"rpcloop",iguana_rpcloop,SuperNET_MYINFO(0),IGUANA_PERMTHREAD);
if ( coinargs != 0 )
iguana_launch(iguana_coinadd("BTCD"),"iguana_coins",iguana_coins,coinargs,IGUANA_PERMTHREAD);
else if ( 1 )
else if ( 0 )
{
#ifdef __APPLE__
sleep(1);

3456
iguana/orderbooks.h

File diff suppressed because it is too large

2
iguana/pangea_hand.c

@ -279,7 +279,7 @@ int32_t pangea_checkstart(struct supernet_info *myinfo,struct table_info *tp)
}
if ( matches == tp->G.numactive )
{
if ( time(NULL) > (tp->priv.myind + hand->startdecktime) )
if ( tp->priv.myind == pangea_slotA(tp) )
{
//if ( PANGEA_PAUSE > 0 )
// sleep(PANGEA_PAUSE);

13
includes/iguana_apideclares.h

@ -20,6 +20,19 @@ HASH_AND_INT(ramchain,getrawtransaction,txid,verbose);
HASH_ARG(ramchain,gettransaction,txid);
STRING_ARG(ramchain,decoderawtransaction,rawtx);
THREE_STRINGS_AND_THREE_INTS(InstantDEX,orderbook,exchange,base,rel,depth,allfields,invert);
THREE_STRINGS_AND_THREE_DOUBLES(InstantDEX,buy,exchange,base,rel,price,volume,dotrade);
THREE_STRINGS_AND_THREE_DOUBLES(InstantDEX,sell,exchange,base,rel,price,volume,dotrade);
THREE_STRINGS_AND_DOUBLE(InstantDEX,withdraw,exchange,base,destaddr,amount);
THREE_STRINGS(InstantDEX,apikeypair,exchange,apikey,apisecret);
THREE_STRINGS(InstantDEX,setuserid,exchange,userid,tradepassword);
THREE_STRINGS(InstantDEX,supports,exchange,base,rel);
TWO_STRINGS(InstantDEX,balance,exchange,base);
TWO_STRINGS(InstantDEX,orderstatus,exchange,orderid);
TWO_STRINGS(InstantDEX,cancelorder,exchange,orderid);
STRING_ARG(InstantDEX,openorders,exchange);
STRING_ARG(InstantDEX,tradehistory,exchange);
/*HASH_AND_ARRAY(pangea,userturn,tablehash,params);
HASH_AND_ARRAY(pangea,status,tableid,params);
HASH_AND_ARRAY(pangea,mode,tableid,params);

7
includes/iguana_apidefs.h

@ -24,6 +24,10 @@
#define IGUANA_CFUNC_SSHII(agent,name,str,str2,hash,val,val2) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,bits256 hash,int32_t val,int32_t val2)
#define IGUANA_CFUNC_SSHHII(agent,name,str,str2,hash,hash2,val,val2) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,bits256 hash,bits256 hash2,int32_t val,int32_t val2)
#define IGUANA_CFUNC_SSS(agent,name,str,str2,str3) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,char *str3)
#define IGUANA_CFUNC_SSSD(agent,name,str,str2,str3,val) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,char *str3,double val)
#define IGUANA_CFUNC_SSSDDD(agent,name,str,str2,str3,val,val2,val3) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,char *str3,double val,double val2,double val3)
#define IGUANA_CFUNC_SSSIII(agent,name,str,str2,str3,val,val2,val3) char *agent ## _ ## name(IGUANA_ARGS,char *str,char *str2,char *str3,int32_t val,int32_t val2,int32_t val3)
#define IGUANA_CFUNC_SI(agent,name,str,val) char *agent ## _ ## name(IGUANA_ARGS,char *str,int32_t val)
#define IGUANA_CFUNC_SII(agent,name,str,val,val2) char *agent ## _ ## name(IGUANA_ARGS,char *str,int32_t val,int32_t val2)
#define IGUANA_CFUNC_HI(agent,name,hash,val) char *agent ## _ ## name(IGUANA_ARGS,bits256 hash,int32_t val)
@ -75,3 +79,6 @@
#define HASH_ARG IGUANA_CFUNC_H
#define HASH_AND_ARRAY IGUANA_CFUNC_HA
#define TWO_HASHES IGUANA_CFUNC_HH
#define THREE_STRINGS_AND_THREE_INTS IGUANA_CFUNC_SSSIII
#define THREE_STRINGS_AND_THREE_DOUBLES IGUANA_CFUNC_SSSDDD
#define THREE_STRINGS_AND_DOUBLE IGUANA_CFUNC_SSSD

4
includes/iguana_apiundefs.h

@ -33,6 +33,10 @@
#undef HASH_ARG
#undef TWO_HASHES
#undef TWOSTRINGS_AND_TWOHASHES_AND_TWOINTS
#undef THREE_STRINGS_AND_THREE_INTS
#undef THREE_STRINGS_AND_THREE_DOUBLES
#undef THREE_STRINGS_AND_DOUBLE
#undef IGUANA_ARGS
#undef IGUANA_CALLARGS

Loading…
Cancel
Save