schwab_rb 1.0.0 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33c611ab09700a163e183723beb5d4434d12b1af49a12949b161f7319a56bceb
4
- data.tar.gz: e900ce468adadc78a6c065cc2198684658cf9519cfc2afd35fe8818929f4171c
3
+ metadata.gz: a575cc586047d31d897d0ec4ba6d35afa1c2c97938a8dbf3e82b292d3b5d74a2
4
+ data.tar.gz: 3c859570ce9831b5b30bc2798d9083d2110d7e9be09065b33a312292334d7963
5
5
  SHA512:
6
- metadata.gz: 4f8ba13ee3acd298b08c7e0ac0f0a2af2c0c8a2f22815e075a837fe4b5109f33bc4e6b526b5fc0c85c7017c5a0ca63957a8b51458b2db5dd1baf2533a765e201
7
- data.tar.gz: 3953d141ecc0440d829d12820259d59d8253bf8377f05a499d859f5a5368d2b4454489a8cc9b9003b09048351232543dd2ed2a6f3674191d6a911a720e4baa46
6
+ metadata.gz: 3c2a2709207b61685083ff764585ccafe8a722ae798faf4c469fe75617585d65ae89847aa63d4b17bd9315a504a234d212b63226c40acfb2324f4e28199e7fc6
7
+ data.tar.gz: 85799a5ec440620b5c3756b2d86ac007e10d5c5c08be8fd08dc793232c0fb2ad1f918787a8fede962a797cecd7f4bef3cc222a121c285faed8ac06e364551355
@@ -16,7 +16,9 @@
16
16
  "Bash(find:*)",
17
17
  "Bash(git pull:*)",
18
18
  "Bash(git fetch:*)",
19
- "Bash(git merge:*)"
19
+ "Bash(git merge:*)",
20
+ "Bash(git stash:*)",
21
+ "Bash(git cherry-pick:*)"
20
22
  ],
21
23
  "deny": [],
22
24
  "ask": []
@@ -16,7 +16,7 @@ Fields = SchwabRb::Stream::Fields
16
16
  client = SchwabRb::Auth.init_client_easy(
17
17
  ENV.fetch("SCHWAB_API_KEY"),
18
18
  ENV.fetch("SCHWAB_APP_SECRET"),
19
- ENV.fetch("APP_CALLBACK_URL")
19
+ ENV.fetch("SCHWAB_APP_CALLBACK_URL")
20
20
  )
21
21
 
22
22
  stream = SchwabRb::Stream::Client.new(client)
@@ -16,7 +16,7 @@ Fields = SchwabRb::Stream::Fields
16
16
  client = SchwabRb::Auth.init_client_easy(
17
17
  ENV.fetch("SCHWAB_API_KEY"),
18
18
  ENV.fetch("SCHWAB_APP_SECRET"),
19
- ENV.fetch("APP_CALLBACK_URL")
19
+ ENV.fetch("SCHWAB_APP_CALLBACK_URL")
20
20
  )
21
21
 
22
22
  stream = SchwabRb::Stream::Client.new(client)
@@ -19,7 +19,7 @@ module SchwabRb
19
19
  "SchwabClientCustomerId" => @customer_id,
20
20
  "SchwabClientCorrelId" => @correl_id,
21
21
  "parameters" => {
22
- "Authorization" => "Bearer #{access_token}",
22
+ "Authorization" => access_token,
23
23
  "SchwabClientChannel" => channel,
24
24
  "SchwabClientFunctionId" => function_id
25
25
  }
@@ -31,7 +31,11 @@ module SchwabRb
31
31
 
32
32
  return null_logger if [:null, "/dev/null"].include?(log_destination)
33
33
 
34
- setup_log_file(log_destination) if log_destination.is_a?(String) && log_destination != "STDOUT"
34
+ if log_destination.is_a?(String) && log_destination.upcase == "STDOUT"
35
+ log_destination = $stdout
36
+ else
37
+ setup_log_file(log_destination)
38
+ end
35
39
 
36
40
  ::Logger.new(log_destination, "weekly").tap do |log|
37
41
  log.level = parse_log_level(config.log_level)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SchwabRb
4
- VERSION = "1.0.0"
4
+ VERSION = "1.0.1"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: schwab_rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joseph Platta
@@ -237,7 +237,6 @@ files:
237
237
  - LICENSE.txt
238
238
  - README.md
239
239
  - Rakefile
240
- - doc/ACCOUNT_MANAGEMENT.md
241
240
  - doc/LOGGING.md
242
241
  - doc/PLACE_ORDER_SAMPLES.md
243
242
  - doc/QUICK_START.md
@@ -1,297 +0,0 @@
1
- # Account Management Guide
2
-
3
- The schwab_rb gem provides a secure and convenient way to manage multiple Schwab accounts using friendly account names instead of exposing account numbers or hashes in your code.
4
-
5
- ## Table of Contents
6
-
7
- - [Overview](#overview)
8
- - [Quick Start](#quick-start)
9
- - [Configuration](#configuration)
10
- - [Account Names Setup](#account-names-setup)
11
- - [Using Account Names](#using-account-names)
12
- - [Security Best Practices](#security-best-practices)
13
- - [Troubleshooting](#troubleshooting)
14
- - [API Reference](#api-reference)
15
-
16
- ## Overview
17
-
18
- Schwab's API requires account hashes for most operations, which:
19
- - Change periodically (accounts get "rehashed")
20
- - Are inconvenient to look up and copy
21
- - Expose sensitive account numbers in code
22
-
23
- schwab_rb provides an account name mapping system that:
24
- - **Increases Security**: Account numbers never appear in your code
25
- - **Improves Usability**: Reference accounts by friendly names like "my_trading_account"
26
- - **Auto-Updates**: Account hashes refresh automatically
27
- - **Handles Staleness**: Retries failed requests with fresh hashes
28
-
29
- ## Quick Start
30
-
31
- ### 1. Create Account Names File
32
-
33
- Create `~/.schwab_rb/account_names.json` with your account mappings:
34
-
35
- ```json
36
- {
37
- "my_trading_account": "12345678",
38
- "my_ira": "87654321",
39
- "my_roth_ira": "11223344"
40
- }
41
- ```
42
-
43
- ### 2. Initialize Client and Fetch Hashes
44
-
45
- ```ruby
46
- require "schwab_rb"
47
-
48
- # Initialize client
49
- client = SchwabRb::Auth.init_client_easy(
50
- ENV['SCHWAB_API_KEY'],
51
- ENV['SCHWAB_APP_SECRET'],
52
- ENV['SCHWAB_APP_CALLBACK_URL'],
53
- ENV['SCHWAB_TOKEN_PATH']
54
- )
55
-
56
- # Fetch account numbers and populate hashes
57
- client.get_account_numbers
58
- ```
59
-
60
- This automatically creates `~/.schwab_rb/account_hashes.json` with the name-to-hash mappings.
61
-
62
- ### 3. Use Account Names in API Calls
63
-
64
- ```ruby
65
- # Get account by name
66
- account = client.get_account(account_name: "my_trading_account")
67
-
68
- # Place order using account name
69
- order = client.place_order(order_spec, account_name: "my_ira")
70
-
71
- # Get transactions
72
- transactions = client.get_transactions(account_name: "my_roth_ira")
73
- ```
74
-
75
- ## Configuration
76
-
77
- ### Default Paths
78
-
79
- By default, schwab_rb uses:
80
- - `schwab_home`: `~/.schwab_rb`
81
- - `account_hashes_path`: `~/.schwab_rb/account_hashes.json`
82
- - `account_names_path`: `~/.schwab_rb/account_names.json`
83
-
84
- ### Custom Paths
85
-
86
- #### Via Environment Variables
87
-
88
- ```bash
89
- export SCHWAB_HOME="/custom/path"
90
- export SCHWAB_ACCOUNT_HASHES_PATH="/custom/path/hashes.json"
91
- export SCHWAB_ACCOUNT_NAMES_PATH="/custom/path/names.json"
92
- ```
93
-
94
- #### Via Ruby Configuration
95
-
96
- ```ruby
97
- SchwabRb.configure do |config|
98
- config.schwab_home = "/custom/path"
99
- config.account_hashes_path = "/custom/path/hashes.json"
100
- config.account_names_path = "/custom/path/names.json"
101
- end
102
- ```
103
-
104
- ## Account Names Setup
105
-
106
- ### File Format
107
-
108
- `account_names.json` is a simple JSON object mapping friendly names to 8-digit account numbers:
109
-
110
- ```json
111
- {
112
- "descriptive_name": "account_number"
113
- }
114
- ```
115
-
116
- ## Using Account Names
117
-
118
- ### Methods Supporting Account Names
119
-
120
- All account-specific methods support both `account_hash` and `account_name`:
121
-
122
- - `get_account(account_name:)` or `get_account(account_hash)`
123
- - `get_order(order_id, account_name:)`
124
- - `cancel_order(order_id, account_name:)`
125
- - `get_account_orders(account_name:)`
126
- - `place_order(order_spec, account_name:)`
127
- - `replace_order(order_id, order_spec, account_name:)`
128
- - `preview_order(order_spec, account_name:)`
129
- - `get_transactions(account_name:)`
130
- - `get_transaction(activity_id, account_name:)`
131
-
132
- ### Calling Patterns
133
-
134
- ```ruby
135
- # Using account name (keyword argument) - RECOMMENDED
136
- client.get_account(account_name: "my_trading_account")
137
-
138
- # Using account hash (positional argument) - still works
139
- client.get_account("ABC123HASH")
140
-
141
- # Using account hash (keyword argument)
142
- client.get_account(account_hash: "ABC123HASH")
143
-
144
- # Priority: account_name always takes precedence
145
- client.get_account("HASH1", account_name: "my_ira") # Uses "my_ira"
146
- ```
147
-
148
- ### List Available Accounts
149
-
150
- ```ruby
151
- # Get list of configured account names
152
- names = client.available_account_names
153
- # => ["my_trading_account", "my_ira", "my_roth_ira"]
154
-
155
- puts "Available accounts:"
156
- names.each { |name| puts " - #{name}" }
157
- ```
158
-
159
- ## Security
160
-
161
- ### 1. Protect Your Files
162
-
163
- The account files contain sensitive information:
164
-
165
- ```bash
166
- # Set restrictive permissions
167
- chmod 600 ~/.schwab_rb/account_names.json
168
- chmod 600 ~/.schwab_rb/account_hashes.json
169
-
170
- # Verify permissions
171
- ls -l ~/.schwab_rb/
172
- ```
173
-
174
- ### 2. Don't Commit to Version Control
175
-
176
- Add to `.gitignore`:
177
-
178
- ```
179
- .schwab_rb/
180
- **/account_names.json
181
- **/account_hashes.json
182
- ```
183
-
184
- ### 3. Environment-Specific Configs
185
-
186
- Use different configs per environment:
187
-
188
- ```ruby
189
- # In development
190
- SchwabRb.configure do |config|
191
- config.schwab_home = "~/.schwab_rb/development"
192
- end
193
-
194
- # In production
195
- SchwabRb.configure do |config|
196
- config.schwab_home = ENV['SCHWAB_CONFIG_PATH']
197
- end
198
- ```
199
-
200
- ## Troubleshooting
201
-
202
- ### Account Name Not Found
203
-
204
- **Error**: `Account name 'my_account' not found in account hashes.`
205
-
206
- **Solutions**:
207
- 1. Run `client.get_account_numbers` to populate hashes
208
- 2. Check spelling in `account_names.json`
209
- 3. Verify account number is correct
210
-
211
- ### Account Numbers File Missing
212
-
213
- **Error**: `Account names file not found at ~/.schwab_rb/account_names.json`
214
-
215
- **Solutions**:
216
- 1. Create the file with your account mappings (see [Quick Start](#quick-start))
217
- 2. Set custom path via config if file is elsewhere
218
-
219
- ### Account Not in API Response
220
-
221
- **Warning**: `Account 'old_account' (98765432) not found in API response.`
222
-
223
- This warning means an account in your `account_names.json` wasn't returned by the API.
224
-
225
- **Possible Causes**:
226
- - Account was closed
227
- - Wrong account number in `account_names.json`
228
- - Account not accessible with current API credentials
229
-
230
- **Actions**:
231
- 1. Verify account status on Schwab website
232
- 2. Check account number in `account_names.json`
233
- 3. Remove closed accounts from config
234
-
235
- ### Stale Account Hashes
236
-
237
- The gem automatically handles stale hashes:
238
- 1. Request fails with stale hash
239
- 2. Calls `get_account_numbers` to refresh
240
- 3. Retries request with new hash
241
- 4. If still fails, raises original error
242
-
243
- ## API Reference
244
-
245
- ### Client Methods
246
-
247
- #### `available_account_names`
248
-
249
- Returns list of configured account names.
250
-
251
- ```ruby
252
- client.available_account_names
253
- # => ["my_trading_account", "my_ira"]
254
- ```
255
-
256
- **Returns**: `Array<String>` - List of account names from `account_names.json`
257
- **Returns**: `[]` - Empty array if file doesn't exist
258
-
259
- #### Account-Specific Methods
260
-
261
- All methods accept either `account_name:` or `account_hash`:
262
-
263
- ```ruby
264
- # Get account
265
- client.get_account(account_name: "my_trading_account")
266
- client.get_account("ABC123HASH")
267
-
268
- # Get orders
269
- client.get_account_orders(account_name: "my_ira", max_results: 10)
270
-
271
- # Place order
272
- client.place_order(order_spec, account_name: "my_trading_account")
273
- ```
274
-
275
- ### AccountHashManager
276
-
277
- Direct access to the account hash manager:
278
-
279
- ```ruby
280
- manager = SchwabRb::AccountHashManager.new
281
-
282
- # Get available names
283
- manager.available_account_names
284
- # => ["my_trading_account", "my_ira"]
285
-
286
- # Get hash by name
287
- manager.get_hash_by_name("my_trading_account")
288
- # => "ABC123HASH"
289
-
290
- # Get all hashes
291
- manager.get_all_hashes
292
- # => {"my_trading_account" => "ABC123HASH", "my_ira" => "XYZ789HASH"}
293
- ```
294
-
295
- ---
296
-
297
- For more information, see the [main README](../README.md) or visit [github.com/jwplatta/schwab_rb](https://github.com/jwplatta/schwab_rb).