Skip to main content

Pepperstone Broker Integration

Summary​

Added Pepperstone as a supported brokerage on the Connections page. Pepperstone connects via cTrader Open API OAuth — no API keys needed. Users authorize directly from their Pepperstone/cTrader account.

Changes​

Backend​

services/backend/src/lib/brokers/broker-adapter.ts

  • Added 'pepperstone' to BrokerProviderId union type

services/backend/src/routes/exchange/exchange-schema.ts

  • Added 'pepperstone' to the provider Zod enum
  • Made apiKey and secret default to '' (instead of requiring .min(1)) to support OAuth-based providers that store tokens instead of static API keys

services/backend/src/lib/brokers/pepperstone-adapter.ts (new file)

  • Implements the BrokerAdapter interface for Pepperstone
  • getBalance and getAccountInfo call the cTrader REST API using the stored OAuth access_token
  • placeOrder returns a 501 Not Implemented error with a clear message — full cTrader OpenAPI proto order execution is a future enhancement
  • id: 'pepperstone', name: 'Pepperstone', supportedAssetClasses: ['forex']

services/backend/src/lib/brokers/broker-registry.ts

  • Registered pepperstoneAdapter in the adapters map

services/backend/src/routes/ctrader/ctrader-router.ts

  • Added POST /api/ctrader/pepperstone/save (auth-protected) endpoint that:
    1. Accepts { code, label, isTestnet } from the frontend after OAuth
    2. Exchanges the auth code for access_token + refresh_token via POST https://id.ctrader.com/connect/token
    3. Stores tokens encrypted in exchange_credentials with provider='pepperstone', exchange='pepperstone', assetClass='forex'
    4. Returns the sanitized credential (no raw tokens)

Frontend​

services/frontend/src/lib/api-client/index.ts

  • Added 'pepperstone' to BrokerProviderId type

services/frontend/src/routes/connections/ConnectionsPage.tsx

  • Added Pepperstone to PROVIDERS array with id: 'pepperstone', assetClass: 'forex', isOAuth: true semantics
  • Added isOAuthProvider detection in AddConnectionDialog — when Pepperstone is selected, shows an info panel redirecting users to the dedicated connect card instead of API key fields
  • Added PepperstoneConnectCard component:
    • Label and "Demo account" inputs
    • "Connect Pepperstone" button that:
      1. Fetches /api/ctrader/connect to get the OAuth URL
      2. Opens a centered popup window to the cTrader authorization page
      3. Listens for postMessage with { type: 'ctrader-auth', code }
      4. POSTs the code to /api/ctrader/pepperstone/save
      5. Refreshes the connections list on success
    • Error handling for blocked popups, abandoned OAuth flows, and API failures
    • Success state with a green confirmation banner
  • Added <PepperstoneConnectCard> to the page below the cTrader config info section under an "Connect via OAuth" heading

OAuth Flow​

User clicks "Connect Pepperstone"
→ Frontend fetches GET /api/ctrader/connect → gets authorizeUrl
→ Opens popup: https://id.ctrader.com/my/settings/openapi/grantingaccess/?client_id=...
→ User authorizes in popup
→ Backend GET /ctrader/callback receives code, posts message back
→ Frontend receives postMessage { type: 'ctrader-auth', code }
→ Frontend POSTs { code, label, isTestnet } to POST /api/ctrader/pepperstone/save
→ Backend exchanges code for tokens via cTrader token endpoint
→ Tokens stored encrypted in exchange_credentials (provider='pepperstone')
→ Connection card appears in the list

Security Notes​

  • OAuth tokens are encrypted at rest using the same encryption used for all other broker credentials
  • The POST /api/ctrader/pepperstone/save endpoint is protected by requireAuth middleware
  • Auth code is exchanged server-side (client secret never exposed to frontend)