Skip to content

Commit 7ff2a70

Browse files
authored
Merge pull request #1 from jbertovic/develop
Integrated auth module from tdamertiradeclient
2 parents a638b47 + 44789ad commit 7ff2a70

File tree

7 files changed

+286
-34
lines changed

7 files changed

+286
-34
lines changed

Cargo.lock

Lines changed: 26 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
[package]
22
name = "tdacli"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
authors = ["Jas Bertovic <jas@bertovic.net>"]
55
edition = "2018"
66

77
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
88

99
[dependencies]
10-
tdameritradeclient = { git = "https://github.com/jbertovic/tdameritradeclient.git", tag = "v0.1.1" }
10+
tdameritradeclient = { git = "https://github.com/jbertovic/tdameritradeclient.git", tag = "v0.2.1" }
1111
clap = "2.33"

Readme.md

Lines changed: 103 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
## TDACLI
22

3-
A simple CLI wrapper around my tdameritradeclient library. You will need to set the token in an environment variable called `TDAUTHTOKEN`. You can go on [developer.tdameritrade.com](http://developer.tdameritrade.com) to see how to manually create a valid token.
3+
A simple CLI wrapper around my tdameritradeclient library. For help enter `tdacli --help`. This will give you access to help and further subcommands.
44

5-
For help enter `tdacli --help`. This will give you access to help and further subcommands.
6-
7-
Current subcommands are: quote, history, optionchain, userprincipals, account.
5+
Current subcommands are: quote, history, optionchain, userprincipals, account, auth, refresh, weblink. See below for description on output of `tdaci --help` in the CLI Commands section
86

7+
Environmental Variable Requirements:
8+
- `TDAUTHTOKEN` on subcommands: account, history, optionchain, quote, userprincipals
9+
- `TDREFRESHTOKEN` on subcommands: refresh
10+
- `TDCODE` on subcommand: auth
11+
- No Env Variable on subcommand: weblink
912

1013
## Example
1114

12-
an example usage piped into jq running on linux
13-
15+
an example usage piped into jq running on linux. Assumes `TDAUTHTOKEN` env variable holds valid token.
1416

1517
```
1618
> tdacli quote SPY,INTC,VNQ | jq '.[] | {symbol, mark, bidPrice, askPrice}'
@@ -34,11 +36,61 @@ an example usage piped into jq running on linux
3436
}
3537
```
3638

37-
## CLI commands
39+
## Authorization from scratch
40+
41+
### 1) Fetch code using weblink
42+
Use the `weblink` subcommand along with registered app on developer.tdameritrade.com to get an authorization link. When you register an app you will have a `consumer_key` (referred through out as clientid) and a `redirect_uri`. I recommend using a redirecturi that is your localhost (`https://127.0.0.1:8080/`). This way you can copy the returned code directly from the query bar in the browser. The below Consumer Key is only an example.
43+
44+
```
45+
> tdacli weblink J3ROAVSNNFTLC9RJE4BD2DO2WJABCDEF https://127.0.0.1:8080/
46+
https://auth.tdameritrade.com/auth?response_type=code&redirect_uri=https%3A%2F%2F127.0.0.1%3A8080%2F&client_id=J3ROAVSNNFTLC9RJE4BD2DO2WJ9JE4DG%40AMER.OAUTHAP
47+
48+
```
49+
50+
Visit this link and authorize your access directly with TDameritrade. You will receive the code in the query bar. Only copy the encoded string after `code=`. Assign this to the environment variable `TDCODE`.
51+
52+
53+
54+
### 2) Use code to retrieve token and refresh_token
55+
56+
From step 1 above with `TDCODE` env variable assigned.
57+
58+
```
59+
> tdacli auth J3ROAVSNNFTLC9RJE4BD2DO2WJABCDEF https://127.0.0.1:8080/
60+
{"Token": "UZfU1e9dhw9zdq26+vJa1tERNhfaa4lFXqgfzeVW+HOEdRKHSDvnq0lepMd.....long string truncated",
61+
"Refresh": "a1tERNhfaa4lFXqgfzeVW+HOEdRKHSDvnq0lepMdvJa1tERNhfa....long string truncated"}
62+
```
63+
64+
Assign the Refresh token to TDREFRESHTOKEN and the Token to TDAUTHTOKEN. You can go ahead and run any of the other subcommands with TDAUTHTOKEN set.
65+
66+
A refresh token lasts for 90 days and can be used to get a valid token to access tdameritrade API. The token is only valid for 30 min before expiring. Reuse the same or new refresh token to renew.
67+
68+
69+
### 3) Use refresh to maintain an active token
70+
71+
Assumes REFRESHTOKEN is set and valid.
72+
73+
```
74+
> tdacli refresh J3ROAVSNNFTLC9RJE4BD2DO2WJABCDEF
75+
zdq26+vJaNhfaa4lFXqgfzeVW+HOEdRKHSDzdq26+vJa1tERNhfaa4lFXqgfzeVW+HOEdRKHSDzdq26+vJa1tERNhfaa4...long string truncated
76+
```
77+
78+
Use the returned value to set TDAUTHTOKEN.
3879

80+
In bash you can automate this with:
3981
```
40-
>tdacli --help
41-
TDAmeritrade API CLI 0.1.0
82+
export TDAUTHTOKEN=$(tdacli refresh J3ROAVSNNFTLC9RJE4BD2DO2WJABCDEF)
83+
```
84+
85+
Not sure how to do this in windows? Please DM me if you know.
86+
87+
## CLI Commands
88+
89+
### Output of main help
90+
91+
```
92+
> tdacli --help
93+
TDAmeritrade API CLI 0.2.0
4294
Command Line Interface into tdameritradeclient rust library
4395
4496
USAGE:
@@ -50,19 +102,59 @@ FLAGS:
50102
51103
SUBCOMMANDS:
52104
account Retrieve account information for <account_id>
105+
auth Retrieves refresh_token using authorization_code grant type
53106
help Prints this message or the help of the given subcommand(s)
54107
history Retrieve history for one <symbol>.
55108
optionchain Retrieve option chain for one <symbol>
56109
quote Retrieve quotes for requested symbols
110+
refresh Fetch valid token or renew refresh_token using a refresh_token grant type
57111
userprincipals Retrieves User Principals
112+
weblink Gives you the url to get authorization code from TDAmeritrade
58113
59-
A valid token must be set in env variable: TDAUTHTOKEN.
114+
Check env variable requirements for each subcommand.
115+
Token can be retrieved using 'refresh' subcommand if you have a valid refresh_token.
116+
Token can also be issued by using 'weblink' subcommand first to retrieve 'authorization_code'
117+
and 'auth' subcommand to issue new token and refresh_token.
60118
'*' indicates default value in subcommand help information.
61119
```
62120

121+
### history help
122+
Included one help output of subcommand as an example. All subcommands have `--help` option to help understand usage.
123+
124+
```
125+
> tdacli history --help
126+
tdacli-history
127+
Retrieve history for one <symbol>.
128+
129+
USAGE:
130+
tdacli history [OPTIONS] <symbol> [ARGS]
131+
132+
FLAGS:
133+
-h, --help Prints help information
134+
135+
OPTIONS:
136+
--freq <freq> Defines number of freq_types to show: minute: 1*,5,10,15,30 | daily: 1* | weekly: 1* |
137+
monthly: 1*
138+
--ftype <freq_type> Defines freq of new candle by period_type: day: minute* | month: daily, weekly* | year:
139+
daily, weekly, monthly* | ytd: daily, weekly*
140+
--period <period> Defines number of periods to show; day: 1,2,3,4,5,10* | month: 1*,2,3,6 | year:
141+
1*,2,3,5,10,15,20 | ytd: 1*
142+
--ptype <period_type> Defines period type: day, month, year, ytd
143+
144+
ARGS:
145+
<symbol> Symbol of instrument.
146+
<startdate> Defines start date in epoch format. <period> should not be provided
147+
<enddate> Defines end date epoch format. Default is previous trading day.
148+
149+
Think of the frequency as the size of a candle on the chart or how to divide the ticks.
150+
and the period as the term or total length of the history.
151+
'*' indicates default value.
152+
```
153+
63154

64155
### TODO
65156

66157
- [ ] add option for date calculations on History epoch data stamps
67158
- [ ] Consider adding date conversion using chrono package
68-
- [ ] once orders are complete on [TDAClient](https://github.com/jbertovic/tdameritradeclient) than to new subcommand
159+
- [ ] orders - adding, deleting, listing
160+
- [ ] potential to integrate a json query language on output

src/auth.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use clap::ArgMatches;
2+
use tdameritradeclient::auth::{getcodeweblink, gettoken_fromrefresh, getrefresh_fromrefresh, TDauth};
3+
4+
/// Create a link to use to get an authorization_code from tdameritrade
5+
/// Code can be used to fetch a token and refresh token in the `auth` subcommand
6+
pub fn weblink(args: &ArgMatches) {
7+
println!("{}",
8+
getcodeweblink(args.value_of("clientid").unwrap(), args.value_of("redirect").unwrap()));
9+
}
10+
/// Fetch updated `token` or `refresh_token` from a current `refresh_token`
11+
pub fn auth(args: &ArgMatches, code: String) {
12+
match args.value_of("clientid") {
13+
Some(clientid) => {
14+
match args.value_of("redirect") {
15+
Some(redirect) => {
16+
let decoded = !args.is_present("decoded");
17+
let tdauth = TDauth::new_fromcode(&code, clientid, redirect, decoded);
18+
let (t, r) = tdauth.gettokens();
19+
println!("{{\"Token\": \"{}\", \"Refresh\": \"{}\"}}", t, r)
20+
},
21+
None => println!("{{ \"error\": \"Missing redirect\"}}"),
22+
}
23+
},
24+
None => println!("{{ \"error\": \"Missing clientid\"}}"),
25+
}
26+
}
27+
/// Fetch updated `token` or `refresh_token` from a current `refresh_token`
28+
pub fn refresh(args: &ArgMatches, rtoken: String) {
29+
match args.value_of("clientid") {
30+
Some(clientid) => {
31+
// do i need to renew refresh or only token?
32+
// need to update tdameritradeclient to include getrefresh_fromrefresh()
33+
let token = if args.is_present("updaterefresh") {
34+
gettoken_fromrefresh(&rtoken, clientid)
35+
} else {
36+
getrefresh_fromrefresh(&rtoken, clientid)
37+
};
38+
println!("{}", token);
39+
}
40+
None => println!("{{ \"error\": \"Missing clientid\"}}"),
41+
}
42+
}

0 commit comments

Comments
 (0)