public Task <IReadOnlyList <(RpcNep17Balance balance, Nep17Contract contract)> > ListBalancesAsync(UInt160 address) { try { if (disposedValue) { return(Task.FromException <IReadOnlyList <(RpcNep17Balance, Nep17Contract)> >(new ObjectDisposedException(nameof(OfflineNode)))); } var contractMap = ExpressRpcServer.GetNep17Contracts(neoSystem, rocksDbStorageProvider).ToDictionary(c => c.ScriptHash); var results = ExpressRpcServer.GetNep17Balances(neoSystem, rocksDbStorageProvider, address) .Select(b => ( balance: new RpcNep17Balance { Amount = b.balance, AssetHash = b.contract.ScriptHash, LastUpdatedBlock = b.lastUpdatedBlock }, contract: contractMap.TryGetValue(b.contract.ScriptHash, out var value) ? value : Nep17Contract.Unknown(b.contract.ScriptHash))); return(Task.FromResult <IReadOnlyList <(RpcNep17Balance, Nep17Contract)> >(results.ToArray())); } catch (Exception ex) { return(Task.FromException <IReadOnlyList <(RpcNep17Balance, Nep17Contract)> >(ex)); } }
public static IEnumerable <(Nep17Contract contract, BigInteger balance, uint lastUpdatedBlock)> GetNep17Balances(NeoSystem neoSystem, IStorageProvider storageProvider, UInt160 address) { // assets key is the script hash of the asset contract // assets value is the last updated block of the assoicated asset for address var assets = new Dictionary <UInt160, uint>(); foreach (var(blockIndex, _, notification) in GetNep17Transfers(storageProvider)) { var from = ToUInt160(notification.State[0]); var to = ToUInt160(notification.State[1]); var fromAddress = notification.State[0].IsNull ? "<null>" : from.ToAddress(neoSystem.Settings.AddressVersion); var toAddress = notification.State[1].IsNull ? "<null>" : to.ToAddress(neoSystem.Settings.AddressVersion); if (from == address || to == address) { assets[notification.ScriptHash] = blockIndex; } } if (!assets.ContainsKey(NativeContract.NEO.Hash)) { assets[NativeContract.NEO.Hash] = 0; } if (!assets.ContainsKey(NativeContract.GAS.Hash)) { assets[NativeContract.GAS.Hash] = 0; } using var snapshot = neoSystem.GetSnapshot(); foreach (var kvp in assets) { if (TryGetBalance(kvp.Key, out var balance) && balance > BigInteger.Zero) { var contract = Nep17Contract.TryLoad(neoSystem.Settings, snapshot, kvp.Key, out var _contract) ? _contract : Nep17Contract.Unknown(kvp.Key); yield return(contract, balance, kvp.Value); } } bool TryGetBalance(UInt160 asset, out BigInteger balance) { using var sb = new ScriptBuilder(); sb.EmitDynamicCall(asset, "balanceOf", address.ToArray()); using var engine = sb.Invoke(neoSystem.Settings, snapshot); if (!engine.State.HasFlag(VMState.FAULT) && engine.ResultStack.Count >= 1) { balance = engine.ResultStack.Pop <Neo.VM.Types.Integer>().GetInteger(); return(true); } balance = default; return(false); } }
public async Task <(Neo.Network.RPC.Models.RpcNep17Balance balance, Nep17Contract contract)[]> GetBalancesAsync(UInt160 address) { var contracts = ((Neo.IO.Json.JArray) await rpcClient.RpcSendAsync("expressgetnep17contracts")) .Select(json => Nep17Contract.FromJson(json)) .ToDictionary(c => c.ScriptHash); var balances = await rpcClient.GetNep17BalancesAsync(address.ToAddress()).ConfigureAwait(false); return(balances.Balances .Select(b => ( balance: b, contract: contracts.TryGetValue(b.AssetHash, out var value) ? value : Nep17Contract.Unknown(b.AssetHash))) .ToArray()); }
public static IEnumerable <Nep17Contract> GetNep17Contracts(IExpressReadOnlyStore store) { var scriptHashes = new HashSet <UInt160>(); foreach (var(_, _, notification) in GetNep17Transfers(store)) { scriptHashes.Add(notification.ScriptHash); } scriptHashes.Add(NativeContract.NEO.Hash); scriptHashes.Add(NativeContract.GAS.Hash); using var snapshot = Blockchain.Singleton.GetSnapshot(); foreach (var scriptHash in scriptHashes) { if (Nep17Contract.TryLoad(snapshot, scriptHash, out var contract)) { yield return(contract); } } }
public static IEnumerable <Nep17Contract> GetNep17Contracts(NeoSystem neoSystem, IStorageProvider storageProvider) { var scriptHashes = new HashSet <UInt160>(); foreach (var(_, _, notification) in GetNep17Transfers(storageProvider)) { scriptHashes.Add(notification.ScriptHash); } scriptHashes.Add(NativeContract.NEO.Hash); scriptHashes.Add(NativeContract.GAS.Hash); using var snapshot = neoSystem.GetSnapshot(); foreach (var scriptHash in scriptHashes) { if (Nep17Contract.TryLoad(neoSystem.Settings, snapshot, scriptHash, out var contract)) { yield return(contract); } } }