From f71bdf3dc45607984ea1b040a36b0b40f99d3ca0 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 12 Feb 2026 12:16:26 +0100 Subject: [PATCH] docs: Adding llm file for AI and scaffold claude folder --- .claude/CLAUDE.md | 96 +++++++++++++++++++++++++++++++++++++++ .claude/skills/broker.md | 24 ++++++++++ .claude/skills/domain.md | 43 ++++++++++++++++++ .claude/skills/release.md | 19 ++++++++ .claude/skills/testing.md | 11 +++++ README.md | 16 +++---- llms.txt | 79 ++++++++++++++++++++++++++++++++ package.json | 5 +- src/client.ts | 37 +++++++++++++++ 9 files changed, 320 insertions(+), 10 deletions(-) create mode 100644 .claude/CLAUDE.md create mode 100644 .claude/skills/broker.md create mode 100644 .claude/skills/domain.md create mode 100644 .claude/skills/release.md create mode 100644 .claude/skills/testing.md create mode 100644 llms.txt diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md new file mode 100644 index 0000000..75c1e40 --- /dev/null +++ b/.claude/CLAUDE.md @@ -0,0 +1,96 @@ +# DXtrade API + +Unofficial TypeScript client for the DXtrade trading API. + +## Commands + +- `npm run build` — Build the project (tsup) +- `npm run dev` — Build in watch mode +- `npm test` — Run tests once (vitest) +- `npm run test:watch` — Run tests in watch mode +- `npm run lint` — Lint source and examples +- `npm run lint:fix` — Lint and auto-fix +- `npm run format` — Format with prettier +- `npm run format:check` — Check formatting +- `npm run commit` — Commit using commitizen (required — `git commit` is disabled via pre-commit hook) + +## Project Structure + +``` +src/ +├── client.ts # Main DxtradeClient class — delegates to domain functions +├── client.types.ts # Config, callbacks, and context types +├── constants/ # Enums, broker URLs, endpoints, errors +├── domains/ # Feature modules (one folder per domain) +│ ├── {domain}/ +│ │ ├── {domain}.ts # Implementation +│ │ ├── {domain}.types.ts # Types (namespace pattern) +│ │ └── index.ts # Barrel exports +│ └── index.ts # Re-exports all domains +└── utils/ # Helpers (websocket, cookies, headers, retry) +tests/ # Unit tests (vitest) +examples/ # Runnable example scripts +``` + +## Path Aliases + +`@/*` maps to `src/*` — configured in tsconfig.json, tsup.config.ts, and vitest.config.ts. + +## Code Style + +- **Quotes**: Double quotes +- **Semicolons**: Always +- **Trailing commas**: Always +- **Print width**: 120 characters +- **Indent**: 2 spaces +- **Naming**: camelCase (functions/vars), PascalCase (classes/types/interfaces), SCREAMING_SNAKE_CASE (enum values) +- **Private fields**: Underscore prefix (`_ctx`) +- **Imports**: Named imports, `import type` for type-only imports, `@/` path alias for src +- **Types**: Namespace pattern for domain types (`Order.SubmitParams`, `Symbol.Info`), `interface` for objects, `type` for unions +- **Async**: async/await, Promise wrappers for WebSocket operations with timeout + cleanup +- **Error handling**: Custom `DxtradeError` class, try-catch with `error: unknown` type guards +- **Nullish coalescing**: `??` over `||` for defaults + +## Domain Pattern + +When adding a new domain: +1. Create `src/domains/{name}/{name}.ts` — implementation functions that take `ClientContext` as first param +2. Create `src/domains/{name}/{name}.types.ts` — types using namespace pattern +3. Create `src/domains/{name}/index.ts` — barrel exports +4. Re-export from `src/domains/index.ts` +5. Add public method(s) to `src/client.ts` with JSDoc comment + +## Example Pattern + +```typescript +import "dotenv/config"; +import { DxtradeClient, BROKER } from "../src"; + +const client = new DxtradeClient({ + username: process.env.DXTRADE_USERNAME!, + password: process.env.DXTRADE_PASSWORD!, + broker: process.env.DXTRADE_BROKER! || BROKER.FTMO, + accountId: process.env.DXTRADE_ACCOUNT_ID, + debug: process.env.DXTRADE_DEBUG || false, +}); + +(async () => { + await client.connect(); + // ... +})().catch(console.error); +``` + +## Rules + +### When adding or removing a feature: +1. Update `README.md` — Features checklist, API section, and Examples section +2. Update `llms.txt` — Keep the LLM reference in sync with the actual API +3. Add JSDoc comment to any new public method in `src/client.ts` +4. Add an example script in `examples/` if the feature is user-facing +5. Add a corresponding npm script in package.json +6. Add or update tests in `tests/` + +### General: +- Do not commit with `git commit` directly — use `npm run commit` +- Run `npm run lint` and `npm test` before committing +- Follow the existing domain pattern for new features diff --git a/.claude/skills/broker.md b/.claude/skills/broker.md new file mode 100644 index 0000000..e077874 --- /dev/null +++ b/.claude/skills/broker.md @@ -0,0 +1,24 @@ +# Broker + +Guide for adding, modifying, or removing a broker. + +## Adding a broker + +1. Add the broker URL to `src/constants/brokers.ts` in the `BROKER` object +2. Update `README.md`: Built-in Brokers section +3. Update `llms.txt`: Enums section (BROKER list) +4. Add a test for the new broker URL in `tests/constants.test.ts` + +## Modifying a broker + +1. Update the URL in `src/constants/brokers.ts` +2. Update `README.md`: Built-in Brokers section +3. Update `llms.txt`: Enums section (BROKER list) +4. Update the test in `tests/constants.test.ts` + +## Removing a broker + +1. Remove the entry from `src/constants/brokers.ts` +2. Update `README.md`: Built-in Brokers section +3. Update `llms.txt`: Enums section (BROKER list) +4. Remove the test from `tests/constants.test.ts` diff --git a/.claude/skills/domain.md b/.claude/skills/domain.md new file mode 100644 index 0000000..456ee63 --- /dev/null +++ b/.claude/skills/domain.md @@ -0,0 +1,43 @@ +# Domain + +Guide for adding, modifying, or removing a domain module. + +## Adding a domain + +1. Create the domain folder: `src/domains/{name}/` +2. Create `{name}.types.ts` with namespace pattern: + ```typescript + export namespace {Name} { + export interface ... { } + } + ``` +3. Create `{name}.ts` with implementation functions that take `ClientContext` as first param +4. Create `index.ts` with barrel exports +5. Re-export from `src/domains/index.ts` +6. Add public method(s) to `src/client.ts` with JSDoc comment +7. Add example script in `examples/` +8. Add npm script in package.json for the example +9. Add unit test in `tests/` +10. Update `README.md`: Features checklist, API section, Examples section +11. Update `llms.txt` with the new method(s) + +## Modifying a domain + +1. Update the implementation in `src/domains/{name}/{name}.ts` +2. Update types in `src/domains/{name}/{name}.types.ts` if signatures changed +3. Update the public method(s) and JSDoc in `src/client.ts` +4. Update the example script in `examples/` +5. Update or add tests in `tests/` +6. Update `README.md`: Features checklist, API section, Examples section +7. Update `llms.txt` to reflect the current API + +## Removing a domain + +1. Delete the domain folder: `src/domains/{name}/` +2. Remove the re-export from `src/domains/index.ts` +3. Remove the public method(s) and import from `src/client.ts` +4. Delete the example script from `examples/` +5. Remove the npm script from package.json +6. Remove or update tests in `tests/` +7. Update `README.md`: Features checklist, API section, Examples section +8. Update `llms.txt` to remove the method(s) diff --git a/.claude/skills/release.md b/.claude/skills/release.md new file mode 100644 index 0000000..3410435 --- /dev/null +++ b/.claude/skills/release.md @@ -0,0 +1,19 @@ +# Release + +Publishing is automated. When a PR is squash-merged to master, the publish workflow: + +1. Bumps the patch version in package.json +2. Publishes to npm with OIDC provenance +3. Creates a GitHub Release with auto-generated notes + +## Manual version bumps + +For minor or major releases, bump the version locally before merging: + +```bash +npm version minor --no-git-tag-version +# or +npm version major --no-git-tag-version +``` + +Then commit the version change and merge the PR. The workflow will skip the auto-bump if the version already changed. diff --git a/.claude/skills/testing.md b/.claude/skills/testing.md new file mode 100644 index 0000000..e7a02c1 --- /dev/null +++ b/.claude/skills/testing.md @@ -0,0 +1,11 @@ +# Testing + +> **Note:** Testing patterns still need to be thought out. Update this file as conventions are established. + +## Setup + +- Framework: vitest +- Config: `vitest.config.ts` +- Test location: `tests/` +- Run once: `npm test` +- Watch mode: `npm run test:watch` diff --git a/README.md b/README.md index b817812..3e3c58d 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,17 @@ [![npm downloads](https://img.shields.io/npm/dm/@danielgroen/dxtrade-api)](https://www.npmjs.com/package/@danielgroen/dxtrade-api) [![license](https://img.shields.io/npm/l/@danielgroen/dxtrade-api)](LICENSE) [![Tests](https://github.com/danielgroen/dxtrade-api/actions/workflows/tests.yml/badge.svg)](https://github.com/danielgroen/dxtrade-api/actions/workflows/tests.yml) -[![Publish to npm](https://github.com/danielgroen/dxtrade-api/actions/workflows/publish.yml/badge.svg)](https://github.com/danielgroen/dxtrade-api/actions/workflows/publish.yml) +[![Publish](https://github.com/danielgroen/dxtrade-api/actions/workflows/publish.yml/badge.svg)](https://github.com/danielgroen/dxtrade-api/actions/workflows/publish.yml) [![DXtrade API](https://raw.githubusercontent.com/danielgroen/dxtrade-api/master/public/logo-dxtrade.svg)](https://demo.dx.trade/developers/#/) -TypeScript client library for the DXtrade trading API based upon Nodejs. +Unofficial TypeScript client for the DXtrade trading API. Connect, trade, and manage positions on any broker that supports DXtrade. + +## Install + +```bash +npm install dxtrade-api +``` ## Features @@ -25,12 +31,6 @@ TypeScript client library for the DXtrade trading API based upon Nodejs. - [ ] Real-time price streaming - [ ] Order history -## Install - -```bash -npm install dxtrade-api -``` - ## Quick Start ```ts diff --git a/llms.txt b/llms.txt new file mode 100644 index 0000000..9479d9c --- /dev/null +++ b/llms.txt @@ -0,0 +1,79 @@ +# DXtrade API + +Unofficial TypeScript client for the DXtrade trading API. +Connect, trade, and manage positions on any broker that supports DXtrade. + +## Installation + +npm install dxtrade-api + +## Quick Start + +import { DxtradeClient, ORDER_TYPE, SIDE, BROKER } from "dxtrade-api"; + +const client = new DxtradeClient({ + username: "your_username", + password: "your_password", + broker: BROKER.FTMO, + accountId: "optional_account_id", +}); + +await client.connect(); + +## Available Methods + +### Session +- client.connect() — Login, fetch CSRF, WebSocket handshake, optional account switch. Call this first. +- client.login() — Authenticate with broker (called automatically by connect) +- client.fetchCsrf() — Fetch CSRF token (called automatically by connect) +- client.switchAccount(accountId: string) — Switch to a specific trading account + +### Market Data +- client.getSymbolSuggestions(text: string) — Search symbols by name, returns Symbol.Suggestion[] +- client.getSymbolInfo(symbol: string) — Get instrument info (volume limits, lot size), returns Symbol.Info +- client.getSymbolLimits() — Get order size limits for all symbols, returns Symbol.Limits[] +- client.getInstruments(params?: Partial) — Get all instruments, optionally filtered (e.g. { type: "FOREX" }) + +### Trading +- client.submitOrder(params: Order.SubmitParams) — Submit order and wait for WebSocket confirmation, returns Order.Update + Required params: symbol, side (SIDE.BUY | SIDE.SELL), quantity, orderType (ORDER_TYPE.MARKET | LIMIT | STOP), instrumentId + Optional params: limitPrice, stopPrice, stopLoss, takeProfit, timeInForce (TIF.GTC | DAY | GTD) + +### Positions +- client.getPositions() — Get all open positions via WebSocket, returns Position.Get[] +- client.closePosition(params: Position.Close) — Close a position + +### Account +- client.getAccountMetrics() — Get equity, balance, margin, open P&L, returns Account.Metrics +- client.getTradeJournal({ from: number, to: number }) — Fetch trade journal for date range (Unix timestamps) + +### Analytics +- client.getAssessments(params: Assessments.Params) — Fetch PnL assessments for a date range + +## Enums + +import { ORDER_TYPE, SIDE, ACTION, TIF, BROKER } from "dxtrade-api"; + +ORDER_TYPE: MARKET, LIMIT, STOP +SIDE: BUY, SELL +ACTION: OPENING, CLOSING +TIF: GTC, DAY, GTD +BROKER: LARKFUNDING, EIGHTCAP, FTMO + +## Callbacks + +const client = new DxtradeClient({ + ...config, + callbacks: { + onLogin: () => {}, + onAccountSwitch: (accountId: string) => {}, + onOrderPlaced: (order: Order.Response) => {}, + onOrderUpdate: (order: Order.Update) => {}, + onError: (error: DxtradeError) => {}, + }, +}); + +## Error Handling + +All errors are instances of DxtradeError with properties: code (string) and message (string). +Common error codes: NO_SESSION, ORDER_TIMEOUT, ORDER_ERROR, POSITION_CLOSE_ERROR. diff --git a/package.json b/package.json index d3034ff..bbac951 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@danielgroen/dxtrade-api", "version": "1.0.18", - "description": "DXtrade trading API client library", + "description": "Unofficial TypeScript client for the DXtrade trading API. Connect, trade, and manage positions on any broker that supports DXtrade.", "main": "./dist/index.js", "module": "./dist/index.mjs", "types": "./dist/index.d.ts", @@ -13,7 +13,8 @@ } }, "files": [ - "dist" + "dist", + "llms.txt" ], "scripts": { "================ Build ===============": "", diff --git a/src/client.ts b/src/client.ts index cb2846e..8e9f456 100644 --- a/src/client.ts +++ b/src/client.ts @@ -18,6 +18,22 @@ import { getTradeJournal, } from "@/domains"; +/** + * Client for interacting with the DXtrade trading API. + * + * @example + * ```ts + * import { DxtradeClient, ORDER_TYPE, SIDE, BROKER } from "dxtrade-api"; + * + * const client = new DxtradeClient({ + * username: "your_username", + * password: "your_password", + * broker: BROKER.FTMO, + * }); + * + * await client.connect(); + * ``` + */ export class DxtradeClient { private _ctx: ClientContext; @@ -45,58 +61,79 @@ export class DxtradeClient { }; } + /** Authenticate with the broker using username and password. */ public async login(): Promise { return login(this._ctx); } + /** Fetch the CSRF token required for authenticated requests. */ public async fetchCsrf(): Promise { return fetchCsrf(this._ctx); } + /** Switch to a specific trading account by ID. */ public async switchAccount(accountId: string): Promise { return switchAccount(this._ctx, accountId); } + /** Connect to the broker: login, fetch CSRF, WebSocket handshake, and optional account switch. */ public async connect(): Promise { return connect(this._ctx); } + /** Search for symbols matching the given text (e.g. "EURUSD", "BTC"). */ public async getSymbolSuggestions(text: string): Promise { return getSymbolSuggestions(this._ctx, text); } + /** Get detailed instrument info for a symbol, including volume limits and lot size. */ public async getSymbolInfo(symbol: string): Promise { return getSymbolInfo(this._ctx, symbol); } + /** Get order size limits and stop/limit distances for all symbols. */ public async getSymbolLimits(): Promise { return getSymbolLimits(this._ctx); } + /** + * Submit a trading order and wait for WebSocket confirmation. + * Supports market, limit, and stop orders with optional stop loss and take profit. + */ public async submitOrder(params: Order.SubmitParams): Promise { return submitOrder(this._ctx, params); } + /** Get account metrics including equity, balance, margin, and open P&L. */ public async getAccountMetrics(): Promise { return getAccountMetrics(this._ctx); } + /** Get all open positions via WebSocket. */ public async getPositions(): Promise { return getPositions(this._ctx); } + /** Close a position. */ public async closePosition(position: Position.Close): Promise { return closePosition(this._ctx, position); } + /** + * Fetch trade journal entries for a date range. + * @param params.from - Start timestamp (Unix ms) + * @param params.to - End timestamp (Unix ms) + */ public async getTradeJournal(params: { from: number; to: number }): Promise { return getTradeJournal(this._ctx, params); } + /** Get all available instruments, optionally filtered by partial match (e.g. `{ type: "FOREX" }`). */ public async getInstruments(params: Partial = {}): Promise { return getInstruments(this._ctx, params); } + /** Fetch PnL assessments for an instrument within a date range. */ public async getAssessments(params: Assessments.Params): Promise { return getAssessments(this._ctx, params); }