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,73 @@
1
+ require_relative 'authorization'
2
+ require_relative 'formatter'
3
+
4
+ # Scope Fcoin::API
5
+ module Fcoin
6
+ module Request
7
+ # Perform an HTTP GET request
8
+ def get(path, auth=true, payload={})
9
+ request(:get, path, auth, payload)
10
+ end
11
+
12
+ # Perform an HTTP POST request
13
+ def post(path, auth=true, payload={})
14
+ request(:post, path, auth, payload)
15
+ end
16
+
17
+ # Perform an HTTP PUT request
18
+ def put(path, auth=true, payload={})
19
+ request(:put, path, auth, payload)
20
+ end
21
+
22
+ # Perform an HTTP DELETE request
23
+ def delete(path, auth=true, payload={})
24
+ request(:delete, path, auth, payload)
25
+ end
26
+
27
+ private
28
+
29
+ # Perform an HTTP request
30
+ def request(http_method, path, auth, payload)
31
+ response = connection.send(http_method) do |request|
32
+ required = {
33
+ http_method: http_method,
34
+ path: path,
35
+ payload: payload,
36
+ endpoint: endpoint,
37
+ api_key: api_key,
38
+ secret_key: secret_key
39
+ }
40
+
41
+ if auth
42
+ auth = Fcoin::Authorization.new(required)
43
+ request.headers.merge!(auth.original_headers)
44
+ end
45
+
46
+ case http_method
47
+ when :get, :delete
48
+ request.url(path, payload)
49
+ when :post, :put
50
+ request.path = path
51
+ request.body = payload unless payload.empty?
52
+ end
53
+ end
54
+
55
+ return formatted(response.body)
56
+ end
57
+
58
+ # change the output format of the body
59
+ #
60
+ # @param body [Hash]
61
+ # @return [Hash or JSON]
62
+ def formatted(body)
63
+ case format_type
64
+ when :json
65
+ body.to_json
66
+ when :hash
67
+ body
68
+ else
69
+ raise "format_type is #{format_type}. format_type must be included in [:json, :hash]."
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,60 @@
1
+ require_relative 'validator_utility'
2
+
3
+ module Fcoin
4
+ class MarketValidator
5
+ include ValidatorUtility
6
+
7
+ # @params params [Hash] Parameter you want to verify including the called method name
8
+ # @option params :level [String or Symbol] Level of depth chart
9
+ # @option params :resolution [String or Symbol] period of Candles Chart
10
+ # @option params :method_name [String or Symbol] invoked method name
11
+ def initialize(params)
12
+ self.level = params[:level]
13
+ self.resolution = params[:resolution]
14
+ self.method_name = params[:method_name]
15
+ end
16
+
17
+ # Validate according to method_name
18
+ def valid?
19
+ case method_name
20
+ when /market_depth|on_depth/
21
+ valid_level?
22
+ when /market_candles|on_candle/
23
+ valid_resolution?
24
+ end
25
+ end
26
+
27
+ # Error message when invalid
28
+ def messages
29
+ return {} if valid?
30
+ results = []
31
+ case method_name
32
+ when /market_depth|on_depth/
33
+ results << includes_error_message(level, :level, valid_levels) unless valid_level?
34
+ when /market_candles|on_candle/
35
+ results << includes_error_message(resolution, :resolution, valid_resolutions) unless valid_resolution?
36
+ end
37
+ results.compact&.each_with_object({}) { |message, data| data.merge!(message) }
38
+ end
39
+
40
+ private
41
+
42
+ attr_accessor :level, :resolution, :method_name
43
+
44
+ def valid_level?
45
+ level.to_s.in? valid_levels
46
+ end
47
+
48
+ def valid_resolution?
49
+ resolution.to_s.in? valid_resolutions
50
+ end
51
+
52
+ def valid_levels
53
+ ::Settings.fcoin.validation.params.level
54
+ end
55
+
56
+ def valid_resolutions
57
+ ::Settings.fcoin.validation.params.resolution
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,96 @@
1
+ module Fcoin
2
+ module Orders
3
+ class BaseValidator
4
+
5
+ # @param params [Hash] Parameter you want to verify including the called method name
6
+ # @option params :symbol [String or Symbol] Transaction pair
7
+ # @option params :side [String or Symbol] Direction of the transaction
8
+ # @option params :price [Float]
9
+ # @option params :total [Float]
10
+ # @option params :amount [Float]
11
+ # @option params :states [String] Order state
12
+ def initialize(params)
13
+ self.symbol = params[:symbol]
14
+ self.side = params[:side]
15
+ self.price = params[:price]
16
+ self.total = params[:total]
17
+ self.amount = params[:amount]
18
+ self.states = params[:states]
19
+ end
20
+
21
+ # Validate according to method_name
22
+ # @abstract Subclass and override {#valid?} to implement
23
+ def valid?
24
+ raise 'Please be implemented in inheriting.'
25
+ end
26
+
27
+ # Error message when invalid
28
+ # @abstract Subclass and override {#messages} to implement
29
+ def messages
30
+ raise 'Please be implemented in inheriting.'
31
+ end
32
+
33
+ private
34
+
35
+ attr_accessor :symbol, :side, :type, :price, :total, :amount, :states
36
+
37
+ def valid_symbol?
38
+ symbol.present?
39
+ end
40
+
41
+ def valid_side?
42
+ side.to_s.in? valid_sides
43
+ end
44
+
45
+ def valid_type?
46
+ type.to_s.in? valid_types
47
+ end
48
+
49
+ def valid_states?
50
+ states_arr = states.to_s.gsub(' ','')&.split(',')
51
+ states_arr.present? && states_arr.map { |state| state.in? valid_states }.all?
52
+ end
53
+
54
+ def valid_price?
55
+ price.present? && price.between?(min(:price), max(:price))
56
+ end
57
+
58
+ def valid_total?
59
+ total.present? && total.between?(min(:total), max(:total))
60
+ end
61
+
62
+ def valid_amount?
63
+ amount.present? && amount.between?(min(:amount), max(:amount))
64
+ end
65
+
66
+ def min(type)
67
+ valid_symbol_setting_exist? ? valid_symbols[symbol][type].to_h[:min] : 0
68
+ end
69
+
70
+ def max(type)
71
+ valid_symbol_setting_exist? ? valid_symbols[symbol][type].to_h[:max] : 0
72
+ end
73
+
74
+ def valid_symbol_setting_exist?
75
+ valid_symbols[symbol].present?
76
+ end
77
+
78
+ def valid_sides
79
+ ::Settings.fcoin.validation.params.side
80
+ end
81
+
82
+ def valid_types
83
+ ::Settings.fcoin.validation.params.type
84
+ end
85
+
86
+ def valid_states
87
+ ::Settings.fcoin.validation.params.states
88
+ end
89
+
90
+ # @abstract Subclass and override {#valid_symbols} to implement
91
+ def valid_symbols
92
+ raise 'Please be implemented in inheriting.'
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,54 @@
1
+ require_relative 'base_validator'
2
+ require_relative '../validator_utility'
3
+
4
+ module Fcoin
5
+ module Orders
6
+ class CreateOrderLimitValidator < BaseValidator
7
+ include ValidatorUtility
8
+
9
+ # @param params [Hash] Parameter you want to verify including the called method name
10
+ # @option params :symbol [String or Symbol] Transaction pair
11
+ # @option params :side [String or Symbol] Direction of the transaction
12
+ # @option params :price [Float]
13
+ # @option params :amount [Float]
14
+ def initialize(params)
15
+ self.symbol = params[:symbol]
16
+ self.side = params[:side]
17
+ self.price = params[:price]
18
+ self.amount = params[:amount]
19
+ end
20
+
21
+ # Validate according to method_name
22
+ def valid?
23
+ if valid_symbol_setting_exist?
24
+ valid_price? && valid_amount?
25
+ else
26
+ valid_symbol? && valid_side?
27
+ end
28
+ end
29
+
30
+ # Error message when invalid
31
+ def messages
32
+ return {} if valid?
33
+ results = []
34
+
35
+ results << presence_error_message(symbol, :symbol) unless valid_symbol?
36
+ results << includes_error_message(side, :side, valid_sides) unless valid_side?
37
+ if valid_symbol_setting_exist?
38
+ results << between_error_message(price, :price, min(:price), max(:price)) unless valid_price?
39
+ results << between_error_message(amount, :amount, min(:amount), max(:amount)) unless valid_amount?
40
+ end
41
+ results.compact&.each_with_object({}) { |message, data| data.merge!(message) }
42
+ end
43
+
44
+ private
45
+
46
+ def valid_symbols
47
+ return HashWithIndifferentAccess.new unless valid_side?
48
+ ::Settings.fcoin.validation.limit[side].to_h.values.flatten.compact.each_with_object(HashWithIndifferentAccess.new) do |setting, data|
49
+ data[setting.symbol] = setting
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,95 @@
1
+ require_relative 'base_validator'
2
+ require_relative '../validator_utility'
3
+
4
+ module Fcoin
5
+ module Orders
6
+ class CreateOrderMarketValidator < BaseValidator
7
+ include ValidatorUtility
8
+
9
+ # @param params [Hash] Parameter you want to verify including the called method name
10
+ # @option params :symbol [String or Symbol] Transaction pair
11
+ # @option params :side [String or Symbol] Direction of the transaction
12
+ # @option params :total [Float]
13
+ # @option params :amount [Float]
14
+ def initialize(params)
15
+ self.symbol = params[:symbol]
16
+ self.side = params[:side]
17
+ self.total = params[:amount] # this is not a mistake
18
+ self.amount = params[:amount]
19
+ end
20
+
21
+ # Validate according to method_name
22
+ def valid?
23
+ case
24
+ when valid_symbol_setting_exist?
25
+ case
26
+ when sell?
27
+ valid_amount?
28
+ when buy?
29
+ valid_total?
30
+ end
31
+ when invalid_symbol_setting_exist?
32
+ false
33
+ else
34
+ valid_symbol? && valid_side?
35
+ end
36
+ end
37
+
38
+ # Error message when invalid
39
+ def messages
40
+ return {} if valid?
41
+ results = []
42
+ results << presence_error_message(symbol, :symbol) unless valid_symbol?
43
+ results << includes_error_message(side, :side, valid_sides) unless valid_side?
44
+
45
+ case
46
+ when valid_symbol_setting_exist?
47
+ case
48
+ when sell?
49
+ results << between_error_message(amount, :amount, min(:amount), max(:amount)) unless valid_amount?
50
+ when buy?
51
+ results << between_error_message(total, :total, min(:total), max(:total)) unless valid_total?
52
+ end
53
+ when invalid_symbol_setting_exist?
54
+ results << invalid_create_order_market_error_message(symbol, :symbol)
55
+ end
56
+ results.compact&.each_with_object({}) { |message, data| data.merge!(message) }
57
+ end
58
+
59
+ private
60
+
61
+ def sell?
62
+ side.to_s == 'sell'
63
+ end
64
+
65
+ def buy?
66
+ side.to_s == 'buy'
67
+ end
68
+
69
+ def invalid_create_order_market_error_message(value, type)
70
+ message = {}
71
+ adjusted_value = value.present? ? value : 'nil'
72
+ message[type] = "#{type} is #{adjusted_value}. This #{type} board is not adapted on-going order."
73
+ message
74
+ end
75
+
76
+ def invalid_symbol_setting_exist?
77
+ invalid_symbols[symbol].present?
78
+ end
79
+
80
+ def valid_symbols
81
+ return HashWithIndifferentAccess.new unless valid_side?
82
+ ::Settings.fcoin.validation.market.valid[side].to_h.values.flatten.compact.each_with_object(HashWithIndifferentAccess.new) do |setting, data|
83
+ data[setting.symbol] = setting
84
+ end
85
+ end
86
+
87
+ def invalid_symbols
88
+ return HashWithIndifferentAccess.new unless valid_side?
89
+ ::Settings.fcoin.validation.market.invalid[side].to_h.values.flatten.compact.each_with_object(HashWithIndifferentAccess.new) do |setting, data|
90
+ data[setting] = setting
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,33 @@
1
+ require_relative 'base_validator'
2
+ require_relative '../validator_utility'
3
+
4
+ module Fcoin
5
+ module Orders
6
+ class OrderListValidator < BaseValidator
7
+ include ValidatorUtility
8
+
9
+ # @param params [Hash] Parameter you want to verify including the called method name
10
+ # @option params :symbol [String or Symbol] Transaction pair
11
+ # @option params :states [String] Order state
12
+ def initialize(params)
13
+ self.symbol = params[:symbol]
14
+ self.states = params[:states]
15
+ end
16
+
17
+ # Validate according to method_name
18
+ def valid?
19
+ valid_symbol? && valid_states?
20
+ end
21
+
22
+ # Error message when invalid
23
+ def messages
24
+ return {} if valid?
25
+ results = []
26
+
27
+ results << presence_error_message(symbol, :symbol) unless valid_symbol?
28
+ results << includes_error_message(states, :states, valid_states) unless valid_states?
29
+ results.compact&.each_with_object({}) { |message, data| data.merge!(message) }
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,69 @@
1
+ require_relative 'orders/create_order_limit_validator'
2
+ require_relative 'orders/create_order_market_validator'
3
+ require_relative 'orders/order_list_validator'
4
+
5
+ module Fcoin
6
+ class OrdersValidator
7
+
8
+ # @param params [Hash] Parameter you want to verify including the called method name
9
+ # @option params :symbol [String or Symbol] Transaction pair
10
+ # @option params :side [String or Symbol] Direction of the transaction
11
+ # @option params :type [String or Symbol] Order type
12
+ # @option params :price [Float]
13
+ # @option params :amount [Float]
14
+ # @option params :states [String] Order state
15
+ # @option params :method_name [String or Symbol] invoked method name
16
+ def initialize(params)
17
+ self.symbol = params[:symbol]
18
+ self.side = params[:side]
19
+ self.type = params[:type]
20
+ self.price = params[:price]
21
+ self.amount = params[:amount]
22
+ self.total = params[:total]
23
+ self.states = params[:states]
24
+ self.method_name = params[:method_name]
25
+ end
26
+
27
+ # Validate according to method_name
28
+ def valid?
29
+ validator.present? ? validator.valid? : false
30
+ end
31
+
32
+ # Error message when invalid
33
+ def messages
34
+ return {} if valid?
35
+ results = []
36
+ results << (validator.present? ? validator.messages : {})
37
+ results.compact&.each_with_object({}) { |message, data| data.merge!(message) }
38
+ end
39
+
40
+ private
41
+
42
+ attr_accessor :symbol, :side, :type, :price, :total, :amount, :states, :method_name
43
+
44
+ def validator
45
+ case method_name.to_sym
46
+ when :create_order_limit
47
+ create_order_limit_validator
48
+ when :create_order_market
49
+ create_order_market_validator
50
+ when :order_list
51
+ order_list_validator
52
+ else
53
+ nil
54
+ end
55
+ end
56
+
57
+ def create_order_limit_validator
58
+ @create_order_limit_validator ||= Orders::CreateOrderLimitValidator.new(symbol: symbol, side: side, price: price, amount: amount)
59
+ end
60
+
61
+ def create_order_market_validator
62
+ @create_order_market_validator ||= Orders::CreateOrderMarketValidator.new(symbol: symbol, side: side, total: total, amount: amount)
63
+ end
64
+
65
+ def order_list_validator
66
+ @order_list_validator ||= Orders::OrderListValidator.new(symbol: symbol, states: states)
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,24 @@
1
+ module Fcoin
2
+ module ValidatorUtility
3
+ def includes_error_message(target, target_type, list)
4
+ message = {}
5
+ target_value = target.present? ? target : 'nil'
6
+ message[target_type] = "#{target_type} is #{target_value}. #{target_type} is not included in the [#{list.join(', ')}]."
7
+ message
8
+ end
9
+
10
+ def between_error_message(target, target_type, min, max)
11
+ message = {}
12
+ target_value = target.present? ? target : 'nil'
13
+ message[target_type] = "#{target_type} is #{target_value}. #{target_type} is not between #{min} and #{max}."
14
+ message
15
+ end
16
+
17
+ def presence_error_message(target, target_type)
18
+ message = {}
19
+ target_value = target.present? ? target : 'nil'
20
+ message[target_type] = "#{target_type} is #{target_value}. #{target_type} can't be blank"
21
+ message
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,58 @@
1
+ require_relative 'validator/market_validator'
2
+ require_relative 'validator/orders_validator'
3
+
4
+ # Scope Fcoin::API
5
+ module Fcoin
6
+ class Validator
7
+ # @param params [Hash] Parameter you want to verify including the called method name
8
+ # @option params :level [String or Symbol] Level of depth chart
9
+ # @option params :resolution [String or Symbol] period of Candles Chart
10
+ # @option params :symbol [String or Symbol] Transaction pair
11
+ # @option params :side [String or Symbol] Direction of the transaction
12
+ # @option params :type [String or Symbol] Order type
13
+ # @option params :price [Float]
14
+ # @option params :amount [Float]
15
+ # @option params :states [String] Order state
16
+ # @option params :method_name [String or Symbol] invoked method name
17
+ def initialize(params)
18
+ self.level = params[:level]
19
+ self.resolution = params[:resolution]
20
+ self.symbol = params[:symbol]
21
+ self.side = params[:side]
22
+ self.type = params[:type]
23
+ self.price = params[:price]
24
+ self.amount = params[:amount]
25
+ self.states = params[:states]
26
+ self.method_name = params[:method_name]
27
+ end
28
+
29
+ # Whether the parameters are valid?
30
+ def valid?
31
+ validator.present? ? validator.valid? : true
32
+ end
33
+
34
+ # Error message when invalid
35
+ def messages
36
+ validator.present? ? validator.messages : {}
37
+ end
38
+
39
+ private
40
+
41
+ def validator
42
+ case method_name
43
+ when /market_depth|on_depth/
44
+ MarketValidator.new(level: level, method_name: method_name)
45
+ when /market_candles|on_candle/
46
+ MarketValidator.new(resolution: resolution, method_name: method_name)
47
+ when /create_order/
48
+ OrdersValidator.new(symbol: symbol, side: side, type: type, price: price, amount: amount, method_name: method_name)
49
+ when /order_list/
50
+ OrdersValidator.new(symbol: symbol, states: states, method_name: method_name)
51
+ else
52
+ nil
53
+ end
54
+ end
55
+
56
+ attr_accessor :level, :resolution, :symbol, :side, :type, :price, :amount, :states, :method_name
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ module Fcoin
2
+ VERSION = "0.1.0"
3
+ end
data/lib/fcoin.rb ADDED
@@ -0,0 +1,11 @@
1
+ require_relative "fcoin/version"
2
+ require_relative "fcoin/configuration"
3
+ require_relative "fcoin/client"
4
+ require_relative "fcoin/realtime/client"
5
+ require_relative "fcoin/cli"
6
+ require_relative "fcoin/generators/validation"
7
+ require_relative "fcoin/generators/locale"
8
+
9
+ module Fcoin
10
+ extend Configuration
11
+ end