Fix seven type errors that broke next build
`npm run build` failed on a clean checkout, so nothing on master could be built for production. `npm run dev` does not hard-fail on type errors, which is why it went unnoticed. - state route returned client.perContractFees, which has never existed on TradovateClient on any branch; nothing consumed it - mapFirmConfig omitted bannedSymbols. Type gap only: the trade path calls isSymbolBanned() against the DB directly, so bans were always enforced - initClient's sync callback was sync where the constructor wants () => Promise<void> - accessInfo and ws are assigned during async connect/auth, never in the constructor, so they take definite-assignment assertions - the socket payload's inline entityType union had drifted five members behind the indirect-callback union above it, making the 'position' and 'cashBalance' branches unreachable to the compiler. Both now share a TradovateEntityType alias. Type-only: those handlers ran fine at runtime Behaviour is unchanged throughout. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
3cc7ddcc5c
commit
fc08a41c4b
@@ -98,7 +98,7 @@ export async function GET() {
|
|||||||
fundTransactions: displayFundTxns,
|
fundTransactions: displayFundTxns,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
return { firm: f.name, connected: true, accounts, perContractFees: client.perContractFees };
|
return { firm: f.name, connected: true, accounts };
|
||||||
});
|
});
|
||||||
|
|
||||||
return NextResponse.json(state);
|
return NextResponse.json(state);
|
||||||
|
|||||||
+2
-1
@@ -7,7 +7,7 @@
|
|||||||
* signal but have since exited and are now eligible.
|
* signal but have since exited and are now eligible.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getFirms, isSymbolBanned, getInstruments } from './db';
|
import { getFirms, isSymbolBanned, getInstruments, getBannedSymbols } from './db';
|
||||||
import { getClients } from './clients';
|
import { getClients } from './clients';
|
||||||
import { computeDailyTarget, resolveEffectiveConfig, POINT_VALUES } from './trading-logic';
|
import { computeDailyTarget, resolveEffectiveConfig, POINT_VALUES } from './trading-logic';
|
||||||
import { getSetting } from './db';
|
import { getSetting } from './db';
|
||||||
@@ -33,6 +33,7 @@ function mapFirmConfig(firm: FirmWithAccounts): FirmConfig {
|
|||||||
firm: firm.name,
|
firm: firm.name,
|
||||||
username: firm.username,
|
username: firm.username,
|
||||||
password: firm.password,
|
password: firm.password,
|
||||||
|
bannedSymbols: getBannedSymbols(firm.id),
|
||||||
accounts: firm.accounts.map((a) => ({
|
accounts: firm.accounts.map((a) => ({
|
||||||
prefix: a.prefix,
|
prefix: a.prefix,
|
||||||
profitTarget: a.profit_target,
|
profitTarget: a.profit_target,
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ function ensureMap(): Map<number, TradovateClient> {
|
|||||||
|
|
||||||
export function initClient(id: number, username: string, password: string, firmName: string): TradovateClient {
|
export function initClient(id: number, username: string, password: string, firmName: string): TradovateClient {
|
||||||
const map = ensureMap();
|
const map = ensureMap();
|
||||||
const client = new TradovateClient(username, password, () => {
|
const client = new TradovateClient(username, password, async () => {
|
||||||
console.log(`[${firmName}] sync complete — ${client.accountList.length} account(s)`);
|
console.log(`[${firmName}] sync complete — ${client.accountList.length} account(s)`);
|
||||||
});
|
});
|
||||||
map.set(id, client);
|
map.set(id, client);
|
||||||
|
|||||||
+21
-17
@@ -7,10 +7,27 @@ import { POINT_VALUES } from './trading-logic';
|
|||||||
import { getCachedContract, resolveContracts } from './contract-resolver';
|
import { getCachedContract, resolveContracts } from './contract-resolver';
|
||||||
import { saveDailyPnL, loadDailyPnL, saveAccountMeta, loadAccountMeta, saveFundTransactions, loadFundTransactions } from './db';
|
import { saveDailyPnL, loadDailyPnL, saveAccountMeta, loadAccountMeta, saveFundTransactions, loadFundTransactions } from './db';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity types Tradovate sends over the user-sync socket. Keep this as the
|
||||||
|
* single source of truth: the inline socket-payload type and the indirect
|
||||||
|
* callback list previously declared it separately and fell out of sync, which
|
||||||
|
* made the 'position' and 'cashBalance' handlers unreachable to the compiler.
|
||||||
|
*/
|
||||||
|
type TradovateEntityType =
|
||||||
|
| 'order'
|
||||||
|
| 'orderVersion'
|
||||||
|
| 'auditUserAction'
|
||||||
|
| 'command'
|
||||||
|
| 'commandReport'
|
||||||
|
| 'fill'
|
||||||
|
| 'executionReport'
|
||||||
|
| 'position'
|
||||||
|
| 'cashBalance';
|
||||||
|
|
||||||
export class TradovateClient {
|
export class TradovateClient {
|
||||||
private name: string;
|
private name: string;
|
||||||
private password: string;
|
private password: string;
|
||||||
private accessInfo: AuthLoginResponse;
|
private accessInfo!: AuthLoginResponse;
|
||||||
private deviceId = randomUUIDV4();
|
private deviceId = randomUUIDV4();
|
||||||
|
|
||||||
public accountList: AccountItem[] = [];
|
public accountList: AccountItem[] = [];
|
||||||
@@ -70,7 +87,7 @@ export class TradovateClient {
|
|||||||
public syncComplete = false;
|
public syncComplete = false;
|
||||||
|
|
||||||
|
|
||||||
private ws: WebSocket;
|
private ws!: WebSocket;
|
||||||
private callbackOnSyncRequest: () => Promise<void>;
|
private callbackOnSyncRequest: () => Promise<void>;
|
||||||
|
|
||||||
/** Incrementing ID for outgoing WebSocket messages — ensures concurrent orders don't clobber each other's callbacks. */
|
/** Incrementing ID for outgoing WebSocket messages — ensures concurrent orders don't clobber each other's callbacks. */
|
||||||
@@ -82,15 +99,7 @@ export class TradovateClient {
|
|||||||
[id: number]: (response: any) => void;
|
[id: number]: (response: any) => void;
|
||||||
} = {};
|
} = {};
|
||||||
private indirectEventCallbacks: {
|
private indirectEventCallbacks: {
|
||||||
entityType:
|
entityType: TradovateEntityType;
|
||||||
| 'order'
|
|
||||||
| 'orderVersion'
|
|
||||||
| 'auditUserAction'
|
|
||||||
| 'command'
|
|
||||||
| 'commandReport'
|
|
||||||
| 'fill'
|
|
||||||
| 'executionReport'
|
|
||||||
| 'cashBalance';
|
|
||||||
eventType: 'Created' | 'Updated';
|
eventType: 'Created' | 'Updated';
|
||||||
// Since the entity is not always the same, we need a validator to check if the response is the one we are looking for
|
// Since the entity is not always the same, we need a validator to check if the response is the one we are looking for
|
||||||
validator: (response: any) => boolean;
|
validator: (response: any) => boolean;
|
||||||
@@ -167,12 +176,7 @@ export class TradovateClient {
|
|||||||
| {
|
| {
|
||||||
e?: string;
|
e?: string;
|
||||||
d?: {
|
d?: {
|
||||||
entityType:
|
entityType: TradovateEntityType;
|
||||||
| 'order'
|
|
||||||
| 'orderVersion'
|
|
||||||
| 'auditUserAction'
|
|
||||||
| 'command'
|
|
||||||
| 'commandReport';
|
|
||||||
eventType: 'Created' | 'Updated';
|
eventType: 'Created' | 'Updated';
|
||||||
entity: any;
|
entity: any;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user