diff --git a/src/Managing.Api/Controllers/BotController.cs b/src/Managing.Api/Controllers/BotController.cs index 5c07735..0e630ce 100644 --- a/src/Managing.Api/Controllers/BotController.cs +++ b/src/Managing.Api/Controllers/BotController.cs @@ -1,5 +1,6 @@ using Managing.Api.Models.Requests; using Managing.Api.Models.Responses; +using Managing.Application.Abstractions; using Managing.Application.Abstractions.Services; using Managing.Application.Hubs; using Managing.Application.ManageBot.Commands; @@ -25,6 +26,7 @@ public class BotController : ControllerBase private readonly ILogger _logger; private readonly IHubContext _hubContext; private readonly IBacktester _backtester; + private readonly IBotService _botService; /// /// Initializes a new instance of the class. @@ -34,12 +36,13 @@ public class BotController : ControllerBase /// SignalR hub context for real-time communication. /// Backtester for running backtests on bots. public BotController(ILogger logger, IMediator mediator, IHubContext hubContext, - IBacktester backtester) + IBacktester backtester, IBotService botService) { _logger = logger; _mediator = mediator; _hubContext = hubContext; _backtester = backtester; + _botService = botService; } /// @@ -86,11 +89,8 @@ public class BotController : ControllerBase [Route("Delete")] public async Task> Delete(string botName) { - var result = await _mediator.Send(new DeleteBotCommand(botName)); - _logger.LogInformation($"{botName} is now deleted"); - + var result = await _botService.DeleteBot(botName); await NotifyBotSubscriberAsync(); - return Ok(result); } diff --git a/src/Managing.Api/Controllers/DataController.cs b/src/Managing.Api/Controllers/DataController.cs index 84a57ff..9536514 100644 --- a/src/Managing.Api/Controllers/DataController.cs +++ b/src/Managing.Api/Controllers/DataController.cs @@ -51,16 +51,19 @@ public class DataController : ControllerBase /// /// Retrieves tickers for a given account and timeframe, utilizing caching to improve performance. /// - /// The name of the account to retrieve tickers for. /// The timeframe for which to retrieve tickers. /// An array of tickers. [HttpPost("GetTickers")] - public async Task> GetTickers(string accountName, Timeframe timeframe) + public async Task> GetTickers(Timeframe timeframe) { - var account = await _accountService.GetAccount(accountName, true, false); - var cacheKey = string.Concat(accountName, timeframe.ToString()); - var tickers = _cacheService.GetOrSave(cacheKey, - () => { return _exchangeService.GetTickers(account, timeframe).Result; }, TimeSpan.FromHours(2)); + var cacheKey = string.Concat(timeframe.ToString()); + var tickers = _cacheService.GetValue>(cacheKey); + + if (tickers == null) + { + tickers = await _exchangeService.GetTickers(timeframe); + _cacheService.SaveValue(cacheKey, tickers, TimeSpan.FromHours(2)); + } return Ok(tickers); } diff --git a/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs b/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs index b9fc2d6..b47a4c0 100644 --- a/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs +++ b/src/Managing.Application.Abstractions/Repositories/IBotRepository.cs @@ -7,5 +7,5 @@ public interface IBotRepository Task InsertBotAsync(BotBackup bot); IEnumerable GetBots(); Task UpdateBackupBot(BotBackup bot); - void DeleteBotBackup(string botName); + Task DeleteBotBackup(string botName); } \ No newline at end of file diff --git a/src/Managing.Application.Abstractions/Services/IExchangeService.cs b/src/Managing.Application.Abstractions/Services/IExchangeService.cs index 198f95f..9b56cce 100644 --- a/src/Managing.Application.Abstractions/Services/IExchangeService.cs +++ b/src/Managing.Application.Abstractions/Services/IExchangeService.cs @@ -30,7 +30,7 @@ public interface IExchangeService Task OpenStopLoss(Account account, Ticker ticker, TradeDirection originalDirection, decimal stopLossPrice, decimal quantity, bool isForPaperTrading = false, DateTime? currentDate = null); - Task> GetTickers(Account account, Timeframe timeframe); + Task> GetTickers(Timeframe timeframe); Task OpenTakeProfit(Account account, Ticker ticker, TradeDirection originalDirection, decimal takeProfitPrice, diff --git a/src/Managing.Application/ManageBot/BotService.cs b/src/Managing.Application/ManageBot/BotService.cs index 126d166..8920637 100644 --- a/src/Managing.Application/ManageBot/BotService.cs +++ b/src/Managing.Application/ManageBot/BotService.cs @@ -178,14 +178,22 @@ namespace Managing.Application.ManageBot { if (_botTasks.TryRemove(botName, out var botWrapper)) { - if (botWrapper.BotInstance is IBot bot) + try { - await Task.Run(() => - bot.Stop()); // Assuming Stop is an asynchronous process wrapped in Task.Run for synchronous methods - } + if (botWrapper.BotInstance is IBot bot) + { + await Task.Run(() => + bot.Stop()); // Assuming Stop is an asynchronous process wrapped in Task.Run for synchronous methods + } - _botRepository.DeleteBotBackup(botName); - return true; + await _botRepository.DeleteBotBackup(botName); + return true; + } + catch (Exception e) + { + Console.WriteLine(e); + return false; + } } return false; diff --git a/src/Managing.Infrastructure.Database/BotRepository.cs b/src/Managing.Infrastructure.Database/BotRepository.cs index 49fb378..b511f9a 100644 --- a/src/Managing.Infrastructure.Database/BotRepository.cs +++ b/src/Managing.Infrastructure.Database/BotRepository.cs @@ -34,8 +34,9 @@ public class BotRepository : IBotRepository _botRepository.Update(dto); } - public void DeleteBotBackup(string botName) + public async Task DeleteBotBackup(string botName) { - _botRepository.DeleteOne(b => b.Name == botName); + var backup = await _botRepository.FindOneAsync(b => b.Name == botName); + await _botRepository.DeleteOneAsync(b => b.Id == backup.Id); } } \ No newline at end of file diff --git a/src/Managing.Infrastructure.Exchanges/ExchangeService.cs b/src/Managing.Infrastructure.Exchanges/ExchangeService.cs index 8f4fbad..e3d6d6a 100644 --- a/src/Managing.Infrastructure.Exchanges/ExchangeService.cs +++ b/src/Managing.Infrastructure.Exchanges/ExchangeService.cs @@ -246,10 +246,10 @@ namespace Managing.Infrastructure.Exchanges return processor.GetVolume(account, ticker); } - public async Task> GetTickers(Account account, Timeframe timeframe) + public async Task> GetTickers(Timeframe timeframe) { var tickers = - await _candleRepository.GetTickersAsync(account.Exchange, timeframe, DateTime.UtcNow.AddDays(-2)); + await _candleRepository.GetTickersAsync(TradingExchanges.Evm, timeframe, DateTime.UtcNow.AddDays(-2)); return tickers.ToList(); } diff --git a/src/Managing.WebApp/src/components/organism/Backtest/backtestModal.tsx b/src/Managing.WebApp/src/components/organism/Backtest/backtestModal.tsx index 6829a4a..a294407 100644 --- a/src/Managing.WebApp/src/components/organism/Backtest/backtestModal.tsx +++ b/src/Managing.WebApp/src/components/organism/Backtest/backtestModal.tsx @@ -157,7 +157,7 @@ const BacktestModal: React.FC = ({ enabled: !!selectedAccount && !!selectedTimeframe, queryFn: () => { if (selectedAccount && selectedTimeframe) { - return dataClient.data_GetTickers(selectedAccount, selectedTimeframe) + return dataClient.data_GetTickers(selectedTimeframe) } }, queryKey: ['tickers', selectedAccount, selectedTimeframe], diff --git a/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx b/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx index 4289a33..9f06c57 100644 --- a/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx +++ b/src/Managing.WebApp/src/components/organism/Backtest/backtestTable.tsx @@ -116,12 +116,12 @@ const BacktestTable: React.FC = ({ list, isFetching }) => { accessor: 'botType', disableSortBy: true, }, - { - Filter: SelectColumnFilter, - Header: 'Account', - accessor: 'accountName', - disableSortBy: true, - }, + // { + // Filter: SelectColumnFilter, + // Header: 'Account', + // accessor: 'accountName', + // disableSortBy: true, + // }, ], }, { diff --git a/src/Managing.WebApp/src/generated/ManagingApi.ts b/src/Managing.WebApp/src/generated/ManagingApi.ts index ccaeba9..27e521c 100644 --- a/src/Managing.WebApp/src/generated/ManagingApi.ts +++ b/src/Managing.WebApp/src/generated/ManagingApi.ts @@ -1,6 +1,6 @@ //---------------------- // -// Generated using the NSwag toolchain v13.16.0.0 (NJsonSchema v10.7.1.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) +// Generated using the NSwag toolchain v14.2.0.0 (NJsonSchema v11.1.0.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) // //---------------------- @@ -19,7 +19,7 @@ export class AccountClient extends AuthorizedApiBase { constructor(configuration: IConfig, baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { super(configuration); this.http = http ? http : window as any; - this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : "https://localhost:5001"; + this.baseUrl = baseUrl ?? "http://localhost:5000"; } account_PostAccount(account: Account): Promise { @@ -123,8 +123,14 @@ export class AccountClient extends AuthorizedApiBase { let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; if (status === 200 || status === 206) { const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; - const fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; - const fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; }); } else if (status !== 200 && status !== 204) { return response.text().then((_responseText) => { @@ -213,7 +219,7 @@ export class BacktestClient extends AuthorizedApiBase { constructor(configuration: IConfig, baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { super(configuration); this.http = http ? http : window as any; - this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : "https://localhost:5001"; + this.baseUrl = baseUrl ?? "http://localhost:5000"; } backtest_Backtests(): Promise { @@ -276,8 +282,14 @@ export class BacktestClient extends AuthorizedApiBase { let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; if (status === 200 || status === 206) { const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; - const fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; - const fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; }); } else if (status !== 200 && status !== 204) { return response.text().then((_responseText) => { @@ -310,8 +322,14 @@ export class BacktestClient extends AuthorizedApiBase { let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; if (status === 200 || status === 206) { const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; - const fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; - const fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; }); } else if (status !== 200 && status !== 204) { return response.text().then((_responseText) => { @@ -403,7 +421,7 @@ export class BotClient extends AuthorizedApiBase { constructor(configuration: IConfig, baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { super(configuration); this.http = http ? http : window as any; - this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : "https://localhost:5001"; + this.baseUrl = baseUrl ?? "http://localhost:5000"; } bot_Start(request: StartBotRequest): Promise { @@ -715,13 +733,11 @@ export class DataClient extends AuthorizedApiBase { constructor(configuration: IConfig, baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { super(configuration); this.http = http ? http : window as any; - this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : "https://localhost:5001"; + this.baseUrl = baseUrl ?? "http://localhost:5000"; } - data_GetTickers(accountName: string | null | undefined, timeframe: Timeframe | undefined): Promise { + data_GetTickers(timeframe: Timeframe | undefined): Promise { let url_ = this.baseUrl + "/Data/GetTickers?"; - if (accountName !== undefined && accountName !== null) - url_ += "accountName=" + encodeURIComponent("" + accountName) + "&"; if (timeframe === null) throw new Error("The parameter 'timeframe' cannot be null."); else if (timeframe !== undefined) @@ -854,7 +870,7 @@ export class MoneyManagementClient extends AuthorizedApiBase { constructor(configuration: IConfig, baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { super(configuration); this.http = http ? http : window as any; - this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : "https://localhost:5001"; + this.baseUrl = baseUrl ?? "http://localhost:5000"; } moneyManagement_PostMoneyManagement(moneyManagement: MoneyManagement): Promise { @@ -958,8 +974,14 @@ export class MoneyManagementClient extends AuthorizedApiBase { let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; if (status === 200 || status === 206) { const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; - const fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; - const fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; }); } else if (status !== 200 && status !== 204) { return response.text().then((_responseText) => { @@ -1013,7 +1035,7 @@ export class ScenarioClient extends AuthorizedApiBase { constructor(configuration: IConfig, baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { super(configuration); this.http = http ? http : window as any; - this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : "https://localhost:5001"; + this.baseUrl = baseUrl ?? "http://localhost:5000"; } scenario_GetScenarios(): Promise { @@ -1117,8 +1139,14 @@ export class ScenarioClient extends AuthorizedApiBase { let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; if (status === 200 || status === 206) { const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; - const fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; - const fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; }); } else if (status !== 200 && status !== 204) { return response.text().then((_responseText) => { @@ -1249,8 +1277,14 @@ export class ScenarioClient extends AuthorizedApiBase { let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; if (status === 200 || status === 206) { const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; - const fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; - const fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; }); } else if (status !== 200 && status !== 204) { return response.text().then((_responseText) => { @@ -1269,7 +1303,7 @@ export class SettingsClient extends AuthorizedApiBase { constructor(configuration: IConfig, baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { super(configuration); this.http = http ? http : window as any; - this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : "https://localhost:5001"; + this.baseUrl = baseUrl ?? "http://localhost:5000"; } settings_SetupSettings(): Promise { @@ -1295,8 +1329,14 @@ export class SettingsClient extends AuthorizedApiBase { let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; if (status === 200 || status === 206) { const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; - const fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; - const fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; }); } else if (status !== 200 && status !== 204) { return response.text().then((_responseText) => { @@ -1350,7 +1390,7 @@ export class TradingClient extends AuthorizedApiBase { constructor(configuration: IConfig, baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { super(configuration); this.http = http ? http : window as any; - this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : "https://localhost:5001"; + this.baseUrl = baseUrl ?? "http://localhost:5000"; } trading_GetPositions(positionInitiator: PositionInitiator | undefined): Promise { @@ -1435,7 +1475,7 @@ export class TradingClient extends AuthorizedApiBase { return Promise.resolve(null as any); } - trading_GetTrades(accountName: string | null | undefined, ticker: Ticker | undefined, exchangeOrderId: string | null | undefined): Promise { + trading_GetTrades(accountName: string | null | undefined, ticker: Ticker | undefined): Promise { let url_ = this.baseUrl + "/Trading/GetTrades?"; if (accountName !== undefined && accountName !== null) url_ += "accountName=" + encodeURIComponent("" + accountName) + "&"; @@ -1443,8 +1483,6 @@ export class TradingClient extends AuthorizedApiBase { throw new Error("The parameter 'ticker' cannot be null."); else if (ticker !== undefined) url_ += "ticker=" + encodeURIComponent("" + ticker) + "&"; - if (exchangeOrderId !== undefined && exchangeOrderId !== null) - url_ += "exchangeOrderId=" + encodeURIComponent("" + exchangeOrderId) + "&"; url_ = url_.replace(/[?&]$/, ""); let options_: RequestInit = { @@ -1585,7 +1623,7 @@ export class UserClient extends AuthorizedApiBase { constructor(configuration: IConfig, baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { super(configuration); this.http = http ? http : window as any; - this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : "https://localhost:5001"; + this.baseUrl = baseUrl ?? "http://localhost:5000"; } user_CreateToken(login: LoginRequest): Promise { @@ -1636,7 +1674,7 @@ export class WorkflowClient extends AuthorizedApiBase { constructor(configuration: IConfig, baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { super(configuration); this.http = http ? http : window as any; - this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : "https://localhost:5001"; + this.baseUrl = baseUrl ?? "http://localhost:5000"; } workflow_PostWorkflow(workflowRequest: SyntheticWorkflow): Promise { @@ -1738,8 +1776,14 @@ export class WorkflowClient extends AuthorizedApiBase { let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; if (status === 200 || status === 206) { const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; - const fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; - const fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; }); } else if (status !== 200 && status !== 204) { return response.text().then((_responseText) => { @@ -1789,10 +1833,10 @@ export interface Account { name: string; exchange: TradingExchanges; type: AccountType; - key?: string | undefined; - secret?: string | undefined; - user?: User | undefined; - balances?: Balance[] | undefined; + key?: string | null; + secret?: string | null; + user?: User | null; + balances?: Balance[] | null; } export enum TradingExchanges { @@ -1800,6 +1844,7 @@ export enum TradingExchanges { Kraken = "Kraken", Ftx = "Ftx", Evm = "Evm", + GmxV2 = "GmxV2", } export enum AccountType { @@ -1810,24 +1855,25 @@ export enum AccountType { } export interface User { - name?: string | undefined; - accounts?: Account[] | undefined; + name?: string | null; + accounts?: Account[] | null; } export interface Balance { - tokenImage?: string | undefined; - tokenName?: string | undefined; + tokenImage?: string | null; + tokenName?: string | null; amount?: number; price?: number; value?: number; - tokenAdress?: string | undefined; - chain?: Chain | undefined; + tokenAdress?: string | null; + chain?: Chain | null; } export interface Chain { - id?: string | undefined; - rpcUrl?: string | undefined; - name?: string | undefined; + id?: string | null; + rpcUrl?: string | null; + name?: string | null; + chainId?: number; } export interface Backtest { @@ -1852,25 +1898,20 @@ export interface Backtest { } export enum Ticker { + AAVE = "AAVE", ADA = "ADA", APE = "APE", - ALICE = "ALICE", ALGO = "ALGO", + ARB = "ARB", ATOM = "ATOM", AVAX = "AVAX", - AXS = "AXS", - BAT = "BAT", BNB = "BNB", BTC = "BTC", BAL = "BAL", - C98 = "C98", - CHR = "CHR", CHZ = "CHZ", COMP = "COMP", CRO = "CRO", CRV = "CRV", - CVC = "CVC", - DEFI = "DEFI", DOGE = "DOGE", DOT = "DOT", DYDX = "DYDX", @@ -1881,29 +1922,22 @@ export enum Ticker { FLM = "FLM", FTM = "FTM", GALA = "GALA", - GMT = "GMT", GMX = "GMX", GRT = "GRT", - HNT = "HNT", IMX = "IMX", JASMY = "JASMY", - KAVA = "KAVA", KSM = "KSM", LDO = "LDO", LINK = "LINK", - LOOKS = "LOOKS", LRC = "LRC", LTC = "LTC", MANA = "MANA", MATIC = "MATIC", MKR = "MKR", NEAR = "NEAR", - NEO = "NEO", - OMG = "OMG", - ONE = "ONE", - ONT = "ONT", + OP = "OP", + PEPE = "PEPE", QTUM = "QTUM", - REEF = "REEF", REN = "REN", ROSE = "ROSE", RSR = "RSR", @@ -1911,21 +1945,19 @@ export enum Ticker { SAND = "SAND", SOL = "SOL", SRM = "SRM", - STMX = "STMX", SUSHI = "SUSHI", - SXP = "SXP", THETA = "THETA", UNI = "UNI", USDC = "USDC", USDT = "USDT", - VET = "VET", - WAVES = "WAVES", + WIF = "WIF", XMR = "XMR", XRP = "XRP", XTZ = "XTZ", - YFI = "YFI", - ZEC = "ZEC", - ZIL = "ZIL", + SHIB = "SHIB", + STX = "STX", + ORDI = "ORDI", + Unknown = "Unknown", } export interface Position { @@ -1937,10 +1969,10 @@ export interface Position { open: Trade; stopLoss: Trade; takeProfit1: Trade; - takeProfit2?: Trade | undefined; - profitAndLoss?: ProfitAndLoss | undefined; + takeProfit2?: Trade | null; + profitAndLoss?: ProfitAndLoss | null; status: PositionStatus; - signalIdentifier?: string | undefined; + signalIdentifier?: string | null; identifier: string; initiator: PositionInitiator; } @@ -1980,7 +2012,7 @@ export interface Trade { price: number; leverage?: number; exchangeOrderId: string; - message?: string | undefined; + message?: string | null; } export enum TradeStatus { @@ -2172,25 +2204,24 @@ export interface Spotlight { } export interface Scenario { - name?: string | undefined; - strategies?: Strategy[] | undefined; + name?: string | null; + strategies?: Strategy[] | null; } export interface Strategy { - name?: string | undefined; + name?: string | null; timeframe?: Timeframe; - candles?: Candle[] | undefined; type?: StrategyType; signalType?: SignalType; minimumHistory?: number; - period?: number | undefined; - fastPeriods?: number | undefined; - slowPeriods?: number | undefined; - signalPeriods?: number | undefined; - multiplier?: number | undefined; - smoothPeriods?: number | undefined; - stochPeriods?: number | undefined; - cyclePeriods?: number | undefined; + period?: number | null; + fastPeriods?: number | null; + slowPeriods?: number | null; + signalPeriods?: number | null; + multiplier?: number | null; + smoothPeriods?: number | null; + stochPeriods?: number | null; + cyclePeriods?: number | null; } export interface TickerSignal { @@ -2227,10 +2258,10 @@ export interface IFlow { type: FlowType; description: string; acceptedInputs: FlowOutput[]; - children?: IFlow[] | undefined; + children?: IFlow[] | null; parameters: FlowParameter[]; parentId?: string; - output?: string | undefined; + output?: string | null; outputTypes: FlowOutput[]; } @@ -2248,8 +2279,8 @@ export enum FlowOutput { } export interface FlowParameter { - value?: any | undefined; - name?: string | undefined; + value?: any | null; + name?: string | null; } export interface SyntheticWorkflow { @@ -2261,7 +2292,7 @@ export interface SyntheticWorkflow { export interface SyntheticFlow { id: string; - parentId?: string | undefined; + parentId?: string | null; type: FlowType; parameters: SyntheticFlowParameter[]; } @@ -2307,4 +2338,4 @@ function throwException(message: string, status: number, response: string, heade throw result; else throw new ApiException(message, status, response, headers, null); -} +} \ No newline at end of file