public override void ApplyTransaction(Transaction tx) { lock (unconfirmed) { unconfirmed[tx.Hash] = tx; } WalletTransaction?.Invoke(this, new WalletTransactionEventArgs { Transaction = tx, RelatedAccounts = tx.Witnesses.Select(p => p.ScriptHash).Union(tx.Outputs.Select(p => p.ScriptHash)).Where(p => Contains(p)).ToArray(), Height = null, Time = DateTime.UtcNow.ToTimestamp() }); }
private void WalletIndexer_WalletTransaction(object sender, WalletTransactionEventArgs e) { lock (unconfirmed) { unconfirmed.Remove(e.Transaction.Hash); } UInt160[] relatedAccounts; lock (accounts) { relatedAccounts = e.RelatedAccounts.Where(p => accounts.ContainsKey(p)).ToArray(); } if (relatedAccounts.Length > 0) { WalletTransaction?.Invoke(this, new WalletTransactionEventArgs { Transaction = e.Transaction, RelatedAccounts = relatedAccounts, Height = e.Height, Time = e.Time }); } }
private void ProcessBlock(Block block, HashSet <UInt160> accounts, WriteBatch batch) { foreach (Transaction tx in block.Transactions) { HashSet <UInt160> accounts_changed = new HashSet <UInt160>(); for (ushort index = 0; index < tx.Outputs.Length; index++) { TransactionOutput output = tx.Outputs[index]; if (accounts_tracked.ContainsKey(output.ScriptHash)) { CoinReference reference = new CoinReference { PrevHash = tx.Hash, PrevIndex = index }; if (coins_tracked.TryGetValue(reference, out Coin coin)) { coin.State |= CoinState.Confirmed; } else { accounts_tracked[output.ScriptHash].Add(reference); coins_tracked.Add(reference, coin = new Coin { Reference = reference, Output = output, State = CoinState.Confirmed }); } batch.Put(SliceBuilder.Begin(DataEntryPrefix.ST_Coin).Add(reference), SliceBuilder.Begin().Add(output).Add((byte)coin.State)); accounts_changed.Add(output.ScriptHash); } } foreach (CoinReference input in tx.Inputs) { if (coins_tracked.TryGetValue(input, out Coin coin)) { if (coin.Output.AssetId.Equals(Blockchain.GoverningToken.Hash)) { coin.State |= CoinState.Spent | CoinState.Confirmed; batch.Put(SliceBuilder.Begin(DataEntryPrefix.ST_Coin).Add(input), SliceBuilder.Begin().Add(coin.Output).Add((byte)coin.State)); } else { accounts_tracked[coin.Output.ScriptHash].Remove(input); coins_tracked.Remove(input); batch.Delete(DataEntryPrefix.ST_Coin, input); } accounts_changed.Add(coin.Output.ScriptHash); } } switch (tx) { case MinerTransaction _: case ContractTransaction _: #pragma warning disable CS0612 case PublishTransaction _: #pragma warning restore CS0612 break; case ClaimTransaction tx_claim: foreach (CoinReference claim in tx_claim.Claims) { if (coins_tracked.TryGetValue(claim, out Coin coin)) { accounts_tracked[coin.Output.ScriptHash].Remove(claim); coins_tracked.Remove(claim); batch.Delete(DataEntryPrefix.ST_Coin, claim); accounts_changed.Add(coin.Output.ScriptHash); } } break; #pragma warning disable CS0612 case EnrollmentTransaction tx_enrollment: if (accounts_tracked.ContainsKey(tx_enrollment.ScriptHash)) { accounts_changed.Add(tx_enrollment.ScriptHash); } break; case RegisterTransaction tx_register: if (accounts_tracked.ContainsKey(tx_register.OwnerScriptHash)) { accounts_changed.Add(tx_register.OwnerScriptHash); } break; #pragma warning restore CS0612 default: foreach (UInt160 hash in tx.Witnesses.Select(p => p.ScriptHash)) { if (accounts_tracked.ContainsKey(hash)) { accounts_changed.Add(hash); } } break; } if (accounts_changed.Count > 0) { foreach (UInt160 account in accounts_changed) { batch.Put(SliceBuilder.Begin(DataEntryPrefix.ST_Transaction).Add(account).Add(tx.Hash), false); } WalletTransaction?.Invoke(null, new WalletTransactionEventArgs { Transaction = tx, RelatedAccounts = accounts_changed.ToArray(), Height = block.Index, Time = block.Timestamp }); } } }