diff --git a/src/Neo/Extensions/SmartContract/NeoTokenExtensions.cs b/src/Neo/Extensions/SmartContract/NeoTokenExtensions.cs new file mode 100644 index 0000000000..e2a2ae2fdb --- /dev/null +++ b/src/Neo/Extensions/SmartContract/NeoTokenExtensions.cs @@ -0,0 +1,42 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// NeoTokenExtensions.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.Persistence; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using System; +using System.Collections.Generic; +using System.Numerics; + +namespace Neo.Extensions +{ + public static class NeoTokenExtensions + { + public static IEnumerable<(UInt160 Address, BigInteger Balance)> GetAccounts(this NeoToken neoToken, DataCache snapshot) + { + if (neoToken is null) + throw new ArgumentNullException(nameof(neoToken)); + + if (snapshot is null) + throw new ArgumentNullException(nameof(snapshot)); + + var kb = new KeyBuilder(neoToken.Id, NeoToken.Prefix_Account); + var prefixKey = kb.ToArray(); + + foreach (var (key, value) in snapshot.Find(prefixKey, SeekDirection.Forward)) + { + var keyBytes = key.ToArray(); + var addressHash = new UInt160(keyBytes.AsSpan(prefixKey.Length)); + yield return new(addressHash, value.GetInteroperable().Balance); + } + } + } +} diff --git a/tests/Neo.UnitTests/Extensions/UT_NeoTokenExtensions.cs b/tests/Neo.UnitTests/Extensions/UT_NeoTokenExtensions.cs new file mode 100644 index 0000000000..fa3eeef2a8 --- /dev/null +++ b/tests/Neo.UnitTests/Extensions/UT_NeoTokenExtensions.cs @@ -0,0 +1,53 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// UT_NeoTokenExtensions.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Extensions; +using Neo.SmartContract.Native; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Text; +using System.Threading.Tasks; + +namespace Neo.UnitTests.Extensions +{ + [TestClass] + public class UT_NeoTokenExtensions + { + private NeoSystem system; + + [TestInitialize] + public void Initialize() + { + system = TestBlockchain.TheNeoSystem; + } + + [TestCleanup] + public void Clean() + { + TestBlockchain.ResetStore(); + } + + [TestMethod] + public void TestGetAccounts() + { + UInt160 expected = "0x9f8f056a53e39585c7bb52886418c7bed83d126b"; + + var accounts = NativeContract.NEO.GetAccounts(system.StoreView); + var actual = accounts.FirstOrDefault(); + + Assert.AreEqual(expected, actual.Address); + Assert.AreEqual(100000000, actual.Balance); + } + } +}