public TxSignature AddSignature(TxSignature signature)
        {
            TxSignature res = GetSignature(signature.TxInputId, signature.TeammateId);

            if (res != null)
            {
                return(res);
            }
            return(Add <TxSignature>(signature));
        }
        private bool ServerUpdatesToLocalDb()
        {
            Key  key          = GetUser().BitcoinPrivateKey;
            long since        = _connection.LastUpdated.Ticks;
            var  txsToUpdate  = _txRepo.GetTxsNeedServerUpdate();
            var  txSignatures = _txRepo.GetTxsSignaturesNeedServerUpdate();

            GetUpdatesResultData serverResponse = _server.GetUpdates(key, since, txsToUpdate.Where(x => x.Teammate.Team.IsInNormalState), txSignatures);

            if (null == serverResponse)
            {
                // todo: log record
                return(false);
            }

            txsToUpdate.ForEach(x =>
            {
                x.NeedUpdateServer = false;
                _txRepo.Update(x);
            });
            txSignatures.ForEach(x =>
            {
                x.NeedUpdateServer = false;
                _txRepo.Update(x);
            });

            serverResponse.Teams.ForEach(team =>
            {
                var existingTeam = _teamRepo.Get(team.Id);
                if (existingTeam == null)
                {
                    team.PayToAddressOkAge             = 14;
                    team.AutoApprovalMyGoodAddress     = 3;
                    team.AutoApprovalMyNewAddress      = 7;
                    team.AutoApprovalCosignGoodAddress = 3;
                    team.AutoApprovalCosignNewAddress  = 7;
                    existingTeam = _teamRepo.Add(team);
                }
                else
                {
                    // Can change Name
                    if (existingTeam.Name != team.Name)
                    {
                        existingTeam.Name = team.Name;
                        _teamRepo.Update(existingTeam);
                    }
                }
            });

            serverResponse.Teammates.ForEach(teammate =>
            {
                var existingTeammate = _teammateRepo.Get(teammate.Id);

                bool okToInsertOrUpdate = true;
                if (existingTeammate != null)
                {
                    if (existingTeammate.PublicKey != null && teammate.PublicKey != existingTeammate.PublicKey ||
                        teammate.FBName != existingTeammate.FBName ||
                        teammate.TeamId != existingTeammate.TeamId)
                    {
                        okToInsertOrUpdate = false; // we don't allow to change basic info
                    }
                }
                if (okToInsertOrUpdate)
                {
                    _teammateRepo.InsertOrUpdateDetached(teammate);
                }
            });

            serverResponse.PayTos.ForEach(payTo =>
            {
                var existingPayTo = _payToRepo.Get(payTo.TeammateId, payTo.Address);
                if (existingPayTo == null)
                {
                    payTo.KnownSince = DateTime.UtcNow;
                    existingPayTo    = _payToRepo.Add(payTo);
                }
                if (existingPayTo.IsDefault)
                {
                    _payToRepo.GetForTeammate(existingPayTo.TeammateId).ForEach(x =>
                    {
                        if (x.Address != existingPayTo.Address)
                        {
                            x.IsDefault = false;
                            _payToRepo.Update(x);
                        }
                    });
                }
            });

            serverResponse.BTCAddresses.ForEach(address =>
            {
                if (address.Address != null && _addressRepo.Get(address.Address) == null)
                {
                    if (address.Status == UserAddressStatus.Previous)
                    {
                        address.Status = UserAddressStatus.ServerPrevious;
                    }
                    else if (address.Status == UserAddressStatus.Current)
                    {
                        address.Status = UserAddressStatus.ServerCurrent;
                    }
                    else if (address.Status == UserAddressStatus.Next)
                    {
                        address.Status = UserAddressStatus.ServerNext;
                    }
                    _addressRepo.Add(address);
                }
            });

            serverResponse.Cosigners.ForEach(cosigner =>
            {
                if (cosigner.AddressId != null)
                {
                    if (_addressRepo.Get(cosigner.AddressId) == null) // can't add cosigners to existing addresses
                    {
                        _cosignerRepo.Add(cosigner);
                    }
                }
            });

            // Rules for setting new current address
            // ok to set first address
            // ok to change to next address if:
            // -- no funds on existing current address
            // -- or a real Tx from current to next occurred

            serverResponse.Txs.ForEach(tx =>
            {
                var existingTx = _txRepo.Get(tx.Id);
                if (existingTx == null)
                {
                    tx.ReceivedTime         = DateTime.UtcNow;
                    tx.UpdateTime           = DateTime.UtcNow;
                    tx.Resolution           = TxClientResolution.None;
                    tx.ClientResolutionTime = null;
                    tx.NeedUpdateServer     = false;
                    _txRepo.Add(tx);
                }
                else
                {
                    existingTx.State          = tx.State;
                    existingTx.UpdateTime     = DateTime.UtcNow;
                    existingTx.ResolutionTime = tx.ResolutionTime;
                    existingTx.ProcessedTime  = tx.ProcessedTime;
                    _txRepo.Update(existingTx);
                }
            });

            foreach (var txInput in serverResponse.TxInputs)
            {
                if (_txRepo.GetInput(txInput.Id) != null)
                {
                    continue; // can't change inputs
                }

                var tx = _txRepo.Get(txInput.TxId);
                if (tx == null)
                {
                    tx = serverResponse.Txs.FirstOrDefault(x => x.Id == txInput.TxId);
                }
                if (tx == null)
                {
                    continue; // malformed TX, todo: add log record
                }
                _txRepo.AddInput(txInput);
            }

            foreach (var txOutput in serverResponse.TxOutputs)
            {
                var tx = _txRepo.Get(txOutput.TxId);
                if (tx != null)
                {
                    continue; // can't add outputs to existing txs
                }
                tx = serverResponse.Txs.FirstOrDefault(x => x.Id == txOutput.TxId);
                if (tx == null)
                {
                    continue; // malformed TX, todo: add log record
                }
                _txRepo.AddOutput(txOutput);
            }

            foreach (var txSignatureInfo in serverResponse.TxSignatures)
            {
                if (_txRepo.GetSignature(txSignatureInfo.TxInputId, txSignatureInfo.TeammateId) != null)
                {
                    continue; // can't change signatures
                }

                var txInput = _txRepo.GetInput(txSignatureInfo.TxInputId);
                if (txInput == null)
                {
                    txInput = serverResponse.TxInputs.FirstOrDefault(x => x.Id == txSignatureInfo.TxInputId);
                }
                if (txInput == null)
                {
                    continue; // malformed TX, todo: add log record
                }
                var txSignature = new TxSignature()
                {
                    TxInputId        = txSignatureInfo.TxInputId,
                    TeammateId       = txSignatureInfo.TeammateId,
                    Signature        = Convert.FromBase64String(txSignatureInfo.Signature),
                    NeedUpdateServer = false
                };
                _txRepo.AddSignature(txSignature);
            }

            _context.SaveChanges();

            // Check outputs
            foreach (var arrivingTx in serverResponse.Txs)
            {
                var  tx           = _txRepo.Get(arrivingTx.Id);
                bool isWalletMove = (tx.Kind == TxKind.MoveToNextWallet || tx.Kind == TxKind.SaveFromPrevWallet);

                // Outputs are required unless it's a wallet update
                if (!isWalletMove && tx.Outputs == null)
                {
                    ChangeTxResolution(tx, TxClientResolution.ErrorBadRequest);
                    continue;
                }

                // AmountBTC sum must match total unless it's a wallet update
                if (!isWalletMove && Math.Abs(tx.Outputs.Sum(x => x.AmountBTC) - tx.AmountBTC.Value) > 0.000001M)
                {
                    ChangeTxResolution(tx, TxClientResolution.ErrorBadRequest);
                    continue;
                }

                if (tx.Resolution == TxClientResolution.None)
                {
                    ChangeTxResolution(tx, TxClientResolution.Received);
                }
            }

            _context.SaveChanges();

            // Check addresses
            serverResponse.BTCAddresses.ForEach(address =>
            {
                var addressSaved = _addressRepo.Get(address.Address);
                if (addressSaved != null)
                {
                    if (SignHelper.GenerateStringAddress(addressSaved) != addressSaved.Address)
                    {
                        addressSaved.Status = UserAddressStatus.Invalid;
                        _addressRepo.Update(addressSaved);
                    }
                }
            });

            // process inputs

            // verify amounts if inputs are set

            _connection.LastUpdated = new DateTime(serverResponse.LastUpdated, DateTimeKind.Utc);
            _connectionRepo.Update(_connection);

            _context.SaveChanges();

            return(true);
        }
 public TxSignature AddSignature(TxSignature signature)
 {
     return(_txRepo.AddSignature(signature));
 }
 public void Update(TxSignature signature)
 {
     Update <TxSignature>(signature);
 }