package Ġshell Ċ Ċ import Ġhttp client . HttpClient Ċ import Ġio . ktor . http . HttpStatusCode . Companion . OK Ċ import Ġkotlinx . serialization . decode FromString Ċ import Ġkotlinx . serialization . json . encode ToJson Element Ċ import Ġmodel . Application Config Ċ import Ġmodel . LoggedIn Ċ import Ġmodel . Login Ċ import Ġmodel . Order Side Ċ import Ġmodel . Orders Response Ċ import Ġmodel . Session Ċ import Ġmodel . to Session Ċ import Ġro bin hood . Api Urls Ċ import Ġro bin hood . getPort fol ios Ċ import Ġro bin hood . get Quote Ċ import Ġro bin hood . make Order Ċ import Ġutil . can Be Double Ċ import Ġutil . can Be Int Ċ import Ġutil . read Content Ċ import Ġutil . read Input S af ely Ċ import Ġutil . round Ċ Ċ class ĠShell Service ( private Ġval Ġapplication Config : ĠApplication Config , Ġprivate Ġval Ġclient : ĠHttpClient ) Ġ{ ĊĠĠĠ Ġfun Ġneeds Login (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( application Config . session . accessToken . isBlank () Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠ Ġapplication Config . session . accessToken . isBlank () Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠ Ġapplication Config . session . expires In Ġ== Ġ 0 Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠ Ġapplication Config . session . account . contains (" XXXXXXXX ") ĊĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġsuspend Ġfun Ġlogin (): ĠSession Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġeither Ġget Ġthe Ġcredentials Ġfrom Ġapplication . conf Ġor Ġfrom Ġconsole ĊĠĠĠĠĠĠĠ Ġvar Ġlogin Ġ= Ġobtain Login Credentials ( true ) ĊĠĠĠĠĠĠĠ Ġvar Ġpayload Ġ= ĠRob in hood Shell . Json . encode ToJson Element ( login ) ĊĠĠĠĠĠĠĠ Ġvar Ġlogin Response Ġ= Ġclient . post ( Api Urls . login , Ġpayload ) ĊĠĠĠĠĠĠĠ Ġvar Ġfirst Attempt Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġwhile Ġ( login Response . status Ġ!= ĠOK ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! first Attempt ) Ġprintln (" Could Ġnot Ġlogin , Ġtry Ġagain ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogin Ġ= Ġobtain Login Credentials ( false ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpayload Ġ= ĠRob in hood Shell . Json . encode ToJson Element ( login ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogin Response Ġ= Ġclient . post ( Api Urls . login , Ġpayload ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfirst Attempt Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġlogin Response Content Ġ= Ġlogin Response . read Content () ĊĊĠĠĠĠĠĠĠ Ġ// Ġcheck Ġfor Ġ 2 fa Ġcode ĊĠĠĠĠĠĠĠ Ġval Ġlogged In Response Ġ= Ġif Ġ( login Response Content . contains ("\" m fa _ required \": true ")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" Enter Ġ 2 FA Ġcode :") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġcode Ġ= Ġread Line ()?. trim ()?. toInt () Ġ?: Ġ- 1 ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlogin 2 FA Ġ= ĠLogin ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġusername Ġ= Ġlogin . username , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpassword Ġ= Ġlogin . password , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm fa Code Ġ= Ġcode ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġm fa Payload Ġ= ĠRob in hood Shell . Json . encode ToJson Element ( login 2 FA ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġm fa Response Ġ= Ġclient . post ( Api Urls . login , Ġm fa Payload ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġm fa Response Content Ġ= Ġm fa Response . read Content () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġneed Ġto Ġtry Ġthis Ġto Ġfailure . ĠApp arent ly , Ġthere Ġis Ġa Ġlimit , Ġmaybe Ġ 5 Ġattempts ? ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( m fa Response . status Ġ!= ĠOK Ġ&& Ġm fa Response Content . contains (" Please Ġenter Ġa Ġvalid Ġcode .")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" Please Ġenter Ġa Ġvalid Ġcode : Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcode Ġ= Ġread Line ()?. trim ()?. toInt () Ġ?: Ġ- 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm fa Payload Ġ= ĠRob in hood Shell . Json . encode ToJson Element ( login 2 FA . copy ( m fa Code Ġ= Ġcode )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm fa Response Ġ= Ġclient . post ( Api Urls . login , Ġm fa Payload ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġm fa Response Content Ġ= Ġm fa Response . read Content () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġm fa Response Content ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogin Response Content ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġprintln () ĊĊĠĠĠĠĠĠĠ Ġval Ġlogged In Ġ= ĠRob in hood Shell . Json . decode FromString < LoggedIn >( logged In Response ) ĊĠĠĠĠĠĠĠ Ġval Ġaccount Ġ= Ġget Port fol ios ( client , Ġlogged In . accessToken ). results . first (). account Ġ// ĠTODO : Ġconfigure Ġand Ġuse Ġaccount ĠAPI Ġinstead Ġof Ġthis ĊĠĠĠĠĠĠĠ Ġreturn Ġlogged In . to Session ( account ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġobtain Login Credentials ( try Using From Config : ĠBoolean Ġ= Ġfalse ): ĠLogin Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġusername Ġ= Ġif Ġ( try Using From Config ) Ġapplication Config . credentials . username Ġelse Ġread Input S af ely (" Username : Ġ") ĊĠĠĠĠĠĠĠ Ġval Ġpassword Ġ= Ġif Ġ( try Using From Config ) Ġapplication Config . credentials . password Ġelse Ġread Input S af ely (" Password : Ġ", Ġtrue ) ĊĊĠĠĠĠĠĠĠ Ġreturn ĠLogin ( username , Ġpassword ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġsuspend Ġfun Ġmake Order ( side : ĠOrder Side , Ġsession : ĠSession , Ġclient : ĠHttpClient , Ġbe arer Token : ĠString ): ĠOrders Response ? Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġsymbol Ġ= Ġread Input S af ely (" Stock ĠSymbol : Ġ"). uppercase () ĊĠĠĠĠĠĠĠ Ġvar Ġquote Ġ= Ġget Quote ( symbol , Ġclient , Ġbe arer Token ) ĊĊĠĠĠĠĠĠĠ Ġwhile Ġ( quote Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" Bad Ġsymbol , Ġtry Ġagain ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsymbol Ġ= Ġread Input S af ely (" Stock ĠSymbol : Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġquote Ġ= Ġget Quote ( symbol . uppercase (), Ġclient , Ġbe arer Token ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġtype Ġ= Ġread Input S af ely (" Order Ġtype Ġ( market , Ġlimit ): Ġ"). let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġinput Ġ= Ġit . lowercase () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( input Ġ!= Ġ" market " Ġ&& Ġinput Ġ!= Ġ" limit ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinput Ġ= Ġread Input S af ely (" Bad Ġorder Ġtype , Ġtry Ġagain . ĠOrder Ġtype Ġ( market , Ġlimit ): Ġ"). lowercase () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinput ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġprice Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( type Ġ== Ġ" limit ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġinput Ġ= Ġread Input S af ely (" Limit Ġprice : Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ(! input . can Be Double ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinput Ġ= Ġread Input S af ely (" Not Ġvalid Ġinput Ġfor Ġprice , Ġtry Ġagain . ĠLimit Ġprice : Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinput . toDouble () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġtime In Force Ġ= Ġread Input S af ely (" Time Ġduration ĠGood Ġfor ĠDay Ġor ĠGood ĠT ill ĠC anceled Ġ( g fd , Ġg tc ): Ġ"). let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġinput Ġ= Ġit . lowercase () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( input Ġ!= Ġ" g fd " Ġ&& Ġinput Ġ!= Ġ" gt c ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinput Ġ= Ġread Input S af ely (" Bad Ġtime Ġduration , Ġtry Ġagain . ĠGood Ġfor ĠDay Ġor ĠGood ĠT ill ĠC anceled Ġ( g fd , Ġg tc ): Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinput ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġquantity Ġ= Ġread Input S af ely (" Quantity : Ġ"). let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġinput Ġ= Ġit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( type Ġ== Ġ" limit ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ(! input . can Be Int ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinput Ġ= Ġread Input S af ely (" Not Ġvalid Ġinput Ġfor Ġquantity , Ġtry Ġagain Ġ( limit Ġorder Ġcannot Ġhave Ġfraction al Ġquantity ). ĠQuantity : Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ(! input . can Be Double ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinput Ġ= Ġread Input S af ely (" Not Ġvalid Ġinput Ġfor Ġquantity , Ġtry Ġagain . ĠQuantity : Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinput . toDouble () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġquote Ġ= Ġget Quote ( symbol , Ġclient , Ġbe arer Token ) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( quote Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" quote Ġis Ġunexpected ly Ġbad Ġand Ġreturned Ġnull ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġmake Order ( session . account , Ġquote . instrument , Ġif Ġ( type Ġ== Ġ" market " Ġ|| Ġprice Ġ== Ġnull ) Ġ( quote . ask Price Ġ* Ġ 1 . 0 5 ). round ( 2 ) Ġelse Ġprice , Ġquantity , Ġside . name , Ġsymbol . uppercase (), Ġtime In Force , Ġtype Ġ= Ġtype , Ġclient Ġ= Ġclient , Ġbe arer Token Ġ= Ġbe arer Token ) ĊĠĠĠ Ġ} Ċ } Ċ