public async Task TestGetPriceAsync() { var url = "https://dealer.devnet.lyra.live:7070"; var dealer = new DealerClient(new Uri(new Uri(url), "/api/dealer/")); var prices = await dealer.GetPricesAsync(); Assert.IsTrue(prices.ContainsKey("LYR")); Assert.IsTrue(prices.ContainsKey("BTC")); Assert.IsTrue(prices.ContainsKey("LYR_INT")); }
public override async Task <APIResultCodes> PreSendAuthAsync(DagSystem sys, SendTransferBlock send, TransactionBlock last) { if (send.Tags.Count != 2 || !send.Tags.ContainsKey("data") || string.IsNullOrWhiteSpace(send.Tags["data"]) ) { return(APIResultCodes.InvalidBlockTags); } OTCTrade trade; try { trade = JsonConvert.DeserializeObject <OTCTrade>(send.Tags["data"]); } catch (Exception ex) { return(APIResultCodes.InvalidBlockTags); } // daoId var dao = await sys.Storage.FindLatestBlockAsync(trade.daoId); if (dao == null || (dao as TransactionBlock).AccountID != send.DestinationAccountId) { return(APIResultCodes.InvalidOrgnization); } // orderId var orderblk = await sys.Storage.FindLatestBlockAsync(trade.orderId) as IOtcOrder; if (orderblk == null) { return(APIResultCodes.InvalidOrder); } var order = orderblk.Order; if (order.daoId != trade.daoId || order.dealerId != trade.dealerId || order.crypto != trade.crypto || order.fiat != trade.fiat || order.price != trade.price || order.amount < trade.amount || order.dir == trade.dir || orderblk.OwnerAccountId != trade.orderOwnerId || trade.pay > order.limitMax || trade.pay < order.limitMin || !order.payBy.Contains(trade.payVia) ) { return(APIResultCodes.InvalidTrade); } // pay if (trade.pay != Math.Round(trade.pay, 2)) { return(APIResultCodes.InvalidTradeAmount); } var got = Math.Round(trade.pay / order.price, 8); if (got != trade.amount) { return(APIResultCodes.InvalidTradeAmount); } // verify collateral var chgs = send.GetBalanceChanges(last); if (!chgs.Changes.ContainsKey(LyraGlobal.OFFICIALTICKERCODE) || chgs.Changes[LyraGlobal.OFFICIALTICKERCODE] < trade.collateral) { return(APIResultCodes.InvalidCollateral); } // check the price of order and collateral. var dlrblk = await sys.Storage.FindLatestBlockAsync(trade.dealerId); var uri = new Uri(new Uri((dlrblk as IDealer).Endpoint), "/api/dealer/"); var dealer = new DealerClient(uri); var prices = await dealer.GetPricesAsync(); var tokenSymbol = order.crypto.Split('/')[1]; if (trade.collateral * prices["LYR"] < prices[tokenSymbol] * trade.amount * ((dao as IDao).BuyerPar / 100)) { return(APIResultCodes.CollateralNotEnough); } return(APIResultCodes.Success); }
public override async Task <APIResultCodes> PreSendAuthAsync(DagSystem sys, SendTransferBlock send, TransactionBlock last) { if (send.Tags.Count != 2 || !send.Tags.ContainsKey("data") || string.IsNullOrWhiteSpace(send.Tags["data"]) ) { return(APIResultCodes.InvalidBlockTags); } OTCOrder order; try { order = JsonConvert.DeserializeObject <OTCOrder>(send.Tags["data"]); } catch (Exception ex) { return(APIResultCodes.InvalidBlockTags); } // daoid var dao = await sys.Storage.FindLatestBlockAsync(order.daoId); if (string.IsNullOrEmpty(order.daoId) || dao == null || (dao as TransactionBlock).AccountID != send.DestinationAccountId) { return(APIResultCodes.InvalidOrgnization); } // verify Dealer exists var dlr = await sys.Storage.FindLatestBlockAsync(order.dealerId); if (string.IsNullOrEmpty(order.dealerId) || dlr == null || dlr is not DealerGenesisBlock) { return(APIResultCodes.InvalidDealerServer); } // check every field of Order // dir, priceType if (order.dir != TradeDirection.Sell || order.priceType != PriceType.Fixed) { return(APIResultCodes.InvalidTagParameters); } // crypto var tokenGenesis = await sys.Storage.FindTokenGenesisBlockAsync(null, order.crypto); if (tokenGenesis == null) { return(APIResultCodes.TokenNotFound); } // fiat if (!FIATS.Contains(order.fiat)) { return(APIResultCodes.Unsupported); } // price, amount if (order.price <= 0.00001m || order.amount < 0.0001m) { return(APIResultCodes.InvalidAmount); } // payBy if (order.payBy == null || order.payBy.Length == 0) { return(APIResultCodes.InvalidOrder); } // verify collateral var chgs = send.GetBalanceChanges(last); if (!chgs.Changes.ContainsKey(LyraGlobal.OFFICIALTICKERCODE) || chgs.Changes[LyraGlobal.OFFICIALTICKERCODE] < order.collateral) { return(APIResultCodes.InvalidCollateral); } // check the price of order and collateral. var dlrblk = await sys.Storage.FindLatestBlockAsync(order.dealerId); var uri = new Uri(new Uri((dlrblk as IDealer).Endpoint), "/api/dealer/"); var dealer = new DealerClient(uri); var prices = await dealer.GetPricesAsync(); var tokenSymbol = order.crypto.Split('/')[1]; if (order.collateralPrice != prices["LYR"] || order.fiatPrice != prices[order.fiat.ToLower()]) { return(APIResultCodes.PriceChanged); } if (order.collateral * prices["LYR"] < prices[tokenSymbol] * order.amount * ((dao as IDao).SellerPar / 100)) { return(APIResultCodes.CollateralNotEnough); } if (order.collateralPrice != prices["LYR"]) { return(APIResultCodes.PriceChanged); } decimal usdprice = 0; if (tokenSymbol == "ETH") { usdprice = prices["ETH"]; } if (tokenSymbol == "BTC") { usdprice = prices["BTC"]; } if (tokenSymbol == "USDT") { usdprice = prices["USDT"]; } var selcryptoprice = Math.Round(usdprice / prices[order.fiat.ToLower()], 2); var total = selcryptoprice * order.amount; // limit if (order.limitMin <= 0 || order.limitMax < order.limitMin || order.limitMax > total) { return(APIResultCodes.InvalidArgument); } return(APIResultCodes.Success); }