fcoin_ruby_client 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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