import {z} from 'zod' export type GetApiRestApiV1AccountsAsyncOptions = {baseUrl?: string | undefined, ApiKeyAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const proxyRegionDTO = z.object({id: z.number().int(), name: z.string().optional()}); export const proxyDTO = z.object({id: z.number().int().optional(), ipAddress: z.string().optional(), region: proxyRegionDTO.optional(), usedByAccounts: z.array(z.string()).optional()}); export const copierDuplicationDTO = z.object({directCopiers: z.number().int().optional(), fromAccount: z.string().optional(), fromAccountId: z.string().optional(), strategies: z.array(z.string()).optional()}); export const expertAdvisorResourceDTO = z.object({cpuPercent: z.number().optional(), featureId: z.string().optional(), lastError: z.string().optional(), memoryBytes: z.number().int().optional(), restartCount: z.number().int().optional(), state: z.enum(["STOPPED", "STARTING", "RUNNING", "ERROR"]).optional()}); export const missingSymbolMappingDTO = z.object({copierId: z.string().optional(), fromAccount: z.string().optional(), fromAccountId: z.string().optional(), lastTimestampDetected: z.number().int().optional(), symbol: z.string().optional()}); export const approvalDTO = z.object({accountFromId: z.string(), ticket: z.number().int(), volume: z.number().optional()}); export const profitTargetStatusDTO = z.object({balanceLastUpdate: z.string().optional(), lossLimitIsHit: z.boolean().optional(), profitTargetFeatureId: z.string().optional(), profitTargetIsHit: z.boolean().optional(), referenceBalance: z.number().optional()}); export const riskLimitStatusDTO = z.object({balanceLastUpdate: z.string().optional(), copierId: z.string().optional(), limitIsHit: z.boolean().optional(), referenceBalance: z.number().optional(), riskLimitId: z.string().optional(), scope: z.enum(["ACCOUNT", "COPIER"]).optional()}); export const walletDTO = z.object({asset: z.string().optional(), balance: z.number().optional()}); export const accountInformationDTO = z.object({accountDuplicationInProjectDetected: z.boolean().optional(), accountMode: z.enum(["NETTING", "HEDGING", "EXCHANGE"]).optional(), avgDrawdown: z.number().optional(), balance: z.number().optional(), brokeTimeOffsetToUtc: z.number().int().optional(), configuredProxy: proxyDTO.optional(), connected: z.boolean().optional(), copierDuplications: z.array(copierDuplicationDTO).optional(), credit: z.number().optional(), currency: z.string().optional(), drawdown: z.number().optional(), environment: z.enum(["LIVE", "DEMO"]).optional(), equity: z.number().optional(), expertAdvisorResources: z.array(expertAdvisorResourceDTO).optional(), fallbackMode: z.boolean().optional(), freeMargin: z.number().optional(), historyDeactivated: z.boolean().optional(), isHyperactive: z.boolean().optional(), isInvestorPassword: z.boolean().optional(), isNative: z.boolean().optional(), latencyInMs: z.number().int().optional(), leverage: z.number().int().optional(), maxDrawdown: z.number().optional(), missingSymbolMappings: z.array(missingSymbolMappingDTO).optional(), openPositions: z.boolean().optional(), openPositionsCount: z.number().int().optional(), pendingApprovals: z.array(approvalDTO).optional(), pendingOrders: z.boolean().optional(), pendingOrdersCount: z.number().int().optional(), positionMismatch: z.boolean().optional(), profitTargetsStatus: z.array(profitTargetStatusDTO).optional(), profitThisMonth: z.number().optional(), profitThisWeek: z.number().optional(), profitToday: z.number().optional(), proxy: proxyDTO.optional(), riskLimitsStatus: z.array(riskLimitStatusDTO).optional(), status: z.string().optional(), unrealizedProfit: z.number().optional(), usedMargin: z.number().optional(), walletBalances: z.array(walletDTO).optional(), wrongCredentials: z.boolean().optional()}); export const accountAppliedTemplateDTO = z.object({appliedAt: z.string().optional(), currentRevision: z.number().int().optional(), templateId: z.string().optional(), templateName: z.string().optional(), templateRevision: z.number().int().optional()}); export const featureDedicatedIpDTO = z.object({dedicatedProxyServerId: z.number().int()}); export const featureMyHomeIpDTO = z.object({host: z.string(), httpPort: z.number().int().optional(), password: z.string(), socksPort: z.number().int().optional(), username: z.string()}); export const regionDTO = z.object({id: z.number().int(), name: z.string().optional()}); export const accountStatusDTO = z.object({id: z.number().int(), name: z.string().optional()}); export const accountTypeDTO = z.object({id: z.number().int(), name: z.string().optional()}); export const accountDTO = z.object({accountInformation: accountInformationDTO.optional(), alias: z.string().max(255).optional(), appliedTemplate: accountAppliedTemplateDTO.optional(), callbackUrl: z.string().optional(), closeUnmanagedPositions: z.boolean().optional(), created: z.string().optional(), ctraderClientId: z.string().optional(), ctraderClientSecret: z.string().optional(), dedicatedIp: featureDedicatedIpDTO.optional(), deleted: z.string().optional(), failIfAccountExistsInProject: z.boolean().optional(), hasActiveCopiers: z.boolean().optional(), hasDisabledCopiers: z.boolean().optional(), hasMonitorOnlyCopiers: z.boolean().optional(), id: z.string().optional(), labels: z.array(z.string()).optional(), loginAccountNumber: z.string().max(255).optional(), loginAccountPassword: z.string().max(2000), loginServer: z.string().max(255), myHomeIp: featureMyHomeIpDTO.optional(), nativeMode: z.boolean().optional(), propFirm: z.boolean().optional(), region: regionDTO, skipCredentialCheck: z.boolean().optional(), status: accountStatusDTO.optional(), statusMessage: z.string().optional(), tradingDisabled: z.boolean().optional(), type: accountTypeDTO, validateCredentialsOnChange: z.boolean().optional()}); export const asyncAccountCreationResponseDTO = z.object({account: accountDTO.optional(), callbackUrl: z.string().optional(), error: z.string().optional(), message: z.string().optional(), requestId: z.string().optional(), status: z.enum(["QUEUED", "PROCESSING", "COMPLETED", "FAILED"]).optional()}); export const getApiRestApiV1AccountsAsyncResponse = z.array(asyncAccountCreationResponseDTO); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Get all async account creation requests * * GET /rest/api/v1/accounts/async */ export const getApiRestApiV1AccountsAsync = async (options?: GetApiRestApiV1AccountsAsyncOptions) => { const {baseUrl = "https://api.metacopier.io", fetch: fetchFn = fetch, ApiKeyAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (ApiKeyAuth !== undefined) headers.set("X-API-KEY", ApiKeyAuth) const url = `${baseUrl.replace(/\/+$/, '')}/rest/api/v1/accounts/async${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(getApiRestApiV1AccountsAsyncResponse, await res.json()) };