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'toBrokerProviderIdunion type
services/backend/src/routes/exchange/exchange-schema.ts
- Added
'pepperstone'to theproviderZod enum - Made
apiKeyandsecretdefault 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
BrokerAdapterinterface for Pepperstone getBalanceandgetAccountInfocall the cTrader REST API using the stored OAuthaccess_tokenplaceOrderreturns a501 Not Implementederror with a clear message — full cTrader OpenAPI proto order execution is a future enhancementid: 'pepperstone',name: 'Pepperstone',supportedAssetClasses: ['forex']
services/backend/src/lib/brokers/broker-registry.ts
- Registered
pepperstoneAdapterin the adapters map
services/backend/src/routes/ctrader/ctrader-router.ts
- Added
POST /api/ctrader/pepperstone/save(auth-protected) endpoint that:- Accepts
{ code, label, isTestnet }from the frontend after OAuth - Exchanges the auth code for
access_token+refresh_tokenviaPOST https://id.ctrader.com/connect/token - Stores tokens encrypted in
exchange_credentialswithprovider='pepperstone',exchange='pepperstone',assetClass='forex' - Returns the sanitized credential (no raw tokens)
- Accepts
Frontend
services/frontend/src/lib/api-client/index.ts
- Added
'pepperstone'toBrokerProviderIdtype
services/frontend/src/routes/connections/ConnectionsPage.tsx
- Added Pepperstone to
PROVIDERSarray withid: 'pepperstone',assetClass: 'forex',isOAuth: truesemantics - Added
isOAuthProviderdetection inAddConnectionDialog— when Pepperstone is selected, shows an info panel redirecting users to the dedicated connect card instead of API key fields - Added
PepperstoneConnectCardcomponent:- Label and "Demo account" inputs
- "Connect Pepperstone" button that:
- Fetches
/api/ctrader/connectto get the OAuth URL - Opens a centered popup window to the cTrader authorization page
- Listens for
postMessagewith{ type: 'ctrader-auth', code } - POSTs the code to
/api/ctrader/pepperstone/save - Refreshes the connections list on success
- Fetches
- 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/saveendpoint is protected byrequireAuthmiddleware - Auth code is exchanged server-side (client secret never exposed to frontend)