fcoin_ruby_client 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/issue_template.md +12 -0
- data/.github/pull_request_template.md +12 -0
- data/.gitignore +13 -0
- data/.rspec +3 -0
- data/.rubocop.yml +12 -0
- data/.rubocop_todo.yml +431 -0
- data/.travis.yml +26 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +176 -0
- data/LICENSE.txt +21 -0
- data/README.md +204 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/fcoin +95 -0
- data/bin/setup +8 -0
- data/examples/cli/realtime_api.md +78 -0
- data/examples/cli/rest_api.md +149 -0
- data/examples/cli/setting.md +39 -0
- data/examples/realtime_api.rb +43 -0
- data/examples/rest_api.rb +47 -0
- data/fcoin_ruby_client.gemspec +39 -0
- data/lib/fcoin/api.rb +47 -0
- data/lib/fcoin/authorization.rb +83 -0
- data/lib/fcoin/cli/endpoint/accounts_task.rb +33 -0
- data/lib/fcoin/cli/endpoint/market_task.rb +98 -0
- data/lib/fcoin/cli/endpoint/orders_task.rb +196 -0
- data/lib/fcoin/cli/endpoint/public_task.rb +59 -0
- data/lib/fcoin/cli/realtime/endpoint_task.rb +107 -0
- data/lib/fcoin/cli.rb +77 -0
- data/lib/fcoin/client.rb +7 -0
- data/lib/fcoin/config/custom_settings.yml +171 -0
- data/lib/fcoin/config/settings.yml +10 -0
- data/lib/fcoin/configuration.rb +95 -0
- data/lib/fcoin/connection.rb +33 -0
- data/lib/fcoin/endpoint/accounts.rb +23 -0
- data/lib/fcoin/endpoint/market.rb +91 -0
- data/lib/fcoin/endpoint/orders.rb +171 -0
- data/lib/fcoin/endpoint/public.rb +51 -0
- data/lib/fcoin/endpoint/utility.rb +14 -0
- data/lib/fcoin/endpoint.rb +13 -0
- data/lib/fcoin/error.rb +4 -0
- data/lib/fcoin/faraday/fcoin_formatter.rb +17 -0
- data/lib/fcoin/formatter/base_formatter.rb +8 -0
- data/lib/fcoin/formatter/depth_formatter.rb +33 -0
- data/lib/fcoin/formatter/ticker_formatter.rb +34 -0
- data/lib/fcoin/formatter.rb +38 -0
- data/lib/fcoin/generators/locale.rb +18 -0
- data/lib/fcoin/generators/templates/locale/locales/en.yml +176 -0
- data/lib/fcoin/generators/templates/locale/locales/ja.yml +176 -0
- data/lib/fcoin/generators/templates/locale/locales/zh_CN.yml +176 -0
- data/lib/fcoin/generators/templates/validation/my_settings.yml +171 -0
- data/lib/fcoin/generators/validation.rb +18 -0
- data/lib/fcoin/realtime/api.rb +38 -0
- data/lib/fcoin/realtime/client.rb +9 -0
- data/lib/fcoin/realtime/endpoint.rb +160 -0
- data/lib/fcoin/realtime/formatter/base_formatter.rb +10 -0
- data/lib/fcoin/realtime/formatter/depth_formatter.rb +37 -0
- data/lib/fcoin/realtime/formatter/ticker_formatter.rb +36 -0
- data/lib/fcoin/realtime/formatter.rb +40 -0
- data/lib/fcoin/realtime/wss.rb +113 -0
- data/lib/fcoin/request.rb +73 -0
- data/lib/fcoin/validator/market_validator.rb +60 -0
- data/lib/fcoin/validator/orders/base_validator.rb +96 -0
- data/lib/fcoin/validator/orders/create_order_limit_validator.rb +54 -0
- data/lib/fcoin/validator/orders/create_order_market_validator.rb +95 -0
- data/lib/fcoin/validator/orders/order_list_validator.rb +33 -0
- data/lib/fcoin/validator/orders_validator.rb +69 -0
- data/lib/fcoin/validator/validator_utility.rb +24 -0
- data/lib/fcoin/validator.rb +58 -0
- data/lib/fcoin/version.rb +3 -0
- data/lib/fcoin.rb +11 -0
- 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,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,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
|