tastytrade 0.2.0 → 0.3.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/commands/plan.md +13 -0
  3. data/.claude/commands/release-pr.md +12 -0
  4. data/CHANGELOG.md +180 -0
  5. data/README.md +424 -3
  6. data/ROADMAP.md +17 -17
  7. data/lib/tastytrade/cli/history_formatter.rb +304 -0
  8. data/lib/tastytrade/cli/orders.rb +749 -0
  9. data/lib/tastytrade/cli/positions_formatter.rb +114 -0
  10. data/lib/tastytrade/cli.rb +701 -12
  11. data/lib/tastytrade/cli_helpers.rb +111 -14
  12. data/lib/tastytrade/client.rb +7 -0
  13. data/lib/tastytrade/file_store.rb +83 -0
  14. data/lib/tastytrade/instruments/equity.rb +42 -0
  15. data/lib/tastytrade/models/account.rb +160 -2
  16. data/lib/tastytrade/models/account_balance.rb +46 -0
  17. data/lib/tastytrade/models/buying_power_effect.rb +61 -0
  18. data/lib/tastytrade/models/live_order.rb +272 -0
  19. data/lib/tastytrade/models/order_response.rb +106 -0
  20. data/lib/tastytrade/models/order_status.rb +84 -0
  21. data/lib/tastytrade/models/trading_status.rb +200 -0
  22. data/lib/tastytrade/models/transaction.rb +151 -0
  23. data/lib/tastytrade/models.rb +6 -0
  24. data/lib/tastytrade/order.rb +191 -0
  25. data/lib/tastytrade/order_validator.rb +355 -0
  26. data/lib/tastytrade/session.rb +26 -1
  27. data/lib/tastytrade/session_manager.rb +43 -14
  28. data/lib/tastytrade/version.rb +1 -1
  29. data/lib/tastytrade.rb +43 -0
  30. data/spec/exe/tastytrade_spec.rb +1 -1
  31. data/spec/tastytrade/cli/positions_spec.rb +267 -0
  32. data/spec/tastytrade/cli_auth_spec.rb +5 -0
  33. data/spec/tastytrade/cli_env_login_spec.rb +199 -0
  34. data/spec/tastytrade/cli_helpers_spec.rb +3 -26
  35. data/spec/tastytrade/cli_orders_spec.rb +168 -0
  36. data/spec/tastytrade/cli_status_spec.rb +153 -164
  37. data/spec/tastytrade/file_store_spec.rb +126 -0
  38. data/spec/tastytrade/models/account_balance_spec.rb +103 -0
  39. data/spec/tastytrade/models/account_order_history_spec.rb +229 -0
  40. data/spec/tastytrade/models/account_order_management_spec.rb +271 -0
  41. data/spec/tastytrade/models/account_place_order_spec.rb +125 -0
  42. data/spec/tastytrade/models/account_spec.rb +86 -15
  43. data/spec/tastytrade/models/buying_power_effect_spec.rb +250 -0
  44. data/spec/tastytrade/models/live_order_json_spec.rb +144 -0
  45. data/spec/tastytrade/models/live_order_spec.rb +295 -0
  46. data/spec/tastytrade/models/order_response_spec.rb +96 -0
  47. data/spec/tastytrade/models/order_status_spec.rb +113 -0
  48. data/spec/tastytrade/models/trading_status_spec.rb +260 -0
  49. data/spec/tastytrade/models/transaction_spec.rb +236 -0
  50. data/spec/tastytrade/order_edge_cases_spec.rb +163 -0
  51. data/spec/tastytrade/order_spec.rb +201 -0
  52. data/spec/tastytrade/order_validator_spec.rb +347 -0
  53. data/spec/tastytrade/session_env_spec.rb +169 -0
  54. data/spec/tastytrade/session_manager_spec.rb +43 -33
  55. metadata +34 -18
  56. data/lib/tastytrade/keyring_store.rb +0 -72
  57. data/spec/tastytrade/keyring_store_spec.rb +0 -168
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe Tastytrade::Session do
6
+ describe ".from_environment" do
7
+ around do |example|
8
+ # Save original environment
9
+ original_env = ENV.to_hash
10
+
11
+ # Clear relevant environment variables
12
+ %w[TASTYTRADE_USERNAME TT_USERNAME TASTYTRADE_PASSWORD TT_PASSWORD
13
+ TASTYTRADE_REMEMBER TT_REMEMBER TASTYTRADE_ENVIRONMENT TT_ENVIRONMENT].each do |key|
14
+ ENV.delete(key)
15
+ end
16
+
17
+ example.run
18
+
19
+ # Restore original environment
20
+ ENV.clear
21
+ ENV.update(original_env)
22
+ end
23
+
24
+ context "with TASTYTRADE_ prefixed variables" do
25
+ before do
26
+ ENV["TASTYTRADE_USERNAME"] = "test@example.com"
27
+ ENV["TASTYTRADE_PASSWORD"] = "test_password"
28
+ end
29
+
30
+ it "creates a session with username and password" do
31
+ session = described_class.from_environment
32
+ expect(session).not_to be_nil
33
+ expect(session.instance_variable_get(:@username)).to eq("test@example.com")
34
+ expect(session.instance_variable_get(:@password)).to eq("test_password")
35
+ end
36
+
37
+ it "defaults to production environment" do
38
+ session = described_class.from_environment
39
+ expect(session.is_test).to be false
40
+ end
41
+
42
+ it "defaults to remember_me false" do
43
+ session = described_class.from_environment
44
+ expect(session.instance_variable_get(:@remember_me)).to be false
45
+ end
46
+
47
+ context "with TASTYTRADE_REMEMBER set to true" do
48
+ before do
49
+ ENV["TASTYTRADE_REMEMBER"] = "true"
50
+ end
51
+
52
+ it "enables remember_me" do
53
+ session = described_class.from_environment
54
+ expect(session.instance_variable_get(:@remember_me)).to be true
55
+ end
56
+ end
57
+
58
+ context "with TASTYTRADE_REMEMBER set to TRUE" do
59
+ before do
60
+ ENV["TASTYTRADE_REMEMBER"] = "TRUE"
61
+ end
62
+
63
+ it "enables remember_me (case insensitive)" do
64
+ session = described_class.from_environment
65
+ expect(session.instance_variable_get(:@remember_me)).to be true
66
+ end
67
+ end
68
+
69
+ context "with TASTYTRADE_ENVIRONMENT set to sandbox" do
70
+ before do
71
+ ENV["TASTYTRADE_ENVIRONMENT"] = "sandbox"
72
+ end
73
+
74
+ it "sets is_test to true" do
75
+ session = described_class.from_environment
76
+ expect(session.is_test).to be true
77
+ end
78
+ end
79
+
80
+ context "with TASTYTRADE_ENVIRONMENT set to SANDBOX" do
81
+ before do
82
+ ENV["TASTYTRADE_ENVIRONMENT"] = "SANDBOX"
83
+ end
84
+
85
+ it "sets is_test to true (case insensitive)" do
86
+ session = described_class.from_environment
87
+ expect(session.is_test).to be true
88
+ end
89
+ end
90
+ end
91
+
92
+ context "with TT_ prefixed variables" do
93
+ before do
94
+ ENV["TT_USERNAME"] = "tt@example.com"
95
+ ENV["TT_PASSWORD"] = "tt_password"
96
+ end
97
+
98
+ it "creates a session with username and password" do
99
+ session = described_class.from_environment
100
+ expect(session).not_to be_nil
101
+ expect(session.instance_variable_get(:@username)).to eq("tt@example.com")
102
+ expect(session.instance_variable_get(:@password)).to eq("tt_password")
103
+ end
104
+
105
+ context "with TT_REMEMBER set" do
106
+ before do
107
+ ENV["TT_REMEMBER"] = "true"
108
+ end
109
+
110
+ it "enables remember_me" do
111
+ session = described_class.from_environment
112
+ expect(session.instance_variable_get(:@remember_me)).to be true
113
+ end
114
+ end
115
+
116
+ context "with TT_ENVIRONMENT set to sandbox" do
117
+ before do
118
+ ENV["TT_ENVIRONMENT"] = "sandbox"
119
+ end
120
+
121
+ it "sets is_test to true" do
122
+ session = described_class.from_environment
123
+ expect(session.is_test).to be true
124
+ end
125
+ end
126
+ end
127
+
128
+ context "with both TASTYTRADE_ and TT_ variables" do
129
+ before do
130
+ ENV["TASTYTRADE_USERNAME"] = "tastytrade@example.com"
131
+ ENV["TT_USERNAME"] = "tt@example.com"
132
+ ENV["TASTYTRADE_PASSWORD"] = "tastytrade_password"
133
+ ENV["TT_PASSWORD"] = "tt_password"
134
+ end
135
+
136
+ it "prefers TASTYTRADE_ prefixed variables" do
137
+ session = described_class.from_environment
138
+ expect(session.instance_variable_get(:@username)).to eq("tastytrade@example.com")
139
+ expect(session.instance_variable_get(:@password)).to eq("tastytrade_password")
140
+ end
141
+ end
142
+
143
+ context "with missing username" do
144
+ before do
145
+ ENV["TASTYTRADE_PASSWORD"] = "test_password"
146
+ end
147
+
148
+ it "returns nil" do
149
+ expect(described_class.from_environment).to be_nil
150
+ end
151
+ end
152
+
153
+ context "with missing password" do
154
+ before do
155
+ ENV["TASTYTRADE_USERNAME"] = "test@example.com"
156
+ end
157
+
158
+ it "returns nil" do
159
+ expect(described_class.from_environment).to be_nil
160
+ end
161
+ end
162
+
163
+ context "with no environment variables set" do
164
+ it "returns nil" do
165
+ expect(described_class.from_environment).to be_nil
166
+ end
167
+ end
168
+ end
169
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "spec_helper"
4
4
  require "tastytrade/session_manager"
5
- require "tastytrade/keyring_store"
5
+ require "tastytrade/file_store"
6
6
  require "tastytrade/cli_config"
7
7
 
8
8
  RSpec.describe Tastytrade::SessionManager do
@@ -16,7 +16,7 @@ RSpec.describe Tastytrade::SessionManager do
16
16
  allow(Tastytrade::CLIConfig).to receive(:new).and_return(config)
17
17
  allow(config).to receive(:set)
18
18
  allow(config).to receive(:delete)
19
- allow(Tastytrade::KeyringStore).to receive(:available?).and_return(true)
19
+ allow(Tastytrade::FileStore).to receive(:available?).and_return(true)
20
20
  end
21
21
 
22
22
  describe "#initialize" do
@@ -34,16 +34,21 @@ RSpec.describe Tastytrade::SessionManager do
34
34
  describe "#save_session" do
35
35
  let(:session_token) { "session_token_123" }
36
36
  let(:remember_token) { "remember_token_456" }
37
+ let(:user) { instance_double(Tastytrade::Models::User,
38
+ email: "test@example.com",
39
+ username: "testuser",
40
+ external_id: "test-external-id") }
37
41
 
38
42
  before do
39
43
  allow(session).to receive(:session_token).and_return(session_token)
40
44
  allow(session).to receive(:remember_token).and_return(remember_token)
41
45
  allow(session).to receive(:session_expiration).and_return(nil)
42
- allow(Tastytrade::KeyringStore).to receive(:set).and_return(true)
46
+ allow(session).to receive(:user).and_return(user)
47
+ allow(Tastytrade::FileStore).to receive(:set).and_return(true)
43
48
  end
44
49
 
45
50
  it "saves session token" do
46
- expect(Tastytrade::KeyringStore).to receive(:set)
51
+ expect(Tastytrade::FileStore).to receive(:set)
47
52
  .with("token_test@example.com_production", session_token)
48
53
 
49
54
  manager.save_session(session)
@@ -57,7 +62,7 @@ RSpec.describe Tastytrade::SessionManager do
57
62
  end
58
63
 
59
64
  it "saves session expiration" do
60
- expect(Tastytrade::KeyringStore).to receive(:set)
65
+ expect(Tastytrade::FileStore).to receive(:set)
61
66
  .with("session_expiration_test@example.com_production", expiration_time.iso8601)
62
67
 
63
68
  manager.save_session(session)
@@ -74,18 +79,18 @@ RSpec.describe Tastytrade::SessionManager do
74
79
 
75
80
  context "with remember option" do
76
81
  it "saves remember token and password" do
77
- expect(Tastytrade::KeyringStore).to receive(:set)
82
+ expect(Tastytrade::FileStore).to receive(:set)
78
83
  .with("remember_test@example.com_production", remember_token)
79
- expect(Tastytrade::KeyringStore).to receive(:set)
84
+ expect(Tastytrade::FileStore).to receive(:set)
80
85
  .with("password_test@example.com_production", "secret123")
81
86
 
82
87
  manager.save_session(session, password: "secret123", remember: true)
83
88
  end
84
89
 
85
90
  it "doesn't save password if keyring unavailable" do
86
- allow(Tastytrade::KeyringStore).to receive(:available?).and_return(false)
91
+ allow(Tastytrade::FileStore).to receive(:available?).and_return(false)
87
92
 
88
- expect(Tastytrade::KeyringStore).not_to receive(:set)
93
+ expect(Tastytrade::FileStore).not_to receive(:set)
89
94
  .with("password_test@example.com_production", anything)
90
95
 
91
96
  manager.save_session(session, password: "secret123", remember: true)
@@ -94,9 +99,9 @@ RSpec.describe Tastytrade::SessionManager do
94
99
 
95
100
  context "without remember option" do
96
101
  it "doesn't save remember token or password" do
97
- expect(Tastytrade::KeyringStore).not_to receive(:set)
102
+ expect(Tastytrade::FileStore).not_to receive(:set)
98
103
  .with("remember_test@example.com_production", anything)
99
- expect(Tastytrade::KeyringStore).not_to receive(:set)
104
+ expect(Tastytrade::FileStore).not_to receive(:set)
100
105
  .with("password_test@example.com_production", anything)
101
106
 
102
107
  manager.save_session(session, password: "secret123", remember: false)
@@ -104,7 +109,7 @@ RSpec.describe Tastytrade::SessionManager do
104
109
  end
105
110
 
106
111
  it "handles errors gracefully" do
107
- allow(Tastytrade::KeyringStore).to receive(:set).and_raise(StandardError, "Save error")
112
+ allow(Tastytrade::FileStore).to receive(:set).and_raise(StandardError, "Save error")
108
113
 
109
114
  expect { manager.save_session(session) }.to output(/Failed to save session/).to_stderr
110
115
  expect(manager.save_session(session)).to be false
@@ -114,11 +119,14 @@ RSpec.describe Tastytrade::SessionManager do
114
119
  describe "#load_session" do
115
120
  context "with saved token" do
116
121
  before do
117
- allow(Tastytrade::KeyringStore).to receive(:get)
122
+ allow(Tastytrade::FileStore).to receive(:get)
118
123
  .with("token_test@example.com_production").and_return("saved_token")
119
- allow(Tastytrade::KeyringStore).to receive(:get)
124
+ allow(Tastytrade::FileStore).to receive(:get)
120
125
  .with("remember_test@example.com_production").and_return("saved_remember")
121
- allow(Tastytrade::KeyringStore).to receive(:get)
126
+ allow(Tastytrade::FileStore).to receive(:get)
127
+ .with("user_data_test@example.com_production")
128
+ .and_return('{"email":"test@example.com","username":"testuser","external_id":"test-external-id"}')
129
+ allow(Tastytrade::FileStore).to receive(:get)
122
130
  .with("session_expiration_test@example.com_production").and_return(nil)
123
131
  end
124
132
 
@@ -128,6 +136,8 @@ RSpec.describe Tastytrade::SessionManager do
128
136
  expect(result).to eq({
129
137
  session_token: "saved_token",
130
138
  remember_token: "saved_remember",
139
+ user_data: { "email" => "test@example.com", "username" => "testuser",
140
+ "external_id" => "test-external-id" },
131
141
  session_expiration: nil,
132
142
  username: username,
133
143
  environment: environment
@@ -137,7 +147,7 @@ RSpec.describe Tastytrade::SessionManager do
137
147
 
138
148
  context "without saved token" do
139
149
  before do
140
- allow(Tastytrade::KeyringStore).to receive(:get)
150
+ allow(Tastytrade::FileStore).to receive(:get)
141
151
  .with("token_test@example.com_production").and_return(nil)
142
152
  end
143
153
 
@@ -157,9 +167,9 @@ RSpec.describe Tastytrade::SessionManager do
157
167
 
158
168
  context "with saved remember token" do
159
169
  before do
160
- allow(Tastytrade::KeyringStore).to receive(:get)
170
+ allow(Tastytrade::FileStore).to receive(:get)
161
171
  .with("password_test@example.com_production").and_return(nil)
162
- allow(Tastytrade::KeyringStore).to receive(:get)
172
+ allow(Tastytrade::FileStore).to receive(:get)
163
173
  .with("remember_test@example.com_production").and_return("saved_remember")
164
174
  end
165
175
 
@@ -177,9 +187,9 @@ RSpec.describe Tastytrade::SessionManager do
177
187
 
178
188
  context "with saved password" do
179
189
  before do
180
- allow(Tastytrade::KeyringStore).to receive(:get)
190
+ allow(Tastytrade::FileStore).to receive(:get)
181
191
  .with("remember_test@example.com_production").and_return(nil)
182
- allow(Tastytrade::KeyringStore).to receive(:get)
192
+ allow(Tastytrade::FileStore).to receive(:get)
183
193
  .with("password_test@example.com_production").and_return("saved_password")
184
194
  end
185
195
 
@@ -199,9 +209,9 @@ RSpec.describe Tastytrade::SessionManager do
199
209
  let(:environment) { "sandbox" }
200
210
 
201
211
  before do
202
- allow(Tastytrade::KeyringStore).to receive(:get)
212
+ allow(Tastytrade::FileStore).to receive(:get)
203
213
  .with("password_test@example.com_sandbox").and_return("saved_password")
204
- allow(Tastytrade::KeyringStore).to receive(:get)
214
+ allow(Tastytrade::FileStore).to receive(:get)
205
215
  .with("remember_test@example.com_sandbox").and_return(nil)
206
216
  end
207
217
 
@@ -216,7 +226,7 @@ RSpec.describe Tastytrade::SessionManager do
216
226
 
217
227
  context "without saved credentials" do
218
228
  before do
219
- allow(Tastytrade::KeyringStore).to receive(:get).and_return(nil)
229
+ allow(Tastytrade::FileStore).to receive(:get).and_return(nil)
220
230
  end
221
231
 
222
232
  it "returns nil" do
@@ -225,9 +235,9 @@ RSpec.describe Tastytrade::SessionManager do
225
235
  end
226
236
 
227
237
  it "handles errors gracefully" do
228
- allow(Tastytrade::KeyringStore).to receive(:get)
238
+ allow(Tastytrade::FileStore).to receive(:get)
229
239
  .with("password_test@example.com_production").and_return("password")
230
- allow(Tastytrade::KeyringStore).to receive(:get)
240
+ allow(Tastytrade::FileStore).to receive(:get)
231
241
  .with("remember_test@example.com_production").and_return(nil)
232
242
  allow(new_session).to receive(:login).and_raise(StandardError, "Login error")
233
243
 
@@ -238,13 +248,13 @@ RSpec.describe Tastytrade::SessionManager do
238
248
 
239
249
  describe "#clear_session!" do
240
250
  it "deletes all stored credentials" do
241
- expect(Tastytrade::KeyringStore).to receive(:delete)
251
+ expect(Tastytrade::FileStore).to receive(:delete)
242
252
  .with("token_test@example.com_production")
243
- expect(Tastytrade::KeyringStore).to receive(:delete)
253
+ expect(Tastytrade::FileStore).to receive(:delete)
244
254
  .with("remember_test@example.com_production")
245
- expect(Tastytrade::KeyringStore).to receive(:delete)
255
+ expect(Tastytrade::FileStore).to receive(:delete)
246
256
  .with("password_test@example.com_production")
247
- expect(Tastytrade::KeyringStore).to receive(:delete)
257
+ expect(Tastytrade::FileStore).to receive(:delete)
248
258
  .with("session_expiration_test@example.com_production")
249
259
 
250
260
  manager.clear_session!
@@ -261,7 +271,7 @@ RSpec.describe Tastytrade::SessionManager do
261
271
  describe "#saved_credentials?" do
262
272
  context "with saved password" do
263
273
  before do
264
- allow(Tastytrade::KeyringStore).to receive(:get)
274
+ allow(Tastytrade::FileStore).to receive(:get)
265
275
  .with("password_test@example.com_production").and_return("password")
266
276
  end
267
277
 
@@ -272,9 +282,9 @@ RSpec.describe Tastytrade::SessionManager do
272
282
 
273
283
  context "with saved remember token" do
274
284
  before do
275
- allow(Tastytrade::KeyringStore).to receive(:get)
285
+ allow(Tastytrade::FileStore).to receive(:get)
276
286
  .with("password_test@example.com_production").and_return(nil)
277
- allow(Tastytrade::KeyringStore).to receive(:get)
287
+ allow(Tastytrade::FileStore).to receive(:get)
278
288
  .with("remember_test@example.com_production").and_return("token")
279
289
  end
280
290
 
@@ -285,7 +295,7 @@ RSpec.describe Tastytrade::SessionManager do
285
295
 
286
296
  context "without saved credentials" do
287
297
  before do
288
- allow(Tastytrade::KeyringStore).to receive(:get).and_return(nil)
298
+ allow(Tastytrade::FileStore).to receive(:get).and_return(nil)
289
299
  end
290
300
 
291
301
  it "returns false" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tastytrade
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Hamamura
@@ -37,20 +37,6 @@ dependencies:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
39
  version: '2.2'
40
- - !ruby/object:Gem::Dependency
41
- name: keyring
42
- requirement: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - "~>"
45
- - !ruby/object:Gem::Version
46
- version: '0.4'
47
- type: :runtime
48
- prerelease: false
49
- version_requirements: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: '0.4'
54
40
  - !ruby/object:Gem::Dependency
55
41
  name: pastel
56
42
  requirement: !ruby/object:Gem::Requirement
@@ -215,6 +201,7 @@ executables:
215
201
  extensions: []
216
202
  extra_rdoc_files: []
217
203
  files:
204
+ - ".claude/commands/plan.md"
218
205
  - ".claude/commands/release-pr.md"
219
206
  - ".github/ISSUE_TEMPLATE/feature_request.md"
220
207
  - ".github/ISSUE_TEMPLATE/roadmap_task.md"
@@ -238,37 +225,66 @@ files:
238
225
  - exe/tastytrade
239
226
  - lib/tastytrade.rb
240
227
  - lib/tastytrade/cli.rb
228
+ - lib/tastytrade/cli/history_formatter.rb
229
+ - lib/tastytrade/cli/orders.rb
230
+ - lib/tastytrade/cli/positions_formatter.rb
241
231
  - lib/tastytrade/cli_config.rb
242
232
  - lib/tastytrade/cli_helpers.rb
243
233
  - lib/tastytrade/client.rb
244
- - lib/tastytrade/keyring_store.rb
234
+ - lib/tastytrade/file_store.rb
235
+ - lib/tastytrade/instruments/equity.rb
245
236
  - lib/tastytrade/models.rb
246
237
  - lib/tastytrade/models/account.rb
247
238
  - lib/tastytrade/models/account_balance.rb
248
239
  - lib/tastytrade/models/base.rb
240
+ - lib/tastytrade/models/buying_power_effect.rb
249
241
  - lib/tastytrade/models/current_position.rb
242
+ - lib/tastytrade/models/live_order.rb
243
+ - lib/tastytrade/models/order_response.rb
244
+ - lib/tastytrade/models/order_status.rb
245
+ - lib/tastytrade/models/trading_status.rb
246
+ - lib/tastytrade/models/transaction.rb
250
247
  - lib/tastytrade/models/user.rb
248
+ - lib/tastytrade/order.rb
249
+ - lib/tastytrade/order_validator.rb
251
250
  - lib/tastytrade/session.rb
252
251
  - lib/tastytrade/session_manager.rb
253
252
  - lib/tastytrade/version.rb
254
253
  - sig/tastytrade.rbs
255
254
  - spec/exe/tastytrade_spec.rb
256
255
  - spec/spec_helper.rb
256
+ - spec/tastytrade/cli/positions_spec.rb
257
257
  - spec/tastytrade/cli_accounts_spec.rb
258
258
  - spec/tastytrade/cli_auth_spec.rb
259
259
  - spec/tastytrade/cli_config_spec.rb
260
+ - spec/tastytrade/cli_env_login_spec.rb
260
261
  - spec/tastytrade/cli_helpers_spec.rb
261
262
  - spec/tastytrade/cli_interactive_spec.rb
262
263
  - spec/tastytrade/cli_logout_spec.rb
264
+ - spec/tastytrade/cli_orders_spec.rb
263
265
  - spec/tastytrade/cli_select_spec.rb
264
266
  - spec/tastytrade/cli_status_spec.rb
265
267
  - spec/tastytrade/client_spec.rb
266
- - spec/tastytrade/keyring_store_spec.rb
268
+ - spec/tastytrade/file_store_spec.rb
267
269
  - spec/tastytrade/models/account_balance_spec.rb
270
+ - spec/tastytrade/models/account_order_history_spec.rb
271
+ - spec/tastytrade/models/account_order_management_spec.rb
272
+ - spec/tastytrade/models/account_place_order_spec.rb
268
273
  - spec/tastytrade/models/account_spec.rb
269
274
  - spec/tastytrade/models/base_spec.rb
275
+ - spec/tastytrade/models/buying_power_effect_spec.rb
270
276
  - spec/tastytrade/models/current_position_spec.rb
277
+ - spec/tastytrade/models/live_order_json_spec.rb
278
+ - spec/tastytrade/models/live_order_spec.rb
279
+ - spec/tastytrade/models/order_response_spec.rb
280
+ - spec/tastytrade/models/order_status_spec.rb
281
+ - spec/tastytrade/models/trading_status_spec.rb
282
+ - spec/tastytrade/models/transaction_spec.rb
271
283
  - spec/tastytrade/models/user_spec.rb
284
+ - spec/tastytrade/order_edge_cases_spec.rb
285
+ - spec/tastytrade/order_spec.rb
286
+ - spec/tastytrade/order_validator_spec.rb
287
+ - spec/tastytrade/session_env_spec.rb
272
288
  - spec/tastytrade/session_manager_spec.rb
273
289
  - spec/tastytrade/session_spec.rb
274
290
  - spec/tastytrade_spec.rb
@@ -297,7 +313,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
297
313
  - !ruby/object:Gem::Version
298
314
  version: '0'
299
315
  requirements: []
300
- rubygems_version: 3.7.0
316
+ rubygems_version: 3.6.9
301
317
  specification_version: 4
302
318
  summary: Unofficial Ruby SDK for the Tastytrade API
303
319
  test_files: []
@@ -1,72 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "keyring"
4
-
5
- module Tastytrade
6
- # Secure credential storage using system keyring
7
- class KeyringStore
8
- SERVICE_NAME = "tastytrade-ruby"
9
-
10
- class << self
11
- # Store a credential securely
12
- #
13
- # @param key [String] The credential key
14
- # @param value [String] The credential value
15
- # @return [Boolean] Success status
16
- def set(key, value)
17
- return false if key.nil? || value.nil?
18
-
19
- backend.set_password(SERVICE_NAME, key.to_s, value.to_s)
20
- true
21
- rescue StandardError => e
22
- warn "Failed to store credential: #{e.message}"
23
- false
24
- end
25
-
26
- # Retrieve a credential
27
- #
28
- # @param key [String] The credential key
29
- # @return [String, nil] The credential value or nil if not found
30
- def get(key)
31
- return nil if key.nil?
32
-
33
- backend.get_password(SERVICE_NAME, key.to_s)
34
- rescue StandardError => e
35
- warn "Failed to retrieve credential: #{e.message}"
36
- nil
37
- end
38
-
39
- # Delete a credential
40
- #
41
- # @param key [String] The credential key
42
- # @return [Boolean] Success status
43
- def delete(key)
44
- return false if key.nil?
45
-
46
- backend.delete_password(SERVICE_NAME, key.to_s)
47
- true
48
- rescue StandardError => e
49
- warn "Failed to delete credential: #{e.message}"
50
- false
51
- end
52
-
53
- # Check if keyring is available
54
- #
55
- # @return [Boolean] True if keyring backend is available
56
- def available?
57
- !backend.nil?
58
- rescue StandardError
59
- false
60
- end
61
-
62
- private
63
-
64
- def backend
65
- @backend ||= Keyring.new
66
- rescue StandardError => e
67
- warn "Keyring not available: #{e.message}"
68
- nil
69
- end
70
- end
71
- end
72
- end