ftx-api 0.2.0 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
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
  - - ">="