示例#1
0
        public override async Task <APIResultCodes> PreSendAuthAsync(DagSystem sys, SendTransferBlock block, TransactionBlock lastBlock)
        {
            if (block.Tags.Count != 2 || !block.Tags.ContainsKey("poolid"))
            {
                return(APIResultCodes.InvalidBlockTags);
            }

            var poolGenesis = sys.Storage.GetPoolByID(block.Tags["poolid"]);

            if (poolGenesis == null)
            {
                return(APIResultCodes.PoolNotExists);
            }

            var chgs = block.GetBalanceChanges(lastBlock);

            if (chgs.Changes[LyraGlobal.OFFICIALTICKERCODE] != 1m)
            {
                return(APIResultCodes.InvalidFeeAmount);
            }

            if (!(await sys.Storage.FindLatestBlockAsync(poolGenesis.AccountID) is IPool pool))
            {
                return(APIResultCodes.PoolNotExists);
            }

            if (!pool.Shares.ContainsKey(block.AccountID))
            {
                return(APIResultCodes.PoolShareNotExists);
            }

            return(APIResultCodes.Success);
        }
示例#2
0
        public override async Task <APIResultCodes> PreSendAuthAsync(DagSystem sys, SendTransferBlock send, TransactionBlock last)
        {
            if (send.Tags.Count != 3 ||
                !send.Tags.ContainsKey("voteid") ||
                string.IsNullOrWhiteSpace(send.Tags["voteid"]) ||
                !send.Tags.ContainsKey("index") ||
                string.IsNullOrWhiteSpace(send.Tags["index"])
                )
            {
                return(APIResultCodes.InvalidBlockTags);
            }

            var voteid = send.Tags["voteid"];
            var index  = int.Parse(send.Tags["index"]);

            var voteg = sys.Storage.FindFirstBlock(voteid) as VotingGenesisBlock;
            var votel = await sys.Storage.FindLatestBlockAsync(voteid);

            // index must in range
            if (index < 0 || index > voteg.Subject.Options.Count() - 1)
            {
                return(APIResultCodes.InvalidVote);
            }

            // voter should in treasure the time when vote generated
            // we find it by voteg.relatedtx
            var vgreltx  = voteg.RelatedTx;
            var allreltx = await sys.Storage.FindBlocksByRelatedTxAsync(vgreltx);

            var dao = await sys.Storage.FindBlockByHashAsync(
                allreltx.First(a => a is DaoRecvBlock).Hash);

            if (!(dao as IDao).Treasure.ContainsKey(send.AccountID))
            {
                return(APIResultCodes.Unauthorized);
            }

            // voter shouldn't multiple vote
            for (var a = votel.Height; a > 1; a--)
            {
                var vx = await sys.Storage.FindBlockByHeightAsync(voteid, a);

                if ((vx as VotingBlock).VoterId == send.AccountID)
                {
                    return(APIResultCodes.InvalidVote);
                }
            }

            // vote should be in progress
            if ((votel as IVoting).VoteState != VoteStatus.InProgress)
            {
                return(APIResultCodes.InvalidVote);
            }

            return(APIResultCodes.Success);
        }
        protected APIResultCodes ValidateReceiveTransAmount(ReceiveTransferBlock block, TransactionInfo receiveTransaction)
        {
            //find the corresponding send block and validate the added transaction amount
            var sourceBlock = _accountCollection.FindBlockByHash(block.SourceHash);

            if (sourceBlock == null)
            {
                return(APIResultCodes.SourceSendBlockNotFound);
            }


            // find the actual amount of transaction

            TransactionBlock prevToSendBlock = _accountCollection.FindBlockByHash(sourceBlock.PreviousHash);

            if (prevToSendBlock == null)
            {
                return(APIResultCodes.CouldNotTraceSendBlockChain);
            }


            TransactionInfo sendTransaction;

            if (block.BlockType == BlockTypes.ReceiveTransfer || block.BlockType == BlockTypes.OpenAccountWithReceiveTransfer)
            {
                if ((sourceBlock as SendTransferBlock).DestinationAccountId != block.AccountID)
                {
                    return(APIResultCodes.InvalidDestinationAccountId);
                }

                sendTransaction = sourceBlock.GetTransaction(prevToSendBlock);

                if (!sourceBlock.ValidateTransaction(prevToSendBlock))
                {
                    return(APIResultCodes.SendTransactionValidationFailed);
                }
                //originallySentAmount = sendTransaction.Amount;
                //originallySentAmount =
                //    prevToSendBlock.Balances[LyraGlobal.LYRA_TICKER_CODE] - sourceBlock.Balances[LyraGlobal.LYRA_TICKER_CODE] - (sourceBlock as IFeebleBlock).Fee;
            }
            else
            if (block.BlockType == BlockTypes.ReceiveFee || block.BlockType == BlockTypes.OpenAccountWithReceiveFee)
            {
                sendTransaction = new TransactionInfo()
                {
                    TokenCode = LyraGlobal.LYRA_TICKER_CODE, Amount = sourceBlock.Fee
                };
            }
            else
            {
                return(APIResultCodes.InvalidBlockType);
            }

            if (sendTransaction.Amount != receiveTransaction.Amount)
            {
                return(APIResultCodes.TransactionAmountDoesNotMatch);
            }

            if (sendTransaction.TokenCode != receiveTransaction.TokenCode)
            {
                return(APIResultCodes.TransactionTokenDoesNotMatch);
            }

            return(APIResultCodes.Success);
        }
        private async Task <AuthorizationAPIResult> ReceiveTransferAsync(NewTransferAPIResult2 new_transfer_info)
        {
            // *** Slava - July 19, 2020 - I am not sure if we need this call anymore?
            //await FindTokenPrecision(new_transfer_info.Transfer.TokenCode);
            // ***

            if (await GetLocalAccountHeightAsync() == 0) // if this is new account with no blocks
            {
                return(await OpenStandardAccountWithReceiveBlockAsync(new_transfer_info));
            }

            var svcBlockResult = await _node.GetLastServiceBlockAsync();

            if (svcBlockResult.ResultCode != APIResultCodes.Success)
            {
                throw new Exception("Unable to get latest service block.");
            }

            TransactionBlock latestBlock = await GetLatestBlockAsync();

            var receiveBlock = new ReceiveTransferBlock
            {
                AccountID        = _accountId,
                VoteFor          = latestBlock.VoteFor,
                ServiceHash      = svcBlockResult.GetBlock().Hash,
                SourceHash       = new_transfer_info.SourceHash,
                Balances         = new Dictionary <string, long>(),
                Fee              = 0,
                FeeType          = AuthorizationFeeTypes.NoFee,
                FeeCode          = LyraGlobal.OFFICIALTICKERCODE,
                NonFungibleToken = new_transfer_info.NonFungibleToken
            };

            var latestBalances = latestBlock.Balances.ToDecimalDict();
            var recvBalances   = latestBlock.Balances.ToDecimalDict();

            foreach (var chg in new_transfer_info.Transfer.Changes)
            {
                if (recvBalances.ContainsKey(chg.Key))
                {
                    recvBalances[chg.Key] += chg.Value;
                }
                else
                {
                    recvBalances.Add(chg.Key, chg.Value);
                }
            }

            receiveBlock.Balances = recvBalances.ToLongDict();

            await receiveBlock.InitializeBlockAsync(latestBlock, _signer);

            if (!receiveBlock.ValidateTransaction(latestBlock))
            {
                throw new Exception("ValidateTransaction failed");
            }

            //receiveBlock.Signature = Signatures.GetSignature(PrivateKey, receiveBlock.Hash);

            var result = await _trans.ReceiveTransferAsync(receiveBlock);

            if (result.ResultCode == APIResultCodes.Success)
            {
                LastBlock = receiveBlock;
            }
            else
            {
                LastBlock = null;
            }
            return(result);
        }
        public async Task <AuthorizationAPIResult> CreateTokenAsync(
            string tokenName,
            string domainName,
            string description,
            sbyte precision,
            decimal supply,
            bool isFinalSupply,
            string owner,               // shop name
            string address,             // shop URL
            string currency,            // USD
            ContractTypes contractType, // reward or discount or custom
            Dictionary <string, string> tags)
        {
            if (string.IsNullOrWhiteSpace(domainName))
            {
                domainName = "Custom";
            }

            string ticker = domainName + "/" + tokenName;

            var blockresult = await _node.GetLastServiceBlockAsync();

            if (blockresult.ResultCode != APIResultCodes.Success)
            {
                return new AuthorizationAPIResult()
                       {
                           ResultCode = blockresult.ResultCode
                       }
            }
            ;

            ServiceBlock lastServiceBlock = blockresult.GetBlock() as ServiceBlock;

            TransactionBlock latestBlock = await GetLatestBlockAsync();

            if (latestBlock == null || latestBlock.Balances[LyraGlobal.OFFICIALTICKERCODE] < lastServiceBlock.TokenGenerationFee.ToBalanceLong())
            {
                //throw new Exception("Insufficent funds");
                return(new AuthorizationAPIResult()
                {
                    ResultCode = APIResultCodes.InsufficientFunds
                });
            }

            var svcBlockResult = await _node.GetLastServiceBlockAsync();

            if (svcBlockResult.ResultCode != APIResultCodes.Success)
            {
                throw new Exception("Unable to get latest service block.");
            }

            // initiate test coins
            TokenGenesisBlock tokenBlock = new TokenGenesisBlock
            {
                Ticker        = ticker,
                DomainName    = domainName,
                Description   = description,
                Precision     = precision,
                IsFinalSupply = isFinalSupply,
                //CustomFee = 0,
                //CustomFeeAccountId = string.Empty,
                AccountID    = AccountId,
                Balances     = new Dictionary <string, long>(),
                ServiceHash  = svcBlockResult.GetBlock().Hash,
                Fee          = lastServiceBlock.TokenGenerationFee,
                FeeCode      = LyraGlobal.OFFICIALTICKERCODE,
                FeeType      = AuthorizationFeeTypes.Regular,
                Owner        = owner,
                Address      = address,
                Currency     = currency,
                Tags         = tags,
                RenewalDate  = DateTime.UtcNow.Add(TimeSpan.FromDays(3650)),
                ContractType = contractType,
                VoteFor      = latestBlock.VoteFor
            };
            // TO DO - set service hash

            //var transaction = new TransactionInfo() { TokenCode = ticker, Amount = supply * (long)Math.Pow(10, precision) };
            var transaction = new TransactionInfo()
            {
                TokenCode = ticker, Amount = supply
            };

            tokenBlock.Balances.Add(transaction.TokenCode, transaction.Amount.ToBalanceLong()); // This is current supply in atomic units (1,000,000.00)
            tokenBlock.Balances.Add(LyraGlobal.OFFICIALTICKERCODE, latestBlock.Balances[LyraGlobal.OFFICIALTICKERCODE] - lastServiceBlock.TokenGenerationFee.ToBalanceLong());
            //tokenBlock.Transaction = transaction;
            // transfer unchanged token balances from the previous block
            foreach (var balance in latestBlock.Balances)
            {
                if (!(tokenBlock.Balances.ContainsKey(balance.Key)))
                {
                    tokenBlock.Balances.Add(balance.Key, balance.Value);
                }
            }

            await tokenBlock.InitializeBlockAsync(latestBlock, _signer);

            //tokenBlock.Signature = Signatures.GetSignature(PrivateKey, tokenBlock.Hash);

            var result = await _trans.CreateTokenAsync(tokenBlock);

            if (result.ResultCode == APIResultCodes.Success)
            {
                LastBlock = tokenBlock;
            }
            else
            {
                LastBlock = null;
            }

            return(result);
        }
        protected override APIResultCodes ValidateNonFungible(TransactionBlock send_or_receice_block, TransactionBlock previousBlock)
        {
            var result = base.ValidateNonFungible(send_or_receice_block, previousBlock);

            if (result != APIResultCodes.Success)
            {
                return(result);
            }

            if (send_or_receice_block.NonFungibleToken == null)
            {
                return(APIResultCodes.Success);
            }

            //if (send_or_receice_block.NonFungibleToken.OriginHash != send_or_receice_block.Hash)
            //    return APIResultCodes.OriginNonFungibleBlockHashDoesNotMatch;


            return(APIResultCodes.Success);
        }
示例#7
0
        public override async Task <APIResultCodes> PreSendAuthAsync(DagSystem sys, SendTransferBlock send, TransactionBlock last)
        {
            if (send.Tags.Count != 2 ||
                !send.Tags.ContainsKey("daoid") ||
                string.IsNullOrWhiteSpace(send.Tags["daoid"])
                )
            {
                return(APIResultCodes.InvalidBlockTags);
            }

            // dao must exists
            var dao = await sys.Storage.FindLatestBlockAsync(send.Tags["daoid"]);

            if (dao == null)
            {
                return(APIResultCodes.InvalidDAO);
            }

            var txInfo = send.GetBalanceChanges(await sys.Storage.FindBlockByHashAsync(send.PreviousHash) as TransactionBlock);

            if (txInfo.Changes.Count != 1 || !txInfo.Changes.ContainsKey("LYR"))
            {
                return(APIResultCodes.InvalidToken);
            }

            //min amount to invest
            var amount = txInfo.Changes["LYR"];

            if (amount < 10000)
            {
                return(APIResultCodes.InvalidAmount);
            }

            return(APIResultCodes.Success);
        }
示例#8
0
        public override async Task <APIResultCodes> PreSendAuthAsync(DagSystem sys, SendTransferBlock block, TransactionBlock lastBlock)
        {
            var chgs = block.GetBalanceChanges(lastBlock);

            if (!chgs.Changes.ContainsKey(LyraGlobal.OFFICIALTICKERCODE))
            {
                return(APIResultCodes.InvalidFeeAmount);
            }

            if (block.Tags.Count == 1)
            {
                // verify sender is the owner of stkingblock
                var stks = await sys.Storage.FindAllStakingAccountForOwnerAsync(block.AccountID);

                if (!stks.Any(a => a.AccountID == block.DestinationAccountId))
                {
                    return(APIResultCodes.InvalidStakingAccount);
                }
            }
            else
            {
                return(APIResultCodes.InvalidBlockTags);
            }

            return(APIResultCodes.Success);
        }
        public override async Task <APIResultCodes> PreSendAuthAsync(DagSystem sys, SendTransferBlock block, TransactionBlock lastBlock)
        {
            var chgs = block.GetBalanceChanges(lastBlock);

            if (!chgs.Changes.ContainsKey(LyraGlobal.OFFICIALTICKERCODE))
            {
                return(APIResultCodes.InvalidFeeAmount);
            }

            if (
                block.Tags.ContainsKey("stkid") && !string.IsNullOrWhiteSpace(block.Tags["stkid"]) &&
                block.Tags.Count == 2
                )
            {
                if (block.DestinationAccountId != PoolFactoryBlock.FactoryAccount)
                {
                    return(APIResultCodes.InvalidServiceRequest);
                }

                // verify sender is the owner of stkingblock
                var stks = await sys.Storage.FindAllStakingAccountForOwnerAsync(block.AccountID);

                if (!stks.Any(a => a.AccountID == block.Tags["stkid"]))
                {
                    return(APIResultCodes.InvalidStakingAccount);
                }

                var lastStk = await sys.Storage.FindLatestBlockAsync(block.Tags["stkid"]) as TransactionBlock;

                if (lastStk == null)
                {
                    return(APIResultCodes.InvalidUnstaking);
                }

                if (lastStk.BlockType == BlockTypes.UnStaking || ((IStaking)lastStk).Start == DateTime.MaxValue)
                {
                    return(APIResultCodes.InvalidUnstaking);
                }

                if (!lastStk.Balances.ContainsKey(LyraGlobal.OFFICIALTICKERCODE) || lastStk.Balances[LyraGlobal.OFFICIALTICKERCODE].ToBalanceDecimal() == 0)
                {
                    return(APIResultCodes.InvalidUnstaking);
                }
            }
            else
            {
                return(APIResultCodes.InvalidBlockTags);
            }

            return(APIResultCodes.Success);
        }
 /// <summary>
 /// Crear nodo génesis.
 /// </summary>
 public async Task InsertTransaction(TransactionBlock transactionBlock)
 {
     await transactionCollection.InsertOneAsync(transactionBlock);
 }
        /// <summary>
        /// Inserar una nueva transacción actualizando el último nodo.
        /// </summary>
        public async Task InsertTransaction(TransactionBlock transactionBlock, string genNodeId)
        {
            transactionBlock.Hash = await UpdateNextHash(await GetLastTransaction(genNodeId));

            await transactionCollection.InsertOneAsync(transactionBlock);
        }
示例#12
0
        public override async Task <TransactionBlock> BrokerOpsAsync(DagSystem sys, SendTransferBlock sendBlock)
        {
            // assume all send variables are legal
            // token0/1, amount, etc.
            var blocks = await sys.Storage.FindBlocksByRelatedTxAsync(sendBlock.Hash);

            if (blocks.Any(a => a is PoolSwapInBlock))
            {
                return(null);
            }

            var lsb = await sys.Storage.GetLastServiceBlockAsync();

            var swapInBlock = new PoolSwapInBlock
            {
                AccountID   = sendBlock.DestinationAccountId,
                VoteFor     = null,
                ServiceHash = lsb.Hash,
                SourceHash  = sendBlock.Hash,
                Balances    = new Dictionary <string, long>(),
                Fee         = 0,
                FeeCode     = LyraGlobal.OFFICIALTICKERCODE,
                FeeType     = AuthorizationFeeTypes.NoFee,

                RelatedTx = sendBlock.Hash
            };

            swapInBlock.AddTag(Block.MANAGEDTAG, "");   // value is always ignored

            TransactionBlock prevSend = await sys.Storage.FindBlockByHashAsync(sendBlock.PreviousHash) as TransactionBlock;

            var txInfo = sendBlock.GetBalanceChanges(prevSend);

            TransactionBlock latestPoolBlock = await sys.Storage.FindLatestBlockAsync(sendBlock.DestinationAccountId) as TransactionBlock;

            PoolGenesisBlock poolGenesis = await sys.Storage.FindFirstBlockAsync(latestPoolBlock.AccountID) as PoolGenesisBlock;

            var depositBalance = new Dictionary <string, decimal>();

            if (latestPoolBlock.Balances.Any())
            {
                var lastBalance = latestPoolBlock.Balances.ToDecimalDict();

                // the rito must be preserved for every deposition
                //var poolRito = lastBalance[poolGenesis.Token0] / lastBalance[poolGenesis.Token1];
                foreach (var oldBalance in lastBalance)
                {
                    if (txInfo.Changes.ContainsKey(oldBalance.Key))
                    {
                        depositBalance.Add(oldBalance.Key, oldBalance.Value + txInfo.Changes[oldBalance.Key]);
                    }
                    else
                    {
                        depositBalance.Add(oldBalance.Key, oldBalance.Value);
                    }
                }

                var prevBalance = lastBalance[poolGenesis.Token0];
                var curBalance  = depositBalance[poolGenesis.Token0];
            }
            else
            {
                foreach (var token in txInfo.Changes)
                {
                    depositBalance.Add(token.Key, token.Value);
                }
            }

            swapInBlock.Balances = depositBalance.ToLongDict();
            swapInBlock.Shares   = (latestPoolBlock as IPool).Shares;
            await swapInBlock.InitializeBlockAsync(latestPoolBlock, (hash) => Task.FromResult(Signatures.GetSignature(sys.PosWallet.PrivateKey, hash, sys.PosWallet.AccountId)));

            return(swapInBlock);
        }
示例#13
0
        public override async Task <APIResultCodes> PreSendAuthAsync(DagSystem sys, SendTransferBlock send, TransactionBlock lastBlock)
        {
            // generic pool factory
            var tgc = await CheckPoolTagsAsync(sys, send);

            if (tgc != APIResultCodes.Success)
            {
                return(tgc);
            }

            var chgs = send.GetBalanceChanges(lastBlock);

            if (!chgs.Changes.ContainsKey(LyraGlobal.OFFICIALTICKERCODE))
            {
                return(APIResultCodes.InvalidFeeAmount);
            }

            if (chgs.Changes.Count > 1)
            {
                return(APIResultCodes.InvalidFeeAmount);
            }

            // check if pool exists
            var factory = await sys.Storage.GetPoolFactoryAsync();

            if (factory == null)
            {
                return(APIResultCodes.SystemNotReadyToServe);
            }

            // action

            if (chgs.Changes[LyraGlobal.OFFICIALTICKERCODE] != PoolFactoryBlock.PoolCreateFee)
            {
                return(APIResultCodes.InvalidFeeAmount);
            }

            var poolGenesis = await sys.Storage.GetPoolAsync(send.Tags["token0"], send.Tags["token1"]);

            if (poolGenesis != null)
            {
                return(APIResultCodes.PoolAlreadyExists);
            }

            return(APIResultCodes.Success);
        }
示例#14
0
        public override async Task <APIResultCodes> PreSendAuthAsync(DagSystem sys, SendTransferBlock block, TransactionBlock lastBlock)
        {
            if (block.Tags.Count > 3 || !block.Tags.ContainsKey("poolid"))
            {
                return(APIResultCodes.InvalidBlockTags);
            }

            if (block.Tags.Count == 3 && !block.Tags.ContainsKey("minrecv"))
            {
                return(APIResultCodes.InvalidBlockTags);
            }

            var vp = await WFPoolAddLiquidate.VerifyPoolAsync(sys, block, lastBlock);

            if (vp != APIResultCodes.Success)
            {
                return(vp);
            }

            var chgs        = block.GetBalanceChanges(lastBlock);
            var poolGenesis = sys.Storage.GetPoolByID(block.Tags["poolid"]);

            if (chgs.Changes.Count != 1)
            {
                return(APIResultCodes.InvalidTokenToSwap);
            }

            string tokenToSwap = null;
            var    kvp         = chgs.Changes.First();

            if (kvp.Key == poolGenesis.Token0)
            {
                tokenToSwap = poolGenesis.Token0;
            }
            else if (kvp.Key == poolGenesis.Token1)
            {
                tokenToSwap = poolGenesis.Token1;
            }

            if (tokenToSwap == null)
            {
                return(APIResultCodes.InvalidTokenToSwap);
            }

            // check amount
            var poolLatest = await sys.Storage.FindLatestBlockAsync(block.DestinationAccountId) as TransactionBlock;

            //if (kvp.Value > poolLatest.Balances[tokenToSwap].ToBalanceDecimal() / 2)
            //    return APIResultCodes.TooManyTokensToSwap;
            // uniswap AMM don't mind how many token want to swap

            if (block.Tags.ContainsKey("minrecv"))
            {
                if (!long.TryParse(block.Tags["minrecv"], out long toGetLong))
                {
                    return(APIResultCodes.InvalidSwapSlippage);
                }

                decimal toGet = toGetLong.ToBalanceDecimal();

                if (toGet <= 0)
                {
                    return(APIResultCodes.InvalidSwapSlippage);
                }

                if (poolLatest.Balances.Any(a => a.Value == 0))
                {
                    // can't calculate rito
                    return(APIResultCodes.PoolOutOfLiquidaty);
                }

                var cal = new SwapCalculator(poolGenesis.Token0, poolGenesis.Token1, poolLatest,
                                             chgs.Changes.First().Key, chgs.Changes.First().Value, 0);

                if (cal.SwapOutAmount < toGet)
                {
                    return(APIResultCodes.SwapSlippageExcceeded);
                }
            }
            return(APIResultCodes.Success);
        }
示例#15
0
        public override async Task <APIResultCodes> PreSendAuthAsync(DagSystem sys, SendTransferBlock send, TransactionBlock last)
        {
            if (
                send.Tags.ContainsKey("objType") && send.Tags["objType"] == nameof(DealerCreateArgument) &&
                send.Tags.ContainsKey("data") && !string.IsNullOrWhiteSpace(send.Tags["data"]) &&
                send.Tags.Count == 3
                )
            {
                DealerCreateArgument arg;
                try
                {
                    arg = JsonConvert.DeserializeObject <DealerCreateArgument>(send.Tags["data"]);
                    if (arg == null)
                    {
                        throw new Exception();
                    }
                }
                catch
                {
                    return(APIResultCodes.InvalidArgument);
                }

                // validate the argument
                if (!Signatures.ValidateAccountId(arg.DealerAccountId))
                {
                    return(APIResultCodes.InvalidAccountId);
                }

                if (arg.Mode != ClientMode.Permissionless)
                {
                    return(APIResultCodes.InvalidArgument);
                }

                // check name dup
                var existsdealer = sys.Storage.GetDealerByName(arg.Name);
                if (existsdealer != null)
                {
                    return(APIResultCodes.DuplicateName);
                }

                return(APIResultCodes.Success);
            }
            else
            {
                return(APIResultCodes.InvalidTagParameters);
            }
        }
示例#16
0
        public override async Task <APIResultCodes> PreSendAuthAsync(DagSystem sys, SendTransferBlock send, TransactionBlock last)
        {
            decimal shareRito, sellerFeeRatio, buyerFeeRatio;
            int     seats;

            if (
                send.Tags.ContainsKey("name") && !string.IsNullOrWhiteSpace(send.Tags["name"]) &&
                send.Tags.ContainsKey("desc") && !string.IsNullOrWhiteSpace(send.Tags["desc"]) &&
                send.Tags.ContainsKey("sellerFeeRatio") && decimal.TryParse(send.Tags["sellerFeeRatio"], out sellerFeeRatio) &&
                send.Tags.ContainsKey("buyerFeeRatio") && decimal.TryParse(send.Tags["buyerFeeRatio"], out buyerFeeRatio) &&
                send.Tags.ContainsKey("sellerPar") && int.TryParse(send.Tags["sellerPar"], out int sellerPar) &&
                send.Tags.ContainsKey("buyerPar") && int.TryParse(send.Tags["sellerPar"], out int buyerPar) &&
                send.Tags.ContainsKey("share") && decimal.TryParse(send.Tags["share"], out shareRito) &&
                send.Tags.ContainsKey("seats") && int.TryParse(send.Tags["seats"], out seats)

                && send.Tags.Count == 9
                )
            {
                var name = send.Tags["name"];
                var desc = send.Tags["desc"];

                // profiting
                if (shareRito >= 0m && shareRito <= 1m && seats >= 0 && seats <= 100)
                {
                }
                else
                {
                    return(APIResultCodes.InvalidShareRitio);
                }

                if (shareRito == 0 && seats != 0)
                {
                    return(APIResultCodes.InvalidShareRitio);
                }

                if (shareRito > 0 && seats == 0)
                {
                    return(APIResultCodes.InvalidShareRitio);
                }

                if (shareRito > 1)
                {
                    return(APIResultCodes.InvalidShareRitio);
                }

                if (name.Length < 3)
                {
                    return(APIResultCodes.InputTooShort);
                }

                if (name.Length > 100 || desc.Length > 300)
                {
                    return(APIResultCodes.InputTooLong);
                }

                if (send.DestinationAccountId != PoolFactoryBlock.FactoryAccount)
                {
                    return(APIResultCodes.InvalidServiceRequest);
                }

                if (sellerPar < 0 || sellerPar > 1000 || buyerPar < 0 || buyerPar > 1000)
                {
                    return(APIResultCodes.InvalidTagParameters);
                }

                if (sellerFeeRatio < 0 || sellerFeeRatio > 1 || buyerFeeRatio < 0 || buyerFeeRatio > 1)
                {
                    return(APIResultCodes.InvalidArgument);
                }

                // check name dup
                var existsdao = sys.Storage.GetDaoByName(name);
                if (existsdao != null)
                {
                    return(APIResultCodes.DuplicateName);
                }

                return(APIResultCodes.Success);
            }
            else
            {
                return(APIResultCodes.InvalidTagParameters);
            }
        }
        public override APIResultCodes Authorize <T>(ref T tblock)
        {
            if (!(tblock is SendTransferBlock))
            {
                return(APIResultCodes.InvalidBlockType);
            }

            var block = tblock as SendTransferBlock;

            // 1. check if the account already exists
            if (!_accountCollection.AccountExists(block.AccountID))
            {
                return(APIResultCodes.AccountDoesNotExist);
            }

            TransactionBlock lastBlock = _accountCollection.FindLatestBlock(block.AccountID);

            if (lastBlock == null)
            {
                return(APIResultCodes.CouldNotFindLatestBlock);
            }

            var result = VerifyBlock(block, lastBlock);

            if (result != APIResultCodes.Success)
            {
                return(result);
            }

            //if (lastBlock.Balances[LyraGlobal.LYRA_TICKER_CODE] <= block.Balances[LyraGlobal.LYRA_TICKER_CODE] + block.Fee)
            //    return AuthorizationResultCodes.NegativeTransactionAmount;

            // Validate the destination account id
            if (!Signatures.ValidateAccountId(block.DestinationAccountId))
            {
                return(APIResultCodes.InvalidDestinationAccountId);
            }

            result = VerifyTransactionBlock(block);
            if (result != APIResultCodes.Success)
            {
                return(result);
            }

            if (!block.ValidateTransaction(lastBlock))
            {
                return(APIResultCodes.SendTransactionValidationFailed);
            }

            result = ValidateNonFungible(block, lastBlock);
            if (result != APIResultCodes.Success)
            {
                return(result);
            }

            Sign(ref block);

            _accountCollection.AddBlock(block);

            return(base.Authorize(ref tblock));
        }
        protected virtual async Task <APIResultCodes> ValidateReceiveTransAmountAsync(DagSystem sys, ReceiveTransferBlock block, BalanceChanges receiveTransaction)
        {
            //find the corresponding send block and validate the added transaction amount
            var srcBlock = await sys.Storage.FindBlockByHashAsync(block.SourceHash);

            if (srcBlock is TransactionBlock sourceBlock)
            {
                if (sourceBlock == null)
                {
                    return(APIResultCodes.SourceSendBlockNotFound);
                }

                // find the actual amount of transaction
                BalanceChanges sendTransaction;
                if (block.BlockType == BlockTypes.ReceiveTransfer || block.BlockType == BlockTypes.OpenAccountWithReceiveTransfer ||
                    block.BlockType == BlockTypes.PoolDeposit || block.BlockType == BlockTypes.PoolSwapIn ||
                    block.BlockType == BlockTypes.Staking || block.BlockType == BlockTypes.Profiting ||
                    block.BlockType == BlockTypes.ReceiveAsFee ||
                    block.BlockType == BlockTypes.DexRecvToken ||
                    block.BlockType == BlockTypes.OrgnizationRecv ||
                    block.BlockType == BlockTypes.OrgnizationChange ||
                    block.BlockType == BlockTypes.OTCOrderRecv ||
                    block.BlockType == BlockTypes.OTCTradeRecv ||
                    block.BlockType == BlockTypes.OTCTradeResolutionRecv ||
                    block.BlockType == BlockTypes.Voting
                    )  // temp code. should use getbalancechanges
                {
                    if ((sourceBlock as SendTransferBlock).DestinationAccountId != block.AccountID)
                    {
                        // first check if the transfer was aimed to imported account
                        if (!await sys.Storage.WasAccountImportedAsync((sourceBlock as SendTransferBlock).DestinationAccountId, block.AccountID))
                        {
                            return(APIResultCodes.InvalidDestinationAccountId);
                        }
                    }

                    TransactionBlock prevToSendBlock = await sys.Storage.FindBlockByHashAsync(sourceBlock.PreviousHash) as TransactionBlock;

                    if (prevToSendBlock == null)
                    {
                        return(APIResultCodes.CouldNotTraceSendBlockChain);
                    }

                    sendTransaction = sourceBlock.GetBalanceChanges(prevToSendBlock);

                    if (!sourceBlock.ValidateTransaction(prevToSendBlock))
                    {
                        return(APIResultCodes.SendTransactionValidationFailed);
                    }
                    //originallySentAmount = sendTransaction.Amount;
                    //originallySentAmount =
                    //    prevToSendBlock.Balances[LyraGlobal.LYRA_TICKER_CODE] - sourceBlock.Balances[LyraGlobal.LYRA_TICKER_CODE] - (sourceBlock as IFeebleBlock).Fee;
                }
                else
                if (block.BlockType == BlockTypes.ReceiveFee || block.BlockType == BlockTypes.OpenAccountWithReceiveFee)
                {
                    sendTransaction = new BalanceChanges();
                    sendTransaction.Changes.Add(LyraGlobal.OFFICIALTICKERCODE, sourceBlock.Fee);
                }
                else
                {
                    return(APIResultCodes.InvalidBlockType);
                }

                if (block.BlockType == BlockTypes.ReceiveAsFee)
                {
                    var send = sendTransaction.Changes[LyraGlobal.OFFICIALTICKERCODE];
                    var recv = receiveTransaction.Changes.Count == 0 ? 0 : receiveTransaction.Changes[LyraGlobal.OFFICIALTICKERCODE];
                    var fee  = block.Fee;
                    if (fee != send || recv != 0)
                    {
                        return(APIResultCodes.InvalidFeeAmount);
                    }
                }
                else
                {
                    if (!sendTransaction.Changes.OrderBy(kvp => kvp.Key)
                        .SequenceEqual(receiveTransaction.Changes.OrderBy(kvp => kvp.Key)))
                    {
                        return(APIResultCodes.TransactionAmountDoesNotMatch);
                    }
                }

                //if (sendTransaction.Amount != receiveTransaction.Amount)
                //    return APIResultCodes.TransactionAmountDoesNotMatch;

                //if (sendTransaction.TokenCode != receiveTransaction.TokenCode)
                //    return APIResultCodes.TransactionTokenDoesNotMatch;
            }
            else if (srcBlock == null)
            {
                if (block is ReceiveNodeProfitBlock)
                {
                    return(APIResultCodes.Success);
                }
            }
            else
            {
                return(APIResultCodes.UnsupportedBlockType);
            }

            return(APIResultCodes.Success);
        }
示例#19
0
        public override async Task <APIResultCodes> PreSendAuthAsync(DagSystem sys, SendTransferBlock send, TransactionBlock last)
        {
            if (send.Tags.Count != 4 ||
                !send.Tags.ContainsKey("tradeid") ||
                string.IsNullOrWhiteSpace(send.Tags["tradeid"]) ||
                !send.Tags.ContainsKey("orderid") ||
                string.IsNullOrWhiteSpace(send.Tags["orderid"]) ||
                !send.Tags.ContainsKey("daoid") ||
                string.IsNullOrWhiteSpace(send.Tags["daoid"])
                )
            {
                return(APIResultCodes.InvalidBlockTags);
            }

            var tradeid = send.Tags["tradeid"];
            var orderid = send.Tags["orderid"];
            var daoid   = send.Tags["daoid"];

            var tradeblk = await sys.Storage.FindLatestBlockAsync(tradeid);

            var daoblk = await sys.Storage.FindLatestBlockAsync((tradeblk as IOtcTrade).Trade.daoId);

            if (daoblk == null || tradeblk == null || (daoblk as TransactionBlock).AccountID != daoid ||
                (tradeblk as IOtcTrade).Trade.daoId != (daoblk as TransactionBlock).AccountID)
            {
                return(APIResultCodes.InvalidTrade);
            }

            if ((tradeblk as IBrokerAccount).OwnerAccountId != send.AccountID)
            {
                return(APIResultCodes.InvalidTrade);
            }

            if ((tradeblk as IOtcTrade).OTStatus != OTCTradeStatus.Open)
            {
                return(APIResultCodes.InvalidTrade);
            }

            var orderblk = await sys.Storage.FindLatestBlockAsync(orderid);

            if (orderblk == null || (tradeblk as IOtcTrade).Trade.orderId != orderid ||
                (tradeblk as IOtcTrade).Trade.daoId != daoid)
            {
                return(APIResultCodes.InvalidTrade);
            }

            if (Settings.Default.LyraNode.Lyra.NetworkId != "xtest")
            {
                // check if trade is cancellable
                var lsb    = sys.Storage.GetLastServiceBlock();
                var wallet = sys.PosWallet;
                var sign   = Signatures.GetSignature(wallet.PrivateKey, lsb.Hash, wallet.AccountId);
                var dlrblk = await sys.Storage.FindLatestBlockAsync((tradeblk as IOtcTrade).Trade.dealerId);

                var uri    = new Uri(new Uri((dlrblk as IDealer).Endpoint), "/api/dealer/");
                var dealer = new DealerClient(uri);
                var ret    = await dealer.GetTradeBriefAsync(tradeid, wallet.AccountId, sign);

                if (!ret.Successful() || !ret.Deserialize <TradeBrief>().IsCancellable)
                {
                    return(APIResultCodes.InvalidOperation);
                }
            }

            return(APIResultCodes.Success);
        }
        protected override async Task <APIResultCodes> ValidateNonFungibleAsync(DagSystem sys, TransactionBlock send_or_receice_block, TransactionBlock previousBlock)
        {
            var result = await base.ValidateNonFungibleAsync(sys, send_or_receice_block, previousBlock);

            if (result != APIResultCodes.Success)
            {
                return(result);
            }

            if (send_or_receice_block.NonFungibleToken == null)
            {
                return(APIResultCodes.Success);
            }

            var originBlock = await sys.Storage.FindBlockByHashAsync((send_or_receice_block as ReceiveTransferBlock).SourceHash) as TransactionBlock;

            if (originBlock == null)
            {
                return(APIResultCodes.OriginNonFungibleBlockNotFound);
            }

            if (!originBlock.ContainsNonFungibleToken())
            {
                return(APIResultCodes.OriginNonFungibleBlockNotFound);
            }

            // this validation eliminates the need to make all the validations that already have been done on send block
            if (originBlock.NonFungibleToken.Hash != send_or_receice_block.NonFungibleToken.Hash)
            {
                return(APIResultCodes.OriginNonFungibleBlockHashDoesNotMatch);
            }

            // this validation eliminates the need to make all the validations that already have been done on send block
            if (originBlock.NonFungibleToken.Signature != send_or_receice_block.NonFungibleToken.Signature)
            {
                return(APIResultCodes.NFTSignaturesDontMatch);
            }

            return(APIResultCodes.Success);
        }
示例#21
0
        public override async Task <APIResultCodes> PreSendAuthAsync(DagSystem sys, SendTransferBlock block, TransactionBlock lastBlock)
        {
            var chgs = block.GetBalanceChanges(lastBlock);

            if (!chgs.Changes.ContainsKey(LyraGlobal.OFFICIALTICKERCODE))
            {
                return(APIResultCodes.InvalidFeeAmount);
            }

            switch (block.Tags[Block.REQSERVICETAG])
            {
            case BrokerActions.BRK_STK_CRSTK:       // create staking
                if (chgs.Changes[LyraGlobal.OFFICIALTICKERCODE] != PoolFactoryBlock.StakingAccountCreateFee)
                {
                    return(APIResultCodes.InvalidFeeAmount);
                }

                string votefor;
                int    days;
                if (
                    block.Tags.ContainsKey("name") && !string.IsNullOrWhiteSpace(block.Tags["name"]) &&
                    block.Tags.ContainsKey("days") && int.TryParse(block.Tags["days"], out days) && days >= 3 &&
                    block.Tags.ContainsKey("voting") && !string.IsNullOrEmpty(block.Tags["voting"]) &&
                    block.Tags.ContainsKey("compound") && !string.IsNullOrEmpty(block.Tags["compound"]) &&
                    block.Tags.Count == 5
                    )
                {
                    var stks = await sys.Storage.FindAllStakingAccountForOwnerAsync(block.AccountID);

                    if (stks.Any(a => a.Name == block.Tags["name"]))
                    {
                        return(APIResultCodes.DuplicateName);
                    }

                    votefor = block.Tags["voting"];
                    if (!Signatures.ValidateAccountId(votefor))
                    {
                        return(APIResultCodes.InvalidProfitingAccount);
                    }
                    var pftgen = await sys.Storage.FindFirstBlockAsync(votefor) as ProfitingGenesis;

                    if (pftgen == null || pftgen.AccountType != AccountTypes.Profiting)
                    {
                        return(APIResultCodes.InvalidProfitingAccount);
                    }
                    if (pftgen.Seats == 0 || pftgen.ShareRito == 0)
                    {
                        return(APIResultCodes.ProfitUnavaliable);
                    }
                    if (days <= 1)
                    {
                        return(APIResultCodes.VotingDaysTooSmall);
                    }
                    if (block.Tags["compound"] != "True" && block.Tags["compound"] != "False")
                    {
                        return(APIResultCodes.InvalidBlockTags);
                    }
                }
                else
                {
                    return(APIResultCodes.InvalidBlockTags);
                }
                break;

            default:
                return(APIResultCodes.InvalidServiceRequest);
            }
            return(APIResultCodes.Success);
        }
        protected override async Task <APIResultCodes> AuthorizeImplAsync <T>(DagSystem sys, T tblock)
        {
            if (!(tblock is ReceiveTransferBlock))
            {
                return(APIResultCodes.InvalidBlockType);
            }

            var block = tblock as ReceiveTransferBlock;

            if (block.AccountID.Equals(LyraGlobal.BURNINGACCOUNTID))
            {
                return(APIResultCodes.InvalidAccountId);
            }

            // 1. check if the account already exists
            //if(block is ProfitingGenesis || block is StakingGenesis || block is PoolGenesisBlock)
            //{
            //    return APIResultCodes.Success;
            //}

            if (block is IOpeningBlock)
            {
                if (block.Height != 1)
                {
                    return(APIResultCodes.InvalidOpeningAccount);
                }

                if (!AllowedOpeningBlockTypes.Any(a => a == block.BlockType))
                {
                    return(APIResultCodes.InvalidOpeningAccount);
                }
            }
            else
            {
                if (!await sys.Storage.AccountExistsAsync(block.AccountID))
                {
                    return(APIResultCodes.AccountDoesNotExist);
                }

                TransactionBlock lastBlock = await sys.Storage.FindLatestBlockAsync(block.AccountID) as TransactionBlock;

                if (lastBlock == null)
                {
                    return(APIResultCodes.CouldNotFindLatestBlock);
                }

                var result = await VerifyTransactionBlockAsync(sys, block);

                if (result != APIResultCodes.Success)
                {
                    return(result);
                }

                if (!block.ValidateTransaction(lastBlock))
                {
                    return(APIResultCodes.ReceiveTransactionValidationFailed);
                }

                result = await ValidateReceiveTransAmountAsync(sys, block, block.GetBalanceChanges(lastBlock));

                if (result != APIResultCodes.Success)
                {
                    return(result);
                }

                if (block.BlockType != BlockTypes.TokenGenesis)
                {
                    result = await ValidateNonFungibleAsync(sys, block, lastBlock);

                    if (result != APIResultCodes.Success)
                    {
                        return(result);
                    }
                }
            }

            if (await sys.Storage.WasAccountImportedAsync(block.AccountID))
            {
                return(APIResultCodes.CannotModifyImportedAccount);
            }

            if (block.SourceHash != null)
            {
                // Check duplicate receives (kind of double spending up down)
                var duplicate_block = await sys.Storage.FindBlockBySourceHashAsync(block.SourceHash);

                if (duplicate_block != null)
                {
                    return(APIResultCodes.DuplicateReceiveBlock);
                }

                var srcblk = sys.Storage.FindBlockByHash(block.SourceHash);
                if (srcblk is not SendTransferBlock)
                {
                    return(APIResultCodes.SourceSendBlockNotFound);
                }
            }

            return(await Lyra.Shared.StopWatcher.TrackAsync(() => base.AuthorizeImplAsync(sys, tblock), "ReceiveTransferAuthorizer->TransactionAuthorizer"));
        }
        public async Task <AuthorizationAPIResult> SendExAsync(string DestinationAccountId, Dictionary <string, decimal> Amounts, Dictionary <string, string> tags)
        {
            if (Amounts.Any(a => a.Value <= 0m))
            {
                throw new Exception("Amount must > 0");
            }

            TransactionBlock previousBlock = await GetLatestBlockAsync();

            if (previousBlock == null)
            {
                //throw new Exception("Previous block not found");
                return(new AuthorizationAPIResult()
                {
                    ResultCode = APIResultCodes.PreviousBlockNotFound
                });
            }

            // check tokens exists
            if (Amounts.Keys.Any(a => !previousBlock.Balances.ContainsKey(a)))
            {
                return(new AuthorizationAPIResult()
                {
                    ResultCode = APIResultCodes.TokenGenesisBlockNotFound
                });
            }

            var blockresult = await _node.GetLastServiceBlockAsync();

            if (blockresult.ResultCode != APIResultCodes.Success)
            {
                return new AuthorizationAPIResult()
                       {
                           ResultCode = blockresult.ResultCode
                       }
            }
            ;

            ServiceBlock lastServiceBlock = blockresult.GetBlock() as ServiceBlock;

            var fee = lastServiceBlock.TransferFee;

            SendTransferBlock sendBlock = new SendTransferBlock()
            {
                AccountID            = AccountId,
                VoteFor              = previousBlock.VoteFor,
                ServiceHash          = lastServiceBlock.Hash,
                DestinationAccountId = DestinationAccountId,
                Balances             = new Dictionary <string, long>(),
                Tags    = tags,
                Fee     = fee,
                FeeCode = LyraGlobal.OFFICIALTICKERCODE,
                FeeType = fee == 0m ? AuthorizationFeeTypes.NoFee : AuthorizationFeeTypes.Regular
            };

            // transfer unchanged token balances from the previous block
            foreach (var balance in previousBlock.Balances)
            {
                if (Amounts.ContainsKey(balance.Key))
                {
                    sendBlock.Balances.Add(balance.Key, (balance.Value.ToBalanceDecimal() - Amounts[balance.Key]).ToBalanceLong());
                }
                else
                {
                    sendBlock.Balances.Add(balance.Key, balance.Value);
                }
            }
            // substract the fee
            // for customer tokens, we pay fee in LYR (unless they are accepted by authorizers as a fee - TO DO)
            sendBlock.Balances[LyraGlobal.OFFICIALTICKERCODE] = (sendBlock.Balances[LyraGlobal.OFFICIALTICKERCODE].ToBalanceDecimal() - fee).ToBalanceLong();

            await sendBlock.InitializeBlockAsync(previousBlock, _signer);

            if (!sendBlock.ValidateTransaction(previousBlock))
            {
                return(new AuthorizationAPIResult()
                {
                    ResultCode = APIResultCodes.SendTransactionValidationFailed
                });
                //throw new Exception("ValidateTransaction failed");
            }

            //sendBlock.Signature = Signatures.GetSignature(PrivateKey, sendBlock.Hash);
            AuthorizationAPIResult result;

            //var stopwatch = Stopwatch.StartNew();
            result = await _trans.SendTransferAsync(sendBlock);

            if (result.ResultCode == APIResultCodes.Success)
            {
                LastBlock = sendBlock;
            }
            else
            {
                LastBlock = null;
            }

            return(result);
        }
 // forward api. should have more control here.
 //public ServiceAccount ServiceAccount => _serviceAccount;
 public void AddBlock(TransactionBlock block) => _store.AddBlock(block);
        public async Task <APIResultCodes> SendAsync(decimal Amount, string destAccount, string ticker = LyraGlobal.OFFICIALTICKERCODE)
        {
            if (Amount <= 0)
            {
                throw new Exception("Amount must > 0");
            }

            TransactionBlock previousBlock = await GetLatestBlockAsync();

            if (previousBlock == null)
            {
                throw new Exception("No balance");
            }

            var blockresult = await _node.GetLastServiceBlockAsync();

            if (blockresult.ResultCode != APIResultCodes.Success)
            {
                return(blockresult.ResultCode);
            }

            ServiceBlock lastServiceBlock = blockresult.GetBlock() as ServiceBlock;

            //long atomicamount = (long)(Amount * (decimal)Math.Pow(10, precision));
            var balance_change = Amount;

            //var transaction = new TransactionInfo() { TokenCode = ticker, Amount = atomicamount };

            var fee = lastServiceBlock.TransferFee;

            if (ticker == LyraGlobal.OFFICIALTICKERCODE)
            {
                balance_change += fee;
            }

            // see if we have enough tokens
            if (previousBlock.Balances[ticker] < balance_change.ToBalanceLong())
            {
                return(APIResultCodes.InsufficientFunds);
                //throw new Exception("Insufficient funds");
            }

            // see if we have enough LYR to pay the transfer fee
            if (ticker != LyraGlobal.OFFICIALTICKERCODE)
            {
                if (!previousBlock.Balances.ContainsKey(LyraGlobal.OFFICIALTICKERCODE) || previousBlock.Balances[LyraGlobal.OFFICIALTICKERCODE] < fee.ToBalanceLong())
                {
                    //throw new Exception("Insufficient funds to pay transfer fee");
                    return(APIResultCodes.InsufficientFunds);
                }
            }

            SendTransferBlock sendBlock;

            sendBlock = new SendTransferBlock()
            {
                AccountID            = _accountId,
                VoteFor              = previousBlock.VoteFor,
                ServiceHash          = lastServiceBlock.Hash,
                DestinationAccountId = destAccount,
                Balances             = new Dictionary <string, long>(),
                //PaymentID = string.Empty,
                Fee     = fee,
                FeeCode = LyraGlobal.OFFICIALTICKERCODE,
                FeeType = fee == 0m ? AuthorizationFeeTypes.NoFee : AuthorizationFeeTypes.Regular
            };

            sendBlock.Balances.Add(ticker, previousBlock.Balances[ticker] - balance_change.ToBalanceLong());
            //sendBlock.Transaction = transaction;

            // for customer tokens, we pay fee in LYR (unless they are accepted by authorizers as a fee - TO DO)
            if (ticker != LyraGlobal.OFFICIALTICKERCODE)
            {
                sendBlock.Balances.Add(LyraGlobal.OFFICIALTICKERCODE, previousBlock.Balances[LyraGlobal.OFFICIALTICKERCODE] - fee.ToBalanceLong());
            }

            // transfer unchanged token balances from the previous block
            foreach (var balance in previousBlock.Balances)
            {
                if (!(sendBlock.Balances.ContainsKey(balance.Key)))
                {
                    sendBlock.Balances.Add(balance.Key, balance.Value);
                }
            }

            await sendBlock.InitializeBlockAsync(previousBlock, _signer);

            if (!sendBlock.ValidateTransaction(previousBlock))
            {
                return(APIResultCodes.SendTransactionValidationFailed);
                //throw new Exception("ValidateTransaction failed");
            }

            //sendBlock.Signature = Signatures.GetSignature(PrivateKey, sendBlock.Hash);
            AuthorizationAPIResult result;

            //var stopwatch = Stopwatch.StartNew();
            result = await _trans.SendTransferAsync(sendBlock);

            //stopwatch.Stop();
            //PrintConLine($"_node.SendTransfer: {stopwatch.ElapsedMilliseconds} ms.");

            if (result.ResultCode == APIResultCodes.Success)
            {
                LastBlock = sendBlock;
            }
            else
            {
                LastBlock = null;
            }
            return(result.ResultCode);
        }
示例#26
0
        SendTransferBlock CreateSendDiscountTokenBlock(NonFungibleToken discount_token, TransactionBlock previousBlock)
        {
            decimal TransferFee = serviceAccount.GetLastServiceBlock().TransferFee;

            sbyte precision = _FirstGenesisBlock.Precision;

            //long atomicamount = (long)(50 * Math.Pow(10, precision));

            SendTransferBlock sendBlock = new SendTransferBlock
            {
                AccountID            = AccountId1,
                ServiceHash          = string.Empty,
                DestinationAccountId = AccountId2,
                Balances             = new Dictionary <string, decimal>(),
                Fee     = TransferFee,
                FeeType = AuthorizationFeeTypes.Regular,
                FeeCode = LyraGlobal.OFFICIALTICKERCODE
            };

            sendBlock.Balances.Add(LyraGlobal.OFFICIALTICKERCODE, previousBlock.Balances[LyraGlobal.OFFICIALTICKERCODE] - TransferFee);
            sendBlock.Balances.Add("Custom.DISC", previousBlock.Balances["Custom.DISC"] - 50);

            if (discount_token != null)
            {
                //sendBlock.NonFungibleTokens = new List<INonFungibleToken>();
                //sendBlock.NonFungibleTokens.Add(discount_token);
                sendBlock.NonFungibleToken = discount_token;

                //if (discount_token.OriginHash == null)
                //    discount_token.OriginHash = sendBlock.CalculateHash();
            }


            sendBlock.InitializeBlock(previousBlock, PrivateKey1, AccountId1);

            //sendBlock.Signature = Signatures.GetSignature(PrivateKey1, sendBlock.Hash);

            return(sendBlock);
        }
        public override APIResultCodes Authorize <T>(ref T tblock)
        {
            if (!(tblock is TradeOrderBlock))
            {
                return(APIResultCodes.InvalidBlockType);
            }

            var block = tblock as TradeOrderBlock;

            if (block.MaxQuantity != 1)
            {
                return(APIResultCodes.FeatureIsNotSupported);
            }

            // 1. check if the account already exists
            if (!_accountCollection.AccountExists(block.AccountID))
            {
                return(APIResultCodes.AccountDoesNotExist);
            }

            TransactionBlock lastBlock = _accountCollection.FindLatestBlock(block.AccountID);

            if (lastBlock == null)
            {
                return(APIResultCodes.CouldNotFindLatestBlock);
            }

            var result = VerifyBlock(block, lastBlock);

            if (result != APIResultCodes.Success)
            {
                return(result);
            }

            //if (lastBlock.Balances[LyraGlobal.LYRA_TICKER_CODE] <= block.Balances[LyraGlobal.LYRA_TICKER_CODE] + block.Fee)
            //    return AuthorizationResultCodes.NegativeTransactionAmount;

            // Validate the destination account id (should be empty)
            if (!string.IsNullOrWhiteSpace(block.DestinationAccountId))
            {
                return(APIResultCodes.InvalidDestinationAccountId);
            }

            result = VerifyTransactionBlock(block);
            if (result != APIResultCodes.Success)
            {
                return(result);
            }

            if (!block.ValidateTransaction(lastBlock))
            {
                return(APIResultCodes.TradeOrderValidationFailed);
            }

            var transaction = block.GetTransaction(lastBlock);

            if (block.MinTradeAmount < 0 || block.MinTradeAmount > block.TradeAmount)
            {
                return(APIResultCodes.TradeOrderValidationFailed);
            }

            if (block.SellTokenCode != transaction.TokenCode)
            {
                return(APIResultCodes.TradeOrderValidationFailed);
            }

            var token = _accountCollection.FindTokenGenesisBlock(null, block.BuyTokenCode);

            if (token == null)
            {
                return(APIResultCodes.TradeOrderValidationFailed);
            }

            bool res = (block.OrderType == TradeOrderTypes.Sell) ? ValidateSellOrder(block, transaction) : ValidateBuyOrder(block, transaction);

            if (!res)
            {
                return(APIResultCodes.TradeOrderValidationFailed);
            }

            MatchTradeBlock = _TradeMatchEngine.Match(block);
            if (MatchTradeBlock != null)
            {
                return(APIResultCodes.TradeOrderMatchFound);
            }

            Sign(ref block);

            _accountCollection.AddBlock(block);

            _TradeMatchEngine.AddOrder(block);

            return(base.Authorize(ref tblock));
        }
示例#28
0
        public override async Task <APIResultCodes> PreSendAuthAsync(DagSystem sys, SendTransferBlock send, TransactionBlock last)
        {
            if (send.Tags.Count != 3 ||
                !send.Tags.ContainsKey("data") ||
                string.IsNullOrWhiteSpace(send.Tags["data"]) ||
                !send.Tags.ContainsKey("voteid")
                )
            {
                return(APIResultCodes.InvalidBlockTags);
            }

            // dao must exists
            var dao = await sys.Storage.FindLatestBlockAsync(send.DestinationAccountId)
                      as IDao;

            if (dao == null)
            {
                return(APIResultCodes.InvalidDAO);
            }

            // verify it
            var change = JsonConvert.DeserializeObject <DAOChange>(send.Tags["data"]);

            if (change == null || change.creator != dao.OwnerAccountId || send.AccountID != dao.OwnerAccountId)
            {
                return(APIResultCodes.Unauthorized);
            }

            var voteid = send.Tags["voteid"];

            if (string.IsNullOrWhiteSpace(voteid))
            {
                return(APIResultCodes.Unauthorized);
            }
            else
            {
                var vs = await sys.Storage.GetVoteSummaryAsync(voteid);

                if (vs == null || !vs.IsDecided)
                {
                    return(APIResultCodes.Unauthorized);
                }

                if (vs.Spec.Proposal.data != send.Tags["data"])
                {
                    return(APIResultCodes.ArgumentOutOfRange);
                }

                // should not execute more than once
                var exec = await sys.Storage.FindExecForVoteAsync(voteid);

                if (exec != null)
                {
                    return(APIResultCodes.AlreadyExecuted);
                }
            }

            if (change.settings == null || change.settings.Count == 0)
            {
                return(APIResultCodes.InvalidArgument);
            }

            return(WFChangeDAO.VerifyDaoChanges(change));
        }
        protected override APIResultCodes ValidateNonFungible(TransactionBlock send_or_receice_block, TransactionBlock previousBlock)
        {
            var result = base.ValidateNonFungible(send_or_receice_block, previousBlock);

            if (result != APIResultCodes.Success)
            {
                return(result);
            }

            if (send_or_receice_block.NonFungibleToken == null)
            {
                return(APIResultCodes.Success);
            }

            var originBlock = _accountCollection.FindBlockByHash((send_or_receice_block as ReceiveTransferBlock).SourceHash);

            if (originBlock == null)
            {
                return(APIResultCodes.OriginNonFungibleBlockNotFound);
            }

            if (!originBlock.ContainsNonFungibleToken())
            {
                return(APIResultCodes.OriginNonFungibleBlockNotFound);
            }

            if (originBlock.NonFungibleToken.Hash != send_or_receice_block.NonFungibleToken.Hash)
            {
                return(APIResultCodes.OriginNonFungibleBlockHashDoesNotMatch);
            }

            return(APIResultCodes.Success);
        }
示例#30
0
        public override async Task <APIResultCodes> PreSendAuthAsync(DagSystem sys, SendTransferBlock block, TransactionBlock lastBlock)
        {
            if (block.Tags.Count != 2 || !block.Tags.ContainsKey("poolid"))
            {
                return(APIResultCodes.InvalidBlockTags);
            }

            var vp = await VerifyPoolAsync(sys, block, lastBlock);

            if (vp != APIResultCodes.Success)
            {
                return(vp);
            }

            var chgs = block.GetBalanceChanges(lastBlock);

            if (chgs.Changes.Count != 2)
            {
                return(APIResultCodes.InvalidPoolDepositionAmount);
            }

            var poolGenesis = sys.Storage.GetPoolByID(block.Tags["poolid"]);

            if (poolGenesis == null)
            {
                return(APIResultCodes.PoolNotExists);
            }

            if (!chgs.Changes.ContainsKey(poolGenesis.Token0) || !chgs.Changes.ContainsKey(poolGenesis.Token1))
            {
                return(APIResultCodes.InvalidPoolDepositionAmount);
            }

            var poolLatest = await sys.Storage.FindLatestBlockAsync(block.DestinationAccountId) as TransactionBlock;

            // compare rito
            if (poolLatest.Balances.ContainsKey(poolGenesis.Token0) && poolLatest.Balances.ContainsKey(poolGenesis.Token1) &&
                poolLatest.Balances[poolGenesis.Token0] > 0 && poolLatest.Balances[poolGenesis.Token1] > 0
                )
            {
                var rito                 = (poolLatest.Balances[poolGenesis.Token0].ToBalanceDecimal() / poolLatest.Balances[poolGenesis.Token1].ToBalanceDecimal());
                var token0Amount         = chgs.Changes[poolGenesis.Token0];
                var token1AmountShouldBe = Math.Round(token0Amount / rito, 8);
                if (chgs.Changes[poolGenesis.Token1] != token1AmountShouldBe &&
                    Math.Abs(chgs.Changes[poolGenesis.Token1] - token1AmountShouldBe) / token1AmountShouldBe > 0.0000001m
                    )
                {
                    return(APIResultCodes.InvalidPoolDepositionRito);
                }
            }
            return(APIResultCodes.Success);
        }