Example #1
0
        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);
        }