public Result SetAccountEligibility(
            List <BlockchainEvent> events,
            SetAccountEligibilityData actionData,
            IUnitOfWork uow)
        {
            var account = NewRepository <Account>(uow)
                          .Get(a => a.Hash == actionData.AccountHash)
                          .SingleOrDefault();

            if (account == null)
            {
                return(Result.Failure("Account {0} does not exist.".F(actionData.AccountHash)));
            }

            var asset = NewRepository <Asset>(uow).Get(a => a.Hash == actionData.AssetHash).SingleOrDefault();

            if (asset == null)
            {
                return(Result.Failure("Asset {0} does not exist.".F(actionData.AssetHash)));
            }

            var holdingRepo = NewRepository <HoldingEligibility>(uow);
            var holding     = holdingRepo
                              .Get(h => h.AssetId == asset.AssetId && h.AccountId == account.AccountId)
                              .SingleOrDefault();
            var isNewHolding = holding == null;

            if (isNewHolding)
            {
                holding = new HoldingEligibility()
                {
                    AssetHash   = asset.Hash,
                    AssetId     = asset.AssetId,
                    AccountHash = account.Hash,
                    AccountId   = account.AccountId
                };
            }

            holding.IsPrimaryEligible   = actionData.IsPrimaryEligible;
            holding.IsSecondaryEligible = actionData.IsSecondaryEligible;

            var firstEvent = events.First();

            firstEvent.AccountId = account.AccountId;
            firstEvent.AssetId   = asset.AssetId;

            if (isNewHolding)
            {
                holdingRepo.Insert(holding);
            }
            else
            {
                holdingRepo.Update(holding);
            }

            return(Result.Success());
        }
        public Result CreateAssetEmission(
            List <BlockchainEvent> events,
            CreateAssetEmissionData actionData,
            IUnitOfWork uow)
        {
            var account = NewRepository <Account>(uow)
                          .Get(a => a.Hash == actionData.EmissionAccountHash)
                          .SingleOrDefault();

            if (account == null)
            {
                return(Result.Failure("Account {0} does not exist.".F(actionData.EmissionAccountHash)));
            }

            var asset = NewRepository <Asset>(uow).Get(a => a.Hash == actionData.AssetHash).SingleOrDefault();

            if (asset == null)
            {
                return(Result.Failure("Asset {0} does not exist.".F(actionData.AssetHash)));
            }

            var holding = new HoldingEligibility()
            {
                AssetHash   = asset.Hash,
                AssetId     = asset.AssetId,
                AccountHash = account.Hash,
                AccountId   = account.AccountId,
                Balance     = actionData.Amount
            };

            var firstEvent = events.First();

            firstEvent.AccountId = account.AccountId;
            firstEvent.AssetId   = asset.AssetId;
            firstEvent.Amount    = actionData.Amount;

            NewRepository <HoldingEligibility>(uow).Insert(holding);

            return(Result.Success());
        }
        public Result ChangeKycControllerAddress(
            List <BlockchainEvent> events,
            ChangeKycControllerAddressData actionData,
            IUnitOfWork uow)
        {
            var account = NewRepository <Account>(uow)
                          .Get(a => a.Hash == actionData.AccountHash)
                          .SingleOrDefault();

            if (account == null)
            {
                return(Result.Failure("Account {0} does not exist.".F(actionData.AccountHash)));
            }

            var asset = NewRepository <Asset>(uow).Get(a => a.Hash == actionData.AssetHash).SingleOrDefault();

            if (asset == null)
            {
                return(Result.Failure("Asset {0} does not exist.".F(actionData.AssetHash)));
            }

            var holdingRepo = NewRepository <HoldingEligibility>(uow);
            var holding     = holdingRepo
                              .Get(h => h.AssetId == asset.AssetId && h.AccountId == account.AccountId)
                              .SingleOrDefault();
            var isNewHolding = holding == null;

            if (isNewHolding)
            {
                holding = new HoldingEligibility()
                {
                    AssetHash   = asset.Hash,
                    AssetId     = asset.AssetId,
                    AccountHash = account.Hash,
                    AccountId   = account.AccountId
                };
            }

            holding.KycControllerAddress = actionData.KycControllerAddress;

            var firstEvent = events.First();

            firstEvent.AccountId = account.AccountId;
            firstEvent.AssetId   = asset.AssetId;

            var kycControllerAddress = NewRepository <Address>(uow)
                                       .Get(a => a.BlockchainAddress == actionData.KycControllerAddress)
                                       .SingleOrDefault();

            if (kycControllerAddress == null)
            {
                return(Result.Failure("Address {0} does not exist.".F(actionData.KycControllerAddress)));
            }

            events.Add(new BlockchainEvent()
            {
                AddressId     = kycControllerAddress.AddressId,
                TxActionId    = firstEvent.TxActionId,
                BlockId       = firstEvent.BlockId,
                Fee           = 0,
                Amount        = 0,
                TransactionId = firstEvent.TransactionId,
                EventType     = EventType.Action.ToString(),
                AccountId     = account.AccountId,
                AssetId       = asset.AssetId
            });

            if (isNewHolding)
            {
                holdingRepo.Insert(holding);
            }
            else
            {
                holdingRepo.Update(holding);
            }

            return(Result.Success());
        }
        public Result TransferAsset(List <BlockchainEvent> events, TransferAssetData actionData, IUnitOfWork uow)
        {
            var addressRepo = NewRepository <Address>(uow);
            var accountRepo = NewRepository <Account>(uow);
            var assetRepo   = NewRepository <Asset>(uow);
            var holdingRepo = NewRepository <HoldingEligibility>(uow);

            var fromAccount = accountRepo.Get(a => a.Hash == actionData.FromAccountHash).SingleOrDefault();

            if (fromAccount == null)
            {
                return(Result.Failure("Account {0} does not exist.".F(actionData.FromAccountHash)));
            }

            var toAccount = accountRepo.Get(a => a.Hash == actionData.ToAccountHash).SingleOrDefault();

            if (toAccount == null)
            {
                return(Result.Failure("Account {0} does not exist.".F(actionData.ToAccountHash)));
            }

            var asset = assetRepo.Get(a => a.Hash == actionData.AssetHash).SingleOrDefault();

            if (asset == null)
            {
                return(Result.Failure("Asset {0} does not exist.".F(actionData.AssetHash)));
            }

            var fromHolding = holdingRepo
                              .Get(h => h.AssetId == asset.AssetId && h.AccountId == fromAccount.AccountId)
                              .SingleOrDefault();

            if (fromHolding == null || fromHolding.Balance < actionData.Amount)
            {
                return(Result.Failure("Account {0} does not sufficient holding.".F(actionData.FromAccountHash)));
            }

            var toHolding = holdingRepo
                            .Get(h => h.AssetId == asset.AssetId && h.AccountId == toAccount.AccountId)
                            .SingleOrDefault();
            var isNewHolding = toHolding == null;

            if (isNewHolding)
            {
                toHolding = new HoldingEligibility()
                {
                    AssetHash   = asset.Hash,
                    AssetId     = asset.AssetId,
                    AccountHash = toAccount.Hash,
                    AccountId   = toAccount.AccountId,
                    Balance     = 0
                };
            }

            fromHolding.Balance -= actionData.Amount;
            toHolding.Balance   += actionData.Amount;

            var firstEvent = events.First();

            firstEvent.AccountId = fromAccount.AccountId;
            firstEvent.AssetId   = asset.AssetId;
            firstEvent.Amount    = actionData.Amount * -1;

            var toControllerAddressId = addressRepo
                                        .GetAs(a => a.BlockchainAddress == toAccount.ControllerAddress, a => a.AddressId)
                                        .SingleOrDefault();

            if (toControllerAddressId == default(long))
            {
                return(Result.Failure("Address {0} does not exist.".F(toAccount.ControllerAddress)));
            }

            events.Add(new BlockchainEvent
            {
                AddressId     = toControllerAddressId,
                TxActionId    = firstEvent.TxActionId,
                BlockId       = firstEvent.BlockId,
                Fee           = 0,
                Amount        = actionData.Amount,
                TransactionId = firstEvent.TransactionId,
                EventType     = EventType.Action.ToString(),
                AccountId     = toAccount.AccountId,
                AssetId       = asset.AssetId
            });

            holdingRepo.Update(fromHolding);
            if (isNewHolding)
            {
                holdingRepo.Insert(toHolding);
            }
            else
            {
                holdingRepo.Update(toHolding);
            }

            return(Result.Success());
        }