docker files fixes from liaqat
This commit is contained in:
27
src/Managing.Api/Authorization/JwtMiddleware.cs
Normal file
27
src/Managing.Api/Authorization/JwtMiddleware.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using Managing.Application.Abstractions.Services;
|
||||
|
||||
namespace Managing.Api.Authorization;
|
||||
|
||||
|
||||
public class JwtMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
|
||||
public JwtMiddleware(RequestDelegate next, IConfiguration config)
|
||||
{
|
||||
_next = next;
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext context, IUserService userService, IJwtUtils jwtUtils)
|
||||
{
|
||||
var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
|
||||
var userId = jwtUtils.ValidateJwtToken(token);
|
||||
if (userId != null)
|
||||
{
|
||||
// attach user to context on successful jwt validation
|
||||
context.Items["User"] = await userService.GetUserByAddressAsync(userId);
|
||||
}
|
||||
|
||||
await _next(context);
|
||||
}
|
||||
}
|
||||
70
src/Managing.Api/Authorization/JwtUtils.cs
Normal file
70
src/Managing.Api/Authorization/JwtUtils.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using Managing.Domain.Users;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
|
||||
namespace Managing.Api.Authorization;
|
||||
|
||||
|
||||
public interface IJwtUtils
|
||||
{
|
||||
public string GenerateJwtToken(User user, string publicAddress);
|
||||
public string ValidateJwtToken(string token);
|
||||
}
|
||||
|
||||
public class JwtUtils : IJwtUtils
|
||||
{
|
||||
private readonly string _secret;
|
||||
public JwtUtils(IConfiguration config)
|
||||
{
|
||||
_secret = config.GetValue<string>("Jwt:Secret");
|
||||
}
|
||||
|
||||
public string GenerateJwtToken(User user, string publicAddress)
|
||||
{
|
||||
// generate token that is valid for 15 minutes
|
||||
var tokenHandler = new JwtSecurityTokenHandler();
|
||||
var key = Encoding.ASCII.GetBytes(_secret);
|
||||
var tokenDescriptor = new SecurityTokenDescriptor
|
||||
{
|
||||
Subject = new ClaimsIdentity(new[] { new Claim("address", publicAddress) }),
|
||||
Expires = DateTime.UtcNow.AddDays(15),
|
||||
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
|
||||
};
|
||||
var token = tokenHandler.CreateToken(tokenDescriptor);
|
||||
return tokenHandler.WriteToken(token);
|
||||
}
|
||||
|
||||
public string ValidateJwtToken(string token)
|
||||
{
|
||||
if (token == null || string.IsNullOrEmpty(token))
|
||||
return null;
|
||||
|
||||
var tokenHandler = new JwtSecurityTokenHandler();
|
||||
var key = Encoding.ASCII.GetBytes(_secret);
|
||||
try
|
||||
{
|
||||
tokenHandler.ValidateToken(token, new TokenValidationParameters
|
||||
{
|
||||
ValidateIssuerSigningKey = true,
|
||||
IssuerSigningKey = new SymmetricSecurityKey(key),
|
||||
ValidateIssuer = false,
|
||||
ValidateAudience = false,
|
||||
// set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
|
||||
ClockSkew = TimeSpan.Zero
|
||||
}, out SecurityToken validatedToken);
|
||||
|
||||
var jwtToken = (JwtSecurityToken)validatedToken;
|
||||
var address = jwtToken.Claims.First(x => x.Type == "address").Value;
|
||||
|
||||
// return user id from JWT token if validation successful
|
||||
return address;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// return null if validation fails
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
58
src/Managing.Api/Controllers/AccountController.cs
Normal file
58
src/Managing.Api/Controllers/AccountController.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Domain.Accounts;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Managing.Api.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class AccountController : BaseController
|
||||
{
|
||||
private readonly IAccountService _AccountService;
|
||||
|
||||
public AccountController(
|
||||
IAccountService AccountService,
|
||||
IUserService userService)
|
||||
: base(userService)
|
||||
{
|
||||
_AccountService = AccountService;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<Account>> PostAccount(Account Account)
|
||||
{
|
||||
var user = await GetUser();
|
||||
return Ok(await _AccountService.CreateAccount(user, Account));
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("accounts")]
|
||||
public async Task<ActionResult<IEnumerable<Account>>> GetAccounts()
|
||||
{
|
||||
var user = await GetUser();
|
||||
return Ok(_AccountService.GetAccountsByUser(user, true));
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("balances")]
|
||||
public async Task<ActionResult<IEnumerable<Account>>> GetAccountsBalances()
|
||||
{
|
||||
var user = await GetUser();
|
||||
return Ok(_AccountService.GetAccountsBalancesByUser(user));
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<Account>> GetAccount(string name)
|
||||
{
|
||||
var user = await GetUser();
|
||||
return Ok(await _AccountService.GetAccountByUser(user, name, true, true));
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
public ActionResult DeleteAccount(string name)
|
||||
{
|
||||
var user = GetUser().Result;
|
||||
return Ok(_AccountService.DeleteAccount(user, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
133
src/Managing.Api/Controllers/BacktestController.cs
Normal file
133
src/Managing.Api/Controllers/BacktestController.cs
Normal file
@@ -0,0 +1,133 @@
|
||||
using Managing.Application.Abstractions;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Hubs;
|
||||
using Managing.Domain.Backtests;
|
||||
using Managing.Domain.MoneyManagements;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
[Route("[controller]")]
|
||||
[Produces("application/json")]
|
||||
public class BacktestController : ControllerBase
|
||||
{
|
||||
private readonly IHubContext<BotHub> _hubContext;
|
||||
private readonly IBacktester _backtester;
|
||||
private readonly IScenarioService _scenarioService;
|
||||
private readonly IAccountService _accountService;
|
||||
private readonly IMoneyManagementService _moneyManagementService;
|
||||
|
||||
public BacktestController(
|
||||
IHubContext<BotHub> hubContext,
|
||||
IBacktester backtester,
|
||||
IScenarioService scenarioService,
|
||||
IAccountService accountService,
|
||||
IMoneyManagementService moneyManagementService)
|
||||
{
|
||||
_hubContext = hubContext;
|
||||
_backtester = backtester;
|
||||
_scenarioService = scenarioService;
|
||||
_accountService = accountService;
|
||||
_moneyManagementService = moneyManagementService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public ActionResult<IEnumerable<Backtest>> Backtests()
|
||||
{
|
||||
return Ok(_backtester.GetBacktests());
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
public ActionResult DeleteBacktest(string id)
|
||||
{
|
||||
return Ok(_backtester.DeleteBacktest(id));
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
[Route("deleteAll")]
|
||||
public ActionResult DeleteBacktests()
|
||||
{
|
||||
return Ok(_backtester.DeleteBacktests());
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("Run")]
|
||||
public async Task<ActionResult<Backtest>> Run(string accountName,
|
||||
BotType botType,
|
||||
Ticker ticker,
|
||||
string scenarioName,
|
||||
Timeframe timeframe,
|
||||
bool watchOnly,
|
||||
int days,
|
||||
decimal balance,
|
||||
string moneyManagementName,
|
||||
MoneyManagement? moneyManagement = null,
|
||||
bool save = false)
|
||||
{
|
||||
if (string.IsNullOrEmpty(accountName))
|
||||
{
|
||||
throw new ArgumentException($"'{nameof(accountName)}' cannot be null or empty.", nameof(accountName));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(scenarioName))
|
||||
{
|
||||
throw new ArgumentException($"'{nameof(scenarioName)}' cannot be null or empty.", nameof(scenarioName));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(moneyManagementName) && moneyManagement == null)
|
||||
{
|
||||
throw new ArgumentException($"'{nameof(moneyManagementName)}' and '{nameof(moneyManagement)}' cannot be null or empty.", nameof(moneyManagementName));
|
||||
}
|
||||
|
||||
if (days > 0)
|
||||
{
|
||||
days = days * -1;
|
||||
}
|
||||
|
||||
Backtest backtestResult = null;
|
||||
var scenario = _scenarioService.GetScenario(scenarioName);
|
||||
var account = await _accountService.GetAccount(accountName, true, false);
|
||||
|
||||
if (!string.IsNullOrEmpty(moneyManagementName) && moneyManagement is null)
|
||||
{
|
||||
moneyManagement = await _moneyManagementService.GetMoneyMangement(moneyManagementName);
|
||||
}
|
||||
else
|
||||
{
|
||||
moneyManagement.FormatPercentage();
|
||||
}
|
||||
|
||||
if (scenario == null)
|
||||
return BadRequest("No scenario found");
|
||||
|
||||
switch (botType)
|
||||
{
|
||||
case BotType.SimpleBot:
|
||||
break;
|
||||
case BotType.ScalpingBot:
|
||||
backtestResult = _backtester.RunScalpingBotBacktest(account, moneyManagement, ticker, scenario,
|
||||
timeframe, Convert.ToDouble(days), balance, watchOnly, save);
|
||||
break;
|
||||
case BotType.FlippingBot:
|
||||
backtestResult = _backtester.RunFlippingBotBacktest(account, moneyManagement, ticker, scenario,
|
||||
timeframe, Convert.ToDouble(days), balance, watchOnly, save);
|
||||
break;
|
||||
}
|
||||
|
||||
await NotifyBacktesingSubscriberAsync(backtestResult);
|
||||
|
||||
return Ok(backtestResult);
|
||||
}
|
||||
|
||||
private async Task NotifyBacktesingSubscriberAsync(Backtest backtesting)
|
||||
{
|
||||
if(backtesting != null){
|
||||
await _hubContext.Clients.All.SendAsync("BacktestsSubscription", backtesting);
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/Managing.Api/Controllers/BaseController.cs
Normal file
35
src/Managing.Api/Controllers/BaseController.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Domain.Users;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace Managing.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("[controller]")]
|
||||
[Produces("application/json")]
|
||||
public abstract class BaseController : ControllerBase
|
||||
{
|
||||
private readonly IUserService _userService;
|
||||
|
||||
public BaseController(IUserService userService)
|
||||
{
|
||||
_userService = userService;
|
||||
}
|
||||
|
||||
protected async Task<User> GetUser()
|
||||
{
|
||||
var identity = HttpContext?.User.Identity as ClaimsIdentity;
|
||||
if (identity != null)
|
||||
{
|
||||
var address = identity.Claims.FirstOrDefault(c => c.Type == "address").Value;
|
||||
var user = await _userService.GetUserByAddressAsync(address);
|
||||
|
||||
if (user != null)
|
||||
return user;
|
||||
|
||||
throw new Exception("User not found for this token");
|
||||
}
|
||||
throw new Exception("Not identity assigned to this token");
|
||||
}
|
||||
}
|
||||
168
src/Managing.Api/Controllers/BotController.cs
Normal file
168
src/Managing.Api/Controllers/BotController.cs
Normal file
@@ -0,0 +1,168 @@
|
||||
using Managing.Api.Models.Requests;
|
||||
using Managing.Api.Models.Responses;
|
||||
using Managing.Application.Abstractions;
|
||||
using Managing.Application.Hubs;
|
||||
using Managing.Application.ManageBot.Commands;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
[Route("[controller]")]
|
||||
[Produces("application/json")]
|
||||
public class BotController : ControllerBase
|
||||
{
|
||||
private readonly IMediator _mediator;
|
||||
private readonly ILogger<BotController> _logger;
|
||||
private readonly IHubContext<BotHub> _hubContext;
|
||||
private readonly IBacktester _backtester;
|
||||
|
||||
public BotController(ILogger<BotController> logger, IMediator mediator, IHubContext<BotHub> hubContext, IBacktester backtester)
|
||||
{
|
||||
_logger = logger;
|
||||
_mediator = mediator;
|
||||
_hubContext = hubContext;
|
||||
_backtester = backtester;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("Start")]
|
||||
public async Task<ActionResult<string>> Start(StartBotRequest request)
|
||||
{
|
||||
var result = await _mediator.Send(new StartBotCommand(request.BotType, request.BotName, request.Ticker,
|
||||
request.Scenario, request.Timeframe, request.AccountName, request.MoneyManagementName, request.IsForWatchOnly));
|
||||
|
||||
await NotifyBotSubscriberAsync();
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("Stop")]
|
||||
public async Task<ActionResult<string>> Stop(BotType botType, string botName)
|
||||
{
|
||||
var result = await _mediator.Send(new StopBotCommand(botType, botName));
|
||||
_logger.LogInformation($"{botType} type called {botName} is now {result}");
|
||||
|
||||
await NotifyBotSubscriberAsync();
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
[Route("Delete")]
|
||||
public async Task<ActionResult<bool>> Delete(string botName)
|
||||
{
|
||||
var result = await _mediator.Send(new DeleteBotCommand(botName));
|
||||
_logger.LogInformation($"{botName} is now deleted");
|
||||
|
||||
await NotifyBotSubscriberAsync();
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("StopAll")]
|
||||
public async Task<string> StopAll()
|
||||
{
|
||||
var bots = await GetBotList();
|
||||
var result = "";
|
||||
foreach (var bot in bots)
|
||||
{
|
||||
result += $"{bot.Name} : ";
|
||||
result = await _mediator.Send(new StopBotCommand(bot.BotType, bot.Name));
|
||||
result += $" |";
|
||||
}
|
||||
|
||||
await NotifyBotSubscriberAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("Restart")]
|
||||
public async Task<ActionResult<string>> Restart(BotType botType, string botName)
|
||||
{
|
||||
var result = await _mediator.Send(new RestartBotCommand(botType, botName));
|
||||
_logger.LogInformation($"{botType} type called {botName} is now {result}");
|
||||
|
||||
await NotifyBotSubscriberAsync();
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("RestartAll")]
|
||||
public async Task<string> RestartAll()
|
||||
{
|
||||
var bots = await GetBotList();
|
||||
var result = "";
|
||||
foreach (var bot in bots)
|
||||
{
|
||||
result += $"{bot.Name} : ";
|
||||
result = await _mediator.Send(new RestartBotCommand(bot.BotType, bot.Name));
|
||||
result += $" |";
|
||||
}
|
||||
|
||||
await NotifyBotSubscriberAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("ToggleIsForWatching")]
|
||||
public async Task<ActionResult<string>> ToggleIsForWatching(string botName)
|
||||
{
|
||||
var result = await _mediator.Send(new ToggleIsForWatchingCommand(botName));
|
||||
_logger.LogInformation($"{botName} bot is now {result}");
|
||||
|
||||
await NotifyBotSubscriberAsync();
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<List<TradingBot>> GetActiveBots()
|
||||
{
|
||||
return await GetBotList();
|
||||
}
|
||||
|
||||
private async Task<List<TradingBot>> GetBotList()
|
||||
{
|
||||
var result = await _mediator.Send(new GetActiveBotsCommand());
|
||||
var list = new List<TradingBot>();
|
||||
|
||||
foreach (var item in result)
|
||||
{
|
||||
list.Add(new TradingBot
|
||||
{
|
||||
Status = item.GetStatus(),
|
||||
Name = item.GetName(),
|
||||
Candles = item.Candles.ToList(),
|
||||
Positions = item.Positions,
|
||||
Signals = item.Signals.ToList(),
|
||||
WinRate = item.GetWinRate(),
|
||||
ProfitAndLoss = item.GetProfitAndLoss(),
|
||||
Timeframe = item.Timeframe,
|
||||
Ticker = item.Ticker,
|
||||
AccountName = item.AccountName,
|
||||
Scenario = item.Scenario,
|
||||
IsForWatchingOnly = item.IsForWatchingOnly,
|
||||
BotType = item.BotType,
|
||||
MoneyManagement = item.MoneyManagement
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private async Task NotifyBotSubscriberAsync()
|
||||
{
|
||||
var botsList = await GetBotList();
|
||||
await _hubContext.Clients.All.SendAsync("BotsSubscription", botsList);
|
||||
}
|
||||
}
|
||||
73
src/Managing.Api/Controllers/DataController.cs
Normal file
73
src/Managing.Api/Controllers/DataController.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using Managing.Application.Abstractions;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Hubs;
|
||||
using Managing.Application.Workers.Abstractions;
|
||||
using Managing.Domain.Candles;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
[Route("[controller]")]
|
||||
public class DataController : ControllerBase
|
||||
{
|
||||
private readonly IExchangeService _exchangeService;
|
||||
private readonly IAccountService _accountService;
|
||||
private readonly ICacheService _cacheService;
|
||||
private readonly IStatisticService _statisticService;
|
||||
private readonly IHubContext<CandleHub> _hubContext;
|
||||
|
||||
public DataController(
|
||||
IExchangeService exchangeService,
|
||||
IAccountService accountService,
|
||||
ICacheService cacheService,
|
||||
IStatisticService statisticService,
|
||||
IHubContext<CandleHub> hubContext)
|
||||
{
|
||||
_exchangeService = exchangeService;
|
||||
_accountService = accountService;
|
||||
_cacheService = cacheService;
|
||||
_statisticService = statisticService;
|
||||
_hubContext = hubContext;
|
||||
}
|
||||
|
||||
[HttpPost("GetTickers")]
|
||||
public async Task<ActionResult<Ticker[]>> GetTickers(string accountName, 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));
|
||||
|
||||
return Ok(tickers);
|
||||
}
|
||||
|
||||
[HttpGet("Spotlight")]
|
||||
public ActionResult<SpotlightOverview> GetSpotlight()
|
||||
{
|
||||
var overview = _cacheService.GetOrSave(nameof(SpotlightOverview), () =>
|
||||
{
|
||||
return _statisticService.GetLastSpotlight(DateTime.Now.AddHours(-3));
|
||||
}, TimeSpan.FromMinutes(2));
|
||||
|
||||
if (overview?.Spotlights.Count < overview?.ScenarioCount)
|
||||
{
|
||||
overview = _statisticService.GetLastSpotlight(DateTime.Now.AddHours(-3));
|
||||
}
|
||||
|
||||
return Ok(overview);
|
||||
}
|
||||
|
||||
[HttpGet("GetCandles")]
|
||||
public async Task<ActionResult<List<Candle>>> GetCandles(TradingExchanges exchange, Ticker ticker, DateTime startDate, Timeframe timeframe)
|
||||
{
|
||||
return Ok(await _exchangeService.GetCandlesInflux(exchange, ticker, startDate, timeframe));
|
||||
}
|
||||
|
||||
}
|
||||
44
src/Managing.Api/Controllers/MoneyManagementController.cs
Normal file
44
src/Managing.Api/Controllers/MoneyManagementController.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using Managing.Application.Abstractions;
|
||||
using Managing.Domain.MoneyManagements;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Managing.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
[Route("[controller]")]
|
||||
[Produces("application/json")]
|
||||
public class MoneyManagementController : ControllerBase
|
||||
{
|
||||
private readonly IMoneyManagementService _moneyManagementService;
|
||||
public MoneyManagementController(IMoneyManagementService moneyManagementService)
|
||||
{
|
||||
_moneyManagementService = moneyManagementService;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<MoneyManagement>> PostMoneyManagement(MoneyManagement moneyManagement)
|
||||
{
|
||||
return Ok(await _moneyManagementService.CreateOrUpdateMoneyManagement(moneyManagement));
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("moneymanagements")]
|
||||
public ActionResult<IEnumerable<MoneyManagement>> GetMoneyManagements()
|
||||
{
|
||||
return Ok(_moneyManagementService.GetMoneyMangements());
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public ActionResult<MoneyManagement> GetMoneyManagement(string name)
|
||||
{
|
||||
return Ok(_moneyManagementService.GetMoneyMangement(name));
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
public ActionResult DeleteMoneyManagement(string name)
|
||||
{
|
||||
return Ok(_moneyManagementService.DeleteMoneyManagement(name));
|
||||
}
|
||||
}
|
||||
83
src/Managing.Api/Controllers/ScenarioController.cs
Normal file
83
src/Managing.Api/Controllers/ScenarioController.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using Managing.Application.Abstractions;
|
||||
using Managing.Domain.Scenarios;
|
||||
using Managing.Domain.Strategies;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
[Route("[controller]")]
|
||||
[Produces("application/json")]
|
||||
public class ScenarioController : ControllerBase
|
||||
{
|
||||
private readonly IScenarioService _scenarioService;
|
||||
public ScenarioController(IScenarioService scenarioService)
|
||||
{
|
||||
_scenarioService = scenarioService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public ActionResult<IEnumerable<Scenario>> GetScenarios()
|
||||
{
|
||||
return Ok(_scenarioService.GetScenarios());
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult<Scenario> CreateScenario(string name, List<string> strategies)
|
||||
{
|
||||
return Ok(_scenarioService.CreateScenario(name, strategies));
|
||||
}
|
||||
|
||||
|
||||
[HttpDelete]
|
||||
public ActionResult DeleteScenario(string name)
|
||||
{
|
||||
return Ok(_scenarioService.DeleteScenario(name));
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("strategy")]
|
||||
public ActionResult<IEnumerable<Strategy>> GetStrategies()
|
||||
{
|
||||
return Ok(_scenarioService.GetStrategies());
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("strategy")]
|
||||
public ActionResult<Strategy> CreateStrategy(
|
||||
StrategyType strategyType,
|
||||
Timeframe timeframe,
|
||||
string name,
|
||||
int? period = null,
|
||||
int? fastPeriods = null,
|
||||
int? slowPeriods = null,
|
||||
int? signalPeriods = null,
|
||||
double? multiplier = null,
|
||||
int? stochPeriods = null,
|
||||
int? smoothPeriods = null,
|
||||
int? cyclePeriods = null)
|
||||
{
|
||||
return Ok(_scenarioService.CreateStrategy(
|
||||
strategyType,
|
||||
timeframe,
|
||||
name,
|
||||
period,
|
||||
fastPeriods,
|
||||
slowPeriods,
|
||||
signalPeriods,
|
||||
multiplier,
|
||||
stochPeriods,
|
||||
smoothPeriods,
|
||||
cyclePeriods));
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
[Route("strategy")]
|
||||
public ActionResult DeleteStrategy(string name)
|
||||
{
|
||||
return Ok(_scenarioService.DeleteStrategy(name));
|
||||
}
|
||||
}
|
||||
30
src/Managing.Api/Controllers/SettingsController.cs
Normal file
30
src/Managing.Api/Controllers/SettingsController.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Managing.Application.Abstractions;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Managing.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
[Route("[controller]")]
|
||||
[Produces("application/json")]
|
||||
public class SettingsController : ControllerBase
|
||||
{
|
||||
private readonly ISettingsService _settingsService;
|
||||
public SettingsController(ISettingsService settingsService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult SetupSettings()
|
||||
{
|
||||
return Ok(_settingsService.SetupSettings());
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
public async Task<ActionResult<bool>> ResetSettings()
|
||||
{
|
||||
return Ok(await _settingsService.ResetSettings());
|
||||
}
|
||||
}
|
||||
107
src/Managing.Api/Controllers/TradingController.cs
Normal file
107
src/Managing.Api/Controllers/TradingController.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using Managing.Application.Abstractions;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Trading.Commands;
|
||||
using Managing.Domain.MoneyManagements;
|
||||
using Managing.Domain.Trades;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
[Route("[controller]")]
|
||||
public class TradingController : ControllerBase
|
||||
{
|
||||
private readonly ICommandHandler<OpenPositionRequest, Position> _openTradeCommandHandler;
|
||||
private readonly ICommandHandler<ClosePositionCommand, Position> _closeTradeCommandHandler;
|
||||
private readonly ITradingService _tradingService;
|
||||
private readonly IMoneyManagementService _moneyManagementService;
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
private readonly ILogger<TradingController> _logger;
|
||||
|
||||
public TradingController(
|
||||
ILogger<TradingController> logger,
|
||||
ICommandHandler<OpenPositionRequest, Position> openTradeCommandHandler,
|
||||
ICommandHandler<ClosePositionCommand, Position> closeTradeCommandHandler,
|
||||
ITradingService tradingService,
|
||||
IMediator mediator)
|
||||
{
|
||||
_logger = logger;
|
||||
_openTradeCommandHandler = openTradeCommandHandler;
|
||||
_closeTradeCommandHandler = closeTradeCommandHandler;
|
||||
_tradingService = tradingService;
|
||||
_mediator = mediator;
|
||||
}
|
||||
|
||||
[HttpGet("GetPositions")]
|
||||
public async Task<ActionResult<List<Position>>> GetPositions(PositionInitiator positionInitiator)
|
||||
{
|
||||
var result = await _mediator.Send(new GetPositionsCommand(positionInitiator));
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpGet("GetTrade")]
|
||||
public async Task<ActionResult<Trade>> GetTrade(string accountName, Ticker ticker, string exchangeOrderId)
|
||||
{
|
||||
var result = await _mediator.Send(new GetTradeCommand(accountName, exchangeOrderId, ticker));
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpGet("GetTrades")]
|
||||
public async Task<ActionResult<Trade>> GetTrades(string accountName, Ticker ticker, string exchangeOrderId)
|
||||
{
|
||||
var result = await _mediator.Send(new GetTradesCommand(ticker, accountName));
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpGet("ClosePosition")]
|
||||
public async Task<ActionResult<Position>> ClosePosition(string identifier)
|
||||
{
|
||||
var position = _tradingService.GetPositionByIdentifier(identifier);
|
||||
var result = await _closeTradeCommandHandler.Handle(new ClosePositionCommand(position));
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpGet("OpenPosition")]
|
||||
public async Task<ActionResult<Position>> Trade(
|
||||
string accountName,
|
||||
string moneyManagementName,
|
||||
TradeDirection direction,
|
||||
Ticker ticker,
|
||||
RiskLevel riskLevel,
|
||||
bool isForPaperTrading,
|
||||
MoneyManagement? moneyManagement = null,
|
||||
decimal? openPrice = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(accountName))
|
||||
{
|
||||
throw new ArgumentException($"'{nameof(accountName)}' cannot be null or empty.", nameof(accountName));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(moneyManagementName) && moneyManagement == null)
|
||||
{
|
||||
throw new ArgumentException($"'{nameof(moneyManagementName)}' cannot be null or empty.", nameof(moneyManagementName));
|
||||
}
|
||||
|
||||
if (moneyManagement == null)
|
||||
{
|
||||
moneyManagement = await _moneyManagementService.GetMoneyMangement(moneyManagementName);
|
||||
}
|
||||
|
||||
var command = new OpenPositionRequest(
|
||||
accountName,
|
||||
moneyManagement,
|
||||
direction,
|
||||
ticker,
|
||||
PositionInitiator.User,
|
||||
DateTime.UtcNow,
|
||||
isForPaperTrading: isForPaperTrading,
|
||||
price: openPrice);
|
||||
var result = await _openTradeCommandHandler.Handle(command);
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
39
src/Managing.Api/Controllers/UserController.cs
Normal file
39
src/Managing.Api/Controllers/UserController.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using Managing.Api.Authorization;
|
||||
using Managing.Api.Models.Requests;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Managing.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("[controller]")]
|
||||
[Produces("application/json")]
|
||||
public class UserController : ControllerBase
|
||||
{
|
||||
private IConfiguration _config;
|
||||
private readonly IUserService _userService;
|
||||
private readonly IJwtUtils _jwtUtils;
|
||||
|
||||
public UserController(IConfiguration config, IUserService userService, IJwtUtils jwtUtils)
|
||||
{
|
||||
_config = config;
|
||||
_userService = userService;
|
||||
_jwtUtils = jwtUtils;
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<string>> CreateToken([FromBody] LoginRequest login)
|
||||
{
|
||||
var user = await _userService.Authenticate(login.Name, login.Address, login.Message, login.Signature);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
var tokenString = _jwtUtils.GenerateJwtToken(user, login.Address);
|
||||
return Ok(tokenString);
|
||||
}
|
||||
|
||||
return Unauthorized();
|
||||
}
|
||||
}
|
||||
45
src/Managing.Api/Controllers/WorkflowController.cs
Normal file
45
src/Managing.Api/Controllers/WorkflowController.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using Managing.Application.Abstractions;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Domain.Workflows;
|
||||
using Managing.Domain.Workflows.Synthetics;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Managing.Api.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class WorkflowController : BaseController
|
||||
{
|
||||
private readonly IWorkflowService _workflowService;
|
||||
|
||||
public WorkflowController(IWorkflowService WorkflowService, IUserService userService) : base(userService)
|
||||
{
|
||||
_workflowService = WorkflowService;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<Workflow>> PostWorkflow([ModelBinder]SyntheticWorkflow workflowRequest)
|
||||
{
|
||||
return Ok(await _workflowService.InsertOrUpdateWorkflow(workflowRequest));
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public ActionResult<IEnumerable<SyntheticWorkflow>> GetWorkflows()
|
||||
{
|
||||
return Ok(_workflowService.GetWorkflows());
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("flows")]
|
||||
public async Task<ActionResult<IEnumerable<IFlow>>> GetAvailableFlows()
|
||||
{
|
||||
return Ok(await _workflowService.GetAvailableFlows());
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
public ActionResult DeleteWorkflow(string name)
|
||||
{
|
||||
return Ok(_workflowService.DeleteWorkflow(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
36
src/Managing.Api/Dockerfile
Normal file
36
src/Managing.Api/Dockerfile
Normal file
@@ -0,0 +1,36 @@
|
||||
# Use the official Microsoft ASP.NET Core runtime as the base image.
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
|
||||
# Use the official Microsoft .NET SDK image to build the code.
|
||||
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
|
||||
WORKDIR /src
|
||||
COPY ["Managing.Api/Managing.Api.csproj", "Managing.Api/"]
|
||||
COPY ["Managing.Bootstrap/Managing.Bootstrap.csproj", "Managing.Bootstrap/"]
|
||||
COPY ["Managing.Infrastructure.Storage/Managing.Infrastructure.Storage.csproj", "Managing.Infrastructure.Storage/"]
|
||||
COPY ["Managing.Application/Managing.Application.csproj", "Managing.Application/"]
|
||||
COPY ["Managing.Infrastructure.MongoDb/Managing.Infrastructure.MongoDb.csproj", "Managing.Infrastructure.MongoDb/"]
|
||||
COPY ["Managing.Common/Managing.Common.csproj", "Managing.Common/"]
|
||||
COPY ["Managing.Core/Managing.Core.csproj", "Managing.Core/"]
|
||||
COPY ["Managing.Application.Abstractions/Managing.Application.Abstractions.csproj", "Managing.Application.Abstractions/"]
|
||||
COPY ["Managing.Domain/Managing.Domain.csproj", "Managing.Domain/"]
|
||||
COPY ["Managing.Application.Workers/Managing.Application.Workers.csproj", "Managing.Application.Workers/"]
|
||||
COPY ["Managing.Infrastructure.Messengers/Managing.Infrastructure.Messengers.csproj", "Managing.Infrastructure.Messengers/"]
|
||||
COPY ["Managing.Infrastructure.Exchanges/Managing.Infrastructure.Exchanges.csproj", "Managing.Infrastructure.Exchanges/"]
|
||||
COPY ["Managing.Infrastructure.Database/Managing.Infrastructure.Databases.csproj", "Managing.Infrastructure.Database/"]
|
||||
RUN dotnet restore "Managing.Api/Managing.Api.csproj"
|
||||
COPY . .
|
||||
WORKDIR "/src/Managing.Api"
|
||||
RUN dotnet build "Managing.Api.csproj" -c Release -o /app/build
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish "Managing.Api.csproj" -c Release -o /app/publish
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app/publish .
|
||||
COPY Managing.Api/managing_cert.pfx .
|
||||
COPY Managing.Api/appsettings.Lowpro.json .
|
||||
ENTRYPOINT ["dotnet", "Managing.Api.dll"]
|
||||
62
src/Managing.Api/Exceptions/GlobalErrorHandlingMiddleware.cs
Normal file
62
src/Managing.Api/Exceptions/GlobalErrorHandlingMiddleware.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Managing.Api.Exceptions;
|
||||
|
||||
public class GlobalErrorHandlingMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
public GlobalErrorHandlingMiddleware(RequestDelegate next)
|
||||
{
|
||||
_next = next;
|
||||
}
|
||||
public async Task Invoke(HttpContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _next(context);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await HandleExceptionAsync(context, ex);
|
||||
}
|
||||
}
|
||||
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
|
||||
{
|
||||
HttpStatusCode status;
|
||||
var exceptionType = exception.GetType();
|
||||
|
||||
if (exceptionType == typeof(Exception))
|
||||
{
|
||||
status = HttpStatusCode.InternalServerError;
|
||||
}
|
||||
else if (exceptionType == typeof(NotImplementedException))
|
||||
{
|
||||
status = HttpStatusCode.NotImplemented;
|
||||
}
|
||||
else if (exceptionType == typeof(UnauthorizedAccessException))
|
||||
{
|
||||
status = HttpStatusCode.Unauthorized;
|
||||
}
|
||||
else if (exceptionType == typeof(ArgumentException))
|
||||
{
|
||||
status = HttpStatusCode.Unauthorized;
|
||||
}
|
||||
else if (exceptionType == typeof(KeyNotFoundException))
|
||||
{
|
||||
status = HttpStatusCode.Unauthorized;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = HttpStatusCode.InternalServerError;
|
||||
}
|
||||
|
||||
var message = exception.Message;
|
||||
var stackTrace = exception.StackTrace;
|
||||
var exceptionResult = JsonSerializer.Serialize(new { error = message, stackTrace });
|
||||
|
||||
context.Response.ContentType = "application/json";
|
||||
context.Response.StatusCode = (int)status;
|
||||
return context.Response.WriteAsync(exceptionResult);
|
||||
}
|
||||
}
|
||||
20
src/Managing.Api/Filters/EnumSchemaFilter.cs
Normal file
20
src/Managing.Api/Filters/EnumSchemaFilter.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
|
||||
namespace Managing.Api.Filters
|
||||
{
|
||||
public class EnumSchemaFilter : ISchemaFilter
|
||||
{
|
||||
public void Apply(OpenApiSchema model, SchemaFilterContext context)
|
||||
{
|
||||
if (context.Type.IsEnum)
|
||||
{
|
||||
model.Enum.Clear();
|
||||
Enum.GetNames(context.Type)
|
||||
.ToList()
|
||||
.ForEach(n => model.Enum.Add(new OpenApiString(n)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
43
src/Managing.Api/Managing.Api.csproj
Normal file
43
src/Managing.Api/Managing.Api.csproj
Normal file
@@ -0,0 +1,43 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<DockerComposeProjectPath>..\..\docker-compose.dcproj</DockerComposeProjectPath>
|
||||
<UserSecretsId>7476db9f-ade4-414a-a420-e3ab55cb5f8d</UserSecretsId>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
<DockerfileContext>..\..</DockerfileContext>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Essential.LoggerProvider.Elasticsearch" Version="1.3.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.10" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" />
|
||||
<PackageReference Include="NSwag.AspNetCore" Version="13.20.0" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.2.0" />
|
||||
<PackageReference Include="Serilog.Exceptions" Version="8.4.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="9.0.3" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.5.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="6.5.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.5.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.5.0" />
|
||||
<PackageReference Include="xunit" Version="2.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Managing.Bootstrap\Managing.Bootstrap.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="appsettings.Oda-sandbox.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
12
src/Managing.Api/Models/Requests/CreateScenarioRequest.cs
Normal file
12
src/Managing.Api/Models/Requests/CreateScenarioRequest.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Managing.Api.Models.Requests
|
||||
{
|
||||
public class CreateScenarioRequest
|
||||
{
|
||||
[Required]
|
||||
public string Name { get; internal set; }
|
||||
[Required]
|
||||
public List<string> Strategies { get; internal set; }
|
||||
}
|
||||
}
|
||||
16
src/Managing.Api/Models/Requests/CreateStrategyRequest.cs
Normal file
16
src/Managing.Api/Models/Requests/CreateStrategyRequest.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Api.Models.Requests;
|
||||
|
||||
public class CreateStrategyRequest
|
||||
{
|
||||
[Required]
|
||||
public StrategyType Type { get; internal set; }
|
||||
[Required]
|
||||
public Timeframe Timeframe { get; internal set; }
|
||||
[Required]
|
||||
public string Name { get; internal set; }
|
||||
[Required]
|
||||
public int Period { get; internal set; }
|
||||
}
|
||||
15
src/Managing.Api/Models/Requests/LoginRequest.cs
Normal file
15
src/Managing.Api/Models/Requests/LoginRequest.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Managing.Api.Models.Requests;
|
||||
|
||||
public class LoginRequest
|
||||
{
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
[Required]
|
||||
public string Address { get; set; }
|
||||
[Required]
|
||||
public string Signature { get; set; }
|
||||
[Required]
|
||||
public string Message { get; set; }
|
||||
}
|
||||
15
src/Managing.Api/Models/Requests/RunBacktestRequest.cs
Normal file
15
src/Managing.Api/Models/Requests/RunBacktestRequest.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Api.Models.Requests
|
||||
{
|
||||
public class RunBacktestRequest
|
||||
{
|
||||
public TradingExchanges Exchange { get; set; }
|
||||
public BotType BotType { get; set; }
|
||||
public Ticker Ticker { get; set; }
|
||||
public Timeframe Timeframe { get; set; }
|
||||
public RiskLevel RiskLevel { get; set; }
|
||||
public bool WatchOnly { get; set; }
|
||||
public int Days { get; set; }
|
||||
}
|
||||
}
|
||||
25
src/Managing.Api/Models/Requests/StartBotRequest.cs
Normal file
25
src/Managing.Api/Models/Requests/StartBotRequest.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Api.Models.Requests
|
||||
{
|
||||
public class StartBotRequest
|
||||
{
|
||||
[Required]
|
||||
public BotType BotType { get; set; }
|
||||
[Required]
|
||||
public string BotName { get; set; }
|
||||
[Required]
|
||||
public Ticker Ticker { get; set; }
|
||||
[Required]
|
||||
public Timeframe Timeframe { get; set; }
|
||||
[Required]
|
||||
public bool IsForWatchOnly { get; set; }
|
||||
[Required]
|
||||
public string Scenario { get; set; }
|
||||
[Required]
|
||||
public string AccountName { get; set; }
|
||||
[Required]
|
||||
public string MoneyManagementName { get; set; }
|
||||
}
|
||||
}
|
||||
45
src/Managing.Api/Models/Responses/TradingBot.cs
Normal file
45
src/Managing.Api/Models/Responses/TradingBot.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.MoneyManagements;
|
||||
using Managing.Domain.Strategies;
|
||||
using Managing.Domain.Trades;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Api.Models.Responses
|
||||
{
|
||||
public class TradingBot
|
||||
{
|
||||
[Required]
|
||||
public string Name { get; internal set; }
|
||||
[Required]
|
||||
public string Status { get; internal set; }
|
||||
[Required]
|
||||
public List<Signal> Signals { get; internal set; }
|
||||
[Required]
|
||||
public List<Position> Positions { get; internal set; }
|
||||
[Required]
|
||||
public List<Candle> Candles { get; internal set; }
|
||||
[Required]
|
||||
public RiskLevel RiskLevel { get; internal set; }
|
||||
[Required]
|
||||
public int WinRate { get; internal set; }
|
||||
[Required]
|
||||
public decimal ProfitAndLoss { get; internal set; }
|
||||
[Required]
|
||||
public Timeframe Timeframe { get; internal set; }
|
||||
[Required]
|
||||
public Ticker Ticker { get; internal set; }
|
||||
[Required]
|
||||
public string Scenario { get; internal set; }
|
||||
[Required]
|
||||
public TradingExchanges Exchange { get; internal set; }
|
||||
[Required]
|
||||
public bool IsForWatchingOnly { get; internal set; }
|
||||
[Required]
|
||||
public BotType BotType { get; internal set; }
|
||||
[Required]
|
||||
public string AccountName { get; internal set; }
|
||||
[Required]
|
||||
public MoneyManagement MoneyManagement { get; internal set; }
|
||||
}
|
||||
}
|
||||
168
src/Managing.Api/Program.cs
Normal file
168
src/Managing.Api/Program.cs
Normal file
@@ -0,0 +1,168 @@
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using Managing.Api.Authorization;
|
||||
using Managing.Api.Exceptions;
|
||||
using Managing.Api.Filters;
|
||||
using Managing.Application.Hubs;
|
||||
using Managing.Bootstrap;
|
||||
using Managing.Common;
|
||||
using Managing.Infrastructure.Databases.InfluxDb.Models;
|
||||
using Managing.Infrastructure.Databases.MongoDb;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using NSwag;
|
||||
using NSwag.Generation.Processors.Security;
|
||||
using Serilog;
|
||||
using Serilog.Sinks.Elasticsearch;
|
||||
|
||||
// Builder
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
builder.Configuration.AddJsonFile("appsettings.Lowpro.json", optional: true, reloadOnChange: true)
|
||||
.AddJsonFile($"config.{builder.Environment.EnvironmentName}.json",
|
||||
optional: true, reloadOnChange: true);
|
||||
|
||||
builder.Configuration.AddEnvironmentVariables();
|
||||
builder.Configuration.AddUserSecrets<Program>();
|
||||
builder.Host.UseSerilog((hostBuilder, loggerConfiguration) =>
|
||||
{
|
||||
var envName = builder.Environment.EnvironmentName.ToLower().Replace(".", "-");
|
||||
var indexFormat = $"managing-{envName}-" + "{0:yyyy.MM.dd}";
|
||||
var yourTemplateName = "dotnetlogs";
|
||||
var es = new ElasticsearchSinkOptions(new Uri(hostBuilder.Configuration["ElasticConfiguration:Uri"]))
|
||||
{
|
||||
IndexFormat = indexFormat.ToLower(),
|
||||
AutoRegisterTemplate = true,
|
||||
OverwriteTemplate = true,
|
||||
TemplateName = yourTemplateName,
|
||||
AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv7,
|
||||
TypeName = null,
|
||||
BatchAction = ElasticOpType.Create,
|
||||
MinimumLogEventLevel = Serilog.Events.LogEventLevel.Information,
|
||||
FailureCallback = e => Console.WriteLine($"Unable to submit event {e.RenderMessage()} to ElasticSearch. " +
|
||||
$"Full message : " + e.Exception.Message),
|
||||
DetectElasticsearchVersion = true,
|
||||
RegisterTemplateFailure = RegisterTemplateRecovery.IndexAnyway,
|
||||
};
|
||||
|
||||
loggerConfiguration
|
||||
.WriteTo.Console()
|
||||
.WriteTo.Elasticsearch(es);
|
||||
});
|
||||
|
||||
builder.Services.AddOptions();
|
||||
builder.Services.Configure<ManagingDatabaseSettings>(builder.Configuration.GetSection(Constants.Databases.MongoDb));
|
||||
builder.Services.Configure<InfluxDbSettings>(builder.Configuration.GetSection(Constants.Databases.InfluxDb));
|
||||
builder.Services.AddControllers().AddJsonOptions(options =>
|
||||
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
|
||||
|
||||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(o =>
|
||||
{
|
||||
o.SaveToken = true;
|
||||
o.TokenValidationParameters = new TokenValidationParameters
|
||||
{
|
||||
ValidIssuer = builder.Configuration["Authentication:Schemes:Bearer:ValidIssuer"],
|
||||
ValidAudience = builder.Configuration["Authentication:Schemes:Bearer:ValidAudiences"],
|
||||
IssuerSigningKey = new SymmetricSecurityKey
|
||||
(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Secret"])),
|
||||
ValidateIssuer = false,
|
||||
ValidateAudience = false,
|
||||
ValidateIssuerSigningKey = true
|
||||
};
|
||||
});
|
||||
builder.Services.AddAuthorization();
|
||||
builder.Services.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
|
||||
{
|
||||
builder
|
||||
.SetIsOriginAllowed((host) => true)
|
||||
.AllowAnyOrigin()
|
||||
.WithOrigins("http://localhost:3000/")
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader()
|
||||
.AllowCredentials();
|
||||
}));
|
||||
|
||||
builder.Services.AddSignalR().AddJsonProtocol();
|
||||
builder.Services.AddScoped<IJwtUtils, JwtUtils>();
|
||||
|
||||
builder.Services.RegisterApiDependencies(builder.Configuration);
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddOpenApiDocument(document =>
|
||||
{
|
||||
document.AddSecurity("JWT", Enumerable.Empty<string>(), new OpenApiSecurityScheme
|
||||
{
|
||||
Type = OpenApiSecuritySchemeType.ApiKey,
|
||||
Name = "Authorization",
|
||||
In = OpenApiSecurityApiKeyLocation.Header,
|
||||
Description = "Type into the textbox: Bearer {your JWT token}."
|
||||
});
|
||||
|
||||
document.OperationProcessors.Add(
|
||||
new AspNetCoreOperationSecurityScopeProcessor("JWT"));
|
||||
});
|
||||
builder.Services.AddSwaggerGen(options =>
|
||||
{
|
||||
options.SchemaFilter<EnumSchemaFilter>();
|
||||
options.AddSecurityDefinition("Bearer,", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
|
||||
{
|
||||
Description = "Please insert your JWT Token into field : Bearer {your_token}",
|
||||
Name = "Authorization",
|
||||
Type = Microsoft.OpenApi.Models.SecuritySchemeType.Http,
|
||||
In = Microsoft.OpenApi.Models.ParameterLocation.Header,
|
||||
Scheme = "Bearer",
|
||||
BearerFormat = "JWT"
|
||||
});
|
||||
options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement{
|
||||
{
|
||||
new Microsoft.OpenApi.Models.OpenApiSecurityScheme{
|
||||
Reference = new Microsoft.OpenApi.Models.OpenApiReference{
|
||||
Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme,
|
||||
Id = "Bearer"
|
||||
}
|
||||
},
|
||||
new string[]{}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
builder.WebHost.SetupDiscordBot();
|
||||
|
||||
// App
|
||||
var app = builder.Build();
|
||||
app.UseSerilogRequestLogging();
|
||||
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
|
||||
app.UseOpenApi();
|
||||
app.UseSwaggerUi3();
|
||||
app.UseSwaggerUI(c =>
|
||||
{
|
||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Managing API v1");
|
||||
c.RoutePrefix = string.Empty;
|
||||
});
|
||||
|
||||
app.UseCors("CorsPolicy");
|
||||
|
||||
app.UseMiddleware(typeof(GlobalErrorHandlingMiddleware));
|
||||
|
||||
app.UseMiddleware<JwtMiddleware>();
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseAuthentication();
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
endpoints.MapHub<BotHub>("/bothub");
|
||||
endpoints.MapHub<BacktestHub>("/backtesthub");
|
||||
endpoints.MapHub<CandleHub>("/candlehub");
|
||||
});
|
||||
|
||||
app.Run();
|
||||
13
src/Managing.Api/appsettings.Development.json
Normal file
13
src/Managing.Api/appsettings.Development.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Error",
|
||||
"System": "Error",
|
||||
"Microsoft": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ElasticConfiguration": {
|
||||
"Uri": "http://elasticsearch:9200/"
|
||||
}
|
||||
}
|
||||
34
src/Managing.Api/appsettings.Khalid.json
Normal file
34
src/Managing.Api/appsettings.Khalid.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"ManagingDatabase": {
|
||||
"ConnectionString": "mongodb://localhost:27017",
|
||||
"DatabaseName": "ManagingDb"
|
||||
},
|
||||
"InfluxDb": {
|
||||
"Url": "http://localhost:8086/",
|
||||
"Organization": "",
|
||||
"Token": ""
|
||||
},
|
||||
"Serilog": {
|
||||
"MinimumLevel": {
|
||||
"Default": "Information",
|
||||
"Override": {
|
||||
"Microsoft": "Information",
|
||||
"System": "Warning"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ElasticConfiguration": {
|
||||
"Uri": "http://elasticsearch:9200"
|
||||
},
|
||||
"Discord": {
|
||||
"ApplicationId": "",
|
||||
"PublicKey": "",
|
||||
"SignalChannelId": 1018897743118340180,
|
||||
"TroublesChannelId": 1018897743118340180,
|
||||
"TradesChannelId": 1020457417877753886,
|
||||
"RequestChannelId": 1020463151034138694,
|
||||
"RequestsChannelId": 1020463151034138694,
|
||||
"ButtonExpirationMinutes": 2
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
46
src/Managing.Api/appsettings.Lowpro.json
Normal file
46
src/Managing.Api/appsettings.Lowpro.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"Authentication": {
|
||||
"Schemes": {
|
||||
"Bearer": {
|
||||
"ValidAudiences": [ "http://localhost:3000/" ],
|
||||
"ValidIssuer": "Managing"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Jwt": {
|
||||
"Secret": "2ed5f490-b6c1-4cad-8824-840c911f1fe6"
|
||||
},
|
||||
"ManagingDatabase": {
|
||||
"ConnectionString": "mongodb://managingdb",
|
||||
"DatabaseName": "ManagingDb"
|
||||
},
|
||||
"InfluxDb": {
|
||||
"Url": "http://influxdb:8086/",
|
||||
"Organization": "managing-org",
|
||||
"Token": "OPjdwQBmKr0zQecJ10IDQ4bt32oOJzmFp687QWWzbGeyH0R-gCA6HnXI_B0oQ_InPmSUXKFje8DSAUPbY0hn-w=="
|
||||
},
|
||||
"Serilog": {
|
||||
"MinimumLevel": {
|
||||
"Default": "Information",
|
||||
"Override": {
|
||||
"Microsoft": "Information",
|
||||
"System": "Warning"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ElasticConfiguration": {
|
||||
"Uri": "http://elasticsearch:9200"
|
||||
},
|
||||
"Discord": {
|
||||
"ApplicationId": "966075382002516031",
|
||||
"PublicKey": "63028f6bb740cd5d26ae0340b582dee2075624011b28757436255fc002ca8a7c",
|
||||
"TokenId": "OTY2MDc1MzgyMDAyNTE2MDMx.Yl8dzw.xpeIAaMwGrwTNY4r9JYv0ebzb-U",
|
||||
"SignalChannelId": 1134858150667898910,
|
||||
"TradesChannelId": 1134858092530634864,
|
||||
"TroublesChannelId": 1134858233031446671,
|
||||
"CopyTradingChannelId": 1134857874896588881,
|
||||
"RequestsChannelId": 1018589494968078356,
|
||||
"ButtonExpirationMinutes": 10
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
37
src/Managing.Api/appsettings.Oda-Sandbox.json
Normal file
37
src/Managing.Api/appsettings.Oda-Sandbox.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"ManagingDatabase": {
|
||||
"ConnectionString": "mongodb://managingdb:27017",
|
||||
"DatabaseName": "ManagingDb"
|
||||
},
|
||||
"InfluxDb": {
|
||||
"Url": "http://influxdb:8086/",
|
||||
"Organization": "",
|
||||
"Token": ""
|
||||
},
|
||||
"Serilog": {
|
||||
"MinimumLevel": {
|
||||
"Default": "Information",
|
||||
"Override": {
|
||||
"Microsoft": "Information",
|
||||
"System": "Warning"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ElasticConfiguration": {
|
||||
"Uri": "http://elasticsearch:9200"
|
||||
},
|
||||
"Discord": {
|
||||
"BotActivity": "trading strategies",
|
||||
"HandleUserAction": true,
|
||||
"ApplicationId": "",
|
||||
"PublicKey": "",
|
||||
"TokenId": "",
|
||||
"SignalChannelId": 966080506473099314,
|
||||
"TradesChannelId": 998374177763491851,
|
||||
"TroublesChannelId": 1015761955321040917,
|
||||
"CopyTradingChannelId": 1132022887012909126,
|
||||
"RequestsChannelId": 1018589494968078356,
|
||||
"ButtonExpirationMinutes": 10
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
36
src/Managing.Api/appsettings.Oda-docker.json
Normal file
36
src/Managing.Api/appsettings.Oda-docker.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"ManagingDatabase": {
|
||||
"ConnectionString": "mongodb://managingdb:27017",
|
||||
"DatabaseName": "ManagingDb",
|
||||
"UserName": "admin",
|
||||
"Password": "!MotdepasseFort11"
|
||||
},
|
||||
"InfluxDb": {
|
||||
"Url": "http://influxdb:8086/",
|
||||
"Organization": "managing-org",
|
||||
"Token": ""
|
||||
},
|
||||
"Serilog": {
|
||||
"MinimumLevel": {
|
||||
"Default": "Information",
|
||||
"Override": {
|
||||
"Microsoft": "Information",
|
||||
"System": "Warning"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ElasticConfiguration": {
|
||||
"Uri": "http://elasticsearch:9200"
|
||||
},
|
||||
"Discord": {
|
||||
"ApplicationId": "",
|
||||
"PublicKey": "",
|
||||
"TokenId": "",
|
||||
"SignalChannelId": 966080506473099314,
|
||||
"TradesChannelId": 998374177763491851,
|
||||
"TroublesChannelId": 1015761955321040917,
|
||||
"RequestsChannelId": 1018589494968078356,
|
||||
"ButtonExpirationMinutes": 2
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
34
src/Managing.Api/appsettings.Oda.json
Normal file
34
src/Managing.Api/appsettings.Oda.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"ManagingDatabase": {
|
||||
"ConnectionString": "mongodb://localhost:27017",
|
||||
"DatabaseName": "ManagingDb"
|
||||
},
|
||||
"InfluxDb": {
|
||||
"Url": "http://localhost:8086/",
|
||||
"Organization": "",
|
||||
"Token": ""
|
||||
},
|
||||
"Serilog": {
|
||||
"MinimumLevel": {
|
||||
"Default": "Information",
|
||||
"Override": {
|
||||
"Microsoft": "Information",
|
||||
"System": "Warning"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ElasticConfiguration": {
|
||||
"Uri": "http://elasticsearch:9200"
|
||||
},
|
||||
"Discord": {
|
||||
"ApplicationId": "",
|
||||
"PublicKey": "",
|
||||
"TokenId": "",
|
||||
"SignalChannelId": 966080506473099314,
|
||||
"TradesChannelId": 998374177763491851,
|
||||
"TroublesChannelId": 1015761955321040917,
|
||||
"RequestsChannelId": 1018589494968078356,
|
||||
"ButtonExpirationMinutes": 2
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
48
src/Managing.Api/appsettings.json
Normal file
48
src/Managing.Api/appsettings.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"Authentication": {
|
||||
"Schemes": {
|
||||
"Bearer": {
|
||||
"ValidAudiences": [ "http://localhost:3000/" ],
|
||||
"ValidIssuer": "Managing"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Jwt": {
|
||||
"Secret": "2ed5f490-b6c1-4cad-8824-840c911f1fe6"
|
||||
},
|
||||
"ManagingDatabase": {
|
||||
"ConnectionString": "mongodb://managingdb",
|
||||
"DatabaseName": "ManagingDb"
|
||||
},
|
||||
"InfluxDb": {
|
||||
"Url": "http://influxdb:8086/",
|
||||
"Organization": "",
|
||||
"Token": ""
|
||||
},
|
||||
"Serilog": {
|
||||
"MinimumLevel": {
|
||||
"Default": "Information",
|
||||
"Override": {
|
||||
"Microsoft": "Information",
|
||||
"System": "Warning"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ElasticConfiguration": {
|
||||
"Uri": "http://elasticsearch:9200/"
|
||||
},
|
||||
"Discord": {
|
||||
"BotActivity": "trading strategies",
|
||||
"HandleUserAction": true,
|
||||
"ApplicationId": "",
|
||||
"PublicKey": "",
|
||||
"TokenId": "",
|
||||
"SignalChannelId": 966080506473099314,
|
||||
"TradesChannelId": 998374177763491851,
|
||||
"TroublesChannelId": 1015761955321040917,
|
||||
"CopyTradingChannelId": 1132022887012909126,
|
||||
"RequestsChannelId": 1018589494968078356,
|
||||
"ButtonExpirationMinutes": 10
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
4
src/Managing.Api/captain-definition
Normal file
4
src/Managing.Api/captain-definition
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"schemaVersion": 2,
|
||||
"dockerfilePath": "Dockerfile"
|
||||
}
|
||||
19
src/Managing.Api/failures.txt
Normal file
19
src/Managing.Api/failures.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
{"Timestamp":"2022-09-13T02:59:02.0040536+02:00","Level":"Information","MessageTemplate":"02:59:01 Discord Discord.Net v3.8.0 (API v9)","Properties":{"SourceContext":"Managing.Infrastructure.Messengers.Discord.DiscordService","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
||||
{"Timestamp":"2022-09-13T02:59:02.0892523+02:00","Level":"Information","MessageTemplate":"02:59:02 Gateway Connecting","Properties":{"SourceContext":"Managing.Infrastructure.Messengers.Discord.DiscordService","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
||||
{"Timestamp":"2022-09-13T02:59:02.2504922+02:00","Level":"Information","MessageTemplate":"Now listening on: {address}","Properties":{"address":"https://localhost:5001","EventId":{"Id":14,"Name":"ListeningOnAddress"},"SourceContext":"Microsoft.Hosting.Lifetime","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
||||
{"Timestamp":"2022-09-13T02:59:02.2556804+02:00","Level":"Information","MessageTemplate":"Now listening on: {address}","Properties":{"address":"http://localhost:5000","EventId":{"Id":14,"Name":"ListeningOnAddress"},"SourceContext":"Microsoft.Hosting.Lifetime","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
||||
{"Timestamp":"2022-09-13T02:59:02.2591276+02:00","Level":"Information","MessageTemplate":"Application started. Press Ctrl+C to shut down.","Properties":{"SourceContext":"Microsoft.Hosting.Lifetime","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
||||
{"Timestamp":"2022-09-13T02:59:02.2625140+02:00","Level":"Information","MessageTemplate":"Hosting environment: {envName}","Properties":{"envName":"Development","SourceContext":"Microsoft.Hosting.Lifetime","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
||||
{"Timestamp":"2022-09-13T02:59:02.2651704+02:00","Level":"Information","MessageTemplate":"Content root path: {contentRoot}","Properties":{"contentRoot":"C:\\Users\\Utilisateur\\Desktop\\Projects\\apps\\Managing\\src\\Managing.Api\\","SourceContext":"Microsoft.Hosting.Lifetime","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
||||
{"Timestamp":"2022-09-13T02:59:03.3572754+02:00","Level":"Information","MessageTemplate":"02:59:03 Gateway You're using the GuildScheduledEvents gateway intent without listening to any events related to that intent, consider removing the intent from your config.","Properties":{"SourceContext":"Managing.Infrastructure.Messengers.Discord.DiscordService","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
||||
{"Timestamp":"2022-09-13T02:59:03.3628433+02:00","Level":"Information","MessageTemplate":"02:59:03 Gateway You're using the GuildInvites gateway intent without listening to any events related to that intent, consider removing the intent from your config.","Properties":{"SourceContext":"Managing.Infrastructure.Messengers.Discord.DiscordService","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
||||
{"Timestamp":"2022-09-13T02:59:03.3688717+02:00","Level":"Information","MessageTemplate":"02:59:03 Gateway Connected","Properties":{"SourceContext":"Managing.Infrastructure.Messengers.Discord.DiscordService","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
||||
{"Timestamp":"2022-09-13T02:59:03.9425506+02:00","Level":"Information","MessageTemplate":"02:59:03 Gateway Ready","Properties":{"SourceContext":"Managing.Infrastructure.Messengers.Discord.DiscordService","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"}}
|
||||
{"Timestamp":"2022-09-13T02:59:10.5882097+02:00","Level":"Information","MessageTemplate":"{HostingRequestStartingLog:l}","Properties":{"Protocol":"HTTP/2","Method":"GET","ContentType":null,"ContentLength":null,"Scheme":"https","Host":"localhost:5001","PathBase":"","Path":"/index.html","QueryString":"","HostingRequestStartingLog":"Request starting HTTP/2 GET https://localhost:5001/index.html - -","EventId":{"Id":1},"SourceContext":"Microsoft.AspNetCore.Hosting.Diagnostics","RequestId":"0HMKL4CJ4LVHE:00000001","RequestPath":"/index.html","ConnectionId":"0HMKL4CJ4LVHE","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"},"Renderings":{"HostingRequestStartingLog":[{"Format":"l","Rendering":"Request starting HTTP/2 GET https://localhost:5001/index.html - -"}]}}
|
||||
{"Timestamp":"2022-09-13T02:59:11.5711332+02:00","Level":"Information","MessageTemplate":"{HostingRequestFinishedLog:l}","Properties":{"ElapsedMilliseconds":996.3451,"StatusCode":200,"ContentType":"text/html;charset=utf-8","ContentLength":null,"Protocol":"HTTP/2","Method":"GET","Scheme":"https","Host":"localhost:5001","PathBase":"","Path":"/index.html","QueryString":"","HostingRequestFinishedLog":"Request finished HTTP/2 GET https://localhost:5001/index.html - - - 200 - text/html;charset=utf-8 996.3451ms","EventId":{"Id":2},"SourceContext":"Microsoft.AspNetCore.Hosting.Diagnostics","RequestId":"0HMKL4CJ4LVHE:00000001","RequestPath":"/index.html","ConnectionId":"0HMKL4CJ4LVHE","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"},"Renderings":{"HostingRequestFinishedLog":[{"Format":"l","Rendering":"Request finished HTTP/2 GET https://localhost:5001/index.html - - - 200 - text/html;charset=utf-8 996.3451ms"}]}}
|
||||
{"Timestamp":"2022-09-13T02:59:11.6123850+02:00","Level":"Information","MessageTemplate":"{HostingRequestStartingLog:l}","Properties":{"Protocol":"HTTP/2","Method":"GET","ContentType":null,"ContentLength":null,"Scheme":"https","Host":"localhost:5001","PathBase":"","Path":"/_framework/aspnetcore-browser-refresh.js","QueryString":"","HostingRequestStartingLog":"Request starting HTTP/2 GET https://localhost:5001/_framework/aspnetcore-browser-refresh.js - -","EventId":{"Id":1},"SourceContext":"Microsoft.AspNetCore.Hosting.Diagnostics","RequestId":"0HMKL4CJ4LVHE:00000003","RequestPath":"/_framework/aspnetcore-browser-refresh.js","ConnectionId":"0HMKL4CJ4LVHE","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"},"Renderings":{"HostingRequestStartingLog":[{"Format":"l","Rendering":"Request starting HTTP/2 GET https://localhost:5001/_framework/aspnetcore-browser-refresh.js - -"}]}}
|
||||
{"Timestamp":"2022-09-13T02:59:11.6281716+02:00","Level":"Information","MessageTemplate":"{HostingRequestFinishedLog:l}","Properties":{"ElapsedMilliseconds":15.5581,"StatusCode":200,"ContentType":"application/javascript; charset=utf-8","ContentLength":11994,"Protocol":"HTTP/2","Method":"GET","Scheme":"https","Host":"localhost:5001","PathBase":"","Path":"/_framework/aspnetcore-browser-refresh.js","QueryString":"","HostingRequestFinishedLog":"Request finished HTTP/2 GET https://localhost:5001/_framework/aspnetcore-browser-refresh.js - - - 200 11994 application/javascript;+charset=utf-8 15.5581ms","EventId":{"Id":2},"SourceContext":"Microsoft.AspNetCore.Hosting.Diagnostics","RequestId":"0HMKL4CJ4LVHE:00000003","RequestPath":"/_framework/aspnetcore-browser-refresh.js","ConnectionId":"0HMKL4CJ4LVHE","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"},"Renderings":{"HostingRequestFinishedLog":[{"Format":"l","Rendering":"Request finished HTTP/2 GET https://localhost:5001/_framework/aspnetcore-browser-refresh.js - - - 200 11994 application/javascript;+charset=utf-8 15.5581ms"}]}}
|
||||
{"Timestamp":"2022-09-13T02:59:11.7015500+02:00","Level":"Information","MessageTemplate":"{HostingRequestStartingLog:l}","Properties":{"Protocol":"HTTP/2","Method":"GET","ContentType":null,"ContentLength":null,"Scheme":"https","Host":"localhost:5001","PathBase":"","Path":"/_vs/browserLink","QueryString":"","HostingRequestStartingLog":"Request starting HTTP/2 GET https://localhost:5001/_vs/browserLink - -","EventId":{"Id":1},"SourceContext":"Microsoft.AspNetCore.Hosting.Diagnostics","RequestId":"0HMKL4CJ4LVHE:00000005","RequestPath":"/_vs/browserLink","ConnectionId":"0HMKL4CJ4LVHE","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"},"Renderings":{"HostingRequestStartingLog":[{"Format":"l","Rendering":"Request starting HTTP/2 GET https://localhost:5001/_vs/browserLink - -"}]}}
|
||||
{"Timestamp":"2022-09-13T02:59:11.8214511+02:00","Level":"Information","MessageTemplate":"{HostingRequestFinishedLog:l}","Properties":{"ElapsedMilliseconds":119.7799,"StatusCode":200,"ContentType":"text/javascript; charset=UTF-8","ContentLength":null,"Protocol":"HTTP/2","Method":"GET","Scheme":"https","Host":"localhost:5001","PathBase":"","Path":"/_vs/browserLink","QueryString":"","HostingRequestFinishedLog":"Request finished HTTP/2 GET https://localhost:5001/_vs/browserLink - - - 200 - text/javascript;+charset=UTF-8 119.7799ms","EventId":{"Id":2},"SourceContext":"Microsoft.AspNetCore.Hosting.Diagnostics","RequestId":"0HMKL4CJ4LVHE:00000005","RequestPath":"/_vs/browserLink","ConnectionId":"0HMKL4CJ4LVHE","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"},"Renderings":{"HostingRequestFinishedLog":[{"Format":"l","Rendering":"Request finished HTTP/2 GET https://localhost:5001/_vs/browserLink - - - 200 - text/javascript;+charset=UTF-8 119.7799ms"}]}}
|
||||
{"Timestamp":"2022-09-13T02:59:11.9652804+02:00","Level":"Information","MessageTemplate":"{HostingRequestStartingLog:l}","Properties":{"Protocol":"HTTP/2","Method":"GET","ContentType":null,"ContentLength":null,"Scheme":"https","Host":"localhost:5001","PathBase":"","Path":"/swagger/v1/swagger.json","QueryString":"","HostingRequestStartingLog":"Request starting HTTP/2 GET https://localhost:5001/swagger/v1/swagger.json - -","EventId":{"Id":1},"SourceContext":"Microsoft.AspNetCore.Hosting.Diagnostics","RequestId":"0HMKL4CJ4LVHE:00000007","RequestPath":"/swagger/v1/swagger.json","ConnectionId":"0HMKL4CJ4LVHE","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"},"Renderings":{"HostingRequestStartingLog":[{"Format":"l","Rendering":"Request starting HTTP/2 GET https://localhost:5001/swagger/v1/swagger.json - -"}]}}
|
||||
{"Timestamp":"2022-09-13T02:59:12.3915820+02:00","Level":"Information","MessageTemplate":"{HostingRequestFinishedLog:l}","Properties":{"ElapsedMilliseconds":426.2987,"StatusCode":200,"ContentType":"application/json;charset=utf-8","ContentLength":null,"Protocol":"HTTP/2","Method":"GET","Scheme":"https","Host":"localhost:5001","PathBase":"","Path":"/swagger/v1/swagger.json","QueryString":"","HostingRequestFinishedLog":"Request finished HTTP/2 GET https://localhost:5001/swagger/v1/swagger.json - - - 200 - application/json;charset=utf-8 426.2987ms","EventId":{"Id":2},"SourceContext":"Microsoft.AspNetCore.Hosting.Diagnostics","RequestId":"0HMKL4CJ4LVHE:00000007","RequestPath":"/swagger/v1/swagger.json","ConnectionId":"0HMKL4CJ4LVHE","Environment":"Microsoft.AspNetCore.Hosting.HostingEnvironment"},"Renderings":{"HostingRequestFinishedLog":[{"Format":"l","Rendering":"Request finished HTTP/2 GET https://localhost:5001/swagger/v1/swagger.json - - - 200 - application/json;charset=utf-8 426.2987ms"}]}}
|
||||
Reference in New Issue
Block a user