coinbase-advanced 0.1.1
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/.rubocop.yml +6 -0
- data/.rubocop_todo.yml +7 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.md +201 -0
- data/README.md +91 -0
- data/Rakefile +12 -0
- data/TODO.md +26 -0
- data/lib/coinbase/advanced/api_base.rb +49 -0
- data/lib/coinbase/advanced/concerns/filter_param.rb +38 -0
- data/lib/coinbase/advanced/constants.rb +43 -0
- data/lib/coinbase/advanced/jwt_generator.rb +3 -0
- data/lib/coinbase/advanced/rest/base_response.rb +35 -0
- data/lib/coinbase/advanced/rest/resources/accounts.rb +21 -0
- data/lib/coinbase/advanced/rest/resources/converts.rb +37 -0
- data/lib/coinbase/advanced/rest/resources/data_api.rb +15 -0
- data/lib/coinbase/advanced/rest/resources/fees.rb +15 -0
- data/lib/coinbase/advanced/rest/resources/futures.rb +49 -0
- data/lib/coinbase/advanced/rest/resources/orders.rb +73 -0
- data/lib/coinbase/advanced/rest/resources/payment_methods.rb +21 -0
- data/lib/coinbase/advanced/rest/resources/perpetuals.rb +49 -0
- data/lib/coinbase/advanced/rest/resources/portfolios.rb +52 -0
- data/lib/coinbase/advanced/rest/resources/products.rb +50 -0
- data/lib/coinbase/advanced/rest/resources/public.rb +50 -0
- data/lib/coinbase/advanced/rest/rest_base.rb +120 -0
- data/lib/coinbase/advanced/version.rb +7 -0
- data/lib/coinbase/advanced.rb +119 -0
- metadata +130 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coinbase
|
4
|
+
module Advanced
|
5
|
+
module REST
|
6
|
+
module Resources
|
7
|
+
module Futures
|
8
|
+
def get_futures_balance_summary # rubocop:disable Naming/AccessorMethodName
|
9
|
+
get("cfm/balance_summary")
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_intraday_margin_setting # rubocop:disable Naming/AccessorMethodName
|
13
|
+
get("cfm/intraday/margin_setting")
|
14
|
+
end
|
15
|
+
|
16
|
+
def set_intraday_margin_setting(params = {})
|
17
|
+
post("cfm/intraday/margin_setting", params)
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_current_margin_window(params = {})
|
21
|
+
get("cfm/intraday/current_margin_window", params)
|
22
|
+
end
|
23
|
+
|
24
|
+
def list_futures_positions
|
25
|
+
get("cfm/positions")
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_futures_position(params = {})
|
29
|
+
raise ArgumentError, "Missing :product_id" unless params.key? :product_id
|
30
|
+
|
31
|
+
get("cfm/positions/#{params[:position_id]}")
|
32
|
+
end
|
33
|
+
|
34
|
+
def schedule_futures_sweep(params = {})
|
35
|
+
post("cfm/sweeps/schedule", params)
|
36
|
+
end
|
37
|
+
|
38
|
+
def list_futures_sweeps
|
39
|
+
get("cfm/sweeps")
|
40
|
+
end
|
41
|
+
|
42
|
+
def cancel_pending_futures_sweep
|
43
|
+
delete("cfm/sweeps")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coinbase
|
4
|
+
module Advanced
|
5
|
+
module REST
|
6
|
+
module Resources
|
7
|
+
# https://docs.cdp.coinbase.com/advanced-trade/reference/retailbrokerageapi_postorder
|
8
|
+
module Orders
|
9
|
+
def create_order(params = {})
|
10
|
+
raise ArgumentError, "Missing client_order_id" unless params.key? :client_order_id
|
11
|
+
raise ArgumentError, "Missing product_id" unless params.key? :product_id
|
12
|
+
raise ArgumentError, "Missing side" unless params.key? :side
|
13
|
+
raise ArgumentError, "Missing order_configuration" unless params.key? :order_configuration
|
14
|
+
|
15
|
+
post("orders", params)
|
16
|
+
end
|
17
|
+
|
18
|
+
def cancel_orders(params = {})
|
19
|
+
raise ArgumentError, "Missing order_ids" unless params.key? :order_ids
|
20
|
+
|
21
|
+
post("orders/batch_cancel", params)
|
22
|
+
end
|
23
|
+
|
24
|
+
def edit_order(params = {})
|
25
|
+
raise ArgumentError, "Missing order_id" unless params.key? :order_id
|
26
|
+
raise ArgumentError, "Missing price" unless params.key? :price
|
27
|
+
raise ArgumentError, "Missing size" unless params.key? :size
|
28
|
+
|
29
|
+
post("orders/edit", params)
|
30
|
+
end
|
31
|
+
|
32
|
+
def edit_order_preview(params = {})
|
33
|
+
raise ArgumentError, "Missing order_id" unless params.key? :order_id
|
34
|
+
raise ArgumentError, "Missing price" unless params.key? :price
|
35
|
+
raise ArgumentError, "Missing size" unless params.key? :size
|
36
|
+
|
37
|
+
post("orders/edit_preview", params)
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_order(params = {})
|
41
|
+
raise ArgumentError, "Missing order_id" unless params.key? :order_id
|
42
|
+
|
43
|
+
order_id = params.delete(:order_id)
|
44
|
+
get("orders/historical/#{order_id}", params)
|
45
|
+
end
|
46
|
+
|
47
|
+
def list_orders(params = {})
|
48
|
+
get("orders/historical/batch", params)
|
49
|
+
end
|
50
|
+
|
51
|
+
def list_fills(params = {})
|
52
|
+
get("orders/historical/fills", params)
|
53
|
+
end
|
54
|
+
|
55
|
+
def preview_order(params = {})
|
56
|
+
raise ArgumentError, "Missing product_id" unless params.key? :product_id
|
57
|
+
raise ArgumentError, "Missing side" unless params.key? :side
|
58
|
+
raise ArgumentError, "Missing order_configuration" unless params.key? :order_configuration
|
59
|
+
|
60
|
+
post("orders/preview", params)
|
61
|
+
end
|
62
|
+
|
63
|
+
def close_position(params = {})
|
64
|
+
raise ArgumentError, "Missing client_order_id" unless params.key? :client_order_id
|
65
|
+
raise ArgumentError, "Missing product_id" unless params.key? :product_id
|
66
|
+
|
67
|
+
post("orders/close_position", params)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coinbase
|
4
|
+
module Advanced
|
5
|
+
module REST
|
6
|
+
module Resources
|
7
|
+
module PaymentMethods
|
8
|
+
def list_payment_methods
|
9
|
+
get("/payment_methods")
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_payment_method(params = {})
|
13
|
+
raise ArgumentError, "Missing :payment_method_id" unless params.key? :payment_method_id
|
14
|
+
|
15
|
+
get("payment_methods/#{params[:payment_method_id]}")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coinbase
|
4
|
+
module Advanced
|
5
|
+
module REST
|
6
|
+
module Resources
|
7
|
+
module Perpetuals
|
8
|
+
def allocate_portfolio(params = {})
|
9
|
+
raise ArgumentError, "Missing :portfolio_uuid" unless params.key? :portfolio_uuid
|
10
|
+
raise ArgumentError, "Missing :symbol" unless params.key? :symbol
|
11
|
+
raise ArgumentError, "Missing :amount" unless params.key? :amount
|
12
|
+
raise ArgumentError, "Missing :currency" unless params.key? :currency
|
13
|
+
|
14
|
+
post("intx/allocate", params)
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_perpetuals_portfolio_summary(params = {})
|
18
|
+
raise ArgumentError, "Missing :portfolio_uuid" unless params.key? :portfolio_uuid
|
19
|
+
|
20
|
+
get("intx/portfolio/#{params[:portfolio_uuid]}")
|
21
|
+
end
|
22
|
+
|
23
|
+
def list_perpetuals_positions(params = {})
|
24
|
+
raise ArgumentError, "Missing :portfolio_uuid" unless params.key? :portfolio_uuid
|
25
|
+
|
26
|
+
get("intx/positions/#{params[:portfolio_uuid]}")
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_perpetuals_position(params = {})
|
30
|
+
raise ArgumentError, "Missing :portfolio_uuid" unless params.key? :portfolio_uuid
|
31
|
+
raise ArgumentError, "Missing :symbol" unless params.key? :symbol
|
32
|
+
|
33
|
+
get("intx/positions/#{params[:portfolio_uuid]}/#{params[:symbol]}")
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_portfolios_balances(params = {})
|
37
|
+
raise ArgumentError, "Missing :portfolio_uuid" unless params.key? :portfolio_uuid
|
38
|
+
|
39
|
+
get("intx/balances/#{params[:portfolio_uuid]}")
|
40
|
+
end
|
41
|
+
|
42
|
+
def opt_in_or_out_of_multi_asset_collateral(params = {})
|
43
|
+
post("intx/multi_asset_collateral", params)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coinbase
|
4
|
+
module Advanced
|
5
|
+
module REST
|
6
|
+
module Resources
|
7
|
+
module Portfolios
|
8
|
+
def list_portfolios(params = {})
|
9
|
+
get("portfolios", params)
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_portfolio(params = {})
|
13
|
+
raise ArgumentError, "Missing :name" unless params.key? :name
|
14
|
+
|
15
|
+
post("portfolios", params)
|
16
|
+
end
|
17
|
+
|
18
|
+
def move_portfolio_funds(params = {})
|
19
|
+
raise ArgumentError, "Missing :funds" unless params.key? :funds
|
20
|
+
raise ArgumentError, "Missing :funds[:value]" unless params[:funds].key? :value
|
21
|
+
raise ArgumentError, "Missing :funds[:currency]" unless params[:funds].key? :currency
|
22
|
+
raise ArgumentError, "Missing :source_portfolio_uuid" unless params.key? :source_portfolio_uuid
|
23
|
+
raise ArgumentError, "Missing :target_portfolio_uuid" unless params.key? :target_portfolio_uuid
|
24
|
+
|
25
|
+
post("portfolios/move_funds", params)
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_portfolio_funds(params = {})
|
29
|
+
raise ArgumentError, "Missing :portfolio_uuid" unless params.key? :portfolio_uuid
|
30
|
+
|
31
|
+
portfolio_uuid = params.delete(:portfolio_uuid)
|
32
|
+
get("portfolios/#{portfolio_uuid}", params)
|
33
|
+
end
|
34
|
+
|
35
|
+
def delete_portfolio(params = {})
|
36
|
+
raise ArgumentError, "Missing :portfolio_uuid" unless params.key? :portfolio_uuid
|
37
|
+
|
38
|
+
delete("portfolios/#{params[:portfolio_uuid]}")
|
39
|
+
end
|
40
|
+
|
41
|
+
def edit_portfolio(params = {})
|
42
|
+
raise ArgumentError, "Missing :portfolio_uuid" unless params.key? :portfolio_uuid
|
43
|
+
raise ArgumentError, "Missing :name" unless params.key? :name
|
44
|
+
|
45
|
+
portfolio_uuid = params.delete(:portfolio_uuid)
|
46
|
+
put("portfolios/#{portfolio_uuid}", params)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coinbase
|
4
|
+
module Advanced
|
5
|
+
module REST
|
6
|
+
module Resources
|
7
|
+
module Products
|
8
|
+
def get_best_bid_ask(params = {})
|
9
|
+
get("best_bid_ask", params)
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_product_book(params = {})
|
13
|
+
raise ArgumentError, "Missing :product_id" unless params.key? :product_id
|
14
|
+
|
15
|
+
get("product_book", params)
|
16
|
+
end
|
17
|
+
|
18
|
+
def list_products(params = {})
|
19
|
+
get("products", params)
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_product(params = {})
|
23
|
+
raise ArgumentError, "Missing :product_id" unless params.key? :product_id
|
24
|
+
|
25
|
+
product_id = params.delete(:product_id)
|
26
|
+
get("products/#{product_id}", params)
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_product_candles(params = {})
|
30
|
+
raise ArgumentError, "Missing :product_id" unless params.key? :product_id
|
31
|
+
raise ArgumentError, "Missing :start" unless params.key? :start
|
32
|
+
raise ArgumentError, "Missing :end" unless params.key? :end
|
33
|
+
raise ArgumentError, "Missing :granularity" unless params.key? :granularity
|
34
|
+
|
35
|
+
product_id = params.delete(:product_id)
|
36
|
+
get("products/#{product_id}/candles", params)
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_market_trades(params = {})
|
40
|
+
raise ArgumentError, "Missing :product_id" unless params.key? :product_id
|
41
|
+
raise ArgumentError, "Missing :limit" unless params.key? :limit
|
42
|
+
|
43
|
+
product_id = params.delete(:product_id)
|
44
|
+
get("products/#{product_id}/ticker", params)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coinbase
|
4
|
+
module Advanced
|
5
|
+
module REST
|
6
|
+
module Resources
|
7
|
+
module Public
|
8
|
+
def get_server_time # rubocop:disable Naming/AccessorMethodName
|
9
|
+
get("time", {}, auth_required: false)
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_public_product_book(params = {})
|
13
|
+
raise ArgumentError, "Missing :product_id" unless params.key? :product_id
|
14
|
+
|
15
|
+
get("market/product_book", params, auth_required: false)
|
16
|
+
end
|
17
|
+
|
18
|
+
def list_public_products(params = {})
|
19
|
+
get("market/products", params, auth_required: false)
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_public_product(params = {})
|
23
|
+
raise ArgumentError, "Missing :product_id" unless params.key? :product_id
|
24
|
+
|
25
|
+
product_id = params.delete(:product_id)
|
26
|
+
get("market/products/#{product_id}", params, auth_required: false)
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_public_product_candles(params = {})
|
30
|
+
raise ArgumentError, "Missing :product_id" unless params.key? :product_id
|
31
|
+
raise ArgumentError, "Missing :start" unless params.key? :start
|
32
|
+
raise ArgumentError, "Missing :end" unless params.key? :end
|
33
|
+
raise ArgumentError, "Missing :granularity" unless params.key? :granularity
|
34
|
+
|
35
|
+
product_id = params.delete(:product_id)
|
36
|
+
get("market/products/#{product_id}/candles", params, auth_required: false)
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_public_market_trades(params = {})
|
40
|
+
raise ArgumentError, "Missing :product_id" unless params.key? :product_id
|
41
|
+
raise ArgumentError, "Missing :limit" unless params.key? :limit
|
42
|
+
|
43
|
+
product_id = params.delete(:product_id)
|
44
|
+
get("market/products/#{product_id}/ticker", params, auth_required: false)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Coinbase
|
4
|
+
module Advanced
|
5
|
+
module REST
|
6
|
+
# RESTBase sets up, executes, and appropriately handles errors strictly within context of HTTP + REST communication
|
7
|
+
class RESTBase < APIBase
|
8
|
+
attr_reader :session
|
9
|
+
|
10
|
+
include Resources::Accounts
|
11
|
+
include Resources::Products
|
12
|
+
include Resources::Orders
|
13
|
+
include Resources::Portfolios
|
14
|
+
include Resources::Futures
|
15
|
+
include Resources::Perpetuals
|
16
|
+
include Resources::Converts
|
17
|
+
include Resources::Fees
|
18
|
+
include Resources::Public
|
19
|
+
include Resources::PaymentMethods
|
20
|
+
include Resources::DataAPI
|
21
|
+
|
22
|
+
AUTH_ERROR_MESSAGE = <<~HEREDOC
|
23
|
+
Unauthenticated request to private endpoint. If you wish to access private endpoints, you must \
|
24
|
+
provide your API key and secret when initializing the RESTClient.
|
25
|
+
HEREDOC
|
26
|
+
|
27
|
+
def initialize(config = Coinbase::Advanced.config)
|
28
|
+
super
|
29
|
+
@session = Faraday.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_headers(method, path)
|
33
|
+
@session.headers = {
|
34
|
+
"User-Agent" => Coinbase::Advanced::USER_AGENT,
|
35
|
+
"Content-Type" => "application/json"
|
36
|
+
}
|
37
|
+
|
38
|
+
return unless @authenticated
|
39
|
+
|
40
|
+
uri = "#{method} #{@base_url}#{path}"
|
41
|
+
@session.headers["Authorization"] = "Bearer #{build_jwt(uri)}"
|
42
|
+
end
|
43
|
+
|
44
|
+
# copied rb sample from https://docs.cdp.coinbase.com/advanced-trade/docs/ws-auth#code-samples
|
45
|
+
# See README if confused why this method is here
|
46
|
+
def build_jwt(uri = nil)
|
47
|
+
header = {
|
48
|
+
typ: "JWT",
|
49
|
+
kid: @api_key,
|
50
|
+
nonce: SecureRandom.hex(16)
|
51
|
+
}
|
52
|
+
|
53
|
+
claims = {
|
54
|
+
sub: @api_key,
|
55
|
+
iss: "cdp",
|
56
|
+
aud: ["cdp_service"],
|
57
|
+
nbf: Time.now.to_i,
|
58
|
+
exp: Time.now.to_i + 120 # Expiration time: 2 minute from now.
|
59
|
+
}
|
60
|
+
|
61
|
+
claims[:uri] = uri if uri
|
62
|
+
|
63
|
+
private_key = OpenSSL::PKey.read(@api_secret)
|
64
|
+
JWT.encode(claims, private_key, "ES256", header)
|
65
|
+
end
|
66
|
+
|
67
|
+
def prepare_and_send_request(http_method, url_path, params = {}, data = {}, auth_required: true)
|
68
|
+
raise AuthenticationError, AUTH_ERROR_MESSAGE if auth_required && !@authenticated
|
69
|
+
|
70
|
+
url_path = "#{@api_prefix}/#{url_path.dup}"
|
71
|
+
|
72
|
+
set_headers(http_method, url_path)
|
73
|
+
@session.params = params unless params.empty?
|
74
|
+
url_path.insert(0, "/") if url_path[0] != "/"
|
75
|
+
|
76
|
+
send_request(http_method, url_path, data)
|
77
|
+
end
|
78
|
+
|
79
|
+
# def send_request(http_method, url_path, params, headers, data = None) - py method signature, lot of redundant shit
|
80
|
+
def send_request(http_method, url_path, data = {})
|
81
|
+
url = URI::HTTPS.build(host: @base_url, path: url_path).to_s
|
82
|
+
|
83
|
+
@config.log("Sending #{http_method.to_s.upcase}:#{url} with body #{data.to_json}") if @verbose
|
84
|
+
|
85
|
+
response = case http_method
|
86
|
+
when :get then @session.get(url)
|
87
|
+
when :post then @session.post(url, data.to_json)
|
88
|
+
when :put then @session.put(url, data.to_json)
|
89
|
+
when :delete then @session.delete(url, data.to_json)
|
90
|
+
else
|
91
|
+
raise URI::BadURIError, "Unknown HTTP method / verb: '#{http_method}'"
|
92
|
+
end
|
93
|
+
|
94
|
+
@config.log("Response object:\n\n#{response.pretty_inspect}") if @verbose
|
95
|
+
|
96
|
+
BaseResponse.new(JSON.parse(response.body))
|
97
|
+
end
|
98
|
+
|
99
|
+
def get(url_path, params = {}, auth_required: true)
|
100
|
+
prepare_and_send_request(:get, url_path, params, {}, auth_required: auth_required)
|
101
|
+
end
|
102
|
+
|
103
|
+
def post(url_path, params = {}, data = {}, auth_required: true)
|
104
|
+
prepare_and_send_request(:post, url_path, params, data, auth_required: auth_required)
|
105
|
+
end
|
106
|
+
|
107
|
+
def put(url_path, params = {}, data = {}, auth_required: true)
|
108
|
+
prepare_and_send_request(:put, url_path, params, data, auth_required: auth_required)
|
109
|
+
end
|
110
|
+
|
111
|
+
def delete(url_path, params = {}, data = {}, auth_required: true)
|
112
|
+
prepare_and_send_request(:delete, url_path, params, data, auth_required: auth_required)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
class AuthenticationError < StandardError
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
require "faraday"
|
5
|
+
|
6
|
+
require "jwt"
|
7
|
+
require "openssl"
|
8
|
+
require "time"
|
9
|
+
require "securerandom"
|
10
|
+
|
11
|
+
require_relative "advanced/concerns/filter_param"
|
12
|
+
|
13
|
+
require_relative "advanced/constants"
|
14
|
+
require_relative "advanced/api_base"
|
15
|
+
require_relative "advanced/version"
|
16
|
+
|
17
|
+
require_relative "advanced/rest/resources/accounts"
|
18
|
+
require_relative "advanced/rest/resources/products"
|
19
|
+
require_relative "advanced/rest/resources/orders"
|
20
|
+
require_relative "advanced/rest/resources/portfolios"
|
21
|
+
require_relative "advanced/rest/resources/futures"
|
22
|
+
require_relative "advanced/rest/resources/perpetuals"
|
23
|
+
require_relative "advanced/rest/resources/converts"
|
24
|
+
require_relative "advanced/rest/resources/fees"
|
25
|
+
require_relative "advanced/rest/resources/public"
|
26
|
+
require_relative "advanced/rest/resources/payment_methods"
|
27
|
+
require_relative "advanced/rest/resources/data_api"
|
28
|
+
|
29
|
+
require_relative "advanced/rest/base_response"
|
30
|
+
require_relative "advanced/rest/rest_base"
|
31
|
+
|
32
|
+
class Configuration
|
33
|
+
DEFAULT_API_BASE_URL = "api.coinbase.com"
|
34
|
+
DEFAULT_API_PREFIX = "/api/v3/brokerage"
|
35
|
+
|
36
|
+
DEFAULT_LOGGER = Logger.new($stdout)
|
37
|
+
DEFAULT_LOG_LEVEL = Logger::INFO
|
38
|
+
|
39
|
+
DEFAULT_SENSITIVE_PARAMS = %i[@api_key @api_secret].freeze
|
40
|
+
|
41
|
+
include Coinbase::Advanced::Concerns::FilterParam
|
42
|
+
|
43
|
+
attr_accessor :base_url, :api_prefix, :key_file, :api_key, :api_secret,
|
44
|
+
:timeout, :verbose, :filter_params
|
45
|
+
|
46
|
+
attr_reader :logger, :log_level
|
47
|
+
|
48
|
+
def initialize
|
49
|
+
@base_url = DEFAULT_API_BASE_URL
|
50
|
+
@api_prefix = DEFAULT_API_PREFIX
|
51
|
+
@timeout = 30
|
52
|
+
|
53
|
+
@key_file = ENV.fetch("COINBASE_JSON_KEY_FILE", nil)
|
54
|
+
@api_key = ENV.fetch("COINBASE_API_KEY", nil)
|
55
|
+
@api_secret = ENV.fetch("COINBASE_API_SECRET", nil)&.gsub('\n', "\n")
|
56
|
+
|
57
|
+
@logger = DEFAULT_LOGGER
|
58
|
+
@logger.level = DEFAULT_LOG_LEVEL
|
59
|
+
@verbose = false
|
60
|
+
@filter_params = DEFAULT_SENSITIVE_PARAMS
|
61
|
+
end
|
62
|
+
|
63
|
+
def setup
|
64
|
+
yield(self) if block_given?
|
65
|
+
end
|
66
|
+
|
67
|
+
# Currently only supporting default logger
|
68
|
+
def logger=(logger)
|
69
|
+
raise ArgumentError, "Only default logger supported" unless logger.is_a?(Logger)
|
70
|
+
|
71
|
+
@logger = logger
|
72
|
+
end
|
73
|
+
|
74
|
+
def log_level=(level)
|
75
|
+
valid_levels = %i[debug info warn error fatal]
|
76
|
+
raise ArgumentError, "Invalid log level" unless valid_levels.include?(level)
|
77
|
+
|
78
|
+
@log_level = level
|
79
|
+
end
|
80
|
+
|
81
|
+
def log(message, level = :info)
|
82
|
+
return unless @logger
|
83
|
+
|
84
|
+
@logger.send(level, message)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# inspired by https://github.com/stripe/stripe-ruby/blob/master/lib/stripe.rb
|
89
|
+
# TODO: this probably is redundant because:
|
90
|
+
# A. configuration class is defined right above
|
91
|
+
# B. def_delegators here are equivalent to attr_accessor
|
92
|
+
# Keeping it here for time being until a Stripe engineer gets back to me
|
93
|
+
module Coinbase
|
94
|
+
module Advanced
|
95
|
+
@config = Configuration.new
|
96
|
+
|
97
|
+
class << self
|
98
|
+
extend Forwardable
|
99
|
+
|
100
|
+
attr_reader :config
|
101
|
+
|
102
|
+
# User configurable options
|
103
|
+
def_delegators :@config, :base_url, :base_url=
|
104
|
+
def_delegators :@config, :api_prefix, :api_prefix=
|
105
|
+
def_delegators :@config, :key_file, :key_file=
|
106
|
+
def_delegators :@config, :api_key, :api_key=
|
107
|
+
def_delegators :@config, :api_secret, :api_secret=
|
108
|
+
def_delegators :@config, :timeout, :timeout=
|
109
|
+
def_delegators :@config, :verbose, :verbose=
|
110
|
+
def_delegators :@config, :logger, :log_level=
|
111
|
+
def_delegators :@config, :log_level, :log_level=
|
112
|
+
def_delegators :@config, :filter_params, :filter_params=
|
113
|
+
|
114
|
+
def configure
|
115
|
+
yield(@config) if block_given?
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|