public void Reset() { Result = MarketDialogResult.Pending; Transaction = null; PlayerColumns.Reconstruct(Player.Resources, new List <ResourceAmount>(), (int)Player.Money); UpdateBottomDisplays(); Layout(); }
public void Reset() { Result = MarketDialogResult.Pending; Transaction = null; PlayerColumns.Reconstruct(Play.Trading.Helper.AggregateResourcesIntoTradeableItems(Player.Resources), new List <TradeableItem>(), (int)Player.Money); UpdateBottomDisplays(); Layout(); }
public async Task <ActionResult> MakeMarketTransaction([FromBody] MarketTransaction marketTransaction, int planetId) { var planet = await _planetService.GetPlanetById(planetId); var result = await _planetService.MakeMarketTransaction(planet, marketTransaction); if (result == null) { return(BadRequest()); } return(Ok(result)); }
private void UpdateTranInvoke() { MarketTransaction mt = null; while (true) { if (QueueTrans.TryDequeue(out mt)) { if (this.UpdateTransaction != null) { this.UpdateTransaction.Invoke(mt); } } else { Thread.Sleep(50); } } }
public async Task <uint256> Order(int accountId, decimal isk) { MarketTransaction mtx = new MarketTransaction { AccountId = accountId, Time = DateTime.Now, Amount = -isk, Type = TransactionType.Buy }; try { var account = await _context.Account .Include(x => x.MarketTransactions) .FirstOrDefaultAsync(x => x.Id == accountId); if (account == null) { _logger.LogCritical($"Order cancelled because no account with id: {accountId} was found"); return(null); } mtx.Fee = -Math.Round(isk * (account.Fee / 100)); decimal rate = Decimal.Zero; using (var scope = _serviceProvider.CreateScope()) { var _tickerService = scope.ServiceProvider.GetRequiredService <TickerService>(); if (_tickerService.MarketState == MarketState.Open) { rate = _tickerService.Tickers["btcisk"].Ask; } else { _logger.LogCritical("Order cancelled because market is closed."); mtx.Status = TransactionStatus.Rejected; account.MarketTransactions.Add(mtx); await _context.SaveChangesAsync(); return(null); } } mtx.Rate = rate; if (rate == Decimal.Zero) { _logger.LogCritical("Order cancelled because rate value was zero, this should never happen."); mtx.Status = TransactionStatus.Rejected; account.MarketTransactions.Add(mtx); await _context.SaveChangesAsync(); return(null); } Money coins = Money.Coins( Math.Round(isk / rate * (1 - account.Fee / 100), 8, MidpointRounding.ToZero)); mtx.Coins = coins.ToDecimal(MoneyUnit.BTC); _logger.LogDebug($"Id: {accountId} Coins: {coins} ISK: {isk} Rate: {rate} Account Balance: {account.Balance}"); if (account.Balance >= isk) { mtx.Balance = account.Balance - isk; _logger.LogDebug($"{accountId} has sufficient balance for the order"); using (var scope = _serviceProvider.CreateScope()) { var _bitcoin = scope.ServiceProvider.GetRequiredService <BitcoinService>(); if (await _bitcoin.BitarCanMakePayment(accountId, coins)) { account.Balance -= isk; await _context.SaveChangesAsync(); ExtKey key = _bitcoin._masterKey.Derive(new KeyPath($"m/84'/0'/{account.Derivation}'/0/0")); var receiver = key.PrivateKey.PubKey.GetSegwitAddress(Network.Main); int bitarAccountId = 0; var result = await _bitcoin.SendBitcoin(0, receiver, coins, 36); if (result != null) { _logger.LogDebug($"Bitcoin transaction result: {result.ToString()}"); mtx.TxId = result.ToString(); mtx.Status = TransactionStatus.Completed; } else { _logger.LogCritical($"Bitcoin transaction failed"); // The bitcoin transaction failed. // Should we refund the user right away? // accountData.Balance += isk; mtx.Status = TransactionStatus.Failed; } _logger.LogWarning( "Market Transaction.\n" + $"Id: {mtx.Id}\n" + $"Date: {mtx.Time}\n" + $"Rate: {mtx.Rate}\n" + $"Coins: {mtx.Coins}\n" + $"Fee: {mtx.Fee}\n" + $"Amount: {mtx.Amount}\n" + $"Type: {mtx.Type}\n" + $"Status: {mtx.Status}"); account.MarketTransactions.Add(mtx); await _context.SaveChangesAsync(); return(result); } } } else { _logger.LogCritical( "Order cancelled.\n" + $"{accountId} does not have sufficient balance for the order.\n" + $"Order => {coins} BTC for {isk} ISK.\n" + $"Current balance: {account.Balance} ISK."); mtx.Status = TransactionStatus.Rejected; account.MarketTransactions.Add(mtx); await _context.SaveChangesAsync(); return(null); } } catch (DbUpdateConcurrencyException) { _logger.LogError($"DbUpdateConcurrencyException: {accountId} {isk} ISK order cancelled."); } return(null); }
public async Task <ActionResult <string> > Withdraw(BitcoinWithdrawal withdrawal) { if (MathDecimals.GetDecimals(withdrawal.Amount) > 8) { return(BadRequest("withdrawal amount cannot have more than 8 decimals")); } if (MathDecimals.GetDecimals(withdrawal.Fees) > 8) { return(BadRequest("withdrawal fees cannot have more than 8 decimals")); } string accountIdString = User.FindFirstValue(ClaimTypes.NameIdentifier); if (accountIdString == null) { return(BadRequest("AccountId missing from request")); } int accountId = int.Parse(accountIdString); var account = await _context.Account .Include(x => x.MarketTransactions) .FirstOrDefaultAsync(x => x.Id == accountId); if (account == null) { return(NotFound("User not found in database")); } if (account.WithdrawalAddress == null) { return(NotFound("User has not set a withdrawal address")); } var address = BitcoinAddress.Create(account.WithdrawalAddress, Network.Main); Money amount = Money.FromUnit(withdrawal.Amount, MoneyUnit.BTC); Money fees = Money.FromUnit(withdrawal.Fees, MoneyUnit.BTC); var result = await _bitcoin.SendBitcoin(accountId, address, amount, fees); if (result == null) { return(Conflict("Failed to create/send transaction")); } decimal rate = Decimal.Zero; if (_ticker.MarketState == MarketState.Open) { rate = _ticker.Tickers["btcisk"].Ask; } MarketTransaction mtx = new MarketTransaction { AccountId = accountId, Time = DateTime.Now, Coins = -(withdrawal.Amount + withdrawal.Fees), TxId = result.ToString(), Type = TransactionType.Withdrawal, Rate = rate, Status = TransactionStatus.Completed }; account.MarketTransactions.Add(mtx); await _context.SaveChangesAsync(); return(result.ToString()); }
public async Task <ActionResult <decimal> > Withdraw([FromBody] decimal amount) { string accountIdString = User.FindFirstValue(ClaimTypes.NameIdentifier); if (accountIdString == null) { return(BadRequest("AccountId missing from request")); } int accountId = int.Parse(accountIdString); var account = await _context.Account .Include(x => x.MarketTransactions) .FirstOrDefaultAsync(x => x.Id == accountId); if (account == null) { return(NotFound("User not found in database")); } if (account.BankAccountNumber == null) { return(NotFound("User has not set a bank account number")); } if (amount <= 0 || amount > 10000000) { return(BadRequest("Invalid amount")); } if (account.Balance - amount >= 0) { try { _logger.LogCritical($"{account.Id} is withdrawing {amount} ISK to {account.BankAccountNumber}"); account.Balance -= amount; await _context.SaveChangesAsync(); string hq = account.BankAccountNumber.Substring(0, 4); string hb = account.BankAccountNumber.Substring(4, 2); string num = account.BankAccountNumber.Substring(6, 6); bool result = _landsbankinn.Pay(hq, hb, num, account.Kennitala, amount); MarketTransaction mtx = new MarketTransaction { AccountId = accountId, Time = DateTime.Now, Amount = -amount, Type = TransactionType.Withdrawal, Status = TransactionStatus.Completed }; if (result == false) { mtx.Status = TransactionStatus.Failed; return(Conflict("Failed to create/send transaction")); } account.MarketTransactions.Add(mtx); await _context.SaveChangesAsync(); _logger.LogCritical($"Withdrawal successful"); return(Ok(account.Balance)); } catch (Exception e) { _logger.LogError(e.ToString()); return(NotFound()); } } return(NotFound("tf did you just try to do?")); }
private void PubRoutine() { if (_pubSocket != null) { while (true) { try { byte[] tmp; if (_marketDataTmp.Count > 0 && _marketDataTmp.TryDequeue(out tmp)) { using (MemoryStream stream = new MemoryStream(tmp)) { MarketData data = _fmt.Deserialize(stream) as MarketData; if (data != null) { //更新当前市场数据 if (_currentMarketDatas.ContainsKey(data.Code)) { _currentMarketDatas[data.Code] = data; } else { _currentMarketDatas.TryAdd(data.Code, data); } //发布市场数据 if (_subCodes.ContainsKey(data.Code)) { using (MemoryStream stream1 = new MemoryStream()) { _fmt.Serialize(stream1, data); byte[] td = stream1.ToArray(); using (ZMessage msg = new ZMessage()) { msg.Add(new ZFrame(data.Code + ":" + "MarketData")); msg.Add(new ZFrame(td)); lock (_pubSocket) { _pubSocket.Send(msg); } } } } } } _bytePool.Free(tmp); } else if (_marketTransactionTmp.Count > 0 && _marketTransactionTmp.TryDequeue(out tmp)) { using (MemoryStream stream = new MemoryStream(tmp)) { MarketTransaction trans = _fmt.Deserialize(stream) as MarketTransaction; if (trans != null) { //更新最近成交 if (_lastTransactions.ContainsKey(trans.Code)) { _lastTransactions[trans.Code] = trans; } else { _lastTransactions.TryAdd(trans.Code, trans); } //发布最新成交 if (_subCodes.ContainsKey(trans.Code)) { using (MemoryStream stream1 = new MemoryStream()) { _fmt.Serialize(stream1, trans); byte[] td = stream1.ToArray(); using (ZMessage msg = new ZMessage()) { msg.Add(new ZFrame(trans.Code + ":" + "MarketTransaction")); msg.Add(new ZFrame(td)); lock (_pubSocket) { _pubSocket.Send(msg); } } } } } } _bytePool.Free(tmp); } else { Thread.Sleep(50); } } catch (Exception ex) { AASClient.Program.logger.LogRunning("DataServerClient:数据发送错误!{0}", ex.Message); } } } }
public override void Construct() { Transaction = null; Result = MarketDialogResult.Pending; Border = "border-fancy"; var bottomRow = AddChild(new Widget { AutoLayout = AutoLayout.DockBottom, MinimumSize = new Point(0, 32) }); bottomRow.AddChild(new Gui.Widgets.Button { Font = "font10", Border = "border-button", TextColor = new Vector4(0, 0, 0, 1), Text = "Propose Trade", AutoLayout = AutoLayout.DockRight, OnClick = (sender, args) => { if (PlayerColumns.Valid) { if (PlayerColumns.SelectedResources.Count == 0) { Root.ShowModalMessage("You've selected nothing to trade."); } else { Result = MarketDialogResult.Propose; Transaction = new MarketTransaction { PlayerEntity = Player, PlayerItems = PlayerColumns.SelectedResources, PlayerMoney = ComputeNetValue() }; Root.SafeCall(OnPlayerAction, this); } } else { Root.ShowTooltip(Root.MousePosition, "Trade is invalid"); } } }); bottomRow.AddChild(new Gui.Widgets.Button { Font = "font10", Border = "border-button", TextColor = new Vector4(0, 0, 0, 1), Text = "Clear", Tooltip = "Clear trade", AutoLayout = AutoLayout.DockRight, OnClick = (sender, args) => { PlayerColumns.Reconstruct(Player.Resources, new List <ResourceAmount>(), (int)Player.Money); UpdateBottomDisplays(); Layout(); } }); bottomRow.AddChild(new Gui.Widgets.Button { Font = "font10", Border = "border-button", TextColor = new Vector4(0, 0, 0, 1), Text = "Stop", Tooltip = "Stop trading.", AutoLayout = AutoLayout.DockRight, //OnLayout = (sender) => sender.Rect.X -= 16, OnClick = (sender, args) => { Result = MarketDialogResult.Cancel; Root.SafeCall(OnPlayerAction, this); //this.Close(); } }); TotalDisplay = bottomRow.AddChild(new Widget { MinimumSize = new Point(256, 64), AutoLayout = AutoLayout.DockFill, Font = "font10", TextColor = new Vector4(0, 0, 0, 1), TextVerticalAlign = VerticalAlign.Bottom, TextHorizontalAlign = HorizontalAlign.Left, Text = "Total Profit: $0" }); var mainPanel = AddChild(new Columns { AutoLayout = AutoLayout.DockFill }); PlayerColumns = mainPanel.AddChild(new ResourceColumns { TradeEntity = Player, ValueSourceEntity = Player, AutoLayout = AutoLayout.DockFill, ReverseColumnOrder = true, LeftHeader = "Our Items", RightHeader = "We Offer", MoneyLabel = "Our money", OnTotalSelectedChanged = (s) => UpdateBottomDisplays(), Tag = "trade_money", ShowMoneyField = false }) as ResourceColumns; UpdateBottomDisplays(); }
private void MarketDataRoutine(object obj) { int index = (int)obj; while (true) { if (_isRunning == true && _source != null) { if (_source.MarketDataCache.Count > 0) { TDFMarketData[] tmd; if (_source.MarketDataCache.TryDequeue(out tmd)) { MarketData[] md = new MarketData[tmd.Length]; for (int i = 0; i < tmd.Length; i++) { md[i] = new MarketData(); md[i].WindCode = tmd[i].WindCode; md[i].Code = tmd[i].Code; md[i].ActionDay = tmd[i].ActionDay; md[i].Time = tmd[i].Time; md[i].Status = tmd[i].Status; md[i].PreClose = tmd[i].PreClose; md[i].Open = tmd[i].Open; md[i].High = tmd[i].High; md[i].Low = tmd[i].Low; md[i].Match = tmd[i].Match; for (int j = 0; j < 10; j++) { md[i].AskPrice[j] = tmd[i].AskPrice[j]; md[i].AskVol[j] = (int)tmd[i].AskVol[j]; md[i].BidPrice[j] = tmd[i].BidPrice[j]; md[i].BidVol[j] = (int)tmd[i].BidVol[j]; } md[i].NumTrades = (int)(tmd[i].NumTrades); md[i].Volume = (int)(tmd[i].Volume); md[i].Turnover = tmd[i].Turnover; md[i].TotalAskVol = (int)(tmd[i].TotalAskVol); md[i].TotalBidVol = (int)(tmd[i].TotalBidVol); md[i].WeightedAvgAskPrice = tmd[i].WeightedAvgAskPrice; md[i].WeightedAvgBidPrice = tmd[i].WeightedAvgBidPrice; md[i].IOPV = tmd[i].IOPV; md[i].YieldToMaturity = tmd[i].YieldToMaturity; md[i].HighLimited = tmd[i].HighLimited; md[i].LowLimited = tmd[i].LowLimited; tmd[i].Prefix.CopyTo(md[i].Prefix, 0); md[i].Syl1 = tmd[i].Syl1; md[i].Syl2 = tmd[i].Syl2; md[i].SD2 = tmd[i].SD2; } lock (this) { _recvDataCount += tmd.Length; } if (NewMarketData != null) { NewMarketData(md); } } } else if (_source.OrderCache.Count > 0) { TDFOrder[] oc; if (_source.OrderCache.TryDequeue(out oc)) { MarketOrder[] mo = new MarketOrder[oc.Length]; for (int i = 0; i < mo.Length; i++) { mo[i] = new MarketOrder(); mo[i].WindCode = oc[i].WindCode; mo[i].Code = oc[i].Code; mo[i].ActionDay = oc[i].ActionDay; mo[i].Time = oc[i].Time; mo[i].Order = oc[i].Order; mo[i].Price = oc[i].Price; mo[i].Volume = oc[i].Volume; mo[i].OrderKind = oc[i].OrderKind; mo[i].FunctionCode = oc[i].FunctionCode; } lock (this) { _recvDataCount += oc.Length; } if (NewMarketOrder != null) { NewMarketOrder(mo); } } } else if (_source.TransactionCache.Count > 0) { TDFTransaction[] t; if (_source.TransactionCache.TryDequeue(out t)) { MarketTransaction[] mt = new MarketTransaction[t.Length]; for (int i = 0; i < t.Length; i++) { mt[i] = new MarketTransaction(); mt[i].WindCode = t[i].WindCode; mt[i].Code = t[i].Code; mt[i].ActionDay = t[i].ActionDay; mt[i].Time = t[i].Time; mt[i].Index = t[i].Index; mt[i].Price = t[i].Price; mt[i].Volume = t[i].Volume; mt[i].Turnover = t[i].Turnover; mt[i].Flag = t[i].BSFlag; mt[i].OrderKind = t[i].OrderKind; mt[i].FunctionCode = t[i].FunctionCode; mt[i].AskOrder = t[i].AskOrder; mt[i].BidOrder = t[i].BidOrder; } lock (this) { _recvDataCount += t.Length; } if (NewMarketTransction != null) { NewMarketTransction(mt); } } } else if (_source.OrderQueueCache.Count > 0) { TDFOrderQueue[] oq; if (_source.OrderQueueCache.TryDequeue(out oq)) { MarketOrderQueue[] moq = new MarketOrderQueue[oq.Length]; for (int i = 0; i < oq.Length; i++) { moq[i] = new MarketOrderQueue(); moq[i].WindCode = oq[i].WindCode; moq[i].Code = oq[i].Code; moq[i].ActionDay = oq[i].ActionDay; moq[i].Time = oq[i].Time; moq[i].Side = oq[i].Side; moq[i].Price = oq[i].Price; moq[i].Orders = oq[i].Orders; moq[i].Items = oq[i].ABItems; oq[i].ABVolume.CopyTo(moq[i].Volume, 0); } lock (this) { _recvDataCount += oq.Length; } if (NewMarketOrderQueue != null) { NewMarketOrderQueue(moq); } } } else { Thread.Sleep(10); } } else { Thread.Sleep(1000); } } }
public async Task <MarketTransactionResult> MakeMarketTransaction(Planet planet, MarketTransaction marketTransaction) { var marketTransactionResult = new MarketTransactionResult(); var p = await _planetRepository.GetAsync(planet.PlanetId); if (p != null) { var market = p.Market; if (marketTransaction.TransactionType == "sell") { var item = market.ConsumableItems.FirstOrDefault(x => x.ItemId == marketTransaction.ItemId); if (item.Amount + marketTransaction.Amount > item.MaxAmount) { marketTransactionResult.Result = false; } else { item.Amount = item.Amount + marketTransaction.Amount; marketTransactionResult.Result = true; marketTransactionResult.TransactionType = marketTransaction.TransactionType; marketTransactionResult.TransactionValue = marketTransaction.Amount * item.BaseValue; } } else if (marketTransaction.TransactionType == "buy") { var item = market.ProductionItems.FirstOrDefault(x => x.ItemId == marketTransaction.ItemId); if (item.Amount - marketTransaction.Amount <= 0) { marketTransactionResult.Result = false; } else { item.Amount = item.Amount - marketTransaction.Amount; marketTransactionResult.Result = true; marketTransactionResult.TransactionType = marketTransaction.TransactionType; marketTransactionResult.TransactionValue = marketTransaction.Amount * item.BaseValue; } } } else { marketTransactionResult.Result = false; } return(marketTransactionResult); }