static void ProcessMoneyTransfer(Core.Domain.Transaction tx, ObsidianChainContext db) { IList <VIn> vins = tx.TransactionIn; List <string> inAdresses = new List <string>(); foreach (var vin in vins) { AddressEntity existing = db.AddressEntities.Find(vin.PrevVOutFetchedAddress); if (existing == null) // work around broken index till indexing is re-run { Console.WriteLine($"This should never happen: {vin.PrevVOutFetchedAddress} could not be found."); continue; } inAdresses.Add(existing.Id); existing.Balance -= vin.PrevVOutFetchedValue; existing.LastModifiedBlockHeight = (int)tx.Block.Height; UpdateTxIdBlog(existing, tx.TransactionId); } IList <Out> vouts = tx.TransactionsOut; foreach (var vout in vouts) { string outAdress = vout.Address; if (outAdress.StartsWith("OP_RETURN", StringComparison.OrdinalIgnoreCase)) { outAdress = "OP_RETURN"; } AddressEntity existing = db.AddressEntities.Find(outAdress); if (existing != null) { existing.Balance += vout.Value; if (!inAdresses.Contains(existing.Id)) { UpdateTxIdBlog(existing, tx.TransactionId); existing.LastModifiedBlockHeight = (int)tx.Block.Height; } } else { var newAddress = new AddressEntity { Id = vout.Address, Balance = vout.Value, LastModifiedBlockHeight = (int)tx.Block.Height, TxIdBlob = tx.TransactionId + CRLF }; InsertAddressIfShouldBeIndexed(newAddress, db); } } }
static void ProcessStakingReward(Core.Domain.Transaction tx, ObsidianChainContext db) { var vin = tx.TransactionIn[0]; var inAddress = vin.PrevVOutFetchedAddress; var oldBalance = vin.PrevVOutFetchedValue; Debug.Assert(inAddress == tx.TransactionsOut[1].Address); Debug.Assert(inAddress == tx.TransactionsOut[2].Address); var outValue1 = tx.TransactionsOut[1].Value; var outValue2 = tx.TransactionsOut[2].Value; var change = outValue1 + outValue2 - oldBalance; // I assume that only pre-existing addresses get a staking reward! AddressEntity existing = db.AddressEntities.Find(inAddress); Debug.Assert(existing != null); existing.Balance += change; existing.LastModifiedBlockHeight = (int)tx.Block.Height; UpdateTxIdBlog(existing, tx.TransactionId); }
static void ProcessTransaction(Core.Domain.Transaction blockTx, ObsidianChainContext db) { switch (blockTx.TransactionType) { case TransactionType.PoW_Reward_Coinbase: ProcessPoWReward(blockTx, db); break; case TransactionType.PoS_Reward: ProcessStakingReward(blockTx, db); break; case TransactionType.Money: ProcessMoneyTransfer(blockTx, db); break; default: throw new IndexOutOfRangeException("Unsupported TransactionType."); } }
static void ProcessPoWReward(Core.Domain.Transaction tx, ObsidianChainContext db) { var vout = tx.TransactionsOut[0]; var address = vout.Address; var amount = vout.Value; AddressEntity existing = db.AddressEntities.Find(address); if (existing == null) { var newAddress = new AddressEntity { Id = address, Balance = amount, LastModifiedBlockHeight = (int)tx.Block.Height, TxIdBlob = tx.TransactionId + CRLF }; InsertAddressIfShouldBeIndexed(newAddress, db); return; } existing.Balance += amount; existing.LastModifiedBlockHeight = (int)tx.Block.Height; UpdateTxIdBlog(existing, tx.TransactionId); }
private Core.Domain.Transaction GetTransaction(TransactionNinjaModel t) { var block = new Core.Domain.Block() { Hash = t.Block.Hash, Height = t.Block.Height, Time = t.Block.Time, Confirmations = t.Block.Confirmations }; var inputs = t.DeserializeInputs.Select(x => new In() { TransactionId = x.TxId, Address = x.Address, Index = x.Index, Value = x.Value, AssetId = x.AssetId, Quantity = x.Quantity }).ToList(); var outputs = t.DeserializeOutputs.Select(x => new Out() { TransactionId = x.TxId, Address = x.Address, Index = x.Index, Value = x.Value, AssetId = x.AssetId, Quantity = x.Quantity }).ToList(); var assets = new List <Core.Domain.Asset>(); foreach (var k in t.Asset.Keys) { var assetRecord = t.Asset[k]; var asset = new Core.Domain.Asset(); asset.Id = k; if (t.TransactionUrl != null) { asset.MetadataUrl = t.TransactionUrl.ToString(); } asset.Input = assetRecord.AssetDataInput.Select(x => new In() { TransactionId = x.TxId, Address = x.Address, Index = x.Index, Value = x.Value, AssetId = x.AssetId, Quantity = x.Quantity }).ToList(); asset.Output = assetRecord.AssetDataOutput.Select(x => new Out() { TransactionId = x.TxId, Address = x.Address, Index = x.Index, Value = x.Value, AssetId = x.AssetId, Quantity = x.Quantity }).ToList(); assets.Add(asset); } var transaction = new Core.Domain.Transaction() { TransactionId = t.TxId, Time = block.Time, Hex = t.Hex, Fees = t.Fees, IsCoinBase = t.IsCoinBase, IsColor = t.IsColor, Block = block, Blockhash = t.Block.Hash, TransactionIn = inputs, TransactionsOut = outputs, Assets = assets }; return(transaction); }