Skip to content

Commit

Permalink
Pass full json message in account streamer; update README with instru… (
Browse files Browse the repository at this point in the history
#2)

* Pass full json message in account streamer; update README with instructions

* Inherit secrets in github workflow

* Jest config updates and dotenv

* Remove customer Id param from customer resource fetch calls
  • Loading branch information
dmoss18 authored Jul 3, 2023
1 parent 3b2ac87 commit 29e424a
Show file tree
Hide file tree
Showing 19 changed files with 62 additions and 125 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/check-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,9 @@ jobs:
- run: npm install
- run: npm run lint
- run: npm run test
env:
BASE_URL: ${{ secrets.BASE_URL }}
API_USERNAME: ${{ secrets.API_USERNAME }}
API_PASSWORD: ${{ secrets.API_PASSWORD }}
API_ACCOUNT_NUMBER: ${{ secrets.API_ACCOUNT_NUMBER }}
- run: npm run build
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,44 @@ const optionChain = await tastytradeClient.instrumentsService.getOptionChain('AA
quoteStreamer.subscribe(optionChain[0]['streamer-symbol'], handleMarketDataReceived)
```

### Account Streamer
```js
const TastytradeApi = require("@tastytrade/api")
const TastytradeClient = TastytradeApi.default
const { AccountStreamer, QuoteStreamer } = TastytradeApi
const _ = require('lodash')

function handleStreamerMessage(json) {
console.log('streamer message received: ', json)
}

function handleStreamerStateChange(streamerState) {
console.log('streamer state changed: ', streamerState)
}

const tastytradeClient = new TastytradeClient(baseUrl, accountStreamerUrl)
const accountStreamer = tastytradeClient.accountStreamer
const loginResponse = await tastytradeClient.sessionService.login(usernameOrEmail, password)
const accounts = await tastytradeClient.accountsAndCustomersService.getCustomerAccounts()
const accountNumbers = _.map(accounts, account => _.get(account, 'account.account-number'))
await accountStreamer.start()
await accountStreamer.subscribeToAccounts(accountNumbers)
accountStreamer.addMessageObserver(handleStreamerMessage)
accountStreamer.addStreamerStateObserver(handleStreamerStateChange)
```

You should then be able to place a trade and see live status updates for the order come through via `handleStreamerMessage`.

## Running in Node
The `cometd` package has an explicit reference to `window`, so there's not a perfect way to run this code in a NodeJs. You could fake the `window` object to get it running. You'll have to `npm install ws` and do this:

```js
const WebSocket = require('ws')

global.WebSocket = WebSocket
global.window = { WebSocket, setTimeout, clearTimeout }
```

## Building Locally
`npm run build`
Outputs everything to `dist/`
Expand Down
48 changes: 4 additions & 44 deletions examples/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"lint": "next lint"
},
"dependencies": {
"@dxfeed/api": "^1.1.0",
"@types/lodash": "^4.14.182",
"axios": "^1.3.4",
"dayjs": "^1.11.1",
Expand Down
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
setupFiles: ["dotenv/config"],
testEnvironment: 'node',
transform: {
'^.+\\.ts?$': 'ts-jest',
Expand Down
4 changes: 2 additions & 2 deletions lib/account-streamer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export type Disposer = () => void

export type StreamerStateObserver = (streamerState: STREAMER_STATE) => void

export type StreamerMessageObserver = (messageType: string, action: string, status: string) => void
export type StreamerMessageObserver = (json: object) => void

const REQUEST_ID = 'request-id'

Expand Down Expand Up @@ -368,7 +368,7 @@ export class AccountStreamer {
this.logger.info(json)

const action = json.action as string
this.streamerMessageObservers.forEach(observer => observer(json.type as string, action, json.status as string))
this.streamerMessageObservers.forEach(observer => observer(json))
if (action) {
if (action === MessageAction.HEARTBEAT) {
// schedule next heartbeat
Expand Down
12 changes: 6 additions & 6 deletions lib/services/accounts-and-customers-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ export default class AccountsAndCustomersService {
}

//Customers: Operations about customers
async getCustomerResource(customerId: string){
async getCustomerResource(){
//Get a full customer resource.
const customerResource = (await this.httpClient.getData(`/customers/${customerId}`, {}, {}))
const customerResource = (await this.httpClient.getData(`/customers/me`, {}, {}))
return extractResponseData(customerResource)
}
async getCustomerAccountResources(customerId: string){
async getCustomerAccountResources(){
//Get a list of all the customer account resources attached to the current customer.
const customerAccountResources = (await this.httpClient.getData(`/customers/${customerId}/accounts`, {}, {}))
const customerAccountResources = (await this.httpClient.getData(`/customers/me/accounts`, {}, {}))
return extractResponseData(customerAccountResources)
}
async getFullCustomerAccountResource(customerId: string, accountNumber: string){
async getFullCustomerAccountResource(accountNumber: string){
//Get a full customer account resource.
const fullCustomerAccountResource = (await this.httpClient.getData(`/customers/${customerId}/accounts/${accountNumber}`, {}, {}))
const fullCustomerAccountResource = (await this.httpClient.getData(`/customers/me/accounts/${accountNumber}`, {}, {}))
return extractResponseData(fullCustomerAccountResource)
}

Expand Down
2 changes: 0 additions & 2 deletions tests/integration/service/account-status-service.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import AccountStatusService from "../../../lib/services/account-status-service";
import TastytradeHttpClient from "../../../lib/services/tastytrade-http-client";
import SessionService from "../../../lib/services/session-service";
import * as dotenv from 'dotenv'
dotenv.config()

const client = new TastytradeHttpClient(process.env.BASE_URL!)
const accountStatusService = new AccountStatusService(client)
Expand Down
10 changes: 4 additions & 6 deletions tests/integration/service/accounts-and-customers-service.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import AccountsAndCustomersService from "../../../lib/services/accounts-and-customers-service";
import TastytradeHttpClient from "../../../lib/services/tastytrade-http-client";
import SessionService from "../../../lib/services/session-service";
import * as dotenv from 'dotenv'
dotenv.config()

const client = new TastytradeHttpClient(process.env.BASE_URL!)
const accountsAndCustomersService = new AccountsAndCustomersService(client)
Expand All @@ -24,14 +22,14 @@ describe('getCustomerAccounts', () => {

describe('getCustomerResource', () => {
it('responds with the correct data', async function() {
const response = await accountsAndCustomersService.getCustomerResource(process.env.API_CUSTOMER_ID!)
expect(response.id).toBe(process.env.API_CUSTOMER_ID!)
const response = await accountsAndCustomersService.getCustomerResource()
expect(response.id).toBe('me')
})
})

describe('getCustomerAccountResources', () => {
it('responds with the correct data', async function() {
const response = await accountsAndCustomersService.getCustomerAccountResources(process.env.API_CUSTOMER_ID!)
const response = await accountsAndCustomersService.getCustomerAccountResources()
expect(response.length).toBeGreaterThan(0)
expect(response[0].account["account-number"]).toBeDefined();
expect(response[0].account["margin-or-cash"]).toBeDefined();
Expand All @@ -41,7 +39,7 @@ describe('getCustomerAccountResources', () => {

describe('getFullCustomerAccountResource', () => {
it('responds with the correct data', async function() {
const response = await accountsAndCustomersService.getFullCustomerAccountResource(process.env.API_CUSTOMER_ID!, process.env.API_ACCOUNT_NUMBER!)
const response = await accountsAndCustomersService.getFullCustomerAccountResource(process.env.API_ACCOUNT_NUMBER!)
expect(response["account-number"]).toBeDefined();
expect(response["margin-or-cash"]).toBeDefined();
expect(response["investment-objective"]).toBeDefined();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import BalancesAndPositionsService from "../../../lib/services/balances-and-positions-service";
import TastytradeHttpClient from "../../../lib/services/tastytrade-http-client";
import SessionService from "../../../lib/services/session-service";
import * as dotenv from 'dotenv'
dotenv.config()

const client = new TastytradeHttpClient(process.env.BASE_URL!)
const balancesAndPositionsService = new BalancesAndPositionsService(client)
Expand Down
2 changes: 0 additions & 2 deletions tests/integration/service/instruments-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import InstrumentsService from "../../../lib/services/instruments-service"
import TastytradeHttpClient from "../../../lib/services/tastytrade-http-client"
import SessionService from "../../../lib/services/session-service"
import _ from 'lodash'
import * as dotenv from 'dotenv'
dotenv.config()

const client = new TastytradeHttpClient(process.env.BASE_URL!)
const instrumentsService = new InstrumentsService(client)
Expand Down
2 changes: 0 additions & 2 deletions tests/integration/service/margin-requirements-service.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import MarginRequirementsService from "../../../lib/services/margin-requirements-service";
import TastytradeHttpClient from "../../../lib/services/tastytrade-http-client";
import SessionService from "../../../lib/services/session-service";
import * as dotenv from 'dotenv'
dotenv.config()

const client = new TastytradeHttpClient(process.env.BASE_URL!)
const marginRequirementsService = new MarginRequirementsService(client)
Expand Down
30 changes: 1 addition & 29 deletions tests/integration/service/orders-service.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import OrderService from "../../../lib/services/orders-service"
import TastytradeHttpClient from "../../../lib/services/tastytrade-http-client";
import SessionService from "../../../lib/services/session-service";
import * as dotenv from 'dotenv'
dotenv.config()

const client = new TastytradeHttpClient(process.env.BASE_URL!)
const orderService = new OrderService(client)
Expand All @@ -12,16 +10,6 @@ beforeAll(async () => {
await sessionService.login(process.env.API_USERNAME!, process.env.API_PASSWORD!)
});

// OrderID ambiguous
// describe('getOrder', () => {
// it('responds with the correct data', async function() {
// const orderId = 10;
// const response = await orderService.getOrder(process.env.API_ACCOUNT_NUMBER!, orderId)
// expect(response).toBeDefined()
// //Not sure what else it should be checking.
// })
// })

describe('getLiveOrders', () => {
it('responds with the correct data', async function() {
const response = await orderService.getLiveOrders(process.env.API_ACCOUNT_NUMBER!)
Expand All @@ -36,20 +24,4 @@ describe('getOrders', () => {
expect(response).toBeDefined()
//Not sure what else it should be checking.
})
})

// describe('getLiveOrdersForCustomer', () => {
// it('responds with the correct data', async function() {
// const response = await orderService.getLiveOrdersForCustomer(process.env.API_CUSTOMER_ID!)
// expect(response).toBeDefined()
// //Not sure what else it should be checking.
// })
// })

// describe('getCustomerOrders', () => {
// it('responds with the correct data', async function() {
// const response = await orderService.getCustomerOrders(process.env.API_CUSTOMER_ID!)
// expect(response).toBeDefined()
// //Not sure what else it should be checking.
// })
// })
})
2 changes: 0 additions & 2 deletions tests/integration/service/risk-parameters-service.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import RiskParametersService from "../../../lib/services/risk-parameters-service"
import TastytradeHttpClient from "../../../lib/services/tastytrade-http-client";
import SessionService from "../../../lib/services/session-service";
import * as dotenv from 'dotenv'
dotenv.config()

const client = new TastytradeHttpClient(process.env.BASE_URL!)
const riskParametersService = new RiskParametersService(client)
Expand Down
2 changes: 0 additions & 2 deletions tests/integration/service/session-service.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import SessionService from "../../../lib/services/session-service"
import TastytradeHttpClient from "../../../lib/services/tastytrade-http-client";
import * as dotenv from 'dotenv'
dotenv.config()

const client = new TastytradeHttpClient(process.env.BASE_URL!)
const sessionService = new SessionService(client)
Expand Down
2 changes: 0 additions & 2 deletions tests/integration/service/symbol-search-service.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import SymbolSearchService from "../../../lib/services/symbol-search-service"
import TastytradeHttpClient from "../../../lib/services/tastytrade-http-client";
import SessionService from "../../../lib/services/session-service";
import * as dotenv from 'dotenv'
dotenv.config()

const client = new TastytradeHttpClient(process.env.BASE_URL!)
const symbolSearchService = new SymbolSearchService(client)
Expand Down
Loading

0 comments on commit 29e424a

Please sign in to comment.