fcoin_ruby_client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.github/issue_template.md +12 -0
  3. data/.github/pull_request_template.md +12 -0
  4. data/.gitignore +13 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +12 -0
  7. data/.rubocop_todo.yml +431 -0
  8. data/.travis.yml +26 -0
  9. data/CHANGELOG.md +2 -0
  10. data/Gemfile +6 -0
  11. data/Gemfile.lock +176 -0
  12. data/LICENSE.txt +21 -0
  13. data/README.md +204 -0
  14. data/Rakefile +6 -0
  15. data/bin/console +14 -0
  16. data/bin/fcoin +95 -0
  17. data/bin/setup +8 -0
  18. data/examples/cli/realtime_api.md +78 -0
  19. data/examples/cli/rest_api.md +149 -0
  20. data/examples/cli/setting.md +39 -0
  21. data/examples/realtime_api.rb +43 -0
  22. data/examples/rest_api.rb +47 -0
  23. data/fcoin_ruby_client.gemspec +39 -0
  24. data/lib/fcoin/api.rb +47 -0
  25. data/lib/fcoin/authorization.rb +83 -0
  26. data/lib/fcoin/cli/endpoint/accounts_task.rb +33 -0
  27. data/lib/fcoin/cli/endpoint/market_task.rb +98 -0
  28. data/lib/fcoin/cli/endpoint/orders_task.rb +196 -0
  29. data/lib/fcoin/cli/endpoint/public_task.rb +59 -0
  30. data/lib/fcoin/cli/realtime/endpoint_task.rb +107 -0
  31. data/lib/fcoin/cli.rb +77 -0
  32. data/lib/fcoin/client.rb +7 -0
  33. data/lib/fcoin/config/custom_settings.yml +171 -0
  34. data/lib/fcoin/config/settings.yml +10 -0
  35. data/lib/fcoin/configuration.rb +95 -0
  36. data/lib/fcoin/connection.rb +33 -0
  37. data/lib/fcoin/endpoint/accounts.rb +23 -0
  38. data/lib/fcoin/endpoint/market.rb +91 -0
  39. data/lib/fcoin/endpoint/orders.rb +171 -0
  40. data/lib/fcoin/endpoint/public.rb +51 -0
  41. data/lib/fcoin/endpoint/utility.rb +14 -0
  42. data/lib/fcoin/endpoint.rb +13 -0
  43. data/lib/fcoin/error.rb +4 -0
  44. data/lib/fcoin/faraday/fcoin_formatter.rb +17 -0
  45. data/lib/fcoin/formatter/base_formatter.rb +8 -0
  46. data/lib/fcoin/formatter/depth_formatter.rb +33 -0
  47. data/lib/fcoin/formatter/ticker_formatter.rb +34 -0
  48. data/lib/fcoin/formatter.rb +38 -0
  49. data/lib/fcoin/generators/locale.rb +18 -0
  50. data/lib/fcoin/generators/templates/locale/locales/en.yml +176 -0
  51. data/lib/fcoin/generators/templates/locale/locales/ja.yml +176 -0
  52. data/lib/fcoin/generators/templates/locale/locales/zh_CN.yml +176 -0
  53. data/lib/fcoin/generators/templates/validation/my_settings.yml +171 -0
  54. data/lib/fcoin/generators/validation.rb +18 -0
  55. data/lib/fcoin/realtime/api.rb +38 -0
  56. data/lib/fcoin/realtime/client.rb +9 -0
  57. data/lib/fcoin/realtime/endpoint.rb +160 -0
  58. data/lib/fcoin/realtime/formatter/base_formatter.rb +10 -0
  59. data/lib/fcoin/realtime/formatter/depth_formatter.rb +37 -0
  60. data/lib/fcoin/realtime/formatter/ticker_formatter.rb +36 -0
  61. data/lib/fcoin/realtime/formatter.rb +40 -0
  62. data/lib/fcoin/realtime/wss.rb +113 -0
  63. data/lib/fcoin/request.rb +73 -0
  64. data/lib/fcoin/validator/market_validator.rb +60 -0
  65. data/lib/fcoin/validator/orders/base_validator.rb +96 -0
  66. data/lib/fcoin/validator/orders/create_order_limit_validator.rb +54 -0
  67. data/lib/fcoin/validator/orders/create_order_market_validator.rb +95 -0
  68. data/lib/fcoin/validator/orders/order_list_validator.rb +33 -0
  69. data/lib/fcoin/validator/orders_validator.rb +69 -0
  70. data/lib/fcoin/validator/validator_utility.rb +24 -0
  71. data/lib/fcoin/validator.rb +58 -0
  72. data/lib/fcoin/version.rb +3 -0
  73. data/lib/fcoin.rb +11 -0
  74. metadata +353 -0
@@ -0,0 +1,171 @@
1
+ ---
2
+ fcoin:
3
+ validation:
4
+ limit:
5
+ sell:
6
+ mainboard_A:
7
+ - { symbol: 'btcusdt', amount: { min: 1, max: 10000 }, price: { min: 1, max: 10000 } }
8
+ - { symbol: 'ethusdt', amount: { min: 0.001, max: 10000 }, price: { min: 1, max: 10000 } }
9
+ - { symbol: 'bchusdt', amount: { min: 0.001, max: 5000 }, price: { min: 1, max: 10000 } }
10
+ - { symbol: 'ltcusdt', amount: { min: 0.001, max: 40000 }, price: { min: 1, max: 10000 } }
11
+ - { symbol: 'etcusdt', amount: { min: 0.001, max: 400000 },price: { min: 1, max: 10000 } }
12
+ - { symbol: 'xrpusdt', amount: { min: 1, max: 10000 }, price: { min: 1, max: 10000 } }
13
+ mainboard_B:
14
+ - { symbol: 'ftusdt', amount: { min: 1, max: 10000 }, price: { min: 1, max: 10000 } }
15
+ - { symbol: 'ftbtc', amount: { min: 1, max: 10000 }, price: { min: 0.0000001, max: 10000 } }
16
+ - { symbol: 'fteth', amount: { min: 1, max: 10000 }, price: { min: 0.000001, max: 10000 } }
17
+ - { symbol: 'zipeth', amount: { min: 1, max: 10000 }, price: { min: 0.000001, max: 10000 } }
18
+ - { symbol: 'omgeth', amount: { min: 1, max: 10000 }, price: { min: 0.000001, max: 10000 } }
19
+ - { symbol: 'btmusdt',amount: { min: 1, max: 10000 }, price: { min: 1, max: 10000 } }
20
+ - { symbol: 'zrxeth', amount: { min: 1, max: 10000 }, price: { min: 0.000001, max: 10000 } }
21
+ - { symbol: 'bnbusdt',amount: { min: 1, max: 10000 }, price: { min: 0.000001, max: 10000 } }
22
+ - { symbol: 'zipusdt',amount: { min: 1, max: 10000 }, price: { min: 1, max: 10000 } }
23
+ - { symbol: 'fieth', amount: { min: 1, max: 10000 }, price: { min: 0.0000011, max: 10000 } }
24
+ - { symbol: 'fiusdt', amount: { min: 1, max: 10000 }, price: { min: 1, max: 10000 } }
25
+ gpm:
26
+ - { symbol: 'fcandyusdt', amount: { min: 0.001, max: 10000 }, price: { min: 1, max: 10000 } }
27
+ - { symbol: 'icxeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
28
+ - { symbol: 'zileth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
29
+ - { symbol: 'aeeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
30
+ - { symbol: '777eth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
31
+ - { symbol: 'guseth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
32
+ - { symbol: 'cccxeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
33
+ - { symbol: 'bancaeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
34
+ - { symbol: 'praeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
35
+ - { symbol: 'dcceth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
36
+ - { symbol: 'ssseth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
37
+ - { symbol: 'mdteth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
38
+ - { symbol: 'tsteth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
39
+ - { symbol: 'pmdeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
40
+ - { symbol: 'rteeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
41
+ - { symbol: 'xpseth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
42
+ - { symbol: 'tcteth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
43
+ - { symbol: 'dwseth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
44
+ - { symbol: 'ngoteth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
45
+ - { symbol: 'ateth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
46
+ - { symbol: 'soceth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
47
+ - { symbol: 'blzeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
48
+ - { symbol: 'ocneth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
49
+ - { symbol: 'datxeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
50
+ - { symbol: 'gtceth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
51
+ - { symbol: 'leteth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
52
+ - { symbol: 'dageth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
53
+ - { symbol: 'yeeeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
54
+ - { symbol: 'aaaeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
55
+ - { symbol: 'nceth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
56
+ - { symbol: 'arpeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
57
+ - { symbol: 'grameth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
58
+ - { symbol: 'ifoodeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
59
+ - { symbol: 'hpceth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
60
+ - { symbol: 'sgcceth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
61
+ - { symbol: '3dbeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
62
+ - { symbol: 'xmxeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
63
+ - { symbol: 'rcteth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
64
+ - { symbol: 'citeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
65
+ - { symbol: 'eeseth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
66
+ - { symbol: 'faireth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
67
+ - { symbol: 'brmeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
68
+ - { symbol: 'sdaeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
69
+ - { symbol: 'cbreth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
70
+ buy:
71
+ mainboard_A:
72
+ - { symbol: 'btcusdt', amount: { min: 1, max: 10000 }, price: { min: 1, max: 10000 } }
73
+ - { symbol: 'ethusdt', amount: { min: 0.001, max: 10000 }, price: { min: 1, max: 10000 } }
74
+ - { symbol: 'bchusdt', amount: { min: 0.001, max: 5000 }, price: { min: 1, max: 10000 } }
75
+ - { symbol: 'ltcusdt', amount: { min: 0.001, max: 40000 }, price: { min: 1, max: 10000 } }
76
+ - { symbol: 'etcusdt', amount: { min: 0.001, max: 400000 },price: { min: 1, max: 10000 } }
77
+ - { symbol: 'xrpusdt', amount: { min: 1, max: 10000 }, price: { min: 1, max: 10000 } }
78
+ mainboard_B:
79
+ - { symbol: 'ftusdt', amount: { min: 1, max: 10000 }, price: { min: 1, max: 10000 } }
80
+ - { symbol: 'ftbtc', amount: { min: 1, max: 10000 }, price: { min: 0.0000001, max: 10000 } }
81
+ - { symbol: 'fteth', amount: { min: 1, max: 10000 }, price: { min: 0.000001, max: 10000 } }
82
+ - { symbol: 'zipeth', amount: { min: 1, max: 10000 }, price: { min: 0.000001, max: 10000 } }
83
+ - { symbol: 'omgeth', amount: { min: 1, max: 10000 }, price: { min: 0.000001, max: 10000 } }
84
+ - { symbol: 'btmusdt',amount: { min: 1, max: 10000 }, price: { min: 1, max: 10000 } }
85
+ - { symbol: 'zrxeth', amount: { min: 1, max: 10000 }, price: { min: 0.000001, max: 10000 } }
86
+ - { symbol: 'bnbusdt',amount: { min: 1, max: 10000 }, price: { min: 0.000001, max: 10000 } }
87
+ - { symbol: 'zipusdt',amount: { min: 1, max: 10000 }, price: { min: 1, max: 10000 } }
88
+ - { symbol: 'fieth', amount: { min: 1, max: 10000 }, price: { min: 0.0000011, max: 10000 } }
89
+ - { symbol: 'fiusdt', amount: { min: 1, max: 10000 }, price: { min: 1, max: 10000 } }
90
+ gpm:
91
+ - { symbol: 'fcandyusdt', amount: { min: 0.001, max: 10000 }, price: { min: 1, max: 10000 } }
92
+ - { symbol: 'icxeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
93
+ - { symbol: 'zileth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
94
+ - { symbol: 'aeeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
95
+ - { symbol: '777eth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
96
+ - { symbol: 'guseth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
97
+ - { symbol: 'cccxeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
98
+ - { symbol: 'bancaeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
99
+ - { symbol: 'praeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
100
+ - { symbol: 'dcceth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
101
+ - { symbol: 'ssseth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
102
+ - { symbol: 'mdteth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
103
+ - { symbol: 'tsteth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
104
+ - { symbol: 'pmdeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
105
+ - { symbol: 'rteeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
106
+ - { symbol: 'xpseth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
107
+ - { symbol: 'tcteth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
108
+ - { symbol: 'dwseth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
109
+ - { symbol: 'ngoteth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
110
+ - { symbol: 'ateth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
111
+ - { symbol: 'soceth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
112
+ - { symbol: 'blzeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
113
+ - { symbol: 'ocneth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
114
+ - { symbol: 'datxeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
115
+ - { symbol: 'gtceth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
116
+ - { symbol: 'leteth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
117
+ - { symbol: 'dageth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
118
+ - { symbol: 'yeeeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
119
+ - { symbol: 'aaaeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
120
+ - { symbol: 'nceth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
121
+ - { symbol: 'arpeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
122
+ - { symbol: 'grameth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
123
+ - { symbol: 'ifoodeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
124
+ - { symbol: 'hpceth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
125
+ - { symbol: 'sgcceth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
126
+ - { symbol: '3dbeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
127
+ - { symbol: 'xmxeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
128
+ - { symbol: 'rcteth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
129
+ - { symbol: 'citeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
130
+ - { symbol: 'eeseth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
131
+ - { symbol: 'faireth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
132
+ - { symbol: 'brmeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
133
+ - { symbol: 'sdaeth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
134
+ - { symbol: 'cbreth', amount: { min: 0.01, max: 10000 }, price: { min: 0.000001, max: 10000 } }
135
+ market:
136
+ valid:
137
+ sell:
138
+ mainboard_A:
139
+ - { symbol: 'btcusdt', amount: { min: 1, max: 10000 } }
140
+ - { symbol: 'ethusdt', amount: { min: 0.001, max: 10000 } }
141
+ - { symbol: 'bchusdt', amount: { min: 0.001, max: 5000 } }
142
+ - { symbol: 'ltcusdt', amount: { min: 0.001, max: 40000 } }
143
+ - { symbol: 'etcusdt', amount: { min: 0.001, max: 400000 } }
144
+ - { symbol: 'xrpusdt', amount: { min: 1, max: 10000 } }
145
+ mainboard_B:
146
+ gpm:
147
+ buy:
148
+ mainboard_A:
149
+ - { symbol: 'btcusdt', total: { min: 1, max: 10000 } }
150
+ - { symbol: 'ethusdt', total: { min: 0.001, max: 10000 } }
151
+ - { symbol: 'bchusdt', total: { min: 0.001, max: 5000 } }
152
+ - { symbol: 'ltcusdt', total: { min: 0.001, max: 40000 } }
153
+ - { symbol: 'etcusdt', total: { min: 0.001, max: 400000 } }
154
+ - { symbol: 'xrpusdt', total: { min: 1, max: 10000 } }
155
+ mainboard_B:
156
+ gpm:
157
+ invalid:
158
+ sell:
159
+ mainboard_A:
160
+ mainboard_B:
161
+ - fiusdt
162
+ - fieth
163
+ gpm:
164
+ - fcandyusdt
165
+ buy:
166
+ mainboard_A:
167
+ mainboard_B:
168
+ - fiusdt
169
+ - fieth
170
+ gpm:
171
+ - fcandyusdt
@@ -0,0 +1,18 @@
1
+ require 'thor'
2
+ require 'thor/group'
3
+
4
+ module Fcoin
5
+ module Generators
6
+ class Validation < Thor::Group
7
+ include Thor::Actions
8
+
9
+ def self.source_root
10
+ File.dirname(__FILE__) + '/templates/validation'
11
+ end
12
+
13
+ def copy_files
14
+ directory '.'
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,38 @@
1
+ require_relative 'endpoint'
2
+ require_relative '../validator'
3
+
4
+ module Fcoin
5
+ module RealTime
6
+ class API
7
+ include EndPoint
8
+
9
+ attr_accessor :callbacks, :topics
10
+
11
+ # @param [Hash] options the options to setting Fcoin Setting. For example, Validation and so on.
12
+ # @option options [String] :adapter(Faraday.default_adapter)
13
+ # @option options [String] :endpoint(https://api.fcoin.com/v2/) REST API endpoint
14
+ # @option options [String] :wss_endpoint(wss://api.fcoin.com/v2/ws) Websocket endpoint
15
+ # @option options [String] :user_agent
16
+ # @option options [String] :proxy(nil)
17
+ # @option options [String] :ca_path
18
+ # @option options [String] :ca_file
19
+ # @option options [Array<Faraday::Middleware>] :middlewares request faraday middlewares
20
+ # @option options [String] :api_key
21
+ # @option options [String] :secret_key
22
+ # @option options [Boolean] :skip_validation(true)
23
+ # @option options [String] :validation_setting_path configuration file path for validation
24
+ def initialize(options={})
25
+ merged_options = Fcoin.options.merge(options)
26
+ Configuration::VALID_OPTIONS_KEYS.each do |key|
27
+ send("#{key}=", merged_options[key])
28
+ end
29
+ self.callbacks = {}
30
+ self.topics = []
31
+ end
32
+
33
+ private
34
+
35
+ attr_accessor :wss_endpoint, *Configuration::VALID_OPTIONS_KEYS
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,9 @@
1
+ require_relative 'api'
2
+
3
+ module Fcoin
4
+ module RealTime
5
+ # @see API
6
+ class Client < API
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,160 @@
1
+ require_relative 'wss'
2
+
3
+ # Scope Fcoin::RealTime::API
4
+ module Fcoin
5
+ module RealTime
6
+ module EndPoint
7
+ include Fcoin::RealTime::WSS
8
+ # Subscribe to ticker information
9
+ #
10
+ # @note Please be sure to call client.subscribe at the end
11
+ #
12
+ # @example Subscribe to ticker information of ethusdt
13
+ # client = Fcoin::Client.new.realtime
14
+ # # client = Fcoin::RealTime::Client.new
15
+ # client.on_ticker(symbol: :ethusdt) do |data|
16
+ # puts data
17
+ # end
18
+ # client.subscribe
19
+ # #=> {"ticker"=>{"latest_price"=>464.14, "most_recent_trade_vol"=>0.0046, "max_buy_price"=>464.12, "max_buy_amount"=>0.8, "min_sell_price"=>464.14, "min_sell_amount"=>0.5154, "trade_price_yesterday"=>468.09, "highest_price_today"=>471.79, "lowest_price_today"=>461.29, "symbol_base_vol_today"=>51512.752914829, "symbol_base_price_today"=>23993418.702288836}, "type"=>"ticker.ethusdt", "seq"=>100851177}
20
+ # #=> ...
21
+ #
22
+ #
23
+ # @see https://developer.fcoin.com/zh.html#ticker
24
+ # @raise [ArgumentError] If the symbol does not have.
25
+ # @param symbol [String or Symbol] Transaction pair
26
+ # @yieldreturn Process block arguments
27
+ def on_ticker(symbol:, &block)
28
+ on("ticker.#{symbol}", nil, &block)
29
+ end
30
+
31
+ # Subscribe to depth information
32
+ #
33
+ # @note Please be sure to call client.subscribe at the end
34
+ #
35
+ # @example Subscribe to depth information of ethusdt specified by L20 level
36
+ # client = Fcoin::Client.new.realtime
37
+ # # client = Fcoin::RealTime::Client.new
38
+ # client.on_depth(symbol: :ethusdt, level: :L20) do |data|
39
+ # puts data
40
+ # end
41
+ # client.subscribe
42
+ # #=> {"bids"=>[{"price"=>460.49, "amount"=>0.1892}, {"price"=>460.48, "amount"=>0.05}, {"price"=>460.43, "amount"=>0.01}, {"price"=>460.41, "amount"=>0.6826}, {"price"=>460.4, "amount"=>0.01}, {"price"=>460.39, "amount"=>0.0203}, {"price"=>460.37, "amount"=>0.0174}, {"price"=>460.34, "amount"=>0.035}, {"price"=>460.31, "amount"=>0.5836}, {"price"=>460.28, "amount"=>0.2341}, {"price"=>460.27, "amount"=>0.01}, {"price"=>460.26, "amount"=>0.2984}, {"price"=>460.25, "amount"=>0.03}, {"price"=>460.22, "amount"=>0.0029}, {"price"=>460.21, "amount"=>0.11}, {"price"=>460.2, "amount"=>0.02}, {"price"=>460.19, "amount"=>0.02}, {"price"=>460.14, "amount"=>0.4256}, {"price"=>460.12, "amount"=>2.6374}, {"price"=>460.11, "amount"=>0.1}], "asks"=>[{"price"=>460.5, "amount"=>1.3892}, {"price"=>460.52, "amount"=>0.0851}, {"price"=>460.55, "amount"=>0.02}, {"price"=>460.57, "amount"=>0.0126}, {"price"=>460.6, "amount"=>23.664678116}, {"price"=>460.63, "amount"=>0.006}, {"price"=>460.64, "amount"=>0.0174}, {"price"=>460.65, "amount"=>0.03}, {"price"=>460.66, "amount"=>0.05}, {"price"=>460.67, "amount"=>0.04}, {"price"=>460.68, "amount"=>0.01}, {"price"=>460.7, "amount"=>0.02}, {"price"=>460.72, "amount"=>0.0528}, {"price"=>460.73, "amount"=>0.07}, {"price"=>460.74, "amount"=>0.12}, {"price"=>460.75, "amount"=>0.03}, {"price"=>460.76, "amount"=>0.01}, {"price"=>460.77, "amount"=>0.03}, {"price"=>460.78, "amount"=>0.01}, {"price"=>460.79, "amount"=>0.05}], "ts"=>1532951053012, "seq"=>101655772, "type"=>"depth.L20.ethusdt"}
43
+ # #=> ...
44
+ #
45
+ #
46
+ # @see https://developer.fcoin.com/zh.html#50f4407ea4
47
+ # @raise [ArgumentError] If the symbol or level does not have.
48
+ # @raise [InvalidValueError] If symbol or level is invalid.
49
+ # @param symbol [String or Symbol] Transaction pair
50
+ # @param level [String or Symbol] Level of depth chart. level must be included in [L20, L40, full]
51
+ # @yieldreturn Process block arguments
52
+ def on_depth(symbol:, level:, &block)
53
+ validator = Fcoin::Validator.new(symbol: symbol, level: level, method_name: __method__)
54
+ if skip_validation || validator.valid?
55
+ on("depth.#{level}.#{symbol}", nil, &block)
56
+ else
57
+ raise InvalidValueError.new(validator.messages)
58
+ end
59
+ end
60
+
61
+ # Subscribe to trade information
62
+ #
63
+ # @note Please be sure to call client.subscribe at the end
64
+ #
65
+ # @example Subscribe to trade information of ethusdt limit 5
66
+ # client = Fcoin::Client.new.realtime
67
+ # # client = Fcoin::RealTime::Client.new
68
+ # client.on_trade(symbol: :ethusdt, limit: 5) do |data|
69
+ # puts data
70
+ # end
71
+ # client.subscribe
72
+ # #=> {"amount"=>0.002, "type"=>"trade.ethusdt", "ts"=>1532951759502, "id"=>101661132001, "side"=>"sell", "price"=>461.31}
73
+ # #=> {"amount"=>0.0063, "type"=>"trade.ethusdt", "ts"=>1532951771509, "id"=>101661197000, "side"=>"buy", "price"=>461.33}
74
+ # #=> ...
75
+ #
76
+ #
77
+ # @see https://developer.fcoin.com/zh.html#6477a1394e
78
+ # @raise [ArgumentError] If the symbol or level does not have.
79
+ # @raise [InvalidValueError] If symbol or level is invalid.
80
+ # @param symbol [String or Symbol] Transaction pair
81
+ # @param limit [Integer]
82
+ # @yieldreturn Process block arguments
83
+ def on_trade(symbol:, limit: 20, &block)
84
+ on("trade.#{symbol}", limit, &block)
85
+ end
86
+
87
+ # Subscribe to candle information
88
+ #
89
+ # @note Please be sure to call client.subscribe at the end
90
+ #
91
+ # @example Subscribe to candle information of ethusdt limit 5
92
+ # client = Fcoin::Client.new.realtime
93
+ # # client = Fcoin::RealTime::Client.new
94
+ # client.on_candle(symbol: :ethusdt, resolution: :MN, limit: 5) do |data|
95
+ # puts data
96
+ # end
97
+ # client.subscribe
98
+ # #=> {"open"=>449.1, "type"=>"candle.MN.ethusdt", "close"=>461.52, "high"=>516.09, "quote_vol"=>1440332504.2648032, "id"=>1530374400, "count"=>6300632, "low"=>418.29, "seq"=>10166589200000, "base_vol"=>3122587.167240264}
99
+ # #=> {"open"=>449.1, "type"=>"candle.MN.ethusdt", "close"=>461.52, "high"=>516.09, "quote_vol"=>1440332527.3408031, "id"=>1530374400, "count"=>6300633, "low"=>418.29, "seq"=>10166601500000, "base_vol"=>3122587.217240264}
100
+ # #=> ...
101
+ #
102
+ #
103
+ # @see https://developer.fcoin.com/zh.html#candle
104
+ # @raise [ArgumentError] If the symbol or resolution does not have.
105
+ # @raise [InvalidValueError] If symbol or resolution is invalid.
106
+ # @param symbol [String or Symbol] Transaction pair
107
+ # @param resolution [String or Symbol] period of candles chart. resolution must be included in [M1, M3, M5, M15, M30, H1, H4, H6, D1, W1, MN]
108
+ # @param limit [Integer]
109
+ # @yieldreturn Process block arguments
110
+ def on_candle(symbol:, resolution:, limit: 20, &block)
111
+ validator = Fcoin::Validator.new(symbol: symbol, resolution: resolution, method_name: __method__)
112
+ if skip_validation || validator.valid?
113
+ on("candle.#{resolution}.#{symbol}", limit, &block)
114
+ else
115
+ raise InvalidValueError.new(validator.messages)
116
+ end
117
+ end
118
+
119
+ # Subscribe to topics
120
+ #
121
+ # @note Please be sure to call client.subscribe at the end
122
+ #
123
+ # @example Subscribe to topics
124
+ # client = Fcoin::Client.new.realtime
125
+ # # client = Fcoin::RealTime::Client.new
126
+ # client.on_ticker(symbol: :ethusdt) do
127
+ # end
128
+ # client.on_topics do |data|
129
+ # puts data
130
+ # end
131
+ # client.subscribe
132
+ # #=> {"id"=>"f44a05d5-9a10-4fed-8719-6b8269cc13ce", "type"=>"topics", "topics"=>["ticker.ethusdt"]}
133
+ #
134
+ #
135
+ # @yieldreturn Process block arguments
136
+ def on_topics(&block)
137
+ on('topics', nil, &block)
138
+ end
139
+
140
+ # Subscribe to server time
141
+ #
142
+ # @note Please be sure to call client.subscribe at the end
143
+ #
144
+ # @example Subscribe to Subscribe to server time
145
+ # client = Fcoin::Client.new.realtime
146
+ # # client = Fcoin::RealTime::Client.new
147
+ # client.on_hello do |data|
148
+ # puts data
149
+ # end
150
+ # client.subscribe
151
+ # #=> {"type"=>"hello", "ts"=>1532953247264}
152
+ #
153
+ #
154
+ # @yieldreturn Process block arguments
155
+ def on_hello(&block)
156
+ on('hello', nil, &block)
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,10 @@
1
+ module Fcoin
2
+ module RealTime
3
+ class BaseFormatter
4
+ # @abstract Subclass and override {#fromatted_data} to implement
5
+ def formatted_data
6
+ raise 'Please be implemented in inheriting.'
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,37 @@
1
+ require_relative 'base_formatter'
2
+ require 'active_support'
3
+ require 'active_support/core_ext'
4
+
5
+ module Fcoin
6
+ module RealTime
7
+ class DepthFormatter < BaseFormatter
8
+
9
+ attr_accessor :data
10
+
11
+ def initialize(data)
12
+ self.data = data
13
+ end
14
+
15
+ # Format response data for JSON
16
+ #
17
+ # @return [Hash]
18
+ def formatted_data
19
+ self.data['bids'] = adjusted('bids')
20
+ self.data['asks'] = adjusted('asks')
21
+ data
22
+ end
23
+
24
+ private
25
+
26
+ def adjusted(type)
27
+ orders = data[type].dup
28
+ orders.in_groups_of(2).map do |order|
29
+ {
30
+ "price" => order[0],
31
+ "amount" => order[1]
32
+ }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,36 @@
1
+ require_relative 'base_formatter'
2
+
3
+ module Fcoin
4
+ module RealTime
5
+ class TickerFormatter < BaseFormatter
6
+
7
+ attr_accessor :data
8
+
9
+ def initialize(data)
10
+ self.data = data
11
+ end
12
+
13
+ # Format response data for JSON
14
+ #
15
+ # @return [Hash]
16
+ def formatted_data
17
+ # https://developer.fcoin.com/en.html
18
+ ticker = data['ticker'].dup
19
+ self.data['ticker'] = {
20
+ "latest_price" => ticker[0],
21
+ "most_recent_trade_vol" => ticker[1],
22
+ "max_buy_price" => ticker[2],
23
+ "max_buy_amount" => ticker[3],
24
+ "min_sell_price" => ticker[4],
25
+ "min_sell_amount" => ticker[5],
26
+ "trade_price_yesterday" => ticker[6],
27
+ "highest_price_today" => ticker[7],
28
+ "lowest_price_today" => ticker[8],
29
+ "symbol_base_vol_today" => ticker[9],
30
+ "symbol_base_price_today" => ticker[10]
31
+ }
32
+ data
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,40 @@
1
+ require_relative 'formatter/ticker_formatter.rb'
2
+ require_relative 'formatter/depth_formatter.rb'
3
+
4
+ module Fcoin
5
+ module RealTime
6
+ class Formatter
7
+ def initialize(data)
8
+ self.data = data
9
+ end
10
+
11
+ # Format data
12
+ def formatted_data
13
+ formatter.present? ? formatter.formatted_data : data
14
+ end
15
+
16
+ private
17
+
18
+ attr_accessor :data
19
+
20
+ def formatter
21
+ if use_formatter?(data)
22
+ case data["type"]
23
+ when /ticker/
24
+ TickerFormatter.new(data)
25
+ when /depth/
26
+ DepthFormatter.new(data)
27
+ else
28
+ nil
29
+ end
30
+ else
31
+ nil
32
+ end
33
+ end
34
+
35
+ def use_formatter?(data)
36
+ data['type'].present?
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,113 @@
1
+ require 'faye/websocket'
2
+ require 'eventmachine'
3
+ require_relative 'formatter'
4
+
5
+ # Scope Fcoin::RealTime::API
6
+ module Fcoin
7
+ module RealTime
8
+ module WSS
9
+ # Subscribe to the channel that you have added to the topics
10
+ #
11
+ # @note Please subscribe to the channel by calling client.on_hello(&block) for the first time
12
+ #
13
+ # @example Subscribe to Subscribe to server time
14
+ # client = Fcoin::Client.new.realtime
15
+ # # client = Fcoin::RealTime::Client.new
16
+ # client.on_hello do |data|
17
+ # puts data
18
+ # end
19
+ # client.subscribe
20
+ # #=> {"type"=>"hello", "ts"=>1532953247264}
21
+ def subscribe
22
+ EM.run do
23
+ wss = Faye::WebSocket::Client.new(wss_endpoint)
24
+
25
+ wss.on(:open) do |handshake|
26
+ self.topics.each do |args|
27
+ wss.send(valid_payload(args))
28
+ end
29
+ end
30
+
31
+ wss.on(:message) do |event|
32
+ data = JSON.parse(event.data)
33
+ topic = data["type"]
34
+ formatter = Fcoin::RealTime::Formatter.new(data)
35
+ call_callbacks(topic, formatter.formatted_data)
36
+ end
37
+
38
+ wss.on(:close) do |event|
39
+ call_callbacks(:close)
40
+ EM.stop
41
+ end
42
+
43
+ wss.on(:error) do |event|
44
+ call_callbacks(:error)
45
+ EM.stop
46
+ end
47
+
48
+ # hit Control + C to stop
49
+ Signal.trap("INT") { EM.stop }
50
+ Signal.trap("TERM") { EM.stop }
51
+ end
52
+ end
53
+
54
+ private
55
+ # Subscribe to topic
56
+ #
57
+ # @param topic [String or Symbol] Channel you want to subscribe to
58
+ # @param limit [Integer]
59
+ def on(topic, limit=nil, &block)
60
+ self.topics << { topic: topic, limit: limit }
61
+ self.callbacks[topic] ||= []
62
+ self.callbacks[topic] << block if block_given?
63
+ end
64
+
65
+ # Subscribe topic?
66
+ #
67
+ # @param topic [String] Channel you want to subscribe to
68
+ def on?(topic)
69
+ topic.present? && callbacks[topic].present?
70
+ end
71
+
72
+ # call callbacks
73
+ #
74
+ # @param topic [String] Channel you want to subscribe to
75
+ # @param data [Hash] Data sent from subscribed channel
76
+ def call_callbacks(topic, data={})
77
+ return unless on?(topic)
78
+ callbacks[topic].each do |callback|
79
+ callback.call formatted(data)
80
+ end
81
+ end
82
+
83
+ # change the output format of the body
84
+ #
85
+ # @param data [Hash]
86
+ # @return [Hash or JSON]
87
+ def formatted(data)
88
+ case format_type
89
+ when :json
90
+ data.to_json
91
+ when :hash
92
+ data
93
+ else
94
+ raise "format_type is #{format_type}. format_type must be included in [:json, :hash]."
95
+ end
96
+ end
97
+
98
+ # Prepare a valid payload
99
+ #
100
+ # @param args [Hash] Parameters to send to subscribed channel
101
+ def valid_payload(args)
102
+ topic = args[:topic]
103
+ limit = args[:limit]
104
+ payload = if limit.present?
105
+ { cmd: :sub, args: [topic, limit], id: SecureRandom.uuid }
106
+ else
107
+ { cmd: :sub, args: [topic], id: SecureRandom.uuid }
108
+ end
109
+ JSON.dump(payload)
110
+ end
111
+ end
112
+ end
113
+ end