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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); } }
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); }
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); }
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); }
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)); }
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); }
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); }