ftx-api 0.2.0 → 0.2.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6164ab4f05bb14b174c612dc06723531a6b8fb96ac4d1abd590c5bd023e1b9e9
4
- data.tar.gz: 14541c5ccbe987d6e8bd726f7caffdff0015b31947550aa51f5e41c1fa33b8cb
3
+ metadata.gz: 58c15096ba4fb95095c38eb810ce23e70066ae3e462cd96d25b4793be3ed0457
4
+ data.tar.gz: 44f47071c91cb4d76a3bf075ae3c4b9e3ad656833936ad7b4cb8e3671908bb33
5
5
  SHA512:
6
- metadata.gz: f26ffc669ae5dadffac282db63a6dd9fdad337cdfa214d94e59e70ff2eaf6125e025d93297a59d56a9ffccbd7c323a90f4952d65a0a47c658dc260aa11a8b586
7
- data.tar.gz: fc799a21f27a4cb6c06eee3e7cf011e9bd56f7687f6de558dd23d4f19c8a7a105e79a27f56b5274f8e19ddc3fb0fa5bfdc4cdc06e05973900b7e37b0550720e5
6
+ metadata.gz: 687383de76c7e9b00e8cc385cc73a32537d45392253881a56b00d70336021e356cd87a6a3804357a18a1933c6be2a9b69fed2969f6817558a7acf0adbffdede3
7
+ data.tar.gz: 25a2ea5c354a87a36074759790b3b28af98aae58f3c9109e7bf7489acaebaa969d3e26c4a49005e18788dc246175340a4b532b8666b1e6b12a761c7106810d87
data/.rubocop.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  AllCops:
2
- TargetRubyVersion: 3.0
2
+ TargetRubyVersion: 3.0.1
3
3
 
4
4
  Style/StringLiterals:
5
5
  Enabled: true
data/Gemfile CHANGED
@@ -8,6 +8,7 @@ gemspec
8
8
  group :test do
9
9
  gem 'simplecov', '< 0.18'
10
10
  gem 'httparty', '~> 0.19'
11
+ gem 'openssl', '~> 2.2'
11
12
  end
12
13
 
13
14
  gem "rake", "~> 13.0"
data/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ftx-api (0.2.0)
4
+ ftx-api (0.2.5)
5
5
  httparty (~> 0.19)
6
+ openssl (~> 2.2)
6
7
 
7
8
  GEM
8
9
  remote: https://rubygems.org/
@@ -21,6 +22,7 @@ GEM
21
22
  mime-types-data (3.2021.0901)
22
23
  minitest (5.14.4)
23
24
  multi_xml (0.6.0)
25
+ openssl (2.2.0)
24
26
  parallel (1.21.0)
25
27
  parser (3.0.2.0)
26
28
  ast (~> 2.4.1)
@@ -60,6 +62,7 @@ DEPENDENCIES
60
62
  ftx-api!
61
63
  httparty (~> 0.19)
62
64
  minitest (~> 5.0)
65
+ openssl (~> 2.2)
63
66
  pry-rails
64
67
  rake (~> 13.0)
65
68
  rubocop (~> 1.7)
data/README.md CHANGED
@@ -1,8 +1,11 @@
1
- # Ftx::Api
1
+ # FTX::API
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/ftx/api`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ This gem is a ruby SDK for the FTX crypto exchange REST API.
4
+
5
+ API docs can be found on the [FTX developer site](https://docs.ftx.com/)
6
+
7
+ It is still under development and currently only covers the markets and futures endpoints.
4
8
 
5
- TODO: Delete this and the text above, and describe your gem
6
9
 
7
10
  ## Installation
8
11
 
@@ -22,11 +25,175 @@ Or install it yourself as:
22
25
 
23
26
  ## Usage
24
27
 
25
- TODO: Write usage instructions here
28
+ ### Markets
29
+
30
+ Initialize a markets session:
31
+ ```ruby
32
+ markets = FXT::API::Markets.new
33
+ ```
34
+
35
+ Query for all current prices:
36
+ ```ruby
37
+ markets.list
38
+ ```
39
+
40
+ Fetch a single market price:
41
+ ```ruby
42
+ markets.get('BTC/USD')
43
+ ```
44
+
45
+ Check for market depth:
46
+ ```ruby
47
+ markets.orderbook('BTC/USD', depth: 3)
48
+ ```
49
+
50
+ View historic prices:
51
+ ```ruby
52
+ markets.historic('BTC/USD', resolution: 86400*30)
53
+ ```
54
+ *Check the [FTX API docs](https://docs.ftx.com/?python#get-historical-prices) for additional parameters such as start_time and end_time*
55
+
56
+ Note: resolution is in seconds so 86,400 would be the number of seconds in a day. As a default, the API responds with 12 months of historical prices.
57
+
58
+ ### Futures
59
+
60
+ Initialize a futures session:
61
+ ```ruby
62
+ futures = FXT::API::Futures.new
63
+ ```
64
+
65
+ Query for all current prices:
66
+ ```ruby
67
+ futures.list
68
+ ```
69
+
70
+ Fetch a single market price:
71
+ ```ruby
72
+ futures.get('BTC-PERP')
73
+ ```
74
+
75
+ ### Account
76
+
77
+ Initialize an account session:
78
+ ```ruby
79
+ account = FXT::API::Account.new(key: 'YOUR FTX KEY', secret: 'YOUR FTX SECRET')
80
+ ```
81
+
82
+ Fetch information about account associated with key/secret:
83
+ ```ruby
84
+ account.get
85
+ ```
86
+
87
+ Query for all current account positions:
88
+ ```ruby
89
+ account.positions
90
+ ```
91
+
92
+ ### Wallet
93
+
94
+ Initialize a wallet session:
95
+ ```ruby
96
+ wallet = FXT::API::Wallet.new(key: 'YOUR FTX KEY', secret: 'YOUR FTX SECRET')
97
+ ```
98
+
99
+ Query for all available coins:
100
+ ```ruby
101
+ wallet.coins
102
+ ```
103
+
104
+ Query for all current coin balances in your account:
105
+ ```ruby
106
+ wallet.balances
107
+ ```
108
+
109
+ Query for all current coin balances split into a hash by subaccount:
110
+ ```ruby
111
+ wallet.all_balances
112
+ ```
113
+
114
+ ### Orders
115
+
116
+ Initialize an orders session:
117
+ ```ruby
118
+ orders = FXT::API::Orders.new(key: 'YOUR FTX KEY', secret: 'YOUR FTX SECRET')
119
+ ```
120
+
121
+ Query for all open orders:
122
+ ```ruby
123
+ orders.open
124
+ ```
125
+
126
+ Query for all historical orders:
127
+ ```ruby
128
+ orders.history
129
+ ```
130
+
131
+ Fetch a specific order:
132
+ ```ruby
133
+ orders.get
134
+ ```
135
+
136
+ Create a new order:
137
+ ```ruby
138
+ args = {
139
+ market: "XRP-PERP", # coin or futures name
140
+ side: "sell", # "buy" or "sell"
141
+ price: 0.306525, # Send nil for market orders.
142
+ type: "limit", # "limit" or "market"
143
+ size: 31431.0,
144
+ reduceOnly: false, # optional; default is false
145
+ ioc: false, # optional; default is false
146
+ postOnly: false, # optional; default is false
147
+ clientId: nil # optional; client order id
148
+ }
149
+
150
+ orders.create(args)
151
+ ```
152
+
153
+ Note: the create order method is not included as a test, because I have not been able to find FTX test keys and it seems a bit ridiculous to execute a live order for testing.
154
+
155
+ *Check the [FTX API docs](https://docs.ftx.com/#orders) for all parameters*
156
+
157
+ ### Convert Coins
158
+
159
+ Initialize an convert session:
160
+ ```ruby
161
+ convert = FXT::API::Convert.new(key: 'YOUR FTX KEY', secret: 'YOUR FTX SECRET')
162
+ ```
163
+
164
+ Create a new quote:
165
+ ```ruby
166
+ args = {
167
+ size: 0.01, # 0.01 is the smallest increment
168
+ fromCoin: "USD",
169
+ toCoin: "BTC",
170
+ }
171
+
172
+ convert.new_quote(args)
173
+ ```
174
+
175
+ Response:
176
+ ```ruby
177
+ {:quoteId=>2*******3}
178
+ ```
179
+
180
+ Fetch a quote:
181
+ ```ruby
182
+ convert.get_quote('quoteId')
183
+ ```
184
+
185
+ Accept a quote:
186
+ ```ruby
187
+ convert.accept_quote('quoteId')
188
+ ```
26
189
 
27
190
  ## Development
28
191
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
192
+ After checking out the repo, run `bin/setup` to install dependencies.
193
+
194
+ You'll then need to add environment variables `ENV['FTX_KEY']` and `ENV['FTX_SECRET']`. API keys can be created in your [FTX settings page](https://ftx.com/profile).
195
+
196
+ Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
197
 
31
198
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
199
 
@@ -40,4 +207,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
40
207
 
41
208
  ## Code of Conduct
42
209
 
43
- Everyone interacting in the Ftx::Api project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/benrs44/ftx-api/blob/master/CODE_OF_CONDUCT.md).
210
+ Everyone interacting in the Ftx::Api project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/benrs44/ftx-api/blob/master/CODE_OF_CONDUCT.md).
data/ftx-api.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = "Ruby gem for the FTX Exchange API"
13
13
  spec.homepage = "https://github.com/benrs44/ftx-api"
14
14
  spec.license = "MIT"
15
- spec.required_ruby_version = ">= 3.0.0"
15
+ spec.required_ruby_version = ">= 3.0.1"
16
16
 
17
17
  # spec.metadata["allowed_push_host"] = "TODO: Set to 'https://mygemserver.com'"
18
18
 
@@ -33,6 +33,7 @@ Gem::Specification.new do |spec|
33
33
 
34
34
  # Uncomment to register a new dependency of your gem
35
35
  spec.add_dependency "httparty", "~> 0.19"
36
+ spec.add_dependency "openssl", "~> 2.2"
36
37
 
37
38
  # For more information and examples about making a new gem, checkout our
38
39
  # guide at: https://bundler.io/guides/creating_gem.html
data/lib/ext/array.rb CHANGED
@@ -3,5 +3,9 @@ class Array
3
3
  def symbolize_keys
4
4
  map(&:symbolize_keys)
5
5
  end
6
+
7
+ def compact_empty
8
+ delete_if {|i| i.respond_to?(:empty?) ? !!i.empty? : !i }
9
+ end
6
10
 
7
11
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'private'
4
+
5
+ class FTX::API::Account < FTX::API::Private
6
+
7
+ def get
8
+ send_request(:get, "/account", {})
9
+ end
10
+
11
+ def positions
12
+ send_request(:get, "/positions", {})
13
+ end
14
+
15
+ end
data/lib/ftx/api/base.rb CHANGED
@@ -3,12 +3,16 @@
3
3
  require 'httparty'
4
4
 
5
5
  class FTX::API::Base
6
- include HTTParty
6
+
7
+ attr_reader :config, :key, :secret
7
8
 
8
- attr_reader :config
9
+ include HTTParty
10
+ base_uri 'https://ftx.com/api'
9
11
 
10
- def initialize(config: nil)
11
- @config = FTX::API::Config.new(config)
12
+ def initialize(args = {})
13
+ @config = FTX::API::Config.new(args.dig(:config))
14
+ @key = args.dig(:key)
15
+ @secret = args.dig(:secret)
12
16
  end
13
17
 
14
18
  protected
@@ -17,16 +21,21 @@ class FTX::API::Base
17
21
  uuid = SecureRandom.uuid
18
22
  print_log(:info, "[API] #{uuid} #{method.upcase} '#{path}' query = #{query}")
19
23
 
20
- body_or_query = method == :get ? :query : :body
24
+ if method == :get
25
+ body_or_query = :query
26
+ else
27
+ body_or_query = :body
28
+ query = query.to_json
29
+ end
21
30
 
22
31
  begin
23
32
  response = self.class.send(
24
- method,
25
- path,
33
+ method,
34
+ path,
26
35
  headers: headers,
27
36
  timeout: @config.timeout,
28
- body_or_query => query,
29
- ).parsed_response
37
+ body_or_query.to_sym => query
38
+ )
30
39
 
31
40
  print_log(:info, "[API] #{uuid} response #{response}")
32
41
  return parse_response(response)
@@ -39,6 +48,7 @@ class FTX::API::Base
39
48
  private
40
49
 
41
50
  def parse_response(response)
51
+ response = response.parsed_response
42
52
  if response.dig("success")
43
53
  response.dig("result").symbolize_keys
44
54
  else
@@ -48,6 +58,9 @@ class FTX::API::Base
48
58
 
49
59
  def print_log(method, message)
50
60
  logger = @config.logger
51
- logger.send(method, message) if logger
61
+ if logger
62
+ puts "#{method}: #{message}"
63
+ end
52
64
  end
65
+
53
66
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class FTX::API::Config
4
- attr_accessor :timeout
5
- attr_accessor :logger
4
+
5
+ attr_accessor :timeout, :logger
6
6
 
7
7
  def initialize(data = nil)
8
8
  data ||= {}
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'private'
4
+
5
+ class FTX::API::Convert < FTX::API::Private
6
+
7
+ def new_quote(query = {})
8
+ raise ArgumentError.new(
9
+ "Size, fromCoin, toCoin params required"
10
+ ) unless [:fromCoin, :toCoin, :size].all? { |i| query.include? i }
11
+
12
+ send_request(:post, "/otc/quotes", query)
13
+ end
14
+
15
+ def get_quote(quote_id)
16
+ send_request(:get, "/otc/quotes/#{quote_id}", {})
17
+ end
18
+
19
+ def accept_quote(quote_id)
20
+ send_request(:post, "/otc/quotes/#{quote_id}/accept", {})
21
+ end
22
+
23
+ end
@@ -3,7 +3,6 @@
3
3
  require_relative 'public'
4
4
 
5
5
  class FTX::API::Futures < FTX::API::Public
6
- base_uri 'https://ftx.com/api'
7
6
 
8
7
  def list
9
8
  send_request(:get, '/futures', {})
@@ -12,4 +11,5 @@ class FTX::API::Futures < FTX::API::Public
12
11
  def get(futures_name)
13
12
  send_request(:get, "/futures/#{futures_name}", {})
14
13
  end
14
+
15
15
  end
@@ -3,7 +3,6 @@
3
3
  require_relative 'public'
4
4
 
5
5
  class FTX::API::Markets < FTX::API::Public
6
- base_uri 'https://ftx.com/api'
7
6
 
8
7
  def list
9
8
  send_request(:get, '/markets', {})
@@ -25,4 +24,5 @@ class FTX::API::Markets < FTX::API::Public
25
24
 
26
25
  send_request(:get, "/markets/#{market_name}/candles", query)
27
26
  end
27
+
28
28
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'private'
4
+
5
+ class FTX::API::Orders < FTX::API::Private
6
+
7
+ def open(query = {})
8
+ send_request(:get, "/orders", query)
9
+ end
10
+
11
+ def history(query = {})
12
+ send_request(:get, "/orders/history", query)
13
+ end
14
+
15
+ def get(order_id)
16
+ send_request(:get, "/orders/#{order_id}", {})
17
+ end
18
+
19
+ def create(query = {})
20
+ raise ArgumentError.new(
21
+ "Market, side, price (can be nil), tupe and size params required"
22
+ ) unless [:market, :side, :price, :type, :size].all? { |i| query.include? i }
23
+
24
+ send_request(:post, "/orders", query)
25
+ end
26
+
27
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ class FTX::API::Private < FTX::API::Base
6
+
7
+ protected
8
+
9
+ def send_request(method, path, query)
10
+ super(method, path, headers(method, path, query), query)
11
+ end
12
+
13
+ def headers(*args)
14
+ {
15
+ 'FTX-KEY' => key,
16
+ 'FTX-SIGN' => signature(*args),
17
+ 'FTX-TS' => ts.to_s,
18
+ 'Content-Type' => 'application/json',
19
+ 'Accepts' => 'application/json',
20
+ }
21
+ end
22
+
23
+ def signature(*args)
24
+ OpenSSL::HMAC.hexdigest(digest, secret, signature_payload(*args))
25
+ end
26
+
27
+ def signature_payload(method, path, query)
28
+ payload = [ts, method.to_s.upcase, "/api", path].compact_empty
29
+
30
+ if method==:post
31
+ payload << query.to_json
32
+ elsif method==:get
33
+ payload << ("?" + URI.encode_www_form(query))
34
+ end unless query.empty?
35
+
36
+ payload.join.encode("UTF-8")
37
+ end
38
+
39
+ def ts
40
+ @ts ||= (Time.now.to_f * 1000).to_i
41
+ end
42
+
43
+ def digest
44
+ @digest ||= OpenSSL::Digest.new('sha256')
45
+ end
46
+
47
+ end
@@ -3,11 +3,11 @@
3
3
  require_relative 'base'
4
4
 
5
5
  class FTX::API::Public < FTX::API::Base
6
- base_uri 'https://ftx.com/api'
7
6
 
8
7
  protected
9
8
 
10
9
  def send_request(method, path, query)
11
10
  super(method, path, {}, query)
12
11
  end
12
+
13
13
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module FTX
4
4
  module API
5
- VERSION = "0.2.0"
5
+ VERSION = "0.2.5"
6
6
  end
7
7
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'private'
4
+
5
+ class FTX::API::Wallet < FTX::API::Private
6
+
7
+ def coins
8
+ send_request(:get, "/wallet/coins", {})
9
+ end
10
+
11
+ def balances
12
+ send_request(:get, "/wallet/balances", {})
13
+ end
14
+
15
+ def all_balances
16
+ send_request(:get, "/wallet/all_balances", {})
17
+ end
18
+
19
+ end
data/lib/ftx/api.rb CHANGED
@@ -3,4 +3,8 @@ require_relative "../ext/base"
3
3
  require_relative "api/version"
4
4
  require_relative "api/config"
5
5
  require_relative "api/markets"
6
- require_relative "api/futures"
6
+ require_relative "api/account"
7
+ require_relative "api/wallet"
8
+ require_relative "api/orders"
9
+ require_relative "api/futures"
10
+ require_relative "api/convert"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ftx-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - benrs44
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-09-23 00:00:00.000000000 Z
11
+ date: 2021-10-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.19'
27
+ - !ruby/object:Gem::Dependency
28
+ name: openssl
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.2'
27
41
  description: Ruby gem for the FTX Exchange API
28
42
  email:
29
43
  - ben@certoris.com
@@ -46,12 +60,17 @@ files:
46
60
  - lib/ext/base.rb
47
61
  - lib/ext/hash.rb
48
62
  - lib/ftx/api.rb
63
+ - lib/ftx/api/account.rb
49
64
  - lib/ftx/api/base.rb
50
65
  - lib/ftx/api/config.rb
66
+ - lib/ftx/api/convert.rb
51
67
  - lib/ftx/api/futures.rb
52
68
  - lib/ftx/api/markets.rb
69
+ - lib/ftx/api/orders.rb
70
+ - lib/ftx/api/private.rb
53
71
  - lib/ftx/api/public.rb
54
72
  - lib/ftx/api/version.rb
73
+ - lib/ftx/api/wallet.rb
55
74
  homepage: https://github.com/benrs44/ftx-api
56
75
  licenses:
57
76
  - MIT
@@ -67,7 +86,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
67
86
  requirements:
68
87
  - - ">="
69
88
  - !ruby/object:Gem::Version
70
- version: 3.0.0
89
+ version: 3.0.1
71
90
  required_rubygems_version: !ruby/object:Gem::Requirement
72
91
  requirements:
73
92
  - - ">="