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.
- 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
|