protected override void OnProcessNewBlock(Block block,
                                                  IEnumerable <WalletCoin> added,
                                                  IEnumerable <WalletCoin> changed,
                                                  IEnumerable <WalletCoin> deleted,
                                                  IEnumerable <JSWalletCoin> jsadded,
                                                  IEnumerable <JSWalletCoin> jschanged,
                                                  IEnumerable <JSWalletCoin> jsdeleted,
                                                  IEnumerable <JSWalletCoin> jswitnesschanged,
                                                  IEnumerable <RCTWalletCoin> rctadded,
                                                  IEnumerable <RCTWalletCoin> rctchanged,
                                                  IEnumerable <RCTWalletCoin> rctdeleted)
        {
            Transaction[] tx_changed = null;
            using (WalletDataContext ctx = new WalletDataContext(DbPath))
            {
                foreach (CoreTransaction tx in block.Transactions.Where(p => IsWalletTransaction(p)))
                {
                    Transaction db_tx = ctx.Transactions.FirstOrDefault(p => p.Hash.SequenceEqual(tx.Hash.ToArray()));
                    if (db_tx == null)
                    {
                        ctx.Transactions.Add(new Transaction
                        {
                            Hash    = tx.Hash.ToArray(),
                            Type    = tx.Type,
                            RawData = tx.ToArray(),
                            Height  = block.Index,
                            Time    = block.Timestamp.ToDateTime()
                        });
                    }
                    else
                    {
                        db_tx.Height = block.Index;
                    }
                }

                tx_changed = ctx.ChangeTracker.Entries <Transaction>().Where(p => p.State != EntityState.Unchanged).Select(p => p.Entity).ToArray();

                OnCoinsChanged(ctx, added, changed, deleted, jsadded, jschanged, jsdeleted, jswitnesschanged, rctadded, rctchanged, rctdeleted);
                if (block.Index == Blockchain.Default.Height || ctx.ChangeTracker.Entries().Any())
                {
                    foreach (Transaction db_tx in ctx.Transactions.Where(p => !p.Height.HasValue))
                    {
                        if (block.Transactions.Any(p => p.Hash == new UInt256(db_tx.Hash)))
                        {
                            db_tx.Height = block.Index;
                        }
                    }

                    ctx.Keys.First(p => p.Name == "Height").Value       = BitConverter.GetBytes(WalletHeight);
                    ctx.Keys.First(p => p.Name == "CmMerkleTree").Value = GetCmMerkleTreeInBytes();

                    try
                    {
                        ctx.SaveChanges();
                    }
                    catch (Exception ex)
                    {
                        string str = ex.Message;
                    }
                }
            }
            if (tx_changed?.Length > 0)
            {
                TransactionsChanged?.Invoke(this, GetTransactionInfo(tx_changed));
            }
        }
        protected override void OnSaveTransaction(CoreTransaction tx,
                                                  IEnumerable <WalletCoin> added,
                                                  IEnumerable <WalletCoin> changed,
                                                  IEnumerable <JSWalletCoin> jsadded,
                                                  IEnumerable <JSWalletCoin> jschanged,
                                                  IEnumerable <JSWalletCoin> jsdeleted,
                                                  IEnumerable <JSWalletCoin> jswitnesschanged,
                                                  IEnumerable <RCTWalletCoin> rctadded,
                                                  IEnumerable <RCTWalletCoin> rctchanged,
                                                  IEnumerable <RCTWalletCoin> rctdeleted)
        {
            Transaction tx_changed = null;

            using (WalletDataContext ctx = new WalletDataContext(DbPath))
            {
                if (IsWalletTransaction(tx))
                {
                    if (tx is AnonymousContractTransaction)
                    {
                        tx_changed = new Transaction
                        {
                            Hash    = tx.Hash.ToArray(),
                            Type    = tx.Type,
                            RawData = tx.ToArray(),
                            Height  = null,
                            Time    = DateTime.Now
                        }
                    }
                    ;
                    else
                    {
                        tx_changed = ctx.Transactions.Add(new Transaction
                        {
                            Hash    = tx.Hash.ToArray(),
                            Type    = tx.Type,
                            RawData = tx.ToArray(),
                            Height  = null,
                            Time    = DateTime.Now
                        }).Entity;
                    }
                }
                OnCoinsChanged(ctx, added, changed, Enumerable.Empty <WalletCoin>(),
                               jsadded,
                               jschanged,
                               jsdeleted,
                               jswitnesschanged,
                               rctadded,
                               rctchanged,
                               rctdeleted);
                try
                {
                    if (!(tx is AnonymousContractTransaction))
                    {
                        ctx.SaveChanges();
                    }
                }
                catch (Exception ex)
                {
                    string str = ex.Message;
                }
            }
            if (tx_changed != null)
            {
                TransactionsChanged?.Invoke(this, GetTransactionInfo(new[] { tx_changed }));
            }
        }
        private void OnCoinsChanged(WalletDataContext ctx,
                                    IEnumerable <WalletCoin> added,
                                    IEnumerable <WalletCoin> changed,
                                    IEnumerable <WalletCoin> deleted,
                                    IEnumerable <JSWalletCoin> jsadded,
                                    IEnumerable <JSWalletCoin> jschanged,
                                    IEnumerable <JSWalletCoin> jsdeleted,
                                    IEnumerable <JSWalletCoin> jswitnesschanged,
                                    IEnumerable <RCTWalletCoin> rctadded,
                                    IEnumerable <RCTWalletCoin> rctchanged,
                                    IEnumerable <RCTWalletCoin> rctdeleted)
        {
            #region Transparent Coin
            foreach (WalletCoin coin in added)
            {
                try
                {
                    ctx.Coins.Add(new Coin
                    {
                        TxId       = coin.Reference.PrevHash.ToArray(),
                        Index      = coin.Reference.PrevIndex,
                        AssetId    = coin.Output.AssetId.ToArray(),
                        Value      = coin.Output.Value.GetData(),
                        ScriptHash = coin.Output.ScriptHash.ToArray(),
                        State      = coin.State
                    });
                    ctx.SaveChanges();
                }
                catch (Exception)
                {
                }
            }
            foreach (WalletCoin coin in changed)
            {
                ctx.Coins.First(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex).State = coin.State;
                try
                {
                    ctx.Coins.Update(ctx.Coins.First(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex));
                    ctx.SaveChanges();
                }
                catch (Exception)
                {
                }
            }
            foreach (WalletCoin coin in deleted)
            {
                try
                {
                    Coin unspent_coin = ctx.Coins.FirstOrDefault(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex);
                    ctx.Coins.Remove(unspent_coin);
                    ctx.SaveChanges();
                }
                catch (Exception)
                {
                }
            }
            #endregion

            #region ZK-SNARKS Coin
            foreach (JSWalletCoin coin in jsadded)
            {
                ctx.JSCoins.Add(new JSCoin
                {
                    TxId          = coin.Reference.PrevHash.ToArray(),
                    JsId          = coin.Reference.PrevJsId,
                    Index         = coin.Reference.PrevIndex,
                    AssetId       = coin.Output.AssetId.ToArray(),
                    Value         = coin.Output.Value.GetData(),
                    ScriptHash    = coin.Output.ScriptHash.ToArray(),
                    State         = coin.State,
                    r             = coin.Output.r.ToArray(),
                    rho           = coin.Output.rho.ToArray(),
                    Witness       = coin.Output.witness,
                    WitnessHeight = coin.Output.witness_height,
                    CMTreeHeight  = coin.Output.cmtree_height
                });

                try
                {
                    ctx.SaveChanges();
                }
                catch (Exception ex)
                {
                    string error = ex.Message;
                }
            }
            foreach (JSWalletCoin coin in jschanged)
            {
                ctx.JSCoins.First(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex && p.JsId == coin.Reference.PrevJsId).State         = coin.State;
                ctx.JSCoins.First(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex && p.JsId == coin.Reference.PrevJsId).Witness       = coin.Output.witness;
                ctx.JSCoins.First(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex && p.JsId == coin.Reference.PrevJsId).WitnessHeight = coin.Output.witness_height;
                ctx.JSCoins.First(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex && p.JsId == coin.Reference.PrevJsId).CMTreeHeight  = coin.Output.cmtree_height;
                try
                {
                    ctx.SaveChanges();
                }
                catch (Exception ex)
                {
                    string error = ex.Message;
                }
            }
            foreach (JSWalletCoin coin in jsdeleted)
            {
                JSCoin unspent_coin = ctx.JSCoins.FirstOrDefault(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex && p.JsId == coin.Reference.PrevJsId);
                ctx.JSCoins.Remove(unspent_coin);
            }
            foreach (JSWalletCoin coin in jswitnesschanged)
            {
                JSCoin update_coin = ctx.JSCoins.FirstOrDefault(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.Index == coin.Reference.PrevIndex && p.JsId == coin.Reference.PrevJsId);
                if (update_coin != null)
                {
                    try
                    {
                        update_coin.Witness       = coin.Output.witness;
                        update_coin.WitnessHeight = coin.Output.witness_height;
                        ctx.JSCoins.Update(update_coin);
                        ctx.SaveChanges();
                    }
                    catch (Exception ex)
                    {
                        string error = ex.Message;
                    }
                }
            }
            #endregion

            #region RingCT Coin
            foreach (RCTWalletCoin coin in rctadded)
            {
                ctx.RCTCoins.Add(new RCTCoin
                {
                    TxId       = coin.Reference.PrevHash.ToArray(),
                    TxRCTHash  = coin.Reference.TxRCTHash.ToArray(),
                    RctID      = coin.Reference.PrevRCTSigId,
                    Index      = coin.Reference.PrevRCTSigIndex,
                    AssetId    = coin.Output.AssetId.ToArray(),
                    Value      = coin.Output.Value.GetData(),
                    PubKey     = coin.Output.PubKey.ToArray(),
                    ScriptHash = coin.Output.ScriptHash.ToArray(),
                    State      = coin.State
                });

                try
                {
                    ctx.SaveChanges();
                }
                catch (Exception ex)
                {
                    string error = ex.Message;
                }
            }

            foreach (RCTWalletCoin coin in rctchanged)
            {
                ctx.RCTCoins.First(p => p.TxRCTHash.SequenceEqual(coin.Reference.TxRCTHash.ToArray()) && p.RctID == coin.Reference.PrevRCTSigId && p.Index == coin.Reference.PrevRCTSigIndex).State = coin.State;

                try
                {
                    ctx.SaveChanges();
                }
                catch (Exception ex)
                {
                    string error = ex.Message;
                }
            }

            foreach (RCTWalletCoin coin in rctdeleted)
            {
                RCTCoin unspent_coin = ctx.RCTCoins.FirstOrDefault(p => p.TxId.SequenceEqual(coin.Reference.PrevHash.ToArray()) && p.RctID == coin.Reference.PrevRCTSigId && p.Index == coin.Reference.PrevRCTSigIndex);
                ctx.RCTCoins.Remove(unspent_coin);
            }
            #endregion
        }