Vest platform: a client for Vest Markets, traded on a session the extension relays
Vest (next.vestmarkets.com) is a perps prop firm: index, metal and energy
perps on CME hours, plus stocks, FX and crypto. It joins as a fourth
platform, 'vest', on the DXtrade engine paths. Those are now keyed by
isNotionalPlatform() instead of === 'dxtrade': the firm's own symbols,
percent fees, notional sizing from volatility, and a scheduler lane of its
own.
- Login is relayed, not stored. Vest signs people in with Google through
Privy and renews the session with a device key the browser won't export.
Extension 0.17.0's vest-relay.js reads the token the Vest app renews for
itself (~15 min). It renews nothing, so the tab is never logged out. The
background script posts that token to POST /api/vest/session, which holds
it in memory only. With no Vest tab open on a machine that trades Vest,
the extension opens one.
- The firm's credential is the Vest login's wallet address. The dashboard's
form offers the relayed wallet with one click.
- VestClient (lib/vest-class.ts), mapped from the web app's traffic and code
since Vest publishes no API:
- Reads the capital accounts, balances (free amount plus position
collateral), positions and open orders with the user token.
- Mints per-account tokens for orders and transactions.
- Names accounts for their rules (V50K-E-D3-T10-34, V50K-F-D3-34,
V25K-I-7) so account-type prefixes can match.
- Takes Vest's own max-drawdown and daily-loss floors. dayStartBalance =
floor + the type's limit, so the engine's room is never more than
Vest's.
- Uses each symbol's taker fee and margin rate from exchangeInfo, and
hourly volatility over in-session hours only.
- Places take-profit and stop as position legs, which Vest cancels as an
OCO pair.
- Daily P&L and fund rows come from /v3/transactions by Vest's 20:00 ET
day. A books check holds an account, naming the transaction types, when
the balance and the transactions disagree.
- scripts/check-vest.mjs (in npm run check): Vest's day across DST, account
names, parsing, volatility gaps, market hours, the session store.
Not yet run against Vest with a live session: the order and exit bodies
come from the app's code, and the transaction classification from its enum.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
5ec5abde6e
commit
96fdd9ca23
+10
-6
@@ -17,7 +17,8 @@
|
||||
* the two are not linked yet.)
|
||||
*/
|
||||
|
||||
import { isFirmPlatform } from './master-protocol';
|
||||
import { isFirmPlatform, isNotionalPlatform } from './master-protocol';
|
||||
import { isVestWalletAddress } from './vest-helpers';
|
||||
import { sanitizeInstruments, sanitizeInstrumentLimits, DEFAULT_MAX_ENTRY_SPREAD } from './instrument-specs';
|
||||
import { normalizeAccountType } from './kept-rules';
|
||||
import type {
|
||||
@@ -170,7 +171,8 @@ export function getCatalogMeta(): {
|
||||
}
|
||||
|
||||
/** Whether stored credentials are what the firm's platform logs in with — a
|
||||
* TopstepX API key, or a username + password (Tradovate, DXTrade). */
|
||||
* TopstepX API key, a username + password (Tradovate, DXTrade), or for Vest
|
||||
* the login's wallet address (its session is relayed by the extension). */
|
||||
export function hasPlatformCredentials(
|
||||
platform: FirmPlatform,
|
||||
creds: { username: string; password: string; apiKey: string } | null | undefined,
|
||||
@@ -178,6 +180,7 @@ export function hasPlatformCredentials(
|
||||
if (!creds) return false;
|
||||
switch (platform) {
|
||||
case 'topstepx': return !!creds.apiKey;
|
||||
case 'vest': return isVestWalletAddress(creds.apiKey);
|
||||
case 'tradovate':
|
||||
case 'dxtrade': return !!creds.username && !!creds.password;
|
||||
}
|
||||
@@ -296,9 +299,10 @@ function validatePayload(raw: unknown): FirmCatalogPayload {
|
||||
warnUnknownPlatform(firm.id, firm.name, platform);
|
||||
return;
|
||||
}
|
||||
// Percent commission and every-day trading are DXtrade settings;
|
||||
// futures firms keep measured per-contract fees and the CME calendar.
|
||||
const dx = platform === 'dxtrade';
|
||||
// Percent commission and every-day trading are settings of the
|
||||
// notional platforms (DXtrade, Vest); futures firms keep measured
|
||||
// per-contract fees and the CME calendar.
|
||||
const dx = isNotionalPlatform(platform);
|
||||
const tradesEveryDay = dx && firm.tradesEveryDay === true;
|
||||
if (!Array.isArray(firm.accountTypes)) throw new Error(`firm ${firm.name} is missing accountTypes`);
|
||||
|
||||
@@ -317,7 +321,7 @@ function validatePayload(raw: unknown): FirmCatalogPayload {
|
||||
// The master's list when it sends one; absent from an older
|
||||
// master, whose bannedSymbols / symbolMap then apply.
|
||||
...(Array.isArray(firm.instruments) ? { instruments: sanitizeInstruments(platform, firm.instruments) } : {}),
|
||||
...(platform !== 'dxtrade' ? { instrumentLimits: sanitizeInstrumentLimits(firm.instrumentLimits) } : {}),
|
||||
...(!dx ? { instrumentLimits: sanitizeInstrumentLimits(firm.instrumentLimits) } : {}),
|
||||
bannedSymbols: Array.isArray(firm.bannedSymbols) ? (firm.bannedSymbols as string[]) : [],
|
||||
accountTypes,
|
||||
...(keptAccountRules ? { keptAccountRules } : {}),
|
||||
|
||||
Reference in New Issue
Block a user