bibox 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 (50) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.gitignore +15 -0
  4. data/.rspec +3 -0
  5. data/.travis.yml +5 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +6 -0
  8. data/Gemfile.lock +67 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +67 -0
  11. data/Rakefile +6 -0
  12. data/bibox.gemspec +36 -0
  13. data/bin/console +31 -0
  14. data/bin/setup +8 -0
  15. data/bin/websocket +71 -0
  16. data/credentials.yml.example +7 -0
  17. data/lib/.DS_Store +0 -0
  18. data/lib/bibox.rb +74 -0
  19. data/lib/bibox/.DS_Store +0 -0
  20. data/lib/bibox/configuration.rb +21 -0
  21. data/lib/bibox/constants.rb +6 -0
  22. data/lib/bibox/errors.rb +17 -0
  23. data/lib/bibox/extensions/string.rb +13 -0
  24. data/lib/bibox/models/asset.rb +29 -0
  25. data/lib/bibox/models/base.rb +26 -0
  26. data/lib/bibox/models/bill.rb +26 -0
  27. data/lib/bibox/models/ohlcv.rb +16 -0
  28. data/lib/bibox/models/order.rb +38 -0
  29. data/lib/bibox/models/order_book.rb +29 -0
  30. data/lib/bibox/models/pair.rb +24 -0
  31. data/lib/bibox/models/ticker.rb +18 -0
  32. data/lib/bibox/models/trade.rb +13 -0
  33. data/lib/bibox/models/transfer.rb +26 -0
  34. data/lib/bibox/models/user_assets.rb +23 -0
  35. data/lib/bibox/rest/client.rb +97 -0
  36. data/lib/bibox/rest/errors.rb +16 -0
  37. data/lib/bibox/rest/private/assets.rb +33 -0
  38. data/lib/bibox/rest/private/bills.rb +31 -0
  39. data/lib/bibox/rest/private/order_book.rb +21 -0
  40. data/lib/bibox/rest/private/orders.rb +131 -0
  41. data/lib/bibox/rest/private/transfers.rb +49 -0
  42. data/lib/bibox/rest/public/klines.rb +22 -0
  43. data/lib/bibox/rest/public/order_book.rb +16 -0
  44. data/lib/bibox/rest/public/pairs.rb +23 -0
  45. data/lib/bibox/rest/public/ticker.rb +16 -0
  46. data/lib/bibox/rest/public/trades.rb +16 -0
  47. data/lib/bibox/utilities.rb +68 -0
  48. data/lib/bibox/version.rb +3 -0
  49. data/lib/bibox/websocket/client.rb +149 -0
  50. metadata +232 -0
Binary file
@@ -0,0 +1,74 @@
1
+ # Rest API
2
+ require "faraday"
3
+ require "faraday_middleware"
4
+ require "openssl"
5
+
6
+ # Websockets
7
+ require "faye/websocket"
8
+ require "eventmachine"
9
+
10
+ # Shared
11
+ require "json"
12
+ require "date"
13
+ require "bigdecimal"
14
+
15
+ # Library
16
+ require "bibox/version"
17
+
18
+ require "bibox/configuration"
19
+ require "bibox/errors"
20
+ require "bibox/constants"
21
+ require "bibox/utilities"
22
+
23
+ require "bibox/models/base"
24
+ require "bibox/models/ticker"
25
+ require "bibox/models/pair"
26
+ require "bibox/models/trade"
27
+ require "bibox/models/order_book"
28
+ require "bibox/models/ohlcv"
29
+ require "bibox/models/order"
30
+ require "bibox/models/asset"
31
+ require "bibox/models/user_assets"
32
+ require "bibox/models/transfer"
33
+ require "bibox/models/bill"
34
+
35
+ require "bibox/rest/public/ticker"
36
+ require "bibox/rest/public/pairs"
37
+ require "bibox/rest/public/trades"
38
+ require "bibox/rest/public/order_book"
39
+ require "bibox/rest/public/klines"
40
+
41
+ require "bibox/rest/private/orders"
42
+ require "bibox/rest/private/order_book"
43
+ require "bibox/rest/private/assets"
44
+ require "bibox/rest/private/transfers"
45
+ require "bibox/rest/private/bills"
46
+
47
+ require "bibox/rest/errors"
48
+ require "bibox/rest/client"
49
+
50
+ require "bibox/websocket/client"
51
+
52
+ if !String.instance_methods(false).include?(:underscore)
53
+ require "bibox/extensions/string"
54
+ end
55
+
56
+ module Bibox
57
+
58
+ class << self
59
+ attr_writer :configuration
60
+ end
61
+
62
+ def self.configuration
63
+ @configuration ||= ::Bibox::Configuration.new
64
+ end
65
+
66
+ def self.reset
67
+ @configuration = ::Bibox::Configuration.new
68
+ end
69
+
70
+ def self.configure
71
+ yield(configuration)
72
+ end
73
+
74
+ end
Binary file
@@ -0,0 +1,21 @@
1
+ module Bibox
2
+ class Configuration
3
+ attr_accessor :key, :secret, :faraday
4
+
5
+ def initialize
6
+ self.key = nil
7
+ self.secret = nil
8
+
9
+ self.faraday = {
10
+ adapter: :net_http,
11
+ user_agent: 'Bibox Ruby',
12
+ verbose: false
13
+ }
14
+ end
15
+
16
+ def verbose_faraday?
17
+ self.faraday.fetch(:verbose, false)
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,6 @@
1
+ module Bibox
2
+ module Constants
3
+ BUY_ORDER = 1
4
+ SELL_ORDER = 2
5
+ end
6
+ end
@@ -0,0 +1,17 @@
1
+ module Bibox
2
+ module Errors
3
+ class Error < StandardError; end;
4
+ class MissingConfigError < Bibox::Errors::Error; end;
5
+ class ParameterError < Bibox::Errors::Error; end;
6
+ class InvalidOrderError < Bibox::Errors::Error; end;
7
+ class ApiNotSupportedError < Bibox::Errors::Error; end;
8
+ class WebsocketError < Bibox::Errors::Error; end;
9
+
10
+ MAPPING = {
11
+ "2033" => -> { raise ::Bibox::Errors::InvalidOrderError.new("Order operation failed! Order has already completed or has already been revoked (code 2033)") },
12
+ "3000" => -> { raise ::Bibox::Errors::ParameterError.new("Invalid parameters specified (code 3000)") },
13
+ "3011" => -> { raise ::Bibox::Errors::ApiNotSupportedError.new("This method isn't available via the API (code 3011)") },
14
+ }
15
+
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ class String
2
+
3
+ def underscore
4
+ word = self.dup
5
+ word.gsub!(/::/, '/')
6
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
7
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
8
+ word.tr!("-", "_")
9
+ word.downcase!
10
+ word
11
+ end
12
+
13
+ end
@@ -0,0 +1,29 @@
1
+ module Bibox
2
+ module Models
3
+ class Asset < Base
4
+ MAPPING = {
5
+ id: :string,
6
+ symbol: :string,
7
+ icon_url: :string,
8
+ describe_url: :string,
9
+ name: :string,
10
+ enable_withdraw: :boolean,
11
+ enable_deposit: :boolean,
12
+ confirm_count: :integer,
13
+ total_balance: :float,
14
+ balance: :float,
15
+ freeze: :float,
16
+ btc_value: :float,
17
+ cny_value: :float,
18
+ usd_value: :float
19
+ }
20
+
21
+ def initialize(hash)
22
+ super(hash)
23
+
24
+ self.symbol = hash.fetch("coin_symbol", nil) if self.symbol.to_s.empty? && hash.has_key?("coin_symbol")
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ module Bibox
2
+ module Models
3
+ class Base
4
+
5
+ def initialize(hash)
6
+ self.class::MAPPING.keys.each { |key| self.class.send(:attr_accessor, key) }
7
+
8
+ hash.each do |key, value|
9
+ key = key.underscore.to_sym
10
+ type = self.class::MAPPING.fetch(key, nil)
11
+ value = value && type ? ::Bibox::Utilities::convert_value(value, type, use_ms_for_time: true) : value
12
+ self.send("#{key}=", value) if self.respond_to?(key)
13
+ end
14
+ end
15
+
16
+ def attributes
17
+ Hash[instance_variables.map { |name| [name.to_s.gsub(/^@/, "").to_sym, instance_variable_get(name)] }]
18
+ end
19
+
20
+ def self.parse(data)
21
+ data&.collect { |item| self.new(item) }
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Bibox
2
+ module Models
3
+ class Bill < Base
4
+ MAPPING = {
5
+ created_at: :datetime,
6
+ symbol: :string,
7
+ change_amount: :float,
8
+ result_amount: :float,
9
+ fee: :float,
10
+ fee_symbol: :string,
11
+ comment: :string,
12
+ bill_type: {enum: {-1 => :all, 0 => :deposit, 2 => :withdrawal, 3 => :sell, 5 => :buy, 31 => :transfer_in, 32 => :transfer_out}},
13
+ }
14
+
15
+ BILL_TYPES = {
16
+ all: -1,
17
+ deposit: 0,
18
+ withdrawal: 2,
19
+ sell: 3,
20
+ buy: 5,
21
+ transfer_in: 31,
22
+ transfer_out: 32
23
+ }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,16 @@
1
+ module Bibox
2
+ module Models
3
+ class OHLCV < Base
4
+
5
+ MAPPING = {
6
+ time: :time,
7
+ open: :float,
8
+ high: :float,
9
+ low: :float,
10
+ close: :float,
11
+ vol: :float
12
+ }
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ module Bibox
2
+ module Models
3
+ class Order < Base
4
+ MAPPING = {
5
+ id: :string,
6
+ created_at: :time,
7
+ account_type: :integer,
8
+ coin_symbol: :string,
9
+ currency_symbol: :string,
10
+ fee_symbol: :string,
11
+ order_side: {enum: {1 => :buy, 2 => :sell}},
12
+ order_type: :integer,
13
+ price: :float,
14
+ amount: :float,
15
+ money: :float,
16
+ fee: :float,
17
+ pay_bix: :boolean,
18
+ deal_price: :float,
19
+ deal_amount: :float,
20
+ deal_money: :float,
21
+ deal_percent: :string,
22
+ status: :integer,
23
+ unexecuted: :float
24
+ }
25
+
26
+ ORDER_SIDES = {
27
+ buy: 1,
28
+ sell: 2
29
+ }
30
+
31
+ ORDER_TYPES = {
32
+ market: 1, # NOT VERIFIED! There's no API documentation so it's just a guess for now.
33
+ limit: 2
34
+ }
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,29 @@
1
+ module Bibox
2
+ module Models
3
+ class OrderBook
4
+ attr_accessor :pair, :update_time, :asks, :bids
5
+
6
+ def initialize(hash)
7
+ self.pair = hash.fetch("pair", nil)
8
+ self.update_time = ::Bibox::Utilities.epoch_to_time(hash.fetch("update_time", nil), ms: true) if hash.has_key?("update_time") && !hash.fetch("update_time", nil).to_s.empty?
9
+
10
+ self.bids = []
11
+ self.asks = []
12
+
13
+ process(hash)
14
+ end
15
+
16
+ def process(hash)
17
+ [:bids, :asks].each do |type|
18
+ hash.fetch(type.to_s, []).each do |item|
19
+ price = ::Bibox::Utilities.convert_value(item.fetch("price", nil), :float)
20
+ volume = ::Bibox::Utilities.convert_value(item.fetch("volume", nil), :float)
21
+ value = !price.nil? && !volume.nil? ? price * volume : nil
22
+ self.send(type).send(:<<, {price: price, volume: volume, value: value})
23
+ end
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,24 @@
1
+ module Bibox
2
+ module Models
3
+ class Pair < Base
4
+ MAPPING = {
5
+ id: :string,
6
+ coin_symbol: :string,
7
+ currency_symbol: :string,
8
+ high: :float,
9
+ low: :float,
10
+ last: :float,
11
+ vol24h: :float,
12
+ amount: :float,
13
+ change: :string,
14
+ percent: :string,
15
+ low_cny: :float,
16
+ high_cny: :float,
17
+ last_cny: :float,
18
+ low_usd: :float,
19
+ high_usd: :float,
20
+ last_usd: :float
21
+ }
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ module Bibox
2
+ module Models
3
+ class Ticker < Base
4
+ MAPPING = {
5
+ buy: :float,
6
+ sell: :float,
7
+ high: :float,
8
+ low: :float,
9
+ last: :float,
10
+ vol: :float,
11
+ timestamp: :time,
12
+ last_cny: :float,
13
+ last_usd: :float,
14
+ percent: :string,
15
+ }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ module Bibox
2
+ module Models
3
+ class Trade < Base
4
+ MAPPING = {
5
+ pair: :string,
6
+ price: :float,
7
+ amount: :float,
8
+ time: :time,
9
+ side: {enum: {1 => :buy, 2 => :sell}}
10
+ }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,26 @@
1
+ module Bibox
2
+ module Models
3
+ class Transfer < Base
4
+ MAPPING = {
5
+ user_id: :string,
6
+ coin_id: :string,
7
+ to: :string,
8
+ coin_symbol: :string,
9
+ confirm_count: :string,
10
+ amount: :float,
11
+ updated_at: :datetime,
12
+ created_at: :datetime,
13
+ url: :string,
14
+ icon_url: :string,
15
+ status: {enum: {1 => :pending, 2 => :success, 3 => :failed}},
16
+ }
17
+
18
+ STATUSES = {
19
+ all: 0,
20
+ pending: 1,
21
+ success: 2,
22
+ failed: 3
23
+ }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ module Bibox
2
+ module Models
3
+ class UserAssets < Base
4
+ attr_accessor :assets
5
+
6
+ MAPPING = {
7
+ total_btc: :float,
8
+ total_cny: :float,
9
+ total_usd: :float,
10
+ }
11
+
12
+ def initialize(hash)
13
+ super(hash)
14
+ process(hash.fetch("assets_list", []))
15
+ end
16
+
17
+ def process(assets)
18
+ self.assets = ::Bibox::Models::Asset.parse(assets)
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,97 @@
1
+ module Bibox
2
+ module Rest
3
+ class Client
4
+ attr_accessor :url, :configuration
5
+
6
+ def initialize(configuration: ::Bibox.configuration)
7
+ self.url = "https://api.bibox.com/v1"
8
+ self.configuration = configuration
9
+ end
10
+
11
+ include ::Bibox::Rest::Errors
12
+
13
+ include ::Bibox::Rest::Public::Ticker
14
+ include ::Bibox::Rest::Public::Pairs
15
+ include ::Bibox::Rest::Public::Trades
16
+ include ::Bibox::Rest::Public::OrderBook
17
+ include ::Bibox::Rest::Public::Klines
18
+
19
+ include ::Bibox::Rest::Private::Orders
20
+ include ::Bibox::Rest::Private::OrderBook
21
+ include ::Bibox::Rest::Private::Assets
22
+ include ::Bibox::Rest::Private::Transfers
23
+ include ::Bibox::Rest::Private::Bills
24
+
25
+ def configured?
26
+ !self.configuration.key.to_s.empty? && !self.configuration.secret.to_s.empty?
27
+ end
28
+
29
+ def check_credentials!
30
+ unless configured?
31
+ raise ::Bibox::Errors::MissingConfigError.new("Bibox gem hasn't been properly configured.")
32
+ end
33
+ end
34
+
35
+ def to_uri(path)
36
+ "#{self.url}#{path}"
37
+ end
38
+
39
+ def parse(response)
40
+ error?(response)
41
+ response
42
+ end
43
+
44
+ def get(path, params: {}, options: {})
45
+ request path, method: :get, params: params, options: options
46
+ end
47
+
48
+ def post(path, params: {}, data: {}, options: {})
49
+ request path, method: :post, params: params, data: auth(data), options: options
50
+ end
51
+
52
+ def auth(payload = {})
53
+ data = {}
54
+ data[:cmds] = payload.to_json
55
+
56
+ if configured?
57
+ data[:apikey] = self.configuration.key
58
+ data[:sign] = ::OpenSSL::HMAC.hexdigest('md5', self.configuration.secret, payload.to_json)
59
+ end
60
+
61
+ return data
62
+ end
63
+
64
+ def request(path, method: :get, params: {}, data: {}, options: {})
65
+ user_agent = options.fetch(:user_agent, self.configuration.faraday.fetch(:user_agent, nil))
66
+ proxy = options.fetch(:proxy, nil)
67
+
68
+ connection = Faraday.new(url: to_uri(path)) do |builder|
69
+ builder.headers[:user_agent] = user_agent if !user_agent.to_s.empty?
70
+ builder.request :url_encoded if method.eql?(:post)
71
+ builder.response :logger if self.configuration.verbose_faraday?
72
+ builder.response :json
73
+
74
+ if proxy
75
+ puts "[Bibox::Rest::Client] - Will connect to Bibox using proxy: #{proxy.inspect}" if self.configuration.verbose_faraday?
76
+ builder.proxy = proxy
77
+ end
78
+
79
+ builder.adapter self.configuration.faraday.fetch(:adapter, :net_http)
80
+ end
81
+
82
+ case method
83
+ when :get
84
+ connection.get do |request|
85
+ request.params = params if params && !params.empty?
86
+ end&.body
87
+ when :post
88
+ connection.post do |request|
89
+ request.body = data
90
+ request.params = params if params && !params.empty?
91
+ end&.body
92
+ end
93
+ end
94
+
95
+ end
96
+ end
97
+ end